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/IOLib.h> 26 27#include "IOHIDKeyboardDevice.h" 28 29typedef struct __attribute__((packed)) GenericKeyboardRpt { 30 UInt8 modifiers; 31 UInt8 reserved; 32 UInt8 keys[6]; 33} GenericKeyboardRpt; 34 35static UInt8 gGenLEDKeyboardDesc[] = { 36 0x05, 0x01, // Usage Page (Generic Desktop) 37 0x09, 0x06, // Usage (Keyboard) 38 0xA1, 0x01, // Collection (Application) 39 0x05, 0x07, // Usage Page (Keyboard/Keypad) 40 0x19, 0xE0, // Usage Minimum........... (224) 41 0x29, 0xE7, // Usage Maximum........... (231) 42 0x15, 0x00, // Logical Minimum......... (0) 43 0x25, 0x01, // Logical Maximum......... (1) 44 0x75, 0x01, // Report Size............. (1) 45 0x95, 0x08, // Report Count............ (8) 46 0x81, 0x02, // Input...................(Data, Variable, Absolute) 47 0x95, 0x01, // Report Count............ (1) 48 0x75, 0x08, // Report Size............. (8) 49 0x81, 0x01, // Input...................(Constant) 50 0x95, 0x02, // Report Count............ (2) 51 0x75, 0x01, // Report Size............. (1) 52 0x05, 0x08, // Usage Page (LED) 53 0x19, 0x01, // Usage Minimum........... (1) 54 0x29, 0x02, // Usage Maximum........... (2) 55 0x91, 0x02, // Output..................(Data, Variable, Absolute) 56 0x95, 0x01, // Report Count............ (1) 57 0x75, 0x06, // Report Size............. (6) 58 0x91, 0x01, // Output..................(Constant) 59 0x95, 0x06, // Report Count............ (6) 60 0x75, 0x08, // Report Size............. (8) 61 0x15, 0x00, // Logical Minimum......... (0) 62 0x26, 0xFF, 0x00, // Logical Maximum......... (255) 63 0x05, 0x07, // Usage Page (Keyboard/Keypad) 64 0x19, 0x00, // Usage Minimum........... (0) 65 0x29, 0xFF, // Usage Maximum........... (255) 66 0x81, 0x00, // Input...................(Data, Array, Absolute) 67 0xC0, // End Collection 68}; 69 70static UInt8 gGenKeyboardDesc[] = { 71 0x05, 0x01, // Usage Page (Generic Desktop) 72 0x09, 0x06, // Usage (Keyboard) 73 0xA1, 0x01, // Collection (Application) 74 0x05, 0x07, // Usage Page (Keyboard/Keypad) 75 0x19, 0xE0, // Usage Minimum........... (224) 76 0x29, 0xE7, // Usage Maximum........... (231) 77 0x15, 0x00, // Logical Minimum......... (0) 78 0x25, 0x01, // Logical Maximum......... (1) 79 0x75, 0x01, // Report Size............. (1) 80 0x95, 0x08, // Report Count............ (8) 81 0x81, 0x02, // Input...................(Data, Variable, Absolute) 82 0x95, 0x01, // Report Count............ (1) 83 0x75, 0x08, // Report Size............. (8) 84 0x81, 0x01, // Input...................(Constant) 85 0x95, 0x06, // Report Count............ (6) 86 0x75, 0x08, // Report Size............. (8) 87 0x15, 0x00, // Logical Minimum......... (0) 88 0x26, 0xFF, 0x00, // Logical Maximum......... (255) 89 0x05, 0x07, // Usage Page (Keyboard/Keypad) 90 0x19, 0x00, // Usage Minimum........... (0) 91 0x29, 0xFF, // Usage Maximum........... (255) 92 0x81, 0x00, // Input...................(Data, Array, Absolute) 93 0xC0, // End Collection 94}; 95 96extern unsigned int hid_adb_2_usb_keymap[]; //In Cosmo_USB2ADB.cpp 97 98#define super IOHIDDeviceShim 99 100OSDefineMetaClassAndStructors( IOHIDKeyboardDevice, IOHIDDeviceShim ) 101 102 103IOHIDKeyboardDevice * 104IOHIDKeyboardDevice::newKeyboardDeviceAndStart(IOService * owner, UInt32 location) 105{ 106 IOService * provider = owner; 107 108 while ( NULL != (provider = provider->getProvider()) ) 109 { 110 if(OSDynamicCast(IOHIDDevice, provider) || OSDynamicCast(IOHIDevice, provider)) 111 return 0; 112 } 113 114 115 IOHIDKeyboardDevice * device = new IOHIDKeyboardDevice; 116 117 if (device) 118 { 119 if ( device->initWithLocation(location) && device->attach(owner) ) 120 { 121 if (!device->start(owner)) 122 { 123 device->detach(owner); 124 device->release(); 125 device = 0; 126 } 127 } 128 else 129 { 130 device->release(); 131 device = 0; 132 } 133 } 134 135 return device; 136} 137 138 139bool IOHIDKeyboardDevice::initWithLocation( UInt32 location ) 140{ 141 if (!super::initWithLocation(location)) 142 return false; 143 144 _report = 0; 145 _cachedLEDState = 0; 146 _inputReportOnly = true; 147 148 return true; 149} 150 151void IOHIDKeyboardDevice::free() 152{ 153 if (_report) _report->release(); 154 155 super::free(); 156} 157 158bool IOHIDKeyboardDevice::handleStart( IOService * provider ) 159{ 160 if (!super::handleStart(provider)) 161 return false; 162 163 if ( (_keyboard = OSDynamicCast(IOHIKeyboard, provider)) ) 164 { 165 _inputReportOnly = ((transport() == kIOHIDTransportADB) && (_keyboard->deviceType() >= 0xc3)); 166 _cachedLEDState = _keyboard->getLEDStatus() & 0x3; 167 } 168 169 _report = IOBufferMemoryDescriptor::withCapacity( 170 sizeof(GenericKeyboardRpt), kIODirectionNone, true); 171 172 bzero(_report->getBytesNoCopy(), sizeof(GenericKeyboardRpt)); 173 174 return (_report) ? true : false; 175} 176 177IOReturn IOHIDKeyboardDevice::newReportDescriptor( 178 IOMemoryDescriptor ** descriptor ) const 179{ 180 void * desc; 181 UInt8 * descBytes; 182 UInt8 descSize; 183 184 if (!descriptor) 185 return kIOReturnBadArgument; 186 187 if (_inputReportOnly) 188 { 189 descSize = sizeof(gGenKeyboardDesc); 190 descBytes = gGenKeyboardDesc; 191 } 192 else 193 { 194 descSize = sizeof(gGenLEDKeyboardDesc); 195 descBytes = gGenLEDKeyboardDesc; 196 } 197 198 *descriptor = IOBufferMemoryDescriptor::withCapacity( 199 descSize, 200 kIODirectionNone, 201 true); 202 203 if (! *descriptor) 204 return kIOReturnNoMemory; 205 206 desc = ((IOBufferMemoryDescriptor *)(*descriptor))->getBytesNoCopy(); 207 bcopy(descBytes, desc, descSize); 208 209 return kIOReturnSuccess; 210} 211 212IOReturn IOHIDKeyboardDevice::getReport(IOMemoryDescriptor *report, 213 IOHIDReportType reportType, 214 IOOptionBits options __unused ) 215{ 216 if (!report) 217 return kIOReturnError; 218 219 if ( reportType != kIOHIDReportTypeInput) 220 return kIOReturnUnsupported; 221 222 report->writeBytes(0, _report->getBytesNoCopy(), min(report->getLength(), _report->getLength())); 223 return kIOReturnSuccess; 224} 225 226IOReturn IOHIDKeyboardDevice::setReport(IOMemoryDescriptor * report, 227 IOHIDReportType reportType __unused, 228 IOOptionBits options ) 229{ 230 UInt8 ledState; 231 UInt8 mask; 232 233 if ((options & 0xff) || (_inputReportOnly) || !_keyboard) 234 return kIOReturnError; 235 236 report->readBytes( 0, (void *)&ledState, sizeof(UInt8) ); 237 238 mask = (1 << (kHIDUsage_LED_NumLock - 1)); 239 if ( (ledState & mask) && !(_cachedLEDState & mask) ) 240 { 241 _keyboard->setNumLockFeedback(true); 242 } 243 else if ( !(ledState & mask) && (_cachedLEDState & mask) ) 244 { 245 _keyboard->setNumLockFeedback(false); 246 } 247 248 mask = (1 << (kHIDUsage_LED_CapsLock - 1)); 249 if ( (ledState & mask) && !(_cachedLEDState & mask) ) 250 { 251 _keyboard->setAlphaLockFeedback(true); 252 } 253 else if ( !(ledState & mask) && (_cachedLEDState & mask) ) 254 { 255 _keyboard->setAlphaLockFeedback(false); 256 } 257 258 _cachedLEDState = ledState; 259 260 return kIOReturnSuccess; 261} 262 263void IOHIDKeyboardDevice::setCapsLockLEDElement(bool state) 264{ 265 UInt8 mask = (1 << (kHIDUsage_LED_CapsLock-1)); 266 267 if (_inputReportOnly) 268 return; 269 270 if (state) 271 _cachedLEDState |= mask; 272 273 else 274 _cachedLEDState &= ~mask; 275 276 *(UInt8 *)(_report->getBytesNoCopy()) = _cachedLEDState; 277 278 handleReport(_report, kIOHIDReportTypeOutput); 279} 280 281void IOHIDKeyboardDevice::setNumLockLEDElement(bool state) 282{ 283 UInt8 mask = (1 << (kHIDUsage_LED_NumLock-1)); 284 285 if (_inputReportOnly) 286 return; 287 288 if (state) 289 _cachedLEDState |= mask; 290 291 else 292 _cachedLEDState &= ~mask; 293 294 *(UInt8 *)(_report->getBytesNoCopy()) = _cachedLEDState; 295 296 handleReport(_report, kIOHIDReportTypeOutput); 297} 298 299#define SET_MODIFIER_BIT(bitField, key, down) \ 300 if (down) {bitField |= (1 << (key - 0xe0));} \ 301 else {bitField &= ~(1 << (key - 0xe0));} 302 303void IOHIDKeyboardDevice::postKeyboardEvent(UInt8 key, bool keyDown) 304{ 305 GenericKeyboardRpt *report = (GenericKeyboardRpt *)_report->getBytesNoCopy(); 306 UInt8 usbKey; 307 308 if (!report) 309 return; 310 311 // Convert ADB scan code to USB 312 if (! (usbKey = hid_adb_2_usb_keymap[key])) 313 return; 314 315 // Check if modifier 316 if ((usbKey >= 0xe0) && (usbKey <= 0xe7)) 317 { 318 SET_MODIFIER_BIT(report->modifiers, usbKey, keyDown); 319 } 320 else 321 { 322 for (int i=0; i<6; i++) 323 { 324 if (report->keys[i] == usbKey) 325 { 326 if (keyDown) return; 327 328 for (int j=i; j<5; j++) 329 report->keys[j] = report->keys[j+1]; 330 331 report->keys[5] = 0; 332 break; 333 } 334 335 else if ((report->keys[i] == 0) && keyDown) 336 { 337 report->keys[i] = usbKey; 338 break; 339 } 340 } 341 } 342 343 handleReport(_report); 344} 345 346enum { 347 kUSB_LEFT_CONTROL_BIT = 0x01, 348 kUSB_LEFT_SHIFT_BIT = 0x02, 349 kUSB_LEFT_ALT_BIT = 0x04, 350 kUSB_LEFT_FLOWER_BIT = 0x08, 351 352 kUSB_RIGHT_CONTROL_BIT = 0x10, 353 kUSB_RIGHT_SHIFT_BIT = 0x20, 354 kUSB_RIGHT_ALT_BIT = 0x040, 355 kUSB_RIGHT_FLOWER_BIT = 0x80 356}; 357 358void IOHIDKeyboardDevice::postFlagKeyboardEvent(UInt32 flags) 359{ 360 GenericKeyboardRpt *report = (GenericKeyboardRpt *)_report->getBytesNoCopy(); 361 UInt32 flagDelta = (flags ^ _lastFlags); 362 363 if (!flagDelta) 364 return; 365 366 report->modifiers = 0; 367 _lastFlags = flags; 368 369 if ( flagDelta & 0x0000ffff ) 370 { 371 if( flags & NX_DEVICELSHIFTKEYMASK ) 372 report->modifiers |= kUSB_LEFT_SHIFT_BIT; 373 if( flags & NX_DEVICELCTLKEYMASK ) 374 report->modifiers |= kUSB_LEFT_CONTROL_BIT; 375 if( flags & NX_DEVICELALTKEYMASK ) 376 report->modifiers |= kUSB_LEFT_ALT_BIT; 377 if( flags & NX_DEVICELCMDKEYMASK ) 378 report->modifiers |= kUSB_LEFT_FLOWER_BIT; 379 380 if( flags & NX_DEVICERSHIFTKEYMASK ) 381 report->modifiers |= kUSB_RIGHT_SHIFT_BIT; 382 if( flags & NX_DEVICERCTLKEYMASK ) 383 report->modifiers |= kUSB_RIGHT_CONTROL_BIT; 384 if( flags & NX_DEVICERALTKEYMASK ) 385 report->modifiers |= kUSB_RIGHT_ALT_BIT; 386 if( flags & NX_DEVICERCMDKEYMASK ) 387 report->modifiers |= kUSB_RIGHT_FLOWER_BIT; 388 } 389 else if ( flagDelta & 0xffff0000 ) 390 { 391 if( flags & NX_SHIFTMASK ) 392 report->modifiers |= kUSB_LEFT_SHIFT_BIT; 393 if( flags & NX_CONTROLMASK ) 394 report->modifiers |= kUSB_LEFT_CONTROL_BIT; 395 if( flags & NX_ALTERNATEMASK ) 396 report->modifiers |= kUSB_LEFT_ALT_BIT; 397 if( flags & NX_COMMANDMASK ) 398 report->modifiers |= kUSB_LEFT_FLOWER_BIT; 399 } 400 401 if ( flagDelta & NX_ALPHASHIFTMASK ) 402 { 403 postKeyboardEvent(0x39, flags & NX_ALPHASHIFTMASK); 404 return; 405 } 406 407 handleReport(_report); 408} 409 410OSString * IOHIDKeyboardDevice::newProductString() const 411{ 412 OSString * string = 0; 413 414 if ( !(string = super::newProductString()) ) 415 string = OSString::withCString("Virtual Keyboard"); 416 417 return string; 418} 419