|
|
1.1 ! root 1: /* ! 2: * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. ! 3: * ! 4: * @APPLE_LICENSE_HEADER_START@ ! 5: * ! 6: * Portions Copyright (c) 1999 Apple Computer, Inc. All Rights ! 7: * Reserved. This file contains Original Code and/or Modifications of ! 8: * Original Code as defined in and that are subject to the Apple Public ! 9: * Source License Version 1.1 (the "License"). You may not use this file ! 10: * except in compliance with the License. Please obtain a copy of the ! 11: * License at http://www.apple.com/publicsource and read it before using ! 12: * this 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 OR NON-INFRINGEMENT. Please see the ! 19: * License for the specific language governing rights and limitations ! 20: * under the License. ! 21: * ! 22: * @APPLE_LICENSE_HEADER_END@ ! 23: */ ! 24: ! 25: /* Copyright (c) 1992 NeXT Computer, Inc. All rights reserved. ! 26: * ! 27: * EventSrcPCPointer.m - PC Pointer EventSrc subclass implementation ! 28: * ! 29: * HISTORY ! 30: * 28 Aug 1992 Joe Pasqua ! 31: * Created. ! 32: * 11 April 1997 Simon Douglas ! 33: * ADB version for PPC. ! 34: */ ! 35: ! 36: // TO DO: ! 37: // * VBL sync'ing ! 38: // * Real Mac scaling & acceleration & move to device ! 39: // * Better FixDiv/Mul ! 40: // ! 41: // NOTES: ! 42: // * The EventSrcExported protocol is implemented completely by our superclass. ! 43: // At this point there is no need for this subclass to override anything. ! 44: // * In the current system the EventDriver instance is always the owner ! 45: // of this EventSrc. ! 46: // * To find things that need to be fixed, search for FIX, to find questions ! 47: // to be resolved, search for ASK, to find stuff that still needs to be ! 48: // done, search for TO DO. ! 49: // ! 50: ! 51: #import <driverkit/generalFuncs.h> ! 52: #import <machkit/NXLock.h> ! 53: #import <bsd/dev/evsio.h> ! 54: #import <bsd/dev/ppc/EventSrcPCPointer.h> ! 55: ! 56: #define MACSCALE 1 ! 57: ! 58: #if MACSCALE ! 59: #define MAXMAG 128 ! 60: static int scaleValues[MAXMAG]; ! 61: static int fractX,fractY; ! 62: #endif ! 63: ! 64: #define PC_PTR_DFLT_DELTA_T 2 ! 65: ! 66: // Default pointer acceleration or scaling table ! 67: static const unsigned int dfltPointerScaling[] = ! 68: { ! 69: 2, 2, // Threshold and scaling pairs ! 70: 3, 3, ! 71: 4, 5, ! 72: 5, 7, ! 73: 6, 10 ! 74: }; ! 75: ! 76: static EventSrcPCPointer *instance = (EventSrcPCPointer *)0; ! 77: ! 78: @implementation EventSrcPCPointer: IOEventSource ! 79: ! 80: int ! 81: FixMul( int a, int b) ! 82: { ! 83: union { ! 84: long long result; ! 85: int word[2]; ! 86: } big; ! 87: ! 88: big.result = ((long long) a) * ((long long) b) * 65536; ! 89: return( big.word[0] ); ! 90: } ! 91: ! 92: int ! 93: FixDiv( int a, int b) ! 94: { ! 95: return( (((long long) a) * 65536) / ((long long) b)); ! 96: } ! 97: ! 98: ! 99: // ! 100: // BEGIN: Implementation of Private EventSrcPCPointer methods ! 101: // ! 102: - scalePointerInX:(int *)dxp ! 103: andY:(int *)dyp ! 104: over:(unsigned)dt ! 105: atRes:(unsigned)res ! 106: // Description: Perform pointer acceleration computations here. ! 107: // Given the resolution, dx, dy, and time, compute the velocity ! 108: // of the pointer over a Manhatten distance in inches/second. ! 109: // Using this velocity, do a lookup in the pointerScaling table ! 110: // to select a scaling factor. Scale dx and dy up as appropriate. ! 111: // Preconditions: ! 112: // * deviceLock should be held on entry ! 113: { ! 114: int dx, dy; ! 115: int absDx, absDy; ! 116: unsigned delta, velocity; ! 117: int index; ! 118: ! 119: dx = *dxp; ! 120: dy = *dyp; ! 121: absDx = (dx < 0) ? -dx : dx; ! 122: absDy = (dy < 0) ? -dy : dy; ! 123: ! 124: #if MACSCALE ! 125: ! 126: #if 1 ! 127: if( absDx > absDy) ! 128: delta = (absDx + (absDy / 2)); ! 129: else ! 130: delta = (absDy + (absDx / 2)); ! 131: #else ! 132: delta = absDx + absDy; ! 133: #endif ! 134: ! 135: // scale ! 136: if( delta > (MAXMAG - 1)) ! 137: delta = MAXMAG - 1; ! 138: dx = FixMul( dx << 16, scaleValues[delta]); ! 139: dy = FixMul( dy << 16, scaleValues[delta]); ! 140: ! 141: // if no direction changes add fract parts ! 142: if( (dx ^ fractX) >= 0) ! 143: dx += fractX; ! 144: if( (dy ^ fractY) >= 0) ! 145: dy += fractY; ! 146: ! 147: *dxp = dx / 65536; ! 148: *dyp = dy / 65536; ! 149: ! 150: // get fractional part with sign extend ! 151: if( dx >= 0) ! 152: fractX = dx & 0xffff; ! 153: else ! 154: fractX = dx | 0xffff0000; ! 155: if( dy >= 0) ! 156: fractY = dy & 0xffff; ! 157: else ! 158: fractY = dy | 0xffff0000; ! 159: ! 160: #else ! 161: ! 162: // Take the sum of the X and Y distances as the delta to compute ! 163: // the velocity. (Manhatten distance) ! 164: delta = absDx + absDy; ! 165: if ( dt == 0 ) ! 166: dt = PC_PTR_DFLT_DELTA_T; ! 167: // ! 168: // Velocity in IPS = (delta in Dots * ticks/sec)/(res in DPI * dT) ! 169: // ! 170: // This is a bit heavyweight, and could probably be approximated ! 171: // with considerable savings. ! 172: // ! 173: velocity = (delta * EV_TICKS_PER_SEC) / (res * dt); ! 174: ! 175: // Look through the scalings for the first threshold greater than ! 176: // or equal to our velocity, and back off by one. ! 177: if ( velocity > pointerScaling.scaleThresholds[0] ) ! 178: { ! 179: for ( index = 1; index < pointerScaling.numScaleLevels; ++index ) ! 180: { ! 181: if ( velocity <= pointerScaling.scaleThresholds[index] ) ! 182: break; ! 183: } ! 184: --index; // Back off to get index covering our velocity. ! 185: *dxp = dx * pointerScaling.scaleFactors[index]; ! 186: *dyp = dy * pointerScaling.scaleFactors[index]; ! 187: } ! 188: ! 189: #endif ! 190: ! 191: return self; ! 192: } ! 193: ! 194: IOReturn ReadNVRAM( unsigned int offset, unsigned int length, unsigned char * buffer ); ! 195: ! 196: - setPointerScaling:(unsigned)numScalings data:(unsigned const *)scaleData ! 197: // Description: Set the pointer scaling factors and thresholds from the int ! 198: // array and count passed in here. There should be 2*numScaling ! 199: // ints in the scaleData array, packed with a threshold followed ! 200: // by a scaling factor. ! 201: // Preconditions: ! 202: // * deviceLock must not be held on entry ! 203: { ! 204: int i; ! 205: if ( numScalings > NX_MAXMOUSESCALINGS ) ! 206: numScalings = NX_MAXMOUSESCALINGS; // Clamp range ! 207: ! 208: [deviceLock lock]; ! 209: ! 210: #if MACSCALE ! 211: // a pale imitation of CrsrDev.a ! 212: { ! 213: static int deviceSpeed[] = { 0x000000, 0x00713b, 0x010000, 0x044ec5, 0x0c0000, 0x16ec4f, 0x1d3b14, 0x227627, 0x7ffffff }; ! 214: static int cursorSpeed[] = { 0x000000, 0x006000, 0x010000, 0x108000, 0x5f0000, 0x8b0000, 0x948000, 0x960000, 0x0960000 }; ! 215: ! 216: int slope,j = 0; ! 217: int x; ! 218: int devSpeed, crsrSpeed; ! 219: int lastCrsrSpeed, nextCrsrSpeed; ! 220: int lastDeviceSpeed, nextDeviceSpeed; ! 221: int accl = 0x008000; ! 222: ! 223: #if 0 ! 224: static int pram2Fixed[] = { 0x000000, 0x002000, 0x005000, 0x008000, 0x00b000, 0x00e000, 0x010000, 0x010000 }; ! 225: unsigned char abyte; ! 226: if( 0 == ReadNVRAM( 0x1300 + 8, 1, &abyte )) { ! 227: abyte = 7 & (abyte >> 3); ! 228: accl = pram2Fixed[ abyte ]; ! 229: } ! 230: #else ! 231: int nxMax = (*(scaleData + (2 * numScalings) - 1)) - 1; ! 232: if( nxMax > 18) ! 233: nxMax = 18; ! 234: accl = FixDiv( nxMax << 16, 18 << 16 ); ! 235: #endif ! 236: kprintf( "Mouse acceleration = 0x%x\n", accl); ! 237: ! 238: // scale for device speed ! 239: devSpeed = FixDiv( 90 << 16, resolution << 16 ); // no vbl sync, so 90 autopolls /s ! 240: // scale for cursor speed ! 241: crsrSpeed = FixDiv( 72 << 16, resolution << 16 ); // screen is 72 dpi ! 242: ! 243: nextCrsrSpeed = 0; ! 244: nextDeviceSpeed = 0; ! 245: ! 246: // Precalculate fixed point scales. Not as accurate as MacOS, but no FixDiv() in handler ! 247: for ( i = 1; i < MAXMAG; i++ ) ! 248: { ! 249: x = FixMul( i << 16, devSpeed ); ! 250: if( x > deviceSpeed[j]) { ! 251: lastCrsrSpeed = nextCrsrSpeed; ! 252: lastDeviceSpeed = nextDeviceSpeed; ! 253: j++; ! 254: nextDeviceSpeed = deviceSpeed[j]; ! 255: // Interpolate by accl between y=x and y=acclTable(x) to get nextCrsrSpeed ! 256: { ! 257: int factorCursor; ! 258: int factorDevice; ! 259: if( cursorSpeed[j] < nextDeviceSpeed) { ! 260: factorDevice = accl; ! 261: factorCursor = (0x10000 - accl); ! 262: } else { ! 263: factorCursor = accl; ! 264: factorDevice = (0x10000 - accl); ! 265: } ! 266: nextCrsrSpeed = FixMul( factorCursor, cursorSpeed[j] ) + FixMul( factorDevice, nextDeviceSpeed); ! 267: } ! 268: slope = FixDiv( nextCrsrSpeed - lastCrsrSpeed, nextDeviceSpeed - lastDeviceSpeed ); ! 269: } ! 270: scaleValues[i] = FixDiv( FixMul( crsrSpeed, FixMul( slope, x - lastDeviceSpeed ) + lastCrsrSpeed), x); ! 271: } ! 272: scaleValues[0] = scaleValues[1]; ! 273: fractX = fractY = 0; ! 274: } ! 275: #endif ! 276: ! 277: pointerScaling.numScaleLevels = numScalings; ! 278: for ( i = 0; i < numScalings; ++i ) ! 279: { ! 280: pointerScaling.scaleThresholds[i] = *scaleData++; ! 281: pointerScaling.scaleFactors[i] = *scaleData++; ! 282: } ! 283: ! 284: [deviceLock unlock]; ! 285: return self; ! 286: } ! 287: ! 288: - pointerScaling:(unsigned *)numScalings data:(unsigned *)scaleData ! 289: // Description: Return the pointer scaling factors and thresholds using the int ! 290: // array and count passed in here. On entry, *numScalings should ! 291: // reflect the max number of scaling entries scaleData can hold. ! 292: { ! 293: int i; ! 294: ! 295: [deviceLock lock]; ! 296: if ( *numScalings > pointerScaling.numScaleLevels ) ! 297: *numScalings = pointerScaling.numScaleLevels; // Clamp range ! 298: ! 299: for ( i = 0; i < *numScalings; ++i ) ! 300: { ! 301: *scaleData++ = pointerScaling.scaleThresholds[i]; ! 302: *scaleData++ = pointerScaling.scaleFactors[i]; ! 303: } ! 304: [deviceLock unlock]; ! 305: return self; ! 306: } ! 307: ! 308: - initPointer ! 309: // Description: Perform setup work needed to find and configure our ! 310: // PCPointer device. We have to tell it to send events to us. ! 311: // Preconditions: ! 312: // * deviceLock must be held on entry ! 313: { ! 314: if ((pointerDevice = [PCPointer activePointerDevice]) == nil) { ! 315: IOLog("initPointer: Can't find active pointer device\n"); ! 316: return nil; ! 317: } ! 318: if ( [pointerDevice respondsTo:@selector(setEventTarget:)] ) ! 319: [pointerDevice setEventTarget: self]; ! 320: else { ! 321: IOLog("initPointer: PCPointer0 does not respond to setEventTarget:\n"); ! 322: return nil; ! 323: } ! 324: [pointerDevice setEventTarget: self]; ! 325: return self; ! 326: } ! 327: ! 328: - resetPointer ! 329: { ! 330: [deviceLock lock]; ! 331: buttonMode = NX_OneButton; ! 332: [deviceLock unlock]; ! 333: // setPointerScaling will try to acquire deviceLock, so release it first. ! 334: [self setPointerScaling: ! 335: ((sizeof dfltPointerScaling/sizeof dfltPointerScaling[0])/2) ! 336: data:dfltPointerScaling]; ! 337: return self; ! 338: } ! 339: // ! 340: // END: Implementation of Private EventSrcPCPointer methods ! 341: // ! 342: ! 343: ! 344: // ! 345: // BEGIN: Implementation of PCPointerTarget protocol ! 346: // ! 347: - (void)dispatchPointerEvent:(PointerEvent *)event ! 348: // Description: This method is the heart of event dispatching. The underlying ! 349: // PCPointer object invokes this method with each event. ! 350: // The event structure passed in by reference should not be freed. ! 351: { ! 352: int buttons; ! 353: int dx; ! 354: int dy; ! 355: unsigned tick; ! 356: unsigned delta_t; ! 357: int menuButton; ! 358: ! 359: [deviceLock lock]; ! 360: ! 361: menuButton = (event->buttonCount > 1); ! 362: buttons = 0; ! 363: ! 364: if (event->b0 == 0) ! 365: buttons |= EV_LB; ! 366: ! 367: if( menuButton) { ! 368: if ((event->b1 || event->b2 || event->b3) == 0) // either down ! 369: buttons |= EV_RB; ! 370: } ! 371: ! 372: dx = event->dx; ! 373: dy = event->dy; ! 374: ! 375: // Convert the nanosecond time into a tick time since boot. ! 376: tick = EV_NS_TO_TICK(event->timeStamp); ! 377: ! 378: // Perform pointer acceleration computations ! 379: if ( lastPointerEvent == 0 ) ! 380: delta_t = PC_PTR_DFLT_DELTA_T; ! 381: else ! 382: delta_t = tick - lastPointerEvent; ! 383: ! 384: [self scalePointerInX:&dx ! 385: andY:&dy ! 386: over:delta_t ! 387: atRes:resolution]; ! 388: lastPointerEvent = tick; ! 389: ! 390: // Perform button tying and mapping. This ! 391: // stuff applies to relative posn devices (mice) only. ! 392: if ( buttonMode == NX_OneButton ) ! 393: { ! 394: if ( (buttons & (EV_LB|EV_RB)) != 0 ) ! 395: buttons = EV_LB; ! 396: } ! 397: else if ( menuButton && (buttonMode == NX_LeftButton) ) // Menus on left button. Swap! ! 398: { ! 399: int temp = 0; ! 400: if ( buttons & EV_LB ) ! 401: temp = EV_RB; ! 402: if ( buttons & EV_RB ) ! 403: temp |= EV_LB; ! 404: buttons = temp; ! 405: } ! 406: [deviceLock unlock]; ! 407: ! 408: [[self owner] relativePointerEvent:buttons ! 409: deltaX:dx ! 410: deltaY:dy ! 411: atTime:event->timeStamp]; ! 412: } ! 413: // ! 414: // END: Implementation of PCPointerTarget protocol ! 415: // ! 416: ! 417: ! 418: // ! 419: // BEGIN: Implementation of Exported EventSrcPCPointer methods ! 420: // ! 421: - init ! 422: // Description: Basic initialization stuff. ! 423: // Preconditions: ! 424: // * deviceLock must not be held on entry ! 425: { ! 426: id rtn; ! 427: ! 428: if ( deviceLock == nil ) ! 429: deviceLock = [NXLock new]; ! 430: [deviceLock lock]; ! 431: [super init]; ! 432: pointerDevice = nil; ! 433: buttonMode = NX_OneButton; ! 434: ! 435: rtn = [self initPointer]; ! 436: resolution = [pointerDevice getResolution]; ! 437: ! 438: [deviceLock unlock]; ! 439: // setPointerScaling will try to acquire deviceLock, so release it first. ! 440: [self setPointerScaling: ! 441: ((sizeof dfltPointerScaling/sizeof dfltPointerScaling[0])/2) ! 442: data:dfltPointerScaling]; ! 443: return rtn; ! 444: } ! 445: ! 446: + probe ! 447: // Description: This is our factory method. It is the IODevice probe ! 448: // routine for psuedo drivers. ! 449: { ! 450: if ( instance != nil ) ! 451: return instance; ! 452: ! 453: instance = [self alloc]; ! 454: ! 455: [instance setName:"EventSrcPCPointer0"]; ! 456: [instance setDeviceKind:"EventSrcPCPointer"]; ! 457: ! 458: if ( [instance init] == nil ) ! 459: [instance free]; // Zaps 'instance' on the way out ! 460: ! 461: return instance; ! 462: } ! 463: ! 464: - free ! 465: // Description: Go Away. Be careful when freeing the lock. ! 466: { ! 467: id lock; ! 468: ! 469: [deviceLock lock]; ! 470: instance = nil; ! 471: lock = deviceLock; ! 472: deviceLock = nil; ! 473: // Release pointer device, so we won't get any more events ! 474: if ( pointerDevice != nil ) ! 475: [pointerDevice setEventTarget:nil]; ! 476: [lock unlock]; ! 477: [lock free]; ! 478: return [super free]; ! 479: } ! 480: ! 481: ! 482: - (IOReturn)getIntValues:(unsigned *)parameterArray ! 483: forParameter:(IOParameterName)parameterName ! 484: count:(unsigned int *)count ! 485: { ! 486: IOReturn r = IO_R_INVALID_ARG; ! 487: NXEventSystemDevice *dp; ! 488: unsigned maxCount = *count; ! 489: unsigned *returnedCount = count; ! 490: ! 491: if ( strcmp( parameterName, EVSIOCMS ) == 0 ) // Pointer Scaling ! 492: { ! 493: parameterArray[EVSIOSMS_NSCALINGS] = (maxCount - 1)/2; ! 494: [self pointerScaling:¶meterArray[EVSIOSMS_NSCALINGS] ! 495: data:¶meterArray[EVSIOSMS_DATA]]; ! 496: *returnedCount = (parameterArray[EVSIOSMS_NSCALINGS] * 2) + 1; ! 497: r = IO_R_SUCCESS; ! 498: } ! 499: else if ( strcmp( parameterName, EVSIOCMH ) == 0 ) // Pointer Handedness ! 500: { ! 501: if ( maxCount >= EVSIOCMH_SIZE ) ! 502: { ! 503: *returnedCount = EVSIOCMH_SIZE; ! 504: [deviceLock lock]; ! 505: parameterArray[0] = buttonMode; ! 506: [deviceLock unlock]; ! 507: r = IO_R_SUCCESS; ! 508: } ! 509: } ! 510: else if ( strcmp( parameterName, EVSIOINFO ) == 0 ) // Device info ! 511: { ! 512: dp = (NXEventSystemDevice *) ¶meterArray[0]; ! 513: *returnedCount = 0; ! 514: // No need to lock device since we're not even reading the structure. ! 515: dp->interface = NX_EVS_DEVICE_INTERFACE_SERIAL_ACE; ! 516: dp->dev_type = NX_EVS_DEVICE_TYPE_MOUSE; ! 517: dp->interface_addr = 0; ! 518: dp->id = 0; ! 519: *returnedCount = sizeof (NXEventSystemDevice) / sizeof (int); ! 520: r = IO_R_SUCCESS; ! 521: } ! 522: else ! 523: { ! 524: r = [super getIntValues:parameterArray ! 525: forParameter: parameterName ! 526: count : count]; ! 527: if (r == IO_R_UNSUPPORTED) ! 528: r = IO_R_INVALID_ARG; ! 529: } ! 530: return r; ! 531: } ! 532: ! 533: - (IOReturn)getCharValues:(unsigned char *)parameterArray ! 534: forParameter:(IOParameterName)parameterName ! 535: count:(unsigned int *)count ! 536: { ! 537: return IO_R_INVALID_ARG; ! 538: } ! 539: ! 540: - (IOReturn)setIntValues:(unsigned *)parameterArray ! 541: forParameter:(IOParameterName)parameterName ! 542: count:(unsigned int)count ! 543: { ! 544: IOReturn r = IO_R_INVALID_ARG; ! 545: int cnt; ! 546: ! 547: if ( strcmp( parameterName, EVSIOSMS ) == 0 ) // Pointer Scaling ! 548: { ! 549: cnt = (parameterArray[EVSIOSMS_NSCALINGS] * 2) + 1; ! 550: if ( count <= EVSIOSMS_SIZE && cnt <= count ) ! 551: { ! 552: [self setPointerScaling:parameterArray[EVSIOSMS_NSCALINGS] ! 553: data:¶meterArray[EVSIOSMS_DATA]]; ! 554: r = IO_R_SUCCESS; ! 555: } ! 556: } ! 557: else if ( strcmp( parameterName, EVSIOSMH ) == 0 ) // Pointer Handedness ! 558: { ! 559: if ( count == EVSIOSMH_SIZE ) ! 560: { ! 561: [deviceLock lock]; ! 562: buttonMode = parameterArray[0]; ! 563: [deviceLock unlock]; ! 564: r = IO_R_SUCCESS; ! 565: } ! 566: } ! 567: else if ( strcmp( parameterName, EVSIORMS ) == 0 ) ! 568: { ! 569: r = IO_R_SUCCESS; ! 570: } ! 571: else ! 572: { ! 573: r = [super setIntValues:parameterArray ! 574: forParameter:parameterName ! 575: count : count]; ! 576: if (r == IO_R_UNSUPPORTED) ! 577: r = IO_R_INVALID_ARG; ! 578: } ! 579: return r; ! 580: } ! 581: // ! 582: // END: Implementation of Exported EventSrcPCPointer methods ! 583: // ! 584: @end
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.