home *** CD-ROM | disk | FTP | other *** search
Wrap
/* File: KBDHIDEmulation.c Contains: Keyboard Emulation code Version: xxx put version here xxx Copyright: © 1998 by Apple Computer, Inc., all rights reserved. */ #include <Types.h> #include <Devices.h> #include <DriverServices.h> #include <USB.h> #ifndef DDKBuild #include <USBPriv.h> #endif #include "KeyboardModule.h" extern usbKeyboardPBStruct myKeyboardPB; extern usbKeyboardPBStruct shimKeyboardPB; void GetKeysPressed(USBHIDData * pKeysPressed); OSStatus USBHIDInstallInterrupt(HIDInterruptProcPtr HIDInterruptFunction, UInt32 refcon) { myKeyboardPB.interruptRefcon = refcon; myKeyboardPB.pSHIMInterruptRoutine = HIDInterruptFunction; return 0; } OSStatus USBHIDControlDevice(UInt32 theControlSelector, void * theControlData) { switch (theControlSelector) { case kHIDSetLEDStateByBits: shimKeyboardPB.hidReport[0] = *(UInt8*)theControlData; shimKeyboardPB.retryCount = kKeyboardRetryCount; shimKeyboardPB.delayLevel = 0; shimKeyboardPB.transDepth = 0; shimKeyboardPB.pb.usbRefcon = kSetKeyboardLEDs; /* Start with setting the interface protocol */ KeyboardModuleInitiateTransaction(&shimKeyboardPB.pb); break; case kHIDRemoveInterruptHandler: myKeyboardPB.interruptRefcon = nil; myKeyboardPB.pSavedInterruptRoutine = nil; myKeyboardPB.pSHIMInterruptRoutine = nil; break; case kHIDEnableDemoMode: USBExpertStatus(myKeyboardPB.deviceRef, "\pUSBHIDKeyboardModule: Demo Mode Enabled", myKeyboardPB.deviceRef); myKeyboardPB.pSavedInterruptRoutine = myKeyboardPB.pSHIMInterruptRoutine; myKeyboardPB.pSHIMInterruptRoutine = USBDemoKeyIn; break; case kHIDDisableDemoMode: USBExpertStatus(myKeyboardPB.deviceRef, "\pUSBHIDKeyboardModule: Demo Mode Disabled", myKeyboardPB.deviceRef); myKeyboardPB.pSHIMInterruptRoutine = myKeyboardPB.pSavedInterruptRoutine; break; default: return paramErr; } return 0; } void GetKeysPressed(USBHIDDataPtr pKeysPressed) { UInt8 i,keycount; keycount = 0; for (i = 0; i < kKeyboardModifierBits; i++) { if (myKeyboardPB.oldHIDReport[0] & (1 << i)) { pKeysPressed->kbd.usbkeycode[keycount++] = (0xe0 + i); } } if ((myKeyboardPB.oldHIDReport[kKeyboardOffsetToKeys] == 0) || (myKeyboardPB.oldHIDReport[kKeyboardOffsetToKeys] > 0x03)) { for (i = kKeyboardOffsetToKeys; i < (kKeyboardOffsetToKeys + kKeyboardReportKeys); i++) { if (myKeyboardPB.oldHIDReport[i] > 0x03) { pKeysPressed->kbd.usbkeycode[keycount++] = myKeyboardPB.oldHIDReport[i]; } } } pKeysPressed->kbd.keycount = keycount; } OSStatus USBHIDGetDeviceInfo(UInt32 theInfoSelector, void * theInfo) { HIDInterruptProcPtr * pHIDIntProcPtr; UInt32 * pInterruptRefcon; switch (theInfoSelector) { case kHIDGetCurrentKeys: GetKeysPressed((USBHIDDataPtr)theInfo); break; case kHIDGetInterruptHandler: pHIDIntProcPtr = (HIDInterruptProcPtr *)theInfo; *pHIDIntProcPtr = myKeyboardPB.pSHIMInterruptRoutine; break; case kHIDGetInterruptRefcon: pInterruptRefcon = (UInt32 *)theInfo; *pInterruptRefcon = myKeyboardPB.interruptRefcon; break; default: return paramErr; } return 0; } OSStatus USBHIDPollDevice(void) { #ifndef DDKBuild USLPolledProcessDoneQueue(); #endif return kUSBNoErr; } OSStatus USBHIDEnterPolledMode(void) { return unimpErr; } OSStatus USBHIDExitPolledMode(void) { return unimpErr; } void NotifyRegisteredHIDUser(UInt32 devicetype, UInt8 hidReport[]) { #pragma unused (devicetype) UInt8 i, j, newkey, oldkey, deltas; UInt8 changedmodifiers, keycount; USBHIDData theKeyboardData; Boolean keypressedflag, keyreleasedflag; deltas = 0; if (myKeyboardPB.hidEmulationInit == false) { myKeyboardPB.hidEmulationInit = true; for (i = 0; i < kKeyboardReportSize; i++) myKeyboardPB.oldHIDReport[i] = 0; }; myKeyboardPB.oldHIDReport[1] = 0x0; hidReport[1] = 0x0; for (i = 0; i < kKeyboardReportSize; i++) { if (hidReport[i] != myKeyboardPB.oldHIDReport[i]) { deltas++; } } if ((myKeyboardPB.sendRawReportFlag) && deltas) { (*myKeyboardPB.pSHIMInterruptRoutine)(0xff, (void *)&hidReport[0]); } else { if (deltas) { keycount = 0; changedmodifiers = hidReport[0] ^ myKeyboardPB.oldHIDReport[0]; if (changedmodifiers) { for (i = 0; i < kKeyboardModifierBits; i++) { if (changedmodifiers & (1 << i)) { if (hidReport[0] & (1 << i)) { theKeyboardData.kbd.usbkeycode[keycount++] = (0xe0 + i); } else { theKeyboardData.kbd.usbkeycode[keycount++] = (0x80e0 + i); } } } myKeyboardPB.oldHIDReport[0] = hidReport[0]; } if ((hidReport[kKeyboardOffsetToKeys] == 0) || (hidReport[kKeyboardOffsetToKeys] > 0x03)) { // While this double loop may look strange, I refer you to appendix C, of the HID Devices specification. // pp. 73 & 74 clearly state that report order is abitrary and does not reflect the order of events. // to quote: "The order of keycodes in array fields has no significance. Order determination is done // by the host software comparing the contents of the previous report to the current report. If two or // more keys are pressed in one report, their order is indeterminate. Keyboards may buffer events that // would have otherwise resulted in multiple events in a single report". // Because this specification (or lack thereof) states that the order is indeterminant, we have to // check all the old keys against all the new keys... for (i = kKeyboardOffsetToKeys; i < (kKeyboardOffsetToKeys + kKeyboardReportKeys); i++) { keypressedflag = true; newkey = hidReport[i]; keyreleasedflag = true; oldkey = myKeyboardPB.oldHIDReport[i]; for (j = kKeyboardOffsetToKeys; j < (kKeyboardOffsetToKeys + kKeyboardReportKeys); j++) // then look through all the keys that were previously and are currently reported as pressed { if (newkey == myKeyboardPB.oldHIDReport[j]) // was this new key already pressed? { keypressedflag = false; // if it was, then don't report it as being pressed. } if (oldkey == hidReport[j]) // Is the old key still pressed? { keyreleasedflag = false; // If yes, then don't report it as being released } } if ((newkey > 0x03) && keypressedflag) { theKeyboardData.kbd.usbkeycode[keycount++] = newkey; } if ((oldkey > 0x03) && keyreleasedflag) { theKeyboardData.kbd.usbkeycode[keycount++] = (oldkey + 0x8000); } if (keycount > 20) // a worse case scenario is: { // 4 modifier keys up break; // the other 4 modifier keys down } // 6 previously reported keys up } // 6 newly reported keys down // 6 + 6 + 4 + 4 = 20 for (i = 0; i<kKeyboardReportSize; i++) { myKeyboardPB.oldHIDReport[i] = hidReport[i]; }; } if ((myKeyboardPB.pSHIMInterruptRoutine) && keycount) { theKeyboardData.kbd.keycount = keycount; (*myKeyboardPB.pSHIMInterruptRoutine)(myKeyboardPB.interruptRefcon, (void *)&theKeyboardData); } } } } USBHIDModuleDispatchTable TheHIDModuleDispatchTable = { (UInt32)0, (USBHIDInstallInterruptProcPtr)USBHIDInstallInterrupt, (USBHIDPollDeviceProcPtr)USBHIDPollDevice, (USBHIDControlDeviceProcPtr)USBHIDControlDevice, (USBHIDGetDeviceInfoProcPtr)USBHIDGetDeviceInfo, (USBHIDEnterPolledModeProcPtr)USBHIDEnterPolledMode, (USBHIDExitPolledModeProcPtr)USBHIDExitPolledMode, };