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/* Copyright (c) 1992 NeXT Computer, Inc. All rights reserved. 24 * 25 * KeyMap.m - Generic keymap string parser and keycode translator. 26 * 27 * HISTORY 28 * 19 June 1992 Mike Paquette at NeXT 29 * Created. 30 * 5 Aug 1993 Erik Kay at NeXT 31 * minor API cleanup 32 * 11 Nov 1993 Erik Kay at NeXT 33 * fix to allow prevent long sequences from overflowing the event queue 34 * 12 Nov 1998 Dan Markarian at Apple 35 * major cleanup of public API's; converted to C++ 36 */ 37 38#include <sys/systm.h> 39 40#include <IOKit/assert.h> 41#include <IOKit/IOLib.h> 42#include <IOKit/IODeviceTreeSupport.h> 43#include <IOKit/hidsystem/IOLLEvent.h> 44#include <IOKit/hidsystem/IOHIKeyboard.h> 45#include <IOKit/hidsystem/IOHIKeyboardMapper.h> 46#include <IOKit/hidsystem/IOHIDParameter.h> 47#include <IOKit/hidsystem/IOHIDSystem.h> 48#include <libkern/OSByteOrder.h> 49#include "IOHIDKeyboardDevice.h" 50#include "IOHIDevicePrivateKeys.h" 51#include "IOHIDFamilyPrivate.h" 52 53// Define expansion data here 54#define _f12Eject_State _reserved->f12Eject_State 55#define _eject_Delay_MS _reserved->eject_Delay_MS 56#define _ejectTimerEventSource _reserved->ejectTimerEventSource 57#define _cached_KeyBits _reserved->cached_KeyBits 58#define _stickyKeys_StuckModifiers _reserved->stickyKeys_StuckModifiers 59#define _stickyKeysMouseClickEventSource _reserved->stickyKeysMouseClickEventSource 60#define _stickyKeysSetFnStateEventSource _reserved->stickyKeysSetFnStateEventSource 61#define _offFnParamDict _reserved->offFnParamDict 62#define _onFnParamDict _reserved->onFnParamDict 63#define _slowKeys_State _reserved->slowKeys_State 64#define _slowKeys_Delay_MS _reserved->slowKeys_Delay_MS 65#define _slowKeysTimerEventSource _reserved->slowKeysTimerEventSource 66#define _slowKeys_Aborted_Key _reserved->slowKeys_Aborted_Key 67#define _slowKeys_Current_Key _reserved->slowKeys_Current_Key 68#define _specialKeyModifierFlags _reserved->specialKeyModifierFlags 69#define _supportsF12Eject _reserved->supportsF12Eject 70#define _modifierSwap_Modifiers _reserved->modifierSwap_Modifiers 71#define _cachedAlphaLockModDefs _reserved->cachedAlphaLockModDefs 72 73#define super OSObject 74OSDefineMetaClassAndStructors(IOHIKeyboardMapper, OSObject); 75 76// sticky keys private state flags 77enum 78{ 79 kState_OptionActivates_Flag = 0x0010, // the 'on' gesture (5 options) will activate mouse keys 80 kState_ClearHeldKeysFirst = 0x0100, // when set, we should clear all held keys 81 // this is a hack we are using since we 82 // cannot post key up events when our 83 // entry point is not a key event 84 85 kState_PrefFnKeyStateOn = 0x0200, 86 kState_StickyFnKeyStateOn = 0x0400, 87 kState_MouseKeyStateOn = 0x0800, 88 kState_StickyFnKeyStateChangePending = 0x1000, 89 90}; 91 92 93 94// delay filter private state flags 95enum 96{ 97 kState_Aborted_Flag = 0x0200, 98 kState_In_Progess_Flag = 0x0400, 99 kState_Is_Repeat_Flag = 0x0800, 100}; 101 102// ADB Key code for F12 103#define kADB_KEYBOARD_F12 0x6f 104 105// Shortcut for post slow key translation 106#define postSlowKeyTranslateKeyCode(owner,key,keyDown,keyBits) \ 107 if (!owner->f12EjectFilterKey(key, keyDown, keyBits)) \ 108 if (!owner->stickyKeysFilterKey(key, keyDown, keyBits)) \ 109 owner->rawTranslateKeyCode(key, keyDown, keyBits); 110 111 112// Shortcut for determining if we are interested in this modifier 113#define modifierOfInterest(keyBits) \ 114 ((keyBits & NX_MODMASK) && \ 115 ((((keyBits & NX_WHICHMODMASK) >= NX_MODIFIERKEY_SHIFT) && \ 116 ((keyBits & NX_WHICHMODMASK) <= NX_MODIFIERKEY_COMMAND)) || \ 117 (((keyBits & NX_WHICHMODMASK) >= NX_MODIFIERKEY_RSHIFT) && \ 118 ((keyBits & NX_WHICHMODMASK) <= NX_MODIFIERKEY_LAST_KEY)) || \ 119 ((keyBits & NX_WHICHMODMASK) == NX_MODIFIERKEY_SECONDARYFN))) 120 121#define mouseKey(keyBits) \ 122 ((keyBits & NX_MODMASK) && \ 123 ((keyBits & NX_WHICHMODMASK) == NX_MODIFIERKEY_NUMERICPAD)) 124 125#define mouseKeyToIgnore(keyBits, key) \ 126 ( mouseKey(keyBits) && \ 127 (((key >= 0x52) && (key <= 0x56)) || \ 128 ((key >= 0x58) && (key <= 0x5c))) ) 129 130#define convertToLeftModBit(modBit) \ 131 modBit -= ((modBit >= NX_MODIFIERKEY_RSHIFT) && \ 132 (modBit <= NX_MODIFIERKEY_LAST_KEY)) ? 8 : 0; 133 134static UInt32 DeviceModifierMasks[NX_NUMMODIFIERS] = 135{ 136 /* NX_MODIFIERKEY_ALPHALOCK */ 0, 137 /* NX_MODIFIERKEY_SHIFT */ NX_DEVICELSHIFTKEYMASK, 138 /* NX_MODIFIERKEY_CONTROL */ NX_DEVICELCTLKEYMASK, 139 /* NX_MODIFIERKEY_ALTERNATE */ NX_DEVICELALTKEYMASK, 140 /* NX_MODIFIERKEY_COMMAND */ NX_DEVICELCMDKEYMASK, 141 /* NX_MODIFIERKEY_NUMERICPAD */ 0, 142 /* NX_MODIFIERKEY_HELP */ 0, 143 /* NX_MODIFIERKEY_SECONDARYFN */ 0, 144 /* NX_MODIFIERKEY_NUMLOCK */ 0, 145 /* NX_MODIFIERKEY_RSHIFT */ NX_DEVICERSHIFTKEYMASK, 146 /* NX_MODIFIERKEY_RCONTROL */ NX_DEVICERCTLKEYMASK, 147 /* NX_MODIFIERKEY_RALTERNATE */ NX_DEVICERALTKEYMASK, 148 /* NX_MODIFIERKEY_RCOMMAND */ NX_DEVICERCMDKEYMASK, 149 /* NX_MODIFIERKEY_ALPHALOCK_STATELESS */ NX_DEVICE_ALPHASHIFT_STATELESS_MASK, 150 0, 151 0 152}; 153 154// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 155 156IOHIKeyboardMapper * IOHIKeyboardMapper::keyboardMapper( 157 IOHIKeyboard * delegate, 158 const UInt8 * mapping, 159 UInt32 mappingLength, 160 bool mappingShouldBeFreed ) 161{ 162 IOHIKeyboardMapper * me = new IOHIKeyboardMapper; 163 164 if (me && !me->init(delegate, mapping, mappingLength, mappingShouldBeFreed)) 165 { 166 me->free(); 167 return 0; 168 } 169 170 return me; 171} 172 173// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 174 175/* 176 * Common KeyMap initialization 177 */ 178bool IOHIKeyboardMapper::init( IOHIKeyboard *delegate, 179 const UInt8 *map, 180 UInt32 mappingLen, 181 bool mappingShouldBeFreed ) 182{ 183 if (!super::init()) return false; 184 185 _delegate = delegate; 186 187 if (!parseKeyMapping(map, mappingLen, &_parsedMapping)) return false; 188 189 _mappingShouldBeFreed = mappingShouldBeFreed; 190 _parsedMapping.mapping = map; 191 _parsedMapping.mappingLen = mappingLen; 192 193 _hidSystem = NULL; 194 _stateDirty = false; 195 196 _reserved = IONew(ExpansionData, 1); 197 198 _ejectTimerEventSource = 0; 199 200 _f12Eject_State = 0; 201 202 _eject_Delay_MS = kEjectF12DelayMS; 203 204 _slowKeys_State = 0; 205 206 _slowKeys_Delay_MS = 0; 207 208 _slowKeysTimerEventSource = 0; 209 210 _specialKeyModifierFlags = 0; 211 212 _supportsF12Eject = 0; 213 214 _cached_KeyBits = 0; 215 216 _cachedAlphaLockModDefs = 0; 217 218 // If there are right hand modifiers defined, set a property 219 if (_delegate && (_parsedMapping.maxMod > 0)) 220 { 221 222 if ( _delegate->doesKeyLock(NX_KEYTYPE_CAPS_LOCK) ) 223 { 224 _delegate->setProperty( kIOHIDKeyboardCapsLockDoesLockKey, kOSBooleanTrue); 225 _cachedAlphaLockModDefs = _parsedMapping.modDefs[NX_MODIFIERKEY_ALPHALOCK]; 226 } 227 else 228 { 229 _delegate->setProperty( kIOHIDKeyboardCapsLockDoesLockKey, kOSBooleanFalse); 230 } 231 232 UInt32 supportedModifiers = 0; 233 OSNumber * number = 0; 234 235 number = (OSNumber *)_delegate->copyProperty(kIOHIDKeyboardSupportedModifiersKey); 236 237 if (number) supportedModifiers = number->unsigned32BitValue(); 238 OSSafeReleaseNULL(number); 239 240 for (int mod=0; mod<NX_NUMMODIFIERS; mod++) 241 { 242 if (_parsedMapping.modDefs[mod]) 243 { 244 if (DeviceModifierMasks[mod]) 245 supportedModifiers |= DeviceModifierMasks[mod]; 246 else 247 supportedModifiers |= 1<<(mod+16); 248 } 249 250 // RY: Init modifier swap while we are at it 251 _modifierSwap_Modifiers[mod] = mod; 252 } 253 _delegate->setProperty( kIOHIDKeyboardSupportedModifiersKey, supportedModifiers, 32 ); 254 255 if ( (supportedModifiers & NX_DEVICERSHIFTKEYMASK) || 256 (supportedModifiers & NX_DEVICERCTLKEYMASK) || 257 (supportedModifiers & NX_DEVICERALTKEYMASK) || 258 (supportedModifiers & NX_DEVICERCMDKEYMASK) ) 259 { 260 _delegate->setProperty("HIDKeyboardRightModifierSupport", kOSBooleanTrue); 261 } 262 } 263 264 if (_parsedMapping.numDefs && _delegate) 265 { 266 _delegate->setProperty("HIDKeyboardKeysDefined", kOSBooleanTrue); 267 268 // If keys are defined, check the device type to determine 269 // if we should support F12 eject. 270 if ((_delegate->interfaceID() == NX_EVS_DEVICE_INTERFACE_ADB) && 271 (((_delegate->deviceType() >= 0xc3) && (_delegate->deviceType() <= 0xc9)) || 272 ((_delegate->deviceType() >= 0x28) && (_delegate->deviceType() <= 0x2a)) || 273 ( (_delegate->deviceType() <= 0x1e)))) 274 { 275 _supportsF12Eject = true; 276 _delegate->setProperty( kIOHIDKeyboardSupportsF12EjectKey, 277 _supportsF12Eject); 278 } 279 } 280 281 if ( !_delegate->doesKeyLock(NX_KEYTYPE_CAPS_LOCK) ) 282 { 283 UInt32 myFlags = _delegate->deviceFlags(); 284 285 if ( _delegate->alphaLock() ) 286 { 287 _specialKeyModifierFlags |= NX_ALPHASHIFTMASK; 288 myFlags |= NX_ALPHASHIFTMASK; 289 290 _delegate->IOHIKeyboard::setDeviceFlags(myFlags); 291 } 292 else 293 { 294 _specialKeyModifierFlags &= ~NX_ALPHASHIFTMASK; 295 myFlags &= ~NX_ALPHASHIFTMASK; 296 297 _delegate->IOHIKeyboard::setDeviceFlags(myFlags); 298 } 299 } 300 301 return stickyKeysinit(); 302} 303 304// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 305void IOHIKeyboardMapper::free() 306{ 307 if (!_parsedMapping.mapping || !_parsedMapping.mappingLen) 308 return; 309 310 stickyKeysfree(); 311 312 if (_ejectTimerEventSource) { 313 _ejectTimerEventSource->cancelTimeout(); 314 315 IOWorkLoop * workLoop = _hidSystem->getWorkLoop(); 316 317 if ( workLoop ) 318 workLoop->removeEventSource( _ejectTimerEventSource ); 319 320 _ejectTimerEventSource->release(); 321 _ejectTimerEventSource = 0; 322 } 323 324 if (_slowKeysTimerEventSource) { 325 _slowKeysTimerEventSource->cancelTimeout(); 326 327 IOWorkLoop * workLoop = _hidSystem->getWorkLoop(); 328 329 if ( workLoop ) 330 workLoop->removeEventSource( _slowKeysTimerEventSource ); 331 332 _slowKeysTimerEventSource->release(); 333 _slowKeysTimerEventSource = 0; 334 } 335 336 if (_reserved) { 337 IODelete(_reserved, ExpansionData, 1); 338 } 339 340 if (_mappingShouldBeFreed) 341 IOFree((void *)_parsedMapping.mapping, _parsedMapping.mappingLen); 342 343 super::free(); 344} 345 346// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 347 348const UInt8 * IOHIKeyboardMapper::mapping() 349{ 350 return (const UInt8 *)_parsedMapping.mapping; 351} 352 353// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 354 355UInt32 IOHIKeyboardMapper::mappingLength() 356{ 357 return _parsedMapping.mappingLen; 358} 359 360// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 361 362bool IOHIKeyboardMapper::serialize(OSSerialize *s) const 363{ 364 OSData * data; 365 bool ok; 366 367 if (s->previouslySerialized(this)) return true; 368 369 data = OSData::withBytesNoCopy( (void *) _parsedMapping.mapping, _parsedMapping.mappingLen ); 370 if (data) { 371 ok = data->serialize(s); 372 data->release(); 373 } else 374 ok = false; 375 376 return( ok ); 377} 378 379// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 380 381// 382// Perform the mapping of 'key' moving in the specified direction 383// into events. 384// 385 386void IOHIKeyboardMapper::translateKeyCode(UInt8 key, 387 bool keyDown, 388 kbdBitVector keyBits) 389{ 390 if ( !_cached_KeyBits ) 391 _cached_KeyBits = keyBits; 392 393 if (!modifierSwapFilterKey(&key)) 394 // SlowKeys filter, if slowKeysFilterKey returns true, 395 // this key is already processed 396 if (!slowKeysFilterKey(key, keyDown, keyBits)) 397 // Filter out F12 to check for an eject 398 if (!f12EjectFilterKey(key, keyDown, keyBits)) 399 // Stickykeys filter, if stickyKeysFilterKey returns true, 400 // this key is already processed 401 if (!stickyKeysFilterKey(key, keyDown, keyBits)) 402 // otherwise, call the original raw translate key code 403 rawTranslateKeyCode(key, keyDown, keyBits); 404} 405 406 407// rawTranslateKeyCode is the original translateKeyCode function, 408// prior to the Stickykeys feature 409// 410// Perform the mapping of 'key' moving in the specified direction 411// into events. 412// 413void IOHIKeyboardMapper::rawTranslateKeyCode(UInt8 key, 414 bool keyDown, 415 kbdBitVector keyBits) 416{ 417 unsigned char thisBits = _parsedMapping.keyBits[key]; 418 419 /* do mod bit update and char generation in useful order */ 420 if (keyDown) 421 { 422 EVK_KEYDOWN(key, keyBits); 423 424 if (thisBits & NX_MODMASK) doModCalc(key, keyBits); 425 if (thisBits & NX_CHARGENMASK) doCharGen(key, keyDown); 426 } 427 else 428 { 429 EVK_KEYUP(key, keyBits); 430 if (thisBits & NX_CHARGENMASK) doCharGen(key, keyDown); 431 if (thisBits & NX_MODMASK) doModCalc(key, keyBits); 432 } 433 434 // Fix JIS localization. We are here because the JIS keys Yen, Ro, Eisu, 435 // Kana, and "," are not matched in _parsedMapping.keyBits[] above even 436 // though the keyboard drivers are sending the correct scan codes. 437 // The check for interfaceID() below makes sure both ADB and USB works. 438 // This fix has been tested with AppKit and Carbon for Kodiak 1H 439 if( 0 == (thisBits & (NX_MODMASK | NX_CHARGENMASK))) 440 if (_delegate->interfaceID() == NX_EVS_DEVICE_INTERFACE_ADB) 441 { 442 unsigned charCode=0; 443 444 switch (key) { 445 case 0x5F: // numpad ',' using raw ADB scan code 446 charCode = ','; 447 break; 448 case 0x5E: //ro 449 charCode = '_'; 450 break; 451 case 0x5d: //Yen 452 charCode = '\\'; 453 break; 454 case 0x0a: 455 charCode = 0xa7; 456 break; 457 case 0x66: // eisu 458 case 0x68: // kana 459 default: 460 // do nothing. AppKit has fix in 1H 461 break; 462 } 463 /* Post the keyboard event */ 464 _delegate->keyboardEvent(keyDown ? NX_KEYDOWN : NX_KEYUP, 465 /* flags */ _delegate->eventFlags(), 466 /* keyCode */ key, 467 /* charCode */ charCode, 468 /* charSet */ 0, //0 is adequate for JIS 469 /* originalCharCode */ 0, 470 /* originalCharSet */ 0); 471 } 472 473#ifdef OMITPENDINGKEYCAPS 474 unsigned char * bp; 475 476 // Make KeyCaps.app see the caps lock 477 if (key == _parsedMapping.specialKeys[NX_KEYTYPE_CAPS_LOCK]) //ADB caps lock 0x39 478 { 479 if (_delegate->alphaLock() == keyDown) 480 //This logic is needed for non-locking USB caps lock 481 { 482 _delegate->keyboardEvent(keyDown ? NX_KEYDOWN : NX_KEYUP, 483 _delegate->eventFlags(), key, 0, 0, 0, 0); 484 } 485 } 486 487 //Find scan code corresponding to PowerBook fn key (0x3f in ADB) 488 bp = _parsedMapping.modDefs[NX_MODIFIERKEY_SECONDARYFN]; //7th array entry 489 if (bp) 490 { 491 bp++; //now points to actual ADB scan code 492 if (key == *bp ) //ADB fn key should be 0x3f here 493 { 494 _delegate->keyboardEvent(keyDown ? NX_KEYDOWN : NX_KEYUP, 495 _delegate->eventFlags(), key, 0, 0, 0, 0); 496 } 497 } 498#endif 499} 500 501// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 502 503// 504// Support goop for parseKeyMapping. These routines are 505// used to walk through the keymapping string. The string 506// may be composed of bytes or shorts. If using shorts, it 507// MUST always be aligned to use short boundries. 508// 509typedef struct { 510 unsigned const char *bp; 511 unsigned const char *endPtr; 512 int shorts; 513} NewMappingData; 514 515static inline unsigned int NextNum(NewMappingData *nmd) 516{ 517 if (nmd->bp >= nmd->endPtr) 518 return(0); 519 if (nmd->shorts) { 520 unsigned short tmp = *((unsigned short *)nmd->bp); 521 nmd->bp += 2; 522 return OSSwapBigToHostInt16(tmp); 523} 524 else { 525 unsigned char tmp = *(nmd->bp); 526 nmd->bp++; 527 return tmp; 528 } 529} 530 531// 532// Perform the actual parsing operation on a keymap. Returns false on failure. 533// 534 535bool IOHIKeyboardMapper::parseKeyMapping(const UInt8 * map, 536 UInt32 mappingLen, 537 NXParsedKeyMapping * parsedMapping) const 538{ 539 NewMappingData nmd; 540 int i, j, k, l, n; 541 unsigned int m; 542 int keyMask, numMods; 543 int maxSeqNum = -1; 544 unsigned char * bp; 545 546 547 /* Initialize the new map. */ 548 bzero( parsedMapping, sizeof (NXParsedKeyMapping) ); 549 parsedMapping->maxMod = -1; 550 parsedMapping->numDefs = -1; 551 parsedMapping->numSeqs = -1; 552 553 if (!map || !mappingLen) 554 return false; 555 556 nmd.endPtr = map + mappingLen; 557 nmd.bp = map; 558 nmd.shorts = 1; // First value, the size, is always a short 559 560 /* Start filling it in with the new data */ 561 parsedMapping->mapping = (unsigned char *)map; 562 parsedMapping->mappingLen = mappingLen; 563 parsedMapping->shorts = nmd.shorts = NextNum(&nmd); 564 565 /* Walk through the modifier definitions */ 566 numMods = NextNum(&nmd); 567 for(i=0; i<numMods; i++) 568 { 569 /* Get bit number */ 570 if ((j = NextNum(&nmd)) >= NX_NUMMODIFIERS) 571 return false; 572 573 /* Check maxMod */ 574 if (j > parsedMapping->maxMod) 575 parsedMapping->maxMod = j; 576 577 /* record position of this def */ 578 parsedMapping->modDefs[j] = (unsigned char *)nmd.bp; 579 580 /* Loop through each key assigned to this bit */ 581 for(k=0,n = NextNum(&nmd);k<n;k++) 582 { 583 /* Check that key code is valid */ 584 if ((l = NextNum(&nmd)) >= NX_NUMKEYCODES) 585 return false; 586 /* Make sure the key's not already assigned */ 587 if (parsedMapping->keyBits[l] & NX_MODMASK) 588 return false; 589 /* Set bit for modifier and which one */ 590 591 //The "if" here is to patch the keymapping file. That file has nothing 592 // for num lock, so no change is required here for num lock. 593 // Also, laptop Macs have num lock handled by Buttons driver 594 if ((j != NX_MODIFIERKEY_ALPHALOCK) || (_delegate->doesKeyLock(NX_KEYTYPE_CAPS_LOCK)) ) 595 { 596 parsedMapping->keyBits[l] |=NX_MODMASK | (j & NX_WHICHMODMASK); 597 } 598 599 } 600 } 601 602 //This is here because keymapping file has an entry for caps lock, but in 603 // order to trigger special code (line 646-), the entry needs to be zero 604 if (!_delegate->doesKeyLock(NX_KEYTYPE_CAPS_LOCK)) 605 parsedMapping->modDefs[NX_MODIFIERKEY_ALPHALOCK] = 0; 606 607 //This section is here to force keymapping to include the PowerBook's secondary 608 // fn key as a new modifier key. This code can be removed once the keymapping 609 // file has the fn key (ADB=0x3f) in the modifiers section. 610 // NX_MODIFIERKEY_SECONDARYFN = 8 in ev_keymap.h 611 if (_delegate->interfaceID() == NX_EVS_DEVICE_INTERFACE_ADB) 612 { 613 parsedMapping->keyBits[0x3f] |=NX_MODMASK | (NX_MODIFIERKEY_SECONDARYFN & NX_WHICHMODMASK); 614 } 615 616 /* Walk through each key definition */ 617 parsedMapping->numDefs = NextNum(&nmd); 618 n = parsedMapping->numDefs; 619 for( i=0; i < NX_NUMKEYCODES; i++) 620 { 621 if (i < n) 622 { 623 parsedMapping->keyDefs[i] = (unsigned char *)nmd.bp; 624 if ((keyMask = NextNum(&nmd)) != (nmd.shorts ? 0xFFFF: 0x00FF)) 625 { 626 /* Set char gen bit for this guy: not a no-op */ 627 parsedMapping->keyBits[i] |= NX_CHARGENMASK; 628 /* Check key defs to find max sequence number */ 629 for(j=0, k=1; j<=parsedMapping->maxMod; j++, keyMask>>=1) 630 { 631 if (keyMask & 0x01) 632 k*= 2; 633 } 634 for(j=0; j<k; j++) 635 { 636 m = NextNum(&nmd); 637 l = NextNum(&nmd); 638 if (m == (unsigned)(nmd.shorts ? 0xFFFF: 0x00FF)) 639 if (((int)l) > maxSeqNum) 640 maxSeqNum = l; /* Update expected # of seqs */ 641 } 642 } 643 else /* unused code within active range */ 644 parsedMapping->keyDefs[i] = NULL; 645 } 646 else /* Unused code past active range */ 647 { 648 parsedMapping->keyDefs[i] = NULL; 649 } 650 } 651 /* Walk through sequence defs */ 652 parsedMapping->numSeqs = NextNum(&nmd); 653 /* If the map calls more sequences than are declared, bail out */ 654 if (parsedMapping->numSeqs <= maxSeqNum) 655 return false; 656 657 /* Walk past all sequences */ 658 for(i = 0; i < parsedMapping->numSeqs; i++) 659 { 660 parsedMapping->seqDefs[i] = (unsigned char *)nmd.bp; 661 /* Walk thru entries in a seq. */ 662 for(j=0, l=NextNum(&nmd); j<l; j++) 663 { 664 NextNum(&nmd); 665 NextNum(&nmd); 666 } 667 } 668 /* Install Special device keys. These override default values. */ 669 numMods = NextNum(&nmd); /* Zero on old style keymaps */ 670 parsedMapping->numSpecialKeys = numMods; 671 if ( numMods > NX_NUMSPECIALKEYS ) 672 return false; 673 if ( numMods ) 674 { 675 for ( i = 0; i < NX_NUMSPECIALKEYS; ++i ) 676 parsedMapping->specialKeys[i] = NX_NOSPECIALKEY; 677 678 //This "if" will cover both ADB and USB keyboards. This code does not 679 // have to be here if the keymaps include these two entries. Keyboard 680 // drivers already have these entries, but keymapping file does not 681 if (_delegate->interfaceID() == NX_EVS_DEVICE_INTERFACE_ADB) 682 { 683 //ADB capslock: 684 parsedMapping->specialKeys[NX_KEYTYPE_CAPS_LOCK] = 0x39; 685 686 //ADB numlock for external keyboards, not PowerBook keyboards: 687 parsedMapping->specialKeys[NX_KEYTYPE_NUM_LOCK] = 0x47; 688 689 //HELP key needs to be visible 690 parsedMapping->keyDefs[0x72] = parsedMapping->keyDefs[0x47]; 691 } 692 693 //Keymapping file can override caps and num lock above now: 694 for ( i = 0; i < numMods; ++i ) 695 { 696 j = NextNum(&nmd); /* Which modifier key? */ 697 l = NextNum(&nmd); /* Scancode for modifier key */ 698 if ( j >= NX_NUMSPECIALKEYS ) 699 return false; 700 parsedMapping->specialKeys[j] = l; 701 } 702 } 703 else /* No special keys defs implies an old style keymap */ 704 { 705 return false; /* Old style keymaps are guaranteed to do */ 706 /* the wrong thing on ADB keyboards */ 707 } 708 709 /* Install bits for Special device keys */ 710 for(i=0; i<NX_NUM_SCANNED_SPECIALKEYS; i++) 711 { 712 if ( parsedMapping->specialKeys[i] != NX_NOSPECIALKEY ) 713 { 714 if (parsedMapping->specialKeys[i] < NX_NUMKEYCODES) 715 parsedMapping->keyBits[parsedMapping->specialKeys[i]] |= (NX_CHARGENMASK | NX_SPECIALKEYMASK); 716 } 717 } 718 719 //caps lock keys should not generate characters. 720 if (_delegate->doesKeyLock(NX_KEYTYPE_CAPS_LOCK)) 721 { 722 if (parsedMapping->specialKeys[NX_KEYTYPE_CAPS_LOCK] < NX_NUMKEYCODES) 723 parsedMapping->keyBits[ parsedMapping->specialKeys[NX_KEYTYPE_CAPS_LOCK] ] &= ~NX_CHARGENMASK; 724 } 725 726 //Find scan code corresponding to PowerBook fn key (0x3f in ADB) 727 // and then make sure it does not generate a character 728 bp = _parsedMapping.modDefs[NX_MODIFIERKEY_SECONDARYFN]; //7th array entry 729 if (bp) 730 { 731 bp++; //now points to actual ADB scan code 732 parsedMapping->keyBits[ *bp ] &= ~NX_CHARGENMASK; 733 } 734 735 if (parsedMapping->specialKeys[NX_MODIFIERKEY_ALPHALOCK_STATELESS] == NX_NOSPECIALKEY) { 736 // check value of keyDefs 737 unsigned char key = NX_NUMKEYCODES - 1; 738 parsedMapping->specialKeys[NX_MODIFIERKEY_ALPHALOCK_STATELESS] = key; 739 parsedMapping->modDefs[key] = NULL; 740 parsedMapping->keyBits[key] = NX_MODIFIERKEY_ALPHALOCK_STATELESS | NX_MODMASK; 741 } 742 else { 743 //IOLog("Stateless alpha lock defined in mapping as %02x\n", parsedMapping->specialKeys[NX_MODIFIERKEY_ALPHALOCK_STATELESS]); 744 } 745 746 return true; 747} 748 749 750//Retrieve a key from mapping above. Useful for IOHIKeyboard 751UInt8 IOHIKeyboardMapper::getParsedSpecialKey(UInt8 logical) 752{ 753 UInt8 retval; 754 755 if ( logical < NX_NUMSPECIALKEYS) 756 retval = _parsedMapping.specialKeys[logical]; 757 else 758 retval = 0xff; //careful, 0 is mapped already 759 return retval; 760} 761 762 763static inline int NEXTNUM(unsigned char ** mapping, short shorts) 764{ 765 int returnValue; 766 767 if (shorts) 768 { 769 returnValue = OSSwapBigToHostInt16(*((unsigned short *)*mapping)); 770 *mapping += sizeof(unsigned short); 771 } 772 else 773 { 774 returnValue = **((unsigned char **)mapping); 775 *mapping += sizeof(unsigned char); 776 } 777 778 return returnValue; 779} 780 781bool IOHIKeyboardMapper::modifierSwapFilterKey(UInt8 * key) 782{ 783 unsigned char thisBits = _parsedMapping.keyBits[*key]; 784 SInt16 modBit = (thisBits & NX_WHICHMODMASK); 785 SInt16 swapBit; 786 unsigned char *map; 787 788 if (!(thisBits & NX_MODMASK)) 789 { 790 if (*key == getParsedSpecialKey(NX_KEYTYPE_CAPS_LOCK)) { 791 modBit = NX_MODIFIERKEY_ALPHALOCK; 792 } 793 else { 794 return false; 795 } 796 } 797 798 if (modBit > NX_MODIFIERKEY_LAST_KEY) { 799 return false; 800 } 801 802 swapBit = _modifierSwap_Modifiers[modBit]; 803 804 if (swapBit == modBit) 805 { 806 // RY: Handle situation where modifiers were mapped to CapsLock on 807 // physically locking caps keyboards. In this case, we want to restore 808 // the NX_MODIFIERKEY_ALPHALOCK modDef and remove the char generation. 809 // This will deactivate the AlphaLock toggle behavior. 810 if (_delegate->doesKeyLock(NX_KEYTYPE_CAPS_LOCK) && (swapBit == NX_MODIFIERKEY_ALPHALOCK)) 811 { 812 if (_parsedMapping.specialKeys[NX_KEYTYPE_CAPS_LOCK] < NX_NUMKEYCODES) 813 _parsedMapping.keyBits[ _parsedMapping.specialKeys[NX_KEYTYPE_CAPS_LOCK] ] &= ~NX_CHARGENMASK; 814 _parsedMapping.modDefs[NX_MODIFIERKEY_ALPHALOCK] = _cachedAlphaLockModDefs; 815 _specialKeyModifierFlags &= ~NX_ALPHASHIFTMASK; 816 } 817 return false; 818 } 819 else if (swapBit == -1) 820 { 821 return true; 822 } 823 824 // RY: Handle situation where modifiers are being mapped to CapsLock on 825 // physically locking caps keyboards. In this case, we want to remove 826 // the NX_MODIFIERKEY_ALPHALOCK modDef and generate a char. This will 827 // activate the AlphaLock toggle behavior. 828 if (_delegate->doesKeyLock(NX_KEYTYPE_CAPS_LOCK) && (swapBit == NX_MODIFIERKEY_ALPHALOCK)) 829 { 830 if (_parsedMapping.specialKeys[NX_KEYTYPE_CAPS_LOCK] < NX_NUMKEYCODES) 831 _parsedMapping.keyBits[ _parsedMapping.specialKeys[NX_KEYTYPE_CAPS_LOCK] ] |= NX_CHARGENMASK; 832 _parsedMapping.modDefs[NX_MODIFIERKEY_ALPHALOCK] = 0; 833 } 834 835 if (((map = _parsedMapping.modDefs[swapBit]) != 0 ) && ( NEXTNUM(&map, _parsedMapping.shorts) )) { 836 *key = NEXTNUM(&map, _parsedMapping.shorts); 837 } 838 else if (swapBit == NX_MODIFIERKEY_ALPHALOCK) { 839 *key = getParsedSpecialKey(NX_KEYTYPE_CAPS_LOCK); 840 } 841 else if (swapBit == NX_MODIFIERKEY_ALPHALOCK_STATELESS) { 842 *key = getParsedSpecialKey(NX_MODIFIERKEY_ALPHALOCK_STATELESS); 843 } 844 845 return false; 846} 847 848// 849// Look up in the keymapping each key associated with the modifier bit. 850// Look in the device state to see if that key is down. 851// Return 1 if a key for modifier 'bit' is down. Return 0 if none is down 852// 853static inline int IsModifierDown(NXParsedKeyMapping *parsedMapping, 854 kbdBitVector keyBits, 855 int bit ) 856{ 857 int i, n; 858 unsigned char *mapping; 859 unsigned key; 860 short shorts = parsedMapping->shorts; 861 862 if ( (mapping = parsedMapping->modDefs[bit]) != 0 ) { 863 for(i=0, n=NEXTNUM(&mapping, shorts); i<n; i++) 864 { 865 key = NEXTNUM(&mapping, shorts); 866 if ( EVK_IS_KEYDOWN(key, keyBits) ) 867 return 1; 868 } 869 } 870 return 0; 871} 872 873void IOHIKeyboardMapper::calcModBit(int bit, kbdBitVector keyBits) 874{ 875 int otherHandBit = 0; 876 int deviceBitMask = 0; 877 int systemBitMask = 0; 878 unsigned myFlags = 0; 879 880 systemBitMask = 1<<(bit+16); 881 deviceBitMask = DeviceModifierMasks[bit]; 882 883 if ((bit >= NX_MODIFIERKEY_RSHIFT) && (bit <= NX_MODIFIERKEY_RCOMMAND)) 884 { 885 otherHandBit = bit - 8; 886 systemBitMask = 1<<(otherHandBit+16); 887 } 888 else if ((bit >= NX_MODIFIERKEY_SHIFT) && (bit <= NX_MODIFIERKEY_COMMAND)) 889 { 890 otherHandBit = bit + 8; 891 } 892 893 /* Initially clear bit, as if key-up */ 894 myFlags = _delegate->deviceFlags() & (~systemBitMask); 895 myFlags &= ~deviceBitMask; 896 897 /* Set bit if any associated keys are down */ 898 if ( IsModifierDown( &_parsedMapping, keyBits, bit )) 899 { 900 myFlags |= (systemBitMask | deviceBitMask); 901 } 902 else if (deviceBitMask && 903 IsModifierDown( &_parsedMapping, keyBits, otherHandBit )) 904 { 905 myFlags |= (systemBitMask); 906 } 907 908 myFlags |= _specialKeyModifierFlags; 909 910 if ( bit == NX_MODIFIERKEY_ALPHALOCK ) {/* Caps Lock key */ 911 _delegate->setAlphaLock((myFlags & NX_ALPHASHIFTMASK) ? true : false); 912 } 913 else if ( bit == NX_MODIFIERKEY_NUMLOCK ) {/* Num Lock key */ 914 _delegate->setNumLock((myFlags & NX_NUMERICPADMASK) ? true : false); 915 } 916 917 _delegate->setDeviceFlags(myFlags); 918 919} 920 921 922// 923// Perform flag state update and generate flags changed events for this key. 924// 925void IOHIKeyboardMapper::doModCalc(int key, kbdBitVector keyBits) 926{ 927 int thisBits; 928 thisBits = _parsedMapping.keyBits[key]; 929 if (thisBits & NX_MODMASK) 930 { 931 calcModBit((thisBits & NX_WHICHMODMASK), keyBits); 932 /* The driver generates flags-changed events only when there is 933 no key-down or key-up event generated */ 934 if (!(thisBits & NX_CHARGENMASK)) 935 { 936 /* Post the flags-changed event */ 937 _delegate->keyboardEvent(NX_FLAGSCHANGED, 938 /* flags */ _delegate->eventFlags(), 939 /* keyCode */ key, 940 /* charCode */ 0, 941 /* charSet */ 0, 942 /* originalCharCode */ 0, 943 /* originalCharSet */ 0); 944#ifdef NEW_HID 945 _delegate->keyboardEvent(EVK_IS_KEYDOWN(key, keyBits) ? NX_KEYDOWN : NX_KEYUP, 946 /* flags */ _delegate->eventFlags(), 947 /* keyCode */ key, 948 /* charCode */ 0, 949 /* charSet */ 0, 950 /* originalCharCode */ 0, 951 /* originalCharSet */ 0); 952#endif 953 } 954 else /* Update, but don't generate an event */ 955 _delegate->updateEventFlags(_delegate->eventFlags()); 956 } 957} 958 959// 960// Perform character event generation for this key 961// 962void IOHIKeyboardMapper::doCharGen(int keyCode, bool down) 963{ 964 int i, n, eventType, adjust, thisMask, modifiers, saveModifiers; 965 short shorts; 966 unsigned charSet, origCharSet; 967 unsigned charCode, origCharCode; 968 unsigned char *map; 969 unsigned eventFlags, origflags; 970 971 _delegate->setCharKeyActive(true); // a character generating key is active 972 973 eventType = (down == true) ? NX_KEYDOWN : NX_KEYUP; 974 eventFlags = _delegate->eventFlags(); 975 saveModifiers = eventFlags >> 16; // machine independent mod bits 976 /* Set NX_ALPHASHIFTMASK based on alphaLock OR shift active */ 977 if( saveModifiers & (NX_SHIFTMASK >> 16)) 978 saveModifiers |= (NX_ALPHASHIFTMASK >> 16); 979 980 981 /* Get this key's key mapping */ 982 shorts = _parsedMapping.shorts; 983 map = _parsedMapping.keyDefs[keyCode]; 984 modifiers = saveModifiers; 985 if ( map ) { 986 987 988 /* Build offset for this key */ 989 thisMask = NEXTNUM(&map, shorts); 990 if (thisMask && modifiers) { 991 adjust = (shorts ? sizeof(short) : sizeof(char))*2; 992 for ( i = 0; i <= _parsedMapping.maxMod; ++i) { 993 if (thisMask & 0x01) { 994 if (modifiers & 0x01) 995 map += adjust; 996 adjust *= 2; 997 } 998 thisMask >>= 1; 999 modifiers >>= 1; 1000 } 1001 } 1002 charSet = NEXTNUM(&map, shorts); 1003 charCode = NEXTNUM(&map, shorts); 1004 1005 /* construct "unmodified" character */ 1006 map = _parsedMapping.keyDefs[keyCode]; 1007 modifiers = saveModifiers & ((NX_ALPHASHIFTMASK | NX_SHIFTMASK) >> 16); 1008 1009 thisMask = NEXTNUM(&map, shorts); 1010 if (thisMask && modifiers) { 1011 adjust = (shorts ? sizeof(short) : sizeof(char)) * 2; 1012 for ( i = 0; i <= _parsedMapping.maxMod; ++i) { 1013 if (thisMask & 0x01) { 1014 if (modifiers & 0x01) 1015 map += adjust; 1016 adjust *= 2; 1017 } 1018 thisMask >>= 1; 1019 modifiers >>= 1; 1020 } 1021 } 1022 origCharSet = NEXTNUM(&map, shorts); 1023 origCharCode = NEXTNUM(&map, shorts); 1024 1025 if (charSet == (unsigned)(shorts ? 0xFFFF : 0x00FF)) { 1026 // Process as a character sequence 1027 // charCode holds the sequence number 1028 map = _parsedMapping.seqDefs[charCode]; 1029 1030 origflags = eventFlags; 1031 for (i=0,n=NEXTNUM(&map, shorts);i<n;i++) { 1032 if ( (charSet = NEXTNUM(&map, shorts)) == 0xFF ) { /* metakey */ 1033 if ( down == true ) { /* down or repeat */ 1034 eventFlags |= (1 << (NEXTNUM(&map, shorts) + 16)); 1035 _delegate->keyboardEvent(NX_FLAGSCHANGED, 1036 /* flags */ _delegate->deviceFlags(), 1037 /* keyCode */ keyCode, 1038 /* charCode */ 0, 1039 /* charSet */ 0, 1040 /* originalCharCode */ 0, 1041 /* originalCharSet */ 0); 1042 } 1043 else 1044 NEXTNUM(&map, shorts); /* Skip over value */ 1045 } 1046 else { 1047 charCode = NEXTNUM(&map, shorts); 1048 _delegate->keyboardEvent(eventType, 1049 /* flags */ eventFlags, 1050 /* keyCode */ keyCode, 1051 /* charCode */ charCode, 1052 /* charSet */ charSet, 1053 /* originalCharCode */ charCode, 1054 /* originalCharSet */ charSet); 1055 } 1056 } 1057 /* Done with macro. Restore the flags if needed. */ 1058 if ( eventFlags != origflags ) { 1059 _delegate->keyboardEvent(NX_FLAGSCHANGED, 1060 /* flags */ _delegate->deviceFlags(), 1061 /* keyCode */ keyCode, 1062 /* charCode */ 0, 1063 /* charSet */ 0, 1064 /* originalCharCode */ 0, 1065 /* originalCharSet */ 0); 1066 eventFlags = origflags; 1067 } 1068 } 1069 else { /* A simple character generating key */ 1070 _delegate->keyboardEvent(eventType, 1071 /* flags */ eventFlags, 1072 /* keyCode */ keyCode, 1073 /* charCode */ charCode, 1074 /* charSet */ charSet, 1075 /* originalCharCode */ origCharCode, 1076 /* originalCharSet */ origCharSet); 1077 } 1078 } /* if (map) */ 1079 1080 /* 1081 * Check for a device control key: note that they always have CHARGEN 1082 * bit set 1083 */ 1084 if (_parsedMapping.keyBits[keyCode] & NX_SPECIALKEYMASK) { 1085 for (i=0; i<NX_NUM_SCANNED_SPECIALKEYS; i++) { 1086 if ( keyCode == _parsedMapping.specialKeys[i] ) { 1087 _delegate->keyboardSpecialEvent(eventType, 1088 /* flags */ eventFlags, 1089 /* keyCode */ keyCode, 1090 /* specialty */ i); 1091 /* 1092 * Special keys hack for letting an arbitrary (non-locking) 1093 * key act as a CAPS-LOCK key. If a special CAPS LOCK key 1094 * is designated, and there is no key designated for the 1095 * AlphaLock function, then we'll let the special key toggle 1096 * the AlphaLock state. 1097 */ 1098 if (i == NX_KEYTYPE_CAPS_LOCK 1099 && down == true 1100 && !_parsedMapping.modDefs[NX_MODIFIERKEY_ALPHALOCK] ) { 1101 unsigned myFlags = _delegate->deviceFlags(); 1102 bool alphaLock = (_delegate->alphaLock() == false); 1103 1104 // Set delegate's alphaLock state 1105 _delegate->setAlphaLock(alphaLock); 1106 // Update the delegate's flags 1107 if ( alphaLock ) { 1108 myFlags |= NX_ALPHASHIFTMASK; 1109 _specialKeyModifierFlags |= NX_ALPHASHIFTMASK; 1110 } 1111 else { 1112 myFlags &= ~NX_ALPHASHIFTMASK; 1113 _specialKeyModifierFlags &= ~NX_ALPHASHIFTMASK; 1114 } 1115 1116 _delegate->setDeviceFlags(myFlags); 1117 1118 _delegate->keyboardEvent(NX_FLAGSCHANGED, 1119 /* flags */ myFlags, 1120 /* keyCode */ keyCode, 1121 /* charCode */ 0, 1122 /* charSet */ 0, 1123 /* originalCharCode */ 0, 1124 /* originalCharSet */ 0); 1125 1126#ifdef NEW_HID 1127 _delegate->keyboardEvent(alphaLock ? NX_KEYDOWN : NX_KEYUP, 1128 /* flags */ myFlags, 1129 /* keyCode */ keyCode, 1130 /* charCode */ 0, 1131 /* charSet */ 0, 1132 /* originalCharCode */ 0, 1133 /* originalCharSet */ 0); 1134#endif 1135 } 1136 else if (i == NX_KEYTYPE_NUM_LOCK 1137 && down == true 1138 && (_delegate->doesKeyLock(NX_KEYTYPE_NUM_LOCK) || _delegate->metaCast("AppleADBButtons")) 1139 && !_parsedMapping.modDefs[NX_MODIFIERKEY_NUMLOCK] ) { 1140 unsigned myFlags = _delegate->deviceFlags(); 1141 bool numLock = (_delegate->numLock() == false); 1142 1143 // Set delegate's numLock state 1144 _delegate->setNumLock(numLock); 1145 if ( numLock ) { 1146 myFlags |= NX_NUMERICPADMASK; 1147 _specialKeyModifierFlags |= NX_NUMERICPADMASK; 1148 } 1149 else { 1150 myFlags &= ~NX_NUMERICPADMASK; 1151 _specialKeyModifierFlags &= ~NX_NUMERICPADMASK; 1152 } 1153 1154 _delegate->setDeviceFlags(myFlags); 1155 _delegate->keyboardEvent(NX_FLAGSCHANGED, 1156 /* flags */ myFlags, 1157 /* keyCode */ keyCode, 1158 /* charCode */ 0, 1159 /* charSet */ 0, 1160 /* originalCharCode */ 0, 1161 /* originalCharSet */ 0); 1162 } 1163 1164 break; 1165 } 1166 } 1167 } 1168} 1169 1170 1171void IOHIKeyboardMapper::setKeyboardTarget (IOService * keyboardTarget) 1172{ 1173 _hidSystem = OSDynamicCast( IOHIDSystem, keyboardTarget ); 1174} 1175 1176void IOHIKeyboardMapper::makeNumberParamProperty( OSDictionary * dict, 1177 const char * key, 1178 unsigned long long number, unsigned int bits ) 1179{ 1180 OSNumber * numberRef; 1181 numberRef = OSNumber::withNumber(number, bits); 1182 1183 if( numberRef) { 1184 dict->setObject( key, numberRef); 1185 numberRef->release(); 1186 } 1187} 1188 1189bool IOHIKeyboardMapper::updateProperties( void ) 1190{ 1191 bool ok = true; 1192 1193 return( ok ); 1194} 1195 1196IOReturn IOHIKeyboardMapper::setParamProperties( OSDictionary * dict ) 1197{ 1198 OSNumber * number = 0; 1199 OSData * data = 0; 1200 OSArray * array = 0; 1201 IOReturn err = kIOReturnSuccess; 1202 bool updated = false; 1203 UInt32 value = 0; 1204 bool issueFlagsChangedEvent = false; 1205 bool alphaState = false; 1206 UInt32 myFlags = _delegate->deviceFlags(); 1207 UInt32 ledStatus = 0; 1208 1209 // Check for eject delay property 1210 if ((number = OSDynamicCast(OSNumber, 1211 dict->getObject(kIOHIDF12EjectDelayKey))) || 1212 (data = OSDynamicCast(OSData, 1213 dict->getObject(kIOHIDF12EjectDelayKey)))) 1214 { 1215 value = (number) ? number->unsigned32BitValue() : *((UInt32 *) (data->getBytesNoCopy())); 1216 1217 // we know we set this as a 32 bit number 1218 _eject_Delay_MS = value; 1219 1220 // we changed something 1221 updated = true; 1222 } 1223 1224 // Check for fkey mode property 1225 if ((number = OSDynamicCast(OSNumber, 1226 dict->getObject(kIOHIDMouseKeysOnKey))) || 1227 (data = OSDynamicCast(OSData, 1228 dict->getObject(kIOHIDMouseKeysOnKey)))) 1229 { 1230 value = (number) ? number->unsigned32BitValue() : *((UInt32 *) (data->getBytesNoCopy())); 1231 1232 // if set, then set the bit in our state 1233 if (value) 1234 _stickyKeys_State |= kState_MouseKeyStateOn; 1235 // otherwise clear the bit in our state 1236 else 1237 _stickyKeys_State &= ~kState_MouseKeyStateOn; 1238 1239 // we changed something 1240 updated = true; 1241 } 1242 1243 // Check for slowKeys delay property 1244 if ((number = OSDynamicCast(OSNumber, 1245 dict->getObject(kIOHIDSlowKeysDelayKey))) || 1246 (data = OSDynamicCast(OSData, 1247 dict->getObject(kIOHIDSlowKeysDelayKey)))) 1248 { 1249 value = (number) ? number->unsigned32BitValue() : *((UInt32 *) (data->getBytesNoCopy())); 1250 // If we are in progess and we are turned off 1251 // cancel the timeout 1252 if ((_slowKeys_Delay_MS > 0) && !value && 1253 ((_slowKeys_State & kState_In_Progess_Flag) != 0)) 1254 _slowKeysTimerEventSource->cancelTimeout(); 1255 1256 1257 _slowKeys_Delay_MS = value; 1258 1259 // we changed something 1260 updated = true; 1261 } 1262 1263 // check for disabled property in the dictionary 1264 if ((number = OSDynamicCast(OSNumber, 1265 dict->getObject(kIOHIDStickyKeysDisabledKey))) || 1266 (data = OSDynamicCast(OSData, 1267 dict->getObject(kIOHIDStickyKeysDisabledKey)))) 1268 { 1269 value = (number) ? number->unsigned32BitValue() : *((UInt32 *) (data->getBytesNoCopy())); 1270 1271 // if set, then set the bit in our state 1272 if (value) 1273 { 1274 _stickyKeys_State |= kState_Disabled_Flag; 1275 stickyKeysCleanup(); 1276 } 1277 // otherwise clear the bit in our state 1278 else 1279 _stickyKeys_State &= ~kState_Disabled_Flag; 1280 1281 // we changed something 1282 updated = true; 1283 } 1284 1285 // check for on/off property in the dictionary 1286 if ((number = OSDynamicCast(OSNumber, 1287 dict->getObject(kIOHIDStickyKeysOnKey))) || 1288 (data = OSDynamicCast(OSData, 1289 dict->getObject(kIOHIDStickyKeysOnKey)))) 1290 { 1291 value = (number) ? number->unsigned32BitValue() : *((UInt32 *) (data->getBytesNoCopy())); 1292 1293 // if set, then set the bit in our state 1294 if (value) { 1295 _stickyKeys_State |= kState_On; 1296 } 1297 // otherwise clear the bit in our state 1298 else { 1299 stickyKeysCleanup(); 1300 } 1301 1302 // we changed something 1303 updated = true; 1304 } 1305 1306 // Check for fkey mode property 1307 if ((dict->getObject(kIOHIDTemporaryParametersKey) == NULL) && 1308 ((NULL != (number = OSDynamicCast(OSNumber, dict->getObject(kIOHIDFKeyModeKey)))) || 1309 (NULL != (data = OSDynamicCast(OSData, dict->getObject(kIOHIDFKeyModeKey)))))) 1310 { 1311 value = (number) ? number->unsigned32BitValue() : *((UInt32 *) (data->getBytesNoCopy())); 1312 1313 // if set, then set the bit in our state 1314 if (value) 1315 _stickyKeys_State |= kState_PrefFnKeyStateOn; 1316 // otherwise clear the bit in our state 1317 else 1318 _stickyKeys_State &= ~kState_PrefFnKeyStateOn; 1319 1320 // we changed something 1321 updated = true; 1322 } 1323 1324 // check for shift toggles property in the dictionary 1325 if ((number = OSDynamicCast(OSNumber, 1326 dict->getObject(kIOHIDStickyKeysShiftTogglesKey))) || 1327 (data = OSDynamicCast(OSData, 1328 dict->getObject(kIOHIDStickyKeysShiftTogglesKey)))) 1329 { 1330 value = (number) ? number->unsigned32BitValue() : *((UInt32 *) (data->getBytesNoCopy())); 1331 1332 // if set, then set the bit in our state 1333 if (value) 1334 _stickyKeys_State |= kState_ShiftActivates_Flag; 1335 // otherwise clear the bit in our state 1336 else 1337 _stickyKeys_State &= ~kState_ShiftActivates_Flag; 1338 1339 // we changed something 1340 updated = true; 1341 } 1342 1343 // check for shift toggles property in the dictionary 1344 if ((number = OSDynamicCast(OSNumber, 1345 dict->getObject(kIOHIDMouseKeysOptionTogglesKey))) || 1346 (data = OSDynamicCast(OSData, 1347 dict->getObject(kIOHIDMouseKeysOptionTogglesKey)))) 1348 { 1349 value = (number) ? number->unsigned32BitValue() : *((UInt32 *) (data->getBytesNoCopy())); 1350 1351 // if set, then set the bit in our state 1352 if (value) 1353 _stickyKeys_State |= kState_OptionActivates_Flag; 1354 // otherwise clear the bit in our state 1355 else 1356 _stickyKeys_State &= ~kState_OptionActivates_Flag; 1357 1358 // we changed something 1359 updated = true; 1360 } 1361 1362 if ((array = OSDynamicCast(OSArray, dict->getObject(kIOHIDKeyboardModifierMappingPairsKey))) && (_parsedMapping.maxMod != -1)) 1363 { 1364 UInt32 count = array->getCount(); 1365 1366 if ( count ) 1367 { 1368 for ( unsigned i=0; i<count; i++) 1369 { 1370 OSDictionary * pair = OSDynamicCast(OSDictionary, array->getObject(i)); 1371 UInt32 src = 0; 1372 UInt32 dst = 0; 1373 1374 if ( !pair ) continue; 1375 1376 number = OSDynamicCast(OSNumber, pair->getObject(kIOHIDKeyboardModifierMappingSrcKey)); 1377 1378 if ( !number ) continue; 1379 1380 src = number->unsigned32BitValue(); 1381 1382 number = OSDynamicCast(OSNumber, pair->getObject(kIOHIDKeyboardModifierMappingDstKey)); 1383 1384 if ( !number ) continue; 1385 1386 dst = number->unsigned32BitValue(); 1387 1388 if ( src == NX_MODIFIERKEY_ALPHALOCK ) 1389 { 1390 ledStatus = _delegate->getLEDStatus(); 1391 1392 if (dst == NX_MODIFIERKEY_ALPHALOCK) 1393 { 1394 if ((ledStatus & 0x2) && !(myFlags & NX_ALPHASHIFTMASK)) 1395 { 1396 issueFlagsChangedEvent = true; 1397 alphaState = true; 1398 } 1399 else if (!(ledStatus & 0x2) && (myFlags & NX_ALPHASHIFTMASK)) 1400 { 1401 issueFlagsChangedEvent = true; 1402 alphaState = false; 1403 } 1404 } 1405 else if (_delegate->doesKeyLock(NX_KEYTYPE_CAPS_LOCK) && (dst != -1)) 1406 { 1407 continue; 1408 } 1409 else 1410 { 1411 issueFlagsChangedEvent = true; 1412 alphaState = false; 1413 } 1414 } 1415 1416 if ((src >= NX_MODIFIERKEY_ALPHALOCK) && 1417 (src <= NX_MODIFIERKEY_LAST_KEY) && 1418 ((dst < NX_NUMMODIFIERS) || (dst == (UInt32) -1)) ) 1419 _modifierSwap_Modifiers[src] = dst; 1420 } 1421 } 1422 else 1423 { 1424 for (unsigned i=0; i<NX_NUMMODIFIERS; i++) 1425 { 1426 if (((i == NX_MODIFIERKEY_ALPHALOCK) && (_modifierSwap_Modifiers[i] != NX_MODIFIERKEY_ALPHALOCK)) || 1427 ((i != NX_MODIFIERKEY_ALPHALOCK) && (_modifierSwap_Modifiers[i] == NX_MODIFIERKEY_ALPHALOCK))) 1428 { 1429 ledStatus = _delegate->getLEDStatus(); 1430 1431 if ((ledStatus & 0x2) && !(myFlags & NX_ALPHASHIFTMASK)) 1432 { 1433 issueFlagsChangedEvent = true; 1434 alphaState = true; 1435 } 1436 else if (!(ledStatus & 0x2) && (myFlags & NX_ALPHASHIFTMASK)) 1437 { 1438 issueFlagsChangedEvent = true; 1439 alphaState = false; 1440 } 1441 } 1442 1443 _modifierSwap_Modifiers[i] = i; 1444 } 1445 1446 } 1447 1448 } 1449 1450 if ( issueFlagsChangedEvent ) 1451 { 1452 if ( alphaState ) 1453 { 1454 if ( !_delegate->doesKeyLock(NX_KEYTYPE_CAPS_LOCK) ) 1455 { 1456 _specialKeyModifierFlags |= NX_ALPHASHIFTMASK; 1457 } 1458 1459 myFlags |= NX_ALPHASHIFTMASK; 1460 1461 _delegate->setDeviceFlags(myFlags); 1462 _delegate->setAlphaLock(true); 1463 } 1464 else 1465 { 1466 _specialKeyModifierFlags &= ~NX_ALPHASHIFTMASK; 1467 myFlags &= ~NX_ALPHASHIFTMASK; 1468 1469 _delegate->setDeviceFlags(myFlags); 1470 _delegate->setAlphaLock(false); 1471 } 1472 1473 UInt8 keyCode; 1474 unsigned char *map; 1475 1476 if (((map = _parsedMapping.modDefs[NX_MODIFIERKEY_ALPHALOCK]) != 0 ) && 1477 ( NEXTNUM(&map, _parsedMapping.shorts) )) 1478 keyCode = NEXTNUM(&map, _parsedMapping.shorts); 1479 else 1480 keyCode = getParsedSpecialKey(NX_KEYTYPE_CAPS_LOCK); 1481 1482 _delegate->keyboardEvent(NX_FLAGSCHANGED, 1483 /* flags */ myFlags, 1484 /* keyCode */ keyCode, 1485 /* charCode */ 0, 1486 /* charSet */ 0, 1487 /* originalCharCode */ 0, 1488 /* originalCharSet */ 0); 1489 1490 1491#ifdef NEW_HID 1492 _delegate->keyboardEvent(alphaState ? NX_KEYDOWN : NX_KEYUP, 1493 /* flags */ myFlags, 1494 /* keyCode */ keyCode, 1495 /* charCode */ 0, 1496 /* charSet */ 0, 1497 /* originalCharCode */ 0, 1498 /* originalCharSet */ 0); 1499#endif 1500 } 1501 1502 // right now updateProperties does nothing interesting 1503 if (updated) 1504 updateProperties(); 1505 1506 return( err ); 1507} 1508 1509// ************* Sticky Keys Functionality **************** 1510 1511// stickyKeysinit 1512// initialize sticky keys variables 1513bool IOHIKeyboardMapper::stickyKeysinit( void ) 1514{ 1515 // default state to off, unless the UI part is installed and turns us on. 1516 // instead of setting shifttoggles and disabled, which would be the other way to do it 1517 // we will just keep all flags clear, making us off but not explicitly 'disabled' 1518 // the behavior is the same, but the meaning is different, we are in default state off, 1519 // not user explictly setting us to off 1520 // NOTE: the real default ends up being set in IOHIDSystem::createParameters 1521 _stickyKeys_State = 0; 1522 1523 _stickyKeys_NumModifiersDown = 0; 1524 1525 // allocate shift toggle struct 1526 _stickyKeys_ShiftToggle = stickyKeysAllocToggleInfo (kNUM_SHIFTS_TO_ACTIVATE); 1527 if (_stickyKeys_ShiftToggle == NULL) 1528 return false; 1529 1530 // initialize shift toggle struct 1531 _stickyKeys_ShiftToggle->toggleModifier = NX_MODIFIERKEY_SHIFT; 1532 _stickyKeys_ShiftToggle->repetitionsToToggle = kNUM_SHIFTS_TO_ACTIVATE; 1533 clock_interval_to_absolutetime_interval( kDEFAULT_SHIFTEXPIREINTERVAL, 1534 kMillisecondScale, 1535 &_stickyKeys_ShiftToggle->expireInterval); 1536 _stickyKeys_ShiftToggle->currentCount = 0; 1537 1538 // allocate option toggle struct 1539 _stickyKeys_OptionToggle = stickyKeysAllocToggleInfo (kNUM_SHIFTS_TO_ACTIVATE); 1540 if (_stickyKeys_OptionToggle == NULL) 1541 return false; 1542 1543 // initialize option toggle struct 1544 _stickyKeys_OptionToggle->toggleModifier = NX_MODIFIERKEY_ALTERNATE; 1545 _stickyKeys_OptionToggle->repetitionsToToggle = kNUM_SHIFTS_TO_ACTIVATE; 1546 clock_interval_to_absolutetime_interval( kDEFAULT_SHIFTEXPIREINTERVAL, 1547 kMillisecondScale, 1548 &_stickyKeys_OptionToggle->expireInterval); 1549 _stickyKeys_OptionToggle->currentCount = 0; 1550 1551 _stickyKeysMouseClickEventSource = 0; 1552 1553 _stickyKeysSetFnStateEventSource = 0; 1554 1555 return createParamDicts(); 1556} 1557 1558// stickyKeysfree 1559// free sticky keys variables 1560void IOHIKeyboardMapper::stickyKeysfree (void) 1561{ 1562 // release shift toggle struct 1563 if (_stickyKeys_ShiftToggle) 1564 stickyKeysFreeToggleInfo(_stickyKeys_ShiftToggle); 1565 1566 // release option toggle struct 1567 if (_stickyKeys_OptionToggle) 1568 stickyKeysFreeToggleInfo(_stickyKeys_OptionToggle); 1569 1570 // release on param dict 1571 if (_onParamDict) 1572 _onParamDict->release(); 1573 1574 // release off param dict 1575 if (_offParamDict) 1576 _offParamDict->release(); 1577 1578 // release off fn param dict 1579 if (_offFnParamDict) 1580 _offFnParamDict->release(); 1581 1582 1583 // release on fn param dict 1584 if (_onFnParamDict) 1585 _onFnParamDict->release(); 1586 1587 if (_stickyKeysMouseClickEventSource) { 1588 _stickyKeysMouseClickEventSource->release(); 1589 _stickyKeysMouseClickEventSource = 0; 1590 } 1591 1592 if (_stickyKeysSetFnStateEventSource) { 1593 _stickyKeysSetFnStateEventSource->release(); 1594 _stickyKeysSetFnStateEventSource = 0; 1595 } 1596 1597 1598} 1599 1600// allocate a StickyKeys_ToggleInfo struct 1601StickyKeys_ToggleInfo * IOHIKeyboardMapper::stickyKeysAllocToggleInfo (unsigned maxCount) 1602{ 1603 StickyKeys_ToggleInfo * toggleInfo; 1604 IOByteCount size; 1605 1606 // size should be size of the structure plus 1607 // the size of each entry of the array (AbsoluteTime) 1608 // note the struct already has room for the first entry 1609 size = sizeof(StickyKeys_ToggleInfo) + 1610 (sizeof(AbsoluteTime) * (maxCount - 1)); 1611 1612 // allocate shift toggle struct 1613 toggleInfo = (StickyKeys_ToggleInfo *) 1614 IOMalloc (size); 1615 1616 // set the size 1617 if (toggleInfo) 1618 toggleInfo->size = size; 1619 1620 return toggleInfo; 1621} 1622 1623// free a StickyKeys_ToggleInfo struct 1624void IOHIKeyboardMapper::stickyKeysFreeToggleInfo (StickyKeys_ToggleInfo * toggleInfo) 1625{ 1626 // free shift toggle struct 1627 IOFree (toggleInfo, toggleInfo->size); 1628} 1629 1630// createParamDicts 1631// create on/off dicts as part of init 1632bool IOHIKeyboardMapper::createParamDicts ( void ) 1633{ 1634 bool ok = true; 1635 1636 // create a dictionary that sets state to on 1637 _onParamDict = OSDictionary::withCapacity(4); 1638 if (_onParamDict) 1639 { 1640 // on 1641 makeNumberParamProperty( _onParamDict, kIOHIDStickyKeysOnKey, 1642 1, 32 ); 1643 } 1644 else 1645 ok = false; 1646 1647 // create a dictionary that sets state to off 1648 if (ok) 1649 _offParamDict = OSDictionary::withCapacity(4); 1650 if (_offParamDict) 1651 { 1652 // off 1653 makeNumberParamProperty( _offParamDict, kIOHIDStickyKeysOnKey, 1654 0, 32 ); 1655 } 1656 else 1657 ok = false; 1658 1659 // create a dictionary that sets fn state to on 1660 if (ok) 1661 _onFnParamDict = OSDictionary::withCapacity(4); 1662 if (_onFnParamDict) 1663 { 1664 // off 1665 makeNumberParamProperty( _onFnParamDict, kIOHIDFKeyModeKey, 1666 1, 32 ); 1667 1668 _onFnParamDict->setObject(kIOHIDTemporaryParametersKey, kOSBooleanTrue); 1669 } 1670 else 1671 ok = false; 1672 1673 // create a dictionary that sets fn state to off 1674 if (ok) 1675 _offFnParamDict = OSDictionary::withCapacity(4); 1676 if (_offFnParamDict) 1677 { 1678 // off 1679 makeNumberParamProperty( _offFnParamDict, kIOHIDFKeyModeKey, 1680 0, 32 ); 1681 1682 _offFnParamDict->setObject(kIOHIDTemporaryParametersKey, kOSBooleanTrue); 1683 } 1684 else 1685 ok = false; 1686 1687 return( ok ); 1688} 1689 1690// postKeyboardSpecialEvent 1691// called to post special keyboard events 1692// thru the event system to outside of kernel clients 1693void IOHIKeyboardMapper::postKeyboardSpecialEvent (unsigned subtype, unsigned eventType) 1694{ 1695 _delegate->keyboardSpecialEvent ( 1696 /* eventType */ eventType, 1697 /* flags */ _delegate->eventFlags(), 1698 /* keyCode */ NX_NOSPECIALKEY, 1699 /* specialty */ subtype); 1700} 1701 1702bool IOHIKeyboardMapper::stickyKeysModifierToggleCheck(StickyKeys_ToggleInfo *toggleInfo, 1703 UInt8 key, 1704 bool keyDown, 1705 kbdBitVector keyBits __unused, 1706 bool mouseClick) 1707{ 1708 unsigned char thisBits = _parsedMapping.keyBits[key]; 1709 int index, innerindex; 1710 AbsoluteTime now, deadline; 1711 bool shouldToggle = false; 1712 unsigned leftModBit = (thisBits & NX_WHICHMODMASK); 1713 1714 // Convert the modbit to left hand modifier 1715 convertToLeftModBit(leftModBit); 1716 1717 // is this the shift key? 1718 if ((leftModBit == toggleInfo->toggleModifier) && !mouseClick) 1719 { 1720 // get the time 1721 clock_get_uptime(&now); 1722 1723 // prune the list of all occurences whose deadline has expired 1724 // start at the end, which is the most recent shift 1725 for (index = toggleInfo->currentCount - 1; index >= 0; index--) 1726 // did this item's deadline expire? 1727 if (AbsoluteTime_to_scalar(&now) > 1728 AbsoluteTime_to_scalar(&toggleInfo->deadlines[index])) 1729 { 1730 // remove this shift and all shifts that occurred previously 1731 1732 // move all newer shifts to the start 1733 int entries_to_delete = index + 1; 1734 1735 for (innerindex = 0; innerindex < (int)(toggleInfo->currentCount - entries_to_delete); innerindex++) 1736 toggleInfo->deadlines[innerindex] = 1737 toggleInfo->deadlines[innerindex + entries_to_delete]; 1738 1739 // update the count 1740 toggleInfo->currentCount -= entries_to_delete; 1741 1742 // defensive code 1743 index = -1; 1744 1745 // stop looping 1746 break; 1747 } 1748 1749 // is this a keydown, if so, add it to the list 1750 if (keyDown) 1751 { 1752 // we will add it if we have room 1753 if (toggleInfo->currentCount < toggleInfo->repetitionsToToggle) 1754 { 1755 // compute a new deadline 1756 clock_absolutetime_interval_to_deadline(toggleInfo->expireInterval, &deadline); 1757 1758 // add it 1759 toggleInfo->deadlines[toggleInfo->currentCount++] = deadline; 1760 } 1761 } 1762 // otherwise its a shift key up, if this the 5th one, then turn us on 1763 else 1764 { 1765 // is this the 5th shift 1766 if (toggleInfo->currentCount == toggleInfo->repetitionsToToggle) 1767 { 1768 // clear the list of shifts we are tracking 1769 toggleInfo->currentCount = 0; 1770 1771 // turn us on 1772 shouldToggle = true; 1773 } 1774 } 1775 1776 } 1777 // a non-shift key was used, start over timing the shift keys 1778 else 1779 toggleInfo->currentCount = 0; 1780 1781 return shouldToggle; 1782} 1783 1784// stickyKeysNonModifierKey 1785// called when a non-modifier key event occurs (up or down) 1786void IOHIKeyboardMapper::stickyKeysNonModifierKey( 1787 UInt8 key, 1788 bool keyDown, 1789 kbdBitVector keyBits, 1790 bool mouseClick) 1791{ 1792 int index; 1793 1794 // first post this non-modifier key down 1795 if (!mouseClick) 1796 rawTranslateKeyCode(key, keyDown, keyBits); 1797 1798 // determine whether or not to post the keyups for the modifiers being held 1799 for (index = 0; index < _stickyKeys_NumModifiersDown; index++) { 1800 _stickyKeys_StuckModifiers[index].state |= kModifier_DidPerformModifiy; 1801 1802 // Has this key been keyed up. If not, leave the key alone 1803 // because the user is still holding it down. 1804 if (((_stickyKeys_StuckModifiers[index].state & kModifier_DidKeyUp) != 0) && 1805 ((_stickyKeys_StuckModifiers[index].state & kModifier_Locked) == 0)) { 1806 // We keyed up ealier, so we should call stickyKeysModifierKey to 1807 // individually release the key 1808 stickyKeysModifierKey(_stickyKeys_StuckModifiers[index].key, false, keyBits); 1809 1810 // We basically took a modifier off the list, so we have to decrement 1811 // our local index 1812 index --; 1813 } 1814 } 1815 1816 // clear state, if modifiers no longer down 1817 if (_stickyKeys_NumModifiersDown == 0) 1818 _stickyKeys_State &= ~kState_On_ModifiersDown; 1819 1820} 1821 1822// stickyKeysModifierKey 1823// called when shift/command/control/option key goes down 1824// returns true if the key should be processed 1825bool IOHIKeyboardMapper::stickyKeysModifierKey( 1826 UInt8 key, 1827 bool keyDown, 1828 kbdBitVector keyBits) 1829{ 1830 unsigned char thisBits = _parsedMapping.keyBits[key]; 1831 int index = 0; 1832 int innerindex = 0; 1833 bool isBeingHeld = false; 1834 bool shouldBeHandled = true; 1835 int heldIndex = 0; 1836 int leftModBit = (thisBits & NX_WHICHMODMASK); 1837 1838 // Convert the modbit to left hand modifier 1839 convertToLeftModBit(leftModBit); 1840 1841 // is this key being held? (if so, dont post the down) 1842 isBeingHeld = false; 1843 for (index = 0; index < _stickyKeys_NumModifiersDown; index++) 1844 if (_stickyKeys_StuckModifiers[index].leftModBit == leftModBit) 1845 { 1846 isBeingHeld = true; 1847 heldIndex = index; 1848 1849 // break out of loop, modifers will not be in twice 1850 break; 1851 } 1852 1853 // The following condition has been added, so that chording of key combinations can be supported 1854 if (! keyDown) { 1855 // For chording, we only care if the modifier is being held 1856 if (isBeingHeld) 1857 { 1858 if (((_stickyKeys_StuckModifiers[heldIndex].state & kModifier_DidPerformModifiy) != 0) && 1859 ((_stickyKeys_StuckModifiers[heldIndex].state & kModifier_Locked) == 0)) { 1860 // This modifier keyed up, but it also modified a key. 1861 // Therefore it needs to be released. 1862 goto RELEASE_STICKY_MODIFIER_KEY; 1863 } 1864 else 1865 { 1866 // set the state flag, so that stickyKeysNonModifierKey can call 1867 // back into this function to release the key. 1868 _stickyKeys_StuckModifiers[heldIndex].state |= kModifier_DidKeyUp; 1869 1870 if (((thisBits & NX_WHICHMODMASK) == NX_MODIFIERKEY_SECONDARYFN) && 1871 ((_stickyKeys_State & kState_StickyFnKeyStateChangePending) != 0)) 1872 { 1873 _stickyKeys_State &= ~kState_StickyFnKeyStateChangePending; 1874 1875 if (_stickyKeysSetFnStateEventSource) 1876 _stickyKeysSetFnStateEventSource->interruptOccurred(0, 0, 0); 1877 } 1878 } 1879 } 1880 // RY: take care of the case where the modifier was held down 1881 // prior to starting sticky keys. The key up will let be 1882 // processed as normal. 1883 else 1884 shouldBeHandled = false; 1885 } 1886 // we have a key down 1887 else 1888 { 1889 // is this key being held? (if so, stop holding it - toggle off) 1890 if (isBeingHeld) 1891 { 1892 1893 // If this key has been locked, then it needs to be release 1894 // The third and final state of the modifier key 1895 if ((_stickyKeys_StuckModifiers[heldIndex].state & kModifier_Locked) != 0) 1896 { 1897RELEASE_STICKY_MODIFIER_KEY: 1898 // stop holding this key down 1899 1900 // post the key up 1901 rawTranslateKeyCode(_stickyKeys_StuckModifiers[heldIndex].key, false, keyBits); 1902 1903 // clear this one (handles the case this is the last key held) 1904 _stickyKeys_StuckModifiers[heldIndex].key = 0; 1905 _stickyKeys_StuckModifiers[heldIndex].state = 0; 1906 _stickyKeys_StuckModifiers[heldIndex].leftModBit = 0; 1907 1908 // reduce our global count 1909 // (do this before the loop, so loop does not overrun) 1910 _stickyKeys_NumModifiersDown--; 1911 1912 // if no more keys being held, clear our state 1913 if (_stickyKeys_NumModifiersDown == 0) 1914 _stickyKeys_State &= ~kState_On_ModifiersDown; 1915 1916 // move each item after this one forward 1917 // note, _stickyKeys_NumModifiersDown already decremented 1918 for (innerindex = heldIndex; innerindex < _stickyKeys_NumModifiersDown; innerindex++) { 1919 _stickyKeys_StuckModifiers[innerindex].key = _stickyKeys_StuckModifiers[innerindex + 1].key; 1920 _stickyKeys_StuckModifiers[innerindex].state = _stickyKeys_StuckModifiers[innerindex + 1].state; 1921 _stickyKeys_StuckModifiers[innerindex].leftModBit = _stickyKeys_StuckModifiers[innerindex + 1].leftModBit; 1922 } 1923 1924 // notify the world we changed 1925 // note, we send a new event every time the user releses the modifier 1926 // while we are still holding modifiers. Clients must know to expect this 1927 switch ((thisBits & NX_WHICHMODMASK)) 1928 { 1929 case NX_MODIFIERKEY_SHIFT: 1930 case NX_MODIFIERKEY_RSHIFT: 1931 postKeyboardSpecialEvent (NX_SUBTYPE_STICKYKEYS_SHIFT_UP); 1932 break; 1933 case NX_MODIFIERKEY_CONTROL: 1934 case NX_MODIFIERKEY_RCONTROL: 1935 postKeyboardSpecialEvent (NX_SUBTYPE_STICKYKEYS_CONTROL_UP); 1936 break; 1937 case NX_MODIFIERKEY_ALTERNATE: 1938 case NX_MODIFIERKEY_RALTERNATE: 1939 postKeyboardSpecialEvent (NX_SUBTYPE_STICKYKEYS_ALTERNATE_UP); 1940 break; 1941 case NX_MODIFIERKEY_COMMAND: 1942 case NX_MODIFIERKEY_RCOMMAND: 1943 postKeyboardSpecialEvent (NX_SUBTYPE_STICKYKEYS_COMMAND_UP); 1944 break; 1945 case NX_MODIFIERKEY_SECONDARYFN: 1946 // Since we most likely running via IOHIDSystem::cmdGate runAction, 1947 // we should really trigger an interrupt to run this later on the 1948 // workloop. This will also avoid any synchronization anomolies. 1949 _stickyKeys_State &= ~(kState_StickyFnKeyStateOn | kState_StickyFnKeyStateChangePending); 1950 1951 if (_stickyKeysSetFnStateEventSource) 1952 _stickyKeysSetFnStateEventSource->interruptOccurred(0, 0, 0); 1953 1954 postKeyboardSpecialEvent (NX_SUBTYPE_STICKYKEYS_FN_UP); 1955 break; 1956 default: 1957 break; 1958 } 1959 1960 } 1961 1962 // This is the second press, therefore this key needs to be locked. 1963 else 1964 { 1965 _stickyKeys_StuckModifiers[heldIndex].state |= kModifier_Locked; 1966 1967 // notify the world we changed 1968 // note, we send a new event every time the user releses the modifier 1969 // while we are still holding modifiers. Clients must know to expect this 1970 switch ((thisBits & NX_WHICHMODMASK)) 1971 { 1972 case NX_MODIFIERKEY_SHIFT: 1973 case NX_MODIFIERKEY_RSHIFT: 1974 postKeyboardSpecialEvent (NX_SUBTYPE_STICKYKEYS_SHIFT_LOCK); 1975 break; 1976 case NX_MODIFIERKEY_CONTROL: 1977 case NX_MODIFIERKEY_RCONTROL: 1978 postKeyboardSpecialEvent (NX_SUBTYPE_STICKYKEYS_CONTROL_LOCK); 1979 break; 1980 case NX_MODIFIERKEY_ALTERNATE: 1981 case NX_MODIFIERKEY_RALTERNATE: 1982 postKeyboardSpecialEvent (NX_SUBTYPE_STICKYKEYS_ALTERNATE_LOCK); 1983 break; 1984 case NX_MODIFIERKEY_COMMAND: 1985 case NX_MODIFIERKEY_RCOMMAND: 1986 postKeyboardSpecialEvent (NX_SUBTYPE_STICKYKEYS_COMMAND_LOCK); 1987 break; 1988 case NX_MODIFIERKEY_SECONDARYFN: 1989 postKeyboardSpecialEvent (NX_SUBTYPE_STICKYKEYS_FN_LOCK); 1990 break; 1991 default: 1992 break; 1993 } 1994 1995 } 1996 } 1997 1998 // if this key is not being held already, then post the modifier down 1999 else 2000 { 2001 rawTranslateKeyCode(key, keyDown, keyBits); 2002 2003 // and remember it is down 2004 if (_stickyKeys_NumModifiersDown < kMAX_MODIFIERS) { 2005 int modifierIndex = _stickyKeys_NumModifiersDown++; 2006 _stickyKeys_StuckModifiers[modifierIndex].key = key; 2007 _stickyKeys_StuckModifiers[modifierIndex].state = 0; 2008 _stickyKeys_StuckModifiers[modifierIndex].leftModBit = leftModBit; 2009 } 2010 else 2011 ; // add a system log error here? 2012 2013 // change our state 2014 _stickyKeys_State |= kState_On_ModifiersDown; 2015 2016 2017 // notify the world we changed 2018 // note, we send a new event every time the user releses the modifier 2019 // while we are still holding modifiers. Clients must know to expect this 2020 switch ((thisBits & NX_WHICHMODMASK)) 2021 { 2022 case NX_MODIFIERKEY_SHIFT: 2023 case NX_MODIFIERKEY_RSHIFT: 2024 postKeyboardSpecialEvent (NX_SUBTYPE_STICKYKEYS_SHIFT_DOWN); 2025 break; 2026 case NX_MODIFIERKEY_CONTROL: 2027 case NX_MODIFIERKEY_RCONTROL: 2028 postKeyboardSpecialEvent (NX_SUBTYPE_STICKYKEYS_CONTROL_DOWN); 2029 break; 2030 case NX_MODIFIERKEY_ALTERNATE: 2031 case NX_MODIFIERKEY_RALTERNATE: 2032 postKeyboardSpecialEvent (NX_SUBTYPE_STICKYKEYS_ALTERNATE_DOWN); 2033 break; 2034 case NX_MODIFIERKEY_COMMAND: 2035 case NX_MODIFIERKEY_RCOMMAND: 2036 postKeyboardSpecialEvent (NX_SUBTYPE_STICKYKEYS_COMMAND_DOWN); 2037 break; 2038 case NX_MODIFIERKEY_SECONDARYFN: 2039 // Since we most likely running via IOHIDSystem::cmdGate runAction, 2040 // we should really trigger an interrupt to run this later on the 2041 // workloop. This will also avoid any synchronization anomolies. 2042 _stickyKeys_State |= kState_StickyFnKeyStateOn | kState_StickyFnKeyStateChangePending; 2043 2044 postKeyboardSpecialEvent (NX_SUBTYPE_STICKYKEYS_FN_DOWN); 2045 break; 2046 default: 2047 break; 2048 } 2049 2050 } 2051 } 2052 return shouldBeHandled; 2053} 2054 2055 2056// stickyKeysFilterKey 2057// returns true if this key event should be ignored 2058// It may call rawTranslateKeyCode multiple times to generate keyups 2059// at the end of a sticky keys sequence 2060// this function is the essence of the sticky keys feature 2061 2062bool IOHIKeyboardMapper::stickyKeysFilterKey( 2063 UInt8 key, 2064 bool keyDown, 2065 kbdBitVector keyBits, 2066 bool mouseClick) 2067{ 2068 unsigned char thisBits = _parsedMapping.keyBits[key]; 2069 bool shouldFilter = false; 2070 bool shouldToggleState = false; 2071 2072 if ( _parsedMapping.maxMod == -1 ) 2073 return false; 2074 2075 // if we are disabled, then do nothing 2076 if ((_stickyKeys_State & kState_Disabled_Flag) != 0) 2077 return false; 2078 2079 // check to see if option key toggle activated 2080 // only do so if the shift toggles bit is set 2081 // we could have a seperate bit to set whether option 2082 // should send the event, but we dont. Since the UI 2083 // uses these to be one in the same, we will as well. 2084 if ((_stickyKeys_State & kState_ShiftActivates_Flag) != 0) 2085 { 2086 // check to see if shift key pressed, possible to toggle state 2087 shouldToggleState = stickyKeysModifierToggleCheck 2088 (_stickyKeys_ShiftToggle, key, keyDown, keyBits, mouseClick); 2089 } 2090 2091 if ((_stickyKeys_State & kState_OptionActivates_Flag) != 0) 2092 { 2093 // if the option was toggled 2094 if (stickyKeysModifierToggleCheck (_stickyKeys_OptionToggle,key, keyDown, keyBits, mouseClick)) 2095 // if so, send the event to toggle mouse driving 2096 postKeyboardSpecialEvent (NX_SUBTYPE_STICKYKEYS_TOGGLEMOUSEDRIVING); 2097 } 2098 2099 // if we are on and holding modifier keys and we have a key down, finish if this is not modifier 2100 if (((_stickyKeys_State & kState_On_ModifiersDown) != 0) && !modifierOfInterest(thisBits)) 2101 { 2102 // Make sure that this is not a key and not a modifier that we track 2103 // This will allow us to pass through other modifiers like the arrow keys 2104 if (mouseClick || 2105 (keyDown && !(((_stickyKeys_State & kState_MouseKeyStateOn) != 0) && mouseKey(thisBits))) || 2106 (!keyDown && !(((_stickyKeys_State & kState_MouseKeyStateOn) != 0) && mouseKeyToIgnore(thisBits, key))) ) 2107 { 2108 // we will handle all the events here, so dont process this one normally 2109 shouldFilter = true; 2110 2111 // handle non-modifer key 2112 stickyKeysNonModifierKey (key, keyDown, keyBits, mouseClick); 2113 } 2114 2115 } 2116 2117 // if we are on and looking for modifier keys, see if this is one 2118 if ((_stickyKeys_State & kState_On) != 0) 2119 { 2120 2121 // set up interrupt event source for to handle sticky mouse down 2122 if (!_stickyKeysMouseClickEventSource && _hidSystem) 2123 { 2124 _stickyKeysMouseClickEventSource = 2125 IOInterruptEventSource::interruptEventSource 2126 (this, (IOInterruptEventSource::Action) stickyKeysMouseUp); 2127 2128 if(_stickyKeysMouseClickEventSource && 2129 (_hidSystem->getWorkLoop()->addEventSource(_stickyKeysMouseClickEventSource) != kIOReturnSuccess)) { 2130 _stickyKeysMouseClickEventSource->release(); 2131 _stickyKeysMouseClickEventSource = 0; 2132 } 2133 } 2134 2135 // set up interrup event source to handle sticky fn state 2136 if (!_stickyKeysSetFnStateEventSource && _hidSystem) 2137 { 2138 _stickyKeysSetFnStateEventSource = 2139 IOInterruptEventSource::interruptEventSource 2140 (this, (IOInterruptEventSource::Action) stickyKeysSetFnState); 2141 2142 if(_stickyKeysSetFnStateEventSource && 2143 (_hidSystem->getWorkLoop()->addEventSource(_stickyKeysSetFnStateEventSource) != kIOReturnSuccess)) { 2144 _stickyKeysSetFnStateEventSource->release(); 2145 _stickyKeysSetFnStateEventSource = 0; 2146 } 2147 } 2148 2149 // is this a sticky keys modifier key? 2150 // is this a modifier? 2151 if (modifierOfInterest(thisBits)) 2152 { 2153 // we will handle all the events here, so dont process this one normally 2154 // RY: stickyKeysModifierKey will return false if the key was held down 2155 // prior to turning on stickykeys. 2156 shouldFilter = stickyKeysModifierKey (key, keyDown, keyBits); 2157 2158 } 2159 } 2160 2161 // if we are supposed to toggle our state, do it now 2162 if (shouldToggleState) 2163 { 2164 // if we were on, clear a few things going off 2165 if ((_stickyKeys_State & kState_On) != 0) 2166 { 2167 stickyKeysCleanup(); 2168 postKeyboardSpecialEvent (NX_SUBTYPE_STICKYKEYS_OFF); 2169 } 2170 else 2171 { 2172 _stickyKeys_State |= kState_On; 2173 postKeyboardSpecialEvent (NX_SUBTYPE_STICKYKEYS_ON); 2174 } 2175 2176 // remember we changed 2177 _stateDirty = true; 2178 2179 // Since we most likely running via IOHIDSystem::cmdGate runAction, 2180 // we should really trigger an interrupt to run this later on the 2181 // workloop. This will also avoid any synchronization anomolies. 2182 if (_stickyKeysSetFnStateEventSource) 2183 _stickyKeysSetFnStateEventSource->interruptOccurred(0, 0, 0); 2184 } 2185 2186 return shouldFilter; 2187} 2188 2189void IOHIKeyboardMapper::stickyKeysCleanup() 2190{ 2191 _stickyKeys_State &= ~kState_On; 2192 2193 // post the keyups for all the modifier keys being held 2194 for (int index = 0; index < _stickyKeys_NumModifiersDown; index++) 2195 rawTranslateKeyCode(_stickyKeys_StuckModifiers[index].key, false, _cached_KeyBits); 2196 2197 // clear state, modifiers no longer down 2198 _stickyKeys_State &= ~kState_On_ModifiersDown; 2199 _stickyKeys_NumModifiersDown = 0; 2200 2201 // clear the fn key state 2202 _stickyKeys_State &= ~kState_StickyFnKeyStateOn; 2203 2204 // Since we most likely running via IOHIDSystem::cmdGate runAction, 2205 // we should really trigger an interrupt to run this later on the 2206 // workloop. This will also avoid any synchronization anomolies. 2207 if (_stickyKeysSetFnStateEventSource) 2208 _stickyKeysSetFnStateEventSource->interruptOccurred(0, 0, 0); 2209 2210} 2211 2212void IOHIKeyboardMapper::keyEventPostProcess (void) 2213{ 2214 bool nowOn; 2215 OSDictionary * dict; 2216 2217 // if the state changed 2218 if (_stateDirty) 2219 { 2220 // if we have a valid IOHIDSystem 2221 if (_hidSystem) 2222 { 2223 // are we now on? 2224 nowOn = ((_stickyKeys_State & kState_On) != 0); 2225 2226 // choose the proper dictionary 2227 dict = nowOn ? _onParamDict : _offParamDict; 2228 2229 // set it 2230 _hidSystem->setParamProperties (dict); 2231 } 2232 2233 // no longer dirty 2234 // (the case of a NULL _hidSystem should not happen, so 2235 // no point in maintaining a dirty state till one shows up) 2236 _stateDirty = false; 2237 } 2238 2239} 2240 2241 2242 2243// F12 Eject member functions 2244 2245// f12EjectFilterKey 2246// This function will determine whether or not f12 was pressed. 2247// If held down for a predetermined amount of time and eject 2248// notification will be issued. If key release early, this method 2249// will call rawTranslateKeyCode for keyDown and return false. 2250 2251bool IOHIKeyboardMapper::f12EjectFilterKey (UInt8 key, bool keyDown, kbdBitVector keyBits) { 2252 2253 // Check the delay time. If 0, then the feature is off. 2254 if ((_eject_Delay_MS == 0) || !_supportsF12Eject ) 2255 return false; 2256 2257 if (key == kADB_KEYBOARD_F12) { 2258 2259 // Let's check to see if an IOTimerEventSource exists. 2260 // If not, create one. 2261 if (!_ejectTimerEventSource) { 2262 // Make sure we have an instance of _hidSystem. 2263 if (_hidSystem == NULL) 2264 return false; 2265 2266 _ejectTimerEventSource = IOTimerEventSource::timerEventSource 2267 (this, (IOTimerEventSource::Action) &IOHIKeyboardMapper::performF12Eject); 2268 2269 if (_hidSystem->getWorkLoop()->addEventSource(_ejectTimerEventSource) != kIOReturnSuccess) 2270 return false; 2271 2272 } 2273 2274 if (keyDown == true) { 2275 // Set the time out and the flag 2276 _f12Eject_State |= kState_In_Progess_Flag; 2277 2278 _ejectTimerEventSource->setTimeoutMS(_eject_Delay_MS); 2279 2280 return true; // prevent processing of f12 2281 2282 } else { 2283 2284 // If the user pulled out early, send a key down event. 2285 // Since we return false, the system will take care of the 2286 // key up. 2287 if ((_f12Eject_State & kState_In_Progess_Flag) != 0) { 2288 2289 _ejectTimerEventSource->cancelTimeout(); 2290 2291 _f12Eject_State &= ~kState_In_Progess_Flag; 2292 2293 rawTranslateKeyCode (key, true, keyBits); 2294 } 2295 2296 // If we get to this point, the eject happened. 2297 // Therefore we should ignore the key up. 2298 else 2299 return true; 2300 2301 } 2302 } 2303 2304 // I think we should process all other key events during this check. 2305 // That is why I'm returning false; 2306 2307 return false; 2308 2309} 2310 2311// performF12Eject 2312// This is a static method called by the ejectTimerEventSource. 2313// It will send an System eject event 2314 2315void IOHIKeyboardMapper::performF12Eject(IOHIKeyboardMapper *owner, IOTimerEventSource *sender __unused) { 2316 2317 // Post the eject keydown event. 2318 owner->postKeyboardSpecialEvent(NX_KEYTYPE_EJECT, NX_KEYDOWN); 2319 2320 // Clear the state 2321 owner->_f12Eject_State &= ~kState_In_Progess_Flag; 2322 2323} 2324 2325// Slowkeys member functions 2326 2327// slowKeysFilterKey 2328// This function will determine whether or not a a key need to be 2329// processed for the slow keys feature. If so, if a key is held 2330// down for a predetermined amount of time, a key down will be 2331// pushed on up to the HID System. Other scenarios to the state 2332// machine are documented in further detail below. 2333 2334bool IOHIKeyboardMapper::slowKeysFilterKey (UInt8 key, bool keyDown, kbdBitVector keyBits __unused) 2335{ 2336 bool returnValue = true; 2337 2338 if (_slowKeys_Delay_MS == 0) 2339 return false; 2340 2341 // Let's check to see if an IOTimerEventSource exists. 2342 // If not, create one. 2343 if (!_slowKeysTimerEventSource) { 2344 2345 // Make sure we have an instance of _hidSystem. 2346 if (_hidSystem == NULL) 2347 return false; 2348 2349 _slowKeysTimerEventSource = IOTimerEventSource::timerEventSource 2350 (this, (IOTimerEventSource::Action) &IOHIKeyboardMapper::slowKeysPostProcess ); 2351 2352 2353 if(_hidSystem->getWorkLoop()->addEventSource(_slowKeysTimerEventSource) != kIOReturnSuccess) 2354 return false; 2355 2356 } 2357 2358 2359 if (keyDown) { 2360 // Ladies and Gentlemen start your engines 2361 if ((_slowKeys_State & kState_In_Progess_Flag) == 0) { 2362 2363 // Check to see if we are currently handling a repeated key. 2364 // If so, and the key pressed differs from the key that is 2365 // being repeated post the key up for that repeated key and 2366 // clear the flag. 2367 if ((key != _slowKeys_Current_Key) && ((_slowKeys_State & kState_Is_Repeat_Flag) != 0)) { 2368 2369 postSlowKeyTranslateKeyCode(this, _slowKeys_Current_Key, false, _cached_KeyBits); 2370 2371 _slowKeys_State &= ~kState_Is_Repeat_Flag; 2372 } 2373 2374 // Start the normal processing. 2375 2376 _slowKeys_State |= kState_In_Progess_Flag; 2377 2378 _slowKeys_Current_Key = key; 2379 2380 _slowKeysTimerEventSource->setTimeoutMS(_slowKeys_Delay_MS); 2381 2382 // Set a state flag telling us that the key is being repeated. 2383 if (_delegate->isRepeat()) 2384 _slowKeys_State |= kState_Is_Repeat_Flag; 2385 2386 // Notify System that this is the start 2387 postKeyboardSpecialEvent(NX_SUBTYPE_SLOWKEYS_START); 2388 } 2389 2390 // if another key goes down while in progress, start abort process 2391 else if (((_slowKeys_State & kState_In_Progess_Flag) != 0) && (key != _slowKeys_Current_Key)) { 2392 2393 _slowKeysTimerEventSource->cancelTimeout(); 2394 2395 _slowKeys_State |= kState_Aborted_Flag; 2396 _slowKeys_State &= ~kState_In_Progess_Flag; 2397 2398 _slowKeys_Aborted_Key = key; 2399 2400 // If the slow key is being repeated, send a key up 2401 // for that key and clear the flag 2402 if ((_slowKeys_State & kState_Is_Repeat_Flag) != 0) { 2403 2404 postSlowKeyTranslateKeyCode(this, _slowKeys_Current_Key, false, _cached_KeyBits); 2405 2406 _slowKeys_State &= ~kState_Is_Repeat_Flag; 2407 } 2408 2409 // Notify System that this is an abort 2410 postKeyboardSpecialEvent(NX_SUBTYPE_SLOWKEYS_ABORT); 2411 } 2412 } 2413 2414 // handing for a key up 2415 else { 2416 2417 if (key == _slowKeys_Current_Key) { 2418 2419 // If the current key come up while in progress, kill it 2420 if ((_slowKeys_State & kState_In_Progess_Flag) != 0) { 2421 2422 _slowKeysTimerEventSource->cancelTimeout(); 2423 _slowKeys_State &= ~kState_In_Progess_Flag; 2424 2425 // If the key is being repeated, pass the key up through 2426 // and clear the flag 2427 if ((_slowKeys_State & kState_Is_Repeat_Flag) != 0) { 2428 2429 _slowKeys_State &= ~kState_Is_Repeat_Flag; 2430 2431 returnValue = false; 2432 } 2433 } 2434 2435 // Otherwise, if the key was not aborted, pass the key up through 2436 else if ((_slowKeys_State & kState_Aborted_Flag) == 0) { 2437 2438 // Clear the flag if this was a repeated key 2439 if ((_slowKeys_State & kState_Is_Repeat_Flag) != 0) 2440 _slowKeys_State &= ~kState_Is_Repeat_Flag; 2441 2442 returnValue = false; 2443 } 2444 } 2445 2446 // If the key that caused an abort comes up, it will kill any current slowkeys action 2447 else if ((key == _slowKeys_Aborted_Key) && ((_slowKeys_State & kState_Aborted_Flag) != 0)){ 2448 2449 _slowKeysTimerEventSource->cancelTimeout(); 2450 2451 _slowKeys_State &= ~kState_Aborted_Flag; 2452 _slowKeys_State &= ~kState_In_Progess_Flag; 2453 2454 // If the slow key is being repeated, send a key up for the slow key 2455 // and clear the flag 2456 if ((_slowKeys_State & kState_Is_Repeat_Flag) != 0) { 2457 2458 postSlowKeyTranslateKeyCode(this, _slowKeys_Current_Key, false, _cached_KeyBits); 2459 2460 _slowKeys_State &= ~kState_Is_Repeat_Flag; 2461 } 2462 2463 // Notify System that this is an abort 2464 postKeyboardSpecialEvent(NX_SUBTYPE_SLOWKEYS_ABORT); 2465 } 2466 2467 // This key has already been processed/ Pass the key up through 2468 else { 2469 2470 returnValue = false; 2471 } 2472 } 2473 2474 return returnValue; 2475} 2476 2477// slowKeysPostProcess 2478 2479// This is a IOTimerEventSource::Action. 2480// It is responsible for sending a key down 2481// to the HID System. 2482 2483void IOHIKeyboardMapper::slowKeysPostProcess (IOHIKeyboardMapper *owner, IOTimerEventSource *sender __unused) 2484{ 2485 owner->_slowKeys_State &= ~kState_In_Progess_Flag; 2486 2487 // Post the key down 2488 postSlowKeyTranslateKeyCode(owner, owner->_slowKeys_Current_Key, true, owner->_cached_KeyBits); 2489 2490 // Notify System that this is the end 2491 owner->postKeyboardSpecialEvent(NX_SUBTYPE_SLOWKEYS_END); 2492} 2493 2494void IOHIKeyboardMapper::stickyKeysSetFnState(IOHIKeyboardMapper *owner, IOEventSource *sender __unused) 2495{ 2496 OSDictionary *dict; 2497 2498 if ((owner->_stickyKeys_State & kState_On) != 0) 2499 { 2500 dict = (((owner->_stickyKeys_State & kState_PrefFnKeyStateOn) != 0) ^ ((owner->_stickyKeys_State & kState_StickyFnKeyStateOn) != 0)) ? 2501 owner->_onFnParamDict : owner->_offFnParamDict; 2502 } 2503 else 2504 { 2505 dict = ((owner->_stickyKeys_State & kState_PrefFnKeyStateOn) != 0) ? owner->_onFnParamDict : owner->_offFnParamDict; 2506 } 2507 2508 owner->_hidSystem->setParamProperties (dict); 2509} 2510 2511void IOHIKeyboardMapper::stickyKeysMouseUp(IOHIKeyboardMapper *owner, IOEventSource *sender __unused) 2512{ 2513 owner->stickyKeysFilterKey (0, 0, owner->_cached_KeyBits, true); 2514} 2515 2516OSMetaClassDefineReservedUsed(IOHIKeyboardMapper, 0); 2517IOReturn IOHIKeyboardMapper::message( UInt32 type, IOService * provider __unused, void * argument __unused ) 2518{ 2519 2520 switch (type) 2521 { 2522 case kIOHIDSystem508MouseClickMessage: 2523 case kIOHIDSystem508SpecialKeyDownMessage: 2524 2525 // Since we most likely running via IOHIDSystem::cmdGate runAction, 2526 // we should really trigger an interrupt to run this later on the 2527 // workloop. This will also avoid any synchronization anomolies. 2528 if (_stickyKeysMouseClickEventSource) 2529 _stickyKeysMouseClickEventSource->interruptOccurred(0, 0, 0); 2530 2531 break; 2532 2533 default: 2534 break; 2535 } 2536 return kIOReturnSuccess; 2537} 2538OSMetaClassDefineReservedUnused(IOHIKeyboardMapper, 1); 2539OSMetaClassDefineReservedUnused(IOHIKeyboardMapper, 2); 2540OSMetaClassDefineReservedUnused(IOHIKeyboardMapper, 3); 2541OSMetaClassDefineReservedUnused(IOHIKeyboardMapper, 4); 2542OSMetaClassDefineReservedUnused(IOHIKeyboardMapper, 5); 2543OSMetaClassDefineReservedUnused(IOHIKeyboardMapper, 6); 2544OSMetaClassDefineReservedUnused(IOHIKeyboardMapper, 7); 2545OSMetaClassDefineReservedUnused(IOHIKeyboardMapper, 8); 2546OSMetaClassDefineReservedUnused(IOHIKeyboardMapper, 9); 2547OSMetaClassDefineReservedUnused(IOHIKeyboardMapper, 10); 2548OSMetaClassDefineReservedUnused(IOHIKeyboardMapper, 11); 2549OSMetaClassDefineReservedUnused(IOHIKeyboardMapper, 12); 2550OSMetaClassDefineReservedUnused(IOHIKeyboardMapper, 13); 2551OSMetaClassDefineReservedUnused(IOHIKeyboardMapper, 14); 2552OSMetaClassDefineReservedUnused(IOHIKeyboardMapper, 15); 2553