summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/usb.c146
1 files changed, 111 insertions, 35 deletions
diff --git a/src/usb.c b/src/usb.c
index e0fadfd..88d781d 100644
--- a/src/usb.c
+++ b/src/usb.c
@@ -61,6 +61,7 @@ struct usb_device {
61 int wMaxPacketSize; 61 int wMaxPacketSize;
62 uint64_t speed; 62 uint64_t speed;
63 struct libusb_device_descriptor devdesc; 63 struct libusb_device_descriptor devdesc;
64 unsigned char transfer_buffer[1024 + LIBUSB_CONTROL_SETUP_SIZE];
64}; 65};
65 66
66static struct collection device_list; 67static struct collection device_list;
@@ -258,6 +259,91 @@ static int start_rx_loop(struct usb_device *dev)
258 return 0; 259 return 0;
259} 260}
260 261
262static void get_serial_callback(struct libusb_transfer *transfer)
263{
264 unsigned int di, si;
265 struct usb_device *usbdev = transfer->user_data;
266
267 if(transfer->status != LIBUSB_TRANSFER_COMPLETED) {
268 usbmuxd_log(LL_ERROR, "Failed to request serial for device %d-%d (%i)", usbdev->bus, usbdev->address, transfer->status);
269 libusb_free_transfer(transfer);
270 return;
271 }
272
273 /* De-unicode, taken from libusb */
274 unsigned char *data = libusb_control_transfer_get_data(transfer);
275 for (di = 0, si = 2; si < data[0] && di < sizeof(usbdev->serial)-1; si += 2) {
276 if ((data[si] & 0x80) || (data[si + 1])) /* non-ASCII */
277 usbdev->serial[di++] = '?';
278 else
279 usbdev->serial[di++] = data[si];
280 }
281 usbdev->serial[di] = 0;
282
283 usbmuxd_log(LL_INFO, "Got serial '%s' for device %d-%d", usbdev->serial, usbdev->bus, usbdev->address);
284
285 libusb_free_transfer(transfer);
286
287 /* Finish setup now */
288 if(device_add(usbdev) < 0) {
289 usb_disconnect(usbdev);
290 return;
291 }
292
293 // Spin up NUM_RX_LOOPS parallel usb data retrieval loops
294 // Old usbmuxds used only 1 rx loop, but that leaves the
295 // USB port sleeping most of the time
296 int rx_loops = NUM_RX_LOOPS;
297 for (rx_loops = NUM_RX_LOOPS; rx_loops > 0; rx_loops--) {
298 if(start_rx_loop(usbdev) < 0) {
299 usbmuxd_log(LL_WARNING, "Failed to start RX loop number %d", NUM_RX_LOOPS - rx_loops);
300 }
301 }
302
303 // Ensure we have at least 1 RX loop going
304 if (rx_loops == NUM_RX_LOOPS) {
305 usbmuxd_log(LL_FATAL, "Failed to start any RX loop for device %d-%d",
306 usbdev->bus, usbdev->address);
307 device_remove(usbdev);
308 usb_disconnect(usbdev);
309 return;
310 } else if (rx_loops > 0) {
311 usbmuxd_log(LL_WARNING, "Failed to start all %d RX loops. Going on with %d loops. "
312 "This may have negative impact on device read speed.",
313 NUM_RX_LOOPS, NUM_RX_LOOPS - rx_loops);
314 } else {
315 usbmuxd_log(LL_DEBUG, "All %d RX loops started successfully", NUM_RX_LOOPS);
316 }
317}
318
319static void get_langid_callback(struct libusb_transfer *transfer)
320{
321 int res;
322 struct usb_device *usbdev = transfer->user_data;
323
324 if(transfer->status != LIBUSB_TRANSFER_COMPLETED) {
325 usbmuxd_log(LL_ERROR, "Failed to request lang ID for device %d-%d (%i)", usbdev->bus,
326 usbdev->address, transfer->status);
327 libusb_free_transfer(transfer);
328 return;
329 }
330
331 unsigned char *data = libusb_control_transfer_get_data(transfer);
332 uint16_t langid = (uint16_t)(data[2] | (data[3] << 8));
333 usbmuxd_log(LL_INFO, "Got lang ID %u for device %d-%d", langid, usbdev->bus, usbdev->address);
334
335 /* re-use the same transfer */
336 libusb_fill_control_setup(usbdev->transfer_buffer, LIBUSB_ENDPOINT_IN, LIBUSB_REQUEST_GET_DESCRIPTOR,
337 (uint16_t)((LIBUSB_DT_STRING << 8) | usbdev->devdesc.iSerialNumber),
338 langid, sizeof(usbdev->transfer_buffer));
339 libusb_fill_control_transfer(transfer, usbdev->dev, usbdev->transfer_buffer, get_serial_callback, usbdev, 1000);
340
341 if((res = libusb_submit_transfer(transfer)) < 0) {
342 usbmuxd_log(LL_ERROR, "Could not request transfer for device %d-%d (%d)", usbdev->bus, usbdev->address, res);
343 libusb_free_transfer(transfer);
344 }
345}
346
261static int usb_device_add(libusb_device* dev) 347static int usb_device_add(libusb_device* dev)
262{ 348{
263 int j, res; 349 int j, res;
@@ -265,6 +351,7 @@ static int usb_device_add(libusb_device* dev)
265 uint8_t bus = libusb_get_bus_number(dev); 351 uint8_t bus = libusb_get_bus_number(dev);
266 uint8_t address = libusb_get_device_address(dev); 352 uint8_t address = libusb_get_device_address(dev);
267 struct libusb_device_descriptor devdesc; 353 struct libusb_device_descriptor devdesc;
354 struct libusb_transfer *transfer;
268 int found = 0; 355 int found = 0;
269 FOREACH(struct usb_device *usbdev, &device_list) { 356 FOREACH(struct usb_device *usbdev, &device_list) {
270 if(usbdev->bus == bus && usbdev->address == address) { 357 if(usbdev->bus == bus && usbdev->address == address) {
@@ -287,7 +374,8 @@ static int usb_device_add(libusb_device* dev)
287 return -1; 374 return -1;
288 libusb_device_handle *handle; 375 libusb_device_handle *handle;
289 usbmuxd_log(LL_INFO, "Found new device with v/p %04x:%04x at %d-%d", devdesc.idVendor, devdesc.idProduct, bus, address); 376 usbmuxd_log(LL_INFO, "Found new device with v/p %04x:%04x at %d-%d", devdesc.idVendor, devdesc.idProduct, bus, address);
290 // potentially blocking operations follow; they will only run when new devices are detected, which is acceptable 377 // No blocking operation can follow: it may be run in the libusb hotplug callback and libusb will refuse any
378 // blocking call
291 if((res = libusb_open(dev, &handle)) != 0) { 379 if((res = libusb_open(dev, &handle)) != 0) {
292 usbmuxd_log(LL_WARNING, "Could not open device %d-%d: %d", bus, address, res); 380 usbmuxd_log(LL_WARNING, "Could not open device %d-%d: %d", bus, address, res);
293 return -1; 381 return -1;
@@ -386,14 +474,15 @@ static int usb_device_add(libusb_device* dev)
386 return -1; 474 return -1;
387 } 475 }
388 476
389 if((res = libusb_get_string_descriptor_ascii(handle, devdesc.iSerialNumber, (uint8_t *)usbdev->serial, 256)) <= 0) { 477 transfer = libusb_alloc_transfer(0);
390 usbmuxd_log(LL_WARNING, "Could not get serial number for device %d-%d: %d", bus, address, res); 478 if(!transfer) {
391 libusb_release_interface(handle, usbdev->interface); 479 usbmuxd_log(LL_WARNING, "Failed to allocate transfer for device %d-%d: %d", bus, address, res);
392 libusb_close(handle); 480 libusb_close(handle);
393 free(usbdev); 481 free(usbdev);
394 return -1; 482 return -1;
395 } 483 }
396 usbdev->serial[res] = 0; 484
485 usbdev->serial[0] = 0;
397 usbdev->bus = bus; 486 usbdev->bus = bus;
398 usbdev->address = address; 487 usbdev->address = address;
399 usbdev->devdesc = devdesc; 488 usbdev->devdesc = devdesc;
@@ -427,40 +516,27 @@ static int usb_device_add(libusb_device* dev)
427 516
428 usbmuxd_log(LL_INFO, "USB Speed is %g MBit/s for device %d-%d", (double)(usbdev->speed / 1000000.0), usbdev->bus, usbdev->address); 517 usbmuxd_log(LL_INFO, "USB Speed is %g MBit/s for device %d-%d", (double)(usbdev->speed / 1000000.0), usbdev->bus, usbdev->address);
429 518
430 collection_init(&usbdev->tx_xfers); 519 /**
431 collection_init(&usbdev->rx_xfers); 520 * From libusb:
432 521 * Asking for the zero'th index is special - it returns a string
433 collection_add(&device_list, usbdev); 522 * descriptor that contains all the language IDs supported by the
434 523 * device.
435 if(device_add(usbdev) < 0) { 524 **/
436 usb_disconnect(usbdev); 525 libusb_fill_control_setup(usbdev->transfer_buffer, LIBUSB_ENDPOINT_IN, LIBUSB_REQUEST_GET_DESCRIPTOR, LIBUSB_DT_STRING << 8, 0, sizeof(usbdev->transfer_buffer));
526 libusb_fill_control_transfer(transfer, handle, usbdev->transfer_buffer, get_langid_callback, usbdev, 1000);
527
528 if((res = libusb_submit_transfer(transfer)) < 0) {
529 usbmuxd_log(LL_ERROR, "Could not request transfer for device %d-%d (%d)", usbdev->bus, usbdev->address, res);
530 libusb_free_transfer(transfer);
531 libusb_close(handle);
532 free(usbdev);
437 return -1; 533 return -1;
438 } 534 }
439 535
440 // Spin up NUM_RX_LOOPS parallel usb data retrieval loops 536 collection_init(&usbdev->tx_xfers);
441 // Old usbmuxds used only 1 rx loop, but that leaves the 537 collection_init(&usbdev->rx_xfers);
442 // USB port sleeping most of the time
443 int rx_loops = NUM_RX_LOOPS;
444 for (rx_loops = NUM_RX_LOOPS; rx_loops > 0; rx_loops--) {
445 if(start_rx_loop(usbdev) < 0) {
446 usbmuxd_log(LL_WARNING, "Failed to start RX loop number %d", NUM_RX_LOOPS - rx_loops);
447 }
448 }
449 538
450 // Ensure we have at least 1 RX loop going 539 collection_add(&device_list, usbdev);
451 if (rx_loops == NUM_RX_LOOPS) {
452 usbmuxd_log(LL_FATAL, "Failed to start any RX loop for device %d-%d",
453 usbdev->bus, usbdev->address);
454 device_remove(usbdev);
455 usb_disconnect(usbdev);
456 return -1;
457 } else if (rx_loops > 0) {
458 usbmuxd_log(LL_WARNING, "Failed to start all %d RX loops. Going on with %d loops. "
459 "This may have negative impact on device read speed.",
460 NUM_RX_LOOPS, NUM_RX_LOOPS - rx_loops);
461 } else {
462 usbmuxd_log(LL_DEBUG, "All %d RX loops started successfully", NUM_RX_LOOPS);
463 }
464 540
465 return 0; 541 return 0;
466} 542}