|
|
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: /* Copyright (c) 1992 NeXT Computer, Inc. All rights reserved. ! 26: * ! 27: * PPCKeyboard.m - Keyboard driver. ! 28: * ! 29: * ! 30: * HISTORY ! 31: * 11-Aug-92 Joe Pasqua at NeXT ! 32: * Created. ! 33: * 8-April-97 Simon Douglas ! 34: * Munged into ADB version. Remove mouse interface. ! 35: */ ! 36: ! 37: // TO DO: ! 38: // Make this an indirect client of ADB. ADB should probe to create multiple ! 39: // event sources. ! 40: // Notes: ! 41: // * To find things that need to be fixed, search for FIX, to find questions ! 42: // to be resolved, search for ASK, to find stuff that still needs to be ! 43: // done, search for TO DO. ! 44: ! 45: #define MACH_USER_API 1 ! 46: #undef KERNEL_PRIVATE ! 47: ! 48: #import <machkit/NXLock.h> ! 49: #import <driverkit/IODevice.h> ! 50: #import <driverkit/driverServer.h> ! 51: #import <driverkit/generalFuncs.h> ! 52: #import <driverkit/interruptMsg.h> ! 53: #import <bsd/dev/ppc/PPCKeyboardPriv.h> ! 54: #import <bsd/dev/ppc/PPCKeyboard.h> ! 55: #import <bsd/dev/ppc/PCKeyboardDefs.h> ! 56: #import <driverkit/ppc/directDevice.h> ! 57: #import <driverkit/ppc/driverTypes.h> ! 58: #import <bsd/dev/ev_types.h> ! 59: #import <bsd/dev/event.h> ! 60: ! 61: #import <kern/thread_call.h> ! 62: ! 63: #include <mach_kdb.h> ! 64: #include <mach/mach_types.h> ! 65: #include <sys/tty.h> ! 66: #include <sys/conf.h> ! 67: #include <machdep/ppc/mach_param.h> ! 68: #include <machine/machspl.h> ! 69: ! 70: #include <machdep/ppc/powermac.h> ! 71: ! 72: #include "busses.h" ! 73: #include "adb.h" ! 74: #import "IOADBBus.h" ! 75: ! 76: unsigned char extendCount; ! 77: ! 78: static int adbAsyncAvail = FALSE; /* can try async ADB */ ! 79: static int keyboard_led_state; /* state of caps/num/scroll lock */ ! 80: static id adb_driver; // pointer to adb indirect driver ! 81: ! 82: extern struct tty cons; ! 83: ! 84: void keyboard_updown(unsigned char key); ! 85: void keyboard_adbhandler(int number, unsigned char *buffer, int count, void * ssp); ! 86: void keyboard_init(void); ! 87: void keyboard_updown(unsigned char key); ! 88: ! 89: io_return_t keyboard_set_led_state(int state); ! 90: int keyboard_get_led_state(void); ! 91: void keyboard_initialize_led_state(void); ! 92: ! 93: boolean_t keyboard_initted = FALSE; ! 94: int keyboard_adb_addr = -1; ! 95: ! 96: #define KeyboardIPL 3 ! 97: #define SAFE_IPL (KeyboardIPL + 1) ! 98: ! 99: #define MAX_PENDING_EVENTS 10 ! 100: ! 101: #if KERNOBJC ! 102: static PPCKeyboard *_kbdObj; ! 103: #endif KERNOBJC ! 104: ! 105: static PCKeyboardEvent _pendingEvents[MAX_PENDING_EVENTS]; ! 106: static int _eventIndex; ! 107: /* Forward declarations */ ! 108: static inline PCKeyboardEvent *PPCScancodeToKeyEvent( unsigned char key); ! 109: static void EnqueueKey(int keyCode, ns_time_t stamp); ! 110: ! 111: ! 112: /* Forward declarations */ ! 113: #define msg_printf null_printf ! 114: #define msg1_printf null_printf ! 115: ! 116: #define busywait(x) delay(x) ! 117: ! 118: ! 119: // ! 120: // BEGIN: Definitions used to keep track of key state ! 121: // ! 122: // NOTES: Key up/down state is tracked in a bit list. Bits are set ! 123: // for key-down, and cleared for key-up. The bit vector and ! 124: // macros for it's manipulation are defined here. ! 125: #define KBV_BITS_PER_UNIT 32 ! 126: #define KBV_BITS_MASK 31 ! 127: #define KBV_BITS_SHIFT 5 // 1<<5 == 32, for cheap divide ! 128: #define KBV_NUNITS ((128 + (KBV_BITS_PER_UNIT-1))/KBV_BITS_PER_UNIT) ! 129: ! 130: #define KBV_KEYDOWN(n, bits) \ ! 131: (bits)[((n)>>KBV_BITS_SHIFT)] |= (1 << ((n) & KBV_BITS_MASK)) ! 132: ! 133: #define KBV_KEYUP(n, bits) \ ! 134: (bits)[((n)>>KBV_BITS_SHIFT)] &= ~(1 << ((n) & KBV_BITS_MASK)) ! 135: ! 136: #define KBV_IS_KEYDOWN(n, bits) \ ! 137: (((bits)[((n)>>KBV_BITS_SHIFT)] & (1 << ((n) & KBV_BITS_MASK))) != 0) ! 138: ! 139: static unsigned long _kbdBitVector[KBV_NUNITS]; ! 140: // ! 141: // END: Definitions used to keep track of key state ! 142: // ! 143: ! 144: ! 145: #if KERNOBJC ! 146: ! 147: @implementation PPCKeyboard ! 148: + (IODeviceStyle) deviceStyle ! 149: { ! 150: return IO_IndirectDevice; ! 151: } ! 152: ! 153: static Protocol *protocols[] = { ! 154: @protocol(ADBprotocol), ! 155: nil ! 156: }; ! 157: ! 158: + (Protocol **)requiredProtocols ! 159: { ! 160: return protocols; ! 161: } ! 162: ! 163: ! 164: ! 165: #endif ! 166: ! 167: // ! 168: // BEGIN: Impl. of internal methods for dealing w/ kbd controller ! 169: // NOTE: The following are utility procedures for dealing with ! 170: // The keyboard controller. They are called from the low ! 171: // level interrupt handler. Because of this, they can not be ! 172: // ObjC methods. ! 173: // ! 174: ! 175: ! 176: static void ADBKeyboardInit(void); ! 177: ! 178: static void ! 179: ADBKeyboardInit(void) ! 180: { ! 181: extern boolean_t adb_initted; //extern from adb.m ! 182: int i; ! 183: IOADBDeviceInfo table[IO_ADB_MAX_DEVICE]; ! 184: ! 185: if (!keyboard_initted) { ! 186: //if early debugging mode, table[] is filled with trash, ADB not initialized ! 187: if (!adb_initted) //set in adb.m if ADB were instantiated ! 188: { ! 189: keyboard_initted = FALSE; ! 190: return; ! 191: } ! 192: [adb_driver GetTable: table: &i]; ! 193: for (i = 0; i < ADB_DEVICE_COUNT; i++) { ! 194: if ((table[i].flags & ADB_FLAGS_PRESENT) == 0) ! 195: { ! 196: continue; ! 197: } ! 198: if (table[i].originalAddress == ADB_DEV_KEYBOARD) { ! 199: /* Find the first ADB keyboard device, and use that. */ ! 200: keyboard_adb_addr = i; ! 201: break; //break out of for loop ! 202: } ! 203: } ! 204: keyboard_initted = TRUE; ! 205: /* Pickup all keyboard devices */ ! 206: [adb_driver adb_register_handler:ADB_DEV_KEYBOARD: keyboard_adbhandler]; ! 207: } ! 208: } ! 209: ! 210: ! 211: /* Called the first time the console is opened, can't be done ! 212: * above since it's too early ! 213: */ ! 214: void ! 215: keyboard_initialize_led_state(void) ! 216: { ! 217: keyboard_led_state = keyboard_get_led_state(); ! 218: } ! 219: ! 220: int ! 221: keyboard_get_led_state(void) ! 222: { ! 223: unsigned short lights = 0; ! 224: unsigned char buffer[8]; ! 225: int length; ! 226: ! 227: if (keyboard_adb_addr == -1) ! 228: return 0; ! 229: ! 230: [adb_driver readADBDeviceRegister: keyboard_adb_addr: 2: buffer: &length]; ! 231: ! 232: lights = buffer[0] << 8; ! 233: if (length > 1) { ! 234: lights |= buffer[1]; ! 235: } ! 236: ! 237: return ~lights; ! 238: } ! 239: ! 240: int ! 241: keyboard_set_led_state(int lights) ! 242: { ! 243: unsigned char buffer[2]; ! 244: ! 245: if (keyboard_adb_addr == -1) ! 246: return D_NO_SUCH_DEVICE; ! 247: ! 248: /* Inverse things for ADB */ ! 249: lights = ~lights; ! 250: buffer[0] = lights >> 8; ! 251: buffer[1] = lights & 0xFF; ! 252: ! 253: [adb_driver writeADBDeviceRegister: keyboard_adb_addr: 2: buffer: 2]; ! 254: ! 255: return D_SUCCESS; ! 256: } ! 257: ! 258: ! 259: #import <kern/kdp_internal.h> ! 260: #import <mach/exception.h> ! 261: ! 262: void ! 263: keyboard_adbhandler(int number, unsigned char *buffer, int count, void * ssp) ! 264: { ! 265: ns_time_t stamp; ! 266: ! 267: if ( (HasPMU() && ! 268: (buffer[0] == ADBK_POWER2 || buffer[1] == ADBK_POWER2)) || ! 269: (!HasPMU() && ! 270: (buffer[0] == ADBK_POWER && buffer[1] == ADBK_POWER)) ) ! 271: { ! 272: if (KBV_IS_KEYDOWN(ADBK_CONTROL, _kbdBitVector)) ! 273: { ! 274: IOGetTimestamp(&stamp); ! 275: ! 276: if (KBV_IS_KEYDOWN(ADBK_OPTION, _kbdBitVector)) ! 277: { ! 278: mini_mon("", "Kernel Debugger",ssp); ! 279: EnqueueKey(ADBK_OPTION, stamp); ! 280: } ! 281: else { ! 282: if( kdp.is_conn) { ! 283: #if 0 ! 284: kdp_raise_exception( EXC_SOFTWARE, 0, 0, ssp); ! 285: #else ! 286: call_kdp(); ! 287: #endif ! 288: } else { ! 289: mini_mon("restart", "Restart",ssp); ! 290: } ! 291: } ! 292: EnqueueKey(ADBK_CONTROL, stamp); ! 293: return; ! 294: } ! 295: keyboard_updown(ADBK_POWER); ! 296: keyboard_updown(ADBK_KEYUP(ADBK_POWER)); ! 297: return; ! 298: } ! 299: ! 300: keyboard_updown(buffer[0]); ! 301: if (buffer[1] != 0xff) ! 302: keyboard_updown(buffer[1]); ! 303: } ! 304: ! 305: ! 306: #if KERNOBJC ! 307: void ! 308: KeyboardCallout() ! 309: { ! 310: [_kbdObj interruptHandler]; ! 311: } ! 312: #else ! 313: void cDispatchKeyboardEvent( PCKeyboardEvent *event); ! 314: #endif KERNOBJC ! 315: ! 316: void ! 317: keyboard_updown(unsigned char key) ! 318: { ! 319: PCKeyboardEvent *event; ! 320: if ( (event = (PCKeyboardEvent *)PPCScancodeToKeyEvent(key)) ) ! 321: { ! 322: // Add this event to the queue. If there is no room in the queue, ! 323: // we toss the event. TO DO: when we fill the last entry in the ! 324: // queue we should disable keyboard interrupts until the queue gets ! 325: // some free space. ! 326: if (_eventIndex == MAX_PENDING_EVENTS) ! 327: return; ! 328: _pendingEvents[_eventIndex++] = *event; ! 329: ! 330: // This call causes an interrupt message to be sent. Note that ! 331: // if a previous message is outstanding, this call does nothing. ! 332: // That is, no new message is queued. ! 333: ! 334: if( adbAsyncAvail) ! 335: { ! 336: ! 337: #if KERNOBJC ! 338: #if DRVRKITINTS ! 339: IOSendInterrupt(identity, state, IO_DEVICE_INTERRUPT_MSG); ! 340: #else ! 341: thread_call_func((thread_call_func_t)KeyboardCallout, 0, TRUE); ! 342: #endif DRVRKITINTS ! 343: ! 344: #else ! 345: cDispatchKeyboardEvent( event ); ! 346: _eventIndex = 0; ! 347: #endif DRIVERKIT ! 348: } ! 349: } ! 350: } ! 351: ! 352: // ! 353: // END: Impl. of internal methods for dealing w/ kbd controller ! 354: // ! 355: ! 356: // ! 357: // BEGIN: Implementation of internal functions and methods ! 358: // ! 359: static void EnqueueKey(int keyCode, ns_time_t stamp) ! 360: // Description: Enqueue an event that corresponds to a key coming up ! 361: { ! 362: PCKeyboardEvent event; ! 363: ! 364: if (_eventIndex != MAX_PENDING_EVENTS) ! 365: { ! 366: event.keyCode = keyCode; ! 367: event.goingDown = 0; ! 368: event.timeStamp = stamp; ! 369: _pendingEvents[_eventIndex++] = event; ! 370: } ! 371: } ! 372: ! 373: static inline ! 374: PCKeyboardEvent *PPCScancodeToKeyEvent( ! 375: unsigned char key) ! 376: // Description: Take a scan code from the keyboard and package it up into ! 377: // a PCKeyboard event. ! 378: { ! 379: static PCKeyboardEvent event; ! 380: ! 381: event.keyCode = ADBK_KEYVAL(key); ! 382: IOGetTimestamp(&event.timeStamp); ! 383: event.goingDown = ADBK_PRESS(key); ! 384: ! 385: if (event.goingDown) ! 386: { ! 387: if (KBV_IS_KEYDOWN(event.keyCode, _kbdBitVector)) ! 388: return (PCKeyboardEvent *)0; ! 389: else ! 390: KBV_KEYDOWN(event.keyCode, _kbdBitVector); ! 391: } ! 392: else ! 393: KBV_KEYUP(event.keyCode, _kbdBitVector); ! 394: ! 395: return (&event); ! 396: } ! 397: ! 398: #if KERNOBJC ! 399: ! 400: - (void)interruptHandler ! 401: // Description: This method is invoked by the I/O Thread when a keyboard ! 402: // interrupt message has been recieved. This method reads ! 403: // the keycode, processes it into a PCKeyboardEvent and ! 404: // sends it to our owner. ! 405: { ! 406: int oldIPL, nEvents, i; ! 407: PCKeyboardEvent events[MAX_PENDING_EVENTS]; ! 408: ! 409: if (_owner == nil) ! 410: { ! 411: _eventIndex = 0; //bug 2228585 ! 412: return; // After all that, no one is interested! ! 413: } ! 414: ! 415: // Safely copy the events from the pending queue ! 416: oldIPL = spltty(); ! 417: if (_eventIndex == 1) ! 418: events[0] = _pendingEvents[0]; ! 419: else ! 420: bcopy(_pendingEvents, events, sizeof(PCKeyboardEvent) * _eventIndex); ! 421: nEvents = _eventIndex; ! 422: _eventIndex = 0; ! 423: (void)splx(oldIPL); ! 424: ! 425: for (i = 0; i < nEvents; i++) ! 426: { ! 427: [_owner dispatchKeyboardEvent:&events[i]]; ! 428: } ! 429: } ! 430: ! 431: #ifdef DRVRKITINTS ! 432: ! 433: static volatile void kbdThread(PPCKeyboard *_kbdObject) ! 434: // Description: This is the function which is executed as the I/O Thread. ! 435: // It waits for messages from driverkit and dispatches them ! 436: // as appropriate. ! 437: { ! 438: kern_return_t result; ! 439: msg_header_t msg, *msgPtr = &msg; ! 440: ! 441: /* For the time being;it is already init to false */ ! 442: ! 443: // ! 444: // Main loop. Wait for incoming messages, dispatch as appropriate. ! 445: // ! 446: while (TRUE) { ! 447: msgPtr->msg_size = sizeof(msg); ! 448: msgPtr->msg_local_port = [_kbdObject interruptPort]; ! 449: ! 450: result = msg_receive(msgPtr, MSG_OPTION_NONE, 0); ! 451: if (result != RCV_SUCCESS) { ! 452: IOLog("kbdThread: msg_receive() returned %d\n", result); ! 453: continue; ! 454: } ! 455: ! 456: if (msgPtr->msg_id == IO_DEVICE_INTERRUPT_MSG) ! 457: { ! 458: [_kbdObject interruptHandler]; ! 459: } else ! 460: IOLog("kbdThread: non intr msg received %d\n", result); ! 461: } ! 462: } ! 463: ! 464: #endif DRVRKITINTS ! 465: ! 466: - (BOOL)kbdInit:(IODeviceDescription *)deviceDescription ! 467: // Description: Initialize the keyboard object. Returns NO on error. ! 468: { ! 469: char locationStr[ 24 ]; ! 470: IOADBDeviceInfo deviceInfo; ! 471: ! 472: _owner = nil; ! 473: _desiredOwner = nil; ! 474: _ownerLock = [NXLock new]; ! 475: ! 476: #ifdef DRVRKITINTS ! 477: [self enableAllInterrupts]; ! 478: IOForkThread((IOThreadFunc)kbdThread, self); ! 479: #else ! 480: _kbdObj = self; ! 481: #endif DRVRKITINTS ! 482: ! 483: ADBKeyboardInit(); ! 484: adbAsyncAvail = TRUE; ! 485: ! 486: interfaceId = NX_EVS_DEVICE_INTERFACE_ADB; ! 487: ! 488: [adb_driver getADBInfo: keyboard_adb_addr: &deviceInfo]; ! 489: handlerId = 16 + (deviceInfo.handlerID); ! 490: ! 491: sprintf( locationStr, "handlerID %d", handlerId); ! 492: [self setLocation:locationStr]; ! 493: ! 494: return YES; ! 495: } ! 496: ! 497: // ! 498: // END: Implementation of internal functions and methods ! 499: // ! 500: ! 501: // ! 502: // BEGIN: EXPORTED PPCKeyboard methods ! 503: // ! 504: + (BOOL)probe:deviceDescription ! 505: // Description: Bring a new instance into existance. ! 506: { ! 507: PPCKeyboard *inst; ! 508: ! 509: // ! 510: // Create an instance and initialize some basic instance variables. ! 511: // ! 512: inst = [[self alloc] initFromDeviceDescription:deviceDescription]; ! 513: ! 514: [inst setUnit: 0]; ! 515: [inst setName:"PPCKeyboard0"]; ! 516: [inst setDeviceKind:"PPCKeyboard"]; ! 517: ! 518: // ! 519: // Proceed with initialization. ! 520: // ! 521: if ([inst kbdInit:deviceDescription] == NO) { ! 522: IOLog("PPCKeyboard probe: kdbInit failed\n"); ! 523: [inst free]; ! 524: return NO; ! 525: } ! 526: else ! 527: [inst registerDevice]; ! 528: ! 529: //IODelay(1000000); ! 530: ! 531: [inst setAlphaLockFeedback:NO]; ! 532: ! 533: return YES; ! 534: } ! 535: ! 536: - initFromDeviceDescription:(IODeviceDescription *)deviceDescription ! 537: { ! 538: ! 539: adb_driver = [deviceDescription directDevice]; ! 540: ! 541: return self; ! 542: } ! 543: ! 544: - (BOOL) getHandler:(IOPPCInterruptHandler *)handler ! 545: level:(unsigned int *) ipl ! 546: argument:(unsigned int *) arg ! 547: forInterrupt:(unsigned int) localInterrupt ! 548: { ! 549: #ifdef DRVRKITINTS ! 550: *handler = KbdIntHandler; ! 551: *ipl = 3; ! 552: *arg = 0xdeadbeef; ! 553: return YES; ! 554: #endif DRVRKITINTS ! 555: return NO; ! 556: } ! 557: ! 558: - free ! 559: // Description: Frees an instance. ! 560: { ! 561: [_ownerLock free]; ! 562: return [super free]; ! 563: } ! 564: ! 565: ! 566: - (int)interfaceId ! 567: // Description: return keyboard interface ID. ! 568: { ! 569: return interfaceId; ! 570: } ! 571: ! 572: - (int)handlerId ! 573: // Description: return keyboard handler ID. ! 574: { ! 575: return handlerId; ! 576: } ! 577: ! 578: - (void)setAlphaLockFeedback:(BOOL)locked ! 579: // Description: Set the keyboard LEDs to indicate the state of alpha lock ! 580: { ! 581: keyboard_set_led_state( locked ? ADBKS_LED_CAPSLOCK : 0 ); ! 582: } ! 583: ! 584: #endif KERNOBJC ! 585: ! 586: static PCKeyboardEvent stolenEvent; ! 587: ! 588: PCKeyboardEvent *PPCStealKeyEvent() ! 589: // Description: Call this routine to steal a keyboard event directly ! 590: // from the hardware. Must be called from interrupt level. ! 591: { ! 592: ADBKeyboardInit(); ! 593: ! 594: if (_eventIndex == 0) { ! 595: CheckADBPoll(); ! 596: if (_eventIndex == 0) ! 597: return NULL; ! 598: } ! 599: // This sucks. ! 600: stolenEvent = _pendingEvents[0]; ! 601: _eventIndex--; ! 602: bcopy( &_pendingEvents[1], &_pendingEvents[0], sizeof(PCKeyboardEvent) * _eventIndex); ! 603: ! 604: return( &stolenEvent ); ! 605: } ! 606: ! 607: // ! 608: // END: EXPORTED PPCKeyboard methods ! 609: // ! 610: ! 611: #if KERNOBJC ! 612: ! 613: // ! 614: // BEGIN: Implementation of the PCKeyboardExported protocol ! 615: // ! 616: - (IOReturn)becomeOwner : client; ! 617: // Description: Register for event dispatch via device-specific protocol. ! 618: // (See the dispatchKeyboardEvent method) ! 619: // Returns IO_R_SUCCESS if successful, else IO_R_BUSY. The ! 620: // relinquishOwnershipRequest: method may be called on another ! 621: // client during the execution of this method. ! 622: { ! 623: IOReturn rtn; ! 624: ! 625: [_ownerLock lock]; ! 626: if(_owner != nil) { ! 627: if([_owner respondsTo:@selector(relinquishOwnershipRequest:)]) ! 628: { ! 629: rtn = [_owner relinquishOwnershipRequest:self]; ! 630: } ! 631: else { ! 632: IOLog("%s: owner %s does not respond to " ! 633: "relinquishOwnershipRequest:\n", ! 634: [self name], [_owner name]); ! 635: rtn = IO_R_BUSY; ! 636: } ! 637: ! 638: if(rtn == IO_R_SUCCESS) { ! 639: _owner = client; ! 640: } ! 641: else { ! 642: // NEGOTIATION FAILED ! 643: } ! 644: } ! 645: else { ! 646: _owner = client; ! 647: rtn = IO_R_SUCCESS; ! 648: } ! 649: ! 650: [_ownerLock unlock]; ! 651: ! 652: if( rtn == IO_R_SUCCESS) { ! 653: // Send the new owner a capslock down ! 654: ! 655: unsigned char read_buf[8]; ! 656: int rcvd_length; ! 657: int s; ! 658: ! 659: [ adb_driver readADBDeviceRegister: keyboard_adb_addr: 2: read_buf: &rcvd_length]; ! 660: if( (rcvd_length == 2) && ! 661: (0 == (read_buf[0] & ADBKS_CAPSLOCK_short))) { ! 662: s = spltty(); ! 663: KBV_KEYUP(ADBK_CAPSLOCK, _kbdBitVector); ! 664: keyboard_updown(ADBK_CAPSLOCK); ! 665: splx(s); ! 666: } ! 667: } ! 668: return rtn; ! 669: } ! 670: ! 671: - (IOReturn)relinquishOwnership : client; ! 672: // Description: Relinquish ownership. Returns IO_R_BUSY if caller is not ! 673: // current owner. ! 674: { ! 675: IOReturn rtn; ! 676: ! 677: [_ownerLock lock]; ! 678: if(_owner == client) { ! 679: rtn = IO_R_SUCCESS; ! 680: _owner = nil; ! 681: } ! 682: else { ! 683: rtn = IO_R_BUSY; ! 684: } ! 685: [_ownerLock unlock]; ! 686: if((rtn == IO_R_SUCCESS) && ! 687: _desiredOwner && ! 688: (_desiredOwner != client)) { ! 689: /* ! 690: * Notify this potential client that it can take over. ! 691: * We'll most likely be called back during this method, ! 692: * which is why we released _ownerLock. ! 693: */ ! 694: if([_desiredOwner respondsTo:@selector(canBecomeOwner:)]) { ! 695: [_desiredOwner canBecomeOwner:self]; ! 696: } ! 697: else { ! 698: IOLog("%s: desiredOwner does not respond to " ! 699: "canBecomeOwner:\n", [self name]); ! 700: } ! 701: } ! 702: return rtn; ! 703: } ! 704: ! 705: ! 706: - (IOReturn)desireOwnership : client; ! 707: // Description: Request notification (via canBecomeOwner:) when ! 708: // relinquishOwnership: is called. This allows one potential ! 709: // client to place itself "next in line" for ownership. The ! 710: // queue is only one deep. ! 711: { ! 712: IOReturn rtn; ! 713: ! 714: [_ownerLock lock]; ! 715: if(_desiredOwner && (_desiredOwner != client)) { ! 716: rtn = IO_R_BUSY; ! 717: } ! 718: else { ! 719: _desiredOwner = client; ! 720: rtn = IO_R_SUCCESS; ! 721: } ! 722: [_ownerLock unlock]; ! 723: return rtn; ! 724: } ! 725: // ! 726: // END: Implementation of the PCKeyboardExported protocol ! 727: // ! 728: @end ! 729: ! 730: #endif KERNOBJC ! 731: ! 732: ! 733: ! 734:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.