/* Copyright (c) 2012 The Chromium OS Authors. All rights reserved. * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ #define _GNU_SOURCE /* for asprintf */ #include #include #include #include #include "cras_alsa_plugin_io.h" #include "cras_apm_list.h" #include "cras_config.h" #include "cras_iodev_list.h" #include "cras_server.h" #include "cras_shm.h" #include "cras_system_state.h" #include "cras_dsp.h" static struct option long_options[] = { { "dsp_config", required_argument, 0, 'd' }, { "syslog_mask", required_argument, 0, 'l' }, { "device_config_dir", required_argument, 0, 'c' }, { "disable_profile", required_argument, 0, 'D' }, { "internal_ucm_suffix", required_argument, 0, 'u' }, { 0, 0, 0, 0 } }; /* Ignores sigpipe, we'll notice when a read/write fails. */ static void set_signals() { signal(SIGPIPE, SIG_IGN); signal(SIGCHLD, SIG_IGN); } /* Entry point for the server. */ int main(int argc, char **argv) { int c, option_index; int log_mask = LOG_WARNING; const char default_dsp_config[] = CRAS_CONFIG_FILE_DIR "/dsp.ini"; const char *dsp_config = default_dsp_config; const char *device_config_dir = CRAS_CONFIG_FILE_DIR; const char *internal_ucm_suffix = NULL; unsigned int profile_disable_mask = 0; set_signals(); while (1) { c = getopt_long(argc, argv, "", long_options, &option_index); if (c == -1) break; switch (c) { /* To keep this code simple we ask the (technical) user to pass one of integer values defined in syslog.h - this is a development feature after all. While there is no formal standard for the integer values there is an informal standard: http://tools.ietf.org/html/rfc5424#page-11 */ case 'l': log_mask = atoi(optarg); break; case 'c': device_config_dir = optarg; break; case 'd': dsp_config = optarg; break; /* --disable_profile option takes list of profile names separated by ',' */ case 'D': while ((optarg != NULL) && (*optarg != 0)) { if (strncmp(optarg, "hfp", 3) == 0) { profile_disable_mask |= CRAS_SERVER_PROFILE_MASK_HFP; } if (strncmp(optarg, "hsp", 3) == 0) { profile_disable_mask |= CRAS_SERVER_PROFILE_MASK_HSP; } if (strncmp(optarg, "a2dp", 4) == 0) { profile_disable_mask |= CRAS_SERVER_PROFILE_MASK_A2DP; } optarg = strchr(optarg, ','); if (optarg != NULL) { optarg++; } } break; case 'u': if (*optarg != 0) internal_ucm_suffix = optarg; break; default: break; } } switch (log_mask) { case LOG_EMERG: case LOG_ALERT: case LOG_CRIT: case LOG_ERR: case LOG_WARNING: case LOG_NOTICE: case LOG_INFO: case LOG_DEBUG: break; default: fprintf(stderr, "Unsupported syslog priority value: %d; using LOG_ERR=%d\n", log_mask, LOG_ERR); log_mask = LOG_ERR; break; } setlogmask(LOG_UPTO(log_mask)); /* Initialize system. */ cras_server_init(); char *shm_name; if (asprintf(&shm_name, "/cras-%d", getpid()) < 0) exit(-1); int rw_shm_fd; int ro_shm_fd; struct cras_server_state *exp_state = (struct cras_server_state *)cras_shm_setup( shm_name, sizeof(*exp_state), &rw_shm_fd, &ro_shm_fd); if (!exp_state) exit(-1); cras_system_state_init(device_config_dir, shm_name, rw_shm_fd, ro_shm_fd, exp_state, sizeof(*exp_state)); free(shm_name); if (internal_ucm_suffix) cras_system_state_set_internal_ucm_suffix(internal_ucm_suffix); cras_dsp_init(dsp_config); cras_apm_list_init(device_config_dir); cras_iodev_list_init(); cras_alsa_plugin_io_init(device_config_dir); /* Start the server. */ return cras_server_run(profile_disable_mask); }