Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

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

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
Loading
Loading
Loading
Loading
+10 −6
Original line number Original line Diff line number Diff line
@@ -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;
		} 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;
						goto try_fun_setup;
			f = NULL;
		}
		}
		f = NULL;


		switch (ctrl->bRequestType & USB_RECIP_MASK) {
		switch (ctrl->bRequestType & USB_RECIP_MASK) {
		case USB_RECIP_INTERFACE:
		case USB_RECIP_INTERFACE:
+7 −2
Original line number Original line Diff line number Diff line
@@ -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,
}
}


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,
+5 −1
Original line number Original line Diff line number Diff line
@@ -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;
+2 −1
Original line number Original line Diff line number Diff line
@@ -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 *);