usb: gadget: f_uvc: add suspend and resume function

This patch adds uvc_function_suspend and uvc_function_resume
for uvc function. With this patch, if usb bus enter suspend
or resume state, the usb controller driver will call the
uvc_function_suspend or uvc_function_resume to send event
to uvc app.

Change-Id: I9c584aae25298747c5a287243cb3efd71c8adfe6
Signed-off-by: William Wu <william.wu@rock-chips.com>
Signed-off-by: Frank Wang <frank.wang@rock-chips.com>
This commit is contained in:
William Wu 2021-03-17 18:37:18 +08:00 committed by Tao Huang
commit 7bb8939e5c
3 changed files with 45 additions and 4 deletions

View file

@ -386,6 +386,14 @@ uvc_function_set_alt(struct usb_function *f, unsigned interface, unsigned alt)
usb_ep_enable(uvc->control_ep);
if (uvc->event_suspend) {
memset(&v4l2_event, 0, sizeof(v4l2_event));
v4l2_event.type = UVC_EVENT_RESUME;
v4l2_event_queue(&uvc->vdev, &v4l2_event);
uvc->event_suspend = 0;
uvc_trace(UVC_TRACE_SUSPEND, "send UVC_EVENT_RESUME\n");
}
if (uvc->state == UVC_STATE_DISCONNECTED) {
memset(&v4l2_event, 0, sizeof(v4l2_event));
v4l2_event.type = UVC_EVENT_CONNECT;
@ -510,6 +518,30 @@ uvc_function_disable(struct usb_function *f)
usb_ep_disable(uvc->control_ep);
}
static void uvc_function_suspend(struct usb_function *f)
{
struct uvc_device *uvc = to_uvc(f);
struct v4l2_event v4l2_event;
memset(&v4l2_event, 0, sizeof(v4l2_event));
v4l2_event.type = UVC_EVENT_SUSPEND;
v4l2_event_queue(&uvc->vdev, &v4l2_event);
uvc->event_suspend = 1;
uvc_trace(UVC_TRACE_SUSPEND, "send UVC_EVENT_SUSPEND\n");
}
static void uvc_function_resume(struct usb_function *f)
{
struct uvc_device *uvc = to_uvc(f);
struct v4l2_event v4l2_event;
memset(&v4l2_event, 0, sizeof(v4l2_event));
v4l2_event.type = UVC_EVENT_RESUME;
v4l2_event_queue(&uvc->vdev, &v4l2_event);
uvc->event_suspend = 0;
uvc_trace(UVC_TRACE_SUSPEND, "send UVC_EVENT_RESUME\n");
}
/* --------------------------------------------------------------------------
* Connection / disconnection
*/
@ -817,9 +849,13 @@ uvc_function_bind(struct usb_configuration *c, struct usb_function *f)
uvc_ss_bulk_streaming_ep.wMaxPacketSize =
cpu_to_le16(max_packet_size);
uvc_ss_streaming_comp.bMaxBurst = opts->streaming_maxburst;
uvc_ss_streaming_comp.wBytesPerInterval =
cpu_to_le16(max_packet_size * opts->streaming_maxburst);
uvc_ss_bulk_streaming_comp.bMaxBurst = opts->streaming_maxburst;
/*
* As per USB 3.1 spec "Table 9-26. SuperSpeed Endpoint
* Companion Descriptor", the wBytesPerInterval must be
* set to zero for bulk endpoints.
*/
uvc_ss_bulk_streaming_comp.wBytesPerInterval = 0;
}
/* Allocate endpoints. */
@ -1199,6 +1235,8 @@ static struct usb_function *uvc_alloc(struct usb_function_instance *fi)
uvc->func.disable = uvc_function_disable;
uvc->func.setup = uvc_function_setup;
uvc->func.free_func = uvc_free;
uvc->func.suspend = uvc_function_suspend;
uvc->func.resume = uvc_function_resume;
uvc->func.bind_deactivated = true;
return &uvc->func;

View file

@ -138,6 +138,7 @@ struct uvc_device {
/* Events */
unsigned int event_length;
unsigned int event_setup_out : 1;
unsigned int event_suspend : 1;
};
static inline struct uvc_device *to_uvc(struct usb_function *f)

View file

@ -19,7 +19,9 @@
#define UVC_EVENT_STREAMOFF (V4L2_EVENT_PRIVATE_START + 3)
#define UVC_EVENT_SETUP (V4L2_EVENT_PRIVATE_START + 4)
#define UVC_EVENT_DATA (V4L2_EVENT_PRIVATE_START + 5)
#define UVC_EVENT_LAST (V4L2_EVENT_PRIVATE_START + 5)
#define UVC_EVENT_SUSPEND (V4L2_EVENT_PRIVATE_START + 6)
#define UVC_EVENT_RESUME (V4L2_EVENT_PRIVATE_START + 7)
#define UVC_EVENT_LAST (V4L2_EVENT_PRIVATE_START + 7)
struct uvc_request_data {
__s32 length;