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@xxxxxxxxxxx> --- drivers/usb/gadget/composite.c | 26 +++++++++++++++++++++++--- 1 file changed, 23 insertions(+), 3 deletions(-) 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); -- 2.7.4