Add transfer flags
authorDaniel Drake <dsd@gentoo.org>
Mon, 10 Mar 2008 18:38:15 +0000 (18:38 +0000)
committerDaniel Drake <dsd@gentoo.org>
Mon, 10 Mar 2008 18:38:15 +0000 (18:38 +0000)
TODO
examples/dpfp.c
libusb/io.c
libusb/libusb.h

diff --git a/TODO b/TODO
index f58873d..8506952 100644 (file)
--- 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?
index c56e8d8..70944f8 100644 (file)
@@ -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);
 }
 
index 77b68ab..118c8b0 100644 (file)
@@ -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);
 }
index a697e4e..4f38ddf 100644 (file)
@@ -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;