5 // Created by Sam McCall on 4/05/09.
11 #import "JSActionAnalog.h"
12 #import "JSActionButton.h"
13 #import "JSActionHat.h"
15 static NSArray *ActionsForElement(IOHIDDeviceRef device, id base) {
16 CFArrayRef elements = IOHIDDeviceCopyMatchingElements(device, NULL, kIOHIDOptionsTypeNone);
17 NSMutableArray *children = [NSMutableArray arrayWithCapacity:CFArrayGetCount(elements)];
23 for (int i = 0; i < CFArrayGetCount(elements); i++) {
24 IOHIDElementRef element = (IOHIDElementRef)CFArrayGetValueAtIndex(elements, i);
25 int type = IOHIDElementGetType(element);
26 int usage = IOHIDElementGetUsage(element);
27 int usagePage = IOHIDElementGetUsagePage(element);
28 int max = IOHIDElementGetPhysicalMax(element);
29 int min = IOHIDElementGetPhysicalMin(element);
30 CFStringRef elName = IOHIDElementGetName(element);
32 JSAction *action = nil;
34 if (!(type == kIOHIDElementTypeInput_Misc
35 || type == kIOHIDElementTypeInput_Axis
36 || type == kIOHIDElementTypeInput_Button))
39 if (max - min == 1 || usagePage == kHIDPage_Button || type == kIOHIDElementTypeInput_Button) {
40 action = [[JSActionButton alloc] initWithName:(__bridge NSString *)elName
43 } else if (usage == kHIDUsage_GD_Hatswitch) {
44 action = [[JSActionHat alloc] initWithIndex:++hats];
45 } else if (usage >= kHIDUsage_GD_X && usage <= kHIDUsage_GD_Rz) {
46 // TODO(jfw): Scaling equation doesn't seem right if min != 0.
47 action = [[JSActionAnalog alloc] initWithIndex:++axes
49 scale:2.f / (max - min)];
54 // TODO(jfw): Should be moved into better constructors.
56 action.cookie = IOHIDElementGetCookie(element);
57 [children addObject:action];
62 @implementation Joystick
65 @synthesize productId;
66 @synthesize productName;
71 - (id)initWithDevice:(IOHIDDeviceRef)dev {
72 if ((self = [super init])) {
74 self.productName = (__bridge NSString *)IOHIDDeviceGetProperty(dev, CFSTR(kIOHIDProductKey));
75 self.vendorId = [(__bridge NSNumber *)IOHIDDeviceGetProperty(dev, CFSTR(kIOHIDVendorIDKey)) intValue];
76 self.productId = [(__bridge NSNumber *)IOHIDDeviceGetProperty(dev, CFSTR(kIOHIDProductIDKey)) intValue];
77 self.children = ActionsForElement(dev, self);
83 return [NSString stringWithFormat:@"%@ #%d", productName, index];
91 return [NSString stringWithFormat: @"%d:%d:%d", vendorId, productId, index];
94 - (JSAction *)findActionByCookie:(void *)cookie {
95 for (JSAction *child in children)
96 if (child.cookie == cookie)
101 - (id)handlerForEvent:(IOHIDValueRef) value {
102 JSAction *mainAction = [self actionForEvent:value];
103 return [mainAction findSubActionForValue:value];
106 - (JSAction *)actionForEvent:(IOHIDValueRef)value {
107 IOHIDElementRef elt = IOHIDValueGetElement(value);
108 void *cookie = IOHIDElementGetCookie(elt);
109 return [self findActionByCookie:cookie];