|
|
1.1 root 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: */
27:
28: #include <IOKit/IOLib.h>
29: #include <IOKit/hidsystem/IOHIKeyboard.h>
30: #include <IOKit/hidsystem/IOHIKeyboardMapper.h>
31: #include <IOKit/hidsystem/IOLLEvent.h>
32: #include <IOKit/hidsystem/IOHIDParameter.h>
33:
34: #define super IOHIDevice
35: OSDefineMetaClassAndStructors(IOHIKeyboard, IOHIDevice);
36:
37: bool IOHIKeyboard::init(OSDictionary * properties)
38: {
39: if (!super::init(properties)) return false;
40:
41: /*
42: * Initialize minimal state.
43: */
44:
45: _deviceLock = IOLockAlloc();
46: _keyMap = 0;
47: _keyStateSize = 4*((maxKeyCodes()+(EVK_BITS_PER_UNIT-1))/EVK_BITS_PER_UNIT);
48: _keyState = (UInt32 *) IOMalloc(_keyStateSize);
49:
50: if (!_deviceLock || !_keyState) return false;
51:
52: IOLockInit(_deviceLock);
53: bzero(_keyState, _keyStateSize);
54:
55: return true;
56: }
57:
58: bool IOHIKeyboard::start(IOService * provider)
59: {
60: if (!super::start(provider)) return false;
61:
62: /*
63: * IOHIKeyboard serves both as a service and a nub (we lead a double
64: * life). Register ourselves as a nub to kick off matching.
65: */
66:
67: registerService();
68:
69: return true;
70: }
71:
72: void IOHIKeyboard::free()
73: // Description: Go Away. Be careful when freeing the lock.
74: {
75: IOLock * lock = NULL;
76:
77: if ( _deviceLock )
78: {
79: lock = _deviceLock;
80: IOTakeLock( lock);
81: _deviceLock = NULL;
82: }
83: if ( _keyMap )
84: _keyMap->release();
85: if( _keyState )
86: IOFree( _keyState, _keyStateSize);
87: if ( lock )
88: {
89: IOUnlock( lock);
90: IOLockFree( lock);
91: }
92: super::free();
93: }
94:
95: IOHIDKind IOHIKeyboard::hidKind()
96: {
97: return kHIKeyboardDevice;
98: }
99:
100: bool IOHIKeyboard::updateProperties( void )
101: {
102: UInt64 keyRepeatNano;
103: UInt64 initialKeyRepeatNano;
104: bool ok;
105:
106: absolutetime_to_nanoseconds( _keyRepeat, &keyRepeatNano);
107: absolutetime_to_nanoseconds( _initialKeyRepeat, &initialKeyRepeatNano);
108:
109: ok = setProperty( kIOHIDKeyMappingKey, _keyMap )
110: & setProperty( kIOHIDKeyRepeatKey, &keyRepeatNano,
111: sizeof(keyRepeatNano))
112: & setProperty( kIOHIDInitialKeyRepeatKey, &initialKeyRepeatNano,
113: sizeof(initialKeyRepeatNano));
114:
115: return( ok & super::updateProperties() );
116: }
117:
118: IOReturn IOHIKeyboard::setParamProperties( OSDictionary * dict )
119: {
120: OSData * data;
121: IOReturn err = kIOReturnSuccess;
122: unsigned char * map;
123: IOHIKeyboardMapper * oldMap;
124: bool updated = false;
125: UInt64 nano;
126: IOTakeLock( _deviceLock);
127:
128: if( (data = OSDynamicCast( OSData,
129: dict->getObject(kIOHIDKeyRepeatKey)))) {
130:
131: nano = *((UInt64 *)(data->getBytesNoCopy()));
132: if( nano < EV_MINKEYREPEAT)
133: nano = EV_MINKEYREPEAT;
134: nanoseconds_to_absolutetime(nano, &_keyRepeat);
135: updated = true;
136: }
137:
138: if( (data = OSDynamicCast( OSData,
139: dict->getObject(kIOHIDInitialKeyRepeatKey)))) {
140:
141: nano = *((UInt64 *)(data->getBytesNoCopy()));
142: if( nano < EV_MINKEYREPEAT)
143: nano = EV_MINKEYREPEAT;
144: nanoseconds_to_absolutetime(nano, &_initialKeyRepeat);
145: updated = true;
146: }
147:
148: if( (data = OSDynamicCast( OSData, dict->getObject(kIOHIDKeyMappingKey)))) {
149:
150: map = (unsigned char *)IOMalloc( data->getLength() );
151: bcopy( data->getBytesNoCopy(), map, data->getLength() );
152: oldMap = _keyMap;
153: _keyMap = IOHIKeyboardMapper::keyboardMapper(this, map, data->getLength(), true);
154: if (_keyMap) {
155: if (oldMap)
156: oldMap->release();
157: updated = true;
158: } else {
159: _keyMap = oldMap;
160: err = kIOReturnBadArgument;
161: }
162: }
163: IOUnlock( _deviceLock);
164:
165: if( dict->getObject(kIOHIDResetKeyboardKey))
166: resetKeyboard();
167:
168: if( updated )
169: updateProperties();
170:
171: return( err );
172: }
173:
174: bool IOHIKeyboard::resetKeyboard()
175: // Description: Reset the keymapping to the default value and reconfigure
176: // the keyboards.
177: {
178: const unsigned char *defaultKeymap;
179: UInt32 defaultKeymapLength;
180:
181: IOTakeLock( _deviceLock);
182:
183: if ( _keyMap )
184: _keyMap->release();
185:
186: // Set up default keymapping.
187: defaultKeymap = defaultKeymapOfLength(&defaultKeymapLength);
188:
189: _keyMap = IOHIKeyboardMapper::keyboardMapper( this,
190: defaultKeymap,
191: defaultKeymapLength,
192: false );
193: if (_keyMap)
194: {
195: clock_interval_to_absolutetime_interval( EV_DEFAULTKEYREPEAT,
196: kNanosecondScale, &_keyRepeat);
197: clock_interval_to_absolutetime_interval( EV_DEFAULTINITIALREPEAT,
198: kNanosecondScale, &_initialKeyRepeat);
199: }
200:
201: updateProperties();
202:
203: IOUnlock( _deviceLock);
204: return (_keyMap) ? true : false;
205: }
206:
207: void IOHIKeyboard::scheduleAutoRepeat()
208: // Description: Schedule a procedure to be called when a timeout has expired
209: // so that we can generate a repeated key.
210: // Preconditions:
211: // * _deviceLock should be held on entry
212: {
213: if ( _calloutPending == true )
214: {
215: thread_call_func_cancel(_autoRepeat, this, true);
216: _calloutPending = false;
217: }
218: if ( AbsoluteTime_to_scalar(&_downRepeatTime) )
219: {
220: AbsoluteTime deadline;
221: clock_absolutetime_interval_to_deadline(_downRepeatTime, &deadline);
222: thread_call_func_delayed(_autoRepeat, this, deadline);
223: _calloutPending = true;
224: }
225: }
226:
227: void IOHIKeyboard::_autoRepeat(thread_call_param_t arg,
228: thread_call_param_t) /* thread_call_func_t */
229: {
230: IOHIKeyboard *self = (IOHIKeyboard *) arg;
231: self->autoRepeat();
232: }
233:
234: void IOHIKeyboard::autoRepeat()
235: // Description: Repeat the currently pressed key and schedule ourselves
236: // to be called again after another interval elapses.
237: // Preconditions:
238: // * Should only be executed on callout thread
239: // * _deviceLock should be unlocked on entry.
240: {
241: IOTakeLock( _deviceLock);
242: if ( _calloutPending == false )
243: {
244: IOUnlock( _deviceLock);
245: return;
246: }
247: _calloutPending = false;
248: _isRepeat = true;
249:
250: if ( AbsoluteTime_to_scalar(&_downRepeatTime) )
251: {
252: // Device is due to generate a repeat
253: if (_keyMap) _keyMap->translateKeyCode(_codeToRepeat,
254: /* direction */ true,
255: /* keyBits */ _keyState);
256: _downRepeatTime = _keyRepeat;
257: }
258:
259: _isRepeat = false;
260: scheduleAutoRepeat();
261: IOUnlock( _deviceLock);
262: }
263:
264: void IOHIKeyboard::setRepeat(unsigned eventType, unsigned keyCode)
265: // Description: Set up or tear down key repeat operations. The method
266: // that locks _deviceLock is a bit higher on the call stack.
267: // This method is invoked as a side effect of our own
268: // invocation of _keyMap->translateKeyCode().
269: // Preconditions:
270: // * _deviceLock should be held upon entry.
271: {
272: if ( _isRepeat == false ) // make sure we're not already repeating
273: {
274: if (eventType == NX_KEYDOWN) // Start repeat
275: {
276: // Set this key to repeat (push out last key if present)
277: _downRepeatTime = _initialKeyRepeat; // + _lastEventTime;
278: _codeToRepeat = keyCode;
279: // reschedule key repeat event here
280: scheduleAutoRepeat();
281: }
282: else if (eventType == NX_KEYUP) // End repeat
283: {
284: /* Remove from downKey */
285: if (_codeToRepeat == keyCode)
286: {
287: AbsoluteTime_to_scalar(&_downRepeatTime) = 0;
288: _codeToRepeat = (unsigned)-1;
289: scheduleAutoRepeat();
290: }
291: }
292: }
293: }
294:
295: //
296: // BEGIN: Implementation of the methods required by IOHIKeyboardMapper.
297: //
298:
299: void IOHIKeyboard::keyboardEvent(unsigned eventType,
300: /* flags */ unsigned flags,
301: /* keyCode */ unsigned keyCode,
302: /* charCode */ unsigned charCode,
303: /* charSet */ unsigned charSet,
304: /* originalCharCode */ unsigned origCharCode,
305: /* originalCharSet */ unsigned origCharSet)
306: // Description: We use this notification to set up our _keyRepeat timer
307: // and to pass along the event to our owner. This method
308: // will be called while the KeyMap object is processing
309: // the key code we've sent it using deliverKey.
310: {
311:
312: if (_keyboardEventAction) /* upstream call */
313: {
314: (*_keyboardEventAction)(_keyboardEventTarget,
315: eventType,
316: /* flags */ flags,
317: /* keyCode */ keyCode,
318: /* charCode */ charCode,
319: /* charSet */ charSet,
320: /* originalCharCode */ origCharCode,
321: /* originalCharSet */ origCharSet,
322: /* repeat */ _isRepeat,
323: /* atTime */ _lastEventTime);
324: }
325:
326: // Set up key repeat operations here.
327: setRepeat(eventType, keyCode);
328: }
329:
330: void IOHIKeyboard::keyboardSpecialEvent(unsigned eventType,
331: /* flags */ unsigned flags,
332: /* keyCode */ unsigned keyCode,
333: /* specialty */ unsigned flavor)
334: // Description: See the description for keyboardEvent.
335: {
336:
337: if (_keyboardSpecialEventAction) /* upstream call */
338: {
339: (*_keyboardSpecialEventAction)(_keyboardSpecialEventTarget,
340: eventType,
341: /* flags */ flags,
342: /* keyCode */ keyCode,
343: /* specialty */ flavor,
344: /* atTime */ _lastEventTime);
345: }
346:
347: // Set up key repeat operations here.
348: if (flavor != NX_KEYTYPE_CAPS_LOCK)
349: setRepeat(eventType, keyCode);
350: }
351:
352: void IOHIKeyboard::updateEventFlags(unsigned flags)
353: // Description: Process non-event-generating flag changes. Simply pass this
354: // along to our owner.
355: {
356: if (_updateEventFlagsAction) /* upstream call */
357: {
358: (*_updateEventFlagsAction)(_updateEventFlagsTarget, flags);
359: }
360: }
361:
362: unsigned IOHIKeyboard::eventFlags()
363: // Description: Return global event flags In this world, there is only
364: // one keyboard device so device flags == global flags.
365: {
366: return _eventFlags;
367: }
368:
369: unsigned IOHIKeyboard::deviceFlags()
370: // Description: Return per-device event flags. In this world, there is only
371: // one keyboard device so device flags == global flags.
372: {
373: return _eventFlags;
374: }
375:
376: void IOHIKeyboard::setDeviceFlags(unsigned flags)
377: // Description: Set device event flags. In this world, there is only
378: // one keyboard device so device flags == global flags.
379: {
380: _eventFlags = flags;
381: }
382:
383: bool IOHIKeyboard::alphaLock()
384: // Description: Return current alpha-lock state. This is a state tracking
385: // callback used by the KeyMap object.
386: {
387: return _alphaLock;
388: }
389:
390: void IOHIKeyboard::setAlphaLock(bool val)
391: // Description: Set current alpha-lock state This is a state tracking
392: // callback used by the KeyMap object.
393: {
394: _alphaLock = val;
395: setAlphaLockFeedback(val);
396: }
397:
398: bool IOHIKeyboard::charKeyActive()
399: // Description: Return true If a character generating key down This is a state
400: // tracking callback used by the KeyMap object.
401: {
402: return _charKeyActive;
403: }
404:
405: void IOHIKeyboard::setCharKeyActive(bool val)
406: // Description: Note whether a char generating key is down. This is a state
407: // tracking callback used by the KeyMap object.
408: {
409: _charKeyActive = val;
410: }
411: //
412: // END: Implementation of the methods required by IOHIKeyboardMapper.
413: //
414:
415: void IOHIKeyboard::dispatchKeyboardEvent(unsigned int keyCode,
416: /* direction */ bool goingDown,
417: /* timeStamp */ AbsoluteTime time)
418: // Description: This method is the heart of event dispatching. The overlying
419: // subclass invokes this method with each event. We then
420: // get the event xlated and dispatched using a _keyMap instance.
421: // The event structure passed in by reference should not be freed.
422: {
423: _lastEventTime = time;
424:
425: IOTakeLock( _deviceLock);
426:
427: if (_keyMap) _keyMap->translateKeyCode(keyCode,
428: /* direction */ goingDown,
429: /* keyBits */ _keyState);
430: IOUnlock( _deviceLock);
431: }
432:
433: const unsigned char * IOHIKeyboard::defaultKeymapOfLength(UInt32 * length)
434: {
435: *length = 0;
436: return NULL;
437: }
438:
439: void IOHIKeyboard::setAlphaLockFeedback(bool /* val */)
440: {
441: return;
442: }
443:
444: UInt32 IOHIKeyboard::maxKeyCodes()
445: {
446: return( 0x80);
447: }
448:
449: bool IOHIKeyboard::open(IOService * client,
450: IOOptionBits options,
451: KeyboardEventAction keAction,
452: KeyboardSpecialEventAction kseAction,
453: UpdateEventFlagsAction uefAction)
454: {
455: if ( (!_keyMap) && (!resetKeyboard())) return false;
456:
457: if (super::open(client, options))
458: {
459: // Note: client object is already retained by superclass' open()
460: _keyboardEventTarget = client;
461: _keyboardEventAction = keAction;
462: _keyboardSpecialEventTarget = client;
463: _keyboardSpecialEventAction = kseAction;
464: _updateEventFlagsTarget = client;
465: _updateEventFlagsAction = uefAction;
466:
467: return true;
468: }
469:
470: return false;
471: }
472:
473: void IOHIKeyboard::close(IOService * client, IOOptionBits)
474: {
475: // kill autorepeat task
476: AbsoluteTime_to_scalar(&_downRepeatTime) = 0;
477: _codeToRepeat = (unsigned)-1;
478: scheduleAutoRepeat();
479: // clear modifiers to avoid stuck keys
480: setAlphaLock(false);
481: if (_updateEventFlagsAction)
482: (*_updateEventFlagsAction)(_updateEventFlagsTarget, 0); _eventFlags = 0;
483: bzero(_keyState, _keyStateSize);
484:
485: _keyboardEventAction = NULL;
486: _keyboardEventTarget = 0;
487: _keyboardSpecialEventAction = NULL;
488: _keyboardSpecialEventTarget = 0;
489: _updateEventFlagsAction = NULL;
490: _updateEventFlagsTarget = 0;
491:
492: super::close(client);
493: }
494:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.