1 /* SPDX-License-Identifier: GPL-2.0-only */
2 /*
3 * Copyright 2022 Collabora Ltd.
4 */
5
6 #include "trace.h"
7
8 extern struct trace_context ctx_trace;
9
trace_open(int fd,const char * path,int oflag,mode_t mode,bool is_open64)10 void trace_open(int fd, const char *path, int oflag, mode_t mode, bool is_open64)
11 {
12 json_object *open_obj = json_object_new_object();
13 json_object_object_add(open_obj, "fd", json_object_new_int(fd));
14
15 json_object *open_args = json_object_new_object();
16 json_object_object_add(open_args, "path", json_object_new_string(path));
17 json_object_object_add(open_args, "oflag",
18 json_object_new_string(val2s(oflag, open_val_def).c_str()));
19 json_object_object_add(open_args, "mode", json_object_new_string(number2s_oct(mode).c_str()));
20 if (is_open64)
21 json_object_object_add(open_obj, "open64", open_args);
22 else
23 json_object_object_add(open_obj, "open", open_args);
24
25 /* Add additional topology information about device. */
26 std::string path_str = path;
27 bool is_media = path_str.find("media") != std::string::npos;
28 bool is_video = path_str.find("video") != std::string::npos;
29
30 int media_fd = -1;
31 if (is_media)
32 media_fd = fd;
33
34 std::string driver;
35 if (is_video) {
36 struct v4l2_capability cap = {};
37 setenv("V4L2_TRACER_PAUSE_TRACE", "true", 0);
38 ioctl(fd, VIDIOC_QUERYCAP, &cap);
39 unsetenv("V4L2_TRACER_PAUSE_TRACE");
40
41 std::string path_media = get_path_media(reinterpret_cast<const char *>(cap.driver));
42
43 setenv("V4L2_TRACER_PAUSE_TRACE", "true", 0);
44 media_fd = open(path_media.c_str(), O_RDONLY);
45 unsetenv("V4L2_TRACER_PAUSE_TRACE");
46 }
47
48 struct media_device_info info = {};
49 ioctl(media_fd, MEDIA_IOC_DEVICE_INFO, &info);
50
51 json_object_object_add(open_obj, "driver", json_object_new_string(info.driver));
52 json_object_object_add(open_obj, "bus_info", json_object_new_string(info.bus_info));
53
54 if (is_video) {
55 std::list<std::string> linked_entities = get_linked_entities(media_fd, path_str);
56 json_object *linked_entities_obj = json_object_new_array();
57 for (auto &name : linked_entities)
58 json_object_array_add(linked_entities_obj, json_object_new_string(name.c_str()));
59 json_object_object_add(open_obj, "linked_entities", linked_entities_obj);
60 setenv("V4L2_TRACER_PAUSE_TRACE", "true", 0);
61 close(media_fd);
62 unsetenv("V4L2_TRACER_PAUSE_TRACE");
63 }
64
65 write_json_object_to_json_file(open_obj);
66 json_object_put(open_obj);
67 }
68
trace_mmap(void * addr,size_t len,int prot,int flags,int fildes,off_t off,unsigned long buf_address,bool is_mmap64)69 void trace_mmap(void *addr, size_t len, int prot, int flags, int fildes, off_t off, unsigned long buf_address, bool is_mmap64)
70 {
71 json_object *mmap_obj = json_object_new_object();
72
73 if (errno)
74 json_object_object_add(mmap_obj, "errno", json_object_new_string(STRERR(errno)));
75
76 json_object *mmap_args = json_object_new_object();
77 json_object_object_add(mmap_args, "addr", json_object_new_int64((int64_t)addr));
78 json_object_object_add(mmap_args, "len", json_object_new_uint64(len));
79 json_object_object_add(mmap_args, "prot", json_object_new_int(prot));
80 json_object_object_add(mmap_args, "flags", json_object_new_string(number2s(flags).c_str()));
81 json_object_object_add(mmap_args, "fildes", json_object_new_int(fildes));
82 json_object_object_add(mmap_args, "off", json_object_new_int64(off));
83
84 if (is_mmap64)
85 json_object_object_add(mmap_obj, "mmap64", mmap_args);
86 else
87 json_object_object_add(mmap_obj, "mmap", mmap_args);
88
89 json_object_object_add(mmap_obj, "buffer_address", json_object_new_uint64(buf_address));
90
91 write_json_object_to_json_file(mmap_obj);
92 json_object_put(mmap_obj);
93 }
94
trace_buffer(unsigned char * buffer_pointer,__u32 bytesused)95 json_object *trace_buffer(unsigned char *buffer_pointer, __u32 bytesused)
96 {
97 const int BUF_SIZE = 5;
98 const int MAX_BYTES_PER_LINE = 32;
99 char buf[BUF_SIZE];
100 std::string str;
101 int byte_count_per_line = 0;
102 json_object *mem_array_obj = json_object_new_array();
103
104 for (__u32 i = 0; i < bytesused; i++) {
105 memset(buf, 0, BUF_SIZE);
106 /* Each byte e.g. D9 will write a string of two characters "D9". */
107 sprintf(buf, "%02x", buffer_pointer[i]);
108 str += buf;
109 byte_count_per_line++;
110
111 /* Add a newline every 32 bytes. */
112 if (byte_count_per_line == MAX_BYTES_PER_LINE) {
113 byte_count_per_line = 0;
114 json_object_array_add(mem_array_obj, json_object_new_string(str.c_str()));
115 str.clear();
116 } else if (getenv("V4L2_TRACER_OPTION_COMPACT_PRINT") == nullptr) {
117 /* Add a space every byte e.g. "01 2A 40 01" */
118 str += " ";
119 }
120 }
121
122 /* Trace the last line if it was less than a full line. */
123 if (byte_count_per_line)
124 json_object_array_add(mem_array_obj, json_object_new_string(str.c_str()));
125
126 return mem_array_obj;
127 }
128
trace_mem(int fd,__u32 offset,__u32 type,int index,__u32 bytesused,unsigned long start)129 void trace_mem(int fd, __u32 offset, __u32 type, int index, __u32 bytesused, unsigned long start)
130 {
131 json_object *mem_obj = json_object_new_object();
132 json_object_object_add(mem_obj, "mem_dump",
133 json_object_new_string(val2s(type, v4l2_buf_type_val_def).c_str()));
134 json_object_object_add(mem_obj, "fd", json_object_new_int(fd));
135 json_object_object_add(mem_obj, "offset", json_object_new_uint64(offset));
136 json_object_object_add(mem_obj, "index", json_object_new_int(index));
137 json_object_object_add(mem_obj, "bytesused", json_object_new_uint64(bytesused));
138 json_object_object_add(mem_obj, "address", json_object_new_uint64(start));
139
140 if ((type == V4L2_BUF_TYPE_VIDEO_OUTPUT || type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) ||
141 (getenv("V4L2_TRACER_OPTION_WRITE_DECODED_TO_JSON_FILE") != nullptr)) {
142 json_object *mem_array_obj = trace_buffer((unsigned char*) start, bytesused);
143 json_object_object_add(mem_obj, "mem_array", mem_array_obj);
144 }
145
146 write_json_object_to_json_file(mem_obj);
147
148 json_object_put(mem_obj);
149 }
150
trace_mem_encoded(int fd,__u32 offset)151 void trace_mem_encoded(int fd, __u32 offset)
152 {
153 unsigned long start = get_buffer_address_trace(fd, offset);
154 if (start == 0U)
155 return;
156
157 __u32 bytesused = get_buffer_bytesused_trace(fd, offset);
158 __u32 type = get_buffer_type_trace(fd, offset);
159 int index = get_buffer_index_trace(fd, offset);
160 trace_mem(fd, offset, type, index, bytesused, start);
161 }
162
trace_mem_decoded(void)163 void trace_mem_decoded(void)
164 {
165 int displayed_count = 0;
166 unsigned expected_length = get_expected_length_trace();
167
168 while (!ctx_trace.decode_order.empty()) {
169 std::list<buffer_trace>::iterator it;
170 long next_frame_to_be_displayed = *std::min_element(ctx_trace.decode_order.begin(),
171 ctx_trace.decode_order.end());
172 for (it = ctx_trace.buffers.begin(); it != ctx_trace.buffers.end(); ++it) {
173 if (it->display_order != next_frame_to_be_displayed)
174 continue;
175 if (!it->address)
176 break;
177 /*
178 * If bytesused exceeds the expected length of the decoded video data,
179 * then assume that this is extraneous padding or info added by the driver
180 * and do not trace it.
181 */
182 if (it->bytesused < expected_length)
183 break;
184 debug_line_info("\n\tDisplaying: %ld, %s, index: %d", it->display_order,
185 val2s(it->type, v4l2_buf_type_val_def).c_str(), it->index);
186 displayed_count++;
187
188 if (getenv("V4L2_TRACER_OPTION_WRITE_DECODED_TO_YUV_FILE") != nullptr) {
189 std::string filename;
190 if (getenv("TRACE_ID") != nullptr)
191 filename = getenv("TRACE_ID");
192 filename += ".yuv";
193 FILE *fp = fopen(filename.c_str(), "a");
194 unsigned char *buffer_pointer = (unsigned char*) it->address;
195 for (__u32 i = 0; i < expected_length; i++)
196 fwrite(&buffer_pointer[i], sizeof(unsigned char), 1, fp);
197 fclose(fp);
198 }
199 trace_mem(it->fd, it->offset, it->type, it->index, it->bytesused, it->address);
200 ctx_trace.decode_order.remove(next_frame_to_be_displayed);
201 it->display_order = -1;
202 break;
203 }
204 if (!it->address || it == ctx_trace.buffers.end() || it->bytesused < expected_length)
205 break;
206 }
207 }
208
trace_v4l2_plane(struct v4l2_plane * ptr,__u32 memory)209 json_object *trace_v4l2_plane(struct v4l2_plane *ptr, __u32 memory)
210 {
211 json_object *plane_obj = json_object_new_object();
212
213 json_object_object_add(plane_obj, "bytesused", json_object_new_int64(ptr->bytesused));
214 json_object_object_add(plane_obj, "length", json_object_new_int64(ptr->length));
215
216 json_object *m_obj = json_object_new_object();
217
218 if (memory == V4L2_MEMORY_MMAP)
219 json_object_object_add(m_obj, "mem_offset", json_object_new_int64(ptr->m.mem_offset));
220 json_object_object_add(plane_obj, "m", m_obj);
221
222 json_object_object_add(plane_obj, "data_offset", json_object_new_int64(ptr->data_offset));
223
224 return plane_obj;
225 }
226
trace_v4l2_buffer(void * arg,json_object * ioctl_args)227 void trace_v4l2_buffer(void *arg, json_object *ioctl_args)
228 {
229 json_object *buf_obj = json_object_new_object();
230 struct v4l2_buffer *buf = static_cast<struct v4l2_buffer*>(arg);
231
232 json_object_object_add(buf_obj, "index", json_object_new_uint64(buf->index));
233 json_object_object_add(buf_obj, "type",
234 json_object_new_string(val2s(buf->type, v4l2_buf_type_val_def).c_str()));
235 json_object_object_add(buf_obj, "bytesused", json_object_new_uint64(buf->bytesused));
236 json_object_object_add(buf_obj, "flags", json_object_new_string(fl2s_buffer(buf->flags).c_str()));
237 json_object_object_add(buf_obj, "field",
238 json_object_new_string(val2s(buf->field, v4l2_field_val_def).c_str()));
239 json_object *timestamp_obj = json_object_new_object();
240 json_object_object_add(timestamp_obj, "tv_sec", json_object_new_int64(buf->timestamp.tv_sec));
241 json_object_object_add(timestamp_obj, "tv_usec",
242 json_object_new_int64(buf->timestamp.tv_usec));
243 json_object_object_add(buf_obj, "timestamp", timestamp_obj);
244 json_object_object_add(buf_obj, "timestamp_ns",
245 json_object_new_uint64(v4l2_timeval_to_ns(&buf->timestamp)));
246
247 json_object_object_add(buf_obj, "sequence", json_object_new_uint64(buf->sequence));
248 json_object_object_add(buf_obj, "memory",
249 json_object_new_string(val2s(buf->memory, v4l2_memory_val_def).c_str()));
250
251 json_object *m_obj = json_object_new_object();
252 if (buf->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE ||
253 buf->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
254 json_object *planes_obj = json_object_new_array();
255 /* TODO add planes > 0 */
256 json_object_array_add(planes_obj, trace_v4l2_plane(buf->m.planes, buf->memory));
257 json_object_object_add(m_obj, "planes", planes_obj);
258 }
259
260 if (buf->type == V4L2_BUF_TYPE_VIDEO_CAPTURE ||
261 buf->type == V4L2_BUF_TYPE_VIDEO_OUTPUT) {
262 if (buf->memory == V4L2_MEMORY_MMAP)
263 json_object_object_add(m_obj, "offset", json_object_new_uint64(buf->m.offset));
264 }
265 json_object_object_add(buf_obj, "m", m_obj);
266 json_object_object_add(buf_obj, "length", json_object_new_uint64(buf->length));
267
268 if (buf->flags & V4L2_BUF_FLAG_REQUEST_FD)
269 json_object_object_add(buf_obj, "request_fd", json_object_new_int(buf->request_fd));
270
271 json_object_object_add(ioctl_args, "v4l2_buffer", buf_obj);
272 }
273
trace_vidioc_stream(void * arg,json_object * ioctl_args)274 void trace_vidioc_stream(void *arg, json_object *ioctl_args)
275 {
276 v4l2_buf_type buf_type = *(static_cast<v4l2_buf_type*>(arg));
277 json_object_object_add(ioctl_args, "type",
278 json_object_new_string(val2s(buf_type, v4l2_buf_type_val_def).c_str()));
279 }
280
trace_v4l2_streamparm(void * arg,json_object * ioctl_args)281 void trace_v4l2_streamparm(void *arg, json_object *ioctl_args)
282 {
283 json_object *v4l2_streamparm_obj = json_object_new_object();
284 struct v4l2_streamparm *streamparm = static_cast<struct v4l2_streamparm*>(arg);
285
286 json_object_object_add(v4l2_streamparm_obj, "type",
287 json_object_new_string(val2s(streamparm->type, v4l2_buf_type_val_def).c_str()));
288
289 if ((streamparm->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) ||
290 (streamparm->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE))
291 trace_v4l2_captureparm_gen(&streamparm->parm, v4l2_streamparm_obj);
292
293 if ((streamparm->type == V4L2_BUF_TYPE_VIDEO_OUTPUT) ||
294 (streamparm->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE))
295 trace_v4l2_outputparm_gen(&streamparm->parm, v4l2_streamparm_obj);
296
297 json_object_object_add(ioctl_args, "v4l2_streamparm", v4l2_streamparm_obj);
298 }
299
trace_v4l2_ext_control(void * arg,json_object * parent_obj,std::string key_name="")300 void trace_v4l2_ext_control(void *arg, json_object *parent_obj, std::string key_name = "")
301 {
302 json_object *v4l2_ext_control_obj = json_object_new_object();
303 struct v4l2_ext_control *p = static_cast<struct v4l2_ext_control*>(arg);
304
305 json_object_object_add(v4l2_ext_control_obj, "id",
306 json_object_new_string(val2s(p->id, control_val_def).c_str()));
307 json_object_object_add(v4l2_ext_control_obj, "size", json_object_new_uint64(p->size));
308
309 /* trace controls of type V4L2_CTRL_TYPE_MENU */
310 switch (p->id) {
311 case V4L2_CID_STATELESS_H264_DECODE_MODE: {
312 json_object_object_add(v4l2_ext_control_obj, "value",
313 json_object_new_string(val2s(p->value, v4l2_stateless_h264_decode_mode_val_def).c_str()));
314 json_object_array_add(parent_obj, v4l2_ext_control_obj);
315 return;
316 }
317 case V4L2_CID_STATELESS_H264_START_CODE: {
318 json_object_object_add(v4l2_ext_control_obj, "value",
319 json_object_new_string(val2s(p->value, v4l2_stateless_h264_start_code_val_def).c_str()));
320 json_object_array_add(parent_obj, v4l2_ext_control_obj);
321 return;
322 }
323 case V4L2_CID_STATELESS_HEVC_DECODE_MODE: {
324 json_object_object_add(v4l2_ext_control_obj, "value",
325 json_object_new_string(val2s(p->value, v4l2_stateless_hevc_decode_mode_val_def).c_str()));
326 json_object_array_add(parent_obj, v4l2_ext_control_obj);
327 return;
328 }
329 case V4L2_CID_STATELESS_HEVC_START_CODE: {
330 json_object_object_add(v4l2_ext_control_obj, "value",
331 json_object_new_string(val2s(p->value, v4l2_stateless_hevc_start_code_val_def).c_str()));
332 json_object_array_add(parent_obj, v4l2_ext_control_obj);
333 return;
334 }
335 default:
336 break;
337 }
338
339 if (p->ptr == nullptr) {
340 json_object_array_add(parent_obj, v4l2_ext_control_obj);
341 return;
342 }
343
344 switch (p->id) {
345 case V4L2_CID_STATELESS_VP8_FRAME:
346 trace_v4l2_ctrl_vp8_frame_gen(p->p_vp8_frame, v4l2_ext_control_obj);
347 break;
348 case V4L2_CID_STATELESS_H264_SPS:
349 trace_v4l2_ctrl_h264_sps_gen(p->p_h264_sps, v4l2_ext_control_obj);
350 break;
351 case V4L2_CID_STATELESS_H264_PPS:
352 trace_v4l2_ctrl_h264_pps_gen(p->p_h264_pps, v4l2_ext_control_obj);
353 break;
354 case V4L2_CID_STATELESS_H264_SCALING_MATRIX:
355 trace_v4l2_ctrl_h264_scaling_matrix_gen(p->p_h264_scaling_matrix, v4l2_ext_control_obj);
356 break;
357 case V4L2_CID_STATELESS_H264_PRED_WEIGHTS:
358 trace_v4l2_ctrl_h264_pred_weights_gen(p->p_h264_pred_weights, v4l2_ext_control_obj);
359 break;
360 case V4L2_CID_STATELESS_H264_SLICE_PARAMS:
361 trace_v4l2_ctrl_h264_slice_params_gen(p->p_h264_slice_params, v4l2_ext_control_obj);
362 break;
363 case V4L2_CID_STATELESS_H264_DECODE_PARAMS:
364 trace_v4l2_ctrl_h264_decode_params_gen(p->p_h264_decode_params, v4l2_ext_control_obj);
365 break;
366 case V4L2_CID_STATELESS_FWHT_PARAMS:
367 trace_v4l2_ctrl_fwht_params_gen(p->p_fwht_params, v4l2_ext_control_obj);
368 break;
369 case V4L2_CID_STATELESS_VP9_FRAME:
370 trace_v4l2_ctrl_vp9_frame_gen(p->p_vp9_frame, v4l2_ext_control_obj);
371 break;
372 case V4L2_CID_STATELESS_VP9_COMPRESSED_HDR:
373 trace_v4l2_ctrl_vp9_compressed_hdr_gen(p->p_vp9_compressed_hdr_probs, v4l2_ext_control_obj);
374 break;
375 case V4L2_CID_STATELESS_HEVC_SPS:
376 trace_v4l2_ctrl_hevc_sps_gen(p->p_hevc_sps, v4l2_ext_control_obj);
377 break;
378 case V4L2_CID_STATELESS_HEVC_PPS:
379 trace_v4l2_ctrl_hevc_pps_gen(p->p_hevc_pps, v4l2_ext_control_obj);
380 break;
381 case V4L2_CID_STATELESS_HEVC_SLICE_PARAMS:
382 trace_v4l2_ctrl_hevc_slice_params_gen(p->p_hevc_slice_params, v4l2_ext_control_obj);
383 break;
384 case V4L2_CID_STATELESS_HEVC_SCALING_MATRIX:
385 trace_v4l2_ctrl_hevc_scaling_matrix_gen(p->p_hevc_scaling_matrix, v4l2_ext_control_obj);
386 break;
387 case V4L2_CID_STATELESS_HEVC_DECODE_PARAMS:
388 trace_v4l2_ctrl_hevc_decode_params_gen(p->p_hevc_decode_params, v4l2_ext_control_obj);
389 break;
390 case V4L2_CID_STATELESS_HEVC_ENTRY_POINT_OFFSETS: {
391 /* V4L2_CTRL_TYPE_U32, V4L2_CTRL_FLAG_DYNAMIC_ARRAY */
392 __u32 elems = ctx_trace.elems;
393 json_object_object_add(v4l2_ext_control_obj, "elems", json_object_new_int64(elems));
394 json_object *hevc_entry_point_offsets_obj = json_object_new_array();
395 for (__u32 i = 0; i < elems; i++)
396 json_object_array_add(hevc_entry_point_offsets_obj, json_object_new_int64(p->p_u32[i]));
397 json_object_object_add(v4l2_ext_control_obj, "p_u32", hevc_entry_point_offsets_obj);
398 break;
399 }
400 case V4L2_CID_STATELESS_MPEG2_SEQUENCE:
401 trace_v4l2_ctrl_mpeg2_sequence_gen(p->p_mpeg2_sequence, v4l2_ext_control_obj);
402 break;
403 case V4L2_CID_STATELESS_MPEG2_PICTURE:
404 trace_v4l2_ctrl_mpeg2_picture_gen(p->p_mpeg2_picture, v4l2_ext_control_obj);
405 break;
406 case V4L2_CID_STATELESS_MPEG2_QUANTISATION:
407 trace_v4l2_ctrl_mpeg2_quantisation_gen(p->p_mpeg2_quantisation, v4l2_ext_control_obj);
408 break;
409 case V4L2_CID_MPEG_VIDEO_DEC_PTS:
410 case V4L2_CID_MPEG_VIDEO_DEC_FRAME:
411 case V4L2_CID_MPEG_VIDEO_DEC_CONCEAL_COLOR:
412 case V4L2_CID_PIXEL_RATE:
413 json_object_object_add(v4l2_ext_control_obj, "value64", json_object_new_int64(p->value64));
414 break;
415 case V4L2_CID_STATELESS_AV1_SEQUENCE:
416 trace_v4l2_ctrl_av1_sequence_gen(p->p_av1_sequence, v4l2_ext_control_obj);
417 break;
418 case V4L2_CID_STATELESS_AV1_TILE_GROUP_ENTRY:
419 trace_v4l2_ctrl_av1_tile_group_entry_gen(p->p_av1_tile_group_entry, v4l2_ext_control_obj);
420 break;
421 case V4L2_CID_STATELESS_AV1_FRAME:
422 trace_v4l2_ctrl_av1_frame_gen(p->p_av1_frame, v4l2_ext_control_obj);
423 break;
424 case V4L2_CID_STATELESS_AV1_FILM_GRAIN:
425 trace_v4l2_ctrl_av1_film_grain_gen(p->p_av1_film_grain, v4l2_ext_control_obj);
426 break;
427 default:
428 if (p->size)
429 line_info("\n\tWarning: cannot trace control: %s", val2s(p->id, control_val_def).c_str());
430 else
431 json_object_object_add(v4l2_ext_control_obj, "value", json_object_new_int(p->value));
432 break;
433 }
434
435 json_object_array_add(parent_obj, v4l2_ext_control_obj);
436 }
437
trace_v4l2_ext_controls(void * arg,json_object * ioctl_args)438 void trace_v4l2_ext_controls(void *arg, json_object *ioctl_args)
439 {
440 json_object *ext_controls_obj = json_object_new_object();
441 struct v4l2_ext_controls *ext_controls = static_cast<struct v4l2_ext_controls*>(arg);
442
443 json_object_object_add(ext_controls_obj, "which",
444 json_object_new_string(val2s(ext_controls->which, which_val_def).c_str()));
445
446 json_object_object_add(ext_controls_obj, "count", json_object_new_int64(ext_controls->count));
447
448 /* error_idx is defined only if the ioctl returned an error */
449 if (errno)
450 json_object_object_add(ext_controls_obj, "error_idx",
451 json_object_new_uint64(ext_controls->error_idx));
452
453 /* request_fd is only valid when "which" == V4L2_CTRL_WHICH_REQUEST_VAL */
454 if (ext_controls->which == V4L2_CTRL_WHICH_REQUEST_VAL)
455 json_object_object_add(ext_controls_obj, "request_fd",
456 json_object_new_int(ext_controls->request_fd));
457
458 json_object *controls_obj = json_object_new_array();
459 for (__u32 i = 0; i < ext_controls->count; i++) {
460 if ((void *) ext_controls->controls == nullptr)
461 break;
462 trace_v4l2_ext_control((void *) &ext_controls->controls[i], controls_obj);
463 }
464 json_object_object_add(ext_controls_obj, "controls", controls_obj);
465
466 json_object_object_add(ioctl_args, "v4l2_ext_controls", ext_controls_obj);
467 }
468
trace_v4l2_decoder_cmd(void * arg,json_object * ioctl_args)469 void trace_v4l2_decoder_cmd(void *arg, json_object *ioctl_args)
470 {
471 json_object *v4l2_decoder_cmd_obj = json_object_new_object();
472 struct v4l2_decoder_cmd *ptr = static_cast<struct v4l2_decoder_cmd*>(arg);
473
474 json_object_object_add(v4l2_decoder_cmd_obj, "cmd",
475 json_object_new_string(val2s(ptr->cmd, decoder_cmd_val_def).c_str()));
476
477 std::string flags;
478
479 switch (ptr->cmd) {
480 case V4L2_DEC_CMD_START: {
481 flags = fl2s(ptr->flags, v4l2_decoder_cmd_start_flag_def);
482 /* struct start */
483 json_object *start_obj = json_object_new_object();
484 json_object_object_add(start_obj, "speed", json_object_new_int(ptr->start.speed));
485
486 std::string format;
487 /* possible values V4L2_DEC_START_FMT_NONE, V4L2_DEC_START_FMT_GOP */
488 if (ptr->start.format == V4L2_DEC_START_FMT_GOP)
489 format = "V4L2_DEC_START_FMT_GOP";
490 else if (ptr->start.format == V4L2_DEC_START_FMT_NONE)
491 format = "V4L2_DEC_START_FMT_NONE";
492 json_object_object_add(start_obj, "format", json_object_new_string(format.c_str()));
493
494 json_object_object_add(v4l2_decoder_cmd_obj, "start", start_obj);
495 break;
496 }
497 case V4L2_DEC_CMD_STOP: {
498 flags = fl2s(ptr->flags, v4l2_decoder_cmd_stop_flag_def);
499 json_object *stop_obj = json_object_new_object();
500 json_object_object_add(stop_obj, "pts", json_object_new_uint64(ptr->stop.pts));
501
502 json_object_object_add(v4l2_decoder_cmd_obj, "stop", stop_obj);
503 break;
504 }
505
506 case V4L2_DEC_CMD_PAUSE: {
507 flags = fl2s(ptr->flags, v4l2_decoder_cmd_pause_flag_def);
508 break;
509 }
510 case V4L2_DEC_CMD_RESUME:
511 case V4L2_DEC_CMD_FLUSH:
512 default:
513 break;
514 }
515 json_object_object_add(v4l2_decoder_cmd_obj, "flags", json_object_new_string(flags.c_str()));
516
517 json_object_object_add(ioctl_args, "v4l2_decoder_cmd", v4l2_decoder_cmd_obj);
518 }
519
trace_ioctl_args(unsigned long cmd,void * arg)520 json_object *trace_ioctl_args(unsigned long cmd, void *arg)
521 {
522 json_object *ioctl_args = json_object_new_object();
523
524 switch (cmd) {
525 case VIDIOC_QUERYCAP:
526 trace_v4l2_capability_gen(arg, ioctl_args);
527 break;
528 case VIDIOC_ENUM_FMT:
529 trace_v4l2_fmtdesc_gen(arg, ioctl_args);
530 break;
531 case VIDIOC_G_FMT:
532 case VIDIOC_TRY_FMT:
533 case VIDIOC_S_FMT:
534 trace_v4l2_format_gen(arg, ioctl_args);
535 break;
536 case VIDIOC_REQBUFS:
537 trace_v4l2_requestbuffers_gen(arg, ioctl_args);
538 break;
539 case VIDIOC_PREPARE_BUF:
540 case VIDIOC_QUERYBUF:
541 case VIDIOC_QBUF:
542 case VIDIOC_DQBUF:
543 trace_v4l2_buffer(arg, ioctl_args);
544 break;
545 case VIDIOC_EXPBUF:
546 trace_v4l2_exportbuffer_gen(arg, ioctl_args);
547 break;
548 case VIDIOC_STREAMON:
549 case VIDIOC_STREAMOFF:
550 trace_vidioc_stream(arg, ioctl_args);
551 break;
552 case VIDIOC_G_PARM:
553 case VIDIOC_S_PARM:
554 trace_v4l2_streamparm(arg, ioctl_args);
555 break;
556 case VIDIOC_ENUMINPUT:
557 trace_v4l2_input_gen(arg, ioctl_args);
558 break;
559 case VIDIOC_G_CTRL:
560 case VIDIOC_S_CTRL:
561 trace_v4l2_control_gen(arg, ioctl_args);
562 break;
563 case VIDIOC_G_TUNER:
564 case VIDIOC_S_TUNER:
565 trace_v4l2_tuner_gen(arg, ioctl_args);
566 break;
567 case VIDIOC_QUERYCTRL:
568 trace_v4l2_queryctrl_gen(arg, ioctl_args);
569 break;
570 case VIDIOC_G_INPUT:
571 case VIDIOC_S_INPUT: {
572 int *input = static_cast<int*>(arg);
573 json_object_object_add(ioctl_args, "input", json_object_new_int(*input));
574 break;
575 }
576 case VIDIOC_G_OUTPUT:
577 case VIDIOC_S_OUTPUT: {
578 int *output = static_cast<int*>(arg);
579 json_object_object_add(ioctl_args, "output", json_object_new_int(*output));
580 break;
581 }
582 case VIDIOC_ENUMOUTPUT:
583 trace_v4l2_output_gen(arg, ioctl_args);
584 break;
585 case VIDIOC_G_CROP:
586 case VIDIOC_S_CROP:
587 trace_v4l2_crop_gen(arg, ioctl_args);
588 break;
589 case VIDIOC_G_EXT_CTRLS:
590 case VIDIOC_TRY_EXT_CTRLS:
591 case VIDIOC_S_EXT_CTRLS:
592 trace_v4l2_ext_controls(arg, ioctl_args);
593 break;
594 case VIDIOC_ENUM_FRAMESIZES:
595 trace_v4l2_frmsizeenum_gen(arg, ioctl_args);
596 break;
597 case VIDIOC_ENUM_FRAMEINTERVALS:
598 trace_v4l2_frmivalenum_gen(arg, ioctl_args);
599 break;
600 case VIDIOC_TRY_ENCODER_CMD:
601 case VIDIOC_ENCODER_CMD:
602 trace_v4l2_encoder_cmd_gen(arg, ioctl_args);
603 break;
604 case VIDIOC_DQEVENT:
605 trace_v4l2_event_gen(arg, ioctl_args);
606 break;
607 case VIDIOC_SUBSCRIBE_EVENT:
608 case VIDIOC_UNSUBSCRIBE_EVENT:
609 trace_v4l2_event_subscription_gen(arg, ioctl_args);
610 break;
611 case VIDIOC_CREATE_BUFS:
612 trace_v4l2_create_buffers_gen(arg, ioctl_args);
613 break;
614 case VIDIOC_G_SELECTION:
615 case VIDIOC_S_SELECTION:
616 trace_v4l2_selection_gen(arg, ioctl_args);
617 break;
618 case VIDIOC_TRY_DECODER_CMD:
619 case VIDIOC_DECODER_CMD:
620 trace_v4l2_decoder_cmd(arg, ioctl_args);
621 break;
622 case VIDIOC_QUERY_EXT_CTRL:
623 trace_v4l2_query_ext_ctrl_gen(arg, ioctl_args);
624 break;
625 case MEDIA_IOC_REQUEST_ALLOC: {
626 __s32 *request_fd = static_cast<__s32*>(arg);
627 json_object_object_add(ioctl_args, "request_fd", json_object_new_int(*request_fd));
628 break;
629 }
630 default:
631 break;
632 }
633
634 return ioctl_args;
635 }
636