blob: 8d23907a03c6b7753469d0b153eab14e359c3afd [file] [log] [blame]
/* 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 <getopt.h>
#include <signal.h>
#include <stdio.h>
#include <syslog.h>
#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);
}