summaryrefslogtreecommitdiff
path: root/libusb/os/linux_usbfs.c
diff options
context:
space:
mode:
authorHans de Goede <hdegoede@redhat.com>2013-09-11 13:06:38 +0200
committerHans de Goede <hdegoede@redhat.com>2014-04-22 14:31:35 +0200
commit0504375ea965dd25f00d4828a19c329b7e7525d4 (patch)
treee207b92c7e777046288be44de2c344b51068906e /libusb/os/linux_usbfs.c
parentc59d574b211bedcab951b2f19de58bb03a04d671 (diff)
downloadlibusb-0504375ea965dd25f00d4828a19c329b7e7525d4.tar.gz
Add API for allocating / freeing usb3 bulk streams + Linux implementation
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
Diffstat (limited to 'libusb/os/linux_usbfs.c')
-rw-r--r--libusb/os/linux_usbfs.c53
1 files changed, 53 insertions, 0 deletions
diff --git a/libusb/os/linux_usbfs.c b/libusb/os/linux_usbfs.c
index 5ad6129..2f6b4af 100644
--- a/libusb/os/linux_usbfs.c
+++ b/libusb/os/linux_usbfs.c
@@ -1495,6 +1495,56 @@ out:
return ret;
}
+static int do_streams_ioctl(struct libusb_device_handle *handle, long req,
+ uint32_t num_streams, unsigned char *endpoints, int num_endpoints)
+{
+ int r, fd = _device_handle_priv(handle)->fd;
+ struct usbfs_streams *streams;
+
+ if (num_endpoints > 30) /* Max 15 in + 15 out eps */
+ return LIBUSB_ERROR_INVALID_PARAM;
+
+ streams = malloc(sizeof(struct usbfs_streams) + num_endpoints);
+ if (!streams)
+ return LIBUSB_ERROR_NO_MEM;
+
+ streams->num_streams = num_streams;
+ streams->num_eps = num_endpoints;
+ memcpy(streams->eps, endpoints, num_endpoints);
+
+ r = ioctl(fd, req, streams);
+
+ free(streams);
+
+ if (r < 0) {
+ if (errno == ENOTTY)
+ return LIBUSB_ERROR_NOT_SUPPORTED;
+ else if (errno == EINVAL)
+ return LIBUSB_ERROR_INVALID_PARAM;
+ else if (errno == ENODEV)
+ return LIBUSB_ERROR_NO_DEVICE;
+
+ usbi_err(HANDLE_CTX(handle),
+ "streams-ioctl failed error %d errno %d", r, errno);
+ return LIBUSB_ERROR_OTHER;
+ }
+ return r;
+}
+
+static int op_alloc_streams(struct libusb_device_handle *handle,
+ uint32_t num_streams, unsigned char *endpoints, int num_endpoints)
+{
+ return do_streams_ioctl(handle, IOCTL_USBFS_ALLOC_STREAMS,
+ num_streams, endpoints, num_endpoints);
+}
+
+static int op_free_streams(struct libusb_device_handle *handle,
+ unsigned char *endpoints, int num_endpoints)
+{
+ return do_streams_ioctl(handle, IOCTL_USBFS_FREE_STREAMS, 0,
+ endpoints, num_endpoints);
+}
+
static int op_kernel_driver_active(struct libusb_device_handle *handle,
int interface)
{
@@ -2596,6 +2646,9 @@ const struct usbi_os_backend linux_usbfs_backend = {
.clear_halt = op_clear_halt,
.reset_device = op_reset_device,
+ .alloc_streams = op_alloc_streams,
+ .free_streams = op_free_streams,
+
.kernel_driver_active = op_kernel_driver_active,
.detach_kernel_driver = op_detach_kernel_driver,
.attach_kernel_driver = op_attach_kernel_driver,