|
|
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: * Copyright (c) 1998 Apple Computer, Inc. All rights reserved.
24: *
25: * HISTORY
26: *
27: */
28:
29:
30: #include "AppleMouse.h"
31: #include <IOKit/hidsystem/IOHIPointing.h>
32: #include <IOKit/IOBufferMemoryDescriptor.h>
33: #include <IOKit/usb/IOUSBInterface.h>
34: #include <IOKit/usb/IOUSBPipe.h>
35: #include <libkern/OSByteOrder.h>
36: #include <IOKit/hidsystem/IOHIDShared.h>
37: #include <IOKit/hidsystem/IOHIDDescriptorParser.h>
38:
39: #define super IOHIPointing
40: #define DEBUGGING_LEVEL 0
41:
42: #define kMaxButtons 32 // Is this defined anywhere in the event headers?
43: #define kMaxValues 32 // This should be plenty big to find the X, Y and wheel values - is there some absolute max?
44:
45: OSDefineMetaClassAndStructors(AppleMouse, IOHIPointing)
46:
47: bool AppleMouse::start(IOService * provider)
48: {
49: IOReturn err = 0;
50:
51: if( !super::start(provider))
52: return (false);
53:
54: if( !provider->open(this))
55: return (false);
56:
57: // remember my device
58: _preparsedReportDescriptorData = NULL;
59: _buttonCollection = -1;
60: _xCollection = -1;
61: _yCollection = -1;
62: _tipPressureCollection = -1;
63: _digitizerButtonCollection = -1;
64: _scrollWheelCollection = -1;
65: _hasInRangeReport = false;
66: _tipPressureMin = 255;
67: _tipPressureMax = 255;
68: _numButtons = 1;
69:
70: _interface = OSDynamicCast(IOUSBInterface, provider);
71: _deviceDescriptor = _interface->deviceDescriptor();
72:
73: do {
74: IOUSBFindEndpointRequest request;
75:
76: IOLog("%s: USB Generic Mouse @ %d\n", getName(), _interface->address());
77:
78: request.type = kUSBInterrupt;
79: request.direction = kUSBIn;
80: _interruptPipe = _interface->findNextPipe(NULL, &request);
81:
82: if(!_interruptPipe)
83: return false;
84:
85: if (!parseHIDDescriptor()) {
86: break;
87: }
88:
89: _maxPacketSize = request.maxPacketSize;
90: _buffer = IOBufferMemoryDescriptor::withCapacity(8, kIODirectionIn);
91:
92: _completion.target = (void *)this;
93: _completion.action = (IOUSBCompletionAction) &AppleMouse::readHandler;
94: _completion.parameter = (void *)0; // not used
95:
96: _buffer->setLength(_maxPacketSize);
97:
98: if ((err = _interruptPipe->read(_buffer, &_completion)))
99: break;
100:
101: #if (DEBUGGING_LEVEL > 0)
102: printInterfaceDescriptor(_interface->descriptor);
103: #endif
104: return(true);
105:
106: } while (false);
107:
108: IOLog("%s: aborting startup. err = %d\n", getName(), err);
109:
110: provider->close(this);
111: stop(provider);
112:
113: return(false);
114: }
115:
116: bool AppleMouse::parseHIDDescriptor()
117: {
118: bool success = true;
119: IOReturn err;
120: IOUSBDevRequest devReq;
121: IOUSBHIDDescriptor hidDescriptor;
122: UInt8 * reportDescriptor = NULL;
123: UInt16 size = 0;
124: OSStatus result;
125: HIDButtonCaps buttonCaps[kMaxButtons];
126: UInt32 numButtonCaps = kMaxButtons;
127: HIDValueCaps valueCaps[kMaxValues];
128: UInt32 numValueCaps = kMaxValues;
129:
130: do {
131: devReq.rqDirection = kUSBIn;
132: devReq.rqType = kUSBStandard;
133: devReq.rqRecipient = kUSBInterface;
134: devReq.bRequest = kUSBRqGetDescriptor;
135: OSWriteLittleInt16(&devReq.wValue, 0, ((0x20 | kUSBHIDDesc) << 8));
136: OSWriteLittleInt16(&devReq.wIndex, 0, _interface->interfaceDescriptor()->interfaceNumber);
137: OSWriteLittleInt16(&devReq.wLength, 0, sizeof(IOUSBHIDDescriptor));
138: devReq.pData = &hidDescriptor;
139:
140: err = _interface->deviceRequest(&devReq);
141: if (err) {
142: IOLog ("%s: error getting HID Descriptor. err=0x%x\n", getName(), err);
143: success = false;
144: break;
145: }
146:
147: size = (hidDescriptor.hidDescriptorLengthHi * 256) + hidDescriptor.hidDescriptorLengthLo;
148: reportDescriptor = (UInt8 *)IOMalloc(size);
149:
150: OSWriteLittleInt16(&devReq.wValue, 0, ((0x20 | kUSBReportDesc) << 8));
151: OSWriteLittleInt16(&devReq.wLength, 0, size);
152: devReq.pData = reportDescriptor;
153:
154: err = _interface->deviceRequest(&devReq);
155: if (err) {
156: IOLog ("%s: error getting HID report descriptor. err=0x%x\n", getName(), err);
157: success = false;
158: break;
159: }
160:
161: result = HIDOpenReportDescriptor (reportDescriptor, size, &_preparsedReportDescriptorData, 0);
162: if (result != noErr) {
163: IOLog ("%s: error parsing HID report descriptor. err=0x%lx\n", getName(), result);
164: success = false;
165: break;
166: }
167:
168: result = HIDGetSpecificButtonCaps(kHIDInputReport,
169: kHIDPage_Button,
170: 0,
171: 0,
172: buttonCaps,
173: &numButtonCaps,
174: _preparsedReportDescriptorData);
175: if ((result == noErr) && (numButtonCaps > 0)) {
176: _buttonCollection = buttonCaps[0].collection; // Do we actually need to look at and store all of the button page collections?
177: if (buttonCaps[0].isRange) {
178: _numButtons = buttonCaps[0].u.range.usageMax - buttonCaps[0].u.range.usageMin + 1;
179: }
180:
181: }
182:
183: numButtonCaps = kMaxButtons;
184: result = HIDGetSpecificButtonCaps(kHIDInputReport,
185: kHIDPage_Digitizer,
186: 0,
187: 0,
188: buttonCaps,
189: &numButtonCaps,
190: _preparsedReportDescriptorData);
191: if ((result == noErr) && (numButtonCaps > 0)) {
192: _digitizerButtonCollection = buttonCaps[0].collection;
193: }
194:
195: numButtonCaps = kMaxButtons;
196: result = HIDGetSpecificButtonCaps(kHIDInputReport,
197: kHIDPage_Digitizer,
198: 0,
199: kHIDUsage_Dig_InRange,
200: buttonCaps,
201: &numButtonCaps,
202: _preparsedReportDescriptorData);
203: if (result == noErr) {
204: _hasInRangeReport = true;
205: }
206:
207: result = HIDGetSpecificValueCaps(kHIDInputReport,
208: kHIDPage_GenericDesktop,
209: 0,
210: kHIDUsage_GD_X,
211: valueCaps,
212: &numValueCaps,
213: _preparsedReportDescriptorData);
214: if ((result == noErr) && (numValueCaps > 0)) {
215: _xCollection = valueCaps[0].collection;
216: _absoluteCoordinates = valueCaps[0].isAbsolute;
217: _bounds.minx = valueCaps[0].logicalMin;
218: _bounds.maxx = valueCaps[0].logicalMax;
219: } else {
220: IOLog ("%s: error getting X axis information from HID report descriptor. err=0x%lx\n", getName(), result);
221: success = false;
222: break;
223: }
224:
225: numValueCaps = kMaxValues;
226: result = HIDGetSpecificValueCaps(kHIDInputReport,
227: kHIDPage_GenericDesktop,
228: 0,
229: kHIDUsage_GD_Y,
230: valueCaps,
231: &numValueCaps,
232: _preparsedReportDescriptorData);
233: if ((result == noErr) && (numValueCaps > 0)) {
234: _yCollection = valueCaps[0].collection;
235: _bounds.miny = valueCaps[0].logicalMin;
236: _bounds.maxy = valueCaps[0].logicalMax;
237: } else {
238: IOLog ("%s: error getting Y axis information from HID report descriptor. err=0x%lx\n", getName(), result);
239: success = false;
240: break;
241: }
242:
243: numValueCaps = kMaxValues;
244: result = HIDGetSpecificValueCaps(kHIDInputReport,
245: kHIDPage_Digitizer,
246: 0,
247: kHIDUsage_Dig_TipPressure,
248: valueCaps,
249: &numValueCaps,
250: _preparsedReportDescriptorData);
251: if ((result == noErr) && (numValueCaps > 0)) {
252: _tipPressureCollection = valueCaps[0].collection;
253: _tipPressureMin = valueCaps[0].logicalMin;
254: _tipPressureMax = valueCaps[0].logicalMax;
255: }
256:
257: numValueCaps = kMaxValues;
258: result = HIDGetSpecificValueCaps(kHIDInputReport,
259: kHIDPage_GenericDesktop,
260: 0,
261: kHIDUsage_GD_Wheel,
262: valueCaps,
263: &numValueCaps,
264: _preparsedReportDescriptorData);
265: if ((result == noErr) && (numValueCaps > 0)) {
266: _scrollWheelCollection = valueCaps[0].collection;
267: }
268: } while (false);
269:
270: if (reportDescriptor) {
271: IOFree(reportDescriptor, size);
272: }
273:
274: return success;
275: }
276:
277: void AppleMouse::stop(IOService * provider)
278: {
279: if (_buffer) {
280: _buffer->release();
281: _buffer = 0;
282: }
283: if (_preparsedReportDescriptorData) {
284: HIDCloseReportDescriptor(_preparsedReportDescriptorData);
285: }
286: super::stop(provider);
287: }
288:
289: void AppleMouse::readHandler(void * parameter,
290: IOReturn status,
291: UInt32 bufferSizeRemaining)
292: {
293: switch (status)
294: {
295: case kIOReturnSuccess:
296: break;
297:
298: case kIOReturnOverrun:
299: // Not sure what to do with this error. It means more data
300: // came back than the size of a descriptor. Hmmm. For now
301: // just ignore it and assume the data that did come back is
302: // useful.
303: IOLog("%s: overrun error. ignoring.\n", getName());
304: break;
305:
306: case kIOReturnNotResponding:
307: // This probably means the device was unplugged. Now
308: // we need to close the driver.
309: IOLog("%s: Device unplugged. Goodbye\n", getName());
310: goto close;
311:
312: default:
313: // We should handle other errors more intelligently, but
314: // for now just return and assume the error is recoverable.
315: IOLog("%s: error reading interrupt pipe\n", getName());
316: goto queueAnother;
317: }
318:
319: // Handle the data
320: MoveMouse((UInt8 *) _buffer->getBytesNoCopy(),
321: (UInt32) _maxPacketSize - bufferSizeRemaining);
322:
323: queueAnother:
324: // Reset the buffer
325: _buffer->setLength(_maxPacketSize);
326:
327: // Queue up another one before we leave.
328: if ((status = _interruptPipe->read(_buffer, &_completion)))
329: {
330: // This is bad. We probably shouldn't continue on from here.
331: IOLog("%s: immediate error %d queueing read\n", getName(), status);
332: goto close;
333: }
334:
335: return;
336:
337: close:
338: _interface->close(this);
339: return;
340: }
341:
342: void AppleMouse::MoveMouse(UInt8 * mouseData,
343: UInt32 ret_bufsize)
344: {
345: OSStatus status;
346: HIDUsage usageList[kMaxButtons];
347: UInt32 usageListSize = kMaxButtons;
348: UInt32 buttonState = 0;
349: SInt32 usageValue;
350: SInt32 pressure = MAXPRESSURE;
351: int dx = 0, dy = 0, scrollWheelDelta = 0;
352: AbsoluteTime now;
353: bool inRange = !_hasInRangeReport;
354:
355: if (_buttonCollection != -1) {
356: status = HIDGetButtonsOnPage (kHIDInputReport,
357: kHIDPage_Button,
358: _buttonCollection,
359: usageList,
360: &usageListSize,
361: _preparsedReportDescriptorData,
362: mouseData,
363: ret_bufsize);
364: if (status == noErr) {
365: UInt32 usageNum;
366: for (usageNum = 0; usageNum < usageListSize; usageNum++) {
367: if (usageList[usageNum] <= kMaxButtons) {
368: buttonState |= (1 << (usageList[usageNum] - 1));
369: }
370: }
371: }
372:
373: }
374:
375: if (_tipPressureCollection != -1) {
376: status = HIDGetUsageValue (kHIDInputReport,
377: kHIDPage_Digitizer,
378: _tipPressureCollection,
379: kHIDUsage_Dig_TipPressure,
380: &usageValue,
381: _preparsedReportDescriptorData,
382: mouseData,
383: ret_bufsize);
384: if (status == noErr) {
385: pressure = usageValue;
386: }
387: }
388:
389: if (_digitizerButtonCollection != -1) {
390: usageListSize = kMaxButtons;
391: status = HIDGetButtonsOnPage (kHIDInputReport,
392: kHIDPage_Digitizer,
393: _digitizerButtonCollection,
394: usageList,
395: &usageListSize,
396: _preparsedReportDescriptorData,
397: mouseData,
398: ret_bufsize);
399: if (status == noErr) {
400: UInt32 usageNum;
401: for (usageNum = 0; usageNum < usageListSize; usageNum++) {
402: switch (usageList[usageNum]) {
403: case kHIDUsage_Dig_BarrelSwitch:
404: buttonState |= 2; // Set the right (secondary) button for the barrel switch
405: break;
406: case kHIDUsage_Dig_TipSwitch:
407: buttonState |= 1; // Set the left (primary) button for the tip switch
408: break;
409: case kHIDUsage_Dig_InRange:
410: inRange = 1;
411: break;
412: default:
413: break;
414: }
415: }
416: }
417: }
418:
419: if (_scrollWheelCollection != -1) {
420: status = HIDGetUsageValue (kHIDInputReport,
421: kHIDPage_GenericDesktop,
422: _scrollWheelCollection,
423: kHIDUsage_GD_Wheel,
424: &usageValue,
425: _preparsedReportDescriptorData,
426: mouseData,
427: ret_bufsize);
428: if (status == noErr) {
429: scrollWheelDelta = usageValue;
430: }
431: }
432:
433: status = HIDGetUsageValue (kHIDInputReport,
434: kHIDPage_GenericDesktop,
435: _xCollection,
436: kHIDUsage_GD_X,
437: &usageValue,
438: _preparsedReportDescriptorData,
439: mouseData,
440: ret_bufsize);
441: if (status == noErr) {
442: dx = usageValue;
443: }
444:
445: status = HIDGetUsageValue (kHIDInputReport,
446: kHIDPage_GenericDesktop,
447: _yCollection,
448: kHIDUsage_GD_Y,
449: &usageValue,
450: _preparsedReportDescriptorData,
451: mouseData,
452: ret_bufsize);
453: if (status == noErr) {
454: dy = usageValue;
455: }
456:
457: clock_get_uptime(&now);
458:
459: if (_absoluteCoordinates) {
460: Point newLoc;
461:
462: newLoc.x = dx;
463: newLoc.y = dy;
464:
465: dispatchAbsolutePointerEvent(&newLoc, &_bounds, buttonState, inRange, pressure, _tipPressureMin, _tipPressureMax, 90, now);
466: } else {
467: dispatchRelativePointerEvent(dx, dy, buttonState, now);
468: }
469:
470: if (scrollWheelDelta != 0) {
471: dispatchScrollWheelEvent(scrollWheelDelta, 0, 0, now);
472: }
473: }
474:
475: UInt32 AppleMouse::interfaceID( void )
476: {
477: return( NX_EVS_DEVICE_INTERFACE_OTHER );
478: }
479:
480: UInt32 AppleMouse::deviceType( void )
481: {
482: return( 0 );
483: }
484:
485: /*
486: * This was taken directly from the AppleADBMouse driver.
487: * We need to determine the best generic acceleration curve for USB devices.
488: */
489:
490: void AppleMouse::accelerationTable ( IOHIAccelerationPoint ** table, IOItemCount * numEntries )
491: {
492: static IOHIAccelerationPoint defaultTable[] = {
493: { 0x0000000, 0x000000 },
494: { 0x000713b, 0x006000 },
495: { 0x0010000, 0x010000 },
496: { 0x0044ec5, 0x108000 },
497: { 0x00c0000, 0x5f0000 },
498: { 0x016ec4f, 0x8b0000 },
499: { 0x01d3b14, 0x948000 },
500: { 0x0227627, 0x960000 },
501: { 0x7ffffff, 0x960000 }
502: };
503:
504: *table = defaultTable;
505: *numEntries = sizeof(defaultTable) / sizeof(defaultTable[0]);
506: }
507:
508: IOFixed AppleMouse::resolution()
509: {
510: return (400 << 16);
511: }
512:
513: IOItemCount AppleMouse::buttonCount()
514: {
515: return _numButtons;
516: }
517:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.