diff options
| author | Laurent Pinchart <laurent.pinchart@ideasonboard.com> | 2018-05-26 20:58:19 +0300 | 
|---|---|---|
| committer | Laurent Pinchart <laurent.pinchart@ideasonboard.com> | 2018-06-01 09:47:11 +0300 | 
| commit | 571e148aaec20c26c308d6611cdb1f34ec81ff1e (patch) | |
| tree | 2d829def0ed54aaf55dddd4743c0e9bbb6dec112 | |
| parent | 203acba635874681e3e744fbce4151d569afa572 (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.c | 108 | ||||
| -rw-r--r-- | configfs.h | 53 | ||||
| -rw-r--r-- | uvc-gadget.c | 4 | 
3 files changed, 128 insertions, 37 deletions
| @@ -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; @@ -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);  } | 
