• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /* Copyright 2019 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 #include <assert.h>
6 #include <stdlib.h>
7 #include <syslog.h>
8 
9 #include "audio_thread.h"
10 #include "audio_thread_log.h"
11 #include "cras_apm_list.h"
12 #include "cras_bt_log.h"
13 #include "cras_config.h"
14 #include "cras_control_rclient.h"
15 #include "cras_dsp.h"
16 #include "cras_iodev.h"
17 #include "cras_iodev_list.h"
18 #include "cras_messages.h"
19 #include "cras_observer.h"
20 #include "cras_rclient.h"
21 #include "cras_rclient_util.h"
22 #include "cras_rstream.h"
23 #include "cras_system_state.h"
24 #include "cras_types.h"
25 #include "cras_util.h"
26 #include "stream_list.h"
27 #include "utlist.h"
28 
29 /* Handles dumping audio thread debug info back to the client. */
dump_audio_thread_info(struct cras_rclient * client)30 static void dump_audio_thread_info(struct cras_rclient *client)
31 {
32 	struct cras_client_audio_debug_info_ready msg;
33 	struct cras_server_state *state;
34 
35 	cras_fill_client_audio_debug_info_ready(&msg);
36 	state = cras_system_state_get_no_lock();
37 	audio_thread_dump_thread_info(cras_iodev_list_get_audio_thread(),
38 				      &state->audio_debug_info);
39 	client->ops->send_message_to_client(client, &msg.header, NULL, 0);
40 }
41 
42 /* Sends shared memory fd for audio thread event log back to the client. */
get_atlog_fd(struct cras_rclient * client)43 static void get_atlog_fd(struct cras_rclient *client)
44 {
45 	struct cras_client_atlog_fd_ready msg;
46 	int atlog_fd;
47 
48 	cras_fill_client_atlog_fd_ready(&msg);
49 	atlog_fd = audio_thread_event_log_shm_fd();
50 	client->ops->send_message_to_client(client, &msg.header, &atlog_fd, 1);
51 }
52 
53 /* Handles dumping audio snapshots to shared memory for the client. */
dump_audio_thread_snapshots(struct cras_rclient * client)54 static void dump_audio_thread_snapshots(struct cras_rclient *client)
55 {
56 	struct cras_client_audio_debug_info_ready msg;
57 
58 	cras_fill_client_audio_debug_info_ready(&msg);
59 	cras_system_state_dump_snapshots();
60 	client->ops->send_message_to_client(client, &msg.header, NULL, 0);
61 }
62 
handle_get_hotword_models(struct cras_rclient * client,cras_node_id_t node_id)63 static void handle_get_hotword_models(struct cras_rclient *client,
64 				      cras_node_id_t node_id)
65 {
66 	struct cras_client_get_hotword_models_ready *msg;
67 	char *hotword_models;
68 	unsigned hotword_models_size;
69 	uint8_t buf[CRAS_CLIENT_MAX_MSG_SIZE];
70 
71 	msg = (struct cras_client_get_hotword_models_ready *)buf;
72 	hotword_models = cras_iodev_list_get_hotword_models(node_id);
73 	if (!hotword_models)
74 		goto empty_reply;
75 	hotword_models_size = strlen(hotword_models);
76 	if (hotword_models_size > CRAS_MAX_HOTWORD_MODELS) {
77 		free(hotword_models);
78 		goto empty_reply;
79 	}
80 
81 	cras_fill_client_get_hotword_models_ready(msg, hotword_models,
82 						  hotword_models_size);
83 	client->ops->send_message_to_client(client, &msg->header, NULL, 0);
84 	free(hotword_models);
85 	return;
86 
87 empty_reply:
88 	cras_fill_client_get_hotword_models_ready(msg, NULL, 0);
89 	client->ops->send_message_to_client(client, &msg->header, NULL, 0);
90 }
91 
92 /* Client notification callback functions. */
93 
send_output_volume_changed(void * context,int32_t volume)94 static void send_output_volume_changed(void *context, int32_t volume)
95 {
96 	struct cras_client_volume_changed msg;
97 	struct cras_rclient *client = (struct cras_rclient *)context;
98 
99 	cras_fill_client_output_volume_changed(&msg, volume);
100 	client->ops->send_message_to_client(client, &msg.header, NULL, 0);
101 }
102 
send_output_mute_changed(void * context,int muted,int user_muted,int mute_locked)103 static void send_output_mute_changed(void *context, int muted, int user_muted,
104 				     int mute_locked)
105 {
106 	struct cras_client_mute_changed msg;
107 	struct cras_rclient *client = (struct cras_rclient *)context;
108 
109 	cras_fill_client_output_mute_changed(&msg, muted, user_muted,
110 					     mute_locked);
111 	client->ops->send_message_to_client(client, &msg.header, NULL, 0);
112 }
113 
send_capture_gain_changed(void * context,int32_t gain)114 static void send_capture_gain_changed(void *context, int32_t gain)
115 {
116 	struct cras_client_volume_changed msg;
117 	struct cras_rclient *client = (struct cras_rclient *)context;
118 
119 	cras_fill_client_capture_gain_changed(&msg, gain);
120 	client->ops->send_message_to_client(client, &msg.header, NULL, 0);
121 }
122 
send_capture_mute_changed(void * context,int muted,int mute_locked)123 static void send_capture_mute_changed(void *context, int muted, int mute_locked)
124 {
125 	struct cras_client_mute_changed msg;
126 	struct cras_rclient *client = (struct cras_rclient *)context;
127 
128 	cras_fill_client_capture_mute_changed(&msg, muted, mute_locked);
129 	client->ops->send_message_to_client(client, &msg.header, NULL, 0);
130 }
131 
send_nodes_changed(void * context)132 static void send_nodes_changed(void *context)
133 {
134 	struct cras_client_nodes_changed msg;
135 	struct cras_rclient *client = (struct cras_rclient *)context;
136 
137 	cras_fill_client_nodes_changed(&msg);
138 	client->ops->send_message_to_client(client, &msg.header, NULL, 0);
139 }
140 
send_active_node_changed(void * context,enum CRAS_STREAM_DIRECTION dir,cras_node_id_t node_id)141 static void send_active_node_changed(void *context,
142 				     enum CRAS_STREAM_DIRECTION dir,
143 				     cras_node_id_t node_id)
144 {
145 	struct cras_client_active_node_changed msg;
146 	struct cras_rclient *client = (struct cras_rclient *)context;
147 
148 	cras_fill_client_active_node_changed(&msg, dir, node_id);
149 	client->ops->send_message_to_client(client, &msg.header, NULL, 0);
150 }
151 
send_output_node_volume_changed(void * context,cras_node_id_t node_id,int32_t volume)152 static void send_output_node_volume_changed(void *context,
153 					    cras_node_id_t node_id,
154 					    int32_t volume)
155 {
156 	struct cras_client_node_value_changed msg;
157 	struct cras_rclient *client = (struct cras_rclient *)context;
158 
159 	cras_fill_client_output_node_volume_changed(&msg, node_id, volume);
160 	client->ops->send_message_to_client(client, &msg.header, NULL, 0);
161 }
162 
send_node_left_right_swapped_changed(void * context,cras_node_id_t node_id,int swapped)163 static void send_node_left_right_swapped_changed(void *context,
164 						 cras_node_id_t node_id,
165 						 int swapped)
166 {
167 	struct cras_client_node_value_changed msg;
168 	struct cras_rclient *client = (struct cras_rclient *)context;
169 
170 	cras_fill_client_node_left_right_swapped_changed(&msg, node_id,
171 							 swapped);
172 	client->ops->send_message_to_client(client, &msg.header, NULL, 0);
173 }
174 
send_input_node_gain_changed(void * context,cras_node_id_t node_id,int32_t gain)175 static void send_input_node_gain_changed(void *context, cras_node_id_t node_id,
176 					 int32_t gain)
177 {
178 	struct cras_client_node_value_changed msg;
179 	struct cras_rclient *client = (struct cras_rclient *)context;
180 
181 	cras_fill_client_input_node_gain_changed(&msg, node_id, gain);
182 	client->ops->send_message_to_client(client, &msg.header, NULL, 0);
183 }
184 
send_num_active_streams_changed(void * context,enum CRAS_STREAM_DIRECTION dir,uint32_t num_active_streams)185 static void send_num_active_streams_changed(void *context,
186 					    enum CRAS_STREAM_DIRECTION dir,
187 					    uint32_t num_active_streams)
188 {
189 	struct cras_client_num_active_streams_changed msg;
190 	struct cras_rclient *client = (struct cras_rclient *)context;
191 
192 	cras_fill_client_num_active_streams_changed(&msg, dir,
193 						    num_active_streams);
194 	client->ops->send_message_to_client(client, &msg.header, NULL, 0);
195 }
196 
register_for_notification(struct cras_rclient * client,enum CRAS_CLIENT_MESSAGE_ID msg_id,int do_register)197 static void register_for_notification(struct cras_rclient *client,
198 				      enum CRAS_CLIENT_MESSAGE_ID msg_id,
199 				      int do_register)
200 {
201 	struct cras_observer_ops observer_ops;
202 	int empty;
203 
204 	cras_observer_get_ops(client->observer, &observer_ops);
205 
206 	switch (msg_id) {
207 	case CRAS_CLIENT_OUTPUT_VOLUME_CHANGED:
208 		observer_ops.output_volume_changed =
209 			do_register ? send_output_volume_changed : NULL;
210 		break;
211 	case CRAS_CLIENT_OUTPUT_MUTE_CHANGED:
212 		observer_ops.output_mute_changed =
213 			do_register ? send_output_mute_changed : NULL;
214 		break;
215 	case CRAS_CLIENT_CAPTURE_GAIN_CHANGED:
216 		observer_ops.capture_gain_changed =
217 			do_register ? send_capture_gain_changed : NULL;
218 		break;
219 	case CRAS_CLIENT_CAPTURE_MUTE_CHANGED:
220 		observer_ops.capture_mute_changed =
221 			do_register ? send_capture_mute_changed : NULL;
222 		break;
223 	case CRAS_CLIENT_NODES_CHANGED:
224 		observer_ops.nodes_changed =
225 			do_register ? send_nodes_changed : NULL;
226 		break;
227 	case CRAS_CLIENT_ACTIVE_NODE_CHANGED:
228 		observer_ops.active_node_changed =
229 			do_register ? send_active_node_changed : NULL;
230 		break;
231 	case CRAS_CLIENT_OUTPUT_NODE_VOLUME_CHANGED:
232 		observer_ops.output_node_volume_changed =
233 			do_register ? send_output_node_volume_changed : NULL;
234 		break;
235 	case CRAS_CLIENT_NODE_LEFT_RIGHT_SWAPPED_CHANGED:
236 		observer_ops.node_left_right_swapped_changed =
237 			do_register ? send_node_left_right_swapped_changed :
238 				      NULL;
239 		break;
240 	case CRAS_CLIENT_INPUT_NODE_GAIN_CHANGED:
241 		observer_ops.input_node_gain_changed =
242 			do_register ? send_input_node_gain_changed : NULL;
243 		break;
244 	case CRAS_CLIENT_NUM_ACTIVE_STREAMS_CHANGED:
245 		observer_ops.num_active_streams_changed =
246 			do_register ? send_num_active_streams_changed : NULL;
247 		break;
248 	default:
249 		syslog(LOG_ERR, "Invalid client notification message ID: %u",
250 		       msg_id);
251 		break;
252 	}
253 
254 	empty = cras_observer_ops_are_empty(&observer_ops);
255 	if (client->observer) {
256 		if (empty) {
257 			cras_observer_remove(client->observer);
258 			client->observer = NULL;
259 		} else {
260 			cras_observer_set_ops(client->observer, &observer_ops);
261 		}
262 	} else if (!empty) {
263 		client->observer = cras_observer_add(&observer_ops, client);
264 	}
265 }
266 
direction_valid(enum CRAS_STREAM_DIRECTION direction)267 static int direction_valid(enum CRAS_STREAM_DIRECTION direction)
268 {
269 	return direction < CRAS_NUM_DIRECTIONS &&
270 	       direction != CRAS_STREAM_UNDEFINED;
271 }
272 
273 /* Entry point for handling a message from the client.  Called from the main
274  * server context. */
ccr_handle_message_from_client(struct cras_rclient * client,const struct cras_server_message * msg,int * fds,unsigned int num_fds)275 static int ccr_handle_message_from_client(struct cras_rclient *client,
276 					  const struct cras_server_message *msg,
277 					  int *fds, unsigned int num_fds)
278 {
279 	int rc = 0;
280 	assert(client && msg);
281 
282 	rc = rclient_validate_message_fds(msg, fds, num_fds);
283 	if (rc < 0) {
284 		for (int i = 0; i < (int)num_fds; i++)
285 			if (fds[i] >= 0)
286 				close(fds[i]);
287 		return rc;
288 	}
289 	int fd = num_fds > 0 ? fds[0] : -1;
290 
291 	switch (msg->id) {
292 	case CRAS_SERVER_CONNECT_STREAM: {
293 		int client_shm_fd = num_fds > 1 ? fds[1] : -1;
294 		struct cras_connect_message cmsg;
295 		if (MSG_LEN_VALID(msg, struct cras_connect_message)) {
296 			return rclient_handle_client_stream_connect(
297 				client,
298 				(const struct cras_connect_message *)msg, fd,
299 				client_shm_fd);
300 		} else if (!convert_connect_message_old(msg, &cmsg)) {
301 			return rclient_handle_client_stream_connect(
302 				client, &cmsg, fd, client_shm_fd);
303 		} else {
304 			return -EINVAL;
305 		}
306 	}
307 	case CRAS_SERVER_DISCONNECT_STREAM:
308 		if (!MSG_LEN_VALID(msg, struct cras_disconnect_stream_message))
309 			return -EINVAL;
310 		rclient_handle_client_stream_disconnect(
311 			client,
312 			(const struct cras_disconnect_stream_message *)msg);
313 		break;
314 	case CRAS_SERVER_SET_SYSTEM_VOLUME:
315 		if (!MSG_LEN_VALID(msg, struct cras_set_system_volume))
316 			return -EINVAL;
317 		cras_system_set_volume(
318 			((const struct cras_set_system_volume *)msg)->volume);
319 		break;
320 	case CRAS_SERVER_SET_SYSTEM_MUTE:
321 		if (!MSG_LEN_VALID(msg, struct cras_set_system_mute))
322 			return -EINVAL;
323 		cras_system_set_mute(
324 			((const struct cras_set_system_mute *)msg)->mute);
325 		break;
326 	case CRAS_SERVER_SET_USER_MUTE:
327 		if (!MSG_LEN_VALID(msg, struct cras_set_system_mute))
328 			return -EINVAL;
329 		cras_system_set_user_mute(
330 			((const struct cras_set_system_mute *)msg)->mute);
331 		break;
332 	case CRAS_SERVER_SET_SYSTEM_MUTE_LOCKED:
333 		if (!MSG_LEN_VALID(msg, struct cras_set_system_mute))
334 			return -EINVAL;
335 		cras_system_set_mute_locked(
336 			((const struct cras_set_system_mute *)msg)->mute);
337 		break;
338 	case CRAS_SERVER_SET_SYSTEM_CAPTURE_GAIN: {
339 		const struct cras_set_system_capture_gain *m =
340 			(const struct cras_set_system_capture_gain *)msg;
341 		if (!MSG_LEN_VALID(msg, struct cras_set_system_capture_gain))
342 			return -EINVAL;
343 		cras_system_set_capture_gain(m->gain);
344 		break;
345 	}
346 	case CRAS_SERVER_SET_SYSTEM_CAPTURE_MUTE:
347 		if (!MSG_LEN_VALID(msg, struct cras_set_system_mute))
348 			return -EINVAL;
349 		cras_system_set_capture_mute(
350 			((const struct cras_set_system_mute *)msg)->mute);
351 		break;
352 	case CRAS_SERVER_SET_SYSTEM_CAPTURE_MUTE_LOCKED:
353 		if (!MSG_LEN_VALID(msg, struct cras_set_system_mute))
354 			return -EINVAL;
355 		cras_system_set_capture_mute_locked(
356 			((const struct cras_set_system_mute *)msg)->mute);
357 		break;
358 	case CRAS_SERVER_SET_NODE_ATTR: {
359 		const struct cras_set_node_attr *m =
360 			(const struct cras_set_node_attr *)msg;
361 		if (!MSG_LEN_VALID(msg, struct cras_set_node_attr))
362 			return -EINVAL;
363 		cras_iodev_list_set_node_attr(m->node_id, m->attr, m->value);
364 		break;
365 	}
366 	case CRAS_SERVER_SELECT_NODE: {
367 		const struct cras_select_node *m =
368 			(const struct cras_select_node *)msg;
369 		if (!MSG_LEN_VALID(msg, struct cras_select_node) ||
370 		    !direction_valid(m->direction))
371 			return -EINVAL;
372 		cras_iodev_list_select_node(m->direction, m->node_id);
373 		break;
374 	}
375 	case CRAS_SERVER_ADD_ACTIVE_NODE: {
376 		const struct cras_add_active_node *m =
377 			(const struct cras_add_active_node *)msg;
378 		if (!MSG_LEN_VALID(msg, struct cras_add_active_node) ||
379 		    !direction_valid(m->direction))
380 			return -EINVAL;
381 		cras_iodev_list_add_active_node(m->direction, m->node_id);
382 		break;
383 	}
384 	case CRAS_SERVER_RM_ACTIVE_NODE: {
385 		const struct cras_rm_active_node *m =
386 			(const struct cras_rm_active_node *)msg;
387 		if (!MSG_LEN_VALID(msg, struct cras_rm_active_node) ||
388 		    !direction_valid(m->direction))
389 			return -EINVAL;
390 		cras_iodev_list_rm_active_node(m->direction, m->node_id);
391 		break;
392 	}
393 	case CRAS_SERVER_RELOAD_DSP:
394 		cras_dsp_reload_ini();
395 		break;
396 	case CRAS_SERVER_DUMP_DSP_INFO:
397 		cras_dsp_dump_info();
398 		break;
399 	case CRAS_SERVER_DUMP_AUDIO_THREAD:
400 		dump_audio_thread_info(client);
401 		break;
402 	case CRAS_SERVER_GET_ATLOG_FD:
403 		get_atlog_fd(client);
404 		break;
405 	case CRAS_SERVER_DUMP_BT: {
406 		struct cras_client_audio_debug_info_ready msg;
407 		struct cras_server_state *state;
408 
409 		state = cras_system_state_get_no_lock();
410 #ifdef CRAS_DBUS
411 		memcpy(&state->bt_debug_info.bt_log, btlog,
412 		       sizeof(struct cras_bt_debug_info));
413 #else
414 		memset(&state->bt_debug_info.bt_log, 0,
415 		       sizeof(struct cras_bt_debug_info));
416 #endif
417 
418 		cras_fill_client_audio_debug_info_ready(&msg);
419 		client->ops->send_message_to_client(client, &msg.header, NULL,
420 						    0);
421 		break;
422 	}
423 	case CRAS_SERVER_SET_BT_WBS_ENABLED: {
424 		const struct cras_set_bt_wbs_enabled *m =
425 			(const struct cras_set_bt_wbs_enabled *)msg;
426 		if (!MSG_LEN_VALID(msg, struct cras_set_bt_wbs_enabled))
427 			return -EINVAL;
428 		cras_system_set_bt_wbs_enabled(m->enabled);
429 		break;
430 	}
431 	case CRAS_SERVER_DUMP_SNAPSHOTS:
432 		dump_audio_thread_snapshots(client);
433 		break;
434 	case CRAS_SERVER_ADD_TEST_DEV: {
435 		const struct cras_add_test_dev *m =
436 			(const struct cras_add_test_dev *)msg;
437 		if (!MSG_LEN_VALID(msg, struct cras_add_test_dev))
438 			return -EINVAL;
439 		cras_iodev_list_add_test_dev(m->type);
440 		break;
441 	}
442 	case CRAS_SERVER_TEST_DEV_COMMAND: {
443 		const struct cras_test_dev_command *m =
444 			(const struct cras_test_dev_command *)msg;
445 		if (!MSG_LEN_VALID(msg, struct cras_test_dev_command))
446 			return -EINVAL;
447 		cras_iodev_list_test_dev_command(
448 			m->iodev_idx, (enum CRAS_TEST_IODEV_CMD)m->command,
449 			m->data_len, m->data);
450 		break;
451 	}
452 	case CRAS_SERVER_SUSPEND:
453 		cras_system_set_suspended(1);
454 		break;
455 	case CRAS_SERVER_RESUME:
456 		cras_system_set_suspended(0);
457 		break;
458 	case CRAS_CONFIG_GLOBAL_REMIX: {
459 		const struct cras_config_global_remix *m =
460 			(const struct cras_config_global_remix *)msg;
461 		if (!MSG_LEN_VALID(msg, struct cras_config_global_remix) ||
462 		    m->num_channels > CRAS_MAX_REMIX_CHANNELS)
463 			return -EINVAL;
464 		size_t size_with_coefficients =
465 			sizeof(*m) + m->num_channels * m->num_channels *
466 					     sizeof(m->coefficient[0]);
467 		if (size_with_coefficients != msg->length)
468 			return -EINVAL;
469 		audio_thread_config_global_remix(
470 			cras_iodev_list_get_audio_thread(), m->num_channels,
471 			m->coefficient);
472 		break;
473 	}
474 	case CRAS_SERVER_GET_HOTWORD_MODELS: {
475 		if (!MSG_LEN_VALID(msg, struct cras_get_hotword_models))
476 			return -EINVAL;
477 		handle_get_hotword_models(
478 			client,
479 			((const struct cras_get_hotword_models *)msg)->node_id);
480 		break;
481 	}
482 	case CRAS_SERVER_SET_HOTWORD_MODEL: {
483 		const struct cras_set_hotword_model *m =
484 			(const struct cras_set_hotword_model *)msg;
485 		if (!MSG_LEN_VALID(msg, struct cras_set_hotword_model))
486 			return -EINVAL;
487 		cras_iodev_list_set_hotword_model(m->node_id, m->model_name);
488 		break;
489 	}
490 	case CRAS_SERVER_REGISTER_NOTIFICATION: {
491 		const struct cras_register_notification *m =
492 			(struct cras_register_notification *)msg;
493 		if (!MSG_LEN_VALID(msg, struct cras_register_notification))
494 			return -EINVAL;
495 		register_for_notification(
496 			client, (enum CRAS_CLIENT_MESSAGE_ID)m->msg_id,
497 			m->do_register);
498 		break;
499 	}
500 	case CRAS_SERVER_SET_AEC_DUMP: {
501 		const struct cras_set_aec_dump *m =
502 			(const struct cras_set_aec_dump *)msg;
503 		if (!MSG_LEN_VALID(msg, struct cras_set_aec_dump))
504 			return -EINVAL;
505 		audio_thread_set_aec_dump(cras_iodev_list_get_audio_thread(),
506 					  m->stream_id, m->start, fd);
507 		break;
508 	}
509 	case CRAS_SERVER_RELOAD_AEC_CONFIG:
510 		cras_apm_list_reload_aec_config();
511 		break;
512 	default:
513 		break;
514 	}
515 
516 	return 0;
517 }
518 
519 /* Declarations of cras_rclient operators for cras_control_rclient. */
520 static const struct cras_rclient_ops cras_control_rclient_ops = {
521 	.handle_message_from_client = ccr_handle_message_from_client,
522 	.send_message_to_client = rclient_send_message_to_client,
523 	.destroy = rclient_destroy,
524 };
525 
526 /*
527  * Exported Functions.
528  */
529 
530 /* Creates a client structure and sends a message back informing the client that
531  * the conneciton has succeeded. */
cras_control_rclient_create(int fd,size_t id)532 struct cras_rclient *cras_control_rclient_create(int fd, size_t id)
533 {
534 	struct cras_rclient *client;
535 	struct cras_client_connected msg;
536 	int state_fd;
537 
538 	client = (struct cras_rclient *)calloc(1, sizeof(struct cras_rclient));
539 	if (!client)
540 		return NULL;
541 
542 	client->fd = fd;
543 	client->id = id;
544 	client->ops = &cras_control_rclient_ops;
545 	client->supported_directions = CRAS_STREAM_ALL_DIRECTION;
546 	/* Filters CRAS_STREAM_UNDEFINED stream out. */
547 	client->supported_directions ^=
548 		cras_stream_direction_mask(CRAS_STREAM_UNDEFINED);
549 
550 	cras_fill_client_connected(&msg, client->id);
551 	state_fd = cras_sys_state_shm_fd();
552 	client->ops->send_message_to_client(client, &msg.header, &state_fd, 1);
553 
554 	return client;
555 }
556