diff options
author | Felix Hädicke <felixhaedicke@web.de> | 2016-06-22 01:12:08 +0200 |
---|---|---|
committer | Felipe Balbi <felipe.balbi@linux.intel.com> | 2016-08-25 12:13:17 +0300 |
commit | 1a00b457a5482c3822bfc0fd64c088b2dba93e26 (patch) | |
tree | 5fa3a86d38d3d521845a3b93ea9c83ec9d0f34a1 | |
parent | 54dfce6d07b0391e23d006579bba488de4f7d6aa (diff) |
usb: gadget: composite: let USB functions process ctrl reqs in cfg0
It can sometimes be necessary for gadget drivers to process non-standard
control requests, which host devices can send without having sent
USB_REQ_SET_CONFIGURATION.
Therefore, the req_match() usb_function method is enhanced with the new
parameter "config0". When a USB configuration is active, this parameter
is false. When a non-core control request is processed in
composite_setup(), without an active configuration, req_match() of the
USB functions of all available configurations which implement this
function, is called with config0=true. Then the control request gets
processed by the first usb_function instance whose req_match() returns
true.
Signed-off-by: Felix Hädicke <felixhaedicke@web.de>
Signed-off-by: Felipe Balbi <felipe.balbi@linux.intel.com>
-rw-r--r-- | drivers/usb/gadget/composite.c | 16 | ||||
-rw-r--r-- | drivers/usb/gadget/function/f_fs.c | 9 | ||||
-rw-r--r-- | drivers/usb/gadget/function/f_printer.c | 6 | ||||
-rw-r--r-- | include/linux/usb/composite.h | 3 |
4 files changed, 24 insertions, 10 deletions
diff --git a/drivers/usb/gadget/composite.c b/drivers/usb/gadget/composite.c index 5ebe6af7976e..32176f779861 100644 --- a/drivers/usb/gadget/composite.c +++ b/drivers/usb/gadget/composite.c @@ -1893,17 +1893,21 @@ unknown: /* functions always handle their interfaces and endpoints... * punt other recipients (other, WUSB, ...) to the current * configuration code. - * - * REVISIT it could make sense to let the composite device - * take such requests too, if that's ever needed: to work - * in config 0, etc. */ if (cdev->config) { list_for_each_entry(f, &cdev->config->functions, list) - if (f->req_match && f->req_match(f, ctrl)) + if (f->req_match && + f->req_match(f, ctrl, false)) goto try_fun_setup; - f = NULL; + } else { + struct usb_configuration *c; + list_for_each_entry(c, &cdev->configs, list) + list_for_each_entry(f, &c->functions, list) + if (f->req_match && + f->req_match(f, ctrl, true)) + goto try_fun_setup; } + f = NULL; switch (ctrl->bRequestType & USB_RECIP_MASK) { case USB_RECIP_INTERFACE: diff --git a/drivers/usb/gadget/function/f_fs.c b/drivers/usb/gadget/function/f_fs.c index d7acab873836..d8f46f6233ac 100644 --- a/drivers/usb/gadget/function/f_fs.c +++ b/drivers/usb/gadget/function/f_fs.c @@ -99,7 +99,8 @@ static void ffs_func_disable(struct usb_function *); static int ffs_func_setup(struct usb_function *, const struct usb_ctrlrequest *); static bool ffs_func_req_match(struct usb_function *, - const struct usb_ctrlrequest *); + const struct usb_ctrlrequest *, + bool config0); static void ffs_func_suspend(struct usb_function *); static void ffs_func_resume(struct usb_function *); @@ -3136,10 +3137,14 @@ static int ffs_func_setup(struct usb_function *f, } static bool ffs_func_req_match(struct usb_function *f, - const struct usb_ctrlrequest *creq) + const struct usb_ctrlrequest *creq, + bool config0) { struct ffs_function *func = ffs_func_from_usb(f); + if (config0) + return false; + switch (creq->bRequestType & USB_RECIP_MASK) { case USB_RECIP_INTERFACE: return ffs_func_revmap_intf(func, diff --git a/drivers/usb/gadget/function/f_printer.c b/drivers/usb/gadget/function/f_printer.c index 64706a789580..0de36cda6e41 100644 --- a/drivers/usb/gadget/function/f_printer.c +++ b/drivers/usb/gadget/function/f_printer.c @@ -889,13 +889,17 @@ static void printer_soft_reset(struct printer_dev *dev) /*-------------------------------------------------------------------------*/ static bool gprinter_req_match(struct usb_function *f, - const struct usb_ctrlrequest *ctrl) + const struct usb_ctrlrequest *ctrl, + bool config0) { struct printer_dev *dev = func_to_printer(f); u16 w_index = le16_to_cpu(ctrl->wIndex); u16 w_value = le16_to_cpu(ctrl->wValue); u16 w_length = le16_to_cpu(ctrl->wLength); + if (config0) + return false; + if ((ctrl->bRequestType & USB_RECIP_MASK) != USB_RECIP_INTERFACE || (ctrl->bRequestType & USB_TYPE_MASK) != USB_TYPE_CLASS) return false; diff --git a/include/linux/usb/composite.h b/include/linux/usb/composite.h index 2b81b24eb5aa..4616a49a1c2e 100644 --- a/include/linux/usb/composite.h +++ b/include/linux/usb/composite.h @@ -220,7 +220,8 @@ struct usb_function { int (*setup)(struct usb_function *, const struct usb_ctrlrequest *); bool (*req_match)(struct usb_function *, - const struct usb_ctrlrequest *); + const struct usb_ctrlrequest *, + bool config0); void (*suspend)(struct usb_function *); void (*resume)(struct usb_function *); |