Annotation of XNU/iokit/Families/IOHIDSystem/IOHIPointing.cpp, revision 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:  * 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: }

unix.superglobalmegacorp.com

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