1/* 2 * Copyright (c) 1999-2008 Apple Computer, Inc. All Rights Reserved. 3 * 4 * @APPLE_LICENSE_HEADER_START@ 5 * 6 * This file contains Original Code and/or Modifications of Original Code 7 * as defined in and that are subject to the Apple Public Source License 8 * Version 2.0 (the 'License'). You may not use this file except in 9 * compliance with the License. Please obtain a copy of the License at 10 * http://www.opensource.apple.com/apsl/ and read it before using this 11 * file. 12 * 13 * The Original Code and all software distributed under the License are 14 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER 15 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, 16 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, 17 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. 18 * Please see the License for the specific language governing rights and 19 * limitations under the License. 20 * 21 * @APPLE_LICENSE_HEADER_END@ 22 */ 23 24#include <pthread.h> 25#include <CoreFoundation/CFRuntime.h> 26#include <CoreFoundation/CFArray.h> 27#include <IOKit/hid/IOHIDElement.h> 28#include <IOKit/hid/IOHIDLibUserClient.h> 29#include <IOKit/hid/IOHIDPrivateKeys.h> 30#include <IOKit/hid/IOHIDDevicePlugIn.h> 31#include <IOKit/hid/IOHIDLibPrivate.h> 32#include "IOHIDManagerPersistentProperties.h" 33 34static IOHIDElementRef __IOHIDElementCreate( 35 CFAllocatorRef allocator, 36 CFAllocatorContext * context); 37static Boolean __IOHIDElementEqual( 38 CFTypeRef cf1, 39 CFTypeRef cf2); 40static CFHashCode __IOHIDElementHash(CFTypeRef cf); 41static void __IOHIDElementRelease( 42 CFTypeRef object ); 43static IOHIDElementStruct * __IOHIDElementGetElementStruct( 44 IOHIDElementRef element); 45static void _IOHIDElementAttach( 46 IOHIDElementRef element, 47 IOHIDElementRef toAttach, 48 Boolean propagate); 49static void _IOHIDElementDetach( 50 IOHIDElementRef element, 51 IOHIDElementRef toAttach, 52 Boolean propagate); 53static void __IOHIDElementApplyCalibration( 54 IOHIDElementRef element); 55 56typedef struct __IOHIDElement 57{ 58 CFRuntimeBase cfBase; // base CFType information 59 60 IOHIDDeviceDeviceInterface** deviceInterface; 61 IOHIDDeviceRef device; 62 IOHIDValueRef value; 63 64 IOHIDElementStruct * elementStructPtr; 65 uint32_t index; 66 CFDataRef data; 67 CFMutableArrayRef attachedElements; 68 CFArrayRef childElements; 69 IOHIDElementRef parentElement; 70 IOHIDElementRef originalElement; 71 IOHIDCalibrationInfo * calibrationPtr; 72 CFMutableDictionaryRef properties; 73 CFStringRef rootKey; 74 Boolean isDirty; 75} __IOHIDElement, *__IOHIDElementRef; 76 77static const CFRuntimeClass __IOHIDElementClass = { 78 0, // version 79 "IOHIDElement", // className 80 NULL, // init 81 NULL, // copy 82 __IOHIDElementRelease, // finalize 83 __IOHIDElementEqual, // equal 84 __IOHIDElementHash, // hash 85 NULL, // copyFormattingDesc 86 NULL, 87 NULL, 88 NULL 89}; 90 91static pthread_once_t __elementTypeInit = PTHREAD_ONCE_INIT; 92static CFTypeID __elementTypeID = _kCFRuntimeNotATypeID; 93static CFStringRef __KIOHIDElementSpecialKeys[] = { 94 CFSTR(kIOHIDElementCalibrationMinKey), 95 CFSTR(kIOHIDElementCalibrationMaxKey), 96 CFSTR(kIOHIDElementCalibrationSaturationMinKey), 97 CFSTR(kIOHIDElementCalibrationSaturationMaxKey), 98 CFSTR(kIOHIDElementCalibrationMaxKey), 99 CFSTR(kIOHIDElementCalibrationMaxKey), 100 CFSTR(kIOHIDElementCalibrationMaxKey), 101 NULL 102}; 103 104 105 106//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 107// __IOHIDElementRegister 108//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 109void __IOHIDElementRegister(void) 110{ 111 __elementTypeID = _CFRuntimeRegisterClass(&__IOHIDElementClass); 112} 113 114//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 115// __IOHIDElementCreate 116//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 117IOHIDElementRef __IOHIDElementCreate( 118 CFAllocatorRef allocator, 119 CFAllocatorContext * context __unused) 120{ 121 IOHIDElementRef element = NULL; 122 void * offset = NULL; 123 uint32_t size; 124 125 /* allocate session */ 126 size = sizeof(__IOHIDElement) - sizeof(CFRuntimeBase); 127 element = (IOHIDElementRef)_CFRuntimeCreateInstance(allocator, IOHIDElementGetTypeID(), size, NULL); 128 129 if (!element) 130 return NULL; 131 132 offset = element; 133 bzero(offset + sizeof(CFRuntimeBase), size); 134 135 return element; 136} 137 138//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 139// __IOHIDElementRelease 140//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 141void __IOHIDElementRelease( CFTypeRef object ) 142{ 143 IOHIDElementRef element = ( IOHIDElementRef ) object; 144 145 CFRELEASE_IF_NOT_NULL(element->attachedElements); 146 CFRELEASE_IF_NOT_NULL(element->childElements); 147 CFRELEASE_IF_NOT_NULL(element->parentElement); 148 CFRELEASE_IF_NOT_NULL(element->data); 149 CFRELEASE_IF_NOT_NULL(element->originalElement); 150 CFRELEASE_IF_NOT_NULL(element->properties); 151 CFRELEASE_IF_NOT_NULL(element->rootKey); 152 153 if (element->calibrationPtr) free(element->calibrationPtr); 154 element->calibrationPtr = NULL; 155} 156 157//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 158// __IOHIDElementEqual 159//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 160Boolean __IOHIDElementEqual(CFTypeRef cf1, CFTypeRef cf2) 161{ 162 if ((CFGetTypeID(cf1) != IOHIDElementGetTypeID()) || 163 (CFGetTypeID(cf2) != IOHIDElementGetTypeID()) || 164 (IOHIDElementGetCookie((IOHIDElementRef)cf1) != IOHIDElementGetCookie((IOHIDElementRef)cf2))) 165 return FALSE; 166 167 return TRUE; 168} 169 170//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 171// __IOHIDElementHash 172//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 173CFHashCode __IOHIDElementHash(CFTypeRef cf) 174{ 175 if (CFGetTypeID(cf) == IOHIDElementGetTypeID()) 176 return (CFHashCode)IOHIDElementGetCookie((IOHIDElementRef)cf); 177 178 return 0; 179} 180 181//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 182// __IOHIDElementGetElementStruct 183//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 184IOHIDElementStruct * __IOHIDElementGetElementStruct(IOHIDElementRef element) 185{ 186 return element->elementStructPtr; 187} 188 189//------------------------------------------------------------------------------ 190// IOHIDElementGetTypeID 191//------------------------------------------------------------------------------ 192CFTypeID IOHIDElementGetTypeID(void) 193{ 194 /* initialize runtime */ 195 if ( __elementTypeID == _kCFRuntimeNotATypeID ) 196 pthread_once(&__elementTypeInit, __IOHIDElementRegister); 197 198 return __elementTypeID; 199} 200 201//------------------------------------------------------------------------------ 202// _IOHIDElementCreateWithParentAndData 203//------------------------------------------------------------------------------ 204IOHIDElementRef _IOHIDElementCreateWithParentAndData( 205 CFAllocatorRef allocator, 206 IOHIDElementRef parent, 207 CFDataRef data, 208 IOHIDElementStruct * elementStruct, 209 uint32_t index) 210{ 211 IOHIDElementRef element = NULL; 212 213 if (!elementStruct) 214 return NULL; 215 216 element = __IOHIDElementCreate(allocator, NULL); 217 218 if (!element) 219 return NULL; 220 221 element->data = (CFDataRef)CFRetain(data); 222 element->elementStructPtr = elementStruct; 223 element->index = index; 224 element->parentElement = (parent) ? (IOHIDElementRef)CFRetain(parent) : 0; 225 226 return element; 227} 228 229//------------------------------------------------------------------------------ 230// _IOHIDElementCreateWithElement 231//------------------------------------------------------------------------------ 232IOHIDElementRef _IOHIDElementCreateWithElement( 233 CFAllocatorRef allocator, 234 IOHIDElementRef original, 235 uint32_t usagePage, 236 uint32_t usage) 237{ 238 IOHIDElementRef element = NULL; 239 240 if ( !original ) 241 return NULL; 242 243 element = __IOHIDElementCreate(allocator, NULL); 244 245 if (!element) 246 return NULL; 247 248 element->index = 0; 249 element->originalElement = (IOHIDElementRef)CFRetain(original); 250 251 // Unlike normal IOHIDElements, this element does not reference IOHIDDeviceClass memory 252 element->data = CFDataCreateMutable(allocator, sizeof(IOHIDElementStruct)); 253 element->elementStructPtr = (IOHIDElementStruct *)CFDataGetMutableBytePtr((CFMutableDataRef)element->data); 254 255 bcopy(__IOHIDElementGetElementStruct(original), element->elementStructPtr, sizeof(IOHIDElementStruct)); 256 257 // To denote a mapped virual element, a simple approach would be to use 258 // the negative cookie value of the original 259 intptr_t cookie = (intptr_t)IOHIDElementGetCookie(original); 260 element->elementStructPtr->cookieMin = -cookie; 261 element->elementStructPtr->cookieMax = -cookie; 262 263 element->elementStructPtr->usagePage = usagePage; 264 element->elementStructPtr->usageMin = usage; 265 element->elementStructPtr->usageMax = usage; 266 element->elementStructPtr->duplicateIndex = 0; 267 element->elementStructPtr->duplicateValueSize = 0; 268 269 return element; 270} 271 272//------------------------------------------------------------------------------ 273// _IOHIDElementSetDevice 274//------------------------------------------------------------------------------ 275void _IOHIDElementSetDevice(IOHIDElementRef element, IOHIDDeviceRef device) 276{ 277 element->device = device; 278} 279 280//------------------------------------------------------------------------------ 281// _IOHIDElementSetDeviceInterface 282//------------------------------------------------------------------------------ 283void _IOHIDElementSetDeviceInterface(IOHIDElementRef element, IOHIDDeviceDeviceInterface ** interface) 284{ 285 element->deviceInterface = interface; 286} 287 288//------------------------------------------------------------------------------ 289// _IOHIDElementGetLength 290//------------------------------------------------------------------------------ 291CFIndex _IOHIDElementGetLength(IOHIDElementRef element) 292{ 293 CFIndex bits = element->elementStructPtr->size; 294 295 if ( element->elementStructPtr->duplicateValueSize && (element->index != 0)) 296 bits = element->elementStructPtr->reportSize; 297 298 return (bits + 7) / 8; 299} 300 301//------------------------------------------------------------------------------ 302// IOHIDElementGetCookie 303//------------------------------------------------------------------------------ 304IOHIDElementCookie IOHIDElementGetCookie(IOHIDElementRef element) 305{ 306 return (IOHIDElementCookie) 307 (element->elementStructPtr->cookieMin + element->index); 308} 309 310//------------------------------------------------------------------------------ 311// IOHIDElementGetType 312//------------------------------------------------------------------------------ 313IOHIDElementType IOHIDElementGetType(IOHIDElementRef element) 314{ 315 return element->elementStructPtr->type; 316} 317 318//------------------------------------------------------------------------------ 319// IOHIDElementCreateWithDictionary 320//------------------------------------------------------------------------------ 321IOHIDElementRef IOHIDElementCreateWithDictionary( 322 CFAllocatorRef allocator, 323 CFDictionaryRef dictionary) 324{ 325 IOHIDElementRef element = NULL; 326 327 if ( !dictionary ) 328 return NULL; 329 330 element = __IOHIDElementCreate(allocator, NULL); 331 332 if (!element) 333 return NULL; 334 335 element->index = 0; 336 337 // Unlike normal IOHIDElements, this element 338 // does not reference IOHIDDeviceClass memory 339 element->data = CFDataCreateMutable( allocator, sizeof(IOHIDElementStruct)); 340 341 if ( !element->data ) { 342 CFRelease(element); 343 return NULL; 344 } 345 346 element->elementStructPtr = (IOHIDElementStruct *)CFDataGetMutableBytePtr( 347 (CFMutableDataRef)element->data); 348 349 // fill in element->elementStructPtr 350 351 return element; 352} 353 354 355//------------------------------------------------------------------------------ 356// IOHIDElementGetCollectionType 357//------------------------------------------------------------------------------ 358IOHIDElementCollectionType IOHIDElementGetCollectionType(IOHIDElementRef element) 359{ 360 return element->elementStructPtr->collectionType; 361} 362 363//------------------------------------------------------------------------------ 364// IOHIDElementGetUsagePage 365//------------------------------------------------------------------------------ 366uint32_t IOHIDElementGetUsagePage(IOHIDElementRef element) 367{ 368 return element->elementStructPtr->usagePage; 369} 370 371//------------------------------------------------------------------------------ 372// IOHIDElementGetUsagePage 373//------------------------------------------------------------------------------ 374uint32_t IOHIDElementGetUsage(IOHIDElementRef element) 375{ 376 return element->elementStructPtr->usageMin + ((element->elementStructPtr->usageMin != element->elementStructPtr->usageMax) ? element->index : 0); 377} 378 379//------------------------------------------------------------------------------ 380// _IOHIDElementGetFlags 381//------------------------------------------------------------------------------ 382uint32_t _IOHIDElementGetFlags(IOHIDElementRef element) 383{ 384 return element->elementStructPtr->flags; 385} 386 387Boolean IOHIDElementIsVirtual(IOHIDElementRef element) 388{ 389 return ( element->originalElement != NULL ); 390} 391 392//------------------------------------------------------------------------------ 393// IOHIDElementIsRelative 394//------------------------------------------------------------------------------ 395Boolean IOHIDElementIsRelative(IOHIDElementRef element) 396{ 397 return ((element->elementStructPtr->flags & kIOHIDElementFlagsRelativeMask) != 0); 398} 399 400//------------------------------------------------------------------------------ 401// IOHIDElementIsWrapping 402//------------------------------------------------------------------------------ 403Boolean IOHIDElementIsWrapping(IOHIDElementRef element) 404{ 405 return ((element->elementStructPtr->flags & kIOHIDElementFlagsWrapMask) != 0); 406} 407 408//------------------------------------------------------------------------------ 409// IOHIDElementIsArray 410//------------------------------------------------------------------------------ 411Boolean IOHIDElementIsArray(IOHIDElementRef element) 412{ 413 return ((element->elementStructPtr->flags & kIOHIDElementFlagsVariableMask) == 0); 414} 415 416//------------------------------------------------------------------------------ 417// IOHIDElementIsNonLinear 418//------------------------------------------------------------------------------ 419Boolean IOHIDElementIsNonLinear(IOHIDElementRef element) 420{ 421 return ((element->elementStructPtr->flags & kIOHIDElementFlagsNonLinearMask) != 0); 422} 423 424//------------------------------------------------------------------------------ 425// IOHIDElementHasPreferredState 426//------------------------------------------------------------------------------ 427Boolean IOHIDElementHasPreferredState(IOHIDElementRef element) 428{ 429 return ((element->elementStructPtr->flags & kIOHIDElementFlagsNoPreferredMask) == 0); 430} 431 432//------------------------------------------------------------------------------ 433// IOHIDElementHasNullState 434//------------------------------------------------------------------------------ 435Boolean IOHIDElementHasNullState(IOHIDElementRef element) 436{ 437 return (element->elementStructPtr->flags & kIOHIDElementFlagsNullStateMask); 438} 439 440//------------------------------------------------------------------------------ 441// IOHIDElementGetName 442//------------------------------------------------------------------------------ 443CFStringRef IOHIDElementGetName(IOHIDElementRef element) 444{ 445 CFTypeRef type = IOHIDElementGetProperty( element, 446 CFSTR(kIOHIDElementNameKey)); 447 448 return (type && (CFGetTypeID(type) == CFStringGetTypeID())) ? 449 (CFStringRef)type : NULL; 450} 451 452//------------------------------------------------------------------------------ 453// IOHIDElementGetReportID 454//------------------------------------------------------------------------------ 455uint32_t IOHIDElementGetReportID(IOHIDElementRef element) 456{ 457 return element->elementStructPtr->reportID; 458} 459 460//------------------------------------------------------------------------------ 461// IOHIDElementGetReportSize 462//------------------------------------------------------------------------------ 463uint32_t IOHIDElementGetReportSize(IOHIDElementRef element) 464{ 465 return element->elementStructPtr->reportSize; 466} 467 468//------------------------------------------------------------------------------ 469// IOHIDElementGetReportCount 470//------------------------------------------------------------------------------ 471uint32_t IOHIDElementGetReportCount(IOHIDElementRef element) 472{ 473 uint32_t reportCount = element->elementStructPtr->reportCount; 474 475 if ( element->elementStructPtr->duplicateValueSize && (element->index != 0)) 476 reportCount = 1; 477 478 return reportCount; 479} 480 481//------------------------------------------------------------------------------ 482// IOHIDElementGetUnit 483//------------------------------------------------------------------------------ 484uint32_t IOHIDElementGetUnit(IOHIDElementRef element) 485{ 486 return element->elementStructPtr->unit; 487} 488 489//------------------------------------------------------------------------------ 490// IOHIDElementGetUnitExponent 491//------------------------------------------------------------------------------ 492uint32_t IOHIDElementGetUnitExponent(IOHIDElementRef element) 493{ 494 return element->elementStructPtr->unitExponent; 495} 496 497//------------------------------------------------------------------------------ 498// IOHIDElementGetLogicalMin 499//------------------------------------------------------------------------------ 500CFIndex IOHIDElementGetLogicalMin(IOHIDElementRef element) 501{ 502 return element->elementStructPtr->min; 503} 504 505//------------------------------------------------------------------------------ 506// IOHIDElementGetLogicalMax 507//------------------------------------------------------------------------------ 508CFIndex IOHIDElementGetLogicalMax(IOHIDElementRef element) 509{ 510 return element->elementStructPtr->max; 511} 512 513//------------------------------------------------------------------------------ 514// IOHIDElementGetPhysicalMin 515//------------------------------------------------------------------------------ 516CFIndex IOHIDElementGetPhysicalMin(IOHIDElementRef element) 517{ 518 return element->elementStructPtr->scaledMin; 519} 520 521//------------------------------------------------------------------------------ 522// IOHIDElementGetPhysicalMax 523//------------------------------------------------------------------------------ 524CFIndex IOHIDElementGetPhysicalMax(IOHIDElementRef element) 525{ 526 return element->elementStructPtr->scaledMax; 527} 528 529//------------------------------------------------------------------------------ 530// IOHIDElementGetDuplicateIndex 531//------------------------------------------------------------------------------ 532uint32_t IOHIDElementGetDuplicateIndex(IOHIDElementRef element) 533{ 534 uint32_t dupIndex = 0; 535 536 if ( element->elementStructPtr->duplicateValueSize && (element->index != 0)) 537 dupIndex = element->index - 1; 538 539 return dupIndex; 540} 541 542//------------------------------------------------------------------------------ 543// IOHIDElementGetDevice 544//------------------------------------------------------------------------------ 545IOHIDDeviceRef IOHIDElementGetDevice(IOHIDElementRef element) 546{ 547 return element->device; 548} 549 550//------------------------------------------------------------------------------ 551// IOHIDElementGetParent 552//------------------------------------------------------------------------------ 553IOHIDElementRef IOHIDElementGetParent(IOHIDElementRef element) 554{ 555 if (!element->parentElement && element->deviceInterface) { 556 CFMutableDictionaryRef matchingDict; 557 CFArrayRef elementArray; 558 559 matchingDict = CFDictionaryCreateMutable( 560 CFGetAllocator(element), 561 1, 562 &kCFTypeDictionaryKeyCallBacks, 563 &kCFTypeDictionaryValueCallBacks); 564 565 if ( matchingDict ) { 566 uint32_t cookie = (uint32_t)element->elementStructPtr->parentCookie; 567 CFNumberRef cookieNumber = CFNumberCreate( 568 CFGetAllocator(element), 569 kCFNumberIntType, 570 &cookie); 571 572 CFDictionarySetValue( matchingDict, 573 CFSTR(kIOHIDElementCookieKey), 574 cookieNumber); 575 CFRelease(cookieNumber); 576 577 (*(element->deviceInterface))->copyMatchingElements( 578 element->deviceInterface, 579 matchingDict, 580 &elementArray, 581 0); 582 583 if (elementArray) { 584 element->parentElement = (IOHIDElementRef)CFRetain( 585 CFArrayGetValueAtIndex(elementArray, 0)); 586 CFRelease(elementArray); 587 } 588 589 CFRelease(matchingDict); 590 } 591 } 592 593 return element->parentElement; 594} 595 596//------------------------------------------------------------------------------ 597// IOHIDElementGetChildren 598//------------------------------------------------------------------------------ 599CFArrayRef IOHIDElementGetChildren(IOHIDElementRef element) 600{ 601 CFArrayRef childrenArray = NULL; 602 603 if (!element->childElements && element->deviceInterface) { 604 CFMutableDictionaryRef matchingDict; 605 606 matchingDict = CFDictionaryCreateMutable( 607 CFGetAllocator(element), 608 1, 609 &kCFTypeDictionaryKeyCallBacks, 610 &kCFTypeDictionaryValueCallBacks); 611 612 if ( matchingDict ) { 613 uint32_t cookie = (uint32_t)IOHIDElementGetCookie(element); 614 615 CFNumberRef cookieNumber = CFNumberCreate( 616 CFGetAllocator(element), 617 kCFNumberIntType, &cookie); 618 619 CFDictionarySetValue( matchingDict, 620 CFSTR(kIOHIDElementCollectionCookieKey), 621 cookieNumber); 622 623 CFRelease(cookieNumber); 624 625 (*(element->deviceInterface))->copyMatchingElements( 626 element->deviceInterface, 627 matchingDict, &childrenArray, 0); 628 629 if (childrenArray) 630 element->childElements = childrenArray; 631 632 CFRelease(matchingDict); 633 } 634 } else 635 childrenArray = element->childElements; 636 637 return childrenArray; 638} 639 640//------------------------------------------------------------------------------ 641// IOHIDElementAttach 642//------------------------------------------------------------------------------ 643void IOHIDElementAttach(IOHIDElementRef element, IOHIDElementRef toAttach) 644{ 645 _IOHIDElementAttach(element, toAttach, TRUE); 646} 647 648//------------------------------------------------------------------------------ 649// IOHIDElementDetach 650//------------------------------------------------------------------------------ 651void IOHIDElementDetach(IOHIDElementRef element, IOHIDElementRef toDetach) 652{ 653 _IOHIDElementDetach(element, toDetach, TRUE); 654} 655 656//------------------------------------------------------------------------------ 657// _IOHIDElementAttach 658//------------------------------------------------------------------------------ 659void _IOHIDElementAttach(IOHIDElementRef element, IOHIDElementRef toAttach, Boolean propagate) 660{ 661 if ( !element->attachedElements ) 662 element->attachedElements = CFArrayCreateMutable( 663 CFGetAllocator(element), 664 0, 665 &kCFTypeArrayCallBacks); 666 667 if ( !element->attachedElements ) 668 return; 669 670 CFIndex index = CFArrayGetFirstIndexOfValue( 671 element->attachedElements, 672 CFRangeMake(0, CFArrayGetCount(element->attachedElements)), 673 toAttach); 674 675 if ( index != kCFNotFound ) 676 return; 677 678 CFArrayAppendValue(element->attachedElements, toAttach); 679 680 if ( propagate ) 681 _IOHIDElementAttach(toAttach, element, FALSE); 682} 683 684//------------------------------------------------------------------------------ 685// _IOHIDElementDetach 686//------------------------------------------------------------------------------ 687void _IOHIDElementDetach(IOHIDElementRef element, IOHIDElementRef toDetach, Boolean propagate) 688{ 689 if ( !element->attachedElements ) 690 return; 691 692 CFIndex index = CFArrayGetFirstIndexOfValue( 693 element->attachedElements, 694 CFRangeMake(0, CFArrayGetCount(element->attachedElements)), 695 toDetach); 696 697 if ( index == kCFNotFound ) 698 return; 699 700 CFArrayRemoveValueAtIndex(element->attachedElements, index); 701 702 if ( propagate ) 703 _IOHIDElementDetach(toDetach, element, FALSE); 704} 705 706//------------------------------------------------------------------------------ 707// IOHIDElementCopyAttached 708//------------------------------------------------------------------------------ 709CFArrayRef IOHIDElementCopyAttached(IOHIDElementRef element) 710{ 711 return element->attachedElements ? 712 CFArrayCreateCopy(CFGetAllocator(element), element->attachedElements) : 713 NULL; 714} 715 716 717//------------------------------------------------------------------------------ 718// _IOHIDElementGetValue 719//------------------------------------------------------------------------------ 720IOHIDValueRef _IOHIDElementGetValue(IOHIDElementRef element) 721{ 722 return element->value; 723} 724 725//------------------------------------------------------------------------------ 726// _IOHIDElementSetValue 727//------------------------------------------------------------------------------ 728void _IOHIDElementSetValue(IOHIDElementRef element, IOHIDValueRef value) 729{ 730 if (element->value) 731 CFRelease(element->value); 732 733 element->value = value ? (IOHIDValueRef)CFRetain(value) : NULL; 734} 735 736//------------------------------------------------------------------------------ 737// _IOHIDElementGetCalibrationInfo 738//------------------------------------------------------------------------------ 739IOHIDCalibrationInfo * _IOHIDElementGetCalibrationInfo(IOHIDElementRef element) 740{ 741 return element->calibrationPtr; 742} 743 744//------------------------------------------------------------------------------ 745// IOHIDElementGetProperty 746//------------------------------------------------------------------------------ 747CFTypeRef IOHIDElementGetProperty(IOHIDElementRef element, CFStringRef key) 748{ 749 if ( !element->properties ) 750 return NULL; 751 752 return CFDictionaryGetValue(element->properties, key); 753} 754 755//------------------------------------------------------------------------------ 756// IOHIDElementSetProperty 757//------------------------------------------------------------------------------ 758CF_EXPORT 759Boolean IOHIDElementSetProperty( IOHIDElementRef element, 760 CFStringRef key, 761 CFTypeRef property) 762{ 763 if ( !element->properties ) { 764 element->properties = CFDictionaryCreateMutable(CFGetAllocator(element), 765 0, 766 &kCFTypeDictionaryKeyCallBacks, 767 &kCFTypeDictionaryValueCallBacks); 768 769 if ( !element->properties ) 770 return FALSE; 771 } 772 773 boolean_t isCalMin = FALSE; 774 boolean_t isCalMax = FALSE; 775 boolean_t isSatMin = FALSE; 776 boolean_t isSatMax = FALSE; 777 boolean_t isDZMin = FALSE; 778 boolean_t isDZMax = FALSE; 779 boolean_t isGran = FALSE; 780 781 element->isDirty = TRUE; 782 783 if ((CFGetTypeID(property) == CFNumberGetTypeID()) && ( 784 (isCalMin = CFEqual(key, CFSTR(kIOHIDElementCalibrationMinKey))) || 785 (isCalMax = CFEqual(key, CFSTR(kIOHIDElementCalibrationMaxKey))) || 786 (isSatMin = CFEqual(key, CFSTR(kIOHIDElementCalibrationSaturationMinKey))) || 787 (isSatMax = CFEqual(key, CFSTR(kIOHIDElementCalibrationSaturationMaxKey))) || 788 (isDZMin = CFEqual(key, CFSTR(kIOHIDElementCalibrationDeadZoneMinKey))) || 789 (isDZMax = CFEqual(key, CFSTR(kIOHIDElementCalibrationDeadZoneMaxKey))) || 790 (isGran = CFEqual(key, CFSTR(kIOHIDElementCalibrationGranularityKey))))) { 791 792 if ( !element->calibrationPtr ) { 793 element->calibrationPtr = 794 (IOHIDCalibrationInfo *)malloc(sizeof(IOHIDCalibrationInfo)); 795 796 bzero(element->calibrationPtr, sizeof(IOHIDCalibrationInfo)); 797 } 798 799 if ( element->calibrationPtr ) { 800 801 CFIndex value = 0; 802 CFNumberGetValue(property, kCFNumberCFIndexType, &value); 803 804 if ( isCalMin ) 805 element->calibrationPtr->min = value; 806 else if ( isCalMax ) 807 element->calibrationPtr->max = value; 808 else if ( isSatMin ) 809 element->calibrationPtr->satMin = value; 810 else if ( isSatMax ) 811 element->calibrationPtr->satMax = value; 812 else if ( isDZMin ) 813 element->calibrationPtr->dzMin = value; 814 else if ( isDZMax ) 815 element->calibrationPtr->dzMax = value; 816 else if ( isGran ) 817 CFNumberGetValue(property, kCFNumberFloat64Type, &element->calibrationPtr->gran); 818 } 819 820 } 821 822 CFDictionarySetValue(element->properties, key, property); 823 824 return TRUE; 825} 826 827//------------------------------------------------------------------------------ 828CFStringRef __IOHIDElementGetRootKey(IOHIDElementRef element) 829{ 830 if (!element->rootKey) { 831 // Device Root Key 832 // All *required* matching information 833 CFStringRef device = __IOHIDDeviceGetUUIDKey(element->device); 834 long int usagePage = (long int)IOHIDElementGetUsagePage(element); 835 long int usage = (long int)IOHIDElementGetUsage(element); 836 long int cookie = (long int)IOHIDElementGetCookie(element); 837 long int type = (long int)IOHIDElementGetType(element); 838 839 element->rootKey = CFStringCreateWithFormat(NULL, NULL, 840 CFSTR("%@#%04lx#%04lx#%016lx#%ld"), 841 device, 842 usagePage, 843 usage, 844 cookie, 845 type); 846 } 847 848 return element->rootKey; 849} 850 851//------------------------------------------------------------------------------ 852void __IOHIDElementSaveProperties(IOHIDElementRef element, __IOHIDPropertyContext *context) 853{ 854 if (element->isDirty && element->properties) { 855 __IOHIDPropertySaveToKeyWithSpecialKeys(element->properties, __IOHIDElementGetRootKey(element), __KIOHIDElementSpecialKeys, context); 856 element->isDirty = FALSE; 857 } 858} 859 860//------------------------------------------------------------------------------ 861void __IOHIDElementLoadProperties(IOHIDElementRef element) 862{ 863 CFMutableDictionaryRef properties = __IOHIDPropertyLoadFromKeyWithSpecialKeys(__IOHIDElementGetRootKey(element), __KIOHIDElementSpecialKeys); 864 865 if (properties) { 866 CFRELEASE_IF_NOT_NULL(element->properties); 867 element->properties = properties; 868 __IOHIDElementApplyCalibration(element); 869 element->isDirty = FALSE; 870 } 871} 872 873//------------------------------------------------------------------------------ 874void __IOHIDElementApplyCalibration(IOHIDElementRef element) 875{ 876 if (element->properties) { 877 CFNumberRef property; 878 879 property = CFDictionaryGetValue(element->properties, CFSTR(kIOHIDElementCalibrationMinKey)); 880 if (property && (CFGetTypeID(property) == CFNumberGetTypeID())) { 881 CFNumberGetValue(property, kCFNumberCFIndexType, &element->calibrationPtr->min); 882 } 883 884 property = CFDictionaryGetValue(element->properties, CFSTR(kIOHIDElementCalibrationMaxKey)); 885 if (property && (CFGetTypeID(property) == CFNumberGetTypeID())) { 886 CFNumberGetValue(property, kCFNumberCFIndexType, &element->calibrationPtr->max); 887 } 888 889 property = CFDictionaryGetValue(element->properties, CFSTR(kIOHIDElementCalibrationSaturationMinKey)); 890 if (property && (CFGetTypeID(property) == CFNumberGetTypeID())) { 891 CFNumberGetValue(property, kCFNumberCFIndexType, &element->calibrationPtr->satMin); 892 } 893 894 property = CFDictionaryGetValue(element->properties, CFSTR(kIOHIDElementCalibrationSaturationMaxKey)); 895 if (property && (CFGetTypeID(property) == CFNumberGetTypeID())) { 896 CFNumberGetValue(property, kCFNumberCFIndexType, &element->calibrationPtr->satMax); 897 } 898 899 property = CFDictionaryGetValue(element->properties, CFSTR(kIOHIDElementCalibrationDeadZoneMinKey)); 900 if (property && (CFGetTypeID(property) == CFNumberGetTypeID())) { 901 CFNumberGetValue(property, kCFNumberCFIndexType, &element->calibrationPtr->dzMin); 902 } 903 904 property = CFDictionaryGetValue(element->properties, CFSTR(kIOHIDElementCalibrationDeadZoneMaxKey)); 905 if (property && (CFGetTypeID(property) == CFNumberGetTypeID())) { 906 CFNumberGetValue(property, kCFNumberCFIndexType, &element->calibrationPtr->dzMax); 907 } 908 909 property = CFDictionaryGetValue(element->properties, CFSTR(kIOHIDElementCalibrationGranularityKey)); 910 if (property && (CFGetTypeID(property) == CFNumberGetTypeID())) { 911 CFNumberGetValue(property, kCFNumberFloat64Type, &element->calibrationPtr->gran); 912 } 913 } 914} 915 916//------------------------------------------------------------------------------ 917void __IOHIDSaveElementSet(const void *value, void *context) { 918 IOHIDElementRef element = (IOHIDElementRef)value; 919 if (element) 920 __IOHIDElementSaveProperties(element, (__IOHIDPropertyContext*)context); 921} 922 923//------------------------------------------------------------------------------ 924void __IOHIDLoadElementSet(const void *value, void *context __unused) { 925 IOHIDElementRef element = (IOHIDElementRef)value; 926 if (element) 927 __IOHIDElementLoadProperties(element); 928} 929 930//------------------------------------------------------------------------------ 931