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 #define _GNU_SOURCE /* for asprintf */
7 #include <getopt.h>
8 #include <signal.h>
9 #include <stdio.h>
10 #include <syslog.h>
11
12 #include "cras_apm_list.h"
13 #include "cras_config.h"
14 #include "cras_iodev_list.h"
15 #include "cras_server.h"
16 #include "cras_shm.h"
17 #include "cras_system_state.h"
18 #include "cras_dsp.h"
19
20 static struct option long_options[] = {
21 {"dsp_config", required_argument, 0, 'd'},
22 {"syslog_mask", required_argument, 0, 'l'},
23 {"device_config_dir", required_argument, 0, 'c'},
24 {"disable_profile", required_argument, 0, 'D'},
25 {"internal_ucm_suffix", required_argument, 0, 'u'},
26 {0, 0, 0, 0}
27 };
28
29 /* Ignores sigpipe, we'll notice when a read/write fails. */
set_signals()30 static void set_signals()
31 {
32 signal(SIGPIPE, SIG_IGN);
33 signal(SIGCHLD, SIG_IGN);
34 }
35
36 /* Entry point for the server. */
main(int argc,char ** argv)37 int main(int argc, char **argv)
38 {
39 int c, option_index;
40 int log_mask = LOG_ERR;
41 const char default_dsp_config[] = CRAS_CONFIG_FILE_DIR "/dsp.ini";
42 const char *dsp_config = default_dsp_config;
43 const char *device_config_dir = CRAS_CONFIG_FILE_DIR;
44 const char *internal_ucm_suffix = NULL;
45 unsigned int profile_disable_mask = 0;
46
47 set_signals();
48
49 while (1) {
50 c = getopt_long(argc, argv, "", long_options, &option_index);
51 if (c == -1)
52 break;
53
54 switch (c) {
55 /* To keep this code simple we ask the (technical)
56 user to pass one of integer values defined in
57 syslog.h - this is a development feature after
58 all. While there is no formal standard for the
59 integer values there is an informal standard:
60 http://tools.ietf.org/html/rfc5424#page-11 */
61 case 'l':
62 log_mask = atoi(optarg);
63 break;
64
65 case 'c':
66 device_config_dir = optarg;
67 break;
68
69 case 'd':
70 dsp_config = optarg;
71 break;
72 /* --disable_profile option takes list of profile names separated by ',' */
73 case 'D':
74 while ((optarg != NULL) && (*optarg != 0)) {
75 if (strncmp(optarg, "hfp", 3) == 0) {
76 profile_disable_mask |= CRAS_SERVER_PROFILE_MASK_HFP;
77 }
78 if (strncmp(optarg, "hsp", 3) == 0) {
79 profile_disable_mask |= CRAS_SERVER_PROFILE_MASK_HSP;
80 }
81 if (strncmp(optarg, "a2dp", 4) == 0) {
82 profile_disable_mask |= CRAS_SERVER_PROFILE_MASK_A2DP;
83 }
84 optarg = strchr(optarg, ',');
85 if (optarg != NULL) {
86 optarg++;
87 }
88 }
89 break;
90 case 'u':
91 if (*optarg != 0)
92 internal_ucm_suffix = optarg;
93 break;
94 default:
95 break;
96 }
97 }
98
99 switch (log_mask) {
100 case LOG_EMERG: case LOG_ALERT: case LOG_CRIT: case LOG_ERR:
101 case LOG_WARNING: case LOG_NOTICE: case LOG_INFO:
102 case LOG_DEBUG:
103 break;
104 default:
105 fprintf(stderr,
106 "Unsupported syslog priority value: %d; using LOG_ERR=%d\n",
107 log_mask, LOG_ERR);
108 log_mask = LOG_ERR;
109 break;
110 }
111 setlogmask(LOG_UPTO(log_mask));
112
113 /* Initialize system. */
114 cras_server_init();
115 char *shm_name;
116 if (asprintf(&shm_name, "/cras-%d", getpid()) < 0)
117 exit(-1);
118 int rw_shm_fd;
119 int ro_shm_fd;
120 struct cras_server_state *exp_state = (struct cras_server_state *)
121 cras_shm_setup(shm_name,
122 sizeof(*exp_state),
123 &rw_shm_fd,
124 &ro_shm_fd);
125 if (!exp_state)
126 exit(-1);
127 cras_system_state_init(device_config_dir,
128 shm_name,
129 rw_shm_fd,
130 ro_shm_fd,
131 exp_state,
132 sizeof(*exp_state));
133 free(shm_name);
134 if (internal_ucm_suffix)
135 cras_system_state_set_internal_ucm_suffix(internal_ucm_suffix);
136 cras_dsp_init(dsp_config);
137 cras_apm_list_init(device_config_dir);
138 cras_iodev_list_init();
139
140 /* Start the server. */
141 return cras_server_run(profile_disable_mask);
142 }
143