summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKieran Bingham <kieran.bingham@ideasonboard.com>2018-05-25 16:31:33 +0100
committerLaurent Pinchart <laurent.pinchart@ideasonboard.com>2018-05-26 18:33:26 +0300
commit7f04878e79b173dbaca546a283850f44188d8840 (patch)
tree59fa5c5e5dea60b4d7e9a0dbd64907c735b33708
parent83fa2cb53742f43c3a254d0453bd96048ee29a82 (diff)
configfs: Handle interface numbers
Store the function configuration pointer in the uvc_device, and use it to identify and store the interface numbers from configfs. Signed-off-by: Kieran Bingham <kieran.bingham@ideasonboard.com> Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
-rw-r--r--configfs.c26
-rw-r--r--configfs.h3
-rw-r--r--uvc-gadget.c25
3 files changed, 39 insertions, 15 deletions
diff --git a/configfs.c b/configfs.c
index 8d36a29..4668e59 100644
--- a/configfs.c
+++ b/configfs.c
@@ -199,6 +199,9 @@ static char *udc_find_video_device(const char *udc, const char *function)
*/
static const struct uvc_function_config g_webcam_config = {
+ .control_interface = 0,
+ .streaming_interface = 1,
+
.streaming_interval = 1,
.streaming_maxburst = 0,
.streaming_maxpacket = 1024,
@@ -266,6 +269,26 @@ void configfs_free_uvc_function(struct uvc_function_config *fc)
free(fc);
}
+static int configfs_parse_interfaces(const char *fpath,
+ struct uvc_function_config *fc)
+{
+ int ret;
+
+ ret = attribute_read_uint(fpath, "control/bInterfaceNumber",
+ &fc->control_interface);
+
+ ret = ret ? : attribute_read_uint(fpath, "streaming/bInterfaceNumber",
+ &fc->streaming_interface);
+
+ if (ret) {
+ printf("Failed to obtain interface numbers, using defaults\n");
+ fc->control_interface = 0;
+ fc->streaming_interface = 1;
+ }
+
+ return 0;
+}
+
/*
* configfs_parse_uvc_function - Parse a UVC function configuration in ConfigFS
* @function: The function name
@@ -323,6 +346,9 @@ struct uvc_function_config *configfs_parse_uvc_function(const char *function)
if (!fc->video)
ret = -ENODEV;
+ /* Identify interface numbers, or fall back to defaults. */
+ configfs_parse_interfaces(fpath, fc);
+
ret = ret ? : attribute_read_uint(fpath, "streaming_interval",
&fc->streaming_interval);
diff --git a/configfs.h b/configfs.h
index 56056c1..fe513ea 100644
--- a/configfs.h
+++ b/configfs.h
@@ -14,6 +14,9 @@ struct uvc_function_config {
char *video;
char *udc;
+ unsigned int control_interface;
+ unsigned int streaming_interface;
+
unsigned int streaming_interval;
unsigned int streaming_maxburst;
unsigned int streaming_maxpacket;
diff --git a/uvc-gadget.c b/uvc-gadget.c
index dbf1e10..96f9996 100644
--- a/uvc-gadget.c
+++ b/uvc-gadget.c
@@ -43,13 +43,12 @@
#include "tools.h"
#include "v4l2.h"
-#define UVC_INTF_CONTROL 0
-#define UVC_INTF_STREAMING 1
-
struct uvc_device
{
struct v4l2_device *vdev;
+ struct uvc_function_config *fc;
+
struct uvc_streaming_control probe;
struct uvc_streaming_control commit;
@@ -410,21 +409,15 @@ uvc_events_process_class(struct uvc_device *dev,
const struct usb_ctrlrequest *ctrl,
struct uvc_request_data *resp)
{
+ unsigned int interface = ctrl->wIndex & 0xff;
+
if ((ctrl->bRequestType & USB_RECIP_MASK) != USB_RECIP_INTERFACE)
return;
- switch (ctrl->wIndex & 0xff) {
- case UVC_INTF_CONTROL:
+ if (interface == dev->fc->control_interface)
uvc_events_process_control(dev, ctrl->bRequest, ctrl->wValue >> 8, resp);
- break;
-
- case UVC_INTF_STREAMING:
+ else if (interface == dev->fc->streaming_interface)
uvc_events_process_streaming(dev, ctrl->bRequest, ctrl->wValue >> 8, resp);
- break;
-
- default:
- break;
- }
}
static void
@@ -611,12 +604,14 @@ static void uvc_stream_delete(struct uvc_stream *stream)
free(stream);
}
-static void uvc_stream_init_uvc(struct uvc_stream *stream)
+static void uvc_stream_init_uvc(struct uvc_stream *stream,
+ struct uvc_function_config *fc)
{
/*
* FIXME: The maximum size should be specified per format and frame.
*/
stream->uvc->maxsize = 0;
+ stream->uvc->fc = fc;
uvc_events_init(stream->uvc);
uvc_video_init(stream->uvc);
@@ -725,7 +720,7 @@ int main(int argc, char *argv[])
goto done;
}
- uvc_stream_init_uvc(stream);
+ uvc_stream_init_uvc(stream, fc);
uvc_stream_set_event_handler(stream, &events);
/* Main capture loop */