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