1/* 2 * 3 * @APPLE_LICENSE_HEADER_START@ 4 * 5 * Copyright (c) 1999-2009 Apple Computer, Inc. All Rights Reserved. 6 * 7 * This file contains Original Code and/or Modifications of Original Code 8 * as defined in and that are subject to the Apple Public Source License 9 * Version 2.0 (the 'License'). You may not use this file except in 10 * compliance with the License. Please obtain a copy of the License at 11 * http://www.opensource.apple.com/apsl/ and read it before using this 12 * file. 13 * 14 * The Original Code and all software distributed under the License are 15 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER 16 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, 17 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, 18 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. 19 * Please see the License for the specific language governing rights and 20 * limitations under the License. 21 * 22 * @APPLE_LICENSE_HEADER_END@ 23 */ 24 25#include "IOHIDEventDriver.h" 26#include "IOHIDInterface.h" 27#include "IOHIDKeys.h" 28#include "IOHIDTypes.h" 29#include "AppleHIDUsageTables.h" 30#include "IOHIDPrivateKeys.h" 31#include <IOKit/hid/IOHIDUsageTables.h> 32#include <IOKit/IOLib.h> 33#include <IOKit/usb/USB.h> 34#include "IOHIDFamilyTrace.h" 35#include "IOHIDEventTypes.h" 36 37enum { 38 kMouseButtons = 0x1, 39 kMouseXAxis = 0x2, 40 kMouseYAxis = 0x4 41}; 42 43enum { 44 kBootMouse = (kMouseXAxis | kMouseYAxis | kMouseButtons) 45}; 46 47enum { 48 kBootProtocolNone = 0, 49 kBootProtocolKeyboard, 50 kBootProtocolMouse 51}; 52 53// Describes the handler(s) at each report dispatch table slot. 54// 55struct IOHIDReportHandler 56{ 57 OSArray * array[ kIOHIDReportTypeCount ]; 58}; 59 60#define kReportHandlerSlots 8 61 62#define GetReportHandlerSlot(id) \ 63 ((id) & (kReportHandlerSlots - 1)) 64 65#define GetElementArray(slot, type) \ 66 _reportHandlers[slot].array[type] 67 68#define GetReportType( type ) \ 69 ((type <= kIOHIDElementTypeInput_ScanCodes) ? kIOHIDReportTypeInput : \ 70 (type <= kIOHIDElementTypeOutput) ? kIOHIDReportTypeOutput : \ 71 (type <= kIOHIDElementTypeFeature) ? kIOHIDReportTypeFeature : -1) 72 73#define GET_AXIS_COUNT(usage) (usage-kHIDUsage_GD_X+ 1) 74#define GET_AXIS_INDEX(usage) (usage-kHIDUsage_GD_X) 75 76 77#define kDefaultAbsoluteAxisRemovalPercentage 15 78#define kDefaultButtonAbsoluteAxisRemovalPercentage 60 79 80//=========================================================================== 81// IOHIDEventDriver class 82 83#define super IOHIDEventService 84 85OSDefineMetaClassAndStructors( IOHIDEventDriver, IOHIDEventService ) 86 87#define _digitizer _reserved->digitizer 88#define _absoluteAxisRemovalPercentage _reserved->absoluteAxisRemovalPercentage 89#define _multiAxis _reserved->multiAxis 90 91 92//==================================================================================================== 93// IOHIDEventDriver::init 94//==================================================================================================== 95bool IOHIDEventDriver::init( OSDictionary * dictionary ) 96{ 97 if ( ! super::init ( dictionary ) ) 98 return false; 99 100 _reserved = IONew(ExpansionData, 1); 101 bzero(_reserved, sizeof(ExpansionData)); 102 103 _cachedRangeState = true; 104 _relativeButtonCollection = false; 105 _multipleReports = false; 106 _absoluteAxisRemovalPercentage = kDefaultAbsoluteAxisRemovalPercentage; 107 108 return true; 109} 110 111//==================================================================================================== 112// IOHIDEventDriver::free 113//==================================================================================================== 114void IOHIDEventDriver::free () 115{ 116 if ( _reportHandlers ) 117 { 118 OSArray * temp; 119 for (int i=0; i<kReportHandlerSlots; i++) 120 { 121 for (int j=0; j<kIOHIDReportTypeCount; j++) 122 { 123 temp = GetElementArray(i, j); 124 if ( temp == NULL ) continue; 125 126 temp->release(); 127 } 128 } 129 IOFree( _reportHandlers, 130 sizeof(IOHIDReportHandler) * kReportHandlerSlots ); 131 _reportHandlers = 0; 132 } 133 134 if ( _supportedElements ) 135 { 136 _supportedElements->release(); 137 _supportedElements = 0; 138 } 139 140 if (_reserved) 141 { 142 IODelete(_reserved, ExpansionData, 1); 143 _reserved = NULL; 144 } 145 146 super::free(); 147} 148 149//==================================================================================================== 150// IOHIDEventDriver::handleStart 151//==================================================================================================== 152bool IOHIDEventDriver::handleStart( IOService * provider ) 153{ 154 _interface = OSDynamicCast( IOHIDInterface, provider ); 155 156 if ( !_interface ) 157 return false; 158 159 IOService * service = this; 160 161 // Check to see if this is a product of an IOHIDDeviceShim 162 while ( NULL != (service = service->getProvider()) ) { 163 if(service->metaCast("IOHIDDeviceShim")) { 164 return false; 165 } 166 } 167 168 if (!_interface->open(this, 0, OSMemberFunctionCast(IOHIDInterface::InterruptReportAction, this, &IOHIDEventDriver::handleInterruptReport), NULL)) 169 return false; 170 171 _reportHandlers = (IOHIDReportHandler *) 172 IOMalloc( sizeof(IOHIDReportHandler) * 173 kReportHandlerSlots ); 174 if ( _reportHandlers == 0 ) 175 return false; 176 177 bzero( _reportHandlers, sizeof(IOHIDReportHandler) * kReportHandlerSlots ); 178 179 UInt32 bootProtocol = 0; 180 OSNumber * number = (OSNumber *)_interface->copyProperty("BootProtocol"); 181 182 if (number) 183 bootProtocol = number->unsigned32BitValue(); 184 185 setProperty("BootProtocol", number); 186 OSSafeReleaseNULL(number); 187 188 number = (OSNumber*)copyProperty(kIOHIDAbsoluteAxisBoundsRemovalPercentage, gIOServicePlane); 189 if ( OSDynamicCast(OSNumber, number) ) { 190 _absoluteAxisRemovalPercentage = number->unsigned32BitValue(); 191 } 192 OSSafeReleaseNULL(number); 193 194 OSArray *elements = _interface->createMatchingElements(); 195 bool result = false; 196 197 if ( elements ) { 198 if ( findElements ( elements, bootProtocol )) { 199 result = true; 200 } 201 } 202 OSSafeRelease(elements); 203 204 return result; 205} 206 207//==================================================================================================== 208// IOHIDEventDriver::getTransport 209//==================================================================================================== 210OSString * IOHIDEventDriver::getTransport () 211{ 212 return _interface ? _interface->getTransport() : (OSString *)OSSymbol::withCString("unknown:") ; 213} 214 215//==================================================================================================== 216// IOHIDEventDriver::getManufacturer 217//==================================================================================================== 218OSString * IOHIDEventDriver::getManufacturer () 219{ 220 return _interface ? _interface->getManufacturer() : (OSString *)OSSymbol::withCString("unknown:") ; 221} 222 223//==================================================================================================== 224// IOHIDEventDriver::getProduct 225//==================================================================================================== 226OSString * IOHIDEventDriver::getProduct () 227{ 228 return _interface ? _interface->getProduct() : (OSString *)OSSymbol::withCString("unknown:") ; 229} 230 231//==================================================================================================== 232// IOHIDEventDriver::getSerialNumber 233//==================================================================================================== 234OSString * IOHIDEventDriver::getSerialNumber () 235{ 236 return _interface ? _interface->getSerialNumber() : (OSString *)OSSymbol::withCString("unknown:") ; 237} 238 239//==================================================================================================== 240// IOHIDEventDriver::getLocationID 241//==================================================================================================== 242UInt32 IOHIDEventDriver::getLocationID () 243{ 244 return _interface ? _interface->getLocationID() : -1 ; 245} 246 247//==================================================================================================== 248// IOHIDEventDriver::getVendorID 249//==================================================================================================== 250UInt32 IOHIDEventDriver::getVendorID () 251{ 252 return _interface ? _interface->getVendorID() : -1 ; 253} 254 255//==================================================================================================== 256// IOHIDEventDriver::getVendorIDSource 257//==================================================================================================== 258UInt32 IOHIDEventDriver::getVendorIDSource () 259{ 260 return _interface ? _interface->getVendorIDSource() : -1 ; 261} 262 263//==================================================================================================== 264// IOHIDEventDriver::getProductID 265//==================================================================================================== 266UInt32 IOHIDEventDriver::getProductID () 267{ 268 return _interface ? _interface->getProductID() : -1 ; 269} 270 271//==================================================================================================== 272// IOHIDEventDriver::getVersion 273//==================================================================================================== 274UInt32 IOHIDEventDriver::getVersion () 275{ 276 return _interface ? _interface->getVersion() : -1 ; 277} 278 279//==================================================================================================== 280// IOHIDEventDriver::getCountryCode 281//==================================================================================================== 282UInt32 IOHIDEventDriver::getCountryCode () 283{ 284 return _interface ? _interface->getCountryCode() : -1 ; 285} 286 287 288//==================================================================================================== 289// IOHIDEventDriver::handleStop 290//==================================================================================================== 291void IOHIDEventDriver::handleStop( IOService * provider __unused ) 292{ 293 //_interface->close(this); 294} 295 296//============================================================================================= 297// IOHIDEventDriver::didTerminate 298//============================================================================================= 299bool IOHIDEventDriver::didTerminate( IOService * provider, IOOptionBits options, bool * defer ) 300{ 301 if (_interface) 302 _interface->close(this); 303 _interface = NULL; 304 305 return super::didTerminate(provider, options, defer); 306} 307 308//==================================================================================================== 309// IOHIDEventDriver::findElements 310//==================================================================================================== 311bool IOHIDEventDriver::findElements ( OSArray* elementArray, UInt32 bootProtocol) 312{ 313 UInt32 count = 0; 314 UInt32 index = 0; 315 UInt32 usage = 0; 316 UInt32 usagePage = 0; 317 bool stored = false; 318 bool pointer = false; 319 bool supportsInk = false; 320 IOHIDElement * element = NULL; 321 IOHIDElement * buttonCollection = NULL; 322 IOHIDElement * relativeCollection = NULL; 323 IOHIDElement * zAxis = NULL; 324 IOHIDElement * rzAxis = NULL; 325 OSArray * buttonArray = NULL; 326 327 if ( bootProtocol == kBootProtocolMouse ) 328 _bootSupport = kBootMouse; 329 330 if ( elementArray ) 331 { 332 _supportedElements = elementArray; 333 _supportedElements->retain(); 334 335 count = elementArray->getCount(); 336 337 for ( index = 0; index < count; index++ ) 338 { 339 bool isRelative = false; 340 UInt32 reportID = 0; 341 342 element = (IOHIDElement *) elementArray->getObject(index); 343 344 if ( element == NULL ) 345 continue; 346 347 if ( element->getType() == kIOHIDElementTypeCollection ) { 348 349 if ( usagePage == kHIDPage_Digitizer ) { 350 switch ( usage ) { 351 case kHIDUsage_Dig_TouchScreen: 352 case kHIDUsage_Dig_TouchPad: 353 case kHIDUsage_Dig_Finger: 354 _digitizer.type = kDigitizerTransducerTypeFinger; 355 break; 356 default: 357 break; 358 359 } 360 } 361 continue; 362 } 363 364 reportID = element->getReportID(); 365 366 if ( reportID > 0) 367 _multipleReports = true; 368 369 if ( element->getFlags() & kIOHIDElementFlagsRelativeMask) 370 isRelative = true; 371 372 usagePage = element->getUsagePage(); 373 usage = element->getUsage(); 374 375 if ( usagePage == kHIDPage_GenericDesktop ) 376 { 377 switch ( usage ) 378 { 379 case kHIDUsage_GD_Dial: 380 case kHIDUsage_GD_Wheel: 381 382 if ((element->getFlags() & (kIOHIDElementFlagsNoPreferredMask|kIOHIDElementFlagsRelativeMask)) == 0) { 383 calibratePreferredStateElement(element, _absoluteAxisRemovalPercentage); 384 } 385 386 stored |= storeReportElement(element); 387 pointer = true; 388 break; 389 390 case kHIDUsage_GD_X: 391 case kHIDUsage_GD_Y: 392 _bootSupport &= (usage==kHIDUsage_GD_X) ? ~kMouseXAxis : ~kMouseYAxis; 393 394 processMultiAxisElement(element, &_multiAxis.capable, &supportsInk, &relativeCollection); 395 396 if ( _multiAxis.capable ) { 397 calibratePreferredStateElement(element, _absoluteAxisRemovalPercentage); 398 399 if ( reportID > _multiAxis.sendingReportID ) 400 _multiAxis.sendingReportID = reportID; 401 402 } else if ( !isRelative ) { 403 calibrateDigitizerElement(element, _absoluteAxisRemovalPercentage); 404 } 405 406 stored |= storeReportElement ( element ); 407 pointer = true; 408 break; 409 410 case kHIDUsage_GD_Z: 411 processMultiAxisElement(element, &_multiAxis.capable); 412 zAxis = element; 413 stored |= storeReportElement(element); 414 pointer = true; 415 break; 416 417 case kHIDUsage_GD_Rx: 418 case kHIDUsage_GD_Ry: 419 if ( _multiAxis.capable ) { 420 _multiAxis.options |= kMultiAxisOptionRotationForTranslation; 421 422 if ( reportID > _multiAxis.sendingReportID ) 423 _multiAxis.sendingReportID = reportID; 424 } 425 426 case kHIDUsage_GD_Rz: 427 pointer = true; 428 processMultiAxisElement(element, &_multiAxis.capable); 429 430 if ( _multiAxis.capable ) { 431 rzAxis = element; 432 stored |= storeReportElement ( element ); 433 } 434 break; 435 436 case kHIDUsage_GD_SystemPowerDown: 437 case kHIDUsage_GD_SystemSleep: 438 case kHIDUsage_GD_SystemWakeUp: 439 stored |= storeReportElement ( element ); 440 break; 441 } 442 } 443 444 else if ( usagePage == kHIDPage_Digitizer ) 445 { 446 switch ( usage ) 447 { 448 case kHIDUsage_Dig_InRange: 449 _digitizer.containsRange = true; 450 _cachedRangeState = false; 451 stored |= storeReportElement ( element ); 452 break; 453 case kHIDUsage_Dig_TipPressure: 454 supportsInk = true; 455 case kHIDUsage_Dig_BarrelPressure: 456 calibrateDigitizerElement(element, _absoluteAxisRemovalPercentage); 457 stored |= storeReportElement ( element ); 458 break; 459 case kHIDUsage_Dig_BarrelSwitch: 460 case kHIDUsage_Dig_TipSwitch: 461 case kHIDUsage_Dig_Eraser: 462 _bootSupport &= ~kMouseButtons; 463 case kHIDUsage_Dig_XTilt: 464 case kHIDUsage_Dig_YTilt: 465 case kHIDUsage_Dig_Twist: 466 case kHIDUsage_Dig_TransducerIndex: 467 case kHIDUsage_Dig_Invert: 468 stored |= storeReportElement ( element ); 469 break; 470 } 471 } 472 473 else if (( usagePage == kHIDPage_KeyboardOrKeypad ) && 474 (( usage >= kHIDUsage_KeyboardA ) && ( usage <= kHIDUsage_KeyboardRightGUI ))) 475 { 476 stored |= storeReportElement ( element ); 477 } 478 479 else if ( usagePage == kHIDPage_Button ) 480 { 481 if ( !buttonArray ) 482 buttonArray = OSArray::withCapacity(4); 483 484 // RY: Save the buttons for later. 485 if ( buttonArray ) 486 buttonArray->setObject(element); 487 } 488 489 else if ( usagePage == kHIDPage_Consumer || usagePage == kHIDPage_Telephony ) 490 { 491 stored |= storeReportElement ( element ); 492 } 493 494 else if (( usagePage == kHIDPage_LEDs ) && 495 (((usage == kHIDUsage_LED_NumLock) || (usage == kHIDUsage_LED_CapsLock)) 496 && (_ledElements[usage - kHIDUsage_LED_NumLock] == 0))) 497 { 498 _ledElements[usage - kHIDUsage_LED_NumLock] = element; 499 } 500 else if ((getVendorID() == kIOUSBVendorIDAppleComputer) 501 && (((usagePage == kHIDPage_AppleVendorTopCase) && (usage == kHIDUsage_AV_TopCase_KeyboardFn)) 502 || ((usagePage == kHIDPage_AppleVendorKeyboard) && (usage == kHIDUsage_AppleVendorKeyboard_Function)))) 503 { 504 stored |= storeReportElement ( element ); 505 } 506 } 507 } 508 509 // RY: Add the buttons only if elements of a pointer have been discovered. 510 if ( buttonArray ) 511 { 512 if ( pointer ) 513 { 514 count = buttonArray->getCount(); 515 516 for (index=0; index<count; index++) 517 { 518 element = (IOHIDElement *)buttonArray->getObject(index); 519 520 if ( !element ) continue; 521 522 _bootSupport &= ~kMouseButtons; 523 524 if ( !buttonCollection ) 525 buttonCollection = element->getParentElement(); 526 527 stored |= storeReportElement ( element ); 528 } 529 } 530 buttonArray->release(); 531 } 532 533 if ( zAxis ) { 534 535 if ( (_multiAxis.capable & ((1<<GET_AXIS_INDEX(kHIDUsage_GD_Rx)) | (1<<GET_AXIS_INDEX(kHIDUsage_GD_Ry)))) == 0) { 536 _multiAxis.options |= kMultiAxisOptionZForScroll; 537 } 538 calibratePreferredStateElement(zAxis, _absoluteAxisRemovalPercentage); 539 } 540 541 if ( rzAxis ) { 542 SInt32 removal = _absoluteAxisRemovalPercentage; 543 544 545 if ( (_multiAxis.capable & ((1<<GET_AXIS_INDEX(kHIDUsage_GD_Rx)) | (1<<GET_AXIS_INDEX(kHIDUsage_GD_Ry)))) != 0) { 546 removal *= 2; 547 } 548 calibratePreferredStateElement(rzAxis, removal); 549 550 } 551 552 setProperty("MultiAxis", _multiAxis.capable, 32); 553 554 if ( supportsInk ) 555 setProperty("SupportsInk", 1, 32); 556 557 if (buttonCollection == relativeCollection) 558 _relativeButtonCollection = true; 559 560 return ( stored || _bootSupport ); 561 562} 563 564//==================================================================================================== 565// IOHIDEventDriver::storeReportElement 566//==================================================================================================== 567bool IOHIDEventDriver::storeReportElement ( IOHIDElement * element ) 568{ 569 OSArray ** array; 570 SInt32 type; 571 572 type = GetReportType(element->getType()); 573 if ( type == -1 ) return false; 574 575 array = &(GetElementArray(GetReportHandlerSlot(element->getReportID()), type)); 576 577 if ( *array == NULL ) 578 { 579 (*array) = OSArray::withCapacity(4); 580 } 581 582 (*array)->setObject ( element ); 583 584 return true; 585} 586 587//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 588// IOHIDEventDriver::processMultiAxisElement 589//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 590void IOHIDEventDriver::processMultiAxisElement(IOHIDElement * element, UInt32 * isMultiAxis, bool * supportsInk, IOHIDElement ** relativeCollection) 591{ 592 // RY: can't deal with array objects 593 if ( (element->getFlags() & kIOHIDElementFlagsVariableMask) == 0 ) { 594 return; 595 } 596 597 if (!(*isMultiAxis & (1<<(element->getUsage()-kHIDUsage_GD_X)))) 598 { 599 if ( !element->conformsTo(kHIDPage_GenericDesktop, kHIDUsage_GD_Mouse) && 600 !element->conformsTo(kHIDPage_Digitizer) ) 601 { 602 bool isAbsolute = (element->getFlags() & (kIOHIDElementFlagsNoPreferredMask|kIOHIDElementFlagsRelativeMask)) == 0; 603 if ( isAbsolute || 604 element->conformsTo(kHIDPage_GenericDesktop, kHIDUsage_GD_MultiAxisController) || 605 element->conformsTo(kHIDPage_GenericDesktop, kHIDUsage_GD_Joystick) ) 606 { 607 *isMultiAxis |= (1<<(element->getUsage()-kHIDUsage_GD_X)); 608 } 609 } 610 } 611 612 if ( relativeCollection && isMultiAxis && supportsInk ) { 613 if ((element->getFlags() & kIOHIDElementFlagsRelativeMask) != 0) { 614 615 if ( !*isMultiAxis && !*relativeCollection ) 616 *relativeCollection = element->getParentElement(); 617 } 618 else if ( !*isMultiAxis ) { 619 *supportsInk = true; 620 } 621 } 622} 623 624//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 625// IOHIDEventDriver::calibratePreferredStateElement 626//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 627void IOHIDEventDriver::calibratePreferredStateElement(IOHIDElement * element, SInt32 removalPercentage) 628{ 629 UInt32 mid = element->getLogicalMin() + ((element->getLogicalMax() - element->getLogicalMin()) / 2); 630 UInt32 satMin = element->getLogicalMin(); 631 UInt32 satMax = element->getLogicalMax(); 632 UInt32 diff = ((satMax - satMin) * removalPercentage) / 200; 633 UInt32 dzMin = mid - diff; 634 UInt32 dzMax = mid + diff; 635 satMin += diff; 636 satMax -= diff; 637 638 element->setCalibration(-1, 1, satMin, satMax, dzMin, dzMax); 639 640} 641 642//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 643// IOHIDEventDriver::calibrateDigitizerElement 644//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 645void IOHIDEventDriver::calibrateDigitizerElement(IOHIDElement * element, SInt32 removalPercentage) 646{ 647#if TARGET_OS_EMBEDDED 648 removalPercentage = 0; 649#endif /* TARGET_OS_EMBEDDED */ 650 UInt32 satMin = element->getLogicalMin(); 651 UInt32 satMax = element->getLogicalMax(); 652 UInt32 diff = ((satMax - satMin) * removalPercentage) / 200; 653 satMin += diff; 654 satMax -= diff; 655 656 element->setCalibration(0, 1, satMin, satMax); 657} 658 659 660//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 661// IOHIDEventDriver::calibrateAxisToButtonElement 662//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 663void IOHIDEventDriver::calibrateAxisToButtonElement(IOHIDElement * element, SInt32 removalPercentage) 664{ 665 UInt32 satMin = element->getLogicalMin(); 666 UInt32 satMax = element->getLogicalMax(); 667 UInt32 diff = ((satMax - satMin) * removalPercentage) / 200; 668 satMin += diff; 669 satMax -= diff; 670 671 element->setCalibration(0, 1, satMin, satMax); 672} 673 674//==================================================================================================== 675// IOHIDEventDriver::getReportElements 676//==================================================================================================== 677OSArray * IOHIDEventDriver::getReportElements() 678{ 679 return _supportedElements; 680} 681 682//==================================================================================================== 683// IOHIDEventDriver::setButtonState 684//==================================================================================================== 685static inline void setButtonState(UInt32 * state, UInt32 bit, UInt32 value) 686{ 687 688 UInt32 buttonMask = (1 << bit); 689 690 if ( value ) 691 (*state) |= buttonMask; 692 else 693 (*state) &= ~buttonMask; 694} 695 696//==================================================================================================== 697// IOHIDEventDriver::handleInterruptReport 698//==================================================================================================== 699void IOHIDEventDriver::handleInterruptReport ( 700 AbsoluteTime timeStamp, 701 IOMemoryDescriptor * report, 702 IOHIDReportType reportType, 703 UInt32 reportID) 704{ 705 OSArray * elements; 706 IOHIDElement * element; 707 UInt32 count = 0; 708 UInt32 index = 0; 709 UInt32 usage = 0; 710 UInt32 usagePage = 0; 711 UInt32 buttonState = _cachedButtonState; 712 UInt32 transducerID = reportID; 713 UInt32 volumeHandled = 0; 714 UInt32 volumeState = 0; 715 SInt32 relativeAxis[GET_AXIS_COUNT(kHIDUsage_GD_Y)] = {}; 716 IOFixed absoluteAxis[GET_AXIS_COUNT(kHIDUsage_GD_Rz)] = {}; 717 IOFixed tipPressure = 0; 718 IOFixed barrelPressure = 0; 719 SInt32 scrollVert = 0; 720 SInt32 scrollHoriz = 0; 721 IOFixed tiltX = 0; 722 IOFixed tiltY = 0; 723 IOFixed twist = 0; 724 bool isAbsoluteAxis = false; 725 bool pointingHandled = false; 726 bool digitizerHandled = false; 727 bool invert = false; 728 bool elementIsCurrent = false; 729 bool inRange = _cachedRangeState; 730 IOOptionBits options = 0; 731 AbsoluteTime elementTS; 732 AbsoluteTime reportTS; 733 734 if (!readyForReports()) 735 return; 736 737 elements = GetElementArray(GetReportHandlerSlot(reportID), reportType); 738 739 IOHID_DEBUG(kIOHIDDebugCode_InturruptReport, reportType, reportID, elements ? elements->getCount() : -1, getRegistryEntryID()); 740 741 if ( elements ) { 742 count = elements->getCount(); 743 744 for (index = 0; index < count; index++) { 745 bool elementIsRelative = false; 746 747 element = (IOHIDElement *)elements->getObject(index); 748 749 elementTS = element->getTimeStamp(); 750 reportTS = timeStamp; 751 elementIsRelative = element->getFlags() & kIOHIDElementFlagsRelativeMask; 752 elementIsCurrent = (CMP_ABSOLUTETIME(&elementTS, &reportTS) == 0); 753 754 if ( element->getReportID() != reportID ) 755 continue; 756 757 usagePage = element->getUsagePage(); 758 usage = element->getUsage(); 759 760 761 if ( usagePage == kHIDPage_GenericDesktop ) { 762 switch ( element->getUsage() ) { 763 case kHIDUsage_GD_X: 764 case kHIDUsage_GD_Y: 765 pointingHandled |= true; 766 if ( _multiAxis.capable ) { 767 _multiAxis.axis[GET_AXIS_INDEX(element->getUsage())] = element->getScaledFixedValue(kIOHIDValueScaleTypeCalibrated); 768 } 769 else if (elementIsRelative) { 770 if ( elementIsCurrent ) 771 relativeAxis[GET_AXIS_INDEX(element->getUsage())] = element->getValue(); 772 } 773 else { 774 digitizerHandled |= elementIsCurrent; 775 isAbsoluteAxis = true; 776 absoluteAxis[GET_AXIS_INDEX(element->getUsage())] = element->getScaledFixedValue(kIOHIDValueScaleTypeCalibrated); 777 } 778 break; 779 case kHIDUsage_GD_Z: 780 if ( _multiAxis.capable ) { 781 _multiAxis.axis[GET_AXIS_INDEX(element->getUsage())] = element->getScaledFixedValue(kIOHIDValueScaleTypeCalibrated); 782 } 783 else if (elementIsRelative) { 784 if ( elementIsCurrent ) 785 scrollHoriz = element->getValue(); 786 } 787 else { 788 digitizerHandled |= elementIsCurrent; 789 absoluteAxis[GET_AXIS_INDEX(element->getUsage())] = element->getValue(); 790 } 791 break; 792 793 case kHIDUsage_GD_Rx: 794 case kHIDUsage_GD_Ry: 795 case kHIDUsage_GD_Rz: 796 if ( _multiAxis.capable ) { 797 pointingHandled |= true; 798 _multiAxis.axis[GET_AXIS_INDEX(element->getUsage())] = element->getScaledFixedValue(kIOHIDValueScaleTypeCalibrated); 799 } 800 break; 801 case kHIDUsage_GD_Wheel: 802 case kHIDUsage_GD_Dial: 803 if ( elementIsCurrent ) { 804 scrollVert = (element->getFlags() & kIOHIDElementFlagsWrapMask) ? element->getValue(kIOHIDValueOptionsFlagRelativeSimple) : element->getValue(); 805 } 806 break; 807 case kHIDUsage_GD_SystemPowerDown: 808 case kHIDUsage_GD_SystemSleep: 809 case kHIDUsage_GD_SystemWakeUp: 810 if ( elementIsCurrent ) 811 dispatchKeyboardEvent( timeStamp, usagePage, usage, element->getValue()); 812 break; 813 } 814 } 815 else if ( usagePage == kHIDPage_Digitizer ) { 816 pointingHandled |= elementIsCurrent; 817 818 switch ( usage ) { 819 case kHIDUsage_Dig_TipSwitch: 820 setButtonState ( &buttonState, 0, element->getValue()); 821 break; 822 case kHIDUsage_Dig_BarrelSwitch: 823 setButtonState ( &buttonState, 1, element->getValue()); 824 break; 825 case kHIDUsage_Dig_Eraser: 826 setButtonState ( &buttonState, 2, element->getValue()); 827 break; 828 case kHIDUsage_Dig_InRange: 829 if ( elementIsCurrent ) { 830 inRange = (element->getValue() != 0); 831 digitizerHandled |= ( inRange != _cachedRangeState ); 832 } 833 break; 834 case kHIDUsage_Dig_BarrelPressure: 835 digitizerHandled |= elementIsCurrent; 836 barrelPressure = element->getScaledFixedValue(kIOHIDValueScaleTypeCalibrated); 837 break; 838 case kHIDUsage_Dig_TipPressure: 839 digitizerHandled |= elementIsCurrent; 840 tipPressure = element->getScaledFixedValue(kIOHIDValueScaleTypeCalibrated); 841 break; 842 case kHIDUsage_Dig_XTilt: 843 digitizerHandled |= elementIsCurrent; 844 tiltX = element->getScaledFixedValue(kIOHIDValueScaleTypePhysical); 845 break; 846 case kHIDUsage_Dig_YTilt: 847 digitizerHandled |= elementIsCurrent; 848 tiltY = element->getScaledFixedValue(kIOHIDValueScaleTypePhysical); 849 break; 850 case kHIDUsage_Dig_Twist: 851 digitizerHandled |= elementIsCurrent; 852 twist = element->getScaledFixedValue(kIOHIDValueScaleTypePhysical); 853 break; 854 case kHIDUsage_Dig_TransducerIndex: 855 digitizerHandled |= elementIsCurrent; 856 transducerID = element->getValue(); 857 break; 858 case kHIDUsage_Dig_Invert: 859 digitizerHandled |= elementIsCurrent; 860 invert = (element->getValue() != 0); 861 break; 862 default: 863 break; 864 } 865 } 866 else if ( usagePage == kHIDPage_Button ) { 867 pointingHandled |= true; 868 869 digitizerHandled |= ( isAbsoluteAxis && elementIsCurrent ); 870 871 setButtonState ( &buttonState, (element->getUsage() - 1), element->getValue()); 872 } 873 else if (( usagePage == kHIDPage_KeyboardOrKeypad || usagePage == kHIDPage_Telephony ) && elementIsCurrent ) { 874 dispatchKeyboardEvent( timeStamp, usagePage, usage, element->getValue()); 875 } 876 else if (( usagePage == kHIDPage_Consumer ) && elementIsCurrent ) { 877 switch ( usage ) { 878 case kHIDUsage_Csmr_VolumeIncrement: 879 volumeHandled |= 0x1; 880 volumeState |= (element->getValue() != 0) ? 0x1:0; 881 break; 882 case kHIDUsage_Csmr_VolumeDecrement: 883 volumeHandled |= 0x2; 884 volumeState |= (element->getValue() != 0) ? 0x2:0; 885 break; 886 case kHIDUsage_Csmr_Mute: 887 volumeHandled |= 0x4; 888 volumeState |= (element->getValue() != 0) ? 0x4:0; 889 break; 890 case kHIDUsage_Csmr_ACPan: 891 scrollHoriz = -element->getValue(); 892 break; 893 default: 894 dispatchKeyboardEvent(timeStamp, usagePage, usage, element->getValue()); 895 break; 896 } 897 } 898 else if (elementIsCurrent && 899 (((usagePage == kHIDPage_AppleVendorTopCase) && (usage == kHIDUsage_AV_TopCase_KeyboardFn)) || 900 ((usagePage == kHIDPage_AppleVendorKeyboard) && (usage == kHIDUsage_AppleVendorKeyboard_Function)))) { 901 dispatchKeyboardEvent(timeStamp, usagePage, usage, element->getValue()); 902 } 903 904 } 905 906 // RY: Handle the case where Vol Increment, Decrement, and Mute are all down 907 // If such an event occurs, it is likely that the device is defective, 908 // and should be ignored. 909 if ( (volumeState != 0x7) && (volumeHandled != 0x7) ) { 910 // Volume Increment 911 if ( volumeHandled & 0x1 ) 912 dispatchKeyboardEvent(timeStamp, kHIDPage_Consumer, kHIDUsage_Csmr_VolumeIncrement, ((volumeState & 0x1) != 0)); 913 // Volume Decrement 914 if ( volumeHandled & 0x2 ) 915 dispatchKeyboardEvent(timeStamp, kHIDPage_Consumer, kHIDUsage_Csmr_VolumeDecrement, ((volumeState & 0x2) != 0)); 916 // Volume Mute 917 if ( volumeHandled & 0x4 ) 918 dispatchKeyboardEvent(timeStamp, kHIDPage_Consumer, kHIDUsage_Csmr_Mute, ((volumeState & 0x4) != 0)); 919 } 920 921 if ( scrollVert || scrollHoriz ) 922 dispatchScrollWheelEvent(timeStamp, scrollVert, scrollHoriz, 0); 923 } 924 925 if ( (_bootSupport & kBootMouse) && (reportID == 0)) { 926 handleBootPointingReport(report, &relativeAxis[GET_AXIS_INDEX(kHIDUsage_GD_X)], &relativeAxis[GET_AXIS_INDEX(kHIDUsage_GD_Y)], &buttonState); 927 pointingHandled |= true; 928 } 929 930 if ( pointingHandled || digitizerHandled ) { 931 932 if ( isAbsoluteAxis && !relativeAxis[GET_AXIS_INDEX(kHIDUsage_GD_X)] && !relativeAxis[GET_AXIS_INDEX(kHIDUsage_GD_Y)] && !_digitizer.containsRange ) { 933#if TARGET_OS_EMBEDDED // { 934 inRange = buttonState & 0x1; 935 936 digitizerHandled = inRange != _cachedRangeState; 937#else // } TARGET_OS_EMBEDDED { 938 //IOLog("Correcting for !_digitizer.containsRange for 0x%08llx\n", getRegistryEntryID()); 939 inRange = digitizerHandled = true; 940#endif // } TARGET_OS_EMBEDDED 941 } 942 943 if ( invert ) 944 options |= IOHIDEventService::kDigitizerInvert; 945 946 if ( _multiAxis.capable ) { 947 if ( reportID == _multiAxis.sendingReportID ) { 948 dispatchMultiAxisPointerEvent(timeStamp, buttonState, _multiAxis.axis[GET_AXIS_INDEX(kHIDUsage_GD_X)], _multiAxis.axis[GET_AXIS_INDEX(kHIDUsage_GD_Y)], _multiAxis.axis[GET_AXIS_INDEX(kHIDUsage_GD_Z)], _multiAxis.axis[GET_AXIS_INDEX(kHIDUsage_GD_Rx)], _multiAxis.axis[GET_AXIS_INDEX(kHIDUsage_GD_Ry)], _multiAxis.axis[GET_AXIS_INDEX(kHIDUsage_GD_Rz)], _multiAxis.options); 949 } 950 else { 951 // event is dropped 952 //IOLog("Dropping event from 0x%08x because %d != %d\n", getRegistryEntryID(), reportID, _multiAxis.sendingReportID); 953 } 954 } 955 else if ( digitizerHandled || (isAbsoluteAxis && !relativeAxis[GET_AXIS_INDEX(kHIDUsage_GD_X)] && !relativeAxis[GET_AXIS_INDEX(kHIDUsage_GD_Y)] && (inRange || ((buttonState != _cachedButtonState) && !_relativeButtonCollection)))) { 956 dispatchDigitizerEventWithTiltOrientation(timeStamp, transducerID, _digitizer.type, inRange, buttonState, absoluteAxis[GET_AXIS_INDEX(kHIDUsage_GD_X)], absoluteAxis[GET_AXIS_INDEX(kHIDUsage_GD_Y)], absoluteAxis[GET_AXIS_INDEX(kHIDUsage_GD_Z)], tipPressure, barrelPressure, twist, tiltX, tiltY, options); 957 } 958 else if (relativeAxis[GET_AXIS_INDEX(kHIDUsage_GD_X)] || relativeAxis[GET_AXIS_INDEX(kHIDUsage_GD_Y)] || (buttonState != _cachedButtonState)) { 959 dispatchRelativePointerEvent(timeStamp, relativeAxis[GET_AXIS_INDEX(kHIDUsage_GD_X)], relativeAxis[GET_AXIS_INDEX(kHIDUsage_GD_Y)], buttonState); 960 } 961 else { 962 // event is dropped 963 //IOLog("Dropping event from 0x%08x\n", getRegistryEntryID()); 964 } 965 966 _cachedRangeState = inRange; 967 _cachedButtonState = buttonState; 968 } 969} 970 971//==================================================================================================== 972// IOHIDEventDriver::handleBootPointingReport 973//==================================================================================================== 974void IOHIDEventDriver::handleBootPointingReport ( 975 IOMemoryDescriptor * report, 976 SInt32 * dX, 977 SInt32 * dY, 978 UInt32 * buttonState) 979{ 980 UInt32 bootOffset; 981 UInt8 * mouseData; 982 IOByteCount reportLength; 983 984 // Get a pointer to the data in the descriptor. 985 reportLength = report->getLength(); 986 987 if ( !reportLength ) 988 return; 989 990 mouseData = (UInt8 *)IOMalloc(reportLength); 991 992 if ( !mouseData ) 993 return; 994 995 report->readBytes( 0, (void *)mouseData, reportLength ); 996 997 if ( reportLength >= 3 ) 998 { 999 bootOffset = ( _multipleReports ) ? 1 : 0; 1000 1001 if ( _bootSupport & kMouseButtons ) 1002 *buttonState = mouseData[bootOffset]; 1003 1004 if ( _bootSupport & kMouseXAxis ) 1005 *dX = mouseData[bootOffset + 1]; 1006 1007 if ( _bootSupport & kMouseYAxis ) 1008 *dY = mouseData[bootOffset + 2]; 1009 } 1010 1011 IOFree((void *)mouseData, reportLength); 1012} 1013 1014 1015//==================================================================================================== 1016// IOHIDEventDriver::setElementValue 1017//==================================================================================================== 1018void IOHIDEventDriver::setElementValue ( 1019 UInt32 usagePage, 1020 UInt32 usage, 1021 UInt32 value ) 1022{ 1023 IOHIDElement *element = 0; 1024 1025 if ( usagePage == kHIDPage_LEDs ) 1026 element = _ledElements[usage - kHIDUsage_LED_NumLock]; 1027 1028 if (element) 1029 element->setValue(value); 1030} 1031 1032//==================================================================================================== 1033// IOHIDEventDriver::getElementValue 1034//==================================================================================================== 1035UInt32 IOHIDEventDriver::getElementValue ( 1036 UInt32 usagePage, 1037 UInt32 usage ) 1038{ 1039 IOHIDElement *element = 0; 1040 1041 if ( usagePage == kHIDPage_LEDs ) 1042 element = _ledElements[usage - kHIDUsage_LED_NumLock]; 1043 1044 return (element) ? element->getValue() : 0; 1045} 1046 1047 1048OSMetaClassDefineReservedUnused(IOHIDEventDriver, 0); 1049OSMetaClassDefineReservedUnused(IOHIDEventDriver, 1); 1050OSMetaClassDefineReservedUnused(IOHIDEventDriver, 2); 1051OSMetaClassDefineReservedUnused(IOHIDEventDriver, 3); 1052OSMetaClassDefineReservedUnused(IOHIDEventDriver, 4); 1053OSMetaClassDefineReservedUnused(IOHIDEventDriver, 5); 1054OSMetaClassDefineReservedUnused(IOHIDEventDriver, 6); 1055OSMetaClassDefineReservedUnused(IOHIDEventDriver, 7); 1056OSMetaClassDefineReservedUnused(IOHIDEventDriver, 8); 1057OSMetaClassDefineReservedUnused(IOHIDEventDriver, 9); 1058OSMetaClassDefineReservedUnused(IOHIDEventDriver, 10); 1059OSMetaClassDefineReservedUnused(IOHIDEventDriver, 11); 1060OSMetaClassDefineReservedUnused(IOHIDEventDriver, 12); 1061OSMetaClassDefineReservedUnused(IOHIDEventDriver, 13); 1062OSMetaClassDefineReservedUnused(IOHIDEventDriver, 14); 1063OSMetaClassDefineReservedUnused(IOHIDEventDriver, 15); 1064OSMetaClassDefineReservedUnused(IOHIDEventDriver, 16); 1065OSMetaClassDefineReservedUnused(IOHIDEventDriver, 17); 1066OSMetaClassDefineReservedUnused(IOHIDEventDriver, 18); 1067OSMetaClassDefineReservedUnused(IOHIDEventDriver, 19); 1068OSMetaClassDefineReservedUnused(IOHIDEventDriver, 20); 1069OSMetaClassDefineReservedUnused(IOHIDEventDriver, 21); 1070OSMetaClassDefineReservedUnused(IOHIDEventDriver, 22); 1071OSMetaClassDefineReservedUnused(IOHIDEventDriver, 23); 1072OSMetaClassDefineReservedUnused(IOHIDEventDriver, 24); 1073OSMetaClassDefineReservedUnused(IOHIDEventDriver, 25); 1074OSMetaClassDefineReservedUnused(IOHIDEventDriver, 26); 1075OSMetaClassDefineReservedUnused(IOHIDEventDriver, 27); 1076OSMetaClassDefineReservedUnused(IOHIDEventDriver, 28); 1077OSMetaClassDefineReservedUnused(IOHIDEventDriver, 29); 1078OSMetaClassDefineReservedUnused(IOHIDEventDriver, 30); 1079OSMetaClassDefineReservedUnused(IOHIDEventDriver, 31); 1080 1081