summaryrefslogtreecommitdiff
path: root/v4l2-apps
diff options
context:
space:
mode:
Diffstat (limited to 'v4l2-apps')
-rw-r--r--v4l2-apps/test/Makefile7
-rw-r--r--v4l2-apps/test/v4l2grab.c162
-rw-r--r--v4l2-apps/util/Makefile26
-rw-r--r--v4l2-apps/util/cx18-ctl.c51
-rwxr-xr-xv4l2-apps/util/gen_keytables.pl7
-rw-r--r--v4l2-apps/util/ivtv-ctl.c47
-rw-r--r--v4l2-apps/util/keytable.c43
-rw-r--r--v4l2-apps/util/rewrite_eeprom.pl336
-rw-r--r--v4l2-apps/util/v4l2-ctl.cpp639
-rw-r--r--v4l2-apps/util/v4l2-dbg-micron.h46
-rw-r--r--v4l2-apps/util/v4l2-dbg.cpp29
-rw-r--r--v4l2-apps/util/v4l2-sysfs-path.c130
-rw-r--r--v4l2-apps/util/xc3028-firmware/firmware-tool.c4
13 files changed, 1327 insertions, 200 deletions
diff --git a/v4l2-apps/test/Makefile b/v4l2-apps/test/Makefile
index d118b9210..13eebf377 100644
--- a/v4l2-apps/test/Makefile
+++ b/v4l2-apps/test/Makefile
@@ -7,6 +7,7 @@ binaries = ioctl-test \
sliced-vbi-detect \
vbi-test \
v4lgrab \
+ v4l2grab \
driver-test \
pixfmt-test \
stress-buffer \
@@ -24,9 +25,15 @@ install:
../libv4l2util/libv4l2util.a: ../libv4l2util/v4l2_driver.c ../libv4l2util/frequencies.c
make -C ../libv4l2util libv4l2util.a
+../libv4l/libv4l2/libv4l2.so:
+ make -C ../libv4l/
+
driver-test: driver-test.o ../libv4l2util/libv4l2util.a
pixfmt-test: pixfmt-test.o
$(CC) $(LDFLAGS) $^ $(LOADLIBES) $(LDLIBS) -o $@ -lX11
+v4l2grab: v4l2grab.o
+ $(CC) $(LDFLAGS) $^ -o $@ -L ../libv4l/libv4l2 -L ../libv4l/libv4lconvert -lv4l2 -lv4lconvert
+
include ../Make.rules
diff --git a/v4l2-apps/test/v4l2grab.c b/v4l2-apps/test/v4l2grab.c
new file mode 100644
index 000000000..de921874b
--- /dev/null
+++ b/v4l2-apps/test/v4l2grab.c
@@ -0,0 +1,162 @@
+/* V4L2 video picture grabber
+ Copyright (C) 2009 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.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <sys/ioctl.h>
+#include <sys/types.h>
+#include <sys/time.h>
+#include <sys/mman.h>
+#include <linux/videodev2.h>
+#include "../libv4l/include/libv4l2.h"
+
+#define CLEAR(x) memset(&(x), 0, sizeof(x))
+
+struct buffer {
+ void *start;
+ size_t length;
+};
+
+static void xioctl(int fh, int request, void *arg)
+{
+ int r;
+
+ do {
+ r = v4l2_ioctl(fh, request, arg);
+ } while (r == -1 && ((errno == EINTR) || (errno == EAGAIN)));
+
+ if (r == -1) {
+ fprintf(stderr, "error %d, %s\n", errno, strerror(errno));
+ exit(EXIT_FAILURE);
+ }
+}
+
+int main(int argc, char **argv)
+{
+ struct v4l2_format fmt;
+ struct v4l2_buffer buf;
+ struct v4l2_requestbuffers req;
+ enum v4l2_buf_type type;
+ fd_set fds;
+ struct timeval tv;
+ int r, fd = -1;
+ unsigned int i, n_buffers;
+ char *dev_name = "/dev/video0";
+ char out_name[256];
+ FILE *fout;
+ struct buffer *buffers;
+
+ fd = v4l2_open(dev_name, O_RDWR | O_NONBLOCK, 0);
+ if (fd < 0) {
+ perror("Cannot open device");
+ exit(EXIT_FAILURE);
+ }
+
+ 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_RGB24;
+ fmt.fmt.pix.field = V4L2_FIELD_INTERLACED;
+ xioctl(fd, VIDIOC_S_FMT, &fmt);
+ if (fmt.fmt.pix.pixelformat != V4L2_PIX_FMT_RGB24) {
+ printf("Libv4l didn't accept RGB24 format. Can't proceed.\n");
+ exit(EXIT_FAILURE);
+ }
+ if ((fmt.fmt.pix.width != 640) || (fmt.fmt.pix.height != 480))
+ printf("Warning: driver is sending image at %dx%d\n",
+ fmt.fmt.pix.width, fmt.fmt.pix.height);
+
+ CLEAR(req);
+ req.count = 2;
+ req.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+ req.memory = V4L2_MEMORY_MMAP;
+ xioctl(fd, VIDIOC_REQBUFS, &req);
+
+ buffers = calloc(req.count, sizeof(*buffers));
+ for (n_buffers = 0; n_buffers < req.count; ++n_buffers) {
+ CLEAR(buf);
+
+ buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+ buf.memory = V4L2_MEMORY_MMAP;
+ buf.index = n_buffers;
+
+ xioctl(fd, VIDIOC_QUERYBUF, &buf);
+
+ buffers[n_buffers].length = buf.length;
+ buffers[n_buffers].start = v4l2_mmap(NULL, buf.length,
+ PROT_READ | PROT_WRITE, MAP_SHARED,
+ fd, buf.m.offset);
+
+ if (MAP_FAILED == buffers[n_buffers].start) {
+ perror("mmap");
+ exit(EXIT_FAILURE);
+ }
+ }
+
+ for (i = 0; i < n_buffers; ++i) {
+ CLEAR(buf);
+ buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+ buf.memory = V4L2_MEMORY_MMAP;
+ buf.index = i;
+ xioctl(fd, VIDIOC_QBUF, &buf);
+ }
+ type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+
+ xioctl(fd, VIDIOC_STREAMON, &type);
+ for (i = 0; i < 20; i++) {
+ do {
+ FD_ZERO(&fds);
+ FD_SET(fd, &fds);
+
+ /* Timeout. */
+ tv.tv_sec = 2;
+ tv.tv_usec = 0;
+
+ r = select(fd + 1, &fds, NULL, NULL, &tv);
+ } while ((r == -1 && (errno = EINTR)));
+ if (r == -1) {
+ perror("select");
+ return errno;
+ }
+
+ CLEAR(buf);
+ buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+ buf.memory = V4L2_MEMORY_MMAP;
+ xioctl(fd, VIDIOC_DQBUF, &buf);
+
+ sprintf(out_name, "out%03d.ppm", i);
+ fout = fopen(out_name, "w");
+ if (!fout) {
+ perror("Cannot open image");
+ exit(EXIT_FAILURE);
+ }
+ fprintf(fout, "P6\n%d %d 255\n",
+ fmt.fmt.pix.width, fmt.fmt.pix.height);
+ fwrite(buffers[buf.index].start, buf.bytesused, 1, fout);
+ fclose(fout);
+
+ xioctl(fd, VIDIOC_QBUF, &buf);
+ }
+
+ type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+ xioctl(fd, VIDIOC_STREAMOFF, &type);
+ for (i = 0; i < n_buffers; ++i)
+ v4l2_munmap(buffers[i].start, buffers[i].length);
+ v4l2_close(fd);
+
+ return 0;
+}
diff --git a/v4l2-apps/util/Makefile b/v4l2-apps/util/Makefile
index 6f9d1071a..29f3f4852 100644
--- a/v4l2-apps/util/Makefile
+++ b/v4l2-apps/util/Makefile
@@ -1,5 +1,26 @@
# Makefile for linuxtv.org v4l2-apps/util
+IR_FILES = "linux/drivers/media/common/ir-keymaps.c \
+linux/drivers/media/dvb/dvb-usb/a800.c \
+linux/drivers/media/dvb/dvb-usb/af9005-remote.c \
+linux/drivers/media/dvb/dvb-usb/af9015.c \
+linux/drivers/media/dvb/dvb-usb/af9015.h \
+linux/drivers/media/dvb/dvb-usb/anysee.c \
+linux/drivers/media/dvb/dvb-usb/cinergyT2-core.c \
+linux/drivers/media/dvb/dvb-usb/cxusb.c \
+linux/drivers/media/dvb/dvb-usb/dib0700_devices.c \
+linux/drivers/media/dvb/dvb-usb/dibusb-common.c \
+linux/drivers/media/dvb/dvb-usb/digitv.c \
+linux/drivers/media/dvb/dvb-usb/dtt200u.c \
+linux/drivers/media/dvb/dvb-usb/dvb-usb-remote.c \
+linux/drivers/media/dvb/dvb-usb/dvb-usb.h \
+linux/drivers/media/dvb/dvb-usb/dw2102.c \
+linux/drivers/media/dvb/dvb-usb/m920x.c \
+linux/drivers/media/dvb/dvb-usb/nova-t-usb2.c \
+linux/drivers/media/dvb/dvb-usb/opera1.c \
+linux/drivers/media/dvb/dvb-usb/vp702x.c \
+linux/drivers/media/dvb/dvb-usb/vp7045.c "
+
ifeq ($(KERNEL_DIR),)
KERNEL_DIR = /usr
endif
@@ -62,8 +83,9 @@ parse.h: $(KERNEL_DIR)/include/linux/input.h
@printf "\t{ NULL, 0}\n};\n" >>parse.h
keytables:
- -mkdir -p keycodes
- ./gen_keytables.pl ../../linux/drivers/media/common/ir-keymaps.c
+ @-mkdir -p keycodes
+ @echo storing existing keycodes at keycodes/
+ @for i in `echo $(IR_FILES)`; do ./gen_keytables.pl ../../$$i; done
keytable: keytable.c parse.h keytables
diff --git a/v4l2-apps/util/cx18-ctl.c b/v4l2-apps/util/cx18-ctl.c
index 3d8ff385d..138f3c26a 100644
--- a/v4l2-apps/util/cx18-ctl.c
+++ b/v4l2-apps/util/cx18-ctl.c
@@ -52,12 +52,6 @@
#define CX18_DBGFLG_HIGHVOL (1 << 8)
/* Internals copied from media/v4l2-common.h */
-struct v4l2_routing {
- __u32 input;
- __u32 output;
-};
-#define VIDIOC_INT_S_AUDIO_ROUTING _IOW('d', 109, struct v4l2_routing)
-
#define VIDIOC_INT_RESET _IOW('d', 102, __u32)
#define __stringify_1(x) #x
@@ -80,7 +74,6 @@ enum Option {
OptHelp = 'h',
OptSetGPIO = 'i',
OptListGPIO = 'I',
- OptSetAudioRoute = 'v',
OptReset = 128,
OptVersion,
OptLast = 256
@@ -97,7 +90,6 @@ static struct option long_options[] = {
{"help", no_argument, 0, OptHelp},
{"set-gpio", required_argument, 0, OptSetGPIO},
{"list-gpio", no_argument, 0, OptListGPIO},
- {"audio-route", required_argument, 0, OptSetAudioRoute},
{"reset", required_argument, 0, OptReset},
{"version", no_argument, 0, OptVersion},
{0, 0, 0, 0}
@@ -129,8 +121,6 @@ static void usage(void)
printf(" show GPIO input/direction/output bits\n");
printf(" -i, --set-gpio [dir=<dir>,]val=<val>\n");
printf(" set GPIO direction bits to <dir> and set output to <val>\n");
- printf(" -v, --audio-route=input=<in>,output=<out>\n");
- printf(" set the audio input/output routing [VIDIOC_INT_S_AUDIO_ROUTING]\n");
exit(0);
}
@@ -250,14 +240,8 @@ int main(int argc, char **argv)
char *subopts[] = {
#define SUB_VAL 0
"val",
-#define SUB_YUV_MODE 1
- "mode",
-#define SUB_DIR 2
+#define SUB_DIR 1
"dir",
-#define SUB_INPUT 3
- "input",
-#define SUB_OUTPUT 4
- "output",
NULL
};
@@ -270,7 +254,6 @@ int main(int argc, char **argv)
const char *device = "/dev/video0"; /* -d device */
int ch;
int yuv_mode = 0;
- struct v4l2_routing route; /* audio_route */
unsigned int gpio_out = 0x0; /* GPIO output data */
unsigned int gpio_dir = 0x0; /* GPIO direction bits */
int gpio_set_dir = 0;
@@ -321,34 +304,6 @@ int main(int argc, char **argv)
device = newdev;
}
break;
- case OptSetAudioRoute:
- subs = optarg;
- while (*subs != '\0') {
- switch (getsubopt(&subs, subopts, &value)) {
- case SUB_INPUT:
- if (value == NULL) {
- printf
- ("No value given to suboption <input>\n");
- usage();
- }
- route.input = strtol(value, 0L, 0);
- break;
- case SUB_OUTPUT:
- if (value == NULL) {
- printf
- ("No value given to suboption <output>\n");
- usage();
- }
- route.output = strtol(value, 0L, 0);
- break;
- default:
- printf
- ("Invalid suboptions specified\n");
- usage();
- break;
- }
- }
- break;
case OptReset:
reset = strtol(optarg, 0L, 0);
break;
@@ -414,10 +369,6 @@ int main(int argc, char **argv)
}
/* Setting Opts */
-
- if (options[OptSetAudioRoute])
- doioctl(fd, VIDIOC_INT_S_AUDIO_ROUTING, &route, "VIDIOC_INT_S_AUDIO_ROUTING");
-
if (options[OptSetGPIO]) {
struct v4l2_dbg_register reg;
diff --git a/v4l2-apps/util/gen_keytables.pl b/v4l2-apps/util/gen_keytables.pl
index 889516de4..fad4ccfeb 100755
--- a/v4l2-apps/util/gen_keytables.pl
+++ b/v4l2-apps/util/gen_keytables.pl
@@ -5,9 +5,8 @@ my $keyname="";
my $debug=0;
while (<>) {
-#IR_KEYTAB_TYPE ir_codes_proteus_2309[IR_KEYTAB_SIZE] = {
- if (m/IR_KEYTAB_TYPE\s+(\w[\w\d_]+)/) {
- $keyname = $1;
+ if (m/struct\s+(dvb_usb_rc_key|ir_scancode)\s+(\w[\w\d_]+)/) {
+ $keyname = $2;
$keyname =~ s/^ir_codes_//;
print "Generating keycodes/$keyname\n" if $debug;
@@ -15,7 +14,7 @@ while (<>) {
next;
}
if ($keyname ne "") {
- if (m/(0x[\d\w]+).*(KEY_[^\s\,]+)/) {
+ if (m/(0x[\dA-Fa-f]+).*(KEY_[^\s\,\}]+)/) {
printf OUT "%s %s\n",$1, $2;
next;
}
diff --git a/v4l2-apps/util/ivtv-ctl.c b/v4l2-apps/util/ivtv-ctl.c
index a05dcbba2..6af8fc663 100644
--- a/v4l2-apps/util/ivtv-ctl.c
+++ b/v4l2-apps/util/ivtv-ctl.c
@@ -56,12 +56,6 @@
#define IVTV_DBGFLG_HIGHVOL (1 << 10)
/* Internals copied from media/v4l2-common.h */
-struct v4l2_routing {
- __u32 input;
- __u32 output;
-};
-#define VIDIOC_INT_S_AUDIO_ROUTING _IOW('d', 109, struct v4l2_routing)
-
#define VIDIOC_INT_RESET _IOW('d', 102, __u32)
#include <linux/ivtv.h>
@@ -81,7 +75,6 @@ enum Option {
OptListGPIO = 'I',
OptPassThrough = 'K',
OptFrameSync = 'k',
- OptSetAudioRoute = 'v',
OptReset = 128,
OptSetYuvMode,
OptGetYuvMode,
@@ -106,7 +99,6 @@ static struct option long_options[] = {
{"list-gpio", no_argument, 0, OptListGPIO},
{"passthrough", required_argument, 0, OptPassThrough},
{"sync", no_argument, 0, OptFrameSync},
- {"audio-route", required_argument, 0, OptSetAudioRoute},
{"reset", required_argument, 0, OptReset},
{"get-yuv-mode", no_argument, 0, OptGetYuvMode},
{"set-yuv-mode", required_argument, 0, OptSetYuvMode},
@@ -167,8 +159,6 @@ static void usage(void)
printf(" -i, --set-gpio [dir=<dir>,]val=<val>\n");
printf(" set GPIO direction bits to <dir> and set output to <val>\n");
printf(" -k, --sync test vsync's capabilities [VIDEO_GET_EVENT]\n");
- printf(" -v, --audio-route=input=<in>,output=<out>\n");
- printf(" set the audio input/output routing [VIDIOC_INT_S_AUDIO_ROUTING]\n");
exit(0);
}
@@ -330,10 +320,6 @@ int main(int argc, char **argv)
"mode",
#define SUB_DIR 2
"dir",
-#define SUB_INPUT 3
- "input",
-#define SUB_OUTPUT 4
- "output",
NULL
};
@@ -346,7 +332,6 @@ int main(int argc, char **argv)
const char *device = "/dev/video0"; /* -d device */
int ch;
int yuv_mode = 0;
- struct v4l2_routing route; /* audio_route */
unsigned short gpio_out = 0x0; /* GPIO output data */
unsigned short gpio_dir = 0x0; /* GPIO direction bits */
int gpio_set_dir = 0;
@@ -424,34 +409,6 @@ int main(int argc, char **argv)
device = newdev;
}
break;
- case OptSetAudioRoute:
- subs = optarg;
- while (*subs != '\0') {
- switch (getsubopt(&subs, subopts, &value)) {
- case SUB_INPUT:
- if (value == NULL) {
- printf
- ("No value given to suboption <input>\n");
- usage();
- }
- route.input = strtol(value, 0L, 0);
- break;
- case SUB_OUTPUT:
- if (value == NULL) {
- printf
- ("No value given to suboption <output>\n");
- usage();
- }
- route.output = strtol(value, 0L, 0);
- break;
- default:
- printf
- ("Invalid suboptions specified\n");
- usage();
- break;
- }
- }
- break;
case OptReset:
reset = strtol(optarg, 0L, 0);
break;
@@ -529,10 +486,6 @@ int main(int argc, char **argv)
/* Setting Opts */
- if (options[OptSetAudioRoute])
- doioctl(fd, VIDIOC_INT_S_AUDIO_ROUTING, &route,
- "VIDIOC_INT_S_AUDIO_ROUTING");
-
if (options[OptFrameSync]) {
printf("ioctl: VIDEO_GET_EVENT\n");
diff --git a/v4l2-apps/util/keytable.c b/v4l2-apps/util/keytable.c
index 3b922f12b..4283782d0 100644
--- a/v4l2-apps/util/keytable.c
+++ b/v4l2-apps/util/keytable.c
@@ -1,6 +1,6 @@
/* keytable.c - This program allows checking/replacing keys at IR
- Copyright (C) 2006 Mauro Carvalho Chehab <mchehab@infradead.org>
+ Copyright (C) 2006-2009 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
@@ -29,7 +29,7 @@ void prtcode (int *codes)
for (p=keynames;p->name!=NULL;p++) {
if (p->value == (unsigned)codes[1]) {
- printf("scancode %d = %s (0x%02x)\n", codes[0], p->name, codes[1]);
+ printf("scancode 0x%04x = %s (0x%02x)\n", codes[0], p->name, codes[1]);
return;
}
}
@@ -55,7 +55,7 @@ int parse_code(char *string)
int main (int argc, char *argv[])
{
int fd;
- unsigned int i;
+ unsigned int i, j;
int codes[2];
if (argc<2 || argc>4) {
@@ -104,10 +104,12 @@ int main (int argc, char *argv[])
}
/* Clears old table */
- for (i=0;i<256;i++) {
- codes[0] = i;
- codes[1] = 0;
- ioctl(fd, EVIOCSKEYCODE, codes);
+ for (j = 0; j < 256; j++) {
+ for (i = 0; i < 256; i++) {
+ codes[0] = (j << 8) | i;
+ codes[1] = KEY_RESERVED;
+ ioctl(fd, EVIOCSKEYCODE, codes);
+ }
}
while (fgets(s,sizeof(s),fin)) {
@@ -116,14 +118,21 @@ int main (int argc, char *argv[])
perror ("parsing input file scancode");
return -1;
}
+ if (!strcasecmp(scancode, "scancode")) {
+ scancode = strtok(NULL,"\n\t =:");
+ if (!scancode) {
+ perror ("parsing input file scancode");
+ return -1;
+ }
+ }
- keycode=strtok(NULL,"\n\t ");
+ keycode=strtok(NULL,"\n\t =:(");
if (!keycode) {
perror ("parsing input file keycode");
return -1;
}
- // printf ("parsing %s=%s:",scancode,keycode);
+ // printf ("parsing %s=%s:", scancode, keycode);
value=parse_code(keycode);
// printf ("\tvalue=%d\n",value);
@@ -136,8 +145,11 @@ int main (int argc, char *argv[])
codes [0] = (unsigned) strtol(scancode, NULL, 0);
codes [1] = (unsigned) value;
- if(ioctl(fd, EVIOCSKEYCODE, codes))
+ // printf("\t%04x=%04x\n",codes[0], codes[1]);
+ if(ioctl(fd, EVIOCSKEYCODE, codes)) {
+ fprintf(stderr, "Setting scancode 0x%04x with 0x%04x via ",codes[0], codes[1]);
perror ("EVIOCSKEYCODE");
+ }
if(ioctl(fd, EVIOCGKEYCODE, codes)==0)
prtcode(codes);
@@ -146,12 +158,13 @@ int main (int argc, char *argv[])
}
/* Get scancode table */
- for (i=0;i<256;i++) {
- codes[0] = i;
- if(ioctl(fd, EVIOCGKEYCODE, codes)==0)
- prtcode(codes);
+ for (j = 0; j < 256; j++) {
+ for (i = 0; i < 256; i++) {
+ codes[0] = (j << 8) | i;
+ if (!ioctl(fd, EVIOCGKEYCODE, codes) && codes[1] != KEY_RESERVED)
+ prtcode(codes);
+ }
}
-
return 0;
}
diff --git a/v4l2-apps/util/rewrite_eeprom.pl b/v4l2-apps/util/rewrite_eeprom.pl
new file mode 100644
index 000000000..495c4717c
--- /dev/null
+++ b/v4l2-apps/util/rewrite_eeprom.pl
@@ -0,0 +1,336 @@
+#!/usr/bin/perl -w
+#
+################################################################################
+# Copyright (C) 2009
+#
+# Mauro Carvalho Chehab <mchehab@redhat.com>
+# Douglas Schilling Landgraf <dougsland@redhat.com>
+#
+# 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.
+#
+# Although not very common, on a few devices, the eeprom may be erased, due to a
+# bug on a *few eeprom* chipsets that sometimes considers i2c messages to other
+# devices as being for it.
+#
+# The solution for it is to reprogram the eeprom with their original contents.
+#
+# Modules this script is known to work with: em28xx and saa7134
+# * Not tested against newer em28xx chipsets like the em2874 and em2884
+#
+########################################################
+# NOTE #
+################################################################################
+# Since the script will try to detect the proper i2c bus address, it will only #
+# work well if you have just one V4L device connected. #
+################################################################################
+#
+########################################
+# What do you need to run this script? #
+########################################
+#
+# * eeprom - A dump file with the older eeprom.
+#
+# As example this is a dump from EMPIRE TV DUAL (310U):
+# ^^^^^^^^^^^^^^
+# shell> dmesg
+#
+# [11196.181543] em28xx #0: i2c eeprom 00: 1a eb 67 95 1a eb 10 e3 d0 12 5c 03 6a 22 00 00
+# [11196.181559] em28xx #0: i2c eeprom 10: 00 00 04 57 4e 07 00 00 00 00 00 00 00 00 00 00
+# [11196.181572] em28xx #0: i2c eeprom 20: 46 00 01 00 f0 10 01 00 00 00 00 00 5b 1e 00 00
+# [11196.181585] em28xx #0: i2c eeprom 30: 00 00 20 40 20 80 02 20 01 01 00 00 00 00 00 00
+# [11196.181598] em28xx #0: i2c eeprom 40: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+# [11196.181610] em28xx #0: i2c eeprom 50: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+# [11196.181622] em28xx #0: i2c eeprom 60: 00 00 00 00 00 00 00 00 00 00 22 03 55 00 53 00
+# [11196.181635] em28xx #0: i2c eeprom 70: 42 00 20 00 32 00 38 00 38 00 31 00 20 00 44 00
+# [11196.181648] em28xx #0: i2c eeprom 80: 65 00 76 00 69 00 63 00 65 00 00 00 00 00 00 00
+# [11196.181660] em28xx #0: i2c eeprom 90: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+# [11196.181673] em28xx #0: i2c eeprom a0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+# [11196.181685] em28xx #0: i2c eeprom b0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+# [11196.181698] em28xx #0: i2c eeprom c0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+# [11196.181710] em28xx #0: i2c eeprom d0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+# [11196.181722] em28xx #0: i2c eeprom e0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+# [11196.181735] em28xx #0: i2c eeprom f0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+#
+#############################################
+# Where can I find my original eeprom? #
+#############################################
+#
+# e.g: Old dmesg output
+#
+########################################
+# How this script works? #
+########################################
+#
+# To use it, you'll need to run the script, passing, as a parameter, the original dmesg with
+# your original eeprom (before the corruption). Something like:
+#
+# shell> perl ./rewrite_eeprom my_old_dmesg_with_right_eeprom.txt > eeprom_script
+#
+# It will generate the eeprom_script file, with a script capable of recovering
+# your eeprom.
+#
+# After having the proper eeprom_script generated, you'll need to run it, as root:
+#
+# shell> sh ./eeprom_script
+#
+#
+# After running the script, your original contents should be restored. Try to
+# remove it and reinsert to see if it will be properly detected again.
+#
+use Switch;
+
+$argv = $ARGV[0];
+
+# Files
+$file_eeprom = "/tmp/eeprom-original.txt";
+$file_bus = "/tmp/i2c-detect-bus.txt";
+$file_addr = "/tmp/i2c-detect-addr.txt";
+$file_i2c_tmp = "/tmp/i2ctmp.txt";
+
+# Bus
+$businfo = "";
+$addrinfo = "";
+
+# Modules
+$modules = "em28xx|saa713";
+$_ = $modules;
+tr/|/ /d;
+s/saa713/saa7134/g;
+$modules_str = $_;
+
+# eeprom stuff
+$eeprom_backup_dir = "~/.eeprom";
+$NR_EEPROM_REGS = 0;
+
+##########################
+# Subroutines #
+##########################
+
+sub build_script
+{
+ my $script_prevent;
+
+ # Building script
+
+ $script_prevent = "#!/bin/bash\n";
+ $script_prevent .= "#\n";
+ $script_prevent .= "# Notes:\n";
+ $script_prevent .= "# - i2c_dev module should be loaded\n";
+ $script_prevent .= "# - v4l driver should be loaded\n\n";
+
+
+ $script_prevent .= "if [ ! \"\$UID\" = \"0\" ]; then\n\techo \"You must run this script as root\";\n\texit;\nfi\n\n";
+
+ $script_prevent .= "i2cset &> /dev/null\n";
+ $script_prevent .= "if [ ! \"\$\?\" = \"1\" ]; then\n";
+ $script_prevent .= "\techo \"Please install i2c-tools package before continue.\";\n";
+ $script_prevent .= "\texit;\n";
+ $script_prevent .= "fi\n\n";
+
+ $script_prevent .= "modprobe i2c-dev\n";
+ $script_prevent .= "if [ ! \"\$\?\" = \"0\" ]; then\n";
+ $script_prevent .= "\techo \"Can't load i2c-dev module.\";\n";
+ $script_prevent .= "\texit;\n";
+ $script_prevent .= "fi\n\n";
+
+ $script_prevent .= "clear;\n";
+ $script_prevent .= "echo \"";
+ $script_prevent .= "\n\033[1;31m# # # ###### # # ### # # #####\n";
+ $script_prevent .= "# # # # # # # ## # # ## # # #\n";
+ $script_prevent .= "# # # # # # # # # # # # # # # \n";
+ $script_prevent .= "# # # # # ###### # # # # # # # # ####\n";
+ $script_prevent .= "# # # ####### # # # # # # # # # # #\n";
+ $script_prevent .= "# # # # # # # # ## # # ## # #\n";
+ $script_prevent .= " ## ## # # # # # # ### # # #####\033[0m\n\n";
+
+
+ $script_prevent .= "This tool is *ONLY RECOMMENDED* in cases of: LOST or CORRUPTED EEPROM data.\n";
+ $script_prevent .= "Otherwise:\n\nYOU MAY *LOST* THE CURRENT EEPROM FROM YOUR DEVICE AND IT WILL MAKE YOUR BOARD ";
+ $script_prevent .= "*DO NOT WORK* UNTIL YOU SET THE RIGHT EEPROM AGAIN!\n\n";
+ $script_prevent .= "If you have *any doubt*, BEFORE run it contact people from: linux-media\@vger.kernel.org\n";
+
+ $script_prevent .= "Are you \033[1;31mABSOLUTELY SURE\033[0m to continue? (yes or not)\";\n\n";
+ $script_prevent .= "read confirmation;\n";
+ $script_prevent .= "if \[ ! \"\$confirmation\" = \"yes\" \]; then\n";
+ $script_prevent .= "\techo \"process aborted\";\n";
+ $script_prevent .= "\texit;\n";
+ $script_prevent .= "fi\n\n";
+
+ $script_prevent .= "lsmod | egrep -e \"$modules\" &> /dev/null\n";
+ $script_prevent .= "if [ ! \"\$\?\" = \"0\" ]; then\n";
+ $script_prevent .= "\techo \"Aborting script.. None of the supported driver $modules_str are loaded. Did you forget to connect the device?\";\n";
+ $script_prevent .= "\texit;";
+ $script_prevent .= "\nfi\n\n";
+
+ print $script_prevent;
+}
+
+sub check_user
+{
+ if ($>) {
+ die "You must run this program as root\n";
+ }
+
+}
+
+sub get_bus_and_addr
+{
+
+ my $lines = 0;
+ my $output = "#!/bin/bash\n";
+
+ system("\ni2cdetect -l | egrep -e \"$modules\" 2> /dev/null | cut -b 5 > $file_bus\n");
+
+ # Checking number if lines
+ open(FILE, $file_bus) or die "Can't open `$file_bus': $!";
+ while (sysread FILE, $buffer, 1) {
+ $lines += ($buffer =~ tr/\n//);
+ }
+ close FILE;
+
+ switch ($lines) {
+ case 0 {
+ $output .= "echo \"Could not detect i2c bus from any device, run again $0. Did you forget to connect the device?\";\n";
+ $output .= "echo \"Modules supported: $modules_str\";\n";
+ $output .= "exit;";
+ print $output;
+ }
+ case 1 {
+ # Starting script
+ &build_script;
+ }
+ else {
+ $output .= "humm, I got too many busses, please connect or plug just a hardware peer time!\n";
+ $output .= "Read a note inside the script!\n";
+ $output .= "exit;";
+ print $output;
+ }
+ }
+
+ # Reading BUS from temporary file
+ open (FILE, $file_bus);
+ while (<FILE>) {
+ $businfo = "$_";
+ chomp($businfo);
+ }
+ close FILE;
+
+ system("i2cdetect -y $businfo > $file_i2c_tmp 2> /dev/null");
+ system("awk \'NR==7\' $file_i2c_tmp | cut -d \' \' -f 2 > $file_addr");
+
+ # Reading BUS from temporary file
+ open (FILE, $file_addr);
+ while (<FILE>) {
+ $addrinfo = "$_";
+ chomp($addrinfo);
+ }
+
+ if($addrinfo eq "--") {
+ print "\necho \"**** Failed to recognize bus address!\n**** Please connect your device *with eeprom* and try to run $0 tool again, aborted!\";\n";
+ print "exit;";
+ }
+
+ # Double check
+ $bkp_eeprom = "\n\ni2cdetect -y $businfo > $file_i2c_tmp 2> /dev/null;\n";
+ $bkp_eeprom .= "BUSCHECK=\`awk \'NR==7\' $file_i2c_tmp | cut -d \' \' -f 2\`;\n";
+ $bkp_eeprom .= "rm -f $file_i2c_tmp;\n";
+ $bkp_eeprom .= "if [ \"\$BUSCHECK\" == \"--\" ]; then\n";
+ $bkp_eeprom .= "\t echo \"Aborting script.. I cannot make backup of your current eeprom.. It's not safe to continue!\";\n";
+ $bkp_eeprom .= "\t exit;\n";
+ $bkp_eeprom .= "fi\n\n";
+
+ # Backup
+ $bkp_eeprom .= "\nDATE=\`/bin/date +%Y%m%d_%I%M%S\`\n";
+ $bkp_eeprom .= "echo \"\nMaking backup of current eeprom - dir [$eeprom_backup_dir/eeprom-\$DATE]\";\n";
+ $bkp_eeprom .= "mkdir -p $eeprom_backup_dir\n";
+ $bkp_eeprom .= "\necho \"\n--EEPROM DUMP START HERE--\n\" > $eeprom_backup_dir/eeprom-\$DATE\n";
+ $bkp_eeprom .= "i2cdump -y $businfo 0x$addrinfo >> $eeprom_backup_dir/eeprom-\$DATE 2> /dev/null\n";
+ $bkp_eeprom .= "if [ ! \"\$\?\" = \"0\" ]; then\n";
+ $bkp_eeprom .= "\t echo \"Aborting script.. I cannot make backup of your current eeprom.. It's not safe to continue!\";\n";
+ $bkp_eeprom .= "\t exit;";
+ $bkp_eeprom .= "\nfi\n";
+ $bkp_eeprom .= "\necho \"\n--DMESG START HERE--\n\" >> $eeprom_backup_dir/eeprom-\$DATE\n";
+ $bkp_eeprom .= "\ndmesg >> $eeprom_backup_dir/eeprom-\$DATE\n";
+
+ print $bkp_eeprom;
+
+ close FILE;
+}
+
+sub print_i2c
+{
+ $cmd = "cat $argv | egrep \"eeprom [0-9a-f]\"| sed -e \"s/.*eeprom/eeprom/\" | cut -d ' ' -f 3-22 > $file_eeprom";
+ system($cmd);
+
+ open (INPUT, "$file_eeprom") or die "Can't open data file: $!";
+
+ # Reading dump
+ @eeprom = "";
+ my $eeprom_pos = 0;
+ while (!eof(INPUT)) {
+ read(INPUT, $fc, 2);
+ $eeprom[$eeprom_pos] = "0x$fc";
+ seek(INPUT, tell(INPUT) + 1, 0);
+ $eeprom_pos++;
+ $NR_EEPROM_REGS++;
+ }
+ close INPUT;
+
+ if ($NR_EEPROM_REGS == 0) {
+ print "\necho \"**** Failed to recognize any dump in: $argv! Make sure that you have the right dump file before run again $0 tool, aborted!\";\n";
+ print "exit;";
+ }
+
+ print "\n\necho \"\033[1;31m\n[DO NOT REMOVE YOUR DEVICE UNTIL THE UPDATE IS FINISHED]\033[0m\";\n";
+ print "echo \"Press ENTER to start\";\n";
+ print "read\n";
+
+ for ($i=0; $i < $NR_EEPROM_REGS; $i++) {
+ printf("i2cset -y $businfo 0x$addrinfo 0x%02x $eeprom[$i] b\n", $i);
+ }
+
+ printf("\necho \"\nDone! Remove and re-insert your device to see if it will be properly detected again. :-)\n\";\n");
+}
+
+################
+# Main #
+################
+
+&check_user;
+
+if (@ARGV <= 0) {
+
+ my $em28xx_note = "\n\033[1;31m\nNOTES\033[0m:\n\t Not tested against newer em28xx chipsets like the em2874 and em2884\n";
+
+ print "\033[1;31m\nWARNING\033[0m:\n \t This script can *\033[1;31mDAMAGE\033[0m* your board, if you are not sure how to use it, *DO NOT* run it\n";
+ print "\t Current modules supported: $modules_str *\033[1;31mONLY\033[0m*";
+ print $em28xx_note;
+ print "\t If you have *any doubt*, \033[1;31mBEFORE run it\033[0m contact people from: linux-media\@vger.kernel.org\n";
+
+ print "\nUsage:\n";
+ print "\tshell>perl $0 ./dmesg-dump-eeprom > eeprom_script.sh\n";
+ print "\tshell>sh ./eeprom_script.sh\n\n";
+ exit();
+}
+
+if (! -e $argv) {
+ printf("No such file: $argv\n");
+ exit();
+}
+
+# Calling sub routines
+&get_bus_and_addr;
+&print_i2c;
+
+# Removing tmp files
+system("rm -f $file_bus");
+system("rm -f $file_addr");
+system("rm -f $file_i2c_tmp");
+system("rm -f $file_eeprom");
diff --git a/v4l2-apps/util/v4l2-ctl.cpp b/v4l2-apps/util/v4l2-ctl.cpp
index dec9edd61..5b38e37b3 100644
--- a/v4l2-apps/util/v4l2-ctl.cpp
+++ b/v4l2-apps/util/v4l2-ctl.cpp
@@ -77,6 +77,8 @@ enum Option {
OptSetTuner = 't',
OptGetVideoFormat = 'V',
OptSetVideoFormat = 'v',
+ OptGetParm = 'P',
+ OptSetParm = 'p',
OptGetSlicedVbiOutFormat = 128,
OptGetOverlayFormat,
@@ -103,6 +105,9 @@ enum Option {
OptStreamOn,
OptListStandards,
OptListFormats,
+ OptListFormatsExt,
+ OptListFrameSizes,
+ OptListFrameIntervals,
OptLogStatus,
OptVerbose,
OptSilent,
@@ -131,7 +136,11 @@ enum Option {
OptOverlay,
OptGetJpegComp,
OptSetJpegComp,
+ OptGetModulator,
+ OptSetModulator,
OptListDevices,
+ OptGetOutputParm,
+ OptSetOutputParm,
OptLast = 256
};
@@ -142,19 +151,17 @@ static int verbose;
static unsigned capabilities;
-typedef std::vector<struct v4l2_ext_control> ctrl_list;
-static ctrl_list user_ctrls;
-static ctrl_list mpeg_ctrls;
+typedef std::map<unsigned, std::vector<struct v4l2_ext_control> > class2ctrls_map;
-typedef std::map<std::string, unsigned> ctrl_strmap;
-static ctrl_strmap ctrl_str2id;
+typedef std::map<std::string, struct v4l2_queryctrl> ctrl_qmap;
+static ctrl_qmap ctrl_str2q;
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;
+typedef std::map<std::string, std::string> ctrl_set_map;
static ctrl_set_map set_ctrls;
typedef std::vector<std::string> dev_vec;
@@ -217,8 +224,15 @@ static struct option long_options[] = {
{"streamon", no_argument, 0, OptStreamOn},
{"list-standards", no_argument, 0, OptListStandards},
{"list-formats", no_argument, 0, OptListFormats},
+ {"list-formats-ext", no_argument, 0, OptListFormatsExt},
+ {"list-framesizes", required_argument, 0, OptListFrameSizes},
+ {"list-frameintervals", required_argument, 0, OptListFrameIntervals},
{"get-standard", no_argument, 0, OptGetStandard},
{"set-standard", required_argument, 0, OptSetStandard},
+ {"get-parm", no_argument, 0, OptGetParm},
+ {"set-parm", required_argument, 0, OptSetParm},
+ {"get-output-parm", no_argument, 0, OptGetOutputParm},
+ {"set-output-parm", required_argument, 0, OptSetOutputParm},
{"info", no_argument, 0, OptGetDriverInfo},
{"list-ctrls", no_argument, 0, OptListCtrls},
{"list-ctrls-menus", no_argument, 0, OptListCtrlsMenus},
@@ -260,6 +274,8 @@ static struct option long_options[] = {
{"set-crop-output-overlay", required_argument, 0, OptSetOutputOverlayCrop},
{"get-jpeg-comp", no_argument, 0, OptGetJpegComp},
{"set-jpeg-comp", required_argument, 0, OptSetJpegComp},
+ {"get-modulator", no_argument, 0, OptGetModulator},
+ {"set-modulator", required_argument, 0, OptSetModulator},
{"overlay", required_argument, 0, OptOverlay},
{"list-devices", no_argument, 0, OptListDevices},
{0, 0, 0, 0}
@@ -301,11 +317,26 @@ static void usage(void)
" 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"
+ " -P, --get-parm display video parameters [VIDIOC_G_PARM]\n"
+ " -p, --set-parm=<fps>\n"
+ " set video framerate in <fps> [VIDIOC_S_PARM]\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"
+ " --list-formats-ext display supported video formats including frame sizes\n"
+ " and intervals\n"
+ " --list-framesizes=<f>\n"
+ " list supported framesizes for pixelformat <f>\n"
+ " [VIDIOC_ENUM_FRAMESIZES]\n"
+ " pixelformat is either the format index as reported by\n"
+ " --list-formats, or the fourcc value as a string\n"
+ " --list-frameintervals=width=<w>,height=<h>,pixelformat=<f>\n"
+ " list supported frame intervals for pixelformat <f> and\n"
+ " the given width and height [VIDIOC_ENUM_FRAMEINTERVALS]\n"
+ " pixelformat is either the format index as reported by\n"
+ " --list-formats, or the fourcc value as a string\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"
@@ -404,6 +435,20 @@ static void usage(void)
" display audio outputs [VIDIOC_ENUMAUDOUT]\n"
" --list-audio-inputs\n"
" display audio inputs [VIDIOC_ENUMAUDIO]\n"
+ " --get-modulator query the modulator settings [VIDIOC_G_MODULATOR]\n"
+ " --set-modulator=<txsubchans>\n"
+ " set the sub-carrier modulation [VIDIOC_S_MODULATOR]\n"
+ " <txsubchans> is one of:\n"
+ " mono: Modulate as mono\n"
+ " mono-rds: Modulate as mono with RDS (radio only)\n"
+ " stereo: Modulate as stereo\n"
+ " stereo-rds: Modulate as stereo with RDS (radio only)\n"
+ " bilingual: Modulate as bilingual\n"
+ " mono-sap: Modulate as mono with Second Audio Program\n"
+ " stereo-sap: Modulate as stereo with Second Audio Program\n"
+ " --get-output-parm display output video parameters [VIDIOC_G_PARM]\n"
+ " --set-output-parm=<fps>\n"
+ " set output video framerate in <fps> [VIDIOC_S_PARM]\n"
"\n");
printf("Expert options:\n"
" --streamoff turn the stream off [VIDIOC_STREAMOFF]\n"
@@ -553,6 +598,43 @@ static std::string name2var(unsigned char *name)
return s;
}
+static std::string safename(const unsigned char *name)
+{
+ std::string s;
+
+ while (*name) {
+ if (*name == '\n') {
+ s += "\\n";
+ }
+ else if (*name == '\r') {
+ s += "\\r";
+ }
+ else if (*name == '\f') {
+ s += "\\f";
+ }
+ else if (*name == '\\') {
+ s += "\\\\";
+ }
+ else if ((*name & 0x7f) < 0x20) {
+ char buf[3];
+
+ sprintf(buf, "%02x", *name);
+ s += "\\x";
+ s += buf;
+ }
+ else {
+ s += *name;
+ }
+ name++;
+ }
+ return s;
+}
+
+static std::string safename(const char *name)
+{
+ return safename((const unsigned char *)name);
+}
+
static void print_qctrl(int fd, struct v4l2_queryctrl *queryctrl,
struct v4l2_ext_control *ctrl, int show_menus)
{
@@ -572,6 +654,12 @@ static void print_qctrl(int fd, struct v4l2_queryctrl *queryctrl,
case V4L2_CTRL_TYPE_INTEGER64:
printf("%31s (int64): value=%lld", s.c_str(), ctrl->value64);
break;
+ case V4L2_CTRL_TYPE_STRING:
+ printf("%31s (str) : min=%d max=%d step=%d value='%s'",
+ s.c_str(),
+ queryctrl->minimum, queryctrl->maximum,
+ queryctrl->step, safename(ctrl->string).c_str());
+ break;
case V4L2_CTRL_TYPE_BOOLEAN:
printf("%31s (bool) : default=%d value=%d",
s.c_str(),
@@ -629,6 +717,11 @@ static int print_control(int fd, struct v4l2_queryctrl &qctrl, int show_menus)
ctrls.controls = &ext_ctrl;
if (V4L2_CTRL_ID2CLASS(qctrl.id) != V4L2_CTRL_CLASS_USER &&
qctrl.id < V4L2_CID_PRIVATE_BASE) {
+ if (qctrl.type == V4L2_CTRL_TYPE_STRING) {
+ ext_ctrl.size = qctrl.maximum + 1;
+ ext_ctrl.string = (char *)malloc(ext_ctrl.size);
+ ext_ctrl.string[0] = 0;
+ }
if (ioctl(fd, VIDIOC_G_EXT_CTRLS, &ctrls)) {
printf("error %d getting ext_ctrl %s\n",
errno, qctrl.name);
@@ -645,6 +738,8 @@ static int print_control(int fd, struct v4l2_queryctrl &qctrl, int show_menus)
ext_ctrl.value = ctrl.value;
}
print_qctrl(fd, &qctrl, &ext_ctrl, show_menus);
+ if (qctrl.type == V4L2_CTRL_TYPE_STRING)
+ free(ext_ctrl.string);
return 1;
}
@@ -678,7 +773,7 @@ static void find_controls(int fd)
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_str2q[name2var(qctrl.name)] = qctrl;
ctrl_id2str[qctrl.id] = name2var(qctrl.name);
}
qctrl.id |= V4L2_CTRL_FLAG_NEXT_CTRL;
@@ -689,14 +784,14 @@ static void find_controls(int fd)
qctrl.id = id;
if (ioctl(fd, VIDIOC_QUERYCTRL, &qctrl) == 0 &&
!(qctrl.flags & V4L2_CTRL_FLAG_DISABLED)) {
- ctrl_str2id[name2var(qctrl.name)] = qctrl.id;
+ ctrl_str2q[name2var(qctrl.name)] = qctrl;
ctrl_id2str[qctrl.id] = name2var(qctrl.name);
}
}
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;
+ ctrl_str2q[name2var(qctrl.name)] = qctrl;
ctrl_id2str[qctrl.id] = name2var(qctrl.name);
}
}
@@ -810,7 +905,7 @@ static void printcropcap(const struct v4l2_cropcap &cropcap)
printf("\tPixel Aspect: %u/%u\n", cropcap.pixelaspect.numerator, cropcap.pixelaspect.denominator);
}
-static void printfmt(struct v4l2_format vfmt)
+static void printfmt(const struct v4l2_format &vfmt)
{
const flag_def vbi_def[] = {
{ V4L2_VBI_UNSYNC, "unsynchronized" },
@@ -874,6 +969,72 @@ static void printfmt(struct v4l2_format vfmt)
}
}
+static std::string frmtype2s(unsigned type)
+{
+ static const char *types[] = {
+ "Unknown",
+ "Discrete",
+ "Continuous",
+ "Stepwise"
+ };
+
+ if (type > 3)
+ type = 0;
+ return types[type];
+}
+
+static std::string fract2sec(const struct v4l2_fract &f)
+{
+ char buf[100];
+
+ sprintf(buf, "%.3f s", (1.0 * f.numerator) / f.denominator);
+ return buf;
+}
+
+static std::string fract2fps(const struct v4l2_fract &f)
+{
+ char buf[100];
+
+ sprintf(buf, "%.3f fps", (1.0 * f.denominator) / f.numerator);
+ return buf;
+}
+
+static void print_frmsize(const struct v4l2_frmsizeenum &frmsize, const char *prefix)
+{
+ printf("%s\tSize: %s ", prefix, frmtype2s(frmsize.type).c_str());
+ if (frmsize.type == V4L2_FRMSIZE_TYPE_DISCRETE) {
+ printf("%dx%d", frmsize.discrete.width, frmsize.discrete.height);
+ } else if (frmsize.type == V4L2_FRMSIZE_TYPE_STEPWISE) {
+ printf("%dx%d - %dx%d with step %d/%d",
+ frmsize.stepwise.min_width,
+ frmsize.stepwise.min_height,
+ frmsize.stepwise.max_width,
+ frmsize.stepwise.max_height,
+ frmsize.stepwise.step_width,
+ frmsize.stepwise.step_height);
+ }
+ printf("\n");
+}
+
+static void print_frmival(const struct v4l2_frmivalenum &frmival, const char *prefix)
+{
+ printf("%s\tInterval: %s ", prefix, frmtype2s(frmival.type).c_str());
+ if (frmival.type == V4L2_FRMIVAL_TYPE_DISCRETE) {
+ printf("%s (%s)\n", fract2sec(frmival.discrete).c_str(),
+ fract2fps(frmival.discrete).c_str());
+ } else if (frmival.type == V4L2_FRMIVAL_TYPE_STEPWISE) {
+ printf("%s - %s with step %s\n",
+ fract2sec(frmival.stepwise.min).c_str(),
+ fract2sec(frmival.stepwise.max).c_str(),
+ fract2sec(frmival.stepwise.step).c_str());
+ printf("%s\t : ", prefix);
+ printf("(%s - %s with step %s)\n",
+ fract2fps(frmival.stepwise.min).c_str(),
+ fract2fps(frmival.stepwise.max).c_str(),
+ fract2fps(frmival.stepwise.step).c_str());
+ }
+}
+
static void print_video_formats(int fd, enum v4l2_buf_type type)
{
struct v4l2_fmtdesc fmt;
@@ -893,6 +1054,43 @@ static void print_video_formats(int fd, enum v4l2_buf_type type)
}
}
+static void print_video_formats_ext(int fd, enum v4l2_buf_type type)
+{
+ struct v4l2_fmtdesc fmt;
+ struct v4l2_frmsizeenum frmsize;
+ struct v4l2_frmivalenum frmival;
+
+ 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("\tPixel Format: '%s'", fcc2s(fmt.pixelformat).c_str());
+ if (fmt.flags)
+ printf(" (compressed)");
+ printf("\n");
+ printf("\tName : %s\n", fmt.description);
+ frmsize.pixel_format = fmt.pixelformat;
+ frmsize.index = 0;
+ while (ioctl(fd, VIDIOC_ENUM_FRAMESIZES, &frmsize) >= 0) {
+ print_frmsize(frmsize, "\t");
+ if (frmsize.type == V4L2_FRMSIZE_TYPE_DISCRETE) {
+ frmival.index = 0;
+ frmival.pixel_format = fmt.pixelformat;
+ frmival.width = frmsize.discrete.width;
+ frmival.height = frmsize.discrete.height;
+ while (ioctl(fd, VIDIOC_ENUM_FRAMEINTERVALS, &frmival) >= 0) {
+ print_frmival(frmival, "\t\t");
+ frmival.index++;
+ }
+ }
+ frmsize.index++;
+ }
+ printf("\n");
+ fmt.index++;
+ }
+}
+
static char *pts_to_string(char *str, unsigned long pts)
{
static char buf[256];
@@ -943,6 +1141,25 @@ static std::string rxsubchans2s(int rxsubchans)
s += "lang1 ";
if (rxsubchans & V4L2_TUNER_SUB_LANG2)
s += "lang2 ";
+ if (rxsubchans & V4L2_TUNER_SUB_RDS)
+ s += "rds ";
+ return s;
+}
+
+static std::string txsubchans2s(int txsubchans)
+{
+ std::string s;
+
+ if (txsubchans & V4L2_TUNER_SUB_MONO)
+ s += "mono";
+ if (txsubchans & V4L2_TUNER_SUB_STEREO)
+ s += "stereo";
+ if (txsubchans & V4L2_TUNER_SUB_LANG1)
+ s += "bilingual";
+ if (txsubchans & V4L2_TUNER_SUB_SAP)
+ s += "+sap";
+ if (txsubchans & V4L2_TUNER_SUB_RDS)
+ s += "+rds";
return s;
}
@@ -962,6 +1179,8 @@ static std::string tcap2s(unsigned cap)
s += "lang1 ";
if (cap & V4L2_TUNER_CAP_LANG2)
s += "lang2 ";
+ if (cap & V4L2_TUNER_CAP_RDS)
+ s += "rds ";
return s;
}
@@ -987,8 +1206,12 @@ static std::string cap2s(unsigned cap)
s += "\t\tSliced VBI Output\n";
if (cap & V4L2_CAP_RDS_CAPTURE)
s += "\t\tRDS Capture\n";
+ if (cap & V4L2_CAP_RDS_OUTPUT)
+ s += "\t\tRDS Output\n";
if (cap & V4L2_CAP_TUNER)
s += "\t\tTuner\n";
+ if (cap & V4L2_CAP_MODULATOR)
+ s += "\t\tModulator\n";
if (cap & V4L2_CAP_AUDIO)
s += "\t\tAudio\n";
if (cap & V4L2_CAP_RADIO)
@@ -1339,6 +1562,17 @@ static enum v4l2_field parse_field(const char *s)
return V4L2_FIELD_ANY;
}
+static __u32 find_pixel_format(int fd, unsigned index)
+{
+ struct v4l2_fmtdesc fmt;
+
+ fmt.index = index;
+ fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+ if (doioctl(fd, VIDIOC_ENUM_FMT, &fmt, "VIDIOC_ENUM_FMT"))
+ return 0;
+ return fmt.pixelformat;
+}
+
int main(int argc, char **argv)
{
char *value, *subs;
@@ -1370,22 +1604,29 @@ int main(int argc, char **argv)
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_tuner tuner; /* set_freq/get_freq */
+ struct v4l2_modulator modulator;/* set_freq/get_freq */
struct v4l2_capability vcap; /* list_cap */
struct v4l2_input vin; /* list_inputs */
struct v4l2_output vout; /* list_outputs */
struct v4l2_audio vaudio; /* list audio inputs */
struct v4l2_audioout vaudout; /* audio outputs */
+ struct v4l2_frmsizeenum frmsize;/* list frame sizes */
+ struct v4l2_frmivalenum frmival;/* list frame intervals */
struct v4l2_rect vcrop; /* crop rect */
struct v4l2_rect vcrop_out; /* crop rect */
struct v4l2_rect vcrop_overlay; /* crop rect */
struct v4l2_rect vcrop_out_overlay; /* crop rect */
struct v4l2_framebuffer fbuf; /* fbuf */
struct v4l2_jpegcompression jpegcomp; /* jpeg compression */
+ struct v4l2_streamparm parm; /* get/set parm */
int input; /* set_input/get_input */
int output; /* set_output/get_output */
+ int txsubchans; /* set_modulator */
v4l2_std_id std; /* get_std/set_std */
double freq = 0; /* get/set frequency */
+ double fps = 0; /* set framerate speed, in fps */
+ double output_fps = 0; /* set framerate speed, in fps */
struct v4l2_frequency vf; /* get_freq/set_freq */
struct v4l2_standard vs; /* list_std */
int overlay; /* overlay */
@@ -1404,11 +1645,14 @@ int main(int argc, char **argv)
memset(&overlay_fmt_out, 0, sizeof(overlay_fmt_out));
memset(&raw_fmt_out, 0, sizeof(raw_fmt_out));
memset(&tuner, 0, sizeof(tuner));
+ memset(&modulator, 0, sizeof(modulator));
memset(&vcap, 0, sizeof(vcap));
memset(&vin, 0, sizeof(vin));
memset(&vout, 0, sizeof(vout));
memset(&vaudio, 0, sizeof(vaudio));
memset(&vaudout, 0, sizeof(vaudout));
+ memset(&frmsize, 0, sizeof(frmsize));
+ memset(&frmival, 0, sizeof(frmival));
memset(&vcrop, 0, sizeof(vcrop));
memset(&vcrop_out, 0, sizeof(vcrop_out));
memset(&vcrop_overlay, 0, sizeof(vcrop_overlay));
@@ -1602,6 +1846,41 @@ int main(int argc, char **argv)
case OptOverlay:
overlay = strtol(optarg, 0L, 0);
break;
+ case OptListFrameSizes:
+ if (strlen(optarg) == 4)
+ frmsize.pixel_format = v4l2_fourcc(optarg[0], optarg[1],
+ optarg[2], optarg[3]);
+ else
+ frmsize.pixel_format = strtol(optarg, 0L, 0);
+ break;
+ case OptListFrameIntervals:
+ subs = optarg;
+ while (*subs != '\0') {
+ static const char *const subopts[] = {
+ "width",
+ "height",
+ "pixelformat",
+ NULL
+ };
+
+ switch (parse_subopt(&subs, subopts, &value)) {
+ case 0:
+ frmival.width = strtol(value, 0L, 0);
+ break;
+ case 1:
+ frmival.height = strtol(value, 0L, 0);
+ break;
+ case 2:
+ if (strlen(value) == 4)
+ frmival.pixel_format =
+ v4l2_fourcc(value[0], value[1],
+ value[2], value[3]);
+ else
+ frmival.pixel_format = strtol(value, 0L, 0);
+ break;
+ }
+ }
+ break;
case OptSetCrop:
parse_crop(optarg, set_crop, vcrop);
break;
@@ -1652,6 +1931,12 @@ int main(int argc, char **argv)
std = strtol(optarg, 0L, 0) | (1ULL << 63);
}
break;
+ case OptSetParm:
+ fps = strtod(optarg, NULL);
+ break;
+ case OptSetOutputParm:
+ output_fps = strtod(optarg, NULL);
+ break;
case OptGetCtrl:
subs = optarg;
while (*subs != '\0') {
@@ -1695,6 +1980,28 @@ int main(int argc, char **argv)
return 1;
}
break;
+ case OptSetModulator:
+ txsubchans = strtol(optarg, 0L, 0);
+ if (!strcmp(optarg, "stereo"))
+ txsubchans = V4L2_TUNER_SUB_STEREO;
+ else if (!strcmp(optarg, "stereo-sap"))
+ txsubchans = V4L2_TUNER_SUB_STEREO | V4L2_TUNER_SUB_SAP;
+ else if (!strcmp(optarg, "bilingual"))
+ txsubchans = V4L2_TUNER_SUB_LANG1;
+ else if (!strcmp(optarg, "mono"))
+ txsubchans = V4L2_TUNER_SUB_MONO;
+ else if (!strcmp(optarg, "mono-sap"))
+ txsubchans = V4L2_TUNER_SUB_MONO | V4L2_TUNER_SUB_SAP;
+ else if (!strcmp(optarg, "stereo-rds"))
+ txsubchans = V4L2_TUNER_SUB_STEREO | V4L2_TUNER_SUB_RDS;
+ else if (!strcmp(optarg, "mono-rds"))
+ txsubchans = V4L2_TUNER_SUB_MONO | V4L2_TUNER_SUB_RDS;
+ else {
+ fprintf(stderr, "Unknown txsubchans value\n");
+ usage();
+ return 1;
+ }
+ break;
case OptSetSlicedVbiFormat:
case OptSetSlicedVbiOutFormat:
case OptTrySlicedVbiFormat:
@@ -1837,13 +2144,13 @@ int main(int argc, char **argv)
capabilities = 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()) {
+ if (ctrl_str2q.find(*iter) == ctrl_str2q.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()) {
+ if (ctrl_str2q.find(iter->first) == ctrl_str2q.end()) {
fprintf(stderr, "unknown control '%s'\n", iter->first.c_str());
exit(1);
}
@@ -1859,8 +2166,11 @@ int main(int argc, char **argv)
options[OptGetAudioInput] = 1;
options[OptGetAudioOutput] = 1;
options[OptGetStandard] = 1;
+ options[OptGetParm] = 1;
+ options[OptGetOutputParm] = 1;
options[OptGetFreq] = 1;
options[OptGetTuner] = 1;
+ options[OptGetModulator] = 1;
options[OptGetOverlayFormat] = 1;
options[OptGetOutputOverlayFormat] = 1;
options[OptGetVbiFormat] = 1;
@@ -1896,11 +2206,17 @@ int main(int argc, char **argv)
if (options[OptSetFreq]) {
double fac = 16;
- if (doioctl(fd, VIDIOC_G_TUNER, &tuner, "VIDIOC_G_TUNER") == 0) {
- fac = (tuner.capability & V4L2_TUNER_CAP_LOW) ? 16000 : 16;
+ if (capabilities & V4L2_CAP_MODULATOR) {
+ if (doioctl(fd, VIDIOC_G_MODULATOR, &modulator, "VIDIOC_G_MODULATOR") == 0)
+ fac = (modulator.capability & V4L2_TUNER_CAP_LOW) ? 16000 : 16;
+ } else {
+ vf.type = V4L2_TUNER_ANALOG_TV;
+ if (doioctl(fd, VIDIOC_G_TUNER, &tuner, "VIDIOC_G_TUNER") == 0) {
+ fac = (tuner.capability & V4L2_TUNER_CAP_LOW) ? 16000 : 16;
+ vf.type = tuner.type;
+ }
}
vf.tuner = 0;
- vf.type = tuner.type;
vf.frequency = __u32(freq * fac);
if (doioctl(fd, VIDIOC_S_FREQUENCY, &vf,
"VIDIOC_S_FREQUENCY") == 0)
@@ -1919,6 +2235,43 @@ int main(int argc, char **argv)
printf("Standard set to %08llx\n", (unsigned long long)std);
}
+
+ if (options[OptSetParm]) {
+ memset(&parm, 0, sizeof(parm));
+ parm.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+ parm.parm.capture.timeperframe.numerator = 1000;
+ parm.parm.capture.timeperframe.denominator =
+ fps * parm.parm.capture.timeperframe.numerator;
+
+ if (doioctl(fd, VIDIOC_S_PARM, &parm, "VIDIOC_S_PARM") == 0) {
+ struct v4l2_fract *tf = &parm.parm.capture.timeperframe;
+
+ if (!tf->denominator || !tf->numerator)
+ printf("Invalid frame rate\n");
+ else
+ printf("Frame rate set to %.3f fps\n",
+ 1.0 * tf->denominator / tf->numerator);
+ }
+ }
+
+ if (options[OptSetOutputParm]) {
+ memset(&parm, 0, sizeof(parm));
+ parm.type = V4L2_BUF_TYPE_VIDEO_OUTPUT;
+ parm.parm.output.timeperframe.numerator = 1000;
+ parm.parm.output.timeperframe.denominator =
+ fps * parm.parm.output.timeperframe.numerator;
+
+ if (doioctl(fd, VIDIOC_S_PARM, &parm, "VIDIOC_S_PARM") == 0) {
+ struct v4l2_fract *tf = &parm.parm.output.timeperframe;
+
+ if (!tf->denominator || !tf->numerator)
+ printf("Invalid frame rate\n");
+ else
+ printf("Frame rate set to %.3f fps\n",
+ 1.0 * tf->denominator / tf->numerator);
+ }
+ }
+
if (options[OptSetInput]) {
if (doioctl(fd, VIDIOC_S_INPUT, &input, "VIDIOC_S_INPUT") == 0) {
printf("Video input set to %d", input);
@@ -1954,6 +2307,16 @@ int main(int argc, char **argv)
}
}
+ if (options[OptSetModulator]) {
+ struct v4l2_modulator mt;
+
+ memset(&mt, 0, sizeof(struct v4l2_modulator));
+ if (doioctl(fd, VIDIOC_G_MODULATOR, &mt, "VIDIOC_G_MODULATOR") == 0) {
+ mt.txsubchans = txsubchans;
+ doioctl(fd, VIDIOC_S_MODULATOR, &mt, "VIDIOC_S_MODULATOR");
+ }
+ }
+
if (options[OptSetVideoFormat] || options[OptTryVideoFormat]) {
struct v4l2_format in_vfmt;
@@ -1966,13 +2329,8 @@ int main(int argc, char **argv)
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;
+ in_vfmt.fmt.pix.pixelformat =
+ find_pixel_format(fd, in_vfmt.fmt.pix.pixelformat);
}
}
if (options[OptSetVideoFormat])
@@ -2116,42 +2474,61 @@ set_vid_fmt_error:
if (options[OptSetCtrl] && !set_ctrls.empty()) {
struct v4l2_ext_controls ctrls = { 0 };
+ class2ctrls_map class2ctrls;
for (ctrl_set_map::iterator iter = set_ctrls.begin();
iter != set_ctrls.end(); ++iter) {
struct v4l2_ext_control ctrl = { 0 };
- ctrl.id = ctrl_str2id[iter->first];
- ctrl.value = strtol(iter->second.c_str(), NULL, 0);
- if (V4L2_CTRL_ID2CLASS(ctrl.id) == V4L2_CTRL_CLASS_MPEG)
- mpeg_ctrls.push_back(ctrl);
- else
- user_ctrls.push_back(ctrl);
- }
- for (unsigned i = 0; i < user_ctrls.size(); i++) {
- struct v4l2_control ctrl;
-
- ctrl.id = user_ctrls[i].id;
- ctrl.value = user_ctrls[i].value;
- if (doioctl(fd, VIDIOC_S_CTRL, &ctrl, "VIDIOC_S_CTRL")) {
- fprintf(stderr, "%s: %s\n",
- ctrl_id2str[ctrl.id].c_str(),
- strerror(errno));
+ ctrl.id = ctrl_str2q[iter->first].id;
+ if (ctrl_str2q[iter->first].type == V4L2_CTRL_TYPE_STRING) {
+ unsigned len = iter->second.length();
+ unsigned maxlen = ctrl_str2q[iter->first].maximum;
+
+ ctrl.size = maxlen + 1;
+ ctrl.string = (char *)malloc(ctrl.size);
+ if (len > maxlen) {
+ memcpy(ctrl.string, iter->second.c_str(), maxlen);
+ ctrl.string[maxlen] = 0;
+ }
+ else {
+ strcpy(ctrl.string, iter->second.c_str());
+ }
+ } else {
+ ctrl.value = strtol(iter->second.c_str(), NULL, 0);
}
+ class2ctrls[V4L2_CTRL_ID2CLASS(ctrl.id)].push_back(ctrl);
}
- if (mpeg_ctrls.size()) {
- ctrls.ctrl_class = V4L2_CTRL_CLASS_MPEG;
- ctrls.count = mpeg_ctrls.size();
- ctrls.controls = &mpeg_ctrls[0];
- if (doioctl(fd, VIDIOC_S_EXT_CTRLS, &ctrls, "VIDIOC_S_EXT_CTRLS")) {
- if (ctrls.error_idx >= ctrls.count) {
- fprintf(stderr, "Error setting MPEG controls: %s\n",
- strerror(errno));
+ for (class2ctrls_map::iterator iter = class2ctrls.begin();
+ iter != class2ctrls.end(); ++iter) {
+ if (iter->first == V4L2_CTRL_CLASS_USER) {
+ for (unsigned i = 0; i < iter->second.size(); i++) {
+ struct v4l2_control ctrl;
+
+ ctrl.id = iter->second[i].id;
+ ctrl.value = iter->second[i].value;
+ if (doioctl(fd, VIDIOC_S_CTRL, &ctrl, "VIDIOC_S_CTRL")) {
+ fprintf(stderr, "%s: %s\n",
+ ctrl_id2str[ctrl.id].c_str(),
+ strerror(errno));
+ }
}
- else {
- fprintf(stderr, "%s: %s\n",
- ctrl_id2str[mpeg_ctrls[ctrls.error_idx].id].c_str(),
- strerror(errno));
+ continue;
+ }
+ if (iter->second.size()) {
+ ctrls.ctrl_class = iter->first;
+ ctrls.count = iter->second.size();
+ ctrls.controls = &iter->second[0];
+ if (doioctl(fd, VIDIOC_S_EXT_CTRLS, &ctrls, "VIDIOC_S_EXT_CTRLS")) {
+ if (ctrls.error_idx >= ctrls.count) {
+ fprintf(stderr, "Error setting MPEG controls: %s\n",
+ strerror(errno));
+ }
+ else {
+ fprintf(stderr, "%s: %s\n",
+ ctrl_id2str[iter->second[ctrls.error_idx].id].c_str(),
+ strerror(errno));
+ }
}
}
}
@@ -2321,6 +2698,16 @@ set_vid_fmt_error:
if (options[OptGetFreq]) {
double fac = 16;
+ if (capabilities & V4L2_CAP_MODULATOR) {
+ if (doioctl(fd, VIDIOC_G_MODULATOR, &modulator, "VIDIOC_G_MODULATOR") == 0)
+ fac = (modulator.capability & V4L2_TUNER_CAP_LOW) ? 16000 : 16;
+ } else {
+ vf.type = V4L2_TUNER_ANALOG_TV;
+ if (doioctl(fd, VIDIOC_G_TUNER, &tuner, "VIDIOC_G_TUNER") == 0) {
+ fac = (tuner.capability & V4L2_TUNER_CAP_LOW) ? 16000 : 16;
+ vf.type = tuner.type;
+ }
+ }
if (doioctl(fd, VIDIOC_G_TUNER, &tuner, "VIDIOC_G_TUNER") == 0) {
fac = (tuner.capability & V4L2_TUNER_CAP_LOW) ? 16000 : 16;
}
@@ -2366,43 +2753,99 @@ set_vid_fmt_error:
}
}
+ if (options[OptGetParm]) {
+ memset(&parm, 0, sizeof(parm));
+ parm.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+ if (doioctl(fd, VIDIOC_G_PARM, &parm, "VIDIOC_G_PARM") == 0) {
+ const struct v4l2_fract &tf = parm.parm.capture.timeperframe;
+
+ printf("Streaming Parameters %s:\n", buftype2s(parm.type).c_str());
+ if (parm.parm.capture.capability & V4L2_CAP_TIMEPERFRAME)
+ printf("\tCapabilities : timeperframe\n");
+ if (parm.parm.capture.capturemode & V4L2_MODE_HIGHQUALITY)
+ printf("\tCapture mode : high quality\n");
+ if (!tf.denominator || !tf.numerator)
+ printf("\tFrames per second: invalid (%d/%d)\n",
+ tf.denominator, tf.numerator);
+ else
+ printf("\tFrames per second: %.3f (%d/%d)\n",
+ (1.0 * tf.denominator) / tf.numerator,
+ tf.denominator, tf.numerator);
+ printf("\tRead buffers : %d\n", parm.parm.output.writebuffers);
+ }
+ }
+
+ if (options[OptGetOutputParm]) {
+ memset(&parm, 0, sizeof(parm));
+ parm.type = V4L2_BUF_TYPE_VIDEO_OUTPUT;
+ if (doioctl(fd, VIDIOC_G_PARM, &parm, "VIDIOC_G_PARM") == 0) {
+ const struct v4l2_fract &tf = parm.parm.output.timeperframe;
+
+ printf("Streaming Parameters %s:\n", buftype2s(parm.type).c_str());
+ if (parm.parm.output.capability & V4L2_CAP_TIMEPERFRAME)
+ printf("\tCapabilities : timeperframe\n");
+ if (parm.parm.output.outputmode & V4L2_MODE_HIGHQUALITY)
+ printf("\tOutput mode : high quality\n");
+ if (!tf.denominator || !tf.numerator)
+ printf("\tFrames per second: invalid (%d/%d)\n",
+ tf.denominator, tf.numerator);
+ else
+ printf("\tFrames per second: %.3f (%d/%d)\n",
+ (1.0 * tf.denominator) / tf.numerator,
+ tf.denominator, tf.numerator);
+ printf("\tWrite buffers : %d\n", parm.parm.output.writebuffers);
+ }
+ }
+
if (options[OptGetCtrl] && !get_ctrls.empty()) {
struct v4l2_ext_controls ctrls = { 0 };
+ class2ctrls_map class2ctrls;
- mpeg_ctrls.clear();
- user_ctrls.clear();
for (ctrl_get_list::iterator iter = get_ctrls.begin();
iter != get_ctrls.end(); ++iter) {
struct v4l2_ext_control ctrl = { 0 };
- ctrl.id = ctrl_str2id[*iter];
- if (V4L2_CTRL_ID2CLASS(ctrl.id) == V4L2_CTRL_CLASS_MPEG)
- mpeg_ctrls.push_back(ctrl);
- else
- user_ctrls.push_back(ctrl);
- }
- for (unsigned i = 0; i < user_ctrls.size(); i++) {
- struct v4l2_control ctrl;
-
- ctrl.id = user_ctrls[i].id;
- doioctl(fd, VIDIOC_G_CTRL, &ctrl, "VIDIOC_G_CTRL");
- printf("%s: %d\n", ctrl_id2str[ctrl.id].c_str(), ctrl.value);
+ ctrl.id = ctrl_str2q[*iter].id;
+ if (ctrl_str2q[*iter].type == V4L2_CTRL_TYPE_STRING) {
+ ctrl.size = ctrl_str2q[*iter].maximum + 1;
+ ctrl.string = (char *)malloc(ctrl.size);
+ ctrl.string[0] = 0;
+ }
+ class2ctrls[V4L2_CTRL_ID2CLASS(ctrl.id)].push_back(ctrl);
}
- if (mpeg_ctrls.size()) {
- ctrls.ctrl_class = V4L2_CTRL_CLASS_MPEG;
- ctrls.count = mpeg_ctrls.size();
- ctrls.controls = &mpeg_ctrls[0];
- doioctl(fd, VIDIOC_G_EXT_CTRLS, &ctrls, "VIDIOC_G_EXT_CTRLS");
- for (unsigned i = 0; i < mpeg_ctrls.size(); i++) {
- struct v4l2_ext_control ctrl = mpeg_ctrls[i];
-
- printf("%s: %d\n", ctrl_id2str[ctrl.id].c_str(), ctrl.value);
+ for (class2ctrls_map::iterator iter = class2ctrls.begin();
+ iter != class2ctrls.end(); ++iter) {
+ if (iter->first == V4L2_CTRL_CLASS_USER) {
+ for (unsigned i = 0; i < iter->second.size(); i++) {
+ struct v4l2_control ctrl;
+
+ ctrl.id = iter->second[i].id;
+ doioctl(fd, VIDIOC_G_CTRL, &ctrl, "VIDIOC_G_CTRL");
+ printf("%s: %d\n", ctrl_id2str[ctrl.id].c_str(), ctrl.value);
+ }
+ continue;
+ }
+ if (iter->second.size()) {
+ ctrls.ctrl_class = iter->first;
+ ctrls.count = iter->second.size();
+ ctrls.controls = &iter->second[0];
+ doioctl(fd, VIDIOC_G_EXT_CTRLS, &ctrls, "VIDIOC_G_EXT_CTRLS");
+ for (unsigned i = 0; i < iter->second.size(); i++) {
+ struct v4l2_ext_control ctrl = iter->second[i];
+
+ if (ctrl_str2q[ctrl_id2str[ctrl.id]].type == V4L2_CTRL_TYPE_STRING)
+ printf("%s: '%s'\n", ctrl_id2str[ctrl.id].c_str(),
+ safename(ctrl.string).c_str());
+ else
+ printf("%s: %d\n", ctrl_id2str[ctrl.id].c_str(), ctrl.value);
+ }
}
}
}
if (options[OptGetTuner]) {
struct v4l2_tuner vt;
+
memset(&vt, 0, sizeof(struct v4l2_tuner));
if (doioctl(fd, VIDIOC_G_TUNER, &vt, "VIDIOC_G_TUNER") == 0) {
printf("Tuner:\n");
@@ -2421,6 +2864,25 @@ set_vid_fmt_error:
}
}
+ if (options[OptGetModulator]) {
+ struct v4l2_modulator mt;
+
+ memset(&mt, 0, sizeof(struct v4l2_modulator));
+ if (doioctl(fd, VIDIOC_G_MODULATOR, &mt, "VIDIOC_G_MODULATOR") == 0) {
+ printf("Modulator:\n");
+ printf("\tName : %s\n", mt.name);
+ printf("\tCapabilities : %s\n", tcap2s(mt.capability).c_str());
+ if (mt.capability & V4L2_TUNER_CAP_LOW)
+ printf("\tFrequency range : %.1f MHz - %.1f MHz\n",
+ mt.rangelow / 16000.0, mt.rangehigh / 16000.0);
+ else
+ printf("\tFrequency range : %.1f MHz - %.1f MHz\n",
+ mt.rangelow / 16.0, mt.rangehigh / 16.0);
+ printf("\tSubchannel modulation: %s\n",
+ txsubchans2s(mt.txsubchans).c_str());
+ }
+ }
+
if (options[OptLogStatus]) {
static char buf[40960];
int len;
@@ -2546,6 +3008,35 @@ set_vid_fmt_error:
print_video_formats(fd, V4L2_BUF_TYPE_VIDEO_OVERLAY);
}
+ if (options[OptListFormatsExt]) {
+ printf("ioctl: VIDIOC_ENUM_FMT\n");
+ print_video_formats_ext(fd, V4L2_BUF_TYPE_VIDEO_CAPTURE);
+ print_video_formats(fd, V4L2_BUF_TYPE_VIDEO_OUTPUT);
+ print_video_formats(fd, V4L2_BUF_TYPE_VIDEO_OVERLAY);
+ }
+
+ if (options[OptListFrameSizes]) {
+ printf("ioctl: VIDIOC_ENUM_FRAMESIZES\n");
+ if (frmsize.pixel_format < 256)
+ frmsize.pixel_format = find_pixel_format(fd, frmsize.pixel_format);
+ frmsize.index = 0;
+ while (ioctl(fd, VIDIOC_ENUM_FRAMESIZES, &frmsize) >= 0) {
+ print_frmsize(frmsize, "");
+ frmsize.index++;
+ }
+ }
+
+ if (options[OptListFrameIntervals]) {
+ printf("ioctl: VIDIOC_ENUM_FRAMEINTERVALS\n");
+ if (frmival.pixel_format < 256)
+ frmival.pixel_format = find_pixel_format(fd, frmival.pixel_format);
+ frmival.index = 0;
+ while (ioctl(fd, VIDIOC_ENUM_FRAMEINTERVALS, &frmival) >= 0) {
+ print_frmival(frmival, "");
+ frmival.index++;
+ }
+ }
+
if (options[OptGetSlicedVbiCap]) {
struct v4l2_sliced_vbi_cap cap;
diff --git a/v4l2-apps/util/v4l2-dbg-micron.h b/v4l2-apps/util/v4l2-dbg-micron.h
new file mode 100644
index 000000000..8466322bf
--- /dev/null
+++ b/v4l2-apps/util/v4l2-dbg-micron.h
@@ -0,0 +1,46 @@
+/*
+ Copyright (C) 2009 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 "v4l2-dbg.h"
+
+#define MT9V011_IDENT "mt9v011"
+
+/* Register name prefix */
+#define MT9V011_PREFIX "MT9V011_"
+
+static struct board_regs mt9v011_regs[] = {
+ {0x00, MT9V011_PREFIX "CHIP_VERSION"},
+ {0x01, MT9V011_PREFIX "ROWSTART"},
+ {0x02, MT9V011_PREFIX "COLSTART"},
+ {0x03, MT9V011_PREFIX "HEIGHT"},
+ {0x04, MT9V011_PREFIX "WIDTH"},
+ {0x05, MT9V011_PREFIX "HBLANK"},
+ {0x06, MT9V011_PREFIX "VBLANK"},
+ {0x07, MT9V011_PREFIX "OUT_CTRL"},
+ {0x09, MT9V011_PREFIX "SHUTTER_WIDTH"},
+ {0x0a, MT9V011_PREFIX "CLK_SPEED"},
+ {0x0b, MT9V011_PREFIX "RESTART"},
+ {0x0c, MT9V011_PREFIX "SHUTTER_DELAY"},
+ {0x0d, MT9V011_PREFIX "RESET"},
+ {0x1e, MT9V011_PREFIX "DIGITAL_ZOOM"},
+ {0x20, MT9V011_PREFIX "READ_MODE"},
+ {0x2b, MT9V011_PREFIX "GREEN_1_GAIN"},
+ {0x2c, MT9V011_PREFIX "BLUE_GAIN"},
+ {0x2d, MT9V011_PREFIX "RED_GAIN"},
+ {0x2e, MT9V011_PREFIX "GREEN_2_GAIN"},
+ {0x35, MT9V011_PREFIX "GLOBAL_GAIN"},
+ {0xf1, MT9V011_PREFIX "CHIP_ENABLE"},
+};
diff --git a/v4l2-apps/util/v4l2-dbg.cpp b/v4l2-apps/util/v4l2-dbg.cpp
index f427d4442..1a481c04c 100644
--- a/v4l2-apps/util/v4l2-dbg.cpp
+++ b/v4l2-apps/util/v4l2-dbg.cpp
@@ -47,6 +47,7 @@
#include "v4l2-dbg-em28xx.h"
#include "v4l2-dbg-ac97.h"
#include "v4l2-dbg-tvp5150.h"
+#include "v4l2-dbg-micron.h"
#define ARRAY_SIZE(arr) ((int)(sizeof(arr) / sizeof((arr)[0])))
@@ -61,7 +62,7 @@ struct board_list {
static const struct board_list boards[] = {
#define AC97_BOARD 0
- { /* From ac97-dbg.h */
+ { /* From v4l2-dbg-ac97.h */
AC97_IDENT,
sizeof(AC97_PREFIX) - 1,
ac97_regs,
@@ -69,7 +70,7 @@ static const struct board_list boards[] = {
NULL,
0,
},
- { /* From bttv-dbg.h */
+ { /* From v4l2-dbg-bttv.h */
BTTV_IDENT,
sizeof(BTTV_PREFIX) - 1,
bt8xx_regs,
@@ -77,7 +78,7 @@ static const struct board_list boards[] = {
bt8xx_regs_other,
ARRAY_SIZE(bt8xx_regs_other),
},
- { /* From saa7134-dbg.h */
+ { /* From v4l2-dbg-saa7134.h */
SAA7134_IDENT,
sizeof(SAA7134_PREFIX) - 1,
saa7134_regs,
@@ -85,7 +86,7 @@ static const struct board_list boards[] = {
NULL,
0,
},
- { /* From em28xx-dbg.h */
+ { /* From v4l2-dbg-em28xx.h */
EM28XX_IDENT,
sizeof(EM28XX_PREFIX) - 1,
em28xx_regs,
@@ -93,7 +94,7 @@ static const struct board_list boards[] = {
em28xx_alt_regs,
ARRAY_SIZE(em28xx_alt_regs),
},
- { /* From tvp5150-dbg.h */
+ { /* From v4l2-dbg-tvp5150.h */
TVP5150_IDENT,
sizeof(TVP5150_PREFIX) - 1,
tvp5150_regs,
@@ -101,6 +102,14 @@ static const struct board_list boards[] = {
NULL,
0,
},
+ { /* From v4l2-dbg-micron.h */
+ MT9V011_IDENT,
+ sizeof(MT9V011_PREFIX) - 1,
+ mt9v011_regs,
+ ARRAY_SIZE(mt9v011_regs),
+ NULL,
+ 0,
+ },
};
struct chipid {
@@ -713,6 +722,9 @@ int main(int argc, char **argv)
case V4L2_IDENT_CX23418:
name = "cx23418";
break;
+ case V4L2_IDENT_CAFE:
+ name = "cafe";
+ break;
default:
if (get_reg.match.type == V4L2_CHIP_MATCH_I2C_DRIVER)
name = get_reg.match.name;
@@ -726,6 +738,8 @@ int main(int argc, char **argv)
print_regs(fd, &get_reg, 0, 0xff, stride);
} else if (name == "saa7127") {
print_regs(fd, &get_reg, 0, 0x7f, stride);
+ } else if (name == "ov7670") {
+ print_regs(fd, &get_reg, 0, 0x89, stride);
} else if (name == "cx25840") {
print_regs(fd, &get_reg, 0, 2, stride);
print_regs(fd, &get_reg, 0x100, 0x15f, stride);
@@ -738,6 +752,11 @@ int main(int argc, char **argv)
print_regs(fd, &get_reg, 0x02000000, 0x020000ff, stride);
} else if (name == "cx23418") {
print_regs(fd, &get_reg, 0x02c40000, 0x02c409c7, stride);
+ } else if (name == "cafe") {
+ print_regs(fd, &get_reg, 0, 0x43, stride);
+ print_regs(fd, &get_reg, 0x88, 0x8f, stride);
+ print_regs(fd, &get_reg, 0xb4, 0xbb, stride);
+ print_regs(fd, &get_reg, 0x3000, 0x300c, stride);
} else {
/* unknown chip, dump 0-0xff by default */
print_regs(fd, &get_reg, 0, 0xff, stride);
diff --git a/v4l2-apps/util/v4l2-sysfs-path.c b/v4l2-apps/util/v4l2-sysfs-path.c
index e3f3e63e8..4f0817017 100644
--- a/v4l2-apps/util/v4l2-sysfs-path.c
+++ b/v4l2-apps/util/v4l2-sysfs-path.c
@@ -23,6 +23,7 @@
#include <stdio.h>
#include <string.h>
#include <dirent.h>
+#include <sys/stat.h>
#define USB_ID "usb-"
#define PCI_ID "PCI:"
@@ -135,6 +136,131 @@ err:
return NULL;
}
+char *seek_name(char *path, char *match)
+{
+ DIR *dir;
+ struct dirent *entry;
+ struct stat st;
+ char *p;
+ static char name[1024];
+ int major, minor;
+
+ dir = opendir(path);
+ if (!dir)
+ return NULL;
+
+ strcpy(name, path);
+ strcat(name, "/");
+ p = name + strlen(name);
+
+ entry = readdir(dir);
+ while (entry) {
+ if (!strncmp(entry->d_name, match, strlen(match))) {
+
+ strcpy(name, entry->d_name);
+ closedir(dir);
+ return name;
+ }
+ entry = readdir(dir);
+ }
+ closedir(dir);
+ return NULL;
+}
+
+int get_dev(char *class, int *major, int *minor, char *extra)
+{
+ char path[1024];
+ char *name;
+ FILE *fp;
+
+ name = strchr(class,':');
+ if (!name)
+ return -1;
+ *name = 0;
+ name++;
+
+ *extra = 0;
+
+ if (!strcmp(class, "input")) {
+ char *event;
+
+ sprintf(path, "/sys/class/%s/%s/", class, name);
+ event = seek_name(path, "event");
+ if (!event)
+ return -1;
+
+ strcpy(extra, event);
+
+ sprintf(path, "/sys/class/%s/%s/%s/dev", class, name, event);
+
+ } else
+ sprintf(path, "/sys/class/%s/%s/dev", class, name);
+
+ fp = fopen(path, "r");
+ if (!fp)
+ return -1;
+
+ fscanf(fp, "%d:%d", major, minor);
+
+ return 0;
+}
+
+/*
+ Examples of subdevs:
+ sound:audio1
+ sound:controlC1
+ sound:dsp1
+ sound:mixer1
+ sound:pcmC1D0c
+ dvb:dvb0.demux0
+ dvb:dvb0.dvr0
+ dvb:dvb0.frontend0
+ dvb:dvb0.net0
+ i2c-adapter:i2c-4
+ input:input8
+*/
+
+void get_subdevs(char *path)
+{
+ DIR *dir;
+ struct dirent *entry;
+ struct stat st;
+ char *p, name[1024], extra[20];
+ int major, minor;
+
+ dir = opendir(path);
+ if (!dir)
+ return;
+
+ strcpy(name, path);
+ strcat(name, "/");
+ p = name + strlen(name);
+
+ printf("Associated devices:\n");
+ entry = readdir(dir);
+ while (entry) {
+ strcpy(p, entry->d_name);
+ if ((lstat(name, &st) == 0) &&
+ !S_ISDIR(st.st_mode)) {
+ char *s = strchr(entry->d_name, ':');
+ if (s) {
+ printf("\t%s", entry->d_name);
+ if (!get_dev(entry->d_name, &major, &minor, extra)) {
+ if (*extra)
+ printf(":%s (dev %d,%d)",
+ extra, major, minor);
+ else
+ printf(" (dev %d,%d)",
+ major, minor);
+ }
+ printf("\n");
+ }
+ }
+ entry = readdir(dir);
+ }
+ closedir(dir);
+}
+
void get_sysfs(char *fname)
{
struct v4l2_driver drv;
@@ -148,9 +274,11 @@ void get_sysfs(char *fname)
printf("bus info = %s\n", drv.cap.bus_info);
path = obtain_bus_sysfs_path((char *)drv.cap.bus_info);
if (path) {
- printf("sysfs path = %s\n\n", path);
+ printf("sysfs path = %s\n", path);
+ get_subdevs(path);
free(path);
}
+ printf("\n");
v4l2_close(&drv);
}
diff --git a/v4l2-apps/util/xc3028-firmware/firmware-tool.c b/v4l2-apps/util/xc3028-firmware/firmware-tool.c
index de1262ceb..43b78df7e 100644
--- a/v4l2-apps/util/xc3028-firmware/firmware-tool.c
+++ b/v4l2-apps/util/xc3028-firmware/firmware-tool.c
@@ -33,8 +33,8 @@
#include <asm/byteorder.h>
#include <asm/types.h>
-#include "../../../linux/drivers/media/video/tuner-xc2028-types.h"
-#include "../../../linux/include/linux/videodev2.h"
+#include "../../../linux/drivers/media/common/tuners/tuner-xc2028-types.h"
+#include "linux/videodev2.h"
#include "extract_head.h"
#include "standards.h"