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 |=
77 CRAS_SERVER_PROFILE_MASK_HFP;
78 }
79 if (strncmp(optarg, "hsp", 3) == 0) {
80 profile_disable_mask |=
81 CRAS_SERVER_PROFILE_MASK_HSP;
82 }
83 if (strncmp(optarg, "a2dp", 4) == 0) {
84 profile_disable_mask |=
85 CRAS_SERVER_PROFILE_MASK_A2DP;
86 }
87 optarg = strchr(optarg, ',');
88 if (optarg != NULL) {
89 optarg++;
90 }
91 }
92 break;
93 case 'u':
94 if (*optarg != 0)
95 internal_ucm_suffix = optarg;
96 break;
97 default:
98 break;
99 }
100 }
101
102 switch (log_mask) {
103 case LOG_EMERG:
104 case LOG_ALERT:
105 case LOG_CRIT:
106 case LOG_ERR:
107 case LOG_WARNING:
108 case LOG_NOTICE:
109 case LOG_INFO:
110 case LOG_DEBUG:
111 break;
112 default:
113 fprintf(stderr,
114 "Unsupported syslog priority value: %d; using LOG_ERR=%d\n",
115 log_mask, LOG_ERR);
116 log_mask = LOG_ERR;
117 break;
118 }
119 setlogmask(LOG_UPTO(log_mask));
120
121 /* Initialize system. */
122 cras_server_init();
123 char *shm_name;
124 if (asprintf(&shm_name, "/cras-%d", getpid()) < 0)
125 exit(-1);
126 int rw_shm_fd;
127 int ro_shm_fd;
128 struct cras_server_state *exp_state =
129 (struct cras_server_state *)cras_shm_setup(
130 shm_name, sizeof(*exp_state), &rw_shm_fd, &ro_shm_fd);
131 if (!exp_state)
132 exit(-1);
133 cras_system_state_init(device_config_dir, shm_name, rw_shm_fd,
134 ro_shm_fd, exp_state, sizeof(*exp_state));
135 free(shm_name);
136 if (internal_ucm_suffix)
137 cras_system_state_set_internal_ucm_suffix(internal_ucm_suffix);
138 cras_dsp_init(dsp_config);
139 cras_apm_list_init(device_config_dir);
140 cras_iodev_list_init();
141
142 /* Start the server. */
143 return cras_server_run(profile_disable_mask);
144 }
145