#include "global.h" #include "KeyboardDevice.h" using namespace __gnu_cxx; bool KeyboardDevice::AddLogicalDevice( int usagePage, int usage ) { return usagePage == kHIDPage_GenericDesktop && usage == kHIDUsage_GD_Keyboard; } static bool UsbKeyToDeviceButton( UInt8 iUsbKey, DeviceButton &buttonOut ) { UInt8 usage = iUsbKey; if( usage < kHIDUsage_KeyboardA ) return false; if( usage <= kHIDUsage_KeyboardZ ) { buttonOut = enum_add2( KEY_Ca, usage - kHIDUsage_KeyboardA ); return true; } // KEY_C0 = KEY_C1 - 1, kHIDUsage_Keyboard0 = kHIDUsage_Keyboard9 + 1 if( usage <= kHIDUsage_Keyboard9 ) { buttonOut = enum_add2( KEY_C1, usage - kHIDUsage_Keyboard1 ); return true; } if( usage >= kHIDUsage_KeyboardF1 && usage <= kHIDUsage_KeyboardF12 ) { buttonOut = enum_add2( KEY_F1, usage - kHIDUsage_KeyboardF1 ); return true; } if( usage >= kHIDUsage_KeyboardF13 && usage <= kHIDUsage_KeyboardF16 ) { buttonOut = enum_add2( KEY_F13, usage - kHIDUsage_KeyboardF13 ); return true; } // keypad 0 is again backward if( usage >= kHIDUsage_Keypad1 && usage <= kHIDUsage_Keypad9 ) { buttonOut = enum_add2( KEY_KP_C1, usage - kHIDUsage_Keypad1 ); return true; } #define OTHER(n) (enum_add2(KEY_OTHER_0, (n))) // [0, 8] if( usage >= kHIDUsage_KeyboardF17 && usage <= kHIDUsage_KeyboardExecute ) { buttonOut = OTHER( 0 + usage - kHIDUsage_KeyboardF17 ); return true; } // [9, 19] if( usage >= kHIDUsage_KeyboardSelect && usage <= kHIDUsage_KeyboardVolumeDown ) { buttonOut = OTHER( 9 + usage - kHIDUsage_KeyboardSelect ); return true; } // [20, 41] if( usage >= kHIDUsage_KeypadEqualSignAS400 && usage <= kHIDUsage_KeyboardCancel ) { buttonOut = OTHER( 20 + usage - kHIDUsage_KeypadEqualSignAS400 ); return true; } // [42, 47] // XXX kHIDUsage_KeyboardClearOrAgain if( usage >= kHIDUsage_KeyboardSeparator && usage <= kHIDUsage_KeyboardExSel ) { buttonOut = OTHER( 32 + usage - kHIDUsage_KeyboardSeparator ); return true; } #define X(x,y) case x: buttonOut = y; return true // Time for the special cases switch( usage ) { X( kHIDUsage_Keyboard0, KEY_C0 ); X( kHIDUsage_Keypad0, KEY_KP_C0 ); X( kHIDUsage_KeyboardReturnOrEnter, KEY_ENTER ); X( kHIDUsage_KeyboardEscape, KEY_ESC ); X( kHIDUsage_KeyboardDeleteOrBackspace, KEY_BACK ); X( kHIDUsage_KeyboardTab, KEY_TAB ); X( kHIDUsage_KeyboardSpacebar, KEY_SPACE ); X( kHIDUsage_KeyboardHyphen, KEY_HYPHEN ); X( kHIDUsage_KeyboardEqualSign, KEY_EQUAL ); X( kHIDUsage_KeyboardOpenBracket, KEY_LBRACKET ); X( kHIDUsage_KeyboardCloseBracket, KEY_RBRACKET ); X( kHIDUsage_KeyboardBackslash, KEY_BACKSLASH ); X( kHIDUsage_KeyboardNonUSPound, KEY_HASH ); X( kHIDUsage_KeyboardSemicolon, KEY_SEMICOLON ); X( kHIDUsage_KeyboardQuote, KEY_SQUOTE ); X( kHIDUsage_KeyboardGraveAccentAndTilde, KEY_ACCENT ); X( kHIDUsage_KeyboardComma, KEY_COMMA ); X( kHIDUsage_KeyboardPeriod, KEY_PERIOD ); X( kHIDUsage_KeyboardSlash, KEY_SLASH ); X( kHIDUsage_KeyboardCapsLock, KEY_CAPSLOCK ); X( kHIDUsage_KeyboardPrintScreen, KEY_PRTSC ); X( kHIDUsage_KeyboardScrollLock, KEY_SCRLLOCK ); X( kHIDUsage_KeyboardPause, KEY_PAUSE ); X( kHIDUsage_KeyboardInsert, KEY_INSERT ); X( kHIDUsage_KeyboardHome, KEY_HOME ); X( kHIDUsage_KeyboardPageUp, KEY_PGUP ); X( kHIDUsage_KeyboardDeleteForward, KEY_DEL ); X( kHIDUsage_KeyboardEnd, KEY_END ); X( kHIDUsage_KeyboardPageDown, KEY_PGDN ); X( kHIDUsage_KeyboardRightArrow, KEY_RIGHT ); X( kHIDUsage_KeyboardLeftArrow, KEY_LEFT ); X( kHIDUsage_KeyboardDownArrow, KEY_DOWN ); X( kHIDUsage_KeyboardUpArrow, KEY_UP ); X( kHIDUsage_KeypadNumLock, KEY_NUMLOCK ); X( kHIDUsage_KeypadSlash, KEY_KP_SLASH ); X( kHIDUsage_KeypadEqualSign, KEY_KP_EQUAL ); X( kHIDUsage_KeypadAsterisk, KEY_KP_ASTERISK ); X( kHIDUsage_KeypadHyphen, KEY_KP_HYPHEN ); X( kHIDUsage_KeypadPlus, KEY_KP_PLUS ); X( kHIDUsage_KeypadEnter, KEY_KP_ENTER ); X( kHIDUsage_KeypadPeriod, KEY_KP_PERIOD ); X( kHIDUsage_KeyboardNonUSBackslash, OTHER(48) ); X( kHIDUsage_KeyboardApplication, OTHER(49) ); X( kHIDUsage_KeyboardClear, KEY_NUMLOCK ); // XXX X( kHIDUsage_KeyboardHelp, KEY_INSERT ); X( kHIDUsage_KeyboardMenu, KEY_MENU ); // XXX kHIDUsage_KeyboardLockingCapsLock // XXX kHIDUsage_KeyboardLockingNumLock // XXX kHIDUsage_KeyboardLockingScrollLock X( kHIDUsage_KeypadComma, KEY_KP_PERIOD ); // XXX X( kHIDUsage_KeyboardReturn, KEY_ENTER ); X( kHIDUsage_KeyboardPrior, OTHER(50) ); X( kHIDUsage_KeyboardLeftControl, KEY_LCTRL ); X( kHIDUsage_KeyboardLeftShift, KEY_LSHIFT ); X( kHIDUsage_KeyboardLeftAlt, KEY_LALT ); X( kHIDUsage_KeyboardLeftGUI, KEY_LMETA ); X( kHIDUsage_KeyboardRightControl, KEY_RCTRL ); X( kHIDUsage_KeyboardRightShift, KEY_RSHIFT ); X( kHIDUsage_KeyboardRightAlt, KEY_RALT ); X( kHIDUsage_KeyboardRightGUI, KEY_RMETA ); } #undef X #undef OTHER return false; } void KeyboardDevice::AddElement( int usagePage, int usage, IOHIDElementCookie cookie, const CFDictionaryRef properties ) { if( usagePage != kHIDPage_KeyboardOrKeypad ) return; DeviceButton button; if( UsbKeyToDeviceButton(usage,button) ) m_Mapping[cookie] = button; } void KeyboardDevice::Open() { for( hash_map::const_iterator i = m_Mapping.begin(); i != m_Mapping.end(); ++i ) { //LOG->Trace( "Adding %s to queue, cookie %p", DeviceButtonToString(i->second).c_str(), i->first ); AddElementToQueue( i->first ); } } void KeyboardDevice::GetButtonPresses( vector& vPresses, IOHIDElementCookie cookie, int value, const RageTimer& now ) const { hash_map::const_iterator iter = m_Mapping.find( cookie ); if( iter != m_Mapping.end() ) { //LOG->Trace( "Pushed %s", DeviceButtonToString(iter->second).c_str() ); vPresses.push_back( DeviceInput(DEVICE_KEYBOARD, iter->second, value, now) ); } } void KeyboardDevice::GetDevicesAndDescriptions( vector& vDevices ) const { if( vDevices.size() && vDevices[0].id == DEVICE_KEYBOARD ) return; vDevices.insert( vDevices.begin(), InputDeviceInfo(DEVICE_KEYBOARD, "Keyboard") ); } // http://lists.apple.com/archives/carbon-dev/2005/Feb/msg00071.html // index represents USB keyboard usage value, content is Mac virtual keycode static UInt8 g_iUsbKeyToMacVirtualKey[256] = { 0xFF, // 00 no event 0xFF, // 01 ErrorRollOver 0xFF, // 02 POSTFail 0xFF, // 03 ErrorUndefined 0x00, // 04 A 0x0B, // 05 B 0x08, // 06 C 0x02, // 07 D 0x0E, // 08 E 0x03, // 09 F 0x05, // 0A G 0x04, // 0B H 0x22, // 0C I 0x26, // 0D J 0x28, // 0E K 0x25, // 0F L 0x2E, // 10 M 0x2D, // 11 N 0x1F, // 12 O 0x23, // 13 P 0x0C, // 14 Q 0x0F, // 15 R 0x01, // 16 S 0x11, // 17 T 0x20, // 18 U 0x09, // 19 V 0x0D, // 1A W 0x07, // 1B X 0x10, // 1C Y 0x06, // 1D Z 0x12, // 1E 1/! 0x13, // 1F 2/@ 0x14, // 20 3 # 0x15, // 21 4 $ 0x17, // 22 5 % 0x16, // 23 6 ^ 0x1A, // 24 7 & 0x1C, // 25 8 * 0x19, // 26 9 ( 0x1D, // 27 0 ) 0x24, // 28 Return (Enter) 0x35, // 29 ESC 0x33, // 2A Delete (Backspace) 0x30, // 2B Tab 0x31, // 2C Spacebar 0x1B, // 2D - _ 0x18, // 2E = + 0x21, // 2F [ { 0x1E, // 30 ] } 0x2A, // 31 \ | 0xFF, // 32 Non-US # and ~ (what?!!!) 0x29, // 33 ; : 0x27, // 34 ' " 0x32, // 35 ` ~ 0x2B, // 36 , < 0x2F, // 37 . > 0x2C, // 38 / ? 0x39, // 39 Caps Lock 0x7A, // 3A F1 0x78, // 3B F2 0x63, // 3C F3 0x76, // 3D F4 0x60, // 3E F5 0x61, // 3F F6 0x62, // 40 F7 0x64, // 41 F8 0x65, // 42 F9 0x6D, // 43 F10 0x67, // 44 F11 0x6F, // 45 F12 0x69, // 46 F13/PrintScreen 0x6B, // 47 F14/ScrollLock 0x71, // 48 F15/Pause 0x72, // 49 Insert 0x73, // 4A Home 0x74, // 4B PageUp 0x75, // 4C Delete Forward 0x77, // 4D End 0x79, // 4E PageDown 0x7C, // 4F RightArrow 0x7B, // 50 LeftArrow 0x7D, // 51 DownArrow 0x7E, // 52 UpArrow 0x47, // 53 NumLock/Clear 0x4B, // 54 Keypad / 0x43, // 55 Keypad * 0x4E, // 56 Keypad - 0x45, // 57 Keypad + 0x4C, // 58 Keypad Enter 0x53, // 59 Keypad 1 0x54, // 5A Keypad 2 0x55, // 5B Keypad 3 0x56, // 5C Keypad 4 0x57, // 5D Keypad 5 0x58, // 5E Keypad 6 0x59, // 5F Keypad 7 0x5B, // 60 Keypad 8 0x5C, // 61 Keypad 9 0x52, // 62 Keypad 0 0x41, // 63 Keypad . 0xFF, // 64 Non-US \ and | (what ??!!) 0x6E, // 65 ApplicationKey (not on Apple keyboards) 0x7F, // 66 PowerKey 0x51, // 67 Keypad = 0x69, // 68 F13 0x6B, // 69 F14 0x71, // 6A F15 0xFF, // 6B F16 0xFF, // 6C F17 0xFF, // 6D F18 0xFF, // 6E F19 0xFF, // 6F F20 0x5B, // 70 F21 0x5C, // 71 F22 0x52, // 72 F23 0x41, // 73 F24 0xFF, // 74 Execute 0xFF, // 75 Help 0x7F, // 76 Menu 0x4C, // 77 Select 0x69, // 78 Stop 0x6B, // 79 Again 0x71, // 7A Undo 0xFF, // 7B Cut 0xFF, // 7C Copy 0xFF, // 7D Paste 0xFF, // 7E Find 0xFF, // 7F Mute 0xFF, // 80 no event 0xFF, // 81 no event 0xFF, // 82 no event 0xFF, // 83 no event 0xFF, // 84 no event 0xFF, // 85 no event 0xFF, // 86 no event 0xFF, // 87 no event 0xFF, // 88 no event 0xFF, // 89 no event 0xFF, // 8A no event 0xFF, // 8B no event 0xFF, // 8C no event 0xFF, // 8D no event 0xFF, // 8E no event 0xFF, // 8F no event 0xFF, // 90 no event 0xFF, // 91 no event 0xFF, // 92 no event 0xFF, // 93 no event 0xFF, // 94 no event 0xFF, // 95 no event 0xFF, // 96 no event 0xFF, // 97 no event 0xFF, // 98 no event 0xFF, // 99 no event 0xFF, // 9A no event 0xFF, // 9B no event 0xFF, // 9C no event 0xFF, // 9D no event 0xFF, // 9E no event 0xFF, // 9F no event 0xFF, // A0 no event 0xFF, // A1 no event 0xFF, // A2 no event 0xFF, // A3 no event 0xFF, // A4 no event 0xFF, // A5 no event 0xFF, // A6 no event 0xFF, // A7 no event 0xFF, // A8 no event 0xFF, // A9 no event 0xFF, // AA no event 0xFF, // AB no event 0xFF, // AC no event 0xFF, // AD no event 0xFF, // AE no event 0xFF, // AF no event 0xFF, // B0 no event 0xFF, // B1 no event 0xFF, // B2 no event 0xFF, // B3 no event 0xFF, // B4 no event 0xFF, // B5 no event 0xFF, // B6 no event 0xFF, // B7 no event 0xFF, // B8 no event 0xFF, // B9 no event 0xFF, // BA no event 0xFF, // BB no event 0xFF, // BC no event 0xFF, // BD no event 0xFF, // BE no event 0xFF, // BF no event 0xFF, // C0 no event 0xFF, // C1 no event 0xFF, // C2 no event 0xFF, // C3 no event 0xFF, // C4 no event 0xFF, // C5 no event 0xFF, // C6 no event 0xFF, // C7 no event 0xFF, // C8 no event 0xFF, // C9 no event 0xFF, // CA no event 0xFF, // CB no event 0xFF, // CC no event 0xFF, // CD no event 0xFF, // CE no event 0xFF, // CF no event 0xFF, // D0 no event 0xFF, // D1 no event 0xFF, // D2 no event 0xFF, // D3 no event 0xFF, // D4 no event 0xFF, // D5 no event 0xFF, // D6 no event 0xFF, // D7 no event 0xFF, // D8 no event 0xFF, // D9 no event 0xFF, // DA no event 0xFF, // DB no event 0xFF, // DC no event 0xFF, // DD no event 0xFF, // DE no event 0xFF, // DF no event 0x3B, // E0 left control key 0x38, // E1 left shift key key 0x3A, // E2 left alt/option key 0x37, // E3 left GUI (windows/cmd) key 0x3B, // E4 right control key 0x38, // E5 right shift key key 0x3A, // E6 right alt/option key 0x37, // E7 right GUI (windows/cmd) key 0xFF, // E8 no event 0xFF, // E9 no event 0xFF, // EA no event 0xFF, // EB no event 0xFF, // EC no event 0xFF, // ED no event 0xFF, // EE no event 0xFF, // EF no event 0xFF, // F0 no event 0xFF, // F1 no event 0xFF, // F2 no event 0xFF, // F3 no event 0xFF, // F4 no event 0xFF, // F5 no event 0xFF, // F6 no event 0xFF, // F7 no event 0xFF, // F8 no event 0xFF, // F9 no event 0xFF, // FA no event 0xFF, // FB no event 0xFF, // FC no event 0xFF, // FD no event 0xFF, // FE no event 0xFF, // FF no event }; static UInt8 g_iDeviceButtonToMacVirtualKey[KEY_OTHER_0]; bool KeyboardDevice::DeviceButtonToMacVirtualKey( DeviceButton button, UInt8 &iMacVKOut ) { static bool bInited = false; if( !bInited ) { memset( g_iDeviceButtonToMacVirtualKey, 0xFF, sizeof(g_iDeviceButtonToMacVirtualKey) ); for( int iUsbKey = 0; iUsbKey < 256; ++iUsbKey ) { DeviceButton button2; if( UsbKeyToDeviceButton(iUsbKey, button2) && size_t(button2) < sizeof(g_iDeviceButtonToMacVirtualKey) ) g_iDeviceButtonToMacVirtualKey[button2] = g_iUsbKeyToMacVirtualKey[iUsbKey]; } bInited = true; } iMacVKOut = g_iDeviceButtonToMacVirtualKey[button]; return iMacVKOut != 0xFF; } /* * (c) 2005-2006 Steve Checkoway * All rights reserved. * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the * "Software"), to deal in the Software without restriction, including * without limitation the rights to use, copy, modify, merge, publish, * distribute, and/or sell copies of the Software, and to permit persons to * whom the Software is furnished to do so, provided that the above * copyright notice(s) and this permission notice appear in all copies of * the Software and that both the above copyright notice(s) and this * permission notice appear in supporting documentation. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF * THIRD PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR HOLDERS * INCLUDED IN THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT * OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR * PERFORMANCE OF THIS SOFTWARE. */