diff options
author | Pete Batard <pete@akeo.ie> | 2013-03-17 22:13:53 +0000 |
---|---|---|
committer | Pete Batard <pete@akeo.ie> | 2013-04-02 19:13:47 +0100 |
commit | e0628c566a3fb928baab9e4359760cdc5afe5e95 (patch) | |
tree | a3848aefed49a67f85ee9640ac7746f81f962b16 | |
parent | f00edf639d3c1272744ab37f07f96fea5246976d (diff) | |
download | libusb-e0628c566a3fb928baab9e4359760cdc5afe5e95.tar.gz |
Core: Add HID and kernel detach capability detection for all backends
* Also remove Linux special case from xusb sample.
* Note that LIBUSBX_API_VERSION is incremented as a result of
libusb_has_capability() returning nonzero rather than 1 when
a capability is supported.
* A LIBUSB_CAP_HAS_HOTPLUG is also added, though it is currently
not implemented on any platform
* Closes #102
-rw-r--r-- | examples/xusb.c | 25 | ||||
-rw-r--r-- | libusb/core.c | 8 | ||||
-rw-r--r-- | libusb/libusb.h | 14 | ||||
-rw-r--r-- | libusb/libusbi.h | 9 | ||||
-rw-r--r-- | libusb/os/darwin_usb.c | 1 | ||||
-rw-r--r-- | libusb/os/linux_usbfs.c | 1 | ||||
-rw-r--r-- | libusb/os/openbsd_usb.c | 1 | ||||
-rw-r--r-- | libusb/os/wince_usb.c | 1 | ||||
-rw-r--r-- | libusb/os/windows_usb.c | 1 | ||||
-rw-r--r-- | libusb/version_nano.h | 2 |
10 files changed, 44 insertions, 19 deletions
diff --git a/examples/xusb.c b/examples/xusb.c index 463cc2f..856f723 100644 --- a/examples/xusb.c +++ b/examples/xusb.c @@ -735,10 +735,8 @@ static int test_device(uint16_t vid, uint16_t pid) const struct libusb_endpoint_descriptor *endpoint; int i, j, k, r; int iface, nb_ifaces, first_iface = -1; -#if defined(__linux__) - // Attaching/detaching the kernel driver is only relevant for Linux + // For attaching/detaching the kernel driver, if needed int iface_detached = -1; -#endif struct libusb_device_descriptor dev_desc; const char* speed_name[5] = { "Unknown", "1.5 Mbit/s (USB LowSpeed)", "12 Mbit/s (USB FullSpeed)", "480 Mbit/s (USB HighSpeed)", "5000 Mbit/s (USB SuperSpeed)"}; @@ -833,16 +831,17 @@ static int test_device(uint16_t vid, uint16_t pid) { printf("\nClaiming interface %d...\n", iface); r = libusb_claim_interface(handle, iface); -#if defined(__linux__) - if ((r != LIBUSB_SUCCESS) && (iface == 0)) { - // Maybe we need to detach the driver - perr(" Failed. Trying to detach driver...\n"); - libusb_detach_kernel_driver(handle, iface); - iface_detached = iface; - printf(" Claiming interface again...\n"); - r = libusb_claim_interface(handle, iface); + if ((r != LIBUSB_SUCCESS) && libusb_has_capability(LIBUSB_CAP_SUPPORTS_DETACH_KERNEL_DRIVER) + && (libusb_kernel_driver_active(handle, iface) > 0)) { + // Try to detach the kernel driver + perr(" A kernel driver is active, trying to detach it...\n"); + r = libusb_detach_kernel_driver(handle, iface); + if (r == LIBUSB_SUCCESS) { + iface_detached = iface; + printf(" Claiming interface again...\n"); + r = libusb_claim_interface(handle, iface); + } } -#endif if (r != LIBUSB_SUCCESS) { perr(" Failed.\n"); } @@ -891,12 +890,10 @@ static int test_device(uint16_t vid, uint16_t pid) libusb_release_interface(handle, iface); } -#if defined(__linux__) if (iface_detached >= 0) { printf("Re-attaching kernel driver...\n"); libusb_attach_kernel_driver(handle, iface_detached); } -#endif printf("Closing device...\n"); libusb_close(handle); diff --git a/libusb/core.c b/libusb/core.c index b3df73a..e2da1ea 100644 --- a/libusb/core.c +++ b/libusb/core.c @@ -1740,15 +1740,21 @@ void API_EXPORTED libusb_exit(struct libusb_context *ctx) /** \ingroup misc * Check at runtime if the loaded library has a given capability. + * This call should be performed after \ref libusb_init(), to ensure the + * backend has updated its capability set. * * \param capability the \ref libusb_capability to check for - * \returns 1 if the running library has the capability, 0 otherwise + * \returns nonzero if the running library has the capability, 0 otherwise */ int API_EXPORTED libusb_has_capability(uint32_t capability) { switch (capability) { case LIBUSB_CAP_HAS_CAPABILITY: return 1; + case LIBUSB_CAP_HAS_HID_ACCESS: + return (usbi_backend->caps && USBI_CAP_HAS_HID_ACCESS); + case LIBUSB_CAP_SUPPORTS_DETACH_KERNEL_DRIVER: + return (usbi_backend->caps && USBI_CAP_SUPPORTS_DETACH_KERNEL_DRIVER); } return 0; } diff --git a/libusb/libusb.h b/libusb/libusb.h index d7e84c0..3613864 100644 --- a/libusb/libusb.h +++ b/libusb/libusb.h @@ -136,7 +136,7 @@ typedef unsigned __int32 uint32_t; * Internally, LIBUSBX_API_VERSION is defined as follows: * (libusbx major << 24) | (libusbx minor << 16) | (16 bit incremental) */ -#define LIBUSBX_API_VERSION 0x010000FF +#define LIBUSBX_API_VERSION 0x01000101 #ifdef __cplusplus extern "C" { @@ -994,7 +994,17 @@ struct libusb_transfer { */ enum libusb_capability { /** The libusb_has_capability() API is available. */ - LIBUSB_CAP_HAS_CAPABILITY = 0, + LIBUSB_CAP_HAS_CAPABILITY = 0x0000, + /** Hotplug support is available. */ + LIBUSB_CAP_HAS_HOTPLUG = 0x0001, + /** The library can access HID devices without requiring user intervention. + * Note that before being able to actually access an HID device, you may + * still have to call additional libusbx functions such as + * \ref libusb_detach_kernel_driver(). */ + LIBUSB_CAP_HAS_HID_ACCESS = 0x0100, + /** The library supports detaching of the default USB driver, using + * \ref libusb_detach_kernel_driver(), if one is set by the OS kernel */ + LIBUSB_CAP_SUPPORTS_DETACH_KERNEL_DRIVER = 0x0101 }; /** \ingroup lib diff --git a/libusb/libusbi.h b/libusb/libusbi.h index eed549e..ed95d43 100644 --- a/libusb/libusbi.h +++ b/libusb/libusbi.h @@ -52,8 +52,12 @@ #define USB_MAXINTERFACES 32 #define USB_MAXCONFIG 8 +/* Backend specific capabilities */ +#define USBI_CAP_HAS_HID_ACCESS 0x00010000 +#define USBI_CAP_SUPPORTS_DETACH_KERNEL_DRIVER 0x00020000 + /* The following is used to silence warnings for unused variables */ -#define UNUSED(var) (void)(var) +#define UNUSED(var) do { (void)(var); } while(0) struct list_head { struct list_head *prev, *next; @@ -446,6 +450,9 @@ struct usbi_os_backend { /* A human-readable name for your backend, e.g. "Linux usbfs" */ const char *name; + /* Binary mask for backend specific capabilities */ + uint32_t caps; + /* Perform initialization of your backend. You might use this function * to determine specific capabilities of the system, allocate required * data structures for later, etc. diff --git a/libusb/os/darwin_usb.c b/libusb/os/darwin_usb.c index 08bd7f0..30ee3ff 100644 --- a/libusb/os/darwin_usb.c +++ b/libusb/os/darwin_usb.c @@ -1782,6 +1782,7 @@ static int darwin_clock_gettime(int clk_id, struct timespec *tp) { const struct usbi_os_backend darwin_backend = { .name = "Darwin", + .caps = 0, .init = darwin_init, .exit = darwin_exit, .get_device_list = darwin_get_device_list, diff --git a/libusb/os/linux_usbfs.c b/libusb/os/linux_usbfs.c index 99bbd07..95e5339 100644 --- a/libusb/os/linux_usbfs.c +++ b/libusb/os/linux_usbfs.c @@ -2527,6 +2527,7 @@ static clockid_t op_get_timerfd_clockid(void) const struct usbi_os_backend linux_usbfs_backend = { .name = "Linux usbfs", + .caps = USBI_CAP_HAS_HID_ACCESS|USBI_CAP_SUPPORTS_DETACH_KERNEL_DRIVER, .init = op_init, .exit = NULL, .get_device_list = op_get_device_list, diff --git a/libusb/os/openbsd_usb.c b/libusb/os/openbsd_usb.c index 88e2c7a..353385b 100644 --- a/libusb/os/openbsd_usb.c +++ b/libusb/os/openbsd_usb.c @@ -89,6 +89,7 @@ static int _access_endpoint(struct libusb_transfer *); const struct usbi_os_backend openbsd_backend = { "Synchronous OpenBSD backend", + 0, NULL, /* init() */ NULL, /* exit() */ obsd_get_device_list, diff --git a/libusb/os/wince_usb.c b/libusb/os/wince_usb.c index 354c0e6..e4f7c7b 100644 --- a/libusb/os/wince_usb.c +++ b/libusb/os/wince_usb.c @@ -973,6 +973,7 @@ static int wince_clock_gettime(int clk_id, struct timespec *tp) const struct usbi_os_backend wince_backend = { "Windows CE", + 0, wince_init, wince_exit, diff --git a/libusb/os/windows_usb.c b/libusb/os/windows_usb.c index 1eb81b4..7c2428d 100644 --- a/libusb/os/windows_usb.c +++ b/libusb/os/windows_usb.c @@ -2262,6 +2262,7 @@ static int windows_clock_gettime(int clk_id, struct timespec *tp) // NB: MSVC6 does not support named initializers. const struct usbi_os_backend windows_backend = { "Windows", + USBI_CAP_HAS_HID_ACCESS, windows_init, windows_exit, diff --git a/libusb/version_nano.h b/libusb/version_nano.h index 5a977a3..26d7735 100644 --- a/libusb/version_nano.h +++ b/libusb/version_nano.h @@ -1 +1 @@ -#define LIBUSB_NANO 10633 +#define LIBUSB_NANO 10634 |