1/* 2 * 3 * @APPLE_LICENSE_HEADER_START@ 4 * 5 * Copyright (c) 1999-2003 Apple Computer, Inc. All Rights Reserved. 6 * 7 * This file contains Original Code and/or Modifications of Original Code 8 * as defined in and that are subject to the Apple Public Source License 9 * Version 2.0 (the 'License'). You may not use this file except in 10 * compliance with the License. Please obtain a copy of the License at 11 * http://www.opensource.apple.com/apsl/ and read it before using this 12 * file. 13 * 14 * The Original Code and all software distributed under the License are 15 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER 16 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, 17 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, 18 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. 19 * Please see the License for the specific language governing rights and 20 * limitations under the License. 21 * 22 * @APPLE_LICENSE_HEADER_END@ 23 */ 24 25#include <IOKit/IOKitKeys.h> 26 27#include <IOKit/hidsystem/ev_keymap.h> 28#include <IOKit/hidsystem/IOHIDShared.h> 29#include <IOKit/hidsystem/IOHIDUsageTables.h> 30 31#include "IOHIDElement.h" 32#include "IOHIDConsumer.h" 33#include "AppleHIDUsageTables.h" 34 35 36//==================================================================================================== 37// Defines 38//==================================================================================================== 39 40#define super IOHIKeyboard 41 42#define DEBUGGING_LEVEL 0 43 44OSDefineMetaClassAndStructors( IOHIDConsumer, IOHIKeyboard ) 45 46//==================================================================================================== 47// Consumer - constructor 48//==================================================================================================== 49IOHIDConsumer * 50IOHIDConsumer::Consumer(bool isDispatcher) 51{ 52 IOHIDConsumer *consumer = new IOHIDConsumer; 53 54 if ((consumer == 0) || !consumer->init()) 55 { 56 if (consumer) consumer->release(); 57 return 0; 58 } 59 60 consumer->_isDispatcher = isDispatcher; 61 62 return consumer; 63} 64 65//==================================================================================================== 66// init 67//==================================================================================================== 68bool 69IOHIDConsumer::init(OSDictionary *properties) 70{ 71 if (!super::init(properties)) return false; 72 73 _otherEventFlags = 0; 74 _otherCapsLockOn = FALSE; 75 76 _repeat = true; 77 setRepeatMode(_repeat); 78 79 return true; 80} 81 82//==================================================================================================== 83// start 84//==================================================================================================== 85bool IOHIDConsumer::start(IOService * provider) 86{ 87 setProperty(kIOHIDVirtualHIDevice, kOSBooleanTrue); 88 89 return super::start(provider); 90} 91 92//==================================================================================================== 93// stop 94//==================================================================================================== 95void IOHIDConsumer::stop(IOService * provider) 96{ 97 OSSafeReleaseNULL(_keyboardNub); 98 super::stop(provider); 99} 100 101 102void IOHIDConsumer::dispatchConsumerEvent( 103 IOHIDKeyboard * sendingkeyboardNub, 104 AbsoluteTime timeStamp, 105 UInt32 usagePage, 106 UInt32 usage, 107 UInt32 value, 108 IOOptionBits options) 109{ 110 SInt32 keyCode = -1; 111 bool repeat = ((options & kHIDDispatchOptionKeyboardNoRepeat) == 0); 112 113 if (usagePage == kHIDPage_Consumer) 114 { 115 switch(usage) 116 { 117 case kHIDUsage_Csmr_Power: 118 case kHIDUsage_Csmr_Reset: 119 case kHIDUsage_Csmr_Sleep: 120 keyCode = NX_POWER_KEY; 121 break; 122 case kHIDUsage_Csmr_Play: 123 case kHIDUsage_Csmr_PlayOrPause: 124 case kHIDUsage_Csmr_PlayOrSkip: 125 keyCode = NX_KEYTYPE_PLAY; 126 break; 127 case kHIDUsage_Csmr_ScanNextTrack: 128 keyCode = NX_KEYTYPE_NEXT; 129 break; 130 case kHIDUsage_Csmr_ScanPreviousTrack: 131 keyCode = NX_KEYTYPE_PREVIOUS; 132 break; 133 case kHIDUsage_Csmr_FastForward: 134 keyCode = NX_KEYTYPE_FAST; 135 break; 136 case kHIDUsage_Csmr_Rewind: 137 keyCode = NX_KEYTYPE_REWIND; 138 break; 139 case kHIDUsage_Csmr_StopOrEject: 140 case kHIDUsage_Csmr_Eject: 141 keyCode = NX_KEYTYPE_EJECT; 142 break; 143 case kHIDUsage_Csmr_VolumeIncrement: 144 keyCode = NX_KEYTYPE_SOUND_UP; 145 break; 146 case kHIDUsage_Csmr_VolumeDecrement: 147 keyCode = NX_KEYTYPE_SOUND_DOWN; 148 break; 149 case kHIDUsage_Csmr_Mute: 150 keyCode = NX_KEYTYPE_MUTE; 151 break; 152 case kHIDUsage_Csmr_DisplayBrightnessIncrement: 153 keyCode = NX_KEYTYPE_BRIGHTNESS_UP; 154 break; 155 case kHIDUsage_Csmr_DisplayBrightnessDecrement: 156 keyCode = NX_KEYTYPE_BRIGHTNESS_DOWN; 157 break; 158 default: 159 break; 160 } 161 } 162 else if (usagePage == kHIDPage_GenericDesktop) 163 { 164 switch (usage) 165 { 166 case kHIDUsage_GD_SystemPowerDown: 167 case kHIDUsage_GD_SystemSleep: 168 case kHIDUsage_GD_SystemWakeUp: 169 keyCode = NX_POWER_KEY; 170 break; 171 } 172 } 173 else if (usagePage == kHIDPage_AppleVendorTopCase) 174 { 175 switch (usage) 176 { 177 case kHIDUsage_AV_TopCase_BrightnessUp: 178 keyCode = NX_KEYTYPE_BRIGHTNESS_UP; 179 break; 180 case kHIDUsage_AV_TopCase_BrightnessDown: 181 keyCode = NX_KEYTYPE_BRIGHTNESS_DOWN; 182 break; 183 case kHIDUsage_AV_TopCase_VideoMirror: 184 keyCode = NX_KEYTYPE_VIDMIRROR; 185 break; 186 case kHIDUsage_AV_TopCase_IlluminationDown: 187 keyCode = NX_KEYTYPE_ILLUMINATION_DOWN; 188 break; 189 case kHIDUsage_AV_TopCase_IlluminationUp: 190 keyCode = NX_KEYTYPE_ILLUMINATION_UP; 191 break; 192 case kHIDUsage_AV_TopCase_IlluminationToggle: 193 keyCode = NX_KEYTYPE_ILLUMINATION_TOGGLE; 194 break; 195 } 196 } 197 else if ((usagePage == kHIDPage_KeyboardOrKeypad) && 198 (usage == kHIDUsage_KeyboardLockingNumLock)) 199 { 200 keyCode = NX_KEYTYPE_NUM_LOCK; 201 } 202 203 204 if (keyCode == -1) 205 return; 206 207 if (repeat != _repeat) 208 { 209 _repeat = repeat; 210 setRepeatMode(_repeat); 211 } 212 213 //Copy the device flags (modifier flags) from the ADB keyboard driver 214 OSSafeReleaseNULL(_keyboardNub); 215 if ( NULL != (_keyboardNub = sendingkeyboardNub) ) 216 { 217 UInt32 currentFlags; 218 219 currentFlags = deviceFlags() & ~_cachedEventFlags; 220 _cachedEventFlags = _keyboardNub->deviceFlags(); 221 currentFlags |= _cachedEventFlags; 222 _deviceType = _keyboardNub->deviceType(); 223 224 setDeviceFlags(currentFlags); 225 _keyboardNub->retain(); 226 } 227 else 228 { 229 findKeyboardsAndGetModifiers(); 230 } 231 232 dispatchKeyboardEvent( keyCode, value, timeStamp ); 233} 234 235//==================================================================================================== 236// eventFlags - IOHIKeyboard override. This is necessary because we will need to return the state 237// of the modifier keys on attached keyboards. If we don't, then we the HIDSystem gets 238// the event, it will look like all modifiers are off. 239//==================================================================================================== 240unsigned IOHIDConsumer::eventFlags() 241{ 242 unsigned flags = 0; 243 244 flags = (_keyboardNub) ? _keyboardNub->eventFlags() : _otherEventFlags; 245 246 return( flags ); 247} 248 249//==================================================================================================== 250// deviceFlags - IOHIKeyboard override. This is necessary because we will need to return the state 251// of the modifier keys on attached keyboards. If we don't, then we the HIDSystem gets 252// the event, it will look like all modifiers are off. 253//==================================================================================================== 254unsigned IOHIDConsumer::deviceFlags() 255{ 256 unsigned flags = 0; 257 258 flags = (_keyboardNub) ? _keyboardNub->deviceFlags() : _otherEventFlags; 259 260 return( flags ); 261} 262 263//==================================================================================================== 264// setDeviceFlags - IOHIKeyboard override. This is necessary because we will need to return the state 265// of the modifier keys on attached keyboards. If we don't, then we the HIDSystem gets 266// the event, it will look like all modifiers are off. 267//==================================================================================================== 268void IOHIDConsumer::setDeviceFlags(unsigned flags) 269{ 270 if ( _keyboardNub ) 271 _keyboardNub->setDeviceFlags(flags); 272 273 super::setDeviceFlags(flags); 274} 275 276 277//==================================================================================================== 278// alphaLock - IOHIKeyboard override. This is necessary because we will need to return the state 279// of the caps lock keys on attached keyboards. If we don't, then we the HIDSystem gets 280// the event, it will look like caps lock keys are off. 281//==================================================================================================== 282bool IOHIDConsumer::alphaLock() 283{ 284 bool state = false; 285 286 state = (_keyboardNub) ? _keyboardNub->alphaLock() : _otherCapsLockOn; 287 288 return( state ); 289} 290 291//==================================================================================================== 292// setNumLock - IOHIKeyboard override. This is necessary because we will need to toggle the num lock 293// led on the keyboard interface 294//==================================================================================================== 295void IOHIDConsumer::setNumLock(bool val) 296{ 297 if (_keyboardNub) _keyboardNub->setNumLock(val); 298} 299 300//==================================================================================================== 301// numLock - IOHIKeyboard override. This is necessary because we will need to check the num lock 302// status on the keyboard interface 303//==================================================================================================== 304bool IOHIDConsumer::numLock() 305{ 306 bool state = false; 307 308 state = (_keyboardNub) ? _keyboardNub->numLock() : super::numLock(); 309 310 return( state ); 311} 312 313//==================================================================================================== 314// doesKeyLock - IOHIKeyboard override. This is necessary because the system will only toggle the led 315// and set appropriate event flags if the num lock key physically locks. 316//==================================================================================================== 317bool IOHIDConsumer:: doesKeyLock ( unsigned key) 318{ 319 if ( key == NX_KEYTYPE_NUM_LOCK ) 320 return true; 321 322 return false; 323} 324 325//==================================================================================================== 326// defaultKeymapOfLength - IOHIKeyboard override 327// This allows us to associate the scancodes we choose with the special 328// keys we are interested in posting later. This gives us auto-repeats for free. Kewl. 329//==================================================================================================== 330const unsigned char * IOHIDConsumer::defaultKeymapOfLength( UInt32 * length ) 331{ 332 static const unsigned char ConsumerKeyMap[] = 333 { 334 // The first 16 bits are always read first, to determine if the rest of 335 // the keymap is in shorts (16 bits) or bytes (8 bits). If the first 16 bits 336 // equals 0, data is in bytes; if first 16 bits equal 1, data is in shorts. 337 338 0x00,0x00, // data is in bytes 339 340 // The next value is the number of modifier keys. We have none in our driver. 341 342 0x00, 343 344 // The next value is number of key definitions. We have none in our driver. 345 346 0x00, 347 348 // The next value is number of of sequence definitions there are. We have none. 349 350 0x00, 351 352 // The next value is the number of special keys. We use these. 353 354 NX_NUMSPECIALKEYS, 355 356 // Special Key SCANCODE 357 //----------------------------------------------------------- 358 359 NX_KEYTYPE_SOUND_UP, NX_KEYTYPE_SOUND_UP, 360 NX_KEYTYPE_SOUND_DOWN, NX_KEYTYPE_SOUND_DOWN, 361 NX_KEYTYPE_BRIGHTNESS_UP, NX_KEYTYPE_BRIGHTNESS_UP, 362 NX_KEYTYPE_BRIGHTNESS_DOWN, NX_KEYTYPE_BRIGHTNESS_DOWN, 363 NX_KEYTYPE_CAPS_LOCK, NX_KEYTYPE_CAPS_LOCK, 364 NX_KEYTYPE_HELP, NX_KEYTYPE_HELP, 365 NX_POWER_KEY, NX_POWER_KEY, 366 NX_KEYTYPE_MUTE, NX_KEYTYPE_MUTE, 367 NX_UP_ARROW_KEY, NX_UP_ARROW_KEY, 368 NX_DOWN_ARROW_KEY, NX_DOWN_ARROW_KEY, 369 NX_KEYTYPE_NUM_LOCK, NX_KEYTYPE_NUM_LOCK, 370 NX_KEYTYPE_CONTRAST_UP, NX_KEYTYPE_CONTRAST_UP, 371 NX_KEYTYPE_CONTRAST_DOWN, NX_KEYTYPE_CONTRAST_DOWN, 372 NX_KEYTYPE_LAUNCH_PANEL, NX_KEYTYPE_LAUNCH_PANEL, 373 NX_KEYTYPE_EJECT, NX_KEYTYPE_EJECT, 374 NX_KEYTYPE_VIDMIRROR, NX_KEYTYPE_VIDMIRROR, 375 NX_KEYTYPE_PLAY, NX_KEYTYPE_PLAY, 376 NX_KEYTYPE_NEXT, NX_KEYTYPE_NEXT, 377 NX_KEYTYPE_PREVIOUS, NX_KEYTYPE_PREVIOUS, 378 NX_KEYTYPE_FAST, NX_KEYTYPE_FAST, 379 NX_KEYTYPE_REWIND, NX_KEYTYPE_REWIND, 380 NX_KEYTYPE_ILLUMINATION_UP, NX_KEYTYPE_ILLUMINATION_UP, 381 NX_KEYTYPE_ILLUMINATION_DOWN, NX_KEYTYPE_ILLUMINATION_DOWN, 382 NX_KEYTYPE_ILLUMINATION_TOGGLE, NX_KEYTYPE_ILLUMINATION_TOGGLE 383 384 }; 385 386 387 if( length ) *length = sizeof( ConsumerKeyMap ); 388 389 return( ConsumerKeyMap ); 390} 391 392//==================================================================================================== 393// findKeyboardsAndGetModifiers 394//==================================================================================================== 395UInt32 IOHIDConsumer::findKeyboardsAndGetModifiers() 396{ 397 OSIterator *iterator = NULL; 398 OSDictionary *matchingDictionary = NULL; 399 IOHIKeyboard *device = NULL; 400 401 _otherEventFlags = 0; 402 _cachedEventFlags = 0; 403 _otherCapsLockOn = FALSE; 404 405 // Get matching dictionary. 406 407 matchingDictionary = IOService::serviceMatching( "IOHIKeyboard" ); 408 if( !matchingDictionary ) 409 { 410 goto exit; 411 } 412 413 // Get an iterator for the IOHIKeyboard devices. 414 415 iterator = IOService::getMatchingServices( matchingDictionary ); 416 if( !iterator ) 417 { 418 goto exit; 419 } 420 421 // User iterator to find devices and eject. 422 // 423 while( (device = (IOHIKeyboard*) iterator->getNextObject()) ) 424 { 425 426 //Ignore the eventFlags keyboards that don't have modifiers defined 427 if (!device->getProperty(kIOHIDKeyboardSupportedModifiersKey)) 428 continue; 429 430 // Save the caps lock state. If more than one keyboard has it down, that's fine -- we 431 // just want to know if ANY keyboards have the key down. 432 // 433 if( device->alphaLock() ) 434 { 435 _otherCapsLockOn = TRUE; 436 } 437 438 // OR in the flags, so we get a combined IOHIKeyboard device flags state. That 439 // way, if the user is pressing command on one keyboard, shift on another, and 440 // then hits an eject key, we'll get both modifiers. 441 // 442 _otherEventFlags |= device->eventFlags(); 443 } 444 445exit: 446 447 if( matchingDictionary ) matchingDictionary->release(); 448 if( iterator ) iterator->release(); 449 450 return( _otherEventFlags ); 451} 452 453