1/* 2 * @APPLE_LICENSE_HEADER_START@ 3 * 4 * Copyright (c) 1999-2009 Apple Computer, Inc. All Rights Reserved. 5 * 6 * This file contains Original Code and/or Modifications of Original Code 7 * as defined in and that are subject to the Apple Public Source License 8 * Version 2.0 (the 'License'). You may not use this file except in 9 * compliance with the License. Please obtain a copy of the License at 10 * http://www.opensource.apple.com/apsl/ and read it before using this 11 * file. 12 * 13 * The Original Code and all software distributed under the License are 14 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER 15 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, 16 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, 17 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. 18 * Please see the License for the specific language governing rights and 19 * limitations under the License. 20 * 21 * @APPLE_LICENSE_HEADER_END@ 22 */ 23/* 24 * 24-Jan-01 bubba Don't auto-repeat on Power Key. This prevents infinite power key 25 * events from being generated when this key is hit on ADB keyboards. 26 */ 27 28#include <AssertMacros.h> 29#include <IOKit/IOLib.h> 30#include <IOKit/IOLocks.h> 31#include <IOKit/hidsystem/IOHIKeyboardMapper.h> 32#include <IOKit/hidsystem/IOLLEvent.h> 33#include <IOKit/hidsystem/IOHIDParameter.h> 34#include "IOKit/hidsystem/IOHIDSystem.h" 35#include "IOKit/hidsystem/IOHIKeyboard.h" 36#include "IOHIDKeyboardDevice.h" 37#include "IOHIDFamilyTrace.h" 38#include "IOHIDSecurePromptClient.h" 39#include "ev_private.h" 40 41//************************************************************************ 42// KeyboardReserved 43// 44// RY: The following was added because the IOHIKeyboard class doesn't have 45// a reserved field defined. Essentially what this does is create a 46// static dictionary that stores OSData objects for each keyboard. These 47// OSData objects will be added and removed as each keyboard enters and 48// leaves the system. 49 50struct KeyboardReserved 51{ 52 IOHIKeyboard * service; 53 thread_call_t repeat_thread_call; 54 bool dispatchEventCalled; 55 bool isSeized; 56 bool repeatMode; 57 bool hasSecurePrompt; 58 IOService * openClient; 59 IOHIDKeyboardDevice * keyboardNub; 60}; 61 62static OSArray *gKeyboardReservedArray = OSArray::withCapacity(4); 63IOLock *gKeyboardReservedArrayLock = IOLockAlloc(); 64 65static KeyboardReserved * GetKeyboardReservedStructEventForService(IOHIKeyboard *service, UInt32 * index = 0) 66{ 67 KeyboardReserved * retVal = 0; 68 if (gKeyboardReservedArray) { 69 OSCollectionIterator * iterator = 0; 70 iterator = OSCollectionIterator::withCollection(gKeyboardReservedArray); 71 if (iterator) { 72 bool done = false; 73 while (!done) { 74 OSObject * obj = 0; 75 IOLockLock(gKeyboardReservedArrayLock); 76 while (!done && (NULL != (obj = iterator->getNextObject()))) { 77 obj->retain(); 78 IOLockUnlock(gKeyboardReservedArrayLock); 79 80 OSData * data = OSDynamicCast(OSData, obj); 81 if (data) { 82 retVal = (KeyboardReserved *)data->getBytesNoCopy(); 83 if (retVal && (retVal->service == service)) { 84 if (index) 85 *index = gKeyboardReservedArray->getNextIndexOfObject(obj, 0); 86 done = true; 87 } 88 else { 89 retVal = 0; 90 } 91 } 92 IOLockLock(gKeyboardReservedArrayLock); 93 } 94 IOLockUnlock(gKeyboardReservedArrayLock); 95 if (iterator->isValid()) { 96 done = true; 97 } 98 else { 99 iterator->reset(); 100 } 101 } 102 iterator->release(); 103 } 104 } 105 return retVal; 106} 107 108static void AppendNewKeyboardReservedStructForService(IOHIKeyboard *service) 109{ 110 KeyboardReserved temp; 111 OSData * data = 0; 112 113 if (gKeyboardReservedArray) 114 { 115 bzero(&temp, sizeof(KeyboardReserved)); 116 temp.repeatMode = true; 117 temp.service = service; 118 data = OSData::withBytes(&temp, sizeof(KeyboardReserved)); 119 IOLockLock(gKeyboardReservedArrayLock); 120 gKeyboardReservedArray->setObject(data); 121 IOLockUnlock(gKeyboardReservedArrayLock); 122 data->release(); 123 } 124} 125 126static void RemoveKeyboardReservedStructForService(IOHIKeyboard *service) 127{ 128 UInt32 index = 0; 129 130 if (gKeyboardReservedArray && GetKeyboardReservedStructEventForService(service, &index) ) 131 { 132 IOLockLock(gKeyboardReservedArrayLock); 133 gKeyboardReservedArray->removeObject(index); 134 IOLockUnlock(gKeyboardReservedArrayLock); 135 } 136} 137 138//************************************************************************ 139 140#define super IOHIDevice 141OSDefineMetaClassAndStructors(IOHIKeyboard, IOHIDevice); 142 143bool IOHIKeyboard::init(OSDictionary * properties) 144{ 145 if (!super::init(properties)) return false; 146 147 /* 148 * Initialize minimal state. 149 */ 150 151 _deviceLock = IOLockAlloc(); 152 _keyMap = 0; 153 _keyStateSize = 4*((maxKeyCodes()+(EVK_BITS_PER_UNIT-1))/EVK_BITS_PER_UNIT); 154 _keyState = (UInt32 *) IOMalloc(_keyStateSize); 155 _codeToRepeat = (unsigned)-1; 156 157 _keyboardEventTarget = 0; 158 _keyboardEventAction = 0; 159 _keyboardSpecialEventTarget = 0; 160 _keyboardSpecialEventAction = 0; 161 _updateEventFlagsTarget = 0; 162 _updateEventFlagsAction = 0; 163 164 if (!_deviceLock || !_keyState) return false; 165 166 bzero(_keyState, _keyStateSize); 167 168 return true; 169} 170 171bool IOHIKeyboard::start(IOService * provider) 172{ 173 if (!super::start(provider)) return false; 174 175 /* 176 * IOHIKeyboard serves both as a service and a nub (we lead a double 177 * life). Register ourselves as a nub to kick off matching. 178 */ 179 180 AppendNewKeyboardReservedStructForService(this); 181 KeyboardReserved * tempReservedStruct = GetKeyboardReservedStructEventForService(this); 182 183 if (tempReservedStruct) 184 { 185 tempReservedStruct->repeat_thread_call = thread_call_allocate(_autoRepeat, this); 186 } 187 188 registerService(kIOServiceAsynchronous); 189 190 return true; 191} 192 193void IOHIKeyboard::stop(IOService * provider) 194{ 195 super::stop(provider); 196 197 KeyboardReserved *tempReservedStruct = GetKeyboardReservedStructEventForService(this); 198 199 if (tempReservedStruct) { 200 thread_call_cancel(tempReservedStruct->repeat_thread_call); 201 thread_call_free(tempReservedStruct->repeat_thread_call); 202 tempReservedStruct->repeat_thread_call = NULL; 203 204 if ( tempReservedStruct->keyboardNub ) 205 tempReservedStruct->keyboardNub->release(); 206 tempReservedStruct->keyboardNub = NULL; 207 208 if ( tempReservedStruct->hasSecurePrompt ) 209 tempReservedStruct->hasSecurePrompt = false; 210 211 RemoveKeyboardReservedStructForService(this); 212 } 213} 214 215void IOHIKeyboard::free() 216// Description: Go Away. Be careful when freeing the lock. 217{ 218 IOLock * lock = NULL; 219 220 if ( _deviceLock ) 221 { 222 lock = _deviceLock; 223 IOLockLock( lock); 224 _deviceLock = NULL; 225 } 226 227 if ( _keyMap ) { 228 _keyMap->release(); 229 _keyMap = 0; 230 } 231 232 if( _keyState ) 233 IOFree( _keyState, _keyStateSize); 234 235 // RY: MENTAL NOTE Do this last 236 if ( lock ) 237 { 238 IOLockUnlock( lock); 239 IOLockFree( lock); 240 } 241 242 super::free(); 243} 244 245IOHIDKind IOHIKeyboard::hidKind() 246{ 247 return kHIKeyboardDevice; 248} 249 250bool IOHIKeyboard::updateProperties( void ) 251{ 252 bool ok; 253 254 ok = setProperty( kIOHIDKeyMappingKey, _keyMap ); 255 256 return( ok & super::updateProperties() ); 257} 258 259IOReturn IOHIKeyboard::setParamProperties( OSDictionary * dict ) 260{ 261 OSData * data = NULL; 262 OSNumber * number = NULL; 263 IOReturn err = kIOReturnSuccess; 264 IOReturn err2 = kIOReturnSuccess; 265 unsigned char * map = NULL; 266 IOHIKeyboardMapper * oldMap = NULL; 267 bool updated = false; 268 UInt64 nano; 269 270 if( dict->getObject(kIOHIDResetKeyboardKey)) 271 resetKeyboard(); 272 273 IOLockLock( _deviceLock); 274 275 if ((number = OSDynamicCast(OSNumber, 276 dict->getObject(kIOHIDKeyRepeatKey))) || 277 (data = OSDynamicCast(OSData, 278 dict->getObject(kIOHIDKeyRepeatKey)))) 279 { 280 nano = (number) ? number->unsigned64BitValue() : *((UInt64 *) (data->getBytesNoCopy())); 281 282 if( nano < EV_MINKEYREPEAT) 283 nano = EV_MINKEYREPEAT; 284 nanoseconds_to_absolutetime(nano, &_keyRepeat); 285 updated = true; 286 } 287 288 if ((number = OSDynamicCast(OSNumber, 289 dict->getObject(kIOHIDInitialKeyRepeatKey))) || 290 (data = OSDynamicCast(OSData, 291 dict->getObject(kIOHIDInitialKeyRepeatKey)))) 292 { 293 nano = (number) ? number->unsigned64BitValue() : *((UInt64 *) (data->getBytesNoCopy())); 294 295 if( nano < EV_MINKEYREPEAT) 296 nano = EV_MINKEYREPEAT; 297 nanoseconds_to_absolutetime(nano, &_initialKeyRepeat); 298 updated = true; 299 } 300 301 if( (data = OSDynamicCast( OSData, dict->getObject(kIOHIDKeyMappingKey)))) 302 { 303 304 map = (unsigned char *)IOMalloc( data->getLength() ); 305 bcopy( data->getBytesNoCopy(), map, data->getLength() ); 306 oldMap = _keyMap; 307 _keyMap = IOHIKeyboardMapper::keyboardMapper(this, map, data->getLength(), true); 308 309 if (_keyMap) 310 { 311 // point the new keymap to the IOHIDSystem, so it can set properties in it 312 _keyMap->setKeyboardTarget((IOService *) _keyboardEventTarget); 313 314 if (oldMap) 315 oldMap->release(); 316 updated = true; 317 } 318 else 319 { 320 _keyMap = oldMap; 321 err = kIOReturnBadArgument; 322 } 323 } 324 if (NULL != (number = OSDynamicCast(OSNumber, dict->getObject(kIOHIDSubinterfaceIDKey)))) 325 { 326 if (!OSDynamicCast(OSNumber, getProperty(kIOHIDOriginalSubinterfaceIDKey))) { 327 // no original key 328 OSNumber *original = (OSNumber*)copyProperty(kIOHIDSubinterfaceIDKey); 329 if (OSDynamicCast(OSNumber, original)) { 330 setProperty(kIOHIDOriginalSubinterfaceIDKey, original); 331 } 332 OSSafeReleaseNULL(original); 333 } 334 _deviceType = number->unsigned32BitValue(); 335 updated = true; 336 } 337 338 // give the keymap a chance to update to new properties 339 if (_keyMap) 340 err2 = _keyMap->setParamProperties(dict); 341 342 IOLockUnlock( _deviceLock); 343 344 if( updated ) 345 updateProperties(); 346 347 // we can only return one error 348 if (err == kIOReturnSuccess) 349 err = err2; 350 351 return( err == kIOReturnSuccess ) ? super::setParamProperties(dict) : err; 352} 353 354// RY: Override IORegistryEntry::setProperties(). This was removed earlier 355// in Leopard, but turns out that won't work as the linker will not end up 356// doing the right thing and travese the super class to resolve the symbol. 357IOReturn IOHIKeyboard::setProperties( OSObject * properties ) 358{ 359 return super::setProperties(properties); 360} 361 362 363 364bool IOHIKeyboard::resetKeyboard() 365// Description: Reset the keymapping to the default value and reconfigure 366// the keyboards. 367{ 368 const unsigned char *defaultKeymap; 369 UInt32 defaultKeymapLength; 370 371 IOLockLock( _deviceLock); 372 373 if ( _keyMap ) { 374 _keyMap->release(); 375 _keyMap = 0; 376 } 377 378 // Set up default keymapping. 379 defaultKeymap = defaultKeymapOfLength(&defaultKeymapLength); 380 381 _keyMap = IOHIKeyboardMapper::keyboardMapper( this, 382 defaultKeymap, 383 defaultKeymapLength, 384 false ); 385 386 if (_keyMap) 387 { 388 // point the new keymap to the IOHIDSystem, so it can set properties in it 389 _keyMap->setKeyboardTarget((IOService *) _keyboardEventTarget); 390 391 clock_interval_to_absolutetime_interval( EV_DEFAULTKEYREPEAT, 392 kNanosecondScale, &_keyRepeat); 393 clock_interval_to_absolutetime_interval( EV_DEFAULTINITIALREPEAT, 394 kNanosecondScale, &_initialKeyRepeat); 395 } 396 397 updateProperties(); 398 399 _interfaceType = interfaceID(); 400 _deviceType = deviceType(); 401 _guid = getGUID(); 402 403 if (getProperty("HIDKeyboardKeysDefined")) 404 { 405 KeyboardReserved * reservedStruct = GetKeyboardReservedStructEventForService(this); 406 407 if ( reservedStruct && !reservedStruct->keyboardNub) 408 reservedStruct->keyboardNub = IOHIDKeyboardDevice::newKeyboardDeviceAndStart(this); 409 } 410 411 IOLockUnlock( _deviceLock); 412 return (_keyMap) ? true : false; 413} 414 415void IOHIKeyboard::scheduleAutoRepeat() 416// Description: Schedule a procedure to be called when a timeout has expired 417// so that we can generate a repeated key. 418// Preconditions: 419// * _deviceLock should be held on entry 420{ 421 KeyboardReserved *tempReservedStruct = GetKeyboardReservedStructEventForService(this); 422 423 if ( _calloutPending == true ) 424 { 425 if (tempReservedStruct) { 426 thread_call_cancel(tempReservedStruct->repeat_thread_call); 427 } 428 _calloutPending = false; 429 } 430 if ( AbsoluteTime_to_scalar(&_downRepeatTime) ) 431 { 432 AbsoluteTime deadline; 433 clock_absolutetime_interval_to_deadline(_downRepeatTime, &deadline); 434 if (tempReservedStruct) { 435 IOHID_DEBUG(kIOHIDDebugCode_KeyboardCapsThreadTrigger, this, __OSAbsoluteTime(deadline), tempReservedStruct->repeat_thread_call, 0); 436 thread_call_enter_delayed(tempReservedStruct->repeat_thread_call, deadline); 437 } 438 _calloutPending = true; 439 } 440} 441 442void IOHIKeyboard::_autoRepeat(thread_call_param_t arg, 443 thread_call_param_t) /* thread_call_func_t */ 444{ 445 IOHIKeyboard *self = (IOHIKeyboard *) arg; 446 IOHID_DEBUG(kIOHIDDebugCode_KeyboardCapsThreadActive, self, self ? self->_codeToRepeat : 0, 0, 0); 447 self->autoRepeat(); 448} 449 450void IOHIKeyboard::autoRepeat() 451// Description: Repeat the currently pressed key and schedule ourselves 452// to be called again after another interval elapses. 453// Preconditions: 454// * Should only be executed on callout thread 455// * _deviceLock should be unlocked on entry. 456{ 457 KeyboardReserved *tempReservedStruct = GetKeyboardReservedStructEventForService(this); 458 459 IOLockLock( _deviceLock); 460 if (( _calloutPending == false ) || 461 ((tempReservedStruct) && tempReservedStruct->dispatchEventCalled )) 462 { 463 IOLockUnlock( _deviceLock); 464 return; 465 } 466 _calloutPending = false; 467 _isRepeat = true; 468 469 if (tempReservedStruct) tempReservedStruct->dispatchEventCalled = true; 470 471 if ( AbsoluteTime_to_scalar(&_downRepeatTime) ) 472 { 473 // Device is due to generate a repeat 474 // <rdar://problem/7415196> 475 if (postSecureKey(_codeToRepeat, true)) { 476 // do nothing 477 } 478 else if (_keyMap) { 479 _keyMap->translateKeyCode(_codeToRepeat, 480 true, /* direction */ 481 _keyState /* keyBits */); 482 } 483 _downRepeatTime = _keyRepeat; 484 } 485 486 if (tempReservedStruct) tempReservedStruct->dispatchEventCalled = false; 487 488 _isRepeat = false; 489 scheduleAutoRepeat(); 490 IOLockUnlock( _deviceLock); 491} 492 493void IOHIKeyboard::setRepeat(unsigned eventType, unsigned keyCode) 494// Description: Set up or tear down key repeat operations. The method 495// that locks _deviceLock is a bit higher on the call stack. 496// This method is invoked as a side effect of our own 497// invocation of _keyMap->translateKeyCode(). 498// Preconditions: 499// * _deviceLock should be held upon entry. 500{ 501 KeyboardReserved *tempReservedStruct; 502 503 if ( _isRepeat == false ) // make sure we're not already repeating 504 { 505 tempReservedStruct = GetKeyboardReservedStructEventForService(this); 506 507 if ((eventType == NX_KEYDOWN) && 508 (tempReservedStruct && (tempReservedStruct->repeatMode == true))) // Start repeat 509 { 510 // Set this key to repeat (push out last key if present) 511 _downRepeatTime = _initialKeyRepeat; // + _lastEventTime; 512 _codeToRepeat = keyCode; 513 // reschedule key repeat event here 514 scheduleAutoRepeat(); 515 } 516 else if (((eventType == NX_KEYUP) && (_codeToRepeat == keyCode)) || 517 (tempReservedStruct && (tempReservedStruct->repeatMode == false))) // End repeat 518 { 519 AbsoluteTime_to_scalar(&_downRepeatTime) = 0; 520 _codeToRepeat = (unsigned)-1; 521 scheduleAutoRepeat(); 522 } 523 } 524} 525 526void IOHIKeyboard::setRepeatMode(bool repeat) 527{ 528 KeyboardReserved *tempReservedStruct = GetKeyboardReservedStructEventForService(this); 529 530 IOLockLock( _deviceLock); 531 if (tempReservedStruct) 532 { 533 tempReservedStruct->repeatMode = repeat; 534 } 535 IOLockUnlock( _deviceLock); 536} 537 538 539// 540// BEGIN: Implementation of the methods required by IOHIKeyboardMapper. 541// 542 543void IOHIKeyboard::keyboardEvent(unsigned eventType, 544 /* flags */ unsigned flags, 545 /* keyCode */ unsigned keyCode, 546 /* charCode */ unsigned charCode, 547 /* charSet */ unsigned charSet, 548 /* originalCharCode */ unsigned origCharCode, 549 /* originalCharSet */ unsigned origCharSet) 550// Description: We use this notification to set up our _keyRepeat timer 551// and to pass along the event to our owner. This method 552// will be called while the KeyMap object is processing 553// the key code we've sent it using deliverKey. 554{ 555 KeyboardReserved *tempReservedStruct = GetKeyboardReservedStructEventForService(this); 556 bool relock = false; 557 558 if (tempReservedStruct && tempReservedStruct->dispatchEventCalled) 559 { 560 relock = true; 561 IOLockUnlock(_deviceLock); 562 } 563 564 UInt16 usage = 0; 565 UInt16 usagePage = 0; 566 unsigned modifiedOrigCharCode = origCharCode; 567 unsigned modifiedOrigCharSet = origCharSet; 568 unsigned modifiedFlags = flags; 569 570 if ((origCharCode < 0xffff) && (origCharSet < 0xffff)) { 571 getLastPageAndUsage(usagePage, usage); 572 573 if (usage || usagePage) { 574 modifiedOrigCharCode |= usage << 16; 575 modifiedOrigCharSet |= usagePage << 16; 576 modifiedFlags |= NX_HIGHCODE_ENCODING_MASK; 577 } 578 } 579 else { 580 IOLog("IOHIKeyboard::keyboardEvent original code/set unusually large %02x:%02x\n", origCharCode, origCharSet); 581 } 582 583 _keyboardEvent( this, 584 eventType, 585 /* flags */ modifiedFlags, 586 /* keyCode */ keyCode, 587 /* charCode */ charCode, 588 /* charSet */ charSet, 589 /* originalCharCode */ modifiedOrigCharCode, 590 /* originalCharSet */ modifiedOrigCharSet, 591 /* keyboardType */ _deviceType, 592 /* repeat */ _isRepeat, 593 /* atTime */ _lastEventTime); 594 595 if (relock) 596 { 597 IOLockLock(_deviceLock); 598 } 599 600 601 if( keyCode == _keyMap->getParsedSpecialKey(NX_KEYTYPE_CAPS_LOCK) || 602 keyCode == _keyMap->getParsedSpecialKey(NX_KEYTYPE_NUM_LOCK) || 603 keyCode == _keyMap->getParsedSpecialKey(NX_POWER_KEY) || 604 keyCode == _keyMap->getParsedSpecialKey(NX_KEYTYPE_MUTE) || 605 keyCode == _keyMap->getParsedSpecialKey(NX_KEYTYPE_PLAY) || 606 keyCode == _keyMap->getParsedSpecialKey(NX_KEYTYPE_EJECT) || 607 keyCode == _keyMap->getParsedSpecialKey(NX_KEYTYPE_VIDMIRROR) || 608 keyCode == _keyMap->getParsedSpecialKey(NX_KEYTYPE_ILLUMINATION_TOGGLE)) 609 { 610 //Don't repeat caps lock on ADB/USB. 0x39 is default ADB code. 611 // We are here because KeyCaps needs to see 0x39 as a real key, 612 // not just another modifier bit. 613 614 if (_interfaceType == NX_EVS_DEVICE_INTERFACE_ADB) 615 { 616 return; 617 } 618 } 619 620 // Set up key repeat operations here. 621 setRepeat(eventType, keyCode); 622} 623 624void IOHIKeyboard::keyboardSpecialEvent(unsigned eventType, 625 /* flags */ unsigned flags, 626 /* keyCode */ unsigned keyCode, 627 /* specialty */ unsigned flavor) 628// Description: See the description for keyboardEvent. 629{ 630 KeyboardReserved *tempReservedStruct = GetKeyboardReservedStructEventForService(this); 631 bool relock = false; 632 633 if (tempReservedStruct && tempReservedStruct->dispatchEventCalled) 634 { 635 relock = true; 636 IOLockUnlock(_deviceLock); 637 } 638 639 _keyboardSpecialEvent(this, 640 eventType, 641 /* flags */ flags, 642 /* keyCode */ keyCode, 643 /* specialty */ flavor, 644 /* guid */ _guid, 645 /* repeat */ _isRepeat, 646 /* atTime */ _lastEventTime); 647 648 if (relock) 649 { 650 IOLockLock(_deviceLock); 651 } 652 653 // Set up key repeat operations here. 654 // Don't repeat capslock, numlock, power key, mute key, play key, 655 // eject key, vidmirror key, illumination toggle key. 656 if( keyCode == _keyMap->getParsedSpecialKey(NX_KEYTYPE_CAPS_LOCK) || 657 keyCode == _keyMap->getParsedSpecialKey(NX_KEYTYPE_NUM_LOCK) || 658 keyCode == _keyMap->getParsedSpecialKey(NX_POWER_KEY) || 659 keyCode == _keyMap->getParsedSpecialKey(NX_KEYTYPE_MUTE) || 660 keyCode == _keyMap->getParsedSpecialKey(NX_KEYTYPE_PLAY) || 661 keyCode == _keyMap->getParsedSpecialKey(NX_KEYTYPE_EJECT) || 662 keyCode == _keyMap->getParsedSpecialKey(NX_KEYTYPE_VIDMIRROR) || 663 keyCode == _keyMap->getParsedSpecialKey(NX_KEYTYPE_ILLUMINATION_TOGGLE)) 664 { 665 return; 666 } 667 668 // Set up key repeat operations here. 669 setRepeat(eventType, keyCode); 670} 671 672void IOHIKeyboard::updateEventFlags(unsigned flags) 673// Description: Process non-event-generating flag changes. Simply pass this 674// along to our owner. 675{ 676 KeyboardReserved *tempReservedStruct = GetKeyboardReservedStructEventForService(this); 677 bool relock = false; 678 679 if (tempReservedStruct && tempReservedStruct->dispatchEventCalled) 680 { 681 relock = true; 682 IOLockUnlock(_deviceLock); 683 } 684 685 _updateEventFlags(this, flags); 686 687 if (relock) 688 { 689 IOLockLock(_deviceLock); 690 } 691} 692 693unsigned IOHIKeyboard::eventFlags() 694// Description: Return global event flags In this world, there is only 695// one keyboard device so device flags == global flags. 696{ 697 return _eventFlags; 698} 699 700unsigned IOHIKeyboard::deviceFlags() 701// Description: Return per-device event flags. In this world, there is only 702// one keyboard device so device flags == global flags. 703{ 704 return _eventFlags; 705} 706 707void IOHIKeyboard::setDeviceFlags(unsigned flags) 708// Description: Set device event flags. In this world, there is only 709// one keyboard device so device flags == global flags. 710{ 711 if (_eventFlags != flags) { 712 _eventFlags = flags; 713 714 // RY: On Modifier change, we should 715 // reset the auto repeat timer 716 AbsoluteTime_to_scalar(&_downRepeatTime) = 0; 717 _codeToRepeat = (unsigned)-1; 718 scheduleAutoRepeat(); 719 } 720} 721 722bool IOHIKeyboard::alphaLock() 723// Description: Return current alpha-lock state. This is a state tracking 724// callback used by the KeyMap object. 725{ 726 return _alphaLock; 727} 728 729void IOHIKeyboard::setAlphaLock(bool val) 730// Description: Set current alpha-lock state This is a state tracking 731// callback used by the KeyMap object. 732{ 733 _alphaLock = val; 734 setAlphaLockFeedback(val); 735 736 KeyboardReserved *tempReservedStruct = GetKeyboardReservedStructEventForService(this); 737 738 if (tempReservedStruct && tempReservedStruct->keyboardNub ) 739 tempReservedStruct->keyboardNub->setCapsLockLEDElement(val); 740 741} 742 743bool IOHIKeyboard::numLock() 744{ 745 return _numLock; 746} 747 748void IOHIKeyboard::setNumLock(bool val) 749{ 750 _numLock = val; 751 752 setNumLockFeedback(val); 753 754 KeyboardReserved *tempReservedStruct = GetKeyboardReservedStructEventForService(this); 755 756 if (tempReservedStruct && tempReservedStruct->keyboardNub ) 757 tempReservedStruct->keyboardNub->setNumLockLEDElement(val); 758 759} 760 761bool IOHIKeyboard::charKeyActive() 762// Description: Return true If a character generating key down This is a state 763// tracking callback used by the KeyMap object. 764{ 765 return _charKeyActive; 766} 767 768void IOHIKeyboard::setCharKeyActive(bool val) 769// Description: Note whether a char generating key is down. This is a state 770// tracking callback used by the KeyMap object. 771{ 772 _charKeyActive = val; 773} 774// 775// END: Implementation of the methods required by IOHIKeyboardMapper. 776// 777 778void IOHIKeyboard::dispatchKeyboardEvent(unsigned int keyCode, 779 /* direction */ bool goingDown, 780 /* timeStamp */ AbsoluteTime time) 781// Description: This method is the heart of event dispatching. The overlying 782// subclass invokes this method with each event. We then 783// get the event xlated and dispatched using a _keyMap instance. 784// The event structure passed in by reference should not be freed. 785{ 786 IOHIKeyboardMapper * theKeyMap; 787 KeyboardReserved *tempReservedStruct = GetKeyboardReservedStructEventForService(this); 788 789 IOLockLock( _deviceLock); 790 791 _lastEventTime = time; 792 793 // <rdar://problem/7415196> 794 if (postSecureKey(keyCode, goingDown)) { 795 IOLockUnlock( _deviceLock); 796 return; 797 } 798 799 if (tempReservedStruct) 800 { 801 if (tempReservedStruct->keyboardNub) 802 { 803 // Post the event to the HID Manager 804 tempReservedStruct->keyboardNub->postKeyboardEvent(keyCode, goingDown); 805 } 806 807 if (tempReservedStruct->isSeized) 808 { 809 IOLockUnlock( _deviceLock); 810 return; 811 } 812 813 tempReservedStruct->dispatchEventCalled = true; 814 } 815 816 if (_keyMap) _keyMap->translateKeyCode(keyCode, 817 /* direction */ goingDown, 818 /* keyBits */ _keyState); 819 820 // remember the keymap while we hold the lock 821 theKeyMap = _keyMap; 822 823 if (tempReservedStruct) tempReservedStruct->dispatchEventCalled = false; 824 825 IOLockUnlock( _deviceLock); 826 827 // outside the lock (because of possible recursion), give the 828 // keymap a chance to do some post processing 829 // since it is possible we will be entered reentrantly and 830 // release the keymap, we will add a retain here. 831 if (theKeyMap) 832 { 833 theKeyMap->retain(); 834 theKeyMap->keyEventPostProcess(); 835 theKeyMap->release(); 836 } 837} 838 839const unsigned char * IOHIKeyboard::defaultKeymapOfLength(UInt32 * length) 840{ 841 *length = 0; 842 return NULL; 843} 844 845void IOHIKeyboard::setAlphaLockFeedback(bool /* val */) 846{ 847 return; 848} 849 850void IOHIKeyboard::setNumLockFeedback(bool /* val */) 851{ 852 return; 853} 854 855UInt32 IOHIKeyboard::maxKeyCodes() 856{ 857 return( NX_NUMKEYCODES ); 858} 859 860bool IOHIKeyboard:: doesKeyLock ( unsigned key __unused) 861{ 862 return false; 863} 864 865unsigned IOHIKeyboard:: getLEDStatus () 866{ 867 return 0; 868} 869 870 871bool IOHIKeyboard::open(IOService * client, 872 IOOptionBits options, 873 KeyboardEventAction keAction, 874 KeyboardSpecialEventAction kseAction, 875 UpdateEventFlagsAction uefAction) 876{ 877 if ( (!_keyMap) && (!resetKeyboard())) return false; 878 879 if (client == this) { 880 KeyboardReserved *tempReservedStruct; 881 tempReservedStruct = GetKeyboardReservedStructEventForService(this); 882 883 return super::open((tempReservedStruct) ? tempReservedStruct->openClient : 0, options); 884 } 885 886 return open(client, 887 options, 888 0, 889 (KeyboardEventCallback)keAction, 890 (KeyboardSpecialEventCallback)kseAction, 891 (UpdateEventFlagsCallback)uefAction); 892} 893 894bool IOHIKeyboard::open( 895 IOService * client, 896 IOOptionBits options, 897 void * /*refcon*/, 898 KeyboardEventCallback keCallback, 899 KeyboardSpecialEventCallback kseCallback, 900 UpdateEventFlagsCallback uefCallback) 901{ 902 if (client == this) return true; 903 904 KeyboardReserved *tempReservedStruct; 905 tempReservedStruct = GetKeyboardReservedStructEventForService(this); 906 907 if (tempReservedStruct) tempReservedStruct->openClient = client; 908 909 bool returnValue = open(this, options, 910 (KeyboardEventAction)_keyboardEvent, 911 (KeyboardSpecialEventAction)_keyboardSpecialEvent, 912 (UpdateEventFlagsAction)_updateEventFlags); 913 914 if (!returnValue) 915 return false; 916 917 // point the new keymap to the IOHIDSystem, so it can set properties in it 918 // this handles the case where although resetKeyboard is called above, 919 // _keyboardEventTarget is as yet unset, so zero is passed 920 if (_keyMap) 921 _keyMap->setKeyboardTarget(client); 922 923 // Note: client object is already retained by superclass' open() 924 _keyboardEventTarget = client; 925 _keyboardEventAction = (KeyboardEventAction)keCallback; 926 _keyboardSpecialEventTarget = client; 927 _keyboardSpecialEventAction = (KeyboardSpecialEventAction)kseCallback; 928 _updateEventFlagsTarget = client; 929 _updateEventFlagsAction = (UpdateEventFlagsAction)uefCallback; 930 931 return true; 932} 933 934void IOHIKeyboard::close(IOService * client, IOOptionBits) 935{ 936 // kill autorepeat task 937 // do this before we issue keyup for any other keys 938 // that are down. 939 AbsoluteTime ts; 940 clock_get_uptime(&ts); 941 if (_codeToRepeat != ((unsigned)-1)) 942 dispatchKeyboardEvent(_codeToRepeat, false, ts); 943 944 // now get rid of any other keys that might be down 945 UInt32 i, maxKeys = maxKeyCodes(); 946 for (i=0; i<maxKeys; i++) 947 if ( EVK_IS_KEYDOWN(i,_keyState) ) 948 dispatchKeyboardEvent(i, false, ts); 949 950 // continue to issue zero'ed out flags changed events 951 // just in case any of the flag bits were manually set 952 _updateEventFlags(this, 0); 953 954 _keyboardSpecialEvent( this, 955 NX_SYSDEFINED, 956 0, 957 NX_NOSPECIALKEY, 958 NX_SUBTYPE_STICKYKEYS_RELEASE, 959 _guid, 960 0, 961 _lastEventTime); 962 963 bzero(_keyState, _keyStateSize); 964 965 _keyboardEventAction = NULL; 966 _keyboardEventTarget = 0; 967 _keyboardSpecialEventAction = NULL; 968 _keyboardSpecialEventTarget = 0; 969 _updateEventFlagsAction = NULL; 970 _updateEventFlagsTarget = 0; 971 972 super::close(client); 973} 974 975IOReturn IOHIKeyboard::message( UInt32 type, IOService * provider, 976 void * argument) 977{ 978 IOReturn ret = kIOReturnSuccess; 979 980 switch(type) 981 { 982 case kIOHIDSystem508MouseClickMessage: 983 case kIOHIDSystem508SpecialKeyDownMessage: 984 if (_keyMap) 985 ret = _keyMap->message(type, this); 986 break; 987 988 case kIOHIDSystemDeviceSeizeRequestMessage: 989 if (OSDynamicCast(IOHIDDevice, provider)) 990 { 991 KeyboardReserved *tempReservedStruct = GetKeyboardReservedStructEventForService(this); 992 993 if (tempReservedStruct) { 994 tempReservedStruct->isSeized = (bool)argument; 995 } 996 } 997 break; 998 999 case IOHIDSecurePromptClient::gatheringMessage: 1000 { 1001 if (argument) { 1002 // Only do things if someone is turning ON gathering. 1003 AbsoluteTime ts; 1004 clock_get_uptime(&ts); 1005 1006 // kill any pending repeat 1007 if (_codeToRepeat != ((unsigned)-1)) 1008 dispatchKeyboardEvent(_codeToRepeat, false, ts); 1009 1010 // now get rid of any other keys that might be down 1011 UInt32 i, maxKeys = maxKeyCodes(); 1012 for (i=0; i<maxKeys; i++) 1013 if ( EVK_IS_KEYDOWN(i,_keyState) ) 1014 dispatchKeyboardEvent(i, false, ts); 1015 1016 // continue to issue zero'ed out flags changed events 1017 // just in case any of the flag bits were manually set 1018 _updateEventFlags(this, 0); 1019 1020 _keyboardSpecialEvent( this, 1021 NX_SYSDEFINED, 1022 0, 1023 NX_NOSPECIALKEY, 1024 NX_SUBTYPE_STICKYKEYS_RELEASE, 1025 _guid, 1026 0, 1027 _lastEventTime); 1028 1029 // Now, disable gathering on all other secure clients 1030 if (provider) { 1031 OSIterator *itr = getClientIterator(); 1032 if (itr) { 1033 IOHIDSecurePromptClient *client = NULL; 1034 do { 1035 client = IOHIDSecurePromptClient::nextForIterator(itr); 1036 if (client && (client != provider) && client->gathering()) { 1037 client->setGathering(0); 1038 } 1039 } 1040 while(client); 1041 itr->release(); 1042 } 1043 } 1044 } 1045 } 1046 1047 default: 1048 ret = super::message(type, provider, argument); 1049 break; 1050 } 1051 1052 return ret; 1053} 1054 1055void IOHIKeyboard::_keyboardEvent( IOHIKeyboard * self, 1056 unsigned eventType, 1057 /* flags */ unsigned flags, 1058 /* keyCode */ unsigned key, 1059 /* charCode */ unsigned charCode, 1060 /* charSet */ unsigned charSet, 1061 /* originalCharCode */ unsigned origCharCode, 1062 /* originalCharSet */ unsigned origCharSet, 1063 /* keyboardType */ unsigned keyboardType, 1064 /* repeat */ bool repeat, 1065 /* atTime */ AbsoluteTime ts) 1066{ 1067 KeyboardEventCallback keCallback; 1068 keCallback = (KeyboardEventCallback)self->_keyboardEventAction; 1069 1070 if ( !keCallback ) 1071 return; 1072 1073 (*keCallback)( self->_keyboardEventTarget, 1074 eventType, 1075 flags, 1076 key, 1077 charCode, 1078 charSet, 1079 origCharCode, 1080 origCharSet, 1081 keyboardType, 1082 repeat, 1083 ts, 1084 self, 1085 0); 1086} 1087 1088void IOHIKeyboard::_keyboardSpecialEvent( 1089 IOHIKeyboard * self, 1090 unsigned eventType, 1091 /* flags */ unsigned flags, 1092 /* keyCode */ unsigned key, 1093 /* specialty */ unsigned flavor, 1094 /* guid */ UInt64 guid, 1095 /* repeat */ bool repeat, 1096 /* atTime */ AbsoluteTime ts) 1097{ 1098 KeyboardSpecialEventCallback kseCallback; 1099 kseCallback = (KeyboardSpecialEventCallback)self->_keyboardSpecialEventAction; 1100 1101 if ( !kseCallback ) 1102 return; 1103 1104 (*kseCallback)( self->_keyboardEventTarget, 1105 eventType, 1106 flags, 1107 key, 1108 flavor, 1109 guid, 1110 repeat, 1111 ts, 1112 self, 1113 0); 1114} 1115 1116void IOHIKeyboard::_updateEventFlags( IOHIKeyboard * self, 1117 unsigned flags) 1118{ 1119 UpdateEventFlagsCallback uefCallback; 1120 uefCallback = (UpdateEventFlagsCallback)self->_updateEventFlagsAction; 1121 1122 if ( !uefCallback ) 1123 return; 1124 1125 (*uefCallback)( self->_updateEventFlagsTarget, 1126 flags, 1127 self, 1128 0); 1129} 1130 1131/******************************************************************************/ 1132IOReturn IOHIKeyboard::newUserClient(task_t owningTask, 1133 void * security_id, 1134 UInt32 type, 1135 OSDictionary * properties, 1136 IOUserClient ** handler ) 1137{ 1138 if ( type == IOHIDSecurePromptClient::clientID ) { 1139 IOWorkLoop *loop = getWorkLoop(); 1140 IOReturn result = kIOReturnNotReady; 1141 1142 if ( loop ) { 1143 result = loop->runAction( OSMemberFunctionCast( IOWorkLoop::Action, this, &IOHIKeyboard::newUserClientGated ), 1144 this, owningTask, security_id, NULL, handler ); 1145 } 1146 else { 1147 IOLog( "IOHIDDevice::newUserClient failed to get a workloop\n" ); 1148 } 1149 1150 return result; 1151 } 1152 1153 return super::newUserClient( owningTask, security_id, type, properties, handler ); 1154} 1155 1156/******************************************************************************/ 1157static bool IOHIKeyboard_attachSecurePromptClient_Callback(void * target, 1158 void * refCon __unused, 1159 IOService * newService, 1160 IONotifier * notifier __unused ) 1161{ 1162 IOHIDSecurePromptClient *client = (IOHIDSecurePromptClient*)target; 1163 IOHIKeyboard *keyboard = OSDynamicCast(IOHIKeyboard, newService); 1164 1165 require(client, improper_call); 1166 require(keyboard, improper_call); 1167 1168 require(!client->dead(), invalid_client); 1169 1170 return client->attach(keyboard); 1171 1172invalid_client: 1173improper_call: 1174 return false; 1175} 1176 1177/******************************************************************************/ 1178IOReturn IOHIKeyboard::newUserClientGated(task_t owningTask, 1179 void * security_id, 1180 OSDictionary * properties, 1181 IOUserClient ** handler ) 1182{ 1183 IOHIDSecurePromptClient * client = new IOHIDSecurePromptClient; 1184 1185 if ( !client->initWithTask( owningTask, security_id, 0, properties ) ) { 1186 client->release(); 1187 return kIOReturnBadArgument; 1188 } 1189 1190 if ( !client->start( this ) ) { 1191 client->detach( this ); 1192 client->release(); 1193 return kIOReturnInternalError; 1194 } 1195 1196 *handler = client; 1197 1198// vtn3 TODO: tell client to guess table 1199 1200 // This user client must be attached to all keyboards 1201 OSDictionary *match = IOService::serviceMatching(kIOHIKeyboardClass); 1202 1203 IONotifier *notifier = IOService::addMatchingNotification(gIOPublishNotification, 1204 match, 1205 IOHIKeyboard_attachSecurePromptClient_Callback, 1206 client); 1207 client->setNotifier(notifier); 1208 match->release(); 1209 notifier->release(); 1210 1211 return kIOReturnSuccess; 1212} 1213 1214/******************************************************************************/ 1215bool IOHIKeyboard:: 1216postSecureKey(UInt8 key, bool down) 1217{ 1218 KeyboardReserved *reservedStruct = GetKeyboardReservedStructEventForService(this); 1219 bool posted = false; 1220 if (reservedStruct->hasSecurePrompt) { 1221 IOHIDSecurePromptClient *client = NULL; 1222 OSIterator *itr = getClientIterator(); 1223 if (itr) { 1224 do { 1225 client = IOHIDSecurePromptClient::nextForIterator(itr); 1226 if (client && client->gathering()) { 1227 IOReturn result = client->postKey(key, down); 1228 client = NULL; 1229 if (result == kIOReturnSuccess) { 1230 // event was posted internally. needs suppression. 1231 posted = true; 1232 } 1233 } 1234 } 1235 while(client); 1236 itr->release(); 1237 } 1238 } 1239 return posted; 1240} 1241 1242/******************************************************************************/ 1243bool IOHIKeyboard:: 1244attachToChild(IORegistryEntry * child, 1245 const IORegistryPlane * plane ) 1246{ 1247 IOHIDSecurePromptClient *secureClient = OSDynamicCast(IOHIDSecurePromptClient, child); 1248 if (secureClient) { 1249 KeyboardReserved *reservedStruct = GetKeyboardReservedStructEventForService(this); 1250 if (reservedStruct) { 1251 reservedStruct->hasSecurePrompt = true; 1252 } 1253 } 1254 return super::attachToChild(child, plane); 1255} 1256 1257/******************************************************************************/ 1258void IOHIKeyboard:: 1259detachFromChild(IORegistryEntry * child, 1260 const IORegistryPlane * plane ) 1261{ 1262 IOHIDSecurePromptClient *secureClient = OSDynamicCast(IOHIDSecurePromptClient, child); 1263 1264 super::detachFromChild(child, plane); 1265 1266 if (secureClient) { 1267 KeyboardReserved *reservedStruct = GetKeyboardReservedStructEventForService(this); 1268 if (reservedStruct && reservedStruct->hasSecurePrompt) { 1269 OSIterator *itr = getClientIterator(); 1270 if (itr) { 1271 if (NULL == IOHIDSecurePromptClient::nextForIterator(itr)) { 1272 reservedStruct->hasSecurePrompt = false; 1273 } 1274 itr->release(); 1275 } 1276 } 1277 } 1278} 1279 1280/******************************************************************************/ 1281void IOHIKeyboard::clearLastPageAndUsage() 1282{ 1283 if (!_lastUsagePage && !_lastUsage) 1284 IOLog("IOHIKeyboard::clearLastPageAndUsage called when not set %02x:%02x\n", _lastUsagePage, _lastUsage); 1285 _lastUsagePage = 0; 1286 _lastUsage = 0; 1287} 1288 1289/******************************************************************************/ 1290void IOHIKeyboard::setLastPageAndUsage(UInt16 usagePage, UInt16 usage) 1291{ 1292 if (_lastUsagePage || _lastUsage) 1293 IOLog("IOHIKeyboard::setLastPageAndUsage called when already set %02x:%02x\n", _lastUsagePage, _lastUsage); 1294 _lastUsagePage = usagePage; 1295 _lastUsage = usage; 1296} 1297 1298/******************************************************************************/ 1299void IOHIKeyboard::getLastPageAndUsage(UInt16 &usagePage, UInt16 &usage) 1300{ 1301 usagePage = _lastUsagePage; 1302 usage = _lastUsage; 1303} 1304 1305/******************************************************************************/ 1306