1/* 2 * 3 * @APPLE_LICENSE_HEADER_START@ 4 * 5 * Copyright (c) 1999-2003 Apple Computer, Inc. All Rights Reserved. 6 * 7 * This file contains Original Code and/or Modifications of Original Code 8 * as defined in and that are subject to the Apple Public Source License 9 * Version 2.0 (the 'License'). You may not use this file except in 10 * compliance with the License. Please obtain a copy of the License at 11 * http://www.opensource.apple.com/apsl/ and read it before using this 12 * file. 13 * 14 * The Original Code and all software distributed under the License are 15 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER 16 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, 17 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, 18 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. 19 * Please see the License for the specific language governing rights and 20 * limitations under the License. 21 * 22 * @APPLE_LICENSE_HEADER_END@ 23 */ 24#define CFRUNLOOP_NEW_API 1 25 26#include <CoreFoundation/CFMachPort.h> 27//#include <IOKit/hid/IOHIDLib.h> 28//#include <unistd.h> 29#include <IOKit/hid/IOHIDValue.h> 30#include "IOHIDQueueClass.h" 31#include "IOHIDLibUserClient.h" 32 33__BEGIN_DECLS 34#include <asl.h> 35#include <IOKit/IODataQueueClient.h> 36#include <mach/mach.h> 37#include <mach/mach_interface.h> 38#include <IOKit/iokitmig.h> 39#include <System/libkern/OSCrossEndian.h> 40__END_DECLS 41 42#define ownerCheck() do { \ 43 if (!fOwningDevice) \ 44 return kIOReturnNoDevice; \ 45} while (0) 46 47#define connectCheck() do { \ 48 if ((!fOwningDevice) || \ 49 (!fOwningDevice->fConnection)) \ 50 return kIOReturnNoDevice; \ 51} while (0) 52 53#define createdCheck() do { \ 54 if (!fIsCreated) \ 55 return kIOReturnError; \ 56} while (0) 57 58#define openCheck() do { \ 59 if (!fOwningDevice || \ 60 !fOwningDevice->fIsOpen) \ 61 return kIOReturnNotOpen; \ 62} while (0) 63 64#define terminatedCheck() do { \ 65 if ((!fOwningDevice) || \ 66 (fOwningDevice->fIsTerminated))\ 67 return kIOReturnNotAttached; \ 68} while (0) 69 70#define mostChecks() do { \ 71 ownerCheck(); \ 72 connectCheck(); \ 73 createdCheck(); \ 74 terminatedCheck(); \ 75} while (0) 76 77#define allChecks() do { \ 78 mostChecks(); \ 79 openCheck(); \ 80} while (0) 81 82 83IOHIDQueueClass::IOHIDQueueClass() : IOHIDIUnknown(NULL) 84{ 85 fHIDQueue.pseudoVTable = (IUnknownVTbl *) &sHIDQueueInterfaceV2; 86 fHIDQueue.obj = this; 87 88 fAsyncPort = MACH_PORT_NULL; 89 fCFMachPort = NULL; 90 fCFSource = NULL; 91 fIsCreated = false; 92 fCreatedFlags = 0; 93 fQueueRef = 0; 94 fCreatedDepth = 0; 95 fQueueEntrySizeChanged = false; 96 fQueueMappedMemory = NULL; 97 fQueueMappedMemorySize = 0; 98 fOwningDevice = NULL; 99 fEventCallback = NULL; 100 fEventRefcon = NULL; 101 fElements = NULL; 102} 103 104IOHIDQueueClass::~IOHIDQueueClass() 105{ 106 if (fIsCreated) 107 dispose(); 108 109 if (fElements) 110 CFRelease(fElements); 111 112 // if we are owned, detatch 113 if (fOwningDevice) 114 fOwningDevice->detachQueue(this); 115 116 if (fCFMachPort) { 117 CFMachPortInvalidate(fCFMachPort); 118 CFRelease(fCFMachPort); 119 } 120 121 if (fAsyncPort) { 122 mach_port_mod_refs(mach_task_self(), fAsyncPort, MACH_PORT_RIGHT_RECEIVE, -1); 123 } 124 125 if (fCFSource) 126 CFRelease(fCFSource); 127} 128 129HRESULT IOHIDQueueClass::queryInterface(REFIID iid, void ** ppv) 130{ 131 CFUUIDRef uuid = CFUUIDCreateFromUUIDBytes(NULL, iid); 132 HRESULT res = S_OK; 133 134 if (CFEqual(uuid, kIOHIDDeviceQueueInterfaceID)) 135 { 136 *ppv = getInterfaceMap(); 137 addRef(); 138 } 139 else { 140 res = fOwningDevice->queryInterface(iid, ppv); 141 } 142 143 if (!*ppv) 144 res = E_NOINTERFACE; 145 146 CFRelease(uuid); 147 return res; 148} 149 150IOReturn IOHIDQueueClass::getAsyncEventSource(CFTypeRef *source) 151{ 152 IOReturn ret; 153 154 if (!fAsyncPort) { 155 ret = getAsyncPort(0); 156 if (kIOReturnSuccess != ret) 157 return ret; 158 } 159 160 if ( !fCFMachPort ) { 161 CFMachPortContext context; 162 Boolean shouldFreeInfo = FALSE; 163 164 context.version = 1; 165 context.info = this; 166 context.retain = NULL; 167 context.release = NULL; 168 context.copyDescription = NULL; 169 170 fCFMachPort = CFMachPortCreateWithPort(NULL, fAsyncPort, 171 (CFMachPortCallBack) IOHIDQueueClass::queueEventSourceCallback, 172 &context, &shouldFreeInfo); 173 174 if ( shouldFreeInfo ) { 175 // The CFMachPort we got might not work, but we'll proceed with it anyway. 176 asl_log(NULL, NULL, ASL_LEVEL_ERR, "%s received an unexpected reused CFMachPort", __func__); 177 } 178 179 if (!fCFMachPort) 180 return kIOReturnNoMemory; 181 } 182 183 if ( !fCFSource ) { 184 fCFSource = CFMachPortCreateRunLoopSource(NULL, fCFMachPort, 0); 185 if (!fCFSource) 186 return kIOReturnNoMemory; 187 } 188 189 if (source) 190 *source = fCFSource; 191 192 return kIOReturnSuccess; 193} 194 195/* CFMachPortCallBack */ 196void IOHIDQueueClass::queueEventSourceCallback(CFMachPortRef cfPort __unused, 197 mach_msg_header_t *msg __unused, 198 CFIndex size __unused, 199 void *info) 200{ 201 202 IOHIDQueueClass *queue = (IOHIDQueueClass *)info; 203 204 if ( queue ) { 205 if ( queue->fEventCallback ) { 206 207 (queue->fEventCallback)(queue->fEventRefcon, 208 kIOReturnSuccess, 209 (void *)&queue->fHIDQueue); 210 } 211 } 212} 213 214 215IOReturn IOHIDQueueClass::getAsyncPort(mach_port_t *port) 216{ 217 IOReturn ret = kIOReturnSuccess; 218 219 connectCheck(); 220 221 if ( fAsyncPort == MACH_PORT_NULL ) { 222 ret = IOCreateReceivePort(kOSAsyncCompleteMessageID, &fAsyncPort); 223 if ( kIOReturnSuccess != ret ) 224 return ret; 225 226 if ( fAsyncPort == MACH_PORT_NULL ) 227 return kIOReturnNoMemory; 228 229 ret = setAsyncPort(fAsyncPort); 230 } 231 232 if (port) 233 *port = fAsyncPort; 234 235 return ret; 236} 237 238IOReturn IOHIDQueueClass::setAsyncPort(mach_port_t port) 239{ 240 if ( !port ) 241 return kIOReturnError; 242 243 fAsyncPort = port; 244 245 if (!fIsCreated) 246 return kIOReturnSuccess; 247 248 io_async_ref64_t asyncRef; 249 uint64_t input = fQueueRef; 250 uint32_t len = 0; 251 252 return IOConnectCallAsyncScalarMethod(fOwningDevice->fConnection, kIOHIDLibUserClientSetQueueAsyncPort, fAsyncPort, asyncRef, 1, &input, 1, 0, &len); 253} 254 255 256IOReturn IOHIDQueueClass::create (IOOptionBits flags, uint32_t depth) 257{ 258 IOReturn ret = kIOReturnSuccess; 259 260 connectCheck(); 261 262 // ���todo, check flags/depth to see if different (might need to recreate?) 263 if (fIsCreated) 264 dispose(); 265 266 // sent message to create queue 267 uint64_t input[2]; 268 uint64_t output; 269 uint32_t outputCount = 1; 270 271 input[0] = flags; 272 input[1] = depth; 273 274 ret = IOConnectCallScalarMethod(fOwningDevice->fConnection, kIOHIDLibUserClientCreateQueue, input, 2, &output, &outputCount); 275 276 if (ret != kIOReturnSuccess) 277 return ret; 278 279 // we have created it 280 fIsCreated = true; 281 fQueueRef = output; 282 fCreatedFlags = flags; 283 fCreatedDepth = depth; 284 285 // if we have async port, set it on other side 286 if (fAsyncPort) 287 { 288 ret = setAsyncPort(fAsyncPort); 289 if (ret != kIOReturnSuccess) { 290 (void) this->dispose(); 291 return ret; 292 } 293 } 294 295 if (!fElements) 296 fElements = CFSetCreateMutable(kCFAllocatorDefault, 0, &kCFTypeSetCallBacks); 297 else { 298 IOHIDElementRef * elements; 299 CFIndex i, count = CFSetGetCount(fElements); 300 301 elements = (IOHIDElementRef *)malloc(sizeof(IOHIDElementRef) * count); 302 303 if (elements) 304 { 305 for (i=0; i<count; i++) 306 addElement(elements[i]); 307 308 free(elements); 309 } 310 } 311 312 return ret; 313} 314 315IOReturn IOHIDQueueClass::dispose() 316{ 317 IOReturn ret = kIOReturnSuccess; 318 319 mostChecks(); 320 321 // ���� TODO unmap memory when that call works 322 if ( fQueueMappedMemory ) 323 { 324#if !__LP64__ 325 vm_address_t mappedMem = (vm_address_t)fQueueMappedMemory; 326#else 327 mach_vm_address_t mappedMem = (mach_vm_address_t)fQueueMappedMemory; 328#endif 329 330 ret = IOConnectUnmapMemory (fOwningDevice->fConnection, 331 fQueueRef, 332 mach_task_self(), 333 mappedMem); 334 fQueueMappedMemory = NULL; 335 fQueueMappedMemorySize = 0; 336 } 337 338 339 uint64_t input = fQueueRef; 340 uint32_t outputCount = 0; 341 342 ret = IOConnectCallScalarMethod(fOwningDevice->fConnection, kIOHIDLibUserClientDisposeQueue, &input, 1, 0, &outputCount); 343 344 if (ret != kIOReturnSuccess) 345 return ret; 346 347 // mark it dead 348 fIsCreated = false; 349 350 fQueueRef = 0; 351 352 return kIOReturnSuccess; 353} 354 355IOReturn IOHIDQueueClass::getDepth(uint32_t * pDepth) 356{ 357 *pDepth = fCreatedDepth; 358 return kIOReturnSuccess; 359} 360 361/* Any number of hid elements can feed the same queue */ 362IOReturn IOHIDQueueClass::addElement (IOHIDElementRef element, IOOptionBits options) 363{ 364 IOReturn ret = kIOReturnSuccess; 365 366 if (!element) 367 return kIOReturnBadArgument; 368 369 mostChecks(); 370 371 uint64_t input[3]; 372 uint64_t sizeChange; 373 uint32_t outputCount = 1; 374 375 input[0] = fQueueRef; 376 input[1] = (uint64_t)IOHIDElementGetCookie(element); 377 input[2] = options; 378 379 ret = IOConnectCallScalarMethod(fOwningDevice->fConnection, kIOHIDLibUserClientAddElementToQueue, input, 3, &sizeChange, &outputCount); 380 381 if (ret != kIOReturnSuccess) 382 return ret; 383 384 fQueueEntrySizeChanged = sizeChange; 385 386 if (fElements) 387 CFSetSetValue(fElements, element); 388 389 return kIOReturnSuccess; 390} 391 392IOReturn IOHIDQueueClass::removeElement (IOHIDElementRef element, IOOptionBits options __unused) 393{ 394 IOReturn ret = kIOReturnSuccess; 395 396 if (!element) 397 return kIOReturnBadArgument; 398 399 mostChecks(); 400 401 uint64_t input[2]; 402 uint64_t sizeChange; 403 uint32_t outputCount = 1; 404 405 input[0] = fQueueRef; 406 input[1] = (uint64_t)IOHIDElementGetCookie(element); 407 408 ret = IOConnectCallScalarMethod(fOwningDevice->fConnection, kIOHIDLibUserClientRemoveElementFromQueue, input, 2, &sizeChange, &outputCount); 409 410 if (ret != kIOReturnSuccess) 411 return ret; 412 413 fQueueEntrySizeChanged = sizeChange; 414 415 if (fElements) 416 CFSetRemoveValue(fElements, element); 417 418 return kIOReturnSuccess; 419} 420 421IOReturn IOHIDQueueClass::hasElement (IOHIDElementRef element, Boolean * pValue, IOOptionBits options __unused) 422{ 423 if (!element || !pValue) 424 return kIOReturnBadArgument; 425 426 mostChecks(); 427 428 uint64_t input[2]; 429 uint64_t returnHasElement; 430 uint32_t outputCount = 1; 431 432 input[0] = fQueueRef; 433 input[1] = (uint64_t)IOHIDElementGetCookie(element); 434 435 IOReturn ret = IOConnectCallScalarMethod(fOwningDevice->fConnection, kIOHIDLibUserClientQueueHasElement, input, 2, &returnHasElement, &outputCount); 436 437 *pValue = returnHasElement; 438 439 return ret; 440} 441 442 443/* start/stop data delivery to a queue */ 444IOReturn IOHIDQueueClass::start (IOOptionBits options __unused) 445{ 446 IOReturn ret = kIOReturnSuccess; 447 448 mostChecks(); 449 450 // if the queue size changes, we will need to dispose of the 451 // queue mapped memory 452 if ( fQueueEntrySizeChanged && fQueueMappedMemory ) 453 { 454 ret = IOConnectUnmapMemory (fOwningDevice->fConnection, 455 fQueueRef, 456 mach_task_self(), 457 (uintptr_t)fQueueMappedMemory); 458 fQueueMappedMemory = NULL; 459 fQueueMappedMemorySize = 0; 460 } 461 462 uint64_t input = fQueueRef; 463 uint32_t outputCount = 0; 464 465 ret = IOConnectCallScalarMethod(fOwningDevice->fConnection, kIOHIDLibUserClientStartQueue, &input, 1, 0, &outputCount); 466 467 if (ret != kIOReturnSuccess) 468 return ret; 469 470 // get the queue shared memory 471 if ( !fQueueMappedMemory ) 472 { 473#if !__LP64__ 474 vm_address_t address = nil; 475 vm_size_t size = 0; 476#else 477 mach_vm_address_t address = nil; 478 mach_vm_size_t size = 0; 479#endif 480 481 ret = IOConnectMapMemory ( fOwningDevice->fConnection, 482 fQueueRef, 483 mach_task_self(), 484 &address, 485 &size, 486 kIOMapAnywhere ); 487 if (ret == kIOReturnSuccess) 488 { 489 fQueueMappedMemory = (IODataQueueMemory *) address; 490 fQueueMappedMemorySize = size; 491 fQueueEntrySizeChanged = false; 492 } 493 } 494 495 return kIOReturnSuccess; 496} 497 498IOReturn IOHIDQueueClass::stop (IOOptionBits options __unused) 499{ 500 IOReturn ret = kIOReturnSuccess; 501 502 allChecks(); 503 504 uint64_t input = fQueueRef; 505 uint32_t outputCount = 0; 506 507 ret = IOConnectCallScalarMethod(fOwningDevice->fConnection, kIOHIDLibUserClientStopQueue, &input, 1, 0, &outputCount); 508 509 if (ret != kIOReturnSuccess) 510 return ret; 511 512 // ��� TODO after we stop the queue, we should empty the queue here, in user space 513 // (to be consistant with setting the head from user space) 514 515 return kIOReturnSuccess; 516} 517 518IOReturn IOHIDQueueClass::copyNextEventValue (IOHIDValueRef *pEvent, 519 uint32_t timeout __unused, 520 IOOptionBits options __unused) 521{ 522 IOReturn ret = kIOReturnSuccess; 523 524 allChecks(); 525 526 if ( !fQueueMappedMemory ) 527 return kIOReturnNoMemory; 528 529 // check entry size 530 IODataQueueEntry * nextEntry = IODataQueuePeek(fQueueMappedMemory); 531 uint32_t entrySize; 532 533 // if queue empty, then stop 534 if (nextEntry == NULL) 535 return kIOReturnUnderrun; 536 537 entrySize = nextEntry->size; 538 ROSETTA_ONLY( 539 entrySize = OSSwapInt32(entrySize); 540 ); 541 542 uint32_t dataSize = sizeof(IOHIDElementValue); 543 544 // check size of next entry 545 // Make sure that it is not smaller than IOHIDElementValue 546 if (entrySize < sizeof(IOHIDElementValue)) 547 HIDLog ("IOHIDQueueClass: Queue size mismatch (%ld, %ld)\n", entrySize, sizeof(IOHIDElementValue)); 548 549 // dequeue the item 550// HIDLog ("IOHIDQueueClass::getNextEvent about to dequeue\n"); 551 ret = IODataQueueDequeue(fQueueMappedMemory, NULL, &dataSize); 552// HIDLog ("IODataQueueDequeue result %lx\n", (uint32_t) ret); 553 554 555 // if we got an entry 556 if (ret == kIOReturnSuccess && nextEntry) 557 { 558 IOHIDElementValue * nextElementValue = (IOHIDElementValue *) &(nextEntry->data); 559 IOHIDElementCookie cookie = nextElementValue->cookie; 560 561 ROSETTA_ONLY( 562 cookie = (IOHIDElementCookie)OSSwapInt32((uint32_t)cookie); 563 ); 564 565 if ( pEvent ) 566 *pEvent = _IOHIDValueCreateWithElementValuePtr(kCFAllocatorDefault, fOwningDevice->getElement(cookie), nextElementValue); 567 } 568 569 return ret; 570} 571 572IOReturn IOHIDQueueClass::setEventCallback (IOHIDCallback callback, void * refcon) 573{ 574 fEventCallback = callback; 575 fEventRefcon = refcon; 576 577 return kIOReturnSuccess; 578} 579 580IOHIDDeviceQueueInterface IOHIDQueueClass::sHIDQueueInterfaceV2 = 581{ 582 0, 583 &IOHIDIUnknown::genericQueryInterface, 584 &IOHIDIUnknown::genericAddRef, 585 &IOHIDIUnknown::genericRelease, 586 &IOHIDQueueClass::_getAsyncEventSource, 587 &IOHIDQueueClass::_setDepth, 588 &IOHIDQueueClass::_getDepth, 589 &IOHIDQueueClass::_addElement, 590 &IOHIDQueueClass::_removeElement, 591 &IOHIDQueueClass::_hasElement, 592 &IOHIDQueueClass::_start, 593 &IOHIDQueueClass::_stop, 594 &IOHIDQueueClass::_setEventCallback, 595 &IOHIDQueueClass::_copyNextEventValue 596}; 597 598IOReturn IOHIDQueueClass::_getAsyncEventSource(void *self, CFTypeRef *source) 599 { return getThis(self)->getAsyncEventSource(source); } 600 601IOReturn IOHIDQueueClass::_getAsyncPort(void *self, mach_port_t *port) 602 { return getThis(self)->getAsyncPort(port); } 603 604IOReturn IOHIDQueueClass::_setDepth(void *self, uint32_t depth, IOOptionBits options) 605 { return getThis(self)->create(options, depth); } 606 607IOReturn IOHIDQueueClass::_getDepth(void *self, uint32_t *pDepth) 608 { return getThis(self)->getDepth(pDepth); } 609 610IOReturn IOHIDQueueClass::_addElement (void * self, IOHIDElementRef element, IOOptionBits options) 611 { return getThis(self)->addElement(element, options); } 612 613IOReturn IOHIDQueueClass::_removeElement (void * self, IOHIDElementRef element, IOOptionBits options) 614 { return getThis(self)->removeElement(element, options); } 615 616IOReturn IOHIDQueueClass::_hasElement (void * self, IOHIDElementRef element, Boolean * pValue, IOOptionBits options) 617 { return getThis(self)->hasElement(element, pValue, options); } 618 619IOReturn IOHIDQueueClass::_start (void * self, IOOptionBits options) 620 { return getThis(self)->start(options); } 621 622IOReturn IOHIDQueueClass::_stop (void * self, IOOptionBits options) 623 { return getThis(self)->stop(options); } 624 625IOReturn IOHIDQueueClass::_copyNextEventValue (void * self, IOHIDValueRef * pEvent, uint32_t timeout, IOOptionBits options) 626 { return getThis(self)->copyNextEventValue(pEvent, timeout, options); } 627 628IOReturn IOHIDQueueClass::_setEventCallback (void * self, IOHIDCallback callback, void * refcon) 629 { return getThis(self)->setEventCallback(callback, refcon); } 630 631 632 633//**************************************************************************************************** 634// Class: IOHIDObsoleteQueueClass 635// Subclasses: IOHIDQueueClass 636//**************************************************************************************************** 637IOHIDQueueInterface IOHIDObsoleteQueueClass::sHIDQueueInterface = 638{ 639 0, 640 &IOHIDIUnknown::genericQueryInterface, 641 &IOHIDIUnknown::genericAddRef, 642 &IOHIDIUnknown::genericRelease, 643 &IOHIDObsoleteQueueClass::_createAsyncEventSource, 644 &IOHIDObsoleteQueueClass::_getAsyncEventSource, 645 &IOHIDQueueClass::_getAsyncPort, 646 &IOHIDObsoleteQueueClass::_getAsyncPort, 647 &IOHIDObsoleteQueueClass::_create, 648 &IOHIDObsoleteQueueClass::_dispose, 649 &IOHIDObsoleteQueueClass::_addElement, 650 &IOHIDObsoleteQueueClass::_removeElement, 651 &IOHIDObsoleteQueueClass::_hasElement, 652 &IOHIDObsoleteQueueClass::_start, 653 &IOHIDObsoleteQueueClass::_stop, 654 &IOHIDObsoleteQueueClass::_getNextEvent, 655 &IOHIDObsoleteQueueClass::_setEventCallout, 656 &IOHIDObsoleteQueueClass::_getEventCallout, 657}; 658 659// Methods for routing asynchronous completion plumbing. 660IOReturn IOHIDObsoleteQueueClass::_createAsyncEventSource(void * self, CFRunLoopSourceRef * pSource) 661{ 662 return getThis(self)->createAsyncEventSource(pSource); 663} 664 665CFRunLoopSourceRef IOHIDObsoleteQueueClass::_getAsyncEventSource(void *self) 666{ 667 CFTypeRef source = NULL; 668 getThis(self)->getAsyncEventSource(&source); 669 return (CFRunLoopSourceRef)source; 670} 671 672mach_port_t IOHIDObsoleteQueueClass::_getAsyncPort(void *self) 673 { mach_port_t port = MACH_PORT_NULL; getThis(self)->getAsyncPort(&port); return port; } 674 675IOReturn IOHIDObsoleteQueueClass::_create (void * self, uint32_t flags, uint32_t depth) 676 { return getThis(self)->create(flags, depth); } 677 678IOReturn IOHIDObsoleteQueueClass::_dispose (void * self) 679 { return getThis(self)->dispose(); } 680 681IOReturn IOHIDObsoleteQueueClass::_addElement (void * self, IOHIDElementCookie cookie, uint32_t flags) 682 { return getThis(self)->addElement(cookie, flags); } 683 684IOReturn IOHIDObsoleteQueueClass::_removeElement (void * self, IOHIDElementCookie elementCookie) 685 { return getThis(self)->removeElement(elementCookie); } 686 687Boolean IOHIDObsoleteQueueClass::_hasElement (void * self, IOHIDElementCookie elementCookie) 688 { return getThis(self)->hasElement(elementCookie); } 689 690IOReturn IOHIDObsoleteQueueClass::_start (void * self) 691 { return getThis(self)->start(); } 692 693IOReturn IOHIDObsoleteQueueClass::_stop (void * self) 694 { return getThis(self)->stop(); } 695 696IOReturn IOHIDObsoleteQueueClass::_getNextEvent (void * self, IOHIDEventStruct * event, AbsoluteTime maxTime, uint32_t timeoutMS) 697 { return getThis(self)->getNextEvent(event, maxTime, timeoutMS); } 698 699IOReturn IOHIDObsoleteQueueClass::_setEventCallout (void * self, IOHIDCallbackFunction callback, void * target, void * refcon) 700 { return getThis(self)->setEventCallout (callback, target, refcon); } 701 702IOReturn IOHIDObsoleteQueueClass::_getEventCallout (void * self, IOHIDCallbackFunction * pCallback, void ** pTarget, void ** pRefcon) 703 { return getThis(self)->getEventCallout(pCallback, pTarget, pRefcon); } 704 705IOHIDObsoleteQueueClass::IOHIDObsoleteQueueClass() : IOHIDQueueClass() 706{ 707 fHIDQueue.pseudoVTable = (IUnknownVTbl *) &sHIDQueueInterface; 708 fHIDQueue.obj = this; 709 710 fCallback = NULL; 711 fTarget = NULL; 712 fRefcon = NULL; 713} 714 715HRESULT IOHIDObsoleteQueueClass::queryInterface(REFIID iid, void ** ppv) 716{ 717 CFUUIDRef uuid = CFUUIDCreateFromUUIDBytes(NULL, iid); 718 HRESULT res = S_OK; 719 720 if (CFEqual(uuid, kIOHIDQueueInterfaceID)) 721 { 722 *ppv = getInterfaceMap(); 723 addRef(); 724 } 725 else { 726 res = fOwningDevice->queryInterface(iid, ppv); 727 } 728 729 if (!*ppv) 730 res = E_NOINTERFACE; 731 732 CFRelease(uuid); 733 return res; 734} 735 736IOReturn IOHIDObsoleteQueueClass::createAsyncEventSource(CFRunLoopSourceRef * pSource) 737{ 738 IOReturn ret = IOHIDQueueClass::getAsyncEventSource((CFTypeRef *)pSource); 739 740 if ( ret == kIOReturnSuccess && pSource && *pSource ) 741 CFRetain(*pSource); 742 743 return ret; 744} 745 746 747IOReturn IOHIDObsoleteQueueClass::addElement (IOHIDElementCookie cookie, uint32_t flags) 748{ 749 return IOHIDQueueClass::addElement(fOwningDevice->getElement(cookie), flags); 750} 751 752IOReturn 753IOHIDObsoleteQueueClass::addElement (IOHIDElementRef element, 754 IOOptionBits options) 755{ 756 return IOHIDQueueClass::addElement(element, options); 757} 758 759 760IOReturn IOHIDObsoleteQueueClass::removeElement (IOHIDElementCookie cookie) 761{ 762 return IOHIDQueueClass::removeElement(fOwningDevice->getElement(cookie)); 763} 764 765IOReturn 766IOHIDObsoleteQueueClass::removeElement (IOHIDElementRef element, 767 IOOptionBits options) 768{ 769 return IOHIDQueueClass::removeElement(element, options); 770} 771 772 773Boolean IOHIDObsoleteQueueClass::hasElement (IOHIDElementCookie cookie) 774{ 775 IOHIDElementRef element = fOwningDevice->getElement(cookie); 776 Boolean value = FALSE; 777 778 return (IOHIDQueueClass::hasElement(element, &value) == kIOReturnSuccess) ? value : FALSE; 779} 780 781IOReturn 782IOHIDObsoleteQueueClass::hasElement (IOHIDElementRef element, 783 Boolean * pValue, 784 IOOptionBits options) 785{ 786 return IOHIDQueueClass::hasElement(element, pValue, options); 787} 788 789IOReturn IOHIDObsoleteQueueClass::getNextEvent (IOHIDEventStruct * pEventStruct, AbsoluteTime maxTime __unused, uint32_t timeoutMS) 790{ 791 IOHIDValueRef event = NULL; 792 IOReturn ret = kIOReturnBadArgument; 793 794 if (pEventStruct) 795 { 796 ret = copyNextEventValue(&event, timeoutMS); 797 798 if ((ret==kIOReturnSuccess) && event) 799 { 800 uint32_t length = _IOHIDElementGetLength(IOHIDValueGetElement(event)); 801 802 pEventStruct->type = IOHIDElementGetType(IOHIDValueGetElement(event)); 803 pEventStruct->elementCookie = IOHIDElementGetCookie(IOHIDValueGetElement(event)); 804 *(UInt64 *)&pEventStruct->timestamp = IOHIDValueGetTimeStamp(event); 805 806 if ( length > sizeof(uint32_t) ) 807 { 808 pEventStruct->longValueSize = length; 809 pEventStruct->longValue = malloc(length); 810 bcopy(IOHIDValueGetBytePtr(event), pEventStruct->longValue, length); 811 } 812 else 813 { 814 pEventStruct->longValueSize = 0; 815 pEventStruct->longValue = NULL; 816 pEventStruct->value = IOHIDValueGetIntegerValue(event); 817 } 818 819 CFRelease(event); 820 } 821 } 822 823 return ret; 824} 825 826IOReturn IOHIDObsoleteQueueClass::getEventCallout (IOHIDCallbackFunction * pCallback, void ** pTarget, void ** pRefcon) 827{ 828 if (pCallback) *pCallback = fCallback; 829 if (pTarget) *pTarget = fTarget; 830 if (pRefcon) *pRefcon = fRefcon; 831 832 return kIOReturnSuccess; 833} 834 835IOReturn IOHIDObsoleteQueueClass::setEventCallout (IOHIDCallbackFunction callback, void * target, void * refcon) 836{ 837 fCallback = callback; 838 fTarget = target; 839 fRefcon = refcon; 840 841 IOHIDQueueClass::setEventCallback(IOHIDObsoleteQueueClass::_eventCallback, this); 842 843 return kIOReturnSuccess; 844} 845 846void IOHIDObsoleteQueueClass::_eventCallback(void * refcon, IOReturn result, void * sender) 847{ 848 IOHIDObsoleteQueueClass * self = (IOHIDObsoleteQueueClass *) refcon; 849 850 if ( self->fCallback ) 851 (*self->fCallback)(self->fTarget, result, self->fRefcon, sender); 852} 853 854