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 <fcntl.h> 7 #include <pthread.h> 8 #include <string.h> 9 #include <stdlib.h> 10 #include <sys/mman.h> 11 #include <sys/param.h> 12 #include <sys/stat.h> 13 #include <syslog.h> 14 15 #include "cras_alsa_card.h" 16 #include "cras_board_config.h" 17 #include "cras_config.h" 18 #include "cras_device_blacklist.h" 19 #include "cras_observer.h" 20 #include "cras_shm.h" 21 #include "cras_system_state.h" 22 #include "cras_tm.h" 23 #include "cras_types.h" 24 #include "cras_util.h" 25 #include "utlist.h" 26 27 struct card_list { 28 struct cras_alsa_card *card; 29 struct card_list *prev, *next; 30 }; 31 32 /* The system state. 33 * Members: 34 * exp_state - The exported system state shared with clients. 35 * shm_name - Name of posix shm region for exported state. 36 * shm_fd - fd for shm area of system_state struct. 37 * shm_fd_ro - fd for shm area of system_state struct, opened read-only. 38 * This copy is to dup and pass to clients. 39 * shm_size - Size of the shm area. 40 * device_config_dir - Directory of device configs where volume curves live. 41 * internal_ucm_suffix - The suffix to append to internal card name to 42 * control which ucm config file to load. 43 * device_blacklist - Blacklist of device the server will ignore. 44 * cards - A list of active sound cards in the system. 45 * update_lock - Protects the update_count, as audio threads can update the 46 * stream count. 47 * tm - The system-wide timer manager. 48 * add_task - Function to handle adding a task for main thread to execute. 49 * task_data - Data to be passed to add_task handler function. 50 */ 51 static struct { 52 struct cras_server_state *exp_state; 53 char shm_name[NAME_MAX]; 54 int shm_fd; 55 int shm_fd_ro; 56 size_t shm_size; 57 const char *device_config_dir; 58 const char *internal_ucm_suffix; 59 struct cras_device_blacklist *device_blacklist; 60 struct card_list *cards; 61 pthread_mutex_t update_lock; 62 struct cras_tm *tm; 63 /* Select loop callback registration. */ 64 int (*fd_add)(int fd, void (*cb)(void *data), 65 void *cb_data, void *select_data); 66 void (*fd_rm)(int fd, void *select_data); 67 void *select_data; 68 int (*add_task)(void (*callback)(void *data), 69 void *callback_data, 70 void *task_data); 71 void *task_data; 72 struct cras_audio_thread_snapshot_buffer snapshot_buffer; 73 } state; 74 75 /* 76 * Exported Interface. 77 */ 78 79 void cras_system_state_init(const char *device_config_dir, 80 const char *shm_name, 81 int rw_shm_fd, 82 int ro_shm_fd, 83 struct cras_server_state *exp_state, 84 size_t exp_state_size) 85 { 86 struct cras_board_config board_config; 87 int rc; 88 89 assert(sizeof(*exp_state) == exp_state_size); 90 state.shm_size = sizeof(*exp_state); 91 92 strncpy(state.shm_name, shm_name, sizeof(state.shm_name)); 93 state.shm_name[sizeof(state.shm_name) - 1] = '\0'; 94 state.shm_fd = rw_shm_fd; 95 state.shm_fd_ro = ro_shm_fd; 96 97 /* Read board config. */ 98 memset(&board_config, 0, sizeof(board_config)); 99 cras_board_config_get(device_config_dir, &board_config); 100 101 /* Initial system state. */ 102 exp_state->state_version = CRAS_SERVER_STATE_VERSION; 103 exp_state->volume = CRAS_MAX_SYSTEM_VOLUME; 104 exp_state->mute = 0; 105 exp_state->mute_locked = 0; 106 exp_state->suspended = 0; 107 exp_state->capture_gain = DEFAULT_CAPTURE_GAIN; 108 exp_state->capture_gain_target = DEFAULT_CAPTURE_GAIN; 109 exp_state->capture_mute = 0; 110 exp_state->capture_mute_locked = 0; 111 exp_state->min_volume_dBFS = DEFAULT_MIN_VOLUME_DBFS; 112 exp_state->max_volume_dBFS = DEFAULT_MAX_VOLUME_DBFS; 113 exp_state->min_capture_gain = DEFAULT_MIN_CAPTURE_GAIN; 114 exp_state->max_capture_gain = DEFAULT_MAX_CAPTURE_GAIN; 115 exp_state->num_streams_attached = 0; 116 exp_state->default_output_buffer_size = 117 board_config.default_output_buffer_size; 118 exp_state->aec_supported = 119 board_config.aec_supported; 120 121 if ((rc = pthread_mutex_init(&state.update_lock, 0) != 0)) { 122 syslog(LOG_ERR, "Fatal: system state mutex init"); 123 exit(rc); 124 } 125 126 state.exp_state = exp_state; 127 128 /* Directory for volume curve configs. 129 * Note that device_config_dir does not affect device blacklist. 130 * Device blacklist is common to all boards so we do not need 131 * to change device blacklist at run time. */ 132 state.device_config_dir = device_config_dir; 133 state.internal_ucm_suffix = NULL; 134 135 state.tm = cras_tm_init(); 136 if (!state.tm) { 137 syslog(LOG_ERR, "Fatal: system state timer init"); 138 exit(-ENOMEM); 139 } 140 141 /* Read config file for blacklisted devices. */ 142 state.device_blacklist = 143 cras_device_blacklist_create(CRAS_CONFIG_FILE_DIR); 144 145 /* Initialize snapshot buffer memory */ 146 memset(&state.snapshot_buffer, 0, 147 sizeof(struct cras_audio_thread_snapshot_buffer)); 148 } 149 150 void cras_system_state_set_internal_ucm_suffix(const char *internal_ucm_suffix) 151 { 152 state.internal_ucm_suffix = internal_ucm_suffix; 153 } 154 155 void cras_system_state_deinit() 156 { 157 /* Free any resources used. This prevents unit tests from leaking. */ 158 159 cras_device_blacklist_destroy(state.device_blacklist); 160 161 cras_tm_deinit(state.tm); 162 163 if (state.exp_state) { 164 munmap(state.exp_state, state.shm_size); 165 cras_shm_close_unlink(state.shm_name, state.shm_fd); 166 if (state.shm_fd_ro != state.shm_fd) 167 close(state.shm_fd_ro); 168 } 169 170 pthread_mutex_destroy(&state.update_lock); 171 } 172 173 void cras_system_set_volume(size_t volume) 174 { 175 if (volume > CRAS_MAX_SYSTEM_VOLUME) 176 syslog(LOG_DEBUG, "system volume set out of range %zu", volume); 177 178 state.exp_state->volume = MIN(volume, CRAS_MAX_SYSTEM_VOLUME); 179 cras_observer_notify_output_volume(state.exp_state->volume); 180 } 181 182 size_t cras_system_get_volume() 183 { 184 return state.exp_state->volume; 185 } 186 187 void cras_system_set_capture_gain(long gain) 188 { 189 /* Adjust targeted gain to be in supported range. */ 190 state.exp_state->capture_gain_target = gain; 191 gain = MAX(gain, state.exp_state->min_capture_gain); 192 gain = MIN(gain, state.exp_state->max_capture_gain); 193 state.exp_state->capture_gain = gain; 194 cras_observer_notify_capture_gain(state.exp_state->capture_gain); 195 } 196 197 long cras_system_get_capture_gain() 198 { 199 return state.exp_state->capture_gain; 200 } 201 202 void cras_system_notify_mute(void) 203 { 204 cras_observer_notify_output_mute(state.exp_state->mute, 205 state.exp_state->user_mute, 206 state.exp_state->mute_locked); 207 } 208 209 void cras_system_set_user_mute(int mute) 210 { 211 int current_mute = cras_system_get_mute(); 212 213 if (state.exp_state->user_mute == !!mute) 214 return; 215 216 state.exp_state->user_mute = !!mute; 217 218 if (current_mute == (mute || state.exp_state->mute)) 219 return; 220 221 cras_system_notify_mute(); 222 } 223 224 void cras_system_set_mute(int mute) 225 { 226 int current_mute = cras_system_get_mute(); 227 228 if (state.exp_state->mute_locked) 229 return; 230 231 if (state.exp_state->mute == !!mute) 232 return; 233 234 state.exp_state->mute = !!mute; 235 236 if (current_mute == (mute || state.exp_state->user_mute)) 237 return; 238 239 cras_system_notify_mute(); 240 } 241 242 void cras_system_set_mute_locked(int locked) 243 { 244 if (state.exp_state->mute_locked == !!locked) 245 return; 246 247 state.exp_state->mute_locked = !!locked; 248 } 249 250 int cras_system_get_mute() 251 { 252 return state.exp_state->mute || state.exp_state->user_mute; 253 } 254 255 int cras_system_get_user_mute() 256 { 257 return state.exp_state->user_mute; 258 } 259 260 int cras_system_get_system_mute() 261 { 262 return state.exp_state->mute; 263 } 264 265 int cras_system_get_mute_locked() 266 { 267 return state.exp_state->mute_locked; 268 } 269 270 void cras_system_notify_capture_mute(void) 271 { 272 cras_observer_notify_capture_mute(state.exp_state->capture_mute, 273 state.exp_state->capture_mute_locked); 274 } 275 276 void cras_system_set_capture_mute(int mute) 277 { 278 if (state.exp_state->capture_mute_locked) 279 return; 280 281 state.exp_state->capture_mute = !!mute; 282 cras_system_notify_capture_mute(); 283 } 284 285 void cras_system_set_capture_mute_locked(int locked) 286 { 287 state.exp_state->capture_mute_locked = !!locked; 288 cras_system_notify_capture_mute(); 289 } 290 291 int cras_system_get_capture_mute() 292 { 293 return state.exp_state->capture_mute; 294 } 295 296 int cras_system_get_capture_mute_locked() 297 { 298 return state.exp_state->capture_mute_locked; 299 } 300 301 int cras_system_get_suspended() 302 { 303 return state.exp_state->suspended; 304 } 305 306 void cras_system_set_suspended(int suspended) 307 { 308 state.exp_state->suspended = suspended; 309 cras_observer_notify_suspend_changed(suspended); 310 } 311 312 void cras_system_set_volume_limits(long min, long max) 313 { 314 state.exp_state->min_volume_dBFS = min; 315 state.exp_state->max_volume_dBFS = max; 316 } 317 318 long cras_system_get_min_volume() 319 { 320 return state.exp_state->min_volume_dBFS; 321 } 322 323 long cras_system_get_max_volume() 324 { 325 return state.exp_state->max_volume_dBFS; 326 } 327 328 void cras_system_set_capture_gain_limits(long min, long max) 329 { 330 state.exp_state->min_capture_gain = MAX(min, DEFAULT_MIN_CAPTURE_GAIN); 331 state.exp_state->max_capture_gain = max; 332 /* Re-apply target gain subjected to the new supported range. */ 333 cras_system_set_capture_gain(state.exp_state->capture_gain_target); 334 } 335 336 long cras_system_get_min_capture_gain() 337 { 338 return state.exp_state->min_capture_gain; 339 } 340 341 long cras_system_get_max_capture_gain() 342 { 343 return state.exp_state->max_capture_gain; 344 } 345 346 int cras_system_get_default_output_buffer_size() 347 { 348 return state.exp_state->default_output_buffer_size; 349 } 350 351 int cras_system_get_aec_supported() 352 { 353 return state.exp_state->aec_supported; 354 } 355 356 int cras_system_add_alsa_card(struct cras_alsa_card_info *alsa_card_info) 357 { 358 struct card_list *card; 359 struct cras_alsa_card *alsa_card; 360 unsigned card_index; 361 362 if (alsa_card_info == NULL) 363 return -EINVAL; 364 365 card_index = alsa_card_info->card_index; 366 367 DL_FOREACH(state.cards, card) { 368 if (card_index == cras_alsa_card_get_index(card->card)) 369 return -EEXIST; 370 } 371 alsa_card = cras_alsa_card_create( 372 alsa_card_info, 373 state.device_config_dir, 374 state.device_blacklist, 375 (alsa_card_info->card_type == ALSA_CARD_TYPE_INTERNAL) 376 ? state.internal_ucm_suffix 377 : NULL); 378 if (alsa_card == NULL) 379 return -ENOMEM; 380 card = calloc(1, sizeof(*card)); 381 if (card == NULL) 382 return -ENOMEM; 383 card->card = alsa_card; 384 DL_APPEND(state.cards, card); 385 return 0; 386 } 387 388 int cras_system_remove_alsa_card(size_t alsa_card_index) 389 { 390 struct card_list *card; 391 392 DL_FOREACH(state.cards, card) { 393 if (alsa_card_index == cras_alsa_card_get_index(card->card)) 394 break; 395 } 396 if (card == NULL) 397 return -EINVAL; 398 DL_DELETE(state.cards, card); 399 cras_alsa_card_destroy(card->card); 400 free(card); 401 return 0; 402 } 403 404 int cras_system_alsa_card_exists(unsigned alsa_card_index) 405 { 406 struct card_list *card; 407 408 DL_FOREACH(state.cards, card) 409 if (alsa_card_index == cras_alsa_card_get_index(card->card)) 410 return 1; 411 return 0; 412 } 413 414 int cras_system_set_select_handler(int (*add)(int fd, 415 void (*callback)(void *data), 416 void *callback_data, 417 void *select_data), 418 void (*rm)(int fd, void *select_data), 419 void *select_data) 420 { 421 if (state.fd_add != NULL || state.fd_rm != NULL) 422 return -EEXIST; 423 state.fd_add = add; 424 state.fd_rm = rm; 425 state.select_data = select_data; 426 return 0; 427 } 428 429 int cras_system_add_select_fd(int fd, 430 void (*callback)(void *data), 431 void *callback_data) 432 { 433 if (state.fd_add == NULL) 434 return -EINVAL; 435 return state.fd_add(fd, callback, callback_data, 436 state.select_data); 437 } 438 439 int cras_system_set_add_task_handler(int (*add_task)(void (*cb)(void *data), 440 void *callback_data, 441 void *task_data), 442 void *task_data) 443 { 444 if (state.add_task != NULL) 445 return -EEXIST; 446 447 state.add_task = add_task; 448 state.task_data = task_data; 449 return 0; 450 } 451 452 int cras_system_add_task(void (*callback)(void *data), void *callback_data) 453 { 454 if (state.add_task == NULL) 455 return -EINVAL; 456 457 return state.add_task(callback, callback_data, state.task_data); 458 } 459 460 void cras_system_rm_select_fd(int fd) 461 { 462 if (state.fd_rm != NULL) 463 state.fd_rm(fd, state.select_data); 464 } 465 466 void cras_system_state_stream_added(enum CRAS_STREAM_DIRECTION direction) 467 { 468 struct cras_server_state *s; 469 470 s = cras_system_state_update_begin(); 471 if (!s) 472 return; 473 474 s->num_active_streams[direction]++; 475 s->num_streams_attached++; 476 477 cras_system_state_update_complete(); 478 cras_observer_notify_num_active_streams( 479 direction, s->num_active_streams[direction]); 480 } 481 482 void cras_system_state_stream_removed(enum CRAS_STREAM_DIRECTION direction) 483 { 484 struct cras_server_state *s; 485 unsigned i, sum; 486 487 488 s = cras_system_state_update_begin(); 489 if (!s) 490 return; 491 492 sum = 0; 493 for (i=0; i < CRAS_NUM_DIRECTIONS; i++) 494 sum += s->num_active_streams[i]; 495 496 /* Set the last active time when removing the final stream. */ 497 if (sum == 1) 498 cras_clock_gettime(CLOCK_MONOTONIC_RAW, 499 &s->last_active_stream_time); 500 s->num_active_streams[direction]--; 501 502 cras_system_state_update_complete(); 503 cras_observer_notify_num_active_streams( 504 direction, s->num_active_streams[direction]); 505 } 506 507 unsigned cras_system_state_get_active_streams() 508 { 509 unsigned i, sum; 510 sum = 0; 511 for (i=0; i < CRAS_NUM_DIRECTIONS; i++) 512 sum += state.exp_state->num_active_streams[i]; 513 return sum; 514 } 515 516 unsigned cras_system_state_get_active_streams_by_direction( 517 enum CRAS_STREAM_DIRECTION direction) 518 { 519 return state.exp_state->num_active_streams[direction]; 520 } 521 522 void cras_system_state_get_last_stream_active_time(struct cras_timespec *ts) 523 { 524 *ts = state.exp_state->last_active_stream_time; 525 } 526 527 int cras_system_state_get_output_devs(const struct cras_iodev_info **devs) 528 { 529 *devs = state.exp_state->output_devs; 530 return state.exp_state->num_output_devs; 531 } 532 533 int cras_system_state_get_input_devs(const struct cras_iodev_info **devs) 534 { 535 *devs = state.exp_state->input_devs; 536 return state.exp_state->num_input_devs; 537 } 538 539 int cras_system_state_get_output_nodes(const struct cras_ionode_info **nodes) 540 { 541 *nodes = state.exp_state->output_nodes; 542 return state.exp_state->num_output_nodes; 543 } 544 545 int cras_system_state_get_input_nodes(const struct cras_ionode_info **nodes) 546 { 547 *nodes = state.exp_state->input_nodes; 548 return state.exp_state->num_input_nodes; 549 } 550 551 void cras_system_state_set_non_empty_status(int non_empty) 552 { 553 state.exp_state->non_empty_status = non_empty; 554 } 555 556 int cras_system_state_get_non_empty_status() 557 { 558 return state.exp_state->non_empty_status; 559 } 560 561 struct cras_server_state *cras_system_state_update_begin() 562 { 563 if (pthread_mutex_lock(&state.update_lock)) { 564 syslog(LOG_ERR, "Failed to lock stream mutex"); 565 return NULL; 566 } 567 568 __sync_fetch_and_add(&state.exp_state->update_count, 1); 569 return state.exp_state; 570 } 571 572 void cras_system_state_update_complete() 573 { 574 __sync_fetch_and_add(&state.exp_state->update_count, 1); 575 pthread_mutex_unlock(&state.update_lock); 576 } 577 578 struct cras_server_state *cras_system_state_get_no_lock() 579 { 580 return state.exp_state; 581 } 582 583 key_t cras_sys_state_shm_fd() 584 { 585 return state.shm_fd_ro; 586 } 587 588 struct cras_tm *cras_system_state_get_tm() 589 { 590 return state.tm; 591 } 592 593 594 void cras_system_state_dump_snapshots() 595 { 596 memcpy(&state.exp_state->snapshot_buffer, &state.snapshot_buffer, 597 sizeof(struct cras_audio_thread_snapshot_buffer)); 598 } 599 600 void cras_system_state_add_snapshot( 601 struct cras_audio_thread_snapshot *snapshot) 602 { 603 state.snapshot_buffer.snapshots[state.snapshot_buffer.pos++] = 604 (*snapshot); 605 state.snapshot_buffer.pos %= 606 CRAS_MAX_AUDIO_THREAD_SNAPSHOTS; 607 } 608