/* SCCSID = "%W% %E%" */
/*
*   IBM Confidential
*
*   OCO Source Materials
*
*   (c) Copyright IBM Corp. 1998
*
*   The source code for this program is not published or otherwise divested of its
*   tradesecrets, irrespective of what has been deposited with the U.S. Copyright Office.
*/

/************************** START OF SPECIFICATIONS ***************************/
/*                                                                            */
/*   SOURCE FILE NAME:  KBDUSB.C                                              */
/*                                                                            */
/*   DESCRIPTIVE NAME:  USB Keyboard Client support routines                  */
/*                                                                            */
/*   FUNCTION:                                                                */
/*                                                                            */
/*   NOTES:                                                                   */
/*      DEPENDENCIES: None                                                    */
/*      RESTRICTIONS: None                                                    */
/*                                                                            */
/*   ENTRY POINTS:                                                            */
/*                                                                            */
/*   EXTERNAL REFERENCES:                                                     */
/*                                                                            */
/* Change Log                                                                 */
/*  Mark    yy/mm/dd  Programmer      Comment                                 */
/*  ----    --------  ----------      -------                                 */
/*          98/06/30  LR                                                      */
/*                                                                            */
/**************************** END OF SPECIFICATIONS ***************************/

#define   KBDUSB
#include "kbdusb.h"

#include "usbchid.h"

#include "kbd.h"
#include "kbddd.h"

/********************** START OF SPECIFICATIONS ***********************/
/*                                                                    */
/* SUBROUTINE NAME:  USBCallIDC                                       */
/*                                                                    */
/* DESCRIPTIVE NAME:  Calls IDC routine                               */
/*                                                                    */
/* FUNCTION:  The function of this routine is calling specific IDC    */
/*            routine, setting required DS value and passing  request */
/*            block address as parameter.                             */
/*                                                                    */
/* NOTES:                                                             */
/*                                                                    */
/* CONTEXT: Task time                                                 */
/*                                                                    */
/* ENTRY POINT:  USBCallIDC                                           */
/*    LINKAGE:  CALL NEAR                                             */
/*                                                                    */
/* INPUT:  PUSBIDCEntry idcEntry - far pointer to IDC routine         */
/*         USHORT callingDS - IDC routine data segment                */
/*         RP_GENIOCTL FAR *pRP - far pointer to parameter block      */
/*                                                                    */
/* EXIT-NORMAL: N/A                                                   */
/*                                                                    */
/* EXIT-ERROR:  N/A                                                   */
/*                                                                    */
/* EFFECTS: none                                                      */
/*                                                                    */
/* INTERNAL REFERENCES:  None                                         */
/*                                                                    */
/* EXTERNAL REFERENCES:  None                                         */
/*                                                                    */
/************************ END OF SPECIFICATIONS ***********************/

void USBCallIDC( PUSBIDCEntry idcEntry, USHORT callingDS, RP_GENIOCTL FAR *pRP )
{
   USHORT         currDS;

   if (idcEntry && callingDS && pRP)
   {
      _asm
      {
         mov   currDS,ds
         mov   ds,callingDS
         push  WORD PTR pRP+2
         push  WORD PTR pRP
         call  idcEntry
         add   sp,4
         mov   ds,currDS
      }
   }
   return;
}

/******************* START OF SPECIFICATIONS **************************/
/*                                                                    */
/* SUBROUTINE NAME:  ProcUSBIRQ                                       */
/*                                                                    */
/* DESCRIPTIVE NAME:  Process USB keyboard IRQs                       */
/*                                                                    */
/* FUNCTION:                                                          */
/*                                                                    */
/* NOTES:                                                             */
/*                                                                    */
/* CONTEXT:                                                           */
/*                                                                    */
/* ENTRY POINT :  ProcUSBIRQ                                          */
/*    LINKAGE  :                                                      */
/*                                                                    */
/* INPUT:  RP_GENIOCTL FAR *prp                                       */
/*                                                                    */
/* EXIT-NORMAL:  KBD IDC RC OK                                        */
/*                                                                    */
/* EXIT-ERROR:  device driver error code                              */
/*                                                                    */
/* EFFECTS:  None                                                     */
/*                                                                    */
/* INTERNAL REFERENCES:                                               */
/*    ROUTINES:                                                       */
/*                                                                    */
/* EXTERNAL REFERENCES:  None                                         */
/*    ROUTINES:                                                       */
/*                                                                    */
/******************* END  OF  SPECIFICATIONS **************************/

void ProcUSBIRQ (RP_GENIOCTL FAR *prp)
{
   USBRB FAR *pRB;
   BYTE  FAR *pScanCode;

   pRB = (USBRB FAR *)prp->ParmPacket;
   pScanCode = (BYTE FAR *)&pRB->requestData3;

#ifdef DEBUG
   dsPrint2 (DBG_IRQFLOW, "IBMKBD: ProcUSBIRQ, Scan Codes = 0x%x, 0x%x\r\n",
             pScanCode[0], pScanCode[1]);
#endif

   SendPacket (pScanCode[0], pScanCode[1]);

   prp->rph.Status = USB_IDC_RC_OK;
}

