(root)/
strace-6.5/
src/
v4l2.c
       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   * Copyright (c) 2014-2023 The strace developers.
       6   * All rights reserved.
       7   *
       8   * SPDX-License-Identifier: LGPL-2.1-or-later
       9   */
      10  
      11  #include "defs.h"
      12  
      13  #include DEF_MPERS_TYPE(kernel_v4l2_buffer_t)
      14  #include DEF_MPERS_TYPE(kernel_v4l2_event_t)
      15  #include DEF_MPERS_TYPE(kernel_v4l2_timeval_t)
      16  #include DEF_MPERS_TYPE(struct_v4l2_clip)
      17  #include DEF_MPERS_TYPE(struct_v4l2_create_buffers)
      18  #include DEF_MPERS_TYPE(struct_v4l2_ext_control)
      19  #include DEF_MPERS_TYPE(struct_v4l2_ext_controls)
      20  #include DEF_MPERS_TYPE(struct_v4l2_format)
      21  #include DEF_MPERS_TYPE(struct_v4l2_framebuffer)
      22  #include DEF_MPERS_TYPE(struct_v4l2_input)
      23  #include DEF_MPERS_TYPE(struct_v4l2_standard)
      24  #include DEF_MPERS_TYPE(struct_v4l2_window)
      25  
      26  #include "kernel_v4l2_types.h"
      27  typedef struct v4l2_clip struct_v4l2_clip;
      28  typedef struct v4l2_create_buffers struct_v4l2_create_buffers;
      29  typedef struct v4l2_ext_control struct_v4l2_ext_control;
      30  typedef struct v4l2_ext_controls struct_v4l2_ext_controls;
      31  typedef struct v4l2_format struct_v4l2_format;
      32  typedef struct v4l2_framebuffer struct_v4l2_framebuffer;
      33  typedef struct v4l2_input struct_v4l2_input;
      34  typedef struct v4l2_standard struct_v4l2_standard;
      35  typedef struct v4l2_window struct_v4l2_window;
      36  
      37  #include MPERS_DEFS
      38  
      39  #include "print_utils.h"
      40  #include "xstring.h"
      41  
      42  #include "xlat/v4l2_meta_fmts.h"
      43  #include "xlat/v4l2_pix_fmts.h"
      44  #include "xlat/v4l2_sdr_fmts.h"
      45  
      46  static void
      47  print_v4l2_rect(const MPERS_PTR_ARG(struct v4l2_rect *) const arg)
      48  {
      49  	const struct v4l2_rect *const p = arg;
      50  	tprint_struct_begin();
      51  	PRINT_FIELD_D(*p, left);
      52  	tprint_struct_next();
      53  	PRINT_FIELD_D(*p, top);
      54  	tprint_struct_next();
      55  	PRINT_FIELD_U(*p, width);
      56  	tprint_struct_next();
      57  	PRINT_FIELD_U(*p, height);
      58  	tprint_struct_end();
      59  }
      60  
      61  #define PRINT_FIELD_FRACT(where_, field_)			\
      62  	do {							\
      63  		tprints_field_name(#field_);			\
      64  		tprintf_string("%u/%u",				\
      65  			      (where_).field_.numerator,	\
      66  			      (where_).field_.denominator);	\
      67  	} while (0)
      68  
      69  static void
      70  print_pixelformat(uint32_t fourcc, const struct xlat *xlat)
      71  {
      72  	if (xlat_verbose(xlat_verbosity) == XLAT_STYLE_RAW) {
      73  		PRINT_VAL_X(fourcc);
      74  		return;
      75  	}
      76  
      77  	unsigned char a[] = {
      78  		(unsigned char) fourcc,
      79  		(unsigned char) (fourcc >> 8),
      80  		(unsigned char) (fourcc >> 16),
      81  		(unsigned char) (fourcc >> 24),
      82  	};
      83  
      84  	tprints_arg_begin("v4l2_fourcc");
      85  	/* Generic char array printing routine.  */
      86  	for (unsigned int i = 0; i < ARRAY_SIZE(a); ++i) {
      87  		unsigned char c = a[i];
      88  
      89  		if (i)
      90  			tprint_arg_next();
      91  
      92  		print_char(c, SCF_QUOTES);
      93  	}
      94  	tprint_arg_end();
      95  
      96  	if (xlat) {
      97  		const char *pixfmt_name = xlookup(xlat, fourcc);
      98  
      99  		if (pixfmt_name)
     100  			tprints_comment(pixfmt_name);
     101  	}
     102  }
     103  
     104  #define PRINT_FIELD_PIXFMT(where_, field_, xlat_)	\
     105  	do {							\
     106  		tprints_field_name(#field_);			\
     107  		print_pixelformat((where_).field_, (xlat_));	\
     108  	} while (0)
     109  
     110  #include "xlat/v4l2_device_capabilities_flags.h"
     111  
     112  static int
     113  print_v4l2_capability(struct tcb *const tcp, const kernel_ulong_t arg)
     114  {
     115  	struct v4l2_capability caps;
     116  
     117  	if (entering(tcp))
     118  		return 0;
     119  
     120  	tprint_arg_next();
     121  	if (umove_or_printaddr(tcp, arg, &caps))
     122  		return RVAL_IOCTL_DECODED;
     123  
     124  	tprint_struct_begin();
     125  	PRINT_FIELD_CSTRING(caps, driver);
     126  	tprint_struct_next();
     127  	PRINT_FIELD_CSTRING(caps, card);
     128  	tprint_struct_next();
     129  	PRINT_FIELD_CSTRING(caps, bus_info);
     130  	tprint_struct_next();
     131  	PRINT_FIELD_OBJ_VAL(caps, version, print_kernel_version);
     132  	tprint_struct_next();
     133  	PRINT_FIELD_FLAGS(caps, capabilities,
     134  			  v4l2_device_capabilities_flags, "V4L2_CAP_???");
     135  	if (caps.device_caps) {
     136  		tprint_struct_next();
     137  		PRINT_FIELD_FLAGS(caps, device_caps,
     138  				  v4l2_device_capabilities_flags,
     139  				  "V4L2_CAP_???");
     140  	}
     141  	tprint_struct_end();
     142  	return RVAL_IOCTL_DECODED;
     143  }
     144  
     145  #include "xlat/v4l2_buf_types.h"
     146  #include "xlat/v4l2_format_description_flags.h"
     147  
     148  static int
     149  print_v4l2_fmtdesc(struct tcb *const tcp, const kernel_ulong_t arg)
     150  {
     151  	struct v4l2_fmtdesc f;
     152  
     153  	if (entering(tcp)) {
     154  		tprint_arg_next();
     155  		if (umove_or_printaddr(tcp, arg, &f))
     156  			return RVAL_IOCTL_DECODED;
     157  
     158  		tprint_struct_begin();
     159  		PRINT_FIELD_U(f, index);
     160  		tprint_struct_next();
     161  		PRINT_FIELD_XVAL(f, type, v4l2_buf_types,
     162  				 "V4L2_BUF_TYPE_???");
     163  		return 0;
     164  	}
     165  
     166  	if (!syserror(tcp) && !umove(tcp, arg, &f)) {
     167  		tprint_struct_next();
     168  		PRINT_FIELD_FLAGS(f, flags,
     169  				  v4l2_format_description_flags,
     170  				  "V4L2_FMT_FLAG_???");
     171  		tprint_struct_next();
     172  		PRINT_FIELD_CSTRING(f, description);
     173  		tprint_struct_next();
     174  		PRINT_FIELD_PIXFMT(f, pixelformat, v4l2_pix_fmts);
     175  	}
     176  	tprint_struct_end();
     177  	return RVAL_IOCTL_DECODED;
     178  }
     179  
     180  #include "xlat/v4l2_fields.h"
     181  #include "xlat/v4l2_colorspaces.h"
     182  #include "xlat/v4l2_vbi_flags.h"
     183  #include "xlat/v4l2_sliced_flags.h"
     184  
     185  static bool
     186  print_v4l2_clip(struct tcb *tcp, void *elem_buf, size_t elem_size, void *data)
     187  {
     188  	const struct_v4l2_clip *p = elem_buf;
     189  	tprint_struct_begin();
     190  	PRINT_FIELD_OBJ_PTR(*p, c, print_v4l2_rect);
     191  	tprint_struct_end();
     192  	return true;
     193  }
     194  
     195  #define DECL_print_v4l2_format_fmt(name_)				\
     196  	print_v4l2_format_fmt_ ## name_(struct tcb *const tcp,		\
     197  		const typeof_field(struct_v4l2_format, fmt.name_) *const p)
     198  
     199  static bool
     200  DECL_print_v4l2_format_fmt(pix)
     201  {
     202  	tprint_struct_begin();
     203  	PRINT_FIELD_U(*p, width);
     204  	tprint_struct_next();
     205  	PRINT_FIELD_U(*p, height);
     206  	tprint_struct_next();
     207  	PRINT_FIELD_PIXFMT(*p, pixelformat, v4l2_pix_fmts);
     208  	tprint_struct_next();
     209  	PRINT_FIELD_XVAL(*p, field, v4l2_fields, "V4L2_FIELD_???");
     210  	tprint_struct_next();
     211  	PRINT_FIELD_U(*p, bytesperline);
     212  	tprint_struct_next();
     213  	PRINT_FIELD_U(*p, sizeimage);
     214  	tprint_struct_next();
     215  	PRINT_FIELD_XVAL(*p, colorspace, v4l2_colorspaces,
     216  			 "V4L2_COLORSPACE_???");
     217  	tprint_struct_end();
     218  	return true;
     219  }
     220  
     221  static bool
     222  print_v4l2_plane_pix_format_array_member(struct tcb *tcp, void *elem_buf,
     223  					 size_t elem_size, void *data)
     224  {
     225  	struct v4l2_plane_pix_format *p = elem_buf;
     226  
     227  	tprint_struct_begin();
     228  	PRINT_FIELD_U(*p, sizeimage);
     229  	tprint_struct_next();
     230  	PRINT_FIELD_U(*p, bytesperline);
     231  	tprint_struct_end();
     232  
     233  	return true;
     234  }
     235  
     236  static bool
     237  DECL_print_v4l2_format_fmt(pix_mp)
     238  {
     239  	tprint_struct_begin();
     240  	PRINT_FIELD_U(*p, width);
     241  	tprint_struct_next();
     242  	PRINT_FIELD_U(*p, height);
     243  	tprint_struct_next();
     244  	PRINT_FIELD_PIXFMT(*p, pixelformat, v4l2_pix_fmts);
     245  	tprint_struct_next();
     246  	PRINT_FIELD_XVAL(*p, field, v4l2_fields, "V4L2_FIELD_???");
     247  	tprint_struct_next();
     248  	PRINT_FIELD_XVAL(*p, colorspace, v4l2_colorspaces,
     249  			 "V4L2_COLORSPACE_???");
     250  	tprint_struct_next();
     251  	PRINT_FIELD_ARRAY_UPTO(*p, plane_fmt, p->num_planes, tcp,
     252  			       print_v4l2_plane_pix_format_array_member);
     253  	tprint_struct_next();
     254  	PRINT_FIELD_U(*p, num_planes);
     255  	tprint_struct_end();
     256  	return true;
     257  }
     258  
     259  static bool
     260  DECL_print_v4l2_format_fmt(win)
     261  {
     262  	tprint_struct_begin();
     263  	PRINT_FIELD_OBJ_PTR(*p, w, print_v4l2_rect);
     264  	tprint_struct_next();
     265  	PRINT_FIELD_XVAL(*p, field, v4l2_fields, "V4L2_FIELD_???");
     266  	tprint_struct_next();
     267  	PRINT_FIELD_X(*p, chromakey);
     268  
     269  	tprint_struct_next();
     270  	tprints_field_name("clips");
     271  	struct_v4l2_clip clip;
     272  	bool rc = print_array(tcp, ptr_to_kulong(p->clips),
     273  			   p->clipcount, &clip, sizeof(clip),
     274  			   tfetch_mem, print_v4l2_clip, 0);
     275  
     276  	tprint_struct_next();
     277  	PRINT_FIELD_U(*p, clipcount);
     278  	tprint_struct_next();
     279  	PRINT_FIELD_PTR(*p, bitmap);
     280  	if (p->global_alpha) {
     281  		tprint_struct_next();
     282  		PRINT_FIELD_X(*p, global_alpha);
     283  	}
     284  	tprint_struct_end();
     285  	return rc;
     286  }
     287  
     288  static bool
     289  DECL_print_v4l2_format_fmt(vbi)
     290  {
     291  	tprint_struct_begin();
     292  	PRINT_FIELD_U(*p, sampling_rate);
     293  	tprint_struct_next();
     294  	PRINT_FIELD_U(*p, offset);
     295  	tprint_struct_next();
     296  	PRINT_FIELD_U(*p, samples_per_line);
     297  	tprint_struct_next();
     298  	PRINT_FIELD_PIXFMT(*p, sample_format, v4l2_pix_fmts);
     299  	tprint_struct_next();
     300  	PRINT_FIELD_D_ARRAY(*p, start);
     301  	tprint_struct_next();
     302  	PRINT_FIELD_U_ARRAY(*p, count);
     303  	tprint_struct_next();
     304  	PRINT_FIELD_FLAGS(*p, flags, v4l2_vbi_flags, "V4L2_VBI_???");
     305  	tprint_struct_end();
     306  	return true;
     307  }
     308  
     309  static bool
     310  DECL_print_v4l2_format_fmt(sliced)
     311  {
     312  	tprint_struct_begin();
     313  	PRINT_FIELD_FLAGS(*p, service_set, v4l2_sliced_flags,
     314  			  "V4L2_SLICED_???");
     315  	tprint_struct_next();
     316  	PRINT_FIELD_X_ARRAY2D(*p, service_lines);
     317  	tprint_struct_next();
     318  	PRINT_FIELD_U(*p, io_size);
     319  	tprint_struct_end();
     320  	return true;
     321  }
     322  
     323  static bool
     324  DECL_print_v4l2_format_fmt(sdr)
     325  {
     326  	tprint_struct_begin();
     327  	PRINT_FIELD_PIXFMT(*p, pixelformat, v4l2_sdr_fmts);
     328  	if (p->buffersize) {
     329  		tprint_struct_next();
     330  		PRINT_FIELD_U(*p, buffersize);
     331  	}
     332  	tprint_struct_end();
     333  	return true;
     334  }
     335  
     336  static bool
     337  DECL_print_v4l2_format_fmt(meta)
     338  {
     339  	tprint_struct_begin();
     340  	PRINT_FIELD_PIXFMT(*p, dataformat, v4l2_meta_fmts);
     341  	tprint_struct_next();
     342  	PRINT_FIELD_U(*p, buffersize);
     343  	tprint_struct_end();
     344  	return true;
     345  }
     346  
     347  #define PRINT_FIELD_V4L2_FORMAT_FMT(where_, fmt_, field_, tcp_, ret_)	\
     348  	do {								\
     349  		tprints_field_name(#fmt_ "." #field_);			\
     350  		(ret_) = (print_v4l2_format_fmt_ ## field_)		\
     351  				((tcp_), &((where_).fmt_.field_));	\
     352  	} while (0)
     353  
     354  static bool
     355  print_v4l2_format_fmt(struct tcb *const tcp, void (*const prefix_fun)(void),
     356  		      const struct_v4l2_format *const f)
     357  {
     358  	bool ret = true;
     359  	switch (f->type) {
     360  	case V4L2_BUF_TYPE_VIDEO_CAPTURE:
     361  	case V4L2_BUF_TYPE_VIDEO_OUTPUT:
     362  		prefix_fun();
     363  		PRINT_FIELD_V4L2_FORMAT_FMT(*f, fmt, pix, tcp, ret);
     364  		break;
     365  
     366  	case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE:
     367  	case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE:
     368  		prefix_fun();
     369  		PRINT_FIELD_V4L2_FORMAT_FMT(*f, fmt, pix_mp, tcp, ret);
     370  		break;
     371  
     372  	/* OUTPUT_OVERLAY since Linux v2.6.22-rc1~1118^2~179 */
     373  	case V4L2_BUF_TYPE_VIDEO_OUTPUT_OVERLAY:
     374  	case V4L2_BUF_TYPE_VIDEO_OVERLAY:
     375  		prefix_fun();
     376  		PRINT_FIELD_V4L2_FORMAT_FMT(*f, fmt, win, tcp, ret);
     377  		break;
     378  
     379  	case V4L2_BUF_TYPE_VBI_CAPTURE:
     380  	case V4L2_BUF_TYPE_VBI_OUTPUT:
     381  		prefix_fun();
     382  		PRINT_FIELD_V4L2_FORMAT_FMT(*f, fmt, vbi, tcp, ret);
     383  		break;
     384  
     385  	/* both since Linux v2.6.14-rc2~64 */
     386  	case V4L2_BUF_TYPE_SLICED_VBI_CAPTURE:
     387  	case V4L2_BUF_TYPE_SLICED_VBI_OUTPUT:
     388  		prefix_fun();
     389  		PRINT_FIELD_V4L2_FORMAT_FMT(*f, fmt, sliced, tcp, ret);
     390  		break;
     391  
     392  	/* since Linux v4.4-rc1~118^2~14 */
     393  	case V4L2_BUF_TYPE_SDR_OUTPUT:
     394  	/* since Linux v3.15-rc1~85^2~213 */
     395  	case V4L2_BUF_TYPE_SDR_CAPTURE:
     396  		prefix_fun();
     397  		PRINT_FIELD_V4L2_FORMAT_FMT(*f, fmt, sdr, tcp, ret);
     398  		break;
     399  	/* since Linux v5.0-rc1~181^2~21 */
     400  	case V4L2_BUF_TYPE_META_OUTPUT:
     401  	/* since Linux v4.12-rc1~85^2~71 */
     402  	case V4L2_BUF_TYPE_META_CAPTURE:
     403  		prefix_fun();
     404  		PRINT_FIELD_V4L2_FORMAT_FMT(*f, fmt, meta, tcp, ret);
     405  		break;
     406  	default:
     407  		return false;
     408  	}
     409  	return ret;
     410  }
     411  
     412  static void
     413  tprint_struct_end_value_changed_struct_begin(void)
     414  {
     415  	tprint_struct_end();
     416  	tprint_value_changed();
     417  	tprint_struct_begin();
     418  }
     419  
     420  static int
     421  print_v4l2_format(struct tcb *const tcp, const kernel_ulong_t arg,
     422  		  const bool is_get)
     423  {
     424  	struct_v4l2_format f;
     425  
     426  	if (entering(tcp)) {
     427  		tprint_arg_next();
     428  		if (umove_or_printaddr(tcp, arg, &f))
     429  			return RVAL_IOCTL_DECODED;
     430  
     431  		tprint_struct_begin();
     432  		PRINT_FIELD_XVAL(f, type, v4l2_buf_types,
     433  				 "V4L2_BUF_TYPE_???");
     434  		if (is_get)
     435  			return 0;
     436  		if (!print_v4l2_format_fmt(tcp, tprint_struct_next, &f)) {
     437  			tprint_struct_end();
     438  			return RVAL_IOCTL_DECODED;
     439  		}
     440  
     441  		return 0;
     442  	}
     443  
     444  	if (!syserror(tcp) && !umove(tcp, arg, &f)) {
     445  		void (*const prefix_fun)(void) =
     446  			is_get ? tprint_struct_next :
     447  			tprint_struct_end_value_changed_struct_begin;
     448  		print_v4l2_format_fmt(tcp, prefix_fun, &f);
     449  	}
     450  
     451  	tprint_struct_end();
     452  
     453  	return RVAL_IOCTL_DECODED;
     454  }
     455  
     456  #include "xlat/v4l2_memories.h"
     457  
     458  static int
     459  print_v4l2_requestbuffers(struct tcb *const tcp, const kernel_ulong_t arg)
     460  {
     461  	struct v4l2_requestbuffers reqbufs;
     462  
     463  	if (entering(tcp)) {
     464  		tprint_arg_next();
     465  		if (umove_or_printaddr(tcp, arg, &reqbufs))
     466  			return RVAL_IOCTL_DECODED;
     467  
     468  		tprint_struct_begin();
     469  		PRINT_FIELD_XVAL(reqbufs, type, v4l2_buf_types,
     470  				 "V4L2_BUF_TYPE_???");
     471  		tprint_struct_next();
     472  		PRINT_FIELD_XVAL(reqbufs, memory, v4l2_memories,
     473  				 "V4L2_MEMORY_???");
     474  		tprint_struct_next();
     475  		PRINT_FIELD_U(reqbufs, count);
     476  
     477  		return 0;
     478  	}
     479  
     480  	if (!syserror(tcp) && !umove(tcp, arg, &reqbufs)) {
     481  		tprint_value_changed();
     482  		PRINT_VAL_U(reqbufs.count);
     483  	}
     484  
     485  	tprint_struct_end();
     486  
     487  	return RVAL_IOCTL_DECODED;
     488  }
     489  
     490  #include "xlat/v4l2_buf_flags.h"
     491  #include "xlat/v4l2_buf_flags_ts_type.h"
     492  #include "xlat/v4l2_buf_flags_ts_src.h"
     493  
     494  static void
     495  print_v4l2_buffer_flags(uint32_t val)
     496  {
     497  	const uint32_t ts_type = val & V4L2_BUF_FLAG_TIMESTAMP_MASK;
     498  	const uint32_t ts_src  = val & V4L2_BUF_FLAG_TSTAMP_SRC_MASK;
     499  	const uint32_t flags   = val & ~ts_type & ~ts_src;
     500  
     501  	if (xlat_verbose(xlat_verbosity) == XLAT_STYLE_RAW) {
     502  		PRINT_VAL_X(val);
     503  		return;
     504  	}
     505  
     506  	tprint_flags_begin();
     507  	if (flags) {
     508  		printflags_in(v4l2_buf_flags, flags, "V4L2_BUF_FLAG_???");
     509  		tprint_flags_or();
     510  	}
     511  	printxval(v4l2_buf_flags_ts_type, ts_type,
     512  		  "V4L2_BUF_FLAG_TIMESTAMP_???");
     513  	tprint_flags_or();
     514  	printxval(v4l2_buf_flags_ts_src, ts_src,
     515  		  "V4L2_BUF_FLAG_TSTAMP_SRC_???");
     516  	tprint_flags_end();
     517  }
     518  
     519  #define PRINT_FIELD_V4L2_BUFFER_FLAGS(where_, field_)		\
     520  	do {							\
     521  		tprints_field_name(#field_);			\
     522  		print_v4l2_buffer_flags((where_).field_);	\
     523  	} while (0)
     524  
     525  static void
     526  print_v4l2_timeval(const MPERS_PTR_ARG(kernel_v4l2_timeval_t *) const arg)
     527  {
     528  	const kernel_v4l2_timeval_t *const t = arg;
     529  	kernel_timeval64_t tv;
     530  
     531  	if (sizeof(tv.tv_sec) == sizeof(t->tv_sec) &&
     532  	    sizeof(tv.tv_usec) == sizeof(t->tv_usec)) {
     533  		print_timeval64_data_size(t, sizeof(*t));
     534  	} else {
     535  		tv.tv_sec = sign_extend_unsigned_to_ll(t->tv_sec);
     536  		tv.tv_usec = zero_extend_signed_to_ull(t->tv_usec);
     537  		print_timeval64_data_size(&tv, sizeof(tv));
     538  	}
     539  }
     540  
     541  #define PRINT_FIELD_V4L2_TIMEVAL(where_, field_)	\
     542  	do {						\
     543  		tprints_field_name(#field_);		\
     544  		print_v4l2_timeval(&((where_).field_));	\
     545  	} while (0)
     546  
     547  static int
     548  print_v4l2_buffer(struct tcb *const tcp, const unsigned int code,
     549  		  const kernel_ulong_t arg)
     550  {
     551  	kernel_v4l2_buffer_t b;
     552  
     553  	if (entering(tcp)) {
     554  		tprint_arg_next();
     555  		if (umove_or_printaddr(tcp, arg, &b))
     556  			return RVAL_IOCTL_DECODED;
     557  
     558  		tprint_struct_begin();
     559  		PRINT_FIELD_XVAL(b, type, v4l2_buf_types,
     560  				 "V4L2_BUF_TYPE_???");
     561  		if (code != VIDIOC_DQBUF) {
     562  			tprint_struct_next();
     563  			PRINT_FIELD_U(b, index);
     564  		}
     565  
     566  		return 0;
     567  	}
     568  
     569  	if (!syserror(tcp) && !umove(tcp, arg, &b)) {
     570  		if (code == VIDIOC_DQBUF) {
     571  			tprint_struct_next();
     572  			PRINT_FIELD_U(b, index);
     573  		}
     574  		tprint_struct_next();
     575  		PRINT_FIELD_XVAL(b, memory, v4l2_memories,
     576  				 "V4L2_MEMORY_???");
     577  
     578  		if (b.memory == V4L2_MEMORY_MMAP) {
     579  			tprint_struct_next();
     580  			PRINT_FIELD_X(b, m.offset);
     581  		} else if (b.memory == V4L2_MEMORY_USERPTR) {
     582  			tprint_struct_next();
     583  			PRINT_FIELD_PTR(b, m.userptr);
     584  		}
     585  
     586  		tprint_struct_next();
     587  		PRINT_FIELD_U(b, length);
     588  		tprint_struct_next();
     589  		PRINT_FIELD_U(b, bytesused);
     590  		tprint_struct_next();
     591  		PRINT_FIELD_V4L2_BUFFER_FLAGS(b, flags);
     592  		if (code == VIDIOC_DQBUF) {
     593  			tprint_struct_next();
     594  			PRINT_FIELD_V4L2_TIMEVAL(b, timestamp);
     595  		}
     596  		tprint_struct_next();
     597  		tprint_more_data_follows();
     598  	}
     599  
     600  	tprint_struct_end();
     601  
     602  	return RVAL_IOCTL_DECODED;
     603  }
     604  
     605  static int
     606  print_v4l2_framebuffer(struct tcb *const tcp, const kernel_ulong_t arg)
     607  {
     608  	struct_v4l2_framebuffer b;
     609  
     610  	tprint_arg_next();
     611  	if (!umove_or_printaddr(tcp, arg, &b)) {
     612  		tprint_struct_begin();
     613  		PRINT_FIELD_X(b, capability);
     614  		tprint_struct_next();
     615  		PRINT_FIELD_X(b, flags);
     616  		tprint_struct_next();
     617  		PRINT_FIELD_PTR(b, base);
     618  		tprint_struct_end();
     619  	}
     620  
     621  	return RVAL_IOCTL_DECODED;
     622  }
     623  
     624  static int
     625  print_v4l2_buf_type(struct tcb *const tcp, const kernel_ulong_t arg)
     626  {
     627  	int type;
     628  
     629  	tprint_arg_next();
     630  	if (!umove_or_printaddr(tcp, arg, &type)) {
     631  		tprint_indirect_begin();
     632  		printxval(v4l2_buf_types, type, "V4L2_BUF_TYPE_???");
     633  		tprint_indirect_end();
     634  	}
     635  	return RVAL_IOCTL_DECODED;
     636  }
     637  
     638  #include "xlat/v4l2_streaming_capabilities.h"
     639  #include "xlat/v4l2_capture_modes.h"
     640  
     641  static void
     642  print_v4l2_streamparm_capture(const struct v4l2_captureparm *const p)
     643  {
     644  	tprint_struct_begin();
     645  	PRINT_FIELD_FLAGS(*p, capability, v4l2_streaming_capabilities,
     646  			  "V4L2_CAP_???");
     647  	tprint_struct_next();
     648  	PRINT_FIELD_FLAGS(*p, capturemode, v4l2_capture_modes,
     649  			  "V4L2_MODE_???");
     650  	tprint_struct_next();
     651  	PRINT_FIELD_FRACT(*p, timeperframe);
     652  	tprint_struct_next();
     653  	PRINT_FIELD_X(*p, extendedmode);
     654  	tprint_struct_next();
     655  	PRINT_FIELD_U(*p, readbuffers);
     656  	tprint_struct_end();
     657  }
     658  
     659  static void
     660  print_v4l2_streamparm_output(const struct v4l2_outputparm *const p)
     661  {
     662  	tprint_struct_begin();
     663  	PRINT_FIELD_FLAGS(*p, capability, v4l2_streaming_capabilities,
     664  			  "V4L2_CAP_???");
     665  	tprint_struct_next();
     666  	PRINT_FIELD_FLAGS(*p, outputmode, v4l2_capture_modes,
     667  			  "V4L2_MODE_???");
     668  	tprint_struct_next();
     669  	PRINT_FIELD_FRACT(*p, timeperframe);
     670  	tprint_struct_next();
     671  	PRINT_FIELD_X(*p, extendedmode);
     672  	tprint_struct_next();
     673  	PRINT_FIELD_U(*p, writebuffers);
     674  	tprint_struct_end();
     675  }
     676  
     677  #define PRINT_FIELD_V4L2_STREAMPARM_PARM(where_, parm_, field_)			\
     678  	do {									\
     679  		tprints_field_name(#parm_ "." #field_);				\
     680  		print_v4l2_streamparm_ ## field_(&((where_).parm_.field_));	\
     681  	} while (0)
     682  
     683  static int
     684  print_v4l2_streamparm(struct tcb *const tcp, const kernel_ulong_t arg,
     685  		      const bool is_get)
     686  {
     687  	struct v4l2_streamparm s;
     688  
     689  	if (entering(tcp)) {
     690  		tprint_arg_next();
     691  		if (umove_or_printaddr(tcp, arg, &s))
     692  			return RVAL_IOCTL_DECODED;
     693  
     694  		tprint_struct_begin();
     695  		PRINT_FIELD_XVAL(s, type, v4l2_buf_types,
     696  				 "V4L2_BUF_TYPE_???");
     697  		switch (s.type) {
     698  			case V4L2_BUF_TYPE_VIDEO_CAPTURE:
     699  			case V4L2_BUF_TYPE_VIDEO_OUTPUT:
     700  				if (is_get)
     701  					return 0;
     702  				tprint_struct_next();
     703  				break;
     704  			default:
     705  				tprint_struct_end();
     706  				return RVAL_IOCTL_DECODED;
     707  		}
     708  	} else {
     709  		if (syserror(tcp) || umove(tcp, arg, &s) < 0) {
     710  			tprint_struct_end();
     711  			return RVAL_IOCTL_DECODED;
     712  		}
     713  		if (is_get) {
     714  			tprint_struct_next();
     715  		} else {
     716  			tprint_struct_end();
     717  			tprint_value_changed();
     718  			tprint_struct_begin();
     719  		}
     720  	}
     721  
     722  	if (s.type == V4L2_BUF_TYPE_VIDEO_CAPTURE) {
     723  		PRINT_FIELD_V4L2_STREAMPARM_PARM(s, parm, capture);
     724  	} else {
     725  		PRINT_FIELD_V4L2_STREAMPARM_PARM(s, parm, output);
     726  	}
     727  
     728  	if (entering(tcp)) {
     729  		return 0;
     730  	} else {
     731  		tprint_struct_end();
     732  		return RVAL_IOCTL_DECODED;
     733  	}
     734  }
     735  
     736  static int
     737  print_v4l2_standard(struct tcb *const tcp, const kernel_ulong_t arg)
     738  {
     739  	struct_v4l2_standard s;
     740  
     741  	if (entering(tcp)) {
     742  		tprint_arg_next();
     743  		if (umove_or_printaddr(tcp, arg, &s))
     744  			return RVAL_IOCTL_DECODED;
     745  
     746  		tprint_struct_begin();
     747  		PRINT_FIELD_U(s, index);
     748  
     749  		return 0;
     750  	}
     751  
     752  	if (!syserror(tcp) && !umove(tcp, arg, &s)) {
     753  		tprint_struct_next();
     754  		PRINT_FIELD_CSTRING(s, name);
     755  		tprint_struct_next();
     756  		PRINT_FIELD_FRACT(s, frameperiod);
     757  		tprint_struct_next();
     758  		PRINT_FIELD_U(s, framelines);
     759  	}
     760  
     761  	tprint_struct_end();
     762  
     763  	return RVAL_IOCTL_DECODED;
     764  }
     765  
     766  #include "xlat/v4l2_input_capabilities_flags.h"
     767  #include "xlat/v4l2_input_status_flags.h"
     768  #include "xlat/v4l2_input_types.h"
     769  #include "xlat/v4l2_std_ids.h"
     770  
     771  static int
     772  print_v4l2_input(struct tcb *const tcp, const kernel_ulong_t arg)
     773  {
     774  	struct_v4l2_input i;
     775  
     776  	if (entering(tcp)) {
     777  		tprint_arg_next();
     778  		if (umove_or_printaddr(tcp, arg, &i))
     779  			return RVAL_IOCTL_DECODED;
     780  
     781  		tprint_struct_begin();
     782  		PRINT_FIELD_U(i, index);
     783  
     784  		return 0;
     785  	}
     786  
     787  	if (!syserror(tcp) && !umove(tcp, arg, &i)) {
     788  		tprint_struct_next();
     789  		PRINT_FIELD_CSTRING(i, name);
     790  		tprint_struct_next();
     791  		PRINT_FIELD_XVAL(i, type, v4l2_input_types,
     792  				 "V4L2_INPUT_TYPE_???");
     793  		tprint_struct_next();
     794  		PRINT_FIELD_X(i, audioset);
     795  		tprint_struct_next();
     796  		PRINT_FIELD_U(i, tuner);
     797  		tprint_struct_next();
     798  		PRINT_FIELD_FLAGS(i, std, v4l2_std_ids, "V4L2_STD_???");
     799  		tprint_struct_next();
     800  		PRINT_FIELD_FLAGS(i, status, v4l2_input_status_flags,
     801  				  "V4L2_IN_ST_???");
     802  		tprint_struct_next();
     803  		PRINT_FIELD_FLAGS(i, capabilities,
     804  				  v4l2_input_capabilities_flags,
     805  				  "V4L2_IN_CAP_???");
     806  	}
     807  
     808  	tprint_struct_end();
     809  
     810  	return RVAL_IOCTL_DECODED;
     811  }
     812  
     813  /*
     814   * We include it here and not before print_v4l2_ext_controls as we need
     815   * V4L2_CTRL_CLASS_* definitions for V4L2_CID_*_BASE ones.
     816   */
     817  #include "xlat/v4l2_control_classes.h"
     818  #include "xlat/v4l2_control_id_bases.h"
     819  #include "xlat/v4l2_control_ids.h"
     820  #include "xlat/v4l2_control_query_flags.h"
     821  
     822  static void
     823  print_v4l2_cid(uint32_t cid, bool next_flags)
     824  {
     825  	if (xlat_verbose(xlat_verbosity) == XLAT_STYLE_RAW) {
     826  		PRINT_VAL_X(cid);
     827  		return;
     828  	}
     829  
     830  	tprint_flags_begin();
     831  	if (next_flags) {
     832  		uint32_t flags = cid & v4l2_control_query_flags->flags_mask;
     833  
     834  		if (flags) {
     835  			printflags_in(v4l2_control_query_flags, flags,
     836  				      "V4L2_CTRL_FLAG_NEXT_???");
     837  			tprint_flags_or();
     838  			cid &= ~flags;
     839  		}
     840  	}
     841  
     842  	const char *id_name = xlookup(v4l2_control_ids, cid);
     843  
     844  	if (id_name) {
     845  		print_xlat_ex(cid, id_name, XLAT_STYLE_DEFAULT);
     846  		tprint_flags_end();
     847  		return;
     848  	}
     849  
     850  	uint64_t class_id = cid;
     851  	const char *class_str = xlookup_le(v4l2_control_classes, &class_id);
     852  
     853  	if (!class_str || (cid - class_id) >= 0x10000) {
     854  		print_xlat_ex(cid, "V4L2_CID_???", PXF_DEFAULT_STR);
     855  		tprint_flags_end();
     856  		return;
     857  	}
     858  
     859  	/*
     860  	 * As of now, the longest control class name is V4L2_CTRL_CLASS_IMAGE_SOURCE,
     861  	 * of 28 characters long.
     862  	 */
     863  	char tmp_str[64 + sizeof("+%#") + sizeof(class_id) * 2];
     864  
     865  	xsprintf(tmp_str, "%s+%#" PRIx64, class_str, cid - class_id);
     866  	print_xlat_ex(cid, tmp_str, XLAT_STYLE_DEFAULT);
     867  	tprint_flags_end();
     868  }
     869  
     870  #define PRINT_FIELD_V4L2_CID(where_, field_, next_)		\
     871  	do {							\
     872  		tprints_field_name(#field_);			\
     873  		print_v4l2_cid((where_).field_, (next_));	\
     874  	} while (0)
     875  
     876  static int
     877  print_v4l2_control(struct tcb *const tcp, const kernel_ulong_t arg,
     878  		   const bool is_get)
     879  {
     880  	struct v4l2_control c;
     881  
     882  	if (entering(tcp)) {
     883  		tprint_arg_next();
     884  		if (umove_or_printaddr(tcp, arg, &c))
     885  			return RVAL_IOCTL_DECODED;
     886  
     887  		tprint_struct_begin();
     888  		PRINT_FIELD_V4L2_CID(c, id, false);
     889  		if (!is_get) {
     890  			tprint_struct_next();
     891  			PRINT_FIELD_D(c, value);
     892  		}
     893  		return 0;
     894  	}
     895  
     896  	if (!syserror(tcp) && !umove(tcp, arg, &c)) {
     897  		if (is_get) {
     898  			tprint_struct_next();
     899  			PRINT_FIELD_D(c, value);
     900  		} else {
     901  			tprint_value_changed();
     902  			PRINT_VAL_D(c.value);
     903  		}
     904  	}
     905  
     906  	tprint_struct_end();
     907  
     908  	return RVAL_IOCTL_DECODED;
     909  }
     910  
     911  #include "xlat/v4l2_tuner_types.h"
     912  #include "xlat/v4l2_tuner_capabilities.h"
     913  #include "xlat/v4l2_tuner_rxsubchanses.h"
     914  #include "xlat/v4l2_tuner_audmodes.h"
     915  
     916  static int
     917  print_v4l2_tuner(struct tcb *const tcp, const kernel_ulong_t arg,
     918  		 const bool is_get)
     919  {
     920  	struct v4l2_tuner c;
     921  	if (entering(tcp)) {
     922  		tprint_arg_next();
     923  		if (umove_or_printaddr(tcp, arg, &c))
     924  			return RVAL_IOCTL_DECODED;
     925  
     926  		tprint_struct_begin();
     927  		PRINT_FIELD_U(c, index);
     928  		if (is_get)
     929  			return 0;
     930  		tprint_struct_next();
     931  	} else {
     932  		if (syserror(tcp) || umove(tcp, arg, &c) < 0) {
     933  			tprint_struct_end();
     934  			return RVAL_IOCTL_DECODED;
     935  		}
     936  		if (is_get) {
     937  			tprint_struct_next();
     938  		} else {
     939  			tprint_struct_end();
     940  			tprint_value_changed();
     941  			tprint_struct_begin();
     942  		}
     943  	}
     944  
     945  	PRINT_FIELD_CSTRING(c, name);
     946  	tprint_struct_next();
     947  	PRINT_FIELD_XVAL(c, type, v4l2_tuner_types, "V4L2_TUNER_???");
     948  	tprint_struct_next();
     949  	PRINT_FIELD_FLAGS(c, capability, v4l2_tuner_capabilities,
     950  			  "V4L2_TUNER_CAP_???");
     951  	tprint_struct_next();
     952  	PRINT_FIELD_U(c, rangelow);
     953  	tprint_struct_next();
     954  	PRINT_FIELD_U(c, rangehigh);
     955  	tprint_struct_next();
     956  	PRINT_FIELD_FLAGS(c, rxsubchans, v4l2_tuner_rxsubchanses,
     957  			  "V4L2_TUNER_SUB_???");
     958  	tprint_struct_next();
     959  	PRINT_FIELD_XVAL(c, audmode, v4l2_tuner_audmodes,
     960  			 "V4L2_TUNER_MODE_???");
     961  	tprint_struct_next();
     962  	PRINT_FIELD_D(c, signal);
     963  	tprint_struct_next();
     964  	PRINT_FIELD_D(c, afc);
     965  
     966  	if (entering(tcp)) {
     967  		return 0;
     968  	} else {
     969  		tprint_struct_end();
     970  		return RVAL_IOCTL_DECODED;
     971  	}
     972  }
     973  
     974  #include "xlat/v4l2_control_types.h"
     975  #include "xlat/v4l2_control_flags.h"
     976  
     977  static int
     978  print_v4l2_queryctrl(struct tcb *const tcp, const kernel_ulong_t arg)
     979  {
     980  	struct v4l2_queryctrl c;
     981  
     982  	if (entering(tcp)) {
     983  		tprint_arg_next();
     984  		if (umove_or_printaddr(tcp, arg, &c))
     985  			return RVAL_IOCTL_DECODED;
     986  
     987  		set_tcb_priv_ulong(tcp, c.id);
     988  		tprint_struct_begin();
     989  		PRINT_FIELD_V4L2_CID(c, id, true);
     990  
     991  		return 0;
     992  	}
     993  
     994  	/* exiting */
     995  	if (syserror(tcp) || umove(tcp, arg, &c) < 0) {
     996  		tprint_struct_end();
     997  		return RVAL_IOCTL_DECODED;
     998  	}
     999  
    1000  	unsigned long entry_id = get_tcb_priv_ulong(tcp);
    1001  
    1002  	if (c.id != entry_id) {
    1003  		tprint_value_changed();
    1004  		print_v4l2_cid(c.id, false);
    1005  	}
    1006  
    1007  	tprint_struct_next();
    1008  	PRINT_FIELD_XVAL(c, type, v4l2_control_types,
    1009  			 "V4L2_CTRL_TYPE_???");
    1010  	tprint_struct_next();
    1011  	PRINT_FIELD_CSTRING(c, name);
    1012  	if (!abbrev(tcp)) {
    1013  		tprint_struct_next();
    1014  		PRINT_FIELD_D(c, minimum);
    1015  		tprint_struct_next();
    1016  		PRINT_FIELD_D(c, maximum);
    1017  		tprint_struct_next();
    1018  		PRINT_FIELD_D(c, step);
    1019  		tprint_struct_next();
    1020  		PRINT_FIELD_D(c, default_value);
    1021  		tprint_struct_next();
    1022  		PRINT_FIELD_FLAGS(c, flags, v4l2_control_flags,
    1023  				  "V4L2_CTRL_FLAG_???");
    1024  		if (!IS_ARRAY_ZERO(c.reserved)) {
    1025  			tprint_struct_next();
    1026  			PRINT_FIELD_ARRAY(c, reserved, tcp,
    1027  					  print_xint_array_member);
    1028  		}
    1029  	} else {
    1030  		tprint_struct_next();
    1031  		tprint_more_data_follows();
    1032  	}
    1033  	tprint_struct_end();
    1034  
    1035  	return RVAL_IOCTL_DECODED;
    1036  }
    1037  
    1038  static int
    1039  print_v4l2_query_ext_ctrl(struct tcb *const tcp, const kernel_ulong_t arg)
    1040  {
    1041  	struct v4l2_query_ext_ctrl c;
    1042  
    1043  	if (entering(tcp)) {
    1044  		tprint_arg_next();
    1045  		if (umove_or_printaddr(tcp, arg, &c))
    1046  			return RVAL_IOCTL_DECODED;
    1047  
    1048  		set_tcb_priv_ulong(tcp, c.id);
    1049  		tprint_struct_begin();
    1050  		PRINT_FIELD_V4L2_CID(c, id, true);
    1051  
    1052  		return 0;
    1053  	}
    1054  
    1055  	/* exiting */
    1056  	if (syserror(tcp) || umove(tcp, arg, &c) < 0) {
    1057  		tprint_struct_end();
    1058  		return RVAL_IOCTL_DECODED;
    1059  	}
    1060  
    1061  	unsigned long entry_id = get_tcb_priv_ulong(tcp);
    1062  
    1063  	if (c.id != entry_id) {
    1064  		tprint_value_changed();
    1065  		print_v4l2_cid(c.id, false);
    1066  	}
    1067  
    1068  	tprint_struct_next();
    1069  	PRINT_FIELD_XVAL(c, type, v4l2_control_types,
    1070  			 "V4L2_CTRL_TYPE_???");
    1071  	tprint_struct_next();
    1072  	PRINT_FIELD_CSTRING(c, name);
    1073  	if (!abbrev(tcp)) {
    1074  		tprint_struct_next();
    1075  		PRINT_FIELD_D(c, minimum);
    1076  		tprint_struct_next();
    1077  		PRINT_FIELD_D(c, maximum);
    1078  		tprint_struct_next();
    1079  		PRINT_FIELD_U(c, step);
    1080  		tprint_struct_next();
    1081  		PRINT_FIELD_D(c, default_value);
    1082  		tprint_struct_next();
    1083  		PRINT_FIELD_FLAGS(c, flags, v4l2_control_flags,
    1084  				  "V4L2_CTRL_FLAG_???");
    1085  		tprint_struct_next();
    1086  		PRINT_FIELD_U(c, elem_size);
    1087  		tprint_struct_next();
    1088  		PRINT_FIELD_U(c, elems);
    1089  		tprint_struct_next();
    1090  		PRINT_FIELD_U(c, nr_of_dims);
    1091  		tprint_struct_next();
    1092  		PRINT_FIELD_ARRAY_UPTO(c, dims, c.nr_of_dims, tcp,
    1093  				       print_uint_array_member);
    1094  		if (!IS_ARRAY_ZERO(c.reserved)) {
    1095  			tprint_struct_next();
    1096  			PRINT_FIELD_ARRAY(c, reserved, tcp,
    1097  					  print_xint_array_member);
    1098  		}
    1099  	} else {
    1100  		tprint_struct_next();
    1101  		tprint_more_data_follows();
    1102  	}
    1103  	tprint_struct_end();
    1104  
    1105  	return RVAL_IOCTL_DECODED;
    1106  }
    1107  
    1108  static int
    1109  print_v4l2_cropcap(struct tcb *const tcp, const kernel_ulong_t arg)
    1110  {
    1111  	struct v4l2_cropcap c;
    1112  
    1113  	if (entering(tcp)) {
    1114  		tprint_arg_next();
    1115  		if (umove_or_printaddr(tcp, arg, &c))
    1116  			return RVAL_IOCTL_DECODED;
    1117  
    1118  		tprint_struct_begin();
    1119  		PRINT_FIELD_XVAL(c, type, v4l2_buf_types,
    1120  				 "V4L2_BUF_TYPE_???");
    1121  
    1122  		return 0;
    1123  	}
    1124  
    1125  	if (!syserror(tcp) && !umove(tcp, arg, &c)) {
    1126  		tprint_struct_next();
    1127  		PRINT_FIELD_OBJ_PTR(c, bounds, print_v4l2_rect);
    1128  		tprint_struct_next();
    1129  		PRINT_FIELD_OBJ_PTR(c, defrect, print_v4l2_rect);
    1130  		tprint_struct_next();
    1131  		PRINT_FIELD_FRACT(c, pixelaspect);
    1132  	}
    1133  
    1134  	tprint_struct_end();
    1135  
    1136  	return RVAL_IOCTL_DECODED;
    1137  }
    1138  
    1139  static int
    1140  print_v4l2_crop(struct tcb *const tcp, const kernel_ulong_t arg,
    1141  		const bool is_get)
    1142  {
    1143  	struct v4l2_crop c;
    1144  
    1145  	if (entering(tcp)) {
    1146  		tprint_arg_next();
    1147  		if (umove_or_printaddr(tcp, arg, &c))
    1148  			return RVAL_IOCTL_DECODED;
    1149  
    1150  		tprint_struct_begin();
    1151  		PRINT_FIELD_XVAL(c, type, v4l2_buf_types,
    1152  				 "V4L2_BUF_TYPE_???");
    1153  		if (is_get)
    1154  			return 0;
    1155  		tprint_struct_next();
    1156  		PRINT_FIELD_OBJ_PTR(c, c, print_v4l2_rect);
    1157  	} else {
    1158  		if (!syserror(tcp) && !umove(tcp, arg, &c)) {
    1159  			tprint_struct_next();
    1160  			PRINT_FIELD_OBJ_PTR(c, c, print_v4l2_rect);
    1161  		}
    1162  	}
    1163  
    1164  	tprint_struct_end();
    1165  
    1166  	return RVAL_IOCTL_DECODED;
    1167  }
    1168  
    1169  static bool
    1170  print_v4l2_ext_control(struct tcb *tcp, void *elem_buf, size_t elem_size, void *data)
    1171  {
    1172  	const struct_v4l2_ext_control *p = elem_buf;
    1173  
    1174  	tprint_struct_begin();
    1175  	PRINT_FIELD_XVAL(*p, id, v4l2_control_ids, "V4L2_CID_???");
    1176  	tprint_struct_next();
    1177  	PRINT_FIELD_U(*p, size);
    1178  	if (p->size > 0) {
    1179  		tprint_struct_next();
    1180  		tprints_field_name("string");
    1181  		printstrn(tcp, ptr_to_kulong(p->string), p->size);
    1182  	} else {
    1183  		tprint_struct_next();
    1184  		PRINT_FIELD_D(*p, value);
    1185  		tprint_struct_next();
    1186  		PRINT_FIELD_D(*p, value64);
    1187  	}
    1188  	tprint_struct_end();
    1189  
    1190  	return true;
    1191  }
    1192  
    1193  static int
    1194  print_v4l2_ext_controls(struct tcb *const tcp, const kernel_ulong_t arg,
    1195  			const bool is_get)
    1196  {
    1197  	struct_v4l2_ext_controls c;
    1198  
    1199  	if (entering(tcp)) {
    1200  		tprint_arg_next();
    1201  		if (umove_or_printaddr(tcp, arg, &c))
    1202  			return RVAL_IOCTL_DECODED;
    1203  
    1204  		tprint_struct_begin();
    1205  		PRINT_FIELD_XVAL(c, ctrl_class, v4l2_control_classes,
    1206  				 "V4L2_CTRL_CLASS_???");
    1207  		tprint_struct_next();
    1208  		PRINT_FIELD_U(c, count);
    1209  		if (!c.count) {
    1210  			tprint_struct_end();
    1211  			return RVAL_IOCTL_DECODED;
    1212  		}
    1213  		if (is_get)
    1214  			return 0;
    1215  		tprint_struct_next();
    1216  	} else {
    1217  		if (umove(tcp, arg, &c) < 0) {
    1218  			tprint_struct_end();
    1219  			return RVAL_IOCTL_DECODED;
    1220  		}
    1221  		if (is_get) {
    1222  			tprint_struct_next();
    1223  		} else {
    1224  			tprint_struct_end();
    1225  			tprint_value_changed();
    1226  			tprint_struct_begin();
    1227  		}
    1228  	}
    1229  
    1230  	tprints_field_name("controls");
    1231  	struct_v4l2_ext_control ctrl;
    1232  	bool fail = !print_array(tcp, ptr_to_kulong(c.controls), c.count,
    1233  				 &ctrl, sizeof(ctrl),
    1234  				 tfetch_mem_ignore_syserror,
    1235  				 print_v4l2_ext_control, 0);
    1236  
    1237  	if (exiting(tcp) && syserror(tcp)) {
    1238  		tprint_struct_next();
    1239  		PRINT_FIELD_U(c, error_idx);
    1240  	}
    1241  
    1242  	if (exiting(tcp) || fail) {
    1243  		tprint_struct_end();
    1244  		return RVAL_IOCTL_DECODED;
    1245  	}
    1246  
    1247  	/* entering */
    1248  	return 0;
    1249  }
    1250  
    1251  #include "xlat/v4l2_framesize_types.h"
    1252  
    1253  static void
    1254  print_v4l2_frmsize_discrete(const struct v4l2_frmsize_discrete *const p)
    1255  {
    1256  	tprint_struct_begin();
    1257  	PRINT_FIELD_U(*p, width);
    1258  	tprint_struct_next();
    1259  	PRINT_FIELD_U(*p, height);
    1260  	tprint_struct_end();
    1261  }
    1262  
    1263  static void
    1264  print_v4l2_frmsize_stepwise(const struct v4l2_frmsize_stepwise *const p)
    1265  {
    1266  	tprint_struct_begin();
    1267  	PRINT_FIELD_U(*p, min_width);
    1268  	tprint_struct_next();
    1269  	PRINT_FIELD_U(*p, max_width);
    1270  	tprint_struct_next();
    1271  	PRINT_FIELD_U(*p, step_width);
    1272  	tprint_struct_next();
    1273  	PRINT_FIELD_U(*p, min_height);
    1274  	tprint_struct_next();
    1275  	PRINT_FIELD_U(*p, max_height);
    1276  	tprint_struct_next();
    1277  	PRINT_FIELD_U(*p, step_height);
    1278  	tprint_struct_end();
    1279  }
    1280  
    1281  #define PRINT_FIELD_V4L2_FRMSIZE_TYPE(where_, field_)			\
    1282  	do {								\
    1283  		tprints_field_name(#field_);				\
    1284  		print_v4l2_frmsize_ ## field_(&((where_).field_));	\
    1285  	} while (0)
    1286  
    1287  static int
    1288  print_v4l2_frmsizeenum(struct tcb *const tcp, const kernel_ulong_t arg)
    1289  {
    1290  	struct v4l2_frmsizeenum s;
    1291  
    1292  	if (entering(tcp)) {
    1293  		tprint_arg_next();
    1294  		if (umove_or_printaddr(tcp, arg, &s))
    1295  			return RVAL_IOCTL_DECODED;
    1296  
    1297  		tprint_struct_begin();
    1298  		PRINT_FIELD_U(s, index);
    1299  		tprint_struct_next();
    1300  		PRINT_FIELD_PIXFMT(s, pixel_format, v4l2_pix_fmts);
    1301  		return 0;
    1302  	}
    1303  
    1304  	if (!syserror(tcp) && !umove(tcp, arg, &s)) {
    1305  		tprint_struct_next();
    1306  		PRINT_FIELD_XVAL(s, type, v4l2_framesize_types,
    1307  				 "V4L2_FRMSIZE_TYPE_???");
    1308  		switch (s.type) {
    1309  		case V4L2_FRMSIZE_TYPE_DISCRETE:
    1310  			tprint_struct_next();
    1311  			PRINT_FIELD_V4L2_FRMSIZE_TYPE(s, discrete);
    1312  			break;
    1313  		case V4L2_FRMSIZE_TYPE_STEPWISE:
    1314  			tprint_struct_next();
    1315  			PRINT_FIELD_V4L2_FRMSIZE_TYPE(s, stepwise);
    1316  			break;
    1317  		}
    1318  	}
    1319  	tprint_struct_end();
    1320  	return RVAL_IOCTL_DECODED;
    1321  }
    1322  
    1323  #include "xlat/v4l2_frameinterval_types.h"
    1324  
    1325  static void
    1326  print_v4l2_frmival_stepwise(const struct v4l2_frmival_stepwise *const p)
    1327  {
    1328  	tprint_struct_begin();
    1329  	PRINT_FIELD_FRACT(*p, min);
    1330  	tprint_struct_next();
    1331  	PRINT_FIELD_FRACT(*p, max);
    1332  	tprint_struct_next();
    1333  	PRINT_FIELD_FRACT(*p, step);
    1334  	tprint_struct_end();
    1335  }
    1336  
    1337  #define PRINT_FIELD_V4L2_FRMIVAL_STEPWISE(where_, field_)		\
    1338  	do {								\
    1339  		tprints_field_name(#field_);				\
    1340  		print_v4l2_frmival_stepwise(&((where_).field_));	\
    1341  	} while (0)
    1342  
    1343  static int
    1344  print_v4l2_frmivalenum(struct tcb *const tcp, const kernel_ulong_t arg)
    1345  {
    1346  	struct v4l2_frmivalenum f;
    1347  
    1348  	if (entering(tcp)) {
    1349  		tprint_arg_next();
    1350  		if (umove_or_printaddr(tcp, arg, &f))
    1351  			return RVAL_IOCTL_DECODED;
    1352  
    1353  		tprint_struct_begin();
    1354  		PRINT_FIELD_U(f, index);
    1355  		tprint_struct_next();
    1356  		PRINT_FIELD_PIXFMT(f, pixel_format, v4l2_pix_fmts);
    1357  		tprint_struct_next();
    1358  		PRINT_FIELD_U(f, width);
    1359  		tprint_struct_next();
    1360  		PRINT_FIELD_U(f, height);
    1361  		return 0;
    1362  	}
    1363  
    1364  	if (!syserror(tcp) && !umove(tcp, arg, &f)) {
    1365  		tprint_struct_next();
    1366  		PRINT_FIELD_XVAL(f, type, v4l2_frameinterval_types,
    1367  				 "V4L2_FRMIVAL_TYPE_???");
    1368  		switch (f.type) {
    1369  		case V4L2_FRMIVAL_TYPE_DISCRETE:
    1370  			tprint_struct_next();
    1371  			PRINT_FIELD_FRACT(f, discrete);
    1372  			break;
    1373  		case V4L2_FRMIVAL_TYPE_STEPWISE:
    1374  		case V4L2_FRMSIZE_TYPE_CONTINUOUS:
    1375  			tprint_struct_next();
    1376  			PRINT_FIELD_V4L2_FRMIVAL_STEPWISE(f, stepwise);
    1377  			break;
    1378  		}
    1379  	}
    1380  
    1381  	tprint_struct_end();
    1382  
    1383  	return RVAL_IOCTL_DECODED;
    1384  }
    1385  
    1386  static void
    1387  print_v4l2_create_buffers_format(const typeof_field(struct_v4l2_create_buffers, format) *const p,
    1388  				 struct tcb *const tcp)
    1389  {
    1390  	tprint_struct_begin();
    1391  	PRINT_FIELD_XVAL(*p, type, v4l2_buf_types,
    1392  			 "V4L2_BUF_TYPE_???");
    1393  	print_v4l2_format_fmt(tcp, tprint_struct_next,
    1394  			      (const struct_v4l2_format *) p);
    1395  	tprint_struct_end();
    1396  }
    1397  
    1398  static int
    1399  print_v4l2_create_buffers(struct tcb *const tcp, const kernel_ulong_t arg)
    1400  {
    1401  	static const char fmt[] = "{index=%u, count=%u}";
    1402  	static char outstr[sizeof(fmt) + sizeof(int) * 6];
    1403  
    1404  	struct_v4l2_create_buffers b;
    1405  
    1406  	if (entering(tcp)) {
    1407  		tprint_arg_next();
    1408  		if (umove_or_printaddr(tcp, arg, &b))
    1409  			return RVAL_IOCTL_DECODED;
    1410  
    1411  		tprint_struct_begin();
    1412  		PRINT_FIELD_U(b, count);
    1413  		tprint_struct_next();
    1414  		PRINT_FIELD_XVAL(b, memory, v4l2_memories,
    1415  				 "V4L2_MEMORY_???");
    1416  		tprint_struct_next();
    1417  		PRINT_FIELD_OBJ_PTR(b, format,
    1418  				    print_v4l2_create_buffers_format, tcp);
    1419  		tprint_struct_end();
    1420  		return 0;
    1421  	}
    1422  
    1423  	if (syserror(tcp) || umove(tcp, arg, &b))
    1424  		return RVAL_IOCTL_DECODED;
    1425  
    1426  	xsprintf(outstr, fmt, b.index, b.count);
    1427  	tcp->auxstr = outstr;
    1428  
    1429  	return RVAL_IOCTL_DECODED | RVAL_STR;
    1430  }
    1431  
    1432  MPERS_PRINTER_DECL(int, v4l2_ioctl, struct tcb *const tcp,
    1433  		   const unsigned int code, const kernel_ulong_t arg)
    1434  {
    1435  	if (!verbose(tcp))
    1436  		return RVAL_DECODED;
    1437  
    1438  	switch (code) {
    1439  	case VIDIOC_QUERYCAP: /* R */
    1440  		return print_v4l2_capability(tcp, arg);
    1441  
    1442  	case VIDIOC_ENUM_FMT: /* RW */
    1443  		return print_v4l2_fmtdesc(tcp, arg);
    1444  
    1445  	case VIDIOC_G_FMT: /* RW */
    1446  	case VIDIOC_S_FMT: /* RW */
    1447  	case VIDIOC_TRY_FMT: /* RW */
    1448  		return print_v4l2_format(tcp, arg, code == VIDIOC_G_FMT);
    1449  
    1450  	case VIDIOC_REQBUFS: /* RW */
    1451  		return print_v4l2_requestbuffers(tcp, arg);
    1452  
    1453  	case VIDIOC_QUERYBUF: /* RW */
    1454  	case VIDIOC_QBUF: /* RW */
    1455  	case VIDIOC_DQBUF: /* RW */
    1456  		return print_v4l2_buffer(tcp, code, arg);
    1457  
    1458  	case VIDIOC_G_FBUF: /* R */
    1459  		if (entering(tcp))
    1460  			return 0;
    1461  		ATTRIBUTE_FALLTHROUGH;
    1462  	case VIDIOC_S_FBUF: /* W */
    1463  		return print_v4l2_framebuffer(tcp, arg);
    1464  
    1465  	case VIDIOC_STREAMON: /* W */
    1466  	case VIDIOC_STREAMOFF: /* W */
    1467  		return print_v4l2_buf_type(tcp, arg);
    1468  
    1469  	case VIDIOC_G_PARM: /* RW */
    1470  	case VIDIOC_S_PARM: /* RW */
    1471  		return print_v4l2_streamparm(tcp, arg, code == VIDIOC_G_PARM);
    1472  
    1473  	case VIDIOC_G_STD: /* R */
    1474  		if (entering(tcp))
    1475  			return 0;
    1476  		ATTRIBUTE_FALLTHROUGH;
    1477  	case VIDIOC_S_STD: /* W */
    1478  		tprint_arg_next();
    1479  		printnum_int64(tcp, arg, "%#" PRIx64);
    1480  		break;
    1481  
    1482  	case VIDIOC_ENUMSTD: /* RW */
    1483  		return print_v4l2_standard(tcp, arg);
    1484  
    1485  	case VIDIOC_ENUMINPUT: /* RW */
    1486  		return print_v4l2_input(tcp, arg);
    1487  
    1488  	case VIDIOC_G_CTRL: /* RW */
    1489  	case VIDIOC_S_CTRL: /* RW */
    1490  		return print_v4l2_control(tcp, arg, code == VIDIOC_G_CTRL);
    1491  
    1492  	case VIDIOC_G_TUNER: /* RW */
    1493  	case VIDIOC_S_TUNER: /* RW */
    1494  		return print_v4l2_tuner(tcp, arg, code == VIDIOC_G_TUNER);
    1495  
    1496  	case VIDIOC_QUERYCTRL: /* RW */
    1497  		return print_v4l2_queryctrl(tcp, arg);
    1498  
    1499  	case VIDIOC_QUERY_EXT_CTRL: /* RW */
    1500  		return print_v4l2_query_ext_ctrl(tcp, arg);
    1501  
    1502  	case VIDIOC_G_INPUT: /* R */
    1503  		if (entering(tcp))
    1504  			return 0;
    1505  		ATTRIBUTE_FALLTHROUGH;
    1506  	case VIDIOC_S_INPUT: /* RW */
    1507  		tprint_arg_next();
    1508  		printnum_int(tcp, arg, "%u");
    1509  		break;
    1510  
    1511  	case VIDIOC_CROPCAP: /* RW */
    1512  		return print_v4l2_cropcap(tcp, arg);
    1513  
    1514  	case VIDIOC_G_CROP: /* RW */
    1515  	case VIDIOC_S_CROP: /* W */
    1516  		return print_v4l2_crop(tcp, arg, code == VIDIOC_G_CROP);
    1517  
    1518  	case VIDIOC_S_EXT_CTRLS: /* RW */
    1519  	case VIDIOC_TRY_EXT_CTRLS: /* RW */
    1520  	case VIDIOC_G_EXT_CTRLS: /* RW */
    1521  		return print_v4l2_ext_controls(tcp, arg,
    1522  					       code == VIDIOC_G_EXT_CTRLS);
    1523  
    1524  	case VIDIOC_ENUM_FRAMESIZES: /* RW */
    1525  		return print_v4l2_frmsizeenum(tcp, arg);
    1526  
    1527  	case VIDIOC_ENUM_FRAMEINTERVALS: /* RW */
    1528  		return print_v4l2_frmivalenum(tcp, arg);
    1529  
    1530  	case VIDIOC_CREATE_BUFS: /* RW */
    1531  		return print_v4l2_create_buffers(tcp, arg);
    1532  
    1533  	default:
    1534  		return RVAL_DECODED;
    1535  	}
    1536  
    1537  	return RVAL_IOCTL_DECODED;
    1538  }