| Philippe De Muyter | 0cc9614 | 2014-11-03 21:27:40 +0100 | [diff] [blame] | 1 | /* | 
|  | 2 | * Copyright (c) 2014 Philippe De Muyter <phdm@macqel.be> | 
|  | 3 | * Copyright (c) 2014 William Manley <will@williammanley.net> | 
|  | 4 | * Copyright (c) 2011 Peter Zotov <whitequark@whitequark.org> | 
|  | 5 | * All rights reserved. | 
|  | 6 | * | 
|  | 7 | * Redistribution and use in source and binary forms, with or without | 
|  | 8 | * modification, are permitted provided that the following conditions | 
|  | 9 | * are met: | 
|  | 10 | * 1. Redistributions of source code must retain the above copyright | 
|  | 11 | *    notice, this list of conditions and the following disclaimer. | 
|  | 12 | * 2. Redistributions in binary form must reproduce the above copyright | 
|  | 13 | *    notice, this list of conditions and the following disclaimer in the | 
|  | 14 | *    documentation and/or other materials provided with the distribution. | 
|  | 15 | * 3. The name of the author may not be used to endorse or promote products | 
|  | 16 | *    derived from this software without specific prior written permission. | 
|  | 17 | * | 
|  | 18 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR | 
|  | 19 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES | 
|  | 20 | * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. | 
|  | 21 | * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, | 
|  | 22 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT | 
|  | 23 | * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | 
|  | 24 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | 
|  | 25 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | 
|  | 26 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF | 
|  | 27 | * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | 
|  | 28 | */ | 
|  | 29 |  | 
|  | 30 | #include "defs.h" | 
|  | 31 |  | 
|  | 32 | #include <stdint.h> | 
|  | 33 | #include <sys/ioctl.h> | 
|  | 34 | #include <linux/videodev2.h> | 
|  | 35 | /* some historical constants */ | 
|  | 36 | #ifndef V4L2_CID_HCENTER | 
|  | 37 | #define V4L2_CID_HCENTER (V4L2_CID_BASE+22) | 
|  | 38 | #endif | 
|  | 39 | #ifndef V4L2_CID_VCENTER | 
|  | 40 | #define V4L2_CID_VCENTER (V4L2_CID_BASE+23) | 
|  | 41 | #endif | 
|  | 42 | #ifndef V4L2_CID_BAND_STOP_FILTER | 
|  | 43 | #define V4L2_CID_BAND_STOP_FILTER (V4L2_CID_BASE+33) | 
|  | 44 | #endif | 
|  | 45 |  | 
|  | 46 | #include "xlat/v4l2_device_capabilities_flags.h" | 
|  | 47 | #include "xlat/v4l2_buf_types.h" | 
|  | 48 | #include "xlat/v4l2_buf_flags.h" | 
|  | 49 | #include "xlat/v4l2_framesize_types.h" | 
|  | 50 | #include "xlat/v4l2_frameinterval_types.h" | 
|  | 51 | #include "xlat/v4l2_fields.h" | 
|  | 52 | #include "xlat/v4l2_colorspaces.h" | 
|  | 53 | #include "xlat/v4l2_format_description_flags.h" | 
|  | 54 | #include "xlat/v4l2_memories.h" | 
|  | 55 | #include "xlat/v4l2_control_ids.h" | 
|  | 56 | #include "xlat/v4l2_control_types.h" | 
|  | 57 | #include "xlat/v4l2_control_flags.h" | 
|  | 58 | #include "xlat/v4l2_control_classes.h" | 
|  | 59 | #include "xlat/v4l2_streaming_capabilities.h" | 
|  | 60 | #include "xlat/v4l2_capture_modes.h" | 
|  | 61 | #include "xlat/v4l2_input_types.h" | 
|  | 62 |  | 
|  | 63 | #define FMT_FRACT "%u/%u" | 
|  | 64 | #define ARGS_FRACT(x) ((x).numerator), ((x).denominator) | 
|  | 65 |  | 
|  | 66 | #define FMT_RECT "{left=%i, top=%i, width=%i, height=%i}" | 
|  | 67 | #define ARGS_RECT(x) (x).left, (x).top, (x).width, (x).height | 
|  | 68 |  | 
|  | 69 | static void print_pixelformat(uint32_t fourcc) | 
|  | 70 | { | 
|  | 71 | #if WORDS_BIGENDIAN | 
|  | 72 | fourcc = htole32(fourcc); | 
|  | 73 | #endif | 
|  | 74 | tprintf("%.4s", (char*)&fourcc); | 
|  | 75 | } | 
|  | 76 |  | 
|  | 77 | static void print_v4l2_format_fmt(const struct v4l2_format *f) | 
|  | 78 | { | 
|  | 79 | tprints("fmt."); | 
|  | 80 | switch (f->type) { | 
|  | 81 | case V4L2_BUF_TYPE_VIDEO_CAPTURE: | 
|  | 82 | case V4L2_BUF_TYPE_VIDEO_OUTPUT: { | 
|  | 83 | const struct v4l2_pix_format *pix = &f->fmt.pix; | 
|  | 84 |  | 
|  | 85 | tprintf("pix={width=%u, height=%u, pixelformat=", | 
|  | 86 | pix->width, pix->height); | 
|  | 87 | print_pixelformat(pix->pixelformat); | 
|  | 88 | tprints(", field="); | 
|  | 89 | printxval(v4l2_fields, pix->field, "V4L2_FIELD_???"); | 
|  | 90 | tprintf(", bytesperline=%u, sizeimage=%u, colorspace=", | 
|  | 91 | pix->bytesperline, pix->sizeimage); | 
|  | 92 | printxval(v4l2_colorspaces, pix->colorspace, | 
|  | 93 | "V4L2_COLORSPACE_???"); | 
|  | 94 | tprints("}"); | 
|  | 95 | break; | 
|  | 96 | } | 
|  | 97 | #if HAVE_DECL_V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE | 
|  | 98 | case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE: | 
|  | 99 | case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE: { | 
|  | 100 | const struct v4l2_pix_format_mplane *pix_mp = &f->fmt.pix_mp; | 
|  | 101 | unsigned int i, max; | 
|  | 102 |  | 
|  | 103 | tprintf("pix_mp={width=%u, height=%u, pixelformat=", | 
|  | 104 | pix_mp->width, pix_mp->height); | 
|  | 105 | print_pixelformat(pix_mp->pixelformat); | 
|  | 106 | tprints(", field="); | 
|  | 107 | printxval(v4l2_fields, pix_mp->field, "V4L2_FIELD_???"); | 
|  | 108 | tprints(", colorspace="); | 
|  | 109 | printxval(v4l2_colorspaces, pix_mp->colorspace, | 
|  | 110 | "V4L2_COLORSPACE_???"); | 
|  | 111 | tprints("plane_fmt=["); | 
|  | 112 | max = pix_mp->num_planes; | 
|  | 113 | if (max > VIDEO_MAX_PLANES) | 
|  | 114 | max = VIDEO_MAX_PLANES; | 
|  | 115 | for (i = 0; i < max; i++) { | 
|  | 116 | if (i > 0) | 
|  | 117 | tprints(", "); | 
|  | 118 | tprintf("{sizeimage=%u, bytesperline=%u}", | 
|  | 119 | pix_mp->plane_fmt[i].sizeimage, | 
|  | 120 | pix_mp->plane_fmt[i].bytesperline); | 
|  | 121 | } | 
|  | 122 | tprintf("], num_planes=%u}", (unsigned) pix_mp->num_planes); | 
|  | 123 | break; | 
|  | 124 | } | 
|  | 125 | #endif | 
|  | 126 |  | 
|  | 127 | /* TODO: Complete this switch statement */ | 
|  | 128 | case V4L2_BUF_TYPE_VIDEO_OVERLAY: | 
| Dmitry V. Levin | 197db57 | 2015-01-09 04:53:19 +0000 | [diff] [blame] | 129 | #if HAVE_DECL_V4L2_BUF_TYPE_VIDEO_OUTPUT_OVERLAY | 
| Philippe De Muyter | 0cc9614 | 2014-11-03 21:27:40 +0100 | [diff] [blame] | 130 | case V4L2_BUF_TYPE_VIDEO_OUTPUT_OVERLAY: | 
| Dmitry V. Levin | 197db57 | 2015-01-09 04:53:19 +0000 | [diff] [blame] | 131 | #endif | 
| Philippe De Muyter | 0cc9614 | 2014-11-03 21:27:40 +0100 | [diff] [blame] | 132 | tprints("win={???}"); | 
|  | 133 | break; | 
|  | 134 |  | 
|  | 135 | case V4L2_BUF_TYPE_VBI_CAPTURE: | 
|  | 136 | case V4L2_BUF_TYPE_VBI_OUTPUT: | 
|  | 137 | tprints("vbi={???}"); | 
|  | 138 | break; | 
|  | 139 |  | 
|  | 140 | case V4L2_BUF_TYPE_SLICED_VBI_CAPTURE: | 
|  | 141 | case V4L2_BUF_TYPE_SLICED_VBI_OUTPUT: | 
|  | 142 | tprints("sliced={???}"); | 
|  | 143 | break; | 
|  | 144 |  | 
|  | 145 | default: | 
|  | 146 | tprints("???"); | 
|  | 147 | break; | 
|  | 148 | } | 
|  | 149 | } | 
|  | 150 |  | 
|  | 151 | int | 
| Dmitry V. Levin | c7afb48 | 2015-01-19 18:44:21 +0000 | [diff] [blame] | 152 | v4l2_ioctl(struct tcb *tcp, const unsigned int code, long arg) | 
| Philippe De Muyter | 0cc9614 | 2014-11-03 21:27:40 +0100 | [diff] [blame] | 153 | { | 
|  | 154 | if (!verbose(tcp)) | 
|  | 155 | return 0; | 
|  | 156 |  | 
|  | 157 | switch (code) { | 
|  | 158 | case VIDIOC_QUERYCAP: /* decode on exit */ { | 
|  | 159 | struct v4l2_capability caps; | 
|  | 160 |  | 
|  | 161 | if (entering(tcp) || syserror(tcp) || umove(tcp, arg, &caps) < 0) | 
|  | 162 | return 0; | 
| Dmitry V. Levin | 1de59cf | 2015-01-26 02:45:09 +0000 | [diff] [blame^] | 163 | tprints(", {driver="); | 
|  | 164 | print_quoted_string((const char *) caps.driver, | 
|  | 165 | sizeof(caps.driver), QUOTE_0_TERMINATED); | 
|  | 166 | tprints(", card="); | 
|  | 167 | print_quoted_string((const char *) caps.card, | 
|  | 168 | sizeof(caps.card), QUOTE_0_TERMINATED); | 
|  | 169 | tprints(", bus_info="); | 
|  | 170 | print_quoted_string((const char *) caps.bus_info, | 
|  | 171 | sizeof(caps.bus_info), QUOTE_0_TERMINATED); | 
|  | 172 | tprintf(", version=%u.%u.%u, capabilities=", | 
|  | 173 | (caps.version >> 16) & 0xFF, | 
|  | 174 | (caps.version >> 8) & 0xFF, | 
|  | 175 | caps.version & 0xFF); | 
| Philippe De Muyter | 0cc9614 | 2014-11-03 21:27:40 +0100 | [diff] [blame] | 176 | printflags(v4l2_device_capabilities_flags, caps.capabilities, | 
|  | 177 | "V4L2_CAP_???"); | 
|  | 178 | #ifdef V4L2_CAP_DEVICE_CAPS | 
|  | 179 | tprints(", device_caps="); | 
|  | 180 | printflags(v4l2_device_capabilities_flags, caps.device_caps, | 
|  | 181 | "V4L2_CAP_???"); | 
|  | 182 | #endif | 
|  | 183 | tprints("}"); | 
|  | 184 | return 1; | 
|  | 185 | } | 
|  | 186 |  | 
| Dmitry V. Levin | 197db57 | 2015-01-09 04:53:19 +0000 | [diff] [blame] | 187 | #ifdef VIDIOC_ENUM_FRAMESIZES | 
| Philippe De Muyter | 0cc9614 | 2014-11-03 21:27:40 +0100 | [diff] [blame] | 188 | case VIDIOC_ENUM_FRAMESIZES: /* decode on exit */ { | 
|  | 189 | struct v4l2_frmsizeenum s; | 
|  | 190 |  | 
|  | 191 | if (entering(tcp) || umove(tcp, arg, &s) < 0) | 
|  | 192 | return 0; | 
|  | 193 | tprintf(", {index=%u, pixel_format=", s.index); | 
|  | 194 | print_pixelformat(s.pixel_format); | 
|  | 195 |  | 
|  | 196 | if (!syserror(tcp)) { | 
|  | 197 | tprints(", type="); | 
|  | 198 | printxval(v4l2_framesize_types, s.type, "V4L2_FRMSIZE_TYPE_???"); | 
|  | 199 | switch (s.type) { | 
|  | 200 | case V4L2_FRMSIZE_TYPE_DISCRETE: | 
|  | 201 | tprintf(", discrete={width=%u, height=%u}", | 
|  | 202 | s.discrete.width, s.discrete.height); | 
|  | 203 | break; | 
|  | 204 | case V4L2_FRMSIZE_TYPE_STEPWISE: | 
|  | 205 | tprintf(", stepwise={min_width=%u, max_width=%u, " | 
|  | 206 | "step_width=%u, min_height=%u, max_height=%u, " | 
|  | 207 | "step_height=%u}", | 
|  | 208 | s.stepwise.min_width, s.stepwise.max_width, | 
|  | 209 | s.stepwise.step_width, s.stepwise.min_height, | 
|  | 210 | s.stepwise.max_height, s.stepwise.step_height); | 
|  | 211 | break; | 
|  | 212 | } | 
|  | 213 | } | 
|  | 214 | tprints("}"); | 
|  | 215 | return 1; | 
|  | 216 | } | 
| Dmitry V. Levin | 197db57 | 2015-01-09 04:53:19 +0000 | [diff] [blame] | 217 | #endif /* VIDIOC_ENUM_FRAMESIZES */ | 
| Philippe De Muyter | 0cc9614 | 2014-11-03 21:27:40 +0100 | [diff] [blame] | 218 |  | 
|  | 219 | case VIDIOC_G_FMT: | 
|  | 220 | case VIDIOC_S_FMT: | 
|  | 221 | case VIDIOC_TRY_FMT: { | 
|  | 222 | struct v4l2_format f; | 
|  | 223 |  | 
|  | 224 | if (umove(tcp, arg, &f) < 0) | 
|  | 225 | return 0; | 
|  | 226 | if (entering(tcp)) { | 
|  | 227 | tprints(", {type="); | 
|  | 228 | printxval(v4l2_buf_types, f.type, "V4L2_BUF_TYPE_???"); | 
|  | 229 | } | 
|  | 230 | if ((entering(tcp) && code != VIDIOC_G_FMT) | 
|  | 231 | || (exiting(tcp) && !syserror(tcp))) { | 
|  | 232 | tprints(exiting(tcp) && code != VIDIOC_G_FMT ? " => " : ", "); | 
|  | 233 | print_v4l2_format_fmt(&f); | 
|  | 234 | } | 
|  | 235 | if (exiting(tcp)) | 
|  | 236 | tprints("}"); | 
|  | 237 | return 1; | 
|  | 238 | } | 
|  | 239 |  | 
|  | 240 | case VIDIOC_ENUM_FMT: { | 
|  | 241 | struct v4l2_fmtdesc f; | 
|  | 242 |  | 
|  | 243 | if (entering(tcp) || umove(tcp, arg, &f) < 0) | 
|  | 244 | return 0; | 
|  | 245 |  | 
|  | 246 | tprintf(", {index=%u", f.index); | 
|  | 247 | if (!syserror(tcp)) { | 
|  | 248 | tprints(", type="); | 
|  | 249 | printxval(v4l2_buf_types, f.type, "V4L2_BUF_TYPE_???"); | 
|  | 250 | tprints(", flags="); | 
|  | 251 | printflags(v4l2_format_description_flags, f.flags, | 
|  | 252 | "V4L2_FMT_FLAG_???"); | 
| Dmitry V. Levin | 1de59cf | 2015-01-26 02:45:09 +0000 | [diff] [blame^] | 253 | tprints(", description="); | 
|  | 254 | print_quoted_string((const char *) f.description, | 
|  | 255 | sizeof(f.description), | 
|  | 256 | QUOTE_0_TERMINATED); | 
|  | 257 | tprints(", pixelformat="); | 
| Philippe De Muyter | 0cc9614 | 2014-11-03 21:27:40 +0100 | [diff] [blame] | 258 | print_pixelformat(f.pixelformat); | 
|  | 259 | } | 
|  | 260 | tprints("}"); | 
|  | 261 | return 1; | 
|  | 262 | } | 
|  | 263 |  | 
|  | 264 | case VIDIOC_G_PARM: | 
|  | 265 | case VIDIOC_S_PARM: { | 
|  | 266 | struct v4l2_streamparm s; | 
|  | 267 |  | 
|  | 268 | if (entering(tcp) && code == VIDIOC_G_PARM) | 
|  | 269 | return 1; | 
|  | 270 | if (exiting(tcp) && syserror(tcp)) | 
|  | 271 | return code == VIDIOC_S_PARM; | 
|  | 272 | if (umove(tcp, arg, &s) < 0) | 
|  | 273 | return 0; | 
|  | 274 | if (entering(tcp)) { | 
|  | 275 | tprints(", {type="); | 
|  | 276 | printxval(v4l2_buf_types, s.type, "V4L2_BUF_TYPE_???"); | 
|  | 277 | } | 
|  | 278 |  | 
|  | 279 | tprints(exiting(tcp) && code == VIDIOC_S_PARM ? " => {" : ", {"); | 
|  | 280 | if (s.type == V4L2_BUF_TYPE_VIDEO_CAPTURE) { | 
|  | 281 | struct v4l2_captureparm *cap = &s.parm.capture; | 
|  | 282 |  | 
|  | 283 | tprints("capability="); | 
|  | 284 | printflags(v4l2_streaming_capabilities, | 
|  | 285 | cap->capability, "V4L2_CAP_???"); | 
|  | 286 |  | 
|  | 287 | tprints(", capturemode="); | 
|  | 288 | printflags(v4l2_capture_modes, | 
|  | 289 | cap->capturemode, "V4L2_MODE_???"); | 
|  | 290 |  | 
|  | 291 | tprintf(", timeperframe=" FMT_FRACT, | 
|  | 292 | ARGS_FRACT(cap->timeperframe)); | 
|  | 293 |  | 
|  | 294 | tprintf(", extendedmode=%u, readbuffers=%u", | 
|  | 295 | cap->extendedmode, | 
|  | 296 | cap->readbuffers); | 
|  | 297 | } else | 
|  | 298 | tprints("..."); | 
|  | 299 | tprints("}"); | 
|  | 300 | if (exiting(tcp)) | 
|  | 301 | tprints("}"); | 
|  | 302 | return 1; | 
|  | 303 | } | 
|  | 304 |  | 
|  | 305 | case VIDIOC_QUERYCTRL: { | 
|  | 306 | struct v4l2_queryctrl c; | 
|  | 307 |  | 
|  | 308 | if (umove(tcp, arg, &c) < 0) | 
|  | 309 | return 0; | 
|  | 310 | /* 'id' field must be printed : | 
|  | 311 | * on enter | 
|  | 312 | * on exit if !syserror(tcp) && V4L2_CTRL_FLAG_NEXT_CTRL was set | 
|  | 313 | */ | 
|  | 314 | if (entering(tcp) | 
|  | 315 | || (exiting(tcp) && tcp->auxstr && !syserror(tcp))) { | 
|  | 316 | tprints(exiting(tcp) ? " => " : ", {id="); | 
|  | 317 | tcp->auxstr = (c.id & V4L2_CTRL_FLAG_NEXT_CTRL) ? "" : NULL; | 
|  | 318 | if (tcp->auxstr) { | 
|  | 319 | tprints("V4L2_CTRL_FLAG_NEXT_CTRL|"); | 
|  | 320 | c.id &= ~V4L2_CTRL_FLAG_NEXT_CTRL; | 
|  | 321 | } | 
|  | 322 | printxval(v4l2_control_ids, c.id, "V4L2_CID_???"); | 
|  | 323 | } | 
|  | 324 | if (exiting(tcp)) { | 
|  | 325 | if (!syserror(tcp)) { | 
|  | 326 | tprints(", type="); | 
|  | 327 | printxval(v4l2_control_types, c.type, | 
|  | 328 | "V4L2_CTRL_TYPE_???"); | 
| Dmitry V. Levin | 1de59cf | 2015-01-26 02:45:09 +0000 | [diff] [blame^] | 329 | tprints(", name="); | 
|  | 330 | print_quoted_string((const char *) c.name, | 
|  | 331 | sizeof(c.name), | 
|  | 332 | QUOTE_0_TERMINATED); | 
|  | 333 | tprintf(", minimum=%i, maximum=%i, step=%i, " | 
| Philippe De Muyter | 0cc9614 | 2014-11-03 21:27:40 +0100 | [diff] [blame] | 334 | "default_value=%i, flags=", | 
| Dmitry V. Levin | 1de59cf | 2015-01-26 02:45:09 +0000 | [diff] [blame^] | 335 | c.minimum, c.maximum, | 
| Philippe De Muyter | 0cc9614 | 2014-11-03 21:27:40 +0100 | [diff] [blame] | 336 | c.step, c.default_value); | 
|  | 337 | printflags(v4l2_control_flags, c.flags, | 
|  | 338 | "V4L2_CTRL_FLAG_???"); | 
|  | 339 | } | 
|  | 340 | tprints("}"); | 
|  | 341 | } | 
|  | 342 | return 1; | 
|  | 343 | } | 
|  | 344 |  | 
|  | 345 | case VIDIOC_G_CTRL: | 
|  | 346 | case VIDIOC_S_CTRL: { | 
|  | 347 | struct v4l2_control c; | 
|  | 348 |  | 
|  | 349 | if (entering(tcp) || umove(tcp, arg, &c) < 0) | 
|  | 350 | return 0; | 
|  | 351 | tprints(", {id="); | 
|  | 352 | printxval(v4l2_control_ids, c.id, "V4L2_CID_???"); | 
|  | 353 | if (!syserror(tcp) || code != VIDIOC_G_CTRL) | 
|  | 354 | tprintf(", value=%i", c.value); | 
|  | 355 | tprints("}"); | 
|  | 356 | return 1; | 
|  | 357 | } | 
|  | 358 |  | 
|  | 359 | case VIDIOC_S_EXT_CTRLS: | 
|  | 360 | case VIDIOC_TRY_EXT_CTRLS: | 
|  | 361 | case VIDIOC_G_EXT_CTRLS: { | 
|  | 362 | struct v4l2_ext_controls c; | 
|  | 363 | unsigned int n; | 
|  | 364 | bool must_print_values; | 
|  | 365 |  | 
|  | 366 | if (entering(tcp) && code == VIDIOC_G_EXT_CTRLS) | 
|  | 367 | return 0; | 
|  | 368 | if (exiting(tcp) && syserror(tcp) && code != VIDIOC_G_EXT_CTRLS) | 
|  | 369 | return 0; | 
|  | 370 | must_print_values = ((entering(tcp) && code != VIDIOC_G_EXT_CTRLS) | 
|  | 371 | || (exiting(tcp) && !syserror(tcp))); | 
|  | 372 | if (umove(tcp, arg, &c) < 0) | 
|  | 373 | return 0; | 
|  | 374 | tprints(code != VIDIOC_G_EXT_CTRLS && exiting(tcp) ? " => " : ", "); | 
|  | 375 | tprints("{ctrl_class="); | 
|  | 376 | printxval(v4l2_control_classes, c.ctrl_class, | 
|  | 377 | "V4L2_CTRL_CLASS_???"); | 
|  | 378 | tprintf(", count=%u", c.count); | 
|  | 379 | if (exiting(tcp) && syserror(tcp)) | 
|  | 380 | tprintf(", error_idx=%u", c.error_idx); | 
|  | 381 | tprints(", controls=["); | 
|  | 382 | for (n = 0; n < c.count; ++n) { | 
|  | 383 | struct v4l2_ext_control ctrl; | 
|  | 384 |  | 
|  | 385 | if (n > 0) | 
|  | 386 | tprints(", "); | 
|  | 387 | if (umove(tcp, (long) (c.controls + n), &ctrl) < 0) | 
|  | 388 | break; | 
|  | 389 | if (abbrev(tcp) && n == 2) { | 
|  | 390 | tprints("..."); | 
|  | 391 | break; | 
|  | 392 | } | 
|  | 393 | tprints("{id="); | 
|  | 394 | printxval(v4l2_control_ids, ctrl.id, "V4L2_CID_???"); | 
|  | 395 | #if HAVE_DECL_V4L2_CTRL_TYPE_STRING | 
|  | 396 | tprintf(", size=%u", ctrl.size); | 
|  | 397 | if (ctrl.size > 0) { | 
|  | 398 | if (must_print_values) { | 
|  | 399 | tprints(", string="); | 
|  | 400 | printstr(tcp, (long) ctrl.string, ctrl.size); | 
|  | 401 | } | 
|  | 402 | } else | 
|  | 403 | #endif | 
|  | 404 | { | 
|  | 405 | if (must_print_values) { | 
|  | 406 | tprintf(", value=%i, value64=%lli", ctrl.value, | 
|  | 407 | ctrl.value64); | 
|  | 408 | } | 
|  | 409 | } | 
|  | 410 | tprints("}"); | 
|  | 411 | } | 
|  | 412 | tprints("]}"); | 
|  | 413 | return 1; | 
|  | 414 | } | 
|  | 415 |  | 
|  | 416 | case VIDIOC_ENUMSTD: { | 
|  | 417 | struct v4l2_standard s; | 
|  | 418 |  | 
|  | 419 | if (umove(tcp, arg, &s) < 0) | 
|  | 420 | return 0; | 
|  | 421 | if (entering(tcp)) | 
|  | 422 | tprintf(", {index=%i", s.index); | 
|  | 423 | else { | 
|  | 424 | if (!syserror(tcp)) { | 
| Dmitry V. Levin | 1de59cf | 2015-01-26 02:45:09 +0000 | [diff] [blame^] | 425 | tprints(", name="); | 
|  | 426 | print_quoted_string((const char *) s.name, | 
|  | 427 | sizeof(s.name), | 
|  | 428 | QUOTE_0_TERMINATED); | 
| Philippe De Muyter | 0cc9614 | 2014-11-03 21:27:40 +0100 | [diff] [blame] | 429 | tprintf(", frameperiod=" FMT_FRACT, ARGS_FRACT(s.frameperiod)); | 
|  | 430 | tprintf(", framelines=%i", s.framelines); | 
|  | 431 | } | 
|  | 432 | tprints("}"); | 
|  | 433 | } | 
|  | 434 | return 1; | 
|  | 435 | } | 
|  | 436 |  | 
|  | 437 | case VIDIOC_G_STD: | 
|  | 438 | case VIDIOC_S_STD: { | 
|  | 439 | v4l2_std_id s; | 
|  | 440 |  | 
|  | 441 | if (code == VIDIOC_G_STD && exiting(tcp) && syserror(tcp)) | 
|  | 442 | return 0; | 
|  | 443 | if (umove(tcp, arg, &s) < 0) | 
|  | 444 | return 0; | 
|  | 445 | if ((code == VIDIOC_S_STD) == entering(tcp)) | 
|  | 446 | tprintf(", std=%#llx", s); | 
|  | 447 | return 1; | 
|  | 448 | } | 
|  | 449 |  | 
|  | 450 | case VIDIOC_ENUMINPUT: { | 
|  | 451 | struct v4l2_input i; | 
|  | 452 |  | 
|  | 453 | if (entering(tcp) || umove(tcp, arg, &i) < 0) | 
|  | 454 | return 0; | 
|  | 455 | tprintf(", {index=%i", i.index); | 
|  | 456 | if (!syserror(tcp)) { | 
| Dmitry V. Levin | 1de59cf | 2015-01-26 02:45:09 +0000 | [diff] [blame^] | 457 | tprints(", name="); | 
|  | 458 | print_quoted_string((const char *) i.name, | 
|  | 459 | sizeof(i.name), QUOTE_0_TERMINATED); | 
|  | 460 | tprints(", type="); | 
| Philippe De Muyter | 0cc9614 | 2014-11-03 21:27:40 +0100 | [diff] [blame] | 461 | printxval(v4l2_input_types, i.type, | 
|  | 462 | "V4L2_INPUT_TYPE_???"); | 
|  | 463 | } | 
|  | 464 | tprints("}"); | 
|  | 465 | return 1; | 
|  | 466 | } | 
|  | 467 |  | 
|  | 468 | case VIDIOC_G_INPUT: | 
|  | 469 | case VIDIOC_S_INPUT: { | 
|  | 470 | int index; | 
|  | 471 |  | 
|  | 472 | if (entering(tcp) || syserror(tcp) || umove(tcp, arg, &index) < 0) | 
|  | 473 | return 0; | 
|  | 474 |  | 
|  | 475 | tprintf(", index=%i", index); | 
|  | 476 | return 1; | 
|  | 477 | } | 
|  | 478 |  | 
| Dmitry V. Levin | 197db57 | 2015-01-09 04:53:19 +0000 | [diff] [blame] | 479 | #ifdef VIDIOC_ENUM_FRAMEINTERVALS | 
| Philippe De Muyter | 0cc9614 | 2014-11-03 21:27:40 +0100 | [diff] [blame] | 480 | case VIDIOC_ENUM_FRAMEINTERVALS: { | 
|  | 481 | struct v4l2_frmivalenum f; | 
|  | 482 |  | 
|  | 483 | if (entering(tcp) || umove(tcp, arg, &f) < 0) | 
|  | 484 | return 0; | 
|  | 485 | tprintf(", {index=%i, pixel_format=", f.index); | 
|  | 486 | print_pixelformat(f.pixel_format); | 
|  | 487 | tprintf(", width=%u, height=%u", f.width, f.height); | 
|  | 488 | if (!syserror(tcp)) { | 
|  | 489 | tprints(", type="); | 
|  | 490 | printxval(v4l2_frameinterval_types, f.type, | 
|  | 491 | "V4L2_FRMIVAL_TYPE_???"); | 
|  | 492 | switch (f.type) { | 
|  | 493 | case V4L2_FRMIVAL_TYPE_DISCRETE: | 
|  | 494 | tprintf(", discrete=" FMT_FRACT, | 
|  | 495 | ARGS_FRACT(f.discrete)); | 
|  | 496 | break; | 
|  | 497 | case V4L2_FRMIVAL_TYPE_STEPWISE: | 
|  | 498 | case V4L2_FRMSIZE_TYPE_CONTINUOUS: | 
|  | 499 | tprintf(", stepwise={min=" FMT_FRACT ", max=" | 
|  | 500 | FMT_FRACT ", step=" FMT_FRACT "}", | 
|  | 501 | ARGS_FRACT(f.stepwise.min), | 
|  | 502 | ARGS_FRACT(f.stepwise.max), | 
|  | 503 | ARGS_FRACT(f.stepwise.step)); | 
|  | 504 | break; | 
|  | 505 | } | 
|  | 506 | } | 
|  | 507 | tprints("}"); | 
|  | 508 | return 1; | 
|  | 509 | } | 
| Dmitry V. Levin | 197db57 | 2015-01-09 04:53:19 +0000 | [diff] [blame] | 510 | #endif /* VIDIOC_ENUM_FRAMEINTERVALS */ | 
| Philippe De Muyter | 0cc9614 | 2014-11-03 21:27:40 +0100 | [diff] [blame] | 511 |  | 
|  | 512 | case VIDIOC_CROPCAP: { | 
|  | 513 | struct v4l2_cropcap c; | 
|  | 514 |  | 
|  | 515 | if (entering(tcp) || umove(tcp, arg, &c) < 0) | 
|  | 516 | return 0; | 
|  | 517 | tprints(", type="); | 
|  | 518 | printxval(v4l2_buf_types, c.type, "V4L2_BUF_TYPE_???"); | 
|  | 519 | if (syserror(tcp)) | 
|  | 520 | return 1; | 
|  | 521 | tprintf(", bounds=" FMT_RECT ", defrect=" FMT_RECT ", " | 
|  | 522 | "pixelaspect=" FMT_FRACT, ARGS_RECT(c.bounds), | 
|  | 523 | ARGS_RECT(c.defrect), ARGS_FRACT(c.pixelaspect)); | 
|  | 524 | return 1; | 
|  | 525 | } | 
|  | 526 |  | 
|  | 527 | case VIDIOC_G_FBUF: | 
|  | 528 | case VIDIOC_S_FBUF: { | 
|  | 529 | struct v4l2_framebuffer b; | 
|  | 530 |  | 
|  | 531 | if (syserror(tcp) && code == VIDIOC_G_FBUF) | 
|  | 532 | return 0; | 
|  | 533 | if (entering(tcp) || umove(tcp, arg, &b) < 0) | 
|  | 534 | return 0; | 
|  | 535 | tprintf(", {capability=%x, flags=%x, base=%p}", | 
|  | 536 | b.capability, b.flags, b.base); | 
|  | 537 | return 1; | 
|  | 538 | } | 
|  | 539 |  | 
|  | 540 | case VIDIOC_REQBUFS: { | 
|  | 541 | struct v4l2_requestbuffers reqbufs; | 
|  | 542 |  | 
|  | 543 | if (umove(tcp, arg, &reqbufs) < 0) | 
|  | 544 | return 0; | 
|  | 545 | if (entering(tcp)) { | 
|  | 546 | tprintf(", {count=%u, type=", reqbufs.count); | 
|  | 547 | printxval(v4l2_buf_types, reqbufs.type, "V4L2_BUF_TYPE_???"); | 
|  | 548 | tprints(", memory="); | 
|  | 549 | printxval(v4l2_memories, reqbufs.memory, "V4L2_MEMORY_???"); | 
|  | 550 | tprints("}"); | 
|  | 551 | return 1; | 
|  | 552 | } else if (syserror(tcp)) | 
|  | 553 | return 1; | 
|  | 554 | else { | 
|  | 555 | static char outstr[sizeof("{count=}") + sizeof(int) * 3]; | 
|  | 556 |  | 
|  | 557 | sprintf(outstr, "{count=%u}", reqbufs.count); | 
|  | 558 | tcp->auxstr = outstr; | 
|  | 559 | return 1 + RVAL_STR; | 
|  | 560 | } | 
|  | 561 | } | 
|  | 562 |  | 
|  | 563 | case VIDIOC_QUERYBUF: | 
|  | 564 | case VIDIOC_QBUF: | 
|  | 565 | case VIDIOC_DQBUF: { | 
|  | 566 | struct v4l2_buffer b; | 
|  | 567 |  | 
|  | 568 | if (umove(tcp, arg, &b) < 0) | 
|  | 569 | return 0; | 
|  | 570 | if (entering(tcp)) { | 
|  | 571 | tprints(", {type="); | 
|  | 572 | printxval(v4l2_buf_types, b.type, "V4L2_BUF_TYPE_???"); | 
|  | 573 | if (code != VIDIOC_DQBUF) | 
|  | 574 | tprintf(", index=%u", b.index); | 
|  | 575 | } else { | 
|  | 576 | if (!syserror(tcp)) { | 
|  | 577 | if (code == VIDIOC_DQBUF) | 
|  | 578 | tprintf(", index=%u", b.index); | 
|  | 579 | tprints(", memory="); | 
|  | 580 | printxval(v4l2_memories, b.memory, "V4L2_MEMORY_???"); | 
|  | 581 |  | 
|  | 582 | if (b.memory == V4L2_MEMORY_MMAP) { | 
|  | 583 | tprintf(", m.offset=%#x", b.m.offset); | 
|  | 584 | } else if (b.memory == V4L2_MEMORY_USERPTR) { | 
|  | 585 | tprintf(", m.userptr=%#lx", b.m.userptr); | 
|  | 586 | } | 
|  | 587 |  | 
|  | 588 | tprintf(", length=%u, bytesused=%u, flags=", | 
|  | 589 | b.length, b.bytesused); | 
|  | 590 | printflags(v4l2_buf_flags, b.flags, "V4L2_BUF_FLAG_???"); | 
|  | 591 | if (code == VIDIOC_DQBUF) | 
|  | 592 | tprintf(", timestamp = {%lu.%06lu}", | 
|  | 593 | b.timestamp.tv_sec, | 
|  | 594 | b.timestamp.tv_usec); | 
|  | 595 | tprints(", ..."); | 
|  | 596 | } | 
|  | 597 | tprints("}"); | 
|  | 598 | } | 
|  | 599 | return 1; | 
|  | 600 | } | 
|  | 601 |  | 
|  | 602 | case VIDIOC_STREAMON: | 
|  | 603 | case VIDIOC_STREAMOFF: { | 
|  | 604 | int type; | 
|  | 605 |  | 
|  | 606 | if (umove(tcp, arg, &type) < 0) | 
|  | 607 | return 0; | 
|  | 608 | if (entering(tcp)) { | 
|  | 609 | tprints(", "); | 
|  | 610 | printxval(v4l2_buf_types, type, "V4L2_BUF_TYPE_???"); | 
|  | 611 | } | 
|  | 612 | return 1; | 
|  | 613 | } | 
|  | 614 |  | 
|  | 615 | default: /* decode on exit */ | 
|  | 616 | return 0; | 
|  | 617 | } | 
|  | 618 | } |