1/*
2 * @APPLE_LICENSE_HEADER_START@
3 *
4 * Copyright (c) 1999-2003 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#ifndef _IOHIKEYBOARDMAPPER_H
24#define _IOHIKEYBOARDMAPPER_H
25
26#include <IOKit/hidsystem/ev_keymap.h>
27#include <IOKit/hidsystem/IOLLEvent.h>
28#include <IOKit/IOTimerEventSource.h>
29#include <IOKit/IOInterruptEventSource.h>
30
31class IOHIKeyboard;
32class IOHIDSystem;
33
34/*
35 * Key ip/down state is tracked in a bit list.  Bits are set
36 * for key-down, and cleared for key-up.  The bit vector and macros
37 * for it's manipulation are defined here.
38 */
39
40typedef	UInt32 * kbdBitVector;
41
42#define EVK_BITS_PER_UNIT	32
43#define EVK_BITS_MASK		31
44#define EVK_BITS_SHIFT		5	// 1<<5 == 32, for cheap divide
45
46#define EVK_KEYDOWN(n, bits) \
47	(bits)[((n)>>EVK_BITS_SHIFT)] |= (1 << ((n) & EVK_BITS_MASK))
48
49#define EVK_KEYUP(n, bits) \
50	(bits)[((n)>>EVK_BITS_SHIFT)] &= ~(1 << ((n) & EVK_BITS_MASK))
51
52#define EVK_IS_KEYDOWN(n, bits) \
53	(((bits)[((n)>>EVK_BITS_SHIFT)] & (1 << ((n) & EVK_BITS_MASK))) != 0)
54
55/* the maximum number of modifier keys sticky keys can hold at once */
56#define kMAX_MODIFIERS					5
57
58/* the number of shift keys in a row that must be depressed to toggle state */
59#define kNUM_SHIFTS_TO_ACTIVATE			5
60
61/* the number of milliseconds all the shifts must be pressed in - 30 seconds (30000 mS)*/
62#define kDEFAULT_SHIFTEXPIREINTERVAL	30000
63
64
65// sticky keys state flags
66enum
67{
68    kState_Disabled_Flag	= 0x0001,	// disabled and will do nothing until this is changed
69    kState_ShiftActivates_Flag	= 0x0002,	// the 'on' gesture (5 shifts) will activate
70    kState_On			= 0x0004,	// currently on, will hold down modifiers when pressed
71    kState_On_ModifiersDown	= 0x0008,	// one or more modifiers being held down
72
73    kState_Mask			= 0x00FF,	// mask for all states
74};
75
76typedef struct _stickyKeys_ToggleInfo
77{
78	// size of this allocation
79	IOByteCount		size;
80
81	// which modifier key we are tracking (using NX_WHICHMODMASK)
82	unsigned		toggleModifier;
83
84	// the number of times the modifier must be pressed to toggle
85	unsigned		repetitionsToToggle;
86
87	// how long the user has to press the modifier repetitionsToToggle times
88	// the default is 30 seconds
89	AbsoluteTime	expireInterval;
90
91	// the number of times the modifier used within the alloted time
92	unsigned		currentCount;
93
94	// the times that the last shift must occer for this one to be used
95	// this array will actually be of size repetitionsToToggle
96	AbsoluteTime	deadlines[1];
97} StickyKeys_ToggleInfo;
98
99// Flags for each sticky key modifier
100// This will allow for chording of keys
101// and for key locking
102enum
103{
104    kModifier_DidPerformModifiy	= 0x01,
105    kModifier_DidKeyUp		= 0x02,
106    kModifier_Locked		= 0x04,
107};
108typedef struct _stickyKeys_ModifierInfo
109{
110	UInt8		key;		// Key code of the sticky modifier
111        UInt8		state;		// The state of the sticky modifier
112        UInt8		leftModBit;	// System Mod bit of the sticky modifier
113} StickyKeys_ModifierInfo;
114
115class IOHIDKeyboardDevice;
116
117class IOHIKeyboardMapper : public OSObject
118{
119  OSDeclareDefaultStructors(IOHIKeyboardMapper);
120
121private:
122	IOHIKeyboard *		_delegate;					// KeyMap delegate
123	bool				_mappingShouldBeFreed;		// true if map can be IOFree'd
124	NXParsedKeyMapping	_parsedMapping;				// current system-wide keymap
125	IOHIDSystem	 *		_hidSystem;					// target of IOHIKeyboard (should be IOHIDSystem)
126
127	// binary compatibility padding
128    struct ExpansionData {
129
130        // This is for F12 eject
131	UInt16 			f12Eject_State;
132	UInt32 			eject_Delay_MS;
133	IOTimerEventSource 	*ejectTimerEventSource;
134
135        // This is for sticky keys
136        kbdBitVector		cached_KeyBits;
137        StickyKeys_ModifierInfo stickyKeys_StuckModifiers[kMAX_MODIFIERS];
138        IOInterruptEventSource  *stickyKeysMouseClickEventSource;
139        IOInterruptEventSource	*stickyKeysSetFnStateEventSource;
140        // The following should really be statics, but placing here
141        // to match design by predecesor.
142        OSDictionary		*offFnParamDict;
143        OSDictionary		*onFnParamDict;
144
145        // This is for SlowKeys
146        UInt16			slowKeys_State;
147        UInt32 			slowKeys_Delay_MS;
148        IOTimerEventSource	*slowKeysTimerEventSource;
149
150        // stored for slowKeysPostProcess
151        UInt8		slowKeys_Aborted_Key;
152        UInt8		slowKeys_Current_Key;
153
154        UInt32		specialKeyModifierFlags;
155
156        bool		supportsF12Eject;
157
158        SInt32      modifierSwap_Modifiers[NX_NUMMODIFIERS];
159
160		unsigned char * cachedAlphaLockModDefs;
161    };
162    ExpansionData * _reserved;				    // Reserved for future use.  (Internal use only)
163
164public:
165	static IOHIKeyboardMapper * keyboardMapper(
166										IOHIKeyboard * delegate,
167										const UInt8 *  mapping,
168										UInt32         mappingLength,
169										bool           mappingShouldBeFreed );
170
171	virtual bool init(IOHIKeyboard * delegate,
172					const UInt8 *  mapping,
173					  UInt32         mappingLength,
174					  bool           mappingShouldBeFreed);
175	virtual void free();
176
177	virtual const UInt8 *   mapping();
178	virtual UInt32          mappingLength();
179	virtual bool 		  	serialize(OSSerialize *s) const;
180
181	virtual void 		translateKeyCode(UInt8 key, bool keyDown, kbdBitVector keyBits);
182	virtual UInt8  		getParsedSpecialKey(UInt8 logical);   //retrieve a key from _parsedMapping
183
184	virtual	void		setKeyboardTarget (IOService * keyboardTarget);
185
186	virtual bool 	    updateProperties (void);
187	virtual IOReturn  	setParamProperties (OSDictionary * dict);
188
189	// keyEventPostProcess is called while a lock is not held, so a recursive
190	// call back into HIKeyboard is possible
191	virtual void 	    keyEventPostProcess (void);
192
193private:
194	static void makeNumberParamProperty( OSDictionary * dict, const char * key,
195                            unsigned long long number, unsigned int bits );
196
197
198	virtual bool parseKeyMapping(const UInt8 *        mapping,
199								 UInt32               mappingLength,
200							     NXParsedKeyMapping * parsedMapping) const;
201
202	virtual void calcModBit(int bit, kbdBitVector keyBits);
203	virtual void doModCalc(int key, kbdBitVector keyBits);
204	virtual void doCharGen(int keyCode, bool down);
205
206	/* sticky keys functionality */
207private:
208	// original translateKeyCode
209	void rawTranslateKeyCode (UInt8 key, bool keyDown, kbdBitVector keyBits);
210    bool modifierSwapFilterKey(UInt8 * key);
211
212	// the current state of stickyKeys
213	UInt32            	_stickyKeys_State;
214
215	// the number of modifiers being held down by stickyKeys
216	int		    		_stickyKeys_NumModifiersDown;
217
218	// contains the info needed to keep track of shift repetitions
219	StickyKeys_ToggleInfo * _stickyKeys_ShiftToggle;
220
221	// contains the info needed to keep track of option repetitions
222	StickyKeys_ToggleInfo * _stickyKeys_OptionToggle;
223
224	// dictionaries with cached on and off states, used to set params when state changes
225	bool				_stateDirty;
226	OSDictionary *		_onParamDict;
227	OSDictionary *		_offParamDict;
228
229	// init/free vars
230	bool stickyKeysinit (void);
231	void stickyKeysfree (void);
232
233	// allocate/free a StickyKeys_ToggleInfo struct
234	static StickyKeys_ToggleInfo * stickyKeysAllocToggleInfo (unsigned maxCount);
235	static void stickyKeysFreeToggleInfo (StickyKeys_ToggleInfo * toggleInfo);
236
237	// create on/off dicts as part of init
238	bool createParamDicts (void);
239
240	// post special keyboard events thru the event system
241	void postKeyboardSpecialEvent (unsigned subtype, unsigned eventType=NX_SYSDEFINED);
242
243	// check any modifier to see if it is pressed 5 times
244	// based on StickyKeys_ToggleInfo
245	bool stickyKeysModifierToggleCheck(
246							StickyKeys_ToggleInfo * toggleInfo,
247							UInt8        key,
248							bool         keyDown,
249							kbdBitVector keyBits,
250                                                        bool 	     mouseClick = false);
251
252	// non-modifier key pressed
253	void stickyKeysNonModifierKey (UInt8 key, bool keyDown, kbdBitVector keyBits, bool mouseClick = false);
254
255	// modifier key pressed (shift, command, option, control)
256	bool stickyKeysModifierKey (UInt8 key, bool keyDown, kbdBitVector keyBits);
257
258	// main entry point, called for all keys (returns true if key handled)
259	bool stickyKeysFilterKey (UInt8 key, bool keyDown, kbdBitVector keyBits, bool mouseClick = false);
260
261        // called by interrupt event source to inform sticky keys of mouse down event
262        static void stickyKeysMouseUp(IOHIKeyboardMapper *owner, IOEventSource *sender);
263
264	void stickyKeysCleanup();
265
266        // called by interrupt event source to restore prior fn state
267	static void stickyKeysSetFnState(IOHIKeyboardMapper *owner, IOEventSource *sender);
268
269        /* F12 Eject Functionality */
270private:
271
272        // Determining f12 eject key press
273        // Returns true if f12 held down for a predetermined period of time.
274        bool f12EjectFilterKey (UInt8 key, bool keyDown, kbdBitVector keyBits);
275
276        // Timer function for eject
277        static void performF12Eject(IOHIKeyboardMapper *owner, IOTimerEventSource *sender);
278
279        /* SlowKeys Functionality */
280private:
281        // Slow keys methods
282        bool slowKeysFilterKey (UInt8 key, bool keyDown, kbdBitVector keyBits);
283
284        static void slowKeysPostProcess (IOHIKeyboardMapper *owner, IOTimerEventSource *sender);
285
286
287public:
288    OSMetaClassDeclareReservedUsed(IOHIKeyboardMapper,  0);
289    virtual IOReturn message( UInt32 type, IOService * provider, void * argument = 0 );
290
291	// binary compatibility padding
292    OSMetaClassDeclareReservedUnused(IOHIKeyboardMapper,  1);
293    OSMetaClassDeclareReservedUnused(IOHIKeyboardMapper,  2);
294    OSMetaClassDeclareReservedUnused(IOHIKeyboardMapper,  3);
295    OSMetaClassDeclareReservedUnused(IOHIKeyboardMapper,  4);
296    OSMetaClassDeclareReservedUnused(IOHIKeyboardMapper,  5);
297    OSMetaClassDeclareReservedUnused(IOHIKeyboardMapper,  6);
298    OSMetaClassDeclareReservedUnused(IOHIKeyboardMapper,  7);
299    OSMetaClassDeclareReservedUnused(IOHIKeyboardMapper,  8);
300    OSMetaClassDeclareReservedUnused(IOHIKeyboardMapper,  9);
301    OSMetaClassDeclareReservedUnused(IOHIKeyboardMapper, 10);
302    OSMetaClassDeclareReservedUnused(IOHIKeyboardMapper, 11);
303    OSMetaClassDeclareReservedUnused(IOHIKeyboardMapper, 12);
304    OSMetaClassDeclareReservedUnused(IOHIKeyboardMapper, 13);
305    OSMetaClassDeclareReservedUnused(IOHIKeyboardMapper, 14);
306    OSMetaClassDeclareReservedUnused(IOHIKeyboardMapper, 15);
307};
308
309#endif // _IOHIKEYBOARDMAPPER_H
310
311/*
312 * HISTORICAL NOTE:
313 *   The "delegate" object had to respond to the following protocol;
314 *   this protocol has since been merged into the IOHIKeyboard class.
315 *
316 * @protocol KeyMapDelegate
317 *
318 * - keyboardEvent	:(unsigned)eventType
319 * 	flags	:(unsigned)flags
320 *	keyCode	:(unsigned)keyCode
321 *	charCode:(unsigned)charCode
322 *	charSet	:(unsigned)charSet
323 *	originalCharCode:(unsigned)origCharCode
324 *	originalCharSet:(unsigned)origCharSet;
325 *
326 * - keyboardSpecialEvent:(unsigned)eventType
327 *	flags	 :(unsigned)flags
328 *	keyCode	:(unsigned)keyCode
329 *	specialty:(unsigned)flavor;
330 *
331 * - updateEventFlags:(unsigned)flags;	// Does not generate events
332 *
333 * - (unsigned)eventFlags;		// Global event flags
334 * - (unsigned)deviceFlags;		// per-device event flags
335 * - setDeviceFlags:(unsigned)flags;	// Set device event flags
336 * - (bool)alphaLock;			// current alpha-lock state
337 * - setAlphaLock:(bool)val;		// Set current alpha-lock state
338 * - (bool)charKeyActive;		// Is a character gen. key down?
339 * - setCharKeyActive:(bool)val;	// Note that a char gen key is down.
340 *
341 * @end
342 */
343