Home | History | Annotate | Line # | Download | only in videoctl
videoctl.c revision 1.2
      1  1.2     joerg /* $NetBSD: videoctl.c,v 1.2 2011/09/16 15:39:30 joerg Exp $ */
      2  1.1  jmcneill 
      3  1.1  jmcneill /*-
      4  1.1  jmcneill  * Copyright (c) 2010 Jared D. McNeill <jmcneill (at) invisible.ca>
      5  1.1  jmcneill  * All rights reserved.
      6  1.1  jmcneill  *
      7  1.1  jmcneill  * Redistribution and use in source and binary forms, with or without
      8  1.1  jmcneill  * modification, are permitted provided that the following conditions
      9  1.1  jmcneill  * are met:
     10  1.1  jmcneill  * 1. Redistributions of source code must retain the above copyright
     11  1.1  jmcneill  *    notice, this list of conditions and the following disclaimer.
     12  1.1  jmcneill  * 2. Redistributions in binary form must reproduce the above copyright
     13  1.1  jmcneill  *    notice, this list of conditions and the following disclaimer in the
     14  1.1  jmcneill  *    documentation and/or other materials provided with the distribution.
     15  1.1  jmcneill  *
     16  1.1  jmcneill  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
     17  1.1  jmcneill  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
     18  1.1  jmcneill  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     19  1.1  jmcneill  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
     20  1.1  jmcneill  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
     21  1.1  jmcneill  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
     22  1.1  jmcneill  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
     23  1.1  jmcneill  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
     24  1.1  jmcneill  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
     25  1.1  jmcneill  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
     26  1.1  jmcneill  * POSSIBILITY OF SUCH DAMAGE.
     27  1.1  jmcneill  */
     28  1.1  jmcneill 
     29  1.1  jmcneill #include <sys/cdefs.h>
     30  1.1  jmcneill __COPYRIGHT("@(#) Copyright (c) 2010\
     31  1.1  jmcneill  Jared D. McNeill <jmcneill (at) invisible.ca>. All rights reserved.");
     32  1.2     joerg __RCSID("$NetBSD: videoctl.c,v 1.2 2011/09/16 15:39:30 joerg Exp $");
     33  1.1  jmcneill 
     34  1.1  jmcneill #include <sys/types.h>
     35  1.1  jmcneill #include <sys/ioctl.h>
     36  1.1  jmcneill #include <sys/videoio.h>
     37  1.1  jmcneill 
     38  1.1  jmcneill #include <err.h>
     39  1.1  jmcneill #include <errno.h>
     40  1.1  jmcneill #include <fcntl.h>
     41  1.1  jmcneill #include <limits.h>
     42  1.1  jmcneill #include <paths.h>
     43  1.1  jmcneill #include <stdio.h>
     44  1.1  jmcneill #include <string.h>
     45  1.1  jmcneill #include <stdbool.h>
     46  1.1  jmcneill #include <stdlib.h>
     47  1.1  jmcneill #include <unistd.h>
     48  1.1  jmcneill #include <util.h>
     49  1.1  jmcneill 
     50  1.2     joerg __dead static void	usage(void);
     51  1.1  jmcneill static void		video_print(const char *);
     52  1.1  jmcneill static void		video_print_all(void);
     53  1.1  jmcneill static bool		video_print_caps(const char *);
     54  1.1  jmcneill static bool		video_print_formats(const char *);
     55  1.1  jmcneill static bool		video_print_inputs(const char *);
     56  1.1  jmcneill static bool		video_print_audios(const char *);
     57  1.1  jmcneill static bool		video_print_standards(const char *);
     58  1.1  jmcneill static bool		video_print_tuners(const char *);
     59  1.1  jmcneill static bool		video_print_ctrl(uint32_t);
     60  1.1  jmcneill static void		video_set(const char *);
     61  1.1  jmcneill static bool		video_set_ctrl(uint32_t, int32_t);
     62  1.1  jmcneill static const char *	video_cid2name(uint32_t);
     63  1.1  jmcneill static uint32_t		video_name2cid(const char *);
     64  1.1  jmcneill 
     65  1.1  jmcneill static const char *video_dev = NULL;
     66  1.1  jmcneill static int video_fd = -1;
     67  1.1  jmcneill static bool aflag = false;
     68  1.1  jmcneill static bool wflag = false;
     69  1.1  jmcneill 
     70  1.1  jmcneill static const struct {
     71  1.1  jmcneill 	uint32_t	id;
     72  1.1  jmcneill 	const char	*name;
     73  1.1  jmcneill } videoctl_cid_names[] = {
     74  1.1  jmcneill 	{ V4L2_CID_BRIGHTNESS,		"brightness" },
     75  1.1  jmcneill 	{ V4L2_CID_CONTRAST,		"contrast" },
     76  1.1  jmcneill 	{ V4L2_CID_SATURATION,		"saturation" },
     77  1.1  jmcneill 	{ V4L2_CID_HUE,			"hue" },
     78  1.1  jmcneill 	{ V4L2_CID_AUDIO_VOLUME,	"audio_volume" },
     79  1.1  jmcneill 	{ V4L2_CID_AUDIO_BALANCE,	"audio_balance" },
     80  1.1  jmcneill 	{ V4L2_CID_AUDIO_BASS,		"audio_bass" },
     81  1.1  jmcneill 	{ V4L2_CID_AUDIO_TREBLE,	"audio_treble" },
     82  1.1  jmcneill 	{ V4L2_CID_AUDIO_MUTE,		"audio_mute" },
     83  1.1  jmcneill 	{ V4L2_CID_AUDIO_LOUDNESS,	"audio_loudness" },
     84  1.1  jmcneill 	{ V4L2_CID_BLACK_LEVEL,		"black_level" },
     85  1.1  jmcneill 	{ V4L2_CID_AUTO_WHITE_BALANCE,	"auto_white_balance" },
     86  1.1  jmcneill 	{ V4L2_CID_DO_WHITE_BALANCE,	"do_white_balance" },
     87  1.1  jmcneill 	{ V4L2_CID_RED_BALANCE,		"red_balance" },
     88  1.1  jmcneill 	{ V4L2_CID_BLUE_BALANCE,	"blue_balance" },
     89  1.1  jmcneill 	{ V4L2_CID_GAMMA,		"gamma" },
     90  1.1  jmcneill 	{ V4L2_CID_WHITENESS,		"whiteness" },
     91  1.1  jmcneill 	{ V4L2_CID_EXPOSURE,		"exposure" },
     92  1.1  jmcneill 	{ V4L2_CID_AUTOGAIN,		"autogain" },
     93  1.1  jmcneill 	{ V4L2_CID_GAIN,		"gain" },
     94  1.1  jmcneill 	{ V4L2_CID_HFLIP,		"hflip" },
     95  1.1  jmcneill 	{ V4L2_CID_VFLIP,		"vflip" },
     96  1.1  jmcneill 	{ V4L2_CID_HCENTER,		"hcenter" },
     97  1.1  jmcneill 	{ V4L2_CID_VCENTER,		"vcenter" },
     98  1.1  jmcneill 	{ V4L2_CID_POWER_LINE_FREQUENCY, "power_line_frequency" },
     99  1.1  jmcneill 	{ V4L2_CID_HUE_AUTO,		"hue_auto" },
    100  1.1  jmcneill 	{ V4L2_CID_WHITE_BALANCE_TEMPERATURE, "white_balance_temperature" },
    101  1.1  jmcneill 	{ V4L2_CID_SHARPNESS,		"sharpness" },
    102  1.1  jmcneill 	{ V4L2_CID_BACKLIGHT_COMPENSATION, "backlight_compensation" },
    103  1.1  jmcneill };
    104  1.1  jmcneill 
    105  1.1  jmcneill int
    106  1.1  jmcneill main(int argc, char *argv[])
    107  1.1  jmcneill {
    108  1.1  jmcneill 	int ch;
    109  1.1  jmcneill 
    110  1.1  jmcneill 	setprogname(argv[0]);
    111  1.1  jmcneill 
    112  1.1  jmcneill 	while ((ch = getopt(argc, argv, "ad:w")) != -1) {
    113  1.1  jmcneill 		switch (ch) {
    114  1.1  jmcneill 		case 'a':
    115  1.1  jmcneill 			aflag = true;
    116  1.1  jmcneill 			break;
    117  1.1  jmcneill 		case 'd':
    118  1.1  jmcneill 			video_dev = strdup(optarg);
    119  1.1  jmcneill 			break;
    120  1.1  jmcneill 		case 'w':
    121  1.1  jmcneill 			wflag = true;
    122  1.1  jmcneill 			break;
    123  1.1  jmcneill 		case 'h':
    124  1.1  jmcneill 		default:
    125  1.1  jmcneill 			usage();
    126  1.1  jmcneill 			/* NOTREACHED */
    127  1.1  jmcneill 		}
    128  1.1  jmcneill 	}
    129  1.1  jmcneill 	argc -= optind;
    130  1.1  jmcneill 	argv += optind;
    131  1.1  jmcneill 
    132  1.1  jmcneill 	if (wflag && aflag)
    133  1.1  jmcneill 		usage();
    134  1.1  jmcneill 		/* NOTREACHED */
    135  1.1  jmcneill 	if (wflag && argc == 0)
    136  1.1  jmcneill 		usage();
    137  1.1  jmcneill 		/* NOTREACHED */
    138  1.1  jmcneill 	if (aflag && argc > 0)
    139  1.1  jmcneill 		usage();
    140  1.1  jmcneill 		/* NOTREACHED */
    141  1.1  jmcneill 	if (!wflag && !aflag && argc == 0)
    142  1.1  jmcneill 		usage();
    143  1.1  jmcneill 		/* NOTREACHED */
    144  1.1  jmcneill 
    145  1.1  jmcneill 	if (video_dev == NULL)
    146  1.1  jmcneill 		video_dev = _PATH_VIDEO0;
    147  1.1  jmcneill 
    148  1.1  jmcneill 	video_fd = open(video_dev, wflag ? O_RDWR : O_RDONLY);
    149  1.1  jmcneill 	if (video_fd == -1)
    150  1.1  jmcneill 		err(EXIT_FAILURE, "couldn't open '%s'", video_dev);
    151  1.1  jmcneill 
    152  1.1  jmcneill 	if (aflag) {
    153  1.1  jmcneill 		video_print_all();
    154  1.1  jmcneill 	} else if (wflag) {
    155  1.1  jmcneill 		while (argc > 0) {
    156  1.1  jmcneill 			video_set(argv[0]);
    157  1.1  jmcneill 			--argc;
    158  1.1  jmcneill 			++argv;
    159  1.1  jmcneill 		}
    160  1.1  jmcneill 	} else {
    161  1.1  jmcneill 		while (argc > 0) {
    162  1.1  jmcneill 			video_print(argv[0]);
    163  1.1  jmcneill 			--argc;
    164  1.1  jmcneill 			++argv;
    165  1.1  jmcneill 		}
    166  1.1  jmcneill 	}
    167  1.1  jmcneill 
    168  1.1  jmcneill 	close(video_fd);
    169  1.1  jmcneill 
    170  1.1  jmcneill 	return EXIT_SUCCESS;
    171  1.1  jmcneill }
    172  1.1  jmcneill 
    173  1.1  jmcneill static void
    174  1.1  jmcneill usage(void)
    175  1.1  jmcneill {
    176  1.1  jmcneill 	fprintf(stderr, "usage: %s [-d file] name ...\n", getprogname());
    177  1.1  jmcneill 	fprintf(stderr, "usage: %s [-d file] -w name=value ...\n",
    178  1.1  jmcneill 	    getprogname());
    179  1.1  jmcneill 	fprintf(stderr, "usage: %s [-d file] -a\n", getprogname());
    180  1.1  jmcneill 	exit(EXIT_FAILURE);
    181  1.1  jmcneill }
    182  1.1  jmcneill 
    183  1.1  jmcneill static void
    184  1.1  jmcneill video_print_all(void)
    185  1.1  jmcneill {
    186  1.1  jmcneill 	video_print_caps(NULL);
    187  1.1  jmcneill 	video_print_formats(NULL);
    188  1.1  jmcneill 	video_print_inputs(NULL);
    189  1.1  jmcneill 	video_print_audios(NULL);
    190  1.1  jmcneill 	video_print_standards(NULL);
    191  1.1  jmcneill 	video_print_tuners(NULL);
    192  1.1  jmcneill 	video_print_ctrl(0);
    193  1.1  jmcneill }
    194  1.1  jmcneill 
    195  1.1  jmcneill static bool
    196  1.1  jmcneill video_print_caps(const char *name)
    197  1.1  jmcneill {
    198  1.1  jmcneill 	struct v4l2_capability cap;
    199  1.1  jmcneill 	char capbuf[128];
    200  1.1  jmcneill 	int error;
    201  1.1  jmcneill 	bool found = false;
    202  1.1  jmcneill 
    203  1.1  jmcneill 	if (strtok(NULL, ".") != NULL)
    204  1.1  jmcneill 		return false;
    205  1.1  jmcneill 
    206  1.1  jmcneill 	/* query capabilities */
    207  1.1  jmcneill 	error = ioctl(video_fd, VIDIOC_QUERYCAP, &cap);
    208  1.1  jmcneill 	if (error == -1)
    209  1.1  jmcneill 		err(EXIT_FAILURE, "VIDIOC_QUERYCAP failed");
    210  1.1  jmcneill 
    211  1.1  jmcneill 	if (!name || strcmp(name, "card") == 0) {
    212  1.1  jmcneill 		printf("info.cap.card=%s\n", cap.card);
    213  1.1  jmcneill 		found = true;
    214  1.1  jmcneill 	}
    215  1.1  jmcneill 	if (!name || strcmp(name, "driver") == 0) {
    216  1.1  jmcneill 		printf("info.cap.driver=%s\n", cap.driver);
    217  1.1  jmcneill 		found = true;
    218  1.1  jmcneill 	}
    219  1.1  jmcneill 	if (!name || strcmp(name, "bus_info") == 0) {
    220  1.1  jmcneill 		printf("info.cap.bus_info=%s\n", cap.bus_info);
    221  1.1  jmcneill 		found = true;
    222  1.1  jmcneill 	}
    223  1.1  jmcneill 	if (!name || strcmp(name, "version") == 0) {
    224  1.1  jmcneill 		printf("info.cap.version=%u.%u.%u\n",
    225  1.1  jmcneill 		    (cap.version >> 16) & 0xff,
    226  1.1  jmcneill 		    (cap.version >> 8) & 0xff,
    227  1.1  jmcneill 		    cap.version & 0xff);
    228  1.1  jmcneill 		found = true;
    229  1.1  jmcneill 	}
    230  1.1  jmcneill 	if (!name || strcmp(name, "capabilities") == 0) {
    231  1.1  jmcneill 		snprintb(capbuf, sizeof(capbuf), V4L2_CAP_BITMASK,
    232  1.1  jmcneill 		    cap.capabilities);
    233  1.1  jmcneill 		printf("info.cap.capabilities=%s\n", capbuf);
    234  1.1  jmcneill 		found = true;
    235  1.1  jmcneill 	}
    236  1.1  jmcneill 
    237  1.1  jmcneill 	return found;
    238  1.1  jmcneill }
    239  1.1  jmcneill 
    240  1.1  jmcneill static bool
    241  1.1  jmcneill video_print_formats(const char *name)
    242  1.1  jmcneill {
    243  1.1  jmcneill 	struct v4l2_fmtdesc fmtdesc;
    244  1.1  jmcneill 	int error;
    245  1.1  jmcneill 
    246  1.1  jmcneill 	fmtdesc.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
    247  1.1  jmcneill 	if (name == NULL) {
    248  1.1  jmcneill 		/* enumerate formats */
    249  1.1  jmcneill 		for (fmtdesc.index = 0; ; fmtdesc.index++) {
    250  1.1  jmcneill 			error = ioctl(video_fd, VIDIOC_ENUM_FMT, &fmtdesc);
    251  1.1  jmcneill 			if (error)
    252  1.1  jmcneill 				break;
    253  1.1  jmcneill 			printf("info.format.%u=%s\n", fmtdesc.index,
    254  1.1  jmcneill 			    fmtdesc.description);
    255  1.1  jmcneill 		}
    256  1.1  jmcneill 	} else {
    257  1.1  jmcneill 		unsigned long n;
    258  1.1  jmcneill 
    259  1.1  jmcneill 		if (strtok(NULL, ".") != NULL)
    260  1.1  jmcneill 			return false;
    261  1.1  jmcneill 
    262  1.1  jmcneill 		n = strtoul(name, NULL, 10);
    263  1.1  jmcneill 		if (n == ULONG_MAX)
    264  1.1  jmcneill 			return false;
    265  1.1  jmcneill 		fmtdesc.index = n;
    266  1.1  jmcneill 		error = ioctl(video_fd, VIDIOC_ENUM_FMT, &fmtdesc);
    267  1.1  jmcneill 		if (error)
    268  1.1  jmcneill 			return false;
    269  1.1  jmcneill 		printf("info.format.%u=%s\n", fmtdesc.index,
    270  1.1  jmcneill 		    fmtdesc.description);
    271  1.1  jmcneill 	}
    272  1.1  jmcneill 
    273  1.1  jmcneill 	return true;
    274  1.1  jmcneill }
    275  1.1  jmcneill 
    276  1.1  jmcneill static bool
    277  1.1  jmcneill video_print_inputs(const char *name)
    278  1.1  jmcneill {
    279  1.1  jmcneill 	struct v4l2_input input;
    280  1.1  jmcneill 	int error;
    281  1.1  jmcneill 
    282  1.1  jmcneill 	if (name == NULL) {
    283  1.1  jmcneill 		/* enumerate inputs */
    284  1.1  jmcneill 		for (input.index = 0; ; input.index++) {
    285  1.1  jmcneill 			error = ioctl(video_fd, VIDIOC_ENUMINPUT, &input);
    286  1.1  jmcneill 			if (error)
    287  1.1  jmcneill 				break;
    288  1.1  jmcneill 			printf("info.input.%u=%s\n", input.index, input.name);
    289  1.1  jmcneill 			printf("info.input.%u.type=", input.index);
    290  1.1  jmcneill 			switch (input.type) {
    291  1.1  jmcneill 			case V4L2_INPUT_TYPE_TUNER:
    292  1.1  jmcneill 				printf("tuner\n");
    293  1.1  jmcneill 				break;
    294  1.1  jmcneill 			case V4L2_INPUT_TYPE_CAMERA:
    295  1.1  jmcneill 				printf("baseband\n");
    296  1.1  jmcneill 				break;
    297  1.1  jmcneill 			default:
    298  1.1  jmcneill 				printf("unknown (%d)\n", input.type);
    299  1.1  jmcneill 				break;
    300  1.1  jmcneill 			}
    301  1.1  jmcneill 		}
    302  1.1  jmcneill 	} else {
    303  1.1  jmcneill 		unsigned long n;
    304  1.1  jmcneill 		char *s;
    305  1.1  jmcneill 
    306  1.1  jmcneill 		n = strtoul(name, NULL, 10);
    307  1.1  jmcneill 		if (n == ULONG_MAX)
    308  1.1  jmcneill 			return false;
    309  1.1  jmcneill 		input.index = n;
    310  1.1  jmcneill 		error = ioctl(video_fd, VIDIOC_ENUMINPUT, &input);
    311  1.1  jmcneill 		if (error)
    312  1.1  jmcneill 			return false;
    313  1.1  jmcneill 
    314  1.1  jmcneill 		s = strtok(NULL, ".");
    315  1.1  jmcneill 		if (s == NULL) {
    316  1.1  jmcneill 			printf("info.input.%u=%s\n", input.index, input.name);
    317  1.1  jmcneill 		} else if (strcmp(s, "type") == 0) {
    318  1.1  jmcneill 			if (strtok(NULL, ".") != NULL)
    319  1.1  jmcneill 				return false;
    320  1.1  jmcneill 			printf("info.input.%u.type=", input.index);
    321  1.1  jmcneill 			switch (input.type) {
    322  1.1  jmcneill 			case V4L2_INPUT_TYPE_TUNER:
    323  1.1  jmcneill 				printf("tuner\n");
    324  1.1  jmcneill 				break;
    325  1.1  jmcneill 			case V4L2_INPUT_TYPE_CAMERA:
    326  1.1  jmcneill 				printf("baseband\n");
    327  1.1  jmcneill 				break;
    328  1.1  jmcneill 			default:
    329  1.1  jmcneill 				printf("unknown (%d)\n", input.type);
    330  1.1  jmcneill 				break;
    331  1.1  jmcneill 			}
    332  1.1  jmcneill 		} else
    333  1.1  jmcneill 			return false;
    334  1.1  jmcneill 	}
    335  1.1  jmcneill 
    336  1.1  jmcneill 	return true;
    337  1.1  jmcneill }
    338  1.1  jmcneill 
    339  1.1  jmcneill static bool
    340  1.1  jmcneill video_print_audios(const char *name)
    341  1.1  jmcneill {
    342  1.1  jmcneill 	struct v4l2_audio audio;
    343  1.1  jmcneill 	int error;
    344  1.1  jmcneill 
    345  1.1  jmcneill 	if (name == NULL) {
    346  1.1  jmcneill 		/* enumerate audio */
    347  1.1  jmcneill 		for (audio.index = 0; ; audio.index++) {
    348  1.1  jmcneill 			error = ioctl(video_fd, VIDIOC_ENUMAUDIO, &audio);
    349  1.1  jmcneill 			if (error)
    350  1.1  jmcneill 				break;
    351  1.1  jmcneill 			printf("info.audio.%u=%s\n", audio.index, audio.name);
    352  1.1  jmcneill 			printf("info.audio.%u.stereo=%d\n", audio.index,
    353  1.1  jmcneill 			    audio.capability & V4L2_AUDCAP_STEREO ? 1 : 0);
    354  1.1  jmcneill 			printf("info.audio.%u.avl=%d\n", audio.index,
    355  1.1  jmcneill 			    audio.capability & V4L2_AUDCAP_AVL ? 1 : 0);
    356  1.1  jmcneill 		}
    357  1.1  jmcneill 	} else {
    358  1.1  jmcneill 		unsigned long n;
    359  1.1  jmcneill 		char *s;
    360  1.1  jmcneill 
    361  1.1  jmcneill 		n = strtoul(name, NULL, 10);
    362  1.1  jmcneill 		if (n == ULONG_MAX)
    363  1.1  jmcneill 			return false;
    364  1.1  jmcneill 		audio.index = n;
    365  1.1  jmcneill 		error = ioctl(video_fd, VIDIOC_ENUMAUDIO, &audio);
    366  1.1  jmcneill 		if (error)
    367  1.1  jmcneill 			return false;
    368  1.1  jmcneill 
    369  1.1  jmcneill 		s = strtok(NULL, ".");
    370  1.1  jmcneill 		if (s == NULL) {
    371  1.1  jmcneill 			printf("info.audio.%u=%s\n", audio.index, audio.name);
    372  1.1  jmcneill 		} else if (strcmp(s, "stereo") == 0) {
    373  1.1  jmcneill 			if (strtok(NULL, ".") != NULL)
    374  1.1  jmcneill 				return false;
    375  1.1  jmcneill 			printf("info.audio.%u.stereo=%d\n", audio.index,
    376  1.1  jmcneill 			    audio.capability & V4L2_AUDCAP_STEREO ? 1 : 0);
    377  1.1  jmcneill 		} else if (strcmp(s, "avl") == 0) {
    378  1.1  jmcneill 			if (strtok(NULL, ".") != NULL)
    379  1.1  jmcneill 				return false;
    380  1.1  jmcneill 			printf("info.audio.%u.avl=%d\n", audio.index,
    381  1.1  jmcneill 			    audio.capability & V4L2_AUDCAP_AVL ? 1 : 0);
    382  1.1  jmcneill 		} else
    383  1.1  jmcneill 			return false;
    384  1.1  jmcneill 	}
    385  1.1  jmcneill 
    386  1.1  jmcneill 	return true;
    387  1.1  jmcneill }
    388  1.1  jmcneill 
    389  1.1  jmcneill static bool
    390  1.1  jmcneill video_print_standards(const char *name)
    391  1.1  jmcneill {
    392  1.1  jmcneill 	struct v4l2_standard std;
    393  1.1  jmcneill 	int error;
    394  1.1  jmcneill 
    395  1.1  jmcneill 	if (name == NULL) {
    396  1.1  jmcneill 		/* enumerate standards */
    397  1.1  jmcneill 		for (std.index = 0; ; std.index++) {
    398  1.1  jmcneill 			error = ioctl(video_fd, VIDIOC_ENUMSTD, &std);
    399  1.1  jmcneill 			if (error)
    400  1.1  jmcneill 				break;
    401  1.1  jmcneill 			printf("info.standard.%u=%s\n", std.index, std.name);
    402  1.1  jmcneill 		}
    403  1.1  jmcneill 	} else {
    404  1.1  jmcneill 		unsigned long n;
    405  1.1  jmcneill 
    406  1.1  jmcneill 		if (strtok(NULL, ".") != NULL)
    407  1.1  jmcneill 			return false;
    408  1.1  jmcneill 
    409  1.1  jmcneill 		n = strtoul(name, NULL, 10);
    410  1.1  jmcneill 		if (n == ULONG_MAX)
    411  1.1  jmcneill 			return false;
    412  1.1  jmcneill 		std.index = n;
    413  1.1  jmcneill 		error = ioctl(video_fd, VIDIOC_ENUMSTD, &std);
    414  1.1  jmcneill 		if (error)
    415  1.1  jmcneill 			return false;
    416  1.1  jmcneill 		printf("info.standard.%u=%s\n", std.index, std.name);
    417  1.1  jmcneill 	}
    418  1.1  jmcneill 
    419  1.1  jmcneill 	return true;
    420  1.1  jmcneill }
    421  1.1  jmcneill 
    422  1.1  jmcneill static bool
    423  1.1  jmcneill video_print_tuners(const char *name)
    424  1.1  jmcneill {
    425  1.1  jmcneill 	struct v4l2_tuner tuner;
    426  1.1  jmcneill 	int error;
    427  1.1  jmcneill 
    428  1.1  jmcneill 	if (name == NULL) {
    429  1.1  jmcneill 		/* enumerate tuners */
    430  1.1  jmcneill 		for (tuner.index = 0; ; tuner.index++) {
    431  1.1  jmcneill 			error = ioctl(video_fd, VIDIOC_G_TUNER, &tuner);
    432  1.1  jmcneill 			if (error)
    433  1.1  jmcneill 				break;
    434  1.1  jmcneill 			printf("info.tuner.%u=%s\n", tuner.index, tuner.name);
    435  1.1  jmcneill 		}
    436  1.1  jmcneill 	} else {
    437  1.1  jmcneill 		unsigned long n;
    438  1.1  jmcneill 
    439  1.1  jmcneill 		if (strtok(NULL, ".") != NULL)
    440  1.1  jmcneill 			return false;
    441  1.1  jmcneill 
    442  1.1  jmcneill 		n = strtoul(name, NULL, 10);
    443  1.1  jmcneill 		if (n == ULONG_MAX)
    444  1.1  jmcneill 			return false;
    445  1.1  jmcneill 		tuner.index = n;
    446  1.1  jmcneill 		error = ioctl(video_fd, VIDIOC_G_TUNER, &tuner);
    447  1.1  jmcneill 		if (error)
    448  1.1  jmcneill 			return false;
    449  1.1  jmcneill 		printf("info.tuner.%u=%s\n", tuner.index, tuner.name);
    450  1.1  jmcneill 	}
    451  1.1  jmcneill 
    452  1.1  jmcneill 	return true;
    453  1.1  jmcneill }
    454  1.1  jmcneill 
    455  1.1  jmcneill static void
    456  1.1  jmcneill video_print(const char *name)
    457  1.1  jmcneill {
    458  1.1  jmcneill 	char *buf, *s, *s2 = NULL;
    459  1.1  jmcneill 	bool found = false;
    460  1.1  jmcneill 
    461  1.1  jmcneill 	buf = strdup(name);
    462  1.1  jmcneill 	s = strtok(buf, ".");
    463  1.1  jmcneill 	if (s == NULL)
    464  1.1  jmcneill 		return;
    465  1.1  jmcneill 
    466  1.1  jmcneill 	if (strcmp(s, "info") == 0) {
    467  1.1  jmcneill 		s = strtok(NULL, ".");
    468  1.1  jmcneill 		if (s)
    469  1.1  jmcneill 			s2 = strtok(NULL, ".");
    470  1.1  jmcneill 		if (s == NULL || strcmp(s, "cap") == 0) {
    471  1.1  jmcneill 			found = video_print_caps(s2);
    472  1.1  jmcneill 		}
    473  1.1  jmcneill 		if (s == NULL || strcmp(s, "format") == 0) {
    474  1.1  jmcneill 			found = video_print_formats(s2);
    475  1.1  jmcneill 		}
    476  1.1  jmcneill 		if (s == NULL || strcmp(s, "input") == 0) {
    477  1.1  jmcneill 			found = video_print_inputs(s2);
    478  1.1  jmcneill 		}
    479  1.1  jmcneill 		if (s == NULL || strcmp(s, "audio") == 0) {
    480  1.1  jmcneill 			found = video_print_audios(s2);
    481  1.1  jmcneill 		}
    482  1.1  jmcneill 		if (s == NULL || strcmp(s, "standard") == 0) {
    483  1.1  jmcneill 			found = video_print_standards(s2);
    484  1.1  jmcneill 		}
    485  1.1  jmcneill 		if (s == NULL || strcmp(s, "tuner") == 0) {
    486  1.1  jmcneill 			found = video_print_tuners(s2);
    487  1.1  jmcneill 		}
    488  1.1  jmcneill 	} else if (strcmp(s, "ctrl") == 0) {
    489  1.1  jmcneill 		s = strtok(NULL, ".");
    490  1.1  jmcneill 		if (s)
    491  1.1  jmcneill 			s2 = strtok(NULL, ".");
    492  1.1  jmcneill 
    493  1.1  jmcneill 		if (s == NULL)
    494  1.1  jmcneill 			found = video_print_ctrl(0);
    495  1.1  jmcneill 		else if (s && !s2)
    496  1.1  jmcneill 			found = video_print_ctrl(video_name2cid(s));
    497  1.1  jmcneill 	}
    498  1.1  jmcneill 
    499  1.1  jmcneill 	free(buf);
    500  1.1  jmcneill 	if (!found)
    501  1.1  jmcneill 		fprintf(stderr, "%s: field %s does not exist\n",
    502  1.1  jmcneill 		    getprogname(), name);
    503  1.1  jmcneill }
    504  1.1  jmcneill 
    505  1.1  jmcneill static bool
    506  1.1  jmcneill video_print_ctrl(uint32_t ctrl_id)
    507  1.1  jmcneill {
    508  1.1  jmcneill 	struct v4l2_control ctrl;
    509  1.1  jmcneill 	const char *ctrlname;
    510  1.1  jmcneill 	bool found = false;
    511  1.1  jmcneill 	int error;
    512  1.1  jmcneill 
    513  1.1  jmcneill 	for (ctrl.id = V4L2_CID_BASE; ctrl.id != V4L2_CID_LASTP1; ctrl.id++) {
    514  1.1  jmcneill 		if (ctrl_id != 0 && ctrl_id != ctrl.id)
    515  1.1  jmcneill 			continue;
    516  1.1  jmcneill 		error = ioctl(video_fd, VIDIOC_G_CTRL, &ctrl);
    517  1.1  jmcneill 		if (error)
    518  1.1  jmcneill 			continue;
    519  1.1  jmcneill 		ctrlname = video_cid2name(ctrl.id);
    520  1.1  jmcneill 		if (ctrlname)
    521  1.1  jmcneill 			printf("ctrl.%s=%d\n", ctrlname, ctrl.value);
    522  1.1  jmcneill 		else
    523  1.1  jmcneill 			printf("ctrl.%08x=%d\n", ctrl.id, ctrl.value);
    524  1.1  jmcneill 		found = true;
    525  1.1  jmcneill 	}
    526  1.1  jmcneill 
    527  1.1  jmcneill 	return found;
    528  1.1  jmcneill }
    529  1.1  jmcneill 
    530  1.1  jmcneill static void
    531  1.1  jmcneill video_set(const char *name)
    532  1.1  jmcneill {
    533  1.1  jmcneill 	char *buf, *key, *value;
    534  1.1  jmcneill 	bool found = false;
    535  1.1  jmcneill 	long n;
    536  1.1  jmcneill 
    537  1.1  jmcneill 	if (strchr(name, '=') == NULL) {
    538  1.1  jmcneill 		fprintf(stderr, "%s: No '=' in %s\n", getprogname(), name);
    539  1.1  jmcneill 		exit(EXIT_FAILURE);
    540  1.1  jmcneill 	}
    541  1.1  jmcneill 
    542  1.1  jmcneill 	buf = strdup(name);
    543  1.1  jmcneill 	key = strtok(buf, "=");
    544  1.1  jmcneill 	if (key == NULL)
    545  1.1  jmcneill 		usage();
    546  1.1  jmcneill 		/* NOTREACHED */
    547  1.1  jmcneill 	value = strtok(NULL, "");
    548  1.1  jmcneill 	if (value == NULL)
    549  1.1  jmcneill 		usage();
    550  1.1  jmcneill 		/* NOTREACHED */
    551  1.1  jmcneill 
    552  1.1  jmcneill 	if (strncmp(key, "info.", strlen("info.")) == 0) {
    553  1.1  jmcneill 		fprintf(stderr, "'info' subtree read-only\n");
    554  1.1  jmcneill 		found = true;
    555  1.1  jmcneill 		goto done;
    556  1.1  jmcneill 	}
    557  1.1  jmcneill 	if (strncmp(key, "ctrl.", strlen("ctrl.")) == 0) {
    558  1.1  jmcneill 		char *ctrlname = key + strlen("ctrl.");
    559  1.1  jmcneill 		uint32_t ctrl_id = video_name2cid(ctrlname);
    560  1.1  jmcneill 
    561  1.1  jmcneill 		n = strtol(value, NULL, 0);
    562  1.1  jmcneill 		if (n == LONG_MIN || n == LONG_MAX)
    563  1.1  jmcneill 			goto done;
    564  1.1  jmcneill 		found = video_set_ctrl(ctrl_id, n);
    565  1.1  jmcneill 	}
    566  1.1  jmcneill 
    567  1.1  jmcneill done:
    568  1.1  jmcneill 	free(buf);
    569  1.1  jmcneill 	if (!found)
    570  1.1  jmcneill 		fprintf(stderr, "%s: field %s does not exist\n",
    571  1.1  jmcneill 		    getprogname(), name);
    572  1.1  jmcneill }
    573  1.1  jmcneill 
    574  1.1  jmcneill static bool
    575  1.1  jmcneill video_set_ctrl(uint32_t ctrl_id, int32_t value)
    576  1.1  jmcneill {
    577  1.1  jmcneill 	struct v4l2_control ctrl;
    578  1.1  jmcneill 	const char *ctrlname;
    579  1.1  jmcneill 	int32_t ovalue;
    580  1.1  jmcneill 	int error;
    581  1.1  jmcneill 
    582  1.1  jmcneill 	ctrlname = video_cid2name(ctrl_id);
    583  1.1  jmcneill 
    584  1.1  jmcneill 	ctrl.id = ctrl_id;
    585  1.1  jmcneill 	error = ioctl(video_fd, VIDIOC_G_CTRL, &ctrl);
    586  1.1  jmcneill 	if (error)
    587  1.1  jmcneill 		return false;
    588  1.1  jmcneill 	ovalue = ctrl.value;
    589  1.1  jmcneill 	ctrl.value = value;
    590  1.1  jmcneill 	error = ioctl(video_fd, VIDIOC_S_CTRL, &ctrl);
    591  1.1  jmcneill 	if (error)
    592  1.1  jmcneill 		err(EXIT_FAILURE, "VIDIOC_S_CTRL failed for '%s'", ctrlname);
    593  1.1  jmcneill 	error = ioctl(video_fd, VIDIOC_G_CTRL, &ctrl);
    594  1.1  jmcneill 	if (error)
    595  1.1  jmcneill 		err(EXIT_FAILURE, "VIDIOC_G_CTRL failed for '%s'", ctrlname);
    596  1.1  jmcneill 
    597  1.1  jmcneill 	if (ctrlname)
    598  1.1  jmcneill 		printf("ctrl.%s: %d -> %d\n", ctrlname, ovalue, ctrl.value);
    599  1.1  jmcneill 	else
    600  1.1  jmcneill 		printf("ctrl.%08x: %d -> %d\n", ctrl.id, ovalue, ctrl.value);
    601  1.1  jmcneill 
    602  1.1  jmcneill 	return true;
    603  1.1  jmcneill }
    604  1.1  jmcneill 
    605  1.1  jmcneill static const char *
    606  1.1  jmcneill video_cid2name(uint32_t id)
    607  1.1  jmcneill {
    608  1.1  jmcneill 	unsigned int i;
    609  1.1  jmcneill 
    610  1.1  jmcneill 	for (i = 0; i < __arraycount(videoctl_cid_names); i++)
    611  1.1  jmcneill 		if (videoctl_cid_names[i].id == id)
    612  1.1  jmcneill 			return videoctl_cid_names[i].name;
    613  1.1  jmcneill 
    614  1.1  jmcneill 	return NULL;
    615  1.1  jmcneill }
    616  1.1  jmcneill 
    617  1.1  jmcneill static uint32_t
    618  1.1  jmcneill video_name2cid(const char *name)
    619  1.1  jmcneill {
    620  1.1  jmcneill 	unsigned int i;
    621  1.1  jmcneill 
    622  1.1  jmcneill 	for (i = 0; i < __arraycount(videoctl_cid_names); i++)
    623  1.1  jmcneill 		if (strcmp(name, videoctl_cid_names[i].name) == 0)
    624  1.1  jmcneill 			return videoctl_cid_names[i].id;
    625  1.1  jmcneill 
    626  1.1  jmcneill 	return (uint32_t)-1;
    627  1.1  jmcneill }
    628