summaryrefslogtreecommitdiffstats
path: root/usb-linux.c
diff options
context:
space:
mode:
Diffstat (limited to 'usb-linux.c')
-rw-r--r--usb-linux.c197
1 files changed, 133 insertions, 64 deletions
diff --git a/usb-linux.c b/usb-linux.c
index 27a7bb1..3a87ba6 100644
--- a/usb-linux.c
+++ b/usb-linux.c
@@ -40,48 +40,50 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
40struct usb_device { 40struct usb_device {
41 libusb_device_handle *dev; 41 libusb_device_handle *dev;
42 uint8_t bus, address; 42 uint8_t bus, address;
43 uint16_t vid, pid;
43 char serial[256]; 44 char serial[256];
44 int alive; 45 int alive;
45 struct libusb_transfer *rx_xfer; 46 struct libusb_transfer *rx_xfer;
47 struct collection tx_xfers;
46}; 48};
47 49
48static int num_devs; 50static struct collection device_list;
49static struct usb_device *device_list;
50 51
51static struct timeval next_dev_poll_time; 52static struct timeval next_dev_poll_time;
52 53
53static int alloc_device(void)
54{
55 int i;
56 for(i=0; i<num_devs; i++) {
57 if(!device_list[i].dev)
58 return i;
59 }
60 num_devs++;
61 device_list = realloc(device_list, sizeof(*device_list) * num_devs);
62 memset(&device_list[num_devs-1], 0, sizeof(*device_list));
63 return num_devs - 1;
64}
65
66static void usb_disconnect(struct usb_device *dev) 54static void usb_disconnect(struct usb_device *dev)
67{ 55{
68 if(!dev->dev) { 56 if(!dev->dev) {
69 return; 57 return;
70 } 58 }
59
60 // kill the rx xfer and tx xfers and try to make sure the callbacks get called before we free the device
71 if(dev->rx_xfer) { 61 if(dev->rx_xfer) {
72 // kill the rx xfer and try to make sure the rx callback gets called before we free the device 62 usbmuxd_log(LL_DEBUG, "usb_disconnect: cancelling RX xfer");
63 libusb_cancel_transfer(dev->rx_xfer);
64 }
65 FOREACH(struct libusb_transfer *xfer, &dev->tx_xfers) {
66 usbmuxd_log(LL_DEBUG, "usb_disconnect: cancelling TX xfer %p", xfer);
67 libusb_cancel_transfer(xfer);
68 } ENDFOREACH
69
70 while(dev->rx_xfer || collection_count(&dev->tx_xfers)) {
73 struct timeval tv; 71 struct timeval tv;
74 int res; 72 int res;
75 // TODO: BUG: outstanding TX xfers are not listed but we need to free them 73
76 libusb_cancel_transfer(dev->rx_xfer); 74 tv.tv_sec = 0;
77 tv.tv_sec = tv.tv_usec = 0; 75 tv.tv_usec = 1000;
78 if((res = libusb_handle_events_timeout(NULL, &tv)) < 0) { 76 if((res = libusb_handle_events_timeout(NULL, &tv)) < 0) {
79 usbmuxd_log(LL_ERROR, "libusb_handle_events_timeout for device removal failed: %d", res); 77 usbmuxd_log(LL_ERROR, "libusb_handle_events_timeout for usb_disconnect failed: %d", res);
78 break;
80 } 79 }
81 } 80 }
81 collection_free(&dev->tx_xfers);
82 libusb_release_interface(dev->dev, USB_INTERFACE); 82 libusb_release_interface(dev->dev, USB_INTERFACE);
83 libusb_close(dev->dev); 83 libusb_close(dev->dev);
84 dev->dev = NULL; 84 dev->dev = NULL;
85 collection_remove(&device_list, dev);
86 free(dev);
85} 87}
86 88
87static void tx_callback(struct libusb_transfer *xfer) 89static void tx_callback(struct libusb_transfer *xfer)
@@ -117,7 +119,9 @@ static void tx_callback(struct libusb_transfer *xfer)
117 // we'll do device_remove there too 119 // we'll do device_remove there too
118 dev->alive = 0; 120 dev->alive = 0;
119 } 121 }
120 free(xfer->buffer); 122 if(xfer->buffer)
123 free(xfer->buffer);
124 collection_remove(&dev->tx_xfers, xfer);
121 libusb_free_transfer(xfer); 125 libusb_free_transfer(xfer);
122} 126}
123 127
@@ -132,6 +136,21 @@ int usb_send(struct usb_device *dev, const unsigned char *buf, int length)
132 libusb_free_transfer(xfer); 136 libusb_free_transfer(xfer);
133 return res; 137 return res;
134 } 138 }
139 collection_add(&dev->tx_xfers, xfer);/*
140 if((length % 512) == 0) {
141 usbmuxd_log(LL_DEBUG, "Send ZLP");
142 // Send Zero Length Packet
143 xfer = libusb_alloc_transfer(0);
144 void *buffer = malloc(1);
145 libusb_fill_bulk_transfer(xfer, dev->dev, BULK_OUT, buffer, 0, tx_callback, dev, 0);
146 xfer->flags = LIBUSB_TRANSFER_SHORT_NOT_OK;
147 if((res = libusb_submit_transfer(xfer)) < 0) {
148 usbmuxd_log(LL_ERROR, "Failed to submit TX ZLP transfer to device %d-%d: %d", dev->bus, dev->address, res);
149 libusb_free_transfer(xfer);
150 return res;
151 }
152 collection_add(&dev->tx_xfers, xfer);
153 }*/
135 return 0; 154 return 0;
136} 155}
137 156
@@ -181,8 +200,8 @@ static int start_rx(struct usb_device *dev)
181 int res; 200 int res;
182 void *buf; 201 void *buf;
183 dev->rx_xfer = libusb_alloc_transfer(0); 202 dev->rx_xfer = libusb_alloc_transfer(0);
184 buf = malloc(USB_MTU); 203 buf = malloc(USB_MRU);
185 libusb_fill_bulk_transfer(dev->rx_xfer, dev->dev, BULK_IN, buf, USB_MTU, rx_callback, dev, 0); 204 libusb_fill_bulk_transfer(dev->rx_xfer, dev->dev, BULK_IN, buf, USB_MRU, rx_callback, dev, 0);
186 if((res = libusb_submit_transfer(dev->rx_xfer)) != 0) { 205 if((res = libusb_submit_transfer(dev->rx_xfer)) != 0) {
187 usbmuxd_log(LL_ERROR, "Failed to submit RX transfer to device %d-%d: %d", dev->bus, dev->address, res); 206 usbmuxd_log(LL_ERROR, "Failed to submit RX transfer to device %d-%d: %d", dev->bus, dev->address, res);
188 libusb_free_transfer(dev->rx_xfer); 207 libusb_free_transfer(dev->rx_xfer);
@@ -194,7 +213,7 @@ static int start_rx(struct usb_device *dev)
194 213
195static int usb_discover(void) 214static int usb_discover(void)
196{ 215{
197 int cnt, i, j, res; 216 int cnt, i, res;
198 int valid_count = 0; 217 int valid_count = 0;
199 libusb_device **devs; 218 libusb_device **devs;
200 219
@@ -206,23 +225,26 @@ static int usb_discover(void)
206 225
207 usbmuxd_log(LL_SPEW, "usb_discover: scanning %d devices", cnt); 226 usbmuxd_log(LL_SPEW, "usb_discover: scanning %d devices", cnt);
208 227
209 for(j=0; j<num_devs; j++) { 228 FOREACH(struct usb_device *usbdev, &device_list) {
210 device_list[j].alive = 0; 229 usbdev->alive = 0;
211 } 230 } ENDFOREACH
231
212 for(i=0; i<cnt; i++) { 232 for(i=0; i<cnt; i++) {
213 // the following are non-blocking operations on the device list 233 // the following are non-blocking operations on the device list
214 libusb_device *dev = devs[i]; 234 libusb_device *dev = devs[i];
215 uint8_t bus = libusb_get_bus_number(dev); 235 uint8_t bus = libusb_get_bus_number(dev);
216 uint8_t address = libusb_get_device_address(dev); 236 uint8_t address = libusb_get_device_address(dev);
217 struct libusb_device_descriptor devdesc; 237 struct libusb_device_descriptor devdesc;
218 for(j=0; j<num_devs; j++) { 238 int found = 0;
219 if(device_list[j].dev && device_list[j].bus == bus && device_list[j].address == address) { 239 FOREACH(struct usb_device *usbdev, &device_list) {
240 if(usbdev->bus == bus && usbdev->address == address) {
220 valid_count++; 241 valid_count++;
221 device_list[j].alive = 1; 242 usbdev->alive = 1;
243 found = 1;
222 break; 244 break;
223 } 245 }
224 } 246 } ENDFOREACH
225 if(j < num_devs) 247 if(found)
226 continue; //device already found 248 continue; //device already found
227 if((res = libusb_get_device_descriptor(dev, &devdesc)) != 0) { 249 if((res = libusb_get_device_descriptor(dev, &devdesc)) != 0) {
228 usbmuxd_log(LL_WARNING, "Could not get device descriptor for device %d-%d: %d", bus, address, res); 250 usbmuxd_log(LL_WARNING, "Could not get device descriptor for device %d-%d: %d", bus, address, res);
@@ -251,37 +273,45 @@ static int usb_discover(void)
251 libusb_close(handle); 273 libusb_close(handle);
252 continue; 274 continue;
253 } 275 }
254 int idx = alloc_device(); 276 struct usb_device *usbdev;
277 usbdev = malloc(sizeof(struct usb_device));
255 278
256 if((res = libusb_get_string_descriptor_ascii(handle, devdesc.iSerialNumber, (uint8_t *)device_list[idx].serial, 256)) <= 0) { 279 if((res = libusb_get_string_descriptor_ascii(handle, devdesc.iSerialNumber, (uint8_t *)usbdev->serial, 256)) <= 0) {
257 usbmuxd_log(LL_WARNING, "Could not get serial number for device %d-%d: %d", bus, address, res); 280 usbmuxd_log(LL_WARNING, "Could not get serial number for device %d-%d: %d", bus, address, res);
258 libusb_release_interface(handle, USB_INTERFACE); 281 libusb_release_interface(handle, USB_INTERFACE);
259 libusb_close(handle); 282 libusb_close(handle);
283 free(usbdev);
260 continue; 284 continue;
261 } 285 }
262 device_list[idx].serial[res] = 0; 286 usbdev->serial[res] = 0;
263 device_list[idx].bus = bus; 287 usbdev->bus = bus;
264 device_list[idx].address = address; 288 usbdev->address = address;
265 device_list[idx].dev = handle; 289 usbdev->vid = devdesc.idVendor;
266 device_list[idx].alive = 1; 290 usbdev->pid = devdesc.idProduct;
291 usbdev->dev = handle;
292 usbdev->alive = 1;
293 collection_init(&usbdev->tx_xfers);
294
295 collection_add(&device_list, usbdev);
267 296
268 if(device_add(&device_list[idx]) < 0) { 297 if(device_add(usbdev) < 0) {
269 usb_disconnect(&device_list[j]); 298 usb_disconnect(usbdev);
270 continue; 299 continue;
271 } 300 }
272 if(start_rx(&device_list[idx]) < 0) { 301 if(start_rx(usbdev) < 0) {
273 device_remove(&device_list[j]); 302 device_remove(usbdev);
274 usb_disconnect(&device_list[j]); 303 usb_disconnect(usbdev);
275 continue; 304 continue;
276 } 305 }
277 valid_count++; 306 valid_count++;
278 } 307 }
279 for(j=0; j<num_devs; j++) { 308 FOREACH(struct usb_device *usbdev, &device_list) {
280 if(device_list[j].dev && !device_list[j].alive) { 309 if(!usbdev->alive) {
281 device_remove(&device_list[j]); 310 device_remove(usbdev);
282 usb_disconnect(&device_list[j]); 311 usb_disconnect(usbdev);
283 } 312 }
284 } 313 } ENDFOREACH
314
285 libusb_free_device_list(devs, 1); 315 libusb_free_device_list(devs, 1);
286 316
287 gettimeofday(&next_dev_poll_time, NULL); 317 gettimeofday(&next_dev_poll_time, NULL);
@@ -300,7 +330,7 @@ const char *usb_get_serial(struct usb_device *dev)
300 return dev->serial; 330 return dev->serial;
301} 331}
302 332
303int usb_get_location(struct usb_device *dev) 333uint32_t usb_get_location(struct usb_device *dev)
304{ 334{
305 if(!dev->dev) { 335 if(!dev->dev) {
306 return 0; 336 return 0;
@@ -308,6 +338,14 @@ int usb_get_location(struct usb_device *dev)
308 return (dev->bus << 16) | dev->address; 338 return (dev->bus << 16) | dev->address;
309} 339}
310 340
341uint16_t usb_get_pid(struct usb_device *dev)
342{
343 if(!dev->dev) {
344 return 0;
345 }
346 return dev->pid;
347}
348
311void usb_get_fds(struct fdlist *list) 349void usb_get_fds(struct fdlist *list)
312{ 350{
313 const struct libusb_pollfd **usbfds; 351 const struct libusb_pollfd **usbfds;
@@ -360,7 +398,7 @@ int usb_get_timeout(void)
360 398
361int usb_process(void) 399int usb_process(void)
362{ 400{
363 int i, res; 401 int res;
364 struct timeval tv; 402 struct timeval tv;
365 tv.tv_sec = tv.tv_usec = 0; 403 tv.tv_sec = tv.tv_usec = 0;
366 res = libusb_handle_events_timeout(NULL, &tv); 404 res = libusb_handle_events_timeout(NULL, &tv);
@@ -369,12 +407,12 @@ int usb_process(void)
369 return res; 407 return res;
370 } 408 }
371 // reap devices marked dead due to an RX error 409 // reap devices marked dead due to an RX error
372 for(i=0; i<num_devs; i++) { 410 FOREACH(struct usb_device *usbdev, &device_list) {
373 if(device_list[i].dev && !device_list[i].alive) { 411 if(!usbdev->alive) {
374 device_remove(&device_list[i]); 412 device_remove(usbdev);
375 usb_disconnect(&device_list[i]); 413 usb_disconnect(usbdev);
376 } 414 }
377 } 415 } ENDFOREACH
378 416
379 if(dev_poll_remain_ms() <= 0) { 417 if(dev_poll_remain_ms() <= 0) {
380 res = usb_discover(); 418 res = usb_discover();
@@ -386,6 +424,39 @@ int usb_process(void)
386 return 0; 424 return 0;
387} 425}
388 426
427int usb_process_timeout(int msec)
428{
429 int res;
430 struct timeval tleft, tcur, tfin;
431 gettimeofday(&tcur, NULL);
432 tfin.tv_sec = tcur.tv_sec + (msec / 1000);
433 tfin.tv_usec = tcur.tv_usec + (msec % 1000) * 1000;
434 tfin.tv_sec += tfin.tv_usec / 1000000;
435 tfin.tv_usec %= 1000000;
436 while((tfin.tv_sec > tcur.tv_sec) || ((tfin.tv_sec == tcur.tv_sec) && (tfin.tv_usec > tcur.tv_usec))) {
437 tleft.tv_sec = tfin.tv_sec - tcur.tv_sec;
438 tleft.tv_usec = tfin.tv_usec - tcur.tv_usec;
439 if(tleft.tv_usec < 0) {
440 tleft.tv_usec += 1000000;
441 tleft.tv_sec -= 1;
442 }
443 res = libusb_handle_events_timeout(NULL, &tleft);
444 if(res < 0) {
445 usbmuxd_log(LL_ERROR, "libusb_handle_events_timeout failed: %d", res);
446 return res;
447 }
448 // reap devices marked dead due to an RX error
449 FOREACH(struct usb_device *usbdev, &device_list) {
450 if(!usbdev->alive) {
451 device_remove(usbdev);
452 usb_disconnect(usbdev);
453 }
454 } ENDFOREACH
455 gettimeofday(&tcur, NULL);
456 }
457 return 0;
458}
459
389int usb_init(void) 460int usb_init(void)
390{ 461{
391 int res; 462 int res;
@@ -398,20 +469,18 @@ int usb_init(void)
398 return -1; 469 return -1;
399 } 470 }
400 471
401 num_devs = 1; 472 collection_init(&device_list);
402 device_list = malloc(sizeof(*device_list) * num_devs);
403 memset(device_list, 0, sizeof(*device_list) * num_devs);
404 473
405 return usb_discover(); 474 return usb_discover();
406} 475}
407 476
408void usb_shutdown(void) 477void usb_shutdown(void)
409{ 478{
410 int i;
411 usbmuxd_log(LL_DEBUG, "usb_shutdown"); 479 usbmuxd_log(LL_DEBUG, "usb_shutdown");
412 for(i=0; i<num_devs; i++) 480 FOREACH(struct usb_device *usbdev, &device_list) {
413 usb_disconnect(&device_list[i]); 481 device_remove(usbdev);
414 free(device_list); 482 usb_disconnect(usbdev);
415 device_list = NULL; 483 } ENDFOREACH
484 collection_free(&device_list);
416 libusb_exit(NULL); 485 libusb_exit(NULL);
417} 486}