forked from Minki/linux
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>
This commit is contained in:
parent
54dfce6d07
commit
1a00b457a5
@ -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:
|
||||
|
@ -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,
|
||||
|
@ -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;
|
||||
|
@ -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 *);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user