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 25#define CFRUNLOOP_NEW_API 1 26 27#include <CoreFoundation/CFMachPort.h> 28//#include <IOKit/hid/IOHIDLib.h> 29//#include <unistd.h> 30 31#include "IOHIDTransactionClass.h" 32#include "IOHIDLibUserClient.h" 33#include "IOHIDTransactionElement.h" 34 35__BEGIN_DECLS 36#include <mach/mach_interface.h> 37#include <mach/mach.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 seizeCheck() do { \ 65 if ((!fOwningDevice) || \ 66 (!fOwningDevice->isValid())) \ 67 return kIOReturnExclusiveAccess;\ 68} while (0) 69 70 71#define mostChecks() do { \ 72 connectCheck(); \ 73 createdCheck(); \ 74} while (0) 75 76#define allChecks() do { \ 77 mostChecks(); \ 78 openCheck(); \ 79 seizeCheck(); \ 80} while (0) 81 82IOHIDTransactionClass::IOHIDTransactionClass() : IOHIDIUnknown(NULL) 83{ 84 fHIDTransaction.pseudoVTable = (IUnknownVTbl *) &sHIDTransactionInterface; 85 fHIDTransaction.obj = this; 86 87 fDirection = 0; 88 fIsCreated = false; 89 fOwningDevice = NULL; 90 fEventCallback = NULL; 91 fEventRefcon = NULL; 92 fElementDictionaryRef = NULL; 93} 94 95IOHIDTransactionClass::~IOHIDTransactionClass() 96{ 97 if (fIsCreated) 98 dispose(); 99 100 if( fOwningDevice ) 101 fOwningDevice->detachTransaction(this); 102 103} 104 105HRESULT IOHIDTransactionClass::queryInterface(REFIID iid, void ** ppv) 106{ 107 CFUUIDRef uuid = CFUUIDCreateFromUUIDBytes(NULL, iid); 108 HRESULT res = S_OK; 109 110 if (CFEqual(uuid, kIOHIDDeviceTransactionInterfaceID)) 111 { 112 *ppv = getInterfaceMap(); 113 addRef(); 114 } 115 else { 116 res = fOwningDevice->queryInterface(iid, ppv); 117 } 118 119 if (!*ppv) 120 res = E_NOINTERFACE; 121 122 CFRelease(uuid); 123 return res; 124} 125 126IOReturn IOHIDTransactionClass::getAsyncEventSource(CFTypeRef *source) 127{ 128 connectCheck(); 129 130 return fOwningDevice->getAsyncEventSource(source); 131} 132 133void IOHIDTransactionClass::_eventSourceCallback(CFMachPortRef *cfPort __unused, mach_msg_header_t *msg __unused, CFIndex size __unused, void *info) 134{ 135 136 IOHIDTransactionClass *transaction = (IOHIDTransactionClass *)info; 137 138 if ( transaction && transaction->fEventCallback) 139 { 140 (transaction->fEventCallback)(transaction->fEventRefcon, kIOReturnSuccess, (void *)&transaction->fHIDTransaction); 141 } 142} 143 144IOReturn IOHIDTransactionClass::getAsyncPort(mach_port_t *port) 145{ 146 connectCheck(); 147 148 return fOwningDevice->getAsyncPort(port); 149} 150 151IOReturn IOHIDTransactionClass::getDirection(IOHIDTransactionDirectionType * pDirection) 152{ 153 if (!pDirection) 154 return kIOReturnBadArgument; 155 156 *pDirection = fDirection; 157 158 return kIOReturnSuccess; 159} 160 161IOReturn IOHIDTransactionClass::setDirection(IOHIDTransactionDirectionType direction, IOOptionBits options __unused) 162{ 163 IOHIDTransactionElementRef *elementRefs = NULL; 164 IOHIDElementRef element = NULL; 165 CFStringRef *keyRefs= NULL; 166 CFIndex numElements = 0; 167 168 if (!fIsCreated || !fElementDictionaryRef) 169 return kIOReturnError; 170 171 // RY: If we change directions, we should remove the opposite direction elements 172 // from the transaction. I might decide to leave them alone in the future and 173 // just ignore them during the commit. 174 numElements = CFDictionaryGetCount(fElementDictionaryRef); 175 176 if (!numElements) 177 return kIOReturnError; 178 179 elementRefs = (IOHIDTransactionElementRef *)malloc(sizeof(IOHIDTransactionElementRef) * numElements); 180 keyRefs = (CFStringRef *)malloc(sizeof(CFStringRef) * numElements); 181 CFDictionaryGetKeysAndValues(fElementDictionaryRef, (const void **)keyRefs, (const void **)elementRefs); 182 183 for (int i=0;i<numElements && elementRefs[i] && keyRefs[i]; i++) 184 { 185 element = IOHIDTransactionElementGetElement(elementRefs[i]); 186 if (((IOHIDElementGetType(element) == kIOHIDElementTypeOutput) && (direction == kIOHIDTransactionDirectionTypeInput)) || 187 ((IOHIDElementGetType(element) >= kIOHIDElementTypeInput_Misc) && (IOHIDElementGetType(element) <= kIOHIDElementTypeInput_ScanCodes) && (direction == kIOHIDTransactionDirectionTypeOutput))) 188 CFDictionaryRemoveValue(fElementDictionaryRef, keyRefs[i]); 189 } 190 191 if (elementRefs) 192 free(elementRefs); 193 194 if (keyRefs) 195 free(keyRefs); 196 197 fDirection = direction; 198 199 return kIOReturnSuccess; 200} 201 202IOReturn IOHIDTransactionClass::create () 203{ 204 IOReturn ret = kIOReturnSuccess; 205 206 connectCheck(); 207 208 if (fIsCreated) 209 return kIOReturnSuccess; 210 211 // Create the mutable dictionary that will hold the transaction elements. 212 fElementDictionaryRef = CFDictionaryCreateMutable(kCFAllocatorDefault, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); 213 214 if (!fElementDictionaryRef) 215 return kIOReturnNoMemory; 216 217 // we have created it 218 fIsCreated = true; 219 220 return ret; 221} 222 223IOReturn IOHIDTransactionClass::dispose() 224{ 225 IOReturn ret = kIOReturnSuccess; 226 227 // mark it dead 228 fIsCreated = false; 229 230 if (fElementDictionaryRef) 231 { 232 CFRelease(fElementDictionaryRef); 233 fElementDictionaryRef = NULL; 234 } 235 236 return ret; 237} 238 239IOReturn IOHIDTransactionClass::addElement (IOHIDElementRef element, IOOptionBits options __unused) 240{ 241 IOHIDTransactionElementRef transactionElement; 242 IOHIDElementType elementType; 243 IOReturn ret = kIOReturnSuccess; 244 Boolean added = false; 245 246 mostChecks(); 247 248 if (!element) 249 return kIOReturnBadArgument; 250 251 if (!fIsCreated || hasElement(element, &added) || added) 252 return kIOReturnError; 253 254 elementType = IOHIDElementGetType(element); 255 256 // Since this is a Output Transaction only allow feature and output elements 257 if ((elementType != kIOHIDElementTypeOutput) && (elementType != kIOHIDElementTypeFeature)) 258 return kIOReturnBadArgument; 259 260 transactionElement = IOHIDTransactionElementCreate(kCFAllocatorDefault, element, 0); 261 262 if (!fElementDictionaryRef || !transactionElement) 263 ret = kIOReturnError; 264 else 265 CFDictionarySetValue(fElementDictionaryRef, element, transactionElement); 266 267 if (transactionElement) CFRelease(transactionElement); 268 269 return kIOReturnSuccess; 270} 271 272IOReturn IOHIDTransactionClass::removeElement (IOHIDElementRef element, IOOptionBits options __unused) 273{ 274 Boolean added; 275 276 mostChecks(); 277 278 if (!element) 279 return kIOReturnBadArgument; 280 281 if (!fIsCreated || !fElementDictionaryRef || hasElement(element, &added) || !added) 282 return kIOReturnError; 283 284 CFDictionaryRemoveValue(fElementDictionaryRef, element); 285 286 return kIOReturnSuccess; 287} 288 289IOReturn IOHIDTransactionClass::hasElement (IOHIDElementRef element, Boolean *pValue, IOOptionBits options __unused) 290{ 291 mostChecks(); 292 293 if (!element || !pValue) 294 return kIOReturnBadArgument; 295 296 if (!fIsCreated || !fElementDictionaryRef) 297 return kIOReturnError; 298 299 *pValue = CFDictionaryContainsKey(fElementDictionaryRef, element); 300 301 return kIOReturnSuccess; 302} 303 304IOReturn IOHIDTransactionClass::setElementValue(IOHIDElementRef element, IOHIDValueRef event, IOOptionBits options) 305{ 306 IOHIDTransactionElementRef transactionElement; 307 308 mostChecks(); 309 310 if (!element || (fDirection == kIOHIDTransactionDirectionTypeInput)) 311 return kIOReturnBadArgument; 312 313 if (!fIsCreated || !fElementDictionaryRef) 314 return kIOReturnError; 315 316 transactionElement = (IOHIDTransactionElementRef)CFDictionaryGetValue(fElementDictionaryRef, element); 317 318 if (!transactionElement) 319 return kIOReturnError; 320 321 if ( options & kIOHIDTransactionOptionDefaultOutputValue ) 322 IOHIDTransactionElementSetDefaultValue(transactionElement, event); 323 else 324 IOHIDTransactionElementSetValue(transactionElement, event); 325 326 return kIOReturnSuccess; 327} 328 329/* get the value for that element */ 330IOReturn IOHIDTransactionClass::getElementValue(IOHIDElementRef element, IOHIDValueRef * pEvent, IOOptionBits options) 331{ 332 IOHIDTransactionElementRef transactionElement; 333 334 mostChecks(); 335 336 if (!element) 337 return kIOReturnBadArgument; 338 339 if (!fIsCreated || !fElementDictionaryRef) 340 return kIOReturnError; 341 342 transactionElement = (IOHIDTransactionElementRef)CFDictionaryGetValue(fElementDictionaryRef, element); 343 344 if (!transactionElement) 345 return kIOReturnError; 346 347 *pEvent = ((fDirection == kIOHIDTransactionDirectionTypeOutput) && (options & kIOHIDTransactionOptionDefaultOutputValue)) ? 348 IOHIDTransactionElementGetDefaultValue(transactionElement) : IOHIDTransactionElementGetValue(transactionElement); 349 350 return kIOReturnSuccess; 351} 352 353/* start/stop data delivery to a queue */ 354IOReturn IOHIDTransactionClass::commit(uint32_t timeoutMS __unused, IOHIDCallback callback __unused, void * callbackRefcon __unused, IOOptionBits options __unused) 355{ 356 IOHIDTransactionElementRef * elementRefs = NULL; 357 uint64_t * cookies = NULL; 358 CFIndex numElements = 0; 359 IOReturn ret = kIOReturnError; 360 int numValidElements = 0; 361 IOHIDValueRef event; 362 363 allChecks(); 364 365 if (!fIsCreated || !fElementDictionaryRef) 366 return kIOReturnError; 367 368 numElements = CFDictionaryGetCount(fElementDictionaryRef); 369 370 if (!numElements) 371 return kIOReturnError; 372 373 cookies = (uint64_t *)malloc(sizeof(uint64_t) * numElements); 374 elementRefs = (IOHIDTransactionElementRef *)malloc(sizeof(IOHIDTransactionElementRef) * numElements); 375 376 CFDictionaryGetKeysAndValues(fElementDictionaryRef, NULL, (const void **)elementRefs); 377 378 // run through and call setElementValue w/o device push 379 // *** we definitely have to hold a lock here. *** 380 for (int i=0;i<numElements && elementRefs[i]; i++) 381 { 382 if ( fDirection == kIOHIDTransactionDirectionTypeOutput ) 383 { 384 if ((event = IOHIDTransactionElementGetValue(elementRefs[i]))) 385 { 386 fOwningDevice->setElementValue(IOHIDTransactionElementGetElement(elementRefs[i]), event, 0, NULL, NULL, kHIDSetElementValuePendEvent); 387 } 388 else if ((event = IOHIDTransactionElementGetDefaultValue(elementRefs[i]))) 389 { 390 fOwningDevice->setElementValue(IOHIDTransactionElementGetElement(elementRefs[i]), event, 0, NULL, NULL, kHIDSetElementValuePendEvent); 391 } 392 else 393 continue; 394 } 395 396 IOHIDTransactionElementSetValue(elementRefs[i], NULL); 397 398 cookies[numValidElements] = (uint32_t)IOHIDElementGetCookie(IOHIDTransactionElementGetElement(elementRefs[i])); 399 ROSETTA_ONLY( 400 cookies[numValidElements] = OSSwapInt32(cookies[numValidElements]); 401 ); 402 403 numValidElements++; 404 } 405 406 uint32_t outputCount = 0; 407 408 if ( fDirection == kIOHIDTransactionDirectionTypeOutput ) 409 { 410 ret = IOConnectCallScalarMethod(fOwningDevice->fConnection, kIOHIDLibUserClientPostElementValues, cookies, numValidElements, 0, &outputCount); 411 } 412 else 413 { 414 // put together an ioconnect here 415 ret = IOConnectCallScalarMethod(fOwningDevice->fConnection, kIOHIDLibUserClientUpdateElementValues, cookies, numValidElements, 0, &outputCount); 416 417 for (int i=0;i<numElements && elementRefs[i]; i++) 418 { 419 fOwningDevice->getElementValue(IOHIDTransactionElementGetElement(elementRefs[i]), &event, 0, NULL, NULL, kHIDGetElementValuePreventPoll); 420 IOHIDTransactionElementSetValue(elementRefs[i], event); 421 } 422 } 423 424 if (elementRefs) 425 free(elementRefs); 426 427 if ( cookies ) 428 free(cookies); 429 430 return ret; 431 432} 433 434IOReturn IOHIDTransactionClass::clear (IOOptionBits options __unused) 435{ 436 IOHIDTransactionElementRef *elementRefs = NULL; 437 CFIndex numElements = 0; 438 439 mostChecks(); 440 441 if (!fIsCreated || !fElementDictionaryRef) 442 return kIOReturnError; 443 444 numElements = CFDictionaryGetCount(fElementDictionaryRef); 445 446 if (!numElements) 447 return kIOReturnError; 448 449 elementRefs = (IOHIDTransactionElementRef *)malloc(sizeof(IOHIDTransactionElementRef) * numElements); 450 451 CFDictionaryGetKeysAndValues(fElementDictionaryRef, NULL, (const void **)elementRefs); 452 453 for (int i=0;i<numElements && elementRefs[i]; i++) 454 IOHIDTransactionElementSetValue(elementRefs[i], NULL); 455 456 if (elementRefs) 457 free(elementRefs); 458 459 return kIOReturnSuccess; 460} 461 462IOHIDDeviceTransactionInterface IOHIDTransactionClass::sHIDTransactionInterface = 463{ 464 0, 465 &IOHIDIUnknown::genericQueryInterface, 466 &IOHIDIUnknown::genericAddRef, 467 &IOHIDIUnknown::genericRelease, 468 &IOHIDTransactionClass::_getAsyncEventSource, 469 &IOHIDTransactionClass::_setDirection, 470 &IOHIDTransactionClass::_getDirection, 471 &IOHIDTransactionClass::_addElement, 472 &IOHIDTransactionClass::_removeElement, 473 &IOHIDTransactionClass::_hasElement, 474 &IOHIDTransactionClass::_setElementValue, 475 &IOHIDTransactionClass::_getElementValue, 476 &IOHIDTransactionClass::_commit, 477 &IOHIDTransactionClass::_clear, 478}; 479 480IOReturn IOHIDTransactionClass::_getAsyncEventSource(void *self, CFTypeRef *source) 481 { return getThis(self)->getAsyncEventSource(source); } 482 483IOReturn IOHIDTransactionClass::_getAsyncPort(void *self, mach_port_t *port) 484 { return getThis(self)->getAsyncPort(port); } 485 486IOReturn IOHIDTransactionClass::_setDirection(void *self, IOHIDTransactionDirectionType direction, IOOptionBits options) 487 { return getThis(self)->setDirection(direction, options); } 488 489IOReturn IOHIDTransactionClass::_getDirection(void *self, IOHIDTransactionDirectionType * pDirection) 490 { return getThis(self)->getDirection(pDirection); } 491 492IOReturn IOHIDTransactionClass::_addElement (void * self, IOHIDElementRef element, IOOptionBits options) 493 { return getThis(self)->addElement(element, options); } 494 495IOReturn IOHIDTransactionClass::_removeElement (void * self, IOHIDElementRef element, IOOptionBits options) 496 { return getThis(self)->removeElement(element, options); } 497 498IOReturn IOHIDTransactionClass::_hasElement (void * self, IOHIDElementRef element, Boolean *pValue, IOOptionBits options) 499 { return getThis(self)->hasElement(element, pValue, options); } 500 501IOReturn IOHIDTransactionClass::_setElementValue(void * self, IOHIDElementRef element, IOHIDValueRef event, IOOptionBits options) 502 { return getThis(self)->setElementValue(element, event, options); } 503 504IOReturn IOHIDTransactionClass::_getElementValue(void * self, IOHIDElementRef element, IOHIDValueRef * pEvent, IOOptionBits options) 505 { return getThis(self)->getElementValue(element, pEvent, options); } 506 507IOReturn IOHIDTransactionClass::_commit(void * self, uint32_t timeoutMS, IOHIDCallback callback, void * callbackRefcon, IOOptionBits options) 508 { return getThis(self)->commit(timeoutMS, callback, callbackRefcon, options);} 509 510IOReturn IOHIDTransactionClass::_clear(void * self, IOOptionBits options) 511 { return getThis(self)->clear(options);} 512 513 514//**************************************************************************************************** 515// Class: IOHIDOutputTransactionClass 516// Subclasses: IOHIDTransactionClass 517//**************************************************************************************************** 518 519IOHIDOutputTransactionInterface IOHIDOutputTransactionClass::sHIDOutputTransactionInterface = 520{ 521 0, 522 &IOHIDIUnknown::genericQueryInterface, 523 &IOHIDIUnknown::genericAddRef, 524 &IOHIDIUnknown::genericRelease, 525 &IOHIDOutputTransactionClass::_createAsyncEventSource, 526 &IOHIDOutputTransactionClass::_getAsyncEventSource, 527 &IOHIDTransactionClass::_getAsyncPort, 528 &IOHIDOutputTransactionClass::_getAsyncPort, 529 &IOHIDOutputTransactionClass::_create, 530 &IOHIDOutputTransactionClass::_dispose, 531 &IOHIDOutputTransactionClass::_addElement, 532 &IOHIDOutputTransactionClass::_removeElement, 533 &IOHIDOutputTransactionClass::_hasElement, 534 &IOHIDOutputTransactionClass::_setElementDefault, 535 &IOHIDOutputTransactionClass::_getElementDefault, 536 &IOHIDOutputTransactionClass::_setElementValue, 537 &IOHIDOutputTransactionClass::_getElementValue, 538 &IOHIDOutputTransactionClass::_commit, 539 &IOHIDOutputTransactionClass::_clear, 540}; 541 542IOReturn IOHIDOutputTransactionClass::_createAsyncEventSource(void * self, CFRunLoopSourceRef * pSource) 543 { return getThis(self)->createAsyncEventSource(pSource); } 544 545CFRunLoopSourceRef IOHIDOutputTransactionClass::_getAsyncEventSource(void *self) 546 { CFTypeRef source = NULL; getThis(self)->getAsyncEventSource(&source); return (CFRunLoopSourceRef)source;} 547 548mach_port_t IOHIDOutputTransactionClass::_getAsyncPort(void *self) 549 { mach_port_t port = MACH_PORT_NULL; getThis(self)->getAsyncPort(&port); return port; } 550 551IOReturn IOHIDOutputTransactionClass::_create(void * self) 552 { return getThis(self)->create(); } 553 554IOReturn IOHIDOutputTransactionClass::_dispose (void * self) 555 { return getThis(self)->dispose(); } 556 557IOReturn IOHIDOutputTransactionClass::_addElement (void * self, IOHIDElementCookie cookie) 558 { return getThis(self)->addElement(cookie); } 559 560IOReturn IOHIDOutputTransactionClass::_removeElement (void * self, IOHIDElementCookie cookie) 561 { return getThis(self)->removeElement(cookie); } 562 563Boolean IOHIDOutputTransactionClass::_hasElement (void * self, IOHIDElementCookie cookie) 564 { return getThis(self)->hasElement(cookie); } 565 566IOReturn IOHIDOutputTransactionClass::_setElementDefault(void * self, IOHIDElementCookie cookie, IOHIDEventStruct * pEvent) 567 { return getThis(self)->setElementValue(cookie, pEvent, kIOHIDTransactionOptionDefaultOutputValue); } 568 569IOReturn IOHIDOutputTransactionClass::_getElementDefault(void * self, IOHIDElementCookie cookie, IOHIDEventStruct * pEvent) 570 { return getThis(self)->getElementValue(cookie, pEvent, kIOHIDTransactionOptionDefaultOutputValue); } 571 572IOReturn IOHIDOutputTransactionClass::_setElementValue(void * self, IOHIDElementCookie cookie, IOHIDEventStruct * pEvent) 573 { return getThis(self)->setElementValue(cookie, pEvent); } 574 575IOReturn IOHIDOutputTransactionClass::_getElementValue(void * self, IOHIDElementCookie cookie, IOHIDEventStruct * pEvent) 576 { return getThis(self)->getElementValue(cookie, pEvent); } 577 578IOReturn IOHIDOutputTransactionClass::_commit(void * self, uint32_t timeoutMS, IOHIDCallbackFunction callback, void * callbackTarget, void * callbackRefcon) 579 { return getThis(self)->commit(timeoutMS, callback, callbackTarget, callbackRefcon);} 580 581IOReturn IOHIDOutputTransactionClass::_clear(void * self) 582 { return getThis(self)->clear();} 583 584IOHIDOutputTransactionClass::IOHIDOutputTransactionClass() : IOHIDTransactionClass() 585{ 586 fHIDTransaction.pseudoVTable = (IUnknownVTbl *) &sHIDOutputTransactionInterface; 587 fHIDTransaction.obj = this; 588 589 fCallback = NULL; 590 fTarget = NULL; 591 fRefcon = NULL; 592} 593 594IOHIDOutputTransactionClass::~IOHIDOutputTransactionClass() 595{ 596} 597 598HRESULT IOHIDOutputTransactionClass::queryInterface(REFIID iid, void ** ppv) 599{ 600 CFUUIDRef uuid = CFUUIDCreateFromUUIDBytes(NULL, iid); 601 HRESULT res = S_OK; 602 603 if (CFEqual(uuid, kIOHIDOutputTransactionInterfaceID)) 604 { 605 *ppv = getInterfaceMap(); 606 addRef(); 607 } 608 else { 609 res = fOwningDevice->queryInterface(iid, ppv); 610 } 611 612 if (!*ppv) 613 res = E_NOINTERFACE; 614 615 CFRelease(uuid); 616 return res; 617} 618 619IOReturn IOHIDOutputTransactionClass::createAsyncEventSource(CFRunLoopSourceRef * pSource) 620{ 621 IOReturn ret = IOHIDTransactionClass::getAsyncEventSource((CFTypeRef *)pSource); 622 623 if ( ret == kIOReturnSuccess && pSource && *pSource ) 624 CFRetain(*pSource); 625 626 return ret; 627} 628 629IOReturn IOHIDOutputTransactionClass::create () 630{ 631 fDirection = kIOHIDTransactionDirectionTypeOutput; 632 633 return IOHIDTransactionClass::create(); 634} 635 636IOReturn IOHIDOutputTransactionClass::addElement (IOHIDElementCookie cookie) 637{ 638 IOHIDElementRef element = fOwningDevice->getElement(cookie); 639 640 return IOHIDTransactionClass::addElement(element); 641} 642 643IOReturn 644IOHIDOutputTransactionClass::addElement(IOHIDElementRef element, 645 IOOptionBits options) 646{ 647 return IOHIDTransactionClass::addElement(element, options); 648} 649 650IOReturn IOHIDOutputTransactionClass::removeElement (IOHIDElementCookie cookie) 651{ 652 IOHIDElementRef element = fOwningDevice->getElement(cookie); 653 654 return IOHIDTransactionClass::removeElement(element); 655} 656 657IOReturn 658IOHIDOutputTransactionClass::removeElement(IOHIDElementRef element, 659 IOOptionBits options) 660{ 661 return IOHIDTransactionClass::removeElement(element, options); 662} 663 664Boolean IOHIDOutputTransactionClass::hasElement (IOHIDElementCookie cookie) 665{ 666 IOHIDElementRef element = fOwningDevice->getElement(cookie); 667 Boolean value = FALSE; 668 669 return (IOHIDTransactionClass::hasElement(element, &value) == kIOReturnSuccess) ? value : FALSE; 670} 671 672IOReturn 673IOHIDOutputTransactionClass::hasElement(IOHIDElementRef element, 674 Boolean * pValue, 675 IOOptionBits options) 676{ 677 return IOHIDTransactionClass::hasElement(element, pValue, options); 678} 679 680/* set the value for that element */ 681IOReturn 682IOHIDOutputTransactionClass::setElementValue(IOHIDElementCookie cookie, 683 IOHIDEventStruct * pEvent, 684 IOOptionBits options) 685{ 686 IOHIDValueRef event; 687 IOHIDElementRef element; 688 IOReturn ret; 689 690 if ( !pEvent ) 691 return kIOReturnBadArgument; 692 693 element = fOwningDevice->getElement(cookie); 694 event = _IOHIDValueCreateWithStruct(kCFAllocatorDefault, element, pEvent); 695 696 ret = IOHIDTransactionClass::setElementValue(element, event, options); 697 698 CFRelease(event); 699 700 return ret; 701} 702 703IOReturn 704IOHIDOutputTransactionClass::setElementValue(IOHIDElementRef element, 705 IOHIDValueRef event, 706 IOOptionBits options) 707{ 708 return IOHIDTransactionClass::setElementValue(element, event, options); 709} 710 711/* get the value for that element */ 712IOReturn 713IOHIDOutputTransactionClass::getElementValue(IOHIDElementCookie cookie, 714 IOHIDEventStruct * pEvent, 715 IOOptionBits options) 716{ 717 IOHIDValueRef event; 718 IOReturn ret; 719 720 if ( !pEvent ) 721 return kIOReturnBadArgument; 722 723 ret = IOHIDTransactionClass::getElementValue(fOwningDevice->getElement(cookie), &event, options); 724 725 if ((ret==kIOReturnSuccess) && event) 726 { 727 uint32_t length = _IOHIDElementGetLength(IOHIDValueGetElement(event));; 728 729 pEvent->type = IOHIDElementGetType(IOHIDValueGetElement(event)); 730 pEvent->elementCookie = cookie; 731 *(UInt64 *)&pEvent->timestamp = IOHIDValueGetTimeStamp(event); 732 733 if ( length > sizeof(uint32_t) ) 734 { 735 pEvent->longValueSize = length; 736 pEvent->longValue = (void *)IOHIDValueGetBytePtr(event); 737 } 738 else 739 { 740 pEvent->longValueSize = 0; 741 pEvent->longValue = NULL; 742 pEvent->value = IOHIDValueGetIntegerValue(event); 743 } 744 } 745 746 return ret; 747} 748 749IOReturn 750IOHIDOutputTransactionClass::getElementValue(IOHIDElementRef element, 751 IOHIDValueRef * pEvent, IOOptionBits options) 752{ 753 return IOHIDTransactionClass::getElementValue(element, pEvent, options); 754} 755 756IOReturn IOHIDOutputTransactionClass::commit(uint32_t timeoutMS, IOHIDCallbackFunction callback, void * target, void * refcon) 757{ 758 fCallback = callback; 759 fTarget = target; 760 fRefcon = refcon; 761 762 return IOHIDTransactionClass::commit(timeoutMS, IOHIDOutputTransactionClass::_commitCallback, this); 763} 764 765IOReturn 766IOHIDOutputTransactionClass::commit(uint32_t timeoutMS, 767 IOHIDCallback callback, 768 void * callbackRefcon, 769 IOOptionBits options) 770{ 771 return IOHIDTransactionClass::commit(timeoutMS, callback, callbackRefcon, options); 772} 773 774void IOHIDOutputTransactionClass::_commitCallback(void * context, IOReturn result __unused, void * sender){ 775 776 IOHIDOutputTransactionClass *transaction = (IOHIDOutputTransactionClass *)context; 777 778 if ( transaction && transaction->fCallback) 779 { 780 (transaction->fCallback)(transaction->fTarget, kIOReturnSuccess, transaction->fRefcon, sender); 781 } 782} 783