IOHIKeyboardMapper.cpp [plain text]
#include <sys/systm.h>
#include <IOKit/assert.h>
#include <IOKit/IOLib.h>
#include <IOKit/IODeviceTreeSupport.h>
#include <IOKit/hidsystem/IOLLEvent.h>
#include <IOKit/hidsystem/IOHIKeyboard.h>
#include <IOKit/hidsystem/IOHIKeyboardMapper.h>
#include <IOKit/hidsystem/IOHIDParameter.h>
#include <IOKit/hidsystem/IOHIDSystem.h>
#include <libkern/OSByteOrder.h>
#include "IOHIDKeyboardDevice.h"
#include "IOHIDevicePrivateKeys.h"
#include "IOHIDFamilyPrivate.h"
#define _f12Eject_State _reserved->f12Eject_State
#define _eject_Delay_MS _reserved->eject_Delay_MS
#define _ejectTimerEventSource _reserved->ejectTimerEventSource
#define _cached_KeyBits _reserved->cached_KeyBits
#define _stickyKeys_StuckModifiers _reserved->stickyKeys_StuckModifiers
#define _stickyKeysMouseClickEventSource _reserved->stickyKeysMouseClickEventSource
#define _stickyKeysSetFnStateEventSource _reserved->stickyKeysSetFnStateEventSource
#define _offFnParamDict _reserved->offFnParamDict
#define _onFnParamDict _reserved->onFnParamDict
#define _slowKeys_State _reserved->slowKeys_State
#define _slowKeys_Delay_MS _reserved->slowKeys_Delay_MS
#define _slowKeysTimerEventSource _reserved->slowKeysTimerEventSource
#define _slowKeys_Aborted_Key _reserved->slowKeys_Aborted_Key
#define _slowKeys_Current_Key _reserved->slowKeys_Current_Key
#define _specialKeyModifierFlags _reserved->specialKeyModifierFlags
#define _supportsF12Eject _reserved->supportsF12Eject
#define _modifierSwap_Modifiers _reserved->modifierSwap_Modifiers
#define _cachedAlphaLockModDefs _reserved->cachedAlphaLockModDefs
#define super OSObject
OSDefineMetaClassAndStructors(IOHIKeyboardMapper, OSObject);
enum
{
kState_OptionActivates_Flag = 0x0010, kState_ClearHeldKeysFirst = 0x0100,
kState_PrefFnKeyStateOn = 0x0200,
kState_StickyFnKeyStateOn = 0x0400,
kState_MouseKeyStateOn = 0x0800,
kState_StickyFnKeyStateChangePending = 0x1000,
};
enum
{
kState_Aborted_Flag = 0x0200,
kState_In_Progess_Flag = 0x0400,
kState_Is_Repeat_Flag = 0x0800,
};
#define kADB_KEYBOARD_F12 0x6f
#define postSlowKeyTranslateKeyCode(owner,key,keyDown,keyBits) \
if (!owner->f12EjectFilterKey(key, keyDown, keyBits)) \
if (!owner->stickyKeysFilterKey(key, keyDown, keyBits)) \
owner->rawTranslateKeyCode(key, keyDown, keyBits);
#define modifierOfInterest(keyBits) \
((keyBits & NX_MODMASK) && \
((((keyBits & NX_WHICHMODMASK) >= NX_MODIFIERKEY_SHIFT) && \
((keyBits & NX_WHICHMODMASK) <= NX_MODIFIERKEY_COMMAND)) || \
(((keyBits & NX_WHICHMODMASK) >= NX_MODIFIERKEY_RSHIFT) && \
((keyBits & NX_WHICHMODMASK) <= NX_MODIFIERKEY_LAST_KEY)) || \
((keyBits & NX_WHICHMODMASK) == NX_MODIFIERKEY_SECONDARYFN)))
#define mouseKey(keyBits) \
((keyBits & NX_MODMASK) && \
((keyBits & NX_WHICHMODMASK) == NX_MODIFIERKEY_NUMERICPAD))
#define mouseKeyToIgnore(keyBits, key) \
( mouseKey(keyBits) && \
(((key >= 0x52) && (key <= 0x56)) || \
((key >= 0x58) && (key <= 0x5c))) )
#define convertToLeftModBit(modBit) \
modBit -= ((modBit >= NX_MODIFIERKEY_RSHIFT) && \
(modBit <= NX_MODIFIERKEY_LAST_KEY)) ? 8 : 0;
static UInt32 DeviceModifierMasks[NX_NUMMODIFIERS] =
{
0,
NX_DEVICELSHIFTKEYMASK,
NX_DEVICELCTLKEYMASK,
NX_DEVICELALTKEYMASK,
NX_DEVICELCMDKEYMASK,
0,
0,
0,
0,
NX_DEVICERSHIFTKEYMASK,
NX_DEVICERCTLKEYMASK,
NX_DEVICERALTKEYMASK,
NX_DEVICERCMDKEYMASK,
NX_DEVICE_ALPHASHIFT_STATELESS_MASK,
0,
0
};
IOHIKeyboardMapper * IOHIKeyboardMapper::keyboardMapper(
IOHIKeyboard * delegate,
const UInt8 * mapping,
UInt32 mappingLength,
bool mappingShouldBeFreed )
{
IOHIKeyboardMapper * me = new IOHIKeyboardMapper;
if (!me && mappingShouldBeFreed && mapping)
IOFree( (void*)mapping, mappingLength );
if (me && !me->init(delegate, mapping, mappingLength, mappingShouldBeFreed))
{
me->release();
return 0;
}
return me;
}
bool IOHIKeyboardMapper::init( IOHIKeyboard *delegate,
const UInt8 *map,
UInt32 mappingLen,
bool mappingShouldBeFreed )
{
_mappingShouldBeFreed = mappingShouldBeFreed;
_parsedMapping.mapping = map;
_parsedMapping.mappingLen = mappingLen;
if (!super::init()) return false;
_delegate = delegate;
if (!parseKeyMapping(map, mappingLen, &_parsedMapping)) return false;
_hidSystem = NULL;
_stateDirty = false;
_reserved = IONew(ExpansionData, 1);
bzero(_reserved, sizeof(ExpansionData));
_ejectTimerEventSource = 0;
_f12Eject_State = 0;
_eject_Delay_MS = kEjectF12DelayMS;
_slowKeys_State = 0;
_slowKeys_Delay_MS = 0;
_slowKeysTimerEventSource = 0;
_specialKeyModifierFlags = 0;
_supportsF12Eject = 0;
_cached_KeyBits = 0;
_cachedAlphaLockModDefs = 0;
if (_delegate && (_parsedMapping.maxMod > 0))
{
if ( _delegate->doesKeyLock(NX_KEYTYPE_CAPS_LOCK) )
{
_delegate->setProperty( kIOHIDKeyboardCapsLockDoesLockKey, kOSBooleanTrue);
_cachedAlphaLockModDefs = _parsedMapping.modDefs[NX_MODIFIERKEY_ALPHALOCK];
}
else
{
_delegate->setProperty( kIOHIDKeyboardCapsLockDoesLockKey, kOSBooleanFalse);
}
UInt32 supportedModifiers = 0;
OSNumber * number = 0;
number = (OSNumber *)_delegate->copyProperty(kIOHIDKeyboardSupportedModifiersKey);
if (number) supportedModifiers = number->unsigned32BitValue();
OSSafeReleaseNULL(number);
for (int mod=0; mod<NX_NUMMODIFIERS; mod++)
{
if (_parsedMapping.modDefs[mod])
{
if (DeviceModifierMasks[mod])
supportedModifiers |= DeviceModifierMasks[mod];
else
supportedModifiers |= 1<<(mod+16);
}
_modifierSwap_Modifiers[mod] = mod;
}
_delegate->setProperty( kIOHIDKeyboardSupportedModifiersKey, supportedModifiers, 32 );
if ( (supportedModifiers & NX_DEVICERSHIFTKEYMASK) ||
(supportedModifiers & NX_DEVICERCTLKEYMASK) ||
(supportedModifiers & NX_DEVICERALTKEYMASK) ||
(supportedModifiers & NX_DEVICERCMDKEYMASK) )
{
_delegate->setProperty("HIDKeyboardRightModifierSupport", kOSBooleanTrue);
}
}
if (_parsedMapping.numDefs && _delegate)
{
_delegate->setProperty("HIDKeyboardKeysDefined", kOSBooleanTrue);
if ((_delegate->interfaceID() == NX_EVS_DEVICE_INTERFACE_ADB) &&
(((_delegate->deviceType() >= 0xc3) && (_delegate->deviceType() <= 0xc9)) ||
((_delegate->deviceType() >= 0x28) && (_delegate->deviceType() <= 0x2a)) ||
( (_delegate->deviceType() <= 0x1e))))
{
_supportsF12Eject = true;
_delegate->setProperty( kIOHIDKeyboardSupportsF12EjectKey,
_supportsF12Eject);
}
}
if ( !_delegate->doesKeyLock(NX_KEYTYPE_CAPS_LOCK) )
{
UInt32 myFlags = _delegate->deviceFlags();
if ( _delegate->alphaLock() )
{
_specialKeyModifierFlags |= NX_ALPHASHIFTMASK;
myFlags |= NX_ALPHASHIFTMASK;
_delegate->IOHIKeyboard::setDeviceFlags(myFlags);
}
else
{
_specialKeyModifierFlags &= ~NX_ALPHASHIFTMASK;
myFlags &= ~NX_ALPHASHIFTMASK;
_delegate->IOHIKeyboard::setDeviceFlags(myFlags);
}
}
return stickyKeysinit();
}
void IOHIKeyboardMapper::free()
{
if (!_parsedMapping.mapping || !_parsedMapping.mappingLen)
return;
stickyKeysfree();
if (_reserved) {
if (_ejectTimerEventSource) {
_ejectTimerEventSource->cancelTimeout();
IOWorkLoop * workLoop = _hidSystem->getWorkLoop();
if ( workLoop )
workLoop->removeEventSource( _ejectTimerEventSource );
_ejectTimerEventSource->release();
_ejectTimerEventSource = 0;
}
if (_slowKeysTimerEventSource) {
_slowKeysTimerEventSource->cancelTimeout();
IOWorkLoop * workLoop = _hidSystem->getWorkLoop();
if ( workLoop )
workLoop->removeEventSource( _slowKeysTimerEventSource );
_slowKeysTimerEventSource->release();
_slowKeysTimerEventSource = 0;
}
IODelete(_reserved, ExpansionData, 1);
}
if (_mappingShouldBeFreed)
IOFree((void *)_parsedMapping.mapping, _parsedMapping.mappingLen);
super::free();
}
const UInt8 * IOHIKeyboardMapper::mapping()
{
return (const UInt8 *)_parsedMapping.mapping;
}
UInt32 IOHIKeyboardMapper::mappingLength()
{
return _parsedMapping.mappingLen;
}
bool IOHIKeyboardMapper::serialize(OSSerialize *s) const
{
OSData * data;
bool ok;
if (s->previouslySerialized(this)) return true;
data = OSData::withBytesNoCopy( (void *) _parsedMapping.mapping, _parsedMapping.mappingLen );
if (data) {
ok = data->serialize(s);
data->release();
} else
ok = false;
return( ok );
}
void IOHIKeyboardMapper::translateKeyCode(UInt8 key,
bool keyDown,
kbdBitVector keyBits)
{
if ( !_cached_KeyBits )
_cached_KeyBits = keyBits;
if (!modifierSwapFilterKey(&key))
if (!slowKeysFilterKey(key, keyDown, keyBits))
if (!f12EjectFilterKey(key, keyDown, keyBits))
if (!stickyKeysFilterKey(key, keyDown, keyBits))
rawTranslateKeyCode(key, keyDown, keyBits);
}
void IOHIKeyboardMapper::rawTranslateKeyCode(UInt8 key,
bool keyDown,
kbdBitVector keyBits)
{
unsigned char thisBits = _parsedMapping.keyBits[key];
if (keyDown)
{
EVK_KEYDOWN(key, keyBits);
if (thisBits & NX_MODMASK) doModCalc(key, keyBits);
if (thisBits & NX_CHARGENMASK) doCharGen(key, keyDown);
}
else
{
EVK_KEYUP(key, keyBits);
if (thisBits & NX_CHARGENMASK) doCharGen(key, keyDown);
if (thisBits & NX_MODMASK) doModCalc(key, keyBits);
}
if( 0 == (thisBits & (NX_MODMASK | NX_CHARGENMASK)))
if (_delegate->interfaceID() == NX_EVS_DEVICE_INTERFACE_ADB)
{
unsigned charCode=0;
switch (key) {
case 0x5F: charCode = ',';
break;
case 0x5E: charCode = '_';
break;
case 0x5d: charCode = '\\';
break;
case 0x0a:
charCode = 0xa7;
break;
case 0x66: case 0x68: default:
break;
}
_delegate->keyboardEvent(keyDown ? NX_KEYDOWN : NX_KEYUP,
_delegate->eventFlags(),
key,
charCode,
0, 0,
0);
}
#ifdef OMITPENDINGKEYCAPS
unsigned char * bp;
if (key == _parsedMapping.specialKeys[NX_KEYTYPE_CAPS_LOCK]) {
if (_delegate->alphaLock() == keyDown)
{
_delegate->keyboardEvent(keyDown ? NX_KEYDOWN : NX_KEYUP,
_delegate->eventFlags(), key, 0, 0, 0, 0);
}
}
bp = _parsedMapping.modDefs[NX_MODIFIERKEY_SECONDARYFN]; if (bp)
{
bp++; if (key == *bp ) {
_delegate->keyboardEvent(keyDown ? NX_KEYDOWN : NX_KEYUP,
_delegate->eventFlags(), key, 0, 0, 0, 0);
}
}
#endif
}
typedef struct {
unsigned const char *bp;
unsigned const char *endPtr;
int shorts;
} NewMappingData;
static inline unsigned int NextNum(NewMappingData *nmd)
{
if (nmd->bp >= nmd->endPtr)
return(0);
if (nmd->shorts) {
unsigned short tmp = *((unsigned short *)nmd->bp);
nmd->bp += 2;
return OSSwapBigToHostInt16(tmp);
}
else {
unsigned char tmp = *(nmd->bp);
nmd->bp++;
return tmp;
}
}
bool IOHIKeyboardMapper::parseKeyMapping(const UInt8 * map,
UInt32 mappingLen,
NXParsedKeyMapping * parsedMapping) const
{
NewMappingData nmd;
int i, j, k, l, n;
unsigned int m;
int keyMask, numMods;
int maxSeqNum = -1;
unsigned char * bp;
bzero( parsedMapping, sizeof (NXParsedKeyMapping) );
parsedMapping->maxMod = -1;
parsedMapping->numDefs = -1;
parsedMapping->numSeqs = -1;
if (!map || !mappingLen)
return false;
nmd.endPtr = map + mappingLen;
nmd.bp = map;
nmd.shorts = 1;
parsedMapping->mapping = (unsigned char *)map;
parsedMapping->mappingLen = mappingLen;
parsedMapping->shorts = nmd.shorts = NextNum(&nmd);
numMods = NextNum(&nmd);
for(i=0; i<numMods; i++)
{
if ((j = NextNum(&nmd)) >= NX_NUMMODIFIERS)
return false;
if (j > parsedMapping->maxMod)
parsedMapping->maxMod = j;
parsedMapping->modDefs[j] = (unsigned char *)nmd.bp;
for(k=0,n = NextNum(&nmd);k<n;k++)
{
if ((l = NextNum(&nmd)) >= NX_NUMKEYCODES)
return false;
if (parsedMapping->keyBits[l] & NX_MODMASK)
return false;
if ((j != NX_MODIFIERKEY_ALPHALOCK) || (_delegate->doesKeyLock(NX_KEYTYPE_CAPS_LOCK)) )
{
parsedMapping->keyBits[l] |=NX_MODMASK | (j & NX_WHICHMODMASK);
}
}
}
if (!_delegate->doesKeyLock(NX_KEYTYPE_CAPS_LOCK))
parsedMapping->modDefs[NX_MODIFIERKEY_ALPHALOCK] = 0;
if (_delegate->interfaceID() == NX_EVS_DEVICE_INTERFACE_ADB)
{
parsedMapping->keyBits[0x3f] |=NX_MODMASK | (NX_MODIFIERKEY_SECONDARYFN & NX_WHICHMODMASK);
}
parsedMapping->numDefs = NextNum(&nmd);
n = parsedMapping->numDefs;
for( i=0; i < NX_NUMKEYCODES; i++)
{
if (i < n)
{
parsedMapping->keyDefs[i] = (unsigned char *)nmd.bp;
if ((keyMask = NextNum(&nmd)) != (nmd.shorts ? 0xFFFF: 0x00FF))
{
parsedMapping->keyBits[i] |= NX_CHARGENMASK;
for(j=0, k=1; j<=parsedMapping->maxMod; j++, keyMask>>=1)
{
if (keyMask & 0x01)
k*= 2;
}
for(j=0; j<k; j++)
{
m = NextNum(&nmd);
l = NextNum(&nmd);
if (m == (unsigned)(nmd.shorts ? 0xFFFF: 0x00FF))
if (((int)l) > maxSeqNum)
maxSeqNum = l;
}
}
else
parsedMapping->keyDefs[i] = NULL;
}
else
{
parsedMapping->keyDefs[i] = NULL;
}
}
parsedMapping->numSeqs = NextNum(&nmd);
if (parsedMapping->numSeqs <= maxSeqNum)
return false;
if (parsedMapping->numSeqs > NX_NUMSEQUENCES)
return false;
for(i = 0; i < parsedMapping->numSeqs; i++)
{
parsedMapping->seqDefs[i] = (unsigned char *)nmd.bp;
for(j=0, l=NextNum(&nmd); j<l; j++)
{
NextNum(&nmd);
NextNum(&nmd);
}
}
numMods = NextNum(&nmd);
parsedMapping->numSpecialKeys = numMods;
if ( numMods > NX_NUMSPECIALKEYS )
return false;
if ( numMods )
{
for ( i = 0; i < NX_NUMSPECIALKEYS; ++i )
parsedMapping->specialKeys[i] = NX_NOSPECIALKEY;
if (_delegate->interfaceID() == NX_EVS_DEVICE_INTERFACE_ADB)
{
parsedMapping->specialKeys[NX_KEYTYPE_CAPS_LOCK] = 0x39;
parsedMapping->specialKeys[NX_KEYTYPE_NUM_LOCK] = 0x47;
parsedMapping->keyDefs[0x72] = parsedMapping->keyDefs[0x47];
}
for ( i = 0; i < numMods; ++i )
{
j = NextNum(&nmd);
l = NextNum(&nmd);
if ( j >= NX_NUMSPECIALKEYS )
return false;
parsedMapping->specialKeys[j] = l;
}
}
else
{
return false;
}
for(i=0; i<NX_NUM_SCANNED_SPECIALKEYS; i++)
{
if ( parsedMapping->specialKeys[i] != NX_NOSPECIALKEY )
{
if (parsedMapping->specialKeys[i] < NX_NUMKEYCODES)
parsedMapping->keyBits[parsedMapping->specialKeys[i]] |= (NX_CHARGENMASK | NX_SPECIALKEYMASK);
}
}
if (_delegate->doesKeyLock(NX_KEYTYPE_CAPS_LOCK))
{
if (parsedMapping->specialKeys[NX_KEYTYPE_CAPS_LOCK] < NX_NUMKEYCODES)
parsedMapping->keyBits[ parsedMapping->specialKeys[NX_KEYTYPE_CAPS_LOCK] ] &= ~NX_CHARGENMASK;
}
bp = _parsedMapping.modDefs[NX_MODIFIERKEY_SECONDARYFN]; if (bp)
{
bp++; parsedMapping->keyBits[ *bp ] &= ~NX_CHARGENMASK;
}
if (parsedMapping->specialKeys[NX_MODIFIERKEY_ALPHALOCK_STATELESS] == NX_NOSPECIALKEY) {
unsigned char key = NX_NUMKEYCODES - 1;
parsedMapping->specialKeys[NX_MODIFIERKEY_ALPHALOCK_STATELESS] = key;
parsedMapping->modDefs[NX_MODIFIERKEY_ALPHALOCK_STATELESS] = 0;
parsedMapping->keyBits[key] = NX_MODIFIERKEY_ALPHALOCK_STATELESS | NX_MODMASK;
}
else {
}
return true;
}
UInt8 IOHIKeyboardMapper::getParsedSpecialKey(UInt8 logical)
{
UInt8 retval;
if ( logical < NX_NUMSPECIALKEYS)
retval = _parsedMapping.specialKeys[logical];
else
retval = 0xff; return retval;
}
static inline int NEXTNUM(unsigned char ** mapping, short shorts)
{
int returnValue;
if (shorts)
{
returnValue = OSSwapBigToHostInt16(*((unsigned short *)*mapping));
*mapping += sizeof(unsigned short);
}
else
{
returnValue = **((unsigned char **)mapping);
*mapping += sizeof(unsigned char);
}
return returnValue;
}
bool IOHIKeyboardMapper::modifierSwapFilterKey(UInt8 * key)
{
unsigned char thisBits = _parsedMapping.keyBits[*key];
SInt16 modBit = (thisBits & NX_WHICHMODMASK);
SInt16 swapBit;
unsigned char *map;
if (!(thisBits & NX_MODMASK))
{
if (*key == getParsedSpecialKey(NX_KEYTYPE_CAPS_LOCK)) {
modBit = NX_MODIFIERKEY_ALPHALOCK;
}
else {
return false;
}
}
if (modBit > NX_MODIFIERKEY_LAST_KEY) {
return false;
}
swapBit = _modifierSwap_Modifiers[modBit];
if (swapBit == modBit)
{
if (_delegate->doesKeyLock(NX_KEYTYPE_CAPS_LOCK) && (swapBit == NX_MODIFIERKEY_ALPHALOCK))
{
if (_parsedMapping.specialKeys[NX_KEYTYPE_CAPS_LOCK] < NX_NUMKEYCODES)
_parsedMapping.keyBits[ _parsedMapping.specialKeys[NX_KEYTYPE_CAPS_LOCK] ] &= ~NX_CHARGENMASK;
_parsedMapping.modDefs[NX_MODIFIERKEY_ALPHALOCK] = _cachedAlphaLockModDefs;
_specialKeyModifierFlags &= ~NX_ALPHASHIFTMASK;
}
return false;
}
else if (swapBit == -1)
{
return true;
}
if (_delegate->doesKeyLock(NX_KEYTYPE_CAPS_LOCK) && (swapBit == NX_MODIFIERKEY_ALPHALOCK))
{
if (_parsedMapping.specialKeys[NX_KEYTYPE_CAPS_LOCK] < NX_NUMKEYCODES)
_parsedMapping.keyBits[ _parsedMapping.specialKeys[NX_KEYTYPE_CAPS_LOCK] ] |= NX_CHARGENMASK;
_parsedMapping.modDefs[NX_MODIFIERKEY_ALPHALOCK] = 0;
}
if (((map = _parsedMapping.modDefs[swapBit]) != 0 ) && ( NEXTNUM(&map, _parsedMapping.shorts) )) {
*key = NEXTNUM(&map, _parsedMapping.shorts);
}
else if (swapBit == NX_MODIFIERKEY_ALPHALOCK) {
*key = getParsedSpecialKey(NX_KEYTYPE_CAPS_LOCK);
}
else if (swapBit == NX_MODIFIERKEY_ALPHALOCK_STATELESS) {
*key = getParsedSpecialKey(NX_MODIFIERKEY_ALPHALOCK_STATELESS);
}
return false;
}
static inline int IsModifierDown(NXParsedKeyMapping *parsedMapping,
kbdBitVector keyBits,
int bit )
{
int i, n;
unsigned char *mapping;
unsigned key;
short shorts = parsedMapping->shorts;
if ( (mapping = parsedMapping->modDefs[bit]) != 0 ) {
for(i=0, n=NEXTNUM(&mapping, shorts); i<n; i++)
{
key = NEXTNUM(&mapping, shorts);
if ( EVK_IS_KEYDOWN(key, keyBits) )
return 1;
}
}
return 0;
}
void IOHIKeyboardMapper::calcModBit(int bit, kbdBitVector keyBits)
{
int otherHandBit = 0;
int deviceBitMask = 0;
int systemBitMask = 0;
unsigned myFlags = 0;
systemBitMask = 1<<(bit+16);
deviceBitMask = DeviceModifierMasks[bit];
if ((bit >= NX_MODIFIERKEY_RSHIFT) && (bit <= NX_MODIFIERKEY_RCOMMAND))
{
otherHandBit = bit - 8;
systemBitMask = 1<<(otherHandBit+16);
}
else if ((bit >= NX_MODIFIERKEY_SHIFT) && (bit <= NX_MODIFIERKEY_COMMAND))
{
otherHandBit = bit + 8;
}
myFlags = _delegate->deviceFlags() & (~systemBitMask);
myFlags &= ~deviceBitMask;
if ( IsModifierDown( &_parsedMapping, keyBits, bit ))
{
myFlags |= (systemBitMask | deviceBitMask);
}
else if (deviceBitMask &&
IsModifierDown( &_parsedMapping, keyBits, otherHandBit ))
{
myFlags |= (systemBitMask);
}
myFlags |= _specialKeyModifierFlags;
if ( bit == NX_MODIFIERKEY_ALPHALOCK ) {
_delegate->setAlphaLock((myFlags & NX_ALPHASHIFTMASK) ? true : false);
}
else if ( bit == NX_MODIFIERKEY_NUMLOCK ) {
_delegate->setNumLock((myFlags & NX_NUMERICPADMASK) ? true : false);
}
_delegate->setDeviceFlags(myFlags);
}
void IOHIKeyboardMapper::doModCalc(int key, kbdBitVector keyBits)
{
int thisBits;
thisBits = _parsedMapping.keyBits[key];
if (thisBits & NX_MODMASK)
{
calcModBit((thisBits & NX_WHICHMODMASK), keyBits);
if (!(thisBits & NX_CHARGENMASK))
{
_delegate->keyboardEvent(NX_FLAGSCHANGED,
_delegate->eventFlags(),
key,
0,
0,
0,
0);
#ifdef NEW_HID
_delegate->keyboardEvent(EVK_IS_KEYDOWN(key, keyBits) ? NX_KEYDOWN : NX_KEYUP,
_delegate->eventFlags(),
key,
0,
0,
0,
0);
#endif
}
else
_delegate->updateEventFlags(_delegate->eventFlags());
}
}
void IOHIKeyboardMapper::doCharGen(int keyCode, bool down)
{
int i, n, eventType, adjust, thisMask, modifiers, saveModifiers;
short shorts;
unsigned charSet, origCharSet;
unsigned charCode, origCharCode;
unsigned char *map;
unsigned eventFlags, origflags;
_delegate->setCharKeyActive(true);
eventType = (down == true) ? NX_KEYDOWN : NX_KEYUP;
eventFlags = _delegate->eventFlags();
saveModifiers = eventFlags >> 16;
if( saveModifiers & (NX_SHIFTMASK >> 16))
saveModifiers |= (NX_ALPHASHIFTMASK >> 16);
shorts = _parsedMapping.shorts;
map = _parsedMapping.keyDefs[keyCode];
modifiers = saveModifiers;
if ( map ) {
thisMask = NEXTNUM(&map, shorts);
if (thisMask && modifiers) {
adjust = (shorts ? sizeof(short) : sizeof(char))*2;
for ( i = 0; i <= _parsedMapping.maxMod; ++i) {
if (thisMask & 0x01) {
if (modifiers & 0x01)
map += adjust;
adjust *= 2;
}
thisMask >>= 1;
modifiers >>= 1;
}
}
charSet = NEXTNUM(&map, shorts);
charCode = NEXTNUM(&map, shorts);
map = _parsedMapping.keyDefs[keyCode];
modifiers = saveModifiers & ((NX_ALPHASHIFTMASK | NX_SHIFTMASK) >> 16);
thisMask = NEXTNUM(&map, shorts);
if (thisMask && modifiers) {
adjust = (shorts ? sizeof(short) : sizeof(char)) * 2;
for ( i = 0; i <= _parsedMapping.maxMod; ++i) {
if (thisMask & 0x01) {
if (modifiers & 0x01)
map += adjust;
adjust *= 2;
}
thisMask >>= 1;
modifiers >>= 1;
}
}
origCharSet = NEXTNUM(&map, shorts);
origCharCode = NEXTNUM(&map, shorts);
if (charSet == (unsigned)(shorts ? 0xFFFF : 0x00FF)) {
map = _parsedMapping.seqDefs[charCode];
origflags = eventFlags;
for (i=0,n=NEXTNUM(&map, shorts);i<n;i++) {
if ( (charSet = NEXTNUM(&map, shorts)) == 0xFF ) {
if ( down == true ) {
eventFlags |= (1 << (NEXTNUM(&map, shorts) + 16));
_delegate->keyboardEvent(NX_FLAGSCHANGED,
_delegate->deviceFlags(),
keyCode,
0,
0,
0,
0);
}
else
NEXTNUM(&map, shorts);
}
else {
charCode = NEXTNUM(&map, shorts);
_delegate->keyboardEvent(eventType,
eventFlags,
keyCode,
charCode,
charSet,
charCode,
charSet);
}
}
if ( eventFlags != origflags ) {
_delegate->keyboardEvent(NX_FLAGSCHANGED,
_delegate->deviceFlags(),
keyCode,
0,
0,
0,
0);
eventFlags = origflags;
}
}
else {
_delegate->keyboardEvent(eventType,
eventFlags,
keyCode,
charCode,
charSet,
origCharCode,
origCharSet);
}
}
if (_parsedMapping.keyBits[keyCode] & NX_SPECIALKEYMASK) {
for (i=0; i<NX_NUM_SCANNED_SPECIALKEYS; i++) {
if ( keyCode == _parsedMapping.specialKeys[i] ) {
_delegate->keyboardSpecialEvent(eventType,
eventFlags,
keyCode,
i);
if (i == NX_KEYTYPE_CAPS_LOCK
&& down == true
&& !_parsedMapping.modDefs[NX_MODIFIERKEY_ALPHALOCK] ) {
unsigned myFlags = _delegate->deviceFlags();
bool alphaLock = (_delegate->alphaLock() == false);
_delegate->setAlphaLock(alphaLock);
if ( alphaLock ) {
myFlags |= NX_ALPHASHIFTMASK;
_specialKeyModifierFlags |= NX_ALPHASHIFTMASK;
}
else {
myFlags &= ~NX_ALPHASHIFTMASK;
_specialKeyModifierFlags &= ~NX_ALPHASHIFTMASK;
}
_delegate->setDeviceFlags(myFlags);
_delegate->keyboardEvent(NX_FLAGSCHANGED,
myFlags,
keyCode,
0,
0,
0,
0);
#ifdef NEW_HID
_delegate->keyboardEvent(alphaLock ? NX_KEYDOWN : NX_KEYUP,
myFlags,
keyCode,
0,
0,
0,
0);
#endif
}
else if (i == NX_KEYTYPE_NUM_LOCK
&& down == true
&& (_delegate->doesKeyLock(NX_KEYTYPE_NUM_LOCK) || _delegate->metaCast("AppleADBButtons"))
&& !_parsedMapping.modDefs[NX_MODIFIERKEY_NUMLOCK] ) {
unsigned myFlags = _delegate->deviceFlags();
bool numLock = (_delegate->numLock() == false);
_delegate->setNumLock(numLock);
if ( numLock ) {
myFlags |= NX_NUMERICPADMASK;
_specialKeyModifierFlags |= NX_NUMERICPADMASK;
}
else {
myFlags &= ~NX_NUMERICPADMASK;
_specialKeyModifierFlags &= ~NX_NUMERICPADMASK;
}
_delegate->setDeviceFlags(myFlags);
_delegate->keyboardEvent(NX_FLAGSCHANGED,
myFlags,
keyCode,
0,
0,
0,
0);
}
break;
}
}
}
}
void IOHIKeyboardMapper::setKeyboardTarget (IOService * keyboardTarget)
{
_hidSystem = OSDynamicCast( IOHIDSystem, keyboardTarget );
}
void IOHIKeyboardMapper::makeNumberParamProperty( OSDictionary * dict,
const char * key,
unsigned long long number, unsigned int bits )
{
OSNumber * numberRef;
numberRef = OSNumber::withNumber(number, bits);
if( numberRef) {
dict->setObject( key, numberRef);
numberRef->release();
}
}
bool IOHIKeyboardMapper::updateProperties( void )
{
bool ok = true;
return( ok );
}
IOReturn IOHIKeyboardMapper::setParamProperties( OSDictionary * dict )
{
OSNumber * number = 0;
OSData * data = 0;
OSArray * array = 0;
IOReturn err = kIOReturnSuccess;
bool updated = false;
UInt32 value = 0;
bool issueFlagsChangedEvent = false;
bool alphaState = false;
UInt32 myFlags = _delegate->deviceFlags();
UInt32 ledStatus = 0;
if ((number = OSDynamicCast(OSNumber,
dict->getObject(kIOHIDF12EjectDelayKey))) ||
(data = OSDynamicCast(OSData,
dict->getObject(kIOHIDF12EjectDelayKey))))
{
value = (number) ? number->unsigned32BitValue() : *((UInt32 *) (data->getBytesNoCopy()));
_eject_Delay_MS = value;
updated = true;
}
if ((number = OSDynamicCast(OSNumber,
dict->getObject(kIOHIDMouseKeysOnKey))) ||
(data = OSDynamicCast(OSData,
dict->getObject(kIOHIDMouseKeysOnKey))))
{
value = (number) ? number->unsigned32BitValue() : *((UInt32 *) (data->getBytesNoCopy()));
if (value)
_stickyKeys_State |= kState_MouseKeyStateOn;
else
_stickyKeys_State &= ~kState_MouseKeyStateOn;
updated = true;
}
if ((number = OSDynamicCast(OSNumber,
dict->getObject(kIOHIDSlowKeysDelayKey))) ||
(data = OSDynamicCast(OSData,
dict->getObject(kIOHIDSlowKeysDelayKey))))
{
value = (number) ? number->unsigned32BitValue() : *((UInt32 *) (data->getBytesNoCopy()));
if ((_slowKeys_Delay_MS > 0) && !value &&
((_slowKeys_State & kState_In_Progess_Flag) != 0))
_slowKeysTimerEventSource->cancelTimeout();
_slowKeys_Delay_MS = value;
updated = true;
}
if ((number = OSDynamicCast(OSNumber,
dict->getObject(kIOHIDStickyKeysDisabledKey))) ||
(data = OSDynamicCast(OSData,
dict->getObject(kIOHIDStickyKeysDisabledKey))))
{
value = (number) ? number->unsigned32BitValue() : *((UInt32 *) (data->getBytesNoCopy()));
if (value)
{
_stickyKeys_State |= kState_Disabled_Flag;
stickyKeysCleanup();
}
else
_stickyKeys_State &= ~kState_Disabled_Flag;
updated = true;
}
if ((number = OSDynamicCast(OSNumber,
dict->getObject(kIOHIDStickyKeysOnKey))) ||
(data = OSDynamicCast(OSData,
dict->getObject(kIOHIDStickyKeysOnKey))))
{
value = (number) ? number->unsigned32BitValue() : *((UInt32 *) (data->getBytesNoCopy()));
if (value) {
_stickyKeys_State |= kState_On;
}
else {
stickyKeysCleanup();
}
updated = true;
}
if ((dict->getObject(kIOHIDTemporaryParametersKey) == NULL) &&
((NULL != (number = OSDynamicCast(OSNumber, dict->getObject(kIOHIDFKeyModeKey)))) ||
(NULL != (data = OSDynamicCast(OSData, dict->getObject(kIOHIDFKeyModeKey))))))
{
value = (number) ? number->unsigned32BitValue() : *((UInt32 *) (data->getBytesNoCopy()));
if (value)
_stickyKeys_State |= kState_PrefFnKeyStateOn;
else
_stickyKeys_State &= ~kState_PrefFnKeyStateOn;
updated = true;
}
if ((number = OSDynamicCast(OSNumber,
dict->getObject(kIOHIDStickyKeysShiftTogglesKey))) ||
(data = OSDynamicCast(OSData,
dict->getObject(kIOHIDStickyKeysShiftTogglesKey))))
{
value = (number) ? number->unsigned32BitValue() : *((UInt32 *) (data->getBytesNoCopy()));
if (value)
_stickyKeys_State |= kState_ShiftActivates_Flag;
else
_stickyKeys_State &= ~kState_ShiftActivates_Flag;
updated = true;
}
if ((number = OSDynamicCast(OSNumber,
dict->getObject(kIOHIDMouseKeysOptionTogglesKey))) ||
(data = OSDynamicCast(OSData,
dict->getObject(kIOHIDMouseKeysOptionTogglesKey))))
{
value = (number) ? number->unsigned32BitValue() : *((UInt32 *) (data->getBytesNoCopy()));
if (value)
_stickyKeys_State |= kState_OptionActivates_Flag;
else
_stickyKeys_State &= ~kState_OptionActivates_Flag;
updated = true;
}
if ((array = OSDynamicCast(OSArray, dict->getObject(kIOHIDKeyboardModifierMappingPairsKey))) && (_parsedMapping.maxMod != -1))
{
UInt32 count = array->getCount();
if ( count )
{
for ( unsigned i=0; i<count; i++)
{
OSDictionary * pair = OSDynamicCast(OSDictionary, array->getObject(i));
UInt32 src = 0;
UInt32 dst = 0;
if ( !pair ) continue;
number = OSDynamicCast(OSNumber, pair->getObject(kIOHIDKeyboardModifierMappingSrcKey));
if ( !number ) continue;
src = number->unsigned32BitValue();
number = OSDynamicCast(OSNumber, pair->getObject(kIOHIDKeyboardModifierMappingDstKey));
if ( !number ) continue;
dst = number->unsigned32BitValue();
if ( src == NX_MODIFIERKEY_ALPHALOCK )
{
ledStatus = _delegate->getLEDStatus();
if (dst == NX_MODIFIERKEY_ALPHALOCK)
{
if ((ledStatus & 0x2) && !(myFlags & NX_ALPHASHIFTMASK))
{
issueFlagsChangedEvent = true;
alphaState = true;
}
else if (!(ledStatus & 0x2) && (myFlags & NX_ALPHASHIFTMASK))
{
issueFlagsChangedEvent = true;
alphaState = false;
}
}
else if (_delegate->doesKeyLock(NX_KEYTYPE_CAPS_LOCK) && (dst != -1))
{
continue;
}
else
{
issueFlagsChangedEvent = true;
alphaState = false;
}
}
if ((src >= NX_MODIFIERKEY_ALPHALOCK) &&
(src <= NX_MODIFIERKEY_LAST_KEY) &&
((dst < NX_NUMMODIFIERS) || (dst == (UInt32) -1)) )
_modifierSwap_Modifiers[src] = dst;
}
}
else
{
for (unsigned i=0; i<NX_NUMMODIFIERS; i++)
{
if (((i == NX_MODIFIERKEY_ALPHALOCK) && (_modifierSwap_Modifiers[i] != NX_MODIFIERKEY_ALPHALOCK)) ||
((i != NX_MODIFIERKEY_ALPHALOCK) && (_modifierSwap_Modifiers[i] == NX_MODIFIERKEY_ALPHALOCK)))
{
ledStatus = _delegate->getLEDStatus();
if ((ledStatus & 0x2) && !(myFlags & NX_ALPHASHIFTMASK))
{
issueFlagsChangedEvent = true;
alphaState = true;
}
else if (!(ledStatus & 0x2) && (myFlags & NX_ALPHASHIFTMASK))
{
issueFlagsChangedEvent = true;
alphaState = false;
}
}
_modifierSwap_Modifiers[i] = i;
}
}
}
if ( issueFlagsChangedEvent )
{
if ( alphaState )
{
if ( !_delegate->doesKeyLock(NX_KEYTYPE_CAPS_LOCK) )
{
_specialKeyModifierFlags |= NX_ALPHASHIFTMASK;
}
myFlags |= NX_ALPHASHIFTMASK;
_delegate->setDeviceFlags(myFlags);
_delegate->setAlphaLock(true);
}
else
{
_specialKeyModifierFlags &= ~NX_ALPHASHIFTMASK;
myFlags &= ~NX_ALPHASHIFTMASK;
_delegate->setDeviceFlags(myFlags);
_delegate->setAlphaLock(false);
}
UInt8 keyCode;
unsigned char *map;
if (((map = _parsedMapping.modDefs[NX_MODIFIERKEY_ALPHALOCK]) != 0 ) &&
( NEXTNUM(&map, _parsedMapping.shorts) ))
keyCode = NEXTNUM(&map, _parsedMapping.shorts);
else
keyCode = getParsedSpecialKey(NX_KEYTYPE_CAPS_LOCK);
_delegate->keyboardEvent(NX_FLAGSCHANGED,
myFlags,
keyCode,
0,
0,
0,
0);
#ifdef NEW_HID
_delegate->keyboardEvent(alphaState ? NX_KEYDOWN : NX_KEYUP,
myFlags,
keyCode,
0,
0,
0,
0);
#endif
}
if (updated)
updateProperties();
return( err );
}
bool IOHIKeyboardMapper::stickyKeysinit( void )
{
_stickyKeys_State = 0;
_stickyKeys_NumModifiersDown = 0;
_stickyKeys_ShiftToggle = stickyKeysAllocToggleInfo (kNUM_SHIFTS_TO_ACTIVATE);
if (_stickyKeys_ShiftToggle == NULL)
return false;
_stickyKeys_ShiftToggle->toggleModifier = NX_MODIFIERKEY_SHIFT;
_stickyKeys_ShiftToggle->repetitionsToToggle = kNUM_SHIFTS_TO_ACTIVATE;
clock_interval_to_absolutetime_interval( kDEFAULT_SHIFTEXPIREINTERVAL,
kMillisecondScale,
&_stickyKeys_ShiftToggle->expireInterval);
_stickyKeys_ShiftToggle->currentCount = 0;
_stickyKeys_OptionToggle = stickyKeysAllocToggleInfo (kNUM_SHIFTS_TO_ACTIVATE);
if (_stickyKeys_OptionToggle == NULL)
return false;
_stickyKeys_OptionToggle->toggleModifier = NX_MODIFIERKEY_ALTERNATE;
_stickyKeys_OptionToggle->repetitionsToToggle = kNUM_SHIFTS_TO_ACTIVATE;
clock_interval_to_absolutetime_interval( kDEFAULT_SHIFTEXPIREINTERVAL,
kMillisecondScale,
&_stickyKeys_OptionToggle->expireInterval);
_stickyKeys_OptionToggle->currentCount = 0;
_stickyKeysMouseClickEventSource = 0;
_stickyKeysSetFnStateEventSource = 0;
return createParamDicts();
}
void IOHIKeyboardMapper::stickyKeysfree (void)
{
if (_stickyKeys_ShiftToggle)
stickyKeysFreeToggleInfo(_stickyKeys_ShiftToggle);
if (_stickyKeys_OptionToggle)
stickyKeysFreeToggleInfo(_stickyKeys_OptionToggle);
if (_onParamDict)
_onParamDict->release();
if (_offParamDict)
_offParamDict->release();
if (_reserved) {
if (_offFnParamDict)
_offFnParamDict->release();
if (_onFnParamDict)
_onFnParamDict->release();
if (_stickyKeysMouseClickEventSource) {
_stickyKeysMouseClickEventSource->release();
_stickyKeysMouseClickEventSource = 0;
}
if (_stickyKeysSetFnStateEventSource) {
_stickyKeysSetFnStateEventSource->release();
_stickyKeysSetFnStateEventSource = 0;
}
}
}
StickyKeys_ToggleInfo * IOHIKeyboardMapper::stickyKeysAllocToggleInfo (unsigned maxCount)
{
StickyKeys_ToggleInfo * toggleInfo;
IOByteCount size;
size = sizeof(StickyKeys_ToggleInfo) +
(sizeof(AbsoluteTime) * (maxCount - 1));
toggleInfo = (StickyKeys_ToggleInfo *)
IOMalloc (size);
if (toggleInfo)
toggleInfo->size = size;
return toggleInfo;
}
void IOHIKeyboardMapper::stickyKeysFreeToggleInfo (StickyKeys_ToggleInfo * toggleInfo)
{
IOFree (toggleInfo, toggleInfo->size);
}
bool IOHIKeyboardMapper::createParamDicts ( void )
{
bool ok = true;
_onParamDict = OSDictionary::withCapacity(4);
if (_onParamDict)
{
makeNumberParamProperty( _onParamDict, kIOHIDStickyKeysOnKey,
1, 32 );
}
else
ok = false;
if (ok)
_offParamDict = OSDictionary::withCapacity(4);
if (_offParamDict)
{
makeNumberParamProperty( _offParamDict, kIOHIDStickyKeysOnKey,
0, 32 );
}
else
ok = false;
if (ok)
_onFnParamDict = OSDictionary::withCapacity(4);
if (_onFnParamDict)
{
makeNumberParamProperty( _onFnParamDict, kIOHIDFKeyModeKey,
1, 32 );
_onFnParamDict->setObject(kIOHIDTemporaryParametersKey, kOSBooleanTrue);
}
else
ok = false;
if (ok)
_offFnParamDict = OSDictionary::withCapacity(4);
if (_offFnParamDict)
{
makeNumberParamProperty( _offFnParamDict, kIOHIDFKeyModeKey,
0, 32 );
_offFnParamDict->setObject(kIOHIDTemporaryParametersKey, kOSBooleanTrue);
}
else
ok = false;
return( ok );
}
void IOHIKeyboardMapper::postKeyboardSpecialEvent (unsigned subtype, unsigned eventType)
{
_delegate->keyboardSpecialEvent (
eventType,
_delegate->eventFlags(),
NX_NOSPECIALKEY,
subtype);
}
bool IOHIKeyboardMapper::stickyKeysModifierToggleCheck(StickyKeys_ToggleInfo *toggleInfo,
UInt8 key,
bool keyDown,
kbdBitVector keyBits __unused,
bool mouseClick)
{
unsigned char thisBits = _parsedMapping.keyBits[key];
int index, innerindex;
AbsoluteTime now, deadline;
bool shouldToggle = false;
unsigned leftModBit = (thisBits & NX_WHICHMODMASK);
convertToLeftModBit(leftModBit);
if ((leftModBit == toggleInfo->toggleModifier) && !mouseClick)
{
clock_get_uptime(&now);
for (index = toggleInfo->currentCount - 1; index >= 0; index--)
if (AbsoluteTime_to_scalar(&now) >
AbsoluteTime_to_scalar(&toggleInfo->deadlines[index]))
{
int entries_to_delete = index + 1;
for (innerindex = 0; innerindex < (int)(toggleInfo->currentCount - entries_to_delete); innerindex++)
toggleInfo->deadlines[innerindex] =
toggleInfo->deadlines[innerindex + entries_to_delete];
toggleInfo->currentCount -= entries_to_delete;
index = -1;
break;
}
if (keyDown)
{
if (toggleInfo->currentCount < toggleInfo->repetitionsToToggle)
{
clock_absolutetime_interval_to_deadline(toggleInfo->expireInterval, &deadline);
toggleInfo->deadlines[toggleInfo->currentCount++] = deadline;
}
}
else
{
if (toggleInfo->currentCount == toggleInfo->repetitionsToToggle)
{
toggleInfo->currentCount = 0;
shouldToggle = true;
}
}
}
else
toggleInfo->currentCount = 0;
return shouldToggle;
}
void IOHIKeyboardMapper::stickyKeysNonModifierKey(
UInt8 key,
bool keyDown,
kbdBitVector keyBits,
bool mouseClick)
{
int index;
if (!mouseClick)
rawTranslateKeyCode(key, keyDown, keyBits);
for (index = 0; index < _stickyKeys_NumModifiersDown; index++) {
_stickyKeys_StuckModifiers[index].state |= kModifier_DidPerformModifiy;
if (((_stickyKeys_StuckModifiers[index].state & kModifier_DidKeyUp) != 0) &&
((_stickyKeys_StuckModifiers[index].state & kModifier_Locked) == 0)) {
stickyKeysModifierKey(_stickyKeys_StuckModifiers[index].key, false, keyBits);
index --;
}
}
if (_stickyKeys_NumModifiersDown == 0)
_stickyKeys_State &= ~kState_On_ModifiersDown;
}
bool IOHIKeyboardMapper::stickyKeysModifierKey(
UInt8 key,
bool keyDown,
kbdBitVector keyBits)
{
unsigned char thisBits = _parsedMapping.keyBits[key];
int index = 0;
int innerindex = 0;
bool isBeingHeld = false;
bool shouldBeHandled = true;
int heldIndex = 0;
int leftModBit = (thisBits & NX_WHICHMODMASK);
convertToLeftModBit(leftModBit);
isBeingHeld = false;
for (index = 0; index < _stickyKeys_NumModifiersDown; index++)
if (_stickyKeys_StuckModifiers[index].leftModBit == leftModBit)
{
isBeingHeld = true;
heldIndex = index;
break;
}
if (! keyDown) {
if (isBeingHeld)
{
if (((_stickyKeys_StuckModifiers[heldIndex].state & kModifier_DidPerformModifiy) != 0) &&
((_stickyKeys_StuckModifiers[heldIndex].state & kModifier_Locked) == 0)) {
goto RELEASE_STICKY_MODIFIER_KEY;
}
else
{
_stickyKeys_StuckModifiers[heldIndex].state |= kModifier_DidKeyUp;
if (((thisBits & NX_WHICHMODMASK) == NX_MODIFIERKEY_SECONDARYFN) &&
((_stickyKeys_State & kState_StickyFnKeyStateChangePending) != 0))
{
_stickyKeys_State &= ~kState_StickyFnKeyStateChangePending;
if (_stickyKeysSetFnStateEventSource)
_stickyKeysSetFnStateEventSource->interruptOccurred(0, 0, 0);
}
}
}
else
shouldBeHandled = false;
}
else
{
if (isBeingHeld)
{
if ((_stickyKeys_StuckModifiers[heldIndex].state & kModifier_Locked) != 0)
{
RELEASE_STICKY_MODIFIER_KEY:
rawTranslateKeyCode(_stickyKeys_StuckModifiers[heldIndex].key, false, keyBits);
_stickyKeys_StuckModifiers[heldIndex].key = 0;
_stickyKeys_StuckModifiers[heldIndex].state = 0;
_stickyKeys_StuckModifiers[heldIndex].leftModBit = 0;
_stickyKeys_NumModifiersDown--;
if (_stickyKeys_NumModifiersDown == 0)
_stickyKeys_State &= ~kState_On_ModifiersDown;
for (innerindex = heldIndex; innerindex < _stickyKeys_NumModifiersDown; innerindex++) {
_stickyKeys_StuckModifiers[innerindex].key = _stickyKeys_StuckModifiers[innerindex + 1].key;
_stickyKeys_StuckModifiers[innerindex].state = _stickyKeys_StuckModifiers[innerindex + 1].state;
_stickyKeys_StuckModifiers[innerindex].leftModBit = _stickyKeys_StuckModifiers[innerindex + 1].leftModBit;
}
switch ((thisBits & NX_WHICHMODMASK))
{
case NX_MODIFIERKEY_SHIFT:
case NX_MODIFIERKEY_RSHIFT:
postKeyboardSpecialEvent (NX_SUBTYPE_STICKYKEYS_SHIFT_UP);
break;
case NX_MODIFIERKEY_CONTROL:
case NX_MODIFIERKEY_RCONTROL:
postKeyboardSpecialEvent (NX_SUBTYPE_STICKYKEYS_CONTROL_UP);
break;
case NX_MODIFIERKEY_ALTERNATE:
case NX_MODIFIERKEY_RALTERNATE:
postKeyboardSpecialEvent (NX_SUBTYPE_STICKYKEYS_ALTERNATE_UP);
break;
case NX_MODIFIERKEY_COMMAND:
case NX_MODIFIERKEY_RCOMMAND:
postKeyboardSpecialEvent (NX_SUBTYPE_STICKYKEYS_COMMAND_UP);
break;
case NX_MODIFIERKEY_SECONDARYFN:
_stickyKeys_State &= ~(kState_StickyFnKeyStateOn | kState_StickyFnKeyStateChangePending);
if (_stickyKeysSetFnStateEventSource)
_stickyKeysSetFnStateEventSource->interruptOccurred(0, 0, 0);
postKeyboardSpecialEvent (NX_SUBTYPE_STICKYKEYS_FN_UP);
break;
default:
break;
}
}
else
{
_stickyKeys_StuckModifiers[heldIndex].state |= kModifier_Locked;
switch ((thisBits & NX_WHICHMODMASK))
{
case NX_MODIFIERKEY_SHIFT:
case NX_MODIFIERKEY_RSHIFT:
postKeyboardSpecialEvent (NX_SUBTYPE_STICKYKEYS_SHIFT_LOCK);
break;
case NX_MODIFIERKEY_CONTROL:
case NX_MODIFIERKEY_RCONTROL:
postKeyboardSpecialEvent (NX_SUBTYPE_STICKYKEYS_CONTROL_LOCK);
break;
case NX_MODIFIERKEY_ALTERNATE:
case NX_MODIFIERKEY_RALTERNATE:
postKeyboardSpecialEvent (NX_SUBTYPE_STICKYKEYS_ALTERNATE_LOCK);
break;
case NX_MODIFIERKEY_COMMAND:
case NX_MODIFIERKEY_RCOMMAND:
postKeyboardSpecialEvent (NX_SUBTYPE_STICKYKEYS_COMMAND_LOCK);
break;
case NX_MODIFIERKEY_SECONDARYFN:
postKeyboardSpecialEvent (NX_SUBTYPE_STICKYKEYS_FN_LOCK);
break;
default:
break;
}
}
}
else
{
rawTranslateKeyCode(key, keyDown, keyBits);
if (_stickyKeys_NumModifiersDown < kMAX_MODIFIERS) {
int modifierIndex = _stickyKeys_NumModifiersDown++;
_stickyKeys_StuckModifiers[modifierIndex].key = key;
_stickyKeys_StuckModifiers[modifierIndex].state = 0;
_stickyKeys_StuckModifiers[modifierIndex].leftModBit = leftModBit;
}
else
;
_stickyKeys_State |= kState_On_ModifiersDown;
switch ((thisBits & NX_WHICHMODMASK))
{
case NX_MODIFIERKEY_SHIFT:
case NX_MODIFIERKEY_RSHIFT:
postKeyboardSpecialEvent (NX_SUBTYPE_STICKYKEYS_SHIFT_DOWN);
break;
case NX_MODIFIERKEY_CONTROL:
case NX_MODIFIERKEY_RCONTROL:
postKeyboardSpecialEvent (NX_SUBTYPE_STICKYKEYS_CONTROL_DOWN);
break;
case NX_MODIFIERKEY_ALTERNATE:
case NX_MODIFIERKEY_RALTERNATE:
postKeyboardSpecialEvent (NX_SUBTYPE_STICKYKEYS_ALTERNATE_DOWN);
break;
case NX_MODIFIERKEY_COMMAND:
case NX_MODIFIERKEY_RCOMMAND:
postKeyboardSpecialEvent (NX_SUBTYPE_STICKYKEYS_COMMAND_DOWN);
break;
case NX_MODIFIERKEY_SECONDARYFN:
_stickyKeys_State |= kState_StickyFnKeyStateOn | kState_StickyFnKeyStateChangePending;
postKeyboardSpecialEvent (NX_SUBTYPE_STICKYKEYS_FN_DOWN);
break;
default:
break;
}
}
}
return shouldBeHandled;
}
bool IOHIKeyboardMapper::stickyKeysFilterKey(
UInt8 key,
bool keyDown,
kbdBitVector keyBits,
bool mouseClick)
{
unsigned char thisBits = _parsedMapping.keyBits[key];
bool shouldFilter = false;
bool shouldToggleState = false;
if ( _parsedMapping.maxMod == -1 )
return false;
if ((_stickyKeys_State & kState_Disabled_Flag) != 0)
return false;
if ((_stickyKeys_State & kState_ShiftActivates_Flag) != 0)
{
shouldToggleState = stickyKeysModifierToggleCheck
(_stickyKeys_ShiftToggle, key, keyDown, keyBits, mouseClick);
}
if ((_stickyKeys_State & kState_OptionActivates_Flag) != 0)
{
if (stickyKeysModifierToggleCheck (_stickyKeys_OptionToggle,key, keyDown, keyBits, mouseClick))
postKeyboardSpecialEvent (NX_SUBTYPE_STICKYKEYS_TOGGLEMOUSEDRIVING);
}
if (((_stickyKeys_State & kState_On_ModifiersDown) != 0) && !modifierOfInterest(thisBits))
{
if (mouseClick ||
(keyDown && !(((_stickyKeys_State & kState_MouseKeyStateOn) != 0) && mouseKey(thisBits))) ||
(!keyDown && !(((_stickyKeys_State & kState_MouseKeyStateOn) != 0) && mouseKeyToIgnore(thisBits, key))) )
{
shouldFilter = true;
stickyKeysNonModifierKey (key, keyDown, keyBits, mouseClick);
}
}
if ((_stickyKeys_State & kState_On) != 0)
{
if (!_stickyKeysMouseClickEventSource && _hidSystem)
{
_stickyKeysMouseClickEventSource =
IOInterruptEventSource::interruptEventSource
(this, (IOInterruptEventSource::Action) stickyKeysMouseUp);
if(_stickyKeysMouseClickEventSource &&
(_hidSystem->getWorkLoop()->addEventSource(_stickyKeysMouseClickEventSource) != kIOReturnSuccess)) {
_stickyKeysMouseClickEventSource->release();
_stickyKeysMouseClickEventSource = 0;
}
}
if (!_stickyKeysSetFnStateEventSource && _hidSystem)
{
_stickyKeysSetFnStateEventSource =
IOInterruptEventSource::interruptEventSource
(this, (IOInterruptEventSource::Action) stickyKeysSetFnState);
if(_stickyKeysSetFnStateEventSource &&
(_hidSystem->getWorkLoop()->addEventSource(_stickyKeysSetFnStateEventSource) != kIOReturnSuccess)) {
_stickyKeysSetFnStateEventSource->release();
_stickyKeysSetFnStateEventSource = 0;
}
}
if (modifierOfInterest(thisBits))
{
shouldFilter = stickyKeysModifierKey (key, keyDown, keyBits);
}
}
if (shouldToggleState)
{
if ((_stickyKeys_State & kState_On) != 0)
{
stickyKeysCleanup();
postKeyboardSpecialEvent (NX_SUBTYPE_STICKYKEYS_OFF);
}
else
{
_stickyKeys_State |= kState_On;
postKeyboardSpecialEvent (NX_SUBTYPE_STICKYKEYS_ON);
}
_stateDirty = true;
if (_stickyKeysSetFnStateEventSource)
_stickyKeysSetFnStateEventSource->interruptOccurred(0, 0, 0);
}
return shouldFilter;
}
void IOHIKeyboardMapper::stickyKeysCleanup()
{
_stickyKeys_State &= ~kState_On;
for (int index = 0; index < _stickyKeys_NumModifiersDown; index++)
rawTranslateKeyCode(_stickyKeys_StuckModifiers[index].key, false, _cached_KeyBits);
_stickyKeys_State &= ~kState_On_ModifiersDown;
_stickyKeys_NumModifiersDown = 0;
_stickyKeys_State &= ~kState_StickyFnKeyStateOn;
if (_stickyKeysSetFnStateEventSource)
_stickyKeysSetFnStateEventSource->interruptOccurred(0, 0, 0);
}
void IOHIKeyboardMapper::keyEventPostProcess (void)
{
bool nowOn;
OSDictionary * dict;
if (_stateDirty)
{
if (_hidSystem)
{
nowOn = ((_stickyKeys_State & kState_On) != 0);
dict = nowOn ? _onParamDict : _offParamDict;
_hidSystem->setParamProperties (dict);
}
_stateDirty = false;
}
}
bool IOHIKeyboardMapper::f12EjectFilterKey (UInt8 key, bool keyDown, kbdBitVector keyBits) {
if ((_eject_Delay_MS == 0) || !_supportsF12Eject )
return false;
if (key == kADB_KEYBOARD_F12) {
if (!_ejectTimerEventSource) {
if (_hidSystem == NULL)
return false;
_ejectTimerEventSource = IOTimerEventSource::timerEventSource
(this, (IOTimerEventSource::Action) &IOHIKeyboardMapper::performF12Eject);
if (_hidSystem->getWorkLoop()->addEventSource(_ejectTimerEventSource) != kIOReturnSuccess)
return false;
}
if (keyDown == true) {
_f12Eject_State |= kState_In_Progess_Flag;
_ejectTimerEventSource->setTimeoutMS(_eject_Delay_MS);
return true;
} else {
if ((_f12Eject_State & kState_In_Progess_Flag) != 0) {
_ejectTimerEventSource->cancelTimeout();
_f12Eject_State &= ~kState_In_Progess_Flag;
rawTranslateKeyCode (key, true, keyBits);
}
else
return true;
}
}
return false;
}
void IOHIKeyboardMapper::performF12Eject(IOHIKeyboardMapper *owner, IOTimerEventSource *sender __unused) {
owner->postKeyboardSpecialEvent(NX_KEYTYPE_EJECT, NX_KEYDOWN);
owner->_f12Eject_State &= ~kState_In_Progess_Flag;
}
bool IOHIKeyboardMapper::slowKeysFilterKey (UInt8 key, bool keyDown, kbdBitVector keyBits __unused)
{
bool returnValue = true;
if (_slowKeys_Delay_MS == 0)
return false;
if (!_slowKeysTimerEventSource) {
if (_hidSystem == NULL)
return false;
_slowKeysTimerEventSource = IOTimerEventSource::timerEventSource
(this, (IOTimerEventSource::Action) &IOHIKeyboardMapper::slowKeysPostProcess );
if(_hidSystem->getWorkLoop()->addEventSource(_slowKeysTimerEventSource) != kIOReturnSuccess)
return false;
}
if (keyDown) {
if ((_slowKeys_State & kState_In_Progess_Flag) == 0) {
if ((key != _slowKeys_Current_Key) && ((_slowKeys_State & kState_Is_Repeat_Flag) != 0)) {
postSlowKeyTranslateKeyCode(this, _slowKeys_Current_Key, false, _cached_KeyBits);
_slowKeys_State &= ~kState_Is_Repeat_Flag;
}
_slowKeys_State |= kState_In_Progess_Flag;
_slowKeys_Current_Key = key;
_slowKeysTimerEventSource->setTimeoutMS(_slowKeys_Delay_MS);
if (_delegate->isRepeat())
_slowKeys_State |= kState_Is_Repeat_Flag;
postKeyboardSpecialEvent(NX_SUBTYPE_SLOWKEYS_START);
}
else if (((_slowKeys_State & kState_In_Progess_Flag) != 0) && (key != _slowKeys_Current_Key)) {
_slowKeysTimerEventSource->cancelTimeout();
_slowKeys_State |= kState_Aborted_Flag;
_slowKeys_State &= ~kState_In_Progess_Flag;
_slowKeys_Aborted_Key = key;
if ((_slowKeys_State & kState_Is_Repeat_Flag) != 0) {
postSlowKeyTranslateKeyCode(this, _slowKeys_Current_Key, false, _cached_KeyBits);
_slowKeys_State &= ~kState_Is_Repeat_Flag;
}
postKeyboardSpecialEvent(NX_SUBTYPE_SLOWKEYS_ABORT);
}
}
else {
if (key == _slowKeys_Current_Key) {
if ((_slowKeys_State & kState_In_Progess_Flag) != 0) {
_slowKeysTimerEventSource->cancelTimeout();
_slowKeys_State &= ~kState_In_Progess_Flag;
if ((_slowKeys_State & kState_Is_Repeat_Flag) != 0) {
_slowKeys_State &= ~kState_Is_Repeat_Flag;
returnValue = false;
}
}
else if ((_slowKeys_State & kState_Aborted_Flag) == 0) {
if ((_slowKeys_State & kState_Is_Repeat_Flag) != 0)
_slowKeys_State &= ~kState_Is_Repeat_Flag;
returnValue = false;
}
}
else if ((key == _slowKeys_Aborted_Key) && ((_slowKeys_State & kState_Aborted_Flag) != 0)){
_slowKeysTimerEventSource->cancelTimeout();
_slowKeys_State &= ~kState_Aborted_Flag;
_slowKeys_State &= ~kState_In_Progess_Flag;
if ((_slowKeys_State & kState_Is_Repeat_Flag) != 0) {
postSlowKeyTranslateKeyCode(this, _slowKeys_Current_Key, false, _cached_KeyBits);
_slowKeys_State &= ~kState_Is_Repeat_Flag;
}
postKeyboardSpecialEvent(NX_SUBTYPE_SLOWKEYS_ABORT);
}
else {
returnValue = false;
}
}
return returnValue;
}
void IOHIKeyboardMapper::slowKeysPostProcess (IOHIKeyboardMapper *owner, IOTimerEventSource *sender __unused)
{
owner->_slowKeys_State &= ~kState_In_Progess_Flag;
postSlowKeyTranslateKeyCode(owner, owner->_slowKeys_Current_Key, true, owner->_cached_KeyBits);
owner->postKeyboardSpecialEvent(NX_SUBTYPE_SLOWKEYS_END);
}
void IOHIKeyboardMapper::stickyKeysSetFnState(IOHIKeyboardMapper *owner, IOEventSource *sender __unused)
{
OSDictionary *dict;
if ((owner->_stickyKeys_State & kState_On) != 0)
{
dict = (((owner->_stickyKeys_State & kState_PrefFnKeyStateOn) != 0) ^ ((owner->_stickyKeys_State & kState_StickyFnKeyStateOn) != 0)) ?
owner->_onFnParamDict : owner->_offFnParamDict;
}
else
{
dict = ((owner->_stickyKeys_State & kState_PrefFnKeyStateOn) != 0) ? owner->_onFnParamDict : owner->_offFnParamDict;
}
owner->_hidSystem->setParamProperties (dict);
}
void IOHIKeyboardMapper::stickyKeysMouseUp(IOHIKeyboardMapper *owner, IOEventSource *sender __unused)
{
owner->stickyKeysFilterKey (0, 0, owner->_cached_KeyBits, true);
}
OSMetaClassDefineReservedUsed(IOHIKeyboardMapper, 0);
IOReturn IOHIKeyboardMapper::message( UInt32 type, IOService * provider __unused, void * argument __unused )
{
switch (type)
{
case kIOHIDSystem508MouseClickMessage:
case kIOHIDSystem508SpecialKeyDownMessage:
if (_stickyKeysMouseClickEventSource)
_stickyKeysMouseClickEventSource->interruptOccurred(0, 0, 0);
break;
default:
break;
}
return kIOReturnSuccess;
}
OSMetaClassDefineReservedUnused(IOHIKeyboardMapper, 1);
OSMetaClassDefineReservedUnused(IOHIKeyboardMapper, 2);
OSMetaClassDefineReservedUnused(IOHIKeyboardMapper, 3);
OSMetaClassDefineReservedUnused(IOHIKeyboardMapper, 4);
OSMetaClassDefineReservedUnused(IOHIKeyboardMapper, 5);
OSMetaClassDefineReservedUnused(IOHIKeyboardMapper, 6);
OSMetaClassDefineReservedUnused(IOHIKeyboardMapper, 7);
OSMetaClassDefineReservedUnused(IOHIKeyboardMapper, 8);
OSMetaClassDefineReservedUnused(IOHIKeyboardMapper, 9);
OSMetaClassDefineReservedUnused(IOHIKeyboardMapper, 10);
OSMetaClassDefineReservedUnused(IOHIKeyboardMapper, 11);
OSMetaClassDefineReservedUnused(IOHIKeyboardMapper, 12);
OSMetaClassDefineReservedUnused(IOHIKeyboardMapper, 13);
OSMetaClassDefineReservedUnused(IOHIKeyboardMapper, 14);
OSMetaClassDefineReservedUnused(IOHIKeyboardMapper, 15);