summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGravatar Eliyahu Stern2022-12-23 12:42:50 +0200
committerGravatar Eliyahu Stern2022-12-23 12:42:50 +0200
commita2cbb595276a328e50c2723fbe3cba8a8099dea0 (patch)
treecc9415c36e8f497966939b2156f90de2c7fc7a70
parent1eb5a01477da3a29803ce5602c85e9e98e4a4b72 (diff)
downloadusbmuxd-a2cbb595276a328e50c2723fbe3cba8a8099dea0.tar.gz
usbmuxd-a2cbb595276a328e50c2723fbe3cba8a8099dea0.tar.bz2
Simplify finding valid configuration, interface and endpoints and refactor to a separate function.
This function can later be used to determine active mode.
-rw-r--r--src/usb.c186
1 files changed, 87 insertions, 99 deletions
diff --git a/src/usb.c b/src/usb.c
index b0810a2..274bebc 100644
--- a/src/usb.c
+++ b/src/usb.c
@@ -390,132 +390,120 @@ static struct usb_device* find_device(int bus, int address)
390 return NULL; 390 return NULL;
391} 391}
392 392
393static void device_complete_initialization(struct mode_context *context, struct libusb_device_handle *handle) 393/// @brief Finds and sets the valid configuration, interface and endpoints on the usb_device
394static int set_valid_configuration(struct libusb_device* dev, struct usb_device *usbdev, struct libusb_device_handle *handle)
394{ 395{
395 struct usb_device *usbdev = find_device(context->bus, context->address); 396 int j, k, res, found = 0;
396 if(!usbdev) { 397 struct libusb_config_descriptor *config;
397 usbmuxd_log(LL_ERROR, "Device %d-%d is missing from device list, aborting initialization", context->bus, context->address); 398 const struct libusb_interface_descriptor *intf;
398 return;
399 }
400 struct libusb_device *dev = context->dev;
401 struct libusb_device_descriptor devdesc = usbdev->devdesc; 399 struct libusb_device_descriptor devdesc = usbdev->devdesc;
402 int bus = context->bus; 400 int bus = usbdev->bus;
403 int address = context->address; 401 int address = usbdev->address;
404 int desired_config = devdesc.bNumConfigurations; 402 int current_config = 0;
405 int j, res; 403
406 struct libusb_transfer *transfer; 404 if((res = libusb_get_configuration(handle, &current_config)) != 0) {
405 usbmuxd_log(LL_WARNING, "Could not get current configuration for device %d-%d: %s", bus, address, libusb_error_name(res));
406 return -1;
407 }
407 408
408 if(desired_config > 4) { 409 for(j = devdesc.bNumConfigurations ; j > 0 ; j--) {
409 if(desired_config > 5) { 410 if((res = libusb_get_config_descriptor_by_value(dev, j, &config)) != 0) {
410 usbmuxd_log(LL_ERROR, "Device %d-%d has more than 5 configurations, but usbmuxd doesn't support that. Choosing configuration 5 instead.", bus, address); 411 usbmuxd_log(LL_NOTICE, "Could not get configuration %i descriptor for device %i-%i: %s", j, bus, address, libusb_error_name(res));
411 desired_config = 5; 412 continue;
412 } 413 }
413 /* verify if the configuration 5 is actually usable */ 414 for(k = 0 ; k < config->bNumInterfaces ; k++) {
414 do { 415 intf = &config->interface[k].altsetting[0];
415 struct libusb_config_descriptor *config; 416 if(intf->bInterfaceClass == INTERFACE_CLASS ||
416 const struct libusb_interface_descriptor *intf; 417 intf->bInterfaceSubClass == INTERFACE_SUBCLASS ||
417 if (libusb_get_config_descriptor_by_value(dev, 5, &config) != 0) { 418 intf->bInterfaceProtocol == INTERFACE_PROTOCOL) {
418 usbmuxd_log(LL_WARNING, "Device %d-%d: Failed to get config descriptor for configuration 5, choosing configuration 4 instead.", bus, address); 419 usbmuxd_log(LL_NOTICE, "Found usbmux interface for device %i-%i: %i", bus, address, intf->bInterfaceNumber);
419 desired_config = 4; 420 if(intf->bNumEndpoints != 2) {
420 break; 421 usbmuxd_log(LL_WARNING, "Endpoint count mismatch for interface %i of device %i-%i", intf->bInterfaceNumber, bus, address);
421 } 422 continue;
422 // In Valeria mode, there are 3 interfaces and usbmuxd is at 2 423 }
423 // In CDC NCM mode, there are 4 interfaces and usbmuxd is at 1 424 if((intf->endpoint[0].bEndpointAddress & 0x80) == LIBUSB_ENDPOINT_OUT &&
424 // Otherwize, 0 is expected to be of a different class. 425 (intf->endpoint[1].bEndpointAddress & 0x80) == LIBUSB_ENDPOINT_IN) {
425 int usbmux_intf_index = config->bNumInterfaces == 3 ? 2 : config->bNumInterfaces == 4 ? 1 : 0; 426 usbdev->interface = intf->bInterfaceNumber;
426 intf = &config->interface[usbmux_intf_index].altsetting[0]; 427 usbdev->ep_out = intf->endpoint[0].bEndpointAddress;
427 if(intf->bInterfaceClass != INTERFACE_CLASS || 428 usbdev->ep_in = intf->endpoint[1].bEndpointAddress;
428 intf->bInterfaceSubClass != INTERFACE_SUBCLASS || 429 usbmuxd_log(LL_INFO, "Found interface %i with endpoints %02x/%02x for device %i-%i", usbdev->interface, usbdev->ep_out, usbdev->ep_in, bus, address);
429 intf->bInterfaceProtocol != INTERFACE_PROTOCOL) { 430 found = 1;
430 usbmuxd_log(LL_WARNING, "Device %d-%d: can't find usbmux interface in configuration 5, choosing configuration 4 instead.", bus, address); 431 break;
431 desired_config = 4; 432 } else if((intf->endpoint[1].bEndpointAddress & 0x80) == LIBUSB_ENDPOINT_OUT &&
433 (intf->endpoint[0].bEndpointAddress & 0x80) == LIBUSB_ENDPOINT_IN) {
434 usbdev->interface = intf->bInterfaceNumber;
435 usbdev->ep_out = intf->endpoint[1].bEndpointAddress;
436 usbdev->ep_in = intf->endpoint[0].bEndpointAddress;
437 usbmuxd_log(LL_INFO, "Found interface %i with swapped endpoints %02x/%02x for device %i-%i", usbdev->interface, usbdev->ep_out, usbdev->ep_in, bus, address);
438 found = 1;
439 break;
440 } else {
441 usbmuxd_log(LL_WARNING, "Endpoint type mismatch for interface %i of device %i-%i", intf->bInterfaceNumber, bus, address);
442 }
432 } 443 }
444 }
445 if(!found) {
433 libusb_free_config_descriptor(config); 446 libusb_free_config_descriptor(config);
434 } while (0); 447 continue;
435 } 448 }
436 int current_config = 0; 449 // If set configuration is required, try to first detach all kernel drivers
437 if((res = libusb_get_configuration(handle, &current_config)) != 0) {
438 usbmuxd_log(LL_WARNING, "Could not get configuration for device %d-%d: %s", bus, address, libusb_error_name(res));
439 usbdev->alive = 0;
440 return;
441 }
442 if (current_config != desired_config) {
443 struct libusb_config_descriptor *config;
444 if (current_config == 0) { 450 if (current_config == 0) {
445 usbmuxd_log(LL_DEBUG, "Device %d-%d is unconfigured", bus, address); 451 usbmuxd_log(LL_DEBUG, "Device %d-%d is unconfigured", bus, address);
446 } else if ((res = libusb_get_active_config_descriptor(dev, &config)) != 0) { 452 }
447 usbmuxd_log(LL_NOTICE, "Could not get old configuration descriptor for device %d-%d: %s", bus, address, libusb_error_name(res)); 453 if(current_config == 0 || config->bConfigurationValue != current_config) {
448 } else { 454 usbmuxd_log(LL_NOTICE, "Changing configuration of device %i-%i: %i -> %i", bus, address, config->bConfigurationValue, current_config);
449 for(j=0; j<config->bNumInterfaces; j++) { 455 for(k=0 ; k < config->bNumInterfaces ; k++) {
450 const struct libusb_interface_descriptor *intf = &config->interface[j].altsetting[0]; 456 const struct libusb_interface_descriptor *intf1 = &config->interface[k].altsetting[0];
451 if((res = libusb_kernel_driver_active(handle, intf->bInterfaceNumber)) < 0) { 457 if((res = libusb_kernel_driver_active(handle, intf1->bInterfaceNumber)) < 0) {
452 usbmuxd_log(LL_NOTICE, "Could not check kernel ownership of interface %d for device %d-%d: %s", intf->bInterfaceNumber, bus, address, libusb_error_name(res)); 458 usbmuxd_log(LL_NOTICE, "Could not check kernel ownership of interface %d for device %d-%d: %s", intf1->bInterfaceNumber, bus, address, libusb_error_name(res));
453 continue; 459 continue;
454 } 460 }
455 if(res == 1) { 461 if(res == 1) {
456 usbmuxd_log(LL_INFO, "Detaching kernel driver for device %d-%d, interface %d", bus, address, intf->bInterfaceNumber); 462 usbmuxd_log(LL_INFO, "Detaching kernel driver for device %d-%d, interface %d", bus, address, intf1->bInterfaceNumber);
457 if((res = libusb_detach_kernel_driver(handle, intf->bInterfaceNumber)) < 0) { 463 if((res = libusb_detach_kernel_driver(handle, intf1->bInterfaceNumber)) < 0) {
458 usbmuxd_log(LL_WARNING, "Could not detach kernel driver, configuration change will probably fail! %s", libusb_error_name(res)); 464 usbmuxd_log(LL_WARNING, "Could not detach kernel driver, configuration change will probably fail! %s", libusb_error_name(res));
459 continue; 465 continue;
460 } 466 }
461 } 467 }
462 } 468 }
463 libusb_free_config_descriptor(config); 469 if((res = libusb_set_configuration(handle, j)) != 0) {
464 } 470 usbmuxd_log(LL_WARNING, "Could not set configuration %d for device %d-%d: %s", j, bus, address, libusb_error_name(res));
465 471 libusb_free_config_descriptor(config);
466 usbmuxd_log(LL_INFO, "Setting configuration for device %d-%d, from %d to %d", bus, address, current_config, desired_config); 472 continue;
467 if((res = libusb_set_configuration(handle, desired_config)) != 0) { 473 }
468 usbmuxd_log(LL_WARNING, "Could not set configuration %d for device %d-%d: %s", desired_config, bus, address, libusb_error_name(res));
469 usbdev->alive = 0;
470 return;
471 } 474 }
475
476 libusb_free_config_descriptor(config);
477 break;
472 } 478 }
473 479
474 struct libusb_config_descriptor *config; 480 if(!found) {
475 if((res = libusb_get_active_config_descriptor(dev, &config)) != 0) { 481 usbmuxd_log(LL_WARNING, "Could not find a suitable USB interface for device %i-%i", bus, address);
476 usbmuxd_log(LL_WARNING, "Could not get configuration descriptor for device %d-%d: %s", bus, address, libusb_error_name(res)); 482 return -1;
477 usbdev->alive = 0;
478 return;
479 } 483 }
480 484
481 for(j=0; j<config->bNumInterfaces; j++) { 485 return 0;
482 const struct libusb_interface_descriptor *intf = &config->interface[j].altsetting[0]; 486}
483 if(intf->bInterfaceClass != INTERFACE_CLASS || 487
484 intf->bInterfaceSubClass != INTERFACE_SUBCLASS || 488static void device_complete_initialization(struct mode_context *context, struct libusb_device_handle *handle)
485 intf->bInterfaceProtocol != INTERFACE_PROTOCOL) 489{
486 continue; 490 struct usb_device *usbdev = find_device(context->bus, context->address);
487 if(intf->bNumEndpoints != 2) { 491 if(!usbdev) {
488 usbmuxd_log(LL_WARNING, "Endpoint count mismatch for interface %d of device %d-%d", intf->bInterfaceNumber, bus, address); 492 usbmuxd_log(LL_ERROR, "Device %d-%d is missing from device list, aborting initialization", context->bus, context->address);
489 continue; 493 return;
490 }
491 if((intf->endpoint[0].bEndpointAddress & 0x80) == LIBUSB_ENDPOINT_OUT &&
492 (intf->endpoint[1].bEndpointAddress & 0x80) == LIBUSB_ENDPOINT_IN) {
493 usbdev->interface = intf->bInterfaceNumber;
494 usbdev->ep_out = intf->endpoint[0].bEndpointAddress;
495 usbdev->ep_in = intf->endpoint[1].bEndpointAddress;
496 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);
497 break;
498 } else if((intf->endpoint[1].bEndpointAddress & 0x80) == LIBUSB_ENDPOINT_OUT &&
499 (intf->endpoint[0].bEndpointAddress & 0x80) == LIBUSB_ENDPOINT_IN) {
500 usbdev->interface = intf->bInterfaceNumber;
501 usbdev->ep_out = intf->endpoint[1].bEndpointAddress;
502 usbdev->ep_in = intf->endpoint[0].bEndpointAddress;
503 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);
504 break;
505 } else {
506 usbmuxd_log(LL_WARNING, "Endpoint type mismatch for interface %d of device %d-%d", intf->bInterfaceNumber, bus, address);
507 }
508 } 494 }
495 struct libusb_device *dev = context->dev;
496 struct libusb_device_descriptor devdesc = usbdev->devdesc;
497 int bus = context->bus;
498 int address = context->address;
499 int res;
500 struct libusb_transfer *transfer;
509 501
510 if(j == config->bNumInterfaces) { 502 if((res = set_valid_configuration(dev, usbdev, handle)) != 0) {
511 usbmuxd_log(LL_WARNING, "Could not find a suitable USB interface for device %d-%d", bus, address);
512 libusb_free_config_descriptor(config);
513 usbdev->alive = 0; 503 usbdev->alive = 0;
514 return; 504 return;
515 } 505 }
516 506
517 libusb_free_config_descriptor(config);
518
519 if((res = libusb_claim_interface(handle, usbdev->interface)) != 0) { 507 if((res = libusb_claim_interface(handle, usbdev->interface)) != 0) {
520 usbmuxd_log(LL_WARNING, "Could not claim interface %d for device %d-%d: %s", usbdev->interface, bus, address, libusb_error_name(res)); 508 usbmuxd_log(LL_WARNING, "Could not claim interface %d for device %d-%d: %s", usbdev->interface, bus, address, libusb_error_name(res));
521 usbdev->alive = 0; 509 usbdev->alive = 0;