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