/* * @APPLE_LICENSE_HEADER_START@ * * Copyright (c) 1999-2003 Apple Computer, Inc. All Rights Reserved. * * This file contains Original Code and/or Modifications of Original Code * as defined in and that are subject to the Apple Public Source License * Version 2.0 (the 'License'). You may not use this file except in * compliance with the License. Please obtain a copy of the License at * http://www.opensource.apple.com/apsl/ and read it before using this * file. * * The Original Code and all software distributed under the License are * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. * Please see the License for the specific language governing rights and * limitations under the License. * * @APPLE_LICENSE_HEADER_END@ */ /* * 24-Jan-01 bubba Don't auto-repeat on Power Key. This prevents infinite power key * events from being generated when this key is hit on ADB keyboards. */ #include #include #include #include #include #include "IOHIDSystem.h" #include "IOHIDKeyboardDevice.h" //************************************************************************ // KeyboardReserved // // RY: The following was added because the IOHIKeyboard class doesn't have // a reserved field defined. Essentially what this does is create a // static dictionary that stores OSData objects for each keyboard. These // OSData objects will be added and removed as each keyboard enters and // leaves the system. struct KeyboardReserved { thread_call_t repeat_thread_call; bool dispatchEventCalled; bool isSeized; IOService * openClient; IOHIDKeyboardDevice * keyboardNub; }; static OSDictionary *gKeyboardReservedDictionary = OSDictionary::withCapacity(4); static OSSymbol * GetKeyForService(OSObject * newService) { char key[9]; sprintf(key, "%x", (UInt32)newService); return OSSymbol::withCString(key); } static KeyboardReserved * GetKeyboardReservedStructEventForService(OSObject *service) { KeyboardReserved * retVal = 0; OSSymbol * key = 0; OSData * data = 0; if (gKeyboardReservedDictionary && (key = GetKeyForService(service))) { if (data = gKeyboardReservedDictionary->getObject(key)) { retVal = (KeyboardReserved *)data->getBytesNoCopy(); } key->release(); } return retVal; } static void AppendNewKeyboardReservedStructForService(OSObject *service) { KeyboardReserved temp; OSSymbol * key = 0; OSData * data = 0; if (gKeyboardReservedDictionary && (key = GetKeyForService(service))) { bzero(&temp, sizeof(KeyboardReserved)); data = OSData::withBytes(&temp, sizeof(KeyboardReserved)); gKeyboardReservedDictionary->setObject(key, data); data->release(); key->release(); } } static void RemoveKeyboardReservedStructForService(OSObject *service) { OSSymbol * key = 0; if (gKeyboardReservedDictionary && (key = GetKeyForService(service))) { gKeyboardReservedDictionary->removeObject(key); key->release(); } } //************************************************************************ #define super IOHIDevice OSDefineMetaClassAndStructors(IOHIKeyboard, IOHIDevice); bool IOHIKeyboard::init(OSDictionary * properties) { if (!super::init(properties)) return false; /* * Initialize minimal state. */ _deviceLock = IOLockAlloc(); _keyMap = 0; _keyStateSize = 4*((maxKeyCodes()+(EVK_BITS_PER_UNIT-1))/EVK_BITS_PER_UNIT); _keyState = (UInt32 *) IOMalloc(_keyStateSize); _keyboardEventTarget = 0; _keyboardEventAction = 0; _keyboardSpecialEventTarget = 0; _keyboardSpecialEventAction = 0; _updateEventFlagsTarget = 0; _updateEventFlagsAction = 0; if (!_deviceLock || !_keyState) return false; bzero(_keyState, _keyStateSize); AppendNewKeyboardReservedStructForService(this); KeyboardReserved * tempReservedStruct = GetKeyboardReservedStructEventForService(this); if (tempReservedStruct) { tempReservedStruct->repeat_thread_call = thread_call_allocate(_autoRepeat, this); } return true; } bool IOHIKeyboard::start(IOService * provider) { if (!super::start(provider)) return false; /* * IOHIKeyboard serves both as a service and a nub (we lead a double * life). Register ourselves as a nub to kick off matching. */ registerService(); return true; } void IOHIKeyboard::stop(IOService * provider) { KeyboardReserved *tempReservedStruct = GetKeyboardReservedStructEventForService(this); if (tempReservedStruct) { if (tempReservedStruct->keyboardNub) { tempReservedStruct->keyboardNub->stop(this); tempReservedStruct->keyboardNub->detach(this); tempReservedStruct->keyboardNub->release(); tempReservedStruct->keyboardNub = 0; } } super::stop(provider); } void IOHIKeyboard::free() // Description: Go Away. Be careful when freeing the lock. { IOLock * lock = NULL; if ( _deviceLock ) { lock = _deviceLock; IOLockLock( lock); _deviceLock = NULL; } if ( _keyMap ) { _keyMap->release(); } if( _keyState ) IOFree( _keyState, _keyStateSize); KeyboardReserved *tempReservedStruct = GetKeyboardReservedStructEventForService(this); if (tempReservedStruct) { thread_call_free(tempReservedStruct->repeat_thread_call); RemoveKeyboardReservedStructForService(this); } // RY: MENTAL NOTE Do this last if ( lock ) { IOLockUnlock( lock); IOLockFree( lock); } super::free(); } IOHIDKind IOHIKeyboard::hidKind() { return kHIKeyboardDevice; } bool IOHIKeyboard::updateProperties( void ) { bool ok; ok = setProperty( kIOHIDKeyMappingKey, _keyMap ); return( ok & super::updateProperties() ); } IOReturn IOHIKeyboard::setParamProperties( OSDictionary * dict ) { OSData * data; OSNumber * number; IOReturn err = kIOReturnSuccess, err2; unsigned char * map; IOHIKeyboardMapper * oldMap; bool updated = false; UInt64 nano; UInt32 value; if( dict->getObject(kIOHIDResetKeyboardKey)) resetKeyboard(); IOLockLock( _deviceLock); if ((number = OSDynamicCast(OSNumber, dict->getObject(kIOHIDKeyRepeatKey))) || (data = OSDynamicCast(OSData, dict->getObject(kIOHIDKeyRepeatKey)))) { nano = (number) ? number->unsigned64BitValue() : *((UInt64 *) (data->getBytesNoCopy())); if( nano < EV_MINKEYREPEAT) nano = EV_MINKEYREPEAT; nanoseconds_to_absolutetime(nano, &_keyRepeat); updated = true; } if ((number = OSDynamicCast(OSNumber, dict->getObject(kIOHIDInitialKeyRepeatKey))) || (data = OSDynamicCast(OSData, dict->getObject(kIOHIDInitialKeyRepeatKey)))) { nano = (number) ? number->unsigned64BitValue() : *((UInt64 *) (data->getBytesNoCopy())); if( nano < EV_MINKEYREPEAT) nano = EV_MINKEYREPEAT; nanoseconds_to_absolutetime(nano, &_initialKeyRepeat); updated = true; } if( (data = OSDynamicCast( OSData, dict->getObject(kIOHIDKeyMappingKey)))) { map = (unsigned char *)IOMalloc( data->getLength() ); bcopy( data->getBytesNoCopy(), map, data->getLength() ); oldMap = _keyMap; _keyMap = IOHIKeyboardMapper::keyboardMapper(this, map, data->getLength(), true); if (_keyMap) { // point the new keymap to the IOHIDSystem, so it can set properties in it _keyMap->setKeyboardTarget((IOService *) _keyboardEventTarget); if (oldMap) oldMap->release(); updated = true; } else { _keyMap = oldMap; err = kIOReturnBadArgument; } } IOLockUnlock( _deviceLock); // give the keymap a chance to update to new properties if (_keyMap) err2 = _keyMap->setParamProperties(dict); if( updated ) updateProperties(); // we can only return one error if (err == kIOReturnSuccess) err = err2; return( err ); } bool IOHIKeyboard::resetKeyboard() // Description: Reset the keymapping to the default value and reconfigure // the keyboards. { const unsigned char *defaultKeymap; UInt32 defaultKeymapLength; IOLockLock( _deviceLock); if ( _keyMap ) _keyMap->release(); // Set up default keymapping. defaultKeymap = defaultKeymapOfLength(&defaultKeymapLength); _keyMap = IOHIKeyboardMapper::keyboardMapper( this, defaultKeymap, defaultKeymapLength, false ); if (_keyMap) { // point the new keymap to the IOHIDSystem, so it can set properties in it _keyMap->setKeyboardTarget((IOService *) _keyboardEventTarget); clock_interval_to_absolutetime_interval( EV_DEFAULTKEYREPEAT, kNanosecondScale, &_keyRepeat); clock_interval_to_absolutetime_interval( EV_DEFAULTINITIALREPEAT, kNanosecondScale, &_initialKeyRepeat); } updateProperties(); if (getProperty("HIDKeyboardKeysDefined")) { IOHIDKeyboardDevice * hidKeyboardNub = 0; KeyboardReserved *tempReservedStruct = GetKeyboardReservedStructEventForService(this); if (tempReservedStruct) { hidKeyboardNub = tempReservedStruct->keyboardNub; if (!hidKeyboardNub) { hidKeyboardNub = IOHIDKeyboardDevice::newKeyboardDevice(this); if (hidKeyboardNub && (!hidKeyboardNub->attach(this) || !hidKeyboardNub->start(this))) { hidKeyboardNub->release(); hidKeyboardNub = 0; } tempReservedStruct->keyboardNub = hidKeyboardNub; } } } _interfaceType = interfaceID(); _deviceType = deviceType(); _guid = getGUID(); IOLockUnlock( _deviceLock); return (_keyMap) ? true : false; } void IOHIKeyboard::scheduleAutoRepeat() // Description: Schedule a procedure to be called when a timeout has expired // so that we can generate a repeated key. // Preconditions: // * _deviceLock should be held on entry { KeyboardReserved *tempReservedStruct = GetKeyboardReservedStructEventForService(this); if ( _calloutPending == true ) { if (tempReservedStruct) { thread_call_cancel(tempReservedStruct->repeat_thread_call); } _calloutPending = false; } if ( AbsoluteTime_to_scalar(&_downRepeatTime) ) { AbsoluteTime deadline; clock_absolutetime_interval_to_deadline(_downRepeatTime, &deadline); if (tempReservedStruct) { thread_call_enter_delayed(tempReservedStruct->repeat_thread_call, deadline); } _calloutPending = true; } } void IOHIKeyboard::_autoRepeat(thread_call_param_t arg, thread_call_param_t) /* thread_call_func_t */ { IOHIKeyboard *self = (IOHIKeyboard *) arg; self->autoRepeat(); } void IOHIKeyboard::autoRepeat() // Description: Repeat the currently pressed key and schedule ourselves // to be called again after another interval elapses. // Preconditions: // * Should only be executed on callout thread // * _deviceLock should be unlocked on entry. { KeyboardReserved *tempReservedStruct = GetKeyboardReservedStructEventForService(this); IOLockLock( _deviceLock); if (( _calloutPending == false ) || ((tempReservedStruct) && tempReservedStruct->dispatchEventCalled )) { IOLockUnlock( _deviceLock); return; } _calloutPending = false; _isRepeat = true; if (tempReservedStruct) tempReservedStruct->dispatchEventCalled = true; if ( AbsoluteTime_to_scalar(&_downRepeatTime) ) { // Device is due to generate a repeat if (_keyMap) _keyMap->translateKeyCode(_codeToRepeat, /* direction */ true, /* keyBits */ _keyState); _downRepeatTime = _keyRepeat; } if (tempReservedStruct) tempReservedStruct->dispatchEventCalled = false; _isRepeat = false; scheduleAutoRepeat(); IOLockUnlock( _deviceLock); } void IOHIKeyboard::setRepeat(unsigned eventType, unsigned keyCode) // Description: Set up or tear down key repeat operations. The method // that locks _deviceLock is a bit higher on the call stack. // This method is invoked as a side effect of our own // invocation of _keyMap->translateKeyCode(). // Preconditions: // * _deviceLock should be held upon entry. { if ( _isRepeat == false ) // make sure we're not already repeating { if (eventType == NX_KEYDOWN) // Start repeat { // Set this key to repeat (push out last key if present) _downRepeatTime = _initialKeyRepeat; // + _lastEventTime; _codeToRepeat = keyCode; // reschedule key repeat event here scheduleAutoRepeat(); } else if (eventType == NX_KEYUP) // End repeat { /* Remove from downKey */ if (_codeToRepeat == keyCode) { AbsoluteTime_to_scalar(&_downRepeatTime) = 0; _codeToRepeat = (unsigned)-1; scheduleAutoRepeat(); } } } } // // BEGIN: Implementation of the methods required by IOHIKeyboardMapper. // void IOHIKeyboard::keyboardEvent(unsigned eventType, /* flags */ unsigned flags, /* keyCode */ unsigned keyCode, /* charCode */ unsigned charCode, /* charSet */ unsigned charSet, /* originalCharCode */ unsigned origCharCode, /* originalCharSet */ unsigned origCharSet) // Description: We use this notification to set up our _keyRepeat timer // and to pass along the event to our owner. This method // will be called while the KeyMap object is processing // the key code we've sent it using deliverKey. { KeyboardReserved *tempReservedStruct = GetKeyboardReservedStructEventForService(this); if (tempReservedStruct && tempReservedStruct->dispatchEventCalled) { IOLockUnlock(_deviceLock); } _keyboardEvent( this, eventType, /* flags */ flags, /* keyCode */ keyCode, /* charCode */ charCode, /* charSet */ charSet, /* originalCharCode */ origCharCode, /* originalCharSet */ origCharSet, /* keyboardType */ _deviceType, /* repeat */ _isRepeat, /* atTime */ _lastEventTime); if (tempReservedStruct && tempReservedStruct->dispatchEventCalled) { IOLockLock(_deviceLock); } if( keyCode == _keyMap->getParsedSpecialKey(NX_KEYTYPE_CAPS_LOCK) || keyCode == _keyMap->getParsedSpecialKey(NX_KEYTYPE_NUM_LOCK) || keyCode == _keyMap->getParsedSpecialKey(NX_POWER_KEY) || keyCode == _keyMap->getParsedSpecialKey(NX_KEYTYPE_MUTE) || keyCode == _keyMap->getParsedSpecialKey(NX_KEYTYPE_PLAY) || keyCode == _keyMap->getParsedSpecialKey(NX_KEYTYPE_EJECT) || keyCode == _keyMap->getParsedSpecialKey(NX_KEYTYPE_VIDMIRROR) || keyCode == _keyMap->getParsedSpecialKey(NX_KEYTYPE_ILLUMINATION_TOGGLE)) { //Don't repeat caps lock on ADB/USB. 0x39 is default ADB code. // We are here because KeyCaps needs to see 0x39 as a real key, // not just another modifier bit. if (_interfaceType == NX_EVS_DEVICE_INTERFACE_ADB) { return; } } // Set up key repeat operations here. setRepeat(eventType, keyCode); } void IOHIKeyboard::keyboardSpecialEvent(unsigned eventType, /* flags */ unsigned flags, /* keyCode */ unsigned keyCode, /* specialty */ unsigned flavor) // Description: See the description for keyboardEvent. { KeyboardReserved *tempReservedStruct = GetKeyboardReservedStructEventForService(this); if (tempReservedStruct && tempReservedStruct->dispatchEventCalled) { IOLockUnlock(_deviceLock); } _keyboardSpecialEvent(this, eventType, /* flags */ flags, /* keyCode */ keyCode, /* specialty */ flavor, /* guid */ _guid, /* repeat */ _isRepeat, /* atTime */ _lastEventTime); if (tempReservedStruct && tempReservedStruct->dispatchEventCalled) { IOLockLock(_deviceLock); } // Set up key repeat operations here. // Don't repeat capslock, numlock, power key, mute key, play key, // eject key, vidmirror key, illumination toggle key. if( keyCode == _keyMap->getParsedSpecialKey(NX_KEYTYPE_CAPS_LOCK) || keyCode == _keyMap->getParsedSpecialKey(NX_KEYTYPE_NUM_LOCK) || keyCode == _keyMap->getParsedSpecialKey(NX_POWER_KEY) || keyCode == _keyMap->getParsedSpecialKey(NX_KEYTYPE_MUTE) || keyCode == _keyMap->getParsedSpecialKey(NX_KEYTYPE_PLAY) || keyCode == _keyMap->getParsedSpecialKey(NX_KEYTYPE_EJECT) || keyCode == _keyMap->getParsedSpecialKey(NX_KEYTYPE_VIDMIRROR) || keyCode == _keyMap->getParsedSpecialKey(NX_KEYTYPE_ILLUMINATION_TOGGLE)) { return; } // Set up key repeat operations here. setRepeat(eventType, keyCode); } void IOHIKeyboard::updateEventFlags(unsigned flags) // Description: Process non-event-generating flag changes. Simply pass this // along to our owner. { KeyboardReserved *tempReservedStruct = GetKeyboardReservedStructEventForService(this); if (tempReservedStruct && tempReservedStruct->dispatchEventCalled) { IOLockUnlock(_deviceLock); } _updateEventFlags(this, flags); if (tempReservedStruct && tempReservedStruct->dispatchEventCalled) { IOLockLock(_deviceLock); } } unsigned IOHIKeyboard::eventFlags() // Description: Return global event flags In this world, there is only // one keyboard device so device flags == global flags. { return _eventFlags; } unsigned IOHIKeyboard::deviceFlags() // Description: Return per-device event flags. In this world, there is only // one keyboard device so device flags == global flags. { return _eventFlags; } void IOHIKeyboard::setDeviceFlags(unsigned flags) // Description: Set device event flags. In this world, there is only // one keyboard device so device flags == global flags. { if (_eventFlags != flags) { _eventFlags = flags; // RY: On Modifier change, we should // reset the auto repeat timer AbsoluteTime_to_scalar(&_downRepeatTime) = 0; _codeToRepeat = (unsigned)-1; scheduleAutoRepeat(); } } bool IOHIKeyboard::alphaLock() // Description: Return current alpha-lock state. This is a state tracking // callback used by the KeyMap object. { return _alphaLock; } void IOHIKeyboard::setAlphaLock(bool val) // Description: Set current alpha-lock state This is a state tracking // callback used by the KeyMap object. { _alphaLock = val; setAlphaLockFeedback(val); KeyboardReserved *tempReservedStruct = GetKeyboardReservedStructEventForService(this); if (tempReservedStruct && tempReservedStruct->keyboardNub ) tempReservedStruct->keyboardNub->setCapsLockLEDElement(val); } bool IOHIKeyboard::numLock() { return _numLock; } void IOHIKeyboard::setNumLock(bool val) { _numLock = val; // RY: Since the num lock buttons, acts // as clear, don't toggle the light //setNumLockFeedback(val); } bool IOHIKeyboard::charKeyActive() // Description: Return true If a character generating key down This is a state // tracking callback used by the KeyMap object. { return _charKeyActive; } void IOHIKeyboard::setCharKeyActive(bool val) // Description: Note whether a char generating key is down. This is a state // tracking callback used by the KeyMap object. { _charKeyActive = val; } // // END: Implementation of the methods required by IOHIKeyboardMapper. // void IOHIKeyboard::dispatchKeyboardEvent(unsigned int keyCode, /* direction */ bool goingDown, /* timeStamp */ AbsoluteTime time) // Description: This method is the heart of event dispatching. The overlying // subclass invokes this method with each event. We then // get the event xlated and dispatched using a _keyMap instance. // The event structure passed in by reference should not be freed. { IOHIKeyboardMapper * theKeyMap; KeyboardReserved *tempReservedStruct = GetKeyboardReservedStructEventForService(this); IOLockLock( _deviceLock); _lastEventTime = time; // Post the event to the HID Manager if (tempReservedStruct) { if (tempReservedStruct->keyboardNub ) { tempReservedStruct->keyboardNub->postKeyboardEvent(keyCode, goingDown); } if (tempReservedStruct->isSeized) { IOLockUnlock( _deviceLock); return; } } if (tempReservedStruct) tempReservedStruct->dispatchEventCalled = true; if (_keyMap) _keyMap->translateKeyCode(keyCode, /* direction */ goingDown, /* keyBits */ _keyState); // remember the keymap while we hold the lock theKeyMap = _keyMap; if (tempReservedStruct) tempReservedStruct->dispatchEventCalled = false; IOLockUnlock( _deviceLock); // outside the lock (because of possible recursion), give the // keymap a chance to do some post processing // since it is possible we will be entered reentrantly and // release the keymap, we will add a retain here. if (theKeyMap) { theKeyMap->retain(); theKeyMap->keyEventPostProcess(); theKeyMap->release(); } } const unsigned char * IOHIKeyboard::defaultKeymapOfLength(UInt32 * length) { *length = 0; return NULL; } void IOHIKeyboard::setAlphaLockFeedback(bool /* val */) { return; } void IOHIKeyboard::setNumLockFeedback(bool /* val */) { return; } UInt32 IOHIKeyboard::maxKeyCodes() { return( 0x80); } bool IOHIKeyboard:: doesKeyLock ( unsigned key) { return false; } unsigned IOHIKeyboard:: getLEDStatus () { return 0; } bool IOHIKeyboard::open(IOService * client, IOOptionBits options, KeyboardEventAction keAction, KeyboardSpecialEventAction kseAction, UpdateEventFlagsAction uefAction) { if ( (!_keyMap) && (!resetKeyboard())) return false; if (client == this) { KeyboardReserved *tempReservedStruct; tempReservedStruct = GetKeyboardReservedStructEventForService(this); return super::open((tempReservedStruct) ? tempReservedStruct->openClient : 0, options); } return open(client, options, 0, (KeyboardEventCallback)keAction, (KeyboardSpecialEventCallback)kseAction, (UpdateEventFlagsCallback)uefAction); } bool IOHIKeyboard::open( IOService * client, IOOptionBits options, void * /*refcon*/, KeyboardEventCallback keCallback, KeyboardSpecialEventCallback kseCallback, UpdateEventFlagsCallback uefCallback) { if (client == this) return true; KeyboardReserved *tempReservedStruct; tempReservedStruct = GetKeyboardReservedStructEventForService(this); if (tempReservedStruct) tempReservedStruct->openClient = client; bool returnValue = open(this, options, (KeyboardEventAction)_keyboardEvent, (KeyboardSpecialEventAction)_keyboardSpecialEvent, (UpdateEventFlagsAction)_updateEventFlags); if (!returnValue) return false; // point the new keymap to the IOHIDSystem, so it can set properties in it // this handles the case where although resetKeyboard is called above, // _keyboardEventTarget is as yet unset, so zero is passed if (_keyMap) _keyMap->setKeyboardTarget(client); // Note: client object is already retained by superclass' open() _keyboardEventTarget = client; _keyboardEventAction = (KeyboardEventAction)keCallback; _keyboardSpecialEventTarget = client; _keyboardSpecialEventAction = (KeyboardSpecialEventAction)kseCallback; _updateEventFlagsTarget = client; _updateEventFlagsAction = (UpdateEventFlagsAction)uefCallback; return true; } void IOHIKeyboard::close(IOService * client, IOOptionBits) { // kill autorepeat task if (_codeToRepeat != -1) { AbsoluteTime ts; clock_get_uptime(&ts); dispatchKeyboardEvent(_codeToRepeat, false, ts); } // clear modifiers to avoid stuck keys setAlphaLock(false); _updateEventFlags(this, 0); _eventFlags = 0; _keyboardSpecialEvent( this, NX_SYSDEFINED, _eventFlags, NX_NOSPECIALKEY, NX_SUBTYPE_STICKYKEYS_RELEASE, _guid, 0, _lastEventTime); bzero(_keyState, _keyStateSize); _keyboardEventAction = NULL; _keyboardEventTarget = 0; _keyboardSpecialEventAction = NULL; _keyboardSpecialEventTarget = 0; _updateEventFlagsAction = NULL; _updateEventFlagsTarget = 0; super::close(client); } IOReturn IOHIKeyboard::message( UInt32 type, IOService * provider, void * argument) { IOReturn ret = kIOReturnSuccess; switch(type) { case kIOHIDSystem508MouseClickMessage: if (_keyMap) ret = _keyMap->message(type, this); break; case kIOHIDSystemDeviceSeizeRequestMessage: if (OSDynamicCast(IOHIDDevice, provider)) { KeyboardReserved *tempReservedStruct = GetKeyboardReservedStructEventForService(this); if (tempReservedStruct) { tempReservedStruct->isSeized = (bool)argument; } } break; default: ret = super::message(type, provider, argument); break; } return ret; } void IOHIKeyboard::_keyboardEvent( IOHIKeyboard * self, unsigned eventType, /* flags */ unsigned flags, /* keyCode */ unsigned key, /* charCode */ unsigned charCode, /* charSet */ unsigned charSet, /* originalCharCode */ unsigned origCharCode, /* originalCharSet */ unsigned origCharSet, /* keyboardType */ unsigned keyboardType, /* repeat */ bool repeat, /* atTime */ AbsoluteTime ts) { KeyboardEventCallback keCallback; keCallback = (KeyboardEventCallback)self->_keyboardEventAction; if ( !keCallback ) return; (*keCallback)( self->_keyboardEventTarget, eventType, flags, key, charCode, charSet, origCharCode, origCharSet, keyboardType, repeat, ts, self, 0); } void IOHIKeyboard::_keyboardSpecialEvent( IOHIKeyboard * self, unsigned eventType, /* flags */ unsigned flags, /* keyCode */ unsigned key, /* specialty */ unsigned flavor, /* guid */ UInt64 guid, /* repeat */ bool repeat, /* atTime */ AbsoluteTime ts) { KeyboardSpecialEventCallback kseCallback; kseCallback = (KeyboardSpecialEventCallback)self->_keyboardSpecialEventAction; if ( !kseCallback ) return; (*kseCallback)( self->_keyboardEventTarget, eventType, flags, key, flavor, guid, repeat, ts, self, 0); } void IOHIKeyboard::_updateEventFlags( IOHIKeyboard * self, unsigned flags) { UpdateEventFlagsCallback uefCallback; uefCallback = (UpdateEventFlagsCallback)self->_updateEventFlagsAction; if ( !uefCallback ) return; (*uefCallback)( self->_updateEventFlagsTarget, flags, self, 0); }