Annotation of XNU/iokit/Families/IOHIDSystem/IOHIKeyboard.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:  *
        !            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.