• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 #ifndef _GNU_SOURCE
7 #define _GNU_SOURCE /* For asprintf */
8 #endif
9 
10 #include <alsa/asoundlib.h>
11 #include <syslog.h>
12 
13 #include "cras_alsa_card.h"
14 #include "cras_alsa_io.h"
15 #include "cras_alsa_mixer.h"
16 #include "cras_alsa_ucm.h"
17 #include "cras_device_blocklist.h"
18 #include "cras_card_config.h"
19 #include "cras_config.h"
20 #include "cras_iodev.h"
21 #include "cras_iodev_list.h"
22 #include "cras_system_state.h"
23 #include "cras_types.h"
24 #include "cras_util.h"
25 #include "utlist.h"
26 
27 #define MAX_ALSA_CARDS 32 /* Alsa limit on number of cards. */
28 #define MAX_ALSA_CARD_NAME_LENGTH 6 /* Alsa card name "hw:XX" + 1 for null. */
29 #define MAX_ALSA_PCM_NAME_LENGTH 9 /* Alsa pcm name "hw:XX,YY" + 1 for null. */
30 #define MAX_COUPLED_OUTPUT_SIZE 4
31 
32 struct iodev_list_node {
33 	struct cras_iodev *iodev;
34 	enum CRAS_STREAM_DIRECTION direction;
35 	struct iodev_list_node *prev, *next;
36 };
37 
38 /* Keeps an fd that is registered with system state.  A list of fds must be
39  * kept so that they can be removed when the card is destroyed. */
40 struct hctl_poll_fd {
41 	int fd;
42 	struct hctl_poll_fd *prev, *next;
43 };
44 
45 /* Holds information about each sound card on the system.
46  * name - of the form hw:XX.
47  * card_index - 0 based index, value of "XX" in the name.
48  * iodevs - Input and output devices for this card.
49  * mixer - Controls the mixer controls for this card.
50  * ucm - CRAS use case manager if available.
51  * hctl - ALSA high-level control interface.
52  * hctl_poll_fds - List of fds registered with cras_system_state.
53  * config - Config info for this card, can be NULL if none found.
54  */
55 struct cras_alsa_card {
56 	char name[MAX_ALSA_CARD_NAME_LENGTH];
57 	size_t card_index;
58 	struct iodev_list_node *iodevs;
59 	struct cras_alsa_mixer *mixer;
60 	struct cras_use_case_mgr *ucm;
61 	snd_hctl_t *hctl;
62 	struct hctl_poll_fd *hctl_poll_fds;
63 	struct cras_card_config *config;
64 };
65 
66 /* Creates an iodev for the given device.
67  * Args:
68  *    alsa_card - the alsa_card the device will be added to.
69  *    info - Information about the card type and priority.
70  *    card_name - The name of the card.
71  *    dev_name - The name of the device.
72  *    dev_id - The id string of the device.
73  *    device_index - 0 based index, value of "YY" in "hw:XX,YY".
74  *    direction - Input or output.
75  * Returns:
76  *    Pointer to the created iodev, or NULL on error.
77  *    other negative error code otherwise.
78  */
create_iodev_for_device(struct cras_alsa_card * alsa_card,struct cras_alsa_card_info * info,const char * card_name,const char * dev_name,const char * dev_id,unsigned device_index,enum CRAS_STREAM_DIRECTION direction)79 struct cras_iodev *create_iodev_for_device(
80 	struct cras_alsa_card *alsa_card, struct cras_alsa_card_info *info,
81 	const char *card_name, const char *dev_name, const char *dev_id,
82 	unsigned device_index, enum CRAS_STREAM_DIRECTION direction)
83 {
84 	struct iodev_list_node *new_dev;
85 	struct iodev_list_node *node;
86 	int first = 1;
87 	char pcm_name[MAX_ALSA_PCM_NAME_LENGTH];
88 
89 	/* Find whether this is the first device in this direction, and
90 	 * avoid duplicate device indexes. */
91 	DL_FOREACH (alsa_card->iodevs, node) {
92 		if (node->direction != direction)
93 			continue;
94 		first = 0;
95 		if (alsa_iodev_index(node->iodev) == device_index) {
96 			syslog(LOG_DEBUG,
97 			       "Skipping duplicate device for %s:%s:%s [%u]",
98 			       card_name, dev_name, dev_id, device_index);
99 			return node->iodev;
100 		}
101 	}
102 
103 	new_dev = calloc(1, sizeof(*new_dev));
104 	if (new_dev == NULL)
105 		return NULL;
106 
107 	/* Append device index to card namem, ex: 'hw:0', for the PCM name of
108 	 * target iodev. */
109 	snprintf(pcm_name, MAX_ALSA_PCM_NAME_LENGTH, "%s,%u", alsa_card->name,
110 		 device_index);
111 
112 	new_dev->direction = direction;
113 	new_dev->iodev =
114 		alsa_iodev_create(info->card_index, card_name, device_index,
115 				  pcm_name, dev_name, dev_id, info->card_type,
116 				  first, alsa_card->mixer, alsa_card->config,
117 				  alsa_card->ucm, alsa_card->hctl, direction,
118 				  info->usb_vendor_id, info->usb_product_id,
119 				  info->usb_serial_number);
120 	if (new_dev->iodev == NULL) {
121 		syslog(LOG_ERR, "Couldn't create alsa_iodev for %s", pcm_name);
122 		free(new_dev);
123 		return NULL;
124 	}
125 
126 	syslog(LOG_DEBUG, "New %s device %s",
127 	       direction == CRAS_STREAM_OUTPUT ? "playback" : "capture",
128 	       pcm_name);
129 
130 	DL_APPEND(alsa_card->iodevs, new_dev);
131 	return new_dev->iodev;
132 }
133 
134 /* Returns non-zero if this card has hctl jacks.
135  */
card_has_hctl_jack(struct cras_alsa_card * alsa_card)136 static int card_has_hctl_jack(struct cras_alsa_card *alsa_card)
137 {
138 	struct iodev_list_node *node;
139 
140 	/* Find the first device that has an hctl jack. */
141 	DL_FOREACH (alsa_card->iodevs, node) {
142 		if (alsa_iodev_has_hctl_jacks(node->iodev))
143 			return 1;
144 	}
145 	return 0;
146 }
147 
148 /* Check if a device should be ignored for this card. Returns non-zero if the
149  * device is in the blocklist and should be ignored.
150  */
should_ignore_dev(struct cras_alsa_card_info * info,struct cras_device_blocklist * blocklist,size_t device_index)151 static int should_ignore_dev(struct cras_alsa_card_info *info,
152 			     struct cras_device_blocklist *blocklist,
153 			     size_t device_index)
154 {
155 	if (info->card_type == ALSA_CARD_TYPE_USB)
156 		return cras_device_blocklist_check(
157 			blocklist, info->usb_vendor_id, info->usb_product_id,
158 			info->usb_desc_checksum, device_index);
159 	return 0;
160 }
161 
162 /* Filters an array of mixer control names. Keep a name if it is
163  * specified in the ucm config. */
filter_controls(struct cras_use_case_mgr * ucm,struct mixer_name * controls)164 static struct mixer_name *filter_controls(struct cras_use_case_mgr *ucm,
165 					  struct mixer_name *controls)
166 {
167 	struct mixer_name *control;
168 	DL_FOREACH (controls, control) {
169 		char *dev = ucm_get_dev_for_mixer(ucm, control->name,
170 						  CRAS_STREAM_OUTPUT);
171 		if (!dev)
172 			DL_DELETE(controls, control);
173 		else
174 			free(dev);
175 	}
176 	return controls;
177 }
178 
179 /* Handles notifications from alsa controls.  Called by main thread when a poll
180  * fd provided by alsa signals there is an event available. */
alsa_control_event_pending(void * arg,int revent)181 static void alsa_control_event_pending(void *arg, int revent)
182 {
183 	struct cras_alsa_card *card;
184 
185 	card = (struct cras_alsa_card *)arg;
186 	if (card == NULL) {
187 		syslog(LOG_ERR, "Invalid card from control event.");
188 		return;
189 	}
190 
191 	/* handle_events will trigger the callback registered with each control
192 	 * that has changed. */
193 	snd_hctl_handle_events(card->hctl);
194 }
195 
196 static int
add_controls_and_iodevs_by_matching(struct cras_alsa_card_info * info,struct cras_device_blocklist * blocklist,struct cras_alsa_card * alsa_card,const char * card_name,snd_ctl_t * handle)197 add_controls_and_iodevs_by_matching(struct cras_alsa_card_info *info,
198 				    struct cras_device_blocklist *blocklist,
199 				    struct cras_alsa_card *alsa_card,
200 				    const char *card_name, snd_ctl_t *handle)
201 {
202 	struct mixer_name *coupled_controls = NULL;
203 	int dev_idx;
204 	snd_pcm_info_t *dev_info;
205 	struct mixer_name *extra_controls = NULL;
206 	int rc = 0;
207 
208 	snd_pcm_info_alloca(&dev_info);
209 
210 	if (alsa_card->ucm) {
211 		char *extra_main_volume;
212 
213 		/* Filter the extra output mixer names */
214 		extra_controls = filter_controls(
215 			alsa_card->ucm,
216 			mixer_name_add(extra_controls, "IEC958",
217 				       CRAS_STREAM_OUTPUT, MIXER_NAME_VOLUME));
218 
219 		/* Get the extra main volume control. */
220 		extra_main_volume =
221 			ucm_get_flag(alsa_card->ucm, "ExtraMainVolume");
222 		if (extra_main_volume) {
223 			extra_controls = mixer_name_add(extra_controls,
224 							extra_main_volume,
225 							CRAS_STREAM_OUTPUT,
226 							MIXER_NAME_MAIN_VOLUME);
227 			free(extra_main_volume);
228 		}
229 		mixer_name_dump(extra_controls, "extra controls");
230 
231 		/* Check if coupled controls has been specified for speaker. */
232 		coupled_controls =
233 			ucm_get_coupled_mixer_names(alsa_card->ucm, "Speaker");
234 		mixer_name_dump(coupled_controls, "coupled controls");
235 	}
236 
237 	/* Add controls to mixer by name matching. */
238 	rc = cras_alsa_mixer_add_controls_by_name_matching(
239 		alsa_card->mixer, extra_controls, coupled_controls);
240 	if (rc) {
241 		syslog(LOG_ERR, "Fail adding controls to mixer for %s.",
242 		       alsa_card->name);
243 		goto error;
244 	}
245 
246 	/* Go through every device. */
247 	dev_idx = -1;
248 	while (1) {
249 		rc = snd_ctl_pcm_next_device(handle, &dev_idx);
250 		if (rc < 0)
251 			goto error;
252 		if (dev_idx < 0)
253 			break;
254 
255 		snd_pcm_info_set_device(dev_info, dev_idx);
256 		snd_pcm_info_set_subdevice(dev_info, 0);
257 
258 		/* Check for playback devices. */
259 		snd_pcm_info_set_stream(dev_info, SND_PCM_STREAM_PLAYBACK);
260 		if (snd_ctl_pcm_info(handle, dev_info) == 0 &&
261 		    !should_ignore_dev(info, blocklist, dev_idx)) {
262 			struct cras_iodev *iodev = create_iodev_for_device(
263 				alsa_card, info, card_name,
264 				snd_pcm_info_get_name(dev_info),
265 				snd_pcm_info_get_id(dev_info), dev_idx,
266 				CRAS_STREAM_OUTPUT);
267 			if (iodev) {
268 				rc = alsa_iodev_legacy_complete_init(iodev);
269 				if (rc < 0)
270 					goto error;
271 			}
272 		}
273 
274 		/* Check for capture devices. */
275 		snd_pcm_info_set_stream(dev_info, SND_PCM_STREAM_CAPTURE);
276 		if (snd_ctl_pcm_info(handle, dev_info) == 0) {
277 			struct cras_iodev *iodev = create_iodev_for_device(
278 				alsa_card, info, card_name,
279 				snd_pcm_info_get_name(dev_info),
280 				snd_pcm_info_get_id(dev_info), dev_idx,
281 				CRAS_STREAM_INPUT);
282 			if (iodev) {
283 				rc = alsa_iodev_legacy_complete_init(iodev);
284 				if (rc < 0)
285 					goto error;
286 			}
287 		}
288 	}
289 error:
290 	mixer_name_free(coupled_controls);
291 	mixer_name_free(extra_controls);
292 	return rc;
293 }
294 
add_controls_and_iodevs_with_ucm(struct cras_alsa_card_info * info,struct cras_alsa_card * alsa_card,const char * card_name,snd_ctl_t * handle)295 static int add_controls_and_iodevs_with_ucm(struct cras_alsa_card_info *info,
296 					    struct cras_alsa_card *alsa_card,
297 					    const char *card_name,
298 					    snd_ctl_t *handle)
299 {
300 	snd_pcm_info_t *dev_info;
301 	struct mixer_name *main_volume_control_names;
302 	struct iodev_list_node *node;
303 	int rc = 0;
304 	struct ucm_section *section;
305 	struct ucm_section *ucm_sections;
306 
307 	snd_pcm_info_alloca(&dev_info);
308 
309 	main_volume_control_names = ucm_get_main_volume_names(alsa_card->ucm);
310 	if (main_volume_control_names) {
311 		rc = cras_alsa_mixer_add_main_volume_control_by_name(
312 			alsa_card->mixer, main_volume_control_names);
313 		if (rc) {
314 			syslog(LOG_ERR,
315 			       "Failed adding main volume controls to"
316 			       " mixer for '%s'.'",
317 			       card_name);
318 			goto cleanup_names;
319 		}
320 	}
321 
322 	/* Get info on the devices specified in the UCM config. */
323 	ucm_sections = ucm_get_sections(alsa_card->ucm);
324 	if (!ucm_sections) {
325 		syslog(LOG_ERR,
326 		       "Could not retrieve any UCM SectionDevice"
327 		       " info for '%s'.",
328 		       card_name);
329 		rc = -ENOENT;
330 		goto cleanup_names;
331 	}
332 
333 	/* Create all of the controls first. */
334 	DL_FOREACH (ucm_sections, section) {
335 		rc = cras_alsa_mixer_add_controls_in_section(alsa_card->mixer,
336 							     section);
337 		if (rc) {
338 			syslog(LOG_ERR,
339 			       "Failed adding controls to"
340 			       " mixer for '%s:%s'",
341 			       card_name, section->name);
342 			goto cleanup;
343 		}
344 	}
345 
346 	/* Create all of the devices. */
347 	DL_FOREACH (ucm_sections, section) {
348 		/* If a UCM section specifies certain device as dependency
349 		 * then don't create an alsa iodev for it, just append it
350 		 * as node later. */
351 		if (section->dependent_dev_idx != -1)
352 			continue;
353 		snd_pcm_info_set_device(dev_info, section->dev_idx);
354 		snd_pcm_info_set_subdevice(dev_info, 0);
355 		if (section->dir == CRAS_STREAM_OUTPUT)
356 			snd_pcm_info_set_stream(dev_info,
357 						SND_PCM_STREAM_PLAYBACK);
358 		else if (section->dir == CRAS_STREAM_INPUT)
359 			snd_pcm_info_set_stream(dev_info,
360 						SND_PCM_STREAM_CAPTURE);
361 		else {
362 			syslog(LOG_ERR, "Unexpected direction: %d",
363 			       section->dir);
364 			rc = -EINVAL;
365 			goto cleanup;
366 		}
367 
368 		if (snd_ctl_pcm_info(handle, dev_info)) {
369 			syslog(LOG_ERR, "Could not get info for device: %s",
370 			       section->name);
371 			continue;
372 		}
373 
374 		create_iodev_for_device(alsa_card, info, card_name,
375 					snd_pcm_info_get_name(dev_info),
376 					snd_pcm_info_get_id(dev_info),
377 					section->dev_idx, section->dir);
378 	}
379 
380 	/* Setup jacks and controls for the devices. If a SectionDevice is
381 	 * dependent on another SectionDevice, it'll be added as a node to
382 	 * a existing ALSA iodev. */
383 	DL_FOREACH (ucm_sections, section) {
384 		DL_FOREACH (alsa_card->iodevs, node) {
385 			if (node->direction != section->dir)
386 				continue;
387 			if (alsa_iodev_index(node->iodev) == section->dev_idx)
388 				break;
389 			if (alsa_iodev_index(node->iodev) ==
390 			    section->dependent_dev_idx)
391 				break;
392 		}
393 		if (node) {
394 			rc = alsa_iodev_ucm_add_nodes_and_jacks(node->iodev,
395 								section);
396 			if (rc < 0)
397 				goto cleanup;
398 		}
399 	}
400 
401 	DL_FOREACH (alsa_card->iodevs, node) {
402 		alsa_iodev_ucm_complete_init(node->iodev);
403 	}
404 
405 cleanup:
406 	ucm_section_free_list(ucm_sections);
407 cleanup_names:
408 	mixer_name_free(main_volume_control_names);
409 	return rc;
410 }
411 
configure_echo_reference_dev(struct cras_alsa_card * alsa_card)412 static void configure_echo_reference_dev(struct cras_alsa_card *alsa_card)
413 {
414 	struct iodev_list_node *dev_node, *echo_ref_node;
415 	const char *echo_ref_name;
416 
417 	if (!alsa_card->ucm)
418 		return;
419 
420 	DL_FOREACH (alsa_card->iodevs, dev_node) {
421 		if (!dev_node->iodev->nodes)
422 			continue;
423 
424 		echo_ref_name = ucm_get_echo_reference_dev_name_for_dev(
425 			alsa_card->ucm, dev_node->iodev->nodes->name);
426 		if (!echo_ref_name)
427 			continue;
428 		DL_FOREACH (alsa_card->iodevs, echo_ref_node) {
429 			if (echo_ref_node->iodev->nodes == NULL)
430 				continue;
431 			if (!strcmp(echo_ref_name,
432 				    echo_ref_node->iodev->nodes->name))
433 				break;
434 		}
435 		if (echo_ref_node)
436 			dev_node->iodev->echo_reference_dev =
437 				echo_ref_node->iodev;
438 		else
439 			syslog(LOG_ERR,
440 			       "Echo ref dev %s doesn't exist on card %s",
441 			       echo_ref_name, alsa_card->name);
442 		free((void *)echo_ref_name);
443 	}
444 }
445 
446 /*
447  * Exported Interface.
448  */
449 
cras_alsa_card_create(struct cras_alsa_card_info * info,const char * device_config_dir,struct cras_device_blocklist * blocklist,const char * ucm_suffix)450 struct cras_alsa_card *cras_alsa_card_create(
451 	struct cras_alsa_card_info *info, const char *device_config_dir,
452 	struct cras_device_blocklist *blocklist, const char *ucm_suffix)
453 {
454 	snd_ctl_t *handle = NULL;
455 	int rc, n;
456 	snd_ctl_card_info_t *card_info;
457 	const char *card_name;
458 	struct cras_alsa_card *alsa_card;
459 
460 	if (info->card_index >= MAX_ALSA_CARDS) {
461 		syslog(LOG_ERR, "Invalid alsa card index %u", info->card_index);
462 		return NULL;
463 	}
464 
465 	snd_ctl_card_info_alloca(&card_info);
466 
467 	alsa_card = calloc(1, sizeof(*alsa_card));
468 	if (alsa_card == NULL)
469 		return NULL;
470 	alsa_card->card_index = info->card_index;
471 
472 	snprintf(alsa_card->name, MAX_ALSA_CARD_NAME_LENGTH, "hw:%u",
473 		 info->card_index);
474 
475 	rc = snd_ctl_open(&handle, alsa_card->name, 0);
476 	if (rc < 0) {
477 		syslog(LOG_ERR, "Fail opening control %s.", alsa_card->name);
478 		goto error_bail;
479 	}
480 
481 	rc = snd_ctl_card_info(handle, card_info);
482 	if (rc < 0) {
483 		syslog(LOG_ERR, "Error getting card info.");
484 		goto error_bail;
485 	}
486 
487 	card_name = snd_ctl_card_info_get_name(card_info);
488 	if (card_name == NULL) {
489 		syslog(LOG_ERR, "Error getting card name.");
490 		goto error_bail;
491 	}
492 
493 	if (info->card_type != ALSA_CARD_TYPE_INTERNAL ||
494 	    cras_system_check_ignore_ucm_suffix(card_name))
495 		ucm_suffix = NULL;
496 
497 	/* Read config file for this card if it exists. */
498 	alsa_card->config =
499 		cras_card_config_create(device_config_dir, card_name);
500 	if (alsa_card->config == NULL)
501 		syslog(LOG_DEBUG, "No config file for %s", alsa_card->name);
502 
503 	/* Create a use case manager if a configuration is available. */
504 	if (ucm_suffix) {
505 		char *ucm_name;
506 		if (asprintf(&ucm_name, "%s.%s", card_name, ucm_suffix) == -1) {
507 			syslog(LOG_ERR, "Error creating ucm name");
508 			goto error_bail;
509 		}
510 		alsa_card->ucm = ucm_create(ucm_name);
511 		syslog(LOG_INFO, "Card %s (%s) has UCM: %s", alsa_card->name,
512 		       ucm_name, alsa_card->ucm ? "yes" : "no");
513 		free(ucm_name);
514 	} else {
515 		alsa_card->ucm = ucm_create(card_name);
516 		syslog(LOG_INFO, "Card %s (%s) has UCM: %s", alsa_card->name,
517 		       card_name, alsa_card->ucm ? "yes" : "no");
518 	}
519 
520 	if (info->card_type == ALSA_CARD_TYPE_INTERNAL && !alsa_card->ucm)
521 		syslog(LOG_ERR, "No ucm config on internal card %s", card_name);
522 
523 	rc = snd_hctl_open(&alsa_card->hctl, alsa_card->name, SND_CTL_NONBLOCK);
524 	if (rc < 0) {
525 		syslog(LOG_DEBUG, "failed to get hctl for %s", alsa_card->name);
526 		alsa_card->hctl = NULL;
527 	} else {
528 		rc = snd_hctl_nonblock(alsa_card->hctl, 1);
529 		if (rc < 0) {
530 			syslog(LOG_ERR, "failed to nonblock hctl for %s",
531 			       alsa_card->name);
532 			goto error_bail;
533 		}
534 
535 		rc = snd_hctl_load(alsa_card->hctl);
536 		if (rc < 0) {
537 			syslog(LOG_ERR, "failed to load hctl for %s",
538 			       alsa_card->name);
539 			goto error_bail;
540 		}
541 	}
542 
543 	/* Create one mixer per card. */
544 	alsa_card->mixer = cras_alsa_mixer_create(alsa_card->name);
545 
546 	if (alsa_card->mixer == NULL) {
547 		syslog(LOG_ERR, "Fail opening mixer for %s.", alsa_card->name);
548 		goto error_bail;
549 	}
550 
551 	if (alsa_card->ucm && ucm_has_fully_specified_ucm_flag(alsa_card->ucm))
552 		rc = add_controls_and_iodevs_with_ucm(info, alsa_card,
553 						      card_name, handle);
554 	else
555 		rc = add_controls_and_iodevs_by_matching(
556 			info, blocklist, alsa_card, card_name, handle);
557 	if (rc)
558 		goto error_bail;
559 
560 	configure_echo_reference_dev(alsa_card);
561 
562 	n = alsa_card->hctl ? snd_hctl_poll_descriptors_count(alsa_card->hctl) :
563 			      0;
564 	if (n != 0 && card_has_hctl_jack(alsa_card)) {
565 		struct hctl_poll_fd *registered_fd;
566 		struct pollfd *pollfds;
567 		int i;
568 
569 		pollfds = malloc(n * sizeof(*pollfds));
570 		if (pollfds == NULL) {
571 			rc = -ENOMEM;
572 			goto error_bail;
573 		}
574 
575 		n = snd_hctl_poll_descriptors(alsa_card->hctl, pollfds, n);
576 		for (i = 0; i < n; i++) {
577 			registered_fd = calloc(1, sizeof(*registered_fd));
578 			if (registered_fd == NULL) {
579 				free(pollfds);
580 				rc = -ENOMEM;
581 				goto error_bail;
582 			}
583 			registered_fd->fd = pollfds[i].fd;
584 			DL_APPEND(alsa_card->hctl_poll_fds, registered_fd);
585 			rc = cras_system_add_select_fd(
586 				registered_fd->fd, alsa_control_event_pending,
587 				alsa_card, POLLIN);
588 			if (rc < 0) {
589 				DL_DELETE(alsa_card->hctl_poll_fds,
590 					  registered_fd);
591 				free(pollfds);
592 				goto error_bail;
593 			}
594 		}
595 		free(pollfds);
596 	}
597 
598 	snd_ctl_close(handle);
599 	return alsa_card;
600 
601 error_bail:
602 	if (handle != NULL)
603 		snd_ctl_close(handle);
604 	cras_alsa_card_destroy(alsa_card);
605 	return NULL;
606 }
607 
cras_alsa_card_destroy(struct cras_alsa_card * alsa_card)608 void cras_alsa_card_destroy(struct cras_alsa_card *alsa_card)
609 {
610 	struct iodev_list_node *curr;
611 	struct hctl_poll_fd *poll_fd;
612 
613 	if (alsa_card == NULL)
614 		return;
615 
616 	DL_FOREACH (alsa_card->iodevs, curr) {
617 		alsa_iodev_destroy(curr->iodev);
618 		DL_DELETE(alsa_card->iodevs, curr);
619 		free(curr);
620 	}
621 	DL_FOREACH (alsa_card->hctl_poll_fds, poll_fd) {
622 		cras_system_rm_select_fd(poll_fd->fd);
623 		DL_DELETE(alsa_card->hctl_poll_fds, poll_fd);
624 		free(poll_fd);
625 	}
626 	if (alsa_card->hctl)
627 		snd_hctl_close(alsa_card->hctl);
628 	if (alsa_card->ucm)
629 		ucm_destroy(alsa_card->ucm);
630 	if (alsa_card->mixer)
631 		cras_alsa_mixer_destroy(alsa_card->mixer);
632 	if (alsa_card->config)
633 		cras_card_config_destroy(alsa_card->config);
634 	free(alsa_card);
635 }
636 
cras_alsa_card_get_index(const struct cras_alsa_card * alsa_card)637 size_t cras_alsa_card_get_index(const struct cras_alsa_card *alsa_card)
638 {
639 	assert(alsa_card);
640 	return alsa_card->card_index;
641 }
642