diff mbox series

[v12,5/6] usb: gadget: arm the function for triggering remote wakeup

Message ID 1679009888-8239-6-git-send-email-quic_eserrao@quicinc.com
State New
Headers show
Series Add function suspend/resume and remote wakeup support | expand

Commit Message

Elson Serrao March 16, 2023, 11:38 p.m. UTC
When host sends function suspend feature selector to the device,
arm the function for remote wakeup based on the received packet.
Also host queries the function wakeup capability  through a get
status request. Handle such requests in composite layer for cases
where function driver has not exposed a get_status callback.

Signed-off-by: Elson Roy Serrao <quic_eserrao@quicinc.com>
---
 drivers/usb/gadget/composite.c | 26 +++++++++++++++++++++++---
 1 file changed, 23 insertions(+), 3 deletions(-)
diff mbox series

Patch

diff --git a/drivers/usb/gadget/composite.c b/drivers/usb/gadget/composite.c
index 2111732..2c1100e 100644
--- a/drivers/usb/gadget/composite.c
+++ b/drivers/usb/gadget/composite.c
@@ -2006,9 +2006,20 @@  composite_setup(struct usb_gadget *gadget, const struct usb_ctrlrequest *ctrl)
 		f = cdev->config->interface[intf];
 		if (!f)
 			break;
-		status = f->get_status ? f->get_status(f) : 0;
-		if (status < 0)
-			break;
+
+		if (f->get_status) {
+			status = f->get_status(f);
+			if (status < 0)
+				break;
+		} else {
+			/* Set D0 and D1 bits based on func wakeup capability */
+			if (f->config->bmAttributes & USB_CONFIG_ATT_WAKEUP) {
+				status |= USB_INTRF_STAT_FUNC_RW_CAP;
+				if (f->func_wakeup_armed)
+					status |= USB_INTRF_STAT_FUNC_RW;
+			}
+		}
+
 		put_unaligned_le16(status & 0x0000ffff, req->buf);
 		break;
 	/*
@@ -2029,6 +2040,15 @@  composite_setup(struct usb_gadget *gadget, const struct usb_ctrlrequest *ctrl)
 			f = cdev->config->interface[intf];
 			if (!f)
 				break;
+
+			if (w_index & USB_INTRF_FUNC_SUSPEND_RW) {
+				if (!(f->config->bmAttributes &
+				      USB_CONFIG_ATT_WAKEUP))
+					break;
+				f->func_wakeup_armed = (ctrl->bRequest ==
+							USB_REQ_SET_FEATURE);
+			}
+
 			value = 0;
 			if (f->func_suspend)
 				value = f->func_suspend(f, w_index >> 8);