Annotation of kernel/bsd/dev/ppc/drvUSBCMD/kbd/KBDHIDEmulation.c, revision 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.