Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

usb: gadget: composite: add req_match method to usb_function

Non-standard requests can encode the actual interface number in a
non-standard way. For example composite_setup() assumes
that it is w_index && 0xFF, but the printer function encodes the interface
number in a context-dependet way (either w_index or w_index >> 8).
This can lead to such requests being directed to wrong functions.

This patch adds req_match() method to usb_function. Its purpose is to
verify that a given request can be handled by a given function.
If any function within a configuration provides the method and it returns
true, then it is assumed that the right function is found.

If a function uses req_match(), it should try as hard as possible to
determine if the request is meant for it.

If no functions in a configuration provide req_match or none of them
returns true, then fall back to the usual approach.

Signed-off-by: Andrzej Pietrasiewicz <andrzej.p@samsung.com>
Signed-off-by: Felipe Balbi <balbi@ti.com>

authored by

Andrzej Pietrasiewicz and committed by
Felipe Balbi
f563d230 143d53e1

+8 -1
+5 -1
drivers/usb/gadget/composite.c
··· 1758 1758 * take such requests too, if that's ever needed: to work 1759 1759 * in config 0, etc. 1760 1760 */ 1761 + list_for_each_entry(f, &cdev->config->functions, list) 1762 + if (f->req_match && f->req_match(f, ctrl)) 1763 + goto try_fun_setup; 1764 + f = NULL; 1761 1765 switch (ctrl->bRequestType & USB_RECIP_MASK) { 1762 1766 case USB_RECIP_INTERFACE: 1763 1767 if (!cdev->config || intf >= MAX_CONFIG_INTERFACES) ··· 1779 1775 f = NULL; 1780 1776 break; 1781 1777 } 1782 - 1778 + try_fun_setup: 1783 1779 if (f && f->setup) 1784 1780 value = f->setup(f, ctrl); 1785 1781 else {
+3
include/linux/usb/composite.h
··· 148 148 * @disable: (REQUIRED) Indicates the function should be disabled. Reasons 149 149 * include host resetting or reconfiguring the gadget, and disconnection. 150 150 * @setup: Used for interface-specific control requests. 151 + * @req_match: Tests if a given class request can be handled by this function. 151 152 * @suspend: Notifies functions when the host stops sending USB traffic. 152 153 * @resume: Notifies functions when the host restarts USB traffic. 153 154 * @get_status: Returns function status as a reply to ··· 213 212 unsigned interface); 214 213 void (*disable)(struct usb_function *); 215 214 int (*setup)(struct usb_function *, 215 + const struct usb_ctrlrequest *); 216 + bool (*req_match)(struct usb_function *, 216 217 const struct usb_ctrlrequest *); 217 218 void (*suspend)(struct usb_function *); 218 219 void (*resume)(struct usb_function *);