/******************* START OF SPECIFICATIONS **************************/
/*                                                                    */
/* SUBROUTINE NAME:  RegisterUSB                                      */
/*                                                                    */
/* DESCRIPTIVE NAME:  Register USB keyboard driver                    */
/*                                                                    */
/* FUNCTION:  This IDC routine registers USB keyboard driver.         */
/*                                                                    */
/* NOTES:                                                             */
/*                                                                    */
/* CONTEXT:                                                           */
/*                                                                    */
/* ENTRY POINT :  RegisterUSB                                         */
/*    LINKAGE  :                                                      */
/*                                                                    */
/* INPUT:  RP_GENIOCTL FAR *prp                                       */
/*                                                                    */
/* EXIT-NORMAL:  KBD IDC RC OK                                        */
/*                                                                    */
/* EXIT-ERROR:  device driver error code                              */
/*                                                                    */
/* EFFECTS:  None                                                     */
/*                                                                    */
/* INTERNAL REFERENCES:                                               */
/*    ROUTINES:                                                       */
/*                                                                    */
/* EXTERNAL REFERENCES:  None                                         */
/*    ROUTINES:                                                       */
/*                                                                    */
/******************* END  OF  SPECIFICATIONS **************************/

void RegisterUSB (RP_GENIOCTL FAR *prp)
{
   USBRegClient FAR *pRegData;

   pRegData = (USBRegClient FAR *)prp->ParmPacket;

   gpUSBIDC  = pRegData->clientIDCAddr;
   gdsUSBIDC = pRegData->clientDS;

   gLegKbd = (BYTE)!prp->sfn;
   if (!gLegKbd)
   {
      if (!DisableFlag)
      {                      // keyboard not already disabled
         _asm CLI;
         if (KbdStatusWait())
         {               // make sure keyboard is ready
            outp (PORT_CMD, CMD_DISABLEKBD); // disable legacy keyboard
            DisableFlag = TURNON;            // show that it is disabled
            _asm STI;
         }
         _asm STI;
      }
      if (DevHelp_UnSetIRQ (KBD_IRQ))
      {

#ifdef DEBUG
         dsPrint (DBG_CRITICAL, "IBMKBD: DevHelp_UnSetIRQ ERROR\r\n");
#endif
      }
   }
   prp->rph.Status = USB_IDC_RC_OK;
}

/******************* START OF SPECIFICATIONS **************************/
/*                                                                    */
/* SUBROUTINE NAME:  USB_IDCfunc                                      */
/*                                                                    */
/* DESCRIPTIVE NAME:  Legacy keyboard driver IDC routines for USB     */
/*                                                                    */
/* FUNCTION:  This routine is the legacy keyboard driver IDC          */
/*            router/handler for USB. IDC function requests are       */
/*            routed to the appropriate worker routine.               */
/* NOTES:                                                             */
/*                                                                    */
/* CONTEXT: Task Time                                                 */
/*                                                                    */
/* ENTRY POINT :  USB_IDCfunc                                         */
/*    LINKAGE  :                                                      */
/*                                                                    */
/* INPUT:  RP_GENIOCTL FAR *pRP_GENIOCTL                              */
/*                                                                    */
/* EXIT-NORMAL:  KBD IDC RC OK                                        */
/*                                                                    */
/* EXIT-ERROR:  device driver error code                              */
/*                                                                    */
/* EFFECTS:  None                                                     */
/*                                                                    */
/* INTERNAL REFERENCES:                                               */
/*    ROUTINES:                                                       */
/*                                                                    */
/* EXTERNAL REFERENCES:  None                                         */
/*    ROUTINES:                                                       */
/*                                                                    */
/******************* END  OF  SPECIFICATIONS **************************/

