rb-blink1 0.0.6 → 0.0.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/ext/blink1/blink1-lib.c +106 -74
- data/ext/blink1/blink1-lib.h +9 -7
- data/ext/blink1/blink1.c +15 -0
- data/ext/blink1/hid.c.libusb +108 -109
- data/ext/blink1/hid.c.mac +115 -160
- data/ext/blink1/hid.c.windows +115 -112
- data/ext/blink1/hidapi.h +3 -2
- data/ext/blink1/osccal.h +7 -7
- data/ext/blink1/usbconfig.h +3 -3
- data/lib/blink1.rb +5 -5
- data/lib/blink1/version.rb +1 -1
- data/spec/blink1_spec.rb +11 -3
- data/spec/spec_helper.rb +7 -1
- metadata +2 -2
data/ext/blink1/hid.c.mac
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
/*******************************************************
|
2
2
|
HIDAPI - Multi-Platform library for
|
3
3
|
communication with HID devices.
|
4
|
-
|
4
|
+
|
5
5
|
Alan Ott
|
6
6
|
Signal 11 Software
|
7
7
|
|
8
8
|
2010-07-03
|
9
9
|
|
10
10
|
Copyright 2010, All Rights Reserved.
|
11
|
-
|
11
|
+
|
12
12
|
At the discretion of the user of this library,
|
13
13
|
this software may be licensed under the terms of the
|
14
14
|
GNU Public License v3, a BSD-Style license, or the
|
@@ -51,7 +51,7 @@ static int pthread_barrier_init(pthread_barrier_t *barrier, const pthread_barrie
|
|
51
51
|
errno = EINVAL;
|
52
52
|
return -1;
|
53
53
|
}
|
54
|
-
|
54
|
+
|
55
55
|
if(pthread_mutex_init(&barrier->mutex, 0) < 0) {
|
56
56
|
return -1;
|
57
57
|
}
|
@@ -118,16 +118,8 @@ struct hid_device_ {
|
|
118
118
|
pthread_barrier_t barrier; /* Ensures correct startup sequence */
|
119
119
|
pthread_barrier_t shutdown_barrier; /* Ensures correct shutdown sequence */
|
120
120
|
int shutdown_thread;
|
121
|
-
|
122
|
-
hid_device *next;
|
123
121
|
};
|
124
122
|
|
125
|
-
/* Static list of all the devices open. This way when a device gets
|
126
|
-
disconnected, its hid_device structure can be marked as disconnected
|
127
|
-
from hid_device_removal_callback(). */
|
128
|
-
static hid_device *device_list = NULL;
|
129
|
-
static pthread_mutex_t device_list_mutex = PTHREAD_MUTEX_INITIALIZER;
|
130
|
-
|
131
123
|
static hid_device *new_hid_device(void)
|
132
124
|
{
|
133
125
|
hid_device *dev = calloc(1, sizeof(hid_device));
|
@@ -141,30 +133,13 @@ static hid_device *new_hid_device(void)
|
|
141
133
|
dev->input_report_buf = NULL;
|
142
134
|
dev->input_reports = NULL;
|
143
135
|
dev->shutdown_thread = 0;
|
144
|
-
dev->next = NULL;
|
145
136
|
|
146
137
|
/* Thread objects */
|
147
138
|
pthread_mutex_init(&dev->mutex, NULL);
|
148
139
|
pthread_cond_init(&dev->condition, NULL);
|
149
140
|
pthread_barrier_init(&dev->barrier, NULL, 2);
|
150
141
|
pthread_barrier_init(&dev->shutdown_barrier, NULL, 2);
|
151
|
-
|
152
|
-
/* Add the new record to the device_list. */
|
153
|
-
pthread_mutex_lock(&device_list_mutex);
|
154
|
-
if (!device_list)
|
155
|
-
device_list = dev;
|
156
|
-
else {
|
157
|
-
hid_device *d = device_list;
|
158
|
-
while (d) {
|
159
|
-
if (!d->next) {
|
160
|
-
d->next = dev;
|
161
|
-
break;
|
162
|
-
}
|
163
|
-
d = d->next;
|
164
|
-
}
|
165
|
-
}
|
166
|
-
pthread_mutex_unlock(&device_list_mutex);
|
167
|
-
|
142
|
+
|
168
143
|
return dev;
|
169
144
|
}
|
170
145
|
|
@@ -172,7 +147,7 @@ static void free_hid_device(hid_device *dev)
|
|
172
147
|
{
|
173
148
|
if (!dev)
|
174
149
|
return;
|
175
|
-
|
150
|
+
|
176
151
|
/* Delete any input reports still left over. */
|
177
152
|
struct input_report *rpt = dev->input_reports;
|
178
153
|
while (rpt) {
|
@@ -197,29 +172,11 @@ static void free_hid_device(hid_device *dev)
|
|
197
172
|
pthread_cond_destroy(&dev->condition);
|
198
173
|
pthread_mutex_destroy(&dev->mutex);
|
199
174
|
|
200
|
-
/* Remove it from the device list. */
|
201
|
-
pthread_mutex_lock(&device_list_mutex);
|
202
|
-
hid_device *d = device_list;
|
203
|
-
if (d == dev) {
|
204
|
-
device_list = d->next;
|
205
|
-
}
|
206
|
-
else {
|
207
|
-
while (d) {
|
208
|
-
if (d->next == dev) {
|
209
|
-
d->next = d->next->next;
|
210
|
-
break;
|
211
|
-
}
|
212
|
-
|
213
|
-
d = d->next;
|
214
|
-
}
|
215
|
-
}
|
216
|
-
pthread_mutex_unlock(&device_list_mutex);
|
217
|
-
|
218
175
|
/* Free the structure itself. */
|
219
176
|
free(dev);
|
220
177
|
}
|
221
178
|
|
222
|
-
static
|
179
|
+
static IOHIDManagerRef hid_mgr = 0x0;
|
223
180
|
|
224
181
|
|
225
182
|
#if 0
|
@@ -234,7 +191,7 @@ static int32_t get_int_property(IOHIDDeviceRef device, CFStringRef key)
|
|
234
191
|
{
|
235
192
|
CFTypeRef ref;
|
236
193
|
int32_t value;
|
237
|
-
|
194
|
+
|
238
195
|
ref = IOHIDDeviceGetProperty(device, key);
|
239
196
|
if (ref) {
|
240
197
|
if (CFGetTypeID(ref) == CFNumberGetTypeID()) {
|
@@ -255,6 +212,10 @@ static unsigned short get_product_id(IOHIDDeviceRef device)
|
|
255
212
|
return get_int_property(device, CFSTR(kIOHIDProductIDKey));
|
256
213
|
}
|
257
214
|
|
215
|
+
static int32_t get_location_id(IOHIDDeviceRef device)
|
216
|
+
{
|
217
|
+
return get_int_property(device, CFSTR(kIOHIDLocationIDKey));
|
218
|
+
}
|
258
219
|
|
259
220
|
static int32_t get_max_report_length(IOHIDDeviceRef device)
|
260
221
|
{
|
@@ -264,7 +225,7 @@ static int32_t get_max_report_length(IOHIDDeviceRef device)
|
|
264
225
|
static int get_string_property(IOHIDDeviceRef device, CFStringRef prop, wchar_t *buf, size_t len)
|
265
226
|
{
|
266
227
|
CFStringRef str;
|
267
|
-
|
228
|
+
|
268
229
|
if (!len)
|
269
230
|
return 0;
|
270
231
|
|
@@ -273,29 +234,34 @@ static int get_string_property(IOHIDDeviceRef device, CFStringRef prop, wchar_t
|
|
273
234
|
buf[0] = 0;
|
274
235
|
|
275
236
|
if (str) {
|
276
|
-
len --;
|
277
|
-
|
278
237
|
CFIndex str_len = CFStringGetLength(str);
|
279
238
|
CFRange range;
|
280
|
-
range.location = 0;
|
281
|
-
range.length = (str_len > len)? len: str_len;
|
282
239
|
CFIndex used_buf_len;
|
283
240
|
CFIndex chars_copied;
|
241
|
+
|
242
|
+
len --;
|
243
|
+
|
244
|
+
range.location = 0;
|
245
|
+
range.length = ((size_t)str_len > len)? len: (size_t)str_len;
|
284
246
|
chars_copied = CFStringGetBytes(str,
|
285
247
|
range,
|
286
248
|
kCFStringEncodingUTF32LE,
|
287
249
|
(char)'?',
|
288
250
|
FALSE,
|
289
251
|
(UInt8*)buf,
|
290
|
-
len,
|
252
|
+
len * sizeof(wchar_t),
|
291
253
|
&used_buf_len);
|
292
254
|
|
293
|
-
|
255
|
+
if (chars_copied == len)
|
256
|
+
buf[len] = 0; /* len is decremented above */
|
257
|
+
else
|
258
|
+
buf[chars_copied] = 0;
|
259
|
+
|
294
260
|
return 0;
|
295
261
|
}
|
296
262
|
else
|
297
263
|
return -1;
|
298
|
-
|
264
|
+
|
299
265
|
}
|
300
266
|
|
301
267
|
static int get_string_property_utf8(IOHIDDeviceRef device, CFStringRef prop, char *buf, size_t len)
|
@@ -314,7 +280,7 @@ static int get_string_property_utf8(IOHIDDeviceRef device, CFStringRef prop, cha
|
|
314
280
|
CFIndex str_len = CFStringGetLength(str);
|
315
281
|
CFRange range;
|
316
282
|
range.location = 0;
|
317
|
-
range.length =
|
283
|
+
range.length = str_len;
|
318
284
|
CFIndex used_buf_len;
|
319
285
|
CFIndex chars_copied;
|
320
286
|
chars_copied = CFStringGetBytes(str,
|
@@ -326,8 +292,12 @@ static int get_string_property_utf8(IOHIDDeviceRef device, CFStringRef prop, cha
|
|
326
292
|
len,
|
327
293
|
&used_buf_len);
|
328
294
|
|
329
|
-
|
330
|
-
|
295
|
+
if (used_buf_len == len)
|
296
|
+
buf[len] = 0; /* len is decremented above */
|
297
|
+
else
|
298
|
+
buf[used_buf_len] = 0;
|
299
|
+
|
300
|
+
return used_buf_len;
|
331
301
|
}
|
332
302
|
else
|
333
303
|
return 0;
|
@@ -366,23 +336,25 @@ static int make_path(IOHIDDeviceRef device, char *buf, size_t len)
|
|
366
336
|
int res;
|
367
337
|
unsigned short vid, pid;
|
368
338
|
char transport[32];
|
339
|
+
int32_t location;
|
369
340
|
|
370
341
|
buf[0] = '\0';
|
371
342
|
|
372
343
|
res = get_string_property_utf8(
|
373
344
|
device, CFSTR(kIOHIDTransportKey),
|
374
345
|
transport, sizeof(transport));
|
375
|
-
|
346
|
+
|
376
347
|
if (!res)
|
377
348
|
return -1;
|
378
349
|
|
350
|
+
location = get_location_id(device);
|
379
351
|
vid = get_vendor_id(device);
|
380
352
|
pid = get_product_id(device);
|
381
353
|
|
382
|
-
res = snprintf(buf, len, "%s_%04hx_%04hx_%
|
383
|
-
|
384
|
-
|
385
|
-
|
354
|
+
res = snprintf(buf, len, "%s_%04hx_%04hx_%x",
|
355
|
+
transport, vid, pid, location);
|
356
|
+
|
357
|
+
|
386
358
|
buf[len-1] = '\0';
|
387
359
|
return res+1;
|
388
360
|
}
|
@@ -390,8 +362,6 @@ static int make_path(IOHIDDeviceRef device, char *buf, size_t len)
|
|
390
362
|
/* Initialize the IOHIDManager. Return 0 for success and -1 for failure. */
|
391
363
|
static int init_hid_manager(void)
|
392
364
|
{
|
393
|
-
//IOReturn res;
|
394
|
-
|
395
365
|
/* Initialize all the HID Manager Objects */
|
396
366
|
hid_mgr = IOHIDManagerCreate(kCFAllocatorDefault, kIOHIDOptionsTypeNone);
|
397
367
|
if (hid_mgr) {
|
@@ -399,7 +369,7 @@ static int init_hid_manager(void)
|
|
399
369
|
IOHIDManagerScheduleWithRunLoop(hid_mgr, CFRunLoopGetCurrent(), kCFRunLoopDefaultMode);
|
400
370
|
return 0;
|
401
371
|
}
|
402
|
-
|
372
|
+
|
403
373
|
return -1;
|
404
374
|
}
|
405
375
|
|
@@ -424,11 +394,11 @@ int HID_API_EXPORT hid_exit(void)
|
|
424
394
|
CFRelease(hid_mgr);
|
425
395
|
hid_mgr = NULL;
|
426
396
|
}
|
427
|
-
|
397
|
+
|
428
398
|
return 0;
|
429
399
|
}
|
430
400
|
|
431
|
-
static void process_pending_events() {
|
401
|
+
static void process_pending_events(void) {
|
432
402
|
SInt32 res;
|
433
403
|
do {
|
434
404
|
res = CFRunLoopRunInMode(kCFRunLoopDefaultMode, 0.001, FALSE);
|
@@ -437,27 +407,27 @@ static void process_pending_events() {
|
|
437
407
|
|
438
408
|
struct hid_device_info HID_API_EXPORT *hid_enumerate(unsigned short vendor_id, unsigned short product_id)
|
439
409
|
{
|
440
|
-
struct hid_device_info *root = NULL;
|
410
|
+
struct hid_device_info *root = NULL; /* return object */
|
441
411
|
struct hid_device_info *cur_dev = NULL;
|
442
412
|
CFIndex num_devices;
|
443
413
|
int i;
|
444
|
-
|
414
|
+
|
445
415
|
/* Set up the HID Manager if it hasn't been done */
|
446
416
|
if (hid_init() < 0)
|
447
417
|
return NULL;
|
448
|
-
|
418
|
+
|
449
419
|
/* give the IOHIDManager a chance to update itself */
|
450
420
|
process_pending_events();
|
451
421
|
|
452
422
|
/* Get a list of the Devices */
|
453
423
|
CFSetRef device_set = IOHIDManagerCopyDevices(hid_mgr);
|
454
424
|
|
455
|
-
/* Convert the list into a C array so we can iterate easily. */
|
425
|
+
/* Convert the list into a C array so we can iterate easily. */
|
456
426
|
num_devices = CFSetGetCount(device_set);
|
457
427
|
IOHIDDeviceRef *device_array = calloc(num_devices, sizeof(IOHIDDeviceRef));
|
458
428
|
CFSetGetValues(device_set, (const void **) device_array);
|
459
429
|
|
460
|
-
/* Iterate over each device, making an entry for it. */
|
430
|
+
/* Iterate over each device, making an entry for it. */
|
461
431
|
for (i = 0; i < num_devices; i++) {
|
462
432
|
unsigned short dev_vid;
|
463
433
|
unsigned short dev_pid;
|
@@ -474,12 +444,12 @@ struct hid_device_info HID_API_EXPORT *hid_enumerate(unsigned short vendor_id,
|
|
474
444
|
dev_pid = get_product_id(dev);
|
475
445
|
|
476
446
|
/* Check the VID/PID against the arguments */
|
477
|
-
if ((vendor_id == 0x0
|
478
|
-
(
|
447
|
+
if ((vendor_id == 0x0 || vendor_id == dev_vid) &&
|
448
|
+
(product_id == 0x0 || product_id == dev_pid)) {
|
479
449
|
struct hid_device_info *tmp;
|
480
450
|
size_t len;
|
481
451
|
|
482
|
-
|
452
|
+
/* VID/PID match. Create the record. */
|
483
453
|
tmp = malloc(sizeof(struct hid_device_info));
|
484
454
|
if (cur_dev) {
|
485
455
|
cur_dev->next = tmp;
|
@@ -489,7 +459,7 @@ struct hid_device_info HID_API_EXPORT *hid_enumerate(unsigned short vendor_id,
|
|
489
459
|
}
|
490
460
|
cur_dev = tmp;
|
491
461
|
|
492
|
-
|
462
|
+
/* Get the Usage Page and Usage for this device. */
|
493
463
|
cur_dev->usage_page = get_int_property(dev, CFSTR(kIOHIDPrimaryUsagePageKey));
|
494
464
|
cur_dev->usage = get_int_property(dev, CFSTR(kIOHIDPrimaryUsageKey));
|
495
465
|
|
@@ -507,7 +477,7 @@ struct hid_device_info HID_API_EXPORT *hid_enumerate(unsigned short vendor_id,
|
|
507
477
|
cur_dev->manufacturer_string = dup_wcs(buf);
|
508
478
|
get_product_string(dev, buf, BUF_LEN);
|
509
479
|
cur_dev->product_string = dup_wcs(buf);
|
510
|
-
|
480
|
+
|
511
481
|
/* VID/PID */
|
512
482
|
cur_dev->vendor_id = dev_vid;
|
513
483
|
cur_dev->product_id = dev_pid;
|
@@ -519,10 +489,10 @@ struct hid_device_info HID_API_EXPORT *hid_enumerate(unsigned short vendor_id,
|
|
519
489
|
cur_dev->interface_number = -1;
|
520
490
|
}
|
521
491
|
}
|
522
|
-
|
492
|
+
|
523
493
|
free(device_array);
|
524
494
|
CFRelease(device_set);
|
525
|
-
|
495
|
+
|
526
496
|
return root;
|
527
497
|
}
|
528
498
|
|
@@ -547,7 +517,7 @@ hid_device * HID_API_EXPORT hid_open(unsigned short vendor_id, unsigned short pr
|
|
547
517
|
struct hid_device_info *devs, *cur_dev;
|
548
518
|
const char *path_to_open = NULL;
|
549
519
|
hid_device * handle = NULL;
|
550
|
-
|
520
|
+
|
551
521
|
devs = hid_enumerate(vendor_id, product_id);
|
552
522
|
cur_dev = devs;
|
553
523
|
while (cur_dev) {
|
@@ -573,25 +543,18 @@ hid_device * HID_API_EXPORT hid_open(unsigned short vendor_id, unsigned short pr
|
|
573
543
|
}
|
574
544
|
|
575
545
|
hid_free_enumeration(devs);
|
576
|
-
|
546
|
+
|
577
547
|
return handle;
|
578
548
|
}
|
579
549
|
|
580
550
|
static void hid_device_removal_callback(void *context, IOReturn result,
|
581
|
-
void *sender
|
551
|
+
void *sender)
|
582
552
|
{
|
583
553
|
/* Stop the Run Loop for this device. */
|
584
|
-
|
585
|
-
|
586
|
-
|
587
|
-
|
588
|
-
d->disconnected = 1;
|
589
|
-
CFRunLoopStop(d->run_loop);
|
590
|
-
}
|
591
|
-
|
592
|
-
d = d->next;
|
593
|
-
}
|
594
|
-
pthread_mutex_unlock(&device_list_mutex);
|
554
|
+
hid_device *d = context;
|
555
|
+
|
556
|
+
d->disconnected = 1;
|
557
|
+
CFRunLoopStop(d->run_loop);
|
595
558
|
}
|
596
559
|
|
597
560
|
/* The Run Loop calls this function for each input report received.
|
@@ -613,7 +576,7 @@ static void hid_report_callback(void *context, IOReturn result, void *sender,
|
|
613
576
|
|
614
577
|
/* Lock this section */
|
615
578
|
pthread_mutex_lock(&dev->mutex);
|
616
|
-
|
579
|
+
|
617
580
|
/* Attach the new report object to the end of the list. */
|
618
581
|
if (dev->input_reports == NULL) {
|
619
582
|
/* The list is empty. Put it at the root. */
|
@@ -650,13 +613,14 @@ static void hid_report_callback(void *context, IOReturn result, void *sender,
|
|
650
613
|
static void perform_signal_callback(void *context)
|
651
614
|
{
|
652
615
|
hid_device *dev = context;
|
653
|
-
CFRunLoopStop(dev->run_loop);
|
616
|
+
CFRunLoopStop(dev->run_loop); /*TODO: CFRunLoopGetCurrent()*/
|
654
617
|
}
|
655
618
|
|
656
619
|
static void *read_thread(void *param)
|
657
620
|
{
|
658
621
|
hid_device *dev = param;
|
659
|
-
|
622
|
+
SInt32 code;
|
623
|
+
|
660
624
|
/* Move the device's run loop to this thread. */
|
661
625
|
IOHIDDeviceScheduleWithRunLoop(dev->device_handle, CFRunLoopGetCurrent(), dev->run_loop_mode);
|
662
626
|
|
@@ -669,7 +633,7 @@ static void *read_thread(void *param)
|
|
669
633
|
ctx.perform = &perform_signal_callback;
|
670
634
|
dev->source = CFRunLoopSourceCreate(kCFAllocatorDefault, 0/*order*/, &ctx);
|
671
635
|
CFRunLoopAddSource(CFRunLoopGetCurrent(), dev->source, dev->run_loop_mode);
|
672
|
-
|
636
|
+
|
673
637
|
/* Store off the Run Loop so it can be stopped from hid_close()
|
674
638
|
and on device disconnection. */
|
675
639
|
dev->run_loop = CFRunLoopGetCurrent();
|
@@ -679,7 +643,6 @@ static void *read_thread(void *param)
|
|
679
643
|
|
680
644
|
/* Run the Event Loop. CFRunLoopRunInMode() will dispatch HID input
|
681
645
|
reports into the hid_report_callback(). */
|
682
|
-
SInt32 code;
|
683
646
|
while (!dev->shutdown_thread && !dev->disconnected) {
|
684
647
|
code = CFRunLoopRunInMode(dev->run_loop_mode, 1000/*sec*/, FALSE);
|
685
648
|
/* Return if the device has been disconnected */
|
@@ -719,10 +682,10 @@ static void *read_thread(void *param)
|
|
719
682
|
|
720
683
|
hid_device * HID_API_EXPORT hid_open_path(const char *path)
|
721
684
|
{
|
722
|
-
|
685
|
+
int i;
|
723
686
|
hid_device *dev = NULL;
|
724
687
|
CFIndex num_devices;
|
725
|
-
|
688
|
+
|
726
689
|
dev = new_hid_device();
|
727
690
|
|
728
691
|
/* Set up the HID Manager if it hasn't been done */
|
@@ -733,19 +696,19 @@ hid_device * HID_API_EXPORT hid_open_path(const char *path)
|
|
733
696
|
process_pending_events();
|
734
697
|
|
735
698
|
CFSetRef device_set = IOHIDManagerCopyDevices(hid_mgr);
|
736
|
-
|
699
|
+
|
737
700
|
num_devices = CFSetGetCount(device_set);
|
738
701
|
IOHIDDeviceRef *device_array = calloc(num_devices, sizeof(IOHIDDeviceRef));
|
739
|
-
CFSetGetValues(device_set, (const void **) device_array);
|
702
|
+
CFSetGetValues(device_set, (const void **) device_array);
|
740
703
|
for (i = 0; i < num_devices; i++) {
|
741
704
|
char cbuf[BUF_LEN];
|
742
705
|
size_t len;
|
743
706
|
IOHIDDeviceRef os_dev = device_array[i];
|
744
|
-
|
707
|
+
|
745
708
|
len = make_path(os_dev, cbuf, sizeof(cbuf));
|
746
709
|
if (!strcmp(cbuf, path)) {
|
747
|
-
|
748
|
-
IOReturn ret = IOHIDDeviceOpen(os_dev,
|
710
|
+
/* Matched Paths. Open this Device. */
|
711
|
+
IOReturn ret = IOHIDDeviceOpen(os_dev, kIOHIDOptionsTypeSeizeDevice);
|
749
712
|
if (ret == kIOReturnSuccess) {
|
750
713
|
char str[32];
|
751
714
|
|
@@ -753,29 +716,29 @@ hid_device * HID_API_EXPORT hid_open_path(const char *path)
|
|
753
716
|
CFRetain(os_dev);
|
754
717
|
CFRelease(device_set);
|
755
718
|
dev->device_handle = os_dev;
|
756
|
-
|
719
|
+
|
757
720
|
/* Create the buffers for receiving data */
|
758
721
|
dev->max_input_report_len = (CFIndex) get_max_report_length(os_dev);
|
759
722
|
dev->input_report_buf = calloc(dev->max_input_report_len, sizeof(uint8_t));
|
760
|
-
|
723
|
+
|
761
724
|
/* Create the Run Loop Mode for this device.
|
762
725
|
printing the reference seems to work. */
|
763
726
|
sprintf(str, "HIDAPI_%p", os_dev);
|
764
|
-
dev->run_loop_mode =
|
727
|
+
dev->run_loop_mode =
|
765
728
|
CFStringCreateWithCString(NULL, str, kCFStringEncodingASCII);
|
766
|
-
|
729
|
+
|
767
730
|
/* Attach the device to a Run Loop */
|
768
731
|
IOHIDDeviceRegisterInputReportCallback(
|
769
732
|
os_dev, dev->input_report_buf, dev->max_input_report_len,
|
770
733
|
&hid_report_callback, dev);
|
771
|
-
|
772
|
-
|
734
|
+
IOHIDDeviceRegisterRemovalCallback(dev->device_handle, hid_device_removal_callback, dev);
|
735
|
+
|
773
736
|
/* Start the read thread */
|
774
737
|
pthread_create(&dev->thread, NULL, read_thread, dev);
|
775
738
|
|
776
739
|
/* Wait here for the read thread to be initialized. */
|
777
740
|
pthread_barrier_wait(&dev->barrier);
|
778
|
-
|
741
|
+
|
779
742
|
return dev;
|
780
743
|
}
|
781
744
|
else {
|
@@ -798,10 +761,9 @@ static int set_report(hid_device *dev, IOHIDReportType type, const unsigned char
|
|
798
761
|
IOReturn res;
|
799
762
|
|
800
763
|
/* Return if the device has been disconnected. */
|
801
|
-
|
802
|
-
|
803
|
-
|
804
|
-
}
|
764
|
+
if (dev->disconnected)
|
765
|
+
return -1;
|
766
|
+
|
805
767
|
if (data[0] == 0x0) {
|
806
768
|
/* Not using numbered Reports.
|
807
769
|
Don't send the report number. */
|
@@ -814,23 +776,20 @@ static int set_report(hid_device *dev, IOHIDReportType type, const unsigned char
|
|
814
776
|
data_to_send = data;
|
815
777
|
length_to_send = length;
|
816
778
|
}
|
817
|
-
|
779
|
+
|
818
780
|
if (!dev->disconnected) {
|
819
781
|
res = IOHIDDeviceSetReport(dev->device_handle,
|
820
782
|
type,
|
821
783
|
data[0], /* Report ID*/
|
822
784
|
data_to_send, length_to_send);
|
823
|
-
|
785
|
+
|
824
786
|
if (res == kIOReturnSuccess) {
|
825
|
-
return
|
787
|
+
return length;
|
826
788
|
}
|
827
|
-
else
|
828
|
-
// error could be 0xe000404f == kIOUSBPipeStalled
|
829
|
-
//printf("not success: %lx : len:%d\n", res,length_to_send);
|
789
|
+
else
|
830
790
|
return -1;
|
831
|
-
}
|
832
791
|
}
|
833
|
-
|
792
|
+
|
834
793
|
return -1;
|
835
794
|
}
|
836
795
|
|
@@ -850,7 +809,7 @@ static int return_data(hid_device *dev, unsigned char *data, size_t length)
|
|
850
809
|
dev->input_reports = rpt->next;
|
851
810
|
free(rpt->data);
|
852
811
|
free(rpt);
|
853
|
-
return
|
812
|
+
return len;
|
854
813
|
}
|
855
814
|
|
856
815
|
static int cond_wait(const hid_device *dev, pthread_cond_t *cond, pthread_mutex_t *mutex)
|
@@ -865,11 +824,11 @@ static int cond_wait(const hid_device *dev, pthread_cond_t *cond, pthread_mutex_
|
|
865
824
|
data in the queue before returning, and if not, go back
|
866
825
|
to sleep. See the pthread_cond_timedwait() man page for
|
867
826
|
details. */
|
868
|
-
|
827
|
+
|
869
828
|
if (dev->shutdown_thread || dev->disconnected)
|
870
829
|
return -1;
|
871
830
|
}
|
872
|
-
|
831
|
+
|
873
832
|
return 0;
|
874
833
|
}
|
875
834
|
|
@@ -885,11 +844,11 @@ static int cond_timedwait(const hid_device *dev, pthread_cond_t *cond, pthread_m
|
|
885
844
|
data in the queue before returning, and if not, go back
|
886
845
|
to sleep. See the pthread_cond_timedwait() man page for
|
887
846
|
details. */
|
888
|
-
|
847
|
+
|
889
848
|
if (dev->shutdown_thread || dev->disconnected)
|
890
849
|
return -1;
|
891
850
|
}
|
892
|
-
|
851
|
+
|
893
852
|
return 0;
|
894
853
|
|
895
854
|
}
|
@@ -900,7 +859,7 @@ int HID_API_EXPORT hid_read_timeout(hid_device *dev, unsigned char *data, size_t
|
|
900
859
|
|
901
860
|
/* Lock the access to the report list. */
|
902
861
|
pthread_mutex_lock(&dev->mutex);
|
903
|
-
|
862
|
+
|
904
863
|
/* There's an input report queued up. Return it. */
|
905
864
|
if (dev->input_reports) {
|
906
865
|
/* Return the first one */
|
@@ -913,7 +872,7 @@ int HID_API_EXPORT hid_read_timeout(hid_device *dev, unsigned char *data, size_t
|
|
913
872
|
bytes_read = -1;
|
914
873
|
goto ret;
|
915
874
|
}
|
916
|
-
|
875
|
+
|
917
876
|
if (dev->shutdown_thread) {
|
918
877
|
/* This means the device has been closed (or there
|
919
878
|
has been an error. An error code of -1 should
|
@@ -923,7 +882,7 @@ int HID_API_EXPORT hid_read_timeout(hid_device *dev, unsigned char *data, size_t
|
|
923
882
|
}
|
924
883
|
|
925
884
|
/* There is no data. Go to sleep and wait for data. */
|
926
|
-
|
885
|
+
|
927
886
|
if (milliseconds == -1) {
|
928
887
|
/* Blocking */
|
929
888
|
int res;
|
@@ -948,7 +907,7 @@ int HID_API_EXPORT hid_read_timeout(hid_device *dev, unsigned char *data, size_t
|
|
948
907
|
ts.tv_sec++;
|
949
908
|
ts.tv_nsec -= 1000000000L;
|
950
909
|
}
|
951
|
-
|
910
|
+
|
952
911
|
res = cond_timedwait(dev, &dev->condition, &dev->mutex, &ts);
|
953
912
|
if (res == 0)
|
954
913
|
bytes_read = return_data(dev, data, length);
|
@@ -977,7 +936,7 @@ int HID_API_EXPORT hid_set_nonblocking(hid_device *dev, int nonblock)
|
|
977
936
|
{
|
978
937
|
/* All Nonblocking operation is handled by the library. */
|
979
938
|
dev->blocking = !nonblock;
|
980
|
-
|
939
|
+
|
981
940
|
return 0;
|
982
941
|
}
|
983
942
|
|
@@ -1000,7 +959,7 @@ int HID_API_EXPORT hid_get_feature_report(hid_device *dev, unsigned char *data,
|
|
1000
959
|
data[0], /* Report ID */
|
1001
960
|
data, &len);
|
1002
961
|
if (res == kIOReturnSuccess)
|
1003
|
-
return
|
962
|
+
return len;
|
1004
963
|
else
|
1005
964
|
return -1;
|
1006
965
|
}
|
@@ -1016,18 +975,18 @@ void HID_API_EXPORT hid_close(hid_device *dev)
|
|
1016
975
|
IOHIDDeviceRegisterInputReportCallback(
|
1017
976
|
dev->device_handle, dev->input_report_buf, dev->max_input_report_len,
|
1018
977
|
NULL, dev);
|
1019
|
-
|
978
|
+
IOHIDDeviceRegisterRemovalCallback(dev->device_handle, NULL, dev);
|
1020
979
|
IOHIDDeviceUnscheduleFromRunLoop(dev->device_handle, dev->run_loop, dev->run_loop_mode);
|
1021
980
|
IOHIDDeviceScheduleWithRunLoop(dev->device_handle, CFRunLoopGetMain(), kCFRunLoopDefaultMode);
|
1022
981
|
}
|
1023
|
-
|
982
|
+
|
1024
983
|
/* Cause read_thread() to stop. */
|
1025
984
|
dev->shutdown_thread = 1;
|
1026
|
-
|
985
|
+
|
1027
986
|
/* Wake up the run thread's event loop so that the thread can exit. */
|
1028
987
|
CFRunLoopSourceSignal(dev->source);
|
1029
988
|
CFRunLoopWakeUp(dev->run_loop);
|
1030
|
-
|
989
|
+
|
1031
990
|
/* Notify the read thread that it can shut down now. */
|
1032
991
|
pthread_barrier_wait(&dev->shutdown_barrier);
|
1033
992
|
|
@@ -1038,9 +997,9 @@ void HID_API_EXPORT hid_close(hid_device *dev)
|
|
1038
997
|
been unplugged. If it's been unplugged, then calling
|
1039
998
|
IOHIDDeviceClose() will crash. */
|
1040
999
|
if (!dev->disconnected) {
|
1041
|
-
IOHIDDeviceClose(dev->device_handle,
|
1000
|
+
IOHIDDeviceClose(dev->device_handle, kIOHIDOptionsTypeSeizeDevice);
|
1042
1001
|
}
|
1043
|
-
|
1002
|
+
|
1044
1003
|
/* Clear out the queue of received reports. */
|
1045
1004
|
pthread_mutex_lock(&dev->mutex);
|
1046
1005
|
while (dev->input_reports) {
|
@@ -1069,7 +1028,7 @@ int HID_API_EXPORT_CALL hid_get_serial_number_string(hid_device *dev, wchar_t *s
|
|
1069
1028
|
|
1070
1029
|
int HID_API_EXPORT_CALL hid_get_indexed_string(hid_device *dev, int string_index, wchar_t *string, size_t maxlen)
|
1071
1030
|
{
|
1072
|
-
|
1031
|
+
/* TODO: */
|
1073
1032
|
|
1074
1033
|
return 0;
|
1075
1034
|
}
|
@@ -1077,7 +1036,7 @@ int HID_API_EXPORT_CALL hid_get_indexed_string(hid_device *dev, int string_index
|
|
1077
1036
|
|
1078
1037
|
HID_API_EXPORT const wchar_t * HID_API_CALL hid_error(hid_device *dev)
|
1079
1038
|
{
|
1080
|
-
|
1039
|
+
/* TODO: */
|
1081
1040
|
|
1082
1041
|
return NULL;
|
1083
1042
|
}
|
@@ -1087,12 +1046,8 @@ HID_API_EXPORT const wchar_t * HID_API_CALL hid_error(hid_device *dev)
|
|
1087
1046
|
|
1088
1047
|
|
1089
1048
|
|
1090
|
-
#if 0
|
1091
|
-
static int32_t get_location_id(IOHIDDeviceRef device)
|
1092
|
-
{
|
1093
|
-
return get_int_property(device, CFSTR(kIOHIDLocationIDKey));
|
1094
|
-
}
|
1095
1049
|
|
1050
|
+
#if 0
|
1096
1051
|
static int32_t get_usage(IOHIDDeviceRef device)
|
1097
1052
|
{
|
1098
1053
|
int32_t res;
|
@@ -1121,17 +1076,17 @@ int main(void)
|
|
1121
1076
|
{
|
1122
1077
|
IOHIDManagerRef mgr;
|
1123
1078
|
int i;
|
1124
|
-
|
1079
|
+
|
1125
1080
|
mgr = IOHIDManagerCreate(kCFAllocatorDefault, kIOHIDOptionsTypeNone);
|
1126
1081
|
IOHIDManagerSetDeviceMatching(mgr, NULL);
|
1127
1082
|
IOHIDManagerOpen(mgr, kIOHIDOptionsTypeNone);
|
1128
|
-
|
1083
|
+
|
1129
1084
|
CFSetRef device_set = IOHIDManagerCopyDevices(mgr);
|
1130
|
-
|
1085
|
+
|
1131
1086
|
CFIndex num_devices = CFSetGetCount(device_set);
|
1132
1087
|
IOHIDDeviceRef *device_array = calloc(num_devices, sizeof(IOHIDDeviceRef));
|
1133
1088
|
CFSetGetValues(device_set, (const void **) device_array);
|
1134
|
-
|
1089
|
+
|
1135
1090
|
for (i = 0; i < num_devices; i++) {
|
1136
1091
|
IOHIDDeviceRef dev = device_array[i];
|
1137
1092
|
printf("Device: %p\n", dev);
|
@@ -1141,16 +1096,16 @@ int main(void)
|
|
1141
1096
|
char cbuf[256];
|
1142
1097
|
get_serial_number(dev, serial, 256);
|
1143
1098
|
|
1144
|
-
|
1099
|
+
|
1145
1100
|
printf(" Serial: %ls\n", serial);
|
1146
1101
|
printf(" Loc: %ld\n", get_location_id(dev));
|
1147
1102
|
get_transport(dev, buf, 256);
|
1148
1103
|
printf(" Trans: %ls\n", buf);
|
1149
1104
|
make_path(dev, cbuf, 256);
|
1150
1105
|
printf(" Path: %s\n", cbuf);
|
1151
|
-
|
1106
|
+
|
1152
1107
|
}
|
1153
|
-
|
1108
|
+
|
1154
1109
|
return 0;
|
1155
1110
|
}
|
1156
|
-
#endif
|
1111
|
+
#endif
|