blob: d4ccbb9fb86b338204f6051d65a8c1ba6f850a58 [file] [log] [blame]
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