summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLaurent Pinchart <laurent.pinchart@ideasonboard.com>2018-05-26 20:58:19 +0300
committerLaurent Pinchart <laurent.pinchart@ideasonboard.com>2018-06-01 09:47:11 +0300
commit571e148aaec20c26c308d6611cdb1f34ec81ff1e (patch)
tree2d829def0ed54aaf55dddd4743c0e9bbb6dec112
parent203acba635874681e3e744fbce4151d569afa572 (diff)
configfs: Refactor ConfigFS parsing code
Move all attribute parsing to a top-level configfs_parse_uvc() function, and split control and streaming interface attributes to two separate helper functions. In addition to making the code more structured, it will also allow supporting multiple streaming interfaces in a single UVC function in the future. The uvc_function_config structure is similarly reorganized in a hierarchical representation of the configuration. Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com> Reviewed-by: Kieran Bingham <kieran.bingham@ideasonboard.com>
-rw-r--r--configfs.c108
-rw-r--r--configfs.h53
-rw-r--r--uvc-gadget.c4
3 files changed, 128 insertions, 37 deletions
diff --git a/configfs.c b/configfs.c
index 3b98f55..38954d5 100644
--- a/configfs.c
+++ b/configfs.c
@@ -199,12 +199,21 @@ 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,
+ .control = {
+ .intf = {
+ .bInterfaceNumber = 0,
+ },
+ },
+ .streaming = {
+ .intf = {
+ .bInterfaceNumber = 1,
+ },
+ .ep = {
+ .bInterval = 1,
+ .bMaxBurst = 0,
+ .wMaxPacketSize = 1024,
+ },
+ },
};
static int parse_legacy_g_webcam(const char *udc,
@@ -269,16 +278,74 @@ 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)
+#define configfs_parse_child(parent, child, cfg, parse) \
+({ \
+ char *__path; \
+ int __ret; \
+ \
+ __path = path_join((parent), (child)); \
+ if (__path) { \
+ __ret = parse(__path, (cfg)); \
+ free(__path); \
+ } else { \
+ __ret = -ENOMEM; \
+ } \
+ \
+ __ret; \
+})
+
+static int configfs_parse_interface(const char *path,
+ struct uvc_function_config_interface *cfg)
{
int ret;
- ret = attribute_read_uint(fpath, "control/bInterfaceNumber",
- &fc->control_interface);
+ ret = attribute_read_uint(path, "bInterfaceNumber",
+ &cfg->bInterfaceNumber);
+
+ return ret;
+}
+
+static int configfs_parse_control(const char *path,
+ struct uvc_function_config_control *cfg)
+{
+ int ret;
+
+ ret = configfs_parse_interface(path, &cfg->intf);
+
+ return ret;
+}
+
+static int configfs_parse_streaming(const char *path,
+ struct uvc_function_config_streaming *cfg)
+{
+ int ret;
+
+ ret = configfs_parse_interface(path, &cfg->intf);
+
+ return ret;
+}
+
+static int configfs_parse_uvc(const char *fpath,
+ struct uvc_function_config *fc)
+{
+ int ret = 0;
- ret = ret ? : attribute_read_uint(fpath, "streaming/bInterfaceNumber",
- &fc->streaming_interface);
+ ret = ret ? : configfs_parse_child(fpath, "control", &fc->control,
+ configfs_parse_control);
+ ret = ret ? : configfs_parse_child(fpath, "streaming", &fc->streaming,
+ configfs_parse_streaming);
+
+ /*
+ * These parameters should be part of the streaming interface in
+ * ConfigFS, but for legacy reasons they are located directly in the
+ * function directory.
+ */
+ ret = ret ? : attribute_read_uint(fpath, "streaming_interval",
+ &fc->streaming.ep.bInterval);
+ ret = ret ? : attribute_read_uint(fpath, "streaming_maxburst",
+ &fc->streaming.ep.bMaxBurst);
+ ret = ret ? : attribute_read_uint(fpath, "streaming_maxpacket",
+ &fc->streaming.ep.wMaxPacketSize);
return ret;
}
@@ -337,21 +404,14 @@ struct uvc_function_config *configfs_parse_uvc_function(const char *function)
fc->udc = attribute_read_str(fpath, "../../UDC");
fc->video = udc_find_video_device(fc->udc, function);
- if (!fc->video)
+ if (!fc->video) {
ret = -ENODEV;
+ goto done;
+ }
- /* Identify interface numbers. */
- ret = ret ? : configfs_parse_interfaces(fpath, fc);
-
- ret = ret ? : attribute_read_uint(fpath, "streaming_interval",
- &fc->streaming_interval);
-
- ret = ret ? : attribute_read_uint(fpath, "streaming_maxburst",
- &fc->streaming_maxburst);
-
- ret = ret ? : attribute_read_uint(fpath, "streaming_maxpacket",
- &fc->streaming_maxpacket);
+ ret = configfs_parse_uvc(fpath, fc);
+done:
if (ret) {
configfs_free_uvc_function(fc);
fc = NULL;
diff --git a/configfs.h b/configfs.h
index b5c7480..9f7f377 100644
--- a/configfs.h
+++ b/configfs.h
@@ -11,25 +11,56 @@
#define __CONFIGFS_H__
/*
+ * struct uvc_function_config_endpoint - Endpoint parameters
+ * @bInterval: Transfer interval (interrupt and isochronous only)
+ * @bMaxBurst: Transfer burst size (super-speed only)
+ * @wMaxPacketSize: Maximum packet size (including the multiplier)
+ */
+struct uvc_function_config_endpoint {
+ unsigned int bInterval;
+ unsigned int bMaxBurst;
+ unsigned int wMaxPacketSize;
+};
+
+/*
+ * struct uvc_function_config_interface - Interface parameters
+ * @bInterfaceNumber: Interface number
+ */
+struct uvc_function_config_interface {
+ unsigned int bInterfaceNumber;
+};
+
+/*
+ * struct uvc_function_config_control - Control interface parameters
+ * @intf: Generic interface parameters
+ */
+struct uvc_function_config_control {
+ struct uvc_function_config_interface intf;
+};
+
+/*
+ * struct uvc_function_config_streaming - Streaming interface parameters
+ * @intf: Generic interface parameters
+ * @ep: Endpoint parameters
+ */
+struct uvc_function_config_streaming {
+ struct uvc_function_config_interface intf;
+ struct uvc_function_config_endpoint ep;
+};
+
+/*
* struct uvc_function_config - UVC function configuration parameters
* @video: Full path to the video device node
* @udc: UDC name
- * @control_interface: Control interface number
- * @streaming_interface: Streaming interface number
- * @streaming_interval: Isochronous interval for the streaming endpoint
- * @streaming_maxburts: Isochronous maximum burst for the streaming endpoint
- * @streaming_maxpacket: Isochronous maximum packets for the streaming endpoint
+ * @control: Control interface configuration
+ * @streaming: Streaming interface configuration
*/
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;
+ struct uvc_function_config_control control;
+ struct uvc_function_config_streaming streaming;
};
struct uvc_function_config *configfs_parse_uvc_function(const char *function);
diff --git a/uvc-gadget.c b/uvc-gadget.c
index 96f9996..57dc097 100644
--- a/uvc-gadget.c
+++ b/uvc-gadget.c
@@ -414,9 +414,9 @@ uvc_events_process_class(struct uvc_device *dev,
if ((ctrl->bRequestType & USB_RECIP_MASK) != USB_RECIP_INTERFACE)
return;
- if (interface == dev->fc->control_interface)
+ if (interface == dev->fc->control.intf.bInterfaceNumber)
uvc_events_process_control(dev, ctrl->bRequest, ctrl->wValue >> 8, resp);
- else if (interface == dev->fc->streaming_interface)
+ else if (interface == dev->fc->streaming.intf.bInterfaceNumber)
uvc_events_process_streaming(dev, ctrl->bRequest, ctrl->wValue >> 8, resp);
}