static int detach_kernel_driver_and_claim(struct libusb_device_handle *handle,
int interface)
{
- int r;
+ struct usbfs_disconnect_claim dc;
+ int r, fd = _device_handle_priv(handle)->fd;
+
+ dc.interface = interface;
+ strcpy(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
+ disconnect-and-claim ioctl */
r = op_detach_kernel_driver(handle, interface);
if (r != 0 && r != LIBUSB_ERROR_NOT_FOUND)
return r;
#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)
#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)
extern usbi_mutex_static_t linux_hotplug_lock;
-#define LIBUSB_NANO 10742
+#define LIBUSB_NANO 10743