Remove website, now in yukkurigames.com repository.
[enjoyable.git] / Classes / NJDevice.m
1 //
2 // NJDevice.m
3 // Enjoy
4 //
5 // Created by Sam McCall on 4/05/09.
6 //
7
8 #import "NJDevice.h"
9
10 #import "NJInput.h"
11 #import "NJInputAnalog.h"
12 #import "NJInputHat.h"
13 #import "NJInputButton.h"
14
15 static NSArray *InputsForElement(IOHIDDeviceRef device, id parent) {
16 CFArrayRef elements = IOHIDDeviceCopyMatchingElements(device, NULL, kIOHIDOptionsTypeNone);
17 NSMutableArray *children = [NSMutableArray arrayWithCapacity:CFArrayGetCount(elements)];
18
19 int buttons = 0;
20 int axes = 0;
21 int hats = 0;
22
23 for (CFIndex i = 0; i < CFArrayGetCount(elements); i++) {
24 IOHIDElementRef element = (IOHIDElementRef)CFArrayGetValueAtIndex(elements, i);
25 IOHIDElementType type = IOHIDElementGetType(element);
26 uint32_t usage = IOHIDElementGetUsage(element);
27 uint32_t usagePage = IOHIDElementGetUsagePage(element);
28 CFIndex max = IOHIDElementGetPhysicalMax(element);
29 CFIndex min = IOHIDElementGetPhysicalMin(element);
30
31 NJInput *input = nil;
32
33 if (!(type == kIOHIDElementTypeInput_Misc
34 || type == kIOHIDElementTypeInput_Axis
35 || type == kIOHIDElementTypeInput_Button))
36 continue;
37
38 if (max - min == 1
39 || usagePage == kHIDPage_Button
40 || type == kIOHIDElementTypeInput_Button) {
41 input = [[NJInputButton alloc] initWithElement:element
42 index:++buttons
43 parent:parent];
44 } else if (usage == kHIDUsage_GD_Hatswitch) {
45 input = [[NJInputHat alloc] initWithElement:element
46 index:++hats
47 parent:parent];
48 } else if (usage >= kHIDUsage_GD_X && usage <= kHIDUsage_GD_Rz) {
49 input = [[NJInputAnalog alloc] initWithElement:element
50 index:++axes
51 parent:parent];
52 } else {
53 continue;
54 }
55
56 [children addObject:input];
57 }
58
59 CFRelease(elements);
60 return children;
61 }
62
63 @implementation NJDevice {
64 int _vendorId;
65 int _productId;
66 }
67
68 - (id)initWithDevice:(IOHIDDeviceRef)dev {
69 NSString *name = (__bridge NSString *)IOHIDDeviceGetProperty(dev, CFSTR(kIOHIDProductKey));
70 if ((self = [super initWithName:name eid:nil parent:nil])) {
71 self.device = dev;
72 _vendorId = [(__bridge NSNumber *)IOHIDDeviceGetProperty(dev, CFSTR(kIOHIDVendorIDKey)) intValue];
73 _productId = [(__bridge NSNumber *)IOHIDDeviceGetProperty(dev, CFSTR(kIOHIDProductIDKey)) intValue];
74 self.children = InputsForElement(dev, self);
75 self.index = 1;
76 }
77 return self;
78 }
79
80 - (BOOL)isEqual:(id)object {
81 return [object isKindOfClass:NJDevice.class]
82 && [[(NJDevice *)object name] isEqualToString:self.name];
83 }
84
85 - (NSString *)name {
86 return [NSString stringWithFormat:@"%@ #%d", super.name, _index];
87 }
88
89 - (NSString *)uid {
90 return [NSString stringWithFormat:@"%d:%d:%d", _vendorId, _productId, _index];
91 }
92
93 - (NJInput *)findInputByCookie:(IOHIDElementCookie)cookie {
94 for (NJInput *child in self.children)
95 if (child.cookie == cookie)
96 return child;
97 return nil;
98 }
99
100 - (NJInput *)handlerForEvent:(IOHIDValueRef)value {
101 NJInput *mainInput = [self inputForEvent:value];
102 return [mainInput findSubInputForValue:value];
103 }
104
105 - (NJInput *)inputForEvent:(IOHIDValueRef)value {
106 IOHIDElementRef elt = IOHIDValueGetElement(value);
107 IOHIDElementCookie cookie = IOHIDElementGetCookie(elt);
108 return [self findInputByCookie:cookie];
109 }
110
111 @end