usb: gadget: composite: add req_match method to usb_function
authorAndrzej Pietrasiewicz <andrzej.p@samsung.com>
Tue, 3 Mar 2015 09:52:23 +0000 (10:52 +0100)
committerFelipe Balbi <balbi@ti.com>
Tue, 10 Mar 2015 20:33:39 +0000 (15:33 -0500)
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>
drivers/usb/gadget/composite.c
include/linux/usb/composite.h

index 9fb92310fb2be85416088e23207770b18e196014..4d25e11b1f729cc4d9786ebb427f0124227a531f 100644 (file)
@@ -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 {
index 3d87defcc5270f1659a610a3d126c0156c0c6ce2..2511469a99048996fa53232801fdb6a72bb90d4b 100644 (file)
@@ -148,6 +148,7 @@ struct usb_os_desc_table {
  * @disable: (REQUIRED) Indicates the function should be disabled.  Reasons
  *     include host resetting or reconfiguring the gadget, and disconnection.
  * @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.
  * @resume: Notifies functions when the host restarts USB traffic.
  * @get_status: Returns function status as a reply to
@@ -213,6 +214,8 @@ struct usb_function {
        void                    (*disable)(struct usb_function *);
        int                     (*setup)(struct usb_function *,
                                        const struct usb_ctrlrequest *);
+       bool                    (*req_match)(struct usb_function *,
+                                       const struct usb_ctrlrequest *);
        void                    (*suspend)(struct usb_function *);
        void                    (*resume)(struct usb_function *);