summaryrefslogtreecommitdiffstats
path: root/src/usb.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/usb.c')
-rw-r--r--src/usb.c470
1 files changed, 268 insertions, 202 deletions
diff --git a/src/usb.c b/src/usb.c
index f5e8092..3ce2abb 100644
--- a/src/usb.c
+++ b/src/usb.c
@@ -36,6 +36,10 @@
36#include "device.h" 36#include "device.h"
37#include "utils.h" 37#include "utils.h"
38 38
39#if (defined(LIBUSB_API_VERSION) && (LIBUSB_API_VERSION >= 0x01000102)) || (defined(LIBUSBX_API_VERSION) && (LIBUSBX_API_VERSION >= 0x01000102))
40#define HAVE_LIBUSB_HOTPLUG_API 1
41#endif
42
39// interval for device connection/disconnection polling, in milliseconds 43// interval for device connection/disconnection polling, in milliseconds
40// we need this because there is currently no asynchronous device discovery mechanism in libusb 44// we need this because there is currently no asynchronous device discovery mechanism in libusb
41#define DEVICE_POLL_TIME 1000 45#define DEVICE_POLL_TIME 1000
@@ -65,6 +69,7 @@ static struct timeval next_dev_poll_time;
65 69
66static int devlist_failures; 70static int devlist_failures;
67static int device_polling; 71static int device_polling;
72static int device_hotplug = 1;
68 73
69static void usb_disconnect(struct usb_device *dev) 74static void usb_disconnect(struct usb_device *dev)
70{ 75{
@@ -253,9 +258,217 @@ static int start_rx_loop(struct usb_device *dev)
253 return 0; 258 return 0;
254} 259}
255 260
261static int usb_device_add(libusb_device* dev)
262{
263 int j, res;
264 // the following are non-blocking operations on the device list
265 uint8_t bus = libusb_get_bus_number(dev);
266 uint8_t address = libusb_get_device_address(dev);
267 struct libusb_device_descriptor devdesc;
268 int found = 0;
269 FOREACH(struct usb_device *usbdev, &device_list) {
270 if(usbdev->bus == bus && usbdev->address == address) {
271 usbdev->alive = 1;
272 found = 1;
273 break;
274 }
275 } ENDFOREACH
276 if(found)
277 return 0; //device already found
278
279 if((res = libusb_get_device_descriptor(dev, &devdesc)) != 0) {
280 usbmuxd_log(LL_WARNING, "Could not get device descriptor for device %d-%d: %d", bus, address, res);
281 return -1;
282 }
283 if(devdesc.idVendor != VID_APPLE)
284 return -1;
285 if((devdesc.idProduct < PID_RANGE_LOW) ||
286 (devdesc.idProduct > PID_RANGE_MAX))
287 return -1;
288 libusb_device_handle *handle;
289 usbmuxd_log(LL_INFO, "Found new device with v/p %04x:%04x at %d-%d", devdesc.idVendor, devdesc.idProduct, bus, address);
290 // potentially blocking operations follow; they will only run when new devices are detected, which is acceptable
291 if((res = libusb_open(dev, &handle)) != 0) {
292 usbmuxd_log(LL_WARNING, "Could not open device %d-%d: %d", bus, address, res);
293 return -1;
294 }
295
296 int current_config = 0;
297 if((res = libusb_get_configuration(handle, &current_config)) != 0) {
298 usbmuxd_log(LL_WARNING, "Could not get configuration for device %d-%d: %d", bus, address, res);
299 libusb_close(handle);
300 return -1;
301 }
302 if (current_config != devdesc.bNumConfigurations) {
303 struct libusb_config_descriptor *config;
304 if((res = libusb_get_active_config_descriptor(dev, &config)) != 0) {
305 usbmuxd_log(LL_NOTICE, "Could not get old configuration descriptor for device %d-%d: %d", bus, address, res);
306 } else {
307 for(j=0; j<config->bNumInterfaces; j++) {
308 const struct libusb_interface_descriptor *intf = &config->interface[j].altsetting[0];
309 if((res = libusb_kernel_driver_active(handle, intf->bInterfaceNumber)) < 0) {
310 usbmuxd_log(LL_NOTICE, "Could not check kernel ownership of interface %d for device %d-%d: %d", intf->bInterfaceNumber, bus, address, res);
311 continue;
312 }
313 if(res == 1) {
314 usbmuxd_log(LL_INFO, "Detaching kernel driver for device %d-%d, interface %d", bus, address, intf->bInterfaceNumber);
315 if((res = libusb_detach_kernel_driver(handle, intf->bInterfaceNumber)) < 0) {
316 usbmuxd_log(LL_WARNING, "Could not detach kernel driver (%d), configuration change will probably fail!", res);
317 continue;
318 }
319 }
320 }
321 libusb_free_config_descriptor(config);
322 }
323
324 usbmuxd_log(LL_INFO, "Setting configuration for device %d-%d, from %d to %d", bus, address, current_config, devdesc.bNumConfigurations);
325 if((res = libusb_set_configuration(handle, devdesc.bNumConfigurations)) != 0) {
326 usbmuxd_log(LL_WARNING, "Could not set configuration %d for device %d-%d: %d", devdesc.bNumConfigurations, bus, address, res);
327 libusb_close(handle);
328 return -1;
329 }
330 }
331
332 struct libusb_config_descriptor *config;
333 if((res = libusb_get_active_config_descriptor(dev, &config)) != 0) {
334 usbmuxd_log(LL_WARNING, "Could not get configuration descriptor for device %d-%d: %d", bus, address, res);
335 libusb_close(handle);
336 return -1;
337 }
338
339 struct usb_device *usbdev;
340 usbdev = malloc(sizeof(struct usb_device));
341 memset(usbdev, 0, sizeof(*usbdev));
342
343 for(j=0; j<config->bNumInterfaces; j++) {
344 const struct libusb_interface_descriptor *intf = &config->interface[j].altsetting[0];
345 if(intf->bInterfaceClass != INTERFACE_CLASS ||
346 intf->bInterfaceSubClass != INTERFACE_SUBCLASS ||
347 intf->bInterfaceProtocol != INTERFACE_PROTOCOL)
348 continue;
349 if(intf->bNumEndpoints != 2) {
350 usbmuxd_log(LL_WARNING, "Endpoint count mismatch for interface %d of device %d-%d", intf->bInterfaceNumber, bus, address);
351 continue;
352 }
353 if((intf->endpoint[0].bEndpointAddress & 0x80) == LIBUSB_ENDPOINT_OUT &&
354 (intf->endpoint[1].bEndpointAddress & 0x80) == LIBUSB_ENDPOINT_IN) {
355 usbdev->interface = intf->bInterfaceNumber;
356 usbdev->ep_out = intf->endpoint[0].bEndpointAddress;
357 usbdev->ep_in = intf->endpoint[1].bEndpointAddress;
358 usbmuxd_log(LL_INFO, "Found interface %d with endpoints %02x/%02x for device %d-%d", usbdev->interface, usbdev->ep_out, usbdev->ep_in, bus, address);
359 break;
360 } else if((intf->endpoint[1].bEndpointAddress & 0x80) == LIBUSB_ENDPOINT_OUT &&
361 (intf->endpoint[0].bEndpointAddress & 0x80) == LIBUSB_ENDPOINT_IN) {
362 usbdev->interface = intf->bInterfaceNumber;
363 usbdev->ep_out = intf->endpoint[1].bEndpointAddress;
364 usbdev->ep_in = intf->endpoint[0].bEndpointAddress;
365 usbmuxd_log(LL_INFO, "Found interface %d with swapped endpoints %02x/%02x for device %d-%d", usbdev->interface, usbdev->ep_out, usbdev->ep_in, bus, address);
366 break;
367 } else {
368 usbmuxd_log(LL_WARNING, "Endpoint type mismatch for interface %d of device %d-%d", intf->bInterfaceNumber, bus, address);
369 }
370 }
371
372 if(j == config->bNumInterfaces) {
373 usbmuxd_log(LL_WARNING, "Could not find a suitable USB interface for device %d-%d", bus, address);
374 libusb_free_config_descriptor(config);
375 libusb_close(handle);
376 free(usbdev);
377 return -1;
378 }
379
380 libusb_free_config_descriptor(config);
381
382 if((res = libusb_claim_interface(handle, usbdev->interface)) != 0) {
383 usbmuxd_log(LL_WARNING, "Could not claim interface %d for device %d-%d: %d", usbdev->interface, bus, address, res);
384 libusb_close(handle);
385 free(usbdev);
386 return -1;
387 }
388
389 if((res = libusb_get_string_descriptor_ascii(handle, devdesc.iSerialNumber, (uint8_t *)usbdev->serial, 256)) <= 0) {
390 usbmuxd_log(LL_WARNING, "Could not get serial number for device %d-%d: %d", bus, address, res);
391 libusb_release_interface(handle, usbdev->interface);
392 libusb_close(handle);
393 free(usbdev);
394 return -1;
395 }
396 usbdev->serial[res] = 0;
397 usbdev->bus = bus;
398 usbdev->address = address;
399 usbdev->vid = devdesc.idVendor;
400 usbdev->pid = devdesc.idProduct;
401 usbdev->speed = 480000000;
402 usbdev->dev = handle;
403 usbdev->alive = 1;
404 usbdev->wMaxPacketSize = libusb_get_max_packet_size(dev, usbdev->ep_out);
405 if (usbdev->wMaxPacketSize <= 0) {
406 usbmuxd_log(LL_ERROR, "Could not determine wMaxPacketSize for device %d-%d, setting to 64", usbdev->bus, usbdev->address);
407 usbdev->wMaxPacketSize = 64;
408 } else {
409 usbmuxd_log(LL_INFO, "Using wMaxPacketSize=%d for device %d-%d", usbdev->wMaxPacketSize, usbdev->bus, usbdev->address);
410 }
411
412 switch (libusb_get_device_speed(dev)) {
413 case LIBUSB_SPEED_LOW:
414 usbdev->speed = 1500000;
415 break;
416 case LIBUSB_SPEED_FULL:
417 usbdev->speed = 12000000;
418 break;
419 case LIBUSB_SPEED_SUPER:
420 usbdev->speed = 5000000000;
421 break;
422 case LIBUSB_SPEED_HIGH:
423 case LIBUSB_SPEED_UNKNOWN:
424 default:
425 usbdev->speed = 480000000;
426 break;
427 }
428
429 usbmuxd_log(LL_INFO, "USB Speed is %g MBit/s for device %d-%d", (double)(usbdev->speed / 1000000.0), usbdev->bus, usbdev->address);
430
431 collection_init(&usbdev->tx_xfers);
432 collection_init(&usbdev->rx_xfers);
433
434 collection_add(&device_list, usbdev);
435
436 if(device_add(usbdev) < 0) {
437 usb_disconnect(usbdev);
438 return -1;
439 }
440
441 // Spin up NUM_RX_LOOPS parallel usb data retrieval loops
442 // Old usbmuxds used only 1 rx loop, but that leaves the
443 // USB port sleeping most of the time
444 int rx_loops = NUM_RX_LOOPS;
445 for (rx_loops = NUM_RX_LOOPS; rx_loops > 0; rx_loops--) {
446 if(start_rx_loop(usbdev) < 0) {
447 usbmuxd_log(LL_WARNING, "Failed to start RX loop number %d", NUM_RX_LOOPS - rx_loops);
448 }
449 }
450
451 // Ensure we have at least 1 RX loop going
452 if (rx_loops == NUM_RX_LOOPS) {
453 usbmuxd_log(LL_FATAL, "Failed to start any RX loop for device %d-%d",
454 usbdev->bus, usbdev->address);
455 device_remove(usbdev);
456 usb_disconnect(usbdev);
457 return -1;
458 } else if (rx_loops > 0) {
459 usbmuxd_log(LL_WARNING, "Failed to start all %d RX loops. Going on with %d loops. "
460 "This may have negative impact on device read speed.",
461 NUM_RX_LOOPS, NUM_RX_LOOPS - rx_loops);
462 } else {
463 usbmuxd_log(LL_DEBUG, "All %d RX loops started successfully", NUM_RX_LOOPS);
464 }
465
466 return 0;
467}
468
256int usb_discover(void) 469int usb_discover(void)
257{ 470{
258 int cnt, i, j, res; 471 int cnt, i;
259 int valid_count = 0; 472 int valid_count = 0;
260 libusb_device **devs; 473 libusb_device **devs;
261 474
@@ -288,209 +501,10 @@ int usb_discover(void)
288 // Enumerate all USB devices and mark the ones we already know 501 // Enumerate all USB devices and mark the ones we already know
289 // about as live, again 502 // about as live, again
290 for(i=0; i<cnt; i++) { 503 for(i=0; i<cnt; i++) {
291 // the following are non-blocking operations on the device list
292 libusb_device *dev = devs[i]; 504 libusb_device *dev = devs[i];
293 uint8_t bus = libusb_get_bus_number(dev); 505 if (usb_device_add(dev) < 0) {
294 uint8_t address = libusb_get_device_address(dev);
295 struct libusb_device_descriptor devdesc;
296 int found = 0;
297 FOREACH(struct usb_device *usbdev, &device_list) {
298 if(usbdev->bus == bus && usbdev->address == address) {
299 valid_count++;
300 usbdev->alive = 1;
301 found = 1;
302 break;
303 }
304 } ENDFOREACH
305 if(found)
306 continue; //device already found
307 if((res = libusb_get_device_descriptor(dev, &devdesc)) != 0) {
308 usbmuxd_log(LL_WARNING, "Could not get device descriptor for device %d-%d: %d", bus, address, res);
309 continue;
310 }
311 if(devdesc.idVendor != VID_APPLE)
312 continue;
313 if((devdesc.idProduct < PID_RANGE_LOW) ||
314 (devdesc.idProduct > PID_RANGE_MAX))
315 continue;
316 libusb_device_handle *handle;
317 usbmuxd_log(LL_INFO, "Found new device with v/p %04x:%04x at %d-%d", devdesc.idVendor, devdesc.idProduct, bus, address);
318 // potentially blocking operations follow; they will only run when new devices are detected, which is acceptable
319 if((res = libusb_open(dev, &handle)) != 0) {
320 usbmuxd_log(LL_WARNING, "Could not open device %d-%d: %d", bus, address, res);
321 continue; 506 continue;
322 } 507 }
323
324 int current_config = 0;
325 if((res = libusb_get_configuration(handle, &current_config)) != 0) {
326 usbmuxd_log(LL_WARNING, "Could not get configuration for device %d-%d: %d", bus, address, res);
327 libusb_close(handle);
328 continue;
329 }
330 if (current_config != devdesc.bNumConfigurations) {
331 struct libusb_config_descriptor *config;
332 if((res = libusb_get_active_config_descriptor(dev, &config)) != 0) {
333 usbmuxd_log(LL_NOTICE, "Could not get old configuration descriptor for device %d-%d: %d", bus, address, res);
334 } else {
335 for(j=0; j<config->bNumInterfaces; j++) {
336 const struct libusb_interface_descriptor *intf = &config->interface[j].altsetting[0];
337 if((res = libusb_kernel_driver_active(handle, intf->bInterfaceNumber)) < 0) {
338 usbmuxd_log(LL_NOTICE, "Could not check kernel ownership of interface %d for device %d-%d: %d", intf->bInterfaceNumber, bus, address, res);
339 continue;
340 }
341 if(res == 1) {
342 usbmuxd_log(LL_INFO, "Detaching kernel driver for device %d-%d, interface %d", bus, address, intf->bInterfaceNumber);
343 if((res = libusb_detach_kernel_driver(handle, intf->bInterfaceNumber)) < 0) {
344 usbmuxd_log(LL_WARNING, "Could not detach kernel driver (%d), configuration change will probably fail!", res);
345 continue;
346 }
347 }
348 }
349 libusb_free_config_descriptor(config);
350 }
351
352 usbmuxd_log(LL_INFO, "Setting configuration for device %d-%d, from %d to %d", bus, address, current_config, devdesc.bNumConfigurations);
353 if((res = libusb_set_configuration(handle, devdesc.bNumConfigurations)) != 0) {
354 usbmuxd_log(LL_WARNING, "Could not set configuration %d for device %d-%d: %d", devdesc.bNumConfigurations, bus, address, res);
355 libusb_close(handle);
356 continue;
357 }
358 }
359
360 struct libusb_config_descriptor *config;
361 if((res = libusb_get_active_config_descriptor(dev, &config)) != 0) {
362 usbmuxd_log(LL_WARNING, "Could not get configuration descriptor for device %d-%d: %d", bus, address, res);
363 libusb_close(handle);
364 continue;
365 }
366
367 struct usb_device *usbdev;
368 usbdev = malloc(sizeof(struct usb_device));
369 memset(usbdev, 0, sizeof(*usbdev));
370
371 for(j=0; j<config->bNumInterfaces; j++) {
372 const struct libusb_interface_descriptor *intf = &config->interface[j].altsetting[0];
373 if(intf->bInterfaceClass != INTERFACE_CLASS ||
374 intf->bInterfaceSubClass != INTERFACE_SUBCLASS ||
375 intf->bInterfaceProtocol != INTERFACE_PROTOCOL)
376 continue;
377 if(intf->bNumEndpoints != 2) {
378 usbmuxd_log(LL_WARNING, "Endpoint count mismatch for interface %d of device %d-%d", intf->bInterfaceNumber, bus, address);
379 continue;
380 }
381 if((intf->endpoint[0].bEndpointAddress & 0x80) == LIBUSB_ENDPOINT_OUT &&
382 (intf->endpoint[1].bEndpointAddress & 0x80) == LIBUSB_ENDPOINT_IN) {
383 usbdev->interface = intf->bInterfaceNumber;
384 usbdev->ep_out = intf->endpoint[0].bEndpointAddress;
385 usbdev->ep_in = intf->endpoint[1].bEndpointAddress;
386 usbmuxd_log(LL_INFO, "Found interface %d with endpoints %02x/%02x for device %d-%d", usbdev->interface, usbdev->ep_out, usbdev->ep_in, bus, address);
387 break;
388 } else if((intf->endpoint[1].bEndpointAddress & 0x80) == LIBUSB_ENDPOINT_OUT &&
389 (intf->endpoint[0].bEndpointAddress & 0x80) == LIBUSB_ENDPOINT_IN) {
390 usbdev->interface = intf->bInterfaceNumber;
391 usbdev->ep_out = intf->endpoint[1].bEndpointAddress;
392 usbdev->ep_in = intf->endpoint[0].bEndpointAddress;
393 usbmuxd_log(LL_INFO, "Found interface %d with swapped endpoints %02x/%02x for device %d-%d", usbdev->interface, usbdev->ep_out, usbdev->ep_in, bus, address);
394 break;
395 } else {
396 usbmuxd_log(LL_WARNING, "Endpoint type mismatch for interface %d of device %d-%d", intf->bInterfaceNumber, bus, address);
397 }
398 }
399
400 if(j == config->bNumInterfaces) {
401 usbmuxd_log(LL_WARNING, "Could not find a suitable USB interface for device %d-%d", bus, address);
402 libusb_free_config_descriptor(config);
403 libusb_close(handle);
404 free(usbdev);
405 continue;
406 }
407
408 libusb_free_config_descriptor(config);
409
410 if((res = libusb_claim_interface(handle, usbdev->interface)) != 0) {
411 usbmuxd_log(LL_WARNING, "Could not claim interface %d for device %d-%d: %d", usbdev->interface, bus, address, res);
412 libusb_close(handle);
413 free(usbdev);
414 continue;
415 }
416
417 if((res = libusb_get_string_descriptor_ascii(handle, devdesc.iSerialNumber, (uint8_t *)usbdev->serial, 256)) <= 0) {
418 usbmuxd_log(LL_WARNING, "Could not get serial number for device %d-%d: %d", bus, address, res);
419 libusb_release_interface(handle, usbdev->interface);
420 libusb_close(handle);
421 free(usbdev);
422 continue;
423 }
424 usbdev->serial[res] = 0;
425 usbdev->bus = bus;
426 usbdev->address = address;
427 usbdev->vid = devdesc.idVendor;
428 usbdev->pid = devdesc.idProduct;
429 usbdev->speed = 480000000;
430 usbdev->dev = handle;
431 usbdev->alive = 1;
432 usbdev->wMaxPacketSize = libusb_get_max_packet_size(dev, usbdev->ep_out);
433 if (usbdev->wMaxPacketSize <= 0) {
434 usbmuxd_log(LL_ERROR, "Could not determine wMaxPacketSize for device %d-%d, setting to 64", usbdev->bus, usbdev->address);
435 usbdev->wMaxPacketSize = 64;
436 } else {
437 usbmuxd_log(LL_INFO, "Using wMaxPacketSize=%d for device %d-%d", usbdev->wMaxPacketSize, usbdev->bus, usbdev->address);
438 }
439
440 switch (libusb_get_device_speed(dev)) {
441 case LIBUSB_SPEED_LOW:
442 usbdev->speed = 1500000;
443 break;
444 case LIBUSB_SPEED_FULL:
445 usbdev->speed = 12000000;
446 break;
447 case LIBUSB_SPEED_SUPER:
448 usbdev->speed = 5000000000;
449 break;
450 case LIBUSB_SPEED_HIGH:
451 case LIBUSB_SPEED_UNKNOWN:
452 default:
453 usbdev->speed = 480000000;
454 break;
455 }
456
457 usbmuxd_log(LL_INFO, "USB Speed is %g MBit/s for device %d-%d", (double)(usbdev->speed / 1000000.0), usbdev->bus, usbdev->address);
458
459 collection_init(&usbdev->tx_xfers);
460 collection_init(&usbdev->rx_xfers);
461
462 collection_add(&device_list, usbdev);
463
464 if(device_add(usbdev) < 0) {
465 usb_disconnect(usbdev);
466 continue;
467 }
468
469 // Spin up NUM_RX_LOOPS parallel usb data retrieval loops
470 // Old usbmuxds used only 1 rx loop, but that leaves the
471 // USB port sleeping most of the time
472 int rx_loops = NUM_RX_LOOPS;
473 for (rx_loops = NUM_RX_LOOPS; rx_loops > 0; rx_loops--) {
474 if(start_rx_loop(usbdev) < 0) {
475 usbmuxd_log(LL_WARNING, "Failed to start RX loop number %d", NUM_RX_LOOPS - rx_loops);
476 }
477 }
478
479 // Ensure we have at least 1 RX loop going
480 if (rx_loops == NUM_RX_LOOPS) {
481 usbmuxd_log(LL_FATAL, "Failed to start any RX loop for device %d-%d",
482 usbdev->bus, usbdev->address);
483 device_remove(usbdev);
484 usb_disconnect(usbdev);
485 continue;
486 } else if (rx_loops > 0) {
487 usbmuxd_log(LL_WARNING, "Failed to start all %d RX loops. Going on with %d loops. "
488 "This may have negative impact on device read speed.",
489 NUM_RX_LOOPS, NUM_RX_LOOPS - rx_loops);
490 } else {
491 usbmuxd_log(LL_DEBUG, "All %d RX loops started successfully", NUM_RX_LOOPS);
492 }
493
494 valid_count++; 508 valid_count++;
495 } 509 }
496 510
@@ -560,6 +574,7 @@ void usb_autodiscover(int enable)
560{ 574{
561 usbmuxd_log(LL_DEBUG, "usb polling enable: %d", enable); 575 usbmuxd_log(LL_DEBUG, "usb polling enable: %d", enable);
562 device_polling = enable; 576 device_polling = enable;
577 device_hotplug = enable;
563} 578}
564 579
565static int dev_poll_remain_ms(void) 580static int dev_poll_remain_ms(void)
@@ -649,6 +664,32 @@ int usb_process_timeout(int msec)
649 return 0; 664 return 0;
650} 665}
651 666
667#ifdef HAVE_LIBUSB_HOTPLUG_API
668static libusb_hotplug_callback_handle usb_hotplug_cb_handle;
669
670static int usb_hotplug_cb(libusb_context *ctx, libusb_device *device, libusb_hotplug_event event, void *user_data)
671{
672 if (LIBUSB_HOTPLUG_EVENT_DEVICE_ARRIVED == event) {
673 if (device_hotplug) {
674 usb_device_add(device);
675 }
676 } else if (LIBUSB_HOTPLUG_EVENT_DEVICE_LEFT == event) {
677 uint8_t bus = libusb_get_bus_number(device);
678 uint8_t address = libusb_get_device_address(device);
679 FOREACH(struct usb_device *usbdev, &device_list) {
680 if(usbdev->bus == bus && usbdev->address == address) {
681 usbdev->alive = 0;
682 device_remove(usbdev);
683 break;
684 }
685 } ENDFOREACH
686 } else {
687 usbmuxd_log(LL_ERROR, "Unhandled event %d", event);
688 }
689 return 0;
690}
691#endif
692
652int usb_init(void) 693int usb_init(void)
653{ 694{
654 int res; 695 int res;
@@ -665,12 +706,37 @@ int usb_init(void)
665 706
666 collection_init(&device_list); 707 collection_init(&device_list);
667 708
668 return usb_discover(); 709#ifdef HAVE_LIBUSB_HOTPLUG_API
710 if (libusb_has_capability(LIBUSB_CAP_HAS_HOTPLUG)) {
711 usbmuxd_log(LL_INFO, "Registering for libusb hotplug events");
712 res = libusb_hotplug_register_callback(NULL, LIBUSB_HOTPLUG_EVENT_DEVICE_ARRIVED | LIBUSB_HOTPLUG_EVENT_DEVICE_LEFT, LIBUSB_HOTPLUG_ENUMERATE, VID_APPLE, LIBUSB_HOTPLUG_MATCH_ANY, 0, usb_hotplug_cb, NULL, &usb_hotplug_cb_handle);
713 if (res == LIBUSB_SUCCESS) {
714 device_polling = 0;
715 } else {
716 usbmuxd_log(LL_ERROR, "ERROR: Could not register for libusb hotplug events (%d)", res);
717 }
718 } else {
719 usbmuxd_log(LL_ERROR, "libusb does not support hotplug events");
720 }
721#endif
722 if (device_polling) {
723 res = usb_discover();
724 if (res >= 0) {
725 }
726 } else {
727 res = collection_count(&device_list);
728 }
729 return res;
669} 730}
670 731
671void usb_shutdown(void) 732void usb_shutdown(void)
672{ 733{
673 usbmuxd_log(LL_DEBUG, "usb_shutdown"); 734 usbmuxd_log(LL_DEBUG, "usb_shutdown");
735
736#ifdef HAVE_LIBUSB_HOTPLUG_API
737 libusb_hotplug_deregister_callback(NULL, usb_hotplug_cb_handle);
738#endif
739
674 FOREACH(struct usb_device *usbdev, &device_list) { 740 FOREACH(struct usb_device *usbdev, &device_list) {
675 device_remove(usbdev); 741 device_remove(usbdev);
676 usb_disconnect(usbdev); 742 usb_disconnect(usbdev);