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( ¤tTime ); 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