@@ -271,8 +271,13 @@ int ioctl(int fd, unsigned long cmd, ...)
if (cmd == VIDIOC_STREAMOFF)
streamoff_cleanup(*(static_cast<v4l2_buf_type*>(arg)));
- /* Trace userspace arguments if driver will be reading them i.e. _IOW or _IOWR ioctls */
- if ((cmd & IOC_IN) != 0U) {
+ /*
+ * To avoid cluttering the trace file, only trace userspace arguments when necessary
+ * or if the option to trace them is selected.
+ */
+ if (((cmd & IOC_INOUT) == IOC_IN) ||
+ (getenv("V4L2_TRACER_OPTION_TRACE_USERSPACE_ARG") != nullptr) ||
+ (cmd == VIDIOC_QBUF)) {
json_object *ioctl_args_userspace = trace_ioctl_args(cmd, arg);
/* Some ioctls won't have arguments to trace e.g. MEDIA_REQUEST_IOC_QUEUE. */
if (json_object_object_length(ioctl_args_userspace))
@@ -309,9 +309,9 @@ struct v4l2_buffer *retrace_v4l2_buffer(json_object *ioctl_args)
return buf;
}
-void retrace_vidioc_querybuf(int fd_retrace, json_object *ioctl_args_user)
+void retrace_vidioc_querybuf(int fd_retrace, json_object *ioctl_args)
{
- struct v4l2_buffer *buf = retrace_v4l2_buffer(ioctl_args_user);
+ struct v4l2_buffer *buf = retrace_v4l2_buffer(ioctl_args);
ioctl(fd_retrace, VIDIOC_QUERYBUF, buf);
@@ -346,9 +346,9 @@ void retrace_vidioc_querybuf(int fd_retrace, json_object *ioctl_args_user)
free(buf);
}
-void retrace_vidioc_qbuf(int fd_retrace, json_object *ioctl_args_user)
+void retrace_vidioc_qbuf(int fd_retrace, json_object *ioctl_args)
{
- struct v4l2_buffer *ptr = retrace_v4l2_buffer(ioctl_args_user);
+ struct v4l2_buffer *ptr = retrace_v4l2_buffer(ioctl_args);
ioctl(fd_retrace, VIDIOC_QBUF, ptr);
@@ -371,9 +371,9 @@ void retrace_vidioc_qbuf(int fd_retrace, json_object *ioctl_args_user)
free(ptr);
}
-void retrace_vidioc_dqbuf(int fd_retrace, json_object *ioctl_args_user)
+void retrace_vidioc_dqbuf(int fd_retrace, json_object *ioctl_args)
{
- struct v4l2_buffer *buf = retrace_v4l2_buffer(ioctl_args_user);
+ struct v4l2_buffer *buf = retrace_v4l2_buffer(ioctl_args);
const int poll_timeout_ms = 5000;
struct pollfd *pfds = (struct pollfd *) calloc(1, sizeof(struct pollfd));
@@ -411,9 +411,9 @@ void retrace_vidioc_dqbuf(int fd_retrace, json_object *ioctl_args_user)
free(buf);
}
-void retrace_vidioc_prepare_buf(int fd_retrace, json_object *ioctl_args_user)
+void retrace_vidioc_prepare_buf(int fd_retrace, json_object *ioctl_args)
{
- struct v4l2_buffer *buf = retrace_v4l2_buffer(ioctl_args_user);
+ struct v4l2_buffer *buf = retrace_v4l2_buffer(ioctl_args);
ioctl(fd_retrace, VIDIOC_PREPARE_BUF, buf);
@@ -447,9 +447,9 @@ void retrace_vidioc_create_bufs(int fd_retrace, json_object *ioctl_args)
free(ptr);
}
-void retrace_vidioc_expbuf(int fd_retrace, json_object *ioctl_args_user, json_object *ioctl_args_driver)
+void retrace_vidioc_expbuf(int fd_retrace, json_object *ioctl_args)
{
- struct v4l2_exportbuffer *ptr = retrace_v4l2_exportbuffer_gen(ioctl_args_user);
+ struct v4l2_exportbuffer *ptr = retrace_v4l2_exportbuffer_gen(ioctl_args);
ioctl(fd_retrace, VIDIOC_EXPBUF, ptr);
int buf_fd_retrace = ptr->fd;
@@ -466,7 +466,7 @@ void retrace_vidioc_expbuf(int fd_retrace, json_object *ioctl_args_user, json_ob
/* Retrace again to associate the original fd with the current buffer fd. */
memset(ptr, 0, sizeof(v4l2_exportbuffer));
- ptr = retrace_v4l2_exportbuffer_gen(ioctl_args_driver);
+ ptr = retrace_v4l2_exportbuffer_gen(ioctl_args);
int buf_fd_trace = ptr->fd;
add_fd(buf_fd_trace, buf_fd_retrace);
@@ -528,9 +528,9 @@ void retrace_vidioc_g_fmt(int fd_retrace, json_object *ioctl_args)
free(ptr);
}
-void retrace_vidioc_s_fmt(int fd_retrace, json_object *ioctl_args_user)
+void retrace_vidioc_s_fmt(int fd_retrace, json_object *ioctl_args)
{
- struct v4l2_format *ptr = retrace_v4l2_format_gen(ioctl_args_user);
+ struct v4l2_format *ptr = retrace_v4l2_format_gen(ioctl_args);
ioctl(fd_retrace, VIDIOC_S_FMT, ptr);
@@ -1265,129 +1265,128 @@ void retrace_ioctl(json_object *syscall_obj)
return;
}
- json_object *ioctl_args_user;
- json_object_object_get_ex(syscall_obj, "from_userspace", &ioctl_args_user);
-
- json_object *ioctl_args_driver;
- json_object_object_get_ex(syscall_obj, "from_driver", &ioctl_args_driver);
+ /* If available, use the ioctl arguments from userspace, otherwise use the driver arguments. */
+ json_object *ioctl_args;
+ if (json_object_object_get_ex(syscall_obj, "from_userspace", &ioctl_args) == false)
+ json_object_object_get_ex(syscall_obj, "from_driver", &ioctl_args);
switch (cmd) {
case VIDIOC_QUERYCAP:
- retrace_vidioc_querycap(fd_retrace, ioctl_args_user);
+ retrace_vidioc_querycap(fd_retrace, ioctl_args);
break;
case VIDIOC_ENUM_FMT:
- retrace_vidioc_enum_fmt(fd_retrace, ioctl_args_user);
+ retrace_vidioc_enum_fmt(fd_retrace, ioctl_args);
break;
case VIDIOC_TRY_FMT:
- retrace_vidioc_try_fmt(fd_retrace, ioctl_args_user);
+ retrace_vidioc_try_fmt(fd_retrace, ioctl_args);
break;
case VIDIOC_G_FMT:
- retrace_vidioc_g_fmt(fd_retrace, ioctl_args_user);
+ retrace_vidioc_g_fmt(fd_retrace, ioctl_args);
break;
case VIDIOC_S_FMT:
- retrace_vidioc_s_fmt(fd_retrace, ioctl_args_user);
+ retrace_vidioc_s_fmt(fd_retrace, ioctl_args);
break;
case VIDIOC_REQBUFS:
- retrace_vidioc_reqbufs(fd_retrace, ioctl_args_user);
+ retrace_vidioc_reqbufs(fd_retrace, ioctl_args);
break;
case VIDIOC_QUERYBUF:
- retrace_vidioc_querybuf(fd_retrace, ioctl_args_user);
+ retrace_vidioc_querybuf(fd_retrace, ioctl_args);
break;
case VIDIOC_QBUF:
- retrace_vidioc_qbuf(fd_retrace, ioctl_args_user);
+ retrace_vidioc_qbuf(fd_retrace, ioctl_args);
break;
case VIDIOC_EXPBUF:
- retrace_vidioc_expbuf(fd_retrace, ioctl_args_user, ioctl_args_driver);
+ retrace_vidioc_expbuf(fd_retrace, ioctl_args);
break;
case VIDIOC_DQBUF:
- retrace_vidioc_dqbuf(fd_retrace, ioctl_args_user);
+ retrace_vidioc_dqbuf(fd_retrace, ioctl_args);
break;
case VIDIOC_STREAMON:
- retrace_vidioc_streamon(fd_retrace, ioctl_args_user);
+ retrace_vidioc_streamon(fd_retrace, ioctl_args);
break;
case VIDIOC_STREAMOFF:
- retrace_vidioc_streamoff(fd_retrace, ioctl_args_user);
+ retrace_vidioc_streamoff(fd_retrace, ioctl_args);
break;
case VIDIOC_G_PARM:
- retrace_vidioc_g_parm(fd_retrace, ioctl_args_user);
+ retrace_vidioc_g_parm(fd_retrace, ioctl_args);
break;
case VIDIOC_S_PARM:
- retrace_vidioc_s_parm(fd_retrace, ioctl_args_user);
+ retrace_vidioc_s_parm(fd_retrace, ioctl_args);
break;
case VIDIOC_ENUMINPUT:
- retrace_vidioc_enuminput(fd_retrace, ioctl_args_user);
+ retrace_vidioc_enuminput(fd_retrace, ioctl_args);
break;
case VIDIOC_G_CTRL:
- retrace_vidioc_g_control(fd_retrace, ioctl_args_user);
+ retrace_vidioc_g_control(fd_retrace, ioctl_args);
break;
case VIDIOC_S_CTRL:
- retrace_vidioc_s_control(fd_retrace, ioctl_args_user);
+ retrace_vidioc_s_control(fd_retrace, ioctl_args);
break;
case VIDIOC_G_TUNER:
- retrace_vidioc_g_tuner(fd_retrace, ioctl_args_user);
+ retrace_vidioc_g_tuner(fd_retrace, ioctl_args);
break;
case VIDIOC_S_TUNER:
- retrace_vidioc_s_tuner(fd_retrace, ioctl_args_user);
+ retrace_vidioc_s_tuner(fd_retrace, ioctl_args);
break;
case VIDIOC_QUERYCTRL:
- retrace_vidioc_queryctrl(fd_retrace, ioctl_args_user);
+ retrace_vidioc_queryctrl(fd_retrace, ioctl_args);
break;
case VIDIOC_G_INPUT:
- retrace_vidioc_g_input(fd_retrace, ioctl_args_user);
+ retrace_vidioc_g_input(fd_retrace, ioctl_args);
break;
case VIDIOC_S_INPUT:
- retrace_vidioc_s_input(fd_retrace, ioctl_args_user);
+ retrace_vidioc_s_input(fd_retrace, ioctl_args);
break;
case VIDIOC_G_OUTPUT:
- retrace_vidioc_g_output(fd_retrace, ioctl_args_user);
+ retrace_vidioc_g_output(fd_retrace, ioctl_args);
break;
case VIDIOC_S_OUTPUT:
- retrace_vidioc_s_output(fd_retrace, ioctl_args_user);
+ retrace_vidioc_s_output(fd_retrace, ioctl_args);
break;
case VIDIOC_ENUMOUTPUT:
- retrace_vidioc_enumoutput(fd_retrace, ioctl_args_user);
+ retrace_vidioc_enumoutput(fd_retrace, ioctl_args);
break;
case VIDIOC_G_CROP:
- retrace_vidioc_g_crop(fd_retrace, ioctl_args_user);
+ retrace_vidioc_g_crop(fd_retrace, ioctl_args);
break;
case VIDIOC_S_CROP:
- retrace_vidioc_s_crop(fd_retrace, ioctl_args_user);
+ retrace_vidioc_s_crop(fd_retrace, ioctl_args);
break;
case VIDIOC_G_EXT_CTRLS:
- retrace_vidioc_g_ext_ctrls(fd_retrace, ioctl_args_user);
+ retrace_vidioc_g_ext_ctrls(fd_retrace, ioctl_args);
break;
case VIDIOC_TRY_EXT_CTRLS:
- retrace_vidioc_try_ext_ctrls(fd_retrace, ioctl_args_user);
+ retrace_vidioc_try_ext_ctrls(fd_retrace, ioctl_args);
break;
case VIDIOC_S_EXT_CTRLS:
- retrace_vidioc_s_ext_ctrls(fd_retrace, ioctl_args_user);
+ retrace_vidioc_s_ext_ctrls(fd_retrace, ioctl_args);
break;
case VIDIOC_ENUM_FRAMESIZES:
- retrace_vidioc_enum_framesizes(fd_retrace, ioctl_args_user);
+ retrace_vidioc_enum_framesizes(fd_retrace, ioctl_args);
break;
case VIDIOC_ENUM_FRAMEINTERVALS:
- retrace_vidioc_enum_frameintervals(fd_retrace, ioctl_args_user);
+ retrace_vidioc_enum_frameintervals(fd_retrace, ioctl_args);
break;
case VIDIOC_TRY_ENCODER_CMD:
- retrace_vidioc_try_encoder_cmd(fd_retrace, ioctl_args_user);
+ retrace_vidioc_try_encoder_cmd(fd_retrace, ioctl_args);
break;
case VIDIOC_ENCODER_CMD:
- retrace_vidioc_encoder_cmd(fd_retrace, ioctl_args_user);
+ retrace_vidioc_encoder_cmd(fd_retrace, ioctl_args);
break;
case VIDIOC_CREATE_BUFS:
- retrace_vidioc_create_bufs(fd_retrace, ioctl_args_user);
+ retrace_vidioc_create_bufs(fd_retrace, ioctl_args);
break;
case VIDIOC_G_SELECTION:
- retrace_vidioc_g_selection(fd_retrace, ioctl_args_user);
+ retrace_vidioc_g_selection(fd_retrace, ioctl_args);
break;
case VIDIOC_S_SELECTION:
- retrace_vidioc_s_selection(fd_retrace, ioctl_args_user);
+ retrace_vidioc_s_selection(fd_retrace, ioctl_args);
break;
case VIDIOC_PREPARE_BUF:
- retrace_vidioc_prepare_buf(fd_retrace, ioctl_args_user);
+ retrace_vidioc_prepare_buf(fd_retrace, ioctl_args);
break;
case VIDIOC_TRY_DECODER_CMD:
- retrace_vidioc_try_decoder_cmd(fd_retrace, ioctl_args_user);
+ retrace_vidioc_try_decoder_cmd(fd_retrace, ioctl_args);
break;
case VIDIOC_DQEVENT:
/* Don't retrace a timed-out DQEVENT */
@@ -1396,19 +1395,19 @@ void retrace_ioctl(json_object *syscall_obj)
retrace_vidioc_dqevent(fd_retrace);
break;
case VIDIOC_SUBSCRIBE_EVENT:
- retrace_vidioc_subscribe_event(fd_retrace, ioctl_args_user);
+ retrace_vidioc_subscribe_event(fd_retrace, ioctl_args);
break;
case VIDIOC_UNSUBSCRIBE_EVENT:
- retrace_vidioc_unsubscribe(fd_retrace, ioctl_args_user);
+ retrace_vidioc_unsubscribe(fd_retrace, ioctl_args);
break;
case VIDIOC_DECODER_CMD:
- retrace_vidioc_decoder_cmd(fd_retrace, ioctl_args_user);
+ retrace_vidioc_decoder_cmd(fd_retrace, ioctl_args);
break;
case VIDIOC_QUERY_EXT_CTRL:
- retrace_vidioc_query_ext_ctrl(fd_retrace, ioctl_args_user);
+ retrace_vidioc_query_ext_ctrl(fd_retrace, ioctl_args);
break;
case MEDIA_IOC_REQUEST_ALLOC:
- retrace_media_ioc_request_alloc(fd_retrace, ioctl_args_driver);
+ retrace_media_ioc_request_alloc(fd_retrace, ioctl_args);
break;
case MEDIA_REQUEST_IOC_QUEUE:
ioctl(fd_retrace, MEDIA_REQUEST_IOC_QUEUE);
@@ -37,6 +37,7 @@ void print_usage(void)
"\t\t-g, --debug Turn on verbose reporting plus additional debug info.\n"
"\t\t-h, --help Display this message.\n"
"\t\t-r --raw Write decoded video frame data to JSON file.\n"
+ "\t\t-u --userspace Trace userspace arguments.\n"
"\t\t-v, --verbose Turn on verbose reporting.\n"
"\t\t-y, --yuv Write decoded video frame data to yuv file.\n\n"
@@ -28,6 +28,7 @@ enum Options {
V4l2TracerOptHelp = 'h',
V4l2TracerOptSetMediaDevice = 'm',
V4l2TracerOptWriteDecodedToJson = 'r',
+ V4l2TracerOptTraceUserspaceArg = 'u',
V4l2TracerOptVerbose = 'v',
V4l2TracerOptWriteDecodedToYUVFile = 'y',
};
@@ -39,6 +40,7 @@ const static struct option long_options[] = {
{ "help", no_argument, nullptr, V4l2TracerOptHelp },
{ "media_device", required_argument, nullptr, V4l2TracerOptSetMediaDevice },
{ "raw", no_argument, nullptr, V4l2TracerOptWriteDecodedToJson },
+ { "userspace", no_argument, nullptr, V4l2TracerOptTraceUserspaceArg},
{ "verbose", no_argument, nullptr, V4l2TracerOptVerbose },
{ "yuv", no_argument, nullptr, V4l2TracerOptWriteDecodedToYUVFile },
{ nullptr, 0, nullptr, 0 }
@@ -51,6 +53,7 @@ const char short_options[] = {
V4l2TracerOptHelp,
V4l2TracerOptSetMediaDevice, ':',
V4l2TracerOptWriteDecodedToJson,
+ V4l2TracerOptTraceUserspaceArg,
V4l2TracerOptVerbose,
V4l2TracerOptWriteDecodedToYUVFile
};
@@ -122,6 +125,9 @@ int get_options(int argc, char *argv[])
case V4l2TracerOptWriteDecodedToJson:
setenv("V4L2_TRACER_OPTION_WRITE_DECODED_TO_JSON_FILE", "true", 0);
break;
+ case V4l2TracerOptTraceUserspaceArg:
+ setenv("V4L2_TRACER_OPTION_TRACE_USERSPACE_ARG", "true", 0);
+ break;
case V4l2TracerOptVerbose:
setenv("V4L2_TRACER_OPTION_VERBOSE", "true", 0);
break;