Skip to content

Commit

Permalink
HID love
Browse files Browse the repository at this point in the history
  • Loading branch information
jweinberg committed Sep 7, 2010
1 parent 0eee59d commit 12a5315
Show file tree
Hide file tree
Showing 3 changed files with 232 additions and 7 deletions.
106 changes: 99 additions & 7 deletions OpenEmu/OEHIDEvent.m
Expand Up @@ -28,6 +28,10 @@
#import "OEHIDEvent.h"
#import "OEHIDDeviceHandler.h"
#import <IOKit/hid/IOHIDUsageTables.h>
#import <Carbon/Carbon.h>


#import "OEHIDUsageToVK.h"

@interface OEHIDEvent ()
- (id)initWithDeviceHandler:(OEHIDDeviceHandler *)aDeviceHandler value:(IOHIDValueRef)aValue;
Expand All @@ -37,14 +41,103 @@ - (id)initWithPadNumber:(NSUInteger)padNumber timestamp:(NSTimeInterval)timestam
@implementation OEHIDEvent
@synthesize padNumber = _padNumber, type = _type, isPushed = _isPushed, timestamp = _timestamp;

NSDictionary *keycodeMap = nil;
+ (void)initialize
static const struct { char const* const name; unichar const glyph; } mapOfNamesForUnicodeGlyphs[] =
{
// Constants defined in NSEvent.h that are expected to relate to unicode characters, but don't seen to translate properly
{ "Up", NSUpArrowFunctionKey },
{ "Down", NSDownArrowFunctionKey },
{ "Left", NSLeftArrowFunctionKey },
{ "Right", NSRightArrowFunctionKey },
{ "Home", NSHomeFunctionKey },
{ "End", NSEndFunctionKey },
{ "Page Up", NSPageUpFunctionKey },
{ "Page Down", NSPageDownFunctionKey },

// These are the actual values that these keys translate to
{ "Up", 0x1E },
{ "Down", 0x1F },
{ "Left", 0x1C },
{ "Right", 0x1D },
{ "Home", 0x1 },
{ "End", 0x4 },
{ "Page Up", 0xB },
{ "Page Down", 0xC },
{ "Return", 0x3 },
{ "Tab", 0x9 },
{ "Backtab", 0x19 },
{ "Enter", 0xd },
{ "Backspace", 0x8 },
{ "Delete", 0x7F },
{ "Escape", 0x1b },
{ "Space", 0x20 }

};

// Need to update this value if you modify mapOfNamesForUnicodeGlyphs
#define NumberOfUnicodeGlyphReplacements 24

+ (NSString *)stringForHIDKeyCode:(NSUInteger)hidCode
{
if (self == [OEHIDEvent class])
CGKeyCode keyCode = 0xFFFF;
for (int i = 0; i < sizeof(hidvk_codes) / sizeof(*hidvk_codes); ++i)
{
if (hidvk_codes[i].hidCode == hidCode)
{
keyCode = hidvk_codes[i].vkCode;
break;
}
}

if (keyCode == 0xFFFF)
{
NSString *path = [[NSBundle mainBundle] pathForResource:@"KeyboardUsages" ofType:@"plist"];
keycodeMap = [[NSDictionary alloc] initWithContentsOfFile:path];
for (int i = 0; i < sizeof(hidlabels) / sizeof(*hidlabels); ++i)
{
if (hidlabels[i].hidCode == hidCode)
{
return hidlabels[i].string;
}
}
return nil;
}

TISInputSourceRef currentKeyboard = TISCopyCurrentKeyboardInputSource();
CFDataRef uchr = (CFDataRef)TISGetInputSourceProperty(currentKeyboard, kTISPropertyUnicodeKeyLayoutData);
const UCKeyboardLayout *keyboardLayout = (const UCKeyboardLayout*)CFDataGetBytePtr(uchr);

if(keyboardLayout) {
UInt32 deadKeyState = 0;
UniCharCount maxStringLength = 255;
UniCharCount actualStringLength = 0;
UniChar unicodeString[maxStringLength];

OSStatus status = UCKeyTranslate(keyboardLayout,
keyCode, kUCKeyActionDown, 0,
LMGetKbdType(), 0,
&deadKeyState,
maxStringLength,
&actualStringLength, unicodeString);

if(status != noErr)
NSLog(@"There was an %s error translating from the '%d' key code to a human readable string: %s",
GetMacOSStatusErrorString(status), status, GetMacOSStatusCommentString(status));
else if(actualStringLength > 0) {
// Replace certain characters with user friendly names, e.g. Space, Enter, Tab etc.
NSUInteger i = 0;
while(i <= NumberOfUnicodeGlyphReplacements) {
if(mapOfNamesForUnicodeGlyphs[i].glyph == unicodeString[0])
return NSLocalizedString(([NSString stringWithFormat:@"%s", mapOfNamesForUnicodeGlyphs[i].name, nil]), @"Friendly Key Name");

i++;
}

// NSLog(@"Unicode character as hexadecimal: %X", unicodeString[0]);
return [[NSString stringWithCharacters:unicodeString length:(NSInteger)actualStringLength] uppercaseString];
} else
NSLog(@"Couldn't find a translation for the '%d' key code", keyCode);
} else
NSLog(@"Couldn't find a suitable keyboard layout from which to translate");

return nil;
}

