Split actual IOKit HID interfacing off from NJDeviceController.
[enjoyable.git] / Classes / NJHIDManager.m
1 //
2 // NJHIDManager.m
3 // Enjoyable
4 //
5 // Created by Joe Wreschnig on 3/13/13.
6 //
7 //
8
9 #import "NJHIDManager.h"
10
11 @implementation NJHIDManager {
12 NSArray *_criteria;
13 IOHIDManagerRef _manager;
14 }
15
16 - (id)initWithCriteria:(NSArray *)criteria
17 delegate:(id <NJHIDManagerDelegate>)delegate
18 {
19 if ((self = [super init])) {
20 self.criteria = criteria;
21 self.delegate = delegate;
22 }
23 return self;
24 }
25
26 - (void)dealloc {
27 [self stop];
28 }
29
30 static void input_callback(void *ctx, IOReturn inResult, void *inSender, IOHIDValueRef value) {
31 NJHIDManager *self = (__bridge NJHIDManager *)ctx;
32 IOHIDDeviceRef device = IOHIDQueueGetDevice(inSender);
33 [self.delegate hidManager:self valueChanged:value fromDevice:device];
34 }
35
36 static void add_callback(void *ctx, IOReturn inResult, void *inSender, IOHIDDeviceRef device) {
37 NJHIDManager *self = (__bridge NJHIDManager *)ctx;
38 [self.delegate hidManager:self deviceAdded:device];
39 IOHIDDeviceRegisterInputValueCallback(device, input_callback, ctx);
40 }
41
42 static void remove_callback(void *ctx, IOReturn inResult, void *inSender, IOHIDDeviceRef device) {
43 NJHIDManager *self = (__bridge NJHIDManager *)ctx;
44 [self.delegate hidManager:self deviceRemoved:device];
45 }
46
47 - (void)start {
48 if (self.running)
49 return;
50 IOHIDManagerRef manager = IOHIDManagerCreate(kCFAllocatorDefault, kIOHIDOptionsTypeNone);
51 IOHIDManagerSetDeviceMatchingMultiple(manager, (__bridge CFArrayRef)self.criteria);
52 IOReturn ret = IOHIDManagerOpen(manager, kIOHIDOptionsTypeNone);
53 if (ret != kIOReturnSuccess) {
54 NSError *error = [NSError errorWithDomain:NSMachErrorDomain code:ret userInfo:nil];
55 IOHIDManagerClose(manager, kIOHIDOptionsTypeNone);
56 CFRelease(manager);
57 [self.delegate hidManager:self didError:error];
58 } else {
59 _manager = manager;
60 IOHIDManagerScheduleWithRunLoop(_manager, CFRunLoopGetCurrent(), kCFRunLoopDefaultMode);
61 IOHIDManagerRegisterDeviceMatchingCallback(_manager, add_callback, (__bridge void *)self);
62 IOHIDManagerRegisterDeviceRemovalCallback(_manager, remove_callback, (__bridge void *)self);
63 [self.delegate hidManagerDidStart:self];
64 NSLog(@"Started HID manager.");
65 }
66 }
67
68 - (void)stop {
69 if (!self.running)
70 return;
71 IOHIDManagerUnscheduleFromRunLoop(_manager, CFRunLoopGetCurrent(), kCFRunLoopDefaultMode);
72 IOHIDManagerClose(_manager, kIOHIDOptionsTypeNone);
73 CFRelease(_manager);
74 _manager = NULL;
75 [self.delegate hidManagerDidStop:self];
76 NSLog(@"Stopped HID manager.");
77 }
78
79 - (BOOL)running {
80 return !!_manager;
81 }
82
83 - (NSArray *)criteria {
84 return _criteria;
85 }
86
87 - (void)setCriteria:(NSArray *)criteria {
88 if (!criteria)
89 criteria = @[];
90 if (![criteria isEqualToArray:_criteria]) {
91 BOOL running = !!_manager;
92 [self stop];
93 _criteria = [criteria copy];
94 if (running)
95 [self start];
96 }
97 }
98
99 @end