Index: third_party/libusb/src/libusb/sync.c |
diff --git a/third_party/libusb/src/libusb/sync.c b/third_party/libusb/src/libusb/sync.c |
index 8eed47b68a8737ba3ffd8d8c881468521525c68d..42e486db390f96b97765b6c1ca26cdf2ea1a0475 100644 |
--- a/third_party/libusb/src/libusb/sync.c |
+++ b/third_party/libusb/src/libusb/sync.c |
@@ -1,6 +1,6 @@ |
/* |
- * Synchronous I/O functions for libusb |
- * Copyright (C) 2007-2008 Daniel Drake <dsd@gentoo.org> |
+ * Synchronous I/O functions for libusbx |
+ * Copyright © 2007-2008 Daniel Drake <dsd@gentoo.org> |
* |
* This library is free software; you can redistribute it and/or |
* modify it under the terms of the GNU Lesser General Public |
@@ -17,7 +17,7 @@ |
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |
*/ |
-#include <config.h> |
+#include "config.h" |
#include <errno.h> |
#include <stdint.h> |
#include <stdlib.h> |
@@ -28,12 +28,12 @@ |
/** |
* @defgroup syncio Synchronous device I/O |
* |
- * This page documents libusb's synchronous (blocking) API for USB device I/O. |
+ * This page documents libusbx's synchronous (blocking) API for USB device I/O. |
* This interface is easy to use but has some limitations. More advanced users |
* may wish to consider using the \ref asyncio "asynchronous I/O API" instead. |
*/ |
-static void LIBUSB_CALL ctrl_transfer_cb(struct libusb_transfer *transfer) |
+static void LIBUSB_CALL sync_transfer_cb(struct libusb_transfer *transfer) |
{ |
int *completed = transfer->user_data; |
*completed = 1; |
@@ -41,6 +41,24 @@ static void LIBUSB_CALL ctrl_transfer_cb(struct libusb_transfer *transfer) |
/* caller interprets result and frees transfer */ |
} |
+static void sync_transfer_wait_for_completion(struct libusb_transfer *transfer) |
+{ |
+ int r, *completed = transfer->user_data; |
+ struct libusb_context *ctx = HANDLE_CTX(transfer->dev_handle); |
+ |
+ while (!*completed) { |
+ r = libusb_handle_events_completed(ctx, completed); |
+ if (r < 0) { |
+ if (r == LIBUSB_ERROR_INTERRUPTED) |
+ continue; |
+ usbi_err(ctx, "libusb_handle_events failed: %s, cancelling transfer and retrying", |
+ libusb_error_name(r)); |
+ libusb_cancel_transfer(transfer); |
+ continue; |
+ } |
+ } |
+} |
+ |
/** \ingroup syncio |
* Perform a USB control transfer. |
* |
@@ -81,7 +99,7 @@ int API_EXPORTED libusb_control_transfer(libusb_device_handle *dev_handle, |
if (!transfer) |
return LIBUSB_ERROR_NO_MEM; |
- buffer = malloc(LIBUSB_CONTROL_SETUP_SIZE + wLength); |
+ buffer = (unsigned char*) malloc(LIBUSB_CONTROL_SETUP_SIZE + wLength); |
if (!buffer) { |
libusb_free_transfer(transfer); |
return LIBUSB_ERROR_NO_MEM; |
@@ -93,7 +111,7 @@ int API_EXPORTED libusb_control_transfer(libusb_device_handle *dev_handle, |
memcpy(buffer + LIBUSB_CONTROL_SETUP_SIZE, data, wLength); |
libusb_fill_control_transfer(transfer, dev_handle, buffer, |
- ctrl_transfer_cb, &completed, timeout); |
+ sync_transfer_cb, &completed, timeout); |
transfer->flags = LIBUSB_TRANSFER_FREE_BUFFER; |
r = libusb_submit_transfer(transfer); |
if (r < 0) { |
@@ -101,19 +119,7 @@ int API_EXPORTED libusb_control_transfer(libusb_device_handle *dev_handle, |
return r; |
} |
- while (!completed) { |
- r = libusb_handle_events_completed(HANDLE_CTX(dev_handle), &completed); |
- if (r < 0) { |
- if (r == LIBUSB_ERROR_INTERRUPTED) |
- continue; |
- libusb_cancel_transfer(transfer); |
- while (!completed) |
- if (libusb_handle_events_completed(HANDLE_CTX(dev_handle), &completed) < 0) |
- break; |
- libusb_free_transfer(transfer); |
- return r; |
- } |
- } |
+ sync_transfer_wait_for_completion(transfer); |
if ((bmRequestType & LIBUSB_ENDPOINT_DIR_MASK) == LIBUSB_ENDPOINT_IN) |
memcpy(data, libusb_control_transfer_get_data(transfer), |
@@ -135,6 +141,10 @@ int API_EXPORTED libusb_control_transfer(libusb_device_handle *dev_handle, |
case LIBUSB_TRANSFER_OVERFLOW: |
r = LIBUSB_ERROR_OVERFLOW; |
break; |
+ case LIBUSB_TRANSFER_ERROR: |
+ case LIBUSB_TRANSFER_CANCELLED: |
+ r = LIBUSB_ERROR_IO; |
+ break; |
default: |
usbi_warn(HANDLE_CTX(dev_handle), |
"unrecognised status code %d", transfer->status); |
@@ -145,14 +155,6 @@ int API_EXPORTED libusb_control_transfer(libusb_device_handle *dev_handle, |
return r; |
} |
-static void LIBUSB_CALL bulk_transfer_cb(struct libusb_transfer *transfer) |
-{ |
- int *completed = transfer->user_data; |
- *completed = 1; |
- usbi_dbg("actual_length=%d", transfer->actual_length); |
- /* caller interprets results and frees transfer */ |
-} |
- |
static int do_sync_bulk_transfer(struct libusb_device_handle *dev_handle, |
unsigned char endpoint, unsigned char *buffer, int length, |
int *transferred, unsigned int timeout, unsigned char type) |
@@ -165,7 +167,7 @@ static int do_sync_bulk_transfer(struct libusb_device_handle *dev_handle, |
return LIBUSB_ERROR_NO_MEM; |
libusb_fill_bulk_transfer(transfer, dev_handle, endpoint, buffer, length, |
- bulk_transfer_cb, &completed, timeout); |
+ sync_transfer_cb, &completed, timeout); |
transfer->type = type; |
r = libusb_submit_transfer(transfer); |
@@ -174,19 +176,7 @@ static int do_sync_bulk_transfer(struct libusb_device_handle *dev_handle, |
return r; |
} |
- while (!completed) { |
- r = libusb_handle_events_completed(HANDLE_CTX(dev_handle), &completed); |
- if (r < 0) { |
- if (r == LIBUSB_ERROR_INTERRUPTED) |
- continue; |
- libusb_cancel_transfer(transfer); |
- while (!completed) |
- if (libusb_handle_events_completed(HANDLE_CTX(dev_handle), &completed) < 0) |
- break; |
- libusb_free_transfer(transfer); |
- return r; |
- } |
- } |
+ sync_transfer_wait_for_completion(transfer); |
*transferred = transfer->actual_length; |
switch (transfer->status) { |
@@ -205,6 +195,10 @@ static int do_sync_bulk_transfer(struct libusb_device_handle *dev_handle, |
case LIBUSB_TRANSFER_NO_DEVICE: |
r = LIBUSB_ERROR_NO_DEVICE; |
break; |
+ case LIBUSB_TRANSFER_ERROR: |
+ case LIBUSB_TRANSFER_CANCELLED: |
+ r = LIBUSB_ERROR_IO; |
+ break; |
default: |
usbi_warn(HANDLE_CTX(dev_handle), |
"unrecognised status code %d", transfer->status); |
@@ -228,9 +222,9 @@ static int do_sync_bulk_transfer(struct libusb_device_handle *dev_handle, |
* Not all of the data may have been written. |
* |
* Also check <tt>transferred</tt> when dealing with a timeout error code. |
- * libusb may have to split your transfer into a number of chunks to satisfy |
+ * libusbx may have to split your transfer into a number of chunks to satisfy |
* underlying O/S requirements, meaning that the timeout may expire after |
- * the first few chunks have completed. libusb is careful not to lose any data |
+ * the first few chunks have completed. libusbx is careful not to lose any data |
* that may have been transferred; do not assume that timeout conditions |
* indicate a complete lack of I/O. |
* |
@@ -276,9 +270,9 @@ int API_EXPORTED libusb_bulk_transfer(struct libusb_device_handle *dev_handle, |
* writes. Not all of the data may have been written. |
* |
* Also check <tt>transferred</tt> when dealing with a timeout error code. |
- * libusb may have to split your transfer into a number of chunks to satisfy |
+ * libusbx may have to split your transfer into a number of chunks to satisfy |
* underlying O/S requirements, meaning that the timeout may expire after |
- * the first few chunks have completed. libusb is careful not to lose any data |
+ * the first few chunks have completed. libusbx is careful not to lose any data |
* that may have been transferred; do not assume that timeout conditions |
* indicate a complete lack of I/O. |
* |
@@ -311,4 +305,3 @@ int API_EXPORTED libusb_interrupt_transfer( |
return do_sync_bulk_transfer(dev_handle, endpoint, data, length, |
transferred, timeout, LIBUSB_TRANSFER_TYPE_INTERRUPT); |
} |
- |