;*DDK*************************************************************************/
;
; COPYRIGHT (C) Microsoft Corporation, 1989
; 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.;
;*****************************************************************************/
     Page  58,132
     Title   KBDMSE - Kbd Device Driver Mouse Interface Code
     Name    KBDMSE

;/*************************************************************************
;*
;* SOURCE FILE NAME = KBDMSE.ASM
;*
;* DESCRIPTIVE NAME = Physical Keyboard Device Driver Mouse Interface
;*                    code.
;*
;* VERSION      V2.0
;*
;* DATE         11/17/90
;*
;* DESCRIPTION  All Mouse interface code for Alternate Input Methods Support
;*
;* FUNCTIONS    AttachToMouse()    Attach to MOUSE$ for special needs support.
;*              QueryMouse()       Query for any mouse activity.
;*
;* NOTES        DEPENDENCIES:  None.
;*
;*              RESTRICTIONS:  Machine must be a 386 or compatible with a 386.
;*
;*
;* STRUCTURES   NONE
;*
;* EXTERNAL REFERENCES
;*
;*              NONE
;*
;* EXTERNAL FUNCTIONS
;*
;*              NONE
;*
;* CHANGE ACTIVITY =
;*   DATE      FLAG        APAR   CHANGE DESCRIPTION
;*   --------  ----------  -----  --------------------------------------
;*   mm/dd/yy  @Vr.mpppxx  xxxxx  xxxxxxx
;*   03/08/93              60343  PenPM support changes
;*                         B730591
;*
;**************************************************************************


.286p
.sall
.xcref
.xlist
  Include       mvdm.inc                ;          
  Include       struc.inc               ;Structured assembly macros.
  Include       devhlp.inc              ;DevHlp & Signal equates, char queue structure.
  Include       devsym.inc              ;Device driver header definitions.
  Include       kbdseg.inc              ;Segment definitions.
  Include       kbdddr.inc              ;Keyboard Device Driver structures & equates.
  Include       infoseg.inc             ;InfoSeg structure.
  Include       basemaca.inc            ;DOS system macros.
  Include       kbdaim.inc              ;AIM
  Include       vkbdpdd.inc             ;VKBD to PDD communication structs
.list

;* External Routines

  Extrn AccessKCB         :Near

;* External Variables

  Extrn MSEDDname         :Word
  Extrn MSEDDpds          :Word
  Extrn MSEFilterHdl      :Word
  Extrn MSEStickyHdl      :Word
  Extrn MSEFilterStatus   :Word
  Extrn MSEStickyStatus   :Word

  Extrn MSEDDrm@          :DWord
  Extrn MSEDDpm@          :DWord
  Extrn DeviceHelp        :DWord
  Extrn AIMFlags          :Word         ;AIM

  Extrn IntCount          :DWord         ; PEN SUPPORT
  Extrn CallBack          :Byte          ; PEN SUPPORT
  Extrn IDC_Write         :Word          ; PEN SUPPORT
  Extrn PenHotKeyAE       :Word          ; PEN SUPPORT
  Extrn PenHotKeyCE       :Word          ; PEN SUPPORT
  Extrn PenBreakEsc       :Word          ; PEN SUPPORT
  Extrn SInfoSeg          :Word          ; PEN SUPPORT
  Extrn CurSG             :Word          ; PEN SUPPORT
  Extrn PSGPointers       :Word          ; PEN SUPPORT
  Extrn SQHotKeyData      :Byte          ; PEN SUPPORT
  Extrn IntFlags          :Byte          ; PEN SUPPORT
  Extrn KeyPacket1        :Word          ; PEN SUPPORT
  Extrn PutInSQB          :Near          ; PEN SUPPORT
  Extrn HKBypass          :Dword         ; PEN SUPPORT           
  Extrn PDDtoVDDSCPkt     :Word          ; PEN SUPPORT           
  Extrn SendVDDSC         :Near          ; PEN SUPPORT           

Code Segment
Assume  CS:Code,DS:DGROUP,ES:Nothing


;**********************************************************************
;*
;* FUNCTION NAME  AttachToMouse
;*
;* DESCRIPTION    Attach to MOUSE$ for special needs support.
;*
;*       This routine will call DevHlp_AttachDD to get the address of the
;*       Inter-Device Driver Communication (IDC) Entry point to MOUSE$.
;*       This entry point is needed so we can call the MOUSE driver with
;*       the Query_Activity (0006h) function.
;*
;* INPUT       DS = Base Keyboard Device Driver Data Selector.
;*
;*             CX = 0   if caller needs handle for Filter Key processing.
;*                  1   if caller needs handle for Sticky Key processing.
;*
;* Exit-normal  Carry Flag clear. Link is now in place to call the
;*              mouse device driver.
;*
;*              MSE*****Hdl = Handle returned by MOUSE$ on the
;*                 Filter     Open_Mouse IDC call. This handle
;*                  or        is needed for all other IDC calls
;*                 Sticky     to MOUSE$.
;*
;* Exit-error   Carry Flag set. Either the DevHlp_AttachDD failed
;*              or the Open_Mouse call failed. In either cases we
;*              simply consider this to be a configuration with no
;*              mouse support.
;*
;* Effects      Flags, ALL registers are preserved.
;*
;* Internal Calls: None.
;*
;* External Calls: DevHlp (AttachDD)
;*
;**********************************************************************
;* PSEUDOCODE
;*
;* Load the address of MOUSE$ string in BX
;* Load the address of the CB that will be filled by DevHlp in DI
;* Call DevHlp_AttachDD
;* If SUCCESSFUL
;*    Load Open_Mouse function # in AX
;*    Load KBD$ data selector value in ES
;*    Load MOUSE$ data selector value in DS
;*    Call MOUSE DD
;*    If SUCCESSFUL
;*       Save returned MSE handle value in (MouseHandle)
;*       Set bit that mouse is in use
;* Return
;**********************************************************************

Public   AttachToMouse
AttachToMouse Proc Far

      pusha
      Push    CX                            ;AIM  Save indicator of who is calling
      lea     bx, MSEDDname                 ;AIM  MSEDDname points to MOUSE$ string
      lea     di, MSEDDrm@                  ;AIM  Start of the IDC CB for MSE
      mov     dl, DevHlp_AttachDD           ;AIM
      Call    DeviceHelp                    ;AIM
      Pop CX                                ;AIM  Restore caller indicator
     .if <nc>                               ;AIM  If no error continue
        SaveReg<es,ds>                      ;AIM
        mov     ax, OPEN_MOUSE              ;AIM  Open_Mouse command
        push    ds                          ;AIM  KBD$ data selector
        pop     es                          ;AIM  needed in ES for IDC call.
        mov     ds, MSEDDpds                ;AIM  MOUSE$ data selector
        call    dword ptr es:MSEDDpm@       ;AIM  Call Mouse DD
        RestoreReg<ds,es>                   ;AIM
        .if <nc>                            ;AIM
           .if <CX eq 0>
               mov word ptr MSEFilterHdl, bx
           .else
               mov word ptr MSEStickyHdl, bx
           .endif
            or AIMFlags, MouseIDC           ;AIM  Indicate Mouse IDC exists
        .endif                              ;AIM
     .endif                                 ;AIM
     popa                                   ;AIM
     ret                                    ;AIM  Return

AttachToMouse Endp


;**********************************************************************
;*
;* FUNCTION NAME   QueryMouse
;*
;* DESCRIPTION     Query for any mouse activity.
;*
;*
;*           This routine will call the Mouse Device Driver via the (IDC) to
;*           query mouse activity. The activity returned is in relation to
;*           the last time this call was made. The first time this call is
;*           made the activity returned is the mouse activity that took place
;*           since the Open_Mouse call was issued for this handle.
;*
;*
;* INPUT     DS = Base Keyboard Device Driver Data Selector.
;*
;* Exit-normal  Carry Flag clear.
;*
;*              MouseStatus is updated.
;*
;*              Where,
;*
;*              The bit definitions are as follows;
;*
;*              BITS    DESCRIPTION
;*              15-11   Reserved = 0
;*               10     Button 5 usage, w/o motion
;*                9     Button 5 usage, w/ motion
;*                8     Button 4 usage, w/o motion
;*                7     Button 4 usage, w/ motion
;*                6     Button 3 usage, w/o motion
;*                5     Button 3 usage, w/ motion
;*                4     Button 2 usage, w/o motion
;*                3     Button 2 usage, w/ motion
;*                2     Button 1 usage, w/o motion
;*                1     Button 1 usage, w/ motion
;*                0     Pure motion was recorded
;*
;* Exit-error   Carry Flag set.
;*
;*              Either the DevHlp_AttachDD failed or the Open_Mouse
;*              call failed. In either cases we simply consider this
;*              a no mouse system.
;*
;* Effects  Flags, ALL registers are preserved.
;*
;* Internal Calls  None.
;*
;* External Calls  MOUSE$ IDC function (0006h) - Query_Mouse
;*
;* PSEUDOCODE  =
;*
;* If Mouse IDC exists
;*   Load Query_Mouse function # in AX
;*   Load MouseHandle in BX
;*   Load KBD$ data selector value in ES
;*   Load MOUSE$ data selector value in DS
;*   Call MOUSE DD
;*   If SUCCESSFUL
;*     Save returned statue value in (MouseStatus)
;*   Endif
;* Else
;*   Put no movement value in MouseStatus
;* Endif
;*
;* Return
;**********************************************************************

Public QueryMouse
QueryMouse  Proc Far

 pusha
 Push    CX                                ;AIM  Save caller (sticky or filter)
.if <bit AIMFlags nz MouseIDC>             ;AIM  If mouse IDC exists
  SaveReg<es,ds>                           ;AIM
  mov  ax, QUERY_MOUSE                     ;AIM  Query_Mouse command.
 .if <CX eq 0>
      mov  bx, MSEFilterHdl                ;AIM  Needed for all other Mouse IDC calls.
 .else
      mov  bx, MSEStickyHdl                ;AIM  Needed for all other Mouse IDC calls.
 .endif
  push ds                                  ;AIM  Save KBD$ data selector.
  pop  es                                  ;AIM  needed in ES for IDC call.
  mov  ds, MSEDDpds                        ;AIM  Get Mouse data selector
  call dword ptr es:MSEDDpm@               ;AIM  Call Mouse DD
  RestoreReg<ds,es>                        ;AIM
  Pop CX                                   ;AIM  Restore caller indicator
 .if <nc>                                  ;AIM  If no error
     .if <CX eq 0>
         mov word ptr MSEFilterStatus, bx
     .else
         mov word ptr MSEStickyStatus, bx
     .endif
 .endif                                    ;AIM  Endif
.else                                      ;AIM  Else
  Pop CX                                   ;AIM
  xor bx, bx                               ;AIM  Clear out bx
 .if <CX eq 0>
      mov word ptr MSEFilterStatus, bx
 .else
      mov word ptr MSEStickyStatus, bx
 .endif
.endif                                     ;AIM  Endif
 popa                                      ;AIM
                                           ;AIM
 ret                                       ;AIM  Return

QueryMouse Endp


;*************************************************
;*         PEN SUPPORT                           *
;*************************************************

Public PENIDC
PENIDC  Proc Near

;**
;**     INPUT:  AX = Function code
;**             DS = Our data segment selector
;**             ES = callers data segment selector
;**             DI = index to SINFO data structure
;**

.386p
    push     bx
    push     ax
   .if <al eq 01>                        ; Read Enable?
      lea     bx, IDC_Write
     .if < [bx].sinfo_service_ds eq 0 >
       mov     ax, es:[di].sinfo_service_ds
       mov     [bx].sinfo_service_ds, ax

       mov     ax, word ptr es:[di].sinfo_service_rtn
       mov     word ptr [bx].sinfo_service_rtn, ax
       mov     ax, word ptr es:[di].sinfo_service_rtn+2
       mov     word ptr [bx].sinfo_service_rtn+2, ax
       clc
     .else                               ; indicate an error
       stc
     .endif

   .elseif <al eq 02>                    ; Query keyboard activity ?
      mov edx, IntCount                  ; get the latest count of incoming interrupts
      clc
   .elseif <al eq 03>                    ; Request callback when key is pressed.
      or CallBack, 01                    ; set flag
      clc
   .elseif <al eq 04> near               ; Request PEN HOT KEY EMULATION
      push si
      push es
      Mov  ES,[SInfoSeg]                 ; Get System Info Segment.
     .if <bx eq 2>                       ; If Hot Key ID is 2
        mov  si, offset PenHotKeyAE      ; Get Alt+Esc scan code values
     .elseif <bx eq 1>                   ; If Hot Key ID is 1
        mov  si, offset PenHotKeyCE      ; Get Ctrl+Esc scan code values
     .else
        pop es
        pop si
        jmp BadReq
     .endif
      push di
      Mov  CX,CurSG                          ; Set SG number for use by KbdXlate.
     .If <CX ge sgidFirstVDM>                ; If a VDM SGID
        Mov CX,Dos3xBoxSG                    ; We use SG 2 for VDMs
     .Endif                                  ; Set up cx
      Mov DI,CX                              ; Get Current Screen Group Number
      Shl DI,1                               ; Make it an offset
      Mov DI,[PSGPointers+DI]                ; Get Pointer to this SGs PSG
     .If <bit [DI].PSGFlags nz SQMODE>       ; If in PM ......
         call EmulHotKey                     ; Emulate a Alt or Ctrl Key MAKE
         add  si, KeyPacketLen               ; Point to next record
         call EmulHotKey                     ; Emulate a Esc Key MAKE
         mov  ah, 6                          ; Session manager hot key
         mov  dl, DevHlp_SendEvent           ; Issue a Hot Key event
         call DeviceHelp
         add  si, KeyPacketLen               ; Point to next record
         call EmulHotKey                     ; Emulate a Esc Key BREAK
         add  si, KeyPacketLen               ; Point to next record
         call EmulHotKey                     ; Emulate a Alt or Ctrl Key BREAK
     .elseif < CX eq Dos3xBoxSG >            ; If we are in a VDM
                                             ; VDM's allow for bypassing OS/2
                                             ; defined hotkeys. We now check this:
            .if <bit HKBypass nz 01> AND     ; If Alt+Esc bypass bit set
            .if <bx eq 2>                    ; If Alt+Esc hot key event
              jmp VDMBypass                  ; DON'T DO IT.  BYPASS IS SET IN
            .endif                           ; DOS SETTINGS.
            .if <bit HKBypass nz 02> AND     ; If Ctrl+Esc bypass bit set
            .if <bx eq 1>                    ; If Ctrl+Esc hot key event
              jmp VDMBypass                  ; DON'T DO IT.  BYPASS IS SET IN
            .endif                           ; DOS SETTINGS.
             jmp IssueEvent                  ; Otherwise go issue the sendevent
VDMBypass:                                   ; jump here if VDM HotKey Bypass
         call VDMEmulHotKey                  ; Emulate a Alt or Ctrl Key MAKE
         add si, KeyPacketLen                ; Point to next record
         call VDMEmulHotKey                  ; Emulate a Esc Key MAKE
         add si, KeyPacketLen                ; Point to next record
         call VDMEmulHotKey                  ; Emulate a Esc Key BREAK
         add si, KeyPacketLen                ; Point to next record
         call VDMEmulHotKey                  ; Emulate a Alt or Ctrl Key BREAK

     .else                                   ; Else- just issue the event
IssueEvent:
         push es                             ; Save SInfoSeg for a bit
         push ds                             ; put ds --
         pop  es                             ;      -->  into es!
         lea  si, PenBreakEsc                ; See kbddata.asm for more info!
         lea  di,KeyPacket1                  ; Get address of KeyPacket1
         mov  cx, KeyPacketLen               ; 
         cld                                 ; 
         rep  movsw                          ; copy data into keypacket1
                                             ; because SGController makes call
                                             ; to putinSQB when session switches
         pop  es                             ; Now we get SInfoSeg back!
         Mov  CX,Word Ptr ES:[SIS_MsCount]   ; Fill in the timestamp crap
         Mov  Word Ptr [SI].Key.Time,CX      ; Save in Key record.
         Mov  CX,Word Ptr ES:[SIS_MsCount+2] ; 
         Mov  Word Ptr [SI].Key.Time+2,CX    ; Save in Key record.
         mov  ah, 6                          ; Session manager hot key
         mov  dl, DevHlp_SendEvent           ; Issue a Hot Key event
         call DeviceHelp                     ; 
     .endif
      pop  di
      pop  es
      pop  si
      clc
   .else                                     ; unknown request
BadReq:                                      ; 
      stc                                    ; indicate error
   .endif                                    ; end
Done:
    pop ax
    pop bx
    ret

.286p

PENIDC  Endp

Public EmulHotKey
EmulHotKey Proc near

;*   Input es= sinfoseg
;*         si= pointer to key packet (scan code and flags structure)

      push   si
      push   cx
      push   es                              ; es and bx get destroyed
      push   bx
      And    IntFlags, NOT Up_LEDs           ; Turn off UP_LEDs Full Screen flag
     .If <bit SQHotKeyData nz 03>            ;            ,If nonzero
        push   si
        Call   PutInSQB                      ; Call SingleQ DD with Hot Key Info
        pop    si
     .Endif                                  ; Endif
      Mov    CX,Word Ptr ES:[SIS_MsCount]    ; Get first two bytes of timestamp.
      Mov    Word Ptr [SI].Key.Time,CX       ; Save in Key record.
      Mov    CX,Word Ptr ES:[SIS_MsCount+2]  ; Get second two bytes.
      Mov    Word Ptr [SI].Key.Time+2,CX     ; Save in Key record.
      Call   PutInSQB
      pop    bx
      pop    es
      pop    cx
      pop    si
      Ret
EmulHotKey Endp

Public VDMEmulHotKey
VDMEmulHotKey Proc near

;*   Input es= sinfoseg
;*         si= pointer to key packet (scan code and flags structure)

    and IntFlags, NOT Up_LEDs                ; Do not update LEDs for VDM SG
   .If <bit AIMFlags z ConsumeScan> AND      ; If we aren't supposed to consume
                                             ;  this scan for sticky keys, AND
   .If <bit IntFlags z Not_VScan>            ; If the scan can be sent to VKBD
        Xor AH,AH                            ; SC is put in low nib
        Mov AL,Byte Ptr [SI].KPacketLen+1    ; Get scan code
        Mov PDDtoVDDSCPkt.kint_chScan,AX     ; Pkt at XLateRetry
        Mov BX,CurSG                         ; Get screen group ID
        Mov PDDtoVDDSCPkt.kint_usSGID,BX     ; Put SGID code in VDDs packet
        Call SendVDDSC                       ; Send the scan code to the VDD
   .Endif                                    ; Endif scan not to be sent to VKBD
    And IntFlags, Not Not_VScan              ; Turn off bit for VKBD scans.
    Ret

VDMEmulHotKey Endp

Code Ends
     End
