summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorVianney le Clément de Saint-Marcq <code@quartic.eu>2016-12-13 15:45:56 +0100
committerNathan Hjelm <hjelmn@me.com>2019-01-08 18:20:28 -0700
commit7332286ecc5830178d98cd5bf240a926cd46c1d1 (patch)
treeceda6a4b3ade9b2e1b87fe237877845365a15ab7
parent86de6b7127bddf15daec778b271b051221745ff4 (diff)
downloadlibusb-7332286ecc5830178d98cd5bf240a926cd46c1d1.tar.gz
core: Add libusb_wrap_sys_device() API
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>
-rw-r--r--libusb/core.c72
-rw-r--r--libusb/libusb.h1
-rw-r--r--libusb/libusbi.h28
-rw-r--r--libusb/version_nano.h2
4 files changed, 102 insertions, 1 deletions
diff --git a/libusb/core.c b/libusb/core.c
index 8cb598d..f839b6a 100644
--- a/libusb/core.c
+++ b/libusb/core.c
@@ -1216,6 +1216,78 @@ int usbi_clear_event(struct libusb_context *ctx)
}
/** \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 a81209a..1229827 100644
--- a/libusb/libusb.h
+++ b/libusb/libusb.h
@@ -1387,6 +1387,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 874505d..c2ec479 100644
--- a/libusb/libusbi.h
+++ b/libusb/libusbi.h
@@ -712,6 +712,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.
diff --git a/libusb/version_nano.h b/libusb/version_nano.h
index a5d62c5..5ce1440 100644
--- a/libusb/version_nano.h
+++ b/libusb/version_nano.h
@@ -1 +1 @@
-#define LIBUSB_NANO 11335
+#define LIBUSB_NANO 11336