514 lines
13 KiB
C++
514 lines
13 KiB
C++
#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<IOHIDElementCookie,DeviceButton>::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<DeviceInput>& vPresses, IOHIDElementCookie cookie, int value, const RageTimer& now ) const
|
|
{
|
|
hash_map<IOHIDElementCookie, DeviceButton>::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<InputDeviceInfo>& 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.
|
|
*/
|