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 <TargetConditionals.h>
26
27#include <IOKit/IOLib.h>    // IOMalloc/IOFree
28#include <IOKit/IOBufferMemoryDescriptor.h>
29#include <IOKit/hidsystem/IOHIDSystem.h>
30#include <IOKit/IOEventSource.h>
31#include <IOKit/IOMessage.h>
32
33#include "IOHIDFamilyPrivate.h"
34#include "IOHIDDevice.h"
35#include "IOHIDElementPrivate.h"
36#include "IOHIDParserPriv.h"
37#include "IOHIDInterface.h"
38#include "IOHIDPrivateKeys.h"
39#include "IOHIDFamilyPrivate.h"
40#include "IOHIDLibUserClient.h"
41#include "IOHIDFamilyTrace.h"
42#include "OSStackRetain.h"
43
44#include <sys/queue.h>
45#include <machine/limits.h>
46
47#if !TARGET_OS_EMBEDDED
48#include "IOHIKeyboard.h"
49#include "IOHIPointing.h"
50#endif
51
52//===========================================================================
53// IOHIDAsyncReportQueue class
54
55class IOHIDAsyncReportQueue : public IOEventSource
56{
57    OSDeclareDefaultStructors( IOHIDAsyncReportQueue )
58
59    struct AsyncReportEntry {
60        queue_chain_t   chain;
61
62        AbsoluteTime                    timeStamp;
63        uint8_t *                       reportData;
64        size_t                          reportLength;
65        IOHIDReportType                 reportType;
66        IOOptionBits                    options;
67        UInt32                          completionTimeout;
68        IOHIDCompletion                 completion;
69    };
70
71    IOLock *        fQueueLock;
72    queue_head_t    fQueueHead;
73
74public:
75    static IOHIDAsyncReportQueue *withOwner(IOHIDDevice *inOwner);
76
77    virtual bool init(IOHIDDevice *owner);
78
79    virtual bool checkForWork();
80
81    virtual IOReturn postReport(AbsoluteTime         timeStamp,
82                                IOMemoryDescriptor * report,
83                                IOHIDReportType      reportType,
84                                IOOptionBits         options,
85                                UInt32               completionTimeout,
86                                IOHIDCompletion *    completion);
87};
88
89OSDefineMetaClassAndStructors( IOHIDAsyncReportQueue, IOEventSource )
90
91//---------------------------------------------------------------------------
92IOHIDAsyncReportQueue *IOHIDAsyncReportQueue::withOwner(IOHIDDevice *inOwner)
93{
94    IOHIDAsyncReportQueue *es = NULL;
95    bool result = false;
96
97    es = OSTypeAlloc( IOHIDAsyncReportQueue );
98    if (es) {
99        result = es->init( inOwner/*, inAction*/ );
100
101        if (!result) {
102            es->release();
103            es = NULL;
104        }
105
106    }
107
108    return es;
109}
110
111//---------------------------------------------------------------------------
112bool IOHIDAsyncReportQueue::init(IOHIDDevice *owner_I)
113{
114    queue_init( &fQueueHead );
115    fQueueLock = IOLockAlloc();
116    return IOEventSource::init(owner_I/*, action*/);
117}
118
119//---------------------------------------------------------------------------
120bool IOHIDAsyncReportQueue::checkForWork()
121{
122    bool moreToDo = false;
123
124    IOLockLock(fQueueLock);
125    if (!queue_empty(&fQueueHead)) {
126
127        AsyncReportEntry *entry = NULL;
128        queue_remove_first(&fQueueHead, entry, AsyncReportEntry *, chain);
129
130        if (entry) {
131            IOLockUnlock(fQueueLock);
132
133            IOReturn status;
134
135            IOMemoryDescriptor *md = IOMemoryDescriptor::withAddress(entry->reportData, entry->reportLength, kIODirectionOut);
136
137            if (md) {
138                md->prepare();
139
140                status = ((IOHIDDevice *)owner)->handleReportWithTime(entry->timeStamp, md, entry->reportType, entry->options);
141
142                md->complete();
143
144                md->release();
145
146                if (entry->completion.action) {
147                    (entry->completion.action)(entry->completion.target, entry->completion.parameter, status, 0);
148                }
149            }
150
151            IOFree(entry->reportData, entry->reportLength);
152            IODelete(entry, AsyncReportEntry, 1);
153
154            IOLockLock(fQueueLock);
155        }
156    }
157
158    moreToDo = (!queue_empty(&fQueueHead));
159    IOLockUnlock(fQueueLock);
160
161    return moreToDo;
162}
163
164//---------------------------------------------------------------------------
165IOReturn IOHIDAsyncReportQueue::postReport(
166                                        AbsoluteTime         timeStamp,
167                                        IOMemoryDescriptor * report,
168                                        IOHIDReportType      reportType,
169                                        IOOptionBits         options,
170                                        UInt32               completionTimeout,
171                                        IOHIDCompletion *    completion)
172{
173    AsyncReportEntry *entry;
174
175    entry = IONew(AsyncReportEntry, 1);
176    if (!entry)
177        return kIOReturnError;
178
179    bzero(entry, sizeof(AsyncReportEntry));
180
181    entry->timeStamp = timeStamp;
182
183    entry->reportLength = report->getLength();
184    entry->reportData = (uint8_t *)IOMalloc(entry->reportLength);
185
186    if (entry->reportData) {
187        report->readBytes(0, entry->reportData, entry->reportLength);
188
189        entry->reportType = reportType;
190        entry->options = options;
191        entry->completionTimeout = completionTimeout;
192
193        if (completion)
194            entry->completion = *completion;
195
196        IOLockLock(fQueueLock);
197        queue_enter(&fQueueHead, entry, AsyncReportEntry *, chain);
198        IOLockUnlock(fQueueLock);
199
200        signalWorkAvailable();
201    } else {
202        IODelete(entry, AsyncReportEntry, 1);
203    }
204
205    return kIOReturnSuccess;
206}
207
208//===========================================================================
209// IOHIDDevice class
210
211#undef  super
212#define super IOService
213
214OSDefineMetaClassAndAbstractStructors( IOHIDDevice, IOService )
215
216// RESERVED IOHIDDevice CLASS VARIABLES
217// Defined here to avoid conflicts from within header file
218#define _clientSet					_reserved->clientSet
219#define _seizedClient				_reserved->seizedClient
220#define _eventDeadline				_reserved->eventDeadline
221#define _inputInterruptElementArray	_reserved->inputInterruptElementArray
222#define _performTickle				_reserved->performTickle
223#define _performWakeTickle          _reserved->performWakeTickle
224#define _interfaceNub				_reserved->interfaceNub
225#define _rollOverElement            _reserved->rollOverElement
226#define _hierarchElements           _reserved->hierarchElements
227#define _asyncReportQueue           _reserved->asyncReportQueue
228
229#define kIOHIDEventThreshold	10
230
231// Number of slots in the report handler dispatch table.
232//
233#define kReportHandlerSlots	8
234
235// Convert from a report ID to a dispatch table slot index.
236//
237#define GetReportHandlerSlot(id)    ((id) & (kReportHandlerSlots - 1))
238
239#define GetElement(index)  \
240    (IOHIDElementPrivate *) _elementArray->getObject((UInt32)index)
241
242// Serialize access to the elements for report handling,
243// event queueing, and report creation.
244//
245#define ELEMENT_LOCK                IORecursiveLockLock( _elementLock )
246#define ELEMENT_UNLOCK              IORecursiveLockUnlock( _elementLock )
247
248// Describes the handler(s) at each report dispatch table slot.
249//
250struct IOHIDReportHandler
251{
252    IOHIDElementPrivate * head[ kIOHIDReportTypeCount ];
253};
254
255#define GetHeadElement(slot, type)  _reportHandlers[slot].head[type]
256
257// #define DEBUG 1
258#ifdef  DEBUG
259#define DLOG(fmt, args...)  IOLog(fmt, args)
260#else
261#define DLOG(fmt, args...)
262#endif
263
264#ifndef kIOUserClientCrossEndianKey
265#define kIOUserClientCrossEndianKey "IOUserClientCrossEndian"
266#endif
267
268#ifndef kIOUserClientCrossEndianCompatibleKey
269#define kIOUserClientCrossEndianCompatibleKey "IOUserClientCrossEndianCompatible"
270#endif
271
272// *** GAME DEVICE HACK ***
273static SInt32 g3DGameControllerCount = 0;
274// *** END GAME DEVICE HACK ***
275
276static IONotifier   *gDeviceMatchedNotifier = 0;
277
278//---------------------------------------------------------------------------
279// Initialize an IOHIDDevice object.
280
281bool IOHIDDevice::init( OSDictionary * dict )
282{
283    _reserved = IONew( ExpansionData, 1 );
284
285    if (!_reserved)
286        return false;
287
288	bzero(_reserved, sizeof(ExpansionData));
289
290    // Create an OSSet to store client objects. Initial capacity
291    // (which can grow) is set at 2 clients.
292
293    _clientSet = OSSet::withCapacity(2);
294    if ( _clientSet == 0 )
295        return false;
296
297    return super::init(dict);
298}
299
300//---------------------------------------------------------------------------
301// Free an IOHIDDevice object after its retain count drops to zero.
302// Release all resource.
303
304void IOHIDDevice::free()
305{
306    if ( _reportHandlers )
307    {
308        IOFree( _reportHandlers,
309                sizeof(IOHIDReportHandler) * kReportHandlerSlots );
310        _reportHandlers = 0;
311    }
312
313    if ( _elementArray )
314    {
315        _elementArray->release();
316        _elementArray = 0;
317    }
318
319    if ( _hierarchElements )
320    {
321        _hierarchElements->release();
322        _hierarchElements = 0;
323    }
324
325
326    if ( _elementValuesDescriptor )
327    {
328        _elementValuesDescriptor->release();
329        _elementValuesDescriptor = 0;
330    }
331
332    if ( _elementLock )
333    {
334        IORecursiveLockFree( _elementLock );
335        _elementLock = 0;
336    }
337
338    if ( _clientSet )
339    {
340        // Should not have any clients.
341        assert(_clientSet->getCount() == 0);
342        _clientSet->release();
343        _clientSet = 0;
344    }
345
346    if (_inputInterruptElementArray)
347    {
348        _inputInterruptElementArray->release();
349        _inputInterruptElementArray = 0;
350    }
351
352    if ( _reserved )
353    {
354        IODelete( _reserved, ExpansionData, 1 );
355    }
356
357
358    return super::free();
359}
360
361static inline OSArray * CreateHierarchicalElementList(IOHIDElement * root)
362{
363    OSArray *       resultArray = 0;
364    OSArray *       subElements = 0;
365    OSArray *       elements    = 0;
366    IOHIDElement *  element     = 0;
367    IOItemCount     count;
368
369    if ( !root ) return NULL;
370
371    elements = root->getChildElements();
372
373    if ( !elements ) return NULL;
374
375    count = elements->getCount();
376
377    resultArray = OSArray::withCapacity(count);
378
379    if ( !resultArray ) return NULL;
380
381    for ( UInt32 index=0; index < count; index++ )
382    {
383        element = OSDynamicCast(IOHIDElement, elements->getObject(index));
384
385        if ( !element ) continue;
386
387        resultArray->setObject(element);
388
389        subElements = CreateHierarchicalElementList(element);
390
391        if ( subElements )
392        {
393            resultArray->merge(subElements);
394            subElements->release();
395            subElements = 0;
396        }
397    }
398
399    return resultArray;
400}
401
402
403//---------------------------------------------------------------------------
404// Start up the IOHIDDevice.
405
406bool IOHIDDevice::start( IOService * provider )
407{
408    IOMemoryDescriptor * reportDescriptor;
409    IOReturn             ret;
410
411    if ( super::start(provider) != true )
412        return false;
413
414    // Allocate a mutex lock to serialize report handling.
415
416    _elementLock = IORecursiveLockAlloc();
417    if ( _elementLock == 0 )
418        return false;
419
420    // Allocate memory for report handler dispatch table.
421
422    _reportHandlers = (IOHIDReportHandler *)
423                      IOMalloc( sizeof(IOHIDReportHandler) *
424                                kReportHandlerSlots );
425    if ( _reportHandlers == 0 )
426        return false;
427
428    bzero( _reportHandlers, sizeof(IOHIDReportHandler) * kReportHandlerSlots );
429
430    // Call handleStart() before fetching the report descriptor.
431
432    if ( handleStart(provider) != true )
433        return false;
434
435    // Fetch report descriptor for the device, and parse it.
436
437    if ( ( newReportDescriptor(&reportDescriptor) != kIOReturnSuccess ) ||
438         ( reportDescriptor == 0 ) )
439        return false;
440
441    IOMemoryMap *tempMap = reportDescriptor->map();
442    if (tempMap) {
443        OSData *descriptor = OSData::withBytes((void*)tempMap->getVirtualAddress(), tempMap->getSize());
444        if (descriptor) {
445            setProperty(kIOHIDReportDescriptorKey, descriptor);
446            descriptor->release();
447        }
448        tempMap->release();
449    }
450
451    ret = parseReportDescriptor( reportDescriptor );
452    reportDescriptor->release();
453
454    if ( ret != kIOReturnSuccess )
455        return false;
456
457    _hierarchElements = CreateHierarchicalElementList((IOHIDElement *)_elementArray->getObject( 0 ));
458
459    if ( _hierarchElements == NULL )
460        return false;
461
462	_interfaceNub = IOHIDInterface::withElements( _hierarchElements );
463
464	if ( _interfaceNub == NULL )
465		return false;
466
467    // Once the report descriptors have been parsed, we are ready
468    // to handle reports from the device.
469
470    _readyForInputReports = true;
471
472    // Publish properties to the registry before any clients are
473    // attached.
474
475    if ( publishProperties(provider) != true )
476        return false;
477
478    OSNumber *primaryUsagePage = (OSNumber*)copyProperty(kIOHIDPrimaryUsagePageKey);
479    OSNumber *primaryUsage = (OSNumber*)copyProperty(kIOHIDPrimaryUsageKey);
480
481    // *** GAME DEVICE HACK ***
482    if ((OSDynamicCast(OSNumber, primaryUsagePage) && (primaryUsagePage->unsigned32BitValue() == 0x05)) &&
483        (OSDynamicCast(OSNumber, primaryUsage) && (primaryUsage->unsigned32BitValue() == 0x01))) {
484        OSIncrementAtomic(&g3DGameControllerCount);
485    }
486    // *** END GAME DEVICE HACK ***
487    OSSafeReleaseNULL(primaryUsagePage);
488    OSSafeReleaseNULL(primaryUsage);
489
490    if (!gDeviceMatchedNotifier) {
491        OSDictionary *      propertyMatch = serviceMatching("IOHIDDevice");
492
493        gDeviceMatchedNotifier = addMatchingNotification(gIOFirstMatchNotification,
494                                                         propertyMatch,
495                                                         IOHIDDevice::_publishDeviceNotificationHandler,
496                                                         NULL);
497        propertyMatch->release();
498    }
499    registerService();
500
501    return true;
502}
503
504//---------------------------------------------------------------------------
505// Stop the IOHIDDevice.
506bool IOHIDDevice::_publishDeviceNotificationHandler(void * target __unused,
507                                                    void * refCon __unused,
508                                                    IOService * newService,
509                                                    IONotifier * notifier __unused)
510    {
511    IOHIDDevice *self = OSDynamicCast(IOHIDDevice, newService);
512    if (self) {
513        if ( self->_interfaceNub->attach(self) )
514        {
515            if (!self->_interfaceNub->start(self))
516            {
517                self->_interfaceNub->detach(self);
518                self->_interfaceNub->release();
519                self->_interfaceNub = 0;
520            }
521        }
522    else
523    {
524            self->_interfaceNub->release();
525            self->_interfaceNub = 0;
526        }
527    }
528    return true;
529}
530
531//---------------------------------------------------------------------------
532// Stop the IOHIDDevice.
533
534void IOHIDDevice::stop(IOService * provider)
535{
536    // *** GAME DEVICE HACK ***
537    OSNumber *primaryUsagePage = (OSNumber*)copyProperty(kIOHIDPrimaryUsagePageKey);
538    OSNumber *primaryUsage = (OSNumber*)copyProperty(kIOHIDPrimaryUsageKey);
539
540    if ((OSDynamicCast(OSNumber, primaryUsagePage) && (primaryUsagePage->unsigned32BitValue() == 0x05)) &&
541        (OSDynamicCast(OSNumber, primaryUsage) && (primaryUsage->unsigned32BitValue() == 0x01))) {
542        OSDecrementAtomic(&g3DGameControllerCount);
543    }
544    OSSafeReleaseNULL(primaryUsagePage);
545    OSSafeReleaseNULL(primaryUsage);
546    // *** END GAME DEVICE HACK ***
547
548    handleStop(provider);
549
550    if ( _elementLock )
551    {
552        ELEMENT_LOCK;
553        _readyForInputReports = false;
554        ELEMENT_UNLOCK;
555    }
556
557    if (_interfaceNub)
558    {
559        _interfaceNub->release();
560        _interfaceNub = 0;
561    }
562
563    super::stop(provider);
564}
565
566
567bool IOHIDDevice::matchPropertyTable(OSDictionary * table, SInt32 * score)
568{
569    bool    match       = true;
570    RETAIN_ON_STACK(this);
571
572    // Ask our superclass' opinion.
573    if (super::matchPropertyTable(table, score) == false)
574        return false;
575
576    match = MatchPropertyTable(this, table, score);
577
578    // *** HACK ***
579    // RY: For games that are accidentaly matching on the keys
580    // PrimaryUsage = 0x01
581    // PrimaryUsagePage = 0x05
582    // If there no devices present that contain these values,
583    // then return true.
584    if (!match && (g3DGameControllerCount <= 0) && table) {
585        OSNumber *primaryUsage = OSDynamicCast(OSNumber, table->getObject(kIOHIDPrimaryUsageKey));
586        OSNumber *primaryUsagePage = OSDynamicCast(OSNumber, table->getObject(kIOHIDPrimaryUsagePageKey));
587
588        if ((primaryUsage && (primaryUsage->unsigned32BitValue() == 0x01)) &&
589            (primaryUsagePage && (primaryUsagePage->unsigned32BitValue() == 0x05))) {
590            match = true;
591            IOLog("IOHIDManager: It appears that an application is attempting to locate an invalid device.  A workaround is in currently in place, but will be removed after version 10.2\n");
592        }
593    }
594    // *** END HACK ***
595
596    return match;
597}
598
599
600
601//---------------------------------------------------------------------------
602// Fetch and publish HID properties to the registry.
603
604bool IOHIDDevice::publishProperties(IOService * provider __unused)
605{
606#define SET_PROP_FROM_VALUE(key, value) \
607    do {                                \
608        OSObject *prop = value;     \
609        if (prop) {                     \
610            setProperty(key, prop);     \
611            _interfaceNub->setProperty(key, prop); \
612            prop->release();        \
613        }                               \
614    } while (0)
615
616    SET_PROP_FROM_VALUE(    kIOHIDTransportKey,         newTransportString()        );
617    SET_PROP_FROM_VALUE(    kIOHIDVendorIDKey,          newVendorIDNumber()         );
618    SET_PROP_FROM_VALUE(    kIOHIDVendorIDSourceKey,    newVendorIDSourceNumber()   );
619    SET_PROP_FROM_VALUE(    kIOHIDProductIDKey,         newProductIDNumber()        );
620    SET_PROP_FROM_VALUE(    kIOHIDVersionNumberKey,     newVersionNumber()          );
621    SET_PROP_FROM_VALUE(    kIOHIDManufacturerKey,      newManufacturerString()     );
622    SET_PROP_FROM_VALUE(    kIOHIDProductKey,           newProductString()          );
623    SET_PROP_FROM_VALUE(    kIOHIDLocationIDKey,        newLocationIDNumber()       );
624    SET_PROP_FROM_VALUE(    kIOHIDCountryCodeKey,       newCountryCodeNumber()      );
625    SET_PROP_FROM_VALUE(    kIOHIDSerialNumberKey,      newSerialNumberString()     );
626    SET_PROP_FROM_VALUE(    kIOHIDPrimaryUsageKey,      newPrimaryUsageNumber()     );
627    SET_PROP_FROM_VALUE(    kIOHIDPrimaryUsagePageKey,  newPrimaryUsagePageNumber() );
628    SET_PROP_FROM_VALUE(    kIOHIDReportIntervalKey,    newReportIntervalNumber()   );
629    SET_PROP_FROM_VALUE(    kIOHIDDeviceUsagePairsKey,  newDeviceUsagePairs()       );
630
631    if ( getProvider() )
632    {
633
634        SET_PROP_FROM_VALUE("BootProtocol", getProvider()->copyProperty("bInterfaceProtocol"));
635        SET_PROP_FROM_VALUE("HIDDefaultBehavior", copyProperty("HIDDefaultBehavior"));
636    }
637
638    return true;
639}
640
641//---------------------------------------------------------------------------
642// Derived from start() and stop().
643
644bool IOHIDDevice::handleStart(IOService * provider __unused)
645{
646    return true;
647}
648
649void IOHIDDevice::handleStop(IOService * provider __unused)
650{
651}
652
653static inline bool ShouldPostDisplayActivityTickles(IOService *device, OSSet * clientSet, bool isSeized)
654{
655    OSNumber *              primaryUsagePage = (OSNumber*)device->copyProperty(kIOHIDPrimaryUsagePageKey);
656
657    if (!clientSet->getCount() || !primaryUsagePage || !OSDynamicCast(OSNumber, primaryUsagePage) ||
658        (primaryUsagePage->unsigned32BitValue() != kHIDPage_GenericDesktop)) {
659        OSSafeReleaseNULL(primaryUsagePage);
660        return false;
661    }
662    OSSafeReleaseNULL(primaryUsagePage);
663
664    // We have clients and this device is generic desktop.
665    // Probe the client list to make sure that we are not
666    // openned by an IOHIDEventService.  If so, there is
667    // no reason to tickle the display, as the HID System
668    // already does this.
669    OSCollectionIterator *  iterator;
670    OSObject *              object;
671    bool                    returnValue = true;
672
673    if ( !isSeized && (iterator = OSCollectionIterator::withCollection(clientSet)) )
674    {
675        bool done = false;
676        while (!done) {
677            iterator->reset();
678            while (!done && (NULL != (object = iterator->getNextObject()))) {
679                if ( object->metaCast("IOHIDEventService"))
680                {
681                    returnValue = false;
682                    done = true;
683                }
684            }
685            if (iterator->isValid()) {
686                done = true;
687            }
688        }
689        iterator->release();
690    }
691    return returnValue;
692}
693
694static inline bool ShouldPostDisplayActivityTicklesForWakeDevice(
695    IOService *device, OSSet * clientSet, bool isSeized)
696{
697    OSNumber *  primaryUsagePage = OSDynamicCast(OSNumber, device->copyProperty(kIOHIDPrimaryUsagePageKey));
698    if (!primaryUsagePage)
699        return false;
700
701    if (primaryUsagePage->unsigned32BitValue() == kHIDPage_Consumer)
702        return true;
703
704    if (!clientSet->getCount() ||
705         (primaryUsagePage->unsigned32BitValue() != kHIDPage_GenericDesktop))
706        return false;
707    OSSafeReleaseNULL(primaryUsagePage);
708
709    // We have clients and this device is generic desktop.
710    // Probe the client list to make sure that we are
711    // openned by an IOHIDEventService.
712
713    OSCollectionIterator *  iterator;
714    OSObject *              object;
715    bool                    returnValue = false;
716
717    if ( !isSeized && (iterator = OSCollectionIterator::withCollection(clientSet)) )
718    {
719        bool done = false;
720        while (!done) {
721            iterator->reset();
722            while (!done && (NULL != (object = iterator->getNextObject()))) {
723                if (object->metaCast("IOHIDEventService"))
724                {
725                    returnValue = true;
726                    done = true;
727                }
728            }
729            if (iterator->isValid()) {
730                done = true;
731            }
732        }
733        iterator->release();
734    }
735    return returnValue;
736}
737
738//---------------------------------------------------------------------------
739// Handle a client open on the interface.
740
741bool IOHIDDevice::handleOpen(IOService      *client,
742                             IOOptionBits   options,
743                             void           *argument __unused)
744{
745    bool  		accept = false;
746
747    do {
748        if ( _seizedClient )
749            break;
750
751        // Was this object already registered as our client?
752
753        if ( _clientSet->containsObject(client) )
754        {
755            DLOG("%s: multiple opens from client %lx\n",
756                 getName(), (UInt32) client);
757            accept = true;
758            break;
759        }
760
761        // Add the new client object to our client set.
762
763        if ( _clientSet->setObject(client) == false )
764            break;
765
766        if (options & kIOServiceSeize)
767        {
768            messageClients( kIOMessageServiceIsRequestingClose, (void*)(intptr_t)options);
769
770            _seizedClient = client;
771
772#if !TARGET_OS_EMBEDDED
773            IOHIKeyboard * keyboard = OSDynamicCast(IOHIKeyboard, getProvider());
774            IOHIPointing * pointing = OSDynamicCast(IOHIPointing, getProvider());
775            if ( keyboard )
776                keyboard->IOHIKeyboard::message(kIOHIDSystemDeviceSeizeRequestMessage, this, (void *)true);
777            else if ( pointing )
778                pointing->IOHIPointing::message(kIOHIDSystemDeviceSeizeRequestMessage, this, (void *)true);
779#endif
780        }
781
782        accept = true;
783    }
784    while (false);
785
786    _performTickle = ShouldPostDisplayActivityTickles(this, _clientSet, _seizedClient);
787    _performWakeTickle = ShouldPostDisplayActivityTicklesForWakeDevice(this, _clientSet, _seizedClient);
788
789    return accept;
790}
791
792//---------------------------------------------------------------------------
793// Handle a client close on the interface.
794
795void IOHIDDevice::handleClose(IOService * client, IOOptionBits options __unused)
796{
797    // Remove the object from the client OSSet.
798
799    if ( _clientSet->containsObject(client) )
800    {
801        // Remove the client from our OSSet.
802        _clientSet->removeObject(client);
803
804        if (client == _seizedClient)
805        {
806            _seizedClient = 0;
807
808#if !TARGET_OS_EMBEDDED
809            IOHIKeyboard * keyboard = OSDynamicCast(IOHIKeyboard, getProvider());
810            IOHIPointing * pointing = OSDynamicCast(IOHIPointing, getProvider());
811            if ( keyboard )
812                keyboard->IOHIKeyboard::message(kIOHIDSystemDeviceSeizeRequestMessage, this, (void *)false);
813            else if ( pointing )
814                pointing->IOHIPointing::message(kIOHIDSystemDeviceSeizeRequestMessage, this, (void *)false);
815#endif
816        }
817
818        _performTickle = ShouldPostDisplayActivityTickles(this, _clientSet, _seizedClient);
819        _performWakeTickle = ShouldPostDisplayActivityTicklesForWakeDevice(this, _clientSet, _seizedClient);
820    }
821}
822
823//---------------------------------------------------------------------------
824// Query whether a client has an open on the interface.
825
826bool IOHIDDevice::handleIsOpen(const IOService * client) const
827{
828    if (client)
829        return _clientSet->containsObject(client);
830    else
831        return (_clientSet->getCount() > 0);
832}
833
834
835//---------------------------------------------------------------------------
836// Create a new user client.
837
838IOReturn IOHIDDevice::newUserClient( task_t          owningTask,
839                                     void *          security_id,
840                                     UInt32          type,
841                                     OSDictionary *  properties,
842                                     IOUserClient ** handler )
843{
844    // RY: This is really skanky.  Apparently there are some subclasses out there
845    // that want all the benefits of IOHIDDevice w/o supporting the default HID
846    // User Client.  I know!  Shocking!  Anyway, passing a type known only to the
847    // default hid clients to ensure that at least connect to our correct client.
848    if ( type == kIOHIDLibUserClientConnectManager ) {
849        if ( isInactive() ) {
850            IOLog( "IOHIDDevice::newUserClient called on an inactive device\n" );
851            *handler = NULL;
852            return kIOReturnNotReady;
853        }
854
855        if ( properties ) {
856            properties->setObject( kIOUserClientCrossEndianCompatibleKey, kOSBooleanTrue );
857        }
858
859        IOWorkLoop *loop = getWorkLoop();
860
861        IOReturn result = kIOReturnNotReady;
862
863        if ( loop ) {
864                result = loop->runAction( OSMemberFunctionCast( IOWorkLoop::Action, this, &IOHIDDevice::newUserClientGated ),
865                                          this, owningTask, security_id, properties, handler );
866            }
867            else {
868            IOLog( "IOHIDDevice::newUserClient failed to get a workloop\n" );
869        }
870
871        return result;
872    }
873
874    return super::newUserClient( owningTask, security_id, type, properties, handler );
875}
876
877IOReturn IOHIDDevice::newUserClientGated( task_t          owningTask,
878										  void *          security_id,
879										  OSDictionary *  properties,
880										  IOUserClient ** handler )
881{
882    IOUserClient * client = new IOHIDLibUserClient;
883
884    if ( !client->initWithTask( owningTask, security_id, kIOHIDLibUserClientConnectManager, properties ) ) {
885        client->release();
886        return kIOReturnBadArgument;
887    }
888
889    if ( !client->attach( this ) ) {
890        client->release();
891        return kIOReturnUnsupported;
892    }
893
894    if ( !client->start( this ) ) {
895        client->detach( this );
896        client->release();
897        return kIOReturnUnsupported;
898    }
899
900    *handler = client;
901
902    return kIOReturnSuccess;
903}
904
905//---------------------------------------------------------------------------
906// Handle provider messages.
907
908IOReturn IOHIDDevice::message( UInt32 type, IOService * provider, void * argument )
909{
910    if ((kIOMessageDeviceSignaledWakeup == type) && _performWakeTickle)
911    {
912        IOHIDSystemActivityTickle(NX_HARDWARE_TICKLE, this); // not a real event. tickle is not maskable.
913        return kIOReturnSuccess;
914    }
915
916    return super::message(type, provider, argument);
917}
918
919//---------------------------------------------------------------------------
920// Default implementation of the HID property 'getter' functions.
921
922OSString * IOHIDDevice::newTransportString() const
923{
924    return 0;
925}
926
927OSString * IOHIDDevice::newManufacturerString() const
928{
929    return 0;
930}
931
932OSString * IOHIDDevice::newProductString() const
933{
934    return 0;
935}
936
937OSNumber * IOHIDDevice::newVendorIDNumber() const
938{
939    return 0;
940}
941
942OSNumber * IOHIDDevice::newProductIDNumber() const
943{
944    return 0;
945}
946
947OSNumber * IOHIDDevice::newVersionNumber() const
948{
949    return 0;
950}
951
952OSNumber * IOHIDDevice::newSerialNumber() const
953{
954    return 0;
955}
956
957OSNumber * IOHIDDevice::newPrimaryUsageNumber() const
958{
959    OSArray * 		childArray;
960    IOHIDElementPrivate * 	child;
961    IOHIDElementPrivate * 	root;
962
963    if ( (root = (IOHIDElementPrivate *) _elementArray->getObject(0)) &&
964         (childArray = root->getChildElements()) &&
965         (child = (IOHIDElementPrivate *) childArray->getObject(0)) )
966    {
967        return OSNumber::withNumber(child->getUsage(), 32);
968    }
969
970    return 0;
971}
972
973OSNumber * IOHIDDevice::newPrimaryUsagePageNumber() const
974{
975    OSArray * 		childArray;
976    IOHIDElementPrivate * 	child;
977    IOHIDElementPrivate * 	root;
978
979    if ( (root = (IOHIDElementPrivate *) _elementArray->getObject(0)) &&
980         (childArray = root->getChildElements()) &&
981         (child = (IOHIDElementPrivate *) childArray->getObject(0)) )
982    {
983        return OSNumber::withNumber(child->getUsagePage(), 32);
984    }
985
986    return 0;
987}
988
989//---------------------------------------------------------------------------
990// Handle input reports (USB Interrupt In pipe) from the device.
991
992IOReturn IOHIDDevice::handleReport( IOMemoryDescriptor * report,
993                                    IOHIDReportType      reportType,
994                                    IOOptionBits         options )
995{
996    AbsoluteTime   currentTime;
997
998    clock_get_uptime( &currentTime );
999
1000	return handleReportWithTime( currentTime, report, reportType, options );
1001}
1002
1003//---------------------------------------------------------------------------
1004// Get a report from the device.
1005
1006IOReturn IOHIDDevice::getReport( IOMemoryDescriptor * report,
1007                                 IOHIDReportType      reportType,
1008                                 IOOptionBits         options )
1009{
1010    return getReport(report, reportType, options, 0, 0);
1011}
1012
1013//---------------------------------------------------------------------------
1014// Send a report to the device.
1015
1016IOReturn IOHIDDevice::setReport( IOMemoryDescriptor * report,
1017                                 IOHIDReportType      reportType,
1018                                 IOOptionBits         options)
1019{
1020    return setReport(report, reportType, options, 0, 0);
1021}
1022
1023//---------------------------------------------------------------------------
1024// Parse a report descriptor, and update the property table with
1025// the IOHIDElementPrivate hierarchy discovered.
1026
1027IOReturn IOHIDDevice::parseReportDescriptor( IOMemoryDescriptor * report,
1028                                             IOOptionBits         options __unused)
1029{
1030    OSStatus             status = kIOReturnError;
1031    HIDPreparsedDataRef  parseData;
1032    void *               reportData;
1033    IOByteCount          reportLength;
1034    IOReturn             ret;
1035
1036    reportLength = report->getLength();
1037
1038    if ( !reportLength )
1039        return kIOReturnBadArgument;
1040
1041    reportData = IOMalloc(reportLength);
1042
1043    if ( !reportData )
1044        return kIOReturnNoMemory;
1045
1046    report->readBytes( 0, reportData, reportLength );
1047
1048    // Parse the report descriptor.
1049
1050    status = HIDOpenReportDescriptor(
1051                reportData,      /* report descriptor */
1052                reportLength,    /* report size in bytes */
1053                &parseData,      /* pre-parse data */
1054                0 );             /* flags */
1055
1056    // Release the buffer
1057    IOFree( reportData, reportLength );
1058
1059    if ( status != kHIDSuccess )
1060    {
1061        return kIOReturnError;
1062    }
1063
1064    // Create a hierarchy of IOHIDElementPrivate objects.
1065
1066    ret = createElementHierarchy( parseData );
1067
1068    getReportCountAndSizes( parseData );
1069
1070    // Release memory.
1071
1072    HIDCloseReportDescriptor( parseData );
1073
1074    return ret;
1075}
1076
1077//---------------------------------------------------------------------------
1078// Build the element hierarchy to describe the device capabilities to
1079// user-space.
1080
1081IOReturn
1082IOHIDDevice::createElementHierarchy( HIDPreparsedDataRef parseData )
1083{
1084    OSStatus   		status;
1085    HIDCapabilities	caps;
1086    IOReturn		ret = kIOReturnNoMemory;
1087
1088    do {
1089        // Get a summary of device capabilities.
1090
1091        status = HIDGetCapabilities( parseData, &caps );
1092        if ( status != kHIDSuccess )
1093        {
1094            ret = kIOReturnError;
1095            break;
1096        }
1097
1098        // Dump HIDCapabilities structure contents.
1099
1100        DLOG("Report bytes: input:%ld output:%ld feature:%ld\n",
1101             caps.inputReportByteLength,
1102             caps.outputReportByteLength,
1103             caps.featureReportByteLength);
1104        DLOG("Collections : %ld\n", caps.numberCollectionNodes);
1105        DLOG("Buttons     : input:%ld output:%ld feature:%ld\n",
1106             caps.numberInputButtonCaps,
1107             caps.numberOutputButtonCaps,
1108             caps.numberFeatureButtonCaps);
1109        DLOG("Values      : input:%ld output:%ld feature:%ld\n",
1110             caps.numberInputValueCaps,
1111             caps.numberOutputValueCaps,
1112             caps.numberFeatureValueCaps);
1113
1114        _maxInputReportSize    = caps.inputReportByteLength;
1115        _maxOutputReportSize   = caps.outputReportByteLength;
1116        _maxFeatureReportSize  = caps.featureReportByteLength;
1117
1118        // RY: These values are useful to the subclasses.  Post them.
1119        setProperty(kIOHIDMaxInputReportSizeKey, _maxInputReportSize, 32);
1120        setProperty(kIOHIDMaxOutputReportSizeKey, _maxOutputReportSize, 32);
1121        setProperty(kIOHIDMaxFeatureReportSizeKey, _maxFeatureReportSize, 32);
1122
1123
1124        // Create an OSArray to store all HID elements.
1125
1126        _elementArray = OSArray::withCapacity(
1127                                     caps.numberCollectionNodes   +
1128                                     caps.numberInputButtonCaps   +
1129                                     caps.numberInputValueCaps    +
1130                                     caps.numberOutputButtonCaps  +
1131                                     caps.numberOutputValueCaps   +
1132                                     caps.numberFeatureButtonCaps +
1133                                     caps.numberFeatureValueCaps  +
1134                                     10 );
1135        if ( _elementArray == 0 ) break;
1136
1137        _elementArray->setCapacityIncrement(10);
1138
1139        // Add collections to the element array.
1140
1141        if ( !createCollectionElements(
1142                                  parseData,
1143                                  _elementArray,
1144                                  caps.numberCollectionNodes ) ) break;
1145
1146        // Everything added to the element array from this point on
1147        // are "data" elements. We cache the starting index.
1148
1149        _dataElementIndex = _elementArray->getCount();
1150
1151        // Add input buttons to the element array.
1152
1153        if ( !createButtonElements( parseData,
1154                                    _elementArray,
1155                                    kHIDInputReport,
1156                                    kIOHIDElementTypeInput_Button,
1157                                    caps.numberInputButtonCaps ) ) break;
1158
1159        // Add output buttons to the element array.
1160
1161        if ( !createButtonElements( parseData,
1162                                    _elementArray,
1163                                    kHIDOutputReport,
1164                                    kIOHIDElementTypeOutput,
1165                                    caps.numberOutputButtonCaps ) ) break;
1166
1167        // Add feature buttons to the element array.
1168
1169        if ( !createButtonElements( parseData,
1170                                    _elementArray,
1171                                    kHIDFeatureReport,
1172                                    kIOHIDElementTypeFeature,
1173                                    caps.numberFeatureButtonCaps ) ) break;
1174
1175        // Add input values to the element array.
1176
1177        if ( !createValueElements( parseData,
1178                                   _elementArray,
1179                                   kHIDInputReport,
1180                                   kIOHIDElementTypeInput_Misc,
1181                                   caps.numberInputValueCaps ) ) break;
1182
1183        // Add output values to the element array.
1184
1185        if ( !createValueElements( parseData,
1186                                   _elementArray,
1187                                   kHIDOutputReport,
1188                                   kIOHIDElementTypeOutput,
1189                                   caps.numberOutputValueCaps ) ) break;
1190
1191        // Add feature values to the element array.
1192
1193        if ( !createValueElements( parseData,
1194                                   _elementArray,
1195                                   kHIDFeatureReport,
1196                                   kIOHIDElementTypeFeature,
1197                                   caps.numberFeatureValueCaps ) ) break;
1198
1199        // Add the input report handler to the element array.
1200        if ( !createReportHandlerElements(parseData) ) break;
1201
1202
1203        // Create a memory to store current element values.
1204
1205        _elementValuesDescriptor = createMemoryForElementValues();
1206        if ( _elementValuesDescriptor == 0 )
1207            break;
1208
1209        // Element hierarchy has been built, add it to the property table.
1210
1211        IOHIDElementPrivate * root = (IOHIDElementPrivate *) _elementArray->getObject( 0 );
1212        if ( root )
1213        {
1214            setProperty( kIOHIDElementKey, root->getChildElements() );
1215        }
1216
1217        // Add the interrupt report handlers to the property table as well.
1218        setProperty(kIOHIDInputReportElementsKey,
1219                        _inputInterruptElementArray);
1220
1221        ret = kIOReturnSuccess;
1222    }
1223    while ( false );
1224
1225    return ret;
1226}
1227
1228//---------------------------------------------------------------------------
1229// Fetch the all the possible functions of the device
1230
1231static OSDictionary * CreateDeviceUsagePairFromElement(IOHIDElementPrivate * element)
1232{
1233    OSDictionary *	pair		= 0;
1234    OSNumber *		usage 		= 0;
1235    OSNumber *		usagePage 	= 0;
1236    OSNumber *		type 		= 0;
1237
1238	pair		= OSDictionary::withCapacity(2);
1239	usage		= OSNumber::withNumber(element->getUsage(), 32);
1240	usagePage	= OSNumber::withNumber(element->getUsagePage(), 32);
1241	type		= OSNumber::withNumber(element->getCollectionType(), 32);
1242
1243	pair->setObject(kIOHIDDeviceUsageKey, usage);
1244	pair->setObject(kIOHIDDeviceUsagePageKey, usagePage);
1245	//pair->setObject(kIOHIDElementCollectionTypeKey, type);
1246
1247	usage->release();
1248	usagePage->release();
1249	type->release();
1250
1251	return pair;
1252 }
1253
1254OSArray * IOHIDDevice::newDeviceUsagePairs()
1255{
1256    IOHIDElementPrivate *	element			= 0;
1257    OSArray *				functions		= 0;
1258    OSDictionary *			pair			= 0;
1259    UInt32					elementCount 	= _elementArray->getCount();
1260
1261	if ( elementCount <= 1 ) // this include vitual collection
1262		return NULL;
1263
1264	functions = OSArray::withCapacity(2);
1265
1266    // starts at one to avoid the virtual collection
1267    for (unsigned i=1; i<elementCount; i++)
1268    {
1269        element = (IOHIDElementPrivate *)_elementArray->getObject(i);
1270
1271        if ((element->getType() == kIOHIDElementTypeCollection) &&
1272            ((element->getCollectionType() == kIOHIDElementCollectionTypeApplication) ||
1273            (element->getCollectionType() == kIOHIDElementCollectionTypePhysical)))
1274        {
1275            pair = CreateDeviceUsagePairFromElement(element);
1276
1277            UInt32 	pairCount = functions->getCount();
1278            bool 	found = false;
1279            for(unsigned j=0; j<pairCount; j++)
1280            {
1281                OSDictionary *tempPair = (OSDictionary *)functions->getObject(j);
1282                found = tempPair->isEqualTo(pair);
1283                if (found)
1284                    break;
1285            }
1286
1287            if (!found)
1288            {
1289                functions->setObject(functions->getCount(), pair);
1290            }
1291
1292            pair->release();
1293        }
1294    }
1295
1296	if ( ! functions->getCount() ) {
1297		pair = CreateDeviceUsagePairFromElement((IOHIDElementPrivate *)_elementArray->getObject(1));
1298		functions->setObject(pair);
1299		pair->release();
1300	}
1301
1302    return functions;
1303}
1304
1305
1306//---------------------------------------------------------------------------
1307// Fetch the total number of reports and the size of each report.
1308
1309bool IOHIDDevice::getReportCountAndSizes( HIDPreparsedDataRef parseData )
1310{
1311    HIDPreparsedDataPtr data   = (HIDPreparsedDataPtr) parseData;
1312    HIDReportSizes *    report = data->reports;
1313
1314    _reportCount = data->reportCount;
1315
1316    DLOG("Report count: %ld\n", _reportCount);
1317
1318    for ( UInt32 num = 0; num < data->reportCount; num++, report++ )
1319    {
1320
1321        DLOG("Report ID: %ld input:%ld output:%ld feature:%ld\n",
1322             report->reportID,
1323             report->inputBitCount,
1324             report->outputBitCount,
1325             report->featureBitCount);
1326
1327        setReportSize( report->reportID,
1328                       kIOHIDReportTypeInput,
1329                       report->inputBitCount );
1330
1331        setReportSize( report->reportID,
1332                       kIOHIDReportTypeOutput,
1333                       report->outputBitCount );
1334
1335        setReportSize( report->reportID,
1336                       kIOHIDReportTypeFeature,
1337                       report->featureBitCount );
1338    }
1339
1340    return true;
1341}
1342
1343//---------------------------------------------------------------------------
1344// Set the report size for the first element in the report handler chain.
1345
1346bool IOHIDDevice::setReportSize( UInt8           reportID,
1347                                 IOHIDReportType reportType,
1348                                 UInt32          numberOfBits )
1349{
1350    IOHIDElementPrivate * element;
1351    bool           ret = false;
1352
1353    element = GetHeadElement( GetReportHandlerSlot(reportID), reportType );
1354
1355    while ( element )
1356    {
1357        if ( element->getReportID() == reportID )
1358        {
1359            element->setReportSize( numberOfBits );
1360            ret = true;
1361            break;
1362        }
1363        element = element->getNextReportHandler();
1364    }
1365    return ret;
1366}
1367
1368//---------------------------------------------------------------------------
1369// Add collection elements to the OSArray object provided.
1370
1371bool
1372IOHIDDevice::createCollectionElements( HIDPreparsedDataRef parseData,
1373                                       OSArray *           array,
1374                                       UInt32              maxCount )
1375{
1376    OSStatus              	  status;
1377    HIDCollectionExtendedNodePtr  collections;
1378    UInt32                        count = maxCount;
1379    bool                  	  ret   = false;
1380    UInt32                        index;
1381
1382    do {
1383        // Allocate memory to fetch all collections from the parseData.
1384
1385        collections = (HIDCollectionExtendedNodePtr)
1386                      IOMalloc( maxCount * sizeof(HIDCollectionExtendedNode) );
1387
1388        if ( collections == 0 ) break;
1389
1390        status = HIDGetCollectionExtendedNodes(
1391                    collections,    /* collectionNodes     */
1392                    &count,         /* collectionNodesSize */
1393                    parseData );    /* preparsedDataRef    */
1394
1395        if ( status != kHIDSuccess ) break;
1396
1397        // Create an IOHIDElementPrivate for each collection.
1398
1399        for ( index = 0; index < count; index++ )
1400        {
1401            IOHIDElementPrivate * element;
1402
1403            element = IOHIDElementPrivate::collectionElement(
1404                                              this,
1405                                              kIOHIDElementTypeCollection,
1406                                              &collections[index] );
1407            if ( element == 0 ) break;
1408
1409            element->release();
1410        }
1411        if ( index < count ) break;
1412
1413        // Create linkage for the collection hierarchy.
1414        // Starts at 1 to skip the root (virtual) collection.
1415
1416        for ( index = 1; index < count; index++ )
1417        {
1418            if ( !linkToParent( array, collections[index].parent, index ) )
1419                break;
1420        }
1421        if ( index < count ) break;
1422
1423        ret = true;
1424    }
1425    while ( false );
1426
1427    if ( collections )
1428        IOFree( collections, maxCount * sizeof(HIDCollectionExtendedNode) );
1429
1430    return ret;
1431}
1432
1433//---------------------------------------------------------------------------
1434// Link an element in the array to another element in the array as its child.
1435
1436bool IOHIDDevice::linkToParent( const OSArray * array,
1437                                UInt32          parentIndex,
1438                                UInt32          childIndex )
1439{
1440    IOHIDElementPrivate * child  = (IOHIDElementPrivate *) array->getObject( childIndex );
1441    IOHIDElementPrivate * parent = (IOHIDElementPrivate *) array->getObject( parentIndex );
1442
1443    return ( parent ) ? parent->addChildElement( child ) : false;
1444}
1445
1446//---------------------------------------------------------------------------
1447// Add Button elements (1 bit value) to the collection.
1448
1449bool IOHIDDevice::createButtonElements( HIDPreparsedDataRef parseData,
1450                                        OSArray *           array,
1451                                        UInt32              hidReportType,
1452                                        IOHIDElementType    elementType,
1453                                        UInt32              maxCount )
1454{
1455    OSStatus          		status;
1456    HIDButtonCapabilitiesPtr 	buttons = 0;
1457    UInt32			count   = maxCount;
1458    bool			ret     = false;
1459    IOHIDElementPrivate *		element;
1460    IOHIDElementPrivate *		parent;
1461
1462    do {
1463        if ( maxCount == 0 )
1464        {
1465            ret = true;
1466            break;
1467        }
1468
1469        // Allocate memory to fetch all button elements from the parseData.
1470
1471        buttons = (HIDButtonCapabilitiesPtr) IOMalloc( maxCount *
1472                                               sizeof(HIDButtonCapabilities) );
1473        if ( buttons == 0 ) break;
1474
1475        status = HIDGetButtonCapabilities( hidReportType,  /* HIDReportType    */
1476                                   buttons,        /* buttonCaps       */
1477                                   &count,         /* buttonCapsSize   */
1478                                   parseData );    /* preparsedDataRef */
1479
1480        if ( status != kHIDSuccess ) break;
1481
1482        // Create an IOHIDElementPrivate for each button and link it to its
1483        // parent collection.
1484
1485        ret = true;
1486
1487        for ( UInt32 i = 0; i < count; i++ )
1488        {
1489            parent  = (IOHIDElementPrivate *) array->getObject(
1490                                              buttons[i].collection );
1491
1492            element = IOHIDElementPrivate::buttonElement(
1493                                          this,
1494                                          elementType,
1495                                          &buttons[i],
1496                                          parent );
1497            if ( element == 0 )
1498            {
1499                ret = false;
1500                break;
1501            }
1502            element->release();
1503        }
1504    }
1505    while ( false );
1506
1507    if ( buttons )
1508        IOFree( buttons, maxCount * sizeof(HIDButtonCapabilities) );
1509
1510    return ret;
1511}
1512
1513//---------------------------------------------------------------------------
1514// Add Value elements to the collection.
1515
1516bool IOHIDDevice::createValueElements( HIDPreparsedDataRef parseData,
1517                                       OSArray *           array,
1518                                       UInt32              hidReportType,
1519                                       IOHIDElementType    elementType,
1520                                       UInt32              maxCount )
1521{
1522    OSStatus         status;
1523    HIDValueCapabilitiesPtr  values = 0;
1524    UInt32           count  = maxCount;
1525    bool             ret    = false;
1526    IOHIDElementPrivate *   element;
1527    IOHIDElementPrivate *   parent;
1528
1529    do {
1530        if ( maxCount == 0 )
1531        {
1532            ret = true;
1533            break;
1534        }
1535
1536        // Allocate memory to fetch all value elements from the parseData.
1537
1538        values = (HIDValueCapabilitiesPtr) IOMalloc( maxCount *
1539                                             sizeof(HIDValueCapabilities) );
1540        if ( values == 0 ) break;
1541
1542        status = HIDGetValueCapabilities( hidReportType,  /* HIDReportType    */
1543                                  values,         /* valueCaps        */
1544                                  &count,         /* valueCapsSize    */
1545                                  parseData );    /* preparsedDataRef */
1546
1547        if ( status != kHIDSuccess ) break;
1548
1549        // Create an IOHIDElementPrivate for each value and link it to its
1550        // parent collection.
1551
1552        ret = true;
1553
1554        for ( UInt32 i = 0; i < count; i++ )
1555        {
1556            parent  = (IOHIDElementPrivate *) array->getObject(
1557                                              values[i].collection );
1558
1559            element = IOHIDElementPrivate::valueElement(
1560                                         this,
1561                                         elementType,
1562                                         &values[i],
1563                                         parent );
1564
1565            if ( element == 0 )
1566            {
1567                ret = false;
1568                break;
1569            }
1570            element->release();
1571        }
1572    }
1573    while ( false );
1574
1575    if ( values )
1576        IOFree( values, maxCount * sizeof(HIDValueCapabilities) );
1577
1578    return ret;
1579}
1580
1581//---------------------------------------------------------------------------
1582// Add report handler elements.
1583
1584bool IOHIDDevice::createReportHandlerElements( HIDPreparsedDataRef parseData)
1585{
1586    HIDPreparsedDataPtr data   = (HIDPreparsedDataPtr) parseData;
1587    HIDReportSizes *    report = data->reports;
1588    IOHIDElementPrivate * 	element = 0;
1589
1590    if ( !(_inputInterruptElementArray = OSArray::withCapacity(data->reportCount)))
1591        return false;
1592
1593    for ( UInt32 num = 0; num < data->reportCount; num++, report++ )
1594    {
1595        element = IOHIDElementPrivate::reportHandlerElement(
1596                                    this,
1597                                    kIOHIDElementTypeInput_Misc,
1598                                    report->reportID,
1599                                    report->inputBitCount);
1600
1601        if ( element == 0 )
1602            continue;
1603
1604        _inputInterruptElementArray->setObject(element);
1605
1606        element->release();
1607    }
1608
1609    return true;
1610}
1611
1612//---------------------------------------------------------------------------
1613// Called by an IOHIDElementPrivate to register itself.
1614
1615bool IOHIDDevice::registerElement( IOHIDElementPrivate * element,
1616                                   IOHIDElementCookie * cookie )
1617{
1618    IOHIDReportType reportType;
1619    UInt32          index = _elementArray->getCount();
1620
1621    // Add the element to the elements array.
1622
1623    if ( _elementArray->setObject( index, element ) != true )
1624    {
1625        return false;
1626    }
1627
1628    // If the element can contribute to an Input, Output, or Feature
1629    // report, then add it to the chain of report handlers.
1630    if ( element->getReportType( &reportType ) )
1631    {
1632        IOHIDReportHandler * reportHandler;
1633        UInt32               slot;
1634
1635        slot = GetReportHandlerSlot( element->getReportID() );
1636
1637        reportHandler = &_reportHandlers[slot];
1638
1639        if ( reportHandler->head[reportType] )
1640        {
1641            element->setNextReportHandler( reportHandler->head[reportType] );
1642        }
1643        reportHandler->head[reportType] = element;
1644
1645        if ( element->getUsagePage() == kHIDPage_KeyboardOrKeypad )
1646        {
1647            UInt32 usage = element->getUsage();
1648
1649            if ( usage == kHIDUsage_KeyboardErrorRollOver)
1650                _rollOverElement = element;
1651
1652            if ( usage >= kHIDUsage_KeyboardLeftControl && usage <= kHIDUsage_KeyboardRightGUI )
1653                element->setRollOverElementPtr(&(_rollOverElement));
1654        }
1655    }
1656
1657    // The cookie returned is simply an index to the element in the
1658    // elements array. We may decide to obfuscate it later on.
1659
1660    *cookie = (IOHIDElementCookie) index;
1661
1662    return true;
1663}
1664
1665//---------------------------------------------------------------------------
1666// Create a buffer memory descriptor, and divide the memory buffer
1667// for each data element.
1668IOBufferMemoryDescriptor * IOHIDDevice::createMemoryForElementValues()
1669{
1670    IOBufferMemoryDescriptor *  descriptor;
1671    IOHIDElementPrivate *       element;
1672    UInt32                      capacity = 0;
1673    UInt8 *                     beginning;
1674    UInt8 *                     buffer;
1675
1676    // Discover the amount of memory required to publish the
1677    // element values for all "data" elements.
1678
1679    for ( UInt32 slot = 0; slot < kReportHandlerSlots; slot++ ) {
1680        for ( UInt32 type = 0; type < kIOHIDReportTypeCount; type++ ) {
1681            element = GetHeadElement(slot, type);
1682            while ( element ) {
1683                UInt32 remaining = ULONG_MAX - capacity;
1684
1685                if ( element->getElementValueSize() > remaining )
1686                    return NULL;
1687
1688                capacity += element->getElementValueSize();
1689                element   = element->getNextReportHandler();
1690            }
1691        }
1692    }
1693
1694    // Allocate an IOBufferMemoryDescriptor object.
1695
1696    DLOG("Element value capacity %ld\n", capacity);
1697
1698    descriptor = IOBufferMemoryDescriptor::withOptions(
1699                     kIOMemoryKernelUserShared,
1700                     capacity );
1701
1702    if ( ( descriptor == 0 ) || ( descriptor->getBytesNoCopy() == 0 ) ) {
1703        if ( descriptor ) descriptor->release();
1704        return 0;
1705    }
1706
1707    // Now assign the update memory area for each report element.
1708    beginning = buffer = (UInt8 *) descriptor->getBytesNoCopy();
1709
1710    for ( UInt32 slot = 0; slot < kReportHandlerSlots; slot++ ) {
1711        for ( UInt32 type = 0; type < kIOHIDReportTypeCount; type++ ) {
1712            element = GetHeadElement(slot, type);
1713            while ( element ) {
1714                assert ( buffer < (beginning + capacity) );
1715
1716                if(buffer >= (beginning + capacity)) {
1717                    descriptor->release();
1718                    return 0;
1719                }
1720
1721                element->setMemoryForElementValue( (IOVirtualAddress) buffer,
1722                                                   (void *) (buffer - beginning));
1723
1724                buffer += element->getElementValueSize();
1725                element = element->getNextReportHandler();
1726            }
1727        }
1728    }
1729
1730    return descriptor;
1731}
1732
1733//---------------------------------------------------------------------------
1734// Get a reference to the memory descriptor created by
1735// createMemoryForElementValues().
1736
1737IOMemoryDescriptor * IOHIDDevice::getMemoryWithCurrentElementValues() const
1738{
1739    return _elementValuesDescriptor;
1740}
1741
1742//---------------------------------------------------------------------------
1743// Start delivering events from the given element to the specified
1744// event queue.
1745
1746IOReturn IOHIDDevice::startEventDelivery( IOHIDEventQueue *  queue,
1747                                          IOHIDElementCookie cookie,
1748                                          IOOptionBits       options __unused)
1749{
1750    IOHIDElementPrivate * element;
1751    UInt32         elementIndex = (UInt32) cookie;
1752    IOReturn       ret = kIOReturnBadArgument;
1753
1754    if ( ( queue == 0 ) || ( elementIndex < _dataElementIndex ) )
1755        return kIOReturnBadArgument;
1756
1757    ELEMENT_LOCK;
1758
1759	do {
1760        if (( element = GetElement(elementIndex) ) == 0)
1761            break;
1762
1763        ret = element->addEventQueue( queue ) ?
1764              kIOReturnSuccess : kIOReturnNoMemory;
1765    }
1766    while ( false );
1767
1768    ELEMENT_UNLOCK;
1769
1770    return ret;
1771}
1772
1773//---------------------------------------------------------------------------
1774// Stop delivering events from the given element to the specified
1775// event queue.
1776
1777IOReturn IOHIDDevice::stopEventDelivery( IOHIDEventQueue *  queue,
1778                                         IOHIDElementCookie cookie )
1779{
1780    IOHIDElementPrivate * element;
1781    UInt32         elementIndex = (UInt32) cookie;
1782    bool           removed      = false;
1783
1784    // If the cookie provided was zero, then loop and remove the queue
1785    // from all elements.
1786
1787    if ( elementIndex == 0 )
1788        elementIndex = _dataElementIndex;
1789	else if ( (queue == 0 ) || ( elementIndex < _dataElementIndex ) )
1790        return kIOReturnBadArgument;
1791
1792    ELEMENT_LOCK;
1793
1794	do {
1795        if (( element = GetElement(elementIndex++) ) == 0)
1796            break;
1797
1798        removed = element->removeEventQueue( queue ) || removed;
1799    }
1800    while ( cookie == 0 );
1801
1802    ELEMENT_UNLOCK;
1803
1804    return removed ? kIOReturnSuccess : kIOReturnNotFound;
1805}
1806
1807//---------------------------------------------------------------------------
1808// Check whether events from the given element will be delivered to
1809// the specified event queue.
1810
1811IOReturn IOHIDDevice::checkEventDelivery( IOHIDEventQueue *  queue,
1812                                          IOHIDElementCookie cookie,
1813                                          bool *             started )
1814{
1815    IOHIDElementPrivate * element = GetElement( cookie );
1816
1817    if ( !queue || !element || !started )
1818        return kIOReturnBadArgument;
1819
1820    ELEMENT_LOCK;
1821
1822    *started = element->hasEventQueue( queue );
1823
1824    ELEMENT_UNLOCK;
1825
1826    return kIOReturnSuccess;
1827}
1828
1829#define SetCookiesTransactionState(element, cookies, count, state, index, offset) \
1830    for (index = offset; index < count; index++) { 			\
1831        element = GetElement(cookies[index]); 				\
1832        if (element == NULL) 						\
1833            continue; 							\
1834        element->setTransactionState (state);				\
1835    }
1836
1837//---------------------------------------------------------------------------
1838// Update the value of the given element, by getting a report from
1839// the device.  Assume that the cookieCount > 0
1840
1841OSMetaClassDefineReservedUsed(IOHIDDevice,  0);
1842IOReturn IOHIDDevice::updateElementValues(IOHIDElementCookie *cookies, UInt32 cookieCount) {
1843    IOMemoryDescriptor *	report = NULL;
1844    IOHIDElementPrivate *		element = NULL;
1845    IOHIDReportType		reportType;
1846    IOByteCount			maxReportLength;
1847    UInt8			reportID;
1848    UInt32			index;
1849    IOReturn			ret = kIOReturnError;
1850
1851    maxReportLength = max(_maxOutputReportSize,
1852                            max(_maxFeatureReportSize, _maxInputReportSize));
1853
1854    // Allocate a mem descriptor with the maxReportLength.
1855    // This way, we only have to allocate one mem discriptor
1856    report = IOBufferMemoryDescriptor::withCapacity(maxReportLength, kIODirectionNone);
1857
1858    if (report == NULL)
1859        return kIOReturnNoMemory;
1860
1861    ELEMENT_LOCK;
1862
1863    SetCookiesTransactionState(element, cookies,
1864            cookieCount, kIOHIDTransactionStatePending, index, 0);
1865
1866    // Iterate though all the elements in the
1867    // transaction.  Generate reports if needed.
1868    for (index = 0; index < cookieCount; index++) {
1869        element = GetElement(cookies[index]);
1870
1871        if (element == NULL)
1872            continue;
1873
1874        if ( element->getTransactionState()
1875                != kIOHIDTransactionStatePending )
1876            continue;
1877
1878        if ( !element->getReportType(&reportType) )
1879            continue;
1880
1881        reportID = element->getReportID();
1882
1883        // calling down into our subclass, so lets unlock
1884        ELEMENT_UNLOCK;
1885
1886        report->prepare();
1887        ret = getReport(report, reportType, reportID);
1888
1889        ELEMENT_LOCK;
1890
1891        if (ret == kIOReturnSuccess) {
1892            // If we have a valid report, go ahead and process it.
1893            ret = handleReport(report, reportType, kIOHIDReportOptionNotInterrupt);
1894        }
1895
1896        report->complete();
1897
1898        if (ret != kIOReturnSuccess)
1899            break;
1900    }
1901
1902    // release the report
1903    report->release();
1904
1905    // If needed, set the transaction state for the
1906    // remaining elements to idle.
1907    SetCookiesTransactionState(element, cookies,
1908            cookieCount, kIOHIDTransactionStateIdle, index, 0);
1909    ELEMENT_UNLOCK;
1910
1911    return ret;
1912}
1913
1914//---------------------------------------------------------------------------
1915// Post the value of the given element, by sending a report to
1916// the device.  Assume that the cookieCount > 0
1917OSMetaClassDefineReservedUsed(IOHIDDevice,  1);
1918IOReturn IOHIDDevice::postElementValues(IOHIDElementCookie * cookies, UInt32 cookieCount)
1919{
1920    IOBufferMemoryDescriptor	*report = NULL;
1921    IOHIDElementPrivate 		*element = NULL;
1922    IOHIDElementPrivate 		*cookieElement = NULL;
1923    UInt8			*reportData = NULL;
1924    UInt32			maxReportLength = 0;
1925    UInt32			reportLength = 0;
1926    IOHIDReportType		reportType;
1927    UInt8			reportID = 0;
1928    UInt32 			index;
1929    IOReturn			ret = kIOReturnError;
1930
1931    // Return an error if no cookies are being set
1932    if (cookieCount == 0)
1933        return ret;
1934
1935    // Get the max report size
1936    maxReportLength = max(_maxOutputReportSize, _maxFeatureReportSize);
1937
1938    // Allocate a buffer mem descriptor with the maxReportLength.
1939    // This way, we only have to allocate one mem buffer.
1940    report = IOBufferMemoryDescriptor::withCapacity(maxReportLength, kIODirectionNone);
1941
1942    if ( report == NULL )
1943        return kIOReturnNoMemory;
1944
1945    ELEMENT_LOCK;
1946
1947    // Set the transaction state on the specified cookies
1948    SetCookiesTransactionState(cookieElement, cookies,
1949            cookieCount, kIOHIDTransactionStatePending, index, 0);
1950
1951    // Obtain the buffer
1952    reportData = (UInt8 *)report->getBytesNoCopy();
1953
1954    // Iterate though all the elements in the
1955    // transaction.  Generate reports if needed.
1956    for (index = 0; index < cookieCount; index ++) {
1957
1958        cookieElement = GetElement(cookies[index]);
1959
1960        if ( cookieElement == NULL )
1961            continue;
1962
1963        // Continue on to the next element if
1964        // we've already processed this one
1965        if ( cookieElement->getTransactionState()
1966                != kIOHIDTransactionStatePending )
1967            continue;
1968
1969        if ( !cookieElement->getReportType(&reportType) )
1970            continue;
1971
1972        reportID = cookieElement->getReportID();
1973
1974        // Start at the head element and iterate through
1975        element = GetHeadElement(GetReportHandlerSlot(reportID), reportType);
1976
1977        while ( element ) {
1978
1979            element->createReport(reportID, reportData, &reportLength, &element);
1980
1981            // If the reportLength was set, then this is
1982            // the head element for this report
1983            if ( reportLength ) {
1984                report->setLength(reportLength);
1985                reportLength = 0;
1986            }
1987
1988        }
1989
1990        // If there are multiple reports, append
1991        // the reportID to the first byte
1992        if ( _reportCount > 1 )
1993            reportData[0] = reportID;
1994
1995        ELEMENT_UNLOCK;
1996
1997        report->prepare();
1998        ret = setReport( report, reportType, reportID);
1999        report->complete();
2000
2001        ELEMENT_LOCK;
2002
2003        if ( ret != kIOReturnSuccess )
2004            break;
2005    }
2006
2007    // If needed, set the transaction state for the
2008    // remaining elements to idle.
2009    SetCookiesTransactionState(cookieElement, cookies,
2010            cookieCount, kIOHIDTransactionStateIdle, index, 0);
2011
2012    ELEMENT_UNLOCK;
2013
2014    if ( report )
2015        report->release();
2016
2017    return ret;
2018}
2019
2020OSMetaClassDefineReservedUsed(IOHIDDevice,  2);
2021OSString * IOHIDDevice::newSerialNumberString() const
2022{
2023	OSString * string = 0;
2024	OSNumber * number = newSerialNumber();
2025
2026	if ( number )
2027	{
2028		char	str[11];
2029		snprintf(str, sizeof (str), "%d", number->unsigned32BitValue());
2030		string = OSString::withCString(str);
2031		number->release();
2032	}
2033
2034    return string;
2035}
2036
2037OSMetaClassDefineReservedUsed(IOHIDDevice,  3);
2038OSNumber * IOHIDDevice::newLocationIDNumber() const
2039{
2040    return 0;
2041}
2042
2043//---------------------------------------------------------------------------
2044// Get an async report from the device.
2045
2046OSMetaClassDefineReservedUsed(IOHIDDevice,  4);
2047IOReturn IOHIDDevice::getReport(IOMemoryDescriptor  *report __unused,
2048                                IOHIDReportType     reportType __unused,
2049                                IOOptionBits        options __unused,
2050                                UInt32              completionTimeout __unused,
2051                                IOHIDCompletion     *completion __unused)
2052{
2053    return kIOReturnUnsupported;
2054}
2055
2056//---------------------------------------------------------------------------
2057// Send an async report to the device.
2058
2059OSMetaClassDefineReservedUsed(IOHIDDevice,  5);
2060IOReturn IOHIDDevice::setReport(IOMemoryDescriptor  *report __unused,
2061                                IOHIDReportType     reportType __unused,
2062                                IOOptionBits        options __unused,
2063                                UInt32              completionTimeout __unused,
2064                                IOHIDCompletion     *completion __unused)
2065{
2066    return kIOReturnUnsupported;
2067}
2068
2069//---------------------------------------------------------------------------
2070// Return the vendor id source
2071
2072OSMetaClassDefineReservedUsed(IOHIDDevice,  6);
2073OSNumber * IOHIDDevice::newVendorIDSourceNumber() const
2074{
2075    return 0;
2076}
2077
2078//---------------------------------------------------------------------------
2079// Return the country code
2080
2081OSMetaClassDefineReservedUsed(IOHIDDevice,  7);
2082OSNumber * IOHIDDevice::newCountryCodeNumber() const
2083{
2084    return 0;
2085}
2086
2087//---------------------------------------------------------------------------
2088// Handle input reports (USB Interrupt In pipe) from the device.
2089
2090OSMetaClassDefineReservedUsed(IOHIDDevice,  8);
2091IOReturn IOHIDDevice::handleReportWithTime(
2092    AbsoluteTime         timeStamp,
2093    IOMemoryDescriptor * report,
2094    IOHIDReportType      reportType,
2095    IOOptionBits         options)
2096{
2097    void *         reportData;
2098    IOByteCount    reportLength;
2099    IOReturn       ret = kIOReturnNotReady;
2100    bool           changed = false;
2101    bool           shouldTickle = false;
2102    UInt8          reportID = 0;
2103
2104    IOHID_DEBUG(kIOHIDDebugCode_HandleReport, reportType, options, __OSAbsoluteTime(timeStamp), getRegistryEntryID());
2105
2106    if ((reportType == kIOHIDReportTypeInput) && !_readyForInputReports)
2107        return kIOReturnOffline;
2108
2109    // Get a pointer to the data in the descriptor.
2110    if ( !report )
2111        return kIOReturnBadArgument;
2112
2113    reportLength = report->getLength();
2114
2115    if ( !reportLength )
2116        return kIOReturnBadArgument;
2117
2118    reportData = IOMalloc(reportLength);
2119
2120    if ( !reportData )
2121        return kIOReturnNoMemory;
2122
2123    report->readBytes( 0, reportData, reportLength );
2124
2125    ELEMENT_LOCK;
2126
2127    if ( _readyForInputReports ) {
2128        IOHIDElementPrivate * element;
2129
2130        // The first byte in the report, may be the report ID.
2131        // XXX - Do we need to advance the start of the report data?
2132
2133        reportID = ( _reportCount > 1 ) ? *((UInt8 *) reportData) : 0;
2134
2135        // Get the first element in the report handler chain.
2136
2137        element = GetHeadElement( GetReportHandlerSlot(reportID),
2138                                  reportType);
2139
2140        while ( element ) {
2141            shouldTickle |= element->shouldTickleActivity();
2142            changed |= element->processReport( reportID,
2143                                               reportData,
2144                                               reportLength << 3,
2145                                               &timeStamp,
2146                                               &element,
2147                                               options );
2148        }
2149
2150        ret = kIOReturnSuccess;
2151    }
2152
2153    if ( ( reportType == kIOHIDReportTypeInput ) &&
2154            (( options & kIOHIDReportOptionNotInterrupt ) == 0 ) && _interfaceNub && !_seizedClient) {
2155        _interfaceNub->handleReport(timeStamp, report, reportType, reportID, options);
2156    }
2157
2158    ELEMENT_UNLOCK;
2159
2160    // Release the buffer
2161    IOFree(reportData, reportLength);
2162
2163    // RY: If this is a non-system HID device, post a null hid
2164    // event to prevent the system from sleeping.
2165    if (changed && shouldTickle && _performTickle
2166            && (CMP_ABSOLUTETIME(&timeStamp, &_eventDeadline) > 0))
2167    {
2168        AbsoluteTime ts;
2169
2170        nanoseconds_to_absolutetime(kIOHIDEventThreshold, &ts);
2171
2172        _eventDeadline = ts;
2173
2174        ADD_ABSOLUTETIME(&_eventDeadline, &timeStamp);
2175
2176        IOHIDSystemActivityTickle(NX_NULLEVENT, this);
2177    }
2178
2179    return ret;
2180}
2181
2182//---------------------------------------------------------------------------
2183// Return the polling interval
2184
2185OSMetaClassDefineReservedUsed(IOHIDDevice, 9);
2186OSNumber * IOHIDDevice::newReportIntervalNumber() const
2187{
2188    UInt32 interval = 8000; // default to 8 milliseconds
2189    OSNumber *number = (OSNumber*)copyProperty(kIOHIDReportIntervalKey, gIOServicePlane, kIORegistryIterateRecursively | kIORegistryIterateParents);
2190    if ( OSDynamicCast(OSNumber, number) )
2191        interval = number->unsigned32BitValue();
2192    OSSafeReleaseNULL(number);
2193
2194    return OSNumber::withNumber(interval, 32);
2195}
2196
2197//---------------------------------------------------------------------------
2198// Asynchronously handle input reports
2199
2200OSMetaClassDefineReservedUsed(IOHIDDevice, 10);
2201IOReturn IOHIDDevice::handleReportWithTimeAsync(
2202                                      AbsoluteTime         timeStamp,
2203                                      IOMemoryDescriptor * report,
2204                                      IOHIDReportType      reportType,
2205                                      IOOptionBits         options,
2206                                      UInt32               completionTimeout,
2207                                      IOHIDCompletion *    completion)
2208{
2209    IOReturn result = kIOReturnError;
2210
2211    if (!_asyncReportQueue) {
2212        _asyncReportQueue = IOHIDAsyncReportQueue::withOwner(this);
2213
2214        if (_asyncReportQueue) {
2215            /*status =*/ getWorkLoop()->addEventSource ( _asyncReportQueue );
2216        }
2217    }
2218
2219    if (_asyncReportQueue) {
2220        result = _asyncReportQueue->postReport(timeStamp, report, reportType, options, completionTimeout, completion);
2221    }
2222
2223    return result;
2224}
2225
2226OSMetaClassDefineReservedUnused(IOHIDDevice, 12);
2227OSMetaClassDefineReservedUnused(IOHIDDevice, 13);
2228OSMetaClassDefineReservedUnused(IOHIDDevice, 14);
2229OSMetaClassDefineReservedUnused(IOHIDDevice, 15);
2230OSMetaClassDefineReservedUnused(IOHIDDevice, 16);
2231OSMetaClassDefineReservedUnused(IOHIDDevice, 17);
2232OSMetaClassDefineReservedUnused(IOHIDDevice, 18);
2233OSMetaClassDefineReservedUnused(IOHIDDevice, 19);
2234OSMetaClassDefineReservedUnused(IOHIDDevice, 20);
2235OSMetaClassDefineReservedUnused(IOHIDDevice, 21);
2236OSMetaClassDefineReservedUnused(IOHIDDevice, 22);
2237OSMetaClassDefineReservedUnused(IOHIDDevice, 23);
2238OSMetaClassDefineReservedUnused(IOHIDDevice, 24);
2239OSMetaClassDefineReservedUnused(IOHIDDevice, 25);
2240OSMetaClassDefineReservedUnused(IOHIDDevice, 26);
2241OSMetaClassDefineReservedUnused(IOHIDDevice, 27);
2242OSMetaClassDefineReservedUnused(IOHIDDevice, 28);
2243OSMetaClassDefineReservedUnused(IOHIDDevice, 29);
2244OSMetaClassDefineReservedUnused(IOHIDDevice, 30);
2245OSMetaClassDefineReservedUnused(IOHIDDevice, 31);
2246OSMetaClassDefineReservedUnused(IOHIDDevice, 32);
2247OSMetaClassDefineReservedUnused(IOHIDDevice, 33);
2248OSMetaClassDefineReservedUnused(IOHIDDevice, 34);
2249OSMetaClassDefineReservedUnused(IOHIDDevice, 35);
2250OSMetaClassDefineReservedUnused(IOHIDDevice, 36);
2251OSMetaClassDefineReservedUnused(IOHIDDevice, 37);
2252OSMetaClassDefineReservedUnused(IOHIDDevice, 38);
2253OSMetaClassDefineReservedUnused(IOHIDDevice, 39);
2254OSMetaClassDefineReservedUnused(IOHIDDevice, 40);
2255
2256