Annotation of XNU/iokit/Drivers/usb/drvAppleMouse/AppleMouse.cpp, revision 1.1.1.1

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: 

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.