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, |