diff mbox

[yavta,5/9] Allow passing file descriptors to yavta

Message ID 1393690690-5004-6-git-send-email-sakari.ailus@iki.fi (mailing list archive)
State New, archived
Headers show

Commit Message

Sakari Ailus March 1, 2014, 4:18 p.m. UTC
Signed-off-by: Sakari Ailus <sakari.ailus@iki.fi>
---
 yavta.c |   63 +++++++++++++++++++++++++++++++++++++++++++--------------------
 1 file changed, 43 insertions(+), 20 deletions(-)

Comments

Laurent Pinchart April 1, 2014, 10:16 p.m. UTC | #1
Hi Sakari,

Thank you for the patch.

On Saturday 01 March 2014 18:18:06 Sakari Ailus wrote:
> Signed-off-by: Sakari Ailus <sakari.ailus@iki.fi>
> ---
>  yavta.c |   63 ++++++++++++++++++++++++++++++++++++++++--------------------
>  1 file changed, 43 insertions(+), 20 deletions(-)
> 
> diff --git a/yavta.c b/yavta.c
> index 870682e..a9b192a 100644
> --- a/yavta.c
> +++ b/yavta.c
> @@ -62,6 +62,7 @@ struct buffer
>  struct device
>  {
>  	int fd;
> +	int opened;
> 
>  	enum v4l2_buf_type type;
>  	enum v4l2_memory memtype;
> @@ -180,13 +181,8 @@ static unsigned int v4l2_format_code(const char *name)
>  	return 0;
>  }
> 
> -static int video_open(struct device *dev, const char *devname, int
> no_query)
> +static int video_open(struct device *dev, const char *devname)
>  {
> -	dev->fd = -1;
> -	dev->memtype = V4L2_MEMORY_MMAP;
> -	dev->buffers = NULL;
> -	dev->type = (enum v4l2_buf_type)-1;
> -
>  	dev->fd = open(devname, O_RDWR);
>  	if (dev->fd < 0) {
>  		printf("Error opening device %s: %s (%d).\n", devname,
> @@ -196,6 +192,16 @@ static int video_open(struct device *dev, const char
> *devname, int no_query)
> 
>  	printf("Device %s opened.\n", devname);
> 
> +	dev->opened = 1;
> +
> +	return 0;
> +}
> +
> +static int video_querycap(struct device *dev, int no_query) {
> +	struct v4l2_capability cap;
> +	unsigned int capabilities;
> +	int ret;
> +

video_querycap ends up setting the dev->type field, which isn't really the job 
of a query function. Would there be a clean way to pass the fd to the 
video_open() function instead ? Maybe video_open() could be split and/or 
renamed to video_init() ?

>  	if (no_query) {
>  		/* Assume capture device. */
>  		dev->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
> @@ -215,9 +221,7 @@ static int video_open(struct device *dev, const char
> *devname, int no_query) else if (capabilities & V4L2_CAP_VIDEO_OUTPUT)
>  		dev->type = V4L2_BUF_TYPE_VIDEO_OUTPUT;
>  	else {
> -		printf("Error opening device %s: neither video capture "
> -			"nor video output supported.\n", devname);
> -		close(dev->fd);
> +		printf("Device supports neither capture nor output.\n");
>  		return -EINVAL;
>  	}
> 
> @@ -231,7 +235,8 @@ static void video_close(struct device *dev)
>  {
>  	free(dev->pattern);
>  	free(dev->buffers);
> -	close(dev->fd);
> +	if (dev->opened)
> +		close(dev->fd);
>  }
> 
>  static unsigned int get_control_type(struct device *dev, unsigned int id)
> @@ -1246,6 +1251,7 @@ static void usage(const char *argv0)
>  	printf("-w, --set-control 'ctrl value'	Set control 'ctrl' to 
'value'\n");
>  	printf("    --enum-formats		Enumerate formats\n");
>  	printf("    --enum-inputs		Enumerate inputs\n");
> +	printf("    --fd                        Use a numeric file descriptor
> insted of a device\n");
>  	printf("    --no-query			Don't query capabilities on open\n");
>  	printf("    --offset			User pointer buffer offset from page
> start\n");
>  	printf("    --requeue-last		Requeue the last buffers before
> streamoff\n");
> @@ -1262,6 +1268,7 @@ static void usage(const char *argv0)
>  #define OPT_USERPTR_OFFSET	261
>  #define OPT_REQUEUE_LAST	262
>  #define OPT_STRIDE		263
> +#define OPT_FD			264
> 
>  static struct option opts[] = {
>  	{"capture", 2, 0, 'c'},
> @@ -1269,6 +1276,7 @@ static struct option opts[] = {
>  	{"delay", 1, 0, 'd'},
>  	{"enum-formats", 0, 0, OPT_ENUM_FORMATS},
>  	{"enum-inputs", 0, 0, OPT_ENUM_INPUTS},
> +	{"fd", 1, 0, OPT_FD},
>  	{"file", 2, 0, 'F'},
>  	{"fill-frames", 0, 0, 'I'},
>  	{"format", 1, 0, 'f'},
> @@ -1297,7 +1305,11 @@ static struct option opts[] = {
>  int main(int argc, char *argv[])
>  {
>  	struct sched_param sched;
> -	struct device dev = { 0 };
> +	struct device dev = {
> +		.fd = -1,
> +		.memtype = V4L2_MEMORY_MMAP,
> +		.type = (enum v4l2_buf_type)-1,
> +	};
>  	int ret;
> 
>  	/* Options parsings */
> @@ -1452,6 +1464,14 @@ int main(int argc, char *argv[])
>  		case OPT_ENUM_INPUTS:
>  			do_enum_inputs = 1;
>  			break;
> +		case OPT_FD:
> +			dev.fd = atoi(optarg);
> +			if (dev.fd < 0) {
> +				printf("Bad file descriptor %d\n", dev.fd);
> +				return 1;
> +			}
> +			printf("Using file descriptor %d\n", dev.fd);
> +			break;
>  		case OPT_NO_QUERY:
>  			no_query = 1;
>  			break;
> @@ -1482,18 +1502,21 @@ int main(int argc, char *argv[])
>  		return 1;
>  	}
> 
> -	if (optind >= argc) {
> -		usage(argv[0]);
> -		return 1;
> -	}
> -
>  	if (!do_file)
>  		filename = NULL;
> 
> -	/* Open the video device. If the device type isn't recognized, set the
> -	 * --no-query option to avoid querying V4L2 subdevs.
> -	 */
> -	ret = video_open(&dev, argv[optind], no_query);
> +	if (dev.fd == -1) {
> +		if (optind >= argc) {
> +			usage(argv[0]);
> +			return 1;
> +		} else {
> +			ret = video_open(&dev, argv[optind]);
> +			if (ret < 0)
> +				return 1;
> +		}
> +	}
> +
> +	ret = video_querycap(&dev, no_query);
>  	if (ret < 0)
>  		return 1;
Sakari Ailus April 10, 2014, 6:48 p.m. UTC | #2
Hi Laurent,

Thanks for the comments.

Laurent Pinchart wrote:
...
>> @@ -196,6 +192,16 @@ static int video_open(struct device *dev, const char
>> *devname, int no_query)
>>
>>   	printf("Device %s opened.\n", devname);
>>
>> +	dev->opened = 1;
>> +
>> +	return 0;
>> +}
>> +
>> +static int video_querycap(struct device *dev, int no_query) {
>> +	struct v4l2_capability cap;
>> +	unsigned int capabilities;
>> +	int ret;
>> +
>
> video_querycap ends up setting the dev->type field, which isn't really the job
> of a query function. Would there be a clean way to pass the fd to the
> video_open() function instead ? Maybe video_open() could be split and/or
> renamed to video_init() ?

Agreed. I'll separate queue type selection from querycap. As the 
querycap needs to be done after opening the device, I'll put it into 
another function. I'm ok with video_init(), but what would you think 
about e.g. video_set_queue_type() as the function does nothing else.
Laurent Pinchart April 10, 2014, 10:17 p.m. UTC | #3
Hi Sakari,

On Thursday 10 April 2014 21:48:55 Sakari Ailus wrote:
> Hi Laurent,
> 
> Thanks for the comments.
> 
> Laurent Pinchart wrote:
> ...
> 
> >> @@ -196,6 +192,16 @@ static int video_open(struct device *dev, const char
> >> *devname, int no_query)
> >> 
> >>   	printf("Device %s opened.\n", devname);
> >> 
> >> +	dev->opened = 1;
> >> +
> >> +	return 0;
> >> +}
> >> +
> >> +static int video_querycap(struct device *dev, int no_query) {
> >> +	struct v4l2_capability cap;
> >> +	unsigned int capabilities;
> >> +	int ret;
> >> +
> > 
> > video_querycap ends up setting the dev->type field, which isn't really the
> > job of a query function. Would there be a clean way to pass the fd to the
> > video_open() function instead ? Maybe video_open() could be split and/or
> > renamed to video_init() ?
> 
> Agreed. I'll separate queue type selection from querycap. As the
> querycap needs to be done after opening the device, I'll put it into
> another function. I'm ok with video_init(), but what would you think
> about e.g. video_set_queue_type() as the function does nothing else.

Just thinking out loud, we need to

- initialize the device structure,
- open the device or use an externally provided fd,
- optionally query the device capabilities,
- optionally override the queue type.

Initializing the device structure must be performed unconditionally, I would 
create a video_init() function for that.

Opening the device or using an externally provided fd are exclusive 
operations, I would create two functions (that wouldn't do much).

Querying the device capabilities is also optional, I would create one function 
for that.

Finally, overriding the queue type is of course optional and should be 
implemented in its own function. We should probably return an error if the 
user tries to set a queue type not reported by QUERYCAP (assuming QUERYCAP has 
been called).

Ideally I'd also like to make the --no-query argument non-mandatory when 
operating on subdev nodes. It has been introduced because QUERYCAP isn't 
supported by subdev nodes, and it would be nice if we could detect somehow 
that the device node corresponds to a subdev and automatically skip QUERYCAP 
in that case.
Sakari Ailus April 10, 2014, 10:30 p.m. UTC | #4
Hi Laurent,

Laurent Pinchart wrote:
> Just thinking out loud, we need to
>
> - initialize the device structure,
> - open the device or use an externally provided fd,
> - optionally query the device capabilities,
> - optionally override the queue type.
>
> Initializing the device structure must be performed unconditionally, I would
> create a video_init() function for that.

This is now performed in the beginning of main(). video_open() no longer 
initialises anything.

> Opening the device or using an externally provided fd are exclusive
> operations, I would create two functions (that wouldn't do much).

Currently this is a few lines in main().

> Querying the device capabilities is also optional, I would create one function
> for that.

Patch 4/9.

> Finally, overriding the queue type is of course optional and should be
> implemented in its own function. We should probably return an error if the
> user tries to set a queue type not reported by QUERYCAP (assuming QUERYCAP has
> been called).

The same check already done in the driver, and an error is returned if 
it's wrong. I'm leaning towards thinking this isn't necessary in yavta.

> Ideally I'd also like to make the --no-query argument non-mandatory when
> operating on subdev nodes. It has been introduced because QUERYCAP isn't
> supported by subdev nodes, and it would be nice if we could detect somehow
> that the device node corresponds to a subdev and automatically skip QUERYCAP
> in that case.

It's already non-mandatory. We don't try to rocognise sub-device nodes, 
but failing querycap is a non-error already without this patchset.
diff mbox

Patch

diff --git a/yavta.c b/yavta.c
index 870682e..a9b192a 100644
--- a/yavta.c
+++ b/yavta.c
@@ -62,6 +62,7 @@  struct buffer
 struct device
 {
 	int fd;
+	int opened;
 
 	enum v4l2_buf_type type;
 	enum v4l2_memory memtype;
@@ -180,13 +181,8 @@  static unsigned int v4l2_format_code(const char *name)
 	return 0;
 }
 
-static int video_open(struct device *dev, const char *devname, int no_query)
+static int video_open(struct device *dev, const char *devname)
 {
-	dev->fd = -1;
-	dev->memtype = V4L2_MEMORY_MMAP;
-	dev->buffers = NULL;
-	dev->type = (enum v4l2_buf_type)-1;
-
 	dev->fd = open(devname, O_RDWR);
 	if (dev->fd < 0) {
 		printf("Error opening device %s: %s (%d).\n", devname,
@@ -196,6 +192,16 @@  static int video_open(struct device *dev, const char *devname, int no_query)
 
 	printf("Device %s opened.\n", devname);
 
+	dev->opened = 1;
+
+	return 0;
+}
+
+static int video_querycap(struct device *dev, int no_query) {
+	struct v4l2_capability cap;
+	unsigned int capabilities;
+	int ret;
+
 	if (no_query) {
 		/* Assume capture device. */
 		dev->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
@@ -215,9 +221,7 @@  static int video_open(struct device *dev, const char *devname, int no_query)
 	else if (capabilities & V4L2_CAP_VIDEO_OUTPUT)
 		dev->type = V4L2_BUF_TYPE_VIDEO_OUTPUT;
 	else {
-		printf("Error opening device %s: neither video capture "
-			"nor video output supported.\n", devname);
-		close(dev->fd);
+		printf("Device supports neither capture nor output.\n");
 		return -EINVAL;
 	}
 
@@ -231,7 +235,8 @@  static void video_close(struct device *dev)
 {
 	free(dev->pattern);
 	free(dev->buffers);
-	close(dev->fd);
+	if (dev->opened)
+		close(dev->fd);
 }
 
 static unsigned int get_control_type(struct device *dev, unsigned int id)
@@ -1246,6 +1251,7 @@  static void usage(const char *argv0)
 	printf("-w, --set-control 'ctrl value'	Set control 'ctrl' to 'value'\n");
 	printf("    --enum-formats		Enumerate formats\n");
 	printf("    --enum-inputs		Enumerate inputs\n");
+	printf("    --fd                        Use a numeric file descriptor insted of a device\n");
 	printf("    --no-query			Don't query capabilities on open\n");
 	printf("    --offset			User pointer buffer offset from page start\n");
 	printf("    --requeue-last		Requeue the last buffers before streamoff\n");
@@ -1262,6 +1268,7 @@  static void usage(const char *argv0)
 #define OPT_USERPTR_OFFSET	261
 #define OPT_REQUEUE_LAST	262
 #define OPT_STRIDE		263
+#define OPT_FD			264
 
 static struct option opts[] = {
 	{"capture", 2, 0, 'c'},
@@ -1269,6 +1276,7 @@  static struct option opts[] = {
 	{"delay", 1, 0, 'd'},
 	{"enum-formats", 0, 0, OPT_ENUM_FORMATS},
 	{"enum-inputs", 0, 0, OPT_ENUM_INPUTS},
+	{"fd", 1, 0, OPT_FD},
 	{"file", 2, 0, 'F'},
 	{"fill-frames", 0, 0, 'I'},
 	{"format", 1, 0, 'f'},
@@ -1297,7 +1305,11 @@  static struct option opts[] = {
 int main(int argc, char *argv[])
 {
 	struct sched_param sched;
-	struct device dev = { 0 };
+	struct device dev = {
+		.fd = -1,
+		.memtype = V4L2_MEMORY_MMAP,
+		.type = (enum v4l2_buf_type)-1,
+	};
 	int ret;
 
 	/* Options parsings */
@@ -1452,6 +1464,14 @@  int main(int argc, char *argv[])
 		case OPT_ENUM_INPUTS:
 			do_enum_inputs = 1;
 			break;
+		case OPT_FD:
+			dev.fd = atoi(optarg);
+			if (dev.fd < 0) {
+				printf("Bad file descriptor %d\n", dev.fd);
+				return 1;
+			}
+			printf("Using file descriptor %d\n", dev.fd);
+			break;
 		case OPT_NO_QUERY:
 			no_query = 1;
 			break;
@@ -1482,18 +1502,21 @@  int main(int argc, char *argv[])
 		return 1;
 	}
 
-	if (optind >= argc) {
-		usage(argv[0]);
-		return 1;
-	}
-
 	if (!do_file)
 		filename = NULL;
 
-	/* Open the video device. If the device type isn't recognized, set the
-	 * --no-query option to avoid querying V4L2 subdevs.
-	 */
-	ret = video_open(&dev, argv[optind], no_query);
+	if (dev.fd == -1) {
+		if (optind >= argc) {
+			usage(argv[0]);
+			return 1;
+		} else {
+			ret = video_open(&dev, argv[optind]);
+			if (ret < 0)
+				return 1;
+		}
+	}
+
+	ret = video_querycap(&dev, no_query);
 	if (ret < 0)
 		return 1;