1/*
2 *
3 * @APPLE_LICENSE_HEADER_START@
4 *
5 * Copyright (c) 1999-2013 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 <AssertMacros.h>
26#include <TargetConditionals.h>
27#include <stdint.h>
28#include <IOKit/hid/IOHIDUsageTables.h>
29#include <IOKit/IOLib.h>
30#include <IOKit/usb/USB.h>
31
32#include "IOHIDKeys.h"
33#include "IOHIDSystem.h"
34#include "IOHIDEventService.h"
35#include "IOHIDInterface.h"
36#include "IOHIDPrivateKeys.h"
37#include "AppleHIDUsageTables.h"
38#include "OSStackRetain.h"
39
40#if !TARGET_OS_EMBEDDED
41    #include "IOHIDPointing.h"
42    #include "IOHIDKeyboard.h"
43    #include "IOHIDConsumer.h"
44#endif /* !TARGET_OS_EMBEDDED */
45
46#include "IOHIDEventData.h"
47
48#include "IOHIDFamilyPrivate.h"
49#include "IOHIDevicePrivateKeys.h"
50#include "ev_private.h"
51#include "IOHIDFamilyTrace.h"
52
53enum {
54    kBootProtocolNone   = 0,
55    kBootProtocolKeyboard,
56    kBootProtocolMouse
57};
58
59enum {
60    kShimEventProcessor = 0x01
61};
62
63#define     kDefaultFixedResolution             (400 << 16)
64#define     kDefaultScrollFixedResolution       (9 << 16)
65
66#define     kMaxSystemAbsoluteRangeUnsigned     65535
67#define     kMaxSystemAbsoluteRangeSigned       32767
68#define     kMaxSystemBarrelPressure            kMaxSystemAbsoluteRangeSigned
69#define     kMaxSystemTipPressure               kMaxSystemAbsoluteRangeUnsigned
70
71#define     kDelayedOption                      (1<<31)
72
73#define     NUB_LOCK                            if (_nubLock) IORecursiveLockLock(_nubLock)
74#define     NUB_UNLOCK                          if (_nubLock) IORecursiveLockUnlock(_nubLock)
75
76#if TARGET_OS_EMBEDDED
77    #define     SET_HID_PROPERTIES_EMBEDDED(service)                                \
78        service->setProperty(kIOHIDPrimaryUsagePageKey, getPrimaryUsagePage(), 32); \
79        service->setProperty(kIOHIDPrimaryUsageKey, getPrimaryUsage(), 32);
80#else
81    #define     SET_HID_PROPERTIES_EMBEDDED(service)                                \
82        {};
83#endif
84
85
86#define     SET_HID_PROPERTIES(service)                                     \
87    service->setProperty(kIOHIDTransportKey, getTransport());               \
88    service->setProperty(kIOHIDLocationIDKey, getLocationID(), 32);         \
89    service->setProperty(kIOHIDVendorIDKey, getVendorID(), 32);             \
90    service->setProperty(kIOHIDVendorIDSourceKey, getVendorIDSource(), 32); \
91    service->setProperty(kIOHIDProductIDKey, getProductID(), 32);           \
92    service->setProperty(kIOHIDVersionNumberKey, getVersion(), 32);         \
93    service->setProperty(kIOHIDCountryCodeKey, getCountryCode(), 32);       \
94    service->setProperty(kIOHIDManufacturerKey, getManufacturer());         \
95    service->setProperty(kIOHIDProductKey, getProduct());                   \
96    service->setProperty(kIOHIDSerialNumberKey, getSerialNumber());         \
97    service->setProperty(kIOHIDDeviceUsagePairsKey, getDeviceUsagePairs()); \
98    service->setProperty(kIOHIDReportIntervalKey, getReportInterval(), 32);
99
100#define		_provider							_reserved->provider
101#define     _workLoop                           _reserved->workLoop
102#define     _deviceUsagePairs                   _reserved->deviceUsagePairs
103#define     _commandGate                        _reserved->commandGate
104#define     _keyboard                           _reserved->keyboard
105#define     _multiAxis                          _reserved->multiAxis
106#define     _digitizer                          _reserved->digitizer
107
108#if TARGET_OS_EMBEDDED
109    #define     _clientDict                         _reserved->clientDict
110
111    #define     kDebuggerDelayMS                    2500
112
113    //===========================================================================
114    // IOHIDClientData class
115    class IOHIDClientData : public OSObject
116    {
117        OSDeclareDefaultStructors(IOHIDClientData)
118
119        IOService * client;
120        void *      context;
121        void *      action;
122
123    public:
124        static IOHIDClientData* withClientInfo(IOService *client, void* context, void * action);
125        inline IOService *  getClient()     { return client; }
126        inline void *       getContext()    { return context; }
127        inline void *       getAction()     { return action; }
128    };
129
130#endif /* TARGET_OS_EMBEDDED */
131
132struct  TransducerData {
133    UInt32  reportID;
134    UInt32  deviceID;
135    UInt32  type;
136    UInt32  capabilities;
137    bool    digitizerCollection;
138    bool    supportsTransducerIndex;
139};
140
141//===========================================================================
142// IOHIDEventService class
143
144#define super IOService
145
146OSDefineMetaClassAndAbstractStructors( IOHIDEventService, IOService )
147//====================================================================================================
148// IOHIDEventService::init
149//====================================================================================================
150bool IOHIDEventService::init ( OSDictionary * properties )
151{
152    if (!super::init(properties))
153        return false;
154
155    _reserved = IONew(ExpansionData, 1);
156    bzero(_reserved, sizeof(ExpansionData));
157
158    _nubLock = IORecursiveLockAlloc();
159
160#if TARGET_OS_EMBEDDED
161    _clientDict = OSDictionary::withCapacity(2);
162    if ( _clientDict == 0 )
163        return false;
164#endif /* TARGET_OS_EMBEDDED */
165
166    _keyboard.eject.delayMS = kEjectKeyDelayMS;
167
168    return true;
169}
170//====================================================================================================
171// IOHIDEventService::start
172//====================================================================================================
173bool IOHIDEventService::start ( IOService * provider )
174{
175    UInt32      bootProtocol = 0;
176    OSNumber    *number       = NULL;
177
178    _provider = provider;
179
180    if ( !super::start(provider) )
181        return false;
182
183    if ( !handleStart(provider) )
184        return false;
185
186    _workLoop = getWorkLoop();
187    if ( !_workLoop )
188        return false;
189
190    _workLoop->retain();
191
192    _keyboard.eject.timer = IOTimerEventSource::timerEventSource(this, OSMemberFunctionCast(IOTimerEventSource::Action, this, &IOHIDEventService::ejectTimerCallback));
193    if (!_keyboard.eject.timer || (_workLoop->addEventSource(_keyboard.eject.timer) != kIOReturnSuccess))
194        return false;
195
196    number = (OSNumber*)copyProperty(kIOHIDKeyboardEjectDelay);
197    if ( OSDynamicCast(OSNumber, number) )
198        _keyboard.eject.delayMS = number->unsigned32BitValue();
199    OSSafeReleaseNULL(number);
200
201    _keyboard.caps.timer =
202            IOTimerEventSource::timerEventSource(this,
203                                                 OSMemberFunctionCast(IOTimerEventSource::Action,
204                                                                      this,
205                                                                      &IOHIDEventService::capsTimerCallback));
206    if (!_keyboard.caps.timer || (_workLoop->addEventSource(_keyboard.caps.timer) != kIOReturnSuccess))
207        return false;
208
209    _multiAxis.timer =
210    IOTimerEventSource::timerEventSource(this,
211                                         OSMemberFunctionCast(IOTimerEventSource::Action,
212                                                              this,
213                                                              &IOHIDEventService::multiAxisTimerCallback));
214    if (!_multiAxis.timer || (_workLoop->addEventSource(_multiAxis.timer) != kIOReturnSuccess))
215        return false;
216
217
218    _commandGate = IOCommandGate::commandGate(this);
219    if (!_commandGate || (_workLoop->addEventSource(_commandGate) != kIOReturnSuccess))
220        return false;
221
222    calculateCapsLockDelay();
223
224    calculateStandardType();
225
226    SET_HID_PROPERTIES(this);
227    SET_HID_PROPERTIES_EMBEDDED(this);
228
229    number = (OSNumber*)copyProperty("BootProtocol");
230    if (OSDynamicCast(OSNumber, number))
231        bootProtocol = number->unsigned32BitValue();
232    OSSafeReleaseNULL(number);
233
234    parseSupportedElements (getReportElements(), bootProtocol);
235
236#if !TARGET_OS_EMBEDDED
237    if ((!_consumerNub && _keyboardNub) || (!_keyboardNub && _consumerNub)) {
238        OSDictionary * matchingDictionary = IOService::serviceMatching( "IOHIDEventService" );
239        if ( matchingDictionary ) {
240            OSDictionary *      propertyMatch = OSDictionary::withCapacity(4);
241
242            if (propertyMatch) {
243                OSObject *          object;
244                object = copyProperty(kIOHIDTransportKey);
245                if (object) propertyMatch->setObject(kIOHIDTransportKey, object);
246                OSSafeReleaseNULL(object);
247
248                object = copyProperty(kIOHIDVendorIDKey);
249                if (object) propertyMatch->setObject(kIOHIDVendorIDKey, object);
250                OSSafeReleaseNULL(object);
251
252                object = copyProperty(kIOHIDProductIDKey);
253                if (object) propertyMatch->setObject(kIOHIDProductIDKey, object);
254                OSSafeReleaseNULL(object);
255
256                object = copyProperty(kIOHIDLocationIDKey);
257                if (object) propertyMatch->setObject(kIOHIDLocationIDKey, object);
258                OSSafeReleaseNULL(object);
259
260                matchingDictionary->setObject(gIOPropertyMatchKey, propertyMatch);
261
262                propertyMatch->release();
263            }
264            _publishNotify = addMatchingNotification( gIOPublishNotification,
265                             matchingDictionary,
266                             &IOHIDEventService::_publishMatchingNotificationHandler,
267                             this, 0 );
268            matchingDictionary->release();
269        }
270    }
271#endif /* TARGET_OS_EMBEDDED */
272
273    _readyForInputReports = true;
274
275    registerService(kIOServiceAsynchronous);
276
277    return true;
278}
279
280#if !TARGET_OS_EMBEDDED
281
282//====================================================================================================
283// stopAndReleaseShim
284//====================================================================================================
285
286static void stopAndReleaseShim ( IOService * service, IOService * provider )
287{
288    if ( !service )
289        return;
290
291    IOService * serviceProvider = service->getProvider();
292
293    if ( serviceProvider == provider )
294    {
295        service->stop(provider);
296        service->detach(provider);
297    }
298    service->release();
299}
300
301#endif /* TARGET_OS_EMBEDDED */
302
303//====================================================================================================
304// IOHIDEventService::stop
305//====================================================================================================
306void IOHIDEventService::stop( IOService * provider )
307{
308    handleStop ( provider );
309
310    if (_keyboard.caps.timer) {
311        _keyboard.caps.timer->cancelTimeout();
312        if ( _workLoop )
313            _workLoop->removeEventSource(_keyboard.caps.timer);
314
315        _keyboard.caps.timer->release();
316        _keyboard.caps.timer = 0;
317    }
318
319    if (_keyboard.eject.timer) {
320        _keyboard.eject.timer->cancelTimeout();
321        if ( _workLoop )
322            _workLoop->removeEventSource(_keyboard.eject.timer);
323
324        _keyboard.eject.timer->release();
325        _keyboard.eject.timer = 0;
326    }
327
328    if (_multiAxis.timer) {
329        _multiAxis.timer->cancelTimeout();
330        if ( _workLoop )
331            _workLoop->removeEventSource(_multiAxis.timer);
332
333        _multiAxis.timer->release();
334        _multiAxis.timer = 0;
335    }
336
337    if (_commandGate) {
338        if ( _workLoop )
339            _workLoop->removeEventSource(_commandGate);
340
341        _commandGate->release();
342        _commandGate = 0;
343    }
344
345#if TARGET_OS_EMBEDDED
346
347    if ( _keyboard.debug.timer ) {
348        _keyboard.debug.timer->cancelTimeout();
349        if ( _workLoop )
350            _workLoop->removeEventSource(_keyboard.debug.timer);
351
352        _keyboard.debug.timer->release();
353        _keyboard.debug.timer = 0;
354    }
355
356#else
357
358    NUB_LOCK;
359
360    stopAndReleaseShim ( _keyboardNub, this );
361    _keyboardNub = 0;
362
363    stopAndReleaseShim ( _pointingNub, this );
364    _pointingNub = 0;
365
366    stopAndReleaseShim ( _consumerNub, this );
367    _consumerNub = 0;
368
369    if (_publishNotify) {
370        _publishNotify->remove();
371    	_publishNotify = 0;
372    }
373
374    NUB_UNLOCK;
375#endif /* TARGET_OS_EMBEDDED */
376
377    super::stop( provider );
378}
379
380//====================================================================================================
381// IOHIDEventService::matchPropertyTable
382//====================================================================================================
383bool IOHIDEventService::matchPropertyTable(OSDictionary * table, SInt32 * score)
384{
385    RETAIN_ON_STACK(this);
386    // Ask our superclass' opinion.
387    if (super::matchPropertyTable(table, score) == false)
388        return false;
389
390    return MatchPropertyTable(this, table, score);
391}
392
393//====================================================================================================
394// IOHIDEventService::_publishMatchingNotificationHandler
395//====================================================================================================
396bool IOHIDEventService::_publishMatchingNotificationHandler(
397    void * target,
398    void * /* ref */,
399    IOService * newService,
400    IONotifier * /* notifier */)
401{
402#if !TARGET_OS_EMBEDDED
403    IOHIDEventService * self    = (IOHIDEventService *) target;
404    IOHIDEventService * service = (IOHIDEventService *) newService;
405
406    // NUB_LOCK;
407    if (self->_nubLock) IORecursiveLockLock(self->_nubLock);
408
409    if ( service->_keyboardNub ) {
410        if ( self->_keyboardNub
411                && self->_keyboardNub->isDispatcher()
412                && !service->_keyboardNub->isDispatcher() ) {
413            stopAndReleaseShim ( self->_keyboardNub, self );
414            self->_keyboardNub = 0;
415        }
416
417        if ( !self->_keyboardNub ) {
418            self->_keyboardNub = service->_keyboardNub;
419            self->_keyboardNub->retain();
420
421            if (self->_publishNotify) {
422                self->_publishNotify->remove();
423                self->_publishNotify = 0;
424            }
425        }
426    }
427
428    if ( service->_consumerNub ) {
429        if ( self->_consumerNub
430                && self->_consumerNub->isDispatcher()
431                && !service->_consumerNub->isDispatcher() ) {
432            stopAndReleaseShim ( self->_consumerNub, self );
433            self->_consumerNub = 0;
434        }
435
436        if ( !self->_consumerNub ) {
437            self->_consumerNub = service->_consumerNub;
438            self->_consumerNub->retain();
439
440            if (self->_publishNotify) {
441                self->_publishNotify->remove();
442                self->_publishNotify = 0;
443            }
444        }
445    }
446
447    // NUB_UNLOCK;
448    if (self->_nubLock) IORecursiveLockUnlock(self->_nubLock);
449
450#endif /* TARGET_OS_EMBEDDED */
451    return true;
452}
453
454//====================================================================================================
455// IOHIDEventService::calculateCapsLockDelay
456//====================================================================================================
457void IOHIDEventService::calculateCapsLockDelay()
458{
459    OSNumber        *delay = NULL;
460    OSNumber        *delayOverride = NULL;
461    OSDictionary    *deviceParameters = NULL;
462    OSArray         *mappings = NULL;
463    UInt32          count = 0;
464
465    // default to no delay
466    _keyboard.caps.delayMS = 0;
467
468    // If this keyboard does not support delay, get out. Otherwise, use it.
469    delay = (OSNumber*)copyProperty(kIOHIDKeyboardCapsLockDelay);
470    if (!OSDynamicCast(OSNumber, delay))
471        goto GET_OUT;
472    _keyboard.caps.delayMS = delay->unsigned32BitValue();
473
474    // If there is an override in place, use that.
475
476    delayOverride = (OSNumber*)copyProperty(kIOHIDKeyboardCapsLockDelayOverride);
477    if (OSDynamicCast(OSNumber, delayOverride))
478        _keyboard.caps.delayMS = delayOverride->unsigned32BitValue();
479    OSSafeReleaseNULL(delayOverride);
480
481    // If there is no delay at this point, get out.
482    if (!_keyboard.caps.delayMS)
483        goto GET_OUT;
484
485    // At this point, we need to scan all of the modifier mappings (if any) to see
486    // if the NX_MODIFIERKEY_ALPHALOCK is remapped to something other than the
487    // NX_MODIFIERKEY_ALPHALOCK.
488    deviceParameters = (OSDictionary*)copyProperty(kIOHIDEventServicePropertiesKey);
489    if (!OSDynamicCast(OSDictionary, deviceParameters))
490        goto GET_OUT;
491
492    mappings = OSDynamicCast(OSArray, deviceParameters->getObject(kIOHIDKeyboardModifierMappingPairsKey));
493    if (!mappings) goto GET_OUT;
494
495    count = mappings->getCount();
496    if ( count ) {
497        for ( unsigned i=0; i < count; i++ ) {
498            OSDictionary    *pair   = OSDynamicCast(OSDictionary, mappings->getObject(i));
499            OSNumber        *number         = NULL;
500            SInt32   src    = 0;
501            SInt32   dst    = 0;
502
503            if ( !pair ) continue;
504
505            number = OSDynamicCast(OSNumber, pair->getObject(kIOHIDKeyboardModifierMappingSrcKey));
506
507            if ( !number ) continue;
508
509            src = number->unsigned32BitValue();
510
511            if (src != NX_MODIFIERKEY_ALPHALOCK) continue;
512
513            number = OSDynamicCast(OSNumber, pair->getObject(kIOHIDKeyboardModifierMappingDstKey));
514
515            if ( !number ) continue;
516
517            dst = number->unsigned32BitValue();
518
519            if (dst == NX_MODIFIERKEY_ALPHALOCK) continue;
520
521            // NX_MODIFIERKEY_ALPHALOCK is remapped. Set delay to 0 and get out.
522            _keyboard.caps.delayMS = 0;
523            goto GET_OUT;
524        }
525    }
526
527GET_OUT:
528    OSSafeReleaseNULL(deviceParameters);
529    OSSafeReleaseNULL(delay);
530    IOHID_DEBUG(kIOHIDDebugCode_CalculatedCapsDelay, _keyboard.caps.delayMS, 0, 0, 0);
531}
532
533//====================================================================================================
534// IOHIDEventService::calculateStandardType
535//====================================================================================================
536void IOHIDEventService::calculateStandardType()
537{
538    IOHIDStandardType   result = kIOHIDStandardTypeANSI;
539    OSNumber *          number;
540
541        number = (OSNumber*)copyProperty(kIOHIDStandardTypeKey);
542        if ( OSDynamicCast(OSNumber, number) ) {
543            result = number->unsigned32BitValue();
544        }
545        else {
546            OSSafeReleaseNULL(number);
547            UInt16 productID    = getProductID();
548            UInt16 vendorID     = getVendorID();
549
550            if (vendorID == kIOUSBVendorIDAppleComputer) {
551
552                switch (productID) {
553                    case kprodUSBCosmoISOKbd:  //Cosmo ISO
554                    case kprodUSBAndyISOKbd:  //Andy ISO
555                    case kprodQ6ISOKbd:  //Q6 ISO
556                    case kprodQ30ISOKbd:  //Q30 ISO
557#if TARGET_OS_EMBEDDED
558                        _keyboard.swapISO = true;
559#endif /* TARGET_OS_EMBEDDED */
560                        // fall through
561                    case kprodFountainISOKbd:  //Fountain ISO
562                    case kprodSantaISOKbd:  //Santa ISO
563                        result = kIOHIDStandardTypeISO;
564                        break;
565                    case kprodUSBCosmoJISKbd:  //Cosmo JIS
566                    case kprodUSBAndyJISKbd:  //Andy JIS is 0x206
567                    case kprodQ6JISKbd:  //Q6 JIS
568                    case kprodQ30JISKbd:  //Q30 JIS
569                    case kprodFountainJISKbd:  //Fountain JIS
570                    case kprodSantaJISKbd:  //Santa JIS
571                        result = kIOHIDStandardTypeJIS;
572                        break;
573                }
574
575                setProperty(kIOHIDStandardTypeKey, result, 32);
576            }
577        }
578    OSSafeReleaseNULL(number);
579
580#if TARGET_OS_EMBEDDED
581    if ( !_keyboard.swapISO && result == kIOHIDStandardTypeISO ) {
582        number = (OSNumber*)copyProperty("alt_handler_id");
583        if ( OSDynamicCast(OSNumber, number) ) {
584            switch (number->unsigned32BitValue()) {
585                case kgestUSBCosmoISOKbd:
586                case kgestUSBAndyISOKbd:
587                case kgestQ6ISOKbd:
588                case kgestQ30ISOKbd:
589                case kgestM89ISOKbd:
590                case kgestUSBGenericISOkd:
591                    _keyboard.swapISO = true;
592                    break;
593            }
594        }
595        OSSafeReleaseNULL(number);
596    }
597#endif /* TARGET_OS_EMBEDDED */
598}
599
600//====================================================================================================
601// IOHIDEventService::setSystemProperties
602//====================================================================================================
603IOReturn IOHIDEventService::setSystemProperties( OSDictionary * properties )
604{
605    OSDictionary *  dict        = NULL;
606    OSArray *       array       = NULL;
607    OSNumber *      number      = NULL;
608    bool            setCapsDelay= false;
609
610    if ( !properties )
611        return kIOReturnBadArgument;
612
613    if ( properties->getObject(kIOHIDDeviceParametersKey) != kOSBooleanTrue ) {
614        OSDictionary * propsCopy = OSDictionary::withDictionary(properties);
615        if ( propsCopy ) {
616            propsCopy->setObject(kIOHIDEventServicePropertiesKey, kOSBooleanTrue);
617
618#if !TARGET_OS_EMBEDDED
619            if ( _keyboardNub )
620                _keyboardNub->setParamProperties(properties);
621
622            if ( _pointingNub )
623                _pointingNub->setParamProperties(properties);
624
625            if ( _consumerNub )
626                _consumerNub->setParamProperties(properties);
627#endif
628            propsCopy->release();
629        }
630    }
631
632    number = OSDynamicCast(OSNumber, properties->getObject(kIOHIDKeyboardCapsLockDelayOverride));
633    if (number) {
634        setProperty(kIOHIDKeyboardCapsLockDelayOverride, number);
635        setCapsDelay = true;
636    }
637
638    if ( ( array = OSDynamicCast(OSArray, properties->getObject(kIOHIDKeyboardModifierMappingPairsKey)) ) ) {
639        UInt32  srcVirtualCode, dstVirtualCode;
640        Boolean capsMap = FALSE;
641
642        for (UInt32 index=0; index<array->getCount(); index++) {
643
644            dict = OSDynamicCast(OSDictionary, array->getObject(index));
645            if ( !dict )
646                continue;
647
648            number = OSDynamicCast(OSNumber, dict->getObject(kIOHIDKeyboardModifierMappingSrcKey));
649            if ( !number )
650                continue;
651
652            srcVirtualCode = number->unsigned32BitValue();
653            if ( srcVirtualCode != NX_MODIFIERKEY_ALPHALOCK )
654                continue;
655
656            number = OSDynamicCast(OSNumber, dict->getObject(kIOHIDKeyboardModifierMappingDstKey));
657            if ( !number )
658                continue;
659
660            dstVirtualCode = number->unsigned32BitValue();
661            if ( dstVirtualCode == srcVirtualCode )
662                continue;
663
664            capsMap = TRUE;
665
666            break;
667        }
668
669        if ( capsMap ) {
670            // Clear out the delay
671            _keyboard.caps.delayMS = 0;
672            setCapsDelay = false;
673        }
674        else if ( !_keyboard.caps.delayMS ) {
675            setCapsDelay = true;
676        }
677    }
678
679    if (setCapsDelay)
680        calculateCapsLockDelay();
681
682    if ( properties->getObject(kIOHIDDeviceParametersKey) == kOSBooleanTrue ) {
683        OSDictionary * eventServiceProperties = (OSDictionary*)copyProperty(kIOHIDEventServicePropertiesKey);
684        if ( OSDynamicCast(OSDictionary, eventServiceProperties) ) {
685            if (eventServiceProperties->setOptions(0, 0) & OSDictionary::kImmutable) {
686                OSDictionary * temp = eventServiceProperties;
687                eventServiceProperties = OSDynamicCast(OSDictionary, temp->copyCollection());
688                temp->release();
689            }
690            else {
691                // do nothing
692            }
693        }
694        else {
695            OSSafeReleaseNULL(eventServiceProperties);
696            eventServiceProperties = OSDictionary::withCapacity(4);
697        }
698
699        if ( eventServiceProperties ) {
700            eventServiceProperties->merge(properties);
701            eventServiceProperties->removeObject(kIOHIDResetKeyboardKey);
702            eventServiceProperties->removeObject(kIOHIDResetPointerKey);
703            eventServiceProperties->removeObject(kIOHIDDeviceParametersKey);
704
705            setProperty(kIOHIDEventServicePropertiesKey, eventServiceProperties);
706            eventServiceProperties->release();
707        }
708    }
709
710    return kIOReturnSuccess;
711}
712
713//====================================================================================================
714// IOHIDEventService::setProperties
715//====================================================================================================
716IOReturn IOHIDEventService::setProperties( OSObject * properties )
717{
718    OSDictionary *  propertyDict    = OSDynamicCast(OSDictionary, properties);
719    IOReturn        ret             = kIOReturnBadArgument;
720
721    if ( propertyDict ) {
722        propertyDict->setObject(kIOHIDDeviceParametersKey, kOSBooleanTrue);
723        ret = setSystemProperties( propertyDict );
724        propertyDict->removeObject(kIOHIDDeviceParametersKey);
725    }
726
727    return ret;
728}
729
730
731//====================================================================================================
732// IOHIDEventService::parseSupportedElements
733//====================================================================================================
734void IOHIDEventService::parseSupportedElements ( OSArray * elementArray, UInt32 bootProtocol )
735{
736    UInt32              count               = 0;
737    UInt32              index               = 0;
738    UInt32              usage               = 0;
739    UInt32              usagePage           = 0;
740    UInt32              supportedModifiers  = 0;
741    UInt32              buttonCount         = 0;
742    IOHIDElement *      element             = 0;
743    OSArray *           functions           = 0;
744    IOFixed             pointingResolution  = 0;
745    IOFixed             scrollResolution    = 0;
746    bool                pointingDevice      = false;
747    bool                keyboardDevice      = false;
748    bool                consumerDevice      = false;
749
750    switch ( bootProtocol )
751    {
752        case kBootProtocolMouse:
753            pointingDevice = true;
754            break;
755        case kBootProtocolKeyboard:
756            keyboardDevice = true;
757            break;
758    }
759
760    if ( elementArray )
761    {
762        count = elementArray->getCount();
763
764        for ( index = 0; index < count; index++ )
765        {
766            element = OSDynamicCast(IOHIDElement, elementArray->getObject(index));
767
768            if ( !element )
769                continue;
770
771            usagePage   = element->getUsagePage();
772            usage       = element->getUsage();
773
774            switch ( usagePage )
775            {
776                case kHIDPage_GenericDesktop:
777                    switch ( usage )
778                    {
779                        case kHIDUsage_GD_Mouse:
780                            pointingDevice      = true;
781                            break;
782                        case kHIDUsage_GD_X:
783                            if ( !(pointingResolution = determineResolution(element)) )
784                                pointingResolution = kDefaultFixedResolution;
785                        case kHIDUsage_GD_Y:
786                        case kHIDUsage_GD_Z:
787                            if ((element->getFlags() & kIOHIDElementFlagsRelativeMask) == 0)
788                            {
789                                processTabletElement ( element );
790                            }
791                            break;
792                        case kHIDUsage_GD_Wheel:
793                            if ( !(scrollResolution = determineResolution(element)) )
794                                scrollResolution = kDefaultScrollFixedResolution;
795                            break;
796                        case kHIDUsage_GD_SystemPowerDown:
797                        case kHIDUsage_GD_SystemSleep:
798                        case kHIDUsage_GD_SystemWakeUp:
799                            consumerDevice      = true;
800                            break;
801                    }
802                    break;
803
804                case kHIDPage_Button:
805                    processTabletElement ( element );
806                    buttonCount ++;
807                    break;
808
809                case kHIDPage_KeyboardOrKeypad:
810                    keyboardDevice = true;
811                    switch ( usage )
812                    {
813                        case kHIDUsage_KeyboardLeftControl:
814                            supportedModifiers |= NX_CONTROLMASK;
815                            supportedModifiers |= NX_DEVICELCTLKEYMASK;
816                            break;
817                        case kHIDUsage_KeyboardLeftShift:
818                            supportedModifiers |= NX_SHIFTMASK;
819                            supportedModifiers |= NX_DEVICELSHIFTKEYMASK;
820                            break;
821                        case kHIDUsage_KeyboardLeftAlt:
822                            supportedModifiers |= NX_ALTERNATEMASK;
823                            supportedModifiers |= NX_DEVICELALTKEYMASK;
824                            break;
825                        case kHIDUsage_KeyboardLeftGUI:
826                            supportedModifiers |= NX_COMMANDMASK;
827                            supportedModifiers |= NX_DEVICELCMDKEYMASK;
828                            break;
829                        case kHIDUsage_KeyboardRightControl:
830                            supportedModifiers |= NX_CONTROLMASK;
831                            supportedModifiers |= NX_DEVICERCTLKEYMASK;
832                            break;
833                        case kHIDUsage_KeyboardRightShift:
834                            supportedModifiers |= NX_SHIFTMASK;
835                            supportedModifiers |= NX_DEVICERSHIFTKEYMASK;
836                            break;
837                        case kHIDUsage_KeyboardRightAlt:
838                            supportedModifiers |= NX_ALTERNATEMASK;
839                            supportedModifiers |= NX_DEVICERALTKEYMASK;
840                            break;
841                        case kHIDUsage_KeyboardRightGUI:
842                            supportedModifiers |= NX_COMMANDMASK;
843                            supportedModifiers |= NX_DEVICERCMDKEYMASK;
844                            break;
845                        case kHIDUsage_KeyboardCapsLock:
846                            supportedModifiers |= NX_ALPHASHIFT_STATELESS_MASK;
847                            supportedModifiers |= NX_DEVICE_ALPHASHIFT_STATELESS_MASK;
848                            break;
849                    }
850                    break;
851
852                case kHIDPage_Consumer:
853                    consumerDevice = true;
854                    break;
855                case kHIDPage_Digitizer:
856                    pointingDevice = true;
857                    switch ( usage )
858                    {
859                        case kHIDUsage_Dig_Pen:
860                        case kHIDUsage_Dig_LightPen:
861                        case kHIDUsage_Dig_TouchScreen:
862                            setProperty(kIOHIDDisplayIntegratedKey, true);
863                            break;
864                        case kHIDUsage_Dig_TipSwitch:
865                        case kHIDUsage_Dig_BarrelSwitch:
866                        case kHIDUsage_Dig_Eraser:
867                            buttonCount ++;
868                        default:
869                             processTabletElement ( element );
870                            break;
871                    }
872                    break;
873                case kHIDPage_AppleVendorTopCase:
874                    if ((getVendorID() == kIOUSBVendorIDAppleComputer) &&
875                        (usage == kHIDUsage_AV_TopCase_KeyboardFn))
876                    {
877                        supportedModifiers |= NX_SECONDARYFNMASK;
878                    }
879                    break;
880            }
881
882            // Cache device functions
883            if ((element->getType() == kIOHIDElementTypeCollection) &&
884                ((element->getCollectionType() == kIOHIDElementCollectionTypeApplication) ||
885                (element->getCollectionType() == kIOHIDElementCollectionTypePhysical)))
886            {
887                OSNumber * usagePageRef, * usageRef;
888                OSDictionary * pairRef;
889
890                if(!functions) functions = OSArray::withCapacity(2);
891
892                pairRef     = OSDictionary::withCapacity(2);
893                usageRef    = OSNumber::withNumber(usage, 32);
894                usagePageRef= OSNumber::withNumber(usagePage, 32);
895
896                pairRef->setObject(kIOHIDDeviceUsageKey, usageRef);
897                pairRef->setObject(kIOHIDDeviceUsagePageKey, usagePageRef);
898
899                UInt32 	pairCount = functions->getCount();
900                bool 	found = false;
901                for(unsigned i=0; i<pairCount; i++)
902                {
903                    OSDictionary *tempPair = (OSDictionary *)functions->getObject(i);
904
905                    if ( NULL != (found = tempPair->isEqualTo(pairRef)) )
906                        break;
907                }
908
909                if (!found)
910                {
911                    functions->setObject(functions->getCount(), pairRef);
912                }
913
914                pairRef->release();
915                usageRef->release();
916                usagePageRef->release();
917            }
918        }
919
920        _deviceUsagePairs = functions;
921    }
922
923    processTransducerData();
924
925    NUB_LOCK;
926
927    if ( pointingDevice )
928    {
929        _pointingNub = newPointingShim(buttonCount, pointingResolution, scrollResolution, kShimEventProcessor);
930    }
931    if ( keyboardDevice )
932    {
933        _keyboardNub = newKeyboardShim(supportedModifiers, kShimEventProcessor);
934	}
935    if ( consumerDevice )
936    {
937        _consumerNub = newConsumerShim(kShimEventProcessor);
938    }
939
940    NUB_UNLOCK;
941}
942
943//====================================================================================================
944// IOHIDEventService::processTabletElement
945//====================================================================================================
946void IOHIDEventService::processTabletElement ( IOHIDElement * element )
947{
948    TransducerData *    transducerRef;
949    IOHIDElement *      parent;
950
951    transducerRef = getTransducerData(element->getReportID());
952
953    if ( !transducerRef )
954    {
955        transducerRef = createTransducerData ( element->getReportID() );
956    }
957
958    if ( element->getUsagePage() == kHIDPage_Digitizer )
959    {
960        switch (element->getUsage())
961        {
962            case kHIDUsage_Dig_Stylus:
963                transducerRef->type         = NX_TABLET_POINTER_PEN;
964                break;
965            case kHIDUsage_Dig_Puck:
966                transducerRef->type         = NX_TABLET_POINTER_CURSOR;
967                break;
968            case kHIDUsage_Dig_XTilt:
969                transducerRef->capabilities |= NX_TABLET_CAPABILITY_TILTXMASK;
970                break;
971            case kHIDUsage_Dig_YTilt:
972                transducerRef->capabilities |= NX_TABLET_CAPABILITY_TILTYMASK;
973                break;
974            case kHIDUsage_Dig_TipPressure:
975                if ( transducerRef->type == NX_TABLET_POINTER_UNKNOWN )
976                    transducerRef->type = NX_TABLET_POINTER_PEN;
977
978                transducerRef->capabilities |= NX_TABLET_CAPABILITY_PRESSUREMASK;
979                break;
980            case kHIDUsage_Dig_BarrelPressure:
981                if ( transducerRef->type == NX_TABLET_POINTER_UNKNOWN )
982                    transducerRef->type = NX_TABLET_POINTER_PEN;
983
984                transducerRef->capabilities |= NX_TABLET_CAPABILITY_TANGENTIALPRESSUREMASK;
985                break;
986            case kHIDUsage_Dig_Twist:
987                transducerRef->capabilities |= NX_TABLET_CAPABILITY_ROTATIONMASK;
988                break;
989            case kHIDUsage_Dig_TransducerIndex:
990                transducerRef->supportsTransducerIndex = true;
991                break;
992            case kHIDUsage_Dig_Eraser:
993                if ( transducerRef->type == NX_TABLET_POINTER_UNKNOWN )
994                    transducerRef->type = NX_TABLET_POINTER_ERASER;
995            case kHIDUsage_Dig_TipSwitch:
996            case kHIDUsage_Dig_BarrelSwitch:
997                if ( transducerRef->type == NX_TABLET_POINTER_UNKNOWN )
998                    transducerRef->type = NX_TABLET_POINTER_PEN;
999
1000                transducerRef->capabilities |= NX_TABLET_CAPABILITY_BUTTONSMASK;
1001                break;
1002        }
1003    }
1004    else if ( element->getUsagePage() == kHIDPage_GenericDesktop )
1005    {
1006        switch (element->getUsage())
1007        {
1008            case kHIDUsage_GD_X:
1009                transducerRef->capabilities |= NX_TABLET_CAPABILITY_ABSXMASK;
1010                break;
1011            case kHIDUsage_GD_Y:
1012                transducerRef->capabilities |= NX_TABLET_CAPABILITY_ABSYMASK;
1013                break;
1014            case kHIDUsage_GD_Z:
1015                transducerRef->capabilities |= NX_TABLET_CAPABILITY_ABSZMASK;
1016                break;
1017        }
1018    }
1019    else if ( element->getUsagePage() == kHIDPage_Button )
1020    {
1021        transducerRef->capabilities |= NX_TABLET_CAPABILITY_BUTTONSMASK;
1022    }
1023
1024    if ( element->getType() != kIOHIDElementTypeCollection )
1025    {
1026        parent = element->getParentElement();
1027
1028        if ( parent && ( parent->getUsagePage() == kHIDPage_Digitizer ))
1029        {
1030            transducerRef->digitizerCollection = true;
1031        }
1032    }
1033}
1034
1035//====================================================================================================
1036// IOHIDEventService::createTransducerData
1037//====================================================================================================
1038TransducerData * IOHIDEventService::createTransducerData ( UInt32 transducerID )
1039{
1040    TransducerData      temp;
1041    OSData *            data;
1042
1043    if ( ! _transducerDataArray )
1044        _transducerDataArray = OSArray::withCapacity(4);
1045
1046    bzero(&temp, sizeof(TransducerData));
1047
1048    temp.reportID   = transducerID;
1049    temp.type       = NX_TABLET_POINTER_UNKNOWN;
1050
1051    data            = OSData::withBytes(&temp, sizeof(TransducerData));
1052
1053    _transducerDataArray->setObject(data);
1054    data->release();
1055
1056    return (data) ? (TransducerData *)data->getBytesNoCopy() : 0;
1057}
1058
1059//====================================================================================================
1060// IOHIDEventService::getTransducerData
1061//====================================================================================================
1062TransducerData * IOHIDEventService::getTransducerData ( UInt32 transducerID )
1063{
1064    TransducerData *    transducerRef       = 0;
1065    TransducerData *    transducerIndexRef  = 0;
1066    OSData *            data                = 0;
1067    bool                found               = 0;
1068
1069    if ( !_transducerDataArray )
1070        return NULL;
1071
1072    UInt32  count = _transducerDataArray->getCount();
1073
1074    for (unsigned i=0; i<count; i++)
1075    {
1076        data = (OSData *)_transducerDataArray->getObject(i);
1077
1078        if (!data) continue;
1079
1080        transducerRef = (TransducerData *)data->getBytesNoCopy();
1081
1082        if (!transducerRef) continue;
1083
1084        if (transducerRef->supportsTransducerIndex)
1085            transducerIndexRef = transducerRef;
1086
1087        if (transducerRef->reportID != transducerID) continue;
1088
1089        found = true;
1090        break;
1091    }
1092
1093    return ( found ) ? transducerRef : transducerIndexRef;
1094}
1095
1096//====================================================================================================
1097// IOHIDEventService::processTransducerData
1098//====================================================================================================
1099void IOHIDEventService::processTransducerData ()
1100{
1101#if !TARGET_OS_EMBEDDED
1102    TransducerData *    transducerRef;
1103    OSData *            data;
1104
1105    if ( ! _transducerDataArray )
1106        return;
1107
1108    for (unsigned i=0; i<_transducerDataArray->getCount(); i++)
1109    {
1110        data = (OSData *)_transducerDataArray->getObject(i);
1111
1112        if (!data) continue;
1113
1114        transducerRef = (TransducerData *)data->getBytesNoCopy();
1115
1116        if ( (transducerRef->capabilities & ~NX_TABLET_CAPABILITY_BUTTONSMASK) ||
1117             (transducerRef->digitizerCollection))
1118        {
1119            transducerRef->deviceID     = IOHIDPointing::generateDeviceID();
1120            transducerRef->capabilities |= NX_TABLET_CAPABILITY_DEVICEIDMASK;
1121        }
1122        else
1123        {
1124            _transducerDataArray->removeObject(i--);
1125        }
1126    }
1127
1128    if ( _transducerDataArray->getCount() == 0 )
1129    {
1130        _transducerDataArray->release();
1131        _transducerDataArray = 0;
1132    }
1133#endif /* TARGET_OS_EMBEDDED */
1134}
1135
1136//====================================================================================================
1137// IOHIDEventService::newPointingShim
1138//====================================================================================================
1139IOHIDPointing * IOHIDEventService::newPointingShim (
1140                            UInt32          buttonCount,
1141                            IOFixed         pointerResolution,
1142                            IOFixed         scrollResolution,
1143                            IOOptionBits    options)
1144{
1145#if !TARGET_OS_EMBEDDED // {
1146    bool            isDispatcher = ((options & kShimEventProcessor) == 0);
1147    IOHIDPointing   *pointingNub = IOHIDPointing::Pointing(buttonCount, pointerResolution, scrollResolution, isDispatcher);;
1148
1149    require(pointingNub, no_nub);
1150
1151	SET_HID_PROPERTIES(pointingNub);
1152
1153    require(pointingNub->attach(this), no_attach);
1154    require(pointingNub->start(this), no_start);
1155
1156    return pointingNub;
1157
1158no_start:
1159    pointingNub->detach(this);
1160
1161no_attach:
1162    pointingNub->release();
1163    pointingNub = NULL;
1164
1165no_nub:
1166
1167#endif // } TARGET_OS_EMBEDDED
1168    return NULL;
1169}
1170
1171//====================================================================================================
1172// IOHIDEventService::newKeyboardShim
1173//====================================================================================================
1174IOHIDKeyboard * IOHIDEventService::newKeyboardShim (
1175                                UInt32          supportedModifiers,
1176                                IOOptionBits    options)
1177{
1178#if !TARGET_OS_EMBEDDED // {
1179    bool            isDispatcher = ((options & kShimEventProcessor) == 0);
1180    IOHIDKeyboard   *keyboardNub = IOHIDKeyboard::Keyboard(supportedModifiers, isDispatcher);
1181
1182    require(keyboardNub, no_nub);
1183
1184        SET_HID_PROPERTIES(keyboardNub);
1185
1186    require(keyboardNub->attach(this), no_attach);
1187    require(keyboardNub->start(this), no_start);
1188
1189    return keyboardNub;
1190
1191no_start:
1192    keyboardNub->detach(this);
1193
1194no_attach:
1195    keyboardNub->release();
1196    keyboardNub = NULL;
1197
1198no_nub:
1199
1200#endif // } TARGET_OS_EMBEDDED
1201    return NULL;
1202}
1203
1204//====================================================================================================
1205// IOHIDEventService::newConsumerShim
1206//====================================================================================================
1207IOHIDConsumer * IOHIDEventService::newConsumerShim ( IOOptionBits options )
1208{
1209#if !TARGET_OS_EMBEDDED // {
1210    bool            isDispatcher = ((options & kShimEventProcessor) == 0);
1211    IOHIDConsumer   *consumerNub = IOHIDConsumer::Consumer(isDispatcher);;
1212
1213    require(consumerNub, no_nub);
1214
1215        SET_HID_PROPERTIES(consumerNub);
1216
1217    require(consumerNub->attach(this), no_attach);
1218    require(consumerNub->start(this), no_start);
1219
1220    return consumerNub;
1221
1222no_start:
1223    consumerNub->detach(this);
1224
1225no_attach:
1226    consumerNub->release();
1227    consumerNub = NULL;
1228
1229no_nub:
1230
1231#endif // } TARGET_OS_EMBEDDED
1232    return NULL;
1233}
1234
1235//====================================================================================================
1236// IOHIDEventService::determineResolution
1237//====================================================================================================
1238IOFixed IOHIDEventService::determineResolution ( IOHIDElement * element )
1239{
1240    IOFixed resolution = 0;
1241    bool supportResolution = true;
1242
1243    if ((element->getFlags() & kIOHIDElementFlagsRelativeMask) != 0) {
1244
1245        if ( element->conformsTo(kHIDPage_GenericDesktop, kHIDUsage_GD_MultiAxisController) )
1246            supportResolution = false;
1247    }
1248    else {
1249        supportResolution = false;
1250    }
1251
1252    if ( supportResolution ) {
1253        if ((element->getPhysicalMin() != element->getLogicalMin()) &&
1254            (element->getPhysicalMax() != element->getLogicalMax()))
1255        {
1256            SInt32 logicalDiff = (element->getLogicalMax() - element->getLogicalMin());
1257            SInt32 physicalDiff = (element->getPhysicalMax() - element->getPhysicalMin());
1258
1259            // Since IOFixedDivide truncated fractional part and can't use floating point
1260            // within the kernel, have to convert equation when using negative exponents:
1261            // _resolution = ((logMax -logMin) * 10 **(-exp))/(physMax -physMin)
1262
1263            // Even though unitExponent is stored as SInt32, The real values are only
1264            // a signed nibble that doesn't expand to the full 32 bits.
1265            SInt32 resExponent = element->getUnitExponent() & 0x0F;
1266
1267            if (resExponent < 8)
1268            {
1269                for (int i = resExponent; i > 0; i--)
1270                {
1271                    physicalDiff *=  10;
1272                }
1273            }
1274            else
1275            {
1276                for (int i = 0x10 - resExponent; i > 0; i--)
1277                {
1278                    logicalDiff *= 10;
1279                }
1280            }
1281            resolution = (logicalDiff / physicalDiff) << 16;
1282        }
1283    }
1284
1285    return resolution;
1286}
1287
1288//====================================================================================================
1289// IOHIDEventService::free
1290//====================================================================================================
1291void IOHIDEventService::free()
1292{
1293    IORecursiveLock* tempLock = NULL;
1294
1295    if ( _nubLock ) {
1296        IORecursiveLockLock(_nubLock);
1297        tempLock = _nubLock;
1298        _nubLock = NULL;
1299    }
1300
1301    if ( _transducerDataArray ) {
1302        _transducerDataArray->release();
1303        _transducerDataArray = 0;
1304    }
1305
1306    if ( _transducerDataArray ) {
1307        _transducerDataArray->release();
1308        _transducerDataArray = 0;
1309    }
1310
1311    if (_keyboard.eject.timer) {
1312        if ( _workLoop )
1313            _workLoop->removeEventSource(_keyboard.eject.timer);
1314
1315        _keyboard.eject.timer->release();
1316        _keyboard.eject.timer = 0;
1317    }
1318
1319    if (_commandGate) {
1320        if ( _workLoop )
1321            _workLoop->removeEventSource(_commandGate);
1322
1323        _commandGate->release();
1324        _commandGate = 0;
1325    }
1326
1327    if (_keyboard.caps.timer) {
1328        if ( _workLoop )
1329            _workLoop->removeEventSource(_keyboard.caps.timer);
1330
1331        _keyboard.caps.timer->release();
1332        _keyboard.caps.timer = 0;
1333    }
1334
1335#if TARGET_OS_EMBEDDED
1336    if ( _deviceUsagePairs ) {
1337        _deviceUsagePairs->release();
1338        _deviceUsagePairs = NULL;
1339    }
1340
1341    if ( _clientDict ) {
1342        assert(_clientDict->getCount() == 0);
1343        _clientDict->release();
1344        _clientDict = NULL;
1345    }
1346
1347    if (_keyboard.debug.timer) {
1348        if ( _workLoop )
1349            _workLoop->removeEventSource(_keyboard.debug.timer);
1350
1351        _keyboard.debug.timer->release();
1352        _keyboard.debug.timer = 0;
1353    }
1354
1355#endif /* TARGET_OS_EMBEDDED */
1356
1357    if ( _workLoop ) {
1358        // not our workloop. don't stop it.
1359        _workLoop->release();
1360        _workLoop = NULL;
1361    }
1362
1363    if (_reserved) {
1364        IODelete(_reserved, ExpansionData, 1);
1365        _reserved = NULL;
1366    }
1367
1368    if ( tempLock ) {
1369        IORecursiveLockUnlock(tempLock);
1370        IORecursiveLockFree(tempLock);
1371    }
1372
1373    super::free();
1374}
1375
1376//==============================================================================
1377// IOHIDEventService::handleOpen
1378//==============================================================================
1379bool IOHIDEventService::handleOpen(IOService *  client,
1380                                    IOOptionBits options,
1381                                    void *       argument)
1382{
1383#if TARGET_OS_EMBEDDED
1384
1385    bool accept = false;
1386    do {
1387        // Was this object already registered as our client?
1388
1389        if ( _clientDict->getObject((const OSSymbol *)client) ) {
1390            accept = true;
1391            break;
1392        }
1393
1394        // Add the new client object to our client dict.
1395        if ( !OSDynamicCast(IOHIDClientData, (OSObject *)argument) ||
1396                !_clientDict->setObject((const OSSymbol *)client, (IOHIDClientData *)argument))
1397            break;
1398
1399        accept = true;
1400    } while (false);
1401
1402    return accept;
1403
1404#else
1405
1406    return super::handleOpen(client, options, argument);
1407
1408#endif /* TARGET_OS_EMBEDDED */
1409
1410}
1411
1412//==============================================================================
1413// IOHIDEventService::handleClose
1414//==============================================================================
1415void IOHIDEventService::handleClose(IOService * client, IOOptionBits options)
1416{
1417#if TARGET_OS_EMBEDDED
1418    if ( _clientDict->getObject((const OSSymbol *)client) )
1419        _clientDict->removeObject((const OSSymbol *)client);
1420#else
1421    super::handleClose(client, options);
1422#endif /* TARGET_OS_EMBEDDED */
1423}
1424
1425//==============================================================================
1426// IOHIDEventService::handleIsOpen
1427//==============================================================================
1428bool IOHIDEventService::handleIsOpen(const IOService * client) const
1429{
1430#if TARGET_OS_EMBEDDED
1431    if (client)
1432        return _clientDict->getObject((const OSSymbol *)client) != NULL;
1433    else
1434        return (_clientDict->getCount() > 0);
1435#else
1436    return super::handleIsOpen(client);
1437#endif /* TARGET_OS_EMBEDDED */
1438}
1439
1440//====================================================================================================
1441// IOHIDEventService::handleStart
1442//====================================================================================================
1443bool IOHIDEventService::handleStart( IOService * provider __unused )
1444{
1445    return true;
1446}
1447
1448//====================================================================================================
1449// IOHIDEventService::handleStop
1450//====================================================================================================
1451void IOHIDEventService::handleStop(  IOService * provider __unused )
1452{}
1453
1454//====================================================================================================
1455// IOHIDEventService::getTransport
1456//====================================================================================================
1457OSString * IOHIDEventService::getTransport ()
1458{
1459    return _provider ? OSDynamicCast(OSString, _provider->getProperty(kIOHIDTransportKey)) : 0;
1460}
1461
1462//====================================================================================================
1463// IOHIDEventService::getManufacturer
1464//====================================================================================================
1465OSString * IOHIDEventService::getManufacturer ()
1466{
1467    // vtn3: This is not safe, but I am unsure how to fix it
1468    return _provider ? OSDynamicCast(OSString, _provider->getProperty(kIOHIDManufacturerKey)) : 0;
1469}
1470
1471//====================================================================================================
1472// IOHIDEventService::getProduct
1473//====================================================================================================
1474OSString * IOHIDEventService::getProduct ()
1475{
1476    // vtn3: This is not safe, but I am unsure how to fix it
1477    return _provider ? OSDynamicCast(OSString, _provider->getProperty(kIOHIDProductKey)) : 0;
1478}
1479
1480//====================================================================================================
1481// IOHIDEventService::getSerialNumber
1482//====================================================================================================
1483OSString * IOHIDEventService::getSerialNumber ()
1484{
1485    // vtn3: This is not safe, but I am unsure how to fix it
1486    return _provider ? OSDynamicCast(OSString, _provider->getProperty(kIOHIDSerialNumberKey)) : 0;
1487}
1488
1489//====================================================================================================
1490// IOHIDEventService::getLocationID
1491//====================================================================================================
1492UInt32 IOHIDEventService::getLocationID ()
1493{
1494	UInt32 value = 0;
1495
1496	if ( _provider ) {
1497		OSNumber * number = (OSNumber*)_provider->copyProperty(kIOHIDSerialNumberKey);
1498		if ( OSDynamicCast(OSNumber, number) )
1499			value = number->unsigned32BitValue();
1500		OSSafeReleaseNULL(number);
1501	}
1502    return value;
1503}
1504
1505//====================================================================================================
1506// IOHIDEventService::getVendorID
1507//====================================================================================================
1508UInt32 IOHIDEventService::getVendorID ()
1509{
1510	UInt32 value = 0;
1511
1512	if ( _provider ) {
1513		OSNumber * number = (OSNumber*)_provider->copyProperty(kIOHIDVendorIDKey);
1514		if ( OSDynamicCast(OSNumber, number) )
1515			value = number->unsigned32BitValue();
1516		OSSafeReleaseNULL(number);
1517	}
1518    return value;
1519}
1520
1521//====================================================================================================
1522// IOHIDEventService::getVendorIDSource
1523//====================================================================================================
1524UInt32 IOHIDEventService::getVendorIDSource ()
1525{
1526	UInt32 value = 0;
1527
1528	if ( _provider ) {
1529		OSNumber * number = (OSNumber*)_provider->copyProperty(kIOHIDVendorIDSourceKey);
1530		if ( OSDynamicCast(OSNumber, number) )
1531			value = number->unsigned32BitValue();
1532		OSSafeReleaseNULL(number);
1533	}
1534    return value;
1535}
1536
1537//====================================================================================================
1538// IOHIDEventService::getProductID
1539//====================================================================================================
1540UInt32 IOHIDEventService::getProductID ()
1541{
1542	UInt32 value = 0;
1543
1544	if ( _provider ) {
1545		OSNumber * number = (OSNumber*)_provider->copyProperty(kIOHIDProductIDKey);
1546		if ( OSDynamicCast(OSNumber, number) )
1547			value = number->unsigned32BitValue();
1548		OSSafeReleaseNULL(number);
1549	}
1550    return value;
1551}
1552
1553//====================================================================================================
1554// IOHIDEventService::getVersion
1555//====================================================================================================
1556UInt32 IOHIDEventService::getVersion ()
1557{
1558	UInt32 value = 0;
1559
1560	if ( _provider ) {
1561		OSNumber * number = (OSNumber*)_provider->copyProperty(kIOHIDVersionNumberKey);
1562		if ( OSDynamicCast(OSNumber, number) )
1563			value = number->unsigned32BitValue();
1564		OSSafeReleaseNULL(number);
1565	}
1566    return value;
1567}
1568
1569//====================================================================================================
1570// IOHIDEventService::getCountryCode
1571//====================================================================================================
1572UInt32 IOHIDEventService::getCountryCode ()
1573{
1574	UInt32 value = 0;
1575
1576	if ( _provider ) {
1577		OSNumber * number = (OSNumber*)_provider->copyProperty(kIOHIDCountryCodeKey);
1578		if ( OSDynamicCast(OSNumber, number) )
1579			value = number->unsigned32BitValue();
1580        OSSafeReleaseNULL(number);
1581	}
1582    return value;
1583}
1584
1585//====================================================================================================
1586// IOHIDEventService::getReportElements
1587//====================================================================================================
1588OSArray * IOHIDEventService::getReportElements()
1589{
1590    return 0;
1591}
1592
1593//====================================================================================================
1594// IOHIDEventService::setElementValue
1595//====================================================================================================
1596void IOHIDEventService::setElementValue (
1597                                UInt32                      usagePage __unused,
1598                                UInt32                      usage __unused,
1599                                UInt32                      value __unused )
1600{
1601}
1602
1603//====================================================================================================
1604// IOHIDEventService::getElementValue
1605//====================================================================================================
1606UInt32 IOHIDEventService::getElementValue (
1607                                UInt32                      usagePage __unused,
1608                                UInt32                      usage __unused )
1609{
1610    return 0;
1611}
1612
1613
1614//====================================================================================================
1615// ejectTimerCallback
1616//====================================================================================================
1617void IOHIDEventService::ejectTimerCallback(IOTimerEventSource *sender __unused)
1618{
1619    IOHID_DEBUG(kIOHIDDebugCode_EjectCallback, _keyboard.eject.state, 0, 0, 0);
1620    if ( _keyboard.eject.state ) {
1621        AbsoluteTime timeStamp;
1622
1623        clock_get_uptime(&timeStamp);
1624
1625        dispatchKeyboardEvent(timeStamp, kHIDPage_Consumer, kHIDUsage_Csmr_Eject, 1, _keyboard.eject.options | kDelayedOption);
1626        dispatchKeyboardEvent(timeStamp, kHIDPage_Consumer, kHIDUsage_Csmr_Eject, 0, _keyboard.eject.options | kDelayedOption);
1627
1628        _keyboard.eject.state = 0;
1629    }
1630}
1631
1632//====================================================================================================
1633// capsTimerCallback
1634//====================================================================================================
1635void IOHIDEventService::capsTimerCallback(IOTimerEventSource *sender __unused)
1636{
1637    IOHID_DEBUG(kIOHIDDebugCode_CapsCallback, _keyboard.caps.state, 0, 0, 0);
1638    if ( _keyboard.caps.state ) {
1639        AbsoluteTime timeStamp;
1640
1641        clock_get_uptime(&timeStamp);
1642
1643        dispatchKeyboardEvent(timeStamp, kHIDPage_KeyboardOrKeypad, kHIDUsage_KeyboardCapsLock, 1, _keyboard.caps.options | kDelayedOption);
1644        dispatchKeyboardEvent(timeStamp, kHIDPage_KeyboardOrKeypad, kHIDUsage_KeyboardCapsLock, 0, _keyboard.caps.options | kDelayedOption);
1645
1646        _keyboard.caps.state = 0;
1647    }
1648}
1649
1650
1651#if TARGET_OS_EMBEDDED
1652//==============================================================================
1653// IOHIDEventService::debuggerTimerCallback
1654//==============================================================================
1655void IOHIDEventService::debuggerTimerCallback(IOTimerEventSource *sender)
1656{
1657    if ( _keyboard.debug.mask && _keyboard.debug.mask == _keyboard.debug.startMask   )
1658        PE_enter_debugger("NMI");
1659}
1660
1661#endif /* TARGET_OS_EMBEDDED */
1662
1663//==============================================================================
1664// IOHIDEventService::multiAxisTimerCallback
1665//==============================================================================
1666void IOHIDEventService::multiAxisTimerCallback(IOTimerEventSource *sender __unused)
1667{
1668    AbsoluteTime timestamp;
1669
1670    clock_get_uptime(&timestamp);
1671    dispatchMultiAxisPointerEvent(timestamp, _multiAxis.buttonState, _multiAxis.x, _multiAxis.y, _multiAxis.z, _multiAxis.rX, _multiAxis.rY, _multiAxis.rZ, _multiAxis.options | kIOHIDEventOptionIsRepeat);
1672}
1673
1674
1675//====================================================================================================
1676// IOHIDEventService::dispatchKeyboardEvent
1677//====================================================================================================
1678void IOHIDEventService::dispatchKeyboardEvent(
1679                                AbsoluteTime                timeStamp,
1680                                UInt32                      usagePage,
1681                                UInt32                      usage,
1682                                UInt32                      value,
1683                                IOOptionBits                options)
1684{
1685    if ( ! _readyForInputReports )
1686        return;
1687
1688#if TARGET_OS_EMBEDDED // {
1689    IOHIDEvent * event = NULL;
1690    UInt32 debugMask = 0;
1691
1692    switch (usagePage) {
1693        case kHIDPage_KeyboardOrKeypad:
1694            if ( _keyboard.swapISO ) {
1695
1696                switch ( usage ) {
1697                    case kHIDUsage_KeyboardGraveAccentAndTilde:
1698                        usage = kHIDUsage_KeyboardNonUSBackslash;
1699                        break;
1700                    case kHIDUsage_KeyboardNonUSBackslash:
1701                        usage = kHIDUsage_KeyboardGraveAccentAndTilde;
1702                        break;
1703                }
1704            }
1705            break;
1706        case kHIDPage_Consumer:
1707            switch (usage) {
1708                case kHIDUsage_Csmr_Power:
1709                    debugMask = 0x1;
1710                    break;
1711                case kHIDUsage_Csmr_VolumeIncrement:
1712                case kHIDUsage_Csmr_VolumeDecrement:
1713                    debugMask = 0x2;
1714                    break;
1715            };
1716            break;
1717        case kHIDPage_Telephony:
1718            switch (usage) {
1719                case kHIDUsage_Tfon_Hold:
1720                    debugMask = 0x1;
1721                    break;
1722            };
1723            break;
1724    };
1725
1726    if ( value )
1727        _keyboard.debug.mask |= debugMask;
1728    else
1729        _keyboard.debug.mask &= ~debugMask;
1730
1731    if ( _keyboard.debug.mask == 0x3) {
1732        if ( !_keyboard.debug.timer ) {
1733            _keyboard.debug.timer = IOTimerEventSource::timerEventSource(this, OSMemberFunctionCast(IOTimerEventSource::Action, this, &IOHIDEventService::debuggerTimerCallback));
1734            if (_keyboard.debug.timer) {
1735                if ((_workLoop->addEventSource(_keyboard.debug.timer) != kIOReturnSuccess)) {
1736                    _keyboard.debug.timer->release();
1737                    _keyboard.debug.timer = NULL;
1738                }
1739            }
1740        }
1741        if ( _keyboard.debug.timer ) {
1742            _keyboard.debug.timer->setTimeoutMS( kDebuggerDelayMS );
1743            _keyboard.debug.startMask = _keyboard.debug.mask;
1744        }
1745    }
1746
1747    event = IOHIDEvent::keyboardEvent(timeStamp, usagePage, usage, value, options);
1748    if ( !event )
1749        return;
1750
1751    dispatchEvent(event);
1752
1753    event->release();
1754
1755#else // } {
1756
1757    NUB_LOCK;
1758
1759    IOHID_DEBUG(kIOHIDDebugCode_DispatchKeyboard, usagePage, usage, value, options);
1760
1761    if ((( usagePage == kHIDPage_KeyboardOrKeypad ) &&
1762            (usage != kHIDUsage_KeyboardLockingNumLock) &&
1763            !(_keyboard.caps.delayMS && (usage == kHIDUsage_KeyboardCapsLock))) ||
1764            ((getVendorID() == kIOUSBVendorIDAppleComputer) &&
1765             ((usagePage == kHIDPage_AppleVendorKeyboard) ||
1766              ((usagePage == kHIDPage_AppleVendorTopCase) &&
1767               (usage == kHIDUsage_AV_TopCase_KeyboardFn))))) {
1768        if ( !_keyboardNub )
1769            _keyboardNub = newKeyboardShim();
1770
1771        if ( _keyboardNub )
1772            _keyboardNub->dispatchKeyboardEvent(timeStamp, usagePage, usage, (value != 0), options);
1773
1774    }
1775    else {
1776        if ( !_consumerNub )
1777            _consumerNub = newConsumerShim();
1778
1779        if ( _consumerNub ) {
1780            if ( (usagePage == kHIDPage_Consumer) && (usage == kHIDUsage_Csmr_Eject) && ((options & kDelayedOption) == 0) && _keyboardNub && ((_keyboardNub->eventFlags() & SPECIALKEYS_MODIFIER_MASK) == 0)) {
1781                if (( _keyboard.eject.state != value ) && _keyboard.eject.timer) {
1782                    if ( value ) {
1783                        _keyboard.eject.options       = options;
1784
1785                        _keyboard.eject.timer->setTimeoutMS( _keyboard.eject.delayMS );
1786                    }
1787                    else {
1788                        _keyboard.eject.timer->cancelTimeout();
1789                    }
1790
1791                   _keyboard.eject.state = value;
1792                }
1793            }
1794            else  if (!(((options & kDelayedOption) == 0) && _keyboard.eject.state && (usagePage == kHIDPage_Consumer) && (usage == kHIDUsage_Csmr_Eject))) {
1795                _consumerNub->dispatchConsumerEvent(_keyboardNub, timeStamp, usagePage, usage, value, options);
1796            }
1797        }
1798
1799        if ( _keyboard.caps.delayMS && (usagePage == kHIDPage_KeyboardOrKeypad) && (usage == kHIDUsage_KeyboardCapsLock)) {
1800            if ( (options & kDelayedOption) == 0) {
1801
1802                if ( getElementValue(kHIDPage_LEDs, kHIDUsage_LED_CapsLock) == 0 ) {
1803                    if (( _keyboard.caps.state != value ) && _keyboard.caps.timer ) {
1804                        if ( value ) {
1805                            _keyboard.caps.options       = options;
1806
1807                            _keyboard.caps.timer->setTimeoutMS( _keyboard.caps.delayMS );
1808                        }
1809                        else {
1810                            _keyboard.caps.timer->cancelTimeout();
1811                        }
1812
1813                        _keyboard.caps.state = value;
1814                    }
1815                }
1816                else {
1817                    _keyboardNub->dispatchKeyboardEvent(timeStamp, usagePage, usage, value, options);
1818                }
1819            }
1820            else  if (!( ((options & kDelayedOption) == 0) && _keyboard.caps.state ) ) {
1821                _keyboardNub->dispatchKeyboardEvent(timeStamp, usagePage, usage, value, options);
1822            }
1823        }
1824    }
1825
1826    NUB_UNLOCK;
1827
1828#endif /* TARGET_OS_EMBEDDED */ // }
1829
1830}
1831
1832
1833//====================================================================================================
1834// IOHIDEventService::dispatchRelativePointerEvent
1835//====================================================================================================
1836void IOHIDEventService::dispatchRelativePointerEvent(
1837                                AbsoluteTime                timeStamp,
1838                                SInt32                      dx,
1839                                SInt32                      dy,
1840                                UInt32                      buttonState,
1841                                IOOptionBits                options)
1842{
1843    IOHID_DEBUG(kIOHIDDebugCode_DispatchRelativePointer, dx, dy, buttonState, options);
1844
1845    if ( ! _readyForInputReports )
1846        return;
1847
1848#if TARGET_OS_EMBEDDED
1849
1850    IOHIDEvent *event = IOHIDEvent::relativePointerEvent(timeStamp, dx, dy, 0, buttonState);
1851
1852    if ( event ) {
1853        dispatchEvent(event);
1854        event->release();
1855    }
1856
1857#else
1858    NUB_LOCK;
1859
1860    if ( !_pointingNub )
1861        _pointingNub = newPointingShim();
1862
1863    if ( _pointingNub )
1864        _pointingNub->dispatchRelativePointerEvent(timeStamp, dx, dy, buttonState, options);
1865
1866    NUB_UNLOCK;
1867#endif /* TARGET_OS_EMBEDDED */
1868}
1869
1870#if TARGET_OS_EMBEDDED
1871static IOFixed __ScaleToFixed(int32_t value, int32_t min, int32_t max)
1872{
1873    int32_t range = max - min;
1874    int32_t offset = value - min;
1875
1876    return IOFixedDivide(offset<<16, range<<16);
1877}
1878#endif
1879
1880//====================================================================================================
1881// IOHIDEventService::dispatchAbsolutePointerEvent
1882//====================================================================================================
1883void IOHIDEventService::dispatchAbsolutePointerEvent(
1884                                                     AbsoluteTime                timeStamp,
1885                                                     SInt32                      x,
1886                                                     SInt32                      y,
1887                                                     IOGBounds *                 bounds,
1888                                                     UInt32                      buttonState,
1889                                                     bool                        inRange,
1890                                                     SInt32                      tipPressure,
1891                                                     SInt32                      tipPressureMin,
1892                                                     SInt32                      tipPressureMax,
1893                                                     IOOptionBits                options)
1894{
1895#if TARGET_OS_EMBEDDED
1896
1897    dispatchDigitizerEvent(timeStamp, 0, kDigitizerTransducerTypeStylus, inRange, buttonState, __ScaleToFixed(x, bounds->minx, bounds->maxx), __ScaleToFixed(y, bounds->miny, bounds->maxy), __ScaleToFixed(tipPressure, tipPressureMin, tipPressureMax));
1898
1899#else
1900    IOHID_DEBUG(kIOHIDDebugCode_DispatchAbsolutePointer, x, y, buttonState, options);
1901
1902    if ( ! _readyForInputReports )
1903        return;
1904
1905    if ( !inRange ) {
1906        buttonState = 0;
1907        tipPressure = tipPressureMin;
1908    }
1909
1910    NUB_LOCK;
1911
1912    if ( !_pointingNub )
1913        _pointingNub = newPointingShim();
1914
1915    IOGPoint newLoc;
1916
1917    newLoc.x = x;
1918    newLoc.y = y;
1919
1920    _pointingNub->dispatchAbsolutePointerEvent(timeStamp, &newLoc, bounds, buttonState, inRange, tipPressure, tipPressureMin, tipPressureMax, options);
1921
1922    NUB_UNLOCK;
1923#endif /* !TARGET_OS_EMBEDDED */
1924
1925}
1926
1927//====================================================================================================
1928// IOHIDEventService::dispatchScrollWheelEvent
1929//====================================================================================================
1930void IOHIDEventService::dispatchScrollWheelEvent(
1931                                AbsoluteTime                timeStamp,
1932                                SInt32                      deltaAxis1,
1933                                SInt32                      deltaAxis2,
1934                                SInt32                      deltaAxis3,
1935                                IOOptionBits                options)
1936{
1937    IOHID_DEBUG(kIOHIDDebugCode_DispatchScroll, deltaAxis1, deltaAxis2, deltaAxis3, options);
1938
1939    if ( ! _readyForInputReports )
1940        return;
1941
1942#if TARGET_OS_EMBEDDED
1943
1944    IOHIDEvent *event = IOHIDEvent::scrollEvent(timeStamp, deltaAxis2, deltaAxis1, deltaAxis3); //yxz should be xyz
1945
1946    if ( event ) {
1947        dispatchEvent(event);
1948        event->release();
1949    }
1950
1951#else
1952
1953    NUB_LOCK;
1954
1955    if ( !_pointingNub )
1956        _pointingNub = newPointingShim();
1957
1958    if ( _pointingNub )
1959        _pointingNub->dispatchScrollWheelEvent(timeStamp, deltaAxis1, deltaAxis2, deltaAxis3, options);
1960
1961    NUB_UNLOCK;
1962#endif /* TARGET_OS_EMBEDDED */
1963}
1964
1965#if !TARGET_OS_EMBEDDED
1966static void ScalePressure(SInt32 *pressure, SInt32 pressureMin, SInt32 pressureMax, SInt32 systemPressureMin, SInt32 systemPressureMax)
1967{
1968    SInt64  systemScale = systemPressureMax - systemPressureMin;
1969
1970
1971    *pressure = ((pressureMin != pressureMax)) ?
1972                (((unsigned)(*pressure - pressureMin) * systemScale) /
1973                (unsigned)( pressureMax - pressureMin)) + systemPressureMin: 0;
1974}
1975#endif /* TARGET_OS_EMBEDDED */
1976
1977//====================================================================================================
1978// IOHIDEventService::dispatchTabletPointEvent
1979//====================================================================================================
1980void IOHIDEventService::dispatchTabletPointerEvent(
1981                                AbsoluteTime                timeStamp,
1982                                UInt32                      transducerID,
1983                                SInt32                      x,
1984                                SInt32                      y,
1985                                SInt32                      z,
1986                                IOGBounds *                 bounds __unused,
1987                                UInt32                      buttonState,
1988                                SInt32                      tipPressure,
1989                                SInt32                      tipPressureMin,
1990                                SInt32                      tipPressureMax,
1991                                SInt32                      barrelPressure,
1992                                SInt32                      barrelPressureMin,
1993                                SInt32                      barrelPressureMax,
1994                                SInt32                      tiltX,
1995                                SInt32                      tiltY,
1996                                UInt32                      twist,
1997                                IOOptionBits                options)
1998{
1999#if !TARGET_OS_EMBEDDED
2000    IOHID_DEBUG(kIOHIDDebugCode_DispatchTabletPointer, x, y, buttonState, options);
2001
2002    if ( ! _readyForInputReports )
2003        return;
2004
2005    NUB_LOCK;
2006
2007    if ( !_pointingNub )
2008        _pointingNub = newPointingShim();
2009
2010    TransducerData *    transducerRef = getTransducerData(transducerID);
2011
2012    if (transducerRef) {
2013        NXEventData         tabletData = {};
2014
2015        ScalePressure(&tipPressure, tipPressureMin, tipPressureMax, 0, kMaxSystemTipPressure);
2016        ScalePressure(&barrelPressure, barrelPressureMin, barrelPressureMax, -kMaxSystemBarrelPressure, kMaxSystemBarrelPressure);
2017
2018        IOGPoint newLoc;
2019
2020        newLoc.x = x;
2021        newLoc.y = y;
2022
2023        //IOHIDSystem::scaleLocationToCurrentScreen(&newLoc, bounds);
2024
2025        tabletData.tablet.x                    = newLoc.x;
2026        tabletData.tablet.y                    = newLoc.y;
2027        tabletData.tablet.z                    = z;
2028        tabletData.tablet.buttons              = buttonState;
2029        tabletData.tablet.pressure             = tipPressure;
2030        tabletData.tablet.tilt.x               = tiltX;
2031        tabletData.tablet.tilt.y               = tiltY;
2032        tabletData.tablet.rotation             = twist;
2033        tabletData.tablet.tangentialPressure   = barrelPressure;
2034        tabletData.tablet.deviceID             = transducerRef->deviceID;
2035
2036        _pointingNub->dispatchTabletEvent(&tabletData, timeStamp);
2037    }
2038
2039    NUB_UNLOCK;
2040#endif /* !TARGET_OS_EMBEDDED */
2041}
2042
2043//====================================================================================================
2044// IOHIDEventService::dispatchTabletProximityEvent
2045//====================================================================================================
2046void IOHIDEventService::dispatchTabletProximityEvent(
2047                                AbsoluteTime                timeStamp,
2048                                UInt32                      transducerID,
2049                                bool                        inRange,
2050                                bool                        invert,
2051                                UInt32                      vendorTransducerUniqueID,
2052                                UInt32                      vendorTransducerSerialNumber,
2053                                IOOptionBits                options)
2054{
2055#if !TARGET_OS_EMBEDDED
2056    IOHID_DEBUG(kIOHIDDebugCode_DispatchTabletProx, transducerID, vendorTransducerUniqueID, vendorTransducerSerialNumber, options);
2057
2058    if ( ! _readyForInputReports )
2059        return;
2060
2061    NUB_LOCK;
2062
2063    if ( !_pointingNub )
2064        _pointingNub = newPointingShim();
2065
2066    TransducerData *    transducerRef = getTransducerData(transducerID);
2067
2068    if (transducerRef) {
2069        NXEventData tabletData = {};
2070
2071        tabletData.proximity.vendorID               = getVendorID();
2072        tabletData.proximity.tabletID               = getProductID();
2073        tabletData.proximity.pointerID              = transducerID;
2074        tabletData.proximity.deviceID               = transducerRef->deviceID;
2075        tabletData.proximity.vendorPointerType      = transducerRef->type;
2076        tabletData.proximity.pointerSerialNumber    = vendorTransducerSerialNumber;
2077        tabletData.proximity.uniqueID               = vendorTransducerUniqueID;
2078        tabletData.proximity.capabilityMask         = transducerRef->capabilities;
2079        tabletData.proximity.enterProximity         = inRange;
2080        tabletData.proximity.pointerType            =
2081            (invert && (transducerRef->type == NX_TABLET_POINTER_PEN)) ?
2082            NX_TABLET_POINTER_ERASER : NX_TABLET_POINTER_PEN;
2083
2084        _pointingNub->dispatchProximityEvent(&tabletData, timeStamp);
2085    }
2086
2087    NUB_UNLOCK;
2088
2089#endif /* !TARGET_OS_EMBEDDED */
2090}
2091
2092bool IOHIDEventService::readyForReports()
2093{
2094    return _readyForInputReports;
2095}
2096
2097//==============================================================================
2098// IOHIDEventService::getDeviceUsagePairs
2099//==============================================================================
2100OSMetaClassDefineReservedUsed(IOHIDEventService,  0);
2101OSArray * IOHIDEventService::getDeviceUsagePairs()
2102{
2103    //RY: Correctly deal with kIOHIDDeviceUsagePairsKey
2104    OSArray * providerUsagePairs = (OSArray*)_provider->copyProperty(kIOHIDDeviceUsagePairsKey);
2105
2106    if ( OSDynamicCast(OSArray, providerUsagePairs) && ( providerUsagePairs != _deviceUsagePairs ) ) {
2107        setProperty(kIOHIDDeviceUsagePairsKey, providerUsagePairs);
2108        if ( _deviceUsagePairs )
2109            _deviceUsagePairs->release();
2110
2111        _deviceUsagePairs = providerUsagePairs;
2112        _deviceUsagePairs->retain();
2113    }
2114#if TARGET_OS_EMBEDDED
2115    else if ( !_deviceUsagePairs ) {
2116        _deviceUsagePairs = OSArray::withCapacity(2);
2117
2118        if ( _deviceUsagePairs ) {
2119            OSDictionary * pair = OSDictionary::withCapacity(2);
2120
2121            if ( pair ) {
2122                OSNumber * number;
2123
2124                number = OSNumber::withNumber(getPrimaryUsagePage(), 32);
2125                if ( number ) {
2126                    pair->setObject(kIOHIDDeviceUsagePageKey, number);
2127                    number->release();
2128                }
2129
2130                number = OSNumber::withNumber(getPrimaryUsage(), 32);
2131                if ( number ) {
2132                    pair->setObject(kIOHIDDeviceUsageKey, number);
2133                    number->release();
2134                }
2135
2136                _deviceUsagePairs->setObject(pair);
2137                pair->release();
2138            }
2139        }
2140    }
2141#endif
2142    OSSafeRelease(providerUsagePairs);
2143
2144    return _deviceUsagePairs;
2145}
2146
2147//==============================================================================
2148// IOHIDEventService::getReportInterval
2149//==============================================================================
2150OSMetaClassDefineReservedUsed(IOHIDEventService,  1);
2151UInt32 IOHIDEventService::getReportInterval()
2152{
2153    UInt32 interval = 8000; // default to 8 milliseconds
2154    OSObject *object = copyProperty(kIOHIDReportIntervalKey, gIOServicePlane, kIORegistryIterateRecursively | kIORegistryIterateParents);
2155    if ( OSDynamicCast(OSNumber, object) )
2156        interval = ((OSNumber*)object)->unsigned32BitValue();
2157    OSSafeReleaseNULL(object);
2158
2159    return interval;
2160}
2161
2162#define kCenteredPointerMaxRelativeValue 8
2163#define GET_RELATIVE_VALUE_FROM_CENTERED(centered,relative) \
2164    relative = (centered * kCenteredPointerMaxRelativeValue) >> 16;\
2165
2166OSMetaClassDefineReservedUsed(IOHIDEventService,  2);
2167//==============================================================================
2168// IOHIDEventService::dispatchMultiAxisPointerEvent
2169//==============================================================================
2170void IOHIDEventService::dispatchMultiAxisPointerEvent(
2171                                                    AbsoluteTime               timeStamp,
2172                                                    UInt32                     buttonState,
2173                                                    IOFixed                    x,
2174                                                    IOFixed                    y,
2175                                                    IOFixed                    z,
2176                                                    IOFixed                    rX,
2177                                                    IOFixed                    rY,
2178                                                    IOFixed                    rZ,
2179                                                    IOOptionBits               options)
2180{
2181
2182    bool    validAxis       = false;
2183    bool    validRelative   = false;
2184    bool    validScroll     = false;
2185    bool    isZButton       = false;
2186    UInt32  interval        = 0;
2187
2188    if ( ! _readyForInputReports )
2189        return;
2190
2191    validRelative   = ( options & kMultiAxisOptionRotationForTranslation ) ? rX || rY || _multiAxis.rX || _multiAxis.rY : x || y || _multiAxis.x || _multiAxis.y;
2192    validScroll     = rZ || _multiAxis.rZ;
2193
2194    validAxis       = x || y || z || rX || rY || rZ || _multiAxis.x || _multiAxis.y || _multiAxis.z || _multiAxis.rX || _multiAxis.rY || _multiAxis.rZ;
2195
2196    if ( options & kMultiAxisOptionZForScroll ) {
2197        validScroll |= z || _multiAxis.z;
2198    } else if ( z > 0 ){
2199        isZButton = true;
2200        buttonState |= (z>>16) & 1;
2201    }
2202
2203    validRelative |= buttonState != _multiAxis.buttonState;
2204
2205    if ( validAxis || validRelative || validScroll ) {
2206
2207        SInt32 dx = 0;
2208        SInt32 dy = 0;
2209        SInt32 sx = 0;
2210        SInt32 sy = 0;
2211
2212        if ( !isZButton && (options & kMultiAxisOptionRotationForTranslation) ) {
2213            GET_RELATIVE_VALUE_FROM_CENTERED(-rY, dx);
2214            GET_RELATIVE_VALUE_FROM_CENTERED(rX, dy);
2215        } else {
2216            GET_RELATIVE_VALUE_FROM_CENTERED(x, dx);
2217            GET_RELATIVE_VALUE_FROM_CENTERED(y, dy);
2218        }
2219
2220        GET_RELATIVE_VALUE_FROM_CENTERED(rZ, sy);
2221
2222        if ( options & kMultiAxisOptionZForScroll )
2223            GET_RELATIVE_VALUE_FROM_CENTERED(z, sx);
2224
2225#if TARGET_OS_EMBEDDED
2226        IOHIDEvent * subEvent = IOHIDEvent::multiAxisPointerEvent(timeStamp, buttonState, x, y, z, rX, rY, rZ);
2227        if ( subEvent ) {
2228
2229            IOHIDEvent * event;
2230
2231            if ( validRelative || (!validRelative && !validScroll) ) {
2232                event = IOHIDEvent::relativePointerEvent(timeStamp, dx, dy, 0, buttonState);
2233                if ( event ) {
2234
2235                    if ( subEvent ) {
2236                        event->appendChild(subEvent);
2237                    }
2238
2239                    dispatchEvent(event);
2240                    event->release();
2241                }
2242            }
2243
2244            if ( validScroll ) {
2245                event = IOHIDEvent::scrollEvent(timeStamp, sx, sy, 0);
2246                if ( event ) {
2247
2248                    if ( subEvent ) {
2249                        event->appendChild(subEvent);
2250                    }
2251
2252                    dispatchEvent(event);
2253                    event->release();
2254                }
2255            }
2256
2257            subEvent->release();
2258        }
2259#else
2260        dispatchRelativePointerEvent(timeStamp, dx, dy, buttonState, options);
2261        dispatchScrollWheelEvent(timeStamp, sy, sx, 0, options);
2262#endif
2263
2264        if ( (options & kIOHIDEventOptionIsRepeat) == 0 ) {
2265            _multiAxis.timer->cancelTimeout();
2266            if ( validAxis )
2267                interval = getReportInterval() + getReportInterval()/2;
2268        } else if ( validAxis ) {
2269            interval = getReportInterval();
2270        }
2271
2272        if ( interval )
2273            _multiAxis.timer->setTimeoutUS(interval);
2274
2275    }
2276
2277    _multiAxis.x            = x;
2278    _multiAxis.y            = y;
2279    _multiAxis.z            = z;
2280    _multiAxis.rX           = rX;
2281    _multiAxis.rY           = rY;
2282    _multiAxis.rZ           = rZ;
2283    _multiAxis.buttonState  = buttonState;
2284    _multiAxis.options      = options;
2285}
2286
2287//==============================================================================
2288// IOHIDEventService::dispatchDigitizerEventWithOrientation
2289//==============================================================================
2290void IOHIDEventService::dispatchDigitizerEventWithOrientation(
2291                                AbsoluteTime                    timeStamp,
2292                                DigitizerTransducerType         type __unused,
2293                                UInt32                          transducerID,
2294                                bool                            inRange,
2295                                UInt32                          buttonState,
2296                                IOFixed                         x,
2297                                IOFixed                         y,
2298                                IOFixed                         z,
2299                                IOFixed                         tipPressure,
2300                                IOFixed                         auxPressure,
2301                                IOFixed                         twist,
2302                                DigitizerOrientationType        orientationType,
2303                                IOFixed *                       orientationParams,
2304                                UInt32                          orientationParamCount,
2305                                IOOptionBits                    options)
2306{
2307    IOHID_DEBUG(kIOHIDDebugCode_DispatchDigitizer, x, y, buttonState, options);
2308
2309    IOFixed params[5]   = {};
2310    bool    touch       = false;
2311
2312    if ( ! _readyForInputReports )
2313        return;
2314
2315    if ( !inRange ) {
2316        buttonState = 0;
2317        tipPressure = 0;
2318    }
2319
2320    if ( orientationParams ) {
2321        orientationParamCount = min(5, orientationParamCount);
2322
2323        bcopy(orientationParams, params, sizeof(IOFixed) * orientationParamCount);
2324    }
2325
2326#if TARGET_OS_EMBEDDED
2327    IOHIDEvent *    collectionEvent = NULL;
2328    IOHIDEvent *    childEvent      = NULL;
2329    SInt32          eventMask       = 0;   // what's changed
2330    UInt32          eventOptions    = 0;
2331
2332    if ( options & kDigitizerInvert )
2333        eventOptions |= kIOHIDTransducerInvert;
2334
2335    childEvent = IOHIDEvent::digitizerEvent(timeStamp, transducerID, type, inRange, buttonState, x, y, z, tipPressure, auxPressure, twist, eventOptions);
2336    require(childEvent, exit);
2337
2338    buttonState |= (tipPressure>>16) & 1;
2339
2340    if ( tipPressure )
2341        touch |= 1;
2342    else
2343        touch |= buttonState & 1;
2344
2345    childEvent->setIntegerValue(kIOHIDEventFieldDigitizerTouch, touch);
2346    if (touch != _digitizer.touch) {
2347        eventMask |= kIOHIDDigitizerEventTouch;
2348    }
2349
2350    if (inRange != _digitizer.range) {
2351        eventMask |= kIOHIDDigitizerEventRange;
2352
2353        if ( inRange ) {
2354            _digitizer.x = x;
2355            _digitizer.y = y;
2356            eventMask |= kIOHIDDigitizerEventIdentity;
2357        }
2358    }
2359
2360    if (inRange && ( (_digitizer.x != x) || (_digitizer.y != y) || (_digitizer.z != z) ) ) {
2361        eventMask |= kIOHIDDigitizerEventPosition;
2362    }
2363
2364
2365    childEvent->setIntegerValue(kIOHIDEventFieldDigitizerEventMask, eventMask);
2366
2367    collectionEvent = IOHIDEvent::digitizerEvent(timeStamp, transducerID, type, inRange, buttonState, x, y, z, tipPressure, auxPressure, twist, eventOptions);
2368    require(collectionEvent, exit);
2369
2370    collectionEvent->setIntegerValue(kIOHIDEventFieldDigitizerCollection, TRUE);
2371    collectionEvent->setIntegerValue(kIOHIDEventFieldDigitizerRange, childEvent->getIntegerValue(kIOHIDEventFieldDigitizerRange));
2372    collectionEvent->setIntegerValue(kIOHIDEventFieldDigitizerEventMask, childEvent->getIntegerValue(kIOHIDEventFieldDigitizerEventMask));
2373    collectionEvent->setIntegerValue(kIOHIDEventFieldDigitizerTouch, childEvent->getIntegerValue(kIOHIDEventFieldDigitizerTouch));
2374
2375    collectionEvent->appendChild(childEvent);
2376
2377    dispatchEvent(collectionEvent);
2378
2379exit:
2380    if ( collectionEvent )
2381        collectionEvent->release();
2382
2383    if ( childEvent )
2384        childEvent->release();
2385
2386#else
2387
2388    bool invert = options & kDigitizerInvert;
2389
2390    // Entering proximity
2391    if ( inRange && inRange != _digitizer.range ) {
2392        dispatchTabletProximityEvent(timeStamp, transducerID, inRange, invert);
2393    }
2394
2395    if ( inRange ) {
2396        Bounds  bounds = {0, kMaxSystemAbsoluteRangeSigned, 0, kMaxSystemAbsoluteRangeSigned};
2397
2398        SInt32 scaledX      = ((SInt64)x * kMaxSystemAbsoluteRangeSigned) >> 16;
2399        SInt32 scaledY      = ((SInt64)y * kMaxSystemAbsoluteRangeSigned) >> 16;
2400        SInt32 scaledZ      = ((SInt64)z * kMaxSystemAbsoluteRangeSigned) >> 16;
2401        SInt32 scaledTP     = ((SInt64)tipPressure * EV_MAXPRESSURE) >> 16;
2402        SInt32 scaledBP     = ((SInt64)auxPressure * EV_MAXPRESSURE) >> 16;
2403        SInt32 scaledTiltX  = (((SInt64)params[0] * kMaxSystemAbsoluteRangeSigned)/90) >> 16;
2404        SInt32 scaledTiltY  = (((SInt64)params[1] * kMaxSystemAbsoluteRangeSigned)/90) >> 16;
2405
2406        if ( orientationType != kDigitizerOrientationTypeTilt )
2407            bzero(params, sizeof(params));
2408
2409        dispatchTabletPointerEvent(timeStamp, transducerID, scaledX, scaledY, scaledZ, &bounds, buttonState, scaledTP, 0, EV_MAXPRESSURE, scaledBP, 0, EV_MAXPRESSURE, scaledTiltX, scaledTiltY, twist>>10 /*10:6 fixed*/);
2410
2411        dispatchAbsolutePointerEvent(timeStamp, scaledX, scaledY, &bounds, buttonState, inRange, scaledTP, 0, EV_MAXPRESSURE);
2412    }
2413
2414    if ( !inRange && inRange != _digitizer.range ) {
2415        dispatchTabletProximityEvent(timeStamp, transducerID, inRange, invert);
2416    }
2417
2418
2419
2420#endif /* TARGET_OS_EMBEDDED */
2421
2422    _digitizer.range        = inRange;
2423    _digitizer.x            = x;
2424    _digitizer.y            = y;
2425    _digitizer.z            = z;
2426    _digitizer.touch        = touch;
2427
2428}
2429
2430//==============================================================================
2431// IOHIDEventService::dispatchDigitizerEvent
2432//==============================================================================
2433OSMetaClassDefineReservedUsed(IOHIDEventService,  3);
2434void IOHIDEventService::dispatchDigitizerEvent(
2435                                               AbsoluteTime                    timeStamp,
2436                                               UInt32                          transducerID,
2437                                               DigitizerTransducerType         type,
2438                                               bool                            inRange,
2439                                               UInt32                          buttonState,
2440                                               IOFixed                         x,
2441                                               IOFixed                         y,
2442                                               IOFixed                         z,
2443                                               IOFixed                         tipPressure,
2444                                               IOFixed                         auxPressure,
2445                                               IOFixed                         twist,
2446                                               IOOptionBits                    options )
2447{
2448    dispatchDigitizerEventWithOrientation(timeStamp, transducerID, type, inRange, buttonState, x, y, z, tipPressure, auxPressure, twist, kDigitizerOrientationTypeTilt, NULL, 0, options);
2449}
2450
2451//==============================================================================
2452// IOHIDEventService::dispatchDigitizerEventWithTiltOrientation
2453//==============================================================================
2454OSMetaClassDefineReservedUsed(IOHIDEventService,  4);
2455void IOHIDEventService::dispatchDigitizerEventWithTiltOrientation(
2456                                                                  AbsoluteTime                    timeStamp,
2457                                                                  UInt32                          transducerID,
2458                                                                  DigitizerTransducerType         type,
2459                                                                  bool                            inRange,
2460                                                                  UInt32                          buttonState,
2461                                                                  IOFixed                         x,
2462                                                                  IOFixed                         y,
2463                                                                  IOFixed                         z,
2464                                                                  IOFixed                         tipPressure,
2465                                                                  IOFixed                         auxPressure,
2466                                                                  IOFixed                         twist,
2467                                                                  IOFixed                         tiltX,
2468                                                                  IOFixed                         tiltY,
2469                                                                  IOOptionBits                    options)
2470{
2471    IOFixed params[] = {tiltX, tiltY};
2472
2473    dispatchDigitizerEventWithOrientation(timeStamp, transducerID, type, inRange, buttonState, x, y, z, tipPressure, auxPressure, twist, kDigitizerOrientationTypeTilt, params, sizeof(params)/sizeof(IOFixed), options);
2474}
2475
2476
2477//==============================================================================
2478// IOHIDEventService::dispatchDigitizerEventWithPolarOrientation
2479//==============================================================================
2480OSMetaClassDefineReservedUsed(IOHIDEventService,  5);
2481void IOHIDEventService::dispatchDigitizerEventWithPolarOrientation(
2482                                                                   AbsoluteTime                    timeStamp,
2483                                                                   UInt32                          transducerID,
2484                                                                   DigitizerTransducerType         type,
2485                                                                   bool                            inRange,
2486                                                                   UInt32                          buttonState,
2487                                                                   IOFixed                         x,
2488                                                                   IOFixed                         y,
2489                                                                   IOFixed                         z,
2490                                                                   IOFixed                         tipPressure,
2491                                                                   IOFixed                         auxPressure,
2492                                                                   IOFixed                         twist,
2493                                                                   IOFixed                         altitude,
2494                                                                   IOFixed                         azimuth,
2495                                                                   IOOptionBits                    options)
2496{
2497    IOFixed params[] = {altitude, azimuth};
2498
2499    dispatchDigitizerEventWithOrientation(timeStamp, transducerID, type, inRange, buttonState, x, y, z, tipPressure, auxPressure, twist, kDigitizerOrientationTypePolar, params, sizeof(params)/sizeof(IOFixed), options);
2500}
2501
2502
2503#if TARGET_OS_EMBEDDED
2504void IOHIDEventService::close(IOService *forClient, IOOptionBits options)
2505{
2506    _commandGate->runAction(OSMemberFunctionCast(IOCommandGate::Action, this, &IOHIDEventService::closeGated), forClient, (void*)options);
2507}
2508
2509void IOHIDEventService::closeGated(IOService *forClient, IOOptionBits options)
2510{
2511    super::close(forClient, options);
2512}
2513
2514OSDefineMetaClassAndStructors(IOHIDClientData, OSObject)
2515
2516IOHIDClientData * IOHIDClientData::withClientInfo(IOService *client, void* context, void * action)
2517{
2518    IOHIDClientData * data = new IOHIDClientData;
2519
2520    if (!data) { }
2521    else if (data->init()) {
2522        data->client  = client;
2523        data->context = context;
2524        data->action  = action;
2525    } else {
2526        data->release();
2527        data = NULL;
2528    }
2529
2530    return data;
2531}
2532
2533//==============================================================================
2534// IOHIDEventService::open
2535//==============================================================================
2536OSMetaClassDefineReservedUsed(IOHIDEventService,  6);
2537bool IOHIDEventService::open(   IOService *                 client,
2538                                IOOptionBits                options,
2539                                void *                      context,
2540                                Action                      action)
2541{
2542    return _commandGate->runAction(OSMemberFunctionCast(IOCommandGate::Action, this, &IOHIDEventService::openGated), client, (void*)options, context, (void*)action);
2543}
2544
2545//==============================================================================
2546// IOHIDEventService::dispatchEvent
2547//==============================================================================
2548OSMetaClassDefineReservedUsed(IOHIDEventService,  7);
2549void IOHIDEventService::dispatchEvent(IOHIDEvent * event, IOOptionBits options)
2550{
2551    OSCollectionIterator *  iterator = OSCollectionIterator::withCollection(_clientDict);
2552    IOHIDClientData *       clientData;
2553    OSObject *              clientKey;
2554    IOService *             client;
2555    void *                  context;
2556    Action                  action;
2557
2558    event->setSenderID(getRegistryEntryID());
2559
2560    IOHID_DEBUG(kIOHIDDebugCode_DispatchHIDEvent, options, 0, 0, 0);
2561
2562    if ( !iterator )
2563        return;
2564
2565    while ((clientKey = iterator->getNextObject())) {
2566
2567        clientData = OSDynamicCast(IOHIDClientData, _clientDict->getObject((const OSSymbol *)clientKey));
2568
2569        if ( !clientData )
2570            continue;
2571
2572        client  = clientData->getClient();
2573        context = clientData->getContext();
2574        action  = (Action)clientData->getAction();
2575
2576        if ( action )
2577            (*action)(client, this, context, event, options);
2578    }
2579
2580    iterator->release();
2581
2582}
2583
2584//==============================================================================
2585// IOHIDEventService::getPrimaryUsagePage
2586//==============================================================================
2587OSMetaClassDefineReservedUsed(IOHIDEventService,  8);
2588UInt32 IOHIDEventService::getPrimaryUsagePage ()
2589{
2590    UInt32		primaryUsagePage = 0;
2591    OSArray *	deviceUsagePairs = getDeviceUsagePairs();
2592
2593    if ( deviceUsagePairs && deviceUsagePairs->getCount() ) {
2594        OSDictionary * pair = OSDynamicCast(OSDictionary, deviceUsagePairs->getObject(0));
2595
2596        if ( pair ) {
2597            OSNumber * number = OSDynamicCast(OSNumber, pair->getObject(kIOHIDDeviceUsagePageKey));
2598
2599            if ( number )
2600                primaryUsagePage = number->unsigned32BitValue();
2601        }
2602    }
2603
2604    return primaryUsagePage;
2605}
2606
2607//==============================================================================
2608// IOHIDEventService::getPrimaryUsage
2609//==============================================================================
2610OSMetaClassDefineReservedUsed(IOHIDEventService,  9);
2611UInt32 IOHIDEventService::getPrimaryUsage ()
2612{
2613    UInt32		primaryUsage		= 0;
2614    OSArray *	deviceUsagePairs	= getDeviceUsagePairs();
2615
2616    if ( deviceUsagePairs && deviceUsagePairs->getCount() ) {
2617        OSDictionary * pair = OSDynamicCast(OSDictionary, deviceUsagePairs->getObject(0));
2618
2619        if ( pair ) {
2620            OSNumber * number = OSDynamicCast(OSNumber, pair->getObject(kIOHIDDeviceUsageKey));
2621
2622            if ( number )
2623                primaryUsage = number->unsigned32BitValue();
2624        }
2625    }
2626
2627    return primaryUsage;
2628}
2629
2630//==============================================================================
2631// IOHIDEventService::copyEvent
2632//==============================================================================
2633OSMetaClassDefineReservedUsed(IOHIDEventService,  10);
2634IOHIDEvent * IOHIDEventService::copyEvent(
2635                                IOHIDEventType              type,
2636                                IOHIDEvent *                matching,
2637                                IOOptionBits                options)
2638{
2639    return NULL;
2640}
2641
2642//==============================================================================
2643// IOHIDEventService::openGated
2644//==============================================================================
2645bool IOHIDEventService::openGated(IOService *                 client,
2646                                  IOOptionBits                options,
2647                                  void *                      context,
2648                                  Action                      action)
2649{
2650    IOHIDClientData * clientData =
2651    IOHIDClientData::withClientInfo(client, context, (void*)action);
2652    bool ret = false;
2653
2654    if ( clientData ) {
2655        if ( super::open(client, options, clientData) )
2656            ret = true;
2657        clientData->release();
2658    }
2659
2660    return ret;
2661}
2662
2663#else
2664
2665OSMetaClassDefineReservedUnused(IOHIDEventService,  6);
2666OSMetaClassDefineReservedUnused(IOHIDEventService,  7);
2667OSMetaClassDefineReservedUnused(IOHIDEventService,  8);
2668OSMetaClassDefineReservedUnused(IOHIDEventService,  9);
2669OSMetaClassDefineReservedUnused(IOHIDEventService, 10);
2670#endif /* TARGET_OS_EMBEDDED */
2671OSMetaClassDefineReservedUnused(IOHIDEventService, 11);
2672OSMetaClassDefineReservedUnused(IOHIDEventService, 12);
2673OSMetaClassDefineReservedUnused(IOHIDEventService, 13);
2674OSMetaClassDefineReservedUnused(IOHIDEventService, 14);
2675OSMetaClassDefineReservedUnused(IOHIDEventService, 15);
2676OSMetaClassDefineReservedUnused(IOHIDEventService, 16);
2677OSMetaClassDefineReservedUnused(IOHIDEventService, 17);
2678OSMetaClassDefineReservedUnused(IOHIDEventService, 18);
2679OSMetaClassDefineReservedUnused(IOHIDEventService, 19);
2680OSMetaClassDefineReservedUnused(IOHIDEventService, 20);
2681OSMetaClassDefineReservedUnused(IOHIDEventService, 21);
2682OSMetaClassDefineReservedUnused(IOHIDEventService, 22);
2683OSMetaClassDefineReservedUnused(IOHIDEventService, 23);
2684OSMetaClassDefineReservedUnused(IOHIDEventService, 24);
2685OSMetaClassDefineReservedUnused(IOHIDEventService, 25);
2686OSMetaClassDefineReservedUnused(IOHIDEventService, 26);
2687OSMetaClassDefineReservedUnused(IOHIDEventService, 27);
2688OSMetaClassDefineReservedUnused(IOHIDEventService, 28);
2689OSMetaClassDefineReservedUnused(IOHIDEventService, 29);
2690OSMetaClassDefineReservedUnused(IOHIDEventService, 30);
2691OSMetaClassDefineReservedUnused(IOHIDEventService, 31);
2692
2693