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