@@ -44,6 +44,9 @@ const std::list<unsigned long> ioctls = {
VIDIOC_ENUM_FRAMEINTERVALS,
VIDIOC_ENCODER_CMD,
VIDIOC_TRY_ENCODER_CMD,
+ VIDIOC_DQEVENT,
+ VIDIOC_SUBSCRIBE_EVENT,
+ VIDIOC_UNSUBSCRIBE_EVENT,
VIDIOC_CREATE_BUFS,
VIDIOC_PREPARE_BUF,
VIDIOC_G_SELECTION,
@@ -1120,6 +1120,61 @@ void retrace_vidioc_try_decoder_cmd(int fd_retrace, json_object *ioctl_args)
free (ptr);
}
+void retrace_vidioc_dqevent(int fd_retrace)
+{
+ const int poll_timeout_ms = 200;
+ struct pollfd *pfds = (struct pollfd *) calloc(1, sizeof(struct pollfd));
+ if (pfds == nullptr)
+ exit(EXIT_FAILURE);
+ pfds[0].fd = fd_retrace;
+ pfds[0].events = POLLIN | POLLPRI;
+ int ret = poll(pfds, 1, poll_timeout_ms);
+
+ if (ret == -1) {
+ line_info("\n\tPoll error.");
+ perror("");
+ free(pfds);
+ exit(EXIT_FAILURE);
+ }
+ if (ret == 0) {
+ line_info("\n\tPoll timed out.");
+ free(pfds);
+ exit(EXIT_FAILURE);
+ }
+
+ struct v4l2_event event = {};
+ ioctl(fd_retrace, VIDIOC_DQEVENT, &event);
+
+ if (is_verbose() || (errno != 0))
+ perror("VIDIOC_DQEVENT");
+
+ free(pfds);
+}
+
+void retrace_vidioc_subscribe_event(int fd_retrace, json_object *ioctl_args)
+{
+ struct v4l2_event_subscription *ptr = retrace_v4l2_event_subscription_gen(ioctl_args);
+
+ ioctl(fd_retrace, VIDIOC_SUBSCRIBE_EVENT, ptr);
+
+ if (is_verbose() || (errno != 0))
+ perror("VIDIOC_SUBSCRIBE_EVENT");
+
+ free (ptr);
+}
+
+void retrace_vidioc_unsubscribe(int fd_retrace, json_object *ioctl_args)
+{
+ struct v4l2_event_subscription *ptr = retrace_v4l2_event_subscription_gen(ioctl_args);
+
+ ioctl(fd_retrace, VIDIOC_UNSUBSCRIBE_EVENT, ptr);
+
+ if (is_verbose() || (errno != 0))
+ perror("VIDIOC_UNSUBSCRIBE_EVENT");
+
+ free (ptr);
+}
+
void retrace_vidioc_decoder_cmd(int fd_retrace, json_object *ioctl_args)
{
struct v4l2_decoder_cmd *ptr = retrace_v4l2_decoder_cmd(ioctl_args);
@@ -1187,19 +1242,25 @@ void retrace_ioctl(json_object *syscall_obj)
{
__s64 cmd = 0;
int fd_retrace = 0;
+ bool ioctl_error = false;
json_object *fd_trace_obj;
json_object_object_get_ex(syscall_obj, "fd", &fd_trace_obj);
fd_retrace = get_fd_retrace_from_fd_trace(json_object_get_int(fd_trace_obj));
- if (fd_retrace < 0) {
- line_info("\n\tBad file descriptor.");
- return;
- }
json_object *cmd_obj;
json_object_object_get_ex(syscall_obj, "ioctl", &cmd_obj);
cmd = s2val(json_object_get_string(cmd_obj), ioctl_val_def);
+ json_object *errno_obj;
+ if (json_object_object_get_ex(syscall_obj, "errno", &errno_obj))
+ ioctl_error = true;
+
+ if (fd_retrace < 0) {
+ line_info("\n\tBad file descriptor on %s\n", json_object_get_string(cmd_obj));
+ return;
+ }
+
json_object *ioctl_args_user;
json_object_object_get_ex(syscall_obj, "from_userspace", &ioctl_args_user);
@@ -1324,6 +1385,18 @@ void retrace_ioctl(json_object *syscall_obj)
case VIDIOC_TRY_DECODER_CMD:
retrace_vidioc_try_decoder_cmd(fd_retrace, ioctl_args_user);
break;
+ case VIDIOC_DQEVENT:
+ /* Don't retrace a timed-out DQEVENT */
+ if (ioctl_error)
+ break;
+ retrace_vidioc_dqevent(fd_retrace);
+ break;
+ case VIDIOC_SUBSCRIBE_EVENT:
+ retrace_vidioc_subscribe_event(fd_retrace, ioctl_args_user);
+ break;
+ case VIDIOC_UNSUBSCRIBE_EVENT:
+ retrace_vidioc_unsubscribe(fd_retrace, ioctl_args_user);
+ break;
case VIDIOC_DECODER_CMD:
retrace_vidioc_decoder_cmd(fd_retrace, ioctl_args_user);
break;
@@ -599,6 +599,13 @@ json_object *trace_ioctl_args(unsigned long cmd, void *arg)
case VIDIOC_ENCODER_CMD:
trace_v4l2_encoder_cmd_gen(arg, ioctl_args);
break;
+ case VIDIOC_DQEVENT:
+ trace_v4l2_event_gen(arg, ioctl_args);
+ break;
+ case VIDIOC_SUBSCRIBE_EVENT:
+ case VIDIOC_UNSUBSCRIBE_EVENT:
+ trace_v4l2_event_subscription_gen(arg, ioctl_args);
+ break;
case VIDIOC_CREATE_BUFS:
trace_v4l2_create_buffers_gen(arg, ioctl_args);
break;
@@ -161,7 +161,7 @@ sub get_val_def_name {
@structs_that_use_v4l2_buf_type = qw(v4l2_fmtdesc v4l2_requestbuffers v4l2_buffer v4l2_crop
v4l2_exportbuffer v4l2_cropcap v4l2_selection
v4l2_sliced_vbi_cap v4l2_format v4l2_streamparm);
- @structs_that_use_v4l2_ctrl_type = qw(v4l2_queryctrl v4l2_query_ext_ctrl);
+ @structs_that_use_v4l2_ctrl_type = qw(v4l2_queryctrl v4l2_query_ext_ctrl v4l2_event_ctrl);
@structs_that_use_v4l2_tuner_type = qw(v4l2_tuner v4l2_frequency);
if ($member eq "type") {
foreach (@structs_that_use_v4l2_buf_type) {
@@ -191,6 +191,9 @@ sub get_val_def_name {
if ($struct_name eq "v4l2_output") {
return $val_def_name = "output_type_val_def";
}
+ if ($struct_name eq "v4l2_event" || $struct_name eq "v4l2_event_subscription") {
+ return $val_def_name = "event_val_def";
+ }
return "nullptr"; # will print as hex string
}
if ($member eq "pixelformat" || $member eq "pixel_format") {
@@ -270,7 +273,10 @@ sub get_flag_def_name {
if ($struct_name =~ /.*selection$/) {
return "v4l2_sel_flag_def";
}
- return "nullptr";
+ if ($struct_name eq "v4l2_event_subscription") {
+ return "v4l2_event_sub_flag_def";
+ }
+ return "nullptr";
}
if ($member =~ /.*cap.*/) {
@@ -289,6 +295,11 @@ sub get_flag_def_name {
if ($member eq "rxsubchans") {
return "tuner_rxsub_flag_def";
}
+ if ($member eq "changes") {
+ if ($struct_name eq "v4l2_event_ctrl") {
+ return "v4l2_event_ctrl_ch_flag_def";
+ }
+ }
return "";
}
@@ -383,6 +394,21 @@ sub handle_union {
printf $fh_trace_cpp "\tdefault:\n\t\tbreak;\n\t}\n";
}
+ if ($struct_name eq "v4l2_event") {
+ printf $fh_trace_cpp "\tswitch (p->type) {\n";
+ printf $fh_trace_cpp "\tcase V4L2_EVENT_VSYNC:\n";
+ printf $fh_trace_cpp "\t\ttrace_v4l2_event_vsync_gen(&p->u, %s_obj);\n\t\tbreak;\n", $struct_name;
+ printf $fh_trace_cpp "\tcase V4L2_EVENT_CTRL:\n";
+ printf $fh_trace_cpp "\t\ttrace_v4l2_event_ctrl_gen(&p->u, %s_obj);\n\t\tbreak;\n", $struct_name;
+ printf $fh_trace_cpp "\tcase V4L2_EVENT_FRAME_SYNC:\n";
+ printf $fh_trace_cpp "\t\ttrace_v4l2_event_frame_sync_gen(&p->u, %s_obj);\n\t\tbreak;\n", $struct_name;
+ printf $fh_trace_cpp "\tcase V4L2_EVENT_SOURCE_CHANGE:\n";
+ printf $fh_trace_cpp "\t\ttrace_v4l2_event_src_change_gen(&p->u, %s_obj);\n\t\tbreak;\n", $struct_name;
+ printf $fh_trace_cpp "\tcase V4L2_EVENT_MOTION_DET:\n";
+ printf $fh_trace_cpp "\t\ttrace_v4l2_event_motion_det_gen(&p->u, %s_obj);\n\t\tbreak;\n", $struct_name;
+ printf $fh_trace_cpp "\tdefault:\n\t\tbreak;\n\t}\n";
+ }
+
return $suppress_union;
}
@@ -854,17 +880,15 @@ while (<>) {
if (grep {/#define __LINUX_VIDEODEV2_H/} $_) {
$in_v4l2_controls = false;
}
-
if (grep {/^#define.+FWHT_FL_.+/} $_) {
flag_gen("fwht");
} elsif (grep {/^#define V4L2_VP8_LF.*/} $_) {
flag_gen("vp8_loop_filter");
- } elsif (grep {/^#define.+_FL_.+/} $_) { #use to get media flags
+ } elsif (grep {/^#define.+_FL_.+/} $_) {
flag_gen();
} elsif (grep {/^#define.+_FLAG_.+/} $_) {
flag_gen();
}
-
if ($in_v4l2_controls eq true) {
if (grep {/^struct/} $_) {
struct_gen_ctrl();
@@ -964,7 +988,16 @@ while (<>) {
val_def_gen("V4L2_DEC_CMD_FLUSH");
next;
}
-
+ if (grep {/^#define V4L2_EVENT_ALL\s+/} $_) {
+ printf $fh_common_info_h "constexpr val_def event_val_def[] = {\n";
+ val_def_gen("V4L2_EVENT_PRIVATE_START");
+ next;
+ }
+ if (grep {/^#define V4L2_EVENT_CTRL_CH_VALUE\s+/} $_) {
+ printf $fh_common_info_h "constexpr flag_def v4l2_event_ctrl_ch_flag_def[] = {\n";
+ flag_def_gen("V4L2_EVENT_CTRL_CH_DIMENSIONS");
+ next
+ }
if (grep {/^#define\s+(VIDIOC_\w*)\s*.*/} $_) {
push (@ioctls, $_);
}
Add tracing and retracing for VIDIOC_DQEVENT, VIDIOC_SUBSCRIBE_EVENT, and VIDIOC_UNSUBSCRIBE_EVENT ioctls. Signed-off-by: Deborah Brouwer <deborah.brouwer@collabora.com> --- utils/v4l2-tracer/libv4l2tracer.cpp | 3 ++ utils/v4l2-tracer/retrace.cpp | 81 ++++++++++++++++++++++++++-- utils/v4l2-tracer/trace.cpp | 7 +++ utils/v4l2-tracer/v4l2-tracer-gen.pl | 45 +++++++++++++--- 4 files changed, 126 insertions(+), 10 deletions(-)