| From e901b9873876ca30a09253731bd3a6b00c44b5b0 Mon Sep 17 00:00:00 2001 |
| From: Takashi Iwai <tiwai@suse.de> |
| Date: Wed, 4 Oct 2017 16:15:59 +0200 |
| Subject: usb: core: Add a helper function to check the validity of EP type in URB |
| |
| From: Takashi Iwai <tiwai@suse.de> |
| |
| commit e901b9873876ca30a09253731bd3a6b00c44b5b0 upstream. |
| |
| This patch adds a new helper function to perform a sanity check of the |
| given URB to see whether it contains a valid endpoint. It's a light- |
| weight version of what usb_submit_urb() does, but without the kernel |
| warning followed by the stack trace, just returns an error code. |
| |
| Especially for a driver that doesn't parse the descriptor but fills |
| the URB with the fixed endpoint (e.g. some quirks for non-compliant |
| devices), this kind of check is preferable at the probe phase before |
| actually submitting the urb. |
| |
| Tested-by: Andrey Konovalov <andreyknvl@google.com> |
| Acked-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> |
| Signed-off-by: Takashi Iwai <tiwai@suse.de> |
| Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> |
| |
| --- |
| drivers/usb/core/urb.c | 30 ++++++++++++++++++++++++++---- |
| include/linux/usb.h | 2 ++ |
| 2 files changed, 28 insertions(+), 4 deletions(-) |
| |
| --- a/drivers/usb/core/urb.c |
| +++ b/drivers/usb/core/urb.c |
| @@ -183,6 +183,31 @@ EXPORT_SYMBOL_GPL(usb_unanchor_urb); |
| |
| /*-------------------------------------------------------------------*/ |
| |
| +static const int pipetypes[4] = { |
| + PIPE_CONTROL, PIPE_ISOCHRONOUS, PIPE_BULK, PIPE_INTERRUPT |
| +}; |
| + |
| +/** |
| + * usb_urb_ep_type_check - sanity check of endpoint in the given urb |
| + * @urb: urb to be checked |
| + * |
| + * This performs a light-weight sanity check for the endpoint in the |
| + * given urb. It returns 0 if the urb contains a valid endpoint, otherwise |
| + * a negative error code. |
| + */ |
| +int usb_urb_ep_type_check(const struct urb *urb) |
| +{ |
| + const struct usb_host_endpoint *ep; |
| + |
| + ep = usb_pipe_endpoint(urb->dev, urb->pipe); |
| + if (!ep) |
| + return -EINVAL; |
| + if (usb_pipetype(urb->pipe) != pipetypes[usb_endpoint_type(&ep->desc)]) |
| + return -EINVAL; |
| + return 0; |
| +} |
| +EXPORT_SYMBOL_GPL(usb_urb_ep_type_check); |
| + |
| /** |
| * usb_submit_urb - issue an asynchronous transfer request for an endpoint |
| * @urb: pointer to the urb describing the request |
| @@ -322,9 +347,6 @@ EXPORT_SYMBOL_GPL(usb_unanchor_urb); |
| */ |
| int usb_submit_urb(struct urb *urb, gfp_t mem_flags) |
| { |
| - static int pipetypes[4] = { |
| - PIPE_CONTROL, PIPE_ISOCHRONOUS, PIPE_BULK, PIPE_INTERRUPT |
| - }; |
| int xfertype, max; |
| struct usb_device *dev; |
| struct usb_host_endpoint *ep; |
| @@ -443,7 +465,7 @@ int usb_submit_urb(struct urb *urb, gfp_ |
| */ |
| |
| /* Check that the pipe's type matches the endpoint's type */ |
| - if (usb_pipetype(urb->pipe) != pipetypes[xfertype]) |
| + if (usb_urb_ep_type_check(urb)) |
| dev_WARN(&dev->dev, "BOGUS urb xfer, pipe %x != type %x\n", |
| usb_pipetype(urb->pipe), pipetypes[xfertype]); |
| |
| --- a/include/linux/usb.h |
| +++ b/include/linux/usb.h |
| @@ -1655,6 +1655,8 @@ static inline int usb_urb_dir_out(struct |
| return (urb->transfer_flags & URB_DIR_MASK) == URB_DIR_OUT; |
| } |
| |
| +int usb_urb_ep_type_check(const struct urb *urb); |
| + |
| void *usb_alloc_coherent(struct usb_device *dev, size_t size, |
| gfp_t mem_flags, dma_addr_t *dma); |
| void usb_free_coherent(struct usb_device *dev, size_t size, |