summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHans de Goede <hdegoede@redhat.com>2013-09-11 13:45:01 +0200
committerHans de Goede <hdegoede@redhat.com>2014-04-22 14:31:56 +0200
commit6d8dfe0aee41a3c7dd862c3de488df3ce452d86e (patch)
treee9932c6109e4ad7a71b7a65e007f0abe4f6f3bf2
parent0504375ea965dd25f00d4828a19c329b7e7525d4 (diff)
downloadlibusb-6d8dfe0aee41a3c7dd862c3de488df3ce452d86e.tar.gz
Add API for using bulk streams
Being able to allocate bulk-streams is not really useful if the user cannot specify the stream ids when submitting transfers. The actual stream id gets added to our private itransfer struct, and a setter + getter are added to get to it. Unfortunately this is the only way to add support for stream ids without breaking ABI. So this is another item to fix when we do break ABI in libusb-2.0. Bulk streams also use a separate transer type, to allow backends to determine if a transfer is a bulk stream transfer or an ordinary bulk transfer. This is added because there is no other reliable way to determine if a transfer is a stream as the stream_id is part of the private itransfer struct so apps re-using a transfer may not set it to 0. Adding a separate transfer-type for this was suggested (and coded) by Nathan Hjelm. Most users will likely use the new libusb_fill_bulk_stream_transfer() though, and will never know the difference. Signed-off-by: Hans de Goede <hdegoede@redhat.com>
-rw-r--r--libusb/io.c37
-rw-r--r--libusb/libusb.h39
-rw-r--r--libusb/libusbi.h1
-rw-r--r--libusb/os/linux_usbfs.c25
-rw-r--r--libusb/os/linux_usbfs.h5
-rw-r--r--libusb/os/netbsd_usb.c3
-rw-r--r--libusb/os/openbsd_usb.c3
-rw-r--r--libusb/os/wince_usb.c4
-rw-r--r--libusb/os/windows_usb.c6
-rw-r--r--libusb/version_nano.h2
10 files changed, 116 insertions, 9 deletions
diff --git a/libusb/io.c b/libusb/io.c
index 8797e6e..6b95441 100644
--- a/libusb/io.c
+++ b/libusb/io.c
@@ -1510,6 +1510,43 @@ int API_EXPORTED libusb_cancel_transfer(struct libusb_transfer *transfer)
return r;
}
+/** \ingroup asyncio
+ * Set a transfers bulk stream id. Note users are advised to use
+ * libusb_fill_bulk_stream_transfer() instead of calling this function
+ * directly.
+ *
+ * Since version 1.0.19, \ref LIBUSB_API_VERSION >= 0x01000103
+ *
+ * \param transfer the transfer to set the stream id for
+ * \param stream_id the stream id to set
+ * \see libusb_alloc_streams()
+ */
+void API_EXPORTED libusb_transfer_set_stream_id(
+ struct libusb_transfer *transfer, uint32_t stream_id)
+{
+ struct usbi_transfer *itransfer =
+ LIBUSB_TRANSFER_TO_USBI_TRANSFER(transfer);
+
+ itransfer->stream_id = stream_id;
+}
+
+/** \ingroup asyncio
+ * Get a transfers bulk stream id.
+ *
+ * Since version 1.0.19, \ref LIBUSB_API_VERSION >= 0x01000103
+ *
+ * \param transfer the transfer to get the stream id for
+ * \returns the stream id for the transfer
+ */
+uint32_t API_EXPORTED libusb_transfer_get_stream_id(
+ struct libusb_transfer *transfer)
+{
+ struct usbi_transfer *itransfer =
+ LIBUSB_TRANSFER_TO_USBI_TRANSFER(transfer);
+
+ return itransfer->stream_id;
+}
+
/* Handle completion of a transfer (completion might be an error condition).
* This will invoke the user-supplied callback function, which may end up
* freeing the transfer. Therefore you cannot use the transfer structure
diff --git a/libusb/libusb.h b/libusb/libusb.h
index ccbad44..a19ab34 100644
--- a/libusb/libusb.h
+++ b/libusb/libusb.h
@@ -144,7 +144,7 @@ typedef unsigned __int32 uint32_t;
* Internally, LIBUSB_API_VERSION is defined as follows:
* (libusb major << 24) | (libusb minor << 16) | (16 bit incremental)
*/
-#define LIBUSB_API_VERSION 0x01000102
+#define LIBUSB_API_VERSION 0x01000103
/* The following is kept for compatibility, but will be deprecated in the future */
#define LIBUSBX_API_VERSION LIBUSB_API_VERSION
@@ -343,7 +343,10 @@ enum libusb_transfer_type {
LIBUSB_TRANSFER_TYPE_BULK = 2,
/** Interrupt endpoint */
- LIBUSB_TRANSFER_TYPE_INTERRUPT = 3
+ LIBUSB_TRANSFER_TYPE_INTERRUPT = 3,
+
+ /** Stream endpoint */
+ LIBUSB_TRANSFER_TYPE_BULK_STREAM = 4,
};
/** \ingroup misc
@@ -1478,6 +1481,10 @@ struct libusb_transfer * LIBUSB_CALL libusb_alloc_transfer(int iso_packets);
int LIBUSB_CALL libusb_submit_transfer(struct libusb_transfer *transfer);
int LIBUSB_CALL libusb_cancel_transfer(struct libusb_transfer *transfer);
void LIBUSB_CALL libusb_free_transfer(struct libusb_transfer *transfer);
+void LIBUSB_CALL libusb_transfer_set_stream_id(
+ struct libusb_transfer *transfer, uint32_t stream_id);
+uint32_t LIBUSB_CALL libusb_transfer_get_stream_id(
+ struct libusb_transfer *transfer);
/** \ingroup asyncio
* Helper function to populate the required \ref libusb_transfer fields
@@ -1555,6 +1562,34 @@ static inline void libusb_fill_bulk_transfer(struct libusb_transfer *transfer,
/** \ingroup asyncio
* Helper function to populate the required \ref libusb_transfer fields
+ * for a bulk transfer using bulk streams.
+ *
+ * Since version 1.0.19, \ref LIBUSB_API_VERSION >= 0x01000103
+ *
+ * \param transfer the transfer to populate
+ * \param dev_handle handle of the device that will handle the transfer
+ * \param endpoint address of the endpoint where this transfer will be sent
+ * \param stream_id bulk stream id for this transfer
+ * \param buffer data buffer
+ * \param length length of data buffer
+ * \param callback callback function to be invoked on transfer completion
+ * \param user_data user data to pass to callback function
+ * \param timeout timeout for the transfer in milliseconds
+ */
+static inline void libusb_fill_bulk_stream_transfer(
+ struct libusb_transfer *transfer, libusb_device_handle *dev_handle,
+ unsigned char endpoint, uint32_t stream_id,
+ unsigned char *buffer, int length, libusb_transfer_cb_fn callback,
+ void *user_data, unsigned int timeout)
+{
+ libusb_fill_bulk_transfer(transfer, dev_handle, endpoint, buffer,
+ length, callback, user_data, timeout);
+ transfer->type = LIBUSB_TRANSFER_TYPE_BULK_STREAM;
+ libusb_transfer_set_stream_id(transfer, stream_id);
+}
+
+/** \ingroup asyncio
+ * Helper function to populate the required \ref libusb_transfer fields
* for an interrupt transfer.
*
* \param transfer the transfer to populate
diff --git a/libusb/libusbi.h b/libusb/libusbi.h
index 225c273..a36482c 100644
--- a/libusb/libusbi.h
+++ b/libusb/libusbi.h
@@ -366,6 +366,7 @@ struct usbi_transfer {
struct list_head list;
struct timeval timeout;
int transferred;
+ uint32_t stream_id;
uint8_t flags;
/* this lock is held during libusb_submit_transfer() and
diff --git a/libusb/os/linux_usbfs.c b/libusb/os/linux_usbfs.c
index 2f6b4af..7cc1032 100644
--- a/libusb/os/linux_usbfs.c
+++ b/libusb/os/linux_usbfs.c
@@ -1752,8 +1752,7 @@ static void free_iso_urbs(struct linux_transfer_priv *tpriv)
tpriv->iso_urbs = NULL;
}
-static int submit_bulk_transfer(struct usbi_transfer *itransfer,
- unsigned char urb_type)
+static int submit_bulk_transfer(struct usbi_transfer *itransfer)
{
struct libusb_transfer *transfer =
USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer);
@@ -1841,7 +1840,19 @@ static int submit_bulk_transfer(struct usbi_transfer *itransfer,
for (i = 0; i < num_urbs; i++) {
struct usbfs_urb *urb = &urbs[i];
urb->usercontext = itransfer;
- urb->type = urb_type;
+ switch (transfer->type) {
+ case LIBUSB_TRANSFER_TYPE_BULK:
+ urb->type = USBFS_URB_TYPE_BULK;
+ urb->stream_id = 0;
+ break;
+ case LIBUSB_TRANSFER_TYPE_BULK_STREAM:
+ urb->type = USBFS_URB_TYPE_BULK;
+ urb->stream_id = itransfer->stream_id;
+ break;
+ case LIBUSB_TRANSFER_TYPE_INTERRUPT:
+ urb->type = USBFS_URB_TYPE_INTERRUPT;
+ break;
+ }
urb->endpoint = transfer->endpoint;
urb->buffer = transfer->buffer + (i * bulk_buffer_len);
/* don't set the short not ok flag for the last URB */
@@ -2124,9 +2135,10 @@ static int op_submit_transfer(struct usbi_transfer *itransfer)
case LIBUSB_TRANSFER_TYPE_CONTROL:
return submit_control_transfer(itransfer);
case LIBUSB_TRANSFER_TYPE_BULK:
- return submit_bulk_transfer(itransfer, USBFS_URB_TYPE_BULK);
+ case LIBUSB_TRANSFER_TYPE_BULK_STREAM:
+ return submit_bulk_transfer(itransfer);
case LIBUSB_TRANSFER_TYPE_INTERRUPT:
- return submit_bulk_transfer(itransfer, USBFS_URB_TYPE_INTERRUPT);
+ return submit_bulk_transfer(itransfer);
case LIBUSB_TRANSFER_TYPE_ISOCHRONOUS:
return submit_iso_transfer(itransfer);
default:
@@ -2144,6 +2156,7 @@ static int op_cancel_transfer(struct usbi_transfer *itransfer)
switch (transfer->type) {
case LIBUSB_TRANSFER_TYPE_BULK:
+ case LIBUSB_TRANSFER_TYPE_BULK_STREAM:
if (tpriv->reap_action == ERROR)
break;
/* else, fall through */
@@ -2174,6 +2187,7 @@ static void op_clear_transfer_priv(struct usbi_transfer *itransfer)
switch (transfer->type) {
case LIBUSB_TRANSFER_TYPE_CONTROL:
case LIBUSB_TRANSFER_TYPE_BULK:
+ case LIBUSB_TRANSFER_TYPE_BULK_STREAM:
case LIBUSB_TRANSFER_TYPE_INTERRUPT:
usbi_mutex_lock(&itransfer->lock);
if (tpriv->urbs)
@@ -2542,6 +2556,7 @@ static int reap_for_handle(struct libusb_device_handle *handle)
case LIBUSB_TRANSFER_TYPE_ISOCHRONOUS:
return handle_iso_completion(itransfer, urb);
case LIBUSB_TRANSFER_TYPE_BULK:
+ case LIBUSB_TRANSFER_TYPE_BULK_STREAM:
case LIBUSB_TRANSFER_TYPE_INTERRUPT:
return handle_bulk_completion(itransfer, urb);
case LIBUSB_TRANSFER_TYPE_CONTROL:
diff --git a/libusb/os/linux_usbfs.h b/libusb/os/linux_usbfs.h
index de5186f..f2404ab 100644
--- a/libusb/os/linux_usbfs.h
+++ b/libusb/os/linux_usbfs.h
@@ -94,7 +94,10 @@ struct usbfs_urb {
int buffer_length;
int actual_length;
int start_frame;
- int number_of_packets;
+ union {
+ int number_of_packets; /* Only used for isoc urbs */
+ unsigned int stream_id; /* Only used with bulk streams */
+ };
int error_count;
unsigned int signr;
void *usercontext;
diff --git a/libusb/os/netbsd_usb.c b/libusb/os/netbsd_usb.c
index 988d3c0..ed4f50e 100644
--- a/libusb/os/netbsd_usb.c
+++ b/libusb/os/netbsd_usb.c
@@ -461,6 +461,9 @@ netbsd_submit_transfer(struct usbi_transfer *itransfer)
}
err = _sync_gen_transfer(itransfer);
break;
+ case LIBUSB_TRANSFER_TYPE_BULK_STREAM:
+ err = LIBUSB_ERROR_NOT_SUPPORTED;
+ break;
}
if (err)
diff --git a/libusb/os/openbsd_usb.c b/libusb/os/openbsd_usb.c
index d56c1af..ff470be 100644
--- a/libusb/os/openbsd_usb.c
+++ b/libusb/os/openbsd_usb.c
@@ -507,6 +507,9 @@ obsd_submit_transfer(struct usbi_transfer *itransfer)
}
err = _sync_gen_transfer(itransfer);
break;
+ case LIBUSB_TRANSFER_TYPE_BULK_STREAM:
+ err = LIBUSB_ERROR_NOT_SUPPORTED;
+ break;
}
if (err)
diff --git a/libusb/os/wince_usb.c b/libusb/os/wince_usb.c
index 656b1de..98304e7 100644
--- a/libusb/os/wince_usb.c
+++ b/libusb/os/wince_usb.c
@@ -689,6 +689,8 @@ static int wince_submit_transfer(
return wince_submit_control_or_bulk_transfer(itransfer);
case LIBUSB_TRANSFER_TYPE_ISOCHRONOUS:
return wince_submit_iso_transfer(itransfer);
+ case LIBUSB_TRANSFER_TYPE_BULK_STREAM:
+ return LIBUSB_ERROR_NOT_SUPPORTED;
default:
usbi_err(TRANSFER_CTX(transfer), "unknown endpoint type %d", transfer->type);
return LIBUSB_ERROR_INVALID_PARAM;
@@ -801,6 +803,8 @@ static void wince_handle_callback (struct usbi_transfer *itransfer, uint32_t io_
case LIBUSB_TRANSFER_TYPE_ISOCHRONOUS:
wince_transfer_callback (itransfer, io_result, io_size);
break;
+ case LIBUSB_TRANSFER_TYPE_BULK_STREAM:
+ return LIBUSB_ERROR_NOT_SUPPORTED;
default:
usbi_err(ITRANSFER_CTX(itransfer), "unknown endpoint type %d", transfer->type);
}
diff --git a/libusb/os/windows_usb.c b/libusb/os/windows_usb.c
index 1a25d37..515ddb1 100644
--- a/libusb/os/windows_usb.c
+++ b/libusb/os/windows_usb.c
@@ -2019,6 +2019,8 @@ static int windows_submit_transfer(struct usbi_transfer *itransfer)
return submit_bulk_transfer(itransfer);
case LIBUSB_TRANSFER_TYPE_ISOCHRONOUS:
return submit_iso_transfer(itransfer);
+ case LIBUSB_TRANSFER_TYPE_BULK_STREAM:
+ return LIBUSB_ERROR_NOT_SUPPORTED;
default:
usbi_err(TRANSFER_CTX(transfer), "unknown endpoint type %d", transfer->type);
return LIBUSB_ERROR_INVALID_PARAM;
@@ -2052,6 +2054,8 @@ static int windows_cancel_transfer(struct usbi_transfer *itransfer)
case LIBUSB_TRANSFER_TYPE_INTERRUPT:
case LIBUSB_TRANSFER_TYPE_ISOCHRONOUS:
return windows_abort_transfers(itransfer);
+ case LIBUSB_TRANSFER_TYPE_BULK_STREAM:
+ return LIBUSB_ERROR_NOT_SUPPORTED;
default:
usbi_err(ITRANSFER_CTX(itransfer), "unknown endpoint type %d", transfer->type);
return LIBUSB_ERROR_INVALID_PARAM;
@@ -2111,6 +2115,8 @@ static void windows_handle_callback (struct usbi_transfer *itransfer, uint32_t i
case LIBUSB_TRANSFER_TYPE_ISOCHRONOUS:
windows_transfer_callback (itransfer, io_result, io_size);
break;
+ case LIBUSB_TRANSFER_TYPE_BULK_STREAM:
+ return LIBUSB_ERROR_NOT_SUPPORTED;
default:
usbi_err(ITRANSFER_CTX(itransfer), "unknown endpoint type %d", transfer->type);
}
diff --git a/libusb/version_nano.h b/libusb/version_nano.h
index f37c06f..3f71231 100644
--- a/libusb/version_nano.h
+++ b/libusb/version_nano.h
@@ -1 +1 @@
-#define LIBUSB_NANO 10879
+#define LIBUSB_NANO 10880