void USB_IDCfunc (USHORT RP_Offset, USHORT RP_Segment)
{
   RP_GENIOCTL FAR *prp;

   prp = MK_FP (RP_Segment, RP_Offset);

#ifdef DEBUG
   dsPrint1 (DBG_HLVLFLOW, "IBMKBD: USB IDC Function = %x\r\n", prp->Function);
#endif

   switch (prp->Function)
   {
   case USB_IDC_FUNCTION_REGISTER:
      RegisterUSB (prp);
      break;
   case USB_IDC_FUNCTION_PRCIRQ:
      ProcUSBIRQ (prp);
      break;
   case USB_IDC_FUNCTION_CHKSERV:
      gUSBKbd = TURNON;
      SetUSBLEDs (LED_State);
      SetUSBTypematic (Type_Rate);
      break;
   case USB_IDC_FUNCTION_DETDEV:
      gUSBKbd = TURNOFF;
      break;
   default:
      prp->rph.Status = USB_IDC_RC_WRONGFUNC;
   }
#ifdef DEBUG
   dsPrint1 (DBG_HLVLFLOW, "IBMKBD: USB IDC Status = %x\r\n", prp->rph.Status);
#endif
}
/******************* START OF SPECIFICATIONS **************************/
/*                                                                    */
/* SUBROUTINE NAME:  SetUSBLEDs                                       */
/*                                                                    */
/* DESCRIPTIVE NAME:                                                  */
/*                                                                    */
/* FUNCTION:                                                          */
/*                                                                    */
/* NOTES:                                                             */
/*                                                                    */
/* CONTEXT:                                                           */
/*                                                                    */
/* ENTRY POINT :  ProcUSBIRQ                                          */
/*    LINKAGE  :                                                      */
/*                                                                    */
/* INPUT:  RP_GENIOCTL FAR *prp                                       */
/*                                                                    */
/* EXIT-NORMAL:  KBD IDC RC OK                                        */
/*                                                                    */
/* EXIT-ERROR:  device driver error code                              */
/*                                                                    */
/* EFFECTS:  None                                                     */
/*                                                                    */
/* INTERNAL REFERENCES:                                               */
/*    ROUTINES:                                                       */
/*                                                                    */
/* EXTERNAL REFERENCES:  None                                         */
/*    ROUTINES:                                                       */
/*                                                                    */
/******************* END  OF  SPECIFICATIONS **************************/

USHORT SetUSBLEDs (BYTE NewLEDState)
{
   RP_GENIOCTL rp;     // GENeric IOCTL Request Packet
   USBLegIO    kbdata;

#ifdef DEBUG
   dsPrint1 (DBG_DETAILED, "IBMKBD: SetUSBLEDs, NewLEDState = %x\r\n", NewLEDState);
#endif
//    setmem ((PSZ)&rp, 0, sizeof(rp));
   rp.rph.Cmd = CMDGenIOCTL;
   rp.Category = USB_IDC_CATEGORY_CLIENT;
   rp.Function = USB_IDC_FUNCTION_ACCIO;
   rp.ParmPacket = (PVOID)&kbdata;
   kbdata.flags = S_LED;
   kbdata.buffPtr = (PCHAR)&NewLEDState;
   USBCallIDC (gpUSBIDC, gdsUSBIDC, (RP_GENIOCTL FAR *)&rp);

#ifdef DEBUG
   dsPrint1 (DBG_DETAILED, "IBMKBD: SetUSBLEDs, Status = %x\r\n", rp.rph.Status);
#endif
   return (rp.rph.Status);
}

/******************* START OF SPECIFICATIONS **************************/
/*                                                                    */
/* SUBROUTINE NAME:  SetUSBTypematic                                  */
/*                                                                    */
/* DESCRIPTIVE NAME:                                                  */
/*                                                                    */
/* FUNCTION:                                                          */
/*                                                                    */
/* NOTES:                                                             */
/*                                                                    */
/* CONTEXT:                                                           */
/*                                                                    */
/* ENTRY POINT :  ProcUSBIRQ                                          */
/*    LINKAGE  :                                                      */
/*                                                                    */
/* INPUT:  RP_GENIOCTL FAR *prp                                       */
/*                                                                    */
/* EXIT-NORMAL:  KBD IDC RC OK                                        */
/*                                                                    */
/* EXIT-ERROR:  device driver error code                              */
/*                                                                    */
/* EFFECTS:  None                                                     */
/*                                                                    */
/* INTERNAL REFERENCES:                                               */
/*    ROUTINES:                                                       */
/*                                                                    */
/* EXTERNAL REFERENCES:  None                                         */
/*    ROUTINES:                                                       */
/*                                                                    */
/******************* END  OF  SPECIFICATIONS **************************/

USHORT SetUSBTypematic (BYTE NewTypeRate)
{
   RP_GENIOCTL rp;     // GENeric IOCTL Request Packet
   USBLegIO    kbdata;

#ifdef DEBUG
   dsPrint1 (DBG_DETAILED, "IBMKBD: SetUSBTypematic, NewTypeRate = 0x%x\r\n", NewTypeRate);
#endif

   rp.rph.Cmd = CMDGenIOCTL;
   rp.Category = USB_IDC_CATEGORY_CLIENT;
   rp.Function = USB_IDC_FUNCTION_ACCIO;
   rp.ParmPacket = (PVOID)&kbdata;
   kbdata.flags = S_Type;
   kbdata.buffPtr = (PCHAR)&NewTypeRate;

   USBCallIDC (gpUSBIDC, gdsUSBIDC, (RP_GENIOCTL FAR *)&rp);

#ifdef DEBUG
   dsPrint1 (DBG_DETAILED, "IBMKBD: SetUSBTypematic, Status = %x\r\n", rp.rph.Status);
#endif
   return (rp.rph.Status);
}

/*****************************************************************************/

VOID PASCAL FAR HookHandler (VOID)
{
   SetUSBLEDs (LED_State);
}

