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