summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--linux/Documentation/video4linux/cx2341x/fw-encoder-api.txt19
-rw-r--r--linux/drivers/media/video/cafe_ccic.c3
-rw-r--r--linux/drivers/media/video/v4l2-common.c4
-rw-r--r--linux/include/linux/dvb/version.h2
-rw-r--r--linux/include/linux/videodev2.h7
-rw-r--r--linux/include/media/cx2341x.h2
-rw-r--r--linux/include/media/v4l2-chip-ident.h4
-rw-r--r--v4l2-apps/util/Makefile2
-rw-r--r--v4l2-apps/util/v4l2-ctl.cpp248
-rw-r--r--v4l2-apps/util/v4l2-dbg.cpp516
10 files changed, 766 insertions, 41 deletions
diff --git a/linux/Documentation/video4linux/cx2341x/fw-encoder-api.txt b/linux/Documentation/video4linux/cx2341x/fw-encoder-api.txt
index 242104ce5..5dd3109a8 100644
--- a/linux/Documentation/video4linux/cx2341x/fw-encoder-api.txt
+++ b/linux/Documentation/video4linux/cx2341x/fw-encoder-api.txt
@@ -663,12 +663,13 @@ Param[0]
-------------------------------------------------------------------------------
-Name CX2341X_ENC_UNKNOWN
+Name CX2341X_ENC_SET_VERT_CROP_LINE
Enum 219/0xDB
Description
- Unknown API, it's used by Hauppauge though.
+ Something to do with 'Vertical Crop Line'
Param[0]
- 0 This is the value Hauppauge uses, Unknown what it means.
+ If saa7114 and raw VBI capture and 60 Hz, then set to 10001.
+ Else 0.
-------------------------------------------------------------------------------
@@ -682,11 +683,9 @@ Param[0]
Command number:
1=set initial SCR value when starting encoding (works).
2=set quality mode (apparently some test setting).
- 3=setup advanced VIM protection handling (supposedly only for the cx23416
- for raw YUV).
- Actually it looks like this should be 0 for saa7114/5 based card and 1
- for cx25840 based cards.
- 4=generate artificial PTS timestamps
+ 3=setup advanced VIM protection handling.
+ Always 1 for the cx23416 and 0 for cx23415.
+ 4=generate DVD compatible PTS timestamps
5=USB flush mode
6=something to do with the quantization matrix
7=set navigation pack insertion for DVD: adds 0xbf (private stream 2)
@@ -698,7 +697,9 @@ Param[0]
9=set history parameters of the video input module
10=set input field order of VIM
11=set quantization matrix
- 12=reset audio interface
+ 12=reset audio interface after channel change or input switch (has no argument).
+ Needed for the cx2584x, not needed for the mspx4xx, but it doesn't seem to
+ do any harm calling it regardless.
13=set audio volume delay
14=set audio delay
diff --git a/linux/drivers/media/video/cafe_ccic.c b/linux/drivers/media/video/cafe_ccic.c
index 5f35836ad..b96d45654 100644
--- a/linux/drivers/media/video/cafe_ccic.c
+++ b/linux/drivers/media/video/cafe_ccic.c
@@ -826,7 +826,7 @@ static int __cafe_cam_reset(struct cafe_camera *cam)
*/
static int cafe_cam_init(struct cafe_camera *cam)
{
- struct v4l2_chip_ident chip = { V4L2_CHIP_MATCH_ALWAYS };
+ struct v4l2_chip_ident chip = { V4L2_CHIP_MATCH_I2C_ADDR, 0, 0, 0 };
int ret;
mutex_lock(&cam->s_mutex);
@@ -836,6 +836,7 @@ static int cafe_cam_init(struct cafe_camera *cam)
ret = __cafe_cam_reset(cam);
if (ret)
goto out;
+ chip.match_chip = cam->sensor->addr;
ret = __cafe_cam_cmd(cam, VIDIOC_G_CHIP_IDENT, &chip);
if (ret)
goto out;
diff --git a/linux/drivers/media/video/v4l2-common.c b/linux/drivers/media/video/v4l2-common.c
index b2d57d888..60c56a8b0 100644
--- a/linux/drivers/media/video/v4l2-common.c
+++ b/linux/drivers/media/video/v4l2-common.c
@@ -1596,8 +1596,6 @@ u32 v4l2_ctrl_next(const u32 * const * ctrl_classes, u32 id)
int v4l2_chip_match_i2c_client(struct i2c_client *c, u32 match_type, u32 match_chip)
{
switch (match_type) {
- case V4L2_CHIP_MATCH_ALWAYS:
- return 1;
case V4L2_CHIP_MATCH_I2C_DRIVER:
return (c != NULL && c->driver != NULL && c->driver->id == match_chip);
case V4L2_CHIP_MATCH_I2C_ADDR:
@@ -1610,8 +1608,6 @@ int v4l2_chip_match_i2c_client(struct i2c_client *c, u32 match_type, u32 match_c
int v4l2_chip_match_host(u32 match_type, u32 match_chip)
{
switch (match_type) {
- case V4L2_CHIP_MATCH_ALWAYS:
- return 1;
case V4L2_CHIP_MATCH_HOST:
return match_chip == 0;
default:
diff --git a/linux/include/linux/dvb/version.h b/linux/include/linux/dvb/version.h
index 6183c9c48..126e0c26c 100644
--- a/linux/include/linux/dvb/version.h
+++ b/linux/include/linux/dvb/version.h
@@ -24,6 +24,6 @@
#define _DVBVERSION_H_
#define DVB_API_VERSION 3
-#define DVB_API_VERSION_MINOR 1
+#define DVB_API_VERSION_MINOR 2
#endif /*_DVBVERSION_H_*/
diff --git a/linux/include/linux/videodev2.h b/linux/include/linux/videodev2.h
index 8a5aabb84..76af1e16a 100644
--- a/linux/include/linux/videodev2.h
+++ b/linux/include/linux/videodev2.h
@@ -1387,10 +1387,9 @@ struct v4l2_streamparm
/* VIDIOC_DBG_G_REGISTER and VIDIOC_DBG_S_REGISTER */
-#define V4L2_CHIP_MATCH_ALWAYS 0 /* Match always (match_chip is not used) */
-#define V4L2_CHIP_MATCH_HOST 1 /* Match against chip ID on host (0 for the host) */
-#define V4L2_CHIP_MATCH_I2C_DRIVER 2 /* Match against I2C driver ID */
-#define V4L2_CHIP_MATCH_I2C_ADDR 3 /* Match against I2C 7-bit address */
+#define V4L2_CHIP_MATCH_HOST 0 /* Match against chip ID on host (0 for the host) */
+#define V4L2_CHIP_MATCH_I2C_DRIVER 1 /* Match against I2C driver ID */
+#define V4L2_CHIP_MATCH_I2C_ADDR 2 /* Match against I2C 7-bit address */
struct v4l2_register {
__u32 match_type; /* Match type */
diff --git a/linux/include/media/cx2341x.h b/linux/include/media/cx2341x.h
index 583b0621f..38c12fed7 100644
--- a/linux/include/media/cx2341x.h
+++ b/linux/include/media/cx2341x.h
@@ -166,7 +166,7 @@ void cx2341x_log_status(struct cx2341x_mpeg_params *p, const char *prefix);
#define CX2341X_ENC_SET_PLACEHOLDER 0xd7
#define CX2341X_ENC_MUTE_VIDEO 0xd9
#define CX2341X_ENC_MUTE_AUDIO 0xda
-#define CX2341X_ENC_UNKNOWN 0xdb
+#define CX2341X_ENC_SET_VERT_CROP_LINE 0xdb
#define CX2341X_ENC_MISC 0xdc
/* OSD API, specific to the cx23415 */
diff --git a/linux/include/media/v4l2-chip-ident.h b/linux/include/media/v4l2-chip-ident.h
index 67a34d528..5698fcd1d 100644
--- a/linux/include/media/v4l2-chip-ident.h
+++ b/linux/include/media/v4l2-chip-ident.h
@@ -55,6 +55,10 @@ enum {
/* OmniVision sensors - range 250-299 */
V4L2_IDENT_OV7670 = 250,
+
+ /* Conexant MPEG encoder/decoders: range 410-420 */
+ V4L2_IDENT_CX23415 = 415,
+ V4L2_IDENT_CX23416 = 416,
};
#endif
diff --git a/v4l2-apps/util/Makefile b/v4l2-apps/util/Makefile
index 06452b0ae..f13773c70 100644
--- a/v4l2-apps/util/Makefile
+++ b/v4l2-apps/util/Makefile
@@ -2,7 +2,7 @@
CPPFLAGS += -I../../linux/include
-binaries = v4l2-ctl
+binaries = v4l2-ctl v4l2-dbg
.PHONY: all clean install qv4l2
diff --git a/v4l2-apps/util/v4l2-ctl.cpp b/v4l2-apps/util/v4l2-ctl.cpp
index 11af185f7..c466b4b63 100644
--- a/v4l2-apps/util/v4l2-ctl.cpp
+++ b/v4l2-apps/util/v4l2-ctl.cpp
@@ -1,8 +1,9 @@
/*
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>
+ Cleanup and VBI and audio in/out options, introduction in v4l-dvb,
+ support for most new APIs since 2006.
+ Copyright (C) 2004, 2006, 2007 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
@@ -79,6 +80,8 @@ enum Option {
OptSetSlicedVbiOutFormat,
OptGetOverlayFormat,
//OptSetOverlayFormat, TODO
+ OptGetOutputOverlayFormat,
+ OptSetOutputOverlayFormat,
OptGetVbiFormat,
//OptSetVbiFormat, TODO
OptGetVbiOutFormat,
@@ -94,6 +97,8 @@ enum Option {
OptSetVideoOutFormat,
OptGetSlicedVbiCap,
OptGetSlicedVbiOutCap,
+ OptGetFBuf,
+ OptSetFBuf,
OptGetVideoCrop,
OptSetVideoCrop,
OptGetAudioInput,
@@ -107,6 +112,8 @@ enum Option {
static char options[OptLast];
+static unsigned capabilities;
+
typedef std::vector<struct v4l2_ext_control> ctrl_list;
static ctrl_list user_ctrls;
static ctrl_list mpeg_ctrls;
@@ -136,8 +143,12 @@ static const flag_def service_def[] = {
};
/* fmts specified */
-#define FMTWidth (1L<<0)
-#define FMTHeight (1L<<1)
+#define FmtTop (1L<<0)
+#define FmtLeft (1L<<1)
+#define FmtWidth (1L<<2)
+#define FmtHeight (1L<<3)
+#define FmtChromaKey (1L<<4)
+#define FmtGlobalAlpha (1L<<5)
/* crop specified */
#define CropWidth (1L<<0)
@@ -183,6 +194,8 @@ static struct option long_options[] = {
{"verbose", no_argument, 0, OptVerbose},
{"log-status", no_argument, 0, OptLogStatus},
{"get-fmt-overlay", no_argument, 0, OptGetOverlayFormat},
+ {"get-fmt-output-overlay", no_argument, 0, OptGetOutputOverlayFormat},
+ {"set-fmt-output-overlay", required_argument, 0, OptSetOutputOverlayFormat},
{"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},
@@ -191,6 +204,8 @@ static struct option long_options[] = {
{"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},
+ {"get-fbuf", no_argument, 0, OptGetFBuf},
+ {"set-fbuf", required_argument, 0, OptSetFBuf},
{"get-crop-video", no_argument, 0, OptGetVideoCrop},
{"set-crop-video", required_argument, 0, OptSetVideoCrop},
{0, 0, 0, 0}
@@ -253,17 +268,21 @@ static void usage(void)
printf(" --list-formats display supported video formats [VIDIOC_ENUM_FMT]\n");
printf(" -V, --get-fmt-video\n");
printf(" query the video capture format [VIDIOC_G_FMT]\n");
- printf(" -v, --set-fmt-video=width=<x>,height=<y>\n");
+ printf(" -v, --set-fmt-video=width=<w>,height=<h>\n");
printf(" set the video capture format [VIDIOC_S_FMT]\n");
printf(" --verbose turn on verbose ioctl error reporting.\n");
printf("\n");
printf("Uncommon options:\n");
printf(" --get-fmt-video-out\n");
printf(" query the video output format [VIDIOC_G_FMT]\n");
- printf(" --set-fmt-video-out=width=<x>,height=<y>\n");
+ printf(" --set-fmt-video-out=left=<x>,top=<y>,width=<w>,height=<h>\n");
printf(" set the video output format [VIDIOC_S_FMT]\n");
printf(" --get-fmt-overlay\n");
printf(" query the video overlay format [VIDIOC_G_FMT]\n");
+ printf(" --get-fmt-output-overlay\n");
+ printf(" query the video output overlay format [VIDIOC_G_FMT]\n");
+ printf(" --set-fmt-output-overlay=chromakey=<key>,global_alpha=<alpha>\n");
+ printf(" set the video output overlay format [VIDIOC_S_FMT]\n");
printf(" --get-sliced-vbi-cap\n");
printf(" query the sliced VBI capture capabilities [VIDIOC_G_SLICED_VBI_CAP]\n");
printf(" --get-sliced-vbi-out-cap\n");
@@ -280,6 +299,9 @@ static void usage(void)
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(" --get-fbuf query the overlay framebuffer data [VIDIOC_G_FBUF]\n");
+ printf(" --set-fbuf=chromakey=<0/1>,global_alpha=<0/1>,local_alpha=<0/1>\n");
+ printf(" set the overlay framebuffer [VIDIOC_S_FBUF]\n");
printf(" --get-crop-video\n");
printf(" query the video capture crop window [VIDIOC_G_CROP]\n");
printf(" --set-crop-video=top=<x>,left=<y>,width=<w>,height=<h>\n");
@@ -327,6 +349,8 @@ static std::string buftype2s(int type)
return "Sliced VBI Capture";
case V4L2_BUF_TYPE_SLICED_VBI_OUTPUT:
return "Sliced VBI Output";
+ case V4L2_BUF_TYPE_VIDEO_OUTPUT_OVERLAY:
+ return "Video Output Overlay";
case V4L2_BUF_TYPE_PRIVATE:
return "Private";
default:
@@ -364,6 +388,10 @@ static std::string field2s(int val)
return "Sequential Bottom-Top";
case V4L2_FIELD_ALTERNATE:
return "Alternating";
+ case V4L2_FIELD_INTERLACED_TB:
+ return "Interlaced Top-Bottom";
+ case V4L2_FIELD_INTERLACED_BT:
+ return "Interlaced Bottom-Top";
default:
return "Unknown (" + num2s(val) + ")";
}
@@ -575,6 +603,62 @@ static void find_controls(int fd)
}
}
+static std::string fbufcap2s(unsigned cap)
+{
+ std::string s;
+
+ if (cap & V4L2_FBUF_CAP_EXTERNOVERLAY)
+ s += "\t\tExtern Overlay\n";
+ if (cap & V4L2_FBUF_CAP_CHROMAKEY)
+ s += "\t\tChromakey\n";
+ if (cap & V4L2_FBUF_CAP_GLOBAL_ALPHA)
+ s += "\t\tGlobal Alpha\n";
+ if (cap & V4L2_FBUF_CAP_LOCAL_ALPHA)
+ s += "\t\tLocal Alpha\n";
+ if (cap & V4L2_FBUF_CAP_LIST_CLIPPING)
+ s += "\t\tClipping List\n";
+ if (cap & V4L2_FBUF_CAP_BITMAP_CLIPPING)
+ s += "\t\tClipping Bitmap\n";
+ if (s.empty()) s += "\t\t\n";
+ return s;
+}
+
+static std::string fbufflags2s(unsigned fl)
+{
+ std::string s;
+
+ if (fl & V4L2_FBUF_FLAG_PRIMARY)
+ s += "\t\tPrimary Graphics Surface\n";
+ if (fl & V4L2_FBUF_FLAG_OVERLAY)
+ s += "\t\tOverlay Matches Capture/Output Size\n";
+ if (fl & V4L2_FBUF_FLAG_CHROMAKEY)
+ s += "\t\tChromakey\n";
+ if (fl & V4L2_FBUF_FLAG_GLOBAL_ALPHA)
+ s += "\t\tGlobal Alpha\n";
+ if (fl & V4L2_FBUF_FLAG_LOCAL_ALPHA)
+ s += "\t\tLocal Alpha\n";
+ if (s.empty()) s += "\t\t\n";
+ return s;
+}
+
+static void printfbuf(const struct v4l2_framebuffer &fb)
+{
+ int is_ext = fb.capability & V4L2_FBUF_CAP_EXTERNOVERLAY;
+
+ printf("Capability : %s", fbufcap2s(fb.capability).c_str() + 2);
+ printf("Flags : %s", fbufflags2s(fb.flags).c_str() + 2);
+ printf("Width : %d\n", fb.fmt.width);
+ printf("Height : %d\n", fb.fmt.height);
+ printf("Pixel Format : %s\n", fcc2s(fb.fmt.pixelformat).c_str());
+ if (!is_ext) {
+ printf("Bytes per Line: %d\n", fb.fmt.bytesperline);
+ printf("Size image : %d\n", fb.fmt.sizeimage);
+ printf("Colorspace : %s\n", colorspace2s(fb.fmt.colorspace).c_str());
+ if (fb.fmt.priv)
+ printf("Custom Info : %08x\n", fb.fmt.priv);
+ }
+}
+
static void printcrop(const struct v4l2_crop &crop)
{
printf("Crop: Left %d, Top %d, Width %d, Height %d\n",
@@ -600,9 +684,15 @@ static int printfmt(struct v4l2_format vfmt)
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.type == V4L2_BUF_TYPE_VIDEO_OUTPUT &&
+ (capabilities & V4L2_CAP_VIDEO_OUTPUT_POS)) {
+ printf("\tLeft/Top : %d/%d\n",
+ vfmt.fmt.pix.left, vfmt.fmt.pix.top);
+ }
if (vfmt.fmt.pix.priv)
printf("\tCustom Info : %08x\n", vfmt.fmt.pix.priv);
break;
+ case V4L2_BUF_TYPE_VIDEO_OUTPUT_OVERLAY:
case V4L2_BUF_TYPE_VIDEO_OVERLAY:
printf("\tType : %s\n", buftype2s(vfmt.type).c_str());
printf("\tLeft/Top : %d/%d\n",
@@ -610,9 +700,10 @@ static int printfmt(struct v4l2_format vfmt)
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("\tChroma Key : 0x%08x\n", vfmt.fmt.win.chromakey);
+ printf("\tGlobal Alpha: 0x%02x\n", vfmt.fmt.win.global_alpha);
printf("\tClip Count : %u\n", vfmt.fmt.win.clipcount);
+ printf("\tClip Bitmap : %s\n", vfmt.fmt.win.bitmap ? "Yes" : "No");
break;
case V4L2_BUF_TYPE_VBI_CAPTURE:
case V4L2_BUF_TYPE_VBI_OUTPUT:
@@ -752,6 +843,8 @@ static std::string cap2s(unsigned cap)
s += "\t\tVideo Output\n";
if (cap & V4L2_CAP_VIDEO_OVERLAY)
s += "\t\tVideo Overlay\n";
+ if (cap & V4L2_CAP_VIDEO_OUTPUT_OVERLAY)
+ s += "\t\tVideo Output Overlay\n";
if (cap & V4L2_CAP_VBI_CAPTURE)
s += "\t\tVBI Capture\n";
if (cap & V4L2_CAP_VBI_OUTPUT)
@@ -762,6 +855,8 @@ 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_VIDEO_OUTPUT_POS)
+ s += "\t\tVideo Output Position\n";
if (cap & V4L2_CAP_TUNER)
s += "\t\tTuner\n";
if (cap & V4L2_CAP_AUDIO)
@@ -942,6 +1037,8 @@ int main(int argc, char **argv)
unsigned int set_fmts = 0;
unsigned int set_fmts_out = 0;
unsigned int set_crop = 0;
+ unsigned int set_fbuf = 0;
+ unsigned int set_overlay_fmt_out = 0;
int mode = V4L2_TUNER_MODE_STEREO; /* set audio mode */
@@ -954,6 +1051,7 @@ int main(int argc, char **argv)
struct v4l2_format vbi_fmt_out; /* set_format/get_format for sliced VBI output */
struct v4l2_format raw_fmt; /* set_format/get_format for VBI */
struct v4l2_format raw_fmt_out; /* set_format/get_format for VBI output */
+ struct v4l2_format overlay_fmt_out; /* set_format/get_format video overlay output */
struct v4l2_tuner tuner; /* set_tuner/get_tuner */
struct v4l2_capability vcap; /* list_cap */
struct v4l2_input vin; /* list_inputs */
@@ -961,6 +1059,7 @@ int main(int argc, char **argv)
struct v4l2_audio vaudio; /* list audio inputs */
struct v4l2_audioout vaudout; /* audio outputs */
struct v4l2_rect vcrop; /* crop rect */
+ struct v4l2_framebuffer fbuf; /* fbuf */
int input; /* set_input/get_input */
int output; /* set_output/get_output */
v4l2_std_id std; /* get_std/set_std */
@@ -975,6 +1074,7 @@ int main(int argc, char **argv)
memset(&raw_fmt, 0, sizeof(raw_fmt));
memset(&vfmt_out, 0, sizeof(vfmt_out));
memset(&vbi_fmt_out, 0, sizeof(vbi_fmt_out));
+ memset(&overlay_fmt_out, 0, sizeof(overlay_fmt_out));
memset(&raw_fmt_out, 0, sizeof(raw_fmt_out));
memset(&tuner, 0, sizeof(tuner));
memset(&vcap, 0, sizeof(vcap));
@@ -985,6 +1085,7 @@ int main(int argc, char **argv)
memset(&vcrop, 0, sizeof(vcrop));
memset(&vf, 0, sizeof(vf));
memset(&vs, 0, sizeof(vs));
+ memset(&fbuf, 0, sizeof(fbuf));
if (argc == 1) {
usage();
@@ -1031,11 +1132,11 @@ int main(int argc, char **argv)
switch (parse_subopt(&subs, subopts, &value)) {
case 0:
vfmt.fmt.pix.width = strtol(value, 0L, 0);
- set_fmts |= FMTWidth;
+ set_fmts |= FmtWidth;
break;
case 1:
vfmt.fmt.pix.height = strtol(value, 0L, 0);
- set_fmts |= FMTHeight;
+ set_fmts |= FmtHeight;
break;
}
}
@@ -1044,6 +1145,8 @@ int main(int argc, char **argv)
subs = optarg;
while (*subs != '\0') {
static char *const subopts[] = {
+ "top",
+ "left",
"width",
"height",
NULL
@@ -1051,12 +1154,67 @@ int main(int argc, char **argv)
switch (parse_subopt(&subs, subopts, &value)) {
case 0:
- vfmt_out.fmt.pix.width = strtol(value, 0L, 0);
- set_fmts_out |= FMTWidth;
+ vfmt_out.fmt.pix.top = strtol(value, 0L, 0);
+ set_fmts_out |= FmtTop;
break;
case 1:
+ vfmt_out.fmt.pix.left = strtol(value, 0L, 0);
+ set_fmts_out |= FmtLeft;
+ break;
+ case 2:
+ vfmt_out.fmt.pix.width = strtol(value, 0L, 0);
+ set_fmts_out |= FmtWidth;
+ break;
+ case 3:
vfmt_out.fmt.pix.height = strtol(value, 0L, 0);
- set_fmts_out |= FMTHeight;
+ set_fmts_out |= FmtHeight;
+ break;
+ }
+ }
+ break;
+ case OptSetOutputOverlayFormat:
+ subs = optarg;
+ while (*subs != '\0') {
+ static char *const subopts[] = {
+ "chromakey",
+ "global_alpha",
+ NULL
+ };
+
+ switch (parse_subopt(&subs, subopts, &value)) {
+ case 0:
+ overlay_fmt_out.fmt.win.chromakey = strtol(value, 0L, 0);
+ set_overlay_fmt_out |= FmtChromaKey;
+ break;
+ case 1:
+ overlay_fmt_out.fmt.win.global_alpha = strtol(value, 0L, 0);
+ set_overlay_fmt_out |= FmtGlobalAlpha;
+ break;
+ }
+ }
+ break;
+ case OptSetFBuf:
+ subs = optarg;
+ while (*subs != '\0') {
+ static char *const subopts[] = {
+ "chromakey",
+ "global_alpha",
+ "local_alpha",
+ NULL
+ };
+
+ switch (parse_subopt(&subs, subopts, &value)) {
+ case 0:
+ fbuf.flags |= strtol(value, 0L, 0) ? V4L2_FBUF_FLAG_CHROMAKEY : 0;
+ set_fbuf |= V4L2_FBUF_FLAG_CHROMAKEY;
+ break;
+ case 1:
+ fbuf.flags |= strtol(value, 0L, 0) ? V4L2_FBUF_FLAG_GLOBAL_ALPHA : 0;
+ set_fbuf |= V4L2_FBUF_FLAG_GLOBAL_ALPHA;
+ break;
+ case 2:
+ fbuf.flags |= strtol(value, 0L, 0) ? V4L2_FBUF_FLAG_LOCAL_ALPHA : 0;
+ set_fbuf |= V4L2_FBUF_FLAG_LOCAL_ALPHA;
break;
}
}
@@ -1251,6 +1409,7 @@ int main(int argc, char **argv)
free(device);
doioctl(fd, VIDIOC_QUERYCAP, &vcap, "VIDIOC_QUERYCAP");
+ 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()) {
@@ -1278,10 +1437,12 @@ int main(int argc, char **argv)
options[OptGetFreq] = 1;
options[OptGetTuner] = 1;
options[OptGetOverlayFormat] = 1;
+ options[OptGetOutputOverlayFormat] = 1;
options[OptGetVbiFormat] = 1;
options[OptGetVbiOutFormat] = 1;
options[OptGetSlicedVbiFormat] = 1;
options[OptGetSlicedVbiOutFormat] = 1;
+ options[OptGetFBuf] = 1;
}
/* Information Opts */
@@ -1373,9 +1534,9 @@ int main(int argc, char **argv)
if (ioctl(fd, VIDIOC_G_FMT, &in_vfmt) < 0)
fprintf(stderr, "ioctl: VIDIOC_G_FMT failed\n");
else {
- if (set_fmts & FMTWidth)
+ if (set_fmts & FmtWidth)
in_vfmt.fmt.pix.width = vfmt.fmt.pix.width;
- if (set_fmts & FMTHeight)
+ 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");
@@ -1389,10 +1550,14 @@ int main(int argc, char **argv)
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 (set_fmts_out & FmtTop)
+ in_vfmt.fmt.pix.top = vfmt_out.fmt.pix.top;
+ if (set_fmts_out & FmtLeft)
+ in_vfmt.fmt.pix.left = vfmt_out.fmt.pix.left;
+ if (set_fmts_out & FmtWidth)
+ in_vfmt.fmt.pix.width = vfmt_out.fmt.pix.width;
+ if (set_fmts_out & FmtHeight)
+ in_vfmt.fmt.pix.height = vfmt_out.fmt.pix.height;
if (ioctl(fd, VIDIOC_S_FMT, &in_vfmt) < 0)
fprintf(stderr, "ioctl: VIDIOC_S_FMT failed\n");
}
@@ -1422,9 +1587,37 @@ int main(int argc, char **argv)
}
}
+ if (options[OptSetOutputOverlayFormat]) {
+ struct v4l2_format fmt;
+ memset(&fmt, 0, sizeof(fmt));
+ fmt.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_OVERLAY;
+ if (ioctl(fd, VIDIOC_G_FMT, &fmt, "VIDIOC_G_FMT") < 0)
+ fprintf(stderr, "ioctl: VIDIOC_G_FMT failed\n");
+ else {
+ if (set_overlay_fmt_out & FmtChromaKey)
+ fmt.fmt.win.chromakey = overlay_fmt_out.fmt.win.chromakey;
+ if (set_overlay_fmt_out & FmtGlobalAlpha)
+ fmt.fmt.win.global_alpha = overlay_fmt_out.fmt.win.global_alpha;
+ if (ioctl(fd, VIDIOC_S_FMT, &fmt, "VIDIOC_S_FMT") < 0)
+ fprintf(stderr, "ioctl: VIDIOC_S_FMT failed\n");
+ }
+ }
+
+ if (options[OptSetFBuf]) {
+ struct v4l2_framebuffer fb;
+ if (ioctl(fd, VIDIOC_G_FBUF, &fb, "VIDIOC_G_FBUF") < 0)
+ fprintf(stderr, "ioctl: VIDIOC_G_FBUF failed\n");
+ else {
+ fb.flags &= ~set_fbuf;
+ fb.flags |= fbuf.flags;
+ if (ioctl(fd, VIDIOC_S_FBUF, &fb) < 0)
+ fprintf(stderr, "ioctl: VIDIOC_S_FBUF failed\n");
+ }
+ }
+
if (options[OptSetVideoCrop]) {
struct v4l2_crop in_crop;
- printf("ioctl: VIDIOC_S_CROP\n");
+
in_crop.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
if (ioctl(fd, VIDIOC_G_CROP, &in_crop) < 0)
fprintf(stderr, "ioctl: VIDIOC_G_CROP failed\n");
@@ -1510,6 +1703,15 @@ int main(int argc, char **argv)
fprintf(stderr, "error printing result\n");
}
+ if (options[OptGetOutputOverlayFormat]) {
+ struct v4l2_format fmt;
+ memset(&fmt, 0, sizeof(fmt));
+ fmt.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_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,
@@ -1546,6 +1748,12 @@ int main(int argc, char **argv)
"error printing result\n");
}
+ if (options[OptGetFBuf]) {
+ struct v4l2_framebuffer fb;
+ if (doioctl(fd, VIDIOC_G_FBUF, &fb, "VIDIOC_G_FBUF") == 0)
+ printfbuf(fb);
+ }
+
if (options[OptGetVideoCrop]) {
struct v4l2_crop crop;
diff --git a/v4l2-apps/util/v4l2-dbg.cpp b/v4l2-apps/util/v4l2-dbg.cpp
new file mode 100644
index 000000000..70d465dea
--- /dev/null
+++ b/v4l2-apps/util/v4l2-dbg.cpp
@@ -0,0 +1,516 @@
+/*
+ Copyright (C) 2007 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 {
+ OptListRegisters = 'R',
+ OptSetRegister = 'r',
+ OptSetSlicedVbiFormat = 'b',
+ OptSetDevice = 'd',
+ OptGetDriverInfo = 'D',
+ OptListChipIdents = 'C',
+ OptGetChipIdent = 'c',
+ OptHelp = 'h',
+
+ OptLogStatus = 128,
+ OptVerbose,
+ OptLast = 256
+};
+
+static char options[OptLast];
+
+static unsigned capabilities;
+
+static struct option long_options[] = {
+ {"device", required_argument, 0, OptSetDevice},
+ {"help", no_argument, 0, OptHelp},
+ {"list-registers", required_argument, 0, OptListRegisters},
+ {"set-register", required_argument, 0, OptSetRegister},
+ {"list-chip-idents", no_argument, 0, OptListChipIdents},
+ {"get-chip-ident", required_argument, 0, OptGetChipIdent},
+ {"info", no_argument, 0, OptGetDriverInfo},
+ {"verbose", no_argument, 0, OptVerbose},
+ {"log-status", no_argument, 0, OptLogStatus},
+ {0, 0, 0, 0}
+};
+
+static void usage(void)
+{
+ printf("Usage:\n");
+ printf(" -D, --info show driver info [VIDIOC_QUERYCAP]\n");
+ printf(" -d, --device=<dev> use device <dev> instead of /dev/video0\n");
+ printf(" if <dev> is a single digit, then /dev/video<dev> is used\n");
+ printf(" -h, --help display this help message\n");
+ printf(" --verbose turn on verbose ioctl error reporting.\n");
+ printf(" -R, --list-registers=type=<host/i2cdrv/i2caddr>,chip=<chip>[,min=<addr>,max=<addr>] \n");
+ printf(" dump registers from <min> to <max> [VIDIOC_DBG_G_REGISTER]\n");
+ printf(" -r, --set-register=type=<host/i2cdrv/i2caddr>,chip=<chip>,reg=<addr>,val=<val>\n");
+ printf(" set the register [VIDIOC_DBG_S_REGISTER]\n");
+ printf(" -C, --list-chip-idents\n");
+ printf(" List the available host and i2c chips [VIDIOC_G_CHIP_IDENT]\n");
+ printf(" -c, --get-chip-ident=type=<host/i2cdrv/i2caddr>,chip=<chip>\n");
+ printf(" Get the chip identifier [VIDIOC_G_CHIP_IDENT]\n");
+ printf(" --log-status log the board status in the kernel log [VIDIOC_LOG_STATUS]\n");
+ printf("\n");
+ printf(" if type == host, then <chip> is the host's chip ID (default 0)\n");
+ printf(" if type == i2cdrv (default), then <chip> is the I2C driver name or ID\n");
+ printf(" if type == i2caddr, then <chip> is the 7-bit I2C address\n");
+ exit(0);
+}
+
+static unsigned parse_type(const std::string &s)
+{
+ if (s == "host") return V4L2_CHIP_MATCH_HOST;
+ if (s == "i2caddr") return V4L2_CHIP_MATCH_I2C_ADDR;
+ return V4L2_CHIP_MATCH_I2C_DRIVER;
+}
+
+/* Copied from <linux/i2c-id.h> */
+#define I2C_DRIVERID_SAA711X 73 /* saa711x video encoders */
+#define I2C_DRIVERID_SAA717X 80 /* saa717x video encoder */
+#define I2C_DRIVERID_SAA7127 72 /* saa7124 video encoder */
+#define I2C_DRIVERID_CX25840 71 /* cx2584x video encoder */
+
+static unsigned parse_chip(int type, const std::string &s)
+{
+ if (type == V4L2_CHIP_MATCH_HOST || type == V4L2_CHIP_MATCH_I2C_ADDR || isdigit(s[0]))
+ return strtoul(s.c_str(), 0, 0);
+ if (s == "saa711x")
+ return I2C_DRIVERID_SAA711X;
+ if (s == "saa717x")
+ return I2C_DRIVERID_SAA717X;
+ if (s == "saa7127")
+ return I2C_DRIVERID_SAA7127;
+ if (s == "cx2584x")
+ return I2C_DRIVERID_CX25840;
+ return 0;
+}
+
+static std::string cap2s(unsigned cap)
+{
+ std::string s;
+
+ if (cap & V4L2_CAP_VIDEO_CAPTURE)
+ s += "\t\tVideo Capture\n";
+ if (cap & V4L2_CAP_VIDEO_OUTPUT)
+ s += "\t\tVideo Output\n";
+ if (cap & V4L2_CAP_VIDEO_OVERLAY)
+ s += "\t\tVideo Overlay\n";
+ if (cap & V4L2_CAP_VIDEO_OUTPUT_OVERLAY)
+ s += "\t\tVideo Output Overlay\n";
+ if (cap & V4L2_CAP_VBI_CAPTURE)
+ s += "\t\tVBI Capture\n";
+ if (cap & V4L2_CAP_VBI_OUTPUT)
+ s += "\t\tVBI Output\n";
+ if (cap & V4L2_CAP_SLICED_VBI_CAPTURE)
+ s += "\t\tSliced VBI Capture\n";
+ if (cap & V4L2_CAP_SLICED_VBI_OUTPUT)
+ s += "\t\tSliced VBI Output\n";
+ if (cap & V4L2_CAP_RDS_CAPTURE)
+ s += "\t\tRDS Capture\n";
+ if (cap & V4L2_CAP_VIDEO_OUTPUT_POS)
+ s += "\t\tVideo Output Position\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 void print_regs(int fd, struct v4l2_register *reg, unsigned long min, unsigned long max, int stride)
+{
+ unsigned long mask = stride > 1 ? 0x1f : 0x0f;
+ unsigned long i;
+ int line = 0;
+
+ for (i = min & ~mask; i <= max; i += stride) {
+ if ((i & mask) == 0 && line % 32 == 0) {
+ if (stride == 4)
+ printf("\n 00 04 08 0C 10 14 18 1C");
+ else
+ printf("\n 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F");
+ }
+
+ if ((i & mask) == 0) {
+ printf("\n%08lx: ", i);
+ line++;
+ }
+ if (i < min) {
+ printf("%*s ", 2 * stride, "");
+ continue;
+ }
+ reg->reg = i;
+ if (ioctl(fd, VIDIOC_DBG_G_REGISTER, reg) < 0) {
+ fprintf(stderr, "ioctl: VIDIOC_DBG_G_REGISTER "
+ "failed for 0x%llx\n", reg->reg);
+ } else {
+ printf("%0*llx ", 2 * stride, reg->val);
+ }
+ usleep(1);
+ }
+ printf("\n");
+}
+
+static void print_chip(struct v4l2_chip_ident *chip)
+{
+ printf("Chip %d, revision 0x%08x\n", chip->ident, chip->revision);
+}
+
+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;
+}
+
+int main(int argc, char **argv)
+{
+ char *value, *subs;
+ int i;
+
+ int fd = -1;
+
+ /* command args */
+ int ch;
+ char *device = strdup("/dev/video0"); /* -d device */
+ struct v4l2_capability vcap; /* list_cap */
+ struct v4l2_register set_reg;
+ struct v4l2_register get_reg;
+ struct v4l2_chip_ident chip_id;
+ char short_options[26 * 2 * 2 + 1];
+ int idx = 0;
+ unsigned long long reg_min = 0, reg_max = 0;
+
+ memset(&set_reg, 0, sizeof(set_reg));
+ memset(&get_reg, 0, sizeof(get_reg));
+ memset(&chip_id, 0, sizeof(chip_id));
+
+ 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 OptSetRegister:
+ subs = optarg;
+ set_reg.match_type = V4L2_CHIP_MATCH_I2C_DRIVER;
+ while (*subs != '\0') {
+ static char *const subopts[] = {
+ "type",
+ "chip",
+ "reg",
+ "val",
+ NULL
+ };
+
+ switch (parse_subopt(&subs, subopts, &value)) {
+ case 0:
+ set_reg.match_type = parse_type(value);
+ break;
+ case 1:
+ set_reg.match_chip = parse_chip(set_reg.match_type, value);
+ break;
+ case 2:
+ set_reg.reg = strtoull(value, 0L, 0);
+ break;
+ case 3:
+ set_reg.val = strtoull(value, 0L, 0);
+ break;
+ }
+ }
+ break;
+ case OptListRegisters:
+ subs = optarg;
+ get_reg.match_type = V4L2_CHIP_MATCH_I2C_DRIVER;
+ while (*subs != '\0') {
+ static char *const subopts[] = {
+ "type",
+ "chip",
+ "min",
+ "max",
+ NULL
+ };
+
+ switch (parse_subopt(&subs, subopts, &value)) {
+ case 0:
+ get_reg.match_type = parse_type(value);
+ break;
+ case 1:
+ get_reg.match_chip = parse_chip(set_reg.match_type, value);
+ break;
+ case 2:
+ reg_min = strtoull(value, 0L, 0);
+ break;
+ case 3:
+ reg_max = strtoull(value, 0L, 0);
+ break;
+ }
+ }
+ break;
+ case OptGetChipIdent:
+ subs = optarg;
+ set_reg.match_type = V4L2_CHIP_MATCH_I2C_DRIVER;
+ while (*subs != '\0') {
+ static char *const subopts[] = {
+ "type",
+ "chip",
+ NULL
+ };
+
+ switch (parse_subopt(&subs, subopts, &value)) {
+ case 0:
+ chip_id.match_type = parse_type(value);
+ break;
+ case 1:
+ chip_id.match_chip = parse_chip(set_reg.match_type, value);
+ break;
+ }
+ }
+ 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");
+ capabilities = vcap.capabilities;
+
+ /* 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[OptSetRegister]) {
+ if (doioctl(fd, VIDIOC_DBG_S_REGISTER, &set_reg,
+ "VIDIOC_DBG_S_REGISTER") == 0)
+ printf("register 0x%llx set to 0x%llx\n", set_reg.reg, set_reg.val);
+ }
+
+ if (options[OptGetChipIdent]) {
+ if (doioctl(fd, VIDIOC_G_CHIP_IDENT, &chip_id, "VIDIOC_G_CHIP_IDENT") == 0)
+ print_chip(&chip_id);
+ }
+
+ if (options[OptListChipIdents]) {
+ int i;
+
+ chip_id.match_type = V4L2_CHIP_MATCH_HOST;
+ chip_id.match_chip = 0;
+ chip_id.ident = 0;
+
+ if (doioctl(fd, VIDIOC_G_CHIP_IDENT, &chip_id, "VIDIOC_G_CHIP_IDENT") == 0 && chip_id.ident)
+ print_chip(&chip_id);
+
+ chip_id.match_type = V4L2_CHIP_MATCH_I2C_ADDR;
+ for (i = 0; i < 128; i++) {
+ chip_id.match_chip = i;
+ chip_id.ident = 0;
+ if (doioctl(fd, VIDIOC_G_CHIP_IDENT, &chip_id, "VIDIOC_G_CHIP_IDENT") == 0 && chip_id.ident) {
+ printf("0x%02x: ", i);
+ print_chip(&chip_id);
+ }
+ }
+ }
+
+ if (options[OptListRegisters]) {
+ int stride = 1;
+
+ if (get_reg.match_type == V4L2_CHIP_MATCH_HOST) stride = 4;
+ printf("ioctl: VIDIOC_DBG_G_REGISTER\n");
+ if (reg_max == 0) {
+ switch (get_reg.match_chip) {
+ case I2C_DRIVERID_SAA711X:
+ print_regs(fd, &get_reg, 0, 0xff, stride);
+ break;
+ case I2C_DRIVERID_SAA717X:
+ // FIXME: use correct reg regions
+ print_regs(fd, &get_reg, 0, 0xff, stride);
+ break;
+ case I2C_DRIVERID_SAA7127:
+ print_regs(fd, &get_reg, 0, 0x7f, stride);
+ break;
+ case I2C_DRIVERID_CX25840:
+ print_regs(fd, &get_reg, 0, 2, stride);
+ print_regs(fd, &get_reg, 0x100, 0x15f, stride);
+ print_regs(fd, &get_reg, 0x200, 0x23f, stride);
+ print_regs(fd, &get_reg, 0x400, 0x4bf, stride);
+ print_regs(fd, &get_reg, 0x800, 0x9af, stride);
+ break;
+ case 0:
+ print_regs(fd, &get_reg, 0x02000000, 0x020000ff, stride);
+ break;
+ }
+ }
+ else {
+ print_regs(fd, &get_reg, reg_min, reg_max, stride);
+ }
+ }
+
+ 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);
+ }
+ }
+ }
+ }
+
+ close(fd);
+ exit(0);
+}