| From 0f3496b17877150221d4eb07a1d4f2bb0b26e335 Mon Sep 17 00:00:00 2001 |
| From: =?UTF-8?q?Vianney=20le=20Cl=C3=A9ment=20de=20Saint-Marcq?= |
| <code@quartic.eu> |
| Date: Tue, 13 Dec 2016 15:45:56 +0100 |
| Subject: [PATCH 04/11] UPSTREAM: core: Add libusb_wrap_sys_device() API |
| MIME-Version: 1.0 |
| Content-Type: text/plain; charset=UTF-8 |
| Content-Transfer-Encoding: 8bit |
| |
| Introduce a new API function for wrapping an existing platform-specific |
| device handle as a libusb_device_handle. |
| |
| Signed-off-by: Vianney le Clément de Saint-Marcq <code@quartic.eu> |
| Signed-off-by: Nathan Hjelm <hjelmn@me.com> |
| (cherry picked from commit 7332286ecc5830178d98cd5bf240a926cd46c1d1) |
| Signed-off-by: Dmitry Torokhov <dtor@chromium.org> |
| --- |
| libusb/core.c | 72 ++++++++++++++++++++++++++++++++++++++++++++++++ |
| libusb/libusb.h | 1 + |
| libusb/libusbi.h | 28 +++++++++++++++++++ |
| 3 files changed, 101 insertions(+) |
| |
| diff --git a/libusb/core.c b/libusb/core.c |
| index 50f92f6..a3b9cc1 100644 |
| --- a/libusb/core.c |
| +++ b/libusb/core.c |
| @@ -1211,6 +1211,78 @@ int usbi_clear_event(struct libusb_context *ctx) |
| return 0; |
| } |
| |
| +/** \ingroup libusb_dev |
| + * Wrap a platform-specific system device handle and obtain a libusb device |
| + * handle for the underlying device. The handle allows you to use libusb to |
| + * perform I/O on the device in question. |
| + * |
| + * On Linux, the system device handle must be a valid file descriptor opened |
| + * on the device node. |
| + * |
| + * The system device handle must remain open until libusb_close() is called. |
| + * The system device handle will not be closed by libusb_close(). |
| + * |
| + * Internally, this function creates a temporary device and makes it |
| + * available to you through libusb_get_device(). This device is destroyed |
| + * during libusb_close(). The device shall not be opened through libusb_open(). |
| + * |
| + * This is a non-blocking function; no requests are sent over the bus. |
| + * |
| + * \param ctx the context to operate on, or NULL for the default context |
| + * \param sys_dev the platform-specific system device handle |
| + * \param dev_handle output location for the returned device handle pointer. Only |
| + * populated when the return code is 0. |
| + * \returns 0 on success |
| + * \returns LIBUSB_ERROR_NO_MEM on memory allocation failure |
| + * \returns LIBUSB_ERROR_ACCESS if the user has insufficient permissions |
| + * \returns LIBUSB_ERROR_NOT_SUPPORTED if the operation is not supported on this |
| + * platform |
| + * \returns another LIBUSB_ERROR code on other failure |
| + */ |
| +int API_EXPORTED libusb_wrap_sys_device(libusb_context *ctx, intptr_t sys_dev, |
| + libusb_device_handle **dev_handle) |
| +{ |
| + struct libusb_device_handle *_dev_handle; |
| + size_t priv_size = usbi_backend.device_handle_priv_size; |
| + int r; |
| + usbi_dbg("wrap_sys_device %p", sys_dev); |
| + |
| + USBI_GET_CONTEXT(ctx); |
| + |
| + if (!usbi_backend.wrap_sys_device) |
| + return LIBUSB_ERROR_NOT_SUPPORTED; |
| + |
| + _dev_handle = malloc(sizeof(*_dev_handle) + priv_size); |
| + if (!_dev_handle) |
| + return LIBUSB_ERROR_NO_MEM; |
| + |
| + r = usbi_mutex_init(&_dev_handle->lock); |
| + if (r) { |
| + free(_dev_handle); |
| + return LIBUSB_ERROR_OTHER; |
| + } |
| + |
| + _dev_handle->dev = NULL; |
| + _dev_handle->auto_detach_kernel_driver = 0; |
| + _dev_handle->claimed_interfaces = 0; |
| + memset(&_dev_handle->os_priv, 0, priv_size); |
| + |
| + r = usbi_backend.wrap_sys_device(ctx, _dev_handle, sys_dev); |
| + if (r < 0) { |
| + usbi_dbg("wrap_sys_device %p returns %d", sys_dev, r); |
| + usbi_mutex_destroy(&_dev_handle->lock); |
| + free(_dev_handle); |
| + return r; |
| + } |
| + |
| + usbi_mutex_lock(&ctx->open_devs_lock); |
| + list_add(&_dev_handle->list, &ctx->open_devs); |
| + usbi_mutex_unlock(&ctx->open_devs_lock); |
| + *dev_handle = _dev_handle; |
| + |
| + return 0; |
| +} |
| + |
| /** \ingroup libusb_dev |
| * Open a device and obtain a device handle. A handle allows you to perform |
| * I/O on the device in question. |
| diff --git a/libusb/libusb.h b/libusb/libusb.h |
| index 430136b..a649e99 100644 |
| --- a/libusb/libusb.h |
| +++ b/libusb/libusb.h |
| @@ -1362,6 +1362,7 @@ int LIBUSB_CALL libusb_get_max_packet_size(libusb_device *dev, |
| int LIBUSB_CALL libusb_get_max_iso_packet_size(libusb_device *dev, |
| unsigned char endpoint); |
| |
| +int LIBUSB_CALL libusb_wrap_sys_device(libusb_context *ctx, intptr_t sys_dev, libusb_device_handle **dev_handle); |
| int LIBUSB_CALL libusb_open(libusb_device *dev, libusb_device_handle **dev_handle); |
| void LIBUSB_CALL libusb_close(libusb_device_handle *dev_handle); |
| libusb_device * LIBUSB_CALL libusb_get_device(libusb_device_handle *dev_handle); |
| diff --git a/libusb/libusbi.h b/libusb/libusbi.h |
| index 31d6ce9..e47ee72 100644 |
| --- a/libusb/libusbi.h |
| +++ b/libusb/libusbi.h |
| @@ -701,6 +701,34 @@ struct usbi_os_backend { |
| */ |
| void (*hotplug_poll)(void); |
| |
| + /* Wrap a platform-specific device handle for I/O and other USB |
| + * operations. The device handle is preallocated for you. |
| + * |
| + * Your backend should allocate any internal resources required for I/O |
| + * and other operations so that those operations can happen (hopefully) |
| + * without hiccup. This is also a good place to inform libusb that it |
| + * should monitor certain file descriptors related to this device - |
| + * see the usbi_add_pollfd() function. |
| + * |
| + * Your backend should also initialize the device structure |
| + * (dev_handle->dev), which is NULL at the beginning of the call. |
| + * |
| + * This function should not generate any bus I/O and should not block. |
| + * |
| + * This function is called when the user attempts to wrap an existing |
| + * platform-specific device handle for a device. |
| + * |
| + * Return: |
| + * - 0 on success |
| + * - LIBUSB_ERROR_ACCESS if the user has insufficient permissions |
| + * - another LIBUSB_ERROR code on other failure |
| + * |
| + * Do not worry about freeing the handle on failed open, the upper layers |
| + * do this for you. |
| + */ |
| + int (*wrap_sys_device)(struct libusb_context *ctx, |
| + struct libusb_device_handle *dev_handle, intptr_t sys_dev); |
| + |
| /* Open a device for I/O and other USB operations. The device handle |
| * is preallocated for you, you can retrieve the device in question |
| * through handle->dev. |
| -- |
| 2.22.0.rc2.383.gf4fbbf30c2-goog |
| |