summaryrefslogtreecommitdiffstats
path: root/drivers/usb/gadget/composite.c
diff options
context:
space:
mode:
authorAndrzej Pietrasiewicz <andrzej.p@samsung.com>2015-03-03 10:52:23 +0100
committerFelipe Balbi <balbi@ti.com>2015-03-10 21:33:39 +0100
commitf563d230903210acc2336af58e422216b68ded76 (patch)
treedbe10a4b868bf144d5565fc5c1c0f4cc6910b2c9 /drivers/usb/gadget/composite.c
parentusb: gadget: printer: add container_of helper for printer_dev (diff)
downloadlinux-f563d230903210acc2336af58e422216b68ded76.tar.xz
linux-f563d230903210acc2336af58e422216b68ded76.zip
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>
Diffstat (limited to 'drivers/usb/gadget/composite.c')
-rw-r--r--drivers/usb/gadget/composite.c6
1 files changed, 5 insertions, 1 deletions
diff --git a/drivers/usb/gadget/composite.c b/drivers/usb/gadget/composite.c
index 9fb92310fb2b..4d25e11b1f72 100644
--- a/drivers/usb/gadget/composite.c
+++ b/drivers/usb/gadget/composite.c
@@ -1758,6 +1758,10 @@ unknown:
* take such requests too, if that's ever needed: to work
* in config 0, etc.
*/
+ list_for_each_entry(f, &cdev->config->functions, list)
+ if (f->req_match && f->req_match(f, ctrl))
+ goto try_fun_setup;
+ f = NULL;
switch (ctrl->bRequestType & USB_RECIP_MASK) {
case USB_RECIP_INTERFACE:
if (!cdev->config || intf >= MAX_CONFIG_INTERFACES)
@@ -1775,7 +1779,7 @@ unknown:
f = NULL;
break;
}
-
+try_fun_setup:
if (f && f->setup)
value = f->setup(f, ctrl);
else {