diff options
| author | Takashi Iwai <tiwai@suse.de> | 2017-10-04 10:15:59 -0400 |
|---|---|---|
| committer | Takashi Iwai <tiwai@suse.de> | 2017-10-11 09:14:32 -0400 |
| commit | e901b9873876ca30a09253731bd3a6b00c44b5b0 (patch) | |
| tree | 9d9c10973fdf8162552f9428eec373137f44f353 | |
| parent | 8a5776a5f49812d29fe4b2d0a2d71675c3facf3f (diff) | |
usb: core: Add a helper function to check the validity of EP type in URB
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>
| -rw-r--r-- | drivers/usb/core/urb.c | 30 | ||||
| -rw-r--r-- | include/linux/usb.h | 2 |
2 files changed, 28 insertions, 4 deletions
diff --git a/drivers/usb/core/urb.c b/drivers/usb/core/urb.c index 47903d510955..8b800e34407b 100644 --- a/drivers/usb/core/urb.c +++ b/drivers/usb/core/urb.c | |||
| @@ -187,6 +187,31 @@ EXPORT_SYMBOL_GPL(usb_unanchor_urb); | |||
| 187 | 187 | ||
| 188 | /*-------------------------------------------------------------------*/ | 188 | /*-------------------------------------------------------------------*/ |
| 189 | 189 | ||
| 190 | static const int pipetypes[4] = { | ||
| 191 | PIPE_CONTROL, PIPE_ISOCHRONOUS, PIPE_BULK, PIPE_INTERRUPT | ||
| 192 | }; | ||
| 193 | |||
| 194 | /** | ||
| 195 | * usb_urb_ep_type_check - sanity check of endpoint in the given urb | ||
| 196 | * @urb: urb to be checked | ||
| 197 | * | ||
| 198 | * This performs a light-weight sanity check for the endpoint in the | ||
| 199 | * given urb. It returns 0 if the urb contains a valid endpoint, otherwise | ||
| 200 | * a negative error code. | ||
| 201 | */ | ||
| 202 | int usb_urb_ep_type_check(const struct urb *urb) | ||
| 203 | { | ||
| 204 | const struct usb_host_endpoint *ep; | ||
| 205 | |||
| 206 | ep = usb_pipe_endpoint(urb->dev, urb->pipe); | ||
| 207 | if (!ep) | ||
| 208 | return -EINVAL; | ||
| 209 | if (usb_pipetype(urb->pipe) != pipetypes[usb_endpoint_type(&ep->desc)]) | ||
| 210 | return -EINVAL; | ||
| 211 | return 0; | ||
| 212 | } | ||
| 213 | EXPORT_SYMBOL_GPL(usb_urb_ep_type_check); | ||
| 214 | |||
| 190 | /** | 215 | /** |
| 191 | * usb_submit_urb - issue an asynchronous transfer request for an endpoint | 216 | * usb_submit_urb - issue an asynchronous transfer request for an endpoint |
| 192 | * @urb: pointer to the urb describing the request | 217 | * @urb: pointer to the urb describing the request |
| @@ -326,9 +351,6 @@ EXPORT_SYMBOL_GPL(usb_unanchor_urb); | |||
| 326 | */ | 351 | */ |
| 327 | int usb_submit_urb(struct urb *urb, gfp_t mem_flags) | 352 | int usb_submit_urb(struct urb *urb, gfp_t mem_flags) |
| 328 | { | 353 | { |
| 329 | static int pipetypes[4] = { | ||
| 330 | PIPE_CONTROL, PIPE_ISOCHRONOUS, PIPE_BULK, PIPE_INTERRUPT | ||
| 331 | }; | ||
| 332 | int xfertype, max; | 354 | int xfertype, max; |
| 333 | struct usb_device *dev; | 355 | struct usb_device *dev; |
| 334 | struct usb_host_endpoint *ep; | 356 | struct usb_host_endpoint *ep; |
| @@ -444,7 +466,7 @@ int usb_submit_urb(struct urb *urb, gfp_t mem_flags) | |||
| 444 | */ | 466 | */ |
| 445 | 467 | ||
| 446 | /* Check that the pipe's type matches the endpoint's type */ | 468 | /* Check that the pipe's type matches the endpoint's type */ |
| 447 | if (usb_pipetype(urb->pipe) != pipetypes[xfertype]) | 469 | if (usb_urb_ep_type_check(urb)) |
| 448 | dev_WARN(&dev->dev, "BOGUS urb xfer, pipe %x != type %x\n", | 470 | dev_WARN(&dev->dev, "BOGUS urb xfer, pipe %x != type %x\n", |
| 449 | usb_pipetype(urb->pipe), pipetypes[xfertype]); | 471 | usb_pipetype(urb->pipe), pipetypes[xfertype]); |
| 450 | 472 | ||
diff --git a/include/linux/usb.h b/include/linux/usb.h index cb9fbd54386e..2b861804fffa 100644 --- a/include/linux/usb.h +++ b/include/linux/usb.h | |||
| @@ -1728,6 +1728,8 @@ static inline int usb_urb_dir_out(struct urb *urb) | |||
| 1728 | return (urb->transfer_flags & URB_DIR_MASK) == URB_DIR_OUT; | 1728 | return (urb->transfer_flags & URB_DIR_MASK) == URB_DIR_OUT; |
| 1729 | } | 1729 | } |
| 1730 | 1730 | ||
| 1731 | int usb_urb_ep_type_check(const struct urb *urb); | ||
| 1732 | |||
| 1731 | void *usb_alloc_coherent(struct usb_device *dev, size_t size, | 1733 | void *usb_alloc_coherent(struct usb_device *dev, size_t size, |
| 1732 | gfp_t mem_flags, dma_addr_t *dma); | 1734 | gfp_t mem_flags, dma_addr_t *dma); |
| 1733 | void usb_free_coherent(struct usb_device *dev, size_t size, | 1735 | void usb_free_coherent(struct usb_device *dev, size_t size, |
