summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGravatar Hector Martin2010-05-18 18:51:20 +0200
committerGravatar Hector Martin2010-05-18 18:51:20 +0200
commitaacdff7345e265b593780115912511cd3724f22f (patch)
treee2a71892b46171a0c5c0a2112d9c88211d454d65
parented5a1f49812a29b6ad806778155890157981f252 (diff)
downloadusbmuxd-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.c59
-rw-r--r--daemon/usb.h7
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
218int usb_discover(void) 219int 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
52struct usb_device; 51struct usb_device;
53 52
54int usb_init(void); 53int usb_init(void);