|
|
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: * ! 24: * From EventSrcPCKeyoard.m - PC Keyboard EventSrc subclass implementation ! 25: * Copyright (c) 1992 NeXT Computer, Inc. All rights reserved. ! 26: */ ! 27: ! 28: #include <IOKit/IOLib.h> ! 29: #include <IOKit/hidsystem/IOHIKeyboard.h> ! 30: #include <IOKit/hidsystem/IOHIKeyboardMapper.h> ! 31: #include <IOKit/hidsystem/IOLLEvent.h> ! 32: #include <IOKit/hidsystem/IOHIDParameter.h> ! 33: ! 34: #define super IOHIDevice ! 35: OSDefineMetaClassAndStructors(IOHIKeyboard, IOHIDevice); ! 36: ! 37: bool IOHIKeyboard::init(OSDictionary * properties) ! 38: { ! 39: if (!super::init(properties)) return false; ! 40: ! 41: /* ! 42: * Initialize minimal state. ! 43: */ ! 44: ! 45: _deviceLock = IOLockAlloc(); ! 46: _keyMap = 0; ! 47: _keyStateSize = 4*((maxKeyCodes()+(EVK_BITS_PER_UNIT-1))/EVK_BITS_PER_UNIT); ! 48: _keyState = (UInt32 *) IOMalloc(_keyStateSize); ! 49: ! 50: if (!_deviceLock || !_keyState) return false; ! 51: ! 52: IOLockInit(_deviceLock); ! 53: bzero(_keyState, _keyStateSize); ! 54: ! 55: return true; ! 56: } ! 57: ! 58: bool IOHIKeyboard::start(IOService * provider) ! 59: { ! 60: if (!super::start(provider)) return false; ! 61: ! 62: /* ! 63: * IOHIKeyboard serves both as a service and a nub (we lead a double ! 64: * life). Register ourselves as a nub to kick off matching. ! 65: */ ! 66: ! 67: registerService(); ! 68: ! 69: return true; ! 70: } ! 71: ! 72: void IOHIKeyboard::free() ! 73: // Description: Go Away. Be careful when freeing the lock. ! 74: { ! 75: IOLock * lock = NULL; ! 76: ! 77: if ( _deviceLock ) ! 78: { ! 79: lock = _deviceLock; ! 80: IOTakeLock( lock); ! 81: _deviceLock = NULL; ! 82: } ! 83: if ( _keyMap ) ! 84: _keyMap->release(); ! 85: if( _keyState ) ! 86: IOFree( _keyState, _keyStateSize); ! 87: if ( lock ) ! 88: { ! 89: IOUnlock( lock); ! 90: IOLockFree( lock); ! 91: } ! 92: super::free(); ! 93: } ! 94: ! 95: IOHIDKind IOHIKeyboard::hidKind() ! 96: { ! 97: return kHIKeyboardDevice; ! 98: } ! 99: ! 100: bool IOHIKeyboard::updateProperties( void ) ! 101: { ! 102: UInt64 keyRepeatNano; ! 103: UInt64 initialKeyRepeatNano; ! 104: bool ok; ! 105: ! 106: absolutetime_to_nanoseconds( _keyRepeat, &keyRepeatNano); ! 107: absolutetime_to_nanoseconds( _initialKeyRepeat, &initialKeyRepeatNano); ! 108: ! 109: ok = setProperty( kIOHIDKeyMappingKey, _keyMap ) ! 110: & setProperty( kIOHIDKeyRepeatKey, &keyRepeatNano, ! 111: sizeof(keyRepeatNano)) ! 112: & setProperty( kIOHIDInitialKeyRepeatKey, &initialKeyRepeatNano, ! 113: sizeof(initialKeyRepeatNano)); ! 114: ! 115: return( ok & super::updateProperties() ); ! 116: } ! 117: ! 118: IOReturn IOHIKeyboard::setParamProperties( OSDictionary * dict ) ! 119: { ! 120: OSData * data; ! 121: IOReturn err = kIOReturnSuccess; ! 122: unsigned char * map; ! 123: IOHIKeyboardMapper * oldMap; ! 124: bool updated = false; ! 125: UInt64 nano; ! 126: IOTakeLock( _deviceLock); ! 127: ! 128: if( (data = OSDynamicCast( OSData, ! 129: dict->getObject(kIOHIDKeyRepeatKey)))) { ! 130: ! 131: nano = *((UInt64 *)(data->getBytesNoCopy())); ! 132: if( nano < EV_MINKEYREPEAT) ! 133: nano = EV_MINKEYREPEAT; ! 134: nanoseconds_to_absolutetime(nano, &_keyRepeat); ! 135: updated = true; ! 136: } ! 137: ! 138: if( (data = OSDynamicCast( OSData, ! 139: dict->getObject(kIOHIDInitialKeyRepeatKey)))) { ! 140: ! 141: nano = *((UInt64 *)(data->getBytesNoCopy())); ! 142: if( nano < EV_MINKEYREPEAT) ! 143: nano = EV_MINKEYREPEAT; ! 144: nanoseconds_to_absolutetime(nano, &_initialKeyRepeat); ! 145: updated = true; ! 146: } ! 147: ! 148: if( (data = OSDynamicCast( OSData, dict->getObject(kIOHIDKeyMappingKey)))) { ! 149: ! 150: map = (unsigned char *)IOMalloc( data->getLength() ); ! 151: bcopy( data->getBytesNoCopy(), map, data->getLength() ); ! 152: oldMap = _keyMap; ! 153: _keyMap = IOHIKeyboardMapper::keyboardMapper(this, map, data->getLength(), true); ! 154: if (_keyMap) { ! 155: if (oldMap) ! 156: oldMap->release(); ! 157: updated = true; ! 158: } else { ! 159: _keyMap = oldMap; ! 160: err = kIOReturnBadArgument; ! 161: } ! 162: } ! 163: IOUnlock( _deviceLock); ! 164: ! 165: if( dict->getObject(kIOHIDResetKeyboardKey)) ! 166: resetKeyboard(); ! 167: ! 168: if( updated ) ! 169: updateProperties(); ! 170: ! 171: return( err ); ! 172: } ! 173: ! 174: bool IOHIKeyboard::resetKeyboard() ! 175: // Description: Reset the keymapping to the default value and reconfigure ! 176: // the keyboards. ! 177: { ! 178: const unsigned char *defaultKeymap; ! 179: UInt32 defaultKeymapLength; ! 180: ! 181: IOTakeLock( _deviceLock); ! 182: ! 183: if ( _keyMap ) ! 184: _keyMap->release(); ! 185: ! 186: // Set up default keymapping. ! 187: defaultKeymap = defaultKeymapOfLength(&defaultKeymapLength); ! 188: ! 189: _keyMap = IOHIKeyboardMapper::keyboardMapper( this, ! 190: defaultKeymap, ! 191: defaultKeymapLength, ! 192: false ); ! 193: if (_keyMap) ! 194: { ! 195: clock_interval_to_absolutetime_interval( EV_DEFAULTKEYREPEAT, ! 196: kNanosecondScale, &_keyRepeat); ! 197: clock_interval_to_absolutetime_interval( EV_DEFAULTINITIALREPEAT, ! 198: kNanosecondScale, &_initialKeyRepeat); ! 199: } ! 200: ! 201: updateProperties(); ! 202: ! 203: IOUnlock( _deviceLock); ! 204: return (_keyMap) ? true : false; ! 205: } ! 206: ! 207: void IOHIKeyboard::scheduleAutoRepeat() ! 208: // Description: Schedule a procedure to be called when a timeout has expired ! 209: // so that we can generate a repeated key. ! 210: // Preconditions: ! 211: // * _deviceLock should be held on entry ! 212: { ! 213: if ( _calloutPending == true ) ! 214: { ! 215: thread_call_func_cancel(_autoRepeat, this, true); ! 216: _calloutPending = false; ! 217: } ! 218: if ( AbsoluteTime_to_scalar(&_downRepeatTime) ) ! 219: { ! 220: AbsoluteTime deadline; ! 221: clock_absolutetime_interval_to_deadline(_downRepeatTime, &deadline); ! 222: thread_call_func_delayed(_autoRepeat, this, deadline); ! 223: _calloutPending = true; ! 224: } ! 225: } ! 226: ! 227: void IOHIKeyboard::_autoRepeat(thread_call_param_t arg, ! 228: thread_call_param_t) /* thread_call_func_t */ ! 229: { ! 230: IOHIKeyboard *self = (IOHIKeyboard *) arg; ! 231: self->autoRepeat(); ! 232: } ! 233: ! 234: void IOHIKeyboard::autoRepeat() ! 235: // Description: Repeat the currently pressed key and schedule ourselves ! 236: // to be called again after another interval elapses. ! 237: // Preconditions: ! 238: // * Should only be executed on callout thread ! 239: // * _deviceLock should be unlocked on entry. ! 240: { ! 241: IOTakeLock( _deviceLock); ! 242: if ( _calloutPending == false ) ! 243: { ! 244: IOUnlock( _deviceLock); ! 245: return; ! 246: } ! 247: _calloutPending = false; ! 248: _isRepeat = true; ! 249: ! 250: if ( AbsoluteTime_to_scalar(&_downRepeatTime) ) ! 251: { ! 252: // Device is due to generate a repeat ! 253: if (_keyMap) _keyMap->translateKeyCode(_codeToRepeat, ! 254: /* direction */ true, ! 255: /* keyBits */ _keyState); ! 256: _downRepeatTime = _keyRepeat; ! 257: } ! 258: ! 259: _isRepeat = false; ! 260: scheduleAutoRepeat(); ! 261: IOUnlock( _deviceLock); ! 262: } ! 263: ! 264: void IOHIKeyboard::setRepeat(unsigned eventType, unsigned keyCode) ! 265: // Description: Set up or tear down key repeat operations. The method ! 266: // that locks _deviceLock is a bit higher on the call stack. ! 267: // This method is invoked as a side effect of our own ! 268: // invocation of _keyMap->translateKeyCode(). ! 269: // Preconditions: ! 270: // * _deviceLock should be held upon entry. ! 271: { ! 272: if ( _isRepeat == false ) // make sure we're not already repeating ! 273: { ! 274: if (eventType == NX_KEYDOWN) // Start repeat ! 275: { ! 276: // Set this key to repeat (push out last key if present) ! 277: _downRepeatTime = _initialKeyRepeat; // + _lastEventTime; ! 278: _codeToRepeat = keyCode; ! 279: // reschedule key repeat event here ! 280: scheduleAutoRepeat(); ! 281: } ! 282: else if (eventType == NX_KEYUP) // End repeat ! 283: { ! 284: /* Remove from downKey */ ! 285: if (_codeToRepeat == keyCode) ! 286: { ! 287: AbsoluteTime_to_scalar(&_downRepeatTime) = 0; ! 288: _codeToRepeat = (unsigned)-1; ! 289: scheduleAutoRepeat(); ! 290: } ! 291: } ! 292: } ! 293: } ! 294: ! 295: // ! 296: // BEGIN: Implementation of the methods required by IOHIKeyboardMapper. ! 297: // ! 298: ! 299: void IOHIKeyboard::keyboardEvent(unsigned eventType, ! 300: /* flags */ unsigned flags, ! 301: /* keyCode */ unsigned keyCode, ! 302: /* charCode */ unsigned charCode, ! 303: /* charSet */ unsigned charSet, ! 304: /* originalCharCode */ unsigned origCharCode, ! 305: /* originalCharSet */ unsigned origCharSet) ! 306: // Description: We use this notification to set up our _keyRepeat timer ! 307: // and to pass along the event to our owner. This method ! 308: // will be called while the KeyMap object is processing ! 309: // the key code we've sent it using deliverKey. ! 310: { ! 311: ! 312: if (_keyboardEventAction) /* upstream call */ ! 313: { ! 314: (*_keyboardEventAction)(_keyboardEventTarget, ! 315: eventType, ! 316: /* flags */ flags, ! 317: /* keyCode */ keyCode, ! 318: /* charCode */ charCode, ! 319: /* charSet */ charSet, ! 320: /* originalCharCode */ origCharCode, ! 321: /* originalCharSet */ origCharSet, ! 322: /* repeat */ _isRepeat, ! 323: /* atTime */ _lastEventTime); ! 324: } ! 325: ! 326: // Set up key repeat operations here. ! 327: setRepeat(eventType, keyCode); ! 328: } ! 329: ! 330: void IOHIKeyboard::keyboardSpecialEvent(unsigned eventType, ! 331: /* flags */ unsigned flags, ! 332: /* keyCode */ unsigned keyCode, ! 333: /* specialty */ unsigned flavor) ! 334: // Description: See the description for keyboardEvent. ! 335: { ! 336: ! 337: if (_keyboardSpecialEventAction) /* upstream call */ ! 338: { ! 339: (*_keyboardSpecialEventAction)(_keyboardSpecialEventTarget, ! 340: eventType, ! 341: /* flags */ flags, ! 342: /* keyCode */ keyCode, ! 343: /* specialty */ flavor, ! 344: /* atTime */ _lastEventTime); ! 345: } ! 346: ! 347: // Set up key repeat operations here. ! 348: if (flavor != NX_KEYTYPE_CAPS_LOCK) ! 349: setRepeat(eventType, keyCode); ! 350: } ! 351: ! 352: void IOHIKeyboard::updateEventFlags(unsigned flags) ! 353: // Description: Process non-event-generating flag changes. Simply pass this ! 354: // along to our owner. ! 355: { ! 356: if (_updateEventFlagsAction) /* upstream call */ ! 357: { ! 358: (*_updateEventFlagsAction)(_updateEventFlagsTarget, flags); ! 359: } ! 360: } ! 361: ! 362: unsigned IOHIKeyboard::eventFlags() ! 363: // Description: Return global event flags In this world, there is only ! 364: // one keyboard device so device flags == global flags. ! 365: { ! 366: return _eventFlags; ! 367: } ! 368: ! 369: unsigned IOHIKeyboard::deviceFlags() ! 370: // Description: Return per-device event flags. In this world, there is only ! 371: // one keyboard device so device flags == global flags. ! 372: { ! 373: return _eventFlags; ! 374: } ! 375: ! 376: void IOHIKeyboard::setDeviceFlags(unsigned flags) ! 377: // Description: Set device event flags. In this world, there is only ! 378: // one keyboard device so device flags == global flags. ! 379: { ! 380: _eventFlags = flags; ! 381: } ! 382: ! 383: bool IOHIKeyboard::alphaLock() ! 384: // Description: Return current alpha-lock state. This is a state tracking ! 385: // callback used by the KeyMap object. ! 386: { ! 387: return _alphaLock; ! 388: } ! 389: ! 390: void IOHIKeyboard::setAlphaLock(bool val) ! 391: // Description: Set current alpha-lock state This is a state tracking ! 392: // callback used by the KeyMap object. ! 393: { ! 394: _alphaLock = val; ! 395: setAlphaLockFeedback(val); ! 396: } ! 397: ! 398: bool IOHIKeyboard::charKeyActive() ! 399: // Description: Return true If a character generating key down This is a state ! 400: // tracking callback used by the KeyMap object. ! 401: { ! 402: return _charKeyActive; ! 403: } ! 404: ! 405: void IOHIKeyboard::setCharKeyActive(bool val) ! 406: // Description: Note whether a char generating key is down. This is a state ! 407: // tracking callback used by the KeyMap object. ! 408: { ! 409: _charKeyActive = val; ! 410: } ! 411: // ! 412: // END: Implementation of the methods required by IOHIKeyboardMapper. ! 413: // ! 414: ! 415: void IOHIKeyboard::dispatchKeyboardEvent(unsigned int keyCode, ! 416: /* direction */ bool goingDown, ! 417: /* timeStamp */ AbsoluteTime time) ! 418: // Description: This method is the heart of event dispatching. The overlying ! 419: // subclass invokes this method with each event. We then ! 420: // get the event xlated and dispatched using a _keyMap instance. ! 421: // The event structure passed in by reference should not be freed. ! 422: { ! 423: _lastEventTime = time; ! 424: ! 425: IOTakeLock( _deviceLock); ! 426: ! 427: if (_keyMap) _keyMap->translateKeyCode(keyCode, ! 428: /* direction */ goingDown, ! 429: /* keyBits */ _keyState); ! 430: IOUnlock( _deviceLock); ! 431: } ! 432: ! 433: const unsigned char * IOHIKeyboard::defaultKeymapOfLength(UInt32 * length) ! 434: { ! 435: *length = 0; ! 436: return NULL; ! 437: } ! 438: ! 439: void IOHIKeyboard::setAlphaLockFeedback(bool /* val */) ! 440: { ! 441: return; ! 442: } ! 443: ! 444: UInt32 IOHIKeyboard::maxKeyCodes() ! 445: { ! 446: return( 0x80); ! 447: } ! 448: ! 449: bool IOHIKeyboard::open(IOService * client, ! 450: IOOptionBits options, ! 451: KeyboardEventAction keAction, ! 452: KeyboardSpecialEventAction kseAction, ! 453: UpdateEventFlagsAction uefAction) ! 454: { ! 455: if ( (!_keyMap) && (!resetKeyboard())) return false; ! 456: ! 457: if (super::open(client, options)) ! 458: { ! 459: // Note: client object is already retained by superclass' open() ! 460: _keyboardEventTarget = client; ! 461: _keyboardEventAction = keAction; ! 462: _keyboardSpecialEventTarget = client; ! 463: _keyboardSpecialEventAction = kseAction; ! 464: _updateEventFlagsTarget = client; ! 465: _updateEventFlagsAction = uefAction; ! 466: ! 467: return true; ! 468: } ! 469: ! 470: return false; ! 471: } ! 472: ! 473: void IOHIKeyboard::close(IOService * client, IOOptionBits) ! 474: { ! 475: // kill autorepeat task ! 476: AbsoluteTime_to_scalar(&_downRepeatTime) = 0; ! 477: _codeToRepeat = (unsigned)-1; ! 478: scheduleAutoRepeat(); ! 479: // clear modifiers to avoid stuck keys ! 480: setAlphaLock(false); ! 481: if (_updateEventFlagsAction) ! 482: (*_updateEventFlagsAction)(_updateEventFlagsTarget, 0); _eventFlags = 0; ! 483: bzero(_keyState, _keyStateSize); ! 484: ! 485: _keyboardEventAction = NULL; ! 486: _keyboardEventTarget = 0; ! 487: _keyboardSpecialEventAction = NULL; ! 488: _keyboardSpecialEventTarget = 0; ! 489: _updateEventFlagsAction = NULL; ! 490: _updateEventFlagsTarget = 0; ! 491: ! 492: super::close(client); ! 493: } ! 494:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.