]> git.saurik.com Git - apple/xnu.git/blob - iokit/Families/IOHIDSystem/IOHIKeyboard.cpp
f0f9c14b5e11c2514d4c282030e99d6e344c98d4
[apple/xnu.git] / iokit / Families / IOHIDSystem / IOHIKeyboard.cpp
1 /*
2 * Copyright (c) 1998-2000 Apple Computer, Inc. All rights reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
6 * The contents of this file constitute Original Code as defined in and
7 * are subject to the Apple Public Source License Version 1.1 (the
8 * "License"). You may not use this file except in compliance with the
9 * License. Please obtain a copy of the License at
10 * http://www.apple.com/publicsource and read it before using this file.
11 *
12 * This Original Code and all software distributed under the License are
13 * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
14 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
15 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the
17 * License for the specific language governing rights and limitations
18 * under the License.
19 *
20 * @APPLE_LICENSE_HEADER_END@
21 */
22 /*
23 *
24 * From EventSrcPCKeyoard.m - PC Keyboard EventSrc subclass implementation
25 * Copyright (c) 1992 NeXT Computer, Inc. All rights reserved.
26 * 20-Dec-00 bubba Save global repeat and delay values when
27 * devices are unplugged. Restore when device is reset.
28 * 24-Jan-01 bubba Don't auto-repeat on Power Key. This prevents infinite power key
29 * events from being generated when this key is hit on ADB keyboards.
30 */
31
32 #include <IOKit/IOLib.h>
33 #include <IOKit/hidsystem/IOHIKeyboard.h>
34 #include <IOKit/hidsystem/IOHIKeyboardMapper.h>
35 #include <IOKit/hidsystem/IOLLEvent.h>
36 #include <IOKit/hidsystem/IOHIDParameter.h>
37
38 AbsoluteTime gKeyRepeat = { 0 }; // Delay between key repeats
39 AbsoluteTime gInitialKeyRepeat = { 0 }; // Delay before initial key repeat
40
41 #define super IOHIDevice
42 OSDefineMetaClassAndStructors(IOHIKeyboard, IOHIDevice);
43
44 bool IOHIKeyboard::init(OSDictionary * properties)
45 {
46 if (!super::init(properties)) return false;
47
48 /*
49 * Initialize minimal state.
50 */
51
52 _deviceLock = IOLockAlloc();
53 _keyMap = 0;
54 _keyStateSize = 4*((maxKeyCodes()+(EVK_BITS_PER_UNIT-1))/EVK_BITS_PER_UNIT);
55 _keyState = (UInt32 *) IOMalloc(_keyStateSize);
56
57 if (!_deviceLock || !_keyState) return false;
58
59 IOLockInit(_deviceLock);
60 bzero(_keyState, _keyStateSize);
61
62 return true;
63 }
64
65 bool IOHIKeyboard::start(IOService * provider)
66 {
67 if (!super::start(provider)) return false;
68
69 /*
70 * IOHIKeyboard serves both as a service and a nub (we lead a double
71 * life). Register ourselves as a nub to kick off matching.
72 */
73
74 registerService();
75
76 return true;
77 }
78
79 void IOHIKeyboard::free()
80 // Description: Go Away. Be careful when freeing the lock.
81 {
82 IOLock * lock = NULL;
83
84 // Save repeat rate and delay, so when we are replugged we'll be ready
85 // with the right values.
86 //
87 gKeyRepeat = _keyRepeat;
88 gInitialKeyRepeat = _initialKeyRepeat;
89
90 if ( _deviceLock )
91 {
92 lock = _deviceLock;
93 IOTakeLock( lock);
94 _deviceLock = NULL;
95 }
96 if ( _keyMap )
97 _keyMap->release();
98 if( _keyState )
99 IOFree( _keyState, _keyStateSize);
100 if ( lock )
101 {
102 IOUnlock( lock);
103 IOLockFree( lock);
104 }
105 super::free();
106 }
107
108 IOHIDKind IOHIKeyboard::hidKind()
109 {
110 return kHIKeyboardDevice;
111 }
112
113 bool IOHIKeyboard::updateProperties( void )
114 {
115 UInt64 keyRepeatNano;
116 UInt64 initialKeyRepeatNano;
117 bool ok;
118
119 absolutetime_to_nanoseconds( _keyRepeat, &keyRepeatNano);
120 absolutetime_to_nanoseconds( _initialKeyRepeat, &initialKeyRepeatNano);
121
122 ok = setProperty( kIOHIDKeyMappingKey, _keyMap )
123 & setProperty( kIOHIDKeyRepeatKey, &keyRepeatNano,
124 sizeof(keyRepeatNano))
125 & setProperty( kIOHIDInitialKeyRepeatKey, &initialKeyRepeatNano,
126 sizeof(initialKeyRepeatNano));
127
128 return( ok & super::updateProperties() );
129 }
130
131 IOReturn IOHIKeyboard::setParamProperties( OSDictionary * dict )
132 {
133 OSData * data;
134 IOReturn err = kIOReturnSuccess;
135 unsigned char * map;
136 IOHIKeyboardMapper * oldMap;
137 bool updated = false;
138 UInt64 nano;
139 IOTakeLock( _deviceLock);
140
141 if( (data = OSDynamicCast( OSData,
142 dict->getObject(kIOHIDKeyRepeatKey)))) {
143
144 nano = *((UInt64 *)(data->getBytesNoCopy()));
145 if( nano < EV_MINKEYREPEAT)
146 nano = EV_MINKEYREPEAT;
147 nanoseconds_to_absolutetime(nano, &_keyRepeat);
148 updated = true;
149 }
150
151 if( (data = OSDynamicCast( OSData,
152 dict->getObject(kIOHIDInitialKeyRepeatKey)))) {
153
154 nano = *((UInt64 *)(data->getBytesNoCopy()));
155 if( nano < EV_MINKEYREPEAT)
156 nano = EV_MINKEYREPEAT;
157 nanoseconds_to_absolutetime(nano, &_initialKeyRepeat);
158 updated = true;
159 }
160
161 if( (data = OSDynamicCast( OSData, dict->getObject(kIOHIDKeyMappingKey)))) {
162
163 map = (unsigned char *)IOMalloc( data->getLength() );
164 bcopy( data->getBytesNoCopy(), map, data->getLength() );
165 oldMap = _keyMap;
166 _keyMap = IOHIKeyboardMapper::keyboardMapper(this, map, data->getLength(), true);
167 if (_keyMap) {
168 if (oldMap)
169 oldMap->release();
170 updated = true;
171 } else {
172 _keyMap = oldMap;
173 err = kIOReturnBadArgument;
174 }
175 }
176 IOUnlock( _deviceLock);
177
178 if( dict->getObject(kIOHIDResetKeyboardKey))
179 resetKeyboard();
180
181 if( updated )
182 updateProperties();
183
184 return( err );
185 }
186
187 bool IOHIKeyboard::resetKeyboard()
188 // Description: Reset the keymapping to the default value and reconfigure
189 // the keyboards.
190 {
191 const unsigned char *defaultKeymap;
192 UInt32 defaultKeymapLength;
193
194 IOTakeLock( _deviceLock);
195
196 if ( _keyMap )
197 _keyMap->release();
198
199 // Set up default keymapping.
200 defaultKeymap = defaultKeymapOfLength(&defaultKeymapLength);
201
202 _keyMap = IOHIKeyboardMapper::keyboardMapper( this,
203 defaultKeymap,
204 defaultKeymapLength,
205 false );
206 if (_keyMap)
207 {
208 clock_interval_to_absolutetime_interval( EV_DEFAULTKEYREPEAT,
209 kNanosecondScale, &_keyRepeat);
210 clock_interval_to_absolutetime_interval( EV_DEFAULTINITIALREPEAT,
211 kNanosecondScale, &_initialKeyRepeat);
212 }
213
214 // Use our globals if valid. That way, if we are unplugged and replugged, we'll
215 // have the proper values, instead of the lame default values.
216 //
217 if( gKeyRepeat.lo > 0 ) _keyRepeat = gKeyRepeat;
218 if( gInitialKeyRepeat.lo > 0 ) _initialKeyRepeat = gInitialKeyRepeat;
219
220 updateProperties();
221
222 _interfaceType = interfaceID();
223 _deviceType = deviceType();
224 _guid = getGUID();
225
226 IOUnlock( _deviceLock);
227 return (_keyMap) ? true : false;
228 }
229
230 void IOHIKeyboard::scheduleAutoRepeat()
231 // Description: Schedule a procedure to be called when a timeout has expired
232 // so that we can generate a repeated key.
233 // Preconditions:
234 // * _deviceLock should be held on entry
235 {
236 if ( _calloutPending == true )
237 {
238 thread_call_func_cancel(_autoRepeat, this, true);
239 _calloutPending = false;
240 }
241 if ( AbsoluteTime_to_scalar(&_downRepeatTime) )
242 {
243 AbsoluteTime deadline;
244 clock_absolutetime_interval_to_deadline(_downRepeatTime, &deadline);
245 thread_call_func_delayed(_autoRepeat, this, deadline);
246 _calloutPending = true;
247 }
248 }
249
250 void IOHIKeyboard::_autoRepeat(thread_call_param_t arg,
251 thread_call_param_t) /* thread_call_func_t */
252 {
253 IOHIKeyboard *self = (IOHIKeyboard *) arg;
254 self->autoRepeat();
255 }
256
257 void IOHIKeyboard::autoRepeat()
258 // Description: Repeat the currently pressed key and schedule ourselves
259 // to be called again after another interval elapses.
260 // Preconditions:
261 // * Should only be executed on callout thread
262 // * _deviceLock should be unlocked on entry.
263 {
264 IOTakeLock( _deviceLock);
265 if ( _calloutPending == false )
266 {
267 IOUnlock( _deviceLock);
268 return;
269 }
270 _calloutPending = false;
271 _isRepeat = true;
272
273 if ( AbsoluteTime_to_scalar(&_downRepeatTime) )
274 {
275 // Device is due to generate a repeat
276 if (_keyMap) _keyMap->translateKeyCode(_codeToRepeat,
277 /* direction */ true,
278 /* keyBits */ _keyState);
279 _downRepeatTime = _keyRepeat;
280 }
281
282 _isRepeat = false;
283 scheduleAutoRepeat();
284 IOUnlock( _deviceLock);
285 }
286
287 void IOHIKeyboard::setRepeat(unsigned eventType, unsigned keyCode)
288 // Description: Set up or tear down key repeat operations. The method
289 // that locks _deviceLock is a bit higher on the call stack.
290 // This method is invoked as a side effect of our own
291 // invocation of _keyMap->translateKeyCode().
292 // Preconditions:
293 // * _deviceLock should be held upon entry.
294 {
295 if ( _isRepeat == false ) // make sure we're not already repeating
296 {
297 if (eventType == NX_KEYDOWN) // Start repeat
298 {
299 // Set this key to repeat (push out last key if present)
300 _downRepeatTime = _initialKeyRepeat; // + _lastEventTime;
301 _codeToRepeat = keyCode;
302 // reschedule key repeat event here
303 scheduleAutoRepeat();
304 }
305 else if (eventType == NX_KEYUP) // End repeat
306 {
307 /* Remove from downKey */
308 if (_codeToRepeat == keyCode)
309 {
310 AbsoluteTime_to_scalar(&_downRepeatTime) = 0;
311 _codeToRepeat = (unsigned)-1;
312 scheduleAutoRepeat();
313 }
314 }
315 }
316 }
317
318 //
319 // BEGIN: Implementation of the methods required by IOHIKeyboardMapper.
320 //
321
322 void IOHIKeyboard::keyboardEvent(unsigned eventType,
323 /* flags */ unsigned flags,
324 /* keyCode */ unsigned keyCode,
325 /* charCode */ unsigned charCode,
326 /* charSet */ unsigned charSet,
327 /* originalCharCode */ unsigned origCharCode,
328 /* originalCharSet */ unsigned origCharSet)
329 // Description: We use this notification to set up our _keyRepeat timer
330 // and to pass along the event to our owner. This method
331 // will be called while the KeyMap object is processing
332 // the key code we've sent it using deliverKey.
333 {
334
335 if (_keyboardEventAction) /* upstream call */
336 {
337 (*_keyboardEventAction)(_keyboardEventTarget,
338 eventType,
339 /* flags */ flags,
340 /* keyCode */ keyCode,
341 /* charCode */ charCode,
342 /* charSet */ charSet,
343 /* originalCharCode */ origCharCode,
344 /* originalCharSet */ origCharSet,
345 /* keyboardType */ _deviceType,
346 /* repeat */ _isRepeat,
347 /* atTime */ _lastEventTime);
348 }
349
350
351 if( keyCode == _keyMap->getParsedSpecialKey(NX_KEYTYPE_CAPS_LOCK) ||
352 keyCode == _keyMap->getParsedSpecialKey(NX_POWER_KEY) )
353 {
354 //Don't repeat caps lock on ADB/USB. 0x39 is default ADB code.
355 // We are here because KeyCaps needs to see 0x39 as a real key,
356 // not just another modifier bit.
357
358 if (_interfaceType == NX_EVS_DEVICE_INTERFACE_ADB)
359 {
360 return;
361 }
362 }
363
364 // Set up key repeat operations here.
365 setRepeat(eventType, keyCode);
366 }
367
368 void IOHIKeyboard::keyboardSpecialEvent(unsigned eventType,
369 /* flags */ unsigned flags,
370 /* keyCode */ unsigned keyCode,
371 /* specialty */ unsigned flavor)
372 // Description: See the description for keyboardEvent.
373 {
374
375 if (_keyboardSpecialEventAction) /* upstream call */
376 {
377 (*_keyboardSpecialEventAction)(_keyboardSpecialEventTarget,
378 eventType,
379 /* flags */ flags,
380 /* keyCode */ keyCode,
381 /* specialty */ flavor,
382 /* guid */ _guid,
383 /* repeat */ _isRepeat,
384 /* atTime */ _lastEventTime);
385 }
386
387 // Set up key repeat operations here.
388
389 // Don't repeat caps lock, numlock or power key.
390 //
391 if ( (flavor != NX_KEYTYPE_CAPS_LOCK) && (flavor != NX_KEYTYPE_NUM_LOCK) &&
392 (flavor != NX_POWER_KEY) )
393 {
394 setRepeat(eventType, keyCode);
395 }
396 }
397
398 void IOHIKeyboard::updateEventFlags(unsigned flags)
399 // Description: Process non-event-generating flag changes. Simply pass this
400 // along to our owner.
401 {
402 if (_updateEventFlagsAction) /* upstream call */
403 {
404 (*_updateEventFlagsAction)(_updateEventFlagsTarget, flags);
405 }
406 }
407
408 unsigned IOHIKeyboard::eventFlags()
409 // Description: Return global event flags In this world, there is only
410 // one keyboard device so device flags == global flags.
411 {
412 return _eventFlags;
413 }
414
415 unsigned IOHIKeyboard::deviceFlags()
416 // Description: Return per-device event flags. In this world, there is only
417 // one keyboard device so device flags == global flags.
418 {
419 return _eventFlags;
420 }
421
422 void IOHIKeyboard::setDeviceFlags(unsigned flags)
423 // Description: Set device event flags. In this world, there is only
424 // one keyboard device so device flags == global flags.
425 {
426 _eventFlags = flags;
427 }
428
429 bool IOHIKeyboard::alphaLock()
430 // Description: Return current alpha-lock state. This is a state tracking
431 // callback used by the KeyMap object.
432 {
433 return _alphaLock;
434 }
435
436 void IOHIKeyboard::setAlphaLock(bool val)
437 // Description: Set current alpha-lock state This is a state tracking
438 // callback used by the KeyMap object.
439 {
440 _alphaLock = val;
441 setAlphaLockFeedback(val);
442 }
443
444 bool IOHIKeyboard::numLock()
445 {
446 return _numLock;
447 }
448
449 void IOHIKeyboard::setNumLock(bool val)
450 {
451 _numLock = val;
452 setNumLockFeedback(val);
453 }
454
455 bool IOHIKeyboard::charKeyActive()
456 // Description: Return true If a character generating key down This is a state
457 // tracking callback used by the KeyMap object.
458 {
459 return _charKeyActive;
460 }
461
462 void IOHIKeyboard::setCharKeyActive(bool val)
463 // Description: Note whether a char generating key is down. This is a state
464 // tracking callback used by the KeyMap object.
465 {
466 _charKeyActive = val;
467 }
468 //
469 // END: Implementation of the methods required by IOHIKeyboardMapper.
470 //
471
472 void IOHIKeyboard::dispatchKeyboardEvent(unsigned int keyCode,
473 /* direction */ bool goingDown,
474 /* timeStamp */ AbsoluteTime time)
475 // Description: This method is the heart of event dispatching. The overlying
476 // subclass invokes this method with each event. We then
477 // get the event xlated and dispatched using a _keyMap instance.
478 // The event structure passed in by reference should not be freed.
479 {
480 _lastEventTime = time;
481
482 IOTakeLock( _deviceLock);
483
484 if (_keyMap) _keyMap->translateKeyCode(keyCode,
485 /* direction */ goingDown,
486 /* keyBits */ _keyState);
487 IOUnlock( _deviceLock);
488 }
489
490 const unsigned char * IOHIKeyboard::defaultKeymapOfLength(UInt32 * length)
491 {
492 *length = 0;
493 return NULL;
494 }
495
496 void IOHIKeyboard::setAlphaLockFeedback(bool /* val */)
497 {
498 return;
499 }
500
501 void IOHIKeyboard::setNumLockFeedback(bool /* val */)
502 {
503 return;
504 }
505
506 UInt32 IOHIKeyboard::maxKeyCodes()
507 {
508 return( 0x80);
509 }
510
511 bool IOHIKeyboard:: doesKeyLock ( unsigned key)
512 {
513 return false;
514 }
515
516 unsigned IOHIKeyboard:: getLEDStatus ()
517 {
518 return 0;
519 }
520
521
522 bool IOHIKeyboard::open(IOService * client,
523 IOOptionBits options,
524 KeyboardEventAction keAction,
525 KeyboardSpecialEventAction kseAction,
526 UpdateEventFlagsAction uefAction)
527 {
528 if ( (!_keyMap) && (!resetKeyboard())) return false;
529
530 // IOLog("***open -- gKeyRepeat.lo = %08lx\n", gKeyRepeat.lo );
531 // IOLog("***open -- gInitialKeyRepeat.lo = %08lx\n", gInitialKeyRepeat.lo );
532
533 if (super::open(client, options))
534 {
535 // Note: client object is already retained by superclass' open()
536 _keyboardEventTarget = client;
537 _keyboardEventAction = keAction;
538 _keyboardSpecialEventTarget = client;
539 _keyboardSpecialEventAction = kseAction;
540 _updateEventFlagsTarget = client;
541 _updateEventFlagsAction = uefAction;
542
543 return true;
544 }
545
546 return false;
547 }
548
549 void IOHIKeyboard::close(IOService * client, IOOptionBits)
550 {
551 // IOLog("***close -- gKeyRepeat.lo = %08lx\n", gKeyRepeat.lo );
552 // IOLog("***close -- gInitialKeyRepeat.lo = %08lx\n", gInitialKeyRepeat.lo );
553
554 // Save repeat rate and delay, so when we are replugged we'll be ready
555 // with the right values.
556 //
557 gKeyRepeat = _keyRepeat;
558 gInitialKeyRepeat = _initialKeyRepeat;
559
560 // kill autorepeat task
561 AbsoluteTime_to_scalar(&_downRepeatTime) = 0;
562 _codeToRepeat = (unsigned)-1;
563 scheduleAutoRepeat();
564 // clear modifiers to avoid stuck keys
565 setAlphaLock(false);
566 if (_updateEventFlagsAction)
567 (*_updateEventFlagsAction)(_updateEventFlagsTarget, 0); _eventFlags = 0;
568 bzero(_keyState, _keyStateSize);
569
570 _keyboardEventAction = NULL;
571 _keyboardEventTarget = 0;
572 _keyboardSpecialEventAction = NULL;
573 _keyboardSpecialEventTarget = 0;
574 _updateEventFlagsAction = NULL;
575 _updateEventFlagsTarget = 0;
576
577 super::close(client);
578 }
579