home *** CD-ROM | disk | FTP | other *** search
/ Apple Developer Connection 1998 Fall: Game Toolkit / Disc.iso / SDKs / Mac OS USB DDK_v1.0.1 / Examples / KeyboardModule / KBDHIDEmulation.c < prev    next >
Encoding:
C/C++ Source or Header  |  1998-09-03  |  7.5 KB  |  278 lines  |  [TEXT/MPS ]

  1. /*
  2.     File:        KBDHIDEmulation.c
  3.  
  4.     Contains:    Keyboard Emulation code
  5.  
  6.     Version:    xxx put version here xxx
  7.  
  8.     Copyright:    © 1998 by Apple Computer, Inc., all rights reserved.
  9.  
  10. */
  11.  
  12. #include <Types.h>
  13. #include <Devices.h>
  14. #include <DriverServices.h>
  15. #include <USB.h>
  16.  
  17. #ifndef DDKBuild
  18. #include <USBPriv.h>
  19. #endif
  20.  
  21. #include "KeyboardModule.h"
  22.  
  23. extern    usbKeyboardPBStruct myKeyboardPB;
  24. extern    usbKeyboardPBStruct shimKeyboardPB;
  25.  
  26. void GetKeysPressed(USBHIDData * pKeysPressed);
  27.  
  28. OSStatus USBHIDInstallInterrupt(HIDInterruptProcPtr HIDInterruptFunction, UInt32 refcon)
  29. {
  30.     myKeyboardPB.interruptRefcon = refcon;
  31.     myKeyboardPB.pSHIMInterruptRoutine = HIDInterruptFunction;
  32.     return 0;
  33. }
  34.  
  35. OSStatus USBHIDControlDevice(UInt32 theControlSelector, void * theControlData)
  36. {
  37.     switch (theControlSelector)
  38.     {
  39.         case kHIDSetLEDStateByBits:
  40.             shimKeyboardPB.hidReport[0] = *(UInt8*)theControlData;
  41.  
  42.             shimKeyboardPB.retryCount = kKeyboardRetryCount;
  43.             shimKeyboardPB.delayLevel = 0;                            
  44.             shimKeyboardPB.transDepth = 0;    
  45.             
  46.             shimKeyboardPB.pb.usbRefcon = kSetKeyboardLEDs;                    /* Start with setting the interface protocol */
  47.             KeyboardModuleInitiateTransaction(&shimKeyboardPB.pb);
  48.             break;
  49.             
  50.         case kHIDRemoveInterruptHandler:
  51.             myKeyboardPB.interruptRefcon = nil;
  52.             myKeyboardPB.pSavedInterruptRoutine = nil;
  53.             myKeyboardPB.pSHIMInterruptRoutine = nil;
  54.             break;
  55.             
  56.         case kHIDEnableDemoMode:
  57.             USBExpertStatus(myKeyboardPB.deviceRef, "\pUSBHIDKeyboardModule: Demo Mode Enabled", myKeyboardPB.deviceRef);
  58.             myKeyboardPB.pSavedInterruptRoutine = myKeyboardPB.pSHIMInterruptRoutine;
  59.             myKeyboardPB.pSHIMInterruptRoutine = USBDemoKeyIn;
  60.             break;
  61.  
  62.         case kHIDDisableDemoMode:
  63.             USBExpertStatus(myKeyboardPB.deviceRef, "\pUSBHIDKeyboardModule: Demo Mode Disabled", myKeyboardPB.deviceRef);
  64.             myKeyboardPB.pSHIMInterruptRoutine = myKeyboardPB.pSavedInterruptRoutine;
  65.             break;
  66.  
  67.         default:
  68.             return paramErr;
  69.     }
  70.     return 0;
  71. }
  72.  
  73. void GetKeysPressed(USBHIDDataPtr pKeysPressed)
  74. {
  75. UInt8    i,keycount;
  76.     
  77.     keycount = 0;
  78.     for (i = 0; i < kKeyboardModifierBits; i++)
  79.     {
  80.         if (myKeyboardPB.oldHIDReport[0] & (1 << i))
  81.         {
  82.             pKeysPressed->kbd.usbkeycode[keycount++] = (0xe0 + i);
  83.         }
  84.     }
  85.             
  86.     if ((myKeyboardPB.oldHIDReport[kKeyboardOffsetToKeys] == 0) || (myKeyboardPB.oldHIDReport[kKeyboardOffsetToKeys] > 0x03))
  87.     {
  88.         for (i = kKeyboardOffsetToKeys; i < (kKeyboardOffsetToKeys + kKeyboardReportKeys); i++)
  89.         {
  90.             if (myKeyboardPB.oldHIDReport[i] > 0x03)
  91.             {
  92.                 pKeysPressed->kbd.usbkeycode[keycount++] = myKeyboardPB.oldHIDReport[i];
  93.             }
  94.         }                                                        
  95.     }
  96.     pKeysPressed->kbd.keycount = keycount;
  97. }
  98.  
  99.  
  100. OSStatus USBHIDGetDeviceInfo(UInt32 theInfoSelector, void * theInfo)
  101. {
  102. HIDInterruptProcPtr * pHIDIntProcPtr;
  103. UInt32 * pInterruptRefcon;
  104.  
  105.     switch (theInfoSelector)
  106.     {
  107.         case kHIDGetCurrentKeys:
  108.             GetKeysPressed((USBHIDDataPtr)theInfo);
  109.             break;
  110.  
  111.         case kHIDGetInterruptHandler:
  112.             pHIDIntProcPtr = (HIDInterruptProcPtr *)theInfo;  
  113.             *pHIDIntProcPtr = myKeyboardPB.pSHIMInterruptRoutine;
  114.             break;
  115.  
  116.         case kHIDGetInterruptRefcon:
  117.             pInterruptRefcon = (UInt32 *)theInfo;
  118.             *pInterruptRefcon = myKeyboardPB.interruptRefcon;
  119.             break;
  120.         
  121.         default:
  122.             return paramErr;
  123.     }
  124.     return 0;
  125. }
  126.  
  127. OSStatus USBHIDPollDevice(void)
  128. {
  129. #ifndef DDKBuild
  130.     USLPolledProcessDoneQueue();
  131. #endif
  132.     return kUSBNoErr;
  133. }
  134.  
  135. OSStatus USBHIDEnterPolledMode(void)
  136. {    
  137.     return unimpErr;
  138. }
  139.  
  140. OSStatus USBHIDExitPolledMode(void)
  141. {
  142.     return unimpErr;
  143. }
  144.  
  145. void NotifyRegisteredHIDUser(UInt32 devicetype, UInt8 hidReport[])
  146. {
  147. #pragma unused (devicetype)
  148.  
  149. UInt8    i, j, newkey, oldkey, deltas;
  150.  
  151. UInt8        changedmodifiers, keycount;
  152. USBHIDData    theKeyboardData;
  153. Boolean        keypressedflag, keyreleasedflag;
  154.     
  155.     deltas = 0;
  156.     
  157.     if (myKeyboardPB.hidEmulationInit == false)
  158.     {
  159.         myKeyboardPB.hidEmulationInit = true;
  160.         for (i = 0; i < kKeyboardReportSize; i++)
  161.             myKeyboardPB.oldHIDReport[i] = 0;
  162.     };
  163.     
  164.     myKeyboardPB.oldHIDReport[1] = 0x0;
  165.     hidReport[1] = 0x0;
  166.     
  167.     for (i = 0; i < kKeyboardReportSize; i++)
  168.     {
  169.         if (hidReport[i] != myKeyboardPB.oldHIDReport[i])
  170.         {
  171.             deltas++;
  172.         }
  173.     }
  174.     
  175.     if ((myKeyboardPB.sendRawReportFlag) && deltas)
  176.     {
  177.         (*myKeyboardPB.pSHIMInterruptRoutine)(0xff, (void *)&hidReport[0]);
  178.     }
  179.     else
  180.     {
  181.         if (deltas)
  182.         {
  183.             keycount = 0;
  184.             changedmodifiers = hidReport[0] ^  myKeyboardPB.oldHIDReport[0];
  185.             
  186.             if (changedmodifiers)
  187.             {
  188.                 for (i = 0; i < kKeyboardModifierBits; i++)
  189.                 {
  190.                     if (changedmodifiers & (1 << i))
  191.                     {
  192.                         if (hidReport[0] & (1 << i))
  193.                         {
  194.                             theKeyboardData.kbd.usbkeycode[keycount++] = (0xe0 + i);
  195.                         }
  196.                         else
  197.                         {
  198.                             theKeyboardData.kbd.usbkeycode[keycount++] = (0x80e0 + i);
  199.                         }
  200.                     }
  201.                 }
  202.                 myKeyboardPB.oldHIDReport[0] = hidReport[0];
  203.             }
  204.             
  205.             if ((hidReport[kKeyboardOffsetToKeys] == 0) || (hidReport[kKeyboardOffsetToKeys] > 0x03))
  206.             {
  207.                 // While this double loop may look strange, I refer you to appendix C, of the HID Devices specification.
  208.                 // pp. 73 & 74 clearly state that report order is abitrary and does not reflect the order of events.
  209.                 // to quote: "The order of keycodes in array fields has no significance.  Order determination is done
  210.                 // by the host software comparing the contents of the previous report to the current report.  If two or 
  211.                 // more keys are pressed in one report, their order is indeterminate.  Keyboards may buffer events that
  212.                 // would have otherwise resulted in multiple events in a single report".
  213.                 
  214.                 // Because this specification (or lack thereof) states that the order is indeterminant, we have to 
  215.                 // check all the old keys against all the new keys...
  216.                 
  217.                 for (i = kKeyboardOffsetToKeys; i < (kKeyboardOffsetToKeys + kKeyboardReportKeys); i++)
  218.                 {
  219.                     keypressedflag = true;
  220.                     newkey = hidReport[i];
  221.                     
  222.                     keyreleasedflag = true;
  223.                     oldkey = myKeyboardPB.oldHIDReport[i];                            
  224.                     for (j = kKeyboardOffsetToKeys; j < (kKeyboardOffsetToKeys + kKeyboardReportKeys); j++)                                // then look through all the keys that were previously and are currently reported as pressed
  225.                     {                                    
  226.                         if (newkey == myKeyboardPB.oldHIDReport[j])        // was this new key already pressed?
  227.                         {                                
  228.                             keypressedflag = false;                        // if it was, then don't report it as being pressed.
  229.                         }
  230.                         
  231.                         if (oldkey == hidReport[j])                        // Is the old key still pressed?
  232.                         {                                
  233.                             keyreleasedflag = false;                    // If yes, then don't report it as being released
  234.                         }
  235.                     }
  236.                     if ((newkey > 0x03) && keypressedflag)
  237.                     {
  238.                         theKeyboardData.kbd.usbkeycode[keycount++] = newkey;
  239.                     }
  240.                     
  241.                     if ((oldkey > 0x03) && keyreleasedflag)
  242.                     {
  243.                         theKeyboardData.kbd.usbkeycode[keycount++] = (oldkey + 0x8000);
  244.                     }
  245.                     
  246.                     if (keycount > 20)                                    // a worse case scenario is:
  247.                     {                                                    // 4 modifier keys up
  248.                         break;                                            // the other 4 modifier keys down
  249.                     }                                                    // 6 previously reported keys up
  250.                 }                                                        // 6 newly reported keys down
  251.                                                                         // 6 + 6 + 4 + 4 = 20
  252.                 for (i = 0; i<kKeyboardReportSize; i++)
  253.                 {
  254.                     myKeyboardPB.oldHIDReport[i] = hidReport[i];
  255.                 };
  256.             }
  257.             
  258.             if ((myKeyboardPB.pSHIMInterruptRoutine) && keycount)
  259.             {
  260.                 theKeyboardData.kbd.keycount = keycount;
  261.                 (*myKeyboardPB.pSHIMInterruptRoutine)(myKeyboardPB.interruptRefcon, (void *)&theKeyboardData);
  262.             }
  263.         }
  264.     }
  265. }
  266.  
  267.  
  268. USBHIDModuleDispatchTable TheHIDModuleDispatchTable =
  269. {
  270.     (UInt32)0,
  271.     (USBHIDInstallInterruptProcPtr)USBHIDInstallInterrupt,
  272.     (USBHIDPollDeviceProcPtr)USBHIDPollDevice,
  273.     (USBHIDControlDeviceProcPtr)USBHIDControlDevice,
  274.     (USBHIDGetDeviceInfoProcPtr)USBHIDGetDeviceInfo,
  275.     (USBHIDEnterPolledModeProcPtr)USBHIDEnterPolledMode,
  276.     (USBHIDExitPolledModeProcPtr)USBHIDExitPolledMode,
  277. };
  278.