diff options
author | Vianney le Clément de Saint-Marcq <code@quartic.eu> | 2016-12-13 15:45:56 +0100 |
---|---|---|
committer | Nathan Hjelm <hjelmn@me.com> | 2019-01-08 18:20:28 -0700 |
commit | 7332286ecc5830178d98cd5bf240a926cd46c1d1 (patch) | |
tree | ceda6a4b3ade9b2e1b87fe237877845365a15ab7 | |
parent | 86de6b7127bddf15daec778b271b051221745ff4 (diff) | |
download | libusb-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.c | 72 | ||||
-rw-r--r-- | libusb/libusb.h | 1 | ||||
-rw-r--r-- | libusb/libusbi.h | 28 | ||||
-rw-r--r-- | libusb/version_nano.h | 2 |
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 |