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