home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
OS/2 Shareware BBS: 10 Tools
/
10-Tools.zip
/
ddkx86v5.zip
/
DDKX86
/
SRC
/
PEN
/
PENTKT
/
PENBASE
/
LOCATOR.ASM
< prev
next >
Wrap
Assembly Source File
|
1995-04-14
|
27KB
|
852 lines
;*DDK*************************************************************************/
;
; COPYRIGHT Copyright (C) 1995 IBM Corporation
;
; The following IBM OS/2 WARP source code is provided to you solely for
; the purpose of assisting you in your development of OS/2 WARP device
; drivers. You may use this code in accordance with the IBM License
; Agreement provided in the IBM Device Driver Source Kit for OS/2. This
; Copyright statement may not be removed.;
;*****************************************************************************/
; /*****************************************************************/
; /* */
; /* */
; /*****************************************************************/
; /******************* START OF SPECIFICATIONS *********************/
; /* */
; /* SOURCE FILE NAME: LOCATOR.ASM */
; /* */
; /* DESCRIPTIVE NAME: Locator handler */
; /* */
; /* */
; /* STATUS: Version 1.0 */
; /* */
; /* NOTES: This module provide support for locator logical */
; /* devices. The device dependent routine calls LOC_ENGINE*/
; /* after filling in the DCB and extended event packet. */
; /* */
; /* Loc_ProxFilter is provided to filter out proximity */
; /* points in a positonary position, for example, if the */
; /* pen is left on the digitizer surface. This routine */
; /* works inconjunction with Loc_ProxFitlerTC. The */
; /* device dependent routine must allocate a BOX_FILTER */
; /* structure and initialize it. */
; /* */
; /* The device dependent routine may need to subclass, */
; /* or replace, the coordinate adjustment routine or the */
; /* forceClear routine. The latter is called after the */
; /* proximity or contact time out occurs. */
; /* */
; /* The locator module also supports a special IOCTL */
; /* intended for use by the alignment calibration program */
; /* that returns raw cooridinates. */
; /* */
; /* ENTRY POINTS: */
; /* See public statements */
; /* EXTERNAL REFERENCES: */
; /* See extrn statements */
; /* */
; /******************* END OF SPECIFICATIONS *********************/
.xlist
include pensegs.inc
include pen.inc
include penidc.inc
include penei.inc
include penioctl.inc
include struc.inc
include devhlp.inc
include infoseg.inc
.list
.286p
;------------------------------------------------------------------------------
; external data references
;------------------------------------------------------------------------------
extrn Device_Help : dword
;------------------------------------------------------------------------------
; external routines
;------------------------------------------------------------------------------
extrn Idc_ReportEvent : near
extrn But_GetButtons : near
extrn But_GetButtonShift : near
extrn Dsp_GetSuppress : near
;------------------------------------------------------------------------------
; local equates
;------------------------------------------------------------------------------
TICK_LIMIT equ 4
;------------------------------------------------------------------------------
; local data declarations
;------------------------------------------------------------------------------
DSEG segment
public qlrc_sem
qlrc_sem db 0 ; reentry semaphore for query locator raw coordinate
stateTable label word ; state transition action table
dw clr_clr
dw 0 ; reserved
dw clr_prx
dw clr_con
dw 0 ; reserved
dw 0 ; reserved
dw 0 ; reserved
dw 0 ; reserved
dw prx_clr
dw 0 ; reserved
dw prx_prx
dw prx_con
dw con_clr
dw 0 ; reserved
dw con_prx
dw con_con
DSEG ends
CSEG SEGMENT
ASSUME CS:CGROUP, SS:nothing, ES:nothing, DS:DGROUP
;---- ROUTINES TO HANDLE EVENTS -----------------------------------------------
;
;------------------------------------------------------------------------------
;------------------------------------------------------------------------------
; process an event for a device dependent locator device
; bx = dcb
; di = extended event packet address
;------------------------------------------------------------------------------
public Loc_Engine
Loc_Engine proc
mov [bx].dcb_StateTimeOut,0 ; reset the watchdog timer
; if anyone is waiting on a query locator raw coordinate (QLRC)
.if <bit [bx].dcb_LocFlags nz QLRC_REQUEST> AND
.if <[bx].dcb_LocNewState eq STATE_CONTACT>
and [bx].dcb_LocFlags,not QLRC_REQUEST ;signals that its our ProcRun that
;woke up the thread, clean up,
;and we don't need to ProcRun
;multiple times if wakeup is slow
push bx
lea bx,qlrc_sem ; set up block id
mov ax,ds
mov dl, DevHlp_ProcRun
call Device_Help ; Invoke function
pop bx
.endif
; process this coorindate point
call detectMotion
call [bx].dcb_@Adjust
call computeStd
call stateMachine
call fillEventBuffer
call Idc_ReportEvent
call updateValues
ret
Loc_Engine endp
;------------------------------------------------------------------------------
; see if the location has changed.
; bx = dcb
;------------------------------------------------------------------------------
public detectMotion ;ddxy
detectMotion proc
.386p
mov eax, [bx].dcb_LocNewX ; check if x has changed
.if <[bx].dcb_LocLastX eq eax> AND
mov eax, [bx].dcb_LocNewY ; check if y has changed
.if <[bx].dcb_LocLastY eq eax>
and [bx].dcb_LocFlags, not LOC_MOTION
.else
or [bx].dcb_LocFlags, LOC_MOTION
.endif
.286p
ret
detectMotion endp
;------------------------------------------------------------------------------
; adjust the coordinates - ABSOLUTE
; bx = dcb
;------------------------------------------------------------------------------
public AdjustCoords ;ddxy
AdjustCoords proc
.386p
; adjust x
mov eax, [bx].dcb_LocNewX
lea si, [bx].dcb_Xtrans
call Loc_normalize
call Loc_slide
mov [bx].dcb_LocNDCX,eax
; adjust y
mov eax, [bx].dcb_LocNewY
lea si, [bx].dcb_Ytrans
call Loc_normalize
call Loc_slide
mov [bx].dcb_LocNDCY,eax
.286p
ret
AdjustCoords endp
;------------------------------------------------------------------------------
; adjust the coordinates - RELATIVE
; bx = dcb
;------------------------------------------------------------------------------
public AdjustRelCoords ;ddxy
AdjustRelCoords proc
.386p
mov eax, [bx].dcb_LocNewX
mov [bx].dcb_LocNDCX,eax
mov eax, [bx].dcb_LocNewY
mov [bx].dcb_LocNDCY,eax
.286p
ret
AdjustRelCoords endp
;------------------------------------------------------------------------------
; convert raw device cooridinate to normalized device cooridinate
;
; 1) adjust from raw device coridinate origin to normalized device origin
; 2) normalized from measured extent to fixed extent
; 3) clip to fixed extent
; 4) invert if necessary
;
; eax = coordinate value
; si = coordinate transformation structure
; returns
; eax = adjusted coordinate value
;------------------------------------------------------------------------------
public Loc_normalize ;ddxy
Loc_normalize proc
.386p
; adjust realitive to normalized origin
add eax, [si].trn_org_adj
.if s ; if result is negative
mov eax,0 ; back it up to 0 (but no more)
.endif
; normalize
mov edx, [si].trn_ext_max
imul edx ; eax*edx = EDX:EAX
mov ecx, [si].trn_ext_adj
idiv ecx ; edx:eax / ecx = EAX.EDX
.if <nonzero edx> ; if remainder
inc eax
.endif
; clip to real extents (max value is extents - 1)
.if <eax ge [si].trn_ext_max>
mov eax,[si].trn_ext_max
dec eax
.endif
; invert if necessary
.if <bit [si].trn_flags nz INVERTED_COORD>
inc eax
neg eax
add eax, [si].trn_ext_max
.endif
.286p
ret
Loc_Normalize endp
;------------------------------------------------------------------------------
; adjust a coordinate using slide algorithm
; eax = coordinate value
; si = coordinate transformation structure
; returns
; eax = adjusted coordinate value
;------------------------------------------------------------------------------
public Loc_slide ;ddxy
Loc_slide proc
.386p
push eax
mov ax, [si].trn_offset
cwde
mov ecx, eax
pop eax
.if <nonzero cx>
mov edx, [si].trn_ext_max
push ebx
.if <ecx lt 0> ; negative offset
mov ebx,ecx ; put OFFSET in bx
add ebx,eax ; add coord to offset
.if s ; if still negative
mov eax,0 ; back it up to 0 (but no more)
.else
mov ebx,edx ; put fixed extent in ebx
add ebx,ecx ; add the OFFSET to fixed extent
.if <eax gt ebx> ; If coord is greater than Offset+FixedExtent
; 2*X - Xm (when X=Xm, coord=extent)
add eax,eax ; slide area situation, double coord
sub eax,edx ; minus the fixed extent from coord
.else ; If coord is less than Offset+FixedExtent
add eax,ecx ; normal area
.endif
.endif
.else ; positive (or zero)
mov ebx,edx ; put extent in ebx
sub ebx,ecx ; ecx=OFFSET
.if <eax gt ebx> ; if coord greater than extent-OFFSET
mov eax,edx ; don't adjust past extent
.else
.if <eax lt ecx>
add eax,eax ; slide area
.else
add eax,ecx ; normal area
.endif
.endif
.endif
pop ebx
.endif
ret
Loc_slide endp
;------------------------------------------------------------------------------
; comput standard coordinate values
; bx = dcb
;------------------------------------------------------------------------------
public computeStd
computeStd proc
mov si,[bx].dcb_@RegCaps
mov di, [bx].dcb_@EiEvent
mov eax,[si].lcap_std_x_extent
imul [bx].dcb_LocNDCX
idiv [si].lcap_dev_x_extent
mov [di].lev_std_x,eax
mov eax,[si].lcap_std_y_extent
imul [bx].dcb_LocNDCY
idiv [si].lcap_dev_y_extent
mov [di].lev_std_y,eax
ret
computeStd endp
;------------------------------------------------------------------------------
; process state transitions. Figure out events and mouse buttons
; bx = dcb
;------------------------------------------------------------------------------
public stateMachine
stateMachine proc
mov di,[bx].dcb_@EiEvent
and [di].lev_cntrl,LOC_REL+LOC_ABS+LOC_FAKE
mov si,[bx].dcb_LocLastState
sal si,2
add si,[bx].dcb_LocNewState
jmp stateTable[si]
stateMachine endp
; this is a strange transition and isn't expected, but its OK
public clr_clr
clr_clr proc
mov [di].cev_devicebits, EV_MOVE
ret
clr_clr endp
; valid only for devices that report proximity
public clr_prx
clr_prx proc
mov [di].cev_devicebits, EV_MOVE + EV_ENTER_PROX
or [di].lev_cntrl,LOC_PROX
ret
clr_prx endp
; can't tell if this is a device that doesn't support proximity or just
; a quite touchdown, so we have to check the capabilities before reporting
; EV_ENTER_PROX
public clr_con
clr_con proc
call But_GetButtonShift
mov [bx].dcb_LocMouBut,al ; save for whole stroke
or [di].lev_cntrl,dx ; returned control information
call Dsp_GetSuppress
or [di].lev_cntrl,dx ; returned control information
mov ah,al
.if <bit [bx].dcb_LocFlags nz LOC_MOTION>
sar al,1
or al,ah
.endif
mov si,[bx].dcb_@regCaps
.if <bit [si].lcap_caps nz PENCAP_PROXIMITY>
or ax,EV_ENTER_PROX
.endif
mov [di].cev_devicebits, ax
or [di].lev_cntrl,LOC_CONTACT
ret
clr_con endp
public prx_clr
prx_clr proc
mov [di].cev_devicebits, EV_MOVE + EV_EXIT_PROX
ret
prx_clr endp
public prx_prx
prx_prx proc
mov [di].cev_devicebits, EV_MOVE
or [di].lev_cntrl,LOC_PROX
ret
prx_prx endp
public prx_con
prx_con proc
call But_GetButtonShift
mov [bx].dcb_LocMouBut,al ; save for whole stroke
or [di].lev_cntrl,dx ; returned control information
call Dsp_GetSuppress
or [di].lev_cntrl,dx ; returned control information
mov ah,al
.if <bit [bx].dcb_LocFlags nz LOC_MOTION>
sar al,1
or al,ah
.endif
mov [di].cev_devicebits, ax
or [di].lev_cntrl,LOC_CONTACT
ret
prx_con endp
; Could be quick lift off or a device that doesn't support proximity.
public con_clr
con_clr proc
mov al, EV_MOVE
mov ah,[bx].dcb_LocMouBut
mov si,[bx].dcb_@regCaps
.if <bit [si].lcap_caps nz PENCAP_PROXIMITY>
or ax,EV_EXIT_PROX
.endif
mov [di].cev_devicebits, ax
ret
con_clr endp
public con_prx
con_prx proc
mov al, EV_MOVE
mov ah,[bx].dcb_LocMouBut
mov [di].cev_devicebits, ax
or [di].lev_cntrl,LOC_PROX
ret
con_prx endp
public con_con
con_con proc
xor ah,ah
mov al,[bx].dcb_LocMouBut
.if <bit [bx].dcb_LocFlags nz LOC_MOTION>
sar al,1
.endif
mov [di].cev_devicebits, ax
or [di].lev_cntrl,LOC_CONTACT
ret
con_con endp
;------------------------------------------------------------------------------
; fill in locator event fields
; bx = dcb
;------------------------------------------------------------------------------
public fillEventBuffer
fillEventBuffer proc
; fill in EIQ locator position
mov di,[bx].dcb_@EiEvent
.386p
mov eax,[bx].dcb_LocNDCX
mov [di].lev_dev_x, eax
mov eax,[bx].dcb_LocNDCY
mov [di].lev_dev_y, eax
.286p
mov ax, [bx].dcb_LocNewZ
mov [di].lev_dev_z, ax
; finish off extended event packet
call But_GetButtons ; get buttons
mov [di].lev_buttons,ax
TraceAbs
ret
fillEventBuffer endp
;------------------------------------------------------------------------------
; update fields for next time
; bx = dcb
;------------------------------------------------------------------------------
public updateValues
updateValues proc
mov ax, [bx].dcb_LocNewState
mov [bx].dcb_LocLastState, ax
.386p
mov eax, [bx].dcb_LocNewX
mov [bx].dcb_LocLastX,eax
mov eax, [bx].dcb_LocNewY
mov [bx].dcb_LocLastY,eax
.286p
mov ax, [bx].dcb_LocNewZ
mov [bx].dcb_LocLastZ,ax
mov di,[bx].dcb_@EiEvent
mov ax, [di].lev_cntrl
mov [bx].dcb_LocLastCntrl,ax
ret
updateValues endp
;---- IOCTL ROUTINES ----------------------------------------------------------
;
;------------------------------------------------------------------------------
;------------------------------------------------------------------------------
; return next raw coordinate (used for calibration)
; edx = timeout value
; bx = dcb
; returns
; eax = dqlrc.rc
; ecx = dqlrc.xRaw
; edx = dqlrc.yRaw
;------------------------------------------------------------------------------
public Loc_qlrc
Loc_qlrc proc
.386p
; back sure only one guy doing this
xor al,al
xchg qlrc_sem,al ;set semaphore
or al,al
.if nz
mov eax,QLRC_BUSY ;someone already has it
.else
; wait for coordinates to be saved by interrupt handler in loc_engine
.repeat
DISABLE
or [bx].dcb_LocFlags,QLRC_REQUEST
push bx
mov cx,dx ; set up timeout value
shr edx,16
mov di,dx
lea bx,qlrc_sem ; set up block id
mov ax,ds
mov dh,0 ; allow interrupts
mov dl, DevHlp_ProcBlock
call Device_Help ; Invoke function
DISABLE
pop bx
.if c ; unusual wake up
mov eax, QLRC_TIMEOUT
and [bx].dcb_LocFlags,not QLRC_REQUEST
jmp short qlrc_done
.endif
.until <bit [bx].dcb_LocFlags z QLRC_REQUEST> ;make sure its our wakeup
mov eax,QLRC_VALID
; return last coordinates saved by interrupt handler in loc_engine
qlrc_done:
mov ecx, [bx].dcb_LocNewX
mov edx, [bx].dcb_LocNewY
ENABLE
mov qlrc_sem,0 ;clear reentry semaphore
.endif
ret
.286p
Loc_qlrc endp
;--- RUNS UNDER TIMER TICK HANDLER --------------------------------------------
;
;------------------------------------------------------------------------------
;------------------------------------------------------------------------------
; See if proximity or contact state has timed out. If so, return to clear.
; bx = dcb
; si = locator event packet
;------------------------------------------------------------------------------
public Loc_Tick
Loc_Tick proc
.if <[bx].dcb_LocLastState ne STATE_CLEAR>
inc [bx].dcb_StateTimeOut
.if <[bx].dcb_LocLastState eq STATE_PROX>
mov cx,[bx].dcb_TimeoutLimProx
.else
mov cx,[bx].dcb_TimeoutLimCont
.endif
.if <nonzero cx>
.if <[bx].dcb_StateTimeout gt cx> ;have we timed out waiting
call [bx].dcb_@Dev_ForceClear ;for Prox data???
.endif
.endif
.endif
ret
Loc_Tick endp
;---- DEFAULT DCB@ ROUTINES ---------------------------------------------------
;
;------------------------------------------------------------------------------
;------------------------------------------------------------------------------
; force to clear state after either prox or contact state timed out
; bx = dcb for this device
;------------------------------------------------------------------------------
public Loc_ForceClear
Loc_ForceClear proc
GetCritSec [bx].dcb_Sem1
.if z
mov [bx].dcb_LocNewState, STATE_CLEAR
.386p
mov eax,[bx].dcb_LocLastX ;Use last position
mov [bx].dcb_LocNewX,eax
mov eax,[bx].dcb_LocLastY
mov [bx].dcb_LocNewY,eax
.286p
mov ax,[bx].dcb_LocLastZ
mov [bx].dcb_LocNewZ,ax
mov di,[bx].dcb_@EiEvent ; set cntrl
mov ax,[bx].dcb_LocLastCntrl
and ax,LOC_ABS+LOC_REL
or ax,LOC_FAKE
mov [di].lev_cntrl, ax
call Loc_Engine ; bx = dcb
; di = event
.endif
ClearCritSec [bx].dcb_Sem1
ret
Loc_ForceClear endp
;---- BOX FILTRER ROUTINES ----------------------------------------------------
;
;------------------------------------------------------------------------------
.386p
;------------------------------------------------------------------------------
; see if the location has moved out the the 'box', if not, then use old
; cooridinates. This must be done before coordinate normalization in case we
; are going to use the last raw coordinates
;
; This routine is called directly from the device dependent routine before
; calling the locator engine.
;
; note: box_flags bit BOX_SMOOTH should be ON if calling to smooth contact pts
;
; bx = dcb
; di = box struc
; returns
; cx == 0 in the box, New coordinates updated to last values
; != 0 out of the box
;------------------------------------------------------------------------------
public Loc_BoxFilter
Loc_BoxFilter proc
xor cx,cx
mov eax, [bx].dcb_LocNewX ; check if x is in the box
sub eax, [di].box_LocLastX
.if s
neg eax
.endif
.if <[di].box_Size lt eax>
inc cx
.endif
mov eax, [bx].dcb_LocNewY ; check if y is in the box
sub eax, [di].box_LocLastY
.if s
neg eax
.endif
.if <[di].box_Size lt eax>
inc cx
.endif
; if its out of the box, update the box for the next area
.if <nonzero cx>
mov eax, [bx].dcb_LocNewX
mov [di].box_LocLastX, eax
mov eax, [bx].dcb_LocNewY
mov [di].box_LocLastY, eax
; if its in the box, then use the
; old raw coordinates so the box does not drift.
.elseif <bit [di].box_flags nz BOX_SMOOTH>
mov eax, [di].box_LocLastX
mov [bx].dcb_LocNewX, eax
mov eax, [di].box_LocLastY
mov [bx].dcb_LocNewY, eax
.endif
ret
Loc_BoxFilter endp
;------------------------------------------------------------------------------
; This routine is called directly from the device dependent routine before
; calling the locator engine. This routine can filters out proximity
; that do not change, for example, a pen left on the digitizer.
;
; note: box_flags bit BOX_SMOOTH should probably be off for filtering prox pts
;
; Inorder of this to work right, the caller should be calling Loc_ProxFilterTC
; on each timer tick from the device dependent tick count routine.
;
; bx = dcb
; di = box structure
; returns
; cx == 0 ignore proximity point
; != 0 pass on prox point
;------------------------------------------------------------------------------
public Loc_ProxFilter
Loc_ProxFilter proc
mov [di].box_ClearCnt, 0 ; used to clear box after prox pts
call Loc_BoxFilter
.if <nonzero cx> ; out of the box
mov [di].box_TickCount,0
.else
mov ax,[di].box_TickCount
.if <ax lt [di].box_TickLimit>
inc cx
.endif
.endif
ret
Loc_ProxFilter endp
;------------------------------------------------------------------------------
; This routine is called directly from the device dependent routine from
; the device dependent tick routine. It works with Loc_ProxFilter to filter
; out proximity points that do not change.
;
; bx = dcb
; di = box structure
; returns
;------------------------------------------------------------------------------
public Loc_ProxFilterTC
Loc_ProxFilterTC proc
mov cx,[di].box_ClearCnt
inc cx
.if <cx lt [bx].dcb_TimeoutLimProx> ; haven't seen a prox latly
mov [di].box_ClearCnt,cx
mov ax,[di].box_TickCount
.if <ax lt [di].box_TickLimit>
inc [di].box_TickCount
.endif
.else
mov [di].box_LocLastX, -1 ; make sure next prox is not 'in the box'
.endif
ret
Loc_ProxFilterTC endp
.286p
CSEG ends
;---- INITIALIZATION ROUTINES -------------------------------------------------
;
; note: this code is truncated from the driver after the INIT command returns
; to OS/2
;------------------------------------------------------------------------------
;------------------------------------------------------------------------------
; Initialize engine
; bx = dcb
;------------------------------------------------------------------------------
CSEGI segment
public Loc_Init
Loc_Init proc
mov [bx].dcb_LocLastState, STATE_CLEAR
mov [bx].dcb_StateTimeout,0
mov [bx].dcb_@Dev_DTTick, offset Loc_Tick
; set the following default handlers
.if <[bx].dcb_@Dev_ForceClear eq 0>
mov [bx].dcb_@Dev_ForceClear, offset Loc_ForceClear
.endif
.if <[bx].dcb_@Adjust eq 0>
mov [bx].dcb_@Adjust, offset AdjustCoords
.endif
; do some error checking on the device dependent set up
.386p
mov si,[bx].dcb_@RegCaps
lea di, [bx].dcb_Xtrans ; check X extents
call Loc_chk_exts
.if <[si].lcap_dev_x_extent eq 0>
mov [si].lcap_dev_x_extent, eax
PANIC PANIC_EXTZERO
.endif
lea di, [bx].dcb_Ytrans ; check Y extents
call Loc_chk_exts
.if <[si].lcap_dev_y_extent eq 0>
mov [si].lcap_dev_y_extent, eax
PANIC PANIC_EXTZERO
.endif
mov ax,[si].lcap_sample_rate ; check rates
.if <zero ax>
mov ax,FAKE_SAMPLE_RATE
mov [si].lcap_sample_rate,ax
PANIC PANIC_RATEZERO
.endif
.if <[si].lcap_max_sample_rate eq 0>
mov [si].lcap_max_sample_rate,ax
PANIC PANIC_RATEZERO
.endif
.286p
ret
Loc_Init endp
;------------------------------------------------------------------------------
; check extents
; di = trn
; returns
; eax = default extent
;------------------------------------------------------------------------------
public Loc_chk_exts
Loc_chk_exts proc
.386p
mov eax,[di].trn_ext_max_PM
.if <zero eax>
mov eax, FAKE_EXTENT
mov [di].trn_ext_max_PM, eax
PANIC PANIC_EXTZERO
.endif
.if <[di].trn_ext_max eq 0>
mov [di].trn_ext_max, eax
PANIC PANIC_EXTZERO
.endif
.if <[di].trn_ext_adj eq 0>
mov [di].trn_ext_adj, eax
PANIC PANIC_EXTZERO
.endif
.if <[di].trn_ext_adj_default eq 0>
mov [di].trn_ext_adj_default, eax
PANIC PANIC_EXTZERO
.endif
.if <[di].trn_ext_adj_calibrated eq 0>
mov [di].trn_ext_adj_calibrated, eax
PANIC PANIC_EXTZERO
.endif
.286p
ret
Loc_chk_exts endp
CSEGI ends
end