Annotation of XNU/iokit/Drivers/usb/drvAppleKeyboard/AppleKeyboard.cpp, revision 1.1

1.1     ! root        1: /*
        !             2:  * Copyright (c) 1998-2000 Apple Computer, Inc. All rights reserved.
        !             3:  *
        !             4:  * @APPLE_LICENSE_HEADER_START@
        !             5:  * 
        !             6:  * The contents of this file constitute Original Code as defined in and
        !             7:  * are subject to the Apple Public Source License Version 1.1 (the
        !             8:  * "License").  You may not use this file except in compliance with the
        !             9:  * License.  Please obtain a copy of the License at
        !            10:  * http://www.apple.com/publicsource and read it before using this file.
        !            11:  * 
        !            12:  * This Original Code and all software distributed under the License are
        !            13:  * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
        !            14:  * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
        !            15:  * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
        !            16:  * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
        !            17:  * License for the specific language governing rights and limitations
        !            18:  * under the License.
        !            19:  * 
        !            20:  * @APPLE_LICENSE_HEADER_END@
        !            21:  */
        !            22: /*
        !            23:  * Copyright (c) 1998, 1999 Apple Computer, Inc.  All rights reserved.
        !            24:  *
        !            25:  * HISTORY
        !            26:  *
        !            27:  */
        !            28: #include <libkern/OSByteOrder.h>
        !            29: 
        !            30: #include "AppleKeyboard.h"
        !            31: #include <IOKit/hidsystem/IOHIPointing.h>
        !            32: #include <IOKit/IOBufferMemoryDescriptor.h>
        !            33: #include <IOKit/usb/IOUSBInterface.h>
        !            34: #include <IOKit/usb/IOUSBPipe.h>
        !            35: #include <IOKit/usb/IOUSBController.h>
        !            36: 
        !            37: extern "C" {
        !            38: #include <pexpert/pexpert.h>
        !            39: }
        !            40: 
        !            41: 
        !            42: #define super IOHIKeyboard
        !            43: #define self this
        !            44: #define DEBUGGING_LEVEL 0
        !            45: 
        !            46: OSDefineMetaClassAndStructors(AppleKeyboard, IOHIKeyboard)
        !            47: 
        !            48: extern unsigned char usb_2_adb_keymap[];  //In Cosmo_USB2ADB.cpp
        !            49: 
        !            50: static IOUSBController *sPollControl;
        !            51: static IOUSBPipe *sPollPipe;
        !            52: static UInt8 sBuffer[8];
        !            53: static IOMemoryDescriptor *sBufDesc;
        !            54: static bool sComplete = true;
        !            55: 
        !            56: 
        !            57: static void bodgeComplete(void *target, void * parameter, IOReturn status, UInt32 bufferSizeRemaining)
        !            58: {
        !            59:     sComplete = true;
        !            60: }
        !            61: 
        !            62: static int PE_usb_poll_input(unsigned int options, char * c)
        !            63: {
        !            64:     static char        adbkeycodes2ascii[] = "asdfhgzxcv_bqwer"//00
        !            65:                                     "yt123465=97-80]o" //10
        !            66:                                     "u[ip\nlj'k;_,/nm."        //20
        !            67:                                     "\t_";             //30
        !            68:     *c = 0xff;
        !            69: 
        !            70:     if(!sPollPipe)
        !            71:        return 0;
        !            72:     if(sComplete) {
        !            73:         IOUSBCompletion        completion;
        !            74:        sComplete = false;
        !            75: 
        !            76:         *c = adbkeycodes2ascii[usb_2_adb_keymap[sBuffer[2]]];
        !            77:         completion.target = 0;
        !            78:         completion.action = bodgeComplete;
        !            79:         completion.parameter = 0;
        !            80: 
        !            81:         sPollControl->PolledRead(
        !            82:                     sPollPipe->address()               /*functionAddress*/,
        !            83:                     sPollPipe->endpoint()->number      /*endpointNumber*/,
        !            84:                     completion                         /*completion*/,
        !            85:                     sBufDesc                           /*buffer*/,
        !            86:                     true                               /*bufferRounding*/,
        !            87:                     sizeof(sBuffer)                    /*bufferSize*/);
        !            88:     }
        !            89:     else
        !            90:         sPollControl->pollInterrupts(bodgeComplete);   // Only complete our transactions
        !            91: 
        !            92:     return 0;
        !            93: }
        !            94: 
        !            95: void usb_asyncLED ( AppleKeyboard * me );
        !            96: AppleKeyboard  *glob_usbkeyboard_obj;
        !            97: 
        !            98: bool AppleKeyboard::start(IOService * provider)
        !            99: {
        !           100:     IOReturn                   err = 0;
        !           101:     
        !           102:     if( !super::start(provider))
        !           103:         return (false);
        !           104: 
        !           105:     // remember my device
        !           106:     _interface         = OSDynamicCast(IOUSBInterface, provider);
        !           107:     _deviceDescriptor  = _interface->deviceDescriptor();
        !           108:     _prevent_LED_set    = FALSE;
        !           109: 
        !           110:     //Following 3 lines moved here from Simulate_ADB_Event to make multiple 
        !           111:     // keyboards work correctly.  The instance variables cannot be shared
        !           112:     // between each instance of this driver for each USB keyboard.
        !           113:     prev_bytes_read=8;
        !           114:     oldmodifier = 0xff;
        !           115:     bzero( old_array, kUSB_LOWSPEED_MAXPACKET);
        !           116: 
        !           117: 
        !           118:     if (_interface->open(self) == false) return false;
        !           119: 
        !           120:     //Fix hardware bug in iMac USB keyboard mapping for ISO keyboards
        !           121:     //kprintf("\nUSB product = %x, vendor = %x\n", _deviceDescriptor->product, _deviceDescriptor->vendor);
        !           122:     if ( _deviceDescriptor)    //just to be safe
        !           123:     {
        !           124:         if (_deviceDescriptor->vendor == 0xac05)  //Apple Corp. vendor ID, not byte swapped
        !           125:         {
        !           126:             switch (_deviceDescriptor->product)
        !           127:             {  
        !           128:                 case 0x0201: //North American iMac keyboard
        !           129:                 break;   // return 18 
        !           130:                 case 0x0203: //38=Japanese.  34 is adjustable JIS
        !           131:                 break;  // return 34;
        !           132:                 case 0x0202: //Arabic, other ISO such as German
        !           133:                 //Swap two ISO keys around
        !           134:                 usb_2_adb_keymap[0x35] = 0x0a;  //Cosmo key18 swaps with key74, 0a is ADB keycode
        !           135:                 usb_2_adb_keymap[0x64] = 0x32;
        !           136:                break;
        !           137:                         // return 21; //21 is Apple ISO Extended Keyboard
        !           138:                 default:
        !           139:                 //return 18;
        !           140:                break;
        !           141:             }
        !           142:         }
        !           143: 
        !           144: 
        !           145: 
        !           146:         if (_deviceDescriptor->vendor == 0x5e04)  //Microsoft ID
        !           147:         {
        !           148:        //Figure out what to do with Microsoft keyboard later
        !           149: 
        !           150:         //if (usb_kbd_product_id == 0x000b)   //Natural USB+PS/2 keyboard
        !           151:             //return 18;
        !           152:         }    
        !           153:     }
        !           154: 
        !           155:     do {
        !           156:         IOLog("%s: USB Generic Keyboard @ %d\n", getName(), _interface->address());
        !           157: 
        !           158: #if 0
        !           159: 
        !           160: kprintf("Adam: Class is %d\n", req.theClass);  //3 HID
        !           161: kprintf("Adam: SubClass is %d\n", req.subClass);  //1
        !           162: kprintf("Adam: Protocol is %d\n", req.protocol); //1 keyboard
        !           163: 
        !           164: kprintf("Adam: Type is %d\n", (_interface->endpoints[0])->transferType); //I get 1
        !           165: kprintf("Adam: Number is %d\n", (_interface->endpoints[0])->number); // I get 1
        !           166: 
        !           167: #endif
        !           168: 
        !           169:         //setAlphaLockFeedback(false);  //Disable caps lock LED at first
        !           170: 
        !           171:         IOUSBFindEndpointRequest request;
        !           172:         request.type = kUSBInterrupt;
        !           173:         request.direction = kUSBIn;
        !           174:         _interruptPipe = _interface->findNextPipe(NULL, &request);
        !           175: 
        !           176:         if(!_interruptPipe)
        !           177:             return false;
        !           178: 
        !           179:         _maxPacketSize = request.maxPacketSize;
        !           180:         _buffer = IOBufferMemoryDescriptor::withCapacity(8, kIODirectionIn);
        !           181: 
        !           182:         _completion.target = (void *)self;
        !           183:         _completion.action = (IOUSBCompletionAction) &AppleKeyboard::readHandler;
        !           184:         _completion.parameter = (void *)0;  // not used
        !           185: 
        !           186:         _buffer->setLength(_maxPacketSize); // shouldn't this be _maxPacketSize?
        !           187: 
        !           188:         if ((err = _interruptPipe->read(_buffer, &_completion)))
        !           189:             break;
        !           190: 
        !           191: #if (DEBUGGING_LEVEL > 0)
        !           192:         //printInterfaceDescriptor(_interface->descriptor);
        !           193: #endif
        !           194: 
        !           195:         // Save stuff for polled mode
        !           196:         sPollControl = _interface->bus();
        !           197:         sPollPipe = _interruptPipe;
        !           198:         sBufDesc = IOMemoryDescriptor::withAddress(sBuffer, 8, kIODirectionIn);
        !           199:        PE_poll_input = PE_usb_poll_input;
        !           200: 
        !           201:         return(true);
        !           202: 
        !           203:     } while (false);
        !           204: 
        !           205:     IOLog("%s: aborting startup.  err = %d\n", getName(), err);
        !           206: 
        !           207:     provider->close(this);
        !           208:     stop(provider);
        !           209: 
        !           210:     return(false);
        !           211: }
        !           212: 
        !           213: void AppleKeyboard::stop(IOService * provider)
        !           214: {
        !           215:     if (_buffer) {
        !           216:        _buffer->release();
        !           217:         _buffer = 0;
        !           218:     }
        !           219:     if(sPollPipe == _interruptPipe) {
        !           220:         sPollControl = NULL;
        !           221:         sPollPipe = NULL;
        !           222:         sBufDesc->release();
        !           223:        sBufDesc = NULL;
        !           224:     }
        !           225:     super::stop(provider);
        !           226: }
        !           227: 
        !           228: void AppleKeyboard::test_myusb_f1(void)
        !           229: {
        !           230: /*
        !           231:     char               dummy[8];
        !           232:     IOReturn           err = kIOReturnSuccess;
        !           233:     OSData             *writebuf;
        !           234:     IOUSBPipe *        tinterruptPipe;
        !           235: 
        !           236:        writebuf = OSData::withCapacity(8);
        !           237:        err = _device->openPipe(&tinterruptPipe, _interface->endpoints[0]);
        !           238:        kprintf("Adam1: err is %x\n", err);
        !           239:        dummy[0] = 0xff;
        !           240:        dummy[1] = 0xff;
        !           241:        dummy[2] = 0xff;
        !           242:        dummy[3] = 0xff;
        !           243:        dummy[4] = 0xff;
        !           244:        dummy[5] = 0xff;
        !           245:        dummy[6] = 0xff;
        !           246:        dummy[7] = 0xff;
        !           247: 
        !           248:        writebuf->appendBytes(dummy, 8);
        !           249: //     err = _device->write(writebuf, tinterruptPipe);
        !           250:        kprintf("Adam2: err is %x\n", err);
        !           251:        //deallocate writebuf
        !           252: */
        !           253: }
        !           254: 
        !           255: 
        !           256: //bits = 2 is Caps Lock, I haven't tried anything else.  0 clears all
        !           257: void AppleKeyboard::Set_LED_States(UInt8 bits)
        !           258: {
        !           259:     IOReturn    err = kIOReturnSuccess;
        !           260:     IOUSBCompletion    completion;
        !           261: 
        !           262: 
        !           263:     if (_prevent_LED_set)
        !           264:         return; 
        !           265: 
        !           266:     //_request and _hid_report must be static because the deviceRequest() call
        !           267:     // is asynchronous.
        !           268: 
        !           269:     _request.rqDirection = kUSBOut;
        !           270:     _request.rqType = kUSBClass;
        !           271:     _request.rqRecipient = kUSBInterface;
        !           272:     _request.bRequest = kHIDRqSetReport;  //Set Report in HID specs
        !           273:     OSWriteLittleInt16(&_request.wValue, 0, (UInt16) kHIDRtOutputReport << 8 );
        !           274:     OSWriteLittleInt16(&_request.wIndex, 0,
        !           275:                _interface->interfaceDescriptor()->interfaceNumber); // 0 for iMac keyboards
        !           276:     OSWriteLittleInt16(&_request.wLength, 0, 1); // MacOS 8.5 hard-codes it to 1 byte length
        !           277:     _hid_report[0] = bits;  // 2 to set LED, 0 to clear all LEDs
        !           278:     _hid_report[1] = 0;
        !           279:     _request.pData = (void *)_hid_report;
        !           280: 
        !           281:     completion.target = (void *)self;
        !           282:     completion.action = &AppleKeyboard::setLEDHandler;
        !           283:     completion.parameter = (void *)0;
        !           284:     err = _interface->deviceRequest(&_request, &completion);
        !           285:     return;
        !           286: 
        !           287: }
        !           288: 
        !           289: 
        !           290: extern "C" { 
        !           291:        void Debugger( const char * ); 
        !           292:        void boot(int paniced, int howto, char * command);
        !           293: #define RB_BOOT                1       /* Causes reboot, not halt.  Is in xnu/bsd/sys/reboot.h */
        !           294: 
        !           295: }
        !           296: 
        !           297: 
        !           298: //This helper function is only called by StartHandler below.  key_ptr points
        !           299: // to 8 (kUSB_LOWSPEED_MAXPACKET) valid bytes of data
        !           300: void AppleKeyboard::Simulate_ADB_Event(UInt8 *key_ptr, UInt32 bytes_read)
        !           301: {
        !           302:     UInt8              alpha, modifier=0;
        !           303:     bool               found;
        !           304:     AbsoluteTime       now;
        !           305:     UInt8              seq_key, i;//counter for alpha keys pressed.
        !           306: 
        !           307: /**
        !           308: UInt8          *kbdData;
        !           309: kbdData = key_ptr;
        !           310: kprintf("Num = %d x%x  x%x  x%x  x%x  x%x  x%x  x%x  x%x\n",
        !           311: bytes_read, *kbdData, *(kbdData +1),
        !           312: *(kbdData+2), *(kbdData +3),
        !           313: *(kbdData+4), *(kbdData +5),
        !           314: *(kbdData+6), *(kbdData +7)
        !           315: );
        !           316: **/
        !           317: 
        !           318:     // Test for the keyboard bug where all the keys are 0x01. JDC.
        !           319:     found = true;
        !           320:     for (seq_key = 2; seq_key < prev_bytes_read; seq_key++) {
        !           321:       if (*(key_ptr + seq_key) != 1) found = false;
        !           322:     }
        !           323:     if (found) return;
        !           324: 
        !           325: 
        !           326:     if (bytes_read > kUSB_LOWSPEED_MAXPACKET)  // 8 bytes
        !           327:     {
        !           328:        bytes_read = kUSB_LOWSPEED_MAXPACKET;  //Limit myself to low-speed keyboards
        !           329:     }
        !           330:     modifier = *key_ptr;
        !           331:     //alpha = *(key_ptr +2);  // byte +1 seems to be unused
        !           332:     //adb_code = usb_2_adb_keymap[alpha];
        !           333: 
        !           334:     //Handle new key information.  The first byte is a set of bits describing
        !           335:     //  which modifier keys are down.  The 2nd byte never seems to be used.
        !           336:     //  The third byte is the first USB key down, and the fourth byte is the
        !           337:     //  second key down, and so on.
        !           338:     //When a key is released, there's no code... just a zero upon USB polling
        !           339:     //8/2/99 A.W. fixed Blue Box's multiple modifier keys being pressed 
        !           340:     //   simultaneously.  The trick is if a modifier key DOWN event is reported,
        !           341:     //   and another DOWN is reported, then Blue Box loses track of it.  I must
        !           342:     //   report a UP key event first, or else avoid resending the DOWN event.
        !           343: 
        !           344:  
        !           345:     //SECTION 1. Handle modifier keys here first
        !           346:     if (modifier == oldmodifier) 
        !           347:     {
        !           348:         //Do nothing.  Same keys are still pressed, or if 0 then none pressed
        !           349:        // so don't overload the HID system with useless events.
        !           350:     }
        !           351:     else //Modifiers may or may not be pressed right now
        !           352:     {
        !           353:        //kprintf("mod is %x\n", modifier);
        !           354:         clock_get_uptime(&now);
        !           355: 
        !           356:         //left-hand CONTROL modifier key
        !           357:         if ((modifier & kUSB_LEFT_CONTROL_BIT) && !(oldmodifier & kUSB_LEFT_CONTROL_BIT))
        !           358:         {
        !           359:             dispatchKeyboardEvent(0x36, true, now);  //ADB left-hand CONTROL
        !           360:            _control_key = true;        //determine if we reboot CPU.  Is instance variable.
        !           361:         }
        !           362:        else if ((oldmodifier & kUSB_LEFT_CONTROL_BIT) && !(modifier & kUSB_LEFT_CONTROL_BIT))
        !           363:        {
        !           364:            //Now check for released modifier keys
        !           365:            dispatchKeyboardEvent(0x36, false, now); 
        !           366:            _control_key = false;       
        !           367:        }
        !           368: 
        !           369:         //right-hand CONTROL modifier
        !           370:         if ((modifier & kUSB_RIGHT_CONTROL_BIT) && !(oldmodifier & kUSB_RIGHT_CONTROL_BIT))
        !           371:         {
        !           372:             dispatchKeyboardEvent(0x7d, true, now);  //right-hand CONTROL
        !           373:            _control_key = true;        //determine if we reboot CPU.  Is instance variable.
        !           374:         }
        !           375:        else if ((oldmodifier & kUSB_RIGHT_CONTROL_BIT) && !(modifier & kUSB_RIGHT_CONTROL_BIT))
        !           376:        {
        !           377:            dispatchKeyboardEvent(0x7d, false, now); 
        !           378:            _control_key = false;       
        !           379:        }
        !           380: 
        !           381:         //left-hand SHIFT
        !           382:         if ((modifier & kUSB_LEFT_SHIFT_BIT) && !(oldmodifier & kUSB_LEFT_SHIFT_BIT))
        !           383:         {
        !           384:            // Debugger("LEFT SHIFT");
        !           385: 
        !           386:             dispatchKeyboardEvent(0x38, true, now);
        !           387:         }
        !           388:        else if ((oldmodifier & kUSB_LEFT_SHIFT_BIT) && !(modifier & kUSB_LEFT_SHIFT_BIT))
        !           389:        {
        !           390:            dispatchKeyboardEvent(0x38, false, now); 
        !           391:        }
        !           392: 
        !           393:         //right-hand SHIFT
        !           394:         if ((modifier & kUSB_RIGHT_SHIFT_BIT) && !(oldmodifier & kUSB_RIGHT_SHIFT_BIT))
        !           395:         {
        !           396:             dispatchKeyboardEvent(0x7b, true, now);
        !           397:         }
        !           398:        else if ((oldmodifier & kUSB_RIGHT_SHIFT_BIT) && !(modifier & kUSB_RIGHT_SHIFT_BIT))
        !           399:        {
        !           400:            dispatchKeyboardEvent(0x7b, false, now); 
        !           401:        }
        !           402: 
        !           403:         if ((modifier & kUSB_LEFT_ALT_BIT) && !(oldmodifier & kUSB_LEFT_ALT_BIT))
        !           404:         {
        !           405:             dispatchKeyboardEvent(0x3a, true, now);
        !           406:         }
        !           407:        else if ((oldmodifier & kUSB_LEFT_ALT_BIT) && !(modifier & kUSB_LEFT_ALT_BIT))
        !           408:        {
        !           409:            dispatchKeyboardEvent(0x3a, false, now); 
        !           410:        }
        !           411: 
        !           412:         if ((modifier & kUSB_RIGHT_ALT_BIT) && !(oldmodifier & kUSB_RIGHT_ALT_BIT))
        !           413:         {
        !           414:             dispatchKeyboardEvent(0x7c, true, now);
        !           415:         }
        !           416:        else if ((oldmodifier & kUSB_RIGHT_ALT_BIT) && !(modifier & kUSB_RIGHT_ALT_BIT))
        !           417:        {
        !           418:            dispatchKeyboardEvent(0x7c, false, now); 
        !           419:        }
        !           420: 
        !           421:         if ((modifier & kUSB_LEFT_FLOWER_BIT) && !(oldmodifier & kUSB_LEFT_FLOWER_BIT))
        !           422:         {
        !           423:             dispatchKeyboardEvent(0x37, true, now);
        !           424:            _flower_key = true; //determine if we go into kernel debugger, or reboot CPU
        !           425:         }
        !           426:        else if ((oldmodifier & kUSB_LEFT_FLOWER_BIT) && !(modifier & kUSB_LEFT_FLOWER_BIT))
        !           427:        {
        !           428:            dispatchKeyboardEvent(0x37, false, now); 
        !           429:            _flower_key = false;
        !           430:        }
        !           431: 
        !           432:         if ((modifier & kUSB_RIGHT_FLOWER_BIT) && !(oldmodifier & kUSB_RIGHT_FLOWER_BIT))
        !           433:         {
        !           434:             //dispatchKeyboardEvent(0x7e, true, now);
        !           435:            //WARNING... NeXT only recognizes left-hand flower key, so
        !           436:            //  emulate that for now
        !           437:            dispatchKeyboardEvent(0x37, true, now);
        !           438:            _flower_key = true; 
        !           439:         }
        !           440:        else if ((oldmodifier & kUSB_RIGHT_FLOWER_BIT) && !(modifier & kUSB_RIGHT_FLOWER_BIT))
        !           441:        {
        !           442:            dispatchKeyboardEvent(0x37, false, now); 
        !           443:            _flower_key = false;
        !           444:        }
        !           445: 
        !           446:     }
        !           447: 
        !           448:     //SECTION 2. Handle regular alphanumeric keys now.  Look first at previous keystrokes.
        !           449:     //  Alphanumeric portion of HID report starts at byte +2.
        !           450: 
        !           451:     for (seq_key = 2; seq_key < prev_bytes_read; seq_key++)
        !           452:     {
        !           453:         alpha = old_array[seq_key];
        !           454:        if (alpha == 0) //No keys pressed
        !           455:        {
        !           456:            break;
        !           457:        }
        !           458:        found = false;
        !           459:        for (i = 2; i < bytes_read; i++)  //Look through current keypresses
        !           460:        {
        !           461:             if (alpha == *(key_ptr + i))
        !           462:            {
        !           463:                found = true;   //This key has been held down for a while, so do nothing.
        !           464:                break;          //   Autorepeat is taken care of by IOKit.
        !           465:            }
        !           466:        }
        !           467:        if (!found)
        !           468:        {
        !           469:            clock_get_uptime(&now);
        !           470:            if (alpha == 0x39)    //This is USB Caps Lock scan code
        !           471:            {
        !           472:                if (!_capsLockState)
        !           473:                 {
        !           474:                    dispatchKeyboardEvent(usb_2_adb_keymap[0x39], false, now);
        !           475:                    //Only dispatch if we're in the correct state for Caps Lock
        !           476:                    Set_LED_States(0);
        !           477:                }
        !           478:            }
        !           479:            else  //For any other keys except LED-setting keys, dispatch immediately
        !           480:            {
        !           481:                dispatchKeyboardEvent(usb_2_adb_keymap[alpha], false, now);  //KEY UP
        !           482:            }
        !           483:        }
        !           484:     }
        !           485: 
        !           486:     //Now take care of KEY DOWN.  
        !           487:     for (seq_key = 2; seq_key < bytes_read; seq_key++)
        !           488:     {
        !           489:         alpha = *(key_ptr + seq_key);
        !           490:        if (alpha == 0) //No keys pressed
        !           491:        {
        !           492:            break;
        !           493:        }
        !           494:        else if (alpha == 0x66)    //POWER ON key
        !           495:        {
        !           496:            if ((_control_key) && (_flower_key))  //User wants to reboot
        !           497:            {
        !           498:                boot( RB_BOOT, 0, 0 );  //call to xnu/bsd/kern/kern_shutdown.c
        !           499:            }
        !           500:            if (_flower_key)  // Apple CMD modifier must be simultaneously held down
        !           501:            {
        !           502:                PE_enter_debugger("USB Programmer Key");
        !           503:                //In xnu/pexpert/ppc/pe_interrupt.c  and defined in pexpert.h above
        !           504:            }
        !           505:            //The reason this kernel debugger call is made here instead of KEY UP
        !           506:            //  is that the HID system will see the POWER key and bring up a
        !           507:            //  dialog box to shut down the computer, which is not what we want.
        !           508:        }
        !           509: 
        !           510:        //Don't dispatch the same key again which was held down previously
        !           511:        found = false;
        !           512:        for (i = 2; i < prev_bytes_read; i++)
        !           513:        {
        !           514:             if (alpha == old_array[i])
        !           515:            {
        !           516:                found = true;
        !           517:                break;
        !           518:            }
        !           519:        }
        !           520:        if (!found)
        !           521:        {
        !           522:                    clock_get_uptime(&now);
        !           523:            //If Debugger() is triggered then I shouldn't show the restart dialog
        !           524:            //  box, but I think developers doing kernel debugging can live with
        !           525:            //  this minor incovenience.  Otherwise I need to do more checking here.
        !           526: 
        !           527:            if (alpha == 0x39)    //This is USB Caps Lock scan code
        !           528:            {
        !           529:                if (_capsLockState)
        !           530:                 {
        !           531:                    _capsLockState = 0;
        !           532:                    //Don't do anything else, wait for KEY_UP loop above to handle it
        !           533:                 }
        !           534:                else
        !           535:                {
        !           536:                    _capsLockState = 1;
        !           537:                    Set_LED_States(kUSB_CAPSLOCKLED_SET);  // kUSB_CAPSLOCKLED_SET  = 2
        !           538:                }
        !           539:            }
        !           540: 
        !           541:            dispatchKeyboardEvent(usb_2_adb_keymap[alpha], true, now);
        !           542:        }
        !           543:     }
        !           544: 
        !           545:     //Save the history for next time
        !           546:     oldmodifier = modifier;
        !           547:     prev_bytes_read = bytes_read;
        !           548:     for (i=0; i< bytes_read; i++)  //guaranteed not to exceed 8
        !           549:     {
        !           550:        old_array[i] = *(key_ptr + i);
        !           551:     }
        !           552: 
        !           553: }
        !           554: 
        !           555: 
        !           556: 
        !           557: void AppleKeyboard::setLEDHandler(void *               parameter,
        !           558:                                   IOReturn             status,
        !           559:                                   UInt32               bufferSizeRemaining)
        !           560: {
        !           561:     if (status)
        !           562:     {       
        !           563:         //Setting the LED causes problems on CMD USB controller on MacOSX, 
        !           564:         //  so if error then prevent further attempts.  Log the failure 
        !           565:         IOLog("USB Keyboard Caps Lock LED failed\n");
        !           566:         kprintf("USB Keyboard Caps Lock LED failed\n");
        !           567:         _prevent_LED_set = TRUE;
        !           568:     }   
        !           569: }
        !           570: 
        !           571: void AppleKeyboard::readHandler(void *                 parameter,
        !           572:                                 IOReturn       status,
        !           573:                                 UInt32         bufferSizeRemaining)
        !           574: {
        !           575:     IOReturn                   err = kIOReturnSuccess;
        !           576: 
        !           577:     // Handle the error if any
        !           578:     switch (status)
        !           579:     {
        !           580:         case kIOReturnSuccess:
        !           581:             break;
        !           582: 
        !           583:         case kIOReturnOverrun:
        !           584:             // Not sure what to do with this error.  It means more data
        !           585:             // came back than the size of a descriptor.  Hmmm.  For now
        !           586:             // just ignore it and assume the data that did come back is
        !           587:             // useful.
        !           588:             IOLog("%s: overrun error.  ignoring.\n", getName());
        !           589:             break;
        !           590: 
        !           591:         case kIOReturnNotResponding:
        !           592:             // This probably means the device was unplugged.  Now
        !           593:             // we need to close the driver.
        !           594:             IOLog("%s: Device unplugged.  Goodbye\n", getName());
        !           595:             goto close;
        !           596: 
        !           597:         default:
        !           598:             // We should handle other errors more intelligently, but
        !           599:             // for now just return and assume the error is recoverable.
        !           600:             IOLog("%s: error %d reading interrupt pipe\n", getName(), status);
        !           601:             goto queueAnother;
        !           602:     }
        !           603: 
        !           604:     // Handle the data
        !           605:     Simulate_ADB_Event((UInt8 *)_buffer->getBytesNoCopy(), 
        !           606:               (UInt32)  _maxPacketSize - bufferSizeRemaining);
        !           607: 
        !           608: queueAnother:
        !           609:     // Reset the buffer
        !           610:     _buffer->setLength(_maxPacketSize);
        !           611: 
        !           612:     // Queue up another one before we leave.
        !           613:     if ((err = _interruptPipe->read(_buffer, &_completion)))
        !           614:     {
        !           615:         // This is bad.  We probably shouldn't continue on from here.
        !           616:         IOLog("%s: immediate error %d queueing read\n", getName(), err);
        !           617:         goto close;
        !           618:     }
        !           619: 
        !           620:     return;
        !           621:     
        !           622: close:
        !           623:     _interface->close(this);
        !           624:     return;
        !           625: }
        !           626: 
        !           627: 
        !           628: 
        !           629: // ***************************************************************************
        !           630: // usb_asyncLED
        !           631: //
        !           632: // Called asynchronously to turn on/off the keyboard LED
        !           633: //
        !           634: // **************************************************************************
        !           635: void usb_asyncLED( thread_call_param_t param, thread_call_param_t )
        !           636: {
        !           637:     AppleKeyboard * me = (AppleKeyboard *) param;
        !           638:     me->Set_LED_States( me->_ledState ); 
        !           639: }
        !           640: 
        !           641: 
        !           642: //******************************************************************************
        !           643: // COPIED from ADB keyboard driver 3/25/99
        !           644: // This is usually called on a call-out thread after the caps-lock key is pressed.
        !           645: // ADB operations to PMU are synchronous, and this is must not be done
        !           646: // on the call-out thread since that is the PMU driver workloop thread, and
        !           647: // it will block itself.
        !           648: //
        !           649: // Therefore, we schedule the ADB write to disconnect the call-out thread
        !           650: // and the one that initiates the ADB write.
        !           651: //
        !           652: // *******************************************************************************
        !           653: void AppleKeyboard::setLEDFeedback( UInt8 LED_state)
        !           654: {
        !           655:     _ledState = LED_state;
        !           656: 
        !           657:     thread_call_func(usb_asyncLED, (thread_call_param_t)this, true);
        !           658: }
        !           659: 
        !           660: 
        !           661: // *****************************************************************************
        !           662: // maxKeyCodes
        !           663: // A.W. copied 3/25/99 from ADB keyboard driver, I don't know what this does
        !           664: // ***************************************************************************
        !           665: UInt32 AppleKeyboard::maxKeyCodes (void )
        !           666: {
        !           667: return 0x80;
        !           668: }
        !           669: 
        !           670: 
        !           671: // *************************************************************************
        !           672: // deviceType
        !           673: //
        !           674: // **************************************************************************
        !           675: UInt32 AppleKeyboard::deviceType ( void )
        !           676: {
        !           677:     return 2;
        !           678: }
        !           679: 
        !           680: // ************************************************************************
        !           681: // interfaceID.  Fake ADB for now since USB defaultKeymapOfLength is too complex
        !           682: //
        !           683: // **************************************************************************
        !           684: UInt32 AppleKeyboard::interfaceID ( void )
        !           685: {
        !           686:     //Return value must match "interface" line in .keyboard file
        !           687:     return NX_EVS_DEVICE_INTERFACE_ADB;  // 2 This matches contents of AppleExt.keyboard
        !           688: }
        !           689: 
        !           690: 
        !           691: /***********************************************/
        !           692: //Get handler ID 
        !           693: //
        !           694: //  I assume that this method is only called if a valid USB keyboard
        !           695: //  is found. This method should return a 0 or something if there's
        !           696: //  no keyboard, but then the USB keyboard driver should never have
        !           697: //  been probed if there's no keyboard, so for now it won't return 0.
        !           698: UInt32 AppleKeyboard::handlerID ( void )
        !           699: {
        !           700:     UInt32 ret_id = 0x201;  //513 decimal is ANSI USB iMac keyboard
        !           701: 
        !           702:     //Return value must match "handler_id" line in .keyboard file
        !           703:     // For some reason the ADB and PS/2 keyboard drivers are missing this method
        !           704:     // Also, Beaker Keyboard Prefs doesn't run properly
        !           705:     //Fix hardware bug in iMac USB keyboard mapping for ISO keyboards
        !           706:     //kprintf("\nUSB product = %x, vendor = %x\n", _deviceDescriptor->product, _deviceDescriptor->vendor);
        !           707:     if ( _deviceDescriptor)    //just to be safe
        !           708:     {
        !           709:         if (_deviceDescriptor->vendor == 0xac05) //Apple USB keyboards
        !           710:         {
        !           711:             ret_id = _deviceDescriptor->product;  //0x201=ANSI, 0x202=ISO, or 0x203=JIS
        !           712:            if (ret_id == 0x202)
        !           713:            {
        !           714:                 usb_2_adb_keymap[0x35] = 0x0a;  //Cosmo key18 swaps with key74, 0a is ADB keycode
        !           715:                 usb_2_adb_keymap[0x64] = 0x32;
        !           716:                IOLog("USB ISO keys swapped\n");
        !           717:            }
        !           718:         }
        !           719: 
        !           720:         if (_deviceDescriptor->vendor == 0x045e)  //Microsoft ID
        !           721:         {
        !           722:             if (_deviceDescriptor->product == 0x000b)   //Natural USB+PS/2 keyboard
        !           723:                 ret_id = 18;  //18 is Apple Extended ADB keyboard
        !           724:         }
        !           725:     }
        !           726: 
        !           727:     return ret_id;
        !           728: }
        !           729: 
        !           730: 
        !           731: // *****************************************************************************
        !           732: // defaultKeymapOfLength
        !           733: // A.W. copied from ADB keyboard, I don't have time to make custom USB version
        !           734: // *****************************************************************************
        !           735: const unsigned char * AppleKeyboard::defaultKeymapOfLength (UInt32 * length )
        !           736: {
        !           737:     static const unsigned char appleUSAKeyMap[] = {
        !           738:         0x00,0x00,0x07,
        !           739:         0x00,0x01,0x39,
        !           740:         0x01,0x02,0x38,0x7b,
        !           741:         0x02,0x02,0x36,0x7d,0x03,0x02,0x3a,0x7c,0x04,
        !           742:         0x01,0x37,0x05,0x15,0x52,0x41,0x4c,0x53,0x54,0x55,0x45,0x58,0x57,0x56,0x5b,0x5c,
        !           743:         0x43,0x4b,0x51,0x3b,0x3d,0x3e,0x3c,0x4e,0x59,0x06,0x01,0x72,0x7b,0x0d,0x00,0x61,
        !           744:         0x00,0x41,0x00,0x01,0x00,0x01,0x00,0xca,0x00,0xc7,0x00,0x01,0x00,0x01,0x0d,0x00,
        !           745:         0x73,0x00,0x53,0x00,0x13,0x00,0x13,0x00,0xfb,0x00,0xa7,0x00,0x13,0x00,0x13,0x0d,
        !           746:         0x00,0x64,0x00,0x44,0x00,0x04,0x00,0x04,0x01,0x44,0x01,0xb6,0x00,0x04,0x00,0x04,
        !           747:         0x0d,0x00,0x66,0x00,0x46,0x00,0x06,0x00,0x06,0x00,0xa6,0x01,0xac,0x00,0x06,0x00,
        !           748:             0x06,0x0d,0x00,0x68,0x00,0x48,0x00,0x08,0x00,0x08,0x00,0xe3,0x00,0xeb,0x00,0x00,
        !           749:             0x18,0x00,0x0d,0x00,0x67,0x00,0x47,0x00,0x07,0x00,0x07,0x00,0xf1,0x00,0xe1,0x00,
        !           750:             0x07,0x00,0x07,0x0d,0x00,0x7a,0x00,0x5a,0x00,0x1a,0x00,0x1a,0x00,0xcf,0x01,0x57,
        !           751:             0x00,0x1a,0x00,0x1a,0x0d,0x00,0x78,0x00,0x58,0x00,0x18,0x00,0x18,0x01,0xb4,0x01,
        !           752:             0xce,0x00,0x18,0x00,0x18,0x0d,0x00,0x63,0x00,0x43,0x00,0x03,0x00,0x03,0x01,0xe3,
        !           753:             0x01,0xd3,0x00,0x03,0x00,0x03,0x0d,0x00,0x76,0x00,0x56,0x00,0x16,0x00,0x16,0x01,
        !           754:             0xd6,0x01,0xe0,0x00,0x16,0x00,0x16,0x02,0x00,0x3c,0x00,0x3e,0x0d,0x00,0x62,0x00,
        !           755:             0x42,0x00,0x02,0x00,0x02,0x01,0xe5,0x01,0xf2,0x00,0x02,0x00,0x02,0x0d,0x00,0x71,
        !           756:             0x00,0x51,0x00,0x11,0x00,0x11,0x00,0xfa,0x00,0xea,0x00,0x11,0x00,0x11,0x0d,0x00,
        !           757:             0x77,0x00,0x57,0x00,0x17,0x00,0x17,0x01,0xc8,0x01,0xc7,0x00,0x17,0x00,0x17,0x0d,
        !           758:             0x00,0x65,0x00,0x45,0x00,0x05,0x00,0x05,0x00,0xc2,0x00,0xc5,0x00,0x05,0x00,0x05,
        !           759:             0x0d,0x00,0x72,0x00,0x52,0x00,0x12,0x00,0x12,0x01,0xe2,0x01,0xd2,0x00,0x12,0x00,
        !           760:             0x12,0x0d,0x00,0x79,0x00,0x59,0x00,0x19,0x00,0x19,0x00,0xa5,0x01,0xdb,0x00,0x19,
        !           761:             0x00,0x19,0x0d,0x00,0x74,0x00,0x54,0x00,0x14,0x00,0x14,0x01,0xe4,0x01,0xd4,0x00,
        !           762:             0x14,0x00,0x14,0x0a,0x00,0x31,0x00,0x21,0x01,0xad,0x00,0xa1,0x0e,0x00,0x32,0x00,
        !           763:             0x40,0x00,0x32,0x00,0x00,0x00,0xb2,0x00,0xb3,0x00,0x00,0x00,0x00,0x0a,0x00,0x33,
        !           764:             0x00,0x23,0x00,0xa3,0x01,0xba,0x0a,0x00,0x34,0x00,0x24,0x00,0xa2,0x00,0xa8,0x0e,
        !           765:             0x00,0x36,0x00,0x5e,0x00,0x36,0x00,0x1e,0x00,0xb6,0x00,0xc3,0x00,0x1e,0x00,0x1e,
        !           766:             0x0a,0x00,0x35,0x00,0x25,0x01,0xa5,0x00,0xbd,0x0a,0x00,0x3d,0x00,0x2b,0x01,0xb9,
        !           767:             0x01,0xb1,0x0a,0x00,0x39,0x00,0x28,0x00,0xac,0x00,0xab,0x0a,0x00,0x37,0x00,0x26,
        !           768:             0x01,0xb0,0x01,0xab,0x0e,0x00,0x2d,0x00,0x5f,0x00,0x1f,0x00,0x1f,0x00,0xb1,0x00,
        !           769:             0xd0,0x00,0x1f,0x00,0x1f,0x0a,0x00,0x38,0x00,0x2a,0x00,0xb7,0x00,0xb4,0x0a,0x00,
        !           770:             0x30,0x00,0x29,0x00,0xad,0x00,0xbb,0x0e,0x00,0x5d,0x00,0x7d,0x00,0x1d,0x00,0x1d,
        !           771:             0x00,0x27,0x00,0xba,0x00,0x1d,0x00,0x1d,0x0d,0x00,0x6f,0x00,0x4f,0x00,0x0f,0x00,
        !           772:             0x0f,0x00,0xf9,0x00,0xe9,0x00,0x0f,0x00,0x0f,0x0d,0x00,0x75,0x00,0x55,0x00,0x15,
        !           773:             0x00,0x15,0x00,0xc8,0x00,0xcd,0x00,0x15,0x00,0x15,0x0e,0x00,0x5b,0x00,0x7b,0x00,
        !           774:             0x1b,0x00,0x1b,0x00,0x60,0x00,0xaa,0x00,0x1b,0x00,0x1b,0x0d,0x00,0x69,0x00,0x49,
        !           775:             0x00,0x09,0x00,0x09,0x00,0xc1,0x00,0xf5,0x00,0x09,0x00,0x09,0x0d,0x00,0x70,0x00,
        !           776:             0x50,0x00,0x10,0x00,0x10,0x01,0x70,0x01,0x50,0x00,0x10,0x00,0x10,0x10,0x00,0x0d,
        !           777:             0x00,0x03,0x0d,0x00,0x6c,0x00,0x4c,0x00,0x0c,0x00,0x0c,0x00,0xf8,0x00,0xe8,0x00,
        !           778:             0x0c,0x00,0x0c,0x0d,0x00,0x6a,0x00,0x4a,0x00,0x0a,0x00,0x0a,0x00,0xc6,0x00,0xae,
        !           779:             0x00,0x0a,0x00,0x0a,0x0a,0x00,0x27,0x00,0x22,0x00,0xa9,0x01,0xae,0x0d,0x00,0x6b,
        !           780:             0x00,0x4b,0x00,0x0b,0x00,0x0b,0x00,0xce,0x00,0xaf,0x00,0x0b,0x00,0x0b,0x0a,0x00,
        !           781:             0x3b,0x00,0x3a,0x01,0xb2,0x01,0xa2,0x0e,0x00,0x5c,0x00,0x7c,0x00,0x1c,0x00,0x1c,
        !           782:             0x00,0xe3,0x00,0xeb,0x00,0x1c,0x00,0x1c,0x0a,0x00,0x2c,0x00,0x3c,0x00,0xcb,0x01,
        !           783:             0xa3,0x0a,0x00,0x2f,0x00,0x3f,0x01,0xb8,0x00,0xbf,0x0d,0x00,0x6e,0x00,0x4e,0x00,
        !           784:             0x0e,0x00,0x0e,0x00,0xc4,0x01,0xaf,0x00,0x0e,0x00,0x0e,0x0d,0x00,0x6d,0x00,0x4d,
        !           785:             0x00,0x0d,0x00,0x0d,0x01,0x6d,0x01,0xd8,0x00,0x0d,0x00,0x0d,0x0a,0x00,0x2e,0x00,
        !           786:             0x3e,0x00,0xbc,0x01,0xb3,0x02,0x00,0x09,0x00,0x19,0x0c,0x00,0x20,0x00,0x00,0x00,
        !           787:             0x80,0x00,0x00,0x0a,0x00,0x60,0x00,0x7e,0x00,0x60,0x01,0xbb,0x02,0x00,0x7f,0x00,
        !           788:             0x08,0xff,0x02,0x00,0x1b,0x00,0x7e,0xff,0xff,0xff,0xff,0xff,0x00,0x01,0xac,0x00,
        !           789:             0x01,0xae,0x00,0x01,0xaf,0x00,0x01,0xad,0xff,0xff,0x00,0x00,0x2e,0xff,0x00,0x00,
        !           790:             0x2a,0xff,0x00,0x00,0x2b,0xff,0x00,0x00,0x1b,0xff,0xff,0xff,0x0e,0x00,0x2f,0x00,
        !           791:             0x5c,0x00,0x2f,0x00,0x1c,0x00,0x2f,0x00,0x5c,0x00,0x00,0x0a,0x00,0x00,0x00,0x0d, //XX03
        !           792:             0xff,0x00,0x00,0x2d,0xff,0xff,0x0e,0x00,0x3d,0x00,0x7c,0x00,0x3d,0x00,0x1c,0x00,
        !           793:             0x3d,0x00,0x7c,0x00,0x00,0x18,0x46,0x00,0x00,0x30,0x00,0x00,0x31,0x00,0x00,0x32,
        !           794:             0x00,0x00,0x33,0x00,0x00,0x34,0x00,0x00,0x35,0x00,0x00,0x36,0x00,0x00,0x37,0xff,
        !           795:             0x00,0x00,0x38,0x00,0x00,0x39,0xff,0xff,0xff,0x00,0xfe,0x24,0x00,0xfe,0x25,0x00,
        !           796:             0xfe,0x26,0x00,0xfe,0x22,0x00,0xfe,0x27,0x00,0xfe,0x28,0xff,0x00,0xfe,0x2a,0xff,
        !           797:             0x00,0xfe,0x32,0xff,0x00,0xfe,0x33,0xff,0x00,0xfe,0x29,0xff,0x00,0xfe,0x2b,0xff,
        !           798:             0x00,0xfe,0x34,0xff,0x00,0xfe,0x2e,0x00,0xfe,0x30,0x00,0xfe,0x2d,0x00,0xfe,0x23,
        !           799:             0x00,0xfe,0x2f,0x00,0xfe,0x21,0x00,0xfe,0x31,0x00,0xfe,0x20,0x0f,0x02,0xff,0x04,
        !           800:             0x00,0x31,0x02,0xff,0x04,0x00,0x32,0x02,0xff,0x04,0x00,0x33,0x02,0xff,0x04,0x00,
        !           801:             0x34,0x02,0xff,0x04,0x00,0x35,0x02,0xff,0x04,0x00,0x36,0x02,0xff,0x04,0x00,0x37,
        !           802:             0x02,0xff,0x04,0x00,0x38,0x02,0xff,0x04,0x00,0x39,0x02,0xff,0x04,0x00,0x30,0x02,
        !           803:             0xff,0x04,0x00,0x2d,0x02,0xff,0x04,0x00,0x3d,0x02,0xff,0x04,0x00,0x70,0x02,0xff,
        !           804:             0x04,0x00,0x5d,0x02,0xff,0x04,0x00,0x5b,0x04,0x05,0x72,0x06,0x7f,0x07,
        !           805:             0x3e,0x08,0x3d
        !           806:     };
        !           807: 
        !           808: *length = sizeof(appleUSAKeyMap);
        !           809: return appleUSAKeyMap;
        !           810: }

unix.superglobalmegacorp.com

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