|
|
1.1 ! root 1: /* ! 2: * Copyright (c) 1998-2000 Apple Computer, Inc. All rights reserved. ! 3: * ! 4: * @APPLE_LICENSE_HEADER_START@ ! 5: * ! 6: * The contents of this file constitute Original Code as defined in and ! 7: * are subject to the Apple Public Source License Version 1.1 (the ! 8: * "License"). You may not use this file except in compliance with the ! 9: * License. Please obtain a copy of the License at ! 10: * http://www.apple.com/publicsource and read it before using this file. ! 11: * ! 12: * This Original Code and all software distributed under the License are ! 13: * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER ! 14: * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, ! 15: * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, ! 16: * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the ! 17: * License for the specific language governing rights and limitations ! 18: * under the License. ! 19: * ! 20: * @APPLE_LICENSE_HEADER_END@ ! 21: */ ! 22: /* ! 23: * 17 July 1998 sdouglas ! 24: */ ! 25: ! 26: #include <IOKit/IOLib.h> ! 27: #include <IOKit/assert.h> ! 28: #include <IOKit/hidsystem/IOHIPointing.h> ! 29: #include <IOKit/hidsystem/IOHIDParameter.h> ! 30: ! 31: #ifndef abs ! 32: #define abs(_a) ((_a >= 0) ? _a : -_a) ! 33: #endif ! 34: ! 35: #define super IOHIDevice ! 36: OSDefineMetaClassAndStructors(IOHIPointing, IOHIDevice); ! 37: ! 38: bool IOHIPointing::init(OSDictionary * properties) ! 39: { ! 40: if (!super::init(properties)) return false; ! 41: ! 42: /* ! 43: * Initialize minimal state. ! 44: */ ! 45: ! 46: _fractX = 0; ! 47: _fractY = 0; ! 48: _acceleration = -1; ! 49: _convertAbsoluteToRelative = false; ! 50: _contactToMove = false; ! 51: _hadContact = false; ! 52: _pressureThresholdToClick = 128; ! 53: _previousLocation.x = 0; ! 54: _previousLocation.y = 0; ! 55: ! 56: _deviceLock = IOLockAlloc(); ! 57: ! 58: if (!_deviceLock) return false; ! 59: ! 60: IOLockInit(_deviceLock); ! 61: ! 62: return true; ! 63: } ! 64: ! 65: bool IOHIPointing::start(IOService * provider) ! 66: { ! 67: if (!super::start(provider)) return false; ! 68: ! 69: /* ! 70: * IOHIPointing serves both as a service and a nub (we lead a double ! 71: * life). Register ourselves as a nub to kick off matching. ! 72: */ ! 73: ! 74: registerService(); ! 75: ! 76: return true; ! 77: } ! 78: ! 79: void IOHIPointing::free() ! 80: // Description: Go Away. Be careful when freeing the lock. ! 81: { ! 82: if (_deviceLock) ! 83: { ! 84: IOLock * lock; ! 85: ! 86: IOTakeLock(_deviceLock); ! 87: ! 88: lock = _deviceLock; ! 89: _deviceLock = NULL; ! 90: ! 91: IOUnlock(lock); ! 92: IOLockFree(lock); ! 93: } ! 94: super::free(); ! 95: } ! 96: ! 97: bool IOHIPointing::open(IOService * client, ! 98: IOOptionBits options, ! 99: RelativePointerEventAction rpeAction, ! 100: AbsolutePointerEventAction apeAction, ! 101: ScrollWheelEventAction sweAction) ! 102: { ! 103: if ( (-1 == _acceleration) && (!resetPointer())) return false; ! 104: ! 105: if (super::open(client, options)) ! 106: { ! 107: // Note: client object is already retained by superclass' open() ! 108: _relativePointerEventTarget = client; ! 109: _relativePointerEventAction = rpeAction; ! 110: _absolutePointerEventTarget = client; ! 111: _absolutePointerEventAction = apeAction; ! 112: _scrollWheelEventTarget = client; ! 113: _scrollWheelEventAction = sweAction; ! 114: return true; ! 115: } ! 116: ! 117: return false; ! 118: } ! 119: ! 120: void IOHIPointing::close(IOService * client, IOOptionBits) ! 121: { ! 122: _relativePointerEventAction = NULL; ! 123: _relativePointerEventTarget = 0; ! 124: _absolutePointerEventAction = NULL; ! 125: _absolutePointerEventTarget = 0; ! 126: ! 127: super::close(client); ! 128: } ! 129: ! 130: IOHIDKind IOHIPointing::hidKind() ! 131: { ! 132: return kHIRelativePointingDevice; ! 133: } ! 134: ! 135: void IOHIPointing::scalePointer(int * dxp, int * dyp) ! 136: // Description: Perform pointer acceleration computations here. ! 137: // Given the resolution, dx, dy, and time, compute the velocity ! 138: // of the pointer over a Manhatten distance in inches/second. ! 139: // Using this velocity, do a lookup in the pointerScaling table ! 140: // to select a scaling factor. Scale dx and dy up as appropriate. ! 141: // Preconditions: ! 142: // * _deviceLock should be held on entry ! 143: { ! 144: int dx, dy; ! 145: int absDx, absDy; ! 146: unsigned delta; ! 147: ! 148: dx = *dxp; ! 149: dy = *dyp; ! 150: absDx = (dx < 0) ? -dx : dx; ! 151: absDy = (dy < 0) ? -dy : dy; ! 152: ! 153: #if 1 ! 154: if( absDx > absDy) ! 155: delta = (absDx + (absDy / 2)); ! 156: else ! 157: delta = (absDy + (absDx / 2)); ! 158: #else ! 159: delta = absDx + absDy; ! 160: #endif ! 161: ! 162: // scale ! 163: if( delta > (MAXMAG - 1)) ! 164: delta = MAXMAG - 1; ! 165: dx = IOFixedMultiply( dx << 16, _scaleValues[delta]); ! 166: dy = IOFixedMultiply( dy << 16, _scaleValues[delta]); ! 167: ! 168: // if no direction changes add fract parts ! 169: if( (dx ^ _fractX) >= 0) ! 170: dx += _fractX; ! 171: if( (dy ^ _fractY) >= 0) ! 172: dy += _fractY; ! 173: ! 174: *dxp = dx / 65536; ! 175: *dyp = dy / 65536; ! 176: ! 177: // get fractional part with sign extend ! 178: if( dx >= 0) ! 179: _fractX = dx & 0xffff; ! 180: else ! 181: _fractX = dx | 0xffff0000; ! 182: if( dy >= 0) ! 183: _fractY = dy & 0xffff; ! 184: else ! 185: _fractY = dy | 0xffff0000; ! 186: } ! 187: ! 188: ! 189: void IOHIPointing::setupForAcceleration(IOFixed accl) ! 190: { ! 191: int slope = 0, i, j = 0; ! 192: int x; ! 193: int devSpeed, crsrSpeed; ! 194: int lastCrsrSpeed = 0, nextCrsrSpeed; ! 195: int lastDeviceSpeed = 0, nextDeviceSpeed; ! 196: IOHIAccelerationPoint * table; ! 197: IOItemCount numEntries; ! 198: IOFixed res = resolution(); ! 199: ! 200: assert(res); ! 201: ! 202: accelerationTable(&table, &numEntries); ! 203: ! 204: if( accl > (1 << 16)) ! 205: accl = (1 << 16); ! 206: ! 207: // scale for device speed ! 208: // no vbl sync, so 90 autopolls /s ! 209: devSpeed = IOFixedDivide( 90 << 16, res ); ! 210: // scale for cursor speed ! 211: // screen is assumed 72 dpi, like MacOS ! 212: crsrSpeed = IOFixedDivide( 72 << 16, res ); ! 213: ! 214: nextCrsrSpeed = 0; ! 215: nextDeviceSpeed = 0; ! 216: ! 217: // Precalculate fixed point scales. Not as accurate as MacOS, ! 218: // but no IOFixedDivide() in handler ! 219: for ( i = 1; i < MAXMAG; i++ ) ! 220: { ! 221: x = IOFixedMultiply( i << 16, devSpeed ); ! 222: if( x > table[j].deviceSpeed) { ! 223: lastCrsrSpeed = nextCrsrSpeed; ! 224: lastDeviceSpeed = nextDeviceSpeed; ! 225: j++; ! 226: nextDeviceSpeed = table[j].deviceSpeed; ! 227: // Interpolate by accl between y=x and y=acclTable(x) ! 228: // to get nextCrsrSpeed ! 229: { ! 230: int factorCursor; ! 231: int factorDevice; ! 232: if( table[j].cursorSpeed < nextDeviceSpeed) { ! 233: factorDevice = accl; ! 234: factorCursor = (0x10000 - accl); ! 235: } else { ! 236: factorCursor = accl; ! 237: factorDevice = (0x10000 - accl); ! 238: } ! 239: nextCrsrSpeed = IOFixedMultiply( factorCursor, table[j].cursorSpeed) ! 240: + IOFixedMultiply( factorDevice, nextDeviceSpeed); ! 241: } ! 242: slope = IOFixedDivide( nextCrsrSpeed - lastCrsrSpeed, ! 243: nextDeviceSpeed - lastDeviceSpeed); ! 244: } ! 245: _scaleValues[i] = IOFixedDivide( IOFixedMultiply( crsrSpeed, ! 246: IOFixedMultiply( slope, x - lastDeviceSpeed ) + lastCrsrSpeed), x); ! 247: } ! 248: _scaleValues[0] = _scaleValues[1]; ! 249: _fractX = _fractY = 0; ! 250: _acceleration = accl; ! 251: } ! 252: ! 253: bool IOHIPointing::resetPointer() ! 254: { ! 255: IOTakeLock( _deviceLock); ! 256: ! 257: _buttonMode = NX_OneButton; ! 258: ! 259: setupForAcceleration(0x8000); ! 260: updateProperties(); ! 261: ! 262: IOUnlock( _deviceLock); ! 263: return true; ! 264: } ! 265: ! 266: void IOHIPointing::dispatchAbsolutePointerEvent(Point * newLoc, ! 267: Bounds * bounds, ! 268: UInt32 buttonState, ! 269: bool proximity, ! 270: int pressure, ! 271: int pressureMin, ! 272: int pressureMax, ! 273: int stylusAngle, ! 274: AbsoluteTime ts) ! 275: { ! 276: int buttons = 0; ! 277: int dx, dy; ! 278: ! 279: IOTakeLock(_deviceLock); ! 280: ! 281: if (buttonState & 1) { ! 282: buttons |= EV_LB; ! 283: } ! 284: ! 285: if (buttonCount() > 1) { ! 286: if (buttonState & -2) { // any other buttons ! 287: buttons |= EV_RB; ! 288: } ! 289: } ! 290: ! 291: if ((_pressureThresholdToClick < 255) && ((pressure - pressureMin) > ((pressureMax - pressureMin) * _pressureThresholdToClick / 256))) { ! 292: buttons |= EV_LB; ! 293: } ! 294: ! 295: if (_buttonMode == NX_OneButton) { ! 296: if ((buttons & (EV_LB|EV_RB)) != 0) { ! 297: buttons = EV_LB; ! 298: } ! 299: } ! 300: ! 301: if (_convertAbsoluteToRelative) { ! 302: dx = newLoc->x - _previousLocation.x; ! 303: dy = newLoc->y - _previousLocation.y; ! 304: ! 305: if ((_contactToMove && !_hadContact && (pressure > pressureMin)) || (abs(dx) > ((bounds->maxx - bounds->minx) / 20)) || (abs(dy) > ((bounds->maxy - bounds->miny) / 20))) { ! 306: dx = 0; ! 307: dy = 0; ! 308: } else { ! 309: scalePointer(&dx, &dy); ! 310: } ! 311: ! 312: _previousLocation.x = newLoc->x; ! 313: _previousLocation.y = newLoc->y; ! 314: } ! 315: ! 316: IOUnlock(_deviceLock); ! 317: ! 318: _hadContact = (pressure > pressureMin); ! 319: ! 320: if (!_contactToMove || (pressure > pressureMin)) { ! 321: pressure -= pressureMin; ! 322: if (pressure > 255) { ! 323: pressure = 255; ! 324: } ! 325: if (_convertAbsoluteToRelative) { ! 326: if (_relativePointerEventAction && _relativePointerEventTarget) { ! 327: (*_relativePointerEventAction)(_relativePointerEventTarget, ! 328: buttons, ! 329: dx, ! 330: dy, ! 331: ts); ! 332: } ! 333: } else { ! 334: if (_absolutePointerEventAction && _absolutePointerEventTarget) { ! 335: (*_absolutePointerEventAction)(_absolutePointerEventTarget, ! 336: buttons, ! 337: newLoc, ! 338: bounds, ! 339: proximity, ! 340: pressure, ! 341: stylusAngle, ! 342: ts); ! 343: } ! 344: } ! 345: } ! 346: ! 347: return; ! 348: } ! 349: ! 350: void IOHIPointing::dispatchRelativePointerEvent(int dx, ! 351: int dy, ! 352: UInt32 buttonState, ! 353: AbsoluteTime ts) ! 354: { ! 355: int buttons; ! 356: ! 357: IOTakeLock( _deviceLock); ! 358: ! 359: buttons = 0; ! 360: ! 361: if( buttonState & 1) ! 362: buttons |= EV_LB; ! 363: ! 364: if( buttonCount() > 1) { ! 365: if( buttonState & -2) // any others down ! 366: buttons |= EV_RB; ! 367: } ! 368: ! 369: // Perform pointer acceleration computations ! 370: scalePointer(&dx, &dy); ! 371: ! 372: // Perform button tying and mapping. This ! 373: // stuff applies to relative posn devices (mice) only. ! 374: if ( _buttonMode == NX_OneButton ) ! 375: { ! 376: if ( (buttons & (EV_LB|EV_RB)) != 0 ) ! 377: buttons = EV_LB; ! 378: } ! 379: else if ( (buttonCount() > 1) && (_buttonMode == NX_LeftButton) ) ! 380: // Menus on left button. Swap! ! 381: { ! 382: int temp = 0; ! 383: if ( buttons & EV_LB ) ! 384: temp = EV_RB; ! 385: if ( buttons & EV_RB ) ! 386: temp |= EV_LB; ! 387: buttons = temp; ! 388: } ! 389: IOUnlock( _deviceLock); ! 390: ! 391: if (_relativePointerEventAction) /* upstream call */ ! 392: { ! 393: (*_relativePointerEventAction)(_relativePointerEventTarget, ! 394: /* buttons */ buttons, ! 395: /* deltaX */ dx, ! 396: /* deltaY */ dy, ! 397: /* atTime */ ts); ! 398: } ! 399: } ! 400: ! 401: void IOHIPointing::dispatchScrollWheelEvent(short deltaAxis1, ! 402: short deltaAxis2, ! 403: short deltaAxis3, ! 404: AbsoluteTime ts) ! 405: { ! 406: if (_scrollWheelEventAction) { ! 407: (*_scrollWheelEventAction)(_scrollWheelEventTarget, ! 408: deltaAxis1, ! 409: deltaAxis2, ! 410: deltaAxis3, ! 411: ts); ! 412: } ! 413: } ! 414: ! 415: bool IOHIPointing::updateProperties( void ) ! 416: { ! 417: bool ok; ! 418: UInt32 res = resolution(); ! 419: ! 420: ok = setProperty( kIOHIDPointerResolutionKey, &res, sizeof( res)) ! 421: & setProperty( kIOHIDPointerAccelerationKey, &_acceleration, ! 422: sizeof( _acceleration)) ! 423: & setProperty( kIOHIDPointerConvertAbsoluteKey, &_convertAbsoluteToRelative, ! 424: sizeof( _convertAbsoluteToRelative)) ! 425: & setProperty( kIOHIDPointerContactToMoveKey, &_contactToMove, ! 426: sizeof( _contactToMove)); ! 427: ! 428: return( ok & super::updateProperties() ); ! 429: } ! 430: ! 431: IOReturn IOHIPointing::setParamProperties( OSDictionary * dict ) ! 432: { ! 433: OSData * data; ! 434: IOReturn err = kIOReturnSuccess; ! 435: bool updated = false; ! 436: UInt8 * bytes; ! 437: ! 438: IOTakeLock( _deviceLock); ! 439: if( (data = OSDynamicCast( OSData, ! 440: dict->getObject(kIOHIDPointerAccelerationKey)))) { ! 441: ! 442: setupForAcceleration( *((IOFixed *)data->getBytesNoCopy()) ); ! 443: updated = true; ! 444: } ! 445: IOUnlock( _deviceLock); ! 446: ! 447: if( dict->getObject(kIOHIDResetPointerKey)) ! 448: resetPointer(); ! 449: ! 450: if ((data = OSDynamicCast(OSData, ! 451: dict->getObject(kIOHIDPointerConvertAbsoluteKey)))) { ! 452: bytes = (UInt8 *) data->getBytesNoCopy(); ! 453: _convertAbsoluteToRelative = (bytes[0] != 0) ? true : false; ! 454: updated = true; ! 455: } ! 456: ! 457: if ((data = OSDynamicCast(OSData, ! 458: dict->getObject(kIOHIDPointerContactToMoveKey)))) { ! 459: bytes = (UInt8 *) data->getBytesNoCopy(); ! 460: _contactToMove = (bytes[0] != 0) ? true : false; ! 461: updated = true; ! 462: } ! 463: ! 464: if( updated ) ! 465: updateProperties(); ! 466: ! 467: return( err ); ! 468: } ! 469: ! 470: // subclasses override ! 471: ! 472: IOItemCount IOHIPointing::buttonCount() ! 473: { ! 474: return (1); ! 475: } ! 476: ! 477: IOFixed IOHIPointing::resolution() ! 478: { ! 479: return (100 << 16); ! 480: } ! 481: ! 482: void IOHIPointing::accelerationTable(IOHIAccelerationPoint ** table, ! 483: IOItemCount * numEntries) ! 484: { ! 485: static IOHIAccelerationPoint defaultTable[] = { ! 486: { 0x000000, 0x000000 }, ! 487: { 0x7ffffff, 0x0960000 } ! 488: }; ! 489: ! 490: *table = defaultTable; ! 491: *numEntries = sizeof( defaultTable) / sizeof( defaultTable[0]); ! 492: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.