Ticket #42 (closed defect: fixed)
Opened 3 years ago
Last modified 13 months ago
Error return code of usb_detach_kernel_driver_np()
| Reported by: | xiaofan | Owned by: | sbrabec |
|---|---|---|---|
| Milestone: | Component: | libusb-compat-0.1 | |
| Keywords: | errorno | Cc: | sbrabec@… |
| Blocked By: | Blocks: |
Description
For usb_detach_kernel_driver_np(), the compat layer will return ENOENT (for LIBUSB_ERROR_NOT_FOUND) instead of ENODATA which is the value returned by libusb-0.1.
From libusb-1.0 (linux_usbfs.c)
static int op_detach_kernel_driver(struct libusb_device_handle *handle,
int interface)
{
int fd = device_handle_priv(handle)->fd;
struct usbfs_ioctl command;
int r;
command.ifno = interface;
command.ioctl_code = IOCTL_USBFS_DISCONNECT;
command.data = NULL;
r = ioctl(fd, IOCTL_USBFS_IOCTL, &command);
if (r) {
if (errno == ENODATA)
return LIBUSB_ERROR_NOT_FOUND;
else if (errno == EINVAL)
return LIBUSB_ERROR_INVALID_PARAM;
else if (errno == ENODEV)
return LIBUSB_ERROR_NO_DEVICE;
usbi_err(HANDLE_CTX(handle),
"detach failed error %d errno %d", r, errno);
return LIBUSB_ERROR_OTHER;
}
return 0;
}
From original libusb-0.1: it is similar to libusb-1.0, so it
can return ENODATA, EINVAL and ENODEV.
int usb_detach_kernel_driver_np(usb_dev_handle *dev, int interface)
{
struct usb_ioctl command;
int ret;
command.ifno = interface;
command.ioctl_code = IOCTL_USB_DISCONNECT;
command.data = NULL;
ret = ioctl(dev->fd, IOCTL_USB_IOCTL, &command);
if (ret)
USB_ERROR_STR(-errno, "could not detach kernel driver from
interface %d: %s",
interface, strerror(errno));
return 0;
}
From libusb-0.1-compat:
static int libusb_to_errno(int result)
{
switch (result) {
case LIBUSB_SUCCESS:
return 0;
case LIBUSB_ERROR_IO:
return EIO;
case LIBUSB_ERROR_INVALID_PARAM:
return EINVAL;
case LIBUSB_ERROR_ACCESS:
return EACCES;
case LIBUSB_ERROR_NO_DEVICE:
return ENXIO;
case LIBUSB_ERROR_NOT_FOUND:
return ENOENT;
case LIBUSB_ERROR_BUSY:
return EBUSY;
case LIBUSB_ERROR_TIMEOUT:
return ETIMEDOUT;
case LIBUSB_ERROR_OVERFLOW:
return EOVERFLOW;
case LIBUSB_ERROR_PIPE:
return EPIPE;
case LIBUSB_ERROR_INTERRUPTED:
return EINTR;
case LIBUSB_ERROR_NO_MEM:
return ENOMEM;
case LIBUSB_ERROR_NOT_SUPPORTED:
return ENOSYS;
default:
return ERANGE;
}
}
API_EXPORTED int usb_detach_kernel_driver_np(usb_dev_handle *dev, int interface)
{
return compat_err(libusb_detach_kernel_driver(dev->handle, interface));
}
Attachments
Change History
Changed 17 months ago by sbrabec
comment:1 Changed 17 months ago by sbrabec
- Cc sbrabec@… added
Proposed patch converts libusb1 errors to libusb0 errors. But maybe it is overcomplicated. If we accept that the function was implemented only in Linux (and the same is valid for libusb0), we can just simply return original errno instead of double conversion of errno to libusb1 error code and back to errno.
As an alternative, we can check only for -ENODATA condition as libusb-compat does in usb_get_driver_np().
The affected software:
lirc-0.8.7/daemons/hw_srm7500libusb.c: srm7500_initialize_usbdongle()
The function continues if usb_detach_kernel_driver_np() finishes with no error or if it returns -ENODATA. But the compat layer returns -ENOENT and the driver considers this error as fatal.
I am waiting for confirmation of the fix.
Downstream bug reference:
https://bugzilla.novell.com/show_bug.cgi?id=683307
Mailing list reference:
https://sourceforge.net/mailarchive/forum.php?thread_name=1325706952.5095.49.camel%40oct.suse.cz&forum_name=libusb-devel
comment:2 Changed 13 months ago by sbrabec
- Owner set to sbrabec
- Resolution set to fixed
- Status changed from new to closed
libusb-compat-usb_detach_kernel_driver_np-error.patch