From 7f04878e79b173dbaca546a283850f44188d8840 Mon Sep 17 00:00:00 2001 From: Kieran Bingham Date: Fri, 25 May 2018 16:31:33 +0100 Subject: 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 Signed-off-by: Laurent Pinchart --- configfs.c | 26 ++++++++++++++++++++++++++ configfs.h | 3 +++ uvc-gadget.c | 25 ++++++++++--------------- 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 */ -- cgit v1.2.3