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