@@ -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);
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(-)