1 /* Copyright 2016 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 #include <stdlib.h>
7 #include <string.h>
8 #include <syslog.h>
9 
10 #include "cras_alsa_ucm_section.h"
11 #include "cras_alsa_mixer_name.h"
12 #include "utlist.h"
13 
ucm_section_free(struct ucm_section * section)14 static void ucm_section_free(struct ucm_section *section)
15 {
16 	free((void *)section->name);
17 	free((void *)section->pcm_name);
18 	free((void *)section->jack_name);
19 	free((void *)section->jack_type);
20 	free((void *)section->mixer_name);
21 	mixer_name_free(section->coupled);
22 	free(section);
23 }
24 
ucm_section_free_list(struct ucm_section * sections)25 void ucm_section_free_list(struct ucm_section *sections)
26 {
27 	struct ucm_section *section;
28 	DL_FOREACH (sections, section) {
29 		DL_DELETE(sections, section);
30 		ucm_section_free(section);
31 	}
32 }
33 
ucm_section_create(const char * name,const char * pcm_name,int dev_idx,int dependent_dev_idx,enum CRAS_STREAM_DIRECTION dir,const char * jack_name,const char * jack_type)34 struct ucm_section *ucm_section_create(const char *name, const char *pcm_name,
35 				       int dev_idx, int dependent_dev_idx,
36 				       enum CRAS_STREAM_DIRECTION dir,
37 				       const char *jack_name,
38 				       const char *jack_type)
39 {
40 	struct ucm_section *section_list = NULL;
41 	struct ucm_section *section;
42 
43 	if (!name)
44 		return NULL;
45 
46 	section = (struct ucm_section *)calloc(1, sizeof(struct ucm_section));
47 	if (!section)
48 		return NULL;
49 
50 	section->dev_idx = dev_idx;
51 	section->dependent_dev_idx = dependent_dev_idx;
52 	section->dir = dir;
53 	section->name = strdup(name);
54 	if (!section->name)
55 		goto error;
56 
57 	section->pcm_name = strdup(pcm_name);
58 	if (!section->pcm_name)
59 		goto error;
60 
61 	if (jack_name) {
62 		section->jack_name = strdup(jack_name);
63 		if (!section->jack_name)
64 			goto error;
65 	}
66 	if (jack_type) {
67 		section->jack_type = strdup(jack_type);
68 		if (!section->jack_type)
69 			goto error;
70 	}
71 	/* Default to -1 which means auto-detect. */
72 	section->jack_switch = -1;
73 
74 	/* Make sure to initialize this item as a list. */
75 	DL_APPEND(section_list, section);
76 	return section_list;
77 
78 error:
79 	ucm_section_free(section);
80 	return NULL;
81 }
82 
ucm_section_set_mixer_name(struct ucm_section * section,const char * name)83 int ucm_section_set_mixer_name(struct ucm_section *section, const char *name)
84 {
85 	if (!section || !name)
86 		return -EINVAL;
87 
88 	if (section->mixer_name)
89 		free((void *)section->mixer_name);
90 	section->mixer_name = strdup(name);
91 	if (!section->mixer_name)
92 		return -ENOMEM;
93 	return 0;
94 }
95 
ucm_section_add_coupled(struct ucm_section * section,const char * name,mixer_name_type type)96 int ucm_section_add_coupled(struct ucm_section *section, const char *name,
97 			    mixer_name_type type)
98 {
99 	struct mixer_name *m_name;
100 
101 	if (!section || !name || type == MIXER_NAME_UNDEFINED)
102 		return -EINVAL;
103 
104 	m_name = mixer_name_add(NULL, name, section->dir, type);
105 	if (!m_name)
106 		return -ENOMEM;
107 	DL_APPEND(section->coupled, m_name);
108 	return 0;
109 }
110 
ucm_section_concat_coupled(struct ucm_section * section,struct mixer_name * coupled)111 int ucm_section_concat_coupled(struct ucm_section *section,
112 			       struct mixer_name *coupled)
113 {
114 	if (!section || !coupled)
115 		return -EINVAL;
116 	DL_CONCAT(section->coupled, coupled);
117 	return 0;
118 }
119 
ucm_section_dump(struct ucm_section * section)120 void ucm_section_dump(struct ucm_section *section)
121 {
122 	syslog(LOG_DEBUG, "section: %s [%d] (%s)", section->name,
123 	       section->dev_idx,
124 	       section->dir == CRAS_STREAM_OUTPUT ? "output" : "input");
125 	syslog(LOG_DEBUG, "  jack: %s %s", section->jack_name,
126 	       section->jack_type);
127 	syslog(LOG_DEBUG, "  mixer_name: %s", section->mixer_name);
128 	mixer_name_dump(section->coupled, "  coupled");
129 }
130