core: Add libusb_wrap_sys_device() API
authorVianney le Clément de Saint-Marcq <code@quartic.eu>
Tue, 13 Dec 2016 14:45:56 +0000 (15:45 +0100)
committerNathan Hjelm <hjelmn@me.com>
Wed, 9 Jan 2019 01:20:28 +0000 (18:20 -0700)
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>
libusb/core.c
libusb/libusb.h
libusb/libusbi.h
libusb/version_nano.h

index 8cb598d..f839b6a 100644 (file)
@@ -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.
  *
index a81209a..1229827 100644 (file)
@@ -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);
index 874505d..c2ec479 100644 (file)
@@ -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.
index a5d62c5..5ce1440 100644 (file)
@@ -1 +1 @@
-#define LIBUSB_NANO 11335
+#define LIBUSB_NANO 11336