From: Paul Elder <paul.elder@ideasonboard.com>
To: laurent.pinchart@ideasonboard.com, kieran.bingham@ideasonboard.com
Cc: Paul Elder <paul.elder@ideasonboard.com>,
b-liu@ti.com, stern@rowland.harvard.edu, rogerq@ti.com,
balbi@kernel.org, gregkh@linuxfoundation.org,
linux-usb@vger.kernel.org, linux-kernel@vger.kernel.org
Subject: [PATCH v6 6/6] usb: gadget: uvc: allow ioctl to send response in status stage
Date: Sun, 20 Jan 2019 14:41:36 -0500 [thread overview]
Message-ID: <20190120194136.21870-7-paul.elder@ideasonboard.com> (raw)
In-Reply-To: <20190120194136.21870-1-paul.elder@ideasonboard.com>
We now have a mechanism to signal the UDC driver to reply to a control
OUT request with STALL or ACK, and we have packaged the setup stage data
and the data stage data of a control OUT request into a single
UVC_EVENT_DATA for userspace to consume. After telling the UDC to delay
the status stage, the ioctl UVCIOC_SEND_RESPONSE should be called to
notify the UDC driver to reply with STALL or ACK, for control OUT
requests. In the case of a control IN request, the ioctl sends the UVC
data as before.
This means that the completion handler will also be called for the
status stage, so make the UVC gadget driver aware of if the
completion handler is called for the status stage, and do nothing (as
opposed to giving userspace the UVC data again).
Signed-off-by: Paul Elder <paul.elder@ideasonboard.com>
---
Changes from v5:
- add event_status flag and use to keep track of whether or not the
gadget is in the status stage or not
- do nothing if the completion handler is called during the status stage
No change from v4
No change from v3
Changes from v2:
- calling usb_ep_set_halt in uvc_send_response if data->length < 0 is
now common for both IN and OUT transfers so make that check common
- remove now unnecessary field setting for the usb_request to be queued
for the status stage
Changes from v1:
- remove usb_ep_delay_status call from the old proposed API
- changed portions of uvc_send_response to match v2 API
- remove UDC warning that send_response is not implemented
drivers/usb/gadget/function/f_uvc.c | 11 +++++++++--
drivers/usb/gadget/function/uvc.h | 1 +
drivers/usb/gadget/function/uvc_v4l2.c | 24 ++++++++++++++++++------
3 files changed, 28 insertions(+), 8 deletions(-)
diff --git a/drivers/usb/gadget/function/f_uvc.c b/drivers/usb/gadget/function/f_uvc.c
index 6303ed346af9..dd3a06e28435 100644
--- a/drivers/usb/gadget/function/f_uvc.c
+++ b/drivers/usb/gadget/function/f_uvc.c
@@ -208,15 +208,19 @@ uvc_function_ep0_complete(struct usb_ep *ep, struct usb_request *req)
struct v4l2_event v4l2_event;
struct uvc_event *uvc_event = (void *)&v4l2_event.u.data;
- if (uvc->event_setup_out) {
- uvc->event_setup_out = 0;
+ if (uvc->event_status) {
+ uvc->event_status = 0;
+ return;
+ }
+ if (uvc->event_setup_out) {
memset(&v4l2_event, 0, sizeof(v4l2_event));
v4l2_event.type = UVC_EVENT_DATA;
uvc_event->data.length = req->actual;
memcpy(&uvc_event->data.data, req->buf, req->actual);
memcpy(&uvc_event->data.setup, &uvc->control_setup,
sizeof(uvc_event->data.setup));
+
v4l2_event_queue(&uvc->vdev, &v4l2_event);
}
}
@@ -242,6 +246,8 @@ uvc_function_setup(struct usb_function *f, const struct usb_ctrlrequest *ctrl)
uvc->event_length = le16_to_cpu(ctrl->wLength);
memcpy(&uvc->control_setup, ctrl, sizeof(uvc->control_setup));
+ uvc->event_status = 0;
+
if (uvc->event_setup_out) {
struct usb_request *req = uvc->control_req;
@@ -251,6 +257,7 @@ uvc_function_setup(struct usb_function *f, const struct usb_ctrlrequest *ctrl)
*/
req->length = uvc->event_length;
req->zero = 0;
+ req->explicit_status = 1;
usb_ep_queue(f->config->cdev->gadget->ep0, req, GFP_KERNEL);
} else {
struct v4l2_event v4l2_event;
diff --git a/drivers/usb/gadget/function/uvc.h b/drivers/usb/gadget/function/uvc.h
index 1d89b1df4ba0..5754548d94c5 100644
--- a/drivers/usb/gadget/function/uvc.h
+++ b/drivers/usb/gadget/function/uvc.h
@@ -171,6 +171,7 @@ struct uvc_device {
/* Events */
unsigned int event_length;
unsigned int event_setup_out : 1;
+ unsigned int event_status : 1;
};
static inline struct uvc_device *to_uvc(struct usb_function *f)
diff --git a/drivers/usb/gadget/function/uvc_v4l2.c b/drivers/usb/gadget/function/uvc_v4l2.c
index ac48f49d9f10..338811c612c5 100644
--- a/drivers/usb/gadget/function/uvc_v4l2.c
+++ b/drivers/usb/gadget/function/uvc_v4l2.c
@@ -35,15 +35,27 @@ uvc_send_response(struct uvc_device *uvc, struct uvc_request_data *data)
struct usb_composite_dev *cdev = uvc->func.config->cdev;
struct usb_request *req = uvc->control_req;
+ if (data->length < 0)
+ return usb_ep_set_halt(cdev->gadget->ep0);
+
/*
* For control OUT transfers the request has been enqueued synchronously
- * by the setup handler, there's nothing to be done here.
+ * by the setup handler, we just need to tell the UDC whether to ACK or
+ * STALL the control transfer.
*/
- if (uvc->event_setup_out)
- return 0;
-
- if (data->length < 0)
- return usb_ep_set_halt(cdev->gadget->ep0);
+ if (uvc->event_setup_out) {
+ /*
+ * The length field carries the control request status.
+ * Negative values signal a STALL and zero values an ACK.
+ * Positive values are not valid as there is no data to send
+ * back in the status stage.
+ */
+ if (data->length > 0)
+ return -EINVAL;
+
+ uvc->event_status = 1;
+ return usb_ep_queue(cdev->gadget->ep0, req, GFP_KERNEL);
+ }
req->length = min_t(unsigned int, uvc->event_length, data->length);
req->zero = data->length < uvc->event_length;
--
2.20.1
prev parent reply other threads:[~2019-01-21 7:32 UTC|newest]
Thread overview: 7+ messages / expand[flat|nested] mbox.gz Atom feed top
2019-01-20 19:41 [PATCH v6 0/6] usb: gadget: add mechanism to asynchronously validate data stage of ctrl out request Paul Elder
2019-01-20 19:41 ` [PATCH v6 1/6] usb: uvc: include videodev2.h in g_uvc.h Paul Elder
2019-01-20 19:41 ` [PATCH v6 2/6] usb: gadget: uvc: enqueue usb request in setup handler for control OUT Paul Elder
2019-01-20 19:41 ` [PATCH v6 3/6] usb: gadget: uvc: package setup and data for control OUT requests Paul Elder
2019-01-20 19:41 ` [PATCH v6 4/6] usb: gadget: add mechanism to specify an explicit status stage Paul Elder
2019-01-20 19:41 ` [PATCH v6 5/6] usb: musb: gadget: implement optional " Paul Elder
2019-01-20 19:41 ` Paul Elder [this message]
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20190120194136.21870-7-paul.elder@ideasonboard.com \
--to=paul.elder@ideasonboard.com \
--cc=b-liu@ti.com \
--cc=balbi@kernel.org \
--cc=gregkh@linuxfoundation.org \
--cc=kieran.bingham@ideasonboard.com \
--cc=laurent.pinchart@ideasonboard.com \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-usb@vger.kernel.org \
--cc=rogerq@ti.com \
--cc=stern@rowland.harvard.edu \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
all inboxes | Powered by JetHome®