Signed-off-by: Hans de Goede <hdego...@redhat.com>
---
 libusb/os/linux_usbfs.c | 28 ++++++++++++++++++++++++++++
 libusb/os/linux_usbfs.h | 10 ++++++++++
 2 files changed, 38 insertions(+)

diff --git a/libusb/os/linux_usbfs.c b/libusb/os/linux_usbfs.c
index b6194ce..9cadca0 100644
--- a/libusb/os/linux_usbfs.c
+++ b/libusb/os/linux_usbfs.c
@@ -1604,9 +1604,37 @@ static int op_detach_kernel_driver_and_claim(
        const char *driver_name)
 {
        int fd = _device_handle_priv(handle)->fd;
+       struct usbfs_disconnect_claim dc;
        struct usbfs_getdriver getdrv;
        int r;
 
+       dc.interface = interface;
+       if (driver_name) {
+               snprintf(dc.driver, sizeof(dc.driver), "%s", driver_name);
+               dc.flags = USBFS_DISCONNECT_CLAIM_IF_DRIVER;
+       } else {
+               snprintf(dc.driver, sizeof(dc.driver), "usbfs");
+               dc.flags = USBFS_DISCONNECT_CLAIM_EXCEPT_DRIVER;
+       }
+       r = ioctl(fd, IOCTL_USBFS_DISCONNECT_CLAIM, &dc);
+       if (r == 0 || (r != 0 && errno != ENOTTY)) {
+               if (r == 0)
+                       return 0;
+               switch (errno) {
+               case EBUSY:
+                       return LIBUSB_ERROR_BUSY;
+               case EINVAL:
+                       return LIBUSB_ERROR_INVALID_PARAM;
+               case ENODEV:
+                       return LIBUSB_ERROR_NO_DEVICE;
+               }
+
+               usbi_err(HANDLE_CTX(handle),
+                       "disconnect-and-claim failed errno %d", errno);
+               return LIBUSB_ERROR_OTHER;
+       }
+
+       /* Fallback code for kernels which don't support the dc ioctl */
        if (driver_name) {
                getdrv.interface = interface;
                r = ioctl(fd, IOCTL_USBFS_GETDRIVER, &getdrv);
diff --git a/libusb/os/linux_usbfs.h b/libusb/os/linux_usbfs.h
index 593e736..3ee80ff 100644
--- a/libusb/os/linux_usbfs.h
+++ b/libusb/os/linux_usbfs.h
@@ -123,6 +123,15 @@ struct usbfs_hub_portinfo {
 #define USBFS_CAP_NO_PACKET_SIZE_LIM   0x04
 #define USBFS_CAP_BULK_SCATTER_GATHER  0x08
 
+#define USBFS_DISCONNECT_CLAIM_IF_DRIVER       0x01
+#define USBFS_DISCONNECT_CLAIM_EXCEPT_DRIVER   0x02
+
+struct usbfs_disconnect_claim {
+       unsigned int interface;
+       unsigned int flags;
+       char driver[USBFS_MAXDRIVERNAME + 1];
+};
+
 #define IOCTL_USBFS_CONTROL    _IOWR('U', 0, struct usbfs_ctrltransfer)
 #define IOCTL_USBFS_BULK               _IOWR('U', 2, struct usbfs_bulktransfer)
 #define IOCTL_USBFS_RESETEP    _IOR('U', 3, unsigned int)
@@ -145,5 +154,6 @@ struct usbfs_hub_portinfo {
 #define IOCTL_USBFS_CLAIM_PORT _IOR('U', 24, unsigned int)
 #define IOCTL_USBFS_RELEASE_PORT       _IOR('U', 25, unsigned int)
 #define IOCTL_USBFS_GET_CAPABILITIES   _IOR('U', 26, __u32)
+#define IOCTL_USBFS_DISCONNECT_CLAIM   _IOR('U', 27, struct 
usbfs_disconnect_claim)
 
 #endif
-- 
1.7.11.4


------------------------------------------------------------------------------
Live Security Virtual Conference
Exclusive live event will cover all the ways today's security and 
threat landscape has changed and how IT managers can respond. Discussions 
will include endpoint security, mobile security and the latest in malware 
threats. http://www.accelacomm.com/jaw/sfrnl04242012/114/50122263/
_______________________________________________
libusbx-devel mailing list
libusbx-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/libusbx-devel

Reply via email to