diff options
| author | 2010-05-18 18:51:20 +0200 | |
|---|---|---|
| committer | 2010-05-18 18:51:20 +0200 | |
| commit | aacdff7345e265b593780115912511cd3724f22f (patch) | |
| tree | e2a71892b46171a0c5c0a2112d9c88211d454d65 | |
| parent | ed5a1f49812a29b6ad806778155890157981f252 (diff) | |
| download | usbmuxd-aacdff7345e265b593780115912511cd3724f22f.tar.gz usbmuxd-aacdff7345e265b593780115912511cd3724f22f.tar.bz2 | |
Parse out interface/endpoint descriptors instead of hardcoding them
This should make usbmuxd work with devices in recovery mode
| -rw-r--r-- | daemon/usb-linux.c | 59 | ||||
| -rw-r--r-- | daemon/usb.h | 7 |
2 files changed, 53 insertions, 13 deletions
diff --git a/daemon/usb-linux.c b/daemon/usb-linux.c index c334ef3..cc1bbaf 100644 --- a/daemon/usb-linux.c +++ b/daemon/usb-linux.c | |||
| @@ -45,6 +45,7 @@ struct usb_device { | |||
| 45 | uint16_t vid, pid; | 45 | uint16_t vid, pid; |
| 46 | char serial[256]; | 46 | char serial[256]; |
| 47 | int alive; | 47 | int alive; |
| 48 | uint8_t interface, ep_in, ep_out; | ||
| 48 | struct libusb_transfer *rx_xfer; | 49 | struct libusb_transfer *rx_xfer; |
| 49 | struct collection tx_xfers; | 50 | struct collection tx_xfers; |
| 50 | int wMaxPacketSize; | 51 | int wMaxPacketSize; |
| @@ -85,7 +86,7 @@ static void usb_disconnect(struct usb_device *dev) | |||
| 85 | } | 86 | } |
| 86 | } | 87 | } |
| 87 | collection_free(&dev->tx_xfers); | 88 | collection_free(&dev->tx_xfers); |
| 88 | libusb_release_interface(dev->dev, USB_INTERFACE); | 89 | libusb_release_interface(dev->dev, dev->interface); |
| 89 | libusb_close(dev->dev); | 90 | libusb_close(dev->dev); |
| 90 | dev->dev = NULL; | 91 | dev->dev = NULL; |
| 91 | collection_remove(&device_list, dev); | 92 | collection_remove(&device_list, dev); |
| @@ -135,7 +136,7 @@ int usb_send(struct usb_device *dev, const unsigned char *buf, int length) | |||
| 135 | { | 136 | { |
| 136 | int res; | 137 | int res; |
| 137 | struct libusb_transfer *xfer = libusb_alloc_transfer(0); | 138 | struct libusb_transfer *xfer = libusb_alloc_transfer(0); |
| 138 | libusb_fill_bulk_transfer(xfer, dev->dev, BULK_OUT, (void*)buf, length, tx_callback, dev, 0); | 139 | libusb_fill_bulk_transfer(xfer, dev->dev, dev->ep_out, (void*)buf, length, tx_callback, dev, 0); |
| 139 | if((res = libusb_submit_transfer(xfer)) < 0) { | 140 | if((res = libusb_submit_transfer(xfer)) < 0) { |
| 140 | usbmuxd_log(LL_ERROR, "Failed to submit TX transfer %p len %d to device %d-%d: %d", buf, length, dev->bus, dev->address, res); | 141 | usbmuxd_log(LL_ERROR, "Failed to submit TX transfer %p len %d to device %d-%d: %d", buf, length, dev->bus, dev->address, res); |
| 141 | libusb_free_transfer(xfer); | 142 | libusb_free_transfer(xfer); |
| @@ -147,7 +148,7 @@ int usb_send(struct usb_device *dev, const unsigned char *buf, int length) | |||
| 147 | // Send Zero Length Packet | 148 | // Send Zero Length Packet |
| 148 | xfer = libusb_alloc_transfer(0); | 149 | xfer = libusb_alloc_transfer(0); |
| 149 | void *buffer = malloc(1); | 150 | void *buffer = malloc(1); |
| 150 | libusb_fill_bulk_transfer(xfer, dev->dev, BULK_OUT, buffer, 0, tx_callback, dev, 0); | 151 | libusb_fill_bulk_transfer(xfer, dev->dev, dev->ep_out, buffer, 0, tx_callback, dev, 0); |
| 151 | if((res = libusb_submit_transfer(xfer)) < 0) { | 152 | if((res = libusb_submit_transfer(xfer)) < 0) { |
| 152 | usbmuxd_log(LL_ERROR, "Failed to submit TX ZLP transfer to device %d-%d: %d", dev->bus, dev->address, res); | 153 | usbmuxd_log(LL_ERROR, "Failed to submit TX ZLP transfer to device %d-%d: %d", dev->bus, dev->address, res); |
| 153 | libusb_free_transfer(xfer); | 154 | libusb_free_transfer(xfer); |
| @@ -205,7 +206,7 @@ static int start_rx(struct usb_device *dev) | |||
| 205 | void *buf; | 206 | void *buf; |
| 206 | dev->rx_xfer = libusb_alloc_transfer(0); | 207 | dev->rx_xfer = libusb_alloc_transfer(0); |
| 207 | buf = malloc(USB_MRU); | 208 | buf = malloc(USB_MRU); |
| 208 | libusb_fill_bulk_transfer(dev->rx_xfer, dev->dev, BULK_IN, buf, USB_MRU, rx_callback, dev, 0); | 209 | libusb_fill_bulk_transfer(dev->rx_xfer, dev->dev, dev->ep_in, buf, USB_MRU, rx_callback, dev, 0); |
| 209 | if((res = libusb_submit_transfer(dev->rx_xfer)) != 0) { | 210 | if((res = libusb_submit_transfer(dev->rx_xfer)) != 0) { |
| 210 | usbmuxd_log(LL_ERROR, "Failed to submit RX transfer to device %d-%d: %d", dev->bus, dev->address, res); | 211 | usbmuxd_log(LL_ERROR, "Failed to submit RX transfer to device %d-%d: %d", dev->bus, dev->address, res); |
| 211 | libusb_free_transfer(dev->rx_xfer); | 212 | libusb_free_transfer(dev->rx_xfer); |
| @@ -217,7 +218,7 @@ static int start_rx(struct usb_device *dev) | |||
| 217 | 218 | ||
| 218 | int usb_discover(void) | 219 | int usb_discover(void) |
| 219 | { | 220 | { |
| 220 | int cnt, i, res; | 221 | int cnt, i, j, res; |
| 221 | int valid_count = 0; | 222 | int valid_count = 0; |
| 222 | libusb_device **devs; | 223 | libusb_device **devs; |
| 223 | 224 | ||
| @@ -291,17 +292,57 @@ int usb_discover(void) | |||
| 291 | continue; | 292 | continue; |
| 292 | } | 293 | } |
| 293 | } | 294 | } |
| 294 | if((res = libusb_claim_interface(handle, USB_INTERFACE)) != 0) { | 295 | |
| 295 | usbmuxd_log(LL_WARNING, "Could not claim interface %d for device %d-%d: %d", USB_INTERFACE, bus, address, res); | 296 | struct libusb_config_descriptor *config; |
| 297 | if((res = libusb_get_active_config_descriptor(dev, &config)) != 0) { | ||
| 298 | usbmuxd_log(LL_WARNING, "Could not get configuration descriptor for device %d-%d: %d", bus, address, res); | ||
| 296 | libusb_close(handle); | 299 | libusb_close(handle); |
| 297 | continue; | 300 | continue; |
| 298 | } | 301 | } |
| 302 | |||
| 299 | struct usb_device *usbdev; | 303 | struct usb_device *usbdev; |
| 300 | usbdev = malloc(sizeof(struct usb_device)); | 304 | usbdev = malloc(sizeof(struct usb_device)); |
| 301 | 305 | ||
| 306 | for(j=0; j<config->bNumInterfaces; j++) { | ||
| 307 | const struct libusb_interface_descriptor *intf = &config->interface[j].altsetting[0]; | ||
| 308 | if(intf->bInterfaceClass != INTERFACE_CLASS || | ||
| 309 | intf->bInterfaceSubClass != INTERFACE_SUBCLASS || | ||
| 310 | intf->bInterfaceProtocol != INTERFACE_PROTOCOL) | ||
| 311 | continue; | ||
| 312 | if(intf->bNumEndpoints != 2) { | ||
| 313 | usbmuxd_log(LL_WARNING, "Endpoint count mismatch for interface %d of device %d-%d", intf->bInterfaceNumber, bus, address); | ||
| 314 | continue; | ||
| 315 | } | ||
| 316 | if((intf->endpoint[0].bEndpointAddress & 0x80) != LIBUSB_ENDPOINT_OUT || | ||
| 317 | (intf->endpoint[1].bEndpointAddress & 0x80) != LIBUSB_ENDPOINT_IN) { | ||
| 318 | usbmuxd_log(LL_WARNING, "Endpoint type mismatch for interface %d of device %d-%d", intf->bInterfaceNumber, bus, address); | ||
| 319 | continue; | ||
| 320 | } | ||
| 321 | usbdev->interface = intf->bInterfaceNumber; | ||
| 322 | usbdev->ep_out = intf->endpoint[0].bEndpointAddress; | ||
| 323 | usbdev->ep_in = intf->endpoint[1].bEndpointAddress; | ||
| 324 | 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); | ||
| 325 | break; | ||
| 326 | } | ||
| 327 | libusb_free_config_descriptor(config); | ||
| 328 | |||
| 329 | if(j == config->bNumInterfaces) { | ||
| 330 | usbmuxd_log(LL_WARNING, "Could not find a suitable USB interface for device %d-%d", bus, address); | ||
| 331 | libusb_close(handle); | ||
| 332 | free(usbdev); | ||
| 333 | continue; | ||
| 334 | } | ||
| 335 | |||
| 336 | if((res = libusb_claim_interface(handle, usbdev->interface)) != 0) { | ||
| 337 | usbmuxd_log(LL_WARNING, "Could not claim interface %d for device %d-%d: %d", usbdev->interface, bus, address, res); | ||
| 338 | libusb_close(handle); | ||
| 339 | free(usbdev); | ||
| 340 | continue; | ||
| 341 | } | ||
| 342 | |||
| 302 | if((res = libusb_get_string_descriptor_ascii(handle, devdesc.iSerialNumber, (uint8_t *)usbdev->serial, 256)) <= 0) { | 343 | if((res = libusb_get_string_descriptor_ascii(handle, devdesc.iSerialNumber, (uint8_t *)usbdev->serial, 256)) <= 0) { |
| 303 | usbmuxd_log(LL_WARNING, "Could not get serial number for device %d-%d: %d", bus, address, res); | 344 | usbmuxd_log(LL_WARNING, "Could not get serial number for device %d-%d: %d", bus, address, res); |
| 304 | libusb_release_interface(handle, USB_INTERFACE); | 345 | libusb_release_interface(handle, usbdev->interface); |
| 305 | libusb_close(handle); | 346 | libusb_close(handle); |
| 306 | free(usbdev); | 347 | free(usbdev); |
| 307 | continue; | 348 | continue; |
| @@ -313,7 +354,7 @@ int usb_discover(void) | |||
| 313 | usbdev->pid = devdesc.idProduct; | 354 | usbdev->pid = devdesc.idProduct; |
| 314 | usbdev->dev = handle; | 355 | usbdev->dev = handle; |
| 315 | usbdev->alive = 1; | 356 | usbdev->alive = 1; |
| 316 | usbdev->wMaxPacketSize = libusb_get_max_packet_size(dev, BULK_OUT); | 357 | usbdev->wMaxPacketSize = libusb_get_max_packet_size(dev, usbdev->ep_out); |
| 317 | if (usbdev->wMaxPacketSize <= 0) { | 358 | if (usbdev->wMaxPacketSize <= 0) { |
| 318 | usbmuxd_log(LL_ERROR, "Could not determine wMaxPacketSize for device %d-%d, setting to 64", usbdev->bus, usbdev->address); | 359 | usbmuxd_log(LL_ERROR, "Could not determine wMaxPacketSize for device %d-%d, setting to 64", usbdev->bus, usbdev->address); |
| 319 | usbdev->wMaxPacketSize = 64; | 360 | usbdev->wMaxPacketSize = 64; |
diff --git a/daemon/usb.h b/daemon/usb.h index 1a58b26..6e507ae 100644 --- a/daemon/usb.h +++ b/daemon/usb.h | |||
| @@ -26,8 +26,9 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA | |||
| 26 | #include <stdint.h> | 26 | #include <stdint.h> |
| 27 | #include "utils.h" | 27 | #include "utils.h" |
| 28 | 28 | ||
| 29 | #define BULK_IN 0x85 | 29 | #define INTERFACE_CLASS 255 |
| 30 | #define BULK_OUT 0x04 | 30 | #define INTERFACE_SUBCLASS 254 |
| 31 | #define INTERFACE_PROTOCOL 2 | ||
| 31 | 32 | ||
| 32 | // libusb fragments packets larger than this (usbfs limitation) | 33 | // libusb fragments packets larger than this (usbfs limitation) |
| 33 | // on input, this creates race conditions and other issues | 34 | // on input, this creates race conditions and other issues |
| @@ -47,8 +48,6 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA | |||
| 47 | #define PID_RANGE_LOW 0x1290 | 48 | #define PID_RANGE_LOW 0x1290 |
| 48 | #define PID_RANGE_MAX 0x129a | 49 | #define PID_RANGE_MAX 0x129a |
| 49 | 50 | ||
| 50 | #define USB_INTERFACE 1 | ||
| 51 | |||
| 52 | struct usb_device; | 51 | struct usb_device; |
| 53 | 52 | ||
| 54 | int usb_init(void); | 53 | int usb_init(void); |
