diff options
author | Nathan Hjelm <hjelmn@me.com> | 2013-09-12 14:57:01 -0600 |
---|---|---|
committer | Nathan Hjelm <hjelmn@me.com> | 2014-05-06 02:21:57 -0600 |
commit | e16575ceaf3148c389d66686e51af7cc8dff6053 (patch) | |
tree | 9aeb748085695229012e3da1842345ee511d11b0 | |
parent | 7200c567ea74ef050eb944ef2eb31fccef605732 (diff) | |
download | libusb-e16575ceaf3148c389d66686e51af7cc8dff6053.tar.gz |
darwin: Add support for bulk stream transfers.
This commit adds support for bulk streams to the darwin backend. I
have not had a chance to fully test this code as I have no access
to any devices that use this interface.
Signed-off-by: Nathan Hjelm <hjelmn@me.com>
-rw-r--r-- | libusb/core.c | 3 | ||||
-rw-r--r-- | libusb/os/darwin_usb.c | 120 | ||||
-rw-r--r-- | libusb/version_nano.h | 2 |
3 files changed, 122 insertions, 3 deletions
diff --git a/libusb/core.c b/libusb/core.c index f766e62..ffce020 100644 --- a/libusb/core.c +++ b/libusb/core.c @@ -1621,7 +1621,8 @@ int API_EXPORTED libusb_reset_device(libusb_device_handle *dev) * some protocols require that endpoints are setup with similar stream ids. * All endpoints passed in must belong to the same interface. * - * Note this function may return less streams then requested. + * Note this function may return less streams then requested. Also note that the + * same number of streams are allocated for each endpoint in the endpoint array. * * Stream id 0 is reserved, and should not be used to communicate with devices. * If libusb_alloc_streams() returns with a value of N, you may use stream ids diff --git a/libusb/os/darwin_usb.c b/libusb/os/darwin_usb.c index b66fe80..dc80281 100644 --- a/libusb/os/darwin_usb.c +++ b/libusb/os/darwin_usb.c @@ -1483,6 +1483,41 @@ static int submit_bulk_transfer(struct usbi_transfer *itransfer) { return darwin_to_libusb (ret); } +#if InterfaceVersion >= 550 +static int submit_stream_transfer(struct usbi_transfer *itransfer) { + struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer); + struct darwin_device_handle_priv *priv = (struct darwin_device_handle_priv *)transfer->dev_handle->os_priv; + struct darwin_interface *cInterface; + uint8_t pipeRef, iface; + IOReturn ret; + + if (ep_to_pipeRef (transfer->dev_handle, transfer->endpoint, &pipeRef, &iface) != 0) { + usbi_err (TRANSFER_CTX (transfer), "endpoint not found on any open interface"); + + return LIBUSB_ERROR_NOT_FOUND; + } + + cInterface = &priv->interfaces[iface]; + + itransfer->flags |= USBI_TRANSFER_OS_HANDLES_TIMEOUT; + + if (IS_XFERIN(transfer)) + ret = (*(cInterface->interface))->ReadStreamsPipeAsyncTO(cInterface->interface, pipeRef, itransfer->stream_id, + transfer->buffer, transfer->length, transfer->timeout, + transfer->timeout, darwin_async_io_callback, (void *)itransfer); + else + ret = (*(cInterface->interface))->WriteStreamsPipeAsyncTO(cInterface->interface, pipeRef, itransfer->stream_id, + transfer->buffer, transfer->length, transfer->timeout, + transfer->timeout, darwin_async_io_callback, (void *)itransfer); + + if (ret) + usbi_err (TRANSFER_CTX (transfer), "bulk stream transfer failed (dir = %s): %s (code = 0x%08x)", IS_XFERIN(transfer) ? "In" : "Out", + darwin_error_str(ret), ret); + + return darwin_to_libusb (ret); +} +#endif + static int submit_iso_transfer(struct usbi_transfer *itransfer) { struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer); struct darwin_transfer_priv *tpriv = usbi_transfer_get_os_priv(itransfer); @@ -1634,6 +1669,13 @@ static int darwin_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: +#if InterfaceVersion >= 550 + return submit_stream_transfer(itransfer); +#else + usbi_err (TRANSFER_CTX(transfer), "IOUSBFamily version does not support bulk stream transfers"); + return LIBUSB_ERROR_NOT_SUPPORTED; +#endif default: usbi_err (TRANSFER_CTX(transfer), "unknown endpoint type %d", transfer->type); return LIBUSB_ERROR_INVALID_PARAM; @@ -1677,7 +1719,12 @@ static int darwin_abort_transfers (struct usbi_transfer *itransfer) { usbi_warn (ITRANSFER_CTX (itransfer), "aborting all transactions on interface %d pipe %d", iface, pipeRef); /* abort transactions */ - (*(cInterface->interface))->AbortPipe (cInterface->interface, pipeRef); +#if InterfaceVersion >= 550 + if (LIBUSB_TRANSFER_TYPE_BULK_STREAM == transfer->type) + (*(cInterface->interface))->AbortStreamsPipe (cInterface->interface, pipeRef, itransfer->stream_id); + else +#endif + (*(cInterface->interface))->AbortPipe (cInterface->interface, pipeRef); usbi_dbg ("calling clear pipe stall to clear the data toggle bit"); @@ -1859,6 +1906,72 @@ static int darwin_clock_gettime(int clk_id, struct timespec *tp) { return 0; } +#if InterfaceVersion >= 550 +static int darwin_alloc_streams (struct libusb_device_handle *dev_handle, uint32_t num_streams, unsigned char *endpoints, + int num_endpoints) { + struct darwin_device_handle_priv *priv = (struct darwin_device_handle_priv *) dev_handle->os_priv; + struct darwin_interface *cInterface; + uint8_t pipeRef, iface; + UInt32 supportsStreams; + int rc, i; + + /* find the mimimum number of supported streams on the endpoint list */ + for (i = 0 ; i < num_endpoints ; ++i) { + if (0 != (rc = ep_to_pipeRef (dev_handle, endpoints[i], &pipeRef, &iface))) { + return rc; + } + + cInterface = &priv->interfaces[iface]; + + (*(cInterface->interface))->SupportsStreams (cInterface->interface, pipeRef, &supportsStreams); + if (num_streams > supportsStreams) + num_streams = supportsStreams; + } + + /* it is an error if any endpoint in endpoints does not support streams */ + if (0 == num_streams) + return LIBUSB_ERROR_INVALID_PARAM; + + /* create the streams */ + for (i = 0 ; i < num_endpoints ; ++i) { + (void) ep_to_pipeRef (dev_handle, endpoints[i], &pipeRef, &iface); + + cInterface = &priv->interfaces[iface]; + + rc = (*(cInterface->interface))->CreateStreams (cInterface->interface, pipeRef, num_streams); + if (kIOReturnSuccess != rc) + return darwin_to_libusb(rc); + } + + return num_streams; +} + +static int darwin_free_streams (struct libusb_device_handle *dev_handle, unsigned char *endpoints, int num_endpoints) { + struct darwin_device_handle_priv *priv = (struct darwin_device_handle_priv *) dev_handle->os_priv; + struct darwin_interface *cInterface; + uint8_t pipeRef, iface; + UInt32 supportsStreams; + int rc; + + for (int i = 0 ; i < num_endpoints ; ++i) { + if (0 != (rc = ep_to_pipeRef (dev_handle, endpoints[i], &pipeRef, &iface))) + return rc; + + cInterface = &priv->interfaces[iface]; + + (*(cInterface->interface))->SupportsStreams (cInterface->interface, pipeRef, &supportsStreams); + if (0 == supportsStreams) + return LIBUSB_ERROR_INVALID_PARAM; + + rc = (*(cInterface->interface))->CreateStreams (cInterface->interface, pipeRef, 0); + if (kIOReturnSuccess != rc) + return darwin_to_libusb(rc); + } + + return LIBUSB_SUCCESS;; +} +#endif + const struct usbi_os_backend darwin_backend = { .name = "Darwin", .caps = 0, @@ -1880,6 +1993,11 @@ const struct usbi_os_backend darwin_backend = { .clear_halt = darwin_clear_halt, .reset_device = darwin_reset_device, +#if InterfaceVersion >= 550 + .alloc_streams = darwin_alloc_streams, + .free_streams = darwin_free_streams, +#endif + .kernel_driver_active = darwin_kernel_driver_active, .detach_kernel_driver = darwin_detach_kernel_driver, .attach_kernel_driver = darwin_attach_kernel_driver, diff --git a/libusb/version_nano.h b/libusb/version_nano.h index 9516b27..191ac46 100644 --- a/libusb/version_nano.h +++ b/libusb/version_nano.h @@ -1 +1 @@ -#define LIBUSB_NANO 10882 +#define LIBUSB_NANO 10883 |