Re: [PATCH v13 5/6] usb: gadget: Handle function suspend feature selector

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On Fri, Mar 24, 2023, Elson Roy Serrao wrote:
> When host sends function suspend feature selector to the device,
> inspect the received packet and trigger function suspend or
> function resume accordingly. Inspect the remote wakeup bit and
> arm the function for remote wakeup if it is wakeup capable. Also
> host queries the function wakeup capability  through a get status
> request before sending function resume. Handle such requests in
> composite layer.
> 
> Signed-off-by: Elson Roy Serrao <quic_eserrao@xxxxxxxxxxx>
> ---
>  drivers/usb/gadget/composite.c | 65 ++++++++++++++++++++++++++++++++++++++----
>  1 file changed, 60 insertions(+), 5 deletions(-)
> 
> diff --git a/drivers/usb/gadget/composite.c b/drivers/usb/gadget/composite.c
> index 2111732..d1d7f89 100644
> --- a/drivers/usb/gadget/composite.c
> +++ b/drivers/usb/gadget/composite.c
> @@ -941,6 +941,9 @@ static void reset_config(struct usb_composite_dev *cdev)
>  		if (f->disable)
>  			f->disable(f);
>  
> +		/* Section 9.1.1.6, disable remote wakeup when device is reset */
> +		f->func_wakeup_armed = false;
> +
>  		bitmap_zero(f->endpoints, 32);
>  	}
>  	cdev->config = NULL;
> @@ -2006,9 +2009,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;
>  	/*
> @@ -2030,8 +2044,44 @@ composite_setup(struct usb_gadget *gadget, const struct usb_ctrlrequest *ctrl)
>  			if (!f)
>  				break;
>  			value = 0;
> -			if (f->func_suspend)
> +			if (f->func_suspend) {
>  				value = f->func_suspend(f, w_index >> 8);
> +			/* SetFeature(FUNCTION_SUSPEND) */
> +			} else if (ctrl->bRequest == USB_REQ_SET_FEATURE) {
> +				if (!(f->config->bmAttributes &
> +				      USB_CONFIG_ATT_WAKEUP) &&
> +				     (w_index & USB_INTRF_FUNC_SUSPEND_RW))
> +					break;
> +
> +				f->func_wakeup_armed = !!(w_index &
> +							  USB_INTRF_FUNC_SUSPEND_RW);
> +
> +				if (w_index & USB_INTRF_FUNC_SUSPEND_LP) {
> +					if (f->suspend && !f->func_suspended) {
> +						f->suspend(f);
> +						f->func_suspended = true;
> +					}
> +				/*
> +				 * Handle cases where host sends function resume
> +				 * through SetFeature(FUNCTION_SUSPEND) but low power
> +				 * bit reset
> +				 */
> +				} else {
> +					if (f->resume && f->func_suspended) {
> +						f->resume(f);
> +						f->func_suspended = false;
> +					}
> +				}
> +			/* ClearFeature(FUNCTION_SUSPEND) */
> +			} else if (ctrl->bRequest == USB_REQ_CLEAR_FEATURE) {
> +				f->func_wakeup_armed = false;
> +
> +				if (f->resume && f->func_suspended) {
> +					f->resume(f);
> +					f->func_suspended = false;
> +				}
> +			}
> +
>  			if (value < 0) {
>  				ERROR(cdev,
>  				      "func_suspend() returned error %d\n",
> @@ -2574,7 +2624,12 @@ void composite_resume(struct usb_gadget *gadget)
>  		cdev->driver->resume(cdev);
>  	if (cdev->config) {
>  		list_for_each_entry(f, &cdev->config->functions, list) {
> -			if (f->resume)
> +			/*
> +			 * Check for func_suspended flag to see if the function is
> +			 * in USB3 FUNCTION_SUSPEND state. In this case resume is
> +			 * done via FUNCTION_SUSPEND feature selector.
> +			 */
> +			if (f->resume && !f->func_suspended)
>  				f->resume(f);
>  		}
>  
> -- 
> 2.7.4
> 

Reviewed-by: Thinh Nguyen <Thinh.Nguyen@xxxxxxxxxxxx>

Thanks,
Thinh




[Index of Archives]     [Linux Media]     [Linux Input]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]     [Old Linux USB Devel Archive]

  Powered by Linux