summaryrefslogtreecommitdiff
path: root/v4l2-apps/util/v4l2-ctl.cpp
diff options
context:
space:
mode:
authorMauro Carvalho Chehab <mchehab@infradead.org>2006-08-25 11:45:51 -0300
committerMauro Carvalho Chehab <mchehab@infradead.org>2006-08-25 11:45:51 -0300
commit7d302bb17d4ebe98e2e0cbe76beb2a72b3292843 (patch)
treedb5d13ef3544100adea173bc9c6f778be7348472 /v4l2-apps/util/v4l2-ctl.cpp
parent46d06fbe2e7e63f51fd16e60ba0371ec1a90953a (diff)
parent1630db850f1bcab986ce1870cd42243c596a2574 (diff)
downloadmediapointer-dvb-s2-7d302bb17d4ebe98e2e0cbe76beb2a72b3292843.tar.gz
mediapointer-dvb-s2-7d302bb17d4ebe98e2e0cbe76beb2a72b3292843.tar.bz2
merge: http://linuxtv.org/hg/~hverkuil/v4l2-apps
From: Mauro Carvalho Chehab <mchehab@infradead.org> Signed-off-by: Mauro Carvalho Chehab <mchehab@infradead.org>
Diffstat (limited to 'v4l2-apps/util/v4l2-ctl.cpp')
-rw-r--r--v4l2-apps/util/v4l2-ctl.cpp1731
1 files changed, 1731 insertions, 0 deletions
diff --git a/v4l2-apps/util/v4l2-ctl.cpp b/v4l2-apps/util/v4l2-ctl.cpp
new file mode 100644
index 000000000..bb7b4bd81
--- /dev/null
+++ b/v4l2-apps/util/v4l2-ctl.cpp
@@ -0,0 +1,1731 @@
+/*
+ Copyright (C) 2003-2004 Kevin Thayer <nufan_wfk at yahoo dot com>
+
+ Cleanup and VBI and audio in/out options:
+ Copyright (C) 2004 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 {
+ OptGetAudioInput = 'A',
+ OptSetAudioInput = 'a',
+ OptGetAudioOutput = 'B',
+ OptSetAudioOutput = 'b',
+ OptGetCtrl = 'C',
+ OptSetCtrl = 'c',
+ OptSetDevice = 'd',
+ OptGetDriverInfo = 'D',
+ OptGetFreq = 'F',
+ OptSetFreq = 'f',
+ OptHelp = 'h',
+ OptGetInput = 'I',
+ OptSetInput = 'i',
+ OptListCtrls = 'l',
+ OptListCtrlsMenus = 'L',
+ OptListOutputs = 'N',
+ OptListInputs = 'n',
+ OptGetOutput = 'O',
+ OptSetOutput = 'o',
+ OptListAudioOutputs = 'Q',
+ OptListAudioInputs = 'q',
+ OptGetStandard = 'S',
+ OptSetStandard = 's',
+ OptGetTuner = 'T',
+ OptSetTuner = 't',
+ OptGetVideoFormat = 'V',
+ OptSetVideoFormat = 'v',
+
+ OptGetSlicedVbiFormat = 128,
+ OptSetSlicedVbiFormat,
+ OptGetSlicedVbiOutFormat,
+ OptSetSlicedVbiOutFormat,
+ OptGetOverlayFormat,
+ //OptSetOverlayFormat, TODO
+ OptGetVbiFormat,
+ //OptSetVbiFormat, TODO
+ OptGetVbiOutFormat,
+ //OptSetVbiOutFormat, TODO
+ OptAll,
+ OptStreamOff,
+ OptStreamOn,
+ OptListStandards,
+ OptLogStatus,
+ OptVerbose,
+ OptGetVideoOutFormat,
+ OptSetVideoOutFormat,
+ OptGetSlicedVbiCap,
+ OptGetSlicedVbiOutCap,
+ OptLast = 256
+};
+
+static char options[OptLast];
+
+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)
+
+static struct option long_options[] = {
+ {"list-audio-inputs", no_argument, 0, OptListAudioInputs},
+ {"list-audio-outputs", no_argument, 0, OptListAudioOutputs},
+ {"all", no_argument, 0, OptAll},
+ {"device", required_argument, 0, OptSetDevice},
+ {"get-fmt-video", no_argument, 0, OptGetVideoFormat},
+ {"set-fmt-video", required_argument, 0, OptSetVideoFormat},
+ {"get-fmt-video-out", no_argument, 0, OptGetVideoOutFormat},
+ {"set-fmt-video-out", required_argument, 0, OptSetVideoOutFormat},
+ {"help", no_argument, 0, OptHelp},
+ {"get-output", no_argument, 0, OptGetOutput},
+ {"set-output", required_argument, 0, OptSetOutput},
+ {"list-outputs", no_argument, 0, OptListOutputs},
+ {"list-inputs", no_argument, 0, OptListInputs},
+ {"get-input", no_argument, 0, OptGetInput},
+ {"set-input", required_argument, 0, OptSetInput},
+ {"get-audio-input", no_argument, 0, OptGetAudioInput},
+ {"set-audio-input", required_argument, 0, OptSetAudioInput},
+ {"get-audio-output", no_argument, 0, OptGetAudioOutput},
+ {"set-audio-output", required_argument, 0, OptSetAudioOutput},
+ {"get-freq", no_argument, 0, OptGetFreq},
+ {"set-freq", required_argument, 0, OptSetFreq},
+ {"streamoff", no_argument, 0, OptStreamOff},
+ {"streamon", no_argument, 0, OptStreamOn},
+ {"list-standards", no_argument, 0, OptListStandards},
+ {"get-standard", no_argument, 0, OptGetStandard},
+ {"set-standard", required_argument, 0, OptSetStandard},
+ {"info", no_argument, 0, OptGetDriverInfo},
+ {"list-ctrls", no_argument, 0, OptListCtrls},
+ {"list-ctrls-menus", no_argument, 0, OptListCtrlsMenus},
+ {"set-ctrl", required_argument, 0, OptSetCtrl},
+ {"get-ctrl", required_argument, 0, OptGetCtrl},
+ {"get-tuner", no_argument, 0, OptGetTuner},
+ {"set-tuner", required_argument, 0, OptSetTuner},
+ {"verbose", no_argument, 0, OptVerbose},
+ {"log-status", no_argument, 0, OptLogStatus},
+ {"get-fmt-overlay", no_argument, 0, OptGetOverlayFormat},
+ {"get-fmt-sliced-vbi", no_argument, 0, OptGetSlicedVbiFormat},
+ {"set-fmt-sliced-vbi", required_argument, 0, OptSetSlicedVbiFormat},
+ {"get-fmt-sliced-vbi-out", no_argument, 0, OptGetSlicedVbiOutFormat},
+ {"set-fmt-sliced-vbi-out", required_argument, 0, OptSetSlicedVbiOutFormat},
+ {"get-fmt-vbi", no_argument, 0, OptGetVbiFormat},
+ {"get-fmt-vbi-out", no_argument, 0, OptGetVbiOutFormat},
+ {"get-sliced-vbi-cap", no_argument, 0, OptGetSlicedVbiCap},
+ {"get-sliced-vbi-out-cap", no_argument, 0, OptGetSlicedVbiOutCap},
+ {0, 0, 0, 0}
+};
+
+static void usage(void)
+{
+ printf("Usage:\n");
+ printf(" --all display all information available\n");
+ printf(" -A, --get-audio-input\n");
+ printf(" query the audio input [VIDIOC_G_AUDIO]\n");
+ printf(" -a, --set-audio-input=<num>\n");
+ printf(" set the audio input to <num> [VIDIOC_S_AUDIO]\n");
+ printf(" -B, --get-audio-output\n");
+ printf(" query the audio output [VIDIOC_G_AUDOUT]\n");
+ printf(" -b, --set-audio-output=<num>\n");
+ printf(" set the audio output to <num> [VIDIOC_S_AUDOUT]\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(" -Q, --list-audio-outputs\n");
+ printf(" display audio outputs [VIDIOC_ENUMAUDOUT]\n");
+ printf(" -q, --list-audio-inputs\n");
+ printf(" display audio inputs [VIDIOC_ENUMAUDIO]\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) 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: 0 (mono), 1 (stereo), 2 (lang2), 3 (lang1), 4 (both)\n");
+ printf(" -V, --get-fmt-video\n");
+ printf(" query the video capture format [VIDIOC_G_FMT]\n");
+ printf(" -v, --set-fmt-video=width=<x>,height=<y>\n");
+ printf(" set the video capture format [VIDIOC_S_FMT]\n");
+ printf(" --get-fmt-video-out\n");
+ printf(" query the video output format [VIDIOC_G_FMT]\n");
+ printf(" --set-fmt-video-out=width=<x>,height=<y>\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-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\n");
+ printf(" query the sliced VBI capture format [VIDIOC_G_FMT]\n");
+ printf(" --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(" --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(" --verbose turn on verbose ioctl error reporting.\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");
+ 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_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";
+ 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(vfmt.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", queryctrl->name, 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) {
+ 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)
+ ctrl_str2id[name2var(qctrl.name)] = qctrl.id;
+ }
+ for (qctrl.id = V4L2_CID_PRIVATE_BASE;
+ ioctl(fd, VIDIOC_QUERYCTRL, &qctrl) == 0; qctrl.id++) {
+ ctrl_str2id[name2var(qctrl.name)] = qctrl.id;
+ }
+}
+
+static int printfmt(struct v4l2_format vfmt)
+{
+ const flag_def vbi_def[] = {
+ { V4L2_VBI_UNSYNC, "unsynchronized" },
+ { V4L2_VBI_INTERLACED, "interlaced" },
+ { 0, NULL }
+ };
+ printf("Format:\n");
+
+ switch (vfmt.type) {
+ case V4L2_BUF_TYPE_VIDEO_CAPTURE:
+ case V4L2_BUF_TYPE_VIDEO_OUTPUT:
+ printf("\tType : %s\n", buftype2s(vfmt.type).c_str());
+ 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_OVERLAY:
+ printf("\tType : %s\n", buftype2s(vfmt.type).c_str());
+ 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());
+ // TODO: check G_FBUF capabilities
+ printf("\tChroma Key : %08x\n", vfmt.fmt.win.chromakey);
+ printf("\tClip Count : %u\n", vfmt.fmt.win.clipcount);
+ break;
+ case V4L2_BUF_TYPE_VBI_CAPTURE:
+ case V4L2_BUF_TYPE_VBI_OUTPUT:
+ printf("\tType : %s\n", buftype2s(vfmt.type).c_str());
+ 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("\tType : %s\n", buftype2s(vfmt.type).c_str());
+ 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:
+ printf("\tType: %s\n", buftype2s(vfmt.type).c_str());
+ break;
+ default:
+ printf("\tType: %s\n", buftype2s(vfmt.type).c_str());
+ return -1;
+ }
+ return 0;
+}
+
+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_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 '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;
+
+ if (!options[OptVerbose]) return ioctl(fd, request, parm);
+ retVal = ioctl(fd, request, parm);
+ printf("%s: ", name);
+ if (retVal < 0)
+ printf("failed: %s\n", strerror(errno));
+ else
+ printf("ok\n");
+
+ 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");
+}
+
+int main(int argc, char **argv)
+{
+ char *value, *subs;
+ int i;
+
+ int fd = -1;
+
+ /* bitfield for fmts */
+ unsigned int set_fmts = 0;
+ unsigned int set_fmts_out = 0;
+
+ int mode = V4L2_TUNER_MODE_STEREO; /* set audio mode */
+
+ /* command args */
+ int ch;
+ char *device = strdup("/dev/video0"); /* -d device */
+ struct v4l2_format vfmt; /* set_format/get_format for video */
+ struct v4l2_format vfmt_out; /* set_format/get_format video output */
+ struct v4l2_format vbi_fmt; /* set_format/get_format for sliced VBI */
+ 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_tuner tuner; /* set_tuner/get_tuner */
+ 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 */
+ int input; /* set_input/get_input */
+ int output; /* set_output/get_output */
+ v4l2_std_id std; /* get_std/set_std */
+ double freq = 0; /* get/set frequency */
+ struct v4l2_frequency vf; /* get_freq/set_freq */
+ struct v4l2_standard vs; /* list_std */
+ char short_options[26 * 2 * 2 + 1];
+ int idx = 0;
+
+ 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(&raw_fmt_out, 0, sizeof(raw_fmt_out));
+ memset(&tuner, 0, sizeof(tuner));
+ 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(&vf, 0, sizeof(vf));
+ memset(&vs, 0, sizeof(vs));
+
+ if (argc == 1) {
+ usage();
+ return 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 OptSetDevice:
+ device = strdup(optarg);
+ if (device[0] >= '0' && device[0] <= '9' && device[1] == 0) {
+ char dev = device[0];
+
+ sprintf(device, "/dev/video%c", dev);
+ }
+ break;
+ case OptSetVideoFormat:
+ subs = optarg;
+ while (*subs != '\0') {
+ static char *const subopts[] = {
+ "width",
+ "height",
+ NULL
+ };
+
+ switch (parse_subopt(&subs, subopts, &value)) {
+ case 0:
+ vfmt.fmt.pix.width = strtol(value, 0L, 0);
+ set_fmts |= FMTWidth;
+ break;
+ case 1:
+ vfmt.fmt.pix.height = strtol(value, 0L, 0);
+ set_fmts |= FMTHeight;
+ break;
+ }
+ }
+ break;
+ case OptSetVideoOutFormat:
+ subs = optarg;
+ while (*subs != '\0') {
+ static char *const subopts[] = {
+ "width",
+ "height",
+ NULL
+ };
+
+ switch (parse_subopt(&subs, subopts, &value)) {
+ case 0:
+ vfmt_out.fmt.pix.width = strtol(value, 0L, 0);
+ set_fmts_out |= FMTWidth;
+ break;
+ case 1:
+ vfmt_out.fmt.pix.height = strtol(value, 0L, 0);
+ set_fmts_out |= FMTHeight;
+ break;
+ }
+ }
+ break;
+ case OptSetInput:
+ input = strtol(optarg, 0L, 0);
+ break;
+ case OptSetOutput:
+ output = strtol(optarg, 0L, 0);
+ break;
+ case OptSetAudioInput:
+ vaudio.index = strtol(optarg, 0L, 0);
+ break;
+ case OptSetAudioOutput:
+ vaudout.index = strtol(optarg, 0L, 0);
+ break;
+ case OptSetFreq:
+ freq = strtod(optarg, NULL);
+ break;
+ case OptSetStandard:
+ if (!strncmp(optarg, "pal", 3)) {
+ if (optarg[3])
+ std = parse_pal(optarg + 3);
+ else
+ std = V4L2_STD_PAL;
+ }
+ else if (!strncmp(optarg, "ntsc", 4)) {
+ if (optarg[4])
+ std = parse_ntsc(optarg + 4);
+ else
+ std = V4L2_STD_NTSC;
+ }
+ else if (!strncmp(optarg, "secam", 5)) {
+ if (optarg[5])
+ std = parse_secam(optarg + 5);
+ else
+ std = V4L2_STD_SECAM;
+ }
+ else {
+ std = strtol(optarg, 0L, 0);
+ }
+ break;
+ case OptGetCtrl:
+ subs = optarg;
+ while (*subs != '\0') {
+ parse_next_subopt(&subs, &value);
+ if (strchr(value, '=')) {
+ usage();
+ exit(1);
+ }
+ else {
+ get_ctrls.push_back(value);
+ }
+ }
+ break;
+ case OptSetCtrl:
+ subs = optarg;
+ while (*subs != '\0') {
+ parse_next_subopt(&subs, &value);
+ if (const char *equal = strchr(value, '=')) {
+ set_ctrls[std::string(value, (equal - value))] = equal + 1;
+ }
+ else {
+ fprintf(stderr, "control '%s' without '='\n", value);
+ exit(1);
+ }
+ }
+ break;
+ case OptSetTuner:
+ if (!strcmp(optarg, "stereo"))
+ mode = V4L2_TUNER_MODE_STEREO;
+ else if (!strcmp(optarg, "lang1"))
+ mode = V4L2_TUNER_MODE_LANG1;
+ else if (!strcmp(optarg, "lang2"))
+ mode = V4L2_TUNER_MODE_LANG2;
+ else if (!strcmp(optarg, "bilingual"))
+ mode = V4L2_TUNER_MODE_LANG1_LANG2;
+ else if (!strcmp(optarg, "mono"))
+ mode = V4L2_TUNER_MODE_MONO;
+ else {
+ fprintf(stderr, "Unknown audio mode\n");
+ usage();
+ return 1;
+ }
+ break;
+ case OptSetSlicedVbiFormat:
+ case OptSetSlicedVbiOutFormat:
+ {
+ bool foundOff = false;
+ v4l2_format *fmt = &vbi_fmt;
+
+ if (ch == OptSetSlicedVbiOutFormat)
+ fmt = &vbi_fmt_out;
+ fmt->fmt.sliced.service_set = 0;
+ subs = optarg;
+ while (*subs != '\0') {
+ static char *const subopts[] = {
+ "off",
+ "teletext",
+ "cc",
+ "wss",
+ "vps",
+ NULL
+ };
+
+ switch (parse_subopt(&subs, subopts, &value)) {
+ case 0:
+ foundOff = true;
+ break;
+ case 1:
+ fmt->fmt.sliced.service_set |=
+ V4L2_SLICED_TELETEXT_B;
+ break;
+ case 2:
+ fmt->fmt.sliced.service_set |=
+ V4L2_SLICED_CAPTION_525;
+ break;
+ case 3:
+ fmt->fmt.sliced.service_set |=
+ V4L2_SLICED_WSS_625;
+ break;
+ case 4:
+ fmt->fmt.sliced.service_set |=
+ V4L2_SLICED_VPS;
+ break;
+ }
+ }
+ if (foundOff && fmt->fmt.sliced.service_set) {
+ fprintf(stderr, "Sliced VBI mode 'off' cannot be combined with other modes\n");
+ usage();
+ return 1;
+ }
+ 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;
+ }
+
+ if ((fd = open(device, O_RDWR)) < 0) {
+ fprintf(stderr, "Failed to open %s: %s\n", device,
+ strerror(errno));
+ exit(1);
+ }
+ free(device);
+
+ doioctl(fd, VIDIOC_QUERYCAP, &vcap, "VIDIOC_QUERYCAP");
+ 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);
+ }
+ }
+
+ if (options[OptAll]) {
+ options[OptGetVideoFormat] = 1;
+ options[OptGetVideoOutFormat] = 1;
+ options[OptGetDriverInfo] = 1;
+ options[OptGetInput] = 1;
+ options[OptGetOutput] = 1;
+ options[OptGetAudioInput] = 1;
+ options[OptGetAudioOutput] = 1;
+ options[OptGetStandard] = 1;
+ options[OptGetFreq] = 1;
+ options[OptGetTuner] = 1;
+ options[OptGetOverlayFormat] = 1;
+ options[OptGetVbiFormat] = 1;
+ options[OptGetVbiOutFormat] = 1;
+ options[OptGetSlicedVbiFormat] = 1;
+ options[OptGetSlicedVbiOutFormat] = 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());
+ }
+
+ /* Set options */
+
+ if (options[OptStreamOff]) {
+ int dummy = 0;
+ doioctl(fd, VIDIOC_STREAMOFF, &dummy, "VIDIOC_STREAMOFF");
+ }
+
+ 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;
+ }
+ vf.tuner = 0;
+ vf.type = tuner.type;
+ vf.frequency = __u32(freq * fac);
+ if (doioctl(fd, VIDIOC_S_FREQUENCY, &vf,
+ "VIDIOC_S_FREQUENCY") == 0)
+ printf("Frequency set to %d (%f MHz)\n", vf.frequency,
+ vf.frequency / fac);
+ }
+
+ if (options[OptSetStandard]) {
+ if (std < 16) {
+ vs.index = std;
+ if (ioctl(fd, VIDIOC_ENUMSTD, &vs) >= 0) {
+ std = vs.id;
+ }
+ }
+ if (doioctl(fd, VIDIOC_S_STD, &std, "VIDIOC_S_STD") == 0)
+ printf("Standard set to %08llx\n", (unsigned long long)std);
+ }
+
+ if (options[OptSetInput]) {
+ if (doioctl(fd, VIDIOC_S_INPUT, &input, "VIDIOC_S_INPUT") == 0) {
+ printf("Video input set to %d", input);
+ vin.index = input;
+ if (ioctl(fd, VIDIOC_ENUMINPUT, &vin) >= 0)
+ printf(" (%s)", vin.name);
+ printf("\n");
+ }
+ }
+
+ if (options[OptSetOutput]) {
+ if (doioctl(fd, VIDIOC_S_OUTPUT, &output, "VIDIOC_S_OUTPUT") == 0)
+ printf("Output set to %d\n", output);
+ }
+
+ if (options[OptSetAudioInput]) {
+ if (doioctl(fd, VIDIOC_S_AUDIO, &vaudio, "VIDIOC_S_AUDIO") == 0)
+ printf("Audio input set to %d\n", vaudio.index);
+ }
+
+ if (options[OptSetAudioOutput]) {
+ if (doioctl(fd, VIDIOC_S_AUDOUT, &vaudout, "VIDIOC_S_AUDOUT") == 0)
+ printf("Audio output set to %d\n", vaudout.index);
+ }
+
+ if (options[OptSetTuner]) {
+ struct v4l2_tuner vt;
+
+ memset(&vt, 0, sizeof(struct v4l2_tuner));
+ if (ioctl(fd, VIDIOC_G_TUNER, &vt) < 0) {
+ fprintf(stderr, "ioctl: VIDIOC_G_TUNER failed\n");
+ exit(1);
+ }
+ vt.audmode = mode;
+ doioctl(fd, VIDIOC_S_TUNER, &vt, "VIDIOC_S_TUNER");
+ }
+
+ if (options[OptSetVideoFormat]) {
+ struct v4l2_format in_vfmt;
+ printf("ioctl: VIDIOC_S_FMT\n");
+ in_vfmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+ if (ioctl(fd, VIDIOC_G_FMT, &in_vfmt) < 0)
+ fprintf(stderr, "ioctl: VIDIOC_G_FMT failed\n");
+ else {
+ if (set_fmts & FMTWidth)
+ in_vfmt.fmt.pix.width = vfmt.fmt.pix.width;
+ if (set_fmts & FMTHeight)
+ in_vfmt.fmt.pix.height = vfmt.fmt.pix.height;
+ if (ioctl(fd, VIDIOC_S_FMT, &in_vfmt) < 0)
+ fprintf(stderr, "ioctl: VIDIOC_S_FMT failed\n");
+ vfmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+ if (ioctl(fd, VIDIOC_G_FMT, &vfmt) < 0)
+ fprintf(stderr, "ioctl: VIDIOC_G_FMT failed\n");
+ }
+ }
+
+ if (options[OptSetVideoOutFormat]) {
+ struct v4l2_format in_vfmt;
+ printf("ioctl: VIDIOC_S_FMT\n");
+ in_vfmt.type = V4L2_BUF_TYPE_VIDEO_OUTPUT;
+ if (ioctl(fd, VIDIOC_G_FMT, &in_vfmt) < 0)
+ fprintf(stderr, "ioctl: VIDIOC_G_FMT failed\n");
+ else {
+ if (set_fmts & FMTWidth)
+ in_vfmt.fmt.pix.width = vfmt.fmt.pix.width;
+ if (set_fmts & FMTHeight)
+ in_vfmt.fmt.pix.height = vfmt.fmt.pix.height;
+ if (ioctl(fd, VIDIOC_S_FMT, &in_vfmt) < 0)
+ fprintf(stderr, "ioctl: VIDIOC_S_FMT failed\n");
+ vfmt_out.type = V4L2_BUF_TYPE_VIDEO_OUTPUT;
+ if (ioctl(fd, VIDIOC_G_FMT, &vfmt_out) < 0)
+ fprintf(stderr, "ioctl: VIDIOC_G_FMT failed\n");
+ }
+ }
+
+ 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[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[OptSetCtrl] && !set_ctrls.empty()) {
+ struct v4l2_ext_controls ctrls = { 0 };
+
+ 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 = atol(iter->second.c_str());
+ 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));
+ }
+ }
+ 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));
+ }
+ else {
+ fprintf(stderr, "%s: %s\n",
+ ctrl_id2str[mpeg_ctrls[ctrls.error_idx].id].c_str(),
+ strerror(errno));
+ }
+ }
+ }
+ }
+
+ /* Get options */
+
+ if (options[OptGetVideoFormat]) {
+ vfmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+ if (doioctl(fd, VIDIOC_G_FMT, &vfmt, "VIDIOC_G_FMT") == 0)
+ if (printfmt(vfmt) != 0)
+ fprintf(stderr, "error printing result\n");
+ }
+
+ if (options[OptGetVideoOutFormat]) {
+ vfmt_out.type = V4L2_BUF_TYPE_VIDEO_OUTPUT;
+ if (doioctl(fd, VIDIOC_G_FMT, &vfmt_out, "VIDIOC_G_FMT") == 0)
+ if (printfmt(vfmt_out) != 0)
+ fprintf(stderr, "error printing result\n");
+ }
+
+ if (options[OptGetOverlayFormat]) {
+ struct v4l2_format fmt;
+ memset(&fmt, 0, sizeof(fmt));
+ fmt.type = V4L2_BUF_TYPE_VIDEO_OVERLAY;
+ if (doioctl(fd, VIDIOC_G_FMT, &fmt, "VIDIOC_G_FMT") == 0)
+ if (printfmt(fmt) != 0)
+ fprintf(stderr, "error printing result\n");
+ }
+
+ if (options[OptGetSlicedVbiFormat]) {
+ vbi_fmt.type = V4L2_BUF_TYPE_SLICED_VBI_CAPTURE;
+ if (doioctl(fd, VIDIOC_G_FMT, &vbi_fmt,
+ "VIDIOC_G_FMT") == 0)
+ if (printfmt(vbi_fmt) != 0)
+ fprintf(stderr,
+ "error printing result\n");
+ }
+
+ if (options[OptGetSlicedVbiOutFormat]) {
+ vbi_fmt_out.type = V4L2_BUF_TYPE_SLICED_VBI_OUTPUT;
+ if (doioctl(fd, VIDIOC_G_FMT, &vbi_fmt_out,
+ "VIDIOC_G_FMT") == 0)
+ if (printfmt(vbi_fmt_out) != 0)
+ fprintf(stderr,
+ "error printing result\n");
+ }
+
+ if (options[OptGetVbiFormat]) {
+ raw_fmt.type = V4L2_BUF_TYPE_VBI_CAPTURE;
+ if (doioctl(fd, VIDIOC_G_FMT, &raw_fmt,
+ "VIDIOC_G_FMT") == 0)
+ if (printfmt(raw_fmt) != 0)
+ fprintf(stderr,
+ "error printing result\n");
+ }
+
+ if (options[OptGetVbiOutFormat]) {
+ raw_fmt_out.type = V4L2_BUF_TYPE_VBI_OUTPUT;
+ if (doioctl(fd, VIDIOC_G_FMT, &raw_fmt_out,
+ "VIDIOC_G_FMT") == 0)
+ if (printfmt(raw_fmt_out) != 0)
+ fprintf(stderr,
+ "error printing result\n");
+ }
+
+ if (options[OptGetInput]) {
+ if (doioctl(fd, VIDIOC_G_INPUT, &input, "VIDIOC_G_INPUT") == 0) {
+ printf("Video input : %d", input);
+ vin.index = input;
+ if (ioctl(fd, VIDIOC_ENUMINPUT, &vin) >= 0)
+ printf(" (%s)", vin.name);
+ printf("\n");
+ }
+ }
+
+ if (options[OptGetOutput]) {
+ if (doioctl(fd, VIDIOC_G_OUTPUT, &output, "VIDIOC_G_OUTPUT") == 0) {
+ printf("Video output: %d", output);
+ vout.index = output;
+ if (ioctl(fd, VIDIOC_ENUMOUTPUT, &vout) >= 0) {
+ printf(" (%s)", vout.name);
+ }
+ printf("\n");
+ }
+ }
+
+ if (options[OptGetAudioInput]) {
+ if (doioctl(fd, VIDIOC_G_AUDIO, &vaudio, "VIDIOC_G_AUDIO") == 0)
+ printf("Audio input : %d (%s)\n", vaudio.index, vaudio.name);
+ }
+
+ if (options[OptGetAudioOutput]) {
+ if (doioctl(fd, VIDIOC_G_AUDOUT, &vaudout, "VIDIOC_G_AUDOUT") == 0)
+ printf("Audio output: %d (%s)\n", vaudout.index, vaudout.name);
+ }
+
+ if (options[OptGetFreq]) {
+ double fac = 16;
+
+ if (doioctl(fd, VIDIOC_G_TUNER, &tuner, "VIDIOC_G_TUNER") == 0) {
+ fac = (tuner.capability & V4L2_TUNER_CAP_LOW) ? 16000 : 16;
+ }
+ vf.tuner = 0;
+ if (doioctl(fd, VIDIOC_G_FREQUENCY, &vf, "VIDIOC_G_FREQUENCY") == 0)
+ printf("Frequency: %d (%f MHz)\n", vf.frequency,
+ vf.frequency / fac);
+ }
+
+ if (options[OptGetStandard]) {
+ if (doioctl(fd, VIDIOC_G_STD, &std, "VIDIOC_G_STD") == 0) {
+ static const char *pal[] = {
+ "B", "B1", "G", "H", "I", "D", "D1", "K",
+ "M", "N", "Nc", "60",
+ NULL
+ };
+ static const char *ntsc[] = {
+ "M", "M-JP", "443", "M-KR",
+ NULL
+ };
+ static const char *secam[] = {
+ "B", "D", "G", "H", "K", "K1", "L", "Lc",
+ NULL
+ };
+ static const char *atsc[] = {
+ "ATSC-8-VSB", "ATSC-16-VSB",
+ NULL
+ };
+
+ printf("Video standard = 0x%08llx\n", (unsigned long long)std);
+ if (std & 0xfff) {
+ print_std("PAL", pal, std);
+ }
+ if (std & 0xf000) {
+ print_std("NTSC", ntsc, std >> 12);
+ }
+ if (std & 0xff0000) {
+ print_std("SECAM", secam, std >> 16);
+ }
+ if (std & 0xf000000) {
+ print_std("ATSC/HDTV", atsc, std >> 24);
+ }
+ }
+ }
+
+ if (options[OptGetCtrl] && !get_ctrls.empty()) {
+ struct v4l2_ext_controls ctrls = { 0 };
+
+ 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);
+ }
+ 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);
+ }
+ }
+ }
+
+ 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");
+ printf("\tCapabilities : %s\n", tcap2s(vt.capability).c_str());
+ if (vt.capability & V4L2_TUNER_CAP_LOW)
+ printf("\tFrequency range : %.1f MHz - %.1f MHz\n",
+ vt.rangelow / 16000.0, vt.rangehigh / 16000.0);
+ 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("\tCurrent audio mode : %s\n", audmode2s(vt.audmode));
+ printf("\tAvailable subchannels: %s\n",
+ rxsubchans2s(vt.rxsubchans).c_str());
+ }
+ }
+
+ if (options[OptLogStatus]) {
+ static char buf[40960];
+ int len;
+
+ if (doioctl(fd, VIDIOC_LOG_STATUS, NULL, "VIDIOC_LOG_STATUS") == 0) {
+ printf("\nStatus Log:\n\n");
+ len = klogctl(3, buf, sizeof(buf) - 1);
+ if (len >= 0) {
+ char *p = buf;
+ char *q;
+
+ buf[len] = 0;
+ while ((q = strstr(p, "START STATUS CARD #"))) {
+ p = q + 1;
+ }
+ if (p) {
+ while (p > buf && *p != '<') p--;
+ q = p;
+ while ((q = strstr(q, "<6>"))) {
+ memcpy(q, " ", 3);
+ }
+ printf("%s", p);
+ }
+ }
+ }
+ }
+
+ /* List options */
+
+ if (options[OptListInputs]) {
+ vin.index = 0;
+ printf("ioctl: VIDIOC_ENUMINPUT\n");
+ while (ioctl(fd, VIDIOC_ENUMINPUT, &vin) >= 0) {
+ if (vin.index)
+ printf("\n");
+ printf("\tInput : %d\n", vin.index);
+ printf("\tName : %s\n", vin.name);
+ printf("\tType : 0x%08X\n", vin.type);
+ printf("\tAudioset: 0x%08X\n", vin.audioset);
+ printf("\tTuner : 0x%08X\n", vin.tuner);
+ printf("\tStandard: 0x%016llX ( ", (unsigned long long)vin.std);
+ if (vin.std & 0x000FFF)
+ printf("PAL "); // hack
+ if (vin.std & 0x00F000)
+ printf("NTSC "); // hack
+ if (vin.std & 0x7F0000)
+ printf("SECAM "); // hack
+ printf(")\n");
+ printf("\tStatus : %d\n", vin.status);
+ vin.index++;
+ }
+ }
+
+ if (options[OptListOutputs]) {
+ vout.index = 0;
+ printf("ioctl: VIDIOC_ENUMOUTPUT\n");
+ while (ioctl(fd, VIDIOC_ENUMOUTPUT, &vout) >= 0) {
+ if (vout.index)
+ printf("\n");
+ printf("\tOutput : %d\n", vout.index);
+ printf("\tName : %s\n", vout.name);
+ printf("\tType : 0x%08X\n", vout.type);
+ printf("\tAudioset: 0x%08X\n", vout.audioset);
+ printf("\tStandard: 0x%016llX ( ", (unsigned long long)vout.std);
+ if (vout.std & 0x000FFF)
+ printf("PAL "); // hack
+ if (vout.std & 0x00F000)
+ printf("NTSC "); // hack
+ if (vout.std & 0x7F0000)
+ printf("SECAM "); // hack
+ printf(")\n");
+ vout.index++;
+ }
+ }
+
+ if (options[OptListAudioInputs]) {
+ struct v4l2_audio vaudio; /* list audio inputs */
+ vaudio.index = 0;
+ printf("ioctl: VIDIOC_ENUMAUDIO\n");
+ while (ioctl(fd, VIDIOC_ENUMAUDIO, &vaudio) >= 0) {
+ if (vaudio.index)
+ printf("\n");
+ printf("\tInput : %d\n", vaudio.index);
+ printf("\tName : %s\n", vaudio.name);
+ vaudio.index++;
+ }
+ }
+
+ if (options[OptListAudioOutputs]) {
+ struct v4l2_audioout vaudio; /* list audio outputs */
+ vaudio.index = 0;
+ printf("ioctl: VIDIOC_ENUMAUDOUT\n");
+ while (ioctl(fd, VIDIOC_ENUMAUDOUT, &vaudio) >= 0) {
+ if (vaudio.index)
+ printf("\n");
+ printf("\tOutput : %d\n", vaudio.index);
+ printf("\tName : %s\n", vaudio.name);
+ vaudio.index++;
+ }
+ }
+
+ if (options[OptListStandards]) {
+ printf("ioctl: VIDIOC_ENUMSTD\n");
+ vs.index = 0;
+ while (ioctl(fd, VIDIOC_ENUMSTD, &vs) >= 0) {
+ if (vs.index)
+ printf("\n");
+ 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",
+ vs.frameperiod.numerator,
+ vs.frameperiod.denominator);
+ printf("\tFrame lines : %d\n", vs.framelines);
+ vs.index++;
+ }
+ }
+
+ if (options[OptGetSlicedVbiCap]) {
+ struct v4l2_sliced_vbi_cap cap;
+
+ if (doioctl(fd, VIDIOC_G_SLICED_VBI_CAP, &cap, "VIDIOC_G_SLICED_VBI_CAP") == 0) {
+ print_sliced_vbi_cap(cap);
+ }
+ }
+
+ if (options[OptGetSlicedVbiOutCap]) {
+ struct v4l2_sliced_vbi_cap cap;
+
+ if (doioctl(fd, VIDIOC_G_SLICED_VBI_CAP, &cap, "VIDIOC_G_SLICED_VBI_CAP") == 0) {
+ print_sliced_vbi_cap(cap);
+ }
+ }
+
+ if (options[OptListCtrlsMenus]) {
+ list_controls(fd, 1);
+ }
+
+ if (options[OptListCtrls]) {
+ list_controls(fd, 0);
+ }
+
+ if (options[OptStreamOn]) {
+ int dummy = 0;
+ doioctl(fd, VIDIOC_STREAMON, &dummy, "VIDIOC_STREAMON");
+ }
+
+ close(fd);
+ exit(0);
+}