summaryrefslogtreecommitdiffstats
path: root/src/usb.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/usb.c')
-rw-r--r--src/usb.c119
1 files changed, 67 insertions, 52 deletions
diff --git a/src/usb.c b/src/usb.c
index f380b60..2e42e59 100644
--- a/src/usb.c
+++ b/src/usb.c
@@ -67,7 +67,6 @@ struct usb_device {
67 67
68struct mode_context { 68struct mode_context {
69 struct libusb_device* dev; 69 struct libusb_device* dev;
70 struct libusb_device_descriptor devdesc;
71 uint8_t bus, address; 70 uint8_t bus, address;
72 uint8_t bRequest; 71 uint8_t bRequest;
73 uint16_t wValue, wIndex, wLength; 72 uint16_t wValue, wIndex, wLength;
@@ -374,17 +373,32 @@ static int submit_vendor_specific(struct libusb_device_handle *handle, struct mo
374 uint8_t bRequestType = LIBUSB_REQUEST_TYPE_VENDOR | LIBUSB_ENDPOINT_IN | LIBUSB_RECIPIENT_DEVICE; 373 uint8_t bRequestType = LIBUSB_REQUEST_TYPE_VENDOR | LIBUSB_ENDPOINT_IN | LIBUSB_RECIPIENT_DEVICE;
375 libusb_fill_control_setup(buffer, bRequestType, context->bRequest, context->wValue, context->wIndex, context->wLength); 374 libusb_fill_control_setup(buffer, bRequestType, context->bRequest, context->wValue, context->wIndex, context->wLength);
376 375
377 ctrl_transfer->flags = LIBUSB_TRANSFER_FREE_TRANSFER | LIBUSB_TRANSFER_FREE_TRANSFER; 376 ctrl_transfer->flags = LIBUSB_TRANSFER_FREE_TRANSFER;
378 libusb_fill_control_transfer(ctrl_transfer, handle, buffer, callback, context, context->timeout); 377 libusb_fill_control_transfer(ctrl_transfer, handle, buffer, callback, context, context->timeout);
379 378
380 ret = libusb_submit_transfer(ctrl_transfer); 379 ret = libusb_submit_transfer(ctrl_transfer);
381 return ret; 380 return ret;
382} 381}
383 382
384static int device_complete_initialization(struct mode_context *context, struct libusb_device_handle *handle) 383static struct usb_device* find_device(int bus, int address)
384{
385 FOREACH(struct usb_device *usbdev, &device_list) {
386 if(usbdev->bus == bus && usbdev->address == address) {
387 return usbdev;
388 }
389 } ENDFOREACH
390 return NULL;
391}
392
393static void device_complete_initialization(struct mode_context *context, struct libusb_device_handle *handle)
385{ 394{
395 struct usb_device *usbdev = find_device(context->bus, context->address);
396 if(!usbdev) {
397 usbmuxd_log(LL_ERROR, "Device %d-%d is missing from device list, aborting initialization", context->bus, context->address);
398 return;
399 }
386 struct libusb_device *dev = context->dev; 400 struct libusb_device *dev = context->dev;
387 struct libusb_device_descriptor devdesc = context->devdesc; 401 struct libusb_device_descriptor devdesc = usbdev->devdesc;
388 int bus = context->bus; 402 int bus = context->bus;
389 int address = context->address; 403 int address = context->address;
390 int desired_config = devdesc.bNumConfigurations; 404 int desired_config = devdesc.bNumConfigurations;
@@ -415,15 +429,15 @@ static int device_complete_initialization(struct mode_context *context, struct l
415 intf->bInterfaceProtocol != INTERFACE_PROTOCOL) { 429 intf->bInterfaceProtocol != INTERFACE_PROTOCOL) {
416 usbmuxd_log(LL_WARNING, "Device %d-%d: can't find usbmux interface in configuration 5, choosing configuration 4 instead.", bus, address); 430 usbmuxd_log(LL_WARNING, "Device %d-%d: can't find usbmux interface in configuration 5, choosing configuration 4 instead.", bus, address);
417 desired_config = 4; 431 desired_config = 4;
418 break;
419 } 432 }
433 libusb_free_config_descriptor(config);
420 } while (0); 434 } while (0);
421 } 435 }
422 int current_config = 0; 436 int current_config = 0;
423 if((res = libusb_get_configuration(handle, &current_config)) != 0) { 437 if((res = libusb_get_configuration(handle, &current_config)) != 0) {
424 usbmuxd_log(LL_WARNING, "Could not get configuration for device %d-%d: %s", bus, address, libusb_error_name(res)); 438 usbmuxd_log(LL_WARNING, "Could not get configuration for device %d-%d: %s", bus, address, libusb_error_name(res));
425 libusb_close(handle); 439 usbdev->alive = 0;
426 return -1; 440 return;
427 } 441 }
428 if (current_config != desired_config) { 442 if (current_config != desired_config) {
429 struct libusb_config_descriptor *config; 443 struct libusb_config_descriptor *config;
@@ -452,22 +466,18 @@ static int device_complete_initialization(struct mode_context *context, struct l
452 usbmuxd_log(LL_INFO, "Setting configuration for device %d-%d, from %d to %d", bus, address, current_config, desired_config); 466 usbmuxd_log(LL_INFO, "Setting configuration for device %d-%d, from %d to %d", bus, address, current_config, desired_config);
453 if((res = libusb_set_configuration(handle, desired_config)) != 0) { 467 if((res = libusb_set_configuration(handle, desired_config)) != 0) {
454 usbmuxd_log(LL_WARNING, "Could not set configuration %d for device %d-%d: %s", desired_config, bus, address, libusb_error_name(res)); 468 usbmuxd_log(LL_WARNING, "Could not set configuration %d for device %d-%d: %s", desired_config, bus, address, libusb_error_name(res));
455 libusb_close(handle); 469 usbdev->alive = 0;
456 return -1; 470 return;
457 } 471 }
458 } 472 }
459 473
460 struct libusb_config_descriptor *config; 474 struct libusb_config_descriptor *config;
461 if((res = libusb_get_active_config_descriptor(dev, &config)) != 0) { 475 if((res = libusb_get_active_config_descriptor(dev, &config)) != 0) {
462 usbmuxd_log(LL_WARNING, "Could not get configuration descriptor for device %d-%d: %s", bus, address, libusb_error_name(res)); 476 usbmuxd_log(LL_WARNING, "Could not get configuration descriptor for device %d-%d: %s", bus, address, libusb_error_name(res));
463 libusb_close(handle); 477 usbdev->alive = 0;
464 return -1; 478 return;
465 } 479 }
466 480
467 struct usb_device *usbdev;
468 usbdev = malloc(sizeof(struct usb_device));
469 memset(usbdev, 0, sizeof(*usbdev));
470
471 for(j=0; j<config->bNumInterfaces; j++) { 481 for(j=0; j<config->bNumInterfaces; j++) {
472 const struct libusb_interface_descriptor *intf = &config->interface[j].altsetting[0]; 482 const struct libusb_interface_descriptor *intf = &config->interface[j].altsetting[0];
473 if(intf->bInterfaceClass != INTERFACE_CLASS || 483 if(intf->bInterfaceClass != INTERFACE_CLASS ||
@@ -500,34 +510,30 @@ static int device_complete_initialization(struct mode_context *context, struct l
500 if(j == config->bNumInterfaces) { 510 if(j == config->bNumInterfaces) {
501 usbmuxd_log(LL_WARNING, "Could not find a suitable USB interface for device %d-%d", bus, address); 511 usbmuxd_log(LL_WARNING, "Could not find a suitable USB interface for device %d-%d", bus, address);
502 libusb_free_config_descriptor(config); 512 libusb_free_config_descriptor(config);
503 libusb_close(handle); 513 usbdev->alive = 0;
504 free(usbdev); 514 return;
505 return -1;
506 } 515 }
507 516
508 libusb_free_config_descriptor(config); 517 libusb_free_config_descriptor(config);
509 518
510 if((res = libusb_claim_interface(handle, usbdev->interface)) != 0) { 519 if((res = libusb_claim_interface(handle, usbdev->interface)) != 0) {
511 usbmuxd_log(LL_WARNING, "Could not claim interface %d for device %d-%d: %s", usbdev->interface, bus, address, libusb_error_name(res)); 520 usbmuxd_log(LL_WARNING, "Could not claim interface %d for device %d-%d: %s", usbdev->interface, bus, address, libusb_error_name(res));
512 libusb_close(handle); 521 usbdev->alive = 0;
513 free(usbdev); 522 return;
514 return -1;
515 } 523 }
516 524
517 transfer = libusb_alloc_transfer(0); 525 transfer = libusb_alloc_transfer(0);
518 if(!transfer) { 526 if(!transfer) {
519 usbmuxd_log(LL_WARNING, "Failed to allocate transfer for device %d-%d: %s", bus, address, libusb_error_name(res)); 527 usbmuxd_log(LL_WARNING, "Failed to allocate transfer for device %d-%d: %s", bus, address, libusb_error_name(res));
520 libusb_close(handle); 528 usbdev->alive = 0;
521 free(usbdev); 529 return;
522 return -1;
523 } 530 }
524 531
525 unsigned char *transfer_buffer = malloc(1024 + LIBUSB_CONTROL_SETUP_SIZE + 8); 532 unsigned char *transfer_buffer = malloc(1024 + LIBUSB_CONTROL_SETUP_SIZE + 8);
526 if (!transfer_buffer) { 533 if (!transfer_buffer) {
527 usbmuxd_log(LL_WARNING, "Failed to allocate transfer buffer for device %d-%d: %s", bus, address, libusb_error_name(res)); 534 usbmuxd_log(LL_WARNING, "Failed to allocate transfer buffer for device %d-%d: %s", bus, address, libusb_error_name(res));
528 libusb_close(handle); 535 usbdev->alive = 0;
529 free(usbdev); 536 return;
530 return -1;
531 } 537 }
532 memset(transfer_buffer, '\0', 1024 + LIBUSB_CONTROL_SETUP_SIZE + 8); 538 memset(transfer_buffer, '\0', 1024 + LIBUSB_CONTROL_SETUP_SIZE + 8);
533 539
@@ -577,18 +583,10 @@ static int device_complete_initialization(struct mode_context *context, struct l
577 if((res = libusb_submit_transfer(transfer)) < 0) { 583 if((res = libusb_submit_transfer(transfer)) < 0) {
578 usbmuxd_log(LL_ERROR, "Could not request transfer for device %d-%d: %s", usbdev->bus, usbdev->address, libusb_error_name(res)); 584 usbmuxd_log(LL_ERROR, "Could not request transfer for device %d-%d: %s", usbdev->bus, usbdev->address, libusb_error_name(res));
579 libusb_free_transfer(transfer); 585 libusb_free_transfer(transfer);
580 libusb_close(handle);
581 free(transfer_buffer); 586 free(transfer_buffer);
582 free(usbdev); 587 usbdev->alive = 0;
583 return -1; 588 return;
584 } 589 }
585
586 collection_init(&usbdev->tx_xfers);
587 collection_init(&usbdev->rx_xfers);
588
589 collection_add(&device_list, usbdev);
590
591 return 0;
592} 590}
593 591
594static void switch_mode_cb(struct libusb_transfer* transfer) 592static void switch_mode_cb(struct libusb_transfer* transfer)
@@ -603,6 +601,8 @@ static void switch_mode_cb(struct libusb_transfer* transfer)
603 usbmuxd_log(LL_INFO, "Received response %i for switch mode %i for device %i-%i", data[0], context->wIndex, context->bus, context->address); 601 usbmuxd_log(LL_INFO, "Received response %i for switch mode %i for device %i-%i", data[0], context->wIndex, context->bus, context->address);
604 } 602 }
605 free(transfer->user_data); 603 free(transfer->user_data);
604 if(transfer->buffer)
605 free(transfer->buffer);
606} 606}
607 607
608static void get_mode_cb(struct libusb_transfer* transfer) 608static void get_mode_cb(struct libusb_transfer* transfer)
@@ -628,11 +628,11 @@ static void get_mode_cb(struct libusb_transfer* transfer)
628 else if(!strncmp(desired_mode, "3", 1)) { 628 else if(!strncmp(desired_mode, "3", 1)) {
629 context->wIndex = 0x3; 629 context->wIndex = 0x3;
630 } 630 }
631 // Response is 3:3:3 for initial mode, 5:3:3 otherwise. 631 // Response is 3:3:3:0 for initial mode, 5:3:3:0 otherwise.
632 // In later commit, should infer the mode from available configurations and interfaces. 632 // In later commit, should infer the mode from available configurations and interfaces.
633 usbmuxd_log(LL_INFO, "Received response %i:%i:%i for get_mode request for device %i-%i", data[0], data[1], data[2], context->bus, context->address); 633 usbmuxd_log(LL_INFO, "Received response %i:%i:%i:%i for get_mode request for device %i-%i", data[0], data[1], data[2], data[3], context->bus, context->address);
634 if(context->wIndex > 1 && data[0] == 3 && data[1] == 3 && data[2] == 3) { 634 if(context->wIndex > 1 && data[0] == 3 && data[1] == 3 && data[2] == 3 && data[3] == 0) {
635 // 3:3:3 means the initial mode 635 // 3:3:3:0 means the initial mode
636 usbmuxd_log(LL_WARNING, "Switching device %i-%i mode to %i", context->bus, context->address, context->wIndex); 636 usbmuxd_log(LL_WARNING, "Switching device %i-%i mode to %i", context->bus, context->address, context->wIndex);
637 637
638 context->bRequest = APPLE_VEND_SPECIFIC_SET_MODE; 638 context->bRequest = APPLE_VEND_SPECIFIC_SET_MODE;
@@ -644,11 +644,13 @@ static void get_mode_cb(struct libusb_transfer* transfer)
644 } 644 }
645 } 645 }
646 else { 646 else {
647 // in other modes, usually 5:3:3 647 // in other modes, usually 5:3:3:0
648 usbmuxd_log(LL_WARNING, "Skipping switch device %i-%i mode", context->bus, context->address); 648 usbmuxd_log(LL_WARNING, "Skipping switch device %i-%i mode", context->bus, context->address);
649 device_complete_initialization(context, transfer->dev_handle); 649 device_complete_initialization(context, transfer->dev_handle);
650 free(context); 650 free(context);
651 } 651 }
652 if(transfer->buffer)
653 free(transfer->buffer);
652} 654}
653 655
654static int usb_device_add(libusb_device* dev) 656static int usb_device_add(libusb_device* dev)
@@ -658,16 +660,11 @@ static int usb_device_add(libusb_device* dev)
658 uint8_t bus = libusb_get_bus_number(dev); 660 uint8_t bus = libusb_get_bus_number(dev);
659 uint8_t address = libusb_get_device_address(dev); 661 uint8_t address = libusb_get_device_address(dev);
660 struct libusb_device_descriptor devdesc; 662 struct libusb_device_descriptor devdesc;
661 int found = 0; 663 struct usb_device *usbdev = find_device(bus, address);
662 FOREACH(struct usb_device *usbdev, &device_list) { 664 if(usbdev) {
663 if(usbdev->bus == bus && usbdev->address == address) { 665 usbdev->alive = 1;
664 usbdev->alive = 1;
665 found = 1;
666 break;
667 }
668 } ENDFOREACH
669 if(found)
670 return 0; //device already found 666 return 0; //device already found
667 }
671 668
672 if((res = libusb_get_device_descriptor(dev, &devdesc)) != 0) { 669 if((res = libusb_get_device_descriptor(dev, &devdesc)) != 0) {
673 usbmuxd_log(LL_WARNING, "Could not get device descriptor for device %d-%d: %s", bus, address, libusb_error_name(res)); 670 usbmuxd_log(LL_WARNING, "Could not get device descriptor for device %d-%d: %s", bus, address, libusb_error_name(res));
@@ -690,6 +687,23 @@ static int usb_device_add(libusb_device* dev)
690 return -1; 687 return -1;
691 } 688 }
692 689
690 // Add the created handle to the device list, so we can close it in case of failure/disconnection
691 usbdev = malloc(sizeof(struct usb_device));
692 memset(usbdev, 0, sizeof(*usbdev));
693
694 usbdev->serial[0] = 0;
695 usbdev->bus = bus;
696 usbdev->address = address;
697 usbdev->devdesc = devdesc;
698 usbdev->speed = 0;
699 usbdev->dev = handle;
700 usbdev->alive = 1;
701
702 collection_init(&usbdev->tx_xfers);
703 collection_init(&usbdev->rx_xfers);
704
705 collection_add(&device_list, usbdev);
706
693 // On top of configurations, Apple have multiple "modes" for devices, namely: 707 // On top of configurations, Apple have multiple "modes" for devices, namely:
694 // 1: An "initial" mode with 4 configurations 708 // 1: An "initial" mode with 4 configurations
695 // 2: "Valeria" mode, where configuration 5 is included with interface for H.265 video capture (activated when recording screen with QuickTime in macOS) 709 // 2: "Valeria" mode, where configuration 5 is included with interface for H.265 video capture (activated when recording screen with QuickTime in macOS)
@@ -698,7 +712,6 @@ static int usb_device_add(libusb_device* dev)
698 usbmuxd_log(LL_INFO, "Requesting current mode from device %i-%i", bus, address); 712 usbmuxd_log(LL_INFO, "Requesting current mode from device %i-%i", bus, address);
699 struct mode_context* context = malloc(sizeof(struct mode_context)); 713 struct mode_context* context = malloc(sizeof(struct mode_context));
700 context->dev = dev; 714 context->dev = dev;
701 context->devdesc = devdesc;
702 context->bus = bus; 715 context->bus = bus;
703 context->address = address; 716 context->address = address;
704 context->bRequest = APPLE_VEND_SPECIFIC_GET_MODE; 717 context->bRequest = APPLE_VEND_SPECIFIC_GET_MODE;
@@ -709,6 +722,8 @@ static int usb_device_add(libusb_device* dev)
709 722
710 if(submit_vendor_specific(handle, context, get_mode_cb) != 0) { 723 if(submit_vendor_specific(handle, context, get_mode_cb) != 0) {
711 usbmuxd_log(LL_WARNING, "Could not request current mode from device %d-%d", bus, address); 724 usbmuxd_log(LL_WARNING, "Could not request current mode from device %d-%d", bus, address);
725 // Schedule device for close and cleanup
726 usbdev->alive = 0;
712 return -1; 727 return -1;
713 } 728 }
714 return 0; 729 return 0;