aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--TODO5
-rw-r--r--examples/dpfp.c4
-rw-r--r--libusb/io.c16
-rw-r--r--libusb/libusb.h13
4 files changed, 31 insertions, 7 deletions
diff --git a/TODO b/TODO
index f58873d..8506952 100644
--- a/TODO
+++ b/TODO
@@ -9,11 +9,6 @@ error codes
fixme review
review functionality missing over 0.1
-add some libusb_transfer flags:
- - treat short transfers as errors
- - unlink behaviour control
- - update timeout with time remaining
-
1.0 API style/naming points to reconsider
=========================================
typedef _cb or _cb_fn or _cb_t?
diff --git a/examples/dpfp.c b/examples/dpfp.c
index c56e8d8..70944f8 100644
--- a/examples/dpfp.c
+++ b/examples/dpfp.c
@@ -162,8 +162,6 @@ static void cb_mode_changed(struct libusb_transfer *transfer)
transfer->length, transfer->actual_length);
if (next_state() < 0)
do_exit = 2;
- free(transfer->buffer);
- libusb_free_transfer(transfer);
}
static int set_mode_async(unsigned char data)
@@ -186,6 +184,8 @@ static int set_mode_async(unsigned char data)
libusb_fill_control_transfer(transfer, devh, buf, cb_mode_changed, NULL,
1000);
+ transfer->flags = LIBUSB_TRANSFER_SHORT_NOT_OK
+ | LIBUSB_TRANSFER_FREE_BUFFER | LIBUSB_TRANSFER_FREE_TRANSFER;
return libusb_submit_transfer(transfer);
}
diff --git a/libusb/io.c b/libusb/io.c
index 77b68ab..118c8b0 100644
--- a/libusb/io.c
+++ b/libusb/io.c
@@ -248,10 +248,23 @@ static void handle_transfer_completion(struct usbi_transfer *itransfer,
if (status == LIBUSB_TRANSFER_SILENT_COMPLETION)
return;
+ if (status == LIBUSB_TRANSFER_COMPLETED
+ && transfer->flags & LIBUSB_TRANSFER_SHORT_NOT_OK) {
+ int rqlen = transfer->length;
+ if (transfer->endpoint_type == LIBUSB_ENDPOINT_TYPE_CONTROL)
+ rqlen -= LIBUSB_CONTROL_SETUP_SIZE;
+ if (rqlen != itransfer->transferred) {
+ usbi_dbg("interpreting short transfer as error");
+ status = LIBUSB_TRANSFER_ERROR;
+ }
+ }
+
transfer->status = status;
transfer->actual_length = itransfer->transferred;
if (transfer->callback)
transfer->callback(transfer);
+ if (transfer->flags & LIBUSB_TRANSFER_FREE_TRANSFER)
+ libusb_free_transfer(transfer);
}
static void handle_transfer_cancellation(struct usbi_transfer *transfer)
@@ -534,6 +547,9 @@ API_EXPORTED void libusb_free_transfer(struct libusb_transfer *transfer)
if (!transfer)
return;
+ if (transfer->flags & LIBUSB_TRANSFER_FREE_BUFFER)
+ free(transfer->buffer);
+
itransfer = TRANSFER_TO_PRIV(transfer);
free(itransfer);
}
diff --git a/libusb/libusb.h b/libusb/libusb.h
index a697e4e..4f38ddf 100644
--- a/libusb/libusb.h
+++ b/libusb/libusb.h
@@ -189,16 +189,29 @@ typedef struct libusb_device_handle libusb_device_handle;
enum libusb_transfer_status {
LIBUSB_TRANSFER_SILENT_COMPLETION = 0,
LIBUSB_TRANSFER_COMPLETED,
+ LIBUSB_TRANSFER_ERROR,
LIBUSB_TRANSFER_TIMED_OUT,
LIBUSB_TRANSFER_CANCELLED,
};
+/* libusb_transfer.flags values */
+
+/* report short frames as errors */
+#define LIBUSB_TRANSFER_SHORT_NOT_OK (1<<0)
+
+/* automatically free() transfer buffer during libusb_free_transfer() */
+#define LIBUSB_TRANSFER_FREE_BUFFER (1<<1)
+
+/* automatically call libusb_free_transfer() after callback returns */
+#define LIBUSB_TRANSFER_FREE_TRANSFER (1<<2)
+
struct libusb_transfer;
typedef void (*libusb_transfer_cb_fn)(struct libusb_transfer *transfer);
struct libusb_transfer {
libusb_device_handle *dev_handle;
+ uint8_t flags;
unsigned char endpoint;
unsigned char endpoint_type;
unsigned int timeout;