From 18255750014d52bc67f4a592d19987e65e57d12d Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Fri, 17 Mar 2017 11:35:30 +0100 Subject: USB: core: add helpers to retrieve endpoints commit 66a359390e7e34f9a4c489467234b107b3d76169 upstream. Many USB drivers iterate over the available endpoints to find required endpoints of a specific type and direction. Typically the endpoints are required for proper function and a missing endpoint should abort probe. To facilitate code reuse, add a helper to retrieve common endpoints (bulk or interrupt, in or out) and four wrappers to find a single endpoint. Note that the helpers are marked as __must_check to serve as a reminder to always verify that all expected endpoints are indeed present. This also means that any optional endpoints, typically need to be looked up through separate calls. Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman --- drivers/usb/core/usb.c | 83 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 83 insertions(+) (limited to 'drivers/usb') diff --git a/drivers/usb/core/usb.c b/drivers/usb/core/usb.c index f3996ba71a59..beebf02130d7 100644 --- a/drivers/usb/core/usb.c +++ b/drivers/usb/core/usb.c @@ -72,6 +72,89 @@ MODULE_PARM_DESC(autosuspend, "default autosuspend delay"); #endif +/** + * usb_find_common_endpoints() -- look up common endpoint descriptors + * @alt: alternate setting to search + * @bulk_in: pointer to descriptor pointer, or NULL + * @bulk_out: pointer to descriptor pointer, or NULL + * @int_in: pointer to descriptor pointer, or NULL + * @int_out: pointer to descriptor pointer, or NULL + * + * Search the alternate setting's endpoint descriptors for the first bulk-in, + * bulk-out, interrupt-in and interrupt-out endpoints and return them in the + * provided pointers (unless they are NULL). + * + * If a requested endpoint is not found, the corresponding pointer is set to + * NULL. + * + * Return: Zero if all requested descriptors were found, or -ENXIO otherwise. + */ +int usb_find_common_endpoints(struct usb_host_interface *alt, + struct usb_endpoint_descriptor **bulk_in, + struct usb_endpoint_descriptor **bulk_out, + struct usb_endpoint_descriptor **int_in, + struct usb_endpoint_descriptor **int_out) +{ + struct usb_endpoint_descriptor *epd; + int i; + + if (bulk_in) + *bulk_in = NULL; + if (bulk_out) + *bulk_out = NULL; + if (int_in) + *int_in = NULL; + if (int_out) + *int_out = NULL; + + for (i = 0; i < alt->desc.bNumEndpoints; ++i) { + epd = &alt->endpoint[i].desc; + + switch (usb_endpoint_type(epd)) { + case USB_ENDPOINT_XFER_BULK: + if (usb_endpoint_dir_in(epd)) { + if (bulk_in && !*bulk_in) { + *bulk_in = epd; + break; + } + } else { + if (bulk_out && !*bulk_out) { + *bulk_out = epd; + break; + } + } + + continue; + case USB_ENDPOINT_XFER_INT: + if (usb_endpoint_dir_in(epd)) { + if (int_in && !*int_in) { + *int_in = epd; + break; + } + } else { + if (int_out && !*int_out) { + *int_out = epd; + break; + } + } + + continue; + default: + continue; + } + + if ((!bulk_in || *bulk_in) && + (!bulk_out || *bulk_out) && + (!int_in || *int_in) && + (!int_out || *int_out)) { + return 0; + } + } + + return -ENXIO; +} +EXPORT_SYMBOL_GPL(usb_find_common_endpoints); + /** * usb_find_alt_setting() - Given a configuration, find the alternate setting * for the given interface. -- cgit v1.2.3