1/*
2 *
3 * @APPLE_LICENSE_HEADER_START@
4 *
5 * Copyright (c) 1999-2003 Apple Computer, Inc.  All Rights Reserved.
6 *
7 * This file contains Original Code and/or Modifications of Original Code
8 * as defined in and that are subject to the Apple Public Source License
9 * Version 2.0 (the 'License'). You may not use this file except in
10 * compliance with the License. Please obtain a copy of the License at
11 * http://www.opensource.apple.com/apsl/ and read it before using this
12 * file.
13 *
14 * The Original Code and all software distributed under the License are
15 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
16 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
17 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
19 * Please see the License for the specific language governing rights and
20 * limitations under the License.
21 *
22 * @APPLE_LICENSE_HEADER_END@
23 */
24
25#include <IOKit/IOLib.h>
26
27#include "IOHIDKeyboardDevice.h"
28
29typedef struct GenericLEDKeyboardDescriptor {
30    //05 01: Usage Page (Generic Desktop)
31    UInt8 devUsagePageOp;
32    UInt8 devUsagePageNum;
33    //09 06: Usage (Keyboard)
34    UInt8 devUsageOp;
35    UInt8 devUsageNum;
36    //A1 01: Collection (Application)
37    UInt8 appCollectionOp;
38    UInt8 appCollectionNum;
39    //05 07:    Usage Page (Key Codes)
40    UInt8 modUsagePageOp;
41    UInt8 modUsagePageNum;
42    //19 e0:    Usage Minimum...... (224)
43    UInt8 modUsageMinOp;
44    UInt8 modUsageMinNum;
45    //29 e7:    Usage Maximum...... (231)
46    UInt8 modUsageMaxOp;
47    UInt8 modUsageMaxNum;
48    //15 00:    Logical Minimum.... (0)
49    UInt8 modLogMinOp;
50    UInt8 modLogMinNum;
51    //25 01:    Logical Maximum.... (1)
52    UInt8 modLogMaxOp;
53    UInt8 modLogMaxNum;
54    //95 01:    Report Count....... (1)
55    UInt8 modRptCountOp;
56    UInt8 modRptCountNum;
57    //75 08:    Report Size........ (8)
58    UInt8 modRptSizeOp;
59    UInt8 modRptSizeNum;
60    //81 02:    Input (Data)
61    UInt8 modInputOp;
62    UInt8 modInputNum;
63
64    //95 01:    Report Count....... (1)
65    UInt8 rsrvCountOp;
66    UInt8 rsrvCountNum;
67    //75 08:    Report Size........ (8)
68    UInt8 rsrvSizeOp;
69    UInt8 rsrvSizeNum;
70    //81 01:    Input (Constant)
71    UInt8 rsrvInputOp;
72    UInt8 rsrvInputNum;
73
74
75    //95 02:    Report Count....... (2)
76    UInt8 ledRptCountOp;
77    UInt8 ledRptCountNum;
78    //75 01:    Report Size........ (1)
79    UInt8 ledRptSizeOp;
80    UInt8 ledRptSizeNum;
81    //05 08:    Usage Page (LEDs)
82    UInt8 ledUsagePageOp;
83    UInt8 ledUsagePageNum;
84    //19 01:    Usage Minimum...... (1)
85    UInt8 ledUsageMinOp;
86    UInt8 ledUsageMinNum;
87    //29 02:    Usage Maximum...... (2)
88    UInt8 ledUsageMaxOp;
89    UInt8 ledUsageMaxNum;
90    //91 02:    Output (Data)
91    UInt8 ledInputOp;
92    UInt8 ledInputNum;
93
94    //95 01:    Report Count....... (1)
95    UInt8 fillRptCountOp;
96    UInt8 fillRptCountNum;
97    //75 03:    Report Size........ (3)
98    UInt8 fillRptSizeOp;
99    UInt8 fillRptSizeNum;
100    //91 01:    Output (Constant)
101    UInt8 fillInputOp;
102    UInt8 fillInputNum;
103
104
105    //95 06:    Report Count....... (6)
106    UInt8 keyRptCountOp;
107    UInt8 keyRptCountNum;
108    //75 08:    Report Size........ (8)
109    UInt8 keyRptSizeOp;
110    UInt8 keyRptSizeNum;
111    //15 00:    Logical Minimum.... (0)
112    UInt8 keyLogMinOp;
113    UInt8 keyLogMinNum;
114    //26 ff 00:    Logical Maximum.... (255)
115    UInt8 keyLogMaxOp;
116    UInt16 keyLogMaxNum;
117    //05 07:    Usage Page (Key Codes)
118    UInt8 keyUsagePageOp;
119    UInt8 keyUsagePageNum;
120    //19 00:    Usage Minimum...... (0)
121    UInt8 keyUsageMinOp;
122    UInt8 keyUsageMinNum;
123    //29 ff:    Usage Maximum...... (255)
124    UInt8 keyUsageMaxOp;
125    UInt8 keyUsageMaxNum;
126    //81 00:    Input (Array)
127    UInt8 keyInputOp;
128    UInt8 keyInputNum;
129
130    //C0:    End Collection
131    UInt8 appCollectionEnd;
132} GenericLEDKeyboardDescriptor;
133
134struct GenericKeyboardDescriptor {
135    //05 01: Usage Page (Generic Desktop)
136    UInt8 devUsagePageOp;
137    UInt8 devUsagePageNum;
138    //09 06: Usage (Keyboard)
139    UInt8 devUsageOp;
140    UInt8 devUsageNum;
141    //A1 01: Collection (Application)
142    UInt8 appCollectionOp;
143    UInt8 appCollectionNum;
144    //05 07:    Usage Page (Key Codes)
145    UInt8 modUsagePageOp;
146    UInt8 modUsagePageNum;
147    //19 e0:    Usage Minimum...... (224)
148    UInt8 modUsageMinOp;
149    UInt8 modUsageMinNum;
150    //29 e7:    Usage Maximum...... (231)
151    UInt8 modUsageMaxOp;
152    UInt8 modUsageMaxNum;
153    //15 00:    Logical Minimum.... (0)
154    UInt8 modLogMinOp;
155    UInt8 modLogMinNum;
156    //25 01:    Logical Maximum.... (1)
157    UInt8 modLogMaxOp;
158    UInt8 modLogMaxNum;
159    //95 01:    Report Count....... (1)
160    UInt8 modRptCountOp;
161    UInt8 modRptCountNum;
162    //75 08:    Report Size........ (8)
163    UInt8 modRptSizeOp;
164    UInt8 modRptSizeNum;
165    //81 02:    Input (Data)
166    UInt8 modInputOp;
167    UInt8 modInputNum;
168
169    //95 01:    Report Count....... (1)
170    UInt8 rsrvCountOp;
171    UInt8 rsrvCountNum;
172    //75 08:    Report Size........ (8)
173    UInt8 rsrvSizeOp;
174    UInt8 rsrvSizeNum;
175    //81 01:    Input (Constant)
176    UInt8 rsrvInputOp;
177    UInt8 rsrvInputNum;
178
179
180    //95 02:    Report Count....... (2)
181    UInt8 ledRptCountOp;
182    UInt8 ledRptCountNum;
183    //75 01:    Report Size........ (1)
184    UInt8 ledRptSizeOp;
185    UInt8 ledRptSizeNum;
186    //05 08:    Usage Page (LEDs)
187    UInt8 ledUsagePageOp;
188    UInt8 ledUsagePageNum;
189    //19 01:    Usage Minimum...... (1)
190    UInt8 ledUsageMinOp;
191    UInt8 ledUsageMinNum;
192    //29 02:    Usage Maximum...... (2)
193    UInt8 ledUsageMaxOp;
194    UInt8 ledUsageMaxNum;
195    //91 02:    Output (Data)
196    UInt8 ledInputOp;
197    UInt8 ledInputNum;
198
199    //95 01:    Report Count....... (1)
200    UInt8 fillRptCountOp;
201    UInt8 fillRptCountNum;
202    //75 03:    Report Size........ (3)
203    UInt8 fillRptSizeOp;
204    UInt8 fillRptSizeNum;
205    //91 01:    Output (Constant)
206    UInt8 fillInputOp;
207    UInt8 fillInputNum;
208
209
210    //95 06:    Report Count....... (6)
211    UInt8 keyRptCountOp;
212    UInt8 keyRptCountNum;
213    //75 08:    Report Size........ (8)
214    UInt8 keyRptSizeOp;
215    UInt8 keyRptSizeNum;
216    //15 00:    Logical Minimum.... (0)
217    UInt8 keyLogMinOp;
218    UInt8 keyLogMinNum;
219    //26 ff 00:    Logical Maximum.... (255)
220    UInt8 keyLogMaxOp;
221    UInt16 keyLogMaxNum;
222    //05 07:    Usage Page (Key Codes)
223    UInt8 keyUsagePageOp;
224    UInt8 keyUsagePageNum;
225    //19 00:    Usage Minimum...... (0)
226    UInt8 keyUsageMinOp;
227    UInt8 keyUsageMinNum;
228    //29 ff:    Usage Maximum...... (255)
229    UInt8 keyUsageMaxOp;
230    UInt8 keyUsageMaxNum;
231    //81 00:    Input (Array)
232    UInt8 keyInputOp;
233    UInt8 keyInputNum;
234
235    //C0:    End Collection
236    UInt8 appCollectionEnd;
237} GenericKeyboardDescriptor;
238
239typedef struct GenericKeyboardRpt {
240    UInt8 modifiers;
241    UInt8 reserved;
242    UInt8 keys[6];
243} GenericKeyboardRpt;
244
245static UInt8 gGenLEDKeyboardDesc[] = {
246    0x05, 0x01,
247    0x09, 0x06,
248    0xA1, 0x01,
249    0x05, 0x07,
250    0x19, 0xe0,
251    0x29, 0xe7,
252    0x15, 0x00,
253    0x25, 0x01,
254    0x75, 0x01,
255    0x95, 0x08,
256    0x81, 0x02,
257    0x95, 0x01,
258    0x75, 0x08,
259    0x81, 0x01,
260
261    0x95, 0x02,
262    0x75, 0x01,
263    0x05, 0x08,
264    0x19, 0x01,
265    0x29, 0x02,
266    0x91, 0x02,
267    0x95, 0x01,
268    0x75, 0x06,
269    0x91, 0x01,
270
271    0x95, 0x06,
272    0x75, 0x08,
273    0x15, 0x00,
274    0x26, 0xff, 0x00,
275    0x05, 0x07,
276    0x19, 0x00,
277    0x29, 0xff,
278    0x81, 0x00,
279    0xC0
280};
281
282static UInt8 gGenKeyboardDesc[] = {
283    0x05, 0x01,
284    0x09, 0x06,
285    0xA1, 0x01,
286    0x05, 0x07,
287    0x19, 0xe0,
288    0x29, 0xe7,
289    0x15, 0x00,
290    0x25, 0x01,
291    0x75, 0x01,
292    0x95, 0x08,
293    0x81, 0x02,
294    0x95, 0x01,
295    0x75, 0x08,
296    0x81, 0x01,
297
298    0x95, 0x06,
299    0x75, 0x08,
300    0x15, 0x00,
301    0x26, 0xff, 0x00,
302    0x05, 0x07,
303    0x19, 0x00,
304    0x29, 0xff,
305    0x81, 0x00,
306    0xC0
307};
308
309extern unsigned int hid_adb_2_usb_keymap[];  //In Cosmo_USB2ADB.cpp
310
311#define super IOHIDDeviceShim
312
313OSDefineMetaClassAndStructors( IOHIDKeyboardDevice, IOHIDDeviceShim )
314
315
316IOHIDKeyboardDevice *
317IOHIDKeyboardDevice::newKeyboardDeviceAndStart(IOService * owner, UInt32 location)
318{
319    IOService * provider = owner;
320
321    while ( NULL != (provider = provider->getProvider()) )
322    {
323	if(OSDynamicCast(IOHIDDevice, provider) || OSDynamicCast(IOHIDevice, provider))
324            return  0;
325    }
326
327
328    IOHIDKeyboardDevice * device = new IOHIDKeyboardDevice;
329
330    if (device)
331    {
332        if ( device->initWithLocation(location) && device->attach(owner) )
333        {
334            if (!device->start(owner))
335            {
336                device->detach(owner);
337                device->release();
338                device = 0;
339            }
340        }
341        else
342        {
343            device->release();
344            device = 0;
345        }
346    }
347
348    return device;
349}
350
351
352bool IOHIDKeyboardDevice::initWithLocation( UInt32 location )
353{
354    if (!super::initWithLocation(location))
355        return false;
356
357    _report 		= 0;
358    _cachedLEDState 	= 0;
359    _inputReportOnly 	= true;
360
361    return true;
362}
363
364void IOHIDKeyboardDevice::free()
365{
366    if (_report) _report->release();
367
368    super::free();
369}
370
371bool IOHIDKeyboardDevice::handleStart( IOService * provider )
372{
373    if (!super::handleStart(provider))
374        return false;
375
376    if ( (_keyboard = OSDynamicCast(IOHIKeyboard, provider)) )
377    {
378        _inputReportOnly = ((transport() == kIOHIDTransportADB) && (_keyboard->deviceType() >= 0xc3));
379        _cachedLEDState = _keyboard->getLEDStatus() & 0x3;
380    }
381
382    _report = IOBufferMemoryDescriptor::withCapacity(
383        sizeof(GenericKeyboardRpt), kIODirectionNone, true);
384
385    bzero(_report->getBytesNoCopy(), sizeof(GenericKeyboardRpt));
386
387    return (_report) ? true : false;
388}
389
390IOReturn IOHIDKeyboardDevice::newReportDescriptor(
391                        IOMemoryDescriptor ** descriptor ) const
392{
393    void  * desc;
394    UInt8 * descBytes;
395    UInt8 descSize;
396
397    if (!descriptor)
398        return kIOReturnBadArgument;
399
400    if (_inputReportOnly)
401    {
402        descSize = sizeof(GenericKeyboardDescriptor);
403        descBytes = gGenKeyboardDesc;
404    }
405    else
406    {
407        descSize = sizeof(GenericLEDKeyboardDescriptor);
408        descBytes = gGenLEDKeyboardDesc;
409    }
410
411    *descriptor = IOBufferMemoryDescriptor::withCapacity(
412        descSize,
413        kIODirectionNone,
414        true);
415
416    if (! *descriptor)
417        return kIOReturnNoMemory;
418
419    desc = ((IOBufferMemoryDescriptor *)(*descriptor))->getBytesNoCopy();
420    bcopy(descBytes, desc, descSize);
421
422    return kIOReturnSuccess;
423}
424
425IOReturn IOHIDKeyboardDevice::getReport(IOMemoryDescriptor  *report,
426                                        IOHIDReportType     reportType,
427                                        IOOptionBits        options __unused )
428{
429    if (!report)
430        return kIOReturnError;
431
432    if ( reportType != kIOHIDReportTypeInput)
433        return kIOReturnUnsupported;
434
435    report->writeBytes(0, _report->getBytesNoCopy(), min(report->getLength(), _report->getLength()));
436    return kIOReturnSuccess;
437}
438
439IOReturn IOHIDKeyboardDevice::setReport(IOMemoryDescriptor * report,
440                                        IOHIDReportType      reportType __unused,
441                                        IOOptionBits         options )
442{
443    UInt8 	ledState;
444    UInt8	mask;
445
446    if ((options & 0xff) || (_inputReportOnly) || !_keyboard)
447        return kIOReturnError;
448
449    report->readBytes( 0, (void *)&ledState, sizeof(UInt8) );
450
451    mask = (1 << (kHIDUsage_LED_NumLock - 1));
452    if ( (ledState & mask) && !(_cachedLEDState & mask) )
453    {
454        _keyboard->setNumLockFeedback(true);
455    }
456    else if ( !(ledState & mask) && (_cachedLEDState & mask) )
457    {
458        _keyboard->setNumLockFeedback(false);
459    }
460
461    mask = (1 << (kHIDUsage_LED_CapsLock - 1));
462    if ( (ledState & mask) && !(_cachedLEDState & mask) )
463    {
464        _keyboard->setAlphaLockFeedback(true);
465    }
466    else if ( !(ledState & mask) && (_cachedLEDState & mask) )
467    {
468        _keyboard->setAlphaLockFeedback(false);
469    }
470
471    _cachedLEDState = ledState;
472
473    return kIOReturnSuccess;
474}
475
476void IOHIDKeyboardDevice::setCapsLockLEDElement(bool state)
477{
478    UInt8	mask = (1 << (kHIDUsage_LED_CapsLock-1));
479
480    if (_inputReportOnly)
481        return;
482
483    if (state)
484        _cachedLEDState |=  mask;
485
486    else
487        _cachedLEDState &= ~mask;
488
489    *(UInt8 *)(_report->getBytesNoCopy()) = _cachedLEDState;
490
491    handleReport(_report, kIOHIDReportTypeOutput);
492}
493
494void IOHIDKeyboardDevice::setNumLockLEDElement(bool state)
495{
496    UInt8	mask = (1 << (kHIDUsage_LED_NumLock-1));
497
498    if (_inputReportOnly)
499        return;
500
501    if (state)
502        _cachedLEDState |= mask;
503
504    else
505        _cachedLEDState &= ~mask;
506
507    *(UInt8 *)(_report->getBytesNoCopy()) = _cachedLEDState;
508
509    handleReport(_report, kIOHIDReportTypeOutput);
510}
511
512#define SET_MODIFIER_BIT(bitField, key, down)	\
513    if (down) {bitField |= (1 << (key - 0xe0));}	\
514    else {bitField &= ~(1 << (key - 0xe0));}
515
516void IOHIDKeyboardDevice::postKeyboardEvent(UInt8 key, bool keyDown)
517{
518    GenericKeyboardRpt *report = (GenericKeyboardRpt *)_report->getBytesNoCopy();
519    UInt8		usbKey;
520
521    if (!report)
522        return;
523
524    // Convert ADB scan code to USB
525    if (! (usbKey = hid_adb_2_usb_keymap[key]))
526        return;
527
528    // Check if modifier
529    if ((usbKey >= 0xe0) && (usbKey <= 0xe7))
530    {
531	SET_MODIFIER_BIT(report->modifiers, usbKey, keyDown);
532    }
533    else
534    {
535        for (int i=0; i<6; i++)
536        {
537            if (report->keys[i] == usbKey)
538            {
539                if (keyDown) return;
540
541                for (int j=i; j<5; j++)
542                    report->keys[j] = report->keys[j+1];
543
544                report->keys[5] = 0;
545                break;
546            }
547
548            else if ((report->keys[i] == 0) && keyDown)
549            {
550                report->keys[i] = usbKey;
551                break;
552            }
553        }
554    }
555
556    handleReport(_report);
557}
558
559enum {
560    kUSB_LEFT_CONTROL_BIT = 0x01,
561    kUSB_LEFT_SHIFT_BIT = 0x02,
562    kUSB_LEFT_ALT_BIT = 0x04,
563    kUSB_LEFT_FLOWER_BIT = 0x08,
564
565    kUSB_RIGHT_CONTROL_BIT = 0x10,
566    kUSB_RIGHT_SHIFT_BIT = 0x20,
567    kUSB_RIGHT_ALT_BIT = 0x040,
568    kUSB_RIGHT_FLOWER_BIT = 0x80
569};
570
571void IOHIDKeyboardDevice::postFlagKeyboardEvent(UInt32 flags)
572{
573    GenericKeyboardRpt *report      = (GenericKeyboardRpt *)_report->getBytesNoCopy();
574    UInt32              flagDelta   = (flags ^ _lastFlags);
575
576    if (!flagDelta)
577        return;
578
579    report->modifiers = 0;
580    _lastFlags = flags;
581
582    if ( flagDelta & 0x0000ffff )
583    {
584        if( flags & NX_DEVICELSHIFTKEYMASK )
585            report->modifiers |= kUSB_LEFT_SHIFT_BIT;
586        if( flags & NX_DEVICELCTLKEYMASK )
587            report->modifiers |= kUSB_LEFT_CONTROL_BIT;
588        if( flags & NX_DEVICELALTKEYMASK )
589            report->modifiers |= kUSB_LEFT_ALT_BIT;
590        if( flags & NX_DEVICELCMDKEYMASK )
591            report->modifiers |= kUSB_LEFT_FLOWER_BIT;
592
593        if( flags & NX_DEVICERSHIFTKEYMASK )
594            report->modifiers |= kUSB_RIGHT_SHIFT_BIT;
595        if( flags & NX_DEVICERCTLKEYMASK )
596            report->modifiers |= kUSB_RIGHT_CONTROL_BIT;
597        if( flags & NX_DEVICERALTKEYMASK )
598            report->modifiers |= kUSB_RIGHT_ALT_BIT;
599        if( flags & NX_DEVICERCMDKEYMASK )
600            report->modifiers |= kUSB_RIGHT_FLOWER_BIT;
601    }
602    else if ( flagDelta & 0xffff0000 )
603    {
604        if( flags & NX_SHIFTMASK )
605            report->modifiers |= kUSB_LEFT_SHIFT_BIT;
606        if( flags & NX_CONTROLMASK )
607            report->modifiers |= kUSB_LEFT_CONTROL_BIT;
608        if( flags & NX_ALTERNATEMASK )
609            report->modifiers |= kUSB_LEFT_ALT_BIT;
610        if( flags & NX_COMMANDMASK )
611            report->modifiers |= kUSB_LEFT_FLOWER_BIT;
612    }
613
614    if ( flagDelta & NX_ALPHASHIFTMASK )
615    {
616        postKeyboardEvent(0x39, flags & NX_ALPHASHIFTMASK);
617        return;
618    }
619
620    handleReport(_report);
621}
622
623OSString * IOHIDKeyboardDevice::newProductString() const
624{
625    OSString * string = 0;
626
627    if ( !(string = super::newProductString()) )
628        string = OSString::withCString("Virtual Keyboard");
629
630    return string;
631}
632