|
|
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.