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