Annotation of XNU/iokit/Families/IOHIDSystem/IOHIKeyboard.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:  *
                     24:  * From EventSrcPCKeyoard.m - PC Keyboard EventSrc subclass implementation
                     25:  *     Copyright (c) 1992 NeXT Computer, Inc.  All rights reserved. 
                     26:  */
                     27: 
                     28: #include <IOKit/IOLib.h>
                     29: #include <IOKit/hidsystem/IOHIKeyboard.h>
                     30: #include <IOKit/hidsystem/IOHIKeyboardMapper.h>
                     31: #include <IOKit/hidsystem/IOLLEvent.h>
                     32: #include <IOKit/hidsystem/IOHIDParameter.h>
                     33: 
                     34: #define super IOHIDevice
                     35: OSDefineMetaClassAndStructors(IOHIKeyboard, IOHIDevice);
                     36: 
                     37: bool IOHIKeyboard::init(OSDictionary * properties)
                     38: {
                     39:   if (!super::init(properties))  return false;
                     40: 
                     41:   /*
                     42:    * Initialize minimal state.
                     43:    */
                     44: 
                     45:   _deviceLock   = IOLockAlloc();
                     46:   _keyMap       = 0;
                     47:   _keyStateSize = 4*((maxKeyCodes()+(EVK_BITS_PER_UNIT-1))/EVK_BITS_PER_UNIT);
                     48:   _keyState     = (UInt32 *) IOMalloc(_keyStateSize);
                     49: 
                     50:   if (!_deviceLock || !_keyState)  return false;
                     51: 
                     52:   IOLockInit(_deviceLock);
                     53:   bzero(_keyState, _keyStateSize);
                     54: 
                     55:   return true;
                     56: }
                     57: 
                     58: bool IOHIKeyboard::start(IOService * provider)
                     59: {
                     60:   if (!super::start(provider))  return false;
                     61: 
                     62:   /*
                     63:    * IOHIKeyboard serves both as a service and a nub (we lead a double
                     64:    * life).  Register ourselves as a nub to kick off matching.
                     65:    */
                     66: 
                     67:   registerService();
                     68: 
                     69:   return true;
                     70: }
                     71: 
                     72: void IOHIKeyboard::free()
                     73: // Description:        Go Away. Be careful when freeing the lock.
                     74: {
                     75:     IOLock * lock = NULL;
                     76:     
                     77:     if ( _deviceLock )
                     78:     {
                     79:       lock = _deviceLock;
                     80:       IOTakeLock( lock);
                     81:       _deviceLock = NULL;
                     82:     }
                     83:     if ( _keyMap )
                     84:        _keyMap->release();
                     85:     if( _keyState )
                     86:         IOFree( _keyState, _keyStateSize);
                     87:     if ( lock )
                     88:     {
                     89:       IOUnlock( lock);
                     90:       IOLockFree( lock);
                     91:     }
                     92:     super::free();
                     93: }
                     94: 
                     95: IOHIDKind IOHIKeyboard::hidKind()
                     96: {
                     97:   return kHIKeyboardDevice;
                     98: }
                     99: 
                    100: bool IOHIKeyboard::updateProperties( void )
                    101: {
                    102:     UInt64     keyRepeatNano;
                    103:     UInt64     initialKeyRepeatNano;
                    104:     bool       ok;
                    105:     
                    106:     absolutetime_to_nanoseconds( _keyRepeat, &keyRepeatNano);
                    107:     absolutetime_to_nanoseconds( _initialKeyRepeat, &initialKeyRepeatNano);
                    108: 
                    109:     ok = setProperty( kIOHIDKeyMappingKey, _keyMap )
                    110:     &    setProperty( kIOHIDKeyRepeatKey, &keyRepeatNano,
                    111:                       sizeof(keyRepeatNano))
                    112:     &    setProperty( kIOHIDInitialKeyRepeatKey, &initialKeyRepeatNano,
                    113:                       sizeof(initialKeyRepeatNano));
                    114: 
                    115:     return( ok & super::updateProperties() );
                    116: }
                    117: 
                    118: IOReturn IOHIKeyboard::setParamProperties( OSDictionary * dict )
                    119: {
                    120:     OSData *           data;
                    121:     IOReturn           err = kIOReturnSuccess;
                    122:     unsigned char *    map;
                    123:     IOHIKeyboardMapper * oldMap;
                    124:     bool               updated = false;
                    125:     UInt64             nano;
                    126:     IOTakeLock( _deviceLock);
                    127: 
                    128:     if( (data = OSDynamicCast( OSData,
                    129:                dict->getObject(kIOHIDKeyRepeatKey)))) {
                    130: 
                    131:         nano = *((UInt64 *)(data->getBytesNoCopy()));
                    132:         if( nano < EV_MINKEYREPEAT)
                    133:             nano = EV_MINKEYREPEAT;
                    134:         nanoseconds_to_absolutetime(nano, &_keyRepeat);
                    135:         updated = true;
                    136:     }
                    137: 
                    138:     if( (data = OSDynamicCast( OSData,
                    139:                dict->getObject(kIOHIDInitialKeyRepeatKey)))) {
                    140: 
                    141:         nano = *((UInt64 *)(data->getBytesNoCopy()));
                    142:         if( nano < EV_MINKEYREPEAT)
                    143:             nano = EV_MINKEYREPEAT;
                    144:         nanoseconds_to_absolutetime(nano, &_initialKeyRepeat);
                    145:        updated = true;
                    146:     }
                    147: 
                    148:     if( (data = OSDynamicCast( OSData, dict->getObject(kIOHIDKeyMappingKey)))) {
                    149: 
                    150:        map = (unsigned char *)IOMalloc( data->getLength() );
                    151:        bcopy( data->getBytesNoCopy(), map, data->getLength() );
                    152:        oldMap = _keyMap;
                    153:        _keyMap = IOHIKeyboardMapper::keyboardMapper(this, map, data->getLength(), true);
                    154:         if (_keyMap) {
                    155:            if (oldMap)
                    156:                oldMap->release();
                    157:             updated = true;
                    158:        } else {
                    159:            _keyMap = oldMap;
                    160:            err = kIOReturnBadArgument;
                    161:        } 
                    162:     }
                    163:     IOUnlock( _deviceLock);
                    164: 
                    165:     if( dict->getObject(kIOHIDResetKeyboardKey))
                    166:        resetKeyboard();
                    167: 
                    168:     if( updated )
                    169:         updateProperties();
                    170: 
                    171:     return( err );
                    172: }
                    173: 
                    174: bool IOHIKeyboard::resetKeyboard()
                    175: // Description:        Reset the keymapping to the default value and reconfigure
                    176: //             the keyboards.
                    177: {
                    178:     const unsigned char *defaultKeymap;
                    179:     UInt32     defaultKeymapLength;
                    180: 
                    181:     IOTakeLock( _deviceLock);
                    182: 
                    183:     if ( _keyMap )
                    184:        _keyMap->release();
                    185: 
                    186:     // Set up default keymapping.
                    187:     defaultKeymap = defaultKeymapOfLength(&defaultKeymapLength);
                    188: 
                    189:     _keyMap = IOHIKeyboardMapper::keyboardMapper( this,
                    190:                                                   defaultKeymap,
                    191:                                                   defaultKeymapLength,
                    192:                                                   false );
                    193:     if (_keyMap)
                    194:     {
                    195:         clock_interval_to_absolutetime_interval( EV_DEFAULTKEYREPEAT,
                    196:                                                  kNanosecondScale, &_keyRepeat);
                    197:         clock_interval_to_absolutetime_interval( EV_DEFAULTINITIALREPEAT,
                    198:                                                  kNanosecondScale, &_initialKeyRepeat);
                    199:     }
                    200: 
                    201:     updateProperties();
                    202: 
                    203:     IOUnlock( _deviceLock);
                    204:     return (_keyMap) ? true : false;
                    205: }
                    206: 
                    207: void IOHIKeyboard::scheduleAutoRepeat()
                    208: // Description:        Schedule a procedure to be called when a timeout has expired
                    209: //             so that we can generate a repeated key.
                    210: // Preconditions:
                    211: // *   _deviceLock should be held on entry
                    212: {
                    213:     if ( _calloutPending == true )
                    214:     {
                    215:         thread_call_func_cancel(_autoRepeat, this, true);
                    216:        _calloutPending = false;
                    217:     }
                    218:     if ( AbsoluteTime_to_scalar(&_downRepeatTime) )
                    219:     {
                    220:         AbsoluteTime deadline;
                    221:         clock_absolutetime_interval_to_deadline(_downRepeatTime, &deadline);
                    222:         thread_call_func_delayed(_autoRepeat, this, deadline);
                    223:        _calloutPending = true;
                    224:     }
                    225: }
                    226: 
                    227: void IOHIKeyboard::_autoRepeat(thread_call_param_t arg,
                    228:                                thread_call_param_t)         /* thread_call_func_t */
                    229: {
                    230:     IOHIKeyboard *self = (IOHIKeyboard *) arg;
                    231:     self->autoRepeat();
                    232: }
                    233: 
                    234: void IOHIKeyboard::autoRepeat()
                    235: // Description:        Repeat the currently pressed key and schedule ourselves
                    236: //             to be called again after another interval elapses.
                    237: // Preconditions:
                    238: // *   Should only be executed on callout thread
                    239: // *   _deviceLock should be unlocked on entry.
                    240: {    
                    241:     IOTakeLock( _deviceLock);
                    242:     if ( _calloutPending == false )
                    243:     {
                    244:        IOUnlock( _deviceLock);
                    245:        return;
                    246:     }
                    247:     _calloutPending = false;
                    248:     _isRepeat = true;
                    249: 
                    250:     if ( AbsoluteTime_to_scalar(&_downRepeatTime) )
                    251:     {
                    252:        // Device is due to generate a repeat
                    253:        if (_keyMap)  _keyMap->translateKeyCode(_codeToRepeat,
                    254:                                 /* direction */ true,
                    255:                                 /* keyBits */   _keyState);
                    256:        _downRepeatTime = _keyRepeat;
                    257:     }
                    258: 
                    259:     _isRepeat = false;
                    260:     scheduleAutoRepeat();
                    261:     IOUnlock( _deviceLock);
                    262: }
                    263: 
                    264: void IOHIKeyboard::setRepeat(unsigned eventType, unsigned keyCode)
                    265: // Description:        Set up or tear down key repeat operations. The method
                    266: //             that locks _deviceLock is a bit higher on the call stack.
                    267: //             This method is invoked as a side effect of our own
                    268: //             invocation of _keyMap->translateKeyCode().
                    269: // Preconditions:
                    270: // *   _deviceLock should be held upon entry.
                    271: {
                    272:     if ( _isRepeat == false )  // make sure we're not already repeating
                    273:     {
                    274:        if (eventType == NX_KEYDOWN)    // Start repeat
                    275:        {
                    276:            // Set this key to repeat (push out last key if present)
                    277:            _downRepeatTime = _initialKeyRepeat; // + _lastEventTime; 
                    278:            _codeToRepeat = keyCode;
                    279:            // reschedule key repeat event here
                    280:            scheduleAutoRepeat();
                    281:        }
                    282:        else if (eventType == NX_KEYUP) // End repeat
                    283:        {
                    284:            /* Remove from downKey */
                    285:            if (_codeToRepeat == keyCode)
                    286:            {
                    287:                 AbsoluteTime_to_scalar(&_downRepeatTime) = 0;
                    288:                _codeToRepeat = (unsigned)-1;
                    289:                scheduleAutoRepeat();
                    290:            }
                    291:        }
                    292:     }
                    293: }
                    294: 
                    295: //
                    296: // BEGIN:      Implementation of the methods required by IOHIKeyboardMapper.
                    297: //
                    298: 
                    299: void IOHIKeyboard::keyboardEvent(unsigned eventType,
                    300:        /* flags */              unsigned flags,
                    301:        /* keyCode */            unsigned keyCode,
                    302:        /* charCode */           unsigned charCode,
                    303:        /* charSet */            unsigned charSet,
                    304:        /* originalCharCode */   unsigned origCharCode,
                    305:        /* originalCharSet */    unsigned origCharSet)
                    306: // Description: We use this notification to set up our _keyRepeat timer
                    307: //             and to pass along the event to our owner. This method
                    308: //             will be called while the KeyMap object is processing
                    309: //             the key code we've sent it using deliverKey.
                    310: {
                    311: 
                    312:     if (_keyboardEventAction)     /* upstream call */ 
                    313:     {
                    314:       (*_keyboardEventAction)(_keyboardEventTarget,
                    315:                               eventType,
                    316:        /* flags */            flags,
                    317:        /* keyCode */          keyCode,
                    318:        /* charCode */         charCode,
                    319:        /* charSet */          charSet,
                    320:        /* originalCharCode */ origCharCode,
                    321:        /* originalCharSet */  origCharSet,
                    322:        /* repeat */           _isRepeat,
                    323:        /* atTime */           _lastEventTime);
                    324:     }
                    325: 
                    326:     // Set up key repeat operations here.
                    327:     setRepeat(eventType, keyCode);
                    328: }
                    329: 
                    330: void IOHIKeyboard::keyboardSpecialEvent(unsigned eventType,
                    331:        /* flags */                     unsigned flags,
                    332:        /* keyCode */                   unsigned keyCode,
                    333:        /* specialty */                 unsigned flavor)
                    334: // Description: See the description for keyboardEvent.
                    335: {
                    336: 
                    337:     if (_keyboardSpecialEventAction)         /* upstream call */
                    338:     {
                    339:       (*_keyboardSpecialEventAction)(_keyboardSpecialEventTarget,
                    340:                                      eventType,
                    341:                      /* flags */     flags,
                    342:                      /* keyCode */   keyCode,
                    343:                      /* specialty */ flavor,
                    344:                      /* atTime */    _lastEventTime);
                    345:     }
                    346: 
                    347:     // Set up key repeat operations here.
                    348:     if (flavor != NX_KEYTYPE_CAPS_LOCK)
                    349:        setRepeat(eventType, keyCode);
                    350: }
                    351: 
                    352: void IOHIKeyboard::updateEventFlags(unsigned flags)
                    353: // Description:        Process non-event-generating flag changes. Simply pass this
                    354: //             along to our owner.
                    355: {
                    356:   if (_updateEventFlagsAction)              /* upstream call */
                    357:   {
                    358:     (*_updateEventFlagsAction)(_updateEventFlagsTarget, flags);
                    359:   }
                    360: }
                    361: 
                    362: unsigned IOHIKeyboard::eventFlags()
                    363: // Description:        Return global event flags In this world, there is only
                    364: //             one keyboard device so device flags == global flags.
                    365: {
                    366:     return _eventFlags;
                    367: }
                    368: 
                    369: unsigned IOHIKeyboard::deviceFlags()
                    370: // Description: Return per-device event flags. In this world, there is only
                    371: //             one keyboard device so device flags == global flags.
                    372: {
                    373:     return _eventFlags;
                    374: }
                    375: 
                    376: void IOHIKeyboard::setDeviceFlags(unsigned flags)
                    377: // Description: Set device event flags. In this world, there is only
                    378: //             one keyboard device so device flags == global flags.
                    379: {
                    380:     _eventFlags = flags;
                    381: }
                    382: 
                    383: bool IOHIKeyboard::alphaLock()
                    384: // Description: Return current alpha-lock state. This is a state tracking
                    385: //             callback used by the KeyMap object.
                    386: {
                    387:     return _alphaLock;
                    388: }
                    389: 
                    390: void IOHIKeyboard::setAlphaLock(bool val)
                    391: // Description: Set current alpha-lock state This is a state tracking
                    392: //             callback used by the KeyMap object.
                    393: {
                    394:     _alphaLock = val;
                    395:     setAlphaLockFeedback(val);
                    396: }
                    397: 
                    398: bool IOHIKeyboard::charKeyActive()
                    399: // Description: Return true If a character generating key down This is a state
                    400: //             tracking callback used by the KeyMap object.
                    401: {
                    402:     return _charKeyActive;
                    403: }
                    404: 
                    405: void IOHIKeyboard::setCharKeyActive(bool val)
                    406: // Description: Note whether a char generating key is down. This is a state
                    407: //             tracking callback used by the KeyMap object.
                    408: {
                    409:     _charKeyActive = val;
                    410: }
                    411: //
                    412: // END:                Implementation of the methods required by IOHIKeyboardMapper.
                    413: //
                    414: 
                    415: void IOHIKeyboard::dispatchKeyboardEvent(unsigned int keyCode,
                    416:                         /* direction */ bool         goingDown,
                    417:                          /* timeStamp */ AbsoluteTime time)
                    418: // Description:        This method is the heart of event dispatching. The overlying
                    419: //             subclass invokes this method with each event. We then
                    420: //             get the event xlated and dispatched using a _keyMap instance.
                    421: //             The event structure passed in by reference should not be freed.
                    422: {
                    423:     _lastEventTime = time;
                    424: 
                    425:     IOTakeLock( _deviceLock);
                    426: 
                    427:     if (_keyMap)  _keyMap->translateKeyCode(keyCode,
                    428:                          /* direction */ goingDown,
                    429:                          /* keyBits */   _keyState);
                    430:     IOUnlock( _deviceLock);
                    431: }
                    432: 
                    433: const unsigned char * IOHIKeyboard::defaultKeymapOfLength(UInt32 * length)
                    434: {
                    435:     *length = 0;
                    436:     return NULL;
                    437: }
                    438: 
                    439: void IOHIKeyboard::setAlphaLockFeedback(bool /* val */)
                    440: {
                    441:     return;
                    442: }
                    443: 
                    444: UInt32 IOHIKeyboard::maxKeyCodes()
                    445: {
                    446:     return( 0x80);
                    447: }
                    448: 
                    449: bool IOHIKeyboard::open(IOService *                client,
                    450:                        IOOptionBits               options,
                    451:                         KeyboardEventAction        keAction,
                    452:                         KeyboardSpecialEventAction kseAction,
                    453:                         UpdateEventFlagsAction     uefAction)
                    454: {
                    455:   if ( (!_keyMap) && (!resetKeyboard()))  return false;
                    456: 
                    457:   if (super::open(client, options))
                    458:   {
                    459:     // Note: client object is already retained by superclass' open()
                    460:     _keyboardEventTarget        = client;
                    461:     _keyboardEventAction        = keAction;
                    462:     _keyboardSpecialEventTarget = client;
                    463:     _keyboardSpecialEventAction = kseAction;
                    464:     _updateEventFlagsTarget     = client;
                    465:     _updateEventFlagsAction     = uefAction;
                    466: 
                    467:     return true;
                    468:   }
                    469: 
                    470:   return false;
                    471: }
                    472: 
                    473: void IOHIKeyboard::close(IOService * client, IOOptionBits)
                    474: {
                    475:        // kill autorepeat task
                    476:         AbsoluteTime_to_scalar(&_downRepeatTime) = 0;
                    477:        _codeToRepeat = (unsigned)-1;
                    478:        scheduleAutoRepeat();
                    479:        // clear modifiers to avoid stuck keys
                    480:        setAlphaLock(false);
                    481:        if (_updateEventFlagsAction)
                    482:          (*_updateEventFlagsAction)(_updateEventFlagsTarget, 0);       _eventFlags = 0;
                    483:        bzero(_keyState, _keyStateSize);
                    484: 
                    485:         _keyboardEventAction        = NULL;
                    486:         _keyboardEventTarget        = 0;
                    487:         _keyboardSpecialEventAction = NULL;
                    488:         _keyboardSpecialEventTarget = 0;
                    489:         _updateEventFlagsAction     = NULL;
                    490:         _updateEventFlagsTarget     = 0;
                    491: 
                    492:        super::close(client);
                    493: }
                    494: 

unix.superglobalmegacorp.com

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