3dbaec3a6cb87335402790f48a54f5bde99b9a71
[enjoyable.git] / Classes / NJHIDManager.m
1 #import "NJHIDManager.h"
2
3 @implementation NJHIDManager {
4 NSArray *_criteria;
5 IOHIDManagerRef _manager;
6 }
7
8 - (id)initWithCriteria:(NSArray *)criteria
9 delegate:(id <NJHIDManagerDelegate>)delegate
10 {
11 if ((self = [super init])) {
12 self.criteria = criteria;
13 self.delegate = delegate;
14 }
15 return self;
16 }
17
18 - (void)dealloc {
19 [self stop];
20 }
21
22 static void _input(void *ctx, IOReturn inResult, void *inSender, IOHIDValueRef value) {
23 NJHIDManager *self = (__bridge NJHIDManager *)ctx;
24 IOHIDDeviceRef device = IOHIDQueueGetDevice(inSender);
25 [self.delegate HIDManager:self valueChanged:value fromDevice:device];
26 }
27
28 static void _add(void *ctx, IOReturn inResult, void *inSender, IOHIDDeviceRef device) {
29 NJHIDManager *self = (__bridge NJHIDManager *)ctx;
30 [self.delegate HIDManager:self deviceAdded:device];
31 IOHIDDeviceRegisterInputValueCallback(device, _input, ctx);
32 }
33
34 static void _remove(void *ctx, IOReturn inResult, void *inSender, IOHIDDeviceRef device) {
35 NJHIDManager *self = (__bridge NJHIDManager *)ctx;
36 [self.delegate HIDManager:self deviceRemoved:device];
37 }
38
39 - (void)start {
40 if (self.running)
41 return;
42 IOHIDManagerRef manager = IOHIDManagerCreate(kCFAllocatorDefault, kIOHIDOptionsTypeNone);
43 IOHIDManagerSetDeviceMatchingMultiple(manager, (__bridge CFArrayRef)self.criteria);
44 IOReturn ret = IOHIDManagerOpen(manager, kIOHIDOptionsTypeNone);
45 if (ret != kIOReturnSuccess) {
46 NSError *error = [NSError errorWithDomain:NSMachErrorDomain code:ret userInfo:nil];
47 IOHIDManagerClose(manager, kIOHIDOptionsTypeNone);
48 CFRelease(manager);
49 [self.delegate HIDManager:self didError:error];
50 NSLog(@"Error starting HID manager: %@.", error);
51 } else {
52 _manager = manager;
53 IOHIDManagerScheduleWithRunLoop(_manager, CFRunLoopGetCurrent(), kCFRunLoopDefaultMode);
54 IOHIDManagerRegisterDeviceMatchingCallback(_manager, _add, (__bridge void *)self);
55 IOHIDManagerRegisterDeviceRemovalCallback(_manager, _remove, (__bridge void *)self);
56 [self.delegate HIDManagerDidStart:self];
57 NSLog(@"Started HID manager.");
58 }
59 }
60
61 - (void)stop {
62 if (!self.running)
63 return;
64 IOHIDManagerUnscheduleFromRunLoop(_manager, CFRunLoopGetCurrent(), kCFRunLoopDefaultMode);
65 IOHIDManagerClose(_manager, kIOHIDOptionsTypeNone);
66 CFRelease(_manager);
67 _manager = NULL;
68 [self.delegate HIDManagerDidStop:self];
69 NSLog(@"Stopped HID manager.");
70 }
71
72 - (BOOL)running {
73 return !!_manager;
74 }
75
76 - (void)setRunning:(BOOL)running {
77 if (running)
78 [self start];
79 else
80 [self stop];
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