• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /* Copyright (c) 2012 The Chromium OS Authors. All rights reserved.
2  * Use of this source code is governed by a BSD-style license that can be
3  * found in the LICENSE file.
4  */
5 
6 #include <errno.h>
7 #include <fcntl.h>
8 #include <getopt.h>
9 #include <inttypes.h>
10 #include <limits.h>
11 #include <math.h>
12 #include <pthread.h>
13 #include <stdio.h>
14 #include <stdint.h>
15 #include <stdlib.h>
16 #include <string.h>
17 #include <syslog.h>
18 #include <sys/mman.h>
19 #include <sys/param.h>
20 #include <sys/select.h>
21 #include <sys/stat.h>
22 #include <sys/types.h>
23 #include <unistd.h>
24 
25 #include "cras_client.h"
26 #include "cras_types.h"
27 #include "cras_util.h"
28 #include "cras_version.h"
29 
30 #define NOT_ASSIGNED (0)
31 #define PLAYBACK_BUFFERED_TIME_IN_US (5000)
32 
33 #define BUF_SIZE 32768
34 
35 static const size_t MAX_IODEVS = 10; /* Max devices to print out. */
36 static const size_t MAX_IONODES = 20; /* Max ionodes to print out. */
37 static const size_t MAX_ATTACHED_CLIENTS = 10; /* Max clients to print out. */
38 
39 static int pipefd[2];
40 static struct timespec last_latency;
41 static int show_latency;
42 static float last_rms_sqr_sum;
43 static int last_rms_size;
44 static float total_rms_sqr_sum;
45 static int total_rms_size;
46 static int show_rms;
47 static int show_total_rms;
48 static int keep_looping = 1;
49 static int exit_after_done_playing = 1;
50 static size_t duration_frames;
51 static int pause_client = 0;
52 static int pause_a_reply = 0;
53 static int pause_in_playback_reply = 1000;
54 
55 static char *channel_layout = NULL;
56 static int pin_device_id;
57 
58 static int play_short_sound = 0;
59 static int play_short_sound_periods = 0;
60 static int play_short_sound_periods_left = 0;
61 
62 static int effect_aec = 0;
63 static int effect_ns = 0;
64 static int effect_agc = 0;
65 static int effect_vad = 0;
66 static char *aecdump_file = NULL;
67 static char time_str[128];
68 
69 /* Sleep interval between cras_client_read_atlog calls. */
70 static const struct timespec follow_atlog_sleep_ts = {
71 	0, 50 * 1000 * 1000 /* 50 ms. */
72 };
73 
74 /* Conditional so the client thread can signal that main should exit. */
75 static pthread_mutex_t done_mutex = PTHREAD_MUTEX_INITIALIZER;
76 static pthread_cond_t done_cond = PTHREAD_COND_INITIALIZER;
77 
78 struct cras_audio_format *aud_format;
79 struct {
80 	char *name;
81 	snd_pcm_format_t format;
82 } supported_formats[] = {
83 	{ "S16_LE", SND_PCM_FORMAT_S16_LE },
84 	{ "S24_LE", SND_PCM_FORMAT_S24_LE },
85 	{ "S32_LE", SND_PCM_FORMAT_S32_LE },
86 	{ NULL, 0 },
87 };
88 
terminate_stream_loop()89 static int terminate_stream_loop()
90 {
91 	keep_looping = 0;
92 	return write(pipefd[1], "1", 1);
93 }
94 
get_block_size(uint64_t buffer_time_in_us,size_t rate)95 static size_t get_block_size(uint64_t buffer_time_in_us, size_t rate)
96 {
97 	return (size_t)(buffer_time_in_us * rate / 1000000);
98 }
99 
check_stream_terminate(size_t frames)100 static void check_stream_terminate(size_t frames)
101 {
102 	if (duration_frames) {
103 		if (duration_frames <= frames)
104 			terminate_stream_loop();
105 		else
106 			duration_frames -= frames;
107 	}
108 }
109 
fill_time_offset(time_t * sec_offset,int32_t * nsec_offset)110 static void fill_time_offset(time_t *sec_offset, int32_t *nsec_offset)
111 {
112 	struct timespec mono_time, real_time;
113 
114 	clock_gettime(CLOCK_MONOTONIC_RAW, &mono_time);
115 	clock_gettime(CLOCK_REALTIME, &real_time);
116 	*sec_offset = real_time.tv_sec - mono_time.tv_sec;
117 	*nsec_offset = real_time.tv_nsec - mono_time.tv_nsec;
118 }
119 
120 /* Compute square sum of samples (for calculation of RMS value). */
compute_sqr_sum_16(const int16_t * samples,int size)121 float compute_sqr_sum_16(const int16_t *samples, int size)
122 {
123 	unsigned i;
124 	float sqr_sum = 0;
125 
126 	for (i = 0; i < size; i++)
127 		sqr_sum += samples[i] * samples[i];
128 
129 	return sqr_sum;
130 }
131 
132 /* Update the RMS values with the given samples. */
update_rms(const uint8_t * samples,int size)133 int update_rms(const uint8_t *samples, int size)
134 {
135 	switch (aud_format->format) {
136 	case SND_PCM_FORMAT_S16_LE: {
137 		last_rms_sqr_sum =
138 			compute_sqr_sum_16((int16_t *)samples, size / 2);
139 		last_rms_size = size / 2;
140 		break;
141 	}
142 	default:
143 		return -EINVAL;
144 	}
145 
146 	total_rms_sqr_sum += last_rms_sqr_sum;
147 	total_rms_size += last_rms_size;
148 
149 	return 0;
150 }
151 
152 /* Parses a string with format <N>:<M> into a node id*/
parse_node_id(char * input,cras_node_id_t * id_out)153 static int parse_node_id(char *input, cras_node_id_t *id_out)
154 {
155 	const char *s;
156 	char *endptr;
157 	int dev_index;
158 	int node_index;
159 
160 	if (!id_out)
161 		return -EINVAL;
162 
163 	s = strtok(input, ":");
164 	if (!s)
165 		return -EINVAL;
166 	dev_index = strtol(s, &endptr, 10);
167 	if (*endptr)
168 		return -EINVAL;
169 
170 	s = strtok(NULL, ":");
171 	if (!s)
172 		return -EINVAL;
173 	node_index = strtol(s, &endptr, 10);
174 	if (*endptr)
175 		return -EINVAL;
176 
177 	*id_out = cras_make_node_id(dev_index, node_index);
178 	return 0;
179 }
180 
181 /* Parses a string with format <N>:<M>:<0-100> into a node id and a value */
parse_node_id_with_value(char * input,cras_node_id_t * id_out,int * value_out)182 static int parse_node_id_with_value(char *input, cras_node_id_t *id_out,
183 				    int *value_out)
184 {
185 	const char *s;
186 	char *endptr;
187 	int dev_index;
188 	int node_index;
189 	long int value;
190 
191 	if (!id_out || !value_out)
192 		return -EINVAL;
193 
194 	s = strtok(input, ":");
195 	if (!s)
196 		return -EINVAL;
197 	dev_index = strtol(s, &endptr, 10);
198 	if (*endptr)
199 		return -EINVAL;
200 
201 	s = strtok(NULL, ":");
202 	if (!s)
203 		return -EINVAL;
204 	node_index = strtol(s, &endptr, 10);
205 	if (*endptr)
206 		return -EINVAL;
207 
208 	s = strtok(NULL, ":");
209 	if (!s)
210 		return -EINVAL;
211 	value = strtol(s, &endptr, 10);
212 	if (*endptr)
213 		return -EINVAL;
214 	if (value > INT_MAX || value < INT_MIN)
215 		return -EOVERFLOW;
216 
217 	*id_out = cras_make_node_id(dev_index, node_index);
218 	*value_out = value;
219 	return 0;
220 }
221 
222 /* Run from callback thread. */
got_samples(struct cras_client * client,cras_stream_id_t stream_id,uint8_t * captured_samples,uint8_t * playback_samples,unsigned int frames,const struct timespec * captured_time,const struct timespec * playback_time,void * user_arg)223 static int got_samples(struct cras_client *client, cras_stream_id_t stream_id,
224 		       uint8_t *captured_samples, uint8_t *playback_samples,
225 		       unsigned int frames,
226 		       const struct timespec *captured_time,
227 		       const struct timespec *playback_time, void *user_arg)
228 {
229 	int *fd = (int *)user_arg;
230 	int ret;
231 	int write_size;
232 	int frame_bytes;
233 
234 	while (pause_client)
235 		usleep(10000);
236 
237 	cras_client_calc_capture_latency(captured_time, &last_latency);
238 
239 	frame_bytes = cras_client_format_bytes_per_frame(aud_format);
240 	write_size = frames * frame_bytes;
241 
242 	/* Update RMS values with all available frames. */
243 	if (keep_looping) {
244 		update_rms(captured_samples,
245 			   MIN(write_size, duration_frames * frame_bytes));
246 	}
247 
248 	check_stream_terminate(frames);
249 
250 	ret = write(*fd, captured_samples, write_size);
251 	if (ret != write_size)
252 		printf("Error writing file\n");
253 	return frames;
254 }
255 
256 /* Run from callback thread. */
put_samples(struct cras_client * client,cras_stream_id_t stream_id,uint8_t * captured_samples,uint8_t * playback_samples,unsigned int frames,const struct timespec * captured_time,const struct timespec * playback_time,void * user_arg)257 static int put_samples(struct cras_client *client, cras_stream_id_t stream_id,
258 		       uint8_t *captured_samples, uint8_t *playback_samples,
259 		       unsigned int frames,
260 		       const struct timespec *captured_time,
261 		       const struct timespec *playback_time, void *user_arg)
262 {
263 	uint32_t frame_bytes = cras_client_format_bytes_per_frame(aud_format);
264 	int fd = *(int *)user_arg;
265 	uint8_t buff[BUF_SIZE];
266 	int nread;
267 
268 	while (pause_client)
269 		usleep(10000);
270 
271 	if (pause_a_reply) {
272 		usleep(pause_in_playback_reply);
273 		pause_a_reply = 0;
274 	}
275 
276 	check_stream_terminate(frames);
277 
278 	cras_client_calc_playback_latency(playback_time, &last_latency);
279 
280 	if (play_short_sound) {
281 		if (play_short_sound_periods_left)
282 			/* Play a period from file. */
283 			play_short_sound_periods_left--;
284 		else {
285 			/* Fill zeros to play silence. */
286 			memset(playback_samples, 0,
287 			       MIN(frames * frame_bytes, BUF_SIZE));
288 			return frames;
289 		}
290 	}
291 
292 	nread = read(fd, buff, MIN(frames * frame_bytes, BUF_SIZE));
293 	if (nread <= 0) {
294 		if (exit_after_done_playing)
295 			terminate_stream_loop();
296 		return nread;
297 	}
298 
299 	memcpy(playback_samples, buff, nread);
300 	return nread / frame_bytes;
301 }
302 
303 /* Run from callback thread. */
304 static int
put_stdin_samples(struct cras_client * client,cras_stream_id_t stream_id,uint8_t * captured_samples,uint8_t * playback_samples,unsigned int frames,const struct timespec * captured_time,const struct timespec * playback_time,void * user_arg)305 put_stdin_samples(struct cras_client *client, cras_stream_id_t stream_id,
306 		  uint8_t *captured_samples, uint8_t *playback_samples,
307 		  unsigned int frames, const struct timespec *captured_time,
308 		  const struct timespec *playback_time, void *user_arg)
309 {
310 	int rc = 0;
311 	uint32_t frame_bytes = cras_client_format_bytes_per_frame(aud_format);
312 
313 	rc = read(0, playback_samples, (size_t)frames * (size_t)frame_bytes);
314 	if (rc <= 0) {
315 		terminate_stream_loop();
316 		return -1;
317 	}
318 
319 	return rc / frame_bytes;
320 }
321 
stream_error(struct cras_client * client,cras_stream_id_t stream_id,int err,void * arg)322 static int stream_error(struct cras_client *client, cras_stream_id_t stream_id,
323 			int err, void *arg)
324 {
325 	printf("Stream error %d\n", err);
326 	terminate_stream_loop();
327 	return 0;
328 }
329 
print_last_latency()330 static void print_last_latency()
331 {
332 	if (last_latency.tv_sec > 0 || last_latency.tv_nsec > 0)
333 		printf("%u.%09u\n", (unsigned)last_latency.tv_sec,
334 		       (unsigned)last_latency.tv_nsec);
335 	else {
336 		printf("-%lld.%09lld\n", (long long)-last_latency.tv_sec,
337 		       (long long)-last_latency.tv_nsec);
338 	}
339 }
340 
print_last_rms()341 static void print_last_rms()
342 {
343 	if (last_rms_size != 0)
344 		printf("%.9f\n", sqrt(last_rms_sqr_sum / last_rms_size));
345 }
346 
print_total_rms()347 static void print_total_rms()
348 {
349 	if (total_rms_size != 0)
350 		printf("%.9f\n", sqrt(total_rms_sqr_sum / total_rms_size));
351 }
352 
print_dev_info(const struct cras_iodev_info * devs,int num_devs)353 static void print_dev_info(const struct cras_iodev_info *devs, int num_devs)
354 {
355 	unsigned i;
356 
357 	printf("\tID\tMaxCha\tName\n");
358 	for (i = 0; i < num_devs; i++)
359 		printf("\t%u\t%u\t%s\n", devs[i].idx,
360 		       devs[i].max_supported_channels, devs[i].name);
361 }
362 
print_node_info(struct cras_client * client,const struct cras_ionode_info * nodes,int num_nodes,int is_input)363 static void print_node_info(struct cras_client *client,
364 			    const struct cras_ionode_info *nodes, int num_nodes,
365 			    int is_input)
366 {
367 	unsigned i;
368 
369 	printf("\tStable Id\t ID\t%4s  UI       Plugged\tL/R swapped\t      "
370 	       "Time Hotword\tType\t\tMaxCha Name\n",
371 	       is_input ? "Gain" : " Vol");
372 	for (i = 0; i < num_nodes; i++) {
373 		char max_channels_str[7];
374 		if (is_input) {
375 			// Print "X" as don't-care for input nodes because
376 			// cras_client_get_max_supported_channels() is only valid for outputs.
377 			strcpy(max_channels_str, "     X");
378 		} else {
379 			uint32_t max_channels;
380 			int rc = cras_client_get_max_supported_channels(
381 				client,
382 				cras_make_node_id(nodes[i].iodev_idx,
383 						  nodes[i].ionode_idx),
384 				&max_channels);
385 			if (rc)
386 				max_channels = 0;
387 			sprintf(max_channels_str, "%6u", max_channels);
388 		}
389 		printf("\t(%08x)\t%u:%u\t%5g %f %7s\t%14s\t%10ld %-7s\t%-16s%-6s%c%s\n",
390 		       nodes[i].stable_id, nodes[i].iodev_idx,
391 		       nodes[i].ionode_idx,
392 		       is_input ? nodes[i].capture_gain / 100.0 :
393 				  (double)nodes[i].volume,
394 		       nodes[i].ui_gain_scaler, nodes[i].plugged ? "yes" : "no",
395 		       nodes[i].left_right_swapped ? "yes" : "no",
396 		       (long)nodes[i].plugged_time.tv_sec,
397 		       nodes[i].active_hotword_model, nodes[i].type,
398 		       max_channels_str, nodes[i].active ? '*' : ' ',
399 		       nodes[i].name);
400 	}
401 }
402 
print_device_lists(struct cras_client * client)403 static void print_device_lists(struct cras_client *client)
404 {
405 	struct cras_iodev_info devs[MAX_IODEVS];
406 	struct cras_ionode_info nodes[MAX_IONODES];
407 	size_t num_devs, num_nodes;
408 	int rc;
409 
410 	num_devs = MAX_IODEVS;
411 	num_nodes = MAX_IONODES;
412 	rc = cras_client_get_output_devices(client, devs, nodes, &num_devs,
413 					    &num_nodes);
414 	if (rc < 0)
415 		return;
416 	printf("Output Devices:\n");
417 	print_dev_info(devs, num_devs);
418 	printf("Output Nodes:\n");
419 	print_node_info(client, nodes, num_nodes, 0);
420 
421 	num_devs = MAX_IODEVS;
422 	num_nodes = MAX_IONODES;
423 	rc = cras_client_get_input_devices(client, devs, nodes, &num_devs,
424 					   &num_nodes);
425 	printf("Input Devices:\n");
426 	print_dev_info(devs, num_devs);
427 	printf("Input Nodes:\n");
428 	print_node_info(client, nodes, num_nodes, 1);
429 }
430 
print_attached_client_list(struct cras_client * client)431 static void print_attached_client_list(struct cras_client *client)
432 {
433 	struct cras_attached_client_info clients[MAX_ATTACHED_CLIENTS];
434 	size_t i;
435 	int num_clients;
436 
437 	num_clients = cras_client_get_attached_clients(client, clients,
438 						       MAX_ATTACHED_CLIENTS);
439 	if (num_clients < 0)
440 		return;
441 	num_clients = MIN(num_clients, MAX_ATTACHED_CLIENTS);
442 	printf("Attached clients:\n");
443 	printf("\tID\tpid\tuid\n");
444 	for (i = 0; i < num_clients; i++)
445 		printf("\t%u\t%d\t%d\n", clients[i].id, clients[i].pid,
446 		       clients[i].gid);
447 }
448 
print_active_stream_info(struct cras_client * client)449 static void print_active_stream_info(struct cras_client *client)
450 {
451 	struct timespec ts;
452 	unsigned num_streams;
453 
454 	num_streams = cras_client_get_num_active_streams(client, &ts);
455 	printf("Num active streams: %u\n", num_streams);
456 	printf("Last audio active time: %llu, %llu\n", (long long)ts.tv_sec,
457 	       (long long)ts.tv_nsec);
458 }
459 
print_system_volumes(struct cras_client * client)460 static void print_system_volumes(struct cras_client *client)
461 {
462 	printf("System Volume (0-100): %zu %s\n"
463 	       "Capture Muted : %s\n",
464 	       cras_client_get_system_volume(client),
465 	       cras_client_get_system_muted(client) ? "(Muted)" : "",
466 	       cras_client_get_system_capture_muted(client) ? "Muted" :
467 							      "Not muted");
468 }
469 
print_user_muted(struct cras_client * client)470 static void print_user_muted(struct cras_client *client)
471 {
472 	printf("User muted: %s\n",
473 	       cras_client_get_user_muted(client) ? "Muted" : "Not muted");
474 }
475 
476 /*
477  * Convert time value from one clock to the other using given offset
478  * in sec and nsec.
479  */
convert_time(unsigned int * sec,unsigned int * nsec,time_t sec_offset,int32_t nsec_offset)480 static void convert_time(unsigned int *sec, unsigned int *nsec,
481 			 time_t sec_offset, int32_t nsec_offset)
482 {
483 	sec_offset += *sec;
484 	nsec_offset += *nsec;
485 	if (nsec_offset >= 1000000000L) {
486 		sec_offset++;
487 		nsec_offset -= 1000000000L;
488 	} else if (nsec_offset < 0) {
489 		sec_offset--;
490 		nsec_offset += 1000000000L;
491 	}
492 	*sec = sec_offset;
493 	*nsec = nsec_offset;
494 }
495 
get_ewma_power_as_float(uint32_t data)496 static float get_ewma_power_as_float(uint32_t data)
497 {
498 	float f = 0.0f;
499 
500 	/* Convert from the uint32_t log type back to float.
501 	 * If data cannot be assigned to float, default value will
502 	 * be printed as -inf to hint the problem.
503 	 */
504 	if (sizeof(uint32_t) == sizeof(float))
505 		memcpy(&f, &data, sizeof(float));
506 	else
507 		printf("%-30s float to uint32_t\n", "MEMORY_NOT_ALIGNED");
508 
509 	/* Convert to dBFS and set to zero if it's
510 	 * insignificantly low.  Picking the same threshold
511 	 * 1.0e-10f as in Chrome.
512 	 */
513 	return (f < 1.0e-10f) ? -INFINITY : 10.0f * log10f(f);
514 }
515 
show_alog_tag(const struct audio_thread_event_log * log,unsigned int tag_idx,int32_t sec_offset,int32_t nsec_offset)516 static void show_alog_tag(const struct audio_thread_event_log *log,
517 			  unsigned int tag_idx, int32_t sec_offset,
518 			  int32_t nsec_offset)
519 {
520 	unsigned int tag = (log->log[tag_idx].tag_sec >> 24) & 0xff;
521 	unsigned int sec = log->log[tag_idx].tag_sec & 0x00ffffff;
522 	unsigned int nsec = log->log[tag_idx].nsec;
523 	unsigned int data1 = log->log[tag_idx].data1;
524 	unsigned int data2 = log->log[tag_idx].data2;
525 	unsigned int data3 = log->log[tag_idx].data3;
526 	time_t lt;
527 	struct tm t;
528 
529 	/* Skip unused log entries. */
530 	if (log->log[tag_idx].tag_sec == 0 && log->log[tag_idx].nsec == 0)
531 		return;
532 
533 	/* Convert from monotonic raw clock to realtime clock. */
534 	convert_time(&sec, &nsec, sec_offset, nsec_offset);
535 	lt = sec;
536 	localtime_r(&lt, &t);
537 	strftime(time_str, 128, "%Y-%m-%dT%H:%M:%S", &t);
538 
539 	printf("%s.%09u cras atlog  ", time_str, nsec);
540 
541 	/* Prepare realtime string for arguments. */
542 	switch (tag) {
543 	case AUDIO_THREAD_A2DP_FLUSH:
544 	case AUDIO_THREAD_READ_AUDIO_TSTAMP:
545 	case AUDIO_THREAD_FILL_AUDIO_TSTAMP:
546 	case AUDIO_THREAD_STREAM_RESCHEDULE:
547 	case AUDIO_THREAD_STREAM_SLEEP_TIME:
548 	case AUDIO_THREAD_STREAM_SLEEP_ADJUST:
549 	case AUDIO_THREAD_DEV_SLEEP_TIME:
550 		sec = data2;
551 		nsec = data3;
552 		break;
553 	}
554 	convert_time(&sec, &nsec, sec_offset, nsec_offset);
555 	lt = sec;
556 	localtime_r(&lt, &t);
557 	strftime(time_str, 128, " %H:%M:%S", &t);
558 
559 	switch (tag) {
560 	case AUDIO_THREAD_WAKE:
561 		printf("%-30s num_fds:%d\n", "WAKE", (int)data1);
562 		break;
563 	case AUDIO_THREAD_SLEEP:
564 		printf("%-30s sleep:%09d.%09d non_empty %u\n", "SLEEP",
565 		       (int)data1, (int)data2, (int)data3);
566 		break;
567 	case AUDIO_THREAD_READ_AUDIO:
568 		printf("%-30s dev:%u hw_level:%u read:%u\n", "READ_AUDIO",
569 		       data1, data2, data3);
570 		break;
571 	case AUDIO_THREAD_READ_AUDIO_TSTAMP:
572 		printf("%-30s dev:%u tstamp:%s.%09u\n", "READ_AUDIO_TSTAMP",
573 		       data1, time_str, nsec);
574 		break;
575 	case AUDIO_THREAD_READ_AUDIO_DONE: {
576 		float f = get_ewma_power_as_float(data2);
577 		printf("%-30s read_remainder:%u power:%f dBFS\n",
578 		       "READ_AUDIO_DONE", data1, f);
579 		break;
580 	}
581 	case AUDIO_THREAD_READ_OVERRUN:
582 		printf("%-30s dev:%u stream:%x num_overruns:%u\n",
583 		       "READ_AUDIO_OVERRUN", data1, data2, data3);
584 		break;
585 	case AUDIO_THREAD_FILL_AUDIO:
586 		printf("%-30s dev:%u hw_level:%u min_cb_level:%u\n",
587 		       "FILL_AUDIO", data1, data2, data3);
588 		break;
589 	case AUDIO_THREAD_FILL_AUDIO_TSTAMP:
590 		printf("%-30s dev:%u tstamp:%s.%09u\n", "FILL_AUDIO_TSTAMP",
591 		       data1, time_str, nsec);
592 		break;
593 	case AUDIO_THREAD_FILL_AUDIO_DONE: {
594 		float f = get_ewma_power_as_float(data3);
595 		printf("%-30s hw_level:%u total_written:%u power:%f dBFS\n",
596 		       "FILL_AUDIO_DONE", data1, data2, f);
597 		break;
598 	}
599 	case AUDIO_THREAD_WRITE_STREAMS_WAIT:
600 		printf("%-30s stream:%x\n", "WRITE_STREAMS_WAIT", data1);
601 		break;
602 	case AUDIO_THREAD_WRITE_STREAMS_WAIT_TO:
603 		printf("%-30s\n", "WRITE_STREAMS_WAIT_TO");
604 		break;
605 	case AUDIO_THREAD_WRITE_STREAMS_MIX:
606 		printf("%-30s write_limit:%u max_offset:%u\n",
607 		       "WRITE_STREAMS_MIX", data1, data2);
608 		break;
609 	case AUDIO_THREAD_WRITE_STREAMS_MIXED:
610 		printf("%-30s write_limit:%u\n", "WRITE_STREAMS_MIXED", data1);
611 		break;
612 	case AUDIO_THREAD_WRITE_STREAMS_STREAM:
613 		printf("%-30s id:%x shm_frames:%u cb_pending:%u\n",
614 		       "WRITE_STREAMS_STREAM", data1, data2, data3);
615 		break;
616 	case AUDIO_THREAD_FETCH_STREAM: {
617 		float f = get_ewma_power_as_float(data3);
618 		printf("%-30s id:%x cbth:%u power:%f dBFS\n",
619 		       "WRITE_STREAMS_FETCH_STREAM", data1, data2, f);
620 		break;
621 	}
622 	case AUDIO_THREAD_STREAM_ADDED:
623 		printf("%-30s id:%x dev:%u\n", "STREAM_ADDED", data1, data2);
624 		break;
625 	case AUDIO_THREAD_STREAM_REMOVED:
626 		printf("%-30s id:%x\n", "STREAM_REMOVED", data1);
627 		break;
628 		break;
629 	case AUDIO_THREAD_A2DP_FLUSH:
630 		printf("%-30s state %u next flush time:%s.%09u\n", "A2DP_FLUSH",
631 		       data1, time_str, nsec);
632 		break;
633 	case AUDIO_THREAD_A2DP_THROTTLE_TIME:
634 		printf("%-30s %u ms, queued:%u\n", "A2DP_THROTTLE_TIME",
635 		       data1 * 1000 + data2 / 1000000, data3);
636 		break;
637 	case AUDIO_THREAD_A2DP_WRITE:
638 		printf("%-30s written:%d queued:%u\n", "A2DP_WRITE", data1,
639 		       data2);
640 		break;
641 	case AUDIO_THREAD_DEV_STREAM_MIX:
642 		printf("%-30s written:%u read:%u\n", "DEV_STREAM_MIX", data1,
643 		       data2);
644 		break;
645 	case AUDIO_THREAD_CAPTURE_POST:
646 		printf("%-30s stream:%x thresh:%u rd_buf:%u\n", "CAPTURE_POST",
647 		       data1, data2, data3);
648 		break;
649 	case AUDIO_THREAD_CAPTURE_WRITE:
650 		printf("%-30s stream:%x write:%u shm_fr:%u\n", "CAPTURE_WRITE",
651 		       data1, data2, data3);
652 		break;
653 	case AUDIO_THREAD_CONV_COPY:
654 		printf("%-30s wr_buf:%u shm_writable:%u offset:%u\n",
655 		       "CONV_COPY", data1, data2, data3);
656 		break;
657 	case AUDIO_THREAD_STREAM_FETCH_PENDING:
658 		printf("%-30s id:%x\n", "STREAM_FETCH_PENGING", data1);
659 		break;
660 	case AUDIO_THREAD_STREAM_RESCHEDULE:
661 		printf("%-30s id:%x next_cb_ts:%s.%09u\n", "STREAM_RESCHEDULE",
662 		       data1, time_str, nsec);
663 		break;
664 	case AUDIO_THREAD_STREAM_SLEEP_TIME:
665 		printf("%-30s id:%x wake:%s.%09u\n", "STREAM_SLEEP_TIME", data1,
666 		       time_str, nsec);
667 		break;
668 	case AUDIO_THREAD_STREAM_SLEEP_ADJUST:
669 		printf("%-30s id:%x from:%s.%09u\n", "STREAM_SLEEP_ADJUST",
670 		       data1, time_str, nsec);
671 		break;
672 	case AUDIO_THREAD_STREAM_SKIP_CB:
673 		printf("%-30s id:%x write_offset_0:%u write_offset_1:%u\n",
674 		       "STREAM_SKIP_CB", data1, data2, data3);
675 		break;
676 	case AUDIO_THREAD_DEV_SLEEP_TIME:
677 		printf("%-30s dev:%u wake:%s.%09u\n", "DEV_SLEEP_TIME", data1,
678 		       time_str, nsec);
679 		break;
680 	case AUDIO_THREAD_SET_DEV_WAKE:
681 		printf("%-30s dev:%u hw_level:%u sleep:%u\n", "SET_DEV_WAKE",
682 		       data1, data2, data3);
683 		break;
684 	case AUDIO_THREAD_DEV_ADDED:
685 		printf("%-30s dev:%u\n", "DEV_ADDED", data1);
686 		break;
687 	case AUDIO_THREAD_DEV_REMOVED:
688 		printf("%-30s dev:%u\n", "DEV_REMOVED", data1);
689 		break;
690 	case AUDIO_THREAD_IODEV_CB:
691 		printf("%-30s revents:%u events:%u\n", "IODEV_CB", data1,
692 		       data2);
693 		break;
694 	case AUDIO_THREAD_PB_MSG:
695 		printf("%-30s msg_id:%u\n", "PB_MSG", data1);
696 		break;
697 	case AUDIO_THREAD_ODEV_NO_STREAMS:
698 		printf("%-30s dev:%u\n", "ODEV_NO_STREAMS", data1);
699 		break;
700 	case AUDIO_THREAD_ODEV_LEAVE_NO_STREAMS:
701 		printf("%-30s dev:%u\n", "ODEV_LEAVE_NO_STREAMS", data1);
702 		break;
703 	case AUDIO_THREAD_ODEV_START:
704 		printf("%-30s dev:%u min_cb_level:%u\n", "ODEV_START", data1,
705 		       data2);
706 		break;
707 	case AUDIO_THREAD_FILL_ODEV_ZEROS:
708 		printf("%-30s dev:%u write:%u\n", "FILL_ODEV_ZEROS", data1,
709 		       data2);
710 		break;
711 	case AUDIO_THREAD_ODEV_DEFAULT_NO_STREAMS:
712 		printf("%-30s dev:%u hw_level:%u target:%u\n",
713 		       "DEFAULT_NO_STREAMS", data1, data2, data3);
714 		break;
715 	case AUDIO_THREAD_UNDERRUN:
716 		printf("%-30s dev:%u hw_level:%u total_written:%u\n",
717 		       "UNDERRUN", data1, data2, data3);
718 		break;
719 	case AUDIO_THREAD_SEVERE_UNDERRUN:
720 		printf("%-30s dev:%u\n", "SEVERE_UNDERRUN", data1);
721 		break;
722 	case AUDIO_THREAD_CAPTURE_DROP_TIME:
723 		printf("%-30s time:%09u.%09d\n", "CAPTURE_DROP_TIME", data1,
724 		       data2);
725 		break;
726 	case AUDIO_THREAD_DEV_DROP_FRAMES:
727 		printf("%-30s dev:%u frames:%u\n", "DEV_DROP_FRAMES", data1,
728 		       data2);
729 		break;
730 	case AUDIO_THREAD_LOOPBACK_PUT:
731 		printf("%-30s nframes_committed:%u\n", "LOOPBACK_PUT", data1);
732 		break;
733 	case AUDIO_THREAD_LOOPBACK_GET:
734 		printf("%-30s nframes_requested:%u avail:%u\n", "LOOPBACK_GET",
735 		       data1, data2);
736 		break;
737 	case AUDIO_THREAD_LOOPBACK_SAMPLE_HOOK:
738 		printf("%-30s frames_to_copy:%u frames_copied:%u\n",
739 		       "LOOPBACK_SAMPLE", data1, data2);
740 		break;
741 	case AUDIO_THREAD_DEV_OVERRUN:
742 		printf("%-30s dev:%u hw_level:%u\n", "DEV_OVERRUN", data1,
743 		       data2);
744 		break;
745 	default:
746 		printf("%-30s tag:%u\n", "UNKNOWN", tag);
747 		break;
748 	}
749 }
750 
print_audio_debug_info(const struct audio_debug_info * info)751 static void print_audio_debug_info(const struct audio_debug_info *info)
752 {
753 	time_t sec_offset;
754 	int32_t nsec_offset;
755 	int i, j;
756 
757 	printf("Audio Debug Stats:\n");
758 	printf("-------------devices------------\n");
759 	if (info->num_devs > MAX_DEBUG_DEVS)
760 		return;
761 
762 	for (i = 0; i < info->num_devs; i++) {
763 		printf("%s dev: %s\n",
764 		       (info->devs[i].direction == CRAS_STREAM_INPUT) ?
765 			       "Input" :
766 			       "Output",
767 		       info->devs[i].dev_name);
768 		printf("buffer_size: %u\n"
769 		       "min_buffer_level: %u\n"
770 		       "min_cb_level: %u\n"
771 		       "max_cb_level: %u\n"
772 		       "frame_rate: %u\n"
773 		       "num_channels: %u\n"
774 		       "est_rate_ratio: %lf\n"
775 		       "num_underruns: %u\n"
776 		       "num_severe_underruns: %u\n"
777 		       "highest_hw_level: %u\n"
778 		       "runtime: %u.%09u\n"
779 		       "longest_wake: %u.%09u\n"
780 		       "software_gain_scaler: %lf\n",
781 		       (unsigned int)info->devs[i].buffer_size,
782 		       (unsigned int)info->devs[i].min_buffer_level,
783 		       (unsigned int)info->devs[i].min_cb_level,
784 		       (unsigned int)info->devs[i].max_cb_level,
785 		       (unsigned int)info->devs[i].frame_rate,
786 		       (unsigned int)info->devs[i].num_channels,
787 		       info->devs[i].est_rate_ratio,
788 		       (unsigned int)info->devs[i].num_underruns,
789 		       (unsigned int)info->devs[i].num_severe_underruns,
790 		       (unsigned int)info->devs[i].highest_hw_level,
791 		       (unsigned int)info->devs[i].runtime_sec,
792 		       (unsigned int)info->devs[i].runtime_nsec,
793 		       (unsigned int)info->devs[i].longest_wake_sec,
794 		       (unsigned int)info->devs[i].longest_wake_nsec,
795 		       info->devs[i].software_gain_scaler);
796 		printf("\n");
797 	}
798 
799 	printf("-------------stream_dump------------\n");
800 	if (info->num_streams > MAX_DEBUG_STREAMS)
801 		return;
802 
803 	for (i = 0; i < info->num_streams; i++) {
804 		int channel;
805 		printf("stream: 0x%" PRIx64 " dev: %u\n",
806 		       info->streams[i].stream_id,
807 		       (unsigned int)info->streams[i].dev_idx);
808 		printf("direction: %s\n",
809 		       (info->streams[i].direction == CRAS_STREAM_INPUT) ?
810 			       "Input" :
811 			       "Output");
812 		printf("stream_type: %s\n",
813 		       cras_stream_type_str(info->streams[i].stream_type));
814 		printf("client_type: %s\n",
815 		       cras_client_type_str(info->streams[i].client_type));
816 		printf("buffer_frames: %u\n"
817 		       "cb_threshold: %u\n"
818 		       "effects: 0x%.4x\n"
819 		       "frame_rate: %u\n"
820 		       "num_channels: %u\n"
821 		       "longest_fetch_sec: %u.%09u\n"
822 		       "num_overruns: %u\n"
823 		       "is_pinned: %x\n"
824 		       "pinned_dev_idx: %x\n"
825 		       "num_missed_cb: %u\n"
826 		       "%s: %lf\n"
827 		       "runtime: %u.%09u\n",
828 		       (unsigned int)info->streams[i].buffer_frames,
829 		       (unsigned int)info->streams[i].cb_threshold,
830 		       (unsigned int)info->streams[i].effects,
831 		       (unsigned int)info->streams[i].frame_rate,
832 		       (unsigned int)info->streams[i].num_channels,
833 		       (unsigned int)info->streams[i].longest_fetch_sec,
834 		       (unsigned int)info->streams[i].longest_fetch_nsec,
835 		       (unsigned int)info->streams[i].num_overruns,
836 		       (unsigned int)info->streams[i].is_pinned,
837 		       (unsigned int)info->streams[i].pinned_dev_idx,
838 		       (unsigned int)info->streams[i].num_missed_cb,
839 		       (info->streams[i].direction == CRAS_STREAM_INPUT) ?
840 			       "gain" :
841 			       "volume",
842 		       info->streams[i].stream_volume,
843 		       (unsigned int)info->streams[i].runtime_sec,
844 		       (unsigned int)info->streams[i].runtime_nsec);
845 		printf("channel map:");
846 		for (channel = 0; channel < CRAS_CH_MAX; channel++)
847 			printf("%d ", info->streams[i].channel_layout[channel]);
848 		printf("\n\n");
849 	}
850 
851 	printf("Audio Thread Event Log:\n");
852 
853 	fill_time_offset(&sec_offset, &nsec_offset);
854 	j = info->log.write_pos % info->log.len;
855 	i = 0;
856 	printf("start at %d\n", j);
857 	for (; i < info->log.len; i++) {
858 		show_alog_tag(&info->log, j, sec_offset, nsec_offset);
859 		j++;
860 		j %= info->log.len;
861 	}
862 }
863 
audio_debug_info(struct cras_client * client)864 static void audio_debug_info(struct cras_client *client)
865 {
866 	const struct audio_debug_info *info;
867 	info = cras_client_get_audio_debug_info(client);
868 	if (!info)
869 		return;
870 	print_audio_debug_info(info);
871 
872 	/* Signal main thread we are done after the last chunk. */
873 	pthread_mutex_lock(&done_mutex);
874 	pthread_cond_signal(&done_cond);
875 	pthread_mutex_unlock(&done_mutex);
876 }
877 
show_mainlog_tag(const struct main_thread_event_log * log,unsigned int tag_idx,int32_t sec_offset,int32_t nsec_offset)878 static void show_mainlog_tag(const struct main_thread_event_log *log,
879 			     unsigned int tag_idx, int32_t sec_offset,
880 			     int32_t nsec_offset)
881 {
882 	unsigned int tag = (log->log[tag_idx].tag_sec >> 24) & 0xff;
883 	unsigned int sec = log->log[tag_idx].tag_sec & 0x00ffffff;
884 	unsigned int nsec = log->log[tag_idx].nsec;
885 	unsigned int data1 = log->log[tag_idx].data1;
886 	unsigned int data2 = log->log[tag_idx].data2;
887 	unsigned int data3 = log->log[tag_idx].data3;
888 	time_t lt;
889 	struct tm t;
890 
891 	/* Skip unused log entries. */
892 	if (log->log[tag_idx].tag_sec == 0 && log->log[tag_idx].nsec == 0)
893 		return;
894 
895 	/* Convert from monotomic raw clock to realtime clock. */
896 	convert_time(&sec, &nsec, sec_offset, nsec_offset);
897 	lt = sec;
898 	localtime_r(&lt, &t);
899 	strftime(time_str, 128, "%Y-%m-%dT%H:%M:%S", &t);
900 
901 	printf("%s.%09u cras mainlog  ", time_str, nsec);
902 
903 	switch (tag) {
904 	case MAIN_THREAD_DEV_CLOSE:
905 		printf("%-30s dev %u\n", "DEV_CLOSE", data1);
906 		break;
907 	case MAIN_THREAD_DEV_DISABLE:
908 		printf("%-30s dev %u force %u\n", "DEV_DISABLE", data1, data2);
909 		break;
910 	case MAIN_THREAD_DEV_INIT:
911 		printf("%-30s dev %u ch %u rate %u\n", "DEV_INIT", data1, data2,
912 		       data3);
913 		break;
914 	case MAIN_THREAD_DEV_REOPEN:
915 		printf("%-30s new ch %u old ch %u rate %u\n", "DEV_REOPEN",
916 		       data1, data2, data3);
917 		break;
918 	case MAIN_THREAD_ADD_ACTIVE_NODE:
919 		printf("%-30s dev %u\n", "ADD_ACTIVE_NODE", data1);
920 		break;
921 	case MAIN_THREAD_SELECT_NODE:
922 		printf("%-30s dev %u\n", "SELECT_NODE", data1);
923 		break;
924 	case MAIN_THREAD_ADD_TO_DEV_LIST:
925 		printf("%-30s dev %u %s\n", "ADD_TO_DEV_LIST", data1,
926 		       (data2 == CRAS_STREAM_OUTPUT) ? "output" : "input");
927 		break;
928 	case MAIN_THREAD_NODE_PLUGGED:
929 		printf("%-30s dev %u %s\n", "NODE_PLUGGED", data1,
930 		       data2 ? "plugged" : "unplugged");
931 		break;
932 	case MAIN_THREAD_INPUT_NODE_GAIN:
933 		printf("%-30s dev %u gain %u\n", "INPUT_NODE_GAIN", data1,
934 		       data2);
935 		break;
936 	case MAIN_THREAD_OUTPUT_NODE_VOLUME:
937 		printf("%-30s dev %u volume %u\n", "OUTPUT_NODE_VOLUME", data1,
938 		       data2);
939 		break;
940 	case MAIN_THREAD_SET_OUTPUT_USER_MUTE:
941 		printf("%-30s mute %u\n", "SET_OUTPUT_USER_MUTE", data1);
942 		break;
943 	case MAIN_THREAD_RESUME_DEVS:
944 		printf("RESUME_DEVS\n");
945 		break;
946 	case MAIN_THREAD_SUSPEND_DEVS:
947 		printf("SUSPEND_DEVS\n");
948 		break;
949 	case MAIN_THREAD_STREAM_ADDED:
950 		printf("%-30s %s stream 0x%x buffer frames %u\n",
951 		       "STREAM_ADDED",
952 		       (data2 == CRAS_STREAM_OUTPUT ? "output" : "input"),
953 		       data1, data3);
954 		break;
955 	case MAIN_THREAD_STREAM_REMOVED:
956 		printf("%-30s stream 0x%x\n", "STREAM_REMOVED", data1);
957 		break;
958 	default:
959 		printf("%-30s\n", "UNKNOWN");
960 		break;
961 	}
962 }
963 
show_btlog_tag(const struct cras_bt_event_log * log,unsigned int tag_idx,int32_t sec_offset,int32_t nsec_offset)964 static void show_btlog_tag(const struct cras_bt_event_log *log,
965 			   unsigned int tag_idx, int32_t sec_offset,
966 			   int32_t nsec_offset)
967 {
968 	unsigned int tag = (log->log[tag_idx].tag_sec >> 24) & 0xff;
969 	unsigned int sec = log->log[tag_idx].tag_sec & 0x00ffffff;
970 	unsigned int nsec = log->log[tag_idx].nsec;
971 	unsigned int data1 = log->log[tag_idx].data1;
972 	unsigned int data2 = log->log[tag_idx].data2;
973 	time_t lt;
974 	struct tm t;
975 
976 	/* Skip unused log entries. */
977 	if (log->log[tag_idx].tag_sec == 0 && log->log[tag_idx].nsec == 0)
978 		return;
979 
980 	/* Convert from monotonic raw clock to realtime clock. */
981 	convert_time(&sec, &nsec, sec_offset, nsec_offset);
982 	lt = sec;
983 	localtime_r(&lt, &t);
984 	strftime(time_str, 128, "%Y-%m-%dT%H:%M:%S", &t);
985 
986 	printf("%s.%09u cras btlog  ", time_str, nsec);
987 
988 	switch (tag) {
989 	case BT_ADAPTER_ADDED:
990 		printf("%-30s\n", "ADAPTER_ADDED");
991 		break;
992 	case BT_ADAPTER_REMOVED:
993 		printf("%-30s\n", "ADAPTER_REMOVED");
994 		break;
995 	case BT_A2DP_CONFIGURED:
996 		printf("%-30s connected profiles 0x%.2x\n", "A2DP_CONFIGURED",
997 		       data1);
998 		break;
999 	case BT_A2DP_START:
1000 		printf("%-30s\n", "A2DP_START");
1001 		break;
1002 	case BT_A2DP_SUSPENDED:
1003 		printf("%-30s\n", "A2DP_SUSPENDED");
1004 		break;
1005 	case BT_AUDIO_GATEWAY_INIT:
1006 		printf("%-30s supported profiles 0x%.2x\n",
1007 		       "AUDIO_GATEWAY_INIT", data1);
1008 		break;
1009 	case BT_AUDIO_GATEWAY_START:
1010 		printf("%-30s \n", "AUDIO_GATEWAY_START");
1011 		break;
1012 	case BT_AVAILABLE_CODECS:
1013 		printf("%-30s codec #%u id %u\n", "AVAILABLE_CODECS", data1,
1014 		       data2);
1015 		break;
1016 	case BT_CODEC_SELECTION:
1017 		printf("%-30s dir %u codec id %u\n", "CODEC_SELECTION", data1,
1018 		       data2);
1019 		break;
1020 	case BT_DEV_CONNECTED:
1021 		printf("%-30s supported profiles 0x%.2x stable_id 0x%08x\n",
1022 		       "DEV_CONNECTED", data1, data2);
1023 		break;
1024 	case BT_DEV_DISCONNECTED:
1025 		printf("%-30s supported profiles 0x%.2x stable_id 0x%08x\n",
1026 		       "DEV_DISCONNECTED", data1, data2);
1027 		break;
1028 	case BT_DEV_CONN_WATCH_CB:
1029 		printf("%-30s %u retries left, supported profiles 0x%.2x\n",
1030 		       "DEV_CONN_WATCH_CB", data1, data2);
1031 		break;
1032 	case BT_DEV_SUSPEND_CB:
1033 		printf("%-30s profiles supported %u, reason %u\n",
1034 		       "DEV_SUSPEND_CB", data1, data2);
1035 		break;
1036 	case BT_HFP_HF_INDICATOR:
1037 		printf("%-30s HF read AG %s indicator\n", "HFP_HF_INDICATOR",
1038 		       data1 ? "enabled" : "supported");
1039 		break;
1040 	case BT_HFP_SET_SPEAKER_GAIN:
1041 		printf("%-30s HF set speaker gain %u\n", "HFP_SET_SPEAKER_GAIN",
1042 		       data1);
1043 		break;
1044 	case BT_HFP_UPDATE_SPEAKER_GAIN:
1045 		printf("%-30s HF update speaker gain %u\n",
1046 		       "HFP_UPDATE_SPEAKER_GAIN", data1);
1047 		break;
1048 	case BT_HFP_NEW_CONNECTION:
1049 		printf("%-30s\n", "HFP_NEW_CONNECTION");
1050 		break;
1051 	case BT_HFP_REQUEST_DISCONNECT:
1052 		printf("%-30s\n", "HFP_REQUEST_DISCONNECT");
1053 		break;
1054 	case BT_HFP_SUPPORTED_FEATURES:
1055 		printf("%-30s role %s features 0x%.4x\n",
1056 		       "HFP_SUPPORTED_FEATURES", data1 ? "AG" : "HF", data2);
1057 		break;
1058 	case BT_HSP_NEW_CONNECTION:
1059 		printf("%-30s\n", "HSP_NEW_CONNECTION");
1060 		break;
1061 	case BT_HSP_REQUEST_DISCONNECT:
1062 		printf("%-30s\n", "HSP_REQUEST_DISCONNECT");
1063 		break;
1064 	case BT_NEW_AUDIO_PROFILE_AFTER_CONNECT:
1065 		printf("%-30s old 0x%.2x, new 0x%.2x\n",
1066 		       "NEW_AUDIO_PROFILE_AFTER_CONNECT", data1, data2);
1067 		break;
1068 	case BT_RESET:
1069 		printf("%-30s\n", "RESET");
1070 		break;
1071 	case BT_SCO_CONNECT:
1072 		printf("%-30s %s sk %d\n", "SCO_CONNECT",
1073 		       data1 ? "success" : "failed", (int)data2);
1074 		break;
1075 	case BT_TRANSPORT_ACQUIRE:
1076 		printf("%-30s %s fd %d\n", "TRANSPORT_ACQUIRE",
1077 		       data1 ? "success" : "failed", (int)data2);
1078 		break;
1079 	case BT_TRANSPORT_RELEASE:
1080 		printf("%-30s\n", "TRANSPORT_RELEASE");
1081 		break;
1082 	case BT_TRANSPORT_SET_VOLUME:
1083 		printf("%-30s %d\n", "TRANSPORT_SET_VOLUME", data1);
1084 		break;
1085 	case BT_TRANSPORT_UPDATE_VOLUME:
1086 		printf("%-30s %d\n", "TRANSPORT_UPDATE_VOLUME", data1);
1087 		break;
1088 	default:
1089 		printf("%-30s\n", "UNKNOWN");
1090 		break;
1091 	}
1092 }
1093 
convert_to_time_str(const struct timespec * ts,time_t sec_offset,int32_t nsec_offset)1094 static void convert_to_time_str(const struct timespec *ts, time_t sec_offset,
1095 				int32_t nsec_offset)
1096 {
1097 	time_t lt = ts->tv_sec;
1098 	struct tm t;
1099 	unsigned int time_nsec;
1100 
1101 	/* Assuming tv_nsec doesn't exceed 10^9 */
1102 	time_nsec = ts->tv_nsec;
1103 	convert_time((unsigned int *)&lt, &time_nsec, sec_offset, nsec_offset);
1104 	localtime_r(&lt, &t);
1105 	strftime(time_str, 128, "%Y-%m-%dT%H:%M:%S", &t);
1106 	snprintf(time_str + strlen(time_str), 128 - strlen(time_str), ".%09u",
1107 		 time_nsec);
1108 }
1109 
cras_bt_debug_info(struct cras_client * client)1110 static void cras_bt_debug_info(struct cras_client *client)
1111 {
1112 	const struct cras_bt_debug_info *info;
1113 	time_t sec_offset;
1114 	int32_t nsec_offset;
1115 	int i, j;
1116 	struct timespec ts;
1117 	struct packet_status_logger wbs_logger;
1118 
1119 	info = cras_client_get_bt_debug_info(client);
1120 	fill_time_offset(&sec_offset, &nsec_offset);
1121 	j = info->bt_log.write_pos;
1122 	i = 0;
1123 	printf("BT debug log:\n");
1124 	for (; i < info->bt_log.len; i++) {
1125 		show_btlog_tag(&info->bt_log, j, sec_offset, nsec_offset);
1126 		j++;
1127 		j %= info->bt_log.len;
1128 	}
1129 
1130 	printf("-------------WBS packet loss------------\n");
1131 	wbs_logger = info->wbs_logger;
1132 
1133 	packet_status_logger_begin_ts(&wbs_logger, &ts);
1134 	convert_to_time_str(&ts, sec_offset, nsec_offset);
1135 	printf("%s [begin]\n", time_str);
1136 
1137 	packet_status_logger_end_ts(&wbs_logger, &ts);
1138 	convert_to_time_str(&ts, sec_offset, nsec_offset);
1139 	printf("%s [end]\n", time_str);
1140 
1141 	printf("In hex format:\n");
1142 	packet_status_logger_dump_hex(&wbs_logger);
1143 
1144 	printf("In binary format:\n");
1145 	packet_status_logger_dump_binary(&wbs_logger);
1146 
1147 	/* Signal main thread we are done after the last chunk. */
1148 	pthread_mutex_lock(&done_mutex);
1149 	pthread_cond_signal(&done_cond);
1150 	pthread_mutex_unlock(&done_mutex);
1151 }
1152 
main_thread_debug_info(struct cras_client * client)1153 static void main_thread_debug_info(struct cras_client *client)
1154 {
1155 	const struct main_thread_debug_info *info;
1156 	time_t sec_offset;
1157 	int32_t nsec_offset;
1158 	int i, j;
1159 
1160 	info = cras_client_get_main_thread_debug_info(client);
1161 	fill_time_offset(&sec_offset, &nsec_offset);
1162 	j = info->main_log.write_pos;
1163 	i = 0;
1164 	printf("Main debug log:\n");
1165 	for (; i < info->main_log.len; i++) {
1166 		show_mainlog_tag(&info->main_log, j, sec_offset, nsec_offset);
1167 		j++;
1168 		j %= info->main_log.len;
1169 	}
1170 
1171 	/* Signal main thread we are done after the last chunk. */
1172 	pthread_mutex_lock(&done_mutex);
1173 	pthread_cond_signal(&done_cond);
1174 	pthread_mutex_unlock(&done_mutex);
1175 }
1176 
print_cras_audio_thread_snapshot(const struct cras_audio_thread_snapshot * snapshot)1177 static void print_cras_audio_thread_snapshot(
1178 	const struct cras_audio_thread_snapshot *snapshot)
1179 {
1180 	printf("-------------snapshot------------\n");
1181 	printf("Event time: %" PRId64 ".%ld\n",
1182 	       (int64_t)snapshot->timestamp.tv_sec,
1183 	       snapshot->timestamp.tv_nsec);
1184 
1185 	printf("Event type: ");
1186 	switch (snapshot->event_type) {
1187 	case AUDIO_THREAD_EVENT_A2DP_THROTTLE:
1188 		printf("a2dp throttle\n");
1189 		break;
1190 	case AUDIO_THREAD_EVENT_BUSYLOOP:
1191 		printf("busyloop\n");
1192 		break;
1193 	case AUDIO_THREAD_EVENT_UNDERRUN:
1194 		printf("underrun\n");
1195 		break;
1196 	case AUDIO_THREAD_EVENT_SEVERE_UNDERRUN:
1197 		printf("severe underrun\n");
1198 		break;
1199 	case AUDIO_THREAD_EVENT_DROP_SAMPLES:
1200 		printf("drop samples\n");
1201 		break;
1202 	case AUDIO_THREAD_EVENT_DEV_OVERRUN:
1203 		printf("device overrun\n");
1204 		break;
1205 	case AUDIO_THREAD_EVENT_DEBUG:
1206 		printf("debug\n");
1207 		break;
1208 	default:
1209 		printf("no such type\n");
1210 	}
1211 	print_audio_debug_info(&snapshot->audio_debug_info);
1212 }
1213 
audio_thread_snapshots(struct cras_client * client)1214 static void audio_thread_snapshots(struct cras_client *client)
1215 {
1216 	const struct cras_audio_thread_snapshot_buffer *snapshot_buffer;
1217 	uint32_t i;
1218 	int j;
1219 	int count = 0;
1220 
1221 	snapshot_buffer = cras_client_get_audio_thread_snapshot_buffer(client);
1222 	i = snapshot_buffer->pos;
1223 	for (j = 0; j < CRAS_MAX_AUDIO_THREAD_SNAPSHOTS; j++) {
1224 		if (snapshot_buffer->snapshots[i].timestamp.tv_sec ||
1225 		    snapshot_buffer->snapshots[i].timestamp.tv_nsec) {
1226 			print_cras_audio_thread_snapshot(
1227 				&snapshot_buffer->snapshots[i]);
1228 			count++;
1229 		}
1230 		i++;
1231 		i %= CRAS_MAX_AUDIO_THREAD_SNAPSHOTS;
1232 	}
1233 	printf("There are %d, snapshots.\n", count);
1234 
1235 	/* Signal main thread we are done after the last chunk. */
1236 	pthread_mutex_lock(&done_mutex);
1237 	pthread_cond_signal(&done_cond);
1238 	pthread_mutex_unlock(&done_mutex);
1239 }
1240 
start_stream(struct cras_client * client,cras_stream_id_t * stream_id,struct cras_stream_params * params,float stream_volume)1241 static int start_stream(struct cras_client *client, cras_stream_id_t *stream_id,
1242 			struct cras_stream_params *params, float stream_volume)
1243 {
1244 	int rc;
1245 
1246 	if (pin_device_id)
1247 		rc = cras_client_add_pinned_stream(client, pin_device_id,
1248 						   stream_id, params);
1249 	else
1250 		rc = cras_client_add_stream(client, stream_id, params);
1251 	if (rc < 0) {
1252 		fprintf(stderr, "adding a stream %d\n", rc);
1253 		return rc;
1254 	}
1255 	return cras_client_set_stream_volume(client, *stream_id, stream_volume);
1256 }
1257 
parse_channel_layout(char * channel_layout_str,int8_t channel_layout[CRAS_CH_MAX])1258 static int parse_channel_layout(char *channel_layout_str,
1259 				int8_t channel_layout[CRAS_CH_MAX])
1260 {
1261 	int i = 0;
1262 	char *chp;
1263 
1264 	chp = strtok(channel_layout_str, ",");
1265 	while (chp && i < CRAS_CH_MAX) {
1266 		channel_layout[i++] = atoi(chp);
1267 		chp = strtok(NULL, ",");
1268 	}
1269 
1270 	return 0;
1271 }
1272 
run_aecdump(struct cras_client * client,uint64_t stream_id,int start)1273 static void run_aecdump(struct cras_client *client, uint64_t stream_id,
1274 			int start)
1275 {
1276 	int aecdump_fd;
1277 	if (start) {
1278 		aecdump_fd =
1279 			open(aecdump_file, O_CREAT | O_RDWR | O_TRUNC, 0666);
1280 		if (aecdump_fd == -1) {
1281 			printf("Fail to open file %s", aecdump_file);
1282 			return;
1283 		}
1284 
1285 		printf("Dumping AEC info to %s, stream %" PRId64 ", fd %d\n",
1286 		       aecdump_file, stream_id, aecdump_fd);
1287 		cras_client_set_aec_dump(client, stream_id, 1, aecdump_fd);
1288 	} else {
1289 		cras_client_set_aec_dump(client, stream_id, 0, -1);
1290 		printf("Close AEC dump file %s\n", aecdump_file);
1291 	}
1292 }
1293 
run_file_io_stream(struct cras_client * client,int fd,enum CRAS_STREAM_DIRECTION direction,size_t block_size,enum CRAS_STREAM_TYPE stream_type,size_t rate,snd_pcm_format_t format,size_t num_channels,uint32_t flags,int is_loopback,int is_post_dsp)1294 static int run_file_io_stream(struct cras_client *client, int fd,
1295 			      enum CRAS_STREAM_DIRECTION direction,
1296 			      size_t block_size,
1297 			      enum CRAS_STREAM_TYPE stream_type, size_t rate,
1298 			      snd_pcm_format_t format, size_t num_channels,
1299 			      uint32_t flags, int is_loopback, int is_post_dsp)
1300 {
1301 	int rc, tty;
1302 	struct cras_stream_params *params;
1303 	cras_unified_cb_t aud_cb;
1304 	cras_stream_id_t stream_id = 0;
1305 	int stream_playing = 0;
1306 	int *pfd = malloc(sizeof(*pfd));
1307 	*pfd = fd;
1308 	fd_set poll_set;
1309 	struct timespec sleep_ts;
1310 	float volume_scaler = 1.0;
1311 	size_t sys_volume = 100;
1312 	int mute = 0;
1313 	int8_t layout[CRAS_CH_MAX];
1314 
1315 	/* Set the sleep interval between latency/RMS prints. */
1316 	sleep_ts.tv_sec = 1;
1317 	sleep_ts.tv_nsec = 0;
1318 
1319 	/* Open the pipe file descriptor. */
1320 	rc = pipe(pipefd);
1321 	if (rc == -1) {
1322 		perror("failed to open pipe");
1323 		return -errno;
1324 	}
1325 
1326 	/* Reset the total RMS value. */
1327 	total_rms_sqr_sum = 0;
1328 	total_rms_size = 0;
1329 
1330 	if (direction == CRAS_STREAM_INPUT)
1331 		aud_cb = got_samples;
1332 	else
1333 		aud_cb = put_samples;
1334 
1335 	if (fd == 0) {
1336 		if (direction != CRAS_STREAM_OUTPUT)
1337 			return -EINVAL;
1338 		aud_cb = put_stdin_samples;
1339 	}
1340 
1341 	aud_format = cras_audio_format_create(format, rate, num_channels);
1342 	if (aud_format == NULL)
1343 		return -ENOMEM;
1344 
1345 	if (channel_layout) {
1346 		/* Set channel layout to format */
1347 		parse_channel_layout(channel_layout, layout);
1348 		cras_audio_format_set_channel_layout(aud_format, layout);
1349 	}
1350 
1351 	params = cras_client_unified_params_create(direction, block_size,
1352 						   stream_type, flags, pfd,
1353 						   aud_cb, stream_error,
1354 						   aud_format);
1355 	if (params == NULL)
1356 		return -ENOMEM;
1357 
1358 	cras_client_stream_params_set_client_type(params,
1359 						  CRAS_CLIENT_TYPE_TEST);
1360 
1361 	if (effect_aec)
1362 		cras_client_stream_params_enable_aec(params);
1363 	if (effect_ns)
1364 		cras_client_stream_params_enable_ns(params);
1365 	if (effect_agc)
1366 		cras_client_stream_params_enable_agc(params);
1367 	if (effect_vad)
1368 		cras_client_stream_params_enable_vad(params);
1369 
1370 	cras_client_run_thread(client);
1371 	if (is_loopback) {
1372 		enum CRAS_NODE_TYPE type =
1373 			(is_post_dsp ? CRAS_NODE_TYPE_POST_DSP :
1374 				       CRAS_NODE_TYPE_POST_MIX_PRE_DSP);
1375 
1376 		cras_client_connected_wait(client);
1377 		pin_device_id = cras_client_get_first_dev_type_idx(
1378 			client, type, CRAS_STREAM_INPUT);
1379 	}
1380 
1381 	stream_playing =
1382 		start_stream(client, &stream_id, params, volume_scaler) == 0;
1383 
1384 	tty = open("/dev/tty", O_RDONLY);
1385 
1386 	// There could be no terminal available when run in autotest.
1387 	if (tty == -1)
1388 		perror("warning: failed to open /dev/tty");
1389 
1390 	while (keep_looping) {
1391 		char input;
1392 		int nread;
1393 
1394 		FD_ZERO(&poll_set);
1395 		if (tty >= 0)
1396 			FD_SET(tty, &poll_set);
1397 		FD_SET(pipefd[0], &poll_set);
1398 		pselect(MAX(tty, pipefd[0]) + 1, &poll_set, NULL, NULL,
1399 			show_latency || show_rms ? &sleep_ts : NULL, NULL);
1400 
1401 		if (stream_playing && show_latency)
1402 			print_last_latency();
1403 
1404 		if (stream_playing && show_rms)
1405 			print_last_rms();
1406 
1407 		if (tty < 0 || !FD_ISSET(tty, &poll_set))
1408 			continue;
1409 
1410 		nread = read(tty, &input, 1);
1411 		if (nread < 1) {
1412 			fprintf(stderr, "Error reading stdin\n");
1413 			return nread;
1414 		}
1415 		switch (input) {
1416 		case 'p':
1417 			pause_client = !pause_client;
1418 			break;
1419 		case 'i':
1420 			pause_a_reply = 1;
1421 			break;
1422 		case 'q':
1423 			terminate_stream_loop();
1424 			break;
1425 		case 's':
1426 			if (stream_playing)
1427 				break;
1428 
1429 			/* If started by hand keep running after it finishes. */
1430 			exit_after_done_playing = 0;
1431 
1432 			stream_playing =
1433 				start_stream(client, &stream_id, params,
1434 					     volume_scaler) == 0;
1435 			break;
1436 		case 'r':
1437 			if (!stream_playing)
1438 				break;
1439 			cras_client_rm_stream(client, stream_id);
1440 			stream_playing = 0;
1441 			break;
1442 		case 'u':
1443 			volume_scaler = MIN(volume_scaler + 0.1, 1.0);
1444 			cras_client_set_stream_volume(client, stream_id,
1445 						      volume_scaler);
1446 			break;
1447 		case 'd':
1448 			volume_scaler = MAX(volume_scaler - 0.1, 0.0);
1449 			cras_client_set_stream_volume(client, stream_id,
1450 						      volume_scaler);
1451 			break;
1452 		case 'k':
1453 			sys_volume = MIN(sys_volume + 1, 100);
1454 			cras_client_set_system_volume(client, sys_volume);
1455 			break;
1456 		case 'j':
1457 			sys_volume = sys_volume == 0 ? 0 : sys_volume - 1;
1458 			cras_client_set_system_volume(client, sys_volume);
1459 			break;
1460 		case 'm':
1461 			mute = !mute;
1462 			cras_client_set_system_mute(client, mute);
1463 			break;
1464 		case '@':
1465 			print_device_lists(client);
1466 			break;
1467 		case '#':
1468 			print_attached_client_list(client);
1469 			break;
1470 		case 'v':
1471 			printf("Volume: %zu%s Min dB: %ld Max dB: %ld\n"
1472 			       "Capture: %s\n",
1473 			       cras_client_get_system_volume(client),
1474 			       cras_client_get_system_muted(client) ?
1475 				       "(Muted)" :
1476 				       "",
1477 			       cras_client_get_system_min_volume(client),
1478 			       cras_client_get_system_max_volume(client),
1479 			       cras_client_get_system_capture_muted(client) ?
1480 				       "Muted" :
1481 				       "Not muted");
1482 			break;
1483 		case '\'':
1484 			play_short_sound_periods_left =
1485 				play_short_sound_periods;
1486 			break;
1487 		case '\n':
1488 			break;
1489 		default:
1490 			printf("Invalid key\n");
1491 			break;
1492 		}
1493 	}
1494 
1495 	if (show_total_rms)
1496 		print_total_rms();
1497 
1498 	cras_client_stop(client);
1499 
1500 	cras_audio_format_destroy(aud_format);
1501 	cras_client_stream_params_destroy(params);
1502 	free(pfd);
1503 
1504 	close(pipefd[0]);
1505 	close(pipefd[1]);
1506 
1507 	return 0;
1508 }
1509 
run_capture(struct cras_client * client,const char * file,size_t block_size,enum CRAS_STREAM_TYPE stream_type,size_t rate,snd_pcm_format_t format,size_t num_channels,uint32_t flags,int is_loopback,int is_post_dsp)1510 static int run_capture(struct cras_client *client, const char *file,
1511 		       size_t block_size, enum CRAS_STREAM_TYPE stream_type,
1512 		       size_t rate, snd_pcm_format_t format,
1513 		       size_t num_channels, uint32_t flags, int is_loopback,
1514 		       int is_post_dsp)
1515 {
1516 	int fd = open(file, O_CREAT | O_RDWR | O_TRUNC, 0666);
1517 	if (fd == -1) {
1518 		perror("failed to open file");
1519 		return -errno;
1520 	}
1521 
1522 	run_file_io_stream(client, fd, CRAS_STREAM_INPUT, block_size,
1523 			   stream_type, rate, format, num_channels, flags,
1524 			   is_loopback, is_post_dsp);
1525 
1526 	close(fd);
1527 	return 0;
1528 }
1529 
run_playback(struct cras_client * client,const char * file,size_t block_size,enum CRAS_STREAM_TYPE stream_type,size_t rate,snd_pcm_format_t format,size_t num_channels)1530 static int run_playback(struct cras_client *client, const char *file,
1531 			size_t block_size, enum CRAS_STREAM_TYPE stream_type,
1532 			size_t rate, snd_pcm_format_t format,
1533 			size_t num_channels)
1534 {
1535 	int fd;
1536 
1537 	fd = open(file, O_RDONLY);
1538 	if (fd == -1) {
1539 		perror("failed to open file");
1540 		return -errno;
1541 	}
1542 
1543 	run_file_io_stream(client, fd, CRAS_STREAM_OUTPUT, block_size,
1544 			   stream_type, rate, format, num_channels, 0, 0, 0);
1545 
1546 	close(fd);
1547 	return 0;
1548 }
1549 
print_server_info(struct cras_client * client)1550 static void print_server_info(struct cras_client *client)
1551 {
1552 	cras_client_run_thread(client);
1553 	cras_client_connected_wait(client); /* To synchronize data. */
1554 	print_system_volumes(client);
1555 	print_user_muted(client);
1556 	print_device_lists(client);
1557 	print_attached_client_list(client);
1558 	print_active_stream_info(client);
1559 }
1560 
show_audio_thread_snapshots(struct cras_client * client)1561 static void show_audio_thread_snapshots(struct cras_client *client)
1562 {
1563 	struct timespec wait_time;
1564 
1565 	cras_client_run_thread(client);
1566 	cras_client_connected_wait(client); /* To synchronize data. */
1567 	cras_client_update_audio_thread_snapshots(client,
1568 						  audio_thread_snapshots);
1569 
1570 	clock_gettime(CLOCK_REALTIME, &wait_time);
1571 	wait_time.tv_sec += 2;
1572 
1573 	pthread_mutex_lock(&done_mutex);
1574 	pthread_cond_timedwait(&done_cond, &done_mutex, &wait_time);
1575 	pthread_mutex_unlock(&done_mutex);
1576 }
1577 
show_audio_debug_info(struct cras_client * client)1578 static void show_audio_debug_info(struct cras_client *client)
1579 {
1580 	struct timespec wait_time;
1581 
1582 	cras_client_run_thread(client);
1583 	cras_client_connected_wait(client); /* To synchronize data. */
1584 	cras_client_update_audio_debug_info(client, audio_debug_info);
1585 
1586 	clock_gettime(CLOCK_REALTIME, &wait_time);
1587 	wait_time.tv_sec += 2;
1588 
1589 	pthread_mutex_lock(&done_mutex);
1590 	pthread_cond_timedwait(&done_cond, &done_mutex, &wait_time);
1591 	pthread_mutex_unlock(&done_mutex);
1592 }
1593 
show_cras_bt_debug_info(struct cras_client * client)1594 static void show_cras_bt_debug_info(struct cras_client *client)
1595 {
1596 	struct timespec wait_time;
1597 
1598 	cras_client_run_thread(client);
1599 	cras_client_connected_wait(client); /* To synchronize data. */
1600 	cras_client_update_bt_debug_info(client, cras_bt_debug_info);
1601 
1602 	clock_gettime(CLOCK_REALTIME, &wait_time);
1603 	wait_time.tv_sec += 2;
1604 
1605 	pthread_mutex_lock(&done_mutex);
1606 	pthread_cond_timedwait(&done_cond, &done_mutex, &wait_time);
1607 	pthread_mutex_unlock(&done_mutex);
1608 }
1609 
show_main_thread_debug_info(struct cras_client * client)1610 static void show_main_thread_debug_info(struct cras_client *client)
1611 {
1612 	struct timespec wait_time;
1613 	cras_client_run_thread(client);
1614 	cras_client_connected_wait(client); /* To synchronize data. */
1615 	cras_client_update_main_thread_debug_info(client,
1616 						  main_thread_debug_info);
1617 
1618 	clock_gettime(CLOCK_REALTIME, &wait_time);
1619 	wait_time.tv_sec += 2;
1620 
1621 	pthread_mutex_lock(&done_mutex);
1622 	pthread_cond_timedwait(&done_cond, &done_mutex, &wait_time);
1623 	pthread_mutex_unlock(&done_mutex);
1624 }
1625 
hotword_models_cb(struct cras_client * client,const char * hotword_models)1626 static void hotword_models_cb(struct cras_client *client,
1627 			      const char *hotword_models)
1628 {
1629 	printf("Hotword models: %s\n", hotword_models);
1630 }
1631 
print_hotword_models(struct cras_client * client,cras_node_id_t id)1632 static void print_hotword_models(struct cras_client *client, cras_node_id_t id)
1633 {
1634 	struct timespec wait_time;
1635 
1636 	cras_client_run_thread(client);
1637 	cras_client_connected_wait(client);
1638 	cras_client_get_hotword_models(client, id, hotword_models_cb);
1639 
1640 	clock_gettime(CLOCK_REALTIME, &wait_time);
1641 	wait_time.tv_sec += 2;
1642 
1643 	pthread_mutex_lock(&done_mutex);
1644 	pthread_cond_timedwait(&done_cond, &done_mutex, &wait_time);
1645 	pthread_mutex_unlock(&done_mutex);
1646 }
1647 
check_output_plugged(struct cras_client * client,const char * name)1648 static void check_output_plugged(struct cras_client *client, const char *name)
1649 {
1650 	cras_client_run_thread(client);
1651 	cras_client_connected_wait(client); /* To synchronize data. */
1652 	printf("%s\n",
1653 	       cras_client_output_dev_plugged(client, name) ? "Yes" : "No");
1654 }
1655 
1656 /* Repeatedly mute and un-mute the output until there is an error. */
mute_loop_test(struct cras_client * client,int auto_reconnect)1657 static void mute_loop_test(struct cras_client *client, int auto_reconnect)
1658 {
1659 	int mute = 0;
1660 	int rc;
1661 
1662 	if (auto_reconnect)
1663 		cras_client_run_thread(client);
1664 	while (1) {
1665 		rc = cras_client_set_user_mute(client, mute);
1666 		printf("cras_client_set_user_mute(%d): %d\n", mute, rc);
1667 		if (rc != 0 && !auto_reconnect)
1668 			return;
1669 		mute = !mute;
1670 		sleep(2);
1671 	}
1672 }
1673 
show_atlog(time_t sec_offset,int32_t nsec_offset,struct audio_thread_event_log * log,int len,uint64_t missing)1674 static void show_atlog(time_t sec_offset, int32_t nsec_offset,
1675 		       struct audio_thread_event_log *log, int len,
1676 		       uint64_t missing)
1677 {
1678 	int i;
1679 	printf("Audio Thread Event Log:\n");
1680 
1681 	if (missing)
1682 		printf("%" PRIu64 " logs are missing.\n", missing);
1683 
1684 	for (i = 0; i < len; ++i) {
1685 		show_alog_tag(log, i, sec_offset, nsec_offset);
1686 	}
1687 }
1688 
unlock_main_thread(struct cras_client * client)1689 static void unlock_main_thread(struct cras_client *client)
1690 {
1691 	pthread_mutex_lock(&done_mutex);
1692 	pthread_cond_signal(&done_cond);
1693 	pthread_mutex_unlock(&done_mutex);
1694 }
1695 
cras_show_continuous_atlog(struct cras_client * client)1696 static void cras_show_continuous_atlog(struct cras_client *client)
1697 {
1698 	struct audio_thread_event_log log;
1699 	struct timespec wait_time;
1700 	static time_t sec_offset;
1701 	static int32_t nsec_offset;
1702 	static uint64_t atlog_read_idx = 0, missing;
1703 	int len, rc;
1704 
1705 	cras_client_run_thread(client);
1706 	cras_client_connected_wait(client); /* To synchronize data. */
1707 	cras_client_get_atlog_access(client, unlock_main_thread);
1708 
1709 	clock_gettime(CLOCK_REALTIME, &wait_time);
1710 	wait_time.tv_sec += 2;
1711 
1712 	pthread_mutex_lock(&done_mutex);
1713 	rc = pthread_cond_timedwait(&done_cond, &done_mutex, &wait_time);
1714 	pthread_mutex_unlock(&done_mutex);
1715 
1716 	if (rc)
1717 		goto fail;
1718 
1719 	fill_time_offset(&sec_offset, &nsec_offset);
1720 
1721 	/* Set stdout buffer to line buffered mode. */
1722 	setlinebuf(stdout);
1723 
1724 	while (1) {
1725 		len = cras_client_read_atlog(client, &atlog_read_idx, &missing,
1726 					     &log);
1727 
1728 		if (len < 0)
1729 			break;
1730 		if (len > 0)
1731 			show_atlog(sec_offset, nsec_offset, &log, len, missing);
1732 		nanosleep(&follow_atlog_sleep_ts, NULL);
1733 	}
1734 fail:
1735 	printf("Failed to get audio thread log.\n");
1736 }
1737 
1738 // clang-format off
1739 static struct option long_options[] = {
1740 	{"show_latency",        no_argument,            &show_latency, 1},
1741 	{"show_rms",            no_argument,            &show_rms, 1},
1742 	{"show_total_rms",      no_argument,            &show_total_rms, 1},
1743 	{"select_input",        required_argument,      0, 'a'},
1744 	{"block_size",          required_argument,      0, 'b'},
1745 	{"num_channels",        required_argument,      0, 'c'},
1746 	{"duration_seconds",    required_argument,      0, 'd'},
1747 	{"dump_events",         no_argument,            0, 'e'},
1748 	{"format",              required_argument,      0, 'f'},
1749 	{"capture_gain",        required_argument,      0, 'g'},
1750 	{"help",                no_argument,            0, 'h'},
1751 	{"dump_server_info",    no_argument,            0, 'i'},
1752 	{"check_output_plugged",required_argument,      0, 'j'},
1753 	{"add_active_input",    required_argument,      0, 'k'},
1754 	{"dump_dsp",            no_argument,            0, 'l'},
1755 	{"dump_audio_thread",   no_argument,            0, 'm'},
1756 	{"syslog_mask",         required_argument,      0, 'n'},
1757 	{"channel_layout",      required_argument,      0, 'o'},
1758 	{"get_aec_group_id",    no_argument,            0, 'p'},
1759 	{"user_mute",           required_argument,      0, 'q'},
1760 	{"rate",                required_argument,      0, 'r'},
1761 	{"reload_dsp",          no_argument,            0, 's'},
1762 	{"add_active_output",   required_argument,      0, 't'},
1763 	{"mute",                required_argument,      0, 'u'},
1764 	{"volume",              required_argument,      0, 'v'},
1765 	{"set_node_volume",     required_argument,      0, 'w'},
1766 	{"plug",                required_argument,      0, 'x'},
1767 	{"select_output",       required_argument,      0, 'y'},
1768 	{"playback_delay_us",   required_argument,      0, 'z'},
1769 	{"capture_mute",        required_argument,      0, '0'},
1770 	{"rm_active_input",     required_argument,      0, '1'},
1771 	{"rm_active_output",    required_argument,      0, '2'},
1772 	{"swap_left_right",     required_argument,      0, '3'},
1773 	{"version",             no_argument,            0, '4'},
1774 	{"add_test_dev",        required_argument,      0, '5'},
1775 	{"test_hotword_file",   required_argument,      0, '6'},
1776 	{"listen_for_hotword",  required_argument,      0, '7'},
1777 	{"pin_device",          required_argument,      0, '8'},
1778 	{"suspend",             required_argument,      0, '9'},
1779 	{"set_node_gain",       required_argument,      0, ':'},
1780 	{"play_short_sound",    required_argument,      0, '!'},
1781 	{"config_global_remix", required_argument,      0, ';'},
1782 	{"set_hotword_model",   required_argument,      0, '<'},
1783 	{"get_hotword_models",  required_argument,      0, '>'},
1784 	{"post_dsp",            required_argument,      0, 'A'},
1785 	{"stream_id",           required_argument,      0, 'B'},
1786 	{"capture_file",        required_argument,      0, 'C'},
1787 	{"reload_aec_config",   no_argument,            0, 'D'},
1788 	{"effects",             required_argument,      0, 'E'},
1789 	{"get_aec_supported",   no_argument,            0, 'F'},
1790 	{"aecdump",             required_argument,      0, 'G'},
1791 	{"dump_bt",             no_argument,            0, 'H'},
1792 	{"set_wbs_enabled",     required_argument,      0, 'I'},
1793 	{"follow_atlog",	no_argument,		0, 'J'},
1794 	{"connection_type",     required_argument,      0, 'K'},
1795 	{"loopback_file",       required_argument,      0, 'L'},
1796 	{"mute_loop_test",      required_argument,      0, 'M'},
1797 	{"dump_main",		no_argument,		0, 'N'},
1798 	{"playback_file",       required_argument,      0, 'P'},
1799 	{"stream_type",         required_argument,      0, 'T'},
1800 	{0, 0, 0, 0}
1801 };
1802 // clang-format on
1803 
show_usage()1804 static void show_usage()
1805 {
1806 	int i;
1807 
1808 	printf("--add_active_input <N>:<M> - "
1809 	       "Add the ionode with the given id to active input device "
1810 	       "list\n");
1811 	printf("--add_active_output <N>:<M> - "
1812 	       "Add the ionode with the given id to active output device "
1813 	       "list\n");
1814 	printf("--add_test_dev <type> - "
1815 	       "Add a test iodev.\n");
1816 	printf("--block_size <N> - "
1817 	       "The number for frames per callback(dictates latency).\n");
1818 	printf("--capture_file <name> - "
1819 	       "Name of file to record to.\n");
1820 	printf("--capture_gain <dB> - "
1821 	       "Set system capture gain in dB*100 (100 = 1dB).\n");
1822 	printf("--capture_mute <0|1> - "
1823 	       "Set capture mute state.\n");
1824 	printf("--channel_layout <layout_str> - "
1825 	       "Set multiple channel layout.\n");
1826 	printf("--check_output_plugged <output name> - "
1827 	       "Check if the output is plugged in\n");
1828 	printf("--connection_type <connection_type> - "
1829 	       "Set cras_client connection_type (default to 0).\n"
1830 	       "                                      "
1831 	       "Argument: 0 - For control client.\n"
1832 	       "                                      "
1833 	       "          1 - For playback client.\n"
1834 	       "                                      "
1835 	       "          2 - For capture client.\n"
1836 	       "                                      "
1837 	       "          3 - For legacy client in vms.\n"
1838 	       "                                      "
1839 	       "          4 - For unified client in vms.\n");
1840 	printf("--dump_audio_thread - "
1841 	       "Dumps audio thread info.\n");
1842 	printf("--dump_bt - "
1843 	       "Dumps debug info for bt audio\n");
1844 	printf("--dump_main - "
1845 	       "Dumps debug info from main thread\n");
1846 	printf("--dump_dsp - "
1847 	       "Print status of dsp to syslog.\n");
1848 	printf("--dump_server_info - "
1849 	       "Print status of the server.\n");
1850 	printf("--duration_seconds <N> - "
1851 	       "Seconds to record or playback.\n");
1852 	printf("--follow_atlog - "
1853 	       "Continuously dumps audio thread event log.\n");
1854 	printf("--format <name> - "
1855 	       "The sample format. Either ");
1856 	for (i = 0; supported_formats[i].name; ++i)
1857 		printf("%s ", supported_formats[i].name);
1858 	printf("(default to S16_LE).\n");
1859 	printf("--get_hotword_models <N>:<M> - "
1860 	       "Get the supported hotword models of node\n");
1861 	printf("--help - "
1862 	       "Print this message.\n");
1863 	printf("--listen_for_hotword <name> - "
1864 	       "Listen and capture hotword stream if supported\n");
1865 	printf("--loopback_file <name> - "
1866 	       "Name of file to record from loopback device.\n");
1867 	printf("--mute <0|1> - "
1868 	       "Set system mute state.\n");
1869 	printf("--mute_loop_test <0|1> - "
1870 	       "Continuously loop mute/un-mute.\n"
1871 	       "                         "
1872 	       "Argument: 0 - stop on error.\n"
1873 	       "                         "
1874 	       "          1 - automatically reconnect to CRAS.\n");
1875 	printf("--num_channels <N> - "
1876 	       "Two for stereo.\n");
1877 	printf("--pin_device <N> - "
1878 	       "Playback/Capture only on the given device.\n");
1879 	printf("--playback_file <name> - "
1880 	       "Name of file to play, "
1881 	       "\"-\" to playback raw audio from stdin.\n");
1882 	printf("--play_short_sound <N> - "
1883 	       "Plays the content in the file for N periods when ' "
1884 	       "is pressed.\n");
1885 	printf("--plug <N>:<M>:<0|1> - "
1886 	       "Set the plug state (0 or 1) for the ionode with the given "
1887 	       "index M on the device with index N\n");
1888 	printf("--rate <N> - "
1889 	       "Specifies the sample rate in Hz.\n");
1890 	printf("--reload_dsp - "
1891 	       "Reload dsp configuration from the ini file\n");
1892 	printf("--rm_active_input <N>:<M> - "
1893 	       "Removes the ionode with the given id from active input device "
1894 	       "list\n");
1895 	printf("--rm_active_output <N>:<M> - "
1896 	       "Removes the ionode with the given id from active output device "
1897 	       "list\n");
1898 	printf("--select_input <N>:<M> - "
1899 	       "Select the ionode with the given id as preferred input\n");
1900 	printf("--select_output <N>:<M> - "
1901 	       "Select the ionode with the given id as preferred output\n");
1902 	printf("--set_hotword_model <N>:<M>:<model> - "
1903 	       "Set the model to node\n");
1904 	printf("--playback_delay_us <N> - "
1905 	       "Set the time in us to delay a reply for playback when i is "
1906 	       "pressed\n");
1907 	printf("--post_dsp <0|1> - "
1908 	       "Use this flag with --loopback_file. The default value is 0.\n"
1909 	       "                   "
1910 	       "Argument: 0 - Record from post-mix, pre-DSP loopback device.\n"
1911 	       "                   "
1912 	       "          1 - Record from post-DSP loopback device.\n");
1913 	printf("--set_node_volume <N>:<M>:<0-100> - "
1914 	       "Set the volume of the ionode with the given id\n");
1915 	printf("--show_latency - "
1916 	       "Display latency while playing or recording.\n");
1917 	printf("--show_rms - "
1918 	       "Display RMS value of loopback stream.\n");
1919 	printf("--show_total_rms - "
1920 	       "Display total RMS value of loopback stream at the end.\n");
1921 	printf("--suspend <0|1> - "
1922 	       "Set audio suspend state.\n");
1923 	printf("--swap_left_right <N>:<M>:<0|1> - "
1924 	       "Swap or un-swap (1 or 0) the left and right channel for the "
1925 	       "ionode with the given index M on the device with index N\n");
1926 	printf("--stream_type <N> - "
1927 	       "Specify the type of the stream.\n");
1928 	printf("--syslog_mask <n> - "
1929 	       "Set the syslog mask to the given log level.\n");
1930 	printf("--test_hotword_file <N>:<filename> - "
1931 	       "Use filename as a hotword buffer for device N\n");
1932 	printf("--user_mute <0|1> - "
1933 	       "Set user mute state.\n");
1934 	printf("--version - "
1935 	       "Print the git commit ID that was used to build the client.\n");
1936 	printf("--volume <0-100> - "
1937 	       "Set system output volume.\n");
1938 }
1939 
cras_client_create_and_connect(struct cras_client ** client,enum CRAS_CONNECTION_TYPE conn_type)1940 static int cras_client_create_and_connect(struct cras_client **client,
1941 					  enum CRAS_CONNECTION_TYPE conn_type)
1942 {
1943 	int rc;
1944 
1945 	rc = cras_client_create_with_type(client, conn_type);
1946 	if (rc < 0) {
1947 		fprintf(stderr, "Couldn't create client.\n");
1948 		return rc;
1949 	}
1950 
1951 	rc = cras_client_connect_timeout(*client, 1000);
1952 	if (rc) {
1953 		fprintf(stderr, "Couldn't connect to server.\n");
1954 		cras_client_destroy(*client);
1955 		return rc;
1956 	}
1957 
1958 	return 0;
1959 }
1960 
main(int argc,char ** argv)1961 int main(int argc, char **argv)
1962 {
1963 	struct cras_client *client;
1964 	int c, option_index;
1965 	size_t block_size = NOT_ASSIGNED;
1966 	size_t rate = 48000;
1967 	size_t num_channels = 2;
1968 	float duration_seconds = 0;
1969 	const char *capture_file = NULL;
1970 	const char *playback_file = NULL;
1971 	const char *loopback_file = NULL;
1972 	int post_dsp = 0;
1973 	enum CRAS_STREAM_TYPE stream_type = CRAS_STREAM_TYPE_DEFAULT;
1974 	int rc = 0;
1975 	uint32_t stream_flags = 0;
1976 	cras_stream_id_t stream_id = 0;
1977 	snd_pcm_format_t format = SND_PCM_FORMAT_S16_LE;
1978 	enum CRAS_CONNECTION_TYPE conn_type = CRAS_CONTROL;
1979 	enum CRAS_CONNECTION_TYPE new_conn_type;
1980 
1981 	option_index = 0;
1982 	openlog("cras_test_client", LOG_PERROR, LOG_USER);
1983 	setlogmask(LOG_UPTO(LOG_INFO));
1984 
1985 	rc = cras_client_create_and_connect(&client, conn_type);
1986 	if (rc) {
1987 		return rc;
1988 	}
1989 
1990 	if (argc == 1) {
1991 		/* Nothing specified, default to dump_server_info. */
1992 		print_server_info(client);
1993 		goto destroy_exit;
1994 	}
1995 
1996 	while (1) {
1997 		c = getopt_long(argc, argv, "o:s:P:C:r:c:f:h", long_options,
1998 				&option_index);
1999 		if (c == -1)
2000 			break;
2001 		switch (c) {
2002 		case 'y':
2003 		case 'a': {
2004 			cras_node_id_t id;
2005 			rc = parse_node_id(optarg, &id);
2006 			if (rc) {
2007 				show_usage();
2008 				return rc;
2009 			}
2010 
2011 			enum CRAS_STREAM_DIRECTION direction =
2012 				(c == 'y') ? CRAS_STREAM_OUTPUT :
2013 					     CRAS_STREAM_INPUT;
2014 			cras_client_select_node(client, direction, id);
2015 			break;
2016 		}
2017 		case 'b':
2018 			block_size = atoi(optarg);
2019 			break;
2020 		case 'c':
2021 			num_channels = atoi(optarg);
2022 			break;
2023 		case 'd':
2024 			duration_seconds = atof(optarg);
2025 			break;
2026 		case 'e':
2027 			show_audio_thread_snapshots(client);
2028 			break;
2029 		case 'f': {
2030 			int i;
2031 
2032 			for (i = 0; supported_formats[i].name; ++i) {
2033 				if (strcasecmp(optarg,
2034 					       supported_formats[i].name) ==
2035 				    0) {
2036 					format = supported_formats[i].format;
2037 					break;
2038 				}
2039 			}
2040 
2041 			if (!supported_formats[i].name) {
2042 				printf("Unsupported format: %s\n", optarg);
2043 				return -EINVAL;
2044 			}
2045 			break;
2046 		}
2047 		case 'h':
2048 			show_usage();
2049 			break;
2050 		case 'i':
2051 			print_server_info(client);
2052 			break;
2053 		case 'j':
2054 			check_output_plugged(client, optarg);
2055 			break;
2056 		case 'k':
2057 		case 't':
2058 		case '1':
2059 		case '2': {
2060 			cras_node_id_t id;
2061 			rc = parse_node_id(optarg, &id);
2062 			if (rc) {
2063 				show_usage();
2064 				return rc;
2065 			}
2066 
2067 			enum CRAS_STREAM_DIRECTION dir;
2068 			if (c == 't' || c == '2')
2069 				dir = CRAS_STREAM_OUTPUT;
2070 			else
2071 				dir = CRAS_STREAM_INPUT;
2072 
2073 			if (c == 'k' || c == 't')
2074 				cras_client_add_active_node(client, dir, id);
2075 			else
2076 				cras_client_rm_active_node(client, dir, id);
2077 			break;
2078 		}
2079 		case 'l':
2080 			cras_client_dump_dsp_info(client);
2081 			break;
2082 		case 'm':
2083 			show_audio_debug_info(client);
2084 			break;
2085 		case 'n': {
2086 			int log_level = atoi(optarg);
2087 
2088 			setlogmask(LOG_UPTO(log_level));
2089 			break;
2090 		}
2091 		case 'o':
2092 			channel_layout = optarg;
2093 			break;
2094 		case 'p':
2095 			printf("AEC group ID %d\n",
2096 			       cras_client_get_aec_group_id(client));
2097 			break;
2098 		case 'q': {
2099 			int mute = atoi(optarg);
2100 			rc = cras_client_set_user_mute(client, mute);
2101 			if (rc < 0) {
2102 				fprintf(stderr, "problem setting mute\n");
2103 				goto destroy_exit;
2104 			}
2105 			break;
2106 		}
2107 		case 'r':
2108 			rate = atoi(optarg);
2109 			break;
2110 		case 's':
2111 			cras_client_reload_dsp(client);
2112 			break;
2113 		case 'u': {
2114 			int mute = atoi(optarg);
2115 			rc = cras_client_set_system_mute(client, mute);
2116 			if (rc < 0) {
2117 				fprintf(stderr, "problem setting mute\n");
2118 				goto destroy_exit;
2119 			}
2120 			break;
2121 		}
2122 		case 'v': {
2123 			int volume = atoi(optarg);
2124 			volume = MIN(100, MAX(0, volume));
2125 			rc = cras_client_set_system_volume(client, volume);
2126 			if (rc < 0) {
2127 				fprintf(stderr, "problem setting volume\n");
2128 				goto destroy_exit;
2129 			}
2130 			break;
2131 		}
2132 		case ':':
2133 		case 'w': {
2134 			cras_node_id_t id;
2135 			int value;
2136 			rc = parse_node_id_with_value(optarg, &id, &value);
2137 			if (rc) {
2138 				show_usage();
2139 				return rc;
2140 			}
2141 
2142 			if (c == 'w')
2143 				cras_client_set_node_volume(client, id, value);
2144 			else
2145 				cras_client_set_node_capture_gain(client, id,
2146 								  value);
2147 			break;
2148 		}
2149 		case 'x': {
2150 			cras_node_id_t id;
2151 			int value;
2152 			rc = parse_node_id_with_value(optarg, &id, &value);
2153 			if (rc) {
2154 				show_usage();
2155 				return rc;
2156 			}
2157 
2158 			enum ionode_attr attr = IONODE_ATTR_PLUGGED;
2159 			cras_client_set_node_attr(client, id, attr, value);
2160 			break;
2161 		}
2162 		case 'z':
2163 			pause_in_playback_reply = atoi(optarg);
2164 			break;
2165 
2166 		case '0': {
2167 			int mute = atoi(optarg);
2168 			rc = cras_client_set_system_capture_mute(client, mute);
2169 			if (rc < 0) {
2170 				fprintf(stderr, "problem setting mute\n");
2171 				goto destroy_exit;
2172 			}
2173 			break;
2174 		}
2175 		case '3': {
2176 			cras_node_id_t id;
2177 			int value;
2178 			rc = parse_node_id_with_value(optarg, &id, &value);
2179 			if (rc) {
2180 				show_usage();
2181 				return rc;
2182 			}
2183 
2184 			cras_client_swap_node_left_right(client, id, value);
2185 			break;
2186 		}
2187 		case '4':
2188 			printf("%s\n", VCSID);
2189 			break;
2190 		case '5': {
2191 			cras_client_add_test_iodev(client, atoi(optarg));
2192 			break;
2193 		}
2194 		case '6': {
2195 			const char *s;
2196 			int dev_index;
2197 
2198 			s = strtok(optarg, ":");
2199 			if (!s) {
2200 				show_usage();
2201 				return -EINVAL;
2202 			}
2203 			dev_index = atoi(s);
2204 
2205 			const char *file_name = strtok(NULL, ":");
2206 			if (!file_name) {
2207 				show_usage();
2208 				return -EINVAL;
2209 			}
2210 			cras_client_test_iodev_command(
2211 				client, dev_index,
2212 				TEST_IODEV_CMD_HOTWORD_TRIGGER,
2213 				strlen(file_name) + 1, (uint8_t *)file_name);
2214 			break;
2215 		}
2216 		case '7': {
2217 			stream_flags = HOTWORD_STREAM;
2218 			capture_file = optarg;
2219 			break;
2220 		}
2221 		case '8':
2222 			pin_device_id = atoi(optarg);
2223 			break;
2224 		case '9': {
2225 			int suspend = atoi(optarg);
2226 			cras_client_set_suspend(client, suspend);
2227 			break;
2228 		}
2229 
2230 		case '!': {
2231 			play_short_sound = 1;
2232 			play_short_sound_periods = atoi(optarg);
2233 			break;
2234 		}
2235 		case ';': {
2236 			char *s;
2237 			int nch;
2238 			int size = 0;
2239 			float *coeff;
2240 
2241 			s = strtok(optarg, ":");
2242 			nch = atoi(s);
2243 			coeff = (float *)calloc((size_t)nch * (size_t)nch,
2244 						sizeof(*coeff));
2245 			for (size = 0; size < nch * nch; size++) {
2246 				s = strtok(NULL, ",");
2247 				if (NULL == s)
2248 					break;
2249 				coeff[size] = atof(s);
2250 			}
2251 			cras_client_config_global_remix(client, nch, coeff);
2252 			free(coeff);
2253 			break;
2254 		}
2255 		case '<':
2256 		case '>': {
2257 			char *s;
2258 			int dev_index;
2259 			int node_index;
2260 
2261 			s = strtok(optarg, ":");
2262 			if (!s) {
2263 				show_usage();
2264 				return -EINVAL;
2265 			}
2266 			dev_index = atoi(s);
2267 
2268 			s = strtok(NULL, ":");
2269 			if (!s) {
2270 				show_usage();
2271 				return -EINVAL;
2272 			}
2273 			node_index = atoi(s);
2274 
2275 			s = strtok(NULL, ":");
2276 			if (!s && c == ';') {
2277 				//TODO: c never == ';'
2278 				show_usage();
2279 				return -EINVAL;
2280 			}
2281 
2282 			cras_node_id_t id =
2283 				cras_make_node_id(dev_index, node_index);
2284 			if (c == '<')
2285 				cras_client_set_hotword_model(client, id, s);
2286 			else
2287 				print_hotword_models(client, id);
2288 			break;
2289 		}
2290 
2291 		case 'A':
2292 			post_dsp = atoi(optarg);
2293 			break;
2294 		case 'B':
2295 			stream_id = atoi(optarg);
2296 			break;
2297 		case 'C':
2298 			capture_file = optarg;
2299 			break;
2300 		case 'D':
2301 			cras_client_reload_aec_config(client);
2302 			break;
2303 		case 'E': {
2304 			char *s;
2305 
2306 			s = strtok(optarg, ",");
2307 			while (s) {
2308 				if (strcmp("aec", s) == 0)
2309 					effect_aec = 1;
2310 				else if (strcmp("ns", s) == 0)
2311 					effect_ns = 1;
2312 				else if (strcmp("agc", s) == 0)
2313 					effect_agc = 1;
2314 				else if (strcmp("vad", s) == 0)
2315 					effect_vad = 1;
2316 				else
2317 					printf("Unknown effect %s\n", s);
2318 				s = strtok(NULL, ",");
2319 			}
2320 			break;
2321 		}
2322 		case 'F':
2323 			printf("AEC supported %d\n",
2324 			       !!cras_client_get_aec_supported(client));
2325 			break;
2326 		case 'G':
2327 			aecdump_file = optarg;
2328 			break;
2329 		case 'H':
2330 			show_cras_bt_debug_info(client);
2331 			break;
2332 		case 'I':
2333 			cras_client_set_bt_wbs_enabled(client, atoi(optarg));
2334 			break;
2335 		case 'J':
2336 			cras_show_continuous_atlog(client);
2337 			break;
2338 		case 'K':
2339 			new_conn_type = atoi(optarg);
2340 			if (cras_validate_connection_type(new_conn_type)) {
2341 				if (new_conn_type != conn_type) {
2342 					cras_client_destroy(client);
2343 					client = NULL;
2344 					rc = cras_client_create_and_connect(
2345 						&client, new_conn_type);
2346 					if (rc) {
2347 						fprintf(stderr,
2348 							"Couldn't connect to "
2349 							"server.\n");
2350 						return rc;
2351 					}
2352 					conn_type = new_conn_type;
2353 				}
2354 			} else {
2355 				printf("Input connection type is not "
2356 				       "supported.\n");
2357 			}
2358 			break;
2359 		case 'L':
2360 			loopback_file = optarg;
2361 			break;
2362 		case 'M':
2363 			mute_loop_test(client, atoi(optarg));
2364 			break;
2365 		case 'N':
2366 			show_main_thread_debug_info(client);
2367 			break;
2368 		case 'P':
2369 			playback_file = optarg;
2370 			break;
2371 		case 'T':
2372 			stream_type = atoi(optarg);
2373 			break;
2374 
2375 		default:
2376 			break;
2377 		}
2378 	}
2379 
2380 	if (optind < argc) {
2381 		printf("Warning: un-welcome arguments: ");
2382 		while (optind < argc)
2383 			printf("%s ", argv[optind++]);
2384 		printf("\n");
2385 		rc = 1;
2386 		goto destroy_exit;
2387 	}
2388 
2389 	duration_frames = duration_seconds * rate;
2390 	if (block_size == NOT_ASSIGNED)
2391 		block_size = get_block_size(PLAYBACK_BUFFERED_TIME_IN_US, rate);
2392 
2393 	if (capture_file != NULL) {
2394 		if (strcmp(capture_file, "-") == 0)
2395 			rc = run_file_io_stream(client, 1, CRAS_STREAM_INPUT,
2396 						block_size, stream_type, rate,
2397 						format, num_channels,
2398 						stream_flags, 0, 0);
2399 		else
2400 			rc = run_capture(client, capture_file, block_size,
2401 					 stream_type, rate, format,
2402 					 num_channels, stream_flags, 0, 0);
2403 	} else if (playback_file != NULL) {
2404 		if (strcmp(playback_file, "-") == 0)
2405 			rc = run_file_io_stream(client, 0, CRAS_STREAM_OUTPUT,
2406 						block_size, stream_type, rate,
2407 						format, num_channels,
2408 						stream_flags, 0, 0);
2409 		else
2410 			rc = run_playback(client, playback_file, block_size,
2411 					  stream_type, rate, format,
2412 					  num_channels);
2413 	} else if (loopback_file != NULL) {
2414 		rc = run_capture(client, loopback_file, block_size, stream_type,
2415 				 rate, format, num_channels, stream_flags, 1,
2416 				 post_dsp);
2417 	} else if (aecdump_file != NULL) {
2418 		run_aecdump(client, stream_id, 1);
2419 		sleep(duration_seconds);
2420 		run_aecdump(client, stream_id, 0);
2421 	}
2422 
2423 destroy_exit:
2424 	cras_client_destroy(client);
2425 	return rc;
2426 }
2427