• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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