Commit f563d230 authored by Andrzej Pietrasiewicz's avatar Andrzej Pietrasiewicz Committed by Felipe Balbi

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: default avatarAndrzej Pietrasiewicz <andrzej.p@samsung.com>
Signed-off-by: default avatarFelipe Balbi <balbi@ti.com>
parent 143d53e1
...@@ -1758,6 +1758,10 @@ composite_setup(struct usb_gadget *gadget, const struct usb_ctrlrequest *ctrl) ...@@ -1758,6 +1758,10 @@ composite_setup(struct usb_gadget *gadget, const struct usb_ctrlrequest *ctrl)
* take such requests too, if that's ever needed: to work * take such requests too, if that's ever needed: to work
* in config 0, etc. * 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) { switch (ctrl->bRequestType & USB_RECIP_MASK) {
case USB_RECIP_INTERFACE: case USB_RECIP_INTERFACE:
if (!cdev->config || intf >= MAX_CONFIG_INTERFACES) if (!cdev->config || intf >= MAX_CONFIG_INTERFACES)
...@@ -1775,7 +1779,7 @@ composite_setup(struct usb_gadget *gadget, const struct usb_ctrlrequest *ctrl) ...@@ -1775,7 +1779,7 @@ composite_setup(struct usb_gadget *gadget, const struct usb_ctrlrequest *ctrl)
f = NULL; f = NULL;
break; break;
} }
try_fun_setup:
if (f && f->setup) if (f && f->setup)
value = f->setup(f, ctrl); value = f->setup(f, ctrl);
else { else {
......
...@@ -148,6 +148,7 @@ struct usb_os_desc_table { ...@@ -148,6 +148,7 @@ struct usb_os_desc_table {
* @disable: (REQUIRED) Indicates the function should be disabled. Reasons * @disable: (REQUIRED) Indicates the function should be disabled. Reasons
* include host resetting or reconfiguring the gadget, and disconnection. * include host resetting or reconfiguring the gadget, and disconnection.
* @setup: Used for interface-specific control requests. * @setup: Used for interface-specific control requests.
* @req_match: Tests if a given class request can be handled by this function.
* @suspend: Notifies functions when the host stops sending USB traffic. * @suspend: Notifies functions when the host stops sending USB traffic.
* @resume: Notifies functions when the host restarts USB traffic. * @resume: Notifies functions when the host restarts USB traffic.
* @get_status: Returns function status as a reply to * @get_status: Returns function status as a reply to
...@@ -213,6 +214,8 @@ struct usb_function { ...@@ -213,6 +214,8 @@ struct usb_function {
void (*disable)(struct usb_function *); void (*disable)(struct usb_function *);
int (*setup)(struct usb_function *, int (*setup)(struct usb_function *,
const struct usb_ctrlrequest *); const struct usb_ctrlrequest *);
bool (*req_match)(struct usb_function *,
const struct usb_ctrlrequest *);
void (*suspend)(struct usb_function *); void (*suspend)(struct usb_function *);
void (*resume)(struct usb_function *); void (*resume)(struct usb_function *);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment