mirror of
https://github.com/freebsd/freebsd-src.git
synced 2026-11-07 04:36:52 -10:00
usb: preserve error when doing request
Currently, USB request not distinguished different error and always return EIO. However, some error are recoverable or ignorable in userspace. Therefore, we preserve the meaning of different error to userspace then allow userspace to decide how to use the return error. Reviewed by: adrian Sponsored by: The FreeBSD Foundation Differential Revision: https://reviews.freebsd.org/D52244
This commit is contained in:
1 parent
3fbffbcbec
commit
2cf2d95563
3 files changed
+127
-11
No files matched your search
@@ -28,6 +28,7 @@
|
||||
#ifdef LIBUSB_GLOBAL_INCLUDE_FILE
|
||||
#include LIBUSB_GLOBAL_INCLUDE_FILE
|
||||
#else
|
||||
#include <assert.h>
|
||||
#include <errno.h>
|
||||
#include <poll.h>
|
||||
#include <pthread.h>
|
||||
@@ -472,6 +473,44 @@ done:
|
||||
|
||||
/* Synchronous device I/O */
|
||||
|
||||
static int
|
||||
libusb10_convert_libusb20_error(int err)
|
||||
{
|
||||
/* LIBUSB20_ERROR_* values are always non-positive */
|
||||
assert(err <= 0);
|
||||
|
||||
switch (err) {
|
||||
case LIBUSB20_SUCCESS:
|
||||
return (0);
|
||||
case LIBUSB20_ERROR_IO:
|
||||
return (LIBUSB_ERROR_IO);
|
||||
case LIBUSB20_ERROR_INVALID_PARAM:
|
||||
return (LIBUSB_ERROR_INVALID_PARAM);
|
||||
case LIBUSB20_ERROR_ACCESS:
|
||||
return (LIBUSB_ERROR_ACCESS);
|
||||
case LIBUSB20_ERROR_NO_DEVICE:
|
||||
return (LIBUSB_ERROR_NO_DEVICE);
|
||||
case LIBUSB20_ERROR_NOT_FOUND:
|
||||
return (LIBUSB_ERROR_NOT_FOUND);
|
||||
case LIBUSB20_ERROR_BUSY:
|
||||
return (LIBUSB_ERROR_BUSY);
|
||||
case LIBUSB20_ERROR_TIMEOUT:
|
||||
return (LIBUSB_ERROR_TIMEOUT);
|
||||
case LIBUSB20_ERROR_OVERFLOW:
|
||||
return (LIBUSB_ERROR_OVERFLOW);
|
||||
case LIBUSB20_ERROR_PIPE:
|
||||
return (LIBUSB_ERROR_PIPE);
|
||||
case LIBUSB20_ERROR_INTERRUPTED:
|
||||
return (LIBUSB_ERROR_INTERRUPTED);
|
||||
case LIBUSB20_ERROR_NO_MEM:
|
||||
return (LIBUSB_ERROR_NO_MEM);
|
||||
case LIBUSB20_ERROR_NOT_SUPPORTED:
|
||||
return (LIBUSB_ERROR_NOT_SUPPORTED);
|
||||
default:
|
||||
return (LIBUSB_ERROR_OTHER);
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
libusb_control_transfer(libusb_device_handle *devh,
|
||||
uint8_t bmRequestType, uint8_t bRequest, uint16_t wValue, uint16_t wIndex,
|
||||
@@ -498,12 +537,8 @@ libusb_control_transfer(libusb_device_handle *devh,
|
||||
err = libusb20_dev_request_sync(devh, &req, data,
|
||||
&actlen, timeout, 0);
|
||||
|
||||
if (err == LIBUSB20_ERROR_PIPE)
|
||||
return (LIBUSB_ERROR_PIPE);
|
||||
else if (err == LIBUSB20_ERROR_TIMEOUT)
|
||||
return (LIBUSB_ERROR_TIMEOUT);
|
||||
else if (err)
|
||||
return (LIBUSB_ERROR_NO_DEVICE);
|
||||
if (err)
|
||||
return (libusb10_convert_libusb20_error(err));
|
||||
|
||||
return (actlen);
|
||||
}
|
||||
|
||||
@@ -97,6 +97,49 @@ static const struct libusb20_device_methods libusb20_ugen20_device_methods = {
|
||||
LIBUSB20_DEVICE(LIBUSB20_DECLARE, ugen20)
|
||||
};
|
||||
|
||||
static int
|
||||
errno_to_libusb_error(int uerr)
|
||||
{
|
||||
switch (uerr) {
|
||||
case 0:
|
||||
return (LIBUSB20_SUCCESS);
|
||||
case EIO:
|
||||
case ERANGE:
|
||||
return (LIBUSB20_ERROR_IO);
|
||||
case EINVAL:
|
||||
case EFAULT:
|
||||
case ENOBUFS:
|
||||
return (LIBUSB20_ERROR_INVALID_PARAM);
|
||||
case EACCES:
|
||||
case EPERM:
|
||||
return (LIBUSB20_ERROR_ACCESS);
|
||||
case ENXIO:
|
||||
case ENODEV:
|
||||
return (LIBUSB20_ERROR_NO_DEVICE);
|
||||
case ENOENT:
|
||||
return (LIBUSB20_ERROR_NOT_FOUND);
|
||||
case EBUSY:
|
||||
case EALREADY:
|
||||
case EADDRINUSE:
|
||||
return (LIBUSB20_ERROR_BUSY);
|
||||
case ETIMEDOUT:
|
||||
return (LIBUSB20_ERROR_TIMEOUT);
|
||||
case EMSGSIZE:
|
||||
return (LIBUSB20_ERROR_OVERFLOW);
|
||||
case EPIPE:
|
||||
return (LIBUSB20_ERROR_PIPE);
|
||||
case EINTR:
|
||||
case ECANCELED:
|
||||
return (LIBUSB20_ERROR_INTERRUPTED);
|
||||
case ENOMEM:
|
||||
return (LIBUSB20_ERROR_NO_MEM);
|
||||
case ENOTSUP:
|
||||
return (LIBUSB20_ERROR_NOT_SUPPORTED);
|
||||
default:
|
||||
return (LIBUSB20_ERROR_OTHER);
|
||||
}
|
||||
}
|
||||
|
||||
static const char *
|
||||
ugen20_get_backend_name(void)
|
||||
{
|
||||
@@ -746,7 +789,7 @@ ugen20_do_request_sync(struct libusb20_device *pdev,
|
||||
/* ignore */
|
||||
}
|
||||
if (ioctl(pdev->file_ctrl, IOUSB(USB_DO_REQUEST), &req)) {
|
||||
return (LIBUSB20_ERROR_OTHER);
|
||||
return (errno_to_libusb_error(errno));
|
||||
}
|
||||
if (pactlen) {
|
||||
/* get actual length */
|
||||
|
||||
@@ -143,6 +143,38 @@ SYSCTL_INT(_hw_usb_ugen, OID_AUTO, debug, CTLFLAG_RWTUN, &ugen_debug,
|
||||
0, "Debug level");
|
||||
#endif
|
||||
|
||||
static const int usb_error_to_errno[USB_ERR_MAX] = {
|
||||
[USB_ERR_NORMAL_COMPLETION] = 0,
|
||||
[USB_ERR_PENDING_REQUESTS] = EALREADY,
|
||||
[USB_ERR_NOT_STARTED] = EINVAL,
|
||||
[USB_ERR_INVAL] = EINVAL,
|
||||
[USB_ERR_NOMEM] = ENOMEM,
|
||||
[USB_ERR_CANCELLED] = ECANCELED,
|
||||
[USB_ERR_BAD_ADDRESS] = EFAULT,
|
||||
[USB_ERR_BAD_BUFSIZE] = ENOBUFS,
|
||||
[USB_ERR_BAD_FLAG] = EINVAL,
|
||||
[USB_ERR_NO_CALLBACK] = EINVAL,
|
||||
[USB_ERR_IN_USE] = EADDRINUSE,
|
||||
[USB_ERR_NO_ADDR] = EADDRNOTAVAIL,
|
||||
[USB_ERR_NO_PIPE] = ENOENT,
|
||||
[USB_ERR_ZERO_NFRAMES] = EINVAL,
|
||||
[USB_ERR_ZERO_MAXP] = EINVAL,
|
||||
[USB_ERR_SET_ADDR_FAILED] = EADDRNOTAVAIL,
|
||||
[USB_ERR_NO_POWER] = ENXIO,
|
||||
[USB_ERR_TOO_DEEP] = EINVAL,
|
||||
[USB_ERR_IOERROR] = EIO,
|
||||
[USB_ERR_NOT_CONFIGURED] = ENXIO,
|
||||
[USB_ERR_TIMEOUT] = ETIMEDOUT,
|
||||
[USB_ERR_SHORT_XFER] = ERANGE,
|
||||
[USB_ERR_STALLED] = EPIPE,
|
||||
[USB_ERR_INTERRUPTED] = EINTR,
|
||||
[USB_ERR_DMA_LOAD_FAILED] = EIO,
|
||||
[USB_ERR_BAD_CONTEXT] = EBADMSG,
|
||||
[USB_ERR_NO_ROOT_HUB] = EINVAL,
|
||||
[USB_ERR_NO_INTR_THREAD] = EIO,
|
||||
[USB_ERR_NOT_LOCKED] = EINVAL,
|
||||
};
|
||||
|
||||
/* prototypes */
|
||||
|
||||
static int
|
||||
@@ -861,10 +893,16 @@ ugen_do_request(struct usb_fifo *f, struct usb_ctl_request *ur)
|
||||
|
||||
ur->ucr_actlen = actlen;
|
||||
|
||||
if (error) {
|
||||
error = EIO;
|
||||
}
|
||||
return (error);
|
||||
/*
|
||||
* Fall back to EIO for USB errors without a table entry, so
|
||||
* that an unmapped error cannot be reported as success.
|
||||
*/
|
||||
if (error < 0 || error >= USB_ERR_MAX ||
|
||||
(error != USB_ERR_NORMAL_COMPLETION &&
|
||||
usb_error_to_errno[error] == 0))
|
||||
return (EIO);
|
||||
|
||||
return (usb_error_to_errno[error]);
|
||||
}
|
||||
|
||||
#ifdef COMPAT_FREEBSD32
|
||||
|
||||
Reference in new issue
Block a user