configfs: Handle interface numbers
authorKieran Bingham <kieran.bingham@ideasonboard.com>
Fri, 25 May 2018 15:31:33 +0000 (16:31 +0100)
committerLaurent Pinchart <laurent.pinchart@ideasonboard.com>
Sat, 26 May 2018 15:33:26 +0000 (18:33 +0300)
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>
configfs.c
configfs.h
uvc-gadget.c

index 8d36a29..4668e59 100644 (file)
@@ -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);
 
index 56056c1..fe513ea 100644 (file)
@@ -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;
index dbf1e10..96f9996 100644 (file)
 #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 */