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 14 static void ucm_section_free(struct ucm_section *section) { 15 if (section->name) 16 free((void *)section->name); 17 if (section->jack_name) 18 free((void *)section->jack_name); 19 if (section->jack_type) 20 free((void *)section->jack_type); 21 if (section->mixer_name) 22 free((void *)section->mixer_name); 23 mixer_name_free(section->coupled); 24 free(section); 25 } 26 27 void ucm_section_free_list(struct ucm_section *sections) 28 { 29 struct ucm_section *section; 30 DL_FOREACH(sections, section) { 31 DL_DELETE(sections, section); 32 ucm_section_free(section); 33 } 34 } 35 36 struct ucm_section *ucm_section_create(const char *name, 37 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 *) 49 calloc(1, sizeof(struct ucm_section)); 50 if (!section) 51 return NULL; 52 53 section->dev_idx = dev_idx; 54 section->dir = dir; 55 section->name = strdup(name); 56 if (!section->name) 57 goto error; 58 59 if (jack_name) { 60 section->jack_name = strdup(jack_name); 61 if (!section->jack_name) 62 goto error; 63 } 64 if (jack_type) { 65 section->jack_type = strdup(jack_type); 66 if (!section->jack_type) 67 goto error; 68 } 69 /* Default to -1 which means auto-detect. */ 70 section->jack_switch = -1; 71 72 /* Make sure to initialize this item as a list. */ 73 DL_APPEND(section_list, section); 74 return section_list; 75 76 error: 77 ucm_section_free(section); 78 return NULL; 79 } 80 81 int ucm_section_set_mixer_name(struct ucm_section *section, 82 const char *name) 83 { 84 if (!section || !name) 85 return -EINVAL; 86 87 if (section->mixer_name) 88 free((void *)section->mixer_name); 89 section->mixer_name = strdup(name); 90 if (!section->mixer_name) 91 return -ENOMEM; 92 return 0; 93 } 94 95 int ucm_section_add_coupled(struct ucm_section *section, 96 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 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 120 void ucm_section_dump(struct ucm_section *section) 121 { 122 syslog(LOG_DEBUG, "section: %s [%d] (%s)", 123 section->name, section->dev_idx, 124 section->dir == CRAS_STREAM_OUTPUT ? "output" : "input"); 125 syslog(LOG_DEBUG, " jack: %s %s", 126 section->jack_name, section->jack_type); 127 syslog(LOG_DEBUG, " mixer_name: %s", section->mixer_name); 128 mixer_name_dump(section->coupled, " coupled"); 129 } 130