- (NSString *)displayDescription
Expand Down Expand Up @@ -76,8 +169,7 @@ - (NSString *)displayDescription
ret = [NSString stringWithFormat:@" H%d/%d", _data.hatSwitch.position, _data.hatSwitch.count];
break;
case OEHIDKeypress :
ret = [NSString stringWithFormat:@"Key %@", [keycodeMap objectForKey:[[NSNumber numberWithUnsignedInteger:_data.keypress.keycode] stringValue]]];
break;
return [NSString stringWithFormat:@"%@", [OEHIDEvent stringForHIDKeyCode:_data.keypress.keycode]];
}

if(ret != nil) ret = [NSString stringWithFormat:@"P%d%@", _padNumber, ret];
Expand Down
123 changes: 123 additions & 0 deletions OpenEmu/OEHIDUsageToVK.h
@@ -0,0 +1,123 @@
/*
* OEHIDUsageToVK.h
* OpenEmu
*
* Created by Josh Weinberg on 9/7/10.
* Copyright 2010 Roundarch Inc. All rights reserved.
*
*/

#import <Carbon/Carbon.h>
#import <IOKit/hid/IOHIDUsageTables.h>

typedef struct
{
NSUInteger hidCode;
CGKeyCode vkCode;
}OE_HIDVKCode;

OE_HIDVKCode hidvk_codes[] = {
{kHIDUsage_Keyboard0, kVK_ANSI_0},
{kHIDUsage_Keyboard1, kVK_ANSI_1},
{kHIDUsage_Keyboard2, kVK_ANSI_2},
{kHIDUsage_Keyboard3, kVK_ANSI_3},
{kHIDUsage_Keyboard4, kVK_ANSI_4},
{kHIDUsage_Keyboard5, kVK_ANSI_5},
{kHIDUsage_Keyboard6, kVK_ANSI_6},
{kHIDUsage_Keyboard7, kVK_ANSI_7},
{kHIDUsage_Keyboard8, kVK_ANSI_8},
{kHIDUsage_Keyboard9, kVK_ANSI_9},
{kHIDUsage_Keyboard0, kVK_ANSI_0},
{kHIDUsage_KeyboardA, kVK_ANSI_A},
{kHIDUsage_KeyboardB, kVK_ANSI_B},
{kHIDUsage_KeyboardC, kVK_ANSI_C},
{kHIDUsage_KeyboardD, kVK_ANSI_D},
{kHIDUsage_KeyboardE, kVK_ANSI_E},
{kHIDUsage_KeyboardF, kVK_ANSI_F},
{kHIDUsage_KeyboardG, kVK_ANSI_G},
{kHIDUsage_KeyboardH, kVK_ANSI_H},
{kHIDUsage_KeyboardI, kVK_ANSI_I},
{kHIDUsage_KeyboardJ, kVK_ANSI_J},
{kHIDUsage_KeyboardK, kVK_ANSI_K},
{kHIDUsage_KeyboardL, kVK_ANSI_L},
{kHIDUsage_KeyboardM, kVK_ANSI_M},
{kHIDUsage_KeyboardN, kVK_ANSI_N},
{kHIDUsage_KeyboardO, kVK_ANSI_O},
{kHIDUsage_KeyboardP, kVK_ANSI_P},
{kHIDUsage_KeyboardQ, kVK_ANSI_Q},
{kHIDUsage_KeyboardR, kVK_ANSI_R},
{kHIDUsage_KeyboardS, kVK_ANSI_S},
{kHIDUsage_KeyboardT, kVK_ANSI_T},
{kHIDUsage_KeyboardU, kVK_ANSI_U},
{kHIDUsage_KeyboardV, kVK_ANSI_V},
{kHIDUsage_KeyboardW, kVK_ANSI_W},
{kHIDUsage_KeyboardX, kVK_ANSI_X},
{kHIDUsage_KeyboardY, kVK_ANSI_Y},
{kHIDUsage_KeyboardZ, kVK_ANSI_Z},
{kHIDUsage_KeyboardGraveAccentAndTilde, kVK_ANSI_Grave}, /* Grave Accent and Tilde */
{kHIDUsage_KeyboardHyphen, kVK_ANSI_Minus}, /* - or _ */
{kHIDUsage_KeyboardEqualSign, kVK_ANSI_Equal}, /* = or + */
{kHIDUsage_KeyboardQuote, kVK_ANSI_Quote}, /* ' or " */
{kHIDUsage_KeyboardOpenBracket, kVK_ANSI_LeftBracket}, /* [ or { */
{kHIDUsage_KeyboardCloseBracket, kVK_ANSI_RightBracket}, /* ] or } */
{kHIDUsage_KeyboardBackslash, kVK_ANSI_Backslash}, /* \ or | */
{kHIDUsage_KeyboardSemicolon, kVK_ANSI_Semicolon}, /* ; or : */
{kHIDUsage_KeyboardComma, kVK_ANSI_Comma}, /* , or < */
{kHIDUsage_KeyboardPeriod, kVK_ANSI_Period}, /* . or > */
{kHIDUsage_KeyboardSlash, kVK_ANSI_Slash}, /* / or ? */

};

