Annotation of kernel/bsd/dev/ppc/drvUSBCMD/kbd/KBDHIDEmulation.c, revision 1.1.1.1

1.1       root        1: /*
                      2:  * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
                      3:  *
                      4:  * @APPLE_LICENSE_HEADER_START@
                      5:  * 
                      6:  * Portions Copyright (c) 1999 Apple Computer, Inc.  All Rights
                      7:  * Reserved.  This file contains Original Code and/or Modifications of
                      8:  * Original Code as defined in and that are subject to the Apple Public
                      9:  * Source License Version 1.1 (the "License").  You may not use this file
                     10:  * except in compliance with the License.  Please obtain a copy of the
                     11:  * License at http://www.apple.com/publicsource and read it before using
                     12:  * this file.
                     13:  * 
                     14:  * The Original Code and all software distributed under the License are
                     15:  * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
                     16:  * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
                     17:  * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
                     18:  * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
                     19:  * License for the specific language governing rights and limitations
                     20:  * under the License.
                     21:  * 
                     22:  * @APPLE_LICENSE_HEADER_END@
                     23:  */
                     24: 
                     25: /*
                     26:        File:           KBDHIDEmulation.c
                     27: 
                     28:        Contains:       Keyboard Emulation code
                     29: 
                     30:        Version:        xxx put version here xxx
                     31: 
                     32:        Copyright:      � 1998 by Apple Computer, Inc., all rights reserved.
                     33: 
                     34:        File Ownership:
                     35: 
                     36:                DRI:                            Craig Keithley
                     37: 
                     38:                Other Contact:          xxx put other contact here xxx
                     39: 
                     40:                Technology:                     USB
                     41: 
                     42:        Writers:
                     43: 
                     44:                (BWS)   Brent Schorsch
                     45:                (BG)    Bill Galcher
                     46:                (CJK)   Craig Keithley
                     47: 
                     48:        Change History (most recent first):
                     49: 
                     50:         <USB32>         6/20/98        CJK             Expand on Brent's comments... It wasn't a "fix" of the refcon,
                     51:                                                                        it was the addition of a new getinfo selector so that an
                     52:                                                                        InputSprocket can ask the Keyboard HID Module to pass back it's
                     53:                                                                        refcon to the caller. There was nothing "broken" in the original
                     54:                                                                        code.
                     55:         <USB31>         6/18/98        BWS             fix interrupt refcon support
                     56:         <USB30>         6/18/98        CJK             update to use modified HID dispatch table (passing in refcon)
                     57:         <USB29>          6/5/98        CJK             remove pragma unused from GetKeysPressed
                     58:         <USB28>         5/28/98        CJK             add HID GetInfo Selector to get notification proc address
                     59:         <USB27>         5/20/98        CJK             change driver name from USBKeyboardModule to
                     60:                                                                        USBHIDKeyboardModule
                     61:         <USB26>         5/20/98        CJK             add check for 'DDKBuild' define. If it's not defined then it's
                     62:                                                                        okay to include USBPriv.h and use the USL's DoneQueue API.
                     63:         <USB25>         5/19/98        CJK             remove include of USBPriv.h. This file should not be included,
                     64:                                                                        as the DDK will not supply it. If there are prototypes needed by
                     65:                                                                        this file, they should be moved to USB.h (usb.i).
                     66:         <USB24>         5/19/98        BG              Add includes of <USBPriv.h> and "UIMPriv.h" to bring in needed
                     67:                                                                        prototypes.
                     68:         <USB23>         5/18/98        CJK             remove the breaks...
                     69:         <USB22>         5/18/98        CJK             Add support for 'GetCurrentKeyboardState' getinfo selector
                     70:         <USB21>         4/30/98        CJK             fix break statements.
                     71:         <USB20>         4/30/98        CJK             handle keyreleasedflag slightly differently
                     72:         <USB19>         4/30/98        CJK             add a "send raw report" mode.  rework so that the old hid report
                     73:                                                                        and initialized flags are kept in the keyboard data structure
                     74:                                                                        (rather than in static vars.)
                     75:         <USB18>         4/27/98        CJK             correct zero'ing of non-relevant hid report bytes.
                     76:         <USB17>         4/27/98        CJK             Add handling of key rollover errors.  No longer sends already
                     77:                                                                        down keys when the rollover error is removed.
                     78:         <USB16>         4/26/98        CJK             update to match reworked keyboard interface driver.
                     79:                                                                        Restructured user notification routine.
                     80:         <USB15>         4/14/98        CJK             change call to USBIdleTask to UIMProcessDoneQueue
                     81:         <USB14>          4/9/98        CJK             remove include of USBDeviceDefines.h
                     82:                <13>      4/8/98        CJK             add enable/disable of emulation code
                     83:                <12>     3/26/98        CJK             remove debugstr
                     84:                <11>     3/17/98        CJK             change }; to just }. MetroWerks has a problem with };.  Also
                     85:                                                                        added parens around pragma unused's variable name.
                     86:                <10>     3/12/98        CJK             Don't worry about initializing the shim keyboard paramblock.
                     87:                                                                        That's done in the keyboard initialize routine.
                     88:                 <9>      3/2/98        CJK             remove include of KBDHIDEmulation.h
                     89:                 <8>      3/2/98        CJK             change to use USBHIDModule hid data structure (rather than the
                     90:                                                                        keyboard data structure).
                     91:                 <7>     2/27/98        CJK             add check for keycount growing too large.  Add include of
                     92:                                                                        USBHIDModules.h.  Change LED control selector to be "by bit" (as
                     93:                                                                        opposed to by ID, which is probably how things will ultimately
                     94:                                                                        work).
                     95:                 <6>     2/26/98        CJK             Add USBHIDControlDevice functionality. All it does (right now)
                     96:                                                                        is set the LEDs.
                     97:                 <5>     2/17/98        CJK             Integrate Ferg's changes.
                     98:                <4*>     2/16/98        DKF             Add keyposting if there is no shim registered
                     99:                 <4>     2/16/98        CJK             remove write of $00 keycodes into the keycode array. Streamline
                    100:                                                                        old vs. new keycode detection (hopefully faster than before).
                    101:                 <3>     2/16/98        CJK             Improve check of modifier key changes (shouldn't need to scan
                    102:                                                                        through each bit to determine if any modifiers changed.  Just check
                    103:                                                                        the changed bits.  If any changed, then look through each bit individually.
                    104:                 <2>     2/10/98        CJK             Correct change history (to reflect the keyboard module changes)
                    105:                 <1>     2/10/98        CJK             First time checkin.  Cloned from Mouse HID Module.
                    106: */
                    107: 
                    108: //#include <Types.h>
                    109: //#include <Devices.h>
                    110: #include "../driverservices.h"
                    111: #include "../USB.h"
                    112: #ifndef DDKBuild
                    113: #include "../USBpriv.h"
                    114: #endif
                    115: 
                    116: #include "KeyboardModule.h"
                    117: //prototype from PPCKeyboard.m
                    118: void keyboard_adbhandler(int number, unsigned char *buffer, int count, void * ssp);
                    119: 
                    120: 
                    121: extern usbKeyboardPBStruct myKeyboardPB;
                    122: extern usbKeyboardPBStruct shimKeyboardPB;
                    123: extern  UInt8 usb_2_adb_keymap[];
                    124: 
                    125: void GetKeysPressed(USBHIDData * pKeysPressed);
                    126: 
                    127: OSStatus kbd_USBHIDInstallInterrupt(HIDInterruptProcPtr HIDInterruptFunction, UInt32 refcon)
                    128: {
                    129:        myKeyboardPB.interruptRefcon = refcon;
                    130:        myKeyboardPB.pSHIMInterruptRoutine = HIDInterruptFunction;
                    131:        return 0;
                    132: }
                    133: 
                    134: OSStatus kbd_USBHIDControlDevice(UInt32 theControlSelector, void * theControlData)
                    135: {
                    136:        switch (theControlSelector)
                    137:        {
                    138:                case kHIDSetLEDStateByBits:
                    139:                        shimKeyboardPB.hidReport[0] = *(UInt8*)theControlData;
                    140: 
                    141:                        shimKeyboardPB.retryCount = kKeyboardRetryCount;
                    142:                        shimKeyboardPB.delayLevel = 0;                                                  
                    143:                        shimKeyboardPB.transDepth = 0;  
                    144:                        
                    145:                        shimKeyboardPB.pb.usbRefcon = kSetKeyboardLEDs;                                 /* Start with setting the interface protocol */
                    146:                        KeyboardModuleInitiateTransaction(&shimKeyboardPB.pb);
                    147:                        break;
                    148:                        
                    149:                case kHIDRemoveInterruptHandler:
                    150:                        myKeyboardPB.interruptRefcon = nil;
                    151:                        myKeyboardPB.pSavedInterruptRoutine = nil;
                    152:                        myKeyboardPB.pSHIMInterruptRoutine = nil;
                    153:                        break;
                    154:                        
                    155:                case kHIDEnableDemoMode:
                    156:                        USBExpertStatus(myKeyboardPB.deviceRef, "USBHIDKeyboardModule: Demo Mode Enabled", myKeyboardPB.deviceRef);
                    157:                        myKeyboardPB.pSavedInterruptRoutine = myKeyboardPB.pSHIMInterruptRoutine;
                    158:                        myKeyboardPB.pSHIMInterruptRoutine = USBDemoKeyIn;
                    159:                        break;
                    160: 
                    161:                case kHIDDisableDemoMode:
                    162:                        USBExpertStatus(myKeyboardPB.deviceRef, "USBHIDKeyboardModule: Demo Mode Disabled", myKeyboardPB.deviceRef);
                    163:                        myKeyboardPB.pSHIMInterruptRoutine = myKeyboardPB.pSavedInterruptRoutine;
                    164:                        break;
                    165: 
                    166:                default:
                    167:                        return paramErr;
                    168:        }
                    169:        return 0;
                    170: }
                    171: 
                    172: void GetKeysPressed(USBHIDDataPtr pKeysPressed)
                    173: {
                    174: UInt8  i,keycount;
                    175:        
                    176:        keycount = 0;
                    177:        for (i = 0; i < kKeyboardModifierBits; i++)
                    178:        {
                    179:                if (myKeyboardPB.oldHIDReport[0] & (1 << i))
                    180:                {
                    181:                        pKeysPressed->kbd.usbkeycode[keycount++] = (0xe0 + i);
                    182:                }
                    183:        }
                    184:                        
                    185:        if ((myKeyboardPB.oldHIDReport[kKeyboardOffsetToKeys] == 0) || (myKeyboardPB.oldHIDReport[kKeyboardOffsetToKeys] > 0x03))
                    186:        {
                    187:                for (i = kKeyboardOffsetToKeys; i < (kKeyboardOffsetToKeys + kKeyboardReportKeys); i++)
                    188:                {
                    189:                        if (myKeyboardPB.oldHIDReport[i] > 0x03)
                    190:                        {
                    191:                                pKeysPressed->kbd.usbkeycode[keycount++] = myKeyboardPB.oldHIDReport[i];
                    192:                        }
                    193:                }                                                                                                               
                    194:        }
                    195:        pKeysPressed->kbd.keycount = keycount;
                    196: }
                    197: 
                    198: 
                    199: OSStatus kbd_USBHIDGetDeviceInfo(UInt32 theInfoSelector, void * theInfo)
                    200: {
                    201: HIDInterruptProcPtr * pHIDIntProcPtr;
                    202: UInt32 * pInterruptRefcon;
                    203: 
                    204:        switch (theInfoSelector)
                    205:        {
                    206:                case kHIDGetCurrentKeys:
                    207:                        GetKeysPressed((USBHIDDataPtr)theInfo);
                    208:                        break;
                    209: 
                    210:                case kHIDGetInterruptHandler:
                    211:                        pHIDIntProcPtr = (HIDInterruptProcPtr *)theInfo;  
                    212:                        *pHIDIntProcPtr = myKeyboardPB.pSHIMInterruptRoutine;
                    213:                        break;
                    214: 
                    215:                case kHIDGetInterruptRefcon:
                    216:                        pInterruptRefcon = (UInt32 *)theInfo;
                    217:                        *pInterruptRefcon = myKeyboardPB.interruptRefcon;
                    218:                        break;
                    219:                
                    220:                default:
                    221:                        return paramErr;
                    222:        }
                    223:        return 0;
                    224: }
                    225: 
                    226: OSStatus kbd_USBHIDPollDevice(void)
                    227: {
                    228: #ifndef DDKBuild
                    229:        USLPolledProcessDoneQueue();
                    230: #endif
                    231:        return kUSBNoErr;
                    232: }
                    233: 
                    234: OSStatus kbd_USBHIDEnterPolledMode(void)
                    235: {    
                    236:        return unimpErr;
                    237: }
                    238: 
                    239: OSStatus kbd_USBHIDExitPolledMode(void)
                    240: {
                    241:        return unimpErr;
                    242: }
                    243: 
                    244: void kbd_NotifyRegisteredHIDUser(UInt32 devicetype, UInt8 hidReport[])
                    245: {
                    246: #pragma unused (devicetype)
                    247: 
                    248: UInt8  i, j, newkey, oldkey, deltas;
                    249: 
                    250: UInt8          changedmodifiers, keycount;
                    251: USBHIDData     theKeyboardData;
                    252: Boolean                keypressedflag, keyreleasedflag;
                    253: char           adb_data[8];
                    254:        
                    255:        deltas = 0;
                    256:        if (myKeyboardPB.hidEmulationInit == false)
                    257:        {
                    258:                myKeyboardPB.hidEmulationInit = true;
                    259:                for (i = 0; i < kKeyboardReportSize; i++)
                    260:                        myKeyboardPB.oldHIDReport[i] = 0;
                    261:        };
                    262:        
                    263:        myKeyboardPB.oldHIDReport[1] = 0x0;
                    264:        hidReport[1] = 0x0;
                    265:        
                    266:        for (i = 0; i < kKeyboardReportSize; i++)
                    267:        {
                    268:                if (hidReport[i] != myKeyboardPB.oldHIDReport[i])
                    269:                {
                    270:                        deltas++;
                    271:                }
                    272:        }
                    273:        
                    274:        if ((myKeyboardPB.sendRawReportFlag) && deltas)
                    275:        {
                    276:                (*myKeyboardPB.pSHIMInterruptRoutine)(0xff, (void *)&hidReport[0]);
                    277:        }
                    278:        else
                    279:        {
                    280:                if (deltas)
                    281:                {
                    282:                        keycount = 0;
                    283:                        changedmodifiers = hidReport[0] ^  myKeyboardPB.oldHIDReport[0];
                    284:                        
                    285:                        if (changedmodifiers)
                    286:                        {
                    287:                                for (i = 0; i < kKeyboardModifierBits; i++)
                    288:                                {
                    289:                                        if (changedmodifiers & (1 << i))
                    290:                                        {
                    291:                                                if (hidReport[0] & (1 << i))
                    292:                                                {
                    293:                                                        theKeyboardData.kbd.usbkeycode[keycount++] = (0xe0 + i);
                    294:                                                }
                    295:                                                else
                    296:                                                {
                    297:                                                        theKeyboardData.kbd.usbkeycode[keycount++] = (0x80e0 + i);
                    298:                                                }
                    299:                                        }
                    300:                                }
                    301:                                myKeyboardPB.oldHIDReport[0] = hidReport[0];
                    302:                        }
                    303:                        
                    304:                        if ((hidReport[kKeyboardOffsetToKeys] == 0) || (hidReport[kKeyboardOffsetToKeys] > 0x03))
                    305:                        {
                    306:                                // While this double loop may look strange, I refer you to appendix C, of the HID Devices specification.
                    307:                                // pp. 73 & 74 clearly state that report order is abitrary and does not reflect the order of events.
                    308:                                // to quote: "The order of keycodes in array fields has no significance.  Order determination is done
                    309:                                // by the host software comparing the contents of the previous report to the current report.  If two or 
                    310:                                // more keys are pressed in one report, their order is indeterminate.  Keyboards may buffer events that
                    311:                                // would have otherwise resulted in multiple events in a single report".
                    312:                                
                    313:                                // Because this specification (or lack thereof) states that the order is indeterminant, we have to 
                    314:                                // check all the old keys against all the new keys...
                    315:                                
                    316:                                for (i = kKeyboardOffsetToKeys; i < (kKeyboardOffsetToKeys + kKeyboardReportKeys); i++)
                    317:                                {
                    318:                                        keypressedflag = true;
                    319:                                        newkey = hidReport[i];
                    320:                                        
                    321:                                        keyreleasedflag = true;
                    322:                                        oldkey = myKeyboardPB.oldHIDReport[i];                                                  
                    323:                                        for (j = kKeyboardOffsetToKeys; j < (kKeyboardOffsetToKeys + kKeyboardReportKeys); j++)                                                         // then look through all the keys that were previously and are currently reported as pressed
                    324:                                        {                                                                       
                    325:                                                if (newkey == myKeyboardPB.oldHIDReport[j])             // was this new key already pressed?
                    326:                                                {                                                               
                    327:                                                        keypressedflag = false;                                         // if it was, then don't report it as being pressed.
                    328:                                                }
                    329:                                                
                    330:                                                if (oldkey == hidReport[j])                                             // Is the old key still pressed?
                    331:                                                {                                                               
                    332:                                                        keyreleasedflag = false;                                        // If yes, then don't report it as being released
                    333:                                                }
                    334:                                        }
                    335:                                        if ((newkey > 0x03) && keypressedflag)
                    336:                                        {
                    337:                                                theKeyboardData.kbd.usbkeycode[keycount++] = newkey;
                    338:                                        }
                    339:                                        
                    340:                                        if ((oldkey > 0x03) && keyreleasedflag)
                    341:                                        {
                    342:                                                theKeyboardData.kbd.usbkeycode[keycount++] = (oldkey + 0x8000);
                    343:                                        }
                    344:                                        
                    345:                                        if (keycount > 20)                                                                      // a worse case scenario is:
                    346:                                        {                                                                                                       // 4 modifier keys up
                    347:                                                break;                                                                                  // the other 4 modifier keys down
                    348:                                        }                                                                                                       // 6 previously reported keys up
                    349:                                }                                                                                                               // 6 newly reported keys down
                    350:                                                                                                                                                // 6 + 6 + 4 + 4 = 20
                    351:                                for (i = 0; i<kKeyboardReportSize; i++)
                    352:                                {
                    353:                                        myKeyboardPB.oldHIDReport[i] = hidReport[i];
                    354:                                };
                    355:                        }
                    356:                        
                    357:                        //Now we map to ADB from USB 
                    358:                        //Adam Wang 12/2/98
                    359:                        adb_data[1] = 0xff;
                    360:                        for(i=0;i<keycount;++i)
                    361:                        {
                    362:                                static char caps_lock_state = 1;
                    363:                                 unsigned char newLEDState;
                    364:                                //Special handling of USB caps-lock-that-doesn't-lock 12/8/98
                    365:                                if ( theKeyboardData.kbd.usbkeycode[i] == 0x0039)  //00 = going down, 39 = caps lock                  
                    366:                                {
                    367:                                        newLEDState = 2;
                    368:                                        //This call to set LED will hang on Yosemite 
                    369:                                        kbd_USBHIDControlDevice(1, &newLEDState);
                    370:                                }
                    371:                                if ( theKeyboardData.kbd.usbkeycode[i] == 0x8039)  //80 = going up, 39 = caps lock                  
                    372:                                { 
                    373:                                        caps_lock_state ^= 1; //toggle bit
                    374:                                        if (caps_lock_state == 0)     
                    375:                                                continue;   //naga changed break to continue
                    376:                                        //The logic is, ignore first caps-up on iMac keyboards        
                    377:                                        newLEDState = 0;
                    378:                                        kbd_USBHIDControlDevice(1, &newLEDState);
                    379:                                }                
                    380: 
                    381:                                adb_data[0] = usb_2_adb_keymap[(theKeyboardData.kbd.usbkeycode[i] & 0x00ff)];
                    382: 
                    383:                                if ((theKeyboardData.kbd.usbkeycode[i] & 0x8000) == 0x8000) // key is on its way up
                    384:                                        adb_data[0] |= 0x80;            //Set ADB most significant bit
                    385:                                
                    386:                                //Special handling needed for ADB POWER key
                    387:                                if (adb_data[0] == 0x7f)
                    388:                                {
                    389:                                        adb_data[1] = 0x7f;  //ADB power scan code is 7f 7f
                    390:                                }
                    391: 
                    392:                                keyboard_adbhandler(2, adb_data, 2, (void *) 0);
                    393:                        }
                    394: 
                    395: 
                    396: /*
                    397:                        if ((myKeyboardPB.pSHIMInterruptRoutine) && keycount)
                    398:                        {
                    399:                                theKeyboardData.kbd.keycount = keycount;
                    400:                                (*myKeyboardPB.pSHIMInterruptRoutine)(myKeyboardPB.interruptRefcon, (void *)&theKeyboardData);
                    401:                        }
                    402: */
                    403:                }
                    404:        }
                    405: }
                    406: 
                    407: 
                    408: USBHIDModuleDispatchTable kbd_TheHIDModuleDispatchTable =
                    409: {
                    410:        (UInt32)0,
                    411:        (USBHIDInstallInterruptProcPtr)kbd_USBHIDInstallInterrupt,
                    412:        (USBHIDPollDeviceProcPtr)kbd_USBHIDPollDevice,
                    413:        (USBHIDControlDeviceProcPtr)kbd_USBHIDControlDevice,
                    414:        (USBHIDGetDeviceInfoProcPtr)kbd_USBHIDGetDeviceInfo,
                    415:        (USBHIDEnterPolledModeProcPtr)kbd_USBHIDEnterPolledMode,
                    416:        (USBHIDExitPolledModeProcPtr)kbd_USBHIDExitPolledMode,
                    417: };

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.