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