typedef struct
{
NSUInteger hidCode;
NSString * string;
}OE_HIDString;

OE_HIDString hidlabels[] = {

{kHIDUsage_KeyboardReturnOrEnter, @"Enter"}, /* Return (Enter) */
{kHIDUsage_KeyboardEscape, @"Escape"},/* Escape */
{kHIDUsage_KeyboardDeleteOrBackspace, @"Delete"}, /* Delete (Backspace) */
{kHIDUsage_KeyboardTab, @"Tab"}, /* Tab */
{kHIDUsage_KeyboardSpacebar, @"Space"}, /* Spacebar */
{kHIDUsage_KeyboardCapsLock, @"Caps Lock"}, /* Caps Lock */
{kHIDUsage_KeyboardF1, @"F1"},
{kHIDUsage_KeyboardF2, @"F2"},
{kHIDUsage_KeyboardF3, @"F3"},
{kHIDUsage_KeyboardF4, @"F4"},
{kHIDUsage_KeyboardF5, @"F5"},
{kHIDUsage_KeyboardF6, @"F6"},
{kHIDUsage_KeyboardF7, @"F7"},
{kHIDUsage_KeyboardF8, @"F8"},
{kHIDUsage_KeyboardF9, @"F9"},
{kHIDUsage_KeyboardF10, @"F10"},
{kHIDUsage_KeyboardF11, @"F11"},
{kHIDUsage_KeyboardF12, @"F12"},
{kHIDUsage_KeyboardF13, @"F13"},
{kHIDUsage_KeyboardF14, @"F14"},
{kHIDUsage_KeyboardF15, @"F15"},
{kHIDUsage_KeyboardF16, @"F16"},
{kHIDUsage_KeyboardF17, @"F17"},
{kHIDUsage_KeyboardF18, @"F18"},
{kHIDUsage_KeyboardF19, @"F19"},
{kHIDUsage_KeyboardF20, @"F20"},
{kHIDUsage_KeyboardF21, @"F21"},
{kHIDUsage_KeyboardF22, @"F22"},
{kHIDUsage_KeyboardF23, @"F23"},
{kHIDUsage_KeyboardF24, @"F24"},

{kHIDUsage_KeyboardLeftControl, @"Left Control"}, /* Left Control */
{kHIDUsage_KeyboardLeftShift, @"Left Shift"}, /* Left Shift */
{kHIDUsage_KeyboardLeftAlt, @"Left Option"}, /* Left Alt */
{kHIDUsage_KeyboardLeftGUI, @"Left Command"}, /* Left GUI */
{kHIDUsage_KeyboardRightControl, @"Right Control"}, /* Right Control */
{kHIDUsage_KeyboardRightShift, @"Right Shift"}, /* Right Shift */
{kHIDUsage_KeyboardRightAlt, @"Right Option"}, /* Right Alt */
{kHIDUsage_KeyboardRightGUI, @"Right Command"}, /* Right GUI */

{kHIDUsage_KeyboardLeftArrow, @"Left"}, /* Right GUI */
{kHIDUsage_KeyboardRightArrow, @"Right"}, /* Right GUI */
{kHIDUsage_KeyboardUpArrow, @"Up"}, /* Right GUI */
{kHIDUsage_KeyboardDownArrow, @"Down"}, /* Right GUI */
};
10 changes: 10 additions & 0 deletions OpenEmu/OpenEmu.xcodeproj/project.pbxproj
Expand Up @@ -210,6 +210,9 @@
82CAFBBE0FEDAA4200CCDC7E /* config.yaml in CopyFiles */ = {isa = PBXBuildFile; fileRef = 82CAFBB70FEDAA3D00CCDC7E /* config.yaml */; };
82D9122310200F7000E370FC /* CoreData.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 82D9122210200F7000E370FC /* CoreData.framework */; };
82DD29DB12369F1100B58A8F /* KeyboardUsages.plist in Resources */ = {isa = PBXBuildFile; fileRef = 82DD29DA12369F1100B58A8F /* KeyboardUsages.plist */; };
82DD2B1E1236CF0200B58A8F /* Carbon.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 82DD2B1D1236CF0200B58A8F /* Carbon.framework */; };
82DD2B3B1236D02D00B58A8F /* Carbon.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 82DD2B1D1236CF0200B58A8F /* Carbon.framework */; };
82DD2B8D1236D0C400B58A8F /* OEHIDUsageToVK.h in Headers */ = {isa = PBXBuildFile; fileRef = 82DD2B8C1236D0C400B58A8F /* OEHIDUsageToVK.h */; };
82DE498B10263A1A007184EB /* OECoreDownloader.m in Sources */ = {isa = PBXBuildFile; fileRef = 82DE498A10263A1A007184EB /* OECoreDownloader.m */; };
82DE49F010263FF3007184EB /* CoreDownloader.xib in Resources */ = {isa = PBXBuildFile; fileRef = 82DE49EF10263FF3007184EB /* CoreDownloader.xib */; };
82DE49F4102641CD007184EB /* OEDownload.m in Sources */ = {isa = PBXBuildFile; fileRef = 82DE49F3102641CD007184EB /* OEDownload.m */; };
Expand Down Expand Up @@ -576,6 +579,8 @@
82CAFBB70FEDAA3D00CCDC7E /* config.yaml */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = config.yaml; sourceTree = "<group>"; };
82D9122210200F7000E370FC /* CoreData.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreData.framework; path = System/Library/Frameworks/CoreData.framework; sourceTree = SDKROOT; };
82DD29DA12369F1100B58A8F /* KeyboardUsages.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = KeyboardUsages.plist; sourceTree = "<group>"; };
82DD2B1D1236CF0200B58A8F /* Carbon.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Carbon.framework; path = System/Library/Frameworks/Carbon.framework; sourceTree = SDKROOT; };
82DD2B8C1236D0C400B58A8F /* OEHIDUsageToVK.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = OEHIDUsageToVK.h; sourceTree = "<group>"; };
82DE446510252F2F007184EB /* IKImageFlowView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = IKImageFlowView.h; sourceTree = "<group>"; };
82DE498910263A1A007184EB /* OECoreDownloader.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = OECoreDownloader.h; sourceTree = "<group>"; };
82DE498A10263A1A007184EB /* OECoreDownloader.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = OECoreDownloader.m; sourceTree = "<group>"; };
Expand Down Expand Up @@ -684,6 +689,7 @@
files = (
C61C98F30F583262007F4242 /* IOKit.framework in Frameworks */,
3D92858211F180BD00CD6CAE /* Cocoa.framework in Frameworks */,
82DD2B3B1236D02D00B58A8F /* Carbon.framework in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
Expand Down Expand Up @@ -718,6 +724,7 @@
829022B10F47FAC100BB7AB7 /* QTKit.framework in Frameworks */,
82D9122310200F7000E370FC /* CoreData.framework in Frameworks */,
3D92856C11F17F3400CD6CAE /* Cocoa.framework in Frameworks */,
82DD2B1E1236CF0200B58A8F /* Carbon.framework in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
Expand Down Expand Up @@ -954,6 +961,7 @@
C60CDDD511780DD100EB472F /* Documentation */,
2A37F4C3FDCFA73011CA2CEA /* Frameworks */,
19C28FB0FE9D524F11CA2CBB /* Products */,
82DD2B1D1236CF0200B58A8F /* Carbon.framework */,
);
name = OpenEmu;
sourceTree = "<group>";
Expand Down Expand Up @@ -1191,6 +1199,7 @@
82AD1B300FD1BD2A00B3A8A9 /* OEMap.m */,
82AFA6670FDDC03500531EE3 /* OERingBuffer.h */,
82AFA6680FDDC03500531EE3 /* OERingBuffer.m */,
82DD2B8C1236D0C400B58A8F /* OEHIDUsageToVK.h */,
);
name = "GameCore framework";
sourceTree = "<group>";
Expand Down Expand Up @@ -1246,6 +1255,7 @@
828CF1A40FD1D86A0041311B /* OEPreferenceViewController.h in Headers */,
82AFA6690FDDC03500531EE3 /* OERingBuffer.h in Headers */,
1BEF2A67116826BC0090F72B /* NSString+UUID.h in Headers */,
82DD2B8D1236D0C400B58A8F /* OEHIDUsageToVK.h in Headers */,
);
runOnlyForDeploymentPostprocessing = 0;
};
Expand Down

0 comments on commit 12a5315

Please sign in to comment.