libusb 0.2.2 → 0.3.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (101) hide show
  1. data/.gitignore +8 -0
  2. data/.travis.yml +10 -0
  3. data/.yardopts +6 -1
  4. data/Gemfile +16 -0
  5. data/{History.txt → History.md} +28 -16
  6. data/README.md +144 -0
  7. data/Rakefile +28 -24
  8. data/ext/extconf.rb +33 -0
  9. data/ext/libusbx-1.0.14/AUTHORS +50 -0
  10. data/ext/libusbx-1.0.14/COPYING +504 -0
  11. data/ext/libusbx-1.0.14/ChangeLog +139 -0
  12. data/ext/libusbx-1.0.14/INSTALL +234 -0
  13. data/ext/libusbx-1.0.14/Makefile.am +23 -0
  14. data/ext/libusbx-1.0.14/Makefile.in +803 -0
  15. data/ext/libusbx-1.0.14/NEWS +2 -0
  16. data/ext/libusbx-1.0.14/PORTING +94 -0
  17. data/ext/libusbx-1.0.14/README +28 -0
  18. data/ext/libusbx-1.0.14/THANKS +7 -0
  19. data/ext/libusbx-1.0.14/TODO +2 -0
  20. data/ext/libusbx-1.0.14/aclocal.m4 +9480 -0
  21. data/ext/libusbx-1.0.14/compile +143 -0
  22. data/ext/libusbx-1.0.14/config.guess +1501 -0
  23. data/ext/libusbx-1.0.14/config.h.in +116 -0
  24. data/ext/libusbx-1.0.14/config.sub +1705 -0
  25. data/ext/libusbx-1.0.14/configure +14818 -0
  26. data/ext/libusbx-1.0.14/configure.ac +230 -0
  27. data/ext/libusbx-1.0.14/depcomp +630 -0
  28. data/ext/libusbx-1.0.14/doc/Makefile.am +9 -0
  29. data/ext/libusbx-1.0.14/doc/Makefile.in +380 -0
  30. data/ext/libusbx-1.0.14/doc/doxygen.cfg.in +1288 -0
  31. data/ext/libusbx-1.0.14/examples/Makefile.am +18 -0
  32. data/ext/libusbx-1.0.14/examples/Makefile.in +596 -0
  33. data/ext/libusbx-1.0.14/examples/dpfp.c +506 -0
  34. data/ext/libusbx-1.0.14/examples/dpfp_threaded.c +544 -0
  35. data/ext/libusbx-1.0.14/examples/ezusb.c +616 -0
  36. data/ext/libusbx-1.0.14/examples/ezusb.h +107 -0
  37. data/ext/libusbx-1.0.14/examples/fxload.c +261 -0
  38. data/ext/libusbx-1.0.14/examples/getopt/getopt.c +1060 -0
  39. data/ext/libusbx-1.0.14/examples/getopt/getopt.h +180 -0
  40. data/ext/libusbx-1.0.14/examples/getopt/getopt1.c +188 -0
  41. data/ext/libusbx-1.0.14/examples/listdevs.c +63 -0
  42. data/ext/libusbx-1.0.14/examples/xusb.c +1036 -0
  43. data/ext/libusbx-1.0.14/install-sh +520 -0
  44. data/ext/libusbx-1.0.14/libusb-1.0.pc.in +11 -0
  45. data/ext/libusbx-1.0.14/libusb/Makefile.am +56 -0
  46. data/ext/libusbx-1.0.14/libusb/Makefile.in +721 -0
  47. data/ext/libusbx-1.0.14/libusb/core.c +1951 -0
  48. data/ext/libusbx-1.0.14/libusb/descriptor.c +731 -0
  49. data/ext/libusbx-1.0.14/libusb/io.c +2450 -0
  50. data/ext/libusbx-1.0.14/libusb/libusb-1.0.def +126 -0
  51. data/ext/libusbx-1.0.14/libusb/libusb-1.0.rc +59 -0
  52. data/ext/libusbx-1.0.14/libusb/libusb.h +1506 -0
  53. data/ext/libusbx-1.0.14/libusb/libusbi.h +910 -0
  54. data/ext/libusbx-1.0.14/libusb/os/darwin_usb.c +1807 -0
  55. data/ext/libusbx-1.0.14/libusb/os/darwin_usb.h +169 -0
  56. data/ext/libusbx-1.0.14/libusb/os/linux_usbfs.c +2569 -0
  57. data/ext/libusbx-1.0.14/libusb/os/linux_usbfs.h +149 -0
  58. data/ext/libusbx-1.0.14/libusb/os/openbsd_usb.c +727 -0
  59. data/ext/libusbx-1.0.14/libusb/os/poll_posix.h +10 -0
  60. data/ext/libusbx-1.0.14/libusb/os/poll_windows.c +747 -0
  61. data/ext/libusbx-1.0.14/libusb/os/poll_windows.h +114 -0
  62. data/ext/libusbx-1.0.14/libusb/os/threads_posix.c +80 -0
  63. data/ext/libusbx-1.0.14/libusb/os/threads_posix.h +50 -0
  64. data/ext/libusbx-1.0.14/libusb/os/threads_windows.c +211 -0
  65. data/ext/libusbx-1.0.14/libusb/os/threads_windows.h +87 -0
  66. data/ext/libusbx-1.0.14/libusb/os/windows_usb.c +4369 -0
  67. data/ext/libusbx-1.0.14/libusb/os/windows_usb.h +979 -0
  68. data/ext/libusbx-1.0.14/libusb/sync.c +321 -0
  69. data/ext/libusbx-1.0.14/libusb/version.h +18 -0
  70. data/ext/libusbx-1.0.14/libusb/version_nano.h +1 -0
  71. data/ext/libusbx-1.0.14/ltmain.sh +9636 -0
  72. data/ext/libusbx-1.0.14/missing +376 -0
  73. data/lib/libusb.rb +2 -3
  74. data/lib/libusb/call.rb +49 -7
  75. data/lib/libusb/compat.rb +15 -9
  76. data/lib/libusb/configuration.rb +15 -3
  77. data/lib/libusb/constants.rb +19 -6
  78. data/lib/libusb/context.rb +181 -3
  79. data/lib/libusb/dev_handle.rb +91 -40
  80. data/lib/libusb/endpoint.rb +41 -14
  81. data/lib/libusb/eventmachine.rb +183 -0
  82. data/lib/libusb/transfer.rb +21 -8
  83. data/lib/libusb/version_gem.rb +19 -0
  84. data/lib/libusb/{version.rb → version_struct.rb} +0 -0
  85. data/libusb.gemspec +31 -0
  86. data/test/test_libusb_compat.rb +1 -1
  87. data/test/test_libusb_compat_mass_storage.rb +2 -2
  88. data/test/test_libusb_descriptors.rb +1 -1
  89. data/test/test_libusb_event_machine.rb +118 -0
  90. data/test/test_libusb_iso_transfer.rb +6 -1
  91. data/test/test_libusb_mass_storage.rb +9 -3
  92. data/test/test_libusb_mass_storage2.rb +1 -1
  93. data/test/test_libusb_structs.rb +45 -0
  94. data/test/test_libusb_threads.rb +89 -0
  95. data/test/test_libusb_version.rb +4 -0
  96. metadata +109 -44
  97. data/.autotest +0 -23
  98. data/.gemtest +0 -0
  99. data/Manifest.txt +0 -3
  100. data/README.rdoc +0 -115
  101. data/test/test_libusb_keyboard.rb +0 -50
