|
|
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: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.