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