@@ -0,0 +1,544 @@
1
+ /*
2
+ * libusbx example program to manipulate U.are.U 4000B fingerprint scanner.
3
+ * Copyright © 2007 Daniel Drake <dsd@gentoo.org>
4
+ *
5
+ * Basic image capture program only, does not consider the powerup quirks or
6
+ * the fact that image encryption may be enabled. Not expected to work
7
+ * flawlessly all of the time.
8
+ *
9
+ * This library is free software; you can redistribute it and/or
10
+ * modify it under the terms of the GNU Lesser General Public
11
+ * License as published by the Free Software Foundation; either
12
+ * version 2.1 of the License, or (at your option) any later version.
13
+ *
14
+ * This library is distributed in the hope that it will be useful,
15
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
16
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17
+ * Lesser General Public License for more details.
18
+ *
19
+ * You should have received a copy of the GNU Lesser General Public
20
+ * License along with this library; if not, write to the Free Software
21
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
22
+ */
23
+
24
+ #include <errno.h>
25
+ #include <pthread.h>
26
+ #include <signal.h>
27
+ #include <string.h>
28
+ #include <stdio.h>
29
+ #include <stdlib.h>
30
+
31
+ #include <libusb.h>
32
+
33
+ #define EP_INTR (1 | LIBUSB_ENDPOINT_IN)
34
+ #define EP_DATA (2 | LIBUSB_ENDPOINT_IN)
35
+ #define CTRL_IN (LIBUSB_REQUEST_TYPE_VENDOR | LIBUSB_ENDPOINT_IN)
36
+ #define CTRL_OUT (LIBUSB_REQUEST_TYPE_VENDOR | LIBUSB_ENDPOINT_OUT)
37
+ #define USB_RQ 0x04
38
+ #define INTR_LENGTH 64
39
+
40
+ enum {
41
+ MODE_INIT = 0x00,
42
+ MODE_AWAIT_FINGER_ON = 0x10,
43
+ MODE_AWAIT_FINGER_OFF = 0x12,
44
+ MODE_CAPTURE = 0x20,
45
+ MODE_SHUT_UP = 0x30,
46
+ MODE_READY = 0x80,
47
+ };
48
+
49
+ static int next_state(void);
50
+
51
+ enum {
52
+ STATE_AWAIT_MODE_CHANGE_AWAIT_FINGER_ON = 1,
53
+ STATE_AWAIT_IRQ_FINGER_DETECTED,
54
+ STATE_AWAIT_MODE_CHANGE_CAPTURE,
55
+ STATE_AWAIT_IMAGE,
56
+ STATE_AWAIT_MODE_CHANGE_AWAIT_FINGER_OFF,
57
+ STATE_AWAIT_IRQ_FINGER_REMOVED,
58
+ };
59
+
60
+ static int state = 0;
61
+ static struct libusb_device_handle *devh = NULL;
62
+ static unsigned char imgbuf[0x1b340];
63
+ static unsigned char irqbuf[INTR_LENGTH];
64
+ static struct libusb_transfer *img_transfer = NULL;
65
+ static struct libusb_transfer *irq_transfer = NULL;
66
+ static int img_idx = 0;
67
+ static int do_exit = 0;
68
+
69
+ static pthread_t poll_thread;
70
+ static pthread_cond_t exit_cond = PTHREAD_COND_INITIALIZER;
71
+ static pthread_mutex_t exit_cond_lock = PTHREAD_MUTEX_INITIALIZER;
72
+
73
+ static void request_exit(int code)
74
+ {
75
+ do_exit = code;
76
+ pthread_cond_signal(&exit_cond);
77
+ }
78
+
79
+ static void *poll_thread_main(void *arg)
80
+ {
81
+ int r = 0;
82
+ printf("poll thread running\n");
83
+
84
+ while (!do_exit) {
85
+ struct timeval tv = { 1, 0 };
86
+ r = libusb_handle_events_timeout(NULL, &tv);
87
+ if (r < 0) {
88
+ request_exit(2);
89
+ break;
90
+ }
91
+ }
92
+
93
+ printf("poll thread shutting down\n");
94
+ return NULL;
95
+ }
96
+
97
+ static int find_dpfp_device(void)
98
+ {
99
+ devh = libusb_open_device_with_vid_pid(NULL, 0x05ba, 0x000a);
100
+ return devh ? 0 : -EIO;
101
+ }
102
+
103
+ static int print_f0_data(void)
104
+ {
105
+ unsigned char data[0x10];
106
+ int r;
107
+ unsigned int i;
108
+
109
+ r = libusb_control_transfer(devh, CTRL_IN, USB_RQ, 0xf0, 0, data,
110
+ sizeof(data), 0);
111
+ if (r < 0) {
112
+ fprintf(stderr, "F0 error %d\n", r);
113
+ return r;
114
+ }
115
+ if ((unsigned int) r < sizeof(data)) {
116
+ fprintf(stderr, "short read (%d)\n", r);
117
+ return -1;
118
+ }
119
+
120
+ printf("F0 data:");
121
+ for (i = 0; i < sizeof(data); i++)
122
+ printf("%02x ", data[i]);
123
+ printf("\n");
124
+ return 0;
125
+ }
126
+
127
+ static int get_hwstat(unsigned char *status)
128
+ {
129
+ int r;
130
+
131
+ r = libusb_control_transfer(devh, CTRL_IN, USB_RQ, 0x07, 0, status, 1, 0);
132
+ if (r < 0) {
133
+ fprintf(stderr, "read hwstat error %d\n", r);
134
+ return r;
135
+ }
136
+ if ((unsigned int) r < 1) {
137
+ fprintf(stderr, "short read (%d)\n", r);
138
+ return -1;
139
+ }
140
+
141
+ printf("hwstat reads %02x\n", *status);
142
+ return 0;
143
+ }
144
+
145
+ static int set_hwstat(unsigned char data)
146
+ {
147
+ int r;
148
+
149
+ printf("set hwstat to %02x\n", data);
150
+ r = libusb_control_transfer(devh, CTRL_OUT, USB_RQ, 0x07, 0, &data, 1, 0);
151
+ if (r < 0) {
152
+ fprintf(stderr, "set hwstat error %d\n", r);
153
+ return r;
154
+ }
155
+ if ((unsigned int) r < 1) {
156
+ fprintf(stderr, "short write (%d)", r);
157
+ return -1;
158
+ }
159
+
160
+ return 0;
161
+ }
162
+
163
+ static int set_mode(unsigned char data)
164
+ {
165
+ int r;
166
+ printf("set mode %02x\n", data);
167
+
168
+ r = libusb_control_transfer(devh, CTRL_OUT, USB_RQ, 0x4e, 0, &data, 1, 0);
169
+ if (r < 0) {
170
+ fprintf(stderr, "set mode error %d\n", r);
171
+ return r;
172
+ }
173
+ if ((unsigned int) r < 1) {
174
+ fprintf(stderr, "short write (%d)", r);
175
+ return -1;
176
+ }
177
+
178
+ return 0;
179
+ }
180
+
181
+ static void LIBUSB_CALL cb_mode_changed(struct libusb_transfer *transfer)
182
+ {
183
+ if (transfer->status != LIBUSB_TRANSFER_COMPLETED) {
184
+ fprintf(stderr, "mode change transfer not completed!\n");
185
+ request_exit(2);
186
+ }
187
+
188
+ printf("async cb_mode_changed length=%d actual_length=%d\n",
189
+ transfer->length, transfer->actual_length);
190
+ if (next_state() < 0)
191
+ request_exit(2);
192
+ }
193
+
194
+ static int set_mode_async(unsigned char data)
195
+ {
196
+ unsigned char *buf = (unsigned char*) malloc(LIBUSB_CONTROL_SETUP_SIZE + 1);
197
+ struct libusb_transfer *transfer;
198
+
199
+ if (!buf)
200
+ return -ENOMEM;
201
+
202
+ transfer = libusb_alloc_transfer(0);
203
+ if (!transfer) {
204
+ free(buf);
205
+ return -ENOMEM;
206
+ }
207
+
208
+ printf("async set mode %02x\n", data);
209
+ libusb_fill_control_setup(buf, CTRL_OUT, USB_RQ, 0x4e, 0, 1);
210
+ buf[LIBUSB_CONTROL_SETUP_SIZE] = data;
211
+ libusb_fill_control_transfer(transfer, devh, buf, cb_mode_changed, NULL,
212
+ 1000);
213
+
214
+ transfer->flags = LIBUSB_TRANSFER_SHORT_NOT_OK
215
+ | LIBUSB_TRANSFER_FREE_BUFFER | LIBUSB_TRANSFER_FREE_TRANSFER;
216
+ return libusb_submit_transfer(transfer);
217
+ }
218
+
219
+ static int do_sync_intr(unsigned char *data)
220
+ {
221
+ int r;
222
+ int transferred;
223
+
224
+ r = libusb_interrupt_transfer(devh, EP_INTR, data, INTR_LENGTH,
225
+ &transferred, 1000);
226
+ if (r < 0) {
227
+ fprintf(stderr, "intr error %d\n", r);
228
+ return r;
229
+ }
230
+ if (transferred < INTR_LENGTH) {
231
+ fprintf(stderr, "short read (%d)\n", r);
232
+ return -1;
233
+ }
234
+
235
+ printf("recv interrupt %04x\n", *((uint16_t *) data));
236
+ return 0;
237
+ }
238
+
239
+ static int sync_intr(unsigned char type)
240
+ {
241
+ int r;
242
+ unsigned char data[INTR_LENGTH];
243
+
244
+ while (1) {
245
+ r = do_sync_intr(data);
246
+ if (r < 0)
247
+ return r;
248
+ if (data[0] == type)
249
+ return 0;
250
+ }
251
+ }
252
+
253
+ static int save_to_file(unsigned char *data)
254
+ {
255
+ FILE *fd;
256
+ char filename[64];
257
+
258
+ snprintf(filename, sizeof(filename), "finger%d.pgm", img_idx++);
259
+ fd = fopen(filename, "w");
260
+ if (!fd)
261
+ return -1;
262
+
263
+ fputs("P5 384 289 255 ", fd);
264
+ (void) fwrite(data + 64, 1, 384*289, fd);
265
+ fclose(fd);
266
+ printf("saved image to %s\n", filename);
267
+ return 0;
268
+ }
269
+
270
+ static int next_state(void)
271
+ {
272
+ int r = 0;
273
+ printf("old state: %d\n", state);
274
+ switch (state) {
275
+ case STATE_AWAIT_IRQ_FINGER_REMOVED:
276
+ state = STATE_AWAIT_MODE_CHANGE_AWAIT_FINGER_ON;
277
+ r = set_mode_async(MODE_AWAIT_FINGER_ON);
278
+ break;
279
+ case STATE_AWAIT_MODE_CHANGE_AWAIT_FINGER_ON:
280
+ state = STATE_AWAIT_IRQ_FINGER_DETECTED;
281
+ break;
282
+ case STATE_AWAIT_IRQ_FINGER_DETECTED:
283
+ state = STATE_AWAIT_MODE_CHANGE_CAPTURE;
284
+ r = set_mode_async(MODE_CAPTURE);
285
+ break;
286
+ case STATE_AWAIT_MODE_CHANGE_CAPTURE:
287
+ state = STATE_AWAIT_IMAGE;
288
+ break;
289
+ case STATE_AWAIT_IMAGE:
290
+ state = STATE_AWAIT_MODE_CHANGE_AWAIT_FINGER_OFF;
291
+ r = set_mode_async(MODE_AWAIT_FINGER_OFF);
292
+ break;
293
+ case STATE_AWAIT_MODE_CHANGE_AWAIT_FINGER_OFF:
294
+ state = STATE_AWAIT_IRQ_FINGER_REMOVED;
295
+ break;
296
+ default:
297
+ printf("unrecognised state %d\n", state);
298
+ }
299
+ if (r < 0) {
300
+ fprintf(stderr, "error detected changing state\n");
301
+ return r;
302
+ }
303
+
304
+ printf("new state: %d\n", state);
305
+ return 0;
306
+ }
307
+
308
+ static void LIBUSB_CALL cb_irq(struct libusb_transfer *transfer)
309
+ {
310
+ unsigned char irqtype = transfer->buffer[0];
311
+
312
+ if (transfer->status != LIBUSB_TRANSFER_COMPLETED) {
313
+ fprintf(stderr, "irq transfer status %d?\n", transfer->status);
314
+ irq_transfer = NULL;
315
+ request_exit(2);
316
+ return;
317
+ }
318
+
319
+ printf("IRQ callback %02x\n", irqtype);
320
+ switch (state) {
321
+ case STATE_AWAIT_IRQ_FINGER_DETECTED:
322
+ if (irqtype == 0x01) {
323
+ if (next_state() < 0) {
324
+ request_exit(2);
325
+ return;
326
+ }
327
+ } else {
328
+ printf("finger-on-sensor detected in wrong state!\n");
329
+ }
330
+ break;
331
+ case STATE_AWAIT_IRQ_FINGER_REMOVED:
332
+ if (irqtype == 0x02) {
333
+ if (next_state() < 0) {
334
+ request_exit(2);
335
+ return;
336
+ }
337
+ } else {
338
+ printf("finger-on-sensor detected in wrong state!\n");
339
+ }
340
+ break;
341
+ }
342
+ if (libusb_submit_transfer(irq_transfer) < 0)
343
+ request_exit(2);
344
+ }
345
+
346
+ static void LIBUSB_CALL cb_img(struct libusb_transfer *transfer)
347
+ {
348
+ if (transfer->status != LIBUSB_TRANSFER_COMPLETED) {
349
+ fprintf(stderr, "img transfer status %d?\n", transfer->status);
350
+ img_transfer = NULL;
351
+ request_exit(2);
352
+ return;
353
+ }
354
+
355
+ printf("Image callback\n");
356
+ save_to_file(imgbuf);
357
+ if (next_state() < 0) {
358
+ request_exit(2);
359
+ return;
360
+ }
361
+ if (libusb_submit_transfer(img_transfer) < 0)
362
+ request_exit(2);
363
+ }
364
+
365
+ static int init_capture(void)
366
+ {
367
+ int r;
368
+
369
+ r = libusb_submit_transfer(irq_transfer);
370
+ if (r < 0)
371
+ return r;
372
+
373
+ r = libusb_submit_transfer(img_transfer);
374
+ if (r < 0) {
375
+ libusb_cancel_transfer(irq_transfer);
376
+ while (irq_transfer)
377
+ if (libusb_handle_events(NULL) < 0)
378
+ break;
379
+ return r;
380
+ }
381
+
382
+ /* start state machine */
383
+ state = STATE_AWAIT_IRQ_FINGER_REMOVED;
384
+ return next_state();
385
+ }
386
+
387
+ static int do_init(void)
388
+ {
389
+ unsigned char status;
390
+ int r;
391
+
392
+ r = get_hwstat(&status);
393
+ if (r < 0)
394
+ return r;
395
+
396
+ if (!(status & 0x80)) {
397
+ r = set_hwstat(status | 0x80);
398
+ if (r < 0)
399
+ return r;
400
+ r = get_hwstat(&status);
401
+ if (r < 0)
402
+ return r;
403
+ }
404
+
405
+ status &= ~0x80;
406
+ r = set_hwstat(status);
407
+ if (r < 0)
408
+ return r;
409
+
410
+ r = get_hwstat(&status);
411
+ if (r < 0)
412
+ return r;
413
+
414
+ r = sync_intr(0x56);
415
+ if (r < 0)
416
+ return r;
417
+
418
+ return 0;
419
+ }
420
+
421
+ static int alloc_transfers(void)
422
+ {
423
+ img_transfer = libusb_alloc_transfer(0);
424
+ if (!img_transfer)
425
+ return -ENOMEM;
426
+
427
+ irq_transfer = libusb_alloc_transfer(0);
428
+ if (!irq_transfer)
429
+ return -ENOMEM;
430
+
431
+ libusb_fill_bulk_transfer(img_transfer, devh, EP_DATA, imgbuf,
432
+ sizeof(imgbuf), cb_img, NULL, 0);
433
+ libusb_fill_interrupt_transfer(irq_transfer, devh, EP_INTR, irqbuf,
434
+ sizeof(irqbuf), cb_irq, NULL, 0);
435
+
436
+ return 0;
437
+ }
438
+
439
+ static void sighandler(int signum)
440
+ {
441
+ request_exit(1);
442
+ }
443
+
444
+ int main(void)
445
+ {
446
+ struct sigaction sigact;
447
+ int r = 1;
448
+
449
+ r = libusb_init(NULL);
450
+ if (r < 0) {
451
+ fprintf(stderr, "failed to initialise libusb\n");
452
+ exit(1);
453
+ }
454
+
455
+ r = find_dpfp_device();
456
+ if (r < 0) {
457
+ fprintf(stderr, "Could not find/open device\n");
458
+ goto out;
459
+ }
460
+
461
+ r = libusb_claim_interface(devh, 0);
462
+ if (r < 0) {
463
+ fprintf(stderr, "usb_claim_interface error %d %s\n", r, strerror(-r));
464
+ goto out;
465
+ }
466
+ printf("claimed interface\n");
467
+
468
+ r = print_f0_data();
469
+ if (r < 0)
470
+ goto out_release;
471
+
472
+ r = do_init();
473
+ if (r < 0)
474
+ goto out_deinit;
475
+
476
+ /* async from here onwards */
477
+
478
+ sigact.sa_handler = sighandler;
479
+ sigemptyset(&sigact.sa_mask);
480
+ sigact.sa_flags = 0;
481
+ sigaction(SIGINT, &sigact, NULL);
482
+ sigaction(SIGTERM, &sigact, NULL);
483
+ sigaction(SIGQUIT, &sigact, NULL);
484
+
485
+ r = pthread_create(&poll_thread, NULL, poll_thread_main, NULL);
486
+ if (r)
487
+ goto out_deinit;
488
+
489
+ r = alloc_transfers();
490
+ if (r < 0) {
491
+ request_exit(1);
492
+ pthread_join(poll_thread, NULL);
493
+ goto out_deinit;
494
+ }
495
+
496
+ r = init_capture();
497
+ if (r < 0) {
498
+ request_exit(1);
499
+ pthread_join(poll_thread, NULL);
500
+ goto out_deinit;
501
+ }
502
+
503
+ while (!do_exit) {
504
+ pthread_mutex_lock(&exit_cond_lock);
505
+ pthread_cond_wait(&exit_cond, &exit_cond_lock);
506
+ pthread_mutex_unlock(&exit_cond_lock);
507
+ }
508
+
509
+ printf("shutting down...\n");
510
+ pthread_join(poll_thread, NULL);
511
+
512
+ r = libusb_cancel_transfer(irq_transfer);
513
+ if (r < 0) {
514
+ request_exit(1);
515
+ goto out_deinit;
516
+ }
517
+
518
+ r = libusb_cancel_transfer(img_transfer);
519
+ if (r < 0) {
520
+ request_exit(1);
521
+ goto out_deinit;
522
+ }
523
+
524
+ while (img_transfer || irq_transfer)
525
+ if (libusb_handle_events(NULL) < 0)
526
+ break;
527
+
528
+ if (do_exit == 1)
529
+ r = 0;
530
+ else
531
+ r = 1;
532
+
533
+ out_deinit:
534
+ libusb_free_transfer(img_transfer);
535
+ libusb_free_transfer(irq_transfer);
536
+ set_mode(0);
537
+ set_hwstat(0x80);
538
+ out_release:
539
+ libusb_release_interface(devh, 0);
540
+ out:
541
+ libusb_close(devh);
542
+ libusb_exit(NULL);
543
+ return r >= 0 ? r : -r;
544
+ }