Commit 1a00b457 authored by Felix Hädicke's avatar Felix Hädicke Committed by Felipe Balbi

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: default avatarFelix Hädicke <felixhaedicke@web.de>
Signed-off-by: default avatarFelipe Balbi <felipe.balbi@linux.intel.com>
parent 54dfce6d
...@@ -1893,17 +1893,21 @@ composite_setup(struct usb_gadget *gadget, const struct usb_ctrlrequest *ctrl) ...@@ -1893,17 +1893,21 @@ composite_setup(struct usb_gadget *gadget, const struct usb_ctrlrequest *ctrl)
/* functions always handle their interfaces and endpoints... /* functions always handle their interfaces and endpoints...
* punt other recipients (other, WUSB, ...) to the current * punt other recipients (other, WUSB, ...) to the current
* configuration code. * 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) { if (cdev->config) {
list_for_each_entry(f, &cdev->config->functions, list) 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; 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) { switch (ctrl->bRequestType & USB_RECIP_MASK) {
case USB_RECIP_INTERFACE: case USB_RECIP_INTERFACE:
......
...@@ -99,7 +99,8 @@ static void ffs_func_disable(struct usb_function *); ...@@ -99,7 +99,8 @@ static void ffs_func_disable(struct usb_function *);
static int ffs_func_setup(struct usb_function *, static int ffs_func_setup(struct usb_function *,
const struct usb_ctrlrequest *); const struct usb_ctrlrequest *);
static bool ffs_func_req_match(struct usb_function *, 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_suspend(struct usb_function *);
static void ffs_func_resume(struct usb_function *); static void ffs_func_resume(struct usb_function *);
...@@ -3136,10 +3137,14 @@ static int ffs_func_setup(struct usb_function *f, ...@@ -3136,10 +3137,14 @@ static int ffs_func_setup(struct usb_function *f,
} }
static bool ffs_func_req_match(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); struct ffs_function *func = ffs_func_from_usb(f);
if (config0)
return false;
switch (creq->bRequestType & USB_RECIP_MASK) { switch (creq->bRequestType & USB_RECIP_MASK) {
case USB_RECIP_INTERFACE: case USB_RECIP_INTERFACE:
return ffs_func_revmap_intf(func, return ffs_func_revmap_intf(func,
......
...@@ -889,13 +889,17 @@ static void printer_soft_reset(struct printer_dev *dev) ...@@ -889,13 +889,17 @@ static void printer_soft_reset(struct printer_dev *dev)
/*-------------------------------------------------------------------------*/ /*-------------------------------------------------------------------------*/
static bool gprinter_req_match(struct usb_function *f, 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); struct printer_dev *dev = func_to_printer(f);
u16 w_index = le16_to_cpu(ctrl->wIndex); u16 w_index = le16_to_cpu(ctrl->wIndex);
u16 w_value = le16_to_cpu(ctrl->wValue); u16 w_value = le16_to_cpu(ctrl->wValue);
u16 w_length = le16_to_cpu(ctrl->wLength); u16 w_length = le16_to_cpu(ctrl->wLength);
if (config0)
return false;
if ((ctrl->bRequestType & USB_RECIP_MASK) != USB_RECIP_INTERFACE || if ((ctrl->bRequestType & USB_RECIP_MASK) != USB_RECIP_INTERFACE ||
(ctrl->bRequestType & USB_TYPE_MASK) != USB_TYPE_CLASS) (ctrl->bRequestType & USB_TYPE_MASK) != USB_TYPE_CLASS)
return false; return false;
......
...@@ -220,7 +220,8 @@ struct usb_function { ...@@ -220,7 +220,8 @@ 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 *, bool (*req_match)(struct usb_function *,
const struct usb_ctrlrequest *); const struct usb_ctrlrequest *,
bool config0);
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