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