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_blacklist.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_PCM_NAME_LENGTH 6 /* Alsa names "hw:XX" + 1 for null. */
29 #define MAX_INI_NAME_LENGTH 63 /* 63 chars + 1 for null where declared. */
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,YY.
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_PCM_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,
81 struct cras_alsa_card_info *info,
82 const char *card_name,
83 const char *dev_name,
84 const char *dev_id,
85 unsigned device_index,
86 enum CRAS_STREAM_DIRECTION direction)
87 {
88 struct iodev_list_node *new_dev;
89 struct iodev_list_node *node;
90 int first = 1;
91
92 /* Find whether this is the first device in this direction, and
93 * avoid duplicate device indexes. */
94 DL_FOREACH(alsa_card->iodevs, node) {
95 if (node->direction != direction)
96 continue;
97 first = 0;
98 if (alsa_iodev_index(node->iodev) == device_index) {
99 syslog(LOG_DEBUG,
100 "Skipping duplicate device for %s:%s:%s [%u]",
101 card_name, dev_name, dev_id, device_index);
102 return node->iodev;
103 }
104 }
105
106 new_dev = calloc(1, sizeof(*new_dev));
107 if (new_dev == NULL)
108 return NULL;
109
110 new_dev->direction = direction;
111 new_dev->iodev = alsa_iodev_create(info->card_index,
112 card_name,
113 device_index,
114 dev_name,
115 dev_id,
116 info->card_type,
117 first,
118 alsa_card->mixer,
119 alsa_card->config,
120 alsa_card->ucm,
121 alsa_card->hctl,
122 direction,
123 info->usb_vendor_id,
124 info->usb_product_id,
125 info->usb_serial_number);
126 if (new_dev->iodev == NULL) {
127 syslog(LOG_ERR, "Couldn't create alsa_iodev for %u:%u\n",
128 info->card_index, device_index);
129 free(new_dev);
130 return NULL;
131 }
132
133 syslog(LOG_DEBUG, "New %s device %u:%d",
134 direction == CRAS_STREAM_OUTPUT ? "playback" : "capture",
135 info->card_index,
136 device_index);
137
138 DL_APPEND(alsa_card->iodevs, new_dev);
139 return new_dev->iodev;
140 }
141
142 /* Returns non-zero if this card has hctl jacks.
143 */
card_has_hctl_jack(struct cras_alsa_card * alsa_card)144 static int card_has_hctl_jack(struct cras_alsa_card *alsa_card)
145 {
146 struct iodev_list_node *node;
147
148 /* Find the first device that has an hctl jack. */
149 DL_FOREACH(alsa_card->iodevs, node) {
150 if (alsa_iodev_has_hctl_jacks(node->iodev))
151 return 1;
152 }
153 return 0;
154 }
155
156 /* Check if a device should be ignored for this card. Returns non-zero if the
157 * device is in the blacklist and should be ignored.
158 */
should_ignore_dev(struct cras_alsa_card_info * info,struct cras_device_blacklist * blacklist,size_t device_index)159 static int should_ignore_dev(struct cras_alsa_card_info *info,
160 struct cras_device_blacklist *blacklist,
161 size_t device_index)
162 {
163 if (info->card_type == ALSA_CARD_TYPE_USB)
164 return cras_device_blacklist_check(blacklist,
165 info->usb_vendor_id,
166 info->usb_product_id,
167 info->usb_desc_checksum,
168 device_index);
169 return 0;
170 }
171
172 /* Filters an array of mixer control names. Keep a name if it is
173 * specified in the ucm config. */
filter_controls(struct cras_use_case_mgr * ucm,struct mixer_name * controls)174 static struct mixer_name *filter_controls(struct cras_use_case_mgr *ucm,
175 struct mixer_name *controls)
176 {
177 struct mixer_name *control;
178 DL_FOREACH(controls, control) {
179 char *dev = ucm_get_dev_for_mixer(ucm, control->name,
180 CRAS_STREAM_OUTPUT);
181 if (!dev)
182 DL_DELETE(controls, control);
183 }
184 return controls;
185 }
186
187 /* Handles notifications from alsa controls. Called by main thread when a poll
188 * fd provided by alsa signals there is an event available. */
alsa_control_event_pending(void * arg)189 static void alsa_control_event_pending(void *arg)
190 {
191 struct cras_alsa_card *card;
192
193 card = (struct cras_alsa_card *)arg;
194 if (card == NULL) {
195 syslog(LOG_ERR, "Invalid card from control event.");
196 return;
197 }
198
199 /* handle_events will trigger the callback registered with each control
200 * that has changed. */
201 snd_hctl_handle_events(card->hctl);
202 }
203
add_controls_and_iodevs_by_matching(struct cras_alsa_card_info * info,struct cras_device_blacklist * blacklist,struct cras_alsa_card * alsa_card,const char * card_name,snd_ctl_t * handle)204 static int add_controls_and_iodevs_by_matching(
205 struct cras_alsa_card_info *info,
206 struct cras_device_blacklist *blacklist,
207 struct cras_alsa_card *alsa_card,
208 const char *card_name,
209 snd_ctl_t *handle)
210 {
211 struct mixer_name *coupled_controls = NULL;
212 int dev_idx;
213 snd_pcm_info_t *dev_info;
214 struct mixer_name *extra_controls = NULL;
215 int rc = 0;
216
217 snd_pcm_info_alloca(&dev_info);
218
219 if (alsa_card->ucm) {
220 char *extra_main_volume;
221
222 /* Filter the extra output mixer names */
223 extra_controls =
224 filter_controls(alsa_card->ucm,
225 mixer_name_add(extra_controls, "IEC958",
226 CRAS_STREAM_OUTPUT,
227 MIXER_NAME_VOLUME));
228
229 /* Get the extra main volume control. */
230 extra_main_volume = ucm_get_flag(alsa_card->ucm,
231 "ExtraMainVolume");
232 if (extra_main_volume) {
233 extra_controls =
234 mixer_name_add(extra_controls,
235 extra_main_volume,
236 CRAS_STREAM_OUTPUT,
237 MIXER_NAME_MAIN_VOLUME);
238 free(extra_main_volume);
239 }
240 mixer_name_dump(extra_controls, "extra controls");
241
242 /* Check if coupled controls has been specified for speaker. */
243 coupled_controls = ucm_get_coupled_mixer_names(
244 alsa_card->ucm, "Speaker");
245 mixer_name_dump(coupled_controls, "coupled controls");
246 }
247
248 /* Add controls to mixer by name matching. */
249 rc = cras_alsa_mixer_add_controls_by_name_matching(
250 alsa_card->mixer,
251 extra_controls,
252 coupled_controls);
253 if (rc) {
254 syslog(LOG_ERR, "Fail adding controls to mixer for %s.",
255 alsa_card->name);
256 goto error;
257 }
258
259 /* Go through every device. */
260 dev_idx = -1;
261 while (1) {
262 rc = snd_ctl_pcm_next_device(handle, &dev_idx);
263 if (rc < 0)
264 goto error;
265 if (dev_idx < 0)
266 break;
267
268 snd_pcm_info_set_device(dev_info, dev_idx);
269 snd_pcm_info_set_subdevice(dev_info, 0);
270
271 /* Check for playback devices. */
272 snd_pcm_info_set_stream(
273 dev_info, SND_PCM_STREAM_PLAYBACK);
274 if (snd_ctl_pcm_info(handle, dev_info) == 0 &&
275 !should_ignore_dev(info, blacklist, dev_idx)) {
276 struct cras_iodev *iodev =
277 create_iodev_for_device(
278 alsa_card,
279 info,
280 card_name,
281 snd_pcm_info_get_name(dev_info),
282 snd_pcm_info_get_id(dev_info),
283 dev_idx,
284 CRAS_STREAM_OUTPUT);
285 if (iodev) {
286 rc = alsa_iodev_legacy_complete_init(
287 iodev);
288 if (rc < 0)
289 goto error;
290 }
291 }
292
293 /* Check for capture devices. */
294 snd_pcm_info_set_stream(
295 dev_info, SND_PCM_STREAM_CAPTURE);
296 if (snd_ctl_pcm_info(handle, dev_info) == 0) {
297 struct cras_iodev *iodev =
298 create_iodev_for_device(
299 alsa_card,
300 info,
301 card_name,
302 snd_pcm_info_get_name(dev_info),
303 snd_pcm_info_get_id(dev_info),
304 dev_idx,
305 CRAS_STREAM_INPUT);
306 if (iodev) {
307 rc = alsa_iodev_legacy_complete_init(
308 iodev);
309 if (rc < 0)
310 goto error;
311 }
312 }
313 }
314 error:
315 mixer_name_free(coupled_controls);
316 mixer_name_free(extra_controls);
317 return rc;
318 }
319
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)320 static int add_controls_and_iodevs_with_ucm(
321 struct cras_alsa_card_info *info,
322 struct cras_alsa_card *alsa_card,
323 const char *card_name,
324 snd_ctl_t *handle)
325 {
326 snd_pcm_info_t *dev_info;
327 struct iodev_list_node *node;
328 int rc = 0;
329 struct ucm_section *section;
330 struct ucm_section *ucm_sections;
331
332 snd_pcm_info_alloca(&dev_info);
333
334 /* Get info on the devices specified in the UCM config. */
335 ucm_sections = ucm_get_sections(alsa_card->ucm);
336 if (!ucm_sections) {
337 syslog(LOG_ERR,
338 "Could not retrieve any UCM SectionDevice"
339 " info for '%s'.", card_name);
340 rc = -ENOENT;
341 goto error;
342 }
343
344 /* Create all of the controls first. */
345 DL_FOREACH(ucm_sections, section) {
346 rc = cras_alsa_mixer_add_controls_in_section(
347 alsa_card->mixer, section);
348 if (rc) {
349 syslog(LOG_ERR, "Failed adding controls to"
350 " mixer for '%s:%s'",
351 card_name,
352 section->name);
353 goto error;
354 }
355 }
356
357 /* Create all of the devices. */
358 DL_FOREACH(ucm_sections, section) {
359 snd_pcm_info_set_device(dev_info, section->dev_idx);
360 snd_pcm_info_set_subdevice(dev_info, 0);
361 if (section->dir == CRAS_STREAM_OUTPUT)
362 snd_pcm_info_set_stream(
363 dev_info, SND_PCM_STREAM_PLAYBACK);
364 else if (section->dir == CRAS_STREAM_INPUT)
365 snd_pcm_info_set_stream(
366 dev_info, SND_PCM_STREAM_CAPTURE);
367 else {
368 syslog(LOG_ERR, "Unexpected direction: %d",
369 section->dir);
370 rc = -EINVAL;
371 goto error;
372 }
373
374 if (snd_ctl_pcm_info(handle, dev_info)) {
375 syslog(LOG_ERR,
376 "Could not get info for device: %s",
377 section->name);
378 continue;
379 }
380
381 create_iodev_for_device(
382 alsa_card, info, card_name,
383 snd_pcm_info_get_name(dev_info),
384 snd_pcm_info_get_id(dev_info),
385 section->dev_idx, section->dir);
386 }
387
388 /* Setup jacks and controls for the devices. */
389 DL_FOREACH(ucm_sections, section) {
390 DL_FOREACH(alsa_card->iodevs, node) {
391 if (node->direction == section->dir &&
392 alsa_iodev_index(node->iodev) ==
393 section->dev_idx)
394 break;
395 }
396 if (node) {
397 rc = alsa_iodev_ucm_add_nodes_and_jacks(
398 node->iodev, section);
399 if (rc < 0)
400 goto error;
401 }
402 }
403
404 DL_FOREACH(alsa_card->iodevs, node) {
405 alsa_iodev_ucm_complete_init(node->iodev);
406 }
407
408 error:
409 ucm_section_free_list(ucm_sections);
410 return rc;
411 }
412
413 /*
414 * Exported Interface.
415 */
416
cras_alsa_card_create(struct cras_alsa_card_info * info,const char * device_config_dir,struct cras_device_blacklist * blacklist,const char * ucm_suffix)417 struct cras_alsa_card *cras_alsa_card_create(
418 struct cras_alsa_card_info *info,
419 const char *device_config_dir,
420 struct cras_device_blacklist *blacklist,
421 const char *ucm_suffix)
422 {
423 snd_ctl_t *handle = NULL;
424 int rc, n;
425 snd_ctl_card_info_t *card_info;
426 const char *card_name;
427 struct cras_alsa_card *alsa_card;
428
429 if (info->card_index >= MAX_ALSA_CARDS) {
430 syslog(LOG_ERR,
431 "Invalid alsa card index %u",
432 info->card_index);
433 return NULL;
434 }
435
436 snd_ctl_card_info_alloca(&card_info);
437
438 alsa_card = calloc(1, sizeof(*alsa_card));
439 if (alsa_card == NULL)
440 return NULL;
441 alsa_card->card_index = info->card_index;
442
443 snprintf(alsa_card->name,
444 MAX_ALSA_PCM_NAME_LENGTH,
445 "hw:%u",
446 info->card_index);
447
448 rc = snd_ctl_open(&handle, alsa_card->name, 0);
449 if (rc < 0) {
450 syslog(LOG_ERR, "Fail opening control %s.", alsa_card->name);
451 goto error_bail;
452 }
453
454 rc = snd_ctl_card_info(handle, card_info);
455 if (rc < 0) {
456 syslog(LOG_ERR, "Error getting card info.");
457 goto error_bail;
458 }
459
460 card_name = snd_ctl_card_info_get_name(card_info);
461 if (card_name == NULL) {
462 syslog(LOG_ERR, "Error getting card name.");
463 goto error_bail;
464 }
465
466 /* Read config file for this card if it exists. */
467 alsa_card->config = cras_card_config_create(device_config_dir,
468 card_name);
469 if (alsa_card->config == NULL)
470 syslog(LOG_DEBUG, "No config file for %s", alsa_card->name);
471
472 /* Create a use case manager if a configuration is available. */
473 if (ucm_suffix) {
474 char *ucm_name;
475 if (asprintf(&ucm_name, "%s.%s", card_name, ucm_suffix) == -1) {
476 syslog(LOG_ERR, "Error creating ucm name");
477 goto error_bail;
478 }
479 alsa_card->ucm = ucm_create(ucm_name);
480 syslog(LOG_INFO, "Card %s (%s) has UCM: %s",
481 alsa_card->name, ucm_name,
482 alsa_card->ucm ? "yes" : "no");
483 free(ucm_name);
484 } else {
485 alsa_card->ucm = ucm_create(card_name);
486 syslog(LOG_INFO, "Card %s (%s) has UCM: %s",
487 alsa_card->name, card_name,
488 alsa_card->ucm ? "yes" : "no");
489 }
490
491 rc = snd_hctl_open(&alsa_card->hctl,
492 alsa_card->name,
493 SND_CTL_NONBLOCK);
494 if (rc < 0) {
495 syslog(LOG_DEBUG,
496 "failed to get hctl for %s", alsa_card->name);
497 alsa_card->hctl = NULL;
498 } else {
499 rc = snd_hctl_nonblock(alsa_card->hctl, 1);
500 if (rc < 0) {
501 syslog(LOG_ERR,
502 "failed to nonblock hctl for %s", alsa_card->name);
503 goto error_bail;
504 }
505
506 rc = snd_hctl_load(alsa_card->hctl);
507 if (rc < 0) {
508 syslog(LOG_ERR,
509 "failed to load hctl for %s", alsa_card->name);
510 goto error_bail;
511 }
512 }
513
514 /* Create one mixer per card. */
515 alsa_card->mixer = cras_alsa_mixer_create(alsa_card->name);
516
517 if (alsa_card->mixer == NULL) {
518 syslog(LOG_ERR, "Fail opening mixer for %s.", alsa_card->name);
519 goto error_bail;
520 }
521
522 if (alsa_card->ucm && ucm_has_fully_specified_ucm_flag(alsa_card->ucm))
523 rc = add_controls_and_iodevs_with_ucm(
524 info, alsa_card, card_name, handle);
525 else
526 rc = add_controls_and_iodevs_by_matching(
527 info, blacklist, alsa_card, card_name, handle);
528 if (rc)
529 goto error_bail;
530
531 n = alsa_card->hctl ?
532 snd_hctl_poll_descriptors_count(alsa_card->hctl) : 0;
533 if (n != 0 && card_has_hctl_jack(alsa_card)) {
534 struct hctl_poll_fd *registered_fd;
535 struct pollfd *pollfds;
536 int i;
537
538 pollfds = malloc(n * sizeof(*pollfds));
539 if (pollfds == NULL) {
540 rc = -ENOMEM;
541 goto error_bail;
542 }
543
544 n = snd_hctl_poll_descriptors(alsa_card->hctl, pollfds, n);
545 for (i = 0; i < n; i++) {
546 registered_fd = calloc(1, sizeof(*registered_fd));
547 if (registered_fd == NULL) {
548 free(pollfds);
549 rc = -ENOMEM;
550 goto error_bail;
551 }
552 registered_fd->fd = pollfds[i].fd;
553 DL_APPEND(alsa_card->hctl_poll_fds, registered_fd);
554 rc = cras_system_add_select_fd(
555 registered_fd->fd,
556 alsa_control_event_pending,
557 alsa_card);
558 if (rc < 0) {
559 DL_DELETE(alsa_card->hctl_poll_fds,
560 registered_fd);
561 free(pollfds);
562 goto error_bail;
563 }
564 }
565 free(pollfds);
566 }
567
568 snd_ctl_close(handle);
569 return alsa_card;
570
571 error_bail:
572 if (handle != NULL)
573 snd_ctl_close(handle);
574 cras_alsa_card_destroy(alsa_card);
575 return NULL;
576 }
577
cras_alsa_card_destroy(struct cras_alsa_card * alsa_card)578 void cras_alsa_card_destroy(struct cras_alsa_card *alsa_card)
579 {
580 struct iodev_list_node *curr;
581 struct hctl_poll_fd *poll_fd;
582
583 if (alsa_card == NULL)
584 return;
585
586 DL_FOREACH(alsa_card->iodevs, curr) {
587 alsa_iodev_destroy(curr->iodev);
588 DL_DELETE(alsa_card->iodevs, curr);
589 free(curr);
590 }
591 DL_FOREACH(alsa_card->hctl_poll_fds, poll_fd) {
592 cras_system_rm_select_fd(poll_fd->fd);
593 DL_DELETE(alsa_card->hctl_poll_fds, poll_fd);
594 free(poll_fd);
595 }
596 if (alsa_card->hctl)
597 snd_hctl_close(alsa_card->hctl);
598 if (alsa_card->ucm)
599 ucm_destroy(alsa_card->ucm);
600 if (alsa_card->mixer)
601 cras_alsa_mixer_destroy(alsa_card->mixer);
602 if (alsa_card->config)
603 cras_card_config_destroy(alsa_card->config);
604 free(alsa_card);
605 }
606
cras_alsa_card_get_index(const struct cras_alsa_card * alsa_card)607 size_t cras_alsa_card_get_index(const struct cras_alsa_card *alsa_card)
608 {
609 assert(alsa_card);
610 return alsa_card->card_index;
611 }
612