summaryrefslogtreecommitdiff
path: root/v4l2-apps
diff options
context:
space:
mode:
Diffstat (limited to 'v4l2-apps')
-rw-r--r--v4l2-apps/Makefile17
-rw-r--r--v4l2-apps/lib/Makefile2
-rw-r--r--v4l2-apps/lib/frequencies.c2
-rw-r--r--v4l2-apps/lib/libv4l/libv4l1/Makefile2
-rw-r--r--v4l2-apps/lib/libv4l/libv4l2/Makefile2
-rw-r--r--v4l2-apps/lib/libv4l/libv4lconvert/Makefile2
-rw-r--r--v4l2-apps/test/Makefile2
-rw-r--r--v4l2-apps/test/capture_example.c124
-rw-r--r--v4l2-apps/test/ioctl-test.c2
-rw-r--r--v4l2-apps/util/Makefile16
-rw-r--r--v4l2-apps/util/ivtv-ctl.c8
-rw-r--r--v4l2-apps/util/qv4l2/qv4l2.pro2
-rw-r--r--v4l2-apps/util/rds/Makefile2
-rw-r--r--v4l2-apps/util/v4l-board-dbg.c335
-rw-r--r--v4l2-apps/util/v4l2-compliance.cpp1122
-rw-r--r--v4l2-apps/util/v4l2-ctl.cpp594
-rw-r--r--v4l2-apps/util/v4l2-dbg-bttv.h (renamed from v4l2-apps/util/bttv-dbg.h)2
-rw-r--r--v4l2-apps/util/v4l2-dbg-em28xx.h (renamed from v4l2-apps/util/em28xx-dbg.h)2
-rw-r--r--v4l2-apps/util/v4l2-dbg-saa7134.h (renamed from v4l2-apps/util/saa7134-dbg.h)2
-rw-r--r--v4l2-apps/util/v4l2-dbg.cpp346
-rw-r--r--v4l2-apps/util/v4l2-dbg.h (renamed from v4l2-apps/util/v4l-board-dbg.h)8
-rw-r--r--v4l2-apps/util/xc3028-firmware/Makefile2
22 files changed, 1893 insertions, 703 deletions
diff --git a/v4l2-apps/Makefile b/v4l2-apps/Makefile
index 550473435..2bba8fcd4 100644
--- a/v4l2-apps/Makefile
+++ b/v4l2-apps/Makefile
@@ -1,11 +1,24 @@
# Makefile for linuxtv.org v4l2-apps
-.PHONY: all clean install
+.PHONY: all distclean clean install
-all clean install:
+all:: prepare-includes
+
+all clean install::
$(MAKE) -C lib $@
$(MAKE) -C util $@
$(MAKE) -C test $@
%:
make -C .. $(MAKECMDGOALS)
+
+clean::
+ -$(RM) -rf include
+
+distclean:: clean
+
+prepare-includes:
+ -if [ ! -d include ]; then \
+ cp -r ../linux/include include ; \
+ ../v4l/scripts/headers_convert.pl `find include -type f` ; \
+ fi
diff --git a/v4l2-apps/lib/Makefile b/v4l2-apps/lib/Makefile
index f123f3380..8443039b4 100644
--- a/v4l2-apps/lib/Makefile
+++ b/v4l2-apps/lib/Makefile
@@ -1,6 +1,6 @@
# Makefile for linuxtv.org v4l2-apps/lib
-CPPFLAGS += -I../../linux/include -I..
+CPPFLAGS += -I../include -I..
includes = v4l2.h
diff --git a/v4l2-apps/lib/frequencies.c b/v4l2-apps/lib/frequencies.c
index 77a79e61c..64379d2b0 100644
--- a/v4l2-apps/lib/frequencies.c
+++ b/v4l2-apps/lib/frequencies.c
@@ -21,7 +21,7 @@
#include <stdlib.h>
-#include "linux/videodev2.h"
+#include <linux/videodev2.h>
#include "v4l2.h"
/* This source was originally written by Nathan Laredo <laredo@gnu.org>.
diff --git a/v4l2-apps/lib/libv4l/libv4l1/Makefile b/v4l2-apps/lib/libv4l/libv4l1/Makefile
index d12e747fb..27848477e 100644
--- a/v4l2-apps/lib/libv4l/libv4l1/Makefile
+++ b/v4l2-apps/lib/libv4l/libv4l1/Makefile
@@ -1,4 +1,4 @@
-override CPPFLAGS += -I../include -I../../../../linux/include -fvisibility=hidden
+override CPPFLAGS += -I../include -I../../../include -fvisibility=hidden
CFLAGS := -g -O1
CFLAGS += -Wall -Wno-unused -Wpointer-arith -Wstrict-prototypes -Wmissing-prototypes
diff --git a/v4l2-apps/lib/libv4l/libv4l2/Makefile b/v4l2-apps/lib/libv4l/libv4l2/Makefile
index 5ed35934a..648d27c0c 100644
--- a/v4l2-apps/lib/libv4l/libv4l2/Makefile
+++ b/v4l2-apps/lib/libv4l/libv4l2/Makefile
@@ -1,4 +1,4 @@
-override CPPFLAGS += -I../include -I../../../../linux/include -fvisibility=hidden
+override CPPFLAGS += -I../include -I../../../include -fvisibility=hidden
CFLAGS := -g -O1
CFLAGS += -Wall -Wno-unused -Wpointer-arith -Wstrict-prototypes -Wmissing-prototypes
diff --git a/v4l2-apps/lib/libv4l/libv4lconvert/Makefile b/v4l2-apps/lib/libv4l/libv4lconvert/Makefile
index 798194434..641d19d6e 100644
--- a/v4l2-apps/lib/libv4l/libv4lconvert/Makefile
+++ b/v4l2-apps/lib/libv4l/libv4lconvert/Makefile
@@ -1,4 +1,4 @@
-override CPPFLAGS += -I../include -I../../../../linux/include -fvisibility=hidden
+override CPPFLAGS += -I../include -I../../../include -fvisibility=hidden
CFLAGS := -g -O1
CFLAGS += -Wall -Wno-unused -Wpointer-arith -Wstrict-prototypes -Wmissing-prototypes
diff --git a/v4l2-apps/test/Makefile b/v4l2-apps/test/Makefile
index ae8868c21..faafed14d 100644
--- a/v4l2-apps/test/Makefile
+++ b/v4l2-apps/test/Makefile
@@ -1,6 +1,6 @@
# Makefile for linuxtv.org v4l2-apps/test
-CPPFLAGS += -I../../linux/include
+CPPFLAGS += -I../include
binaries = ioctl-test \
sliced-vbi-test \
diff --git a/v4l2-apps/test/capture_example.c b/v4l2-apps/test/capture_example.c
index b2260b05f..a15ef3c09 100644
--- a/v4l2-apps/test/capture_example.c
+++ b/v4l2-apps/test/capture_example.c
@@ -36,22 +36,21 @@ typedef enum {
} io_method;
struct buffer {
- void * start;
- size_t length;
+ void *start;
+ size_t length;
};
-static char * dev_name = NULL;
-static io_method io = IO_METHOD_MMAP;
-static int fd = -1;
-struct buffer * buffers = NULL;
-static unsigned int n_buffers = 0;
-static int out_buf = 0;
+static char *dev_name;
+static io_method io = IO_METHOD_MMAP;
+static int fd = -1;
+struct buffer *buffers;
+static unsigned int n_buffers;
+static int out_buf;
+static int force_format;
static void errno_exit(const char *s)
{
- fprintf(stderr, "%s error %d, %s\n",
- s, errno, strerror(errno));
-
+ fprintf(stderr, "%s error %d, %s\n", s, errno, strerror(errno));
exit(EXIT_FAILURE);
}
@@ -68,11 +67,11 @@ static int xioctl(int fh, int request, void *arg)
static void process_image(const void *p, int size)
{
- if (!out_buf)
- fputc('.', stdout);
- else
+ if (out_buf)
fwrite(p, size, 1, stdout);
+ fflush(stderr);
+ fprintf(stderr, ".");
fflush(stdout);
}
@@ -99,7 +98,6 @@ static int read_frame(void)
}
process_image(buffers[0].start, buffers[0].length);
-
break;
case IO_METHOD_MMAP:
@@ -125,11 +123,10 @@ static int read_frame(void)
assert(buf.index < n_buffers);
- process_image(buffers[buf.index].start, buffers[buf.index].length);
+ process_image(buffers[buf.index].start, buf.bytesused);
if (-1 == xioctl(fd, VIDIOC_QBUF, &buf))
errno_exit("VIDIOC_QBUF");
-
break;
case IO_METHOD_USERPTR:
@@ -154,17 +151,16 @@ static int read_frame(void)
}
for (i = 0; i < n_buffers; ++i)
- if (buf.m.userptr == (unsigned long) buffers[i].start
+ if (buf.m.userptr == (unsigned long)buffers[i].start
&& buf.length == buffers[i].length)
break;
assert(i < n_buffers);
- process_image((void *) buf.m.userptr, buf.length);
+ process_image((void *)buf.m.userptr, buf.bytesused);
if (-1 == xioctl(fd, VIDIOC_QBUF, &buf))
errno_exit("VIDIOC_QBUF");
-
break;
}
@@ -195,7 +191,6 @@ static void mainloop(void)
if (-1 == r) {
if (EINTR == errno)
continue;
-
errno_exit("select");
}
@@ -206,7 +201,6 @@ static void mainloop(void)
if (read_frame())
break;
-
/* EAGAIN - continue select loop. */
}
}
@@ -224,10 +218,8 @@ static void stop_capturing(void)
case IO_METHOD_MMAP:
case IO_METHOD_USERPTR:
type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
-
if (-1 == xioctl(fd, VIDIOC_STREAMOFF, &type))
errno_exit("VIDIOC_STREAMOFF");
-
break;
}
}
@@ -247,20 +239,16 @@ static void start_capturing(void)
struct v4l2_buffer buf;
CLEAR(buf);
-
- buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
- buf.memory = V4L2_MEMORY_MMAP;
- buf.index = i;
+ buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+ buf.memory = V4L2_MEMORY_MMAP;
+ buf.index = i;
if (-1 == xioctl(fd, VIDIOC_QBUF, &buf))
errno_exit("VIDIOC_QBUF");
}
-
type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
-
if (-1 == xioctl(fd, VIDIOC_STREAMON, &type))
errno_exit("VIDIOC_STREAMON");
-
break;
case IO_METHOD_USERPTR:
@@ -268,22 +256,18 @@ static void start_capturing(void)
struct v4l2_buffer buf;
CLEAR(buf);
-
- buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
- buf.memory = V4L2_MEMORY_USERPTR;
- buf.index = i;
- buf.m.userptr = (unsigned long) buffers[i].start;
- buf.length = buffers[i].length;
+ buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+ buf.memory = V4L2_MEMORY_USERPTR;
+ buf.index = i;
+ buf.m.userptr = (unsigned long)buffers[i].start;
+ buf.length = buffers[i].length;
if (-1 == xioctl(fd, VIDIOC_QBUF, &buf))
errno_exit("VIDIOC_QBUF");
}
-
type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
-
if (-1 == xioctl(fd, VIDIOC_STREAMON, &type))
errno_exit("VIDIOC_STREAMON");
-
break;
}
}
@@ -336,9 +320,9 @@ static void init_mmap(void)
CLEAR(req);
- req.count = 4;
- req.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
- req.memory = V4L2_MEMORY_MMAP;
+ req.count = 4;
+ req.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+ req.memory = V4L2_MEMORY_MMAP;
if (-1 == xioctl(fd, VIDIOC_REQBUFS, &req)) {
if (EINVAL == errno) {
@@ -457,7 +441,6 @@ static void init_device(void)
dev_name);
exit(EXIT_FAILURE);
}
-
break;
case IO_METHOD_MMAP:
@@ -467,7 +450,6 @@ static void init_device(void)
dev_name);
exit(EXIT_FAILURE);
}
-
break;
}
@@ -500,16 +482,22 @@ static void init_device(void)
CLEAR(fmt);
- fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
- fmt.fmt.pix.width = 640;
- fmt.fmt.pix.height = 480;
- fmt.fmt.pix.pixelformat = V4L2_PIX_FMT_YUYV;
- fmt.fmt.pix.field = V4L2_FIELD_INTERLACED;
+ fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+ if (force_format) {
+ fmt.fmt.pix.width = 640;
+ fmt.fmt.pix.height = 480;
+ fmt.fmt.pix.pixelformat = V4L2_PIX_FMT_YUYV;
+ fmt.fmt.pix.field = V4L2_FIELD_INTERLACED;
- if (-1 == xioctl(fd, VIDIOC_S_FMT, &fmt))
- errno_exit("VIDIOC_S_FMT");
+ if (-1 == xioctl(fd, VIDIOC_S_FMT, &fmt))
+ errno_exit("VIDIOC_S_FMT");
- /* Note VIDIOC_S_FMT may change width and height. */
+ /* Note VIDIOC_S_FMT may change width and height. */
+ } else {
+ /* Preserve original settings as set by v4l2-ctl for example */
+ if (-1 == xioctl(fd, VIDIOC_G_FMT, &fmt))
+ errno_exit("VIDIOC_G_FMT");
+ }
/* Buggy driver paranoia. */
min = fmt.fmt.pix.width * 2;
@@ -571,40 +559,41 @@ static void usage(FILE *fp, int argc, char **argv)
fprintf(fp,
"Usage: %s [options]\n\n"
"Options:\n"
- "-d | --device name Video device name [/dev/video]\n"
+ "-d | --device name Video device name [/dev/video0]\n"
"-h | --help Print this message\n"
"-m | --mmap Use memory mapped buffers\n"
"-r | --read Use read() calls\n"
"-u | --userp Use application allocated buffers\n"
"-o | --output Outputs stream to stdout\n"
+ "-f | --format Force format to 640x480 YUYV\n"
"",
argv[0]);
}
-static const char short_options [] = "d:hmruo";
+static const char short_options[] = "d:hmruof";
static const struct option
-long_options [] = {
- { "device", required_argument, NULL, 'd' },
- { "help", no_argument, NULL, 'h' },
- { "mmap", no_argument, NULL, 'm' },
- { "read", no_argument, NULL, 'r' },
- { "userp", no_argument, NULL, 'u' },
- { "output", no_argument, NULL, 'o' },
+long_options[] = {
+ { "device", required_argument, NULL, 'd' },
+ { "help", no_argument, NULL, 'h' },
+ { "mmap", no_argument, NULL, 'm' },
+ { "read", no_argument, NULL, 'r' },
+ { "userp", no_argument, NULL, 'u' },
+ { "output", no_argument, NULL, 'o' },
+ { "format", no_argument, NULL, 'f' },
{ 0, 0, 0, 0 }
};
int main(int argc, char **argv)
{
- dev_name = "/dev/video";
+ dev_name = "/dev/video0";
for (;;) {
int idx;
int c;
c = getopt_long(argc, argv,
- short_options, long_options,
- &idx);
+ short_options, long_options, &idx);
if (-1 == c)
break;
@@ -637,6 +626,10 @@ int main(int argc, char **argv)
out_buf++;
break;
+ case 'f':
+ force_format++;
+ break;
+
default:
usage(stderr, argc, argv);
exit(EXIT_FAILURE);
@@ -650,5 +643,6 @@ int main(int argc, char **argv)
stop_capturing();
uninit_device();
close_device();
+ fprintf(stderr, "\n");
return 0;
}
diff --git a/v4l2-apps/test/ioctl-test.c b/v4l2-apps/test/ioctl-test.c
index f483338fb..99ad717e5 100644
--- a/v4l2-apps/test/ioctl-test.c
+++ b/v4l2-apps/test/ioctl-test.c
@@ -42,7 +42,7 @@
typedef __u8 u8;
typedef __u32 u32;
#include <linux/version.h>
-#include "../linux/include/media/v4l2-common.h"
+#include <media/v4l2-common.h>
#include <linux/video_decoder.h>
#else
typedef u_int32_t u32;
diff --git a/v4l2-apps/util/Makefile b/v4l2-apps/util/Makefile
index 41d4712e1..dcef94e0f 100644
--- a/v4l2-apps/util/Makefile
+++ b/v4l2-apps/util/Makefile
@@ -4,10 +4,10 @@ ifeq ($(KERNEL_DIR),)
KERNEL_DIR = /usr
endif
-CPPFLAGS += -I../../linux/include -D_GNU_SOURCE
+CPPFLAGS += -I../include -D_GNU_SOURCE
LDFLAGS += -lm
-binaries = v4l2-ctl v4l2-dbg ivtv-ctl cx18-ctl v4l-board-dbg
+binaries = v4l2-ctl v4l2-dbg v4l2-compliance ivtv-ctl cx18-ctl
ifeq ($(prefix),)
prefix = /usr
@@ -26,12 +26,14 @@ clean::
rm -rf keycodes parse.h keytable
qv4l2:
- if [ ! -f qv4l2/Makefile ]; then (cd qv4l2; qmake); fi
- make -C qv4l2
+ -if [ ! -f qv4l2/Makefile ]; then (cd qv4l2; qmake); fi
+ $(MAKE) -C qv4l2
v4l2-dbg: v4l2-dbg.o v4l2-driverids.o v4l2-chipids.o
$(CXX) $^ -o $@
+v4l2-dbg.o: v4l2-dbg.h v4l2-dbg-bttv.h v4l2-dbg-em28xx.h v4l2-dbg-saa7134.h
+
install:
mkdir -p $(prefix)/bin
cp $(binaries) $(prefix)/bin
@@ -57,14 +59,12 @@ keytables:
keytable: keytable.c parse.h keytables
-v4l-board-dbg: v4l-board-dbg.c bttv-dbg.h saa7134-dbg.h em28xx-dbg.h
-
-v4l2-driverids.cpp: ../../linux/include/linux/i2c-id.h
+v4l2-driverids.cpp: ../include/linux/i2c-id.h
@echo "struct driverid { const char *name; unsigned id; } driverids[] = {" >$@
@grep I2C_DRIVERID_ $^ | sed -e 's/.*I2C_DRIVERID_\([0-9A-Z_]*\)[^0-9]*\([0-9]*\).*/{ "\1", \2 },/' | tr A-Z a-z >>$@
@echo "{ 0, 0 }};" >>$@
-v4l2-chipids.cpp: ../../linux/include/media/v4l2-chip-ident.h
+v4l2-chipids.cpp: ../include/media/v4l2-chip-ident.h
@echo "struct chipid { const char *name; unsigned id; } chipids[] = {" >$@
@grep V4L2_IDENT_ $^ | sed -e 's/.*V4L2_IDENT_\([0-9A-Z_]*\)[^=]*=[^0-9]*\([0-9]*\).*/{ "\1", \2 },/' | tr A-Z a-z >>$@
@echo "{ 0, 0 }};" >>$@
diff --git a/v4l2-apps/util/ivtv-ctl.c b/v4l2-apps/util/ivtv-ctl.c
index ab836e240..af84164e3 100644
--- a/v4l2-apps/util/ivtv-ctl.c
+++ b/v4l2-apps/util/ivtv-ctl.c
@@ -351,9 +351,9 @@ int main(int argc, char **argv)
unsigned short gpio_dir = 0x0; /* GPIO direction bits */
int gpio_set_dir = 0;
int passthrough = 0;
- int audio_mute = 0;
- int stereo_mode = 0;
- int bilingual_mode = 0;
+ long audio_mute = 0;
+ long stereo_mode = 0;
+ long bilingual_mode = 0;
int debug_level = 0;
__u32 reset = 0;
int new_debug_level, gdebug_level;
@@ -621,7 +621,7 @@ int main(int argc, char **argv)
}
if (options[OptPassThrough]) {
- int source = passthrough ? VIDEO_SOURCE_DEMUX : VIDEO_SOURCE_MEMORY;
+ long source = passthrough ? VIDEO_SOURCE_DEMUX : VIDEO_SOURCE_MEMORY;
doioctl(fd, VIDEO_SELECT_SOURCE, (void *)source,
"IVTV_IOC_PASSTHROUGH");
diff --git a/v4l2-apps/util/qv4l2/qv4l2.pro b/v4l2-apps/util/qv4l2/qv4l2.pro
index c53a098b5..5e0b7555d 100644
--- a/v4l2-apps/util/qv4l2/qv4l2.pro
+++ b/v4l2-apps/util/qv4l2/qv4l2.pro
@@ -3,7 +3,7 @@
######################################################################
TEMPLATE = app
-INCLUDEPATH += . ../../../linux/include ../../lib
+INCLUDEPATH += . ../../include ../../lib
CONFIG += debug
# Input
diff --git a/v4l2-apps/util/rds/Makefile b/v4l2-apps/util/rds/Makefile
index 4f6ebd9f2..fb2213c99 100644
--- a/v4l2-apps/util/rds/Makefile
+++ b/v4l2-apps/util/rds/Makefile
@@ -1,6 +1,6 @@
# Makefile for linuxtv.org v4l2-apps/util/xc3028-firmware
-CPPFLAGS += -I../../../linux/include
+CPPFLAGS += -I../../include
binaries = rds-saa6588
diff --git a/v4l2-apps/util/v4l-board-dbg.c b/v4l2-apps/util/v4l-board-dbg.c
deleted file mode 100644
index e74c7300e..000000000
--- a/v4l2-apps/util/v4l-board-dbg.c
+++ /dev/null
@@ -1,335 +0,0 @@
-/*
- Copyright (C) 2008 Mauro Carvalho Chehab <mchehab@infradead.org>
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation version 2 of the License.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-#include <unistd.h>
-#include <stdlib.h>
-#include <stdio.h>
-#include <string.h>
-#include <getopt.h>
-#include <fcntl.h>
-#include <errno.h>
-#include <sys/ioctl.h>
-#include <sys/time.h>
-#include <linux/types.h>
-#include <linux/videodev2.h>
-
-#include "bttv-dbg.h"
-#include "saa7134-dbg.h"
-#include "em28xx-dbg.h"
-
-#define ARRAY_SIZE(arr) ((int)(sizeof(arr) / sizeof((arr)[0])))
-
-struct board_list {
- char *name;
- int prefix; /* Register prefix size */
- struct board_regs *regs;
- int regs_size;
- struct board_regs *alt_regs;
- int alt_regs_size;
-};
-
-struct board_list boards[] = {
- [0] = { /* From bttv-dbg.h */
- .name = BTTV_IDENT,
- .prefix = sizeof(BTTV_PREFIX) - 1,
- .regs = bt8xx_regs,
- .regs_size = ARRAY_SIZE(bt8xx_regs),
- .alt_regs = bt8xx_regs_other,
- .alt_regs_size = ARRAY_SIZE(bt8xx_regs_other),
- },
- [1] = { /* From saa7134-dbg.h */
- .name = SAA7134_IDENT,
- .prefix = sizeof(SAA7134_PREFIX) - 1,
- .regs = saa7134_regs,
- .regs_size = ARRAY_SIZE(saa7134_regs),
- .alt_regs = NULL,
- .alt_regs_size = 0,
- },
- [2] = { /* From em28xx-dbg.h */
- .name = EM28XX_IDENT,
- .prefix = sizeof(EM28XX_PREFIX) - 1,
- .regs = em28xx_regs,
- .regs_size = ARRAY_SIZE(em28xx_regs),
- .alt_regs = NULL,
- .alt_regs_size = 0,
- },
-};
-
-static int is_get=0, is_set=0;
-
-static int doioctl(int fd, int request, void *parm, const char *name)
-{
- int retVal;
-
- printf("ioctl %s ", name);
- retVal = ioctl(fd, request, parm);
- if (retVal < 0)
- printf("failed: %s\n", strerror(errno));
- else
- printf("ok\n");
-
- return retVal;
-}
-
-static void usage(void)
-{
- printf("bttv-dbg <args>\n");
-}
-
-enum Option {
- OptGetReg = 'g',
- OptSetReg = 's',
- OptHelp = 'h',
-};
-
-static void print_bin (int val, int size)
-{
- int i, j, v;
-
- printf("(");
- for (i = size-1; i >= 0; i--) {
- v = (val >> (i * 8)) & 0xff;
- for (j = 7; j >= 0; j--) {
- int bit = (v >> j) & 0x1;
- if (bit)
- printf("1");
- else
- printf("0");
- }
- if (i)
- printf(" ");
- else
- printf(")");
- }
-}
-
-int main(int argc, char **argv)
-{
- char *device = strdup("/dev/video0");
- char *reg_set = NULL;
- int ch;
- int i;
- int fd = -1;
- struct v4l2_register reg;
- struct v4l2_capability cap;
- struct board_list *curr_bd;
- int board = 0;
- struct option long_options[] = {
- /* Please keep in alphabetical order of the short option.
- That makes it easier to see which options are still free. */
- {"get-reg", no_argument, 0, OptGetReg},
- {"set-reg", required_argument, 0, OptSetReg},
- {"help", no_argument, 0, OptHelp},
- {0, 0, 0, 0}
- };
-
- /* command args */
- if (argc == 1) {
- usage();
- return 0;
- }
- while (1) {
- int option_index = 0;
-
- ch = getopt_long(argc, argv, "gs:", long_options, &option_index);
- if (ch == -1)
- break;
-
- switch (ch) {
- case OptHelp:
- usage();
- return 0;
- case OptGetReg:
- is_get++;
- break;
- case OptSetReg:
- is_set++;
- reg_set = optarg;
-
- break;
- case '?':
- fprintf(stderr, "Unknown argument `%s'\n",
- argv[optind]);
- usage();
- return 1;
- }
- }
- if (optind < argc) {
- printf("unknown arguments: ");
- while (optind < argc)
- printf("%s ", argv[optind++]);
- printf("\n");
- usage();
- return 1;
- }
-
- fd = open(device, O_RDWR);
- if (fd < 0) {
- fprintf(stderr, "Failed to open %s: %s\n", device,
- strerror(errno));
- exit(1);
- }
- free(device);
-
- if (ioctl(fd, VIDIOC_QUERYCAP, &cap) < 0) {
- printf("Error while reading capabilities\n");
- exit(2);
- }
-
- for (board = ARRAY_SIZE(boards)-1; board >= 0; board--) {
- if (!strcasecmp((char *)cap.driver, boards[board].name))
- break;
- }
- if (board < 0) {
- printf("This software doesn't support %s yet\n", cap.driver);
- exit(3);
- }
-
- curr_bd = &boards[board];
-
- reg.match_type = V4L2_CHIP_MATCH_HOST;
- reg.match_chip = 0;
-
- if (is_get) {
- for (i = 0; i < curr_bd->regs_size; i++) {
- char name[256];
- reg.reg = curr_bd->regs[i].reg;
- if (ioctl(fd, VIDIOC_DBG_G_REGISTER, &reg) < 0) {
- printf("Error while reading. Maybe you're not root?\n");
- continue;
- }
- sprintf(name, "%s:", curr_bd->regs[i].name);
-
- switch (curr_bd->regs[i].size) {
- case 1:
- printf("%-32s %02llx ", name, reg.val & 0xff);
- break;
- case 2:
- printf("%-32s %04llx ", name, reg.val & 0xffff);
- break;
- case 4:
- printf("%-32s %08llx ", name, reg.val & 0xffffffff);
- break;
- }
- print_bin (reg.val, curr_bd->regs[i].size);
- printf("\n");
- }
- return 0;
- }
-
- if (is_set) {
- char *reg_name;
- int val;
- int r, size;
- unsigned prev;
- struct board_regs *bd_reg;
-
- reg_name = strtok(reg_set, "=:");
- val = strtol(strtok(NULL, "=:"), 0L, 0);
-
- if (!reg_name) {
- printf("set argument is invalid\n");
- return -1;
- }
-
- for (i = curr_bd->regs_size - 1; i >=0 ; i--) {
- if (!strcasecmp(reg_name, curr_bd->regs[i].name)) {
- bd_reg = &curr_bd->regs[i];
- r = bd_reg->reg;
- size = bd_reg->size;
- break;
- }
- }
-
- if (i < 0) {
- for (i = curr_bd->alt_regs_size - 1; i >=0 ; i--) {
- if (!strcasecmp(reg_name, curr_bd->alt_regs[i].name)) {
- bd_reg = &curr_bd->alt_regs[i];
- r = bd_reg->reg;
- size = bd_reg->size;
- break;
- }
- }
- }
-
- if (i < 0) {
- for (i = curr_bd->regs_size - 1; i >=0 ; i--) {
- if (!strcasecmp(reg_name, curr_bd->regs[i].name + curr_bd->prefix)) {
- bd_reg = &curr_bd->regs[i];
- r = bd_reg->reg;
- size = bd_reg->size;
- break;
- }
- }
- }
-
- if (i < 0) {
- for (i = curr_bd->alt_regs_size - 1; i >=0 ; i--) {
- if (!strcasecmp(reg_name, curr_bd->alt_regs[i].name + curr_bd->prefix)) {
- bd_reg = &curr_bd->regs[i];
- r = bd_reg->reg;
- size = bd_reg->size;
- break;
- }
- }
- }
-
- if (i < 0) {
- printf("Register not found\n");
- return -1;
- }
-
- reg.reg = r;
- if (ioctl(fd, VIDIOC_DBG_G_REGISTER, &reg) < 0) {
- printf("Error while reading register 0x%02x\n", r);
- return -1;
- }
- prev = reg.val;
-
- switch (size) {
- case 1:
- reg.val = (reg.val & (~0xff)) | val;
- break;
- case 2:
- reg.val = (reg.val & (~0xffff)) | val;
- break;
- case 4:
- reg.val = val;
- break;
- }
-
- printf("Changing value of register %s(0x%x) from 0x%02x to 0x%02x\n",
- bd_reg->name, r, prev, (unsigned int)reg.val);
-
- prev = reg.val;
-
- if (ioctl(fd, VIDIOC_DBG_S_REGISTER, &reg) < 0) {
- printf("Error while writing\n");
- return -1;
- }
- if (ioctl(fd, VIDIOC_DBG_G_REGISTER, &reg) < 0) {
- printf("Error while reading register 0x%02x\n", r);
- return -1;
- }
- if (reg.val != prev) {
- printf("Value of register %s(0x%x) is now 0x%02x\n",
- bd_reg->name, r, (unsigned int)reg.val);
- }
- }
-
- close(fd);
- exit(0);
-}
diff --git a/v4l2-apps/util/v4l2-compliance.cpp b/v4l2-apps/util/v4l2-compliance.cpp
new file mode 100644
index 000000000..2fe5292fe
--- /dev/null
+++ b/v4l2-apps/util/v4l2-compliance.cpp
@@ -0,0 +1,1122 @@
+/*
+ V4L2 API compliance test tool.
+
+ Copyright (C) 2008 Hans Verkuil <hverkuil@xs4all.nl>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include <unistd.h>
+#include <features.h> /* Uses _GNU_SOURCE to define getsubopt in stdlib.h */
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <inttypes.h>
+#include <getopt.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <ctype.h>
+#include <errno.h>
+#include <sys/ioctl.h>
+#include <sys/time.h>
+#include <math.h>
+#include <sys/klog.h>
+
+#include <linux/videodev2.h>
+
+#include <list>
+#include <vector>
+#include <map>
+#include <string>
+
+/* Short option list
+
+ Please keep in alphabetical order.
+ That makes it easier to see which short options are still free.
+
+ In general the lower case is used to set something and the upper
+ case is used to retrieve a setting. */
+enum Option {
+ OptSetDevice = 'd',
+ OptGetDriverInfo = 'D',
+ OptHelp = 'h',
+ OptTest = 't',
+ OptVerbose = 'v',
+ OptLast = 256
+};
+
+enum Test {
+ TestCap = 0,
+ TestChipIdent,
+ TestRegister,
+ TestLogStatus,
+ TestMax
+};
+
+static int test[TestMax];
+
+static char options[OptLast];
+
+static int app_result;
+static int verbose;
+
+static unsigned caps;
+
+typedef std::vector<struct v4l2_ext_control> ctrl_list;
+static ctrl_list user_ctrls;
+static ctrl_list mpeg_ctrls;
+
+typedef std::map<std::string, unsigned> ctrl_strmap;
+static ctrl_strmap ctrl_str2id;
+typedef std::map<unsigned, std::string> ctrl_idmap;
+static ctrl_idmap ctrl_id2str;
+
+typedef std::list<std::string> ctrl_get_list;
+static ctrl_get_list get_ctrls;
+
+typedef std::map<std::string,std::string> ctrl_set_map;
+static ctrl_set_map set_ctrls;
+
+typedef struct {
+ unsigned flag;
+ const char *str;
+} flag_def;
+
+static const flag_def service_def[] = {
+ { V4L2_SLICED_TELETEXT_B, "teletext" },
+ { V4L2_SLICED_VPS, "vps" },
+ { V4L2_SLICED_CAPTION_525, "cc" },
+ { V4L2_SLICED_WSS_625, "wss" },
+ { 0, NULL }
+};
+
+/* fmts specified */
+#define FmtWidth (1L<<0)
+#define FmtHeight (1L<<1)
+#define FmtChromaKey (1L<<2)
+#define FmtGlobalAlpha (1L<<3)
+
+/* crop specified */
+#define CropWidth (1L<<0)
+#define CropHeight (1L<<1)
+#define CropLeft (1L<<2)
+#define CropTop (1L<<3)
+
+static struct option long_options[] = {
+ {"device", required_argument, 0, OptSetDevice},
+ {"help", no_argument, 0, OptHelp},
+ {"info", no_argument, 0, OptGetDriverInfo},
+ {"verbose", no_argument, 0, OptVerbose},
+ {"test", required_argument, 0, OptTest},
+ {0, 0, 0, 0}
+};
+
+static void usage(void)
+{
+ printf("Usage:\n");
+ printf("Common options:\n");
+ printf(" -D, --info show driver info [VIDIOC_QUERYCAP]\n");
+ printf(" -d, --device=<dev> use device <dev> instead of /dev/video0\n");
+ printf(" if <dev> is a single digit, then /dev/video<dev> is used\n");
+ printf(" -h, --help display this help message\n");
+ printf(" -t, --test=<num> run specified test.\n");
+ printf(" By default all tests are run.\n");
+ printf(" 0 = test VIDIOC_QUERYCAP\n");
+ printf(" -v, --verbose turn on verbose ioctl error reporting.\n");
+ exit(0);
+}
+
+static std::string num2s(unsigned num)
+{
+ char buf[10];
+
+ sprintf(buf, "%08x", num);
+ return buf;
+}
+
+static std::string buftype2s(int type)
+{
+ switch (type) {
+ case V4L2_BUF_TYPE_VIDEO_CAPTURE:
+ return "Video Capture";
+ case V4L2_BUF_TYPE_VIDEO_OUTPUT:
+ return "Video Output";
+ case V4L2_BUF_TYPE_VIDEO_OVERLAY:
+ return "Video Overlay";
+ case V4L2_BUF_TYPE_VBI_CAPTURE:
+ return "VBI Capture";
+ case V4L2_BUF_TYPE_VBI_OUTPUT:
+ return "VBI Output";
+ case V4L2_BUF_TYPE_SLICED_VBI_CAPTURE:
+ return "Sliced VBI Capture";
+ case V4L2_BUF_TYPE_SLICED_VBI_OUTPUT:
+ return "Sliced VBI Output";
+ case V4L2_BUF_TYPE_VIDEO_OUTPUT_OVERLAY:
+ return "Video Output Overlay";
+ case V4L2_BUF_TYPE_PRIVATE:
+ return "Private";
+ default:
+ return "Unknown (" + num2s(type) + ")";
+ }
+}
+
+static std::string fcc2s(unsigned int val)
+{
+ std::string s;
+
+ s += val & 0xff;
+ s += (val >> 8) & 0xff;
+ s += (val >> 16) & 0xff;
+ s += (val >> 24) & 0xff;
+ return s;
+}
+
+static std::string field2s(int val)
+{
+ switch (val) {
+ case V4L2_FIELD_ANY:
+ return "Any";
+ case V4L2_FIELD_NONE:
+ return "None";
+ case V4L2_FIELD_TOP:
+ return "Top";
+ case V4L2_FIELD_BOTTOM:
+ return "Bottom";
+ case V4L2_FIELD_INTERLACED:
+ return "Interlaced";
+ case V4L2_FIELD_SEQ_TB:
+ return "Sequential Top-Bottom";
+ case V4L2_FIELD_SEQ_BT:
+ return "Sequential Bottom-Top";
+ case V4L2_FIELD_ALTERNATE:
+ return "Alternating";
+ case V4L2_FIELD_INTERLACED_TB:
+ return "Interlaced Top-Bottom";
+ case V4L2_FIELD_INTERLACED_BT:
+ return "Interlaced Bottom-Top";
+ default:
+ return "Unknown (" + num2s(val) + ")";
+ }
+}
+
+static std::string colorspace2s(int val)
+{
+ switch (val) {
+ case V4L2_COLORSPACE_SMPTE170M:
+ return "Broadcast NTSC/PAL (SMPTE170M/ITU601)";
+ case V4L2_COLORSPACE_SMPTE240M:
+ return "1125-Line (US) HDTV (SMPTE240M)";
+ case V4L2_COLORSPACE_REC709:
+ return "HDTV and modern devices (ITU709)";
+ case V4L2_COLORSPACE_BT878:
+ return "Broken Bt878";
+ case V4L2_COLORSPACE_470_SYSTEM_M:
+ return "NTSC/M (ITU470/ITU601)";
+ case V4L2_COLORSPACE_470_SYSTEM_BG:
+ return "PAL/SECAM BG (ITU470/ITU601)";
+ case V4L2_COLORSPACE_JPEG:
+ return "JPEG (JFIF/ITU601)";
+ case V4L2_COLORSPACE_SRGB:
+ return "SRGB";
+ default:
+ return "Unknown (" + num2s(val) + ")";
+ }
+}
+
+static std::string flags2s(unsigned val, const flag_def *def)
+{
+ std::string s;
+
+ while (def->flag) {
+ if (val & def->flag) {
+ if (s.length()) s += " ";
+ s += def->str;
+ }
+ def++;
+ }
+ return s;
+}
+
+static void print_sliced_vbi_cap(struct v4l2_sliced_vbi_cap &cap)
+{
+ printf("\tType : %s\n", buftype2s(cap.type).c_str());
+ printf("\tService Set : %s\n",
+ flags2s(cap.service_set, service_def).c_str());
+ for (int i = 0; i < 24; i++) {
+ printf("\tService Line %2d: %8s / %-8s\n", i,
+ flags2s(cap.service_lines[0][i], service_def).c_str(),
+ flags2s(cap.service_lines[1][i], service_def).c_str());
+ }
+}
+
+static std::string name2var(unsigned char *name)
+{
+ std::string s;
+
+ while (*name) {
+ if (*name == ' ') s += "_";
+ else s += std::string(1, tolower(*name));
+ name++;
+ }
+ return s;
+}
+
+static void print_qctrl(int fd, struct v4l2_queryctrl *queryctrl,
+ struct v4l2_ext_control *ctrl, int show_menus)
+{
+ struct v4l2_querymenu qmenu = { 0 };
+ std::string s = name2var(queryctrl->name);
+ int i;
+
+ qmenu.id = queryctrl->id;
+ switch (queryctrl->type) {
+ case V4L2_CTRL_TYPE_INTEGER:
+ printf("%31s (int) : min=%d max=%d step=%d default=%d value=%d",
+ s.c_str(),
+ queryctrl->minimum, queryctrl->maximum,
+ queryctrl->step, queryctrl->default_value,
+ ctrl->value);
+ break;
+ case V4L2_CTRL_TYPE_INTEGER64:
+ printf("%31s (int64): value=%lld", s.c_str(), ctrl->value64);
+ break;
+ case V4L2_CTRL_TYPE_BOOLEAN:
+ printf("%31s (bool) : default=%d value=%d",
+ s.c_str(),
+ queryctrl->default_value, ctrl->value);
+ break;
+ case V4L2_CTRL_TYPE_MENU:
+ printf("%31s (menu) : min=%d max=%d default=%d value=%d",
+ s.c_str(),
+ queryctrl->minimum, queryctrl->maximum,
+ queryctrl->default_value, ctrl->value);
+ break;
+ case V4L2_CTRL_TYPE_BUTTON:
+ printf("%31s (button)\n", s.c_str());
+ break;
+ default: break;
+ }
+ if (queryctrl->flags) {
+ const flag_def def[] = {
+ { V4L2_CTRL_FLAG_GRABBED, "grabbed" },
+ { V4L2_CTRL_FLAG_READ_ONLY, "readonly" },
+ { V4L2_CTRL_FLAG_UPDATE, "update" },
+ { V4L2_CTRL_FLAG_INACTIVE, "inactive" },
+ { V4L2_CTRL_FLAG_SLIDER, "slider" },
+ { 0, NULL }
+ };
+ printf(" flags=%s", flags2s(queryctrl->flags, def).c_str());
+ }
+ printf("\n");
+ if (queryctrl->type == V4L2_CTRL_TYPE_MENU && show_menus) {
+ for (i = 0; i <= queryctrl->maximum; i++) {
+ qmenu.index = i;
+ if (ioctl(fd, VIDIOC_QUERYMENU, &qmenu))
+ continue;
+ printf("\t\t\t\t%d: %s\n", i, qmenu.name);
+ }
+ }
+}
+
+static int print_control(int fd, struct v4l2_queryctrl &qctrl, int show_menus)
+{
+ struct v4l2_control ctrl = { 0 };
+ struct v4l2_ext_control ext_ctrl = { 0 };
+ struct v4l2_ext_controls ctrls = { 0 };
+
+ if (qctrl.flags & V4L2_CTRL_FLAG_DISABLED)
+ return 1;
+ if (qctrl.type == V4L2_CTRL_TYPE_CTRL_CLASS) {
+ printf("\n%s\n\n", qctrl.name);
+ return 1;
+ }
+ ext_ctrl.id = qctrl.id;
+ ctrls.ctrl_class = V4L2_CTRL_ID2CLASS(qctrl.id);
+ ctrls.count = 1;
+ ctrls.controls = &ext_ctrl;
+ if (V4L2_CTRL_ID2CLASS(qctrl.id) != V4L2_CTRL_CLASS_USER &&
+ qctrl.id < V4L2_CID_PRIVATE_BASE) {
+ if (ioctl(fd, VIDIOC_G_EXT_CTRLS, &ctrls)) {
+ printf("error %d getting ext_ctrl %s\n",
+ errno, qctrl.name);
+ return 0;
+ }
+ }
+ else {
+ ctrl.id = qctrl.id;
+ if (ioctl(fd, VIDIOC_G_CTRL, &ctrl)) {
+ printf("error %d getting ctrl %s\n",
+ errno, qctrl.name);
+ return 0;
+ }
+ ext_ctrl.value = ctrl.value;
+ }
+ print_qctrl(fd, &qctrl, &ext_ctrl, show_menus);
+ return 1;
+}
+
+static void list_controls(int fd, int show_menus)
+{
+ struct v4l2_queryctrl qctrl = { V4L2_CTRL_FLAG_NEXT_CTRL };
+ int id;
+
+ while (ioctl(fd, VIDIOC_QUERYCTRL, &qctrl) == 0) {
+ print_control(fd, qctrl, show_menus);
+ qctrl.id |= V4L2_CTRL_FLAG_NEXT_CTRL;
+ }
+ if (qctrl.id != V4L2_CTRL_FLAG_NEXT_CTRL)
+ return;
+ for (id = V4L2_CID_USER_BASE; id < V4L2_CID_LASTP1; id++) {
+ qctrl.id = id;
+ if (ioctl(fd, VIDIOC_QUERYCTRL, &qctrl) == 0)
+ print_control(fd, qctrl, show_menus);
+ }
+ for (qctrl.id = V4L2_CID_PRIVATE_BASE;
+ ioctl(fd, VIDIOC_QUERYCTRL, &qctrl) == 0; qctrl.id++) {
+ print_control(fd, qctrl, show_menus);
+ }
+}
+
+static void find_controls(int fd)
+{
+ struct v4l2_queryctrl qctrl = { V4L2_CTRL_FLAG_NEXT_CTRL };
+ int id;
+
+ while (ioctl(fd, VIDIOC_QUERYCTRL, &qctrl) == 0) {
+ if (qctrl.type != V4L2_CTRL_TYPE_CTRL_CLASS &&
+ !(qctrl.flags & V4L2_CTRL_FLAG_DISABLED)) {
+ ctrl_str2id[name2var(qctrl.name)] = qctrl.id;
+ ctrl_id2str[qctrl.id] = name2var(qctrl.name);
+ }
+ qctrl.id |= V4L2_CTRL_FLAG_NEXT_CTRL;
+ }
+ if (qctrl.id != V4L2_CTRL_FLAG_NEXT_CTRL)
+ return;
+ for (id = V4L2_CID_USER_BASE; id < V4L2_CID_LASTP1; id++) {
+ qctrl.id = id;
+ if (ioctl(fd, VIDIOC_QUERYCTRL, &qctrl) == 0 &&
+ !(qctrl.flags & V4L2_CTRL_FLAG_DISABLED))
+ ctrl_str2id[name2var(qctrl.name)] = qctrl.id;
+ }
+ for (qctrl.id = V4L2_CID_PRIVATE_BASE;
+ ioctl(fd, VIDIOC_QUERYCTRL, &qctrl) == 0; qctrl.id++) {
+ if (!(qctrl.flags & V4L2_CTRL_FLAG_DISABLED))
+ ctrl_str2id[name2var(qctrl.name)] = qctrl.id;
+ }
+}
+
+static std::string fbufcap2s(unsigned cap)
+{
+ std::string s;
+
+ if (cap & V4L2_FBUF_CAP_EXTERNOVERLAY)
+ s += "\t\t\tExtern Overlay\n";
+ if (cap & V4L2_FBUF_CAP_CHROMAKEY)
+ s += "\t\t\tChromakey\n";
+ if (cap & V4L2_FBUF_CAP_GLOBAL_ALPHA)
+ s += "\t\t\tGlobal Alpha\n";
+ if (cap & V4L2_FBUF_CAP_LOCAL_ALPHA)
+ s += "\t\t\tLocal Alpha\n";
+ if (cap & V4L2_FBUF_CAP_LOCAL_INV_ALPHA)
+ s += "\t\t\tLocal Inverted Alpha\n";
+ if (cap & V4L2_FBUF_CAP_LIST_CLIPPING)
+ s += "\t\t\tClipping List\n";
+ if (cap & V4L2_FBUF_CAP_BITMAP_CLIPPING)
+ s += "\t\t\tClipping Bitmap\n";
+ if (s.empty()) s += "\t\t\t\n";
+ return s;
+}
+
+static std::string fbufflags2s(unsigned fl)
+{
+ std::string s;
+
+ if (fl & V4L2_FBUF_FLAG_PRIMARY)
+ s += "\t\t\tPrimary Graphics Surface\n";
+ if (fl & V4L2_FBUF_FLAG_OVERLAY)
+ s += "\t\t\tOverlay Matches Capture/Output Size\n";
+ if (fl & V4L2_FBUF_FLAG_CHROMAKEY)
+ s += "\t\t\tChromakey\n";
+ if (fl & V4L2_FBUF_FLAG_GLOBAL_ALPHA)
+ s += "\t\t\tGlobal Alpha\n";
+ if (fl & V4L2_FBUF_FLAG_LOCAL_ALPHA)
+ s += "\t\t\tLocal Alpha\n";
+ if (fl & V4L2_FBUF_FLAG_LOCAL_INV_ALPHA)
+ s += "\t\t\tLocal Inverted Alpha\n";
+ if (s.empty()) s += "\t\t\t\n";
+ return s;
+}
+
+static void printfbuf(const struct v4l2_framebuffer &fb)
+{
+ int is_ext = fb.capability & V4L2_FBUF_CAP_EXTERNOVERLAY;
+
+ printf("Framebuffer Format:\n");
+ printf("\tCapability : %s", fbufcap2s(fb.capability).c_str() + 3);
+ printf("\tFlags : %s", fbufflags2s(fb.flags).c_str() + 3);
+ if (fb.base)
+ printf("\tBase : 0x%p\n", fb.base);
+ printf("\tWidth : %d\n", fb.fmt.width);
+ printf("\tHeight : %d\n", fb.fmt.height);
+ printf("\tPixel Format : %s\n", fcc2s(fb.fmt.pixelformat).c_str());
+ if (!is_ext) {
+ printf("\tBytes per Line: %d\n", fb.fmt.bytesperline);
+ printf("\tSize image : %d\n", fb.fmt.sizeimage);
+ printf("\tColorspace : %s\n", colorspace2s(fb.fmt.colorspace).c_str());
+ if (fb.fmt.priv)
+ printf("\tCustom Info : %08x\n", fb.fmt.priv);
+ }
+}
+
+static void printcrop(const struct v4l2_crop &crop)
+{
+ printf("Crop: Left %d, Top %d, Width %d, Height %d\n",
+ crop.c.left, crop.c.top, crop.c.width, crop.c.height);
+}
+
+static void printcropcap(const struct v4l2_cropcap &cropcap)
+{
+ printf("Crop Capability %s:\n", buftype2s(cropcap.type).c_str());
+ printf("\tBounds : Left %d, Top %d, Width %d, Height %d\n",
+ cropcap.bounds.left, cropcap.bounds.top, cropcap.bounds.width, cropcap.bounds.height);
+ printf("\tDefault : Left %d, Top %d, Width %d, Height %d\n",
+ cropcap.defrect.left, cropcap.defrect.top, cropcap.defrect.width, cropcap.defrect.height);
+ printf("\tPixel Aspect: %u/%u\n", cropcap.pixelaspect.numerator, cropcap.pixelaspect.denominator);
+}
+
+static void printfmt(struct v4l2_format vfmt)
+{
+ const flag_def vbi_def[] = {
+ { V4L2_VBI_UNSYNC, "unsynchronized" },
+ { V4L2_VBI_INTERLACED, "interlaced" },
+ { 0, NULL }
+ };
+ printf("Format %s:\n", buftype2s(vfmt.type).c_str());
+
+ switch (vfmt.type) {
+ case V4L2_BUF_TYPE_VIDEO_CAPTURE:
+ case V4L2_BUF_TYPE_VIDEO_OUTPUT:
+ printf("\tWidth/Height : %u/%u\n", vfmt.fmt.pix.width, vfmt.fmt.pix.height);
+ printf("\tPixel Format : %s\n", fcc2s(vfmt.fmt.pix.pixelformat).c_str());
+ printf("\tField : %s\n", field2s(vfmt.fmt.pix.field).c_str());
+ printf("\tBytes per Line: %u\n", vfmt.fmt.pix.bytesperline);
+ printf("\tSize Image : %u\n", vfmt.fmt.pix.sizeimage);
+ printf("\tColorspace : %s\n", colorspace2s(vfmt.fmt.pix.colorspace).c_str());
+ if (vfmt.fmt.pix.priv)
+ printf("\tCustom Info : %08x\n", vfmt.fmt.pix.priv);
+ break;
+ case V4L2_BUF_TYPE_VIDEO_OUTPUT_OVERLAY:
+ case V4L2_BUF_TYPE_VIDEO_OVERLAY:
+ printf("\tLeft/Top : %d/%d\n",
+ vfmt.fmt.win.w.left, vfmt.fmt.win.w.top);
+ printf("\tWidth/Height: %d/%d\n",
+ vfmt.fmt.win.w.width, vfmt.fmt.win.w.height);
+ printf("\tField : %s\n", field2s(vfmt.fmt.win.field).c_str());
+ printf("\tChroma Key : 0x%08x\n", vfmt.fmt.win.chromakey);
+ printf("\tGlobal Alpha: 0x%02x\n", vfmt.fmt.win.global_alpha);
+ printf("\tClip Count : %u\n", vfmt.fmt.win.clipcount);
+ printf("\tClip Bitmap : %s\n", vfmt.fmt.win.bitmap ? "Yes" : "No");
+ break;
+ case V4L2_BUF_TYPE_VBI_CAPTURE:
+ case V4L2_BUF_TYPE_VBI_OUTPUT:
+ printf("\tSampling Rate : %u Hz\n", vfmt.fmt.vbi.sampling_rate);
+ printf("\tOffset : %u samples (%g secs after leading edge)\n",
+ vfmt.fmt.vbi.offset,
+ (double)vfmt.fmt.vbi.offset / (double)vfmt.fmt.vbi.sampling_rate);
+ printf("\tSamples per Line: %u\n", vfmt.fmt.vbi.samples_per_line);
+ printf("\tSample Format : %s\n", fcc2s(vfmt.fmt.vbi.sample_format).c_str());
+ printf("\tStart 1st Field : %u\n", vfmt.fmt.vbi.start[0]);
+ printf("\tCount 1st Field : %u\n", vfmt.fmt.vbi.count[0]);
+ printf("\tStart 2nd Field : %u\n", vfmt.fmt.vbi.start[1]);
+ printf("\tCount 2nd Field : %u\n", vfmt.fmt.vbi.count[1]);
+ if (vfmt.fmt.vbi.flags)
+ printf("\tFlags : %s\n", flags2s(vfmt.fmt.vbi.flags, vbi_def).c_str());
+ break;
+ case V4L2_BUF_TYPE_SLICED_VBI_CAPTURE:
+ case V4L2_BUF_TYPE_SLICED_VBI_OUTPUT:
+ printf("\tService Set : %s\n",
+ flags2s(vfmt.fmt.sliced.service_set, service_def).c_str());
+ for (int i = 0; i < 24; i++) {
+ printf("\tService Line %2d: %8s / %-8s\n", i,
+ flags2s(vfmt.fmt.sliced.service_lines[0][i], service_def).c_str(),
+ flags2s(vfmt.fmt.sliced.service_lines[1][i], service_def).c_str());
+ }
+ printf("\tI/O Size : %u\n", vfmt.fmt.sliced.io_size);
+ break;
+ case V4L2_BUF_TYPE_PRIVATE:
+ break;
+ }
+}
+
+static void print_video_formats(int fd, enum v4l2_buf_type type)
+{
+ struct v4l2_fmtdesc fmt;
+
+ fmt.index = 0;
+ fmt.type = type;
+ while (ioctl(fd, VIDIOC_ENUM_FMT, &fmt) >= 0) {
+ printf("\tType : %s\n", buftype2s(type).c_str());
+ printf("\tPixelformat : %s", fcc2s(fmt.pixelformat).c_str());
+ if (fmt.flags)
+ printf(" (compressed)");
+ printf("\n");
+ printf("\tName : %s\n", fmt.description);
+ printf("\n");
+ fmt.index++;
+ }
+}
+
+static char *pts_to_string(char *str, unsigned long pts)
+{
+ static char buf[256];
+ int hours, minutes, seconds, fracsec;
+ float fps;
+ int frame;
+ char *p = (str) ? str : buf;
+
+ static const int MPEG_CLOCK_FREQ = 90000;
+ seconds = pts / MPEG_CLOCK_FREQ;
+ fracsec = pts % MPEG_CLOCK_FREQ;
+
+ minutes = seconds / 60;
+ seconds = seconds % 60;
+
+ hours = minutes / 60;
+ minutes = minutes % 60;
+
+ fps = 30;
+ frame = (int)ceilf(((float)fracsec / (float)MPEG_CLOCK_FREQ) * fps);
+
+ snprintf(p, sizeof(buf), "%d:%02d:%02d:%d", hours, minutes, seconds,
+ frame);
+ return p;
+}
+
+static const char *audmode2s(int audmode)
+{
+ switch (audmode) {
+ case V4L2_TUNER_MODE_STEREO: return "stereo";
+ case V4L2_TUNER_MODE_LANG1: return "lang1";
+ case V4L2_TUNER_MODE_LANG2: return "lang2";
+ case V4L2_TUNER_MODE_LANG1_LANG2: return "bilingual";
+ case V4L2_TUNER_MODE_MONO: return "mono";
+ default: return "unknown";
+ }
+}
+
+static std::string rxsubchans2s(int rxsubchans)
+{
+ std::string s;
+
+ if (rxsubchans & V4L2_TUNER_SUB_MONO)
+ s += "mono ";
+ if (rxsubchans & V4L2_TUNER_SUB_STEREO)
+ s += "stereo ";
+ if (rxsubchans & V4L2_TUNER_SUB_LANG1)
+ s += "lang1 ";
+ if (rxsubchans & V4L2_TUNER_SUB_LANG2)
+ s += "lang2 ";
+ return s;
+}
+
+static std::string tcap2s(unsigned cap)
+{
+ std::string s;
+
+ if (cap & V4L2_TUNER_CAP_LOW)
+ s += "62.5 Hz ";
+ else
+ s += "62.5 kHz ";
+ if (cap & V4L2_TUNER_CAP_NORM)
+ s += "multi-standard ";
+ if (cap & V4L2_TUNER_CAP_STEREO)
+ s += "stereo ";
+ if (cap & V4L2_TUNER_CAP_LANG1)
+ s += "lang1 ";
+ if (cap & V4L2_TUNER_CAP_LANG2)
+ s += "lang2 ";
+ return s;
+}
+
+static std::string cap2s(unsigned cap)
+{
+ std::string s;
+
+ if (cap & V4L2_CAP_VIDEO_CAPTURE)
+ s += "\t\tVideo Capture\n";
+ if (cap & V4L2_CAP_VIDEO_OUTPUT)
+ s += "\t\tVideo Output\n";
+ if (cap & V4L2_CAP_VIDEO_OVERLAY)
+ s += "\t\tVideo Overlay\n";
+ if (cap & V4L2_CAP_VIDEO_OUTPUT_OVERLAY)
+ s += "\t\tVideo Output Overlay\n";
+ if (cap & V4L2_CAP_VBI_CAPTURE)
+ s += "\t\tVBI Capture\n";
+ if (cap & V4L2_CAP_VBI_OUTPUT)
+ s += "\t\tVBI Output\n";
+ if (cap & V4L2_CAP_SLICED_VBI_CAPTURE)
+ s += "\t\tSliced VBI Capture\n";
+ if (cap & V4L2_CAP_SLICED_VBI_OUTPUT)
+ s += "\t\tSliced VBI Output\n";
+ if (cap & V4L2_CAP_RDS_CAPTURE)
+ s += "\t\tRDS Capture\n";
+ if (cap & V4L2_CAP_TUNER)
+ s += "\t\tTuner\n";
+ if (cap & V4L2_CAP_AUDIO)
+ s += "\t\tAudio\n";
+ if (cap & V4L2_CAP_RADIO)
+ s += "\t\tRadio\n";
+ if (cap & V4L2_CAP_READWRITE)
+ s += "\t\tRead/Write\n";
+ if (cap & V4L2_CAP_ASYNCIO)
+ s += "\t\tAsync I/O\n";
+ if (cap & V4L2_CAP_STREAMING)
+ s += "\t\tStreaming\n";
+ return s;
+}
+
+static v4l2_std_id parse_pal(const char *pal)
+{
+ if (pal[0] == '-') {
+ switch (pal[1]) {
+ case '6':
+ return V4L2_STD_PAL_60;
+ case 'b':
+ case 'B':
+ case 'g':
+ case 'G':
+ return V4L2_STD_PAL_BG;
+ case 'h':
+ case 'H':
+ return V4L2_STD_PAL_H;
+ case 'n':
+ case 'N':
+ if (pal[2] == 'c' || pal[2] == 'C')
+ return V4L2_STD_PAL_Nc;
+ return V4L2_STD_PAL_N;
+ case 'i':
+ case 'I':
+ return V4L2_STD_PAL_I;
+ case 'd':
+ case 'D':
+ case 'k':
+ case 'K':
+ return V4L2_STD_PAL_DK;
+ case 'M':
+ case 'm':
+ return V4L2_STD_PAL_M;
+ case '-':
+ break;
+ }
+ }
+ fprintf(stderr, "pal specifier not recognised\n");
+ return 0;
+}
+
+static v4l2_std_id parse_secam(const char *secam)
+{
+ if (secam[0] == '-') {
+ switch (secam[1]) {
+ case 'b':
+ case 'B':
+ case 'g':
+ case 'G':
+ case 'h':
+ case 'H':
+ return V4L2_STD_SECAM_B | V4L2_STD_SECAM_G | V4L2_STD_SECAM_H;
+ case 'd':
+ case 'D':
+ case 'k':
+ case 'K':
+ return V4L2_STD_SECAM_DK;
+ case 'l':
+ case 'L':
+ if (secam[2] == 'C' || secam[2] == 'c')
+ return V4L2_STD_SECAM_LC;
+ return V4L2_STD_SECAM_L;
+ case '-':
+ break;
+ }
+ }
+ fprintf(stderr, "secam specifier not recognised\n");
+ return 0;
+}
+
+static v4l2_std_id parse_ntsc(const char *ntsc)
+{
+ if (ntsc[0] == '-') {
+ switch (ntsc[1]) {
+ case 'm':
+ case 'M':
+ return V4L2_STD_NTSC_M;
+ case 'j':
+ case 'J':
+ return V4L2_STD_NTSC_M_JP;
+ case 'k':
+ case 'K':
+ return V4L2_STD_NTSC_M_KR;
+ case '-':
+ break;
+ }
+ }
+ fprintf(stderr, "ntsc specifier not recognised\n");
+ return 0;
+}
+
+static int doioctl(int fd, int request, void *parm, const char *name)
+{
+ int retVal;
+ int e;
+
+ errno = 0;
+ retVal = ioctl(fd, request, parm);
+ e = errno;
+ if (verbose)
+ printf("\t\t%s returned %d (%s)\n", name, retVal, strerror(e));
+ if (retVal == 0) return retVal;
+ if (retVal != -1) {
+ return -1;
+ }
+ retVal = e;
+ return retVal;
+}
+
+static int parse_subopt(char **subs, char * const *subopts, char **value)
+{
+ int opt = getsubopt(subs, subopts, value);
+
+ if (opt == -1) {
+ fprintf(stderr, "Invalid suboptions specified\n");
+ usage();
+ exit(1);
+ }
+ if (value == NULL) {
+ fprintf(stderr, "No value given to suboption <%s>\n",
+ subopts[opt]);
+ usage();
+ exit(1);
+ }
+ return opt;
+}
+
+static void parse_next_subopt(char **subs, char **value)
+{
+ static char *const subopts[] = {
+ NULL
+ };
+ int opt = getsubopt(subs, subopts, value);
+
+ if (value == NULL) {
+ fprintf(stderr, "No value given to suboption <%s>\n",
+ subopts[opt]);
+ usage();
+ exit(1);
+ }
+}
+
+static void print_std(const char *prefix, const char *stds[], unsigned long long std)
+{
+ int first = 1;
+
+ printf("\t%s-", prefix);
+ while (*stds) {
+ if (std & 1) {
+ if (!first)
+ printf("/");
+ first = 0;
+ printf("%s", *stds);
+ }
+ stds++;
+ std >>= 1;
+ }
+ printf("\n");
+}
+
+static const char *ok(int res)
+{
+ if (res)
+ app_result = res;
+ return res ? "FAIL" : "OK";
+}
+
+static int check_string(const char *s, int len, const char *fld)
+{
+ if (strlen(s) == 0) {
+ if (verbose)
+ printf("%s field empty\n", fld);
+ return -1;
+ }
+ if (strlen(s) >= len) {
+ if (verbose)
+ printf("%s field not 0-terminated\n", fld);
+ return -1;
+ }
+ return 0;
+}
+
+static int check_ustring(const __u8 *s, int len, const char *fld)
+{
+ return check_string((const char *)s, len, fld);
+}
+
+static int check_0(void *p, int len)
+{
+ __u8 *q = (__u8 *)p;
+
+ while (len--)
+ if (*q++) {
+ if (verbose)
+ printf("array not zeroed by driver\n");
+ return -1;
+ }
+ return 0;
+}
+
+static int testCap(int fd)
+{
+ struct v4l2_capability vcap;
+ __u32 caps;
+
+ if (doioctl(fd, VIDIOC_QUERYCAP, &vcap, "VIDIOC_QUERYCAP"))
+ return -1;
+ if (check_ustring(vcap.driver, sizeof(vcap.driver), "driver"))
+ return -1;
+ if (check_ustring(vcap.card, sizeof(vcap.card), "card"))
+ return -1;
+ if (check_ustring(vcap.bus_info, sizeof(vcap.bus_info), "bus_info"))
+ return -1;
+ if (check_0(vcap.reserved, sizeof(vcap.reserved)))
+ return -1;
+ caps = vcap.capabilities;
+ if (caps == 0) {
+ if (verbose) printf("no capabilities set\n");
+ return -1;
+ }
+ return 0;
+}
+
+static int testChipIdent(int fd)
+{
+ struct v4l2_chip_ident chip;
+ int ret;
+
+ chip.match_type = V4L2_CHIP_MATCH_HOST;
+ chip.match_chip = 0;
+ ret = doioctl(fd, VIDIOC_G_CHIP_IDENT, &chip, "VIDIOC_G_CHIP_IDENT");
+ // Must return either 0 (OK) or EINVAL (not supported)
+ if (ret == 0) {
+ struct v4l2_chip_ident orig;
+
+ // set invalid match_type
+ chip.match_type = V4L2_CHIP_MATCH_I2C_ADDR + 1;
+ chip.match_chip = 0xdeadbeef;
+ chip.ident = 0xdeadbeef;
+ chip.revision = 0xdeadbeef;
+ orig = chip;
+ ret = doioctl(fd, VIDIOC_G_CHIP_IDENT, &chip, "VIDIOC_G_CHIP_IDENT");
+ if (ret != EINVAL) {
+ if (verbose)
+ printf("Invalid match_type accepted\n");
+ return -1;
+ }
+ if (memcmp(&orig, &chip, sizeof(chip))) {
+ if (verbose)
+ printf("Error, but struct modified\n");
+ return -1;
+ }
+ return 0;
+ }
+ return ret != EINVAL;
+}
+
+static int testRegister(int fd)
+{
+ struct v4l2_register reg;
+ struct v4l2_chip_ident chip;
+ int ret;
+ int uid = getuid();
+
+ reg.match_type = V4L2_CHIP_MATCH_HOST;
+ reg.match_chip = 0;
+ reg.reg = 0;
+ ret = doioctl(fd, VIDIOC_DBG_G_REGISTER, &reg, "VIDIOC_DBG_G_REGISTER");
+ if (ret == EINVAL)
+ return 0;
+ if (uid && ret != EPERM) {
+ printf("Not allowed to call VIDIOC_DBG_G_REGISTER unless root\n");
+ return -1;
+ }
+ if (uid == 0 && ret) {
+ printf("Not allowed to call VIDIOC_DBG_G_REGISTER even though we are root\n");
+ return -1;
+ }
+ chip.match_type = V4L2_CHIP_MATCH_HOST;
+ chip.match_chip = 0;
+ if (doioctl(fd, VIDIOC_G_CHIP_IDENT, &chip, "VIDIOC_G_CHIP_IDENT")) {
+ printf("Must support VIDIOC_G_CHIP_IDENT\n");
+ return -1;
+ }
+ if (uid) {
+ // Don't test S_REGISTER as root, don't want to risk
+ // messing with registers in the compliance test.
+ reg.reg = reg.val = 0;
+ ret = doioctl(fd, VIDIOC_DBG_S_REGISTER, &reg, "VIDIOC_DBG_S_REGISTER");
+ if (ret != EINVAL && ret != EPERM) {
+ printf("Invalid error calling VIDIOC_DBG_S_REGISTER as non-root\n");
+ return -1;
+ }
+ }
+ return 0;
+}
+
+static int testLogStatus(int fd)
+{
+ int ret = doioctl(fd, VIDIOC_LOG_STATUS, NULL, "VIDIOC_LOG_STATUS");
+
+ return (ret == 0 || ret == EINVAL) ? 0 : -1;
+}
+
+int main(int argc, char **argv)
+{
+ char *value, *subs;
+ int i;
+ unsigned t;
+ int fd = -1;
+
+ /* command args */
+ int ch;
+ const char *device = "/dev/video0"; /* -d device */
+ struct v4l2_capability vcap; /* list_cap */
+ char short_options[26 * 2 * 2 + 1];
+ int idx = 0;
+ int tests = 0;
+
+ for (i = 0; long_options[i].name; i++) {
+ if (!isalpha(long_options[i].val))
+ continue;
+ short_options[idx++] = long_options[i].val;
+ if (long_options[i].has_arg == required_argument)
+ short_options[idx++] = ':';
+ }
+ while (1) {
+ int option_index = 0;
+
+ short_options[idx] = 0;
+ ch = getopt_long(argc, argv, short_options,
+ long_options, &option_index);
+ if (ch == -1)
+ break;
+
+ options[(int)ch] = 1;
+ switch (ch) {
+ case OptHelp:
+ usage();
+ return 0;
+ case OptTest:
+ t = strtoul(optarg, NULL, 0);
+
+ if (t >= TestMax)
+ usage();
+ test[t] = 1;
+ tests++;
+ break;
+ case OptSetDevice:
+ device = optarg;
+ if (device[0] >= '0' && device[0] <= '9' && device[1] == 0) {
+ static char newdev[20];
+ char dev = device[0];
+
+ sprintf(newdev, "/dev/video%c", dev);
+ device = newdev;
+ }
+ break;
+ case ':':
+ fprintf(stderr, "Option `%s' requires a value\n",
+ argv[optind]);
+ usage();
+ return 1;
+ case '?':
+ fprintf(stderr, "Unknown argument `%s'\n",
+ argv[optind]);
+ usage();
+ return 1;
+ }
+ }
+ if (optind < argc) {
+ printf("unknown arguments: ");
+ while (optind < argc)
+ printf("%s ", argv[optind++]);
+ printf("\n");
+ usage();
+ return 1;
+ }
+ verbose = options[OptVerbose];
+ if (!tests) {
+ for (t = 0; t < TestMax; t++)
+ test[t] = 1;
+ }
+
+ if ((fd = open(device, O_RDWR)) < 0) {
+ fprintf(stderr, "Failed to open %s: %s\n", device,
+ strerror(errno));
+ exit(1);
+ }
+
+ ioctl(fd, VIDIOC_QUERYCAP, &vcap, "VIDIOC_QUERYCAP");
+ caps = vcap.capabilities;
+ find_controls(fd);
+ for (ctrl_get_list::iterator iter = get_ctrls.begin(); iter != get_ctrls.end(); ++iter) {
+ if (ctrl_str2id.find(*iter) == ctrl_str2id.end()) {
+ fprintf(stderr, "unknown control '%s'\n", (*iter).c_str());
+ exit(1);
+ }
+ }
+ for (ctrl_set_map::iterator iter = set_ctrls.begin(); iter != set_ctrls.end(); ++iter) {
+ if (ctrl_str2id.find(iter->first) == ctrl_str2id.end()) {
+ fprintf(stderr, "unknown control '%s'\n", iter->first.c_str());
+ exit(1);
+ }
+ }
+
+ /* Information Opts */
+
+ if (options[OptGetDriverInfo]) {
+ printf("Driver Info:\n");
+ printf("\tDriver name : %s\n", vcap.driver);
+ printf("\tCard type : %s\n", vcap.card);
+ printf("\tBus info : %s\n", vcap.bus_info);
+ printf("\tDriver version: %d\n", vcap.version);
+ printf("\tCapabilities : 0x%08X\n", vcap.capabilities);
+ printf("%s", cap2s(vcap.capabilities).c_str());
+ }
+
+ printf("Compliance test for device %s:\n\n", device);
+
+ printf("Required ioctls:\n");
+ if (test[TestCap])
+ printf("\ttest VIDIOC_QUERYCAP: %s\n", ok(testCap(fd)));
+
+ printf("Debug ioctls:\n");
+ if (test[TestChipIdent])
+ printf("\ttest VIDIOC_G_CHIP_IDENT: %s\n", ok(testChipIdent(fd)));
+ if (test[TestRegister])
+ printf("\ttest VIDIOC_DBG_G/S_REGISTER: %s\n", ok(testRegister(fd)));
+ if (test[TestLogStatus])
+ printf("\ttest VIDIOC_LOG_STATUS: %s\n", ok(testLogStatus(fd)));
+
+ close(fd);
+ exit(app_result);
+}
diff --git a/v4l2-apps/util/v4l2-ctl.cpp b/v4l2-apps/util/v4l2-ctl.cpp
index 41946978a..417721c57 100644
--- a/v4l2-apps/util/v4l2-ctl.cpp
+++ b/v4l2-apps/util/v4l2-ctl.cpp
@@ -34,6 +34,7 @@
#include <errno.h>
#include <sys/ioctl.h>
#include <sys/time.h>
+#include <dirent.h>
#include <math.h>
#include <sys/klog.h>
@@ -43,6 +44,7 @@
#include <vector>
#include <map>
#include <string>
+#include <algorithm>
/* Short option list
@@ -77,15 +79,25 @@ enum Option {
OptSetVideoFormat = 'v',
OptGetSlicedVbiOutFormat = 128,
- OptSetSlicedVbiOutFormat,
OptGetOverlayFormat,
- //OptSetOverlayFormat, TODO
OptGetOutputOverlayFormat,
- OptSetOutputOverlayFormat,
OptGetVbiFormat,
- //OptSetVbiFormat, TODO
OptGetVbiOutFormat,
+ OptGetVideoOutFormat,
+ OptSetSlicedVbiOutFormat,
+ OptSetOutputOverlayFormat,
+ OptSetOverlayFormat,
+ //OptSetVbiFormat, TODO
//OptSetVbiOutFormat, TODO
+ OptSetVideoOutFormat,
+ OptTryVideoOutFormat,
+ OptTrySlicedVbiOutFormat,
+ OptTrySlicedVbiFormat,
+ OptTryVideoFormat,
+ OptTryOutputOverlayFormat,
+ OptTryOverlayFormat,
+ //OptTryVbiFormat, TODO
+ //OptTryVbiOutFormat, TODO
OptAll,
OptStreamOff,
OptStreamOn,
@@ -93,8 +105,7 @@ enum Option {
OptListFormats,
OptLogStatus,
OptVerbose,
- OptGetVideoOutFormat,
- OptSetVideoOutFormat,
+ OptSilent,
OptGetSlicedVbiCap,
OptGetSlicedVbiOutCap,
OptGetFBuf,
@@ -118,12 +129,14 @@ enum Option {
OptGetOverlayCropCap,
OptGetOutputOverlayCropCap,
OptOverlay,
+ OptListDevices,
OptLast = 256
};
static char options[OptLast];
static int app_result;
+static int verbose;
static unsigned capabilities;
@@ -142,6 +155,9 @@ static ctrl_get_list get_ctrls;
typedef std::map<std::string,std::string> ctrl_set_map;
static ctrl_set_map set_ctrls;
+typedef std::vector<std::string> dev_vec;
+typedef std::map<std::string, std::string> dev_map;
+
typedef struct {
unsigned flag;
const char *str;
@@ -160,6 +176,10 @@ static const flag_def service_def[] = {
#define FmtHeight (1L<<1)
#define FmtChromaKey (1L<<2)
#define FmtGlobalAlpha (1L<<3)
+#define FmtPixelFormat (1L<<4)
+#define FmtLeft (1L<<5)
+#define FmtTop (1L<<6)
+#define FmtField (1L<<7)
/* crop specified */
#define CropWidth (1L<<0)
@@ -174,8 +194,10 @@ static struct option long_options[] = {
{"device", required_argument, 0, OptSetDevice},
{"get-fmt-video", no_argument, 0, OptGetVideoFormat},
{"set-fmt-video", required_argument, 0, OptSetVideoFormat},
+ {"try-fmt-video", required_argument, 0, OptTryVideoFormat},
{"get-fmt-video-out", no_argument, 0, OptGetVideoOutFormat},
{"set-fmt-video-out", required_argument, 0, OptSetVideoOutFormat},
+ {"try-fmt-video-out", required_argument, 0, OptTryVideoOutFormat},
{"help", no_argument, 0, OptHelp},
{"get-output", no_argument, 0, OptGetOutput},
{"set-output", required_argument, 0, OptSetOutput},
@@ -205,12 +227,17 @@ static struct option long_options[] = {
{"verbose", no_argument, 0, OptVerbose},
{"log-status", no_argument, 0, OptLogStatus},
{"get-fmt-overlay", no_argument, 0, OptGetOverlayFormat},
+ {"set-fmt-overlay", required_argument, 0, OptSetOverlayFormat},
+ {"try-fmt-overlay", required_argument, 0, OptTryOverlayFormat},
{"get-fmt-output-overlay", no_argument, 0, OptGetOutputOverlayFormat},
{"set-fmt-output-overlay", required_argument, 0, OptSetOutputOverlayFormat},
+ {"try-fmt-output-overlay", required_argument, 0, OptTryOutputOverlayFormat},
{"get-fmt-sliced-vbi", no_argument, 0, OptGetSlicedVbiFormat},
{"set-fmt-sliced-vbi", required_argument, 0, OptSetSlicedVbiFormat},
+ {"try-fmt-sliced-vbi", required_argument, 0, OptTrySlicedVbiFormat},
{"get-fmt-sliced-vbi-out", no_argument, 0, OptGetSlicedVbiOutFormat},
{"set-fmt-sliced-vbi-out", required_argument, 0, OptSetSlicedVbiOutFormat},
+ {"try-fmt-sliced-vbi-out", required_argument, 0, OptTrySlicedVbiOutFormat},
{"get-fmt-vbi", no_argument, 0, OptGetVbiFormat},
{"get-fmt-vbi-out", no_argument, 0, OptGetVbiOutFormat},
{"get-sliced-vbi-cap", no_argument, 0, OptGetSlicedVbiCap},
@@ -230,132 +257,144 @@ static struct option long_options[] = {
{"get-crop-output-overlay", no_argument, 0, OptGetOutputOverlayCrop},
{"set-crop-output-overlay", required_argument, 0, OptSetOutputOverlayCrop},
{"overlay", required_argument, 0, OptOverlay},
+ {"list-devices", no_argument, 0, OptListDevices},
{0, 0, 0, 0}
};
static void usage(void)
{
printf("Usage:\n");
- printf("Common options:\n");
- printf(" --all display all information available\n");
- printf(" -B, --get-fmt-sliced-vbi\n");
- printf(" query the sliced VBI capture format [VIDIOC_G_FMT]\n");
- printf(" -b, --set-fmt-sliced-vbi=<mode>\n");
- printf(" set the sliced VBI capture format to <mode> [VIDIOC_S_FMT]\n");
- printf(" <mode> is a comma separated list of:\n");
- printf(" off: turn off sliced VBI (cannot be combined with other modes)\n");
- printf(" teletext: teletext (PAL/SECAM)\n");
- printf(" cc: closed caption (NTSC)\n");
- printf(" wss: widescreen signal (PAL/SECAM)\n");
- printf(" vps: VPS (PAL/SECAM)\n");
- printf(" -C, --get-ctrl=<ctrl>[,<ctrl>...]\n");
- printf(" get the value of the controls [VIDIOC_G_EXT_CTRLS]\n");
- printf(" -c, --set-ctrl=<ctrl>=<val>[,<ctrl>=<val>...]\n");
- printf(" set the controls to the values specified [VIDIOC_S_EXT_CTRLS]\n");
- printf(" -D, --info show driver info [VIDIOC_QUERYCAP]\n");
- printf(" -d, --device=<dev> use device <dev> instead of /dev/video0\n");
- printf(" if <dev> is a single digit, then /dev/video<dev> is used\n");
- printf(" -F, --get-freq query the frequency [VIDIOC_G_FREQUENCY]\n");
- printf(" -f, --set-freq=<freq>\n");
- printf(" set the frequency to <freq> MHz [VIDIOC_S_FREQUENCY]\n");
- printf(" -h, --help display this help message\n");
- printf(" -I, --get-input query the video input [VIDIOC_G_INPUT]\n");
- printf(" -i, --set-input=<num>\n");
- printf(" set the video input to <num> [VIDIOC_S_INPUT]\n");
- printf(" -l, --list-ctrls display all controls and their values [VIDIOC_QUERYCTRL]\n");
- printf(" -L, --list-ctrls-menus\n");
- printf(" display all controls, their values and the menus [VIDIOC_QUERYMENU]\n");
- printf(" -N, --list-outputs display video outputs [VIDIOC_ENUMOUTPUT]\n");
- printf(" -n, --list-inputs display video inputs [VIDIOC_ENUMINPUT]\n");
- printf(" -O, --get-output query the video output [VIDIOC_G_OUTPUT]\n");
- printf(" -o, --set-output=<num>\n");
- printf(" set the video output to <num> [VIDIOC_S_OUTPUT]\n");
- printf(" -S, --get-standard\n");
- printf(" query the video standard [VIDIOC_G_STD]\n");
- printf(" -s, --set-standard=<num>\n");
- printf(" set the video standard to <num> [VIDIOC_S_STD]\n");
- printf(" <num> can be a numerical v4l2_std value, or it can be one of:\n");
- printf(" pal-X (X = B/G/H/N/Nc/I/D/K/M/60) or just 'pal' (V4L2_STD_PAL)\n");
- printf(" ntsc-X (X = M/J/K) or just 'ntsc' (V4L2_STD_NTSC)\n");
- printf(" secam-X (X = B/G/H/D/K/L/Lc) or just 'secam' (V4L2_STD_SECAM)\n");
- printf(" --list-standards display supported video standards [VIDIOC_ENUMSTD]\n");
- printf(" -T, --get-tuner query the tuner settings [VIDIOC_G_TUNER]\n");
- printf(" -t, --set-tuner=<mode>\n");
- printf(" set the audio mode of the tuner [VIDIOC_S_TUNER]\n");
- printf(" Possible values: mono, stereo, lang2, lang1, bilingual\n");
- printf(" --list-formats display supported video formats [VIDIOC_ENUM_FMT]\n");
- printf(" -V, --get-fmt-video\n");
- printf(" query the video capture format [VIDIOC_G_FMT]\n");
- printf(" -v, --set-fmt-video=width=<w>,height=<h>\n");
- printf(" set the video capture format [VIDIOC_S_FMT]\n");
- printf(" --verbose turn on verbose ioctl error reporting.\n");
- printf("\n");
- printf("Uncommon options:\n");
- printf(" --get-fmt-video-out\n");
- printf(" query the video output format [VIDIOC_G_FMT]\n");
- printf(" --set-fmt-video-out=width=<w>,height=<h>\n");
- printf(" set the video output format [VIDIOC_S_FMT]\n");
- printf(" --get-fmt-overlay\n");
- printf(" query the video overlay format [VIDIOC_G_FMT]\n");
- printf(" --get-fmt-output-overlay\n");
- printf(" query the video output overlay format [VIDIOC_G_FMT]\n");
- printf(" --set-fmt-output-overlay=chromakey=<key>,global_alpha=<alpha>\n");
- printf(" set the video output overlay format [VIDIOC_S_FMT]\n");
- printf(" --get-sliced-vbi-cap\n");
- printf(" query the sliced VBI capture capabilities [VIDIOC_G_SLICED_VBI_CAP]\n");
- printf(" --get-sliced-vbi-out-cap\n");
- printf(" query the sliced VBI output capabilities [VIDIOC_G_SLICED_VBI_CAP]\n");
- printf(" --get-fmt-sliced-vbi-out\n");
- printf(" query the sliced VBI output format [VIDIOC_G_FMT]\n");
- printf(" --set-fmt-sliced-vbi-out=<mode>\n");
- printf(" set the sliced VBI output format to <mode> [VIDIOC_S_FMT]\n");
- printf(" <mode> is a comma separated list of:\n");
- printf(" off: turn off sliced VBI (cannot be combined with other modes)\n");
- printf(" teletext: teletext (PAL/SECAM)\n");
- printf(" cc: closed caption (NTSC)\n");
- printf(" wss: widescreen signal (PAL/SECAM)\n");
- printf(" vps: VPS (PAL/SECAM)\n");
- printf(" --get-fmt-vbi query the VBI capture format [VIDIOC_G_FMT]\n");
- printf(" --get-fmt-vbi-out query the VBI output format [VIDIOC_G_FMT]\n");
- printf(" --overlay=<on> turn overlay on (1) or off (0) (VIDIOC_OVERLAY)\n");
- printf(" --get-fbuf query the overlay framebuffer data [VIDIOC_G_FBUF]\n");
- printf(" --set-fbuf=chromakey=<0/1>,global_alpha=<0/1>,local_alpha=<0/1>,local_inv_alpha=<0/1>\n");
- printf(" set the overlay framebuffer [VIDIOC_S_FBUF]\n");
- printf(" --get-cropcap query the crop capabilities [VIDIOC_CROPCAP]\n");
- printf(" --get-crop query the video capture crop window [VIDIOC_G_CROP]\n");
- printf(" --set-crop=top=<x>,left=<y>,width=<w>,height=<h>\n");
- printf(" set the video capture crop window [VIDIOC_S_CROP]\n");
- printf(" --get-cropcap-output\n");
- printf(" query the crop capabilities for video output [VIDIOC_CROPCAP]\n");
- printf(" --get-crop-output query the video output crop window [VIDIOC_G_CROP]\n");
- printf(" --set-crop-output=top=<x>,left=<y>,width=<w>,height=<h>\n");
- printf(" set the video output crop window [VIDIOC_S_CROP]\n");
- printf(" --get-cropcap-overlay\n");
- printf(" query the crop capabilities for video overlay [VIDIOC_CROPCAP]\n");
- printf(" --get-crop-overlay query the video overlay crop window [VIDIOC_G_CROP]\n");
- printf(" --set-crop-overlay=top=<x>,left=<y>,width=<w>,height=<h>\n");
- printf(" set the video overlay crop window [VIDIOC_S_CROP]\n");
- printf(" --get-cropcap-output-overlay\n");
- printf(" query the crop capabilities for video output overlays [VIDIOC_CROPCAP]\n");
- printf(" --get-crop-output-overlay\n");
- printf(" query the video output overlay crop window [VIDIOC_G_CROP]\n");
- printf(" --set-crop-output-overlay=top=<x>,left=<y>,width=<w>,height=<h>\n");
- printf(" set the video output overlay crop window [VIDIOC_S_CROP]\n");
- printf(" --get-audio-input query the audio input [VIDIOC_G_AUDIO]\n");
- printf(" --set-audio-input=<num>\n");
- printf(" set the audio input to <num> [VIDIOC_S_AUDIO]\n");
- printf(" --get-audio-output query the audio output [VIDIOC_G_AUDOUT]\n");
- printf(" --set-audio-output=<num>\n");
- printf(" set the audio output to <num> [VIDIOC_S_AUDOUT]\n");
- printf(" --list-audio-outputs\n");
- printf(" display audio outputs [VIDIOC_ENUMAUDOUT]\n");
- printf(" --list-audio-inputs\n");
- printf(" display audio inputs [VIDIOC_ENUMAUDIO]\n");
- printf("\n");
- printf("Expert options:\n");
- printf(" --streamoff turn the stream off [VIDIOC_STREAMOFF]\n");
- printf(" --streamon turn the stream on [VIDIOC_STREAMOFF]\n");
- printf(" --log-status log the board status in the kernel log [VIDIOC_LOG_STATUS]\n");
+ printf("Common options:\n"
+ " --all display all information available\n"
+ " -C, --get-ctrl=<ctrl>[,<ctrl>...]\n"
+ " get the value of the controls [VIDIOC_G_EXT_CTRLS]\n"
+ " -c, --set-ctrl=<ctrl>=<val>[,<ctrl>=<val>...]\n"
+ " set the controls to the values specified [VIDIOC_S_EXT_CTRLS]\n"
+ " -D, --info show driver info [VIDIOC_QUERYCAP]\n"
+ " -d, --device=<dev> use device <dev> instead of /dev/video0\n"
+ " if <dev> is a single digit, then /dev/video<dev> is used\n"
+ " -F, --get-freq query the frequency [VIDIOC_G_FREQUENCY]\n"
+ " -f, --set-freq=<freq>\n"
+ " set the frequency to <freq> MHz [VIDIOC_S_FREQUENCY]\n"
+ " -h, --help display this help message\n"
+ " -I, --get-input query the video input [VIDIOC_G_INPUT]\n"
+ " -i, --set-input=<num>\n"
+ " set the video input to <num> [VIDIOC_S_INPUT]\n"
+ " -l, --list-ctrls display all controls and their values [VIDIOC_QUERYCTRL]\n"
+ " -L, --list-ctrls-menus\n"
+ " display all controls, their values and the menus [VIDIOC_QUERYMENU]\n"
+ " -N, --list-outputs display video outputs [VIDIOC_ENUMOUTPUT]\n"
+ " -n, --list-inputs display video inputs [VIDIOC_ENUMINPUT]\n"
+ " -O, --get-output query the video output [VIDIOC_G_OUTPUT]\n"
+ " -o, --set-output=<num>\n"
+ " set the video output to <num> [VIDIOC_S_OUTPUT]\n"
+ " -S, --get-standard\n"
+ " query the video standard [VIDIOC_G_STD]\n"
+ " -s, --set-standard=<num>\n"
+ " set the video standard to <num> [VIDIOC_S_STD]\n"
+ " <num> can be a numerical v4l2_std value, or it can be one of:\n"
+ " pal-X (X = B/G/H/N/Nc/I/D/K/M/60) or just 'pal' (V4L2_STD_PAL)\n"
+ " ntsc-X (X = M/J/K) or just 'ntsc' (V4L2_STD_NTSC)\n"
+ " secam-X (X = B/G/H/D/K/L/Lc) or just 'secam' (V4L2_STD_SECAM)\n"
+ " --list-standards display supported video standards [VIDIOC_ENUMSTD]\n"
+ " -T, --get-tuner query the tuner settings [VIDIOC_G_TUNER]\n"
+ " -t, --set-tuner=<mode>\n"
+ " set the audio mode of the tuner [VIDIOC_S_TUNER]\n"
+ " Possible values: mono, stereo, lang2, lang1, bilingual\n"
+ " --list-formats display supported video formats [VIDIOC_ENUM_FMT]\n"
+ " -V, --get-fmt-video\n"
+ " query the video capture format [VIDIOC_G_FMT]\n"
+ " -v, --set-fmt-video=width=<w>,height=<h>,pixelformat=<f>\n"
+ " set the video capture format [VIDIOC_S_FMT]\n"
+ " pixelformat is either the format index as reported by\n"
+ " --list-formats, or the fourcc value as a string\n"
+ " --list-devices list all v4l devices\n"
+ " --silent only set the result code, do not print any messages\n"
+ " --verbose turn on verbose ioctl status reporting\n"
+ "\n");
+ printf("Uncommon options:\n"
+ " --try-fmt-video=width=<w>,height=<h>,pixelformat=<f>\n"
+ " try the video capture format [VIDIOC_TRY_FMT]\n"
+ " pixelformat is either the format index as reported by\n"
+ " --list-formats, or the fourcc value as a string\n"
+ " --get-fmt-video-out\n"
+ " query the video output format [VIDIOC_G_FMT]\n"
+ " --set-fmt-video-out=width=<w>,height=<h>\n"
+ " set the video output format [VIDIOC_S_FMT]\n"
+ " --try-fmt-video-out=width=<w>,height=<h>\n"
+ " try the video output format [VIDIOC_TRY_FMT]\n"
+ " --get-fmt-overlay query the video overlay format [VIDIOC_G_FMT]\n"
+ " --get-fmt-output-overlay\n"
+ " query the video output overlay format [VIDIOC_G_FMT]\n"
+ " --set-fmt-overlay\n"
+ " --try-fmt-overlay\n"
+ " --set-fmt-output-overlay\n"
+ " --try-fmt-output-overlay=chromakey=<key>,global_alpha=<alpha>,\n"
+ " top=<t>,left=<l>,width=<w>,height=<h>,field=<f>\n"
+ " set/try the video or video output overlay format [VIDIOC_TRY_FMT]\n"
+ " <f> can be one of:\n"
+ " any, none, top, bottom, interlaced, seq_tb, seq_bt, alternate,\n"
+ " interlaced_tb, interlaced_bt\n"
+ " --get-sliced-vbi-cap\n"
+ " query the sliced VBI capture capabilities [VIDIOC_G_SLICED_VBI_CAP]\n"
+ " --get-sliced-vbi-out-cap\n"
+ " query the sliced VBI output capabilities [VIDIOC_G_SLICED_VBI_CAP]\n"
+ " -B, --get-fmt-sliced-vbi\n"
+ " query the sliced VBI capture format [VIDIOC_G_FMT]\n"
+ " --get-fmt-sliced-vbi-out\n"
+ " query the sliced VBI output format [VIDIOC_G_FMT]\n"
+ " -b, --set-fmt-sliced-vbi\n"
+ " --try-fmt-sliced-vbi\n"
+ " --set-fmt-sliced-vbi-out\n"
+ " --try-fmt-sliced-vbi-out=<mode>\n"
+ " (try to) set the sliced VBI capture/output format to <mode> [VIDIOC_S/TRY_FMT]\n"
+ " <mode> is a comma separated list of:\n"
+ " off: turn off sliced VBI (cannot be combined with other modes)\n"
+ " teletext: teletext (PAL/SECAM)\n"
+ " cc: closed caption (NTSC)\n"
+ " wss: widescreen signal (PAL/SECAM)\n"
+ " vps: VPS (PAL/SECAM)\n"
+ " --get-fmt-vbi query the VBI capture format [VIDIOC_G_FMT]\n"
+ " --get-fmt-vbi-out query the VBI output format [VIDIOC_G_FMT]\n"
+ " --overlay=<on> turn overlay on (1) or off (0) (VIDIOC_OVERLAY)\n"
+ " --get-fbuf query the overlay framebuffer data [VIDIOC_G_FBUF]\n"
+ " --set-fbuf=chromakey=<0/1>,global_alpha=<0/1>,local_alpha=<0/1>,local_inv_alpha=<0/1>\n"
+ " set the overlay framebuffer [VIDIOC_S_FBUF]\n"
+ " --get-cropcap query the crop capabilities [VIDIOC_CROPCAP]\n"
+ " --get-crop query the video capture crop window [VIDIOC_G_CROP]\n"
+ " --set-crop=top=<x>,left=<y>,width=<w>,height=<h>\n"
+ " set the video capture crop window [VIDIOC_S_CROP]\n"
+ " --get-cropcap-output\n"
+ " query the crop capabilities for video output [VIDIOC_CROPCAP]\n"
+ " --get-crop-output query the video output crop window [VIDIOC_G_CROP]\n"
+ " --set-crop-output=top=<x>,left=<y>,width=<w>,height=<h>\n"
+ " set the video output crop window [VIDIOC_S_CROP]\n"
+ " --get-cropcap-overlay\n"
+ " query the crop capabilities for video overlay [VIDIOC_CROPCAP]\n"
+ " --get-crop-overlay query the video overlay crop window [VIDIOC_G_CROP]\n"
+ " --set-crop-overlay=top=<x>,left=<y>,width=<w>,height=<h>\n"
+ " set the video overlay crop window [VIDIOC_S_CROP]\n"
+ " --get-cropcap-output-overlay\n"
+ " query the crop capabilities for video output overlays [VIDIOC_CROPCAP]\n"
+ " --get-crop-output-overlay\n"
+ " query the video output overlay crop window [VIDIOC_G_CROP]\n"
+ " --set-crop-output-overlay=top=<x>,left=<y>,width=<w>,height=<h>\n"
+ " set the video output overlay crop window [VIDIOC_S_CROP]\n"
+ " --get-audio-input query the audio input [VIDIOC_G_AUDIO]\n"
+ " --set-audio-input=<num>\n"
+ " set the audio input to <num> [VIDIOC_S_AUDIO]\n"
+ " --get-audio-output query the audio output [VIDIOC_G_AUDOUT]\n"
+ " --set-audio-output=<num>\n"
+ " set the audio output to <num> [VIDIOC_S_AUDOUT]\n"
+ " --list-audio-outputs\n"
+ " display audio outputs [VIDIOC_ENUMAUDOUT]\n"
+ " --list-audio-inputs\n"
+ " display audio inputs [VIDIOC_ENUMAUDIO]\n"
+ "\n");
+ printf("Expert options:\n"
+ " --streamoff turn the stream off [VIDIOC_STREAMOFF]\n"
+ " --streamon turn the stream on [VIDIOC_STREAMOFF]\n"
+ " --log-status log the board status in the kernel log [VIDIOC_LOG_STATUS]\n");
exit(0);
}
@@ -701,7 +740,7 @@ static void printfbuf(const struct v4l2_framebuffer &fb)
printf("\tBase : 0x%p\n", fb.base);
printf("\tWidth : %d\n", fb.fmt.width);
printf("\tHeight : %d\n", fb.fmt.height);
- printf("\tPixel Format : %s\n", fcc2s(fb.fmt.pixelformat).c_str());
+ printf("\tPixel Format : '%s'\n", fcc2s(fb.fmt.pixelformat).c_str());
if (!is_ext) {
printf("\tBytes per Line: %d\n", fb.fmt.bytesperline);
printf("\tSize image : %d\n", fb.fmt.sizeimage);
@@ -740,7 +779,7 @@ static void printfmt(struct v4l2_format vfmt)
case V4L2_BUF_TYPE_VIDEO_CAPTURE:
case V4L2_BUF_TYPE_VIDEO_OUTPUT:
printf("\tWidth/Height : %u/%u\n", vfmt.fmt.pix.width, vfmt.fmt.pix.height);
- printf("\tPixel Format : %s\n", fcc2s(vfmt.fmt.pix.pixelformat).c_str());
+ printf("\tPixel Format : '%s'\n", fcc2s(vfmt.fmt.pix.pixelformat).c_str());
printf("\tField : %s\n", field2s(vfmt.fmt.pix.field).c_str());
printf("\tBytes per Line: %u\n", vfmt.fmt.pix.bytesperline);
printf("\tSize Image : %u\n", vfmt.fmt.pix.sizeimage);
@@ -798,8 +837,9 @@ static void print_video_formats(int fd, enum v4l2_buf_type type)
fmt.index = 0;
fmt.type = type;
while (ioctl(fd, VIDIOC_ENUM_FMT, &fmt) >= 0) {
+ printf("\tIndex : %d\n", fmt.index);
printf("\tType : %s\n", buftype2s(type).c_str());
- printf("\tPixelformat : %s", fcc2s(fmt.pixelformat).c_str());
+ printf("\tPixel Format: '%s'", fcc2s(fmt.pixelformat).c_str());
if (fmt.flags)
printf(" (compressed)");
printf("\n");
@@ -1013,16 +1053,94 @@ static int doioctl(int fd, int request, void *parm, const char *name)
if (retVal < 0) {
app_result = -1;
}
- if (!options[OptVerbose]) return retVal;
- printf("%s: ", name);
+ if (options[OptSilent]) return retVal;
if (retVal < 0)
- printf("failed: %s\n", strerror(errno));
- else
- printf("ok\n");
+ printf("%s: failed: %s\n", name, strerror(errno));
+ else if (verbose)
+ printf("%s: ok\n", name);
return retVal;
}
+static bool is_v4l_dev(const char *name)
+{
+ return !memcmp(name, "vtx", 3) ||
+ !memcmp(name, "video", 5) ||
+ !memcmp(name, "radio", 5) ||
+ !memcmp(name, "vbi", 3);
+}
+
+static int calc_node_val(const char *s)
+{
+ int n = 0;
+
+ s = strrchr(s, '/') + 1;
+ if (!memcmp(s, "video", 5)) n = 0;
+ else if (!memcmp(s, "radio", 5)) n = 0x100;
+ else if (!memcmp(s, "vbi", 3)) n = 0x200;
+ else if (!memcmp(s, "vtx", 3)) n = 0x300;
+ n += atol(s + (n >= 0x200 ? 3 : 5));
+ return n;
+}
+
+static bool sort_on_device_name(const std::string &s1, const std::string &s2)
+{
+ int n1 = calc_node_val(s1.c_str());
+ int n2 = calc_node_val(s2.c_str());
+
+ return n1 < n2;
+}
+
+static void list_devices()
+{
+ DIR *dp;
+ struct dirent *ep;
+ dev_vec files;
+ dev_map cards;
+ struct v4l2_capability vcap;
+
+ dp = opendir("/dev");
+ if (dp == NULL) {
+ perror ("Couldn't open the directory");
+ return;
+ }
+ while (ep = readdir(dp))
+ if (is_v4l_dev(ep->d_name))
+ files.push_back(std::string("/dev/") + ep->d_name);
+ closedir(dp);
+
+#if 0
+ dp = opendir("/dev/v4l");
+ if (dp) {
+ while (ep = readdir(dp))
+ if (is_v4l_dev(ep->d_name))
+ files.push_back(std::string("/dev/v4l/") + ep->d_name);
+ closedir(dp);
+ }
+#endif
+
+ std::sort(files.begin(), files.end(), sort_on_device_name);
+
+ for (dev_vec::iterator iter = files.begin();
+ iter != files.end(); ++iter) {
+ int fd = open(iter->c_str(), O_RDWR);
+ std::string bus_info;
+
+ if (fd < 0)
+ continue;
+ doioctl(fd, VIDIOC_QUERYCAP, &vcap, "VIDIOC_QUERYCAP");
+ close(fd);
+ bus_info = (const char *)vcap.bus_info;
+ if (cards[bus_info].empty())
+ cards[bus_info] += std::string((char *)vcap.card) + " (" + bus_info + "):\n";
+ cards[bus_info] += "\t" + (*iter) + "\n";
+ }
+ for (dev_map::iterator iter = cards.begin();
+ iter != cards.end(); ++iter) {
+ printf("%s\n", iter->second.c_str());
+ }
+}
+
static int parse_subopt(char **subs, const char * const *subopts, char **value)
{
int opt = getsubopt(subs, (char * const *)subopts, value);
@@ -1127,6 +1245,21 @@ static void parse_crop(char *optarg, unsigned int &set_crop, v4l2_rect &vcrop)
}
}
+static enum v4l2_field parse_field(const char *s)
+{
+ if (!strcmp(s, "any")) return V4L2_FIELD_ANY;
+ if (!strcmp(s, "none")) return V4L2_FIELD_NONE;
+ if (!strcmp(s, "top")) return V4L2_FIELD_TOP;
+ if (!strcmp(s, "bottom")) return V4L2_FIELD_BOTTOM;
+ if (!strcmp(s, "interlaced")) return V4L2_FIELD_INTERLACED;
+ if (!strcmp(s, "seq_tb")) return V4L2_FIELD_SEQ_TB;
+ if (!strcmp(s, "seq_bt")) return V4L2_FIELD_SEQ_BT;
+ if (!strcmp(s, "alternate")) return V4L2_FIELD_ALTERNATE;
+ if (!strcmp(s, "interlaced_tb")) return V4L2_FIELD_INTERLACED_TB;
+ if (!strcmp(s, "interlaced_bt")) return V4L2_FIELD_INTERLACED_BT;
+ return V4L2_FIELD_ANY;
+}
+
int main(int argc, char **argv)
{
char *value, *subs;
@@ -1142,6 +1275,7 @@ int main(int argc, char **argv)
unsigned int set_crop_overlay = 0;
unsigned int set_crop_out_overlay = 0;
unsigned int set_fbuf = 0;
+ unsigned int set_overlay_fmt = 0;
unsigned int set_overlay_fmt_out = 0;
int mode = V4L2_TUNER_MODE_STEREO; /* set audio mode */
@@ -1155,6 +1289,7 @@ int main(int argc, char **argv)
struct v4l2_format vbi_fmt_out; /* set_format/get_format for sliced VBI output */
struct v4l2_format raw_fmt; /* set_format/get_format for VBI */
struct v4l2_format raw_fmt_out; /* set_format/get_format for VBI output */
+ struct v4l2_format overlay_fmt; /* set_format/get_format video overlay */
struct v4l2_format overlay_fmt_out; /* set_format/get_format video overlay output */
struct v4l2_tuner tuner; /* set_tuner/get_tuner */
struct v4l2_capability vcap; /* list_cap */
@@ -1174,14 +1309,18 @@ int main(int argc, char **argv)
struct v4l2_frequency vf; /* get_freq/set_freq */
struct v4l2_standard vs; /* list_std */
int overlay; /* overlay */
+ unsigned int *set_overlay_fmt_ptr;
+ struct v4l2_format *overlay_fmt_ptr;
char short_options[26 * 2 * 2 + 1];
int idx = 0;
+ int ret;
memset(&vfmt, 0, sizeof(vfmt));
memset(&vbi_fmt, 0, sizeof(vbi_fmt));
memset(&raw_fmt, 0, sizeof(raw_fmt));
memset(&vfmt_out, 0, sizeof(vfmt_out));
memset(&vbi_fmt_out, 0, sizeof(vbi_fmt_out));
+ memset(&overlay_fmt, 0, sizeof(overlay_fmt));
memset(&overlay_fmt_out, 0, sizeof(overlay_fmt_out));
memset(&raw_fmt_out, 0, sizeof(raw_fmt_out));
memset(&tuner, 0, sizeof(tuner));
@@ -1234,11 +1373,13 @@ int main(int argc, char **argv)
}
break;
case OptSetVideoFormat:
+ case OptTryVideoFormat:
subs = optarg;
while (*subs != '\0') {
static const char *const subopts[] = {
"width",
"height",
+ "pixelformat",
NULL
};
@@ -1251,10 +1392,20 @@ int main(int argc, char **argv)
vfmt.fmt.pix.height = strtol(value, 0L, 0);
set_fmts |= FmtHeight;
break;
+ case 2:
+ if (strlen(value) == 4)
+ vfmt.fmt.pix.pixelformat =
+ v4l2_fourcc(value[0], value[1],
+ value[2], value[3]);
+ else
+ vfmt.fmt.pix.pixelformat = strtol(value, 0L, 0);
+ set_fmts |= FmtPixelFormat;
+ break;
}
}
break;
case OptSetVideoOutFormat:
+ case OptTryVideoOutFormat:
subs = optarg;
while (*subs != '\0') {
static const char *const subopts[] = {
@@ -1275,23 +1426,63 @@ int main(int argc, char **argv)
}
}
break;
+ case OptSetOverlayFormat:
+ case OptTryOverlayFormat:
case OptSetOutputOverlayFormat:
+ case OptTryOutputOverlayFormat:
+ switch (ch) {
+ case OptSetOverlayFormat:
+ case OptTryOverlayFormat:
+ set_overlay_fmt_ptr = &set_overlay_fmt;
+ overlay_fmt_ptr = &overlay_fmt;
+ break;
+ case OptSetOutputOverlayFormat:
+ case OptTryOutputOverlayFormat:
+ set_overlay_fmt_ptr = &set_overlay_fmt_out;
+ overlay_fmt_ptr = &overlay_fmt_out;
+ break;
+ }
subs = optarg;
while (*subs != '\0') {
static const char *const subopts[] = {
"chromakey",
"global_alpha",
+ "left",
+ "top",
+ "width",
+ "height",
+ "field",
NULL
};
switch (parse_subopt(&subs, subopts, &value)) {
case 0:
- overlay_fmt_out.fmt.win.chromakey = strtol(value, 0L, 0);
- set_overlay_fmt_out |= FmtChromaKey;
+ overlay_fmt_ptr->fmt.win.chromakey = strtol(value, 0L, 0);
+ *set_overlay_fmt_ptr |= FmtChromaKey;
break;
case 1:
- overlay_fmt_out.fmt.win.global_alpha = strtol(value, 0L, 0);
- set_overlay_fmt_out |= FmtGlobalAlpha;
+ overlay_fmt_ptr->fmt.win.global_alpha = strtol(value, 0L, 0);
+ *set_overlay_fmt_ptr |= FmtGlobalAlpha;
+ break;
+ case 2:
+ overlay_fmt_ptr->fmt.win.w.left = strtol(value, 0L, 0);
+ *set_overlay_fmt_ptr |= FmtLeft;
+ break;
+ case 3:
+ overlay_fmt_ptr->fmt.win.w.top = strtol(value, 0L, 0);
+ *set_overlay_fmt_ptr |= FmtTop;
+ break;
+ case 4:
+ overlay_fmt_ptr->fmt.win.w.width = strtol(value, 0L, 0);
+ *set_overlay_fmt_ptr |= FmtWidth;
+ break;
+ case 5:
+ overlay_fmt_ptr->fmt.win.w.height = strtol(value, 0L, 0);
+ *set_overlay_fmt_ptr |= FmtHeight;
+ break;
+ case 6:
+ overlay_fmt_ptr->fmt.win.field = parse_field(value);
+ *set_overlay_fmt_ptr |= FmtField;
break;
}
}
@@ -1425,11 +1616,13 @@ int main(int argc, char **argv)
break;
case OptSetSlicedVbiFormat:
case OptSetSlicedVbiOutFormat:
+ case OptTrySlicedVbiFormat:
+ case OptTrySlicedVbiOutFormat:
{
bool foundOff = false;
v4l2_format *fmt = &vbi_fmt;
- if (ch == OptSetSlicedVbiOutFormat)
+ if (ch == OptSetSlicedVbiOutFormat || ch == OptTrySlicedVbiOutFormat)
fmt = &vbi_fmt_out;
fmt->fmt.sliced.service_set = 0;
subs = optarg;
@@ -1472,6 +1665,9 @@ int main(int argc, char **argv)
}
break;
}
+ case OptListDevices:
+ list_devices();
+ break;
case ':':
fprintf(stderr, "Option `%s' requires a value\n",
argv[optind]);
@@ -1499,6 +1695,7 @@ int main(int argc, char **argv)
exit(1);
}
+ verbose = options[OptVerbose];
doioctl(fd, VIDIOC_QUERYCAP, &vcap, "VIDIOC_QUERYCAP");
capabilities = vcap.capabilities;
find_controls(fd);
@@ -1536,6 +1733,7 @@ int main(int argc, char **argv)
options[OptGetFBuf] = 1;
options[OptGetCropCap] = 1;
options[OptGetOutputCropCap] = 1;
+ options[OptSilent] = 1;
}
/* Information Opts */
@@ -1618,7 +1816,7 @@ int main(int argc, char **argv)
}
}
- if (options[OptSetVideoFormat]) {
+ if (options[OptSetVideoFormat] || options[OptTryVideoFormat]) {
struct v4l2_format in_vfmt;
in_vfmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
@@ -1627,11 +1825,29 @@ int main(int argc, char **argv)
in_vfmt.fmt.pix.width = vfmt.fmt.pix.width;
if (set_fmts & FmtHeight)
in_vfmt.fmt.pix.height = vfmt.fmt.pix.height;
- doioctl(fd, VIDIOC_S_FMT, &in_vfmt, "VIDIOC_S_FMT");
+ if (set_fmts & FmtPixelFormat) {
+ in_vfmt.fmt.pix.pixelformat = vfmt.fmt.pix.pixelformat;
+ if (in_vfmt.fmt.pix.pixelformat < 256) {
+ struct v4l2_fmtdesc fmt;
+
+ fmt.index = in_vfmt.fmt.pix.pixelformat;
+ fmt.type = in_vfmt.type;
+ if (doioctl(fd, VIDIOC_ENUM_FMT, &fmt, "VIDIOC_ENUM_FMT"))
+ goto set_vid_fmt_error;
+ in_vfmt.fmt.pix.pixelformat = fmt.pixelformat;
+ }
+ }
+ if (options[OptSetVideoFormat])
+ ret = doioctl(fd, VIDIOC_S_FMT, &in_vfmt, "VIDIOC_S_FMT");
+ else
+ ret = doioctl(fd, VIDIOC_TRY_FMT, &in_vfmt, "VIDIOC_TRY_FMT");
+ if (ret == 0 && verbose)
+ printfmt(in_vfmt);
}
}
+set_vid_fmt_error:
- if (options[OptSetVideoOutFormat]) {
+ if (options[OptSetVideoOutFormat] || options[OptTryVideoOutFormat]) {
struct v4l2_format in_vfmt;
in_vfmt.type = V4L2_BUF_TYPE_VIDEO_OUTPUT;
@@ -1640,35 +1856,65 @@ int main(int argc, char **argv)
in_vfmt.fmt.pix.width = vfmt_out.fmt.pix.width;
if (set_fmts_out & FmtHeight)
in_vfmt.fmt.pix.height = vfmt_out.fmt.pix.height;
- doioctl(fd, VIDIOC_S_FMT, &in_vfmt, "VIDIOC_S_FMT");
+
+ if (options[OptSetVideoOutFormat])
+ ret = doioctl(fd, VIDIOC_S_FMT, &in_vfmt, "VIDIOC_S_FMT");
+ else
+ ret = doioctl(fd, VIDIOC_TRY_FMT, &in_vfmt, "VIDIOC_TRY_FMT");
+ if (ret == 0 && verbose)
+ printfmt(in_vfmt);
}
}
- if (options[OptSetSlicedVbiFormat]) {
- if (vbi_fmt.fmt.sliced.service_set == 0) {
- // switch to raw mode
- vbi_fmt.type = V4L2_BUF_TYPE_VBI_CAPTURE;
- if (doioctl(fd, VIDIOC_G_FMT, &vbi_fmt, "VIDIOC_G_FMT") == 0)
- doioctl(fd, VIDIOC_S_FMT, &vbi_fmt, "VIDIOC_S_FMT");
- } else {
- vbi_fmt.type = V4L2_BUF_TYPE_SLICED_VBI_CAPTURE;
- doioctl(fd, VIDIOC_S_FMT, &vbi_fmt, "VIDIOC_S_FMT");
- }
+ if (options[OptSetSlicedVbiFormat] || options[OptTrySlicedVbiFormat]) {
+ vbi_fmt.type = V4L2_BUF_TYPE_SLICED_VBI_CAPTURE;
+ if (options[OptSetSlicedVbiFormat])
+ ret = doioctl(fd, VIDIOC_S_FMT, &vbi_fmt, "VIDIOC_S_FMT");
+ else
+ ret = doioctl(fd, VIDIOC_TRY_FMT, &vbi_fmt, "VIDIOC_TRY_FMT");
+ if (ret == 0 && verbose)
+ printfmt(vbi_fmt);
+ }
+
+ if (options[OptSetSlicedVbiOutFormat] || options[OptTrySlicedVbiOutFormat]) {
+ vbi_fmt_out.type = V4L2_BUF_TYPE_SLICED_VBI_OUTPUT;
+ if (options[OptSetSlicedVbiOutFormat])
+ ret = doioctl(fd, VIDIOC_S_FMT, &vbi_fmt_out, "VIDIOC_S_FMT");
+ else
+ ret = doioctl(fd, VIDIOC_TRY_FMT, &vbi_fmt_out, "VIDIOC_TRY_FMT");
+ if (ret == 0 && verbose)
+ printfmt(vbi_fmt_out);
}
- if (options[OptSetSlicedVbiOutFormat]) {
- if (vbi_fmt_out.fmt.sliced.service_set == 0) {
- // switch to raw mode
- vbi_fmt_out.type = V4L2_BUF_TYPE_VBI_OUTPUT;
- if (doioctl(fd, VIDIOC_G_FMT, &vbi_fmt_out, "VIDIOC_G_FMT") == 0)
- doioctl(fd, VIDIOC_S_FMT, &vbi_fmt_out, "VIDIOC_S_FMT");
- } else {
- vbi_fmt_out.type = V4L2_BUF_TYPE_SLICED_VBI_OUTPUT;
- doioctl(fd, VIDIOC_S_FMT, &vbi_fmt_out, "VIDIOC_S_FMT");
+ if (options[OptSetOverlayFormat] || options[OptTryOverlayFormat]) {
+ struct v4l2_format fmt;
+
+ fmt.type = V4L2_BUF_TYPE_VIDEO_OVERLAY;
+ if (doioctl(fd, VIDIOC_G_FMT, &fmt, "VIDIOC_G_FMT") == 0) {
+ if (set_overlay_fmt & FmtChromaKey)
+ fmt.fmt.win.chromakey = overlay_fmt.fmt.win.chromakey;
+ if (set_overlay_fmt & FmtGlobalAlpha)
+ fmt.fmt.win.global_alpha = overlay_fmt.fmt.win.global_alpha;
+ if (set_overlay_fmt & FmtLeft)
+ fmt.fmt.win.w.left = overlay_fmt.fmt.win.w.left;
+ if (set_overlay_fmt & FmtTop)
+ fmt.fmt.win.w.top = overlay_fmt.fmt.win.w.top;
+ if (set_overlay_fmt & FmtWidth)
+ fmt.fmt.win.w.width = overlay_fmt.fmt.win.w.width;
+ if (set_overlay_fmt & FmtHeight)
+ fmt.fmt.win.w.height = overlay_fmt.fmt.win.w.height;
+ if (set_overlay_fmt & FmtField)
+ fmt.fmt.win.field = overlay_fmt.fmt.win.field;
+ if (options[OptSetOverlayFormat])
+ ret = doioctl(fd, VIDIOC_S_FMT, &fmt, "VIDIOC_S_FMT");
+ else
+ ret = doioctl(fd, VIDIOC_TRY_FMT, &fmt, "VIDIOC_TRY_FMT");
+ if (ret == 0 && verbose)
+ printfmt(fmt);
}
}
- if (options[OptSetOutputOverlayFormat]) {
+ if (options[OptSetOutputOverlayFormat] || options[OptTryOutputOverlayFormat]) {
struct v4l2_format fmt;
fmt.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_OVERLAY;
@@ -1677,7 +1923,22 @@ int main(int argc, char **argv)
fmt.fmt.win.chromakey = overlay_fmt_out.fmt.win.chromakey;
if (set_overlay_fmt_out & FmtGlobalAlpha)
fmt.fmt.win.global_alpha = overlay_fmt_out.fmt.win.global_alpha;
- doioctl(fd, VIDIOC_S_FMT, &fmt, "VIDIOC_S_FMT");
+ if (set_overlay_fmt_out & FmtLeft)
+ fmt.fmt.win.w.left = overlay_fmt_out.fmt.win.w.left;
+ if (set_overlay_fmt_out & FmtTop)
+ fmt.fmt.win.w.top = overlay_fmt_out.fmt.win.w.top;
+ if (set_overlay_fmt_out & FmtWidth)
+ fmt.fmt.win.w.width = overlay_fmt_out.fmt.win.w.width;
+ if (set_overlay_fmt_out & FmtHeight)
+ fmt.fmt.win.w.height = overlay_fmt_out.fmt.win.w.height;
+ if (set_overlay_fmt_out & FmtField)
+ fmt.fmt.win.field = overlay_fmt_out.fmt.win.field;
+ if (options[OptSetOutputOverlayFormat])
+ ret = doioctl(fd, VIDIOC_S_FMT, &fmt, "VIDIOC_S_FMT");
+ else
+ ret = doioctl(fd, VIDIOC_TRY_FMT, &fmt, "VIDIOC_TRY_FMT");
+ if (ret == 0 && verbose)
+ printfmt(fmt);
}
}
@@ -1997,6 +2258,7 @@ int main(int argc, char **argv)
memset(&vt, 0, sizeof(struct v4l2_tuner));
if (doioctl(fd, VIDIOC_G_TUNER, &vt, "VIDIOC_G_TUNER") == 0) {
printf("Tuner:\n");
+ printf("\tName : %s\n", vt.name);
printf("\tCapabilities : %s\n", tcap2s(vt.capability).c_str());
if (vt.capability & V4L2_TUNER_CAP_LOW)
printf("\tFrequency range : %.1f MHz - %.1f MHz\n",
@@ -2004,7 +2266,7 @@ int main(int argc, char **argv)
else
printf("\tFrequency range : %.1f MHz - %.1f MHz\n",
vt.rangelow / 16.0, vt.rangehigh / 16.0);
- printf("\tSignal strength : %d%%\n", (int)(vt.signal / 655.35));
+ printf("\tSignal strength/AFC : %d%%/%d\n", (int)(vt.signal / 655.35), vt.afc);
printf("\tCurrent audio mode : %s\n", audmode2s(vt.audmode));
printf("\tAvailable subchannels: %s\n",
rxsubchans2s(vt.rxsubchans).c_str());
@@ -2118,7 +2380,7 @@ int main(int argc, char **argv)
while (ioctl(fd, VIDIOC_ENUMSTD, &vs) >= 0) {
if (vs.index)
printf("\n");
- printf("\tindex : %d\n", vs.index);
+ printf("\tIndex : %d\n", vs.index);
printf("\tID : 0x%016llX\n", (unsigned long long)vs.id);
printf("\tName : %s\n", vs.name);
printf("\tFrame period: %d/%d\n",
diff --git a/v4l2-apps/util/bttv-dbg.h b/v4l2-apps/util/v4l2-dbg-bttv.h
index 02f829773..cf6274284 100644
--- a/v4l2-apps/util/bttv-dbg.h
+++ b/v4l2-apps/util/v4l2-dbg-bttv.h
@@ -14,7 +14,7 @@
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
-#include "v4l-board-dbg.h"
+#include "v4l2-dbg.h"
#define BTTV_IDENT "bttv"
diff --git a/v4l2-apps/util/em28xx-dbg.h b/v4l2-apps/util/v4l2-dbg-em28xx.h
index 3d3600c44..c5117c6e7 100644
--- a/v4l2-apps/util/em28xx-dbg.h
+++ b/v4l2-apps/util/v4l2-dbg-em28xx.h
@@ -14,7 +14,7 @@
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
-#include "v4l-board-dbg.h"
+#include "v4l2-dbg.h"
#define EM28XX_IDENT "em28xx"
diff --git a/v4l2-apps/util/saa7134-dbg.h b/v4l2-apps/util/v4l2-dbg-saa7134.h
index aee29da76..70fd4e068 100644
--- a/v4l2-apps/util/saa7134-dbg.h
+++ b/v4l2-apps/util/v4l2-dbg-saa7134.h
@@ -14,7 +14,7 @@
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
-#include "v4l-board-dbg.h"
+#include "v4l2-dbg.h"
#define SAA7134_IDENT "saa7134"
diff --git a/v4l2-apps/util/v4l2-dbg.cpp b/v4l2-apps/util/v4l2-dbg.cpp
index 2561f42b2..e0d6153fe 100644
--- a/v4l2-apps/util/v4l2-dbg.cpp
+++ b/v4l2-apps/util/v4l2-dbg.cpp
@@ -42,6 +42,48 @@
#include <map>
#include <string>
+#include "v4l2-dbg-bttv.h"
+#include "v4l2-dbg-saa7134.h"
+#include "v4l2-dbg-em28xx.h"
+
+#define ARRAY_SIZE(arr) ((int)(sizeof(arr) / sizeof((arr)[0])))
+
+struct board_list {
+ const char *name;
+ int prefix; /* Register prefix size */
+ const struct board_regs *regs;
+ int regs_size;
+ const struct board_regs *alt_regs;
+ int alt_regs_size;
+};
+
+static const struct board_list boards[] = {
+ { /* From bttv-dbg.h */
+ BTTV_IDENT,
+ sizeof(BTTV_PREFIX) - 1,
+ bt8xx_regs,
+ ARRAY_SIZE(bt8xx_regs),
+ bt8xx_regs_other,
+ ARRAY_SIZE(bt8xx_regs_other),
+ },
+ { /* From saa7134-dbg.h */
+ SAA7134_IDENT,
+ sizeof(SAA7134_PREFIX) - 1,
+ saa7134_regs,
+ ARRAY_SIZE(saa7134_regs),
+ NULL,
+ 0,
+ },
+ { /* From em28xx-dbg.h */
+ EM28XX_IDENT,
+ sizeof(EM28XX_PREFIX) - 1,
+ em28xx_regs,
+ ARRAY_SIZE(em28xx_regs),
+ NULL,
+ 0,
+ },
+};
+
struct driverid {
const char *name;
unsigned id;
@@ -64,19 +106,21 @@ extern struct chipid chipids[];
In general the lower case is used to set something and the upper
case is used to retrieve a setting. */
enum Option {
- OptListRegisters = 'R',
- OptSetRegister = 'r',
- OptSetSlicedVbiFormat = 'b',
+ OptListRegisters = 'l',
+ OptGetRegister = 'g',
+ OptSetRegister = 's',
OptSetDevice = 'd',
OptGetDriverInfo = 'D',
- OptScanChipIdents = 'C',
- OptGetChipIdent = 'c',
+ OptChip = 'c',
+ OptScanChipIdents = 'S',
+ OptGetChipIdent = 'i',
OptSetStride = 'w',
OptHelp = 'h',
OptLogStatus = 128,
OptVerbose,
OptListDriverIDs,
+ OptListSymbols,
OptLast = 256
};
@@ -87,56 +131,56 @@ static unsigned capabilities;
static struct option long_options[] = {
{"device", required_argument, 0, OptSetDevice},
{"help", no_argument, 0, OptHelp},
- {"list-registers", required_argument, 0, OptListRegisters},
+ {"list-registers", optional_argument, 0, OptListRegisters},
+ {"get-register", required_argument, 0, OptGetRegister},
{"set-register", required_argument, 0, OptSetRegister},
+ {"chip", required_argument, 0, OptChip},
{"scan-chip-idents", no_argument, 0, OptScanChipIdents},
{"get-chip-ident", required_argument, 0, OptGetChipIdent},
{"info", no_argument, 0, OptGetDriverInfo},
{"verbose", no_argument, 0, OptVerbose},
{"log-status", no_argument, 0, OptLogStatus},
{"list-driverids", no_argument, 0, OptListDriverIDs},
+ {"list-symbols", no_argument, 0, OptListSymbols},
{"wide", required_argument, 0, OptSetStride},
{0, 0, 0, 0}
};
static void usage(void)
{
- printf("Usage:\n");
- printf(" -D, --info show driver info [VIDIOC_QUERYCAP]\n");
- printf(" -d, --device=<dev> use device <dev> instead of /dev/video0\n");
- printf(" if <dev> is a single digit, then /dev/video<dev> is used\n");
- printf(" -h, --help display this help message\n");
- printf(" --verbose turn on verbose ioctl error reporting.\n");
- printf(" -R, --list-registers=type=<host/i2cdrv/i2caddr>,chip=<chip>[,min=<addr>,max=<addr>] \n");
- printf(" dump registers from <min> to <max> [VIDIOC_DBG_G_REGISTER]\n");
- printf(" -r, --set-register=type=<host/i2cdrv/i2caddr>,chip=<chip>,reg=<addr>,val=<val>\n");
- printf(" set the register [VIDIOC_DBG_S_REGISTER]\n");
- printf(" -C, --scan-chip-idents\n");
- printf(" Scan the available host and i2c chips [VIDIOC_G_CHIP_IDENT]\n");
- printf(" -c, --get-chip-ident=type=<host/i2cdrv/i2caddr>,chip=<chip>\n");
- printf(" Get the chip identifier [VIDIOC_G_CHIP_IDENT]\n");
- printf(" -w, --wide=<reg length>\n");
- printf(" Sets step between two registers\n");
- printf(" --log-status log the board status in the kernel log [VIDIOC_LOG_STATUS]\n");
- printf(" --list-driverids list the known I2C driver IDs for use with the i2cdrv type\n");
- printf("\n");
- printf(" if type == host, then <chip> is the host's chip ID (default 0)\n");
- printf(" if type == i2cdrv (default), then <chip> is the I2C driver name or ID\n");
- printf(" if type == i2caddr, then <chip> is the 7-bit I2C address\n");
+ printf("Usage: v4l2-dbg [options] [values]\n"
+ " -D, --info Show driver info [VIDIOC_QUERYCAP]\n"
+ " -d, --device=<dev> Use device <dev> instead of /dev/video0\n"
+ " If <dev> is a single digit, then /dev/video<dev> is used\n"
+ " -h, --help Display this help message\n"
+ " --verbose Turn on verbose ioctl error reporting\n"
+ " -c, --chip=<chip> The chip identifier to use with other commands\n"
+ " It can be one of:\n"
+ " I2C driver ID (see --list-driverids)\n"
+ " I2C 7-bit address\n"
+ " host<num>: host chip number <num>\n"
+ " host (default): same as host0\n"
+ " -l, --list-registers[=min=<addr>[,max=<addr>]]\n"
+ " Dump registers from <min> to <max> [VIDIOC_DBG_G_REGISTER]\n"
+ " -g, --get-register=<addr>\n"
+ " Get the specified register [VIDIOC_DBG_G_REGISTER]\n"
+ " -s, --set-register=<addr>\n"
+ " Set the register with the commandline arguments\n"
+ " The register will autoincrement [VIDIOC_DBG_S_REGISTER]\n"
+ " -S, --scan-chip-idents\n"
+ " Scan the available host and i2c chips [VIDIOC_G_CHIP_IDENT]\n"
+ " -i, --get-chip-ident\n"
+ " Get the chip identifier [VIDIOC_G_CHIP_IDENT]\n"
+ " -w, --wide=<reg length>\n"
+ " Sets step between two registers\n"
+ " --list-symbols List the symbolic register names you can use, if any\n"
+ " --log-status Log the board status in the kernel log [VIDIOC_LOG_STATUS]\n"
+ " --list-driverids List the known I2C driver IDs for use with the i2cdrv type\n");
exit(0);
}
-static unsigned parse_type(const std::string &s)
-{
- if (s == "host") return V4L2_CHIP_MATCH_HOST;
- if (s == "i2caddr") return V4L2_CHIP_MATCH_I2C_ADDR;
- return V4L2_CHIP_MATCH_I2C_DRIVER;
-}
-
-static unsigned parse_chip(int type, const std::string &s)
+static unsigned parse_chip(const std::string &s)
{
- if (type == V4L2_CHIP_MATCH_HOST || type == V4L2_CHIP_MATCH_I2C_ADDR || isdigit(s[0]))
- return strtoul(s.c_str(), 0, 0);
for (int i = 0; driverids[i].name; i++)
if (!strcasecmp(s.c_str(), driverids[i].name))
return driverids[i].id;
@@ -230,6 +274,56 @@ static void print_chip(struct v4l2_chip_ident *chip)
printf("%-10d revision 0x%08x\n", chip->ident, chip->revision);
}
+static unsigned long long parse_reg(const struct board_list *curr_bd, const std::string &reg)
+{
+ if (curr_bd) {
+ for (int i = 0; i < curr_bd->regs_size; i++) {
+ if (!strcasecmp(reg.c_str(), curr_bd->regs[i].name) ||
+ !strcasecmp(reg.c_str(), curr_bd->regs[i].name + curr_bd->prefix)) {
+ return curr_bd->regs[i].reg;
+ }
+ }
+ for (int i = 0; i < curr_bd->alt_regs_size; i++) {
+ if (!strcasecmp(reg.c_str(), curr_bd->alt_regs[i].name) ||
+ !strcasecmp(reg.c_str(), curr_bd->alt_regs[i].name + curr_bd->prefix)) {
+ return curr_bd->alt_regs[i].reg;
+ }
+ }
+ }
+ return strtoull(reg.c_str(), NULL, 0);
+}
+
+static const char *binary(unsigned long long val)
+{
+ static char bin[80];
+ char *p = bin;
+ int i, j;
+ int bits = 64;
+
+ if ((val & 0xffffffff00000000LL) == 0) {
+ if ((val & 0xffff0000) == 0) {
+ if ((val & 0xff00) == 0)
+ bits = 8;
+ else
+ bits= 16;
+ }
+ else
+ bits = 32;
+ }
+
+ for (i = bits - 1; i >= 0; i -= 8) {
+ for (j = i; j >= i - 7; j--) {
+ if (val & (1LL << j))
+ *p++ = '1';
+ else
+ *p++ = '0';
+ }
+ *p++ = ' ';
+ }
+ p[-1] = 0;
+ return bin;
+}
+
static int doioctl(int fd, int request, void *parm, const char *name)
{
int retVal;
@@ -277,9 +371,15 @@ int main(int argc, char **argv)
struct v4l2_register set_reg;
struct v4l2_register get_reg;
struct v4l2_chip_ident chip_id;
+ const struct board_list *curr_bd = NULL;
char short_options[26 * 2 * 2 + 1];
int idx = 0;
+ std::string reg_min_arg, reg_max_arg;
+ std::string reg_set_arg;
unsigned long long reg_min = 0, reg_max = 0;
+ std::vector<std::string> get_regs;
+ int match_type = V4L2_CHIP_MATCH_HOST;
+ int match_chip = 0;
memset(&set_reg, 0, sizeof(set_reg));
memset(&get_reg, 0, sizeof(get_reg));
@@ -310,6 +410,7 @@ int main(int argc, char **argv)
case OptHelp:
usage();
return 0;
+
case OptSetDevice:
device = optarg;
if (device[0] >= '0' && device[0] <= '9' && device[1] == 0) {
@@ -320,43 +421,44 @@ int main(int argc, char **argv)
device = newdev;
}
break;
- case OptSetRegister:
- subs = optarg;
- set_reg.match_type = V4L2_CHIP_MATCH_I2C_DRIVER;
- while (*subs != '\0') {
- static const char * const subopts[] = {
- "type",
- "chip",
- "reg",
- "val",
- NULL
- };
- switch (parse_subopt(&subs, subopts, &value)) {
- case 0:
- set_reg.match_type = parse_type(value);
- break;
- case 1:
- set_reg.match_chip = parse_chip(set_reg.match_type, value);
- break;
- case 2:
- set_reg.reg = strtoull(value, 0L, 0);
- break;
- case 3:
- set_reg.val = strtoull(value, 0L, 0);
- break;
- }
+ case OptChip:
+ if (isdigit(optarg[0])) {
+ match_type = V4L2_CHIP_MATCH_I2C_ADDR;
+ match_chip = strtoul(optarg, NULL, 0);
+ break;
+ }
+ if (!memcmp(optarg, "host", 4)) {
+ match_type = V4L2_CHIP_MATCH_HOST;
+ match_chip = strtoul(optarg + 4, NULL, 0);
+ break;
}
+ match_type = V4L2_CHIP_MATCH_I2C_DRIVER;
+ match_chip = parse_chip(optarg);
+ if (!match_chip) {
+ fprintf(stderr, "unknown driver ID %s\n", optarg);
+ exit(-1);
+ }
+ break;
+
+ case OptSetRegister:
+ reg_set_arg = optarg;
+ break;
+
+ case OptGetRegister:
+ get_regs.push_back(optarg);
+ break;
+
case OptSetStride:
forcedstride = strtoull(optarg, 0L, 0);
break;
+
case OptListRegisters:
subs = optarg;
- get_reg.match_type = V4L2_CHIP_MATCH_I2C_DRIVER;
+ if (subs == NULL)
+ break;
while (*subs != '\0') {
static const char * const subopts[] = {
- "type",
- "chip",
"min",
"max",
NULL
@@ -364,47 +466,27 @@ int main(int argc, char **argv)
switch (parse_subopt(&subs, subopts, &value)) {
case 0:
- get_reg.match_type = parse_type(value);
+ reg_min_arg = value;
+ //if (reg_max == 0)
+ // reg_max = reg_min + 0xff;
break;
case 1:
- get_reg.match_chip = parse_chip(get_reg.match_type, value);
- break;
- case 2:
- reg_min = strtoull(value, 0L, 0);
- if (reg_max == 0)
- reg_max = reg_min + 0xff;
- break;
- case 3:
- reg_max = strtoull(value, 0L, 0);
+ reg_max_arg = value;
break;
}
}
break;
- case OptGetChipIdent:
- subs = optarg;
- set_reg.match_type = V4L2_CHIP_MATCH_I2C_DRIVER;
- while (*subs != '\0') {
- static const char *const subopts[] = {
- "type",
- "chip",
- NULL
- };
- switch (parse_subopt(&subs, subopts, &value)) {
- case 0:
- chip_id.match_type = parse_type(value);
- break;
- case 1:
- chip_id.match_chip = parse_chip(chip_id.match_type, value);
- break;
- }
- }
+ case OptGetChipIdent:
+ case OptListSymbols:
break;
+
case ':':
fprintf(stderr, "Option `%s' requires a value\n",
argv[optind]);
usage();
return 1;
+
case '?':
fprintf(stderr, "Unknown argument `%s'\n",
argv[optind]);
@@ -412,14 +494,6 @@ int main(int argc, char **argv)
return 1;
}
}
- if (optind < argc) {
- printf("unknown arguments: ");
- while (optind < argc)
- printf("%s ", argv[optind++]);
- printf("\n");
- usage();
- return 1;
- }
if ((fd = open(device, O_RDWR)) < 0) {
fprintf(stderr, "Failed to open %s: %s\n", device,
@@ -442,15 +516,33 @@ int main(int argc, char **argv)
printf("%s", cap2s(vcap.capabilities).c_str());
}
+ for (int board = ARRAY_SIZE(boards) - 1; board >= 0; board--) {
+ if (!strcasecmp((char *)vcap.driver, boards[board].name)) {
+ curr_bd = &boards[board];
+ break;
+ }
+ }
+
/* Set options */
if (options[OptSetRegister]) {
- if (doioctl(fd, VIDIOC_DBG_S_REGISTER, &set_reg,
- "VIDIOC_DBG_S_REGISTER") == 0)
- printf("register 0x%llx set to 0x%llx\n", set_reg.reg, set_reg.val);
+ set_reg.match_type = match_type;
+ set_reg.match_chip = match_chip;
+ if (optind >= argc)
+ usage();
+ set_reg.reg = parse_reg(curr_bd, reg_set_arg);
+ while (optind < argc) {
+ set_reg.val = strtoull(argv[optind++], NULL, 0);
+ if (doioctl(fd, VIDIOC_DBG_S_REGISTER, &set_reg,
+ "VIDIOC_DBG_S_REGISTER") == 0)
+ printf("register 0x%llx set to 0x%llx\n", set_reg.reg, set_reg.val);
+ set_reg.reg++;
+ }
}
if (options[OptGetChipIdent]) {
+ chip_id.match_type = match_type;
+ chip_id.match_chip = match_chip;
if (doioctl(fd, VIDIOC_G_CHIP_IDENT, &chip_id, "VIDIOC_G_CHIP_IDENT") == 0)
print_chip(&chip_id);
}
@@ -462,7 +554,7 @@ int main(int argc, char **argv)
chip_id.match_chip = 0;
while (doioctl(fd, VIDIOC_G_CHIP_IDENT, &chip_id, "VIDIOC_G_CHIP_IDENT") == 0 && chip_id.ident) {
- printf("host 0x%x: ", chip_id.match_chip);
+ printf("host%d: ", chip_id.match_chip);
print_chip(&chip_id);
chip_id.match_chip++;
}
@@ -477,8 +569,30 @@ int main(int argc, char **argv)
}
}
+ if (options[OptGetRegister]) {
+ int stride = 1;
+
+ get_reg.match_type = match_type;
+ get_reg.match_chip = match_chip;
+ printf("ioctl: VIDIOC_DBG_G_REGISTER\n");
+
+ for (std::vector<std::string>::iterator iter = get_regs.begin();
+ iter != get_regs.end(); ++iter) {
+ get_reg.reg = parse_reg(curr_bd, *iter);
+ if (ioctl(fd, VIDIOC_DBG_G_REGISTER, &get_reg) < 0)
+ fprintf(stderr, "ioctl: VIDIOC_DBG_G_REGISTER "
+ "failed for 0x%llx\n", get_reg.reg);
+ else
+ printf("%llx = %llxh = %lldd = %sb\n", get_reg.reg,
+ get_reg.val, get_reg.val, binary(get_reg.val));
+ }
+ }
+
if (options[OptListRegisters]) {
int stride = 1;
+
+ get_reg.match_type = match_type;
+ get_reg.match_chip = match_chip;
if (forcedstride) {
stride = forcedstride;
} else {
@@ -487,7 +601,12 @@ int main(int argc, char **argv)
}
printf("ioctl: VIDIOC_DBG_G_REGISTER\n");
- if (reg_max != 0) {
+ if (!reg_min_arg.empty()) {
+ reg_min = parse_reg(curr_bd, reg_min_arg);
+ if (reg_max_arg.empty())
+ reg_max = reg_min + 0xff;
+ else
+ reg_max = parse_reg(curr_bd, reg_max_arg);
/* Explicit memory range: just do it */
print_regs(fd, &get_reg, reg_min, reg_max, stride);
goto list_done;
@@ -580,6 +699,19 @@ list_done:
printf("%s\n", driverids[i].name);
}
+ if (options[OptListSymbols]) {
+ if (curr_bd == NULL) {
+ printf("No symbols found for driver %s\n", vcap.driver);
+ }
+ else {
+ printf("Symbols for driver %s:\n", vcap.driver);
+ for (int i = 0; i < curr_bd->regs_size; i++)
+ printf("0x%08x: %s\n", curr_bd->regs[i], curr_bd->regs[i].name);
+ for (int i = 0; i < curr_bd->alt_regs_size; i++)
+ printf("0x%08x: %s\n", curr_bd->alt_regs[i], curr_bd->alt_regs[i].name);
+ }
+ }
+
close(fd);
exit(0);
}
diff --git a/v4l2-apps/util/v4l-board-dbg.h b/v4l2-apps/util/v4l2-dbg.h
index d7e7a9ef3..06ceb0ea2 100644
--- a/v4l2-apps/util/v4l-board-dbg.h
+++ b/v4l2-apps/util/v4l2-dbg.h
@@ -14,11 +14,13 @@
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
-#ifndef _V4L_BOARD_DBG
-#define _V4L_BOARD_DBG
+#ifndef _V4L2_DBG_H_
+#define _V4L2_DBG_H_
+
struct board_regs {
unsigned int reg;
- char *name;
+ const char *name;
int size;
};
+
#endif
diff --git a/v4l2-apps/util/xc3028-firmware/Makefile b/v4l2-apps/util/xc3028-firmware/Makefile
index 102f712fd..6894e984e 100644
--- a/v4l2-apps/util/xc3028-firmware/Makefile
+++ b/v4l2-apps/util/xc3028-firmware/Makefile
@@ -1,6 +1,6 @@
# Makefile for linuxtv.org v4l2-apps/util/xc3028-firmware
-CPPFLAGS += -I../../../linux/include
+CPPFLAGS += -I../../include
binaries = firmware-tool