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

libusb-compat-usb_detach_kernel_driver_np-error.patch (639 bytes) - added by sbrabec 17 months ago.
libusb-compat-usb_detach_kernel_driver_np-error.patch

Download all attachments as: .zip

Change History

Changed 17 months ago by sbrabec

libusb-compat-usb_detach_kernel_driver_np-error.patch

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

In 983fabd544ca9879d8901f05e286a674db97070e/libusb-compat-0.1:

Fix #42 usb_detach_kernel_driver_np() error mapping

usb_detach_kernel_driver_np() from libusb-compat-0.1 returns different
error messages than the old libusb-0.1. It causes problems for drivers
that expect exact error code.

Convert libusb-1.0 errors back to libusb-0.1 errors to get 1:1 mapping
of kernel error codes.

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 libusb-compat-0.1 used to
return -ENOENT and the driver considers this error as fatal.

Upstream bug reference:
http://libusb.org/ticket/42
Upstream mailing list reference:
http://marc.info/?m=133355454809642
Downstream bug reference:
https://bugzilla.novell.com/show_bug.cgi?id=683307

Note: See TracTickets for help on using tickets.