1 /***
2 This file is part of PulseAudio.
3
4 Copyright 2009 Lennart Poettering
5
6 PulseAudio is free software; you can redistribute it and/or modify
7 it under the terms of the GNU Lesser General Public License as published
8 by the Free Software Foundation; either version 2.1 of the License,
9 or (at your option) any later version.
10
11 PulseAudio is distributed in the hope that it will be useful, but
12 WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 General Public License for more details.
15
16 You should have received a copy of the GNU Lesser General Public License
17 along with PulseAudio; if not, see <http://www.gnu.org/licenses/>.
18 ***/
19
20 #ifdef HAVE_CONFIG_H
21 #include <config.h>
22 #endif
23
24 #include <pulse/xmalloc.h>
25
26 #include <pulsecore/core-util.h>
27 #include <pulsecore/i18n.h>
28 #include <pulsecore/modargs.h>
29 #include <pulsecore/queue.h>
30
31 #include <modules/reserve-wrap.h>
32
33 #ifdef HAVE_UDEV
34 #include <modules/udev-util.h>
35 #endif
36
37 #include "alsa-util.h"
38 #include "alsa-ucm.h"
39 #include "alsa-sink.h"
40 #include "alsa-source.h"
41
42 PA_MODULE_AUTHOR("Lennart Poettering");
43 PA_MODULE_DESCRIPTION("ALSA Card");
44 PA_MODULE_VERSION(PACKAGE_VERSION);
45 PA_MODULE_LOAD_ONCE(false);
46 PA_MODULE_USAGE(
47 "name=<name for the card/sink/source, to be prefixed> "
48 "card_name=<name for the card> "
49 "card_properties=<properties for the card> "
50 "sink_name=<name for the sink> "
51 "sink_properties=<properties for the sink> "
52 "source_name=<name for the source> "
53 "source_properties=<properties for the source> "
54 "namereg_fail=<when false attempt to synthesise new names if they are already taken> "
55 "device_id=<ALSA card index> "
56 "format=<sample format> "
57 "rate=<sample rate> "
58 "fragments=<number of fragments> "
59 "fragment_size=<fragment size> "
60 "mmap=<enable memory mapping?> "
61 "tsched=<enable system timer based scheduling mode?> "
62 "tsched_buffer_size=<buffer size when using timer based scheduling> "
63 "tsched_buffer_watermark=<lower fill watermark> "
64 "profile=<profile name> "
65 "fixed_latency_range=<disable latency range changes on underrun?> "
66 "ignore_dB=<ignore dB information from the device?> "
67 "deferred_volume=<Synchronize software and hardware volume changes to avoid momentary jumps?> "
68 "profile_set=<profile set configuration file> "
69 "paths_dir=<directory containing the path configuration files> "
70 "use_ucm=<load use case manager> "
71 "avoid_resampling=<use stream original sample rate if possible?> "
72 "control=<name of mixer control> "
73 );
74
75 static const char* const valid_modargs[] = {
76 "name",
77 "card_name",
78 "card_properties",
79 "sink_name",
80 "sink_properties",
81 "source_name",
82 "source_properties",
83 "namereg_fail",
84 "device_id",
85 "format",
86 "rate",
87 "fragments",
88 "fragment_size",
89 "mmap",
90 "tsched",
91 "tsched_buffer_size",
92 "tsched_buffer_watermark",
93 "fixed_latency_range",
94 "profile",
95 "ignore_dB",
96 "deferred_volume",
97 "profile_set",
98 "paths_dir",
99 "use_ucm",
100 "avoid_resampling",
101 "control",
102 NULL
103 };
104
105 #define DEFAULT_DEVICE_ID "0"
106
107 #define PULSE_MODARGS "PULSE_MODARGS"
108
109 /* dynamic profile priority bonus, for all alsa profiles, the original priority
110 needs to be less than 0x7fff (32767), then could apply the rule of priority
111 bonus. So far there are 2 kinds of alsa profiles, one is from alsa ucm, the
112 other is from mixer profile-sets, their priorities are all far less than 0x7fff
113 */
114 #define PROFILE_PRIO_BONUS 0x8000
115
116 struct userdata {
117 pa_core *core;
118 pa_module *module;
119
120 char *device_id;
121 int alsa_card_index;
122
123 pa_hashmap *mixers;
124 pa_hashmap *jacks;
125
126 pa_card *card;
127
128 pa_modargs *modargs;
129
130 pa_alsa_profile_set *profile_set;
131
132 /* ucm stuffs */
133 bool use_ucm;
134 pa_alsa_ucm_config ucm;
135
136 };
137
138 struct profile_data {
139 pa_alsa_profile *profile;
140 };
141
add_profiles(struct userdata * u,pa_hashmap * h,pa_hashmap * ports)142 static void add_profiles(struct userdata *u, pa_hashmap *h, pa_hashmap *ports) {
143 pa_alsa_profile *ap;
144 void *state;
145
146 pa_assert(u);
147 pa_assert(h);
148
149 PA_HASHMAP_FOREACH(ap, u->profile_set->profiles, state) {
150 struct profile_data *d;
151 pa_card_profile *cp;
152 pa_alsa_mapping *m;
153 uint32_t idx;
154
155 cp = pa_card_profile_new(ap->name, ap->description, sizeof(struct profile_data));
156 cp->priority = ap->priority ? ap->priority : 1;
157 cp->input_name = pa_xstrdup(ap->input_name);
158 cp->output_name = pa_xstrdup(ap->output_name);
159
160 if (ap->output_mappings) {
161 cp->n_sinks = pa_idxset_size(ap->output_mappings);
162
163 PA_IDXSET_FOREACH(m, ap->output_mappings, idx) {
164 if (u->use_ucm)
165 pa_alsa_ucm_add_ports_combination(NULL, &m->ucm_context, true, ports, cp, u->core);
166 else
167 pa_alsa_path_set_add_ports(m->output_path_set, cp, ports, NULL, u->core);
168 if (m->channel_map.channels > cp->max_sink_channels)
169 cp->max_sink_channels = m->channel_map.channels;
170 }
171 }
172
173 if (ap->input_mappings) {
174 cp->n_sources = pa_idxset_size(ap->input_mappings);
175
176 PA_IDXSET_FOREACH(m, ap->input_mappings, idx) {
177 if (u->use_ucm)
178 pa_alsa_ucm_add_ports_combination(NULL, &m->ucm_context, false, ports, cp, u->core);
179 else
180 pa_alsa_path_set_add_ports(m->input_path_set, cp, ports, NULL, u->core);
181 if (m->channel_map.channels > cp->max_source_channels)
182 cp->max_source_channels = m->channel_map.channels;
183 }
184 }
185
186 d = PA_CARD_PROFILE_DATA(cp);
187 d->profile = ap;
188
189 pa_hashmap_put(h, cp->name, cp);
190 }
191 }
192
add_disabled_profile(pa_hashmap * profiles)193 static void add_disabled_profile(pa_hashmap *profiles) {
194 pa_card_profile *p;
195 struct profile_data *d;
196
197 p = pa_card_profile_new("off", _("Off"), sizeof(struct profile_data));
198
199 d = PA_CARD_PROFILE_DATA(p);
200 d->profile = NULL;
201
202 pa_hashmap_put(profiles, p->name, p);
203 }
204
card_set_profile(pa_card * c,pa_card_profile * new_profile)205 static int card_set_profile(pa_card *c, pa_card_profile *new_profile) {
206 struct userdata *u;
207 struct profile_data *nd, *od;
208 uint32_t idx;
209 pa_alsa_mapping *am;
210 pa_queue *sink_inputs = NULL, *source_outputs = NULL;
211 int ret = 0;
212
213 pa_assert(c);
214 pa_assert(new_profile);
215 pa_assert_se(u = c->userdata);
216
217 nd = PA_CARD_PROFILE_DATA(new_profile);
218 od = PA_CARD_PROFILE_DATA(c->active_profile);
219
220 if (od->profile && od->profile->output_mappings)
221 PA_IDXSET_FOREACH(am, od->profile->output_mappings, idx) {
222 if (!am->sink)
223 continue;
224
225 if (nd->profile &&
226 nd->profile->output_mappings &&
227 pa_idxset_get_by_data(nd->profile->output_mappings, am, NULL))
228 continue;
229
230 sink_inputs = pa_sink_move_all_start(am->sink, sink_inputs);
231 pa_alsa_sink_free(am->sink);
232 am->sink = NULL;
233 }
234
235 if (od->profile && od->profile->input_mappings)
236 PA_IDXSET_FOREACH(am, od->profile->input_mappings, idx) {
237 if (!am->source)
238 continue;
239
240 if (nd->profile &&
241 nd->profile->input_mappings &&
242 pa_idxset_get_by_data(nd->profile->input_mappings, am, NULL))
243 continue;
244
245 source_outputs = pa_source_move_all_start(am->source, source_outputs);
246 pa_alsa_source_free(am->source);
247 am->source = NULL;
248 }
249
250 /* if UCM is available for this card then update the verb */
251 if (u->use_ucm) {
252 if (pa_alsa_ucm_set_profile(&u->ucm, c, nd->profile ? nd->profile->name : NULL,
253 od->profile ? od->profile->name : NULL) < 0) {
254 ret = -1;
255 goto finish;
256 }
257 }
258
259 if (nd->profile && nd->profile->output_mappings)
260 PA_IDXSET_FOREACH(am, nd->profile->output_mappings, idx) {
261
262 if (!am->sink)
263 am->sink = pa_alsa_sink_new(c->module, u->modargs, __FILE__, c, am);
264
265 if (sink_inputs && am->sink) {
266 pa_sink_move_all_finish(am->sink, sink_inputs, false);
267 sink_inputs = NULL;
268 }
269 }
270
271 if (nd->profile && nd->profile->input_mappings)
272 PA_IDXSET_FOREACH(am, nd->profile->input_mappings, idx) {
273
274 if (!am->source)
275 am->source = pa_alsa_source_new(c->module, u->modargs, __FILE__, c, am);
276
277 if (source_outputs && am->source) {
278 pa_source_move_all_finish(am->source, source_outputs, false);
279 source_outputs = NULL;
280 }
281 }
282
283 finish:
284 if (sink_inputs)
285 pa_sink_move_all_fail(sink_inputs);
286
287 if (source_outputs)
288 pa_source_move_all_fail(source_outputs);
289
290 return ret;
291 }
292
init_profile(struct userdata * u)293 static void init_profile(struct userdata *u) {
294 uint32_t idx;
295 pa_alsa_mapping *am;
296 struct profile_data *d;
297 pa_alsa_ucm_config *ucm = &u->ucm;
298
299 pa_assert(u);
300
301 d = PA_CARD_PROFILE_DATA(u->card->active_profile);
302
303 if (d->profile && u->use_ucm) {
304 /* Set initial verb */
305 if (pa_alsa_ucm_set_profile(ucm, u->card, d->profile->name, NULL) < 0) {
306 pa_log("Failed to set ucm profile %s", d->profile->name);
307 return;
308 }
309 }
310
311 if (d->profile && d->profile->output_mappings)
312 PA_IDXSET_FOREACH(am, d->profile->output_mappings, idx)
313 am->sink = pa_alsa_sink_new(u->module, u->modargs, __FILE__, u->card, am);
314
315 if (d->profile && d->profile->input_mappings)
316 PA_IDXSET_FOREACH(am, d->profile->input_mappings, idx)
317 am->source = pa_alsa_source_new(u->module, u->modargs, __FILE__, u->card, am);
318 }
319
calc_port_state(pa_device_port * p,struct userdata * u)320 static pa_available_t calc_port_state(pa_device_port *p, struct userdata *u) {
321 void *state;
322 pa_alsa_jack *jack;
323 pa_available_t pa = PA_AVAILABLE_UNKNOWN;
324 pa_device_port *port;
325
326 PA_HASHMAP_FOREACH(jack, u->jacks, state) {
327 pa_available_t cpa;
328
329 if (u->use_ucm)
330 port = pa_hashmap_get(u->card->ports, jack->name);
331 else {
332 if (jack->path)
333 port = jack->path->port;
334 else
335 continue;
336 }
337
338 if (p != port)
339 continue;
340
341 cpa = jack->plugged_in ? jack->state_plugged : jack->state_unplugged;
342
343 if (cpa == PA_AVAILABLE_NO) {
344 /* If a plugged-in jack causes the availability to go to NO, it
345 * should override all other availability information (like a
346 * blacklist) so set and bail */
347 if (jack->plugged_in) {
348 pa = cpa;
349 break;
350 }
351
352 /* If the current availablility is unknown go the more precise no,
353 * but otherwise don't change state */
354 if (pa == PA_AVAILABLE_UNKNOWN)
355 pa = cpa;
356 } else if (cpa == PA_AVAILABLE_YES) {
357 /* Output is available through at least one jack, so go to that
358 * level of availability. We still need to continue iterating through
359 * the jacks in case a jack is plugged in that forces the state to no
360 */
361 pa = cpa;
362 }
363 }
364 return pa;
365 }
366
367 struct temp_port_avail {
368 pa_device_port *port;
369 pa_available_t avail;
370 };
371
report_jack_state(snd_mixer_elem_t * melem,unsigned int mask)372 static int report_jack_state(snd_mixer_elem_t *melem, unsigned int mask) {
373 struct userdata *u = snd_mixer_elem_get_callback_private(melem);
374 snd_hctl_elem_t *elem = snd_mixer_elem_get_private(melem);
375 snd_ctl_elem_value_t *elem_value;
376 bool plugged_in;
377 void *state;
378 pa_alsa_jack *jack;
379 struct temp_port_avail *tp, *tports;
380 pa_card_profile *profile;
381 pa_available_t active_available = PA_AVAILABLE_UNKNOWN;
382
383 pa_assert(u);
384
385 /* Changing the jack state may cause a port change, and a port change will
386 * make the sink or source change the mixer settings. If there are multiple
387 * users having pulseaudio running, the mixer changes done by inactive
388 * users may mess up the volume settings for the active users, because when
389 * the inactive users change the mixer settings, those changes are picked
390 * up by the active user's pulseaudio instance and the changes are
391 * interpreted as if the active user changed the settings manually e.g.
392 * with alsamixer. Even single-user systems suffer from this, because gdm
393 * runs its own pulseaudio instance.
394 *
395 * We rerun this function when being unsuspended to catch up on jack state
396 * changes */
397 if (u->card->suspend_cause & PA_SUSPEND_SESSION)
398 return 0;
399
400 if (mask == SND_CTL_EVENT_MASK_REMOVE)
401 return 0;
402
403 snd_ctl_elem_value_alloca(&elem_value);
404 if (snd_hctl_elem_read(elem, elem_value) < 0) {
405 pa_log_warn("Failed to read jack detection from '%s'", pa_strnull(snd_hctl_elem_get_name(elem)));
406 return 0;
407 }
408
409 plugged_in = !!snd_ctl_elem_value_get_boolean(elem_value, 0);
410
411 pa_log_debug("Jack '%s' is now %s", pa_strnull(snd_hctl_elem_get_name(elem)), plugged_in ? "plugged in" : "unplugged");
412
413 tports = tp = pa_xnew0(struct temp_port_avail, pa_hashmap_size(u->jacks)+1);
414
415 PA_HASHMAP_FOREACH(jack, u->jacks, state)
416 if (jack->melem == melem) {
417 pa_alsa_jack_set_plugged_in(jack, plugged_in);
418
419 if (u->use_ucm) {
420 /* When using UCM, pa_alsa_jack_set_plugged_in() maps the jack
421 * state to port availability. */
422 continue;
423 }
424
425 /* When not using UCM, we have to do the jack state -> port
426 * availability mapping ourselves. */
427 pa_assert_se(tp->port = jack->path->port);
428 tp->avail = calc_port_state(tp->port, u);
429 tp++;
430 }
431
432 /* Report available ports before unavailable ones: in case port 1 becomes available when port 2 becomes unavailable,
433 this prevents an unnecessary switch port 1 -> port 3 -> port 2 */
434
435 for (tp = tports; tp->port; tp++)
436 if (tp->avail != PA_AVAILABLE_NO)
437 pa_device_port_set_available(tp->port, tp->avail);
438 for (tp = tports; tp->port; tp++)
439 if (tp->avail == PA_AVAILABLE_NO)
440 pa_device_port_set_available(tp->port, tp->avail);
441
442 for (tp = tports; tp->port; tp++) {
443 pa_alsa_port_data *data;
444 pa_sink *sink;
445 uint32_t idx;
446
447 data = PA_DEVICE_PORT_DATA(tp->port);
448
449 if (!data->suspend_when_unavailable)
450 continue;
451
452 PA_IDXSET_FOREACH(sink, u->core->sinks, idx) {
453 if (sink->active_port == tp->port)
454 pa_sink_suspend(sink, tp->avail == PA_AVAILABLE_NO, PA_SUSPEND_UNAVAILABLE);
455 }
456 }
457
458 /* Update profile availabilities. Ideally we would mark all profiles
459 * unavailable that contain unavailable devices. We can't currently do that
460 * in all cases, because if there are multiple sinks in a profile, and the
461 * profile contains a mix of available and unavailable ports, we don't know
462 * how the ports are distributed between the different sinks. It's possible
463 * that some sinks contain only unavailable ports, in which case we should
464 * mark the profile as unavailable, but it's also possible that all sinks
465 * contain at least one available port, in which case we should mark the
466 * profile as available. Until the data structures are improved so that we
467 * can distinguish between these two cases, we mark the problematic cases
468 * as available (well, "unknown" to be precise, but there's little
469 * practical difference).
470 *
471 * A profile will be marked unavailable:
472 * only contains output ports and all ports are unavailable
473 * only contains input ports and all ports are unavailable
474 * contains both input and output ports and all ports are unavailable
475 *
476 * A profile will be awarded priority bonus:
477 * only contains output ports and at least one port is available
478 * only contains input ports and at least one port is available
479 * contains both output and input ports and at least one output port
480 * and one input port are available
481 *
482 * The rest profiles will not be marked unavailable and will not be
483 * awarded priority bonus
484 *
485 * If there are no output ports at all, but the profile contains at least
486 * one sink, then the output is considered to be available. */
487 if (u->card->active_profile)
488 active_available = u->card->active_profile->available;
489 PA_HASHMAP_FOREACH(profile, u->card->profiles, state) {
490 pa_device_port *port;
491 void *state2;
492 bool has_input_port = false;
493 bool has_output_port = false;
494 bool found_available_input_port = false;
495 bool found_available_output_port = false;
496 pa_available_t available = PA_AVAILABLE_UNKNOWN;
497
498 profile->priority &= ~PROFILE_PRIO_BONUS;
499 PA_HASHMAP_FOREACH(port, u->card->ports, state2) {
500 if (!pa_hashmap_get(port->profiles, profile->name))
501 continue;
502
503 if (port->direction == PA_DIRECTION_INPUT) {
504 has_input_port = true;
505
506 if (port->available != PA_AVAILABLE_NO)
507 found_available_input_port = true;
508 } else {
509 has_output_port = true;
510
511 if (port->available != PA_AVAILABLE_NO)
512 found_available_output_port = true;
513 }
514 }
515
516 if ((has_input_port && found_available_input_port && !has_output_port) ||
517 (has_output_port && found_available_output_port && !has_input_port) ||
518 (has_input_port && found_available_input_port && has_output_port && found_available_output_port))
519 profile->priority |= PROFILE_PRIO_BONUS;
520
521 if ((has_input_port && !found_available_input_port && has_output_port && !found_available_output_port) ||
522 (has_input_port && !found_available_input_port && !has_output_port) ||
523 (has_output_port && !found_available_output_port && !has_input_port))
524 available = PA_AVAILABLE_NO;
525
526 /* We want to update the active profile's status last, so logic that
527 * may change the active profile based on profile availability status
528 * has an updated view of all profiles' availabilities. */
529 if (profile == u->card->active_profile)
530 active_available = available;
531 else
532 pa_card_profile_set_available(profile, available);
533 }
534
535 if (u->card->active_profile)
536 pa_card_profile_set_available(u->card->active_profile, active_available);
537
538 pa_xfree(tports);
539 return 0;
540 }
541
find_port_with_eld_device(struct userdata * u,int device)542 static pa_device_port* find_port_with_eld_device(struct userdata *u, int device) {
543 void *state;
544 pa_device_port *p;
545
546 if (u->use_ucm) {
547 PA_HASHMAP_FOREACH(p, u->card->ports, state) {
548 pa_alsa_ucm_port_data *data = PA_DEVICE_PORT_DATA(p);
549 pa_assert(data->eld_mixer_device_name);
550 if (device == data->eld_device)
551 return p;
552 }
553 } else {
554 PA_HASHMAP_FOREACH(p, u->card->ports, state) {
555 pa_alsa_port_data *data = PA_DEVICE_PORT_DATA(p);
556 pa_assert(data->path);
557 if (device == data->path->eld_device)
558 return p;
559 }
560 }
561 return NULL;
562 }
563
hdmi_eld_changed(snd_mixer_elem_t * melem,unsigned int mask)564 static int hdmi_eld_changed(snd_mixer_elem_t *melem, unsigned int mask) {
565 struct userdata *u = snd_mixer_elem_get_callback_private(melem);
566 snd_hctl_elem_t *elem = snd_mixer_elem_get_private(melem);
567 int device = snd_hctl_elem_get_device(elem);
568 const char *old_monitor_name;
569 pa_device_port *p;
570 pa_hdmi_eld eld;
571 bool changed = false;
572
573 if (mask == SND_CTL_EVENT_MASK_REMOVE)
574 return 0;
575
576 p = find_port_with_eld_device(u, device);
577 if (p == NULL) {
578 pa_log_error("Invalid device changed in ALSA: %d", device);
579 return 0;
580 }
581
582 if (pa_alsa_get_hdmi_eld(elem, &eld) < 0)
583 memset(&eld, 0, sizeof(eld));
584
585 old_monitor_name = pa_proplist_gets(p->proplist, PA_PROP_DEVICE_PRODUCT_NAME);
586 if (eld.monitor_name[0] == '\0') {
587 changed |= old_monitor_name != NULL;
588 pa_proplist_unset(p->proplist, PA_PROP_DEVICE_PRODUCT_NAME);
589 } else {
590 changed |= (old_monitor_name == NULL) || (strcmp(old_monitor_name, eld.monitor_name) != 0);
591 pa_proplist_sets(p->proplist, PA_PROP_DEVICE_PRODUCT_NAME, eld.monitor_name);
592 }
593
594 if (changed && mask != 0)
595 pa_subscription_post(u->core, PA_SUBSCRIPTION_EVENT_CARD|PA_SUBSCRIPTION_EVENT_CHANGE, u->card->index);
596
597 return 0;
598 }
599
init_eld_ctls(struct userdata * u)600 static void init_eld_ctls(struct userdata *u) {
601 void *state;
602 pa_device_port *port;
603
604 /* The code in this function expects ports to have a pa_alsa_port_data
605 * struct as their data, but in UCM mode ports don't have any data. Hence,
606 * the ELD controls can't currently be used in UCM mode. */
607 PA_HASHMAP_FOREACH(port, u->card->ports, state) {
608 snd_mixer_t *mixer_handle;
609 snd_mixer_elem_t* melem;
610 int device;
611
612 if (u->use_ucm) {
613 pa_alsa_ucm_port_data *data = PA_DEVICE_PORT_DATA(port);
614 device = data->eld_device;
615 if (device < 0 || !data->eld_mixer_device_name)
616 continue;
617
618 mixer_handle = pa_alsa_open_mixer_by_name(u->mixers, data->eld_mixer_device_name, true);
619 } else {
620 pa_alsa_port_data *data = PA_DEVICE_PORT_DATA(port);
621
622 pa_assert(data->path);
623
624 device = data->path->eld_device;
625 if (device < 0)
626 continue;
627
628 mixer_handle = pa_alsa_open_mixer(u->mixers, u->alsa_card_index, true);
629 }
630
631 if (!mixer_handle)
632 continue;
633
634 melem = pa_alsa_mixer_find_pcm(mixer_handle, "ELD", device);
635 if (melem) {
636 pa_alsa_mixer_set_fdlist(u->mixers, mixer_handle, u->core->mainloop);
637 snd_mixer_elem_set_callback(melem, hdmi_eld_changed);
638 snd_mixer_elem_set_callback_private(melem, u);
639 hdmi_eld_changed(melem, 0);
640 pa_log_info("ELD device found for port %s (%d).", port->name, device);
641 }
642 else
643 pa_log_debug("No ELD device found for port %s (%d).", port->name, device);
644 }
645 }
646
init_jacks(struct userdata * u)647 static void init_jacks(struct userdata *u) {
648 void *state;
649 pa_alsa_path* path;
650 pa_alsa_jack* jack;
651 char buf[64];
652
653 u->jacks = pa_hashmap_new(pa_idxset_trivial_hash_func, pa_idxset_trivial_compare_func);
654
655 if (u->use_ucm) {
656 PA_LLIST_FOREACH(jack, u->ucm.jacks)
657 if (jack->has_control)
658 pa_hashmap_put(u->jacks, jack, jack);
659 } else {
660 /* See if we have any jacks */
661 if (u->profile_set->output_paths)
662 PA_HASHMAP_FOREACH(path, u->profile_set->output_paths, state)
663 PA_LLIST_FOREACH(jack, path->jacks)
664 if (jack->has_control)
665 pa_hashmap_put(u->jacks, jack, jack);
666
667 if (u->profile_set->input_paths)
668 PA_HASHMAP_FOREACH(path, u->profile_set->input_paths, state)
669 PA_LLIST_FOREACH(jack, path->jacks)
670 if (jack->has_control)
671 pa_hashmap_put(u->jacks, jack, jack);
672 }
673
674 pa_log_debug("Found %d jacks.", pa_hashmap_size(u->jacks));
675
676 if (pa_hashmap_size(u->jacks) == 0)
677 return;
678
679 PA_HASHMAP_FOREACH(jack, u->jacks, state) {
680 if (!jack->mixer_device_name) {
681 jack->mixer_handle = pa_alsa_open_mixer(u->mixers, u->alsa_card_index, false);
682 if (!jack->mixer_handle) {
683 pa_log("Failed to open mixer for card %d for jack detection", u->alsa_card_index);
684 continue;
685 }
686 } else {
687 jack->mixer_handle = pa_alsa_open_mixer_by_name(u->mixers, jack->mixer_device_name, false);
688 if (!jack->mixer_handle) {
689 pa_log("Failed to open mixer '%s' for jack detection", jack->mixer_device_name);
690 continue;
691 }
692 }
693 pa_alsa_mixer_set_fdlist(u->mixers, jack->mixer_handle, u->core->mainloop);
694 jack->melem = pa_alsa_mixer_find_card(jack->mixer_handle, &jack->alsa_id, 0);
695 if (!jack->melem) {
696 pa_alsa_mixer_id_to_string(buf, sizeof(buf), &jack->alsa_id);
697 pa_log_warn("Jack %s seems to have disappeared.", buf);
698 pa_alsa_jack_set_has_control(jack, false);
699 continue;
700 }
701 snd_mixer_elem_set_callback(jack->melem, report_jack_state);
702 snd_mixer_elem_set_callback_private(jack->melem, u);
703 report_jack_state(jack->melem, 0);
704 }
705 }
706
prune_singleton_availability_groups(pa_hashmap * ports)707 static void prune_singleton_availability_groups(pa_hashmap *ports) {
708 pa_device_port *p;
709 pa_hashmap *group_counts;
710 void *state, *count;
711 const char *group;
712
713 /* Collect groups and erase those that don't have more than 1 path */
714 group_counts = pa_hashmap_new(pa_idxset_string_hash_func, pa_idxset_string_compare_func);
715
716 PA_HASHMAP_FOREACH(p, ports, state) {
717 if (p->availability_group) {
718 count = pa_hashmap_get(group_counts, p->availability_group);
719 pa_hashmap_remove(group_counts, p->availability_group);
720 pa_hashmap_put(group_counts, p->availability_group, PA_UINT_TO_PTR(PA_PTR_TO_UINT(count) + 1));
721 }
722 }
723
724 /* Now we have an availability_group -> count map, let's drop all groups
725 * that have only one member */
726 PA_HASHMAP_FOREACH_KV(group, count, group_counts, state) {
727 if (count == PA_UINT_TO_PTR(1))
728 pa_hashmap_remove(group_counts, group);
729 }
730
731 PA_HASHMAP_FOREACH(p, ports, state) {
732 if (p->availability_group && !pa_hashmap_get(group_counts, p->availability_group)) {
733 pa_log_debug("Pruned singleton availability group %s from port %s", p->availability_group, p->name);
734
735 pa_xfree(p->availability_group);
736 p->availability_group = NULL;
737 }
738 }
739
740 pa_hashmap_free(group_counts);
741 }
742
set_card_name(pa_card_new_data * data,pa_modargs * ma,const char * device_id)743 static void set_card_name(pa_card_new_data *data, pa_modargs *ma, const char *device_id) {
744 char *t;
745 const char *n;
746
747 pa_assert(data);
748 pa_assert(ma);
749 pa_assert(device_id);
750
751 if ((n = pa_modargs_get_value(ma, "card_name", NULL))) {
752 pa_card_new_data_set_name(data, n);
753 data->namereg_fail = true;
754 return;
755 }
756
757 if ((n = pa_modargs_get_value(ma, "name", NULL)))
758 data->namereg_fail = true;
759 else {
760 n = device_id;
761 data->namereg_fail = false;
762 }
763
764 t = pa_sprintf_malloc("alsa_card.%s", n);
765 pa_card_new_data_set_name(data, t);
766 pa_xfree(t);
767 }
768
card_suspend_changed(pa_core * c,pa_card * card,struct userdata * u)769 static pa_hook_result_t card_suspend_changed(pa_core *c, pa_card *card, struct userdata *u) {
770 void *state;
771 pa_alsa_jack *jack;
772
773 if (card->suspend_cause == 0) {
774 /* We were unsuspended, update jack state in case it changed while we were suspended */
775 PA_HASHMAP_FOREACH(jack, u->jacks, state) {
776 if (jack->melem)
777 report_jack_state(jack->melem, 0);
778 }
779 }
780
781 return PA_HOOK_OK;
782 }
783
sink_input_put_hook_callback(pa_core * c,pa_sink_input * sink_input,struct userdata * u)784 static pa_hook_result_t sink_input_put_hook_callback(pa_core *c, pa_sink_input *sink_input, struct userdata *u) {
785 const char *role;
786 pa_sink *sink = sink_input->sink;
787
788 pa_assert(sink);
789
790 role = pa_proplist_gets(sink_input->proplist, PA_PROP_MEDIA_ROLE);
791
792 /* new sink input linked to sink of this card */
793 if (role && sink->card == u->card)
794 pa_alsa_ucm_roled_stream_begin(&u->ucm, role, PA_DIRECTION_OUTPUT);
795
796 return PA_HOOK_OK;
797 }
798
source_output_put_hook_callback(pa_core * c,pa_source_output * source_output,struct userdata * u)799 static pa_hook_result_t source_output_put_hook_callback(pa_core *c, pa_source_output *source_output, struct userdata *u) {
800 const char *role;
801 pa_source *source = source_output->source;
802
803 pa_assert(source);
804
805 role = pa_proplist_gets(source_output->proplist, PA_PROP_MEDIA_ROLE);
806
807 /* new source output linked to source of this card */
808 if (role && source->card == u->card)
809 pa_alsa_ucm_roled_stream_begin(&u->ucm, role, PA_DIRECTION_INPUT);
810
811 return PA_HOOK_OK;
812 }
813
sink_input_unlink_hook_callback(pa_core * c,pa_sink_input * sink_input,struct userdata * u)814 static pa_hook_result_t sink_input_unlink_hook_callback(pa_core *c, pa_sink_input *sink_input, struct userdata *u) {
815 const char *role;
816 pa_sink *sink = sink_input->sink;
817
818 pa_assert(sink);
819
820 role = pa_proplist_gets(sink_input->proplist, PA_PROP_MEDIA_ROLE);
821
822 /* new sink input unlinked from sink of this card */
823 if (role && sink->card == u->card)
824 pa_alsa_ucm_roled_stream_end(&u->ucm, role, PA_DIRECTION_OUTPUT);
825
826 return PA_HOOK_OK;
827 }
828
source_output_unlink_hook_callback(pa_core * c,pa_source_output * source_output,struct userdata * u)829 static pa_hook_result_t source_output_unlink_hook_callback(pa_core *c, pa_source_output *source_output, struct userdata *u) {
830 const char *role;
831 pa_source *source = source_output->source;
832
833 pa_assert(source);
834
835 role = pa_proplist_gets(source_output->proplist, PA_PROP_MEDIA_ROLE);
836
837 /* new source output unlinked from source of this card */
838 if (role && source->card == u->card)
839 pa_alsa_ucm_roled_stream_end(&u->ucm, role, PA_DIRECTION_INPUT);
840
841 return PA_HOOK_OK;
842 }
843
pa__init(pa_module * m)844 int pa__init(pa_module *m) {
845 pa_card_new_data data;
846 bool ignore_dB = false;
847 struct userdata *u;
848 pa_reserve_wrapper *reserve = NULL;
849 const char *description;
850 const char *profile_str = NULL;
851 char *fn = NULL;
852 char *udev_args = NULL;
853 bool namereg_fail = false;
854 int err = -PA_MODULE_ERR_UNSPECIFIED, rval;
855
856 pa_alsa_refcnt_inc();
857
858 pa_assert(m);
859
860 m->userdata = u = pa_xnew0(struct userdata, 1);
861 u->core = m->core;
862 u->module = m;
863 u->use_ucm = true;
864 u->ucm.core = m->core;
865
866 u->mixers = pa_hashmap_new_full(pa_idxset_string_hash_func, pa_idxset_string_compare_func,
867 pa_xfree, (pa_free_cb_t) pa_alsa_mixer_free);
868 u->ucm.mixers = u->mixers; /* alias */
869
870 if (!(u->modargs = pa_modargs_new(m->argument, valid_modargs))) {
871 pa_log("Failed to parse module arguments.");
872 goto fail;
873 }
874
875 u->device_id = pa_xstrdup(pa_modargs_get_value(u->modargs, "device_id", DEFAULT_DEVICE_ID));
876
877 if ((u->alsa_card_index = snd_card_get_index(u->device_id)) < 0) {
878 pa_log("Card '%s' doesn't exist: %s", u->device_id, pa_alsa_strerror(u->alsa_card_index));
879 goto fail;
880 }
881
882 #ifdef HAVE_UDEV
883 udev_args = pa_udev_get_property(u->alsa_card_index, PULSE_MODARGS);
884 #endif
885
886 if (udev_args) {
887 bool udev_modargs_success = true;
888 pa_modargs *temp_ma = pa_modargs_new(udev_args, valid_modargs);
889
890 if (temp_ma) {
891 /* do not try to replace device_id */
892
893 if (pa_modargs_remove_key(temp_ma, "device_id") == 0) {
894 pa_log_warn("Unexpected 'device_id' module argument override ignored from udev " PULSE_MODARGS "='%s'", udev_args);
895 }
896
897 /* Implement modargs override by copying original module arguments
898 * over udev entry arguments ignoring duplicates. */
899
900 if (pa_modargs_merge_missing(temp_ma, u->modargs, valid_modargs) == 0) {
901 /* swap module arguments */
902 pa_modargs *old_ma = u->modargs;
903 u->modargs = temp_ma;
904 temp_ma = old_ma;
905
906 pa_log_info("Applied module arguments override from udev " PULSE_MODARGS "='%s'", udev_args);
907 } else {
908 pa_log("Failed to apply module arguments override from udev " PULSE_MODARGS "='%s'", udev_args);
909 udev_modargs_success = false;
910 }
911
912 pa_modargs_free(temp_ma);
913 } else {
914 pa_log("Failed to parse module arguments from udev " PULSE_MODARGS "='%s'", udev_args);
915 udev_modargs_success = false;
916 }
917 pa_xfree(udev_args);
918
919 if (!udev_modargs_success)
920 goto fail;
921 }
922
923 if (pa_modargs_get_value_boolean(u->modargs, "ignore_dB", &ignore_dB) < 0) {
924 pa_log("Failed to parse ignore_dB argument.");
925 goto fail;
926 }
927
928 if (!pa_in_system_mode()) {
929 char *rname;
930
931 if ((rname = pa_alsa_get_reserve_name(u->device_id))) {
932 reserve = pa_reserve_wrapper_get(m->core, rname);
933 pa_xfree(rname);
934
935 if (!reserve)
936 goto fail;
937 }
938 }
939
940 if (pa_modargs_get_value_boolean(u->modargs, "use_ucm", &u->use_ucm) < 0) {
941 pa_log("Failed to parse use_ucm argument.");
942 goto fail;
943 }
944
945 /* Force ALSA to reread its configuration. This matters if our device
946 * was hot-plugged after ALSA has already read its configuration - see
947 * https://bugs.freedesktop.org/show_bug.cgi?id=54029
948 */
949
950 snd_config_update_free_global();
951
952 rval = u->use_ucm ? pa_alsa_ucm_query_profiles(&u->ucm, u->alsa_card_index) : -1;
953 if (rval == -PA_ALSA_ERR_UCM_LINKED) {
954 err = -PA_MODULE_ERR_SKIP;
955 goto fail;
956 }
957 if (rval == 0) {
958 pa_log_info("Found UCM profiles");
959
960 u->profile_set = pa_alsa_ucm_add_profile_set(&u->ucm, &u->core->default_channel_map);
961
962 /* hook start of sink input/source output to enable modifiers */
963 /* A little bit later than module-role-cork */
964 pa_module_hook_connect(m, &m->core->hooks[PA_CORE_HOOK_SINK_INPUT_PUT], PA_HOOK_LATE+10,
965 (pa_hook_cb_t) sink_input_put_hook_callback, u);
966 pa_module_hook_connect(m, &m->core->hooks[PA_CORE_HOOK_SOURCE_OUTPUT_PUT], PA_HOOK_LATE+10,
967 (pa_hook_cb_t) source_output_put_hook_callback, u);
968
969 /* hook end of sink input/source output to disable modifiers */
970 /* A little bit later than module-role-cork */
971 pa_module_hook_connect(m, &m->core->hooks[PA_CORE_HOOK_SINK_INPUT_UNLINK], PA_HOOK_LATE+10,
972 (pa_hook_cb_t) sink_input_unlink_hook_callback, u);
973 pa_module_hook_connect(m, &m->core->hooks[PA_CORE_HOOK_SOURCE_OUTPUT_UNLINK], PA_HOOK_LATE+10,
974 (pa_hook_cb_t) source_output_unlink_hook_callback, u);
975 }
976 else {
977 u->use_ucm = false;
978 #ifdef HAVE_UDEV
979 fn = pa_udev_get_property(u->alsa_card_index, "PULSE_PROFILE_SET");
980 #endif
981
982 if (pa_modargs_get_value(u->modargs, "profile_set", NULL)) {
983 pa_xfree(fn);
984 fn = pa_xstrdup(pa_modargs_get_value(u->modargs, "profile_set", NULL));
985 }
986
987 u->profile_set = pa_alsa_profile_set_new(fn, &u->core->default_channel_map);
988 pa_xfree(fn);
989 }
990
991 if (!u->profile_set)
992 goto fail;
993
994 u->profile_set->ignore_dB = ignore_dB;
995
996 pa_alsa_profile_set_probe(u->profile_set, u->mixers, u->device_id, &m->core->default_sample_spec, m->core->default_n_fragments, m->core->default_fragment_size_msec);
997 pa_alsa_profile_set_dump(u->profile_set);
998
999 pa_card_new_data_init(&data);
1000 data.driver = __FILE__;
1001 data.module = m;
1002
1003 pa_alsa_init_proplist_card(m->core, data.proplist, u->alsa_card_index);
1004
1005 pa_proplist_sets(data.proplist, PA_PROP_DEVICE_STRING, u->device_id);
1006 pa_alsa_init_description(data.proplist, NULL);
1007 set_card_name(&data, u->modargs, u->device_id);
1008
1009 /* We need to give pa_modargs_get_value_boolean() a pointer to a local
1010 * variable instead of using &data.namereg_fail directly, because
1011 * data.namereg_fail is a bitfield and taking the address of a bitfield
1012 * variable is impossible. */
1013 namereg_fail = data.namereg_fail;
1014 if (pa_modargs_get_value_boolean(u->modargs, "namereg_fail", &namereg_fail) < 0) {
1015 pa_log("Failed to parse namereg_fail argument.");
1016 pa_card_new_data_done(&data);
1017 goto fail;
1018 }
1019 data.namereg_fail = namereg_fail;
1020
1021 if (reserve)
1022 if ((description = pa_proplist_gets(data.proplist, PA_PROP_DEVICE_DESCRIPTION)))
1023 pa_reserve_wrapper_set_application_device_name(reserve, description);
1024
1025 add_profiles(u, data.profiles, data.ports);
1026
1027 if (pa_hashmap_isempty(data.profiles)) {
1028 pa_log("Failed to find a working profile.");
1029 pa_card_new_data_done(&data);
1030 goto fail;
1031 }
1032
1033 add_disabled_profile(data.profiles);
1034 prune_singleton_availability_groups(data.ports);
1035
1036 if (pa_modargs_get_proplist(u->modargs, "card_properties", data.proplist, PA_UPDATE_REPLACE) < 0) {
1037 pa_log("Invalid properties");
1038 pa_card_new_data_done(&data);
1039 goto fail;
1040 }
1041
1042 /* The Intel HDMI LPE driver needs some special handling. When the HDMI
1043 * cable is not plugged in, trying to play audio doesn't work. Any written
1044 * audio is immediately discarded and an underrun is reported, and that
1045 * results in an infinite loop of "fill buffer, handle underrun". To work
1046 * around this issue, the suspend_when_unavailable flag is used to stop
1047 * playback when the HDMI cable is unplugged. */
1048 if (!u->use_ucm &&
1049 pa_safe_streq(pa_proplist_gets(data.proplist, "alsa.driver_name"), "snd_hdmi_lpe_audio")) {
1050 pa_device_port *port;
1051 void *state;
1052
1053 PA_HASHMAP_FOREACH(port, data.ports, state) {
1054 pa_alsa_port_data *port_data;
1055
1056 port_data = PA_DEVICE_PORT_DATA(port);
1057 port_data->suspend_when_unavailable = true;
1058 }
1059 }
1060
1061 u->card = pa_card_new(m->core, &data);
1062 pa_card_new_data_done(&data);
1063
1064 if (!u->card)
1065 goto fail;
1066
1067 u->card->userdata = u;
1068 u->card->set_profile = card_set_profile;
1069
1070 pa_module_hook_connect(m, &m->core->hooks[PA_CORE_HOOK_CARD_SUSPEND_CHANGED], PA_HOOK_NORMAL,
1071 (pa_hook_cb_t) card_suspend_changed, u);
1072
1073 init_jacks(u);
1074
1075 pa_card_choose_initial_profile(u->card);
1076
1077 /* If the "profile" modarg is given, we have to override whatever the usual
1078 * policy chose in pa_card_choose_initial_profile(). */
1079 profile_str = pa_modargs_get_value(u->modargs, "profile", NULL);
1080 if (profile_str) {
1081 pa_card_profile *profile;
1082
1083 profile = pa_hashmap_get(u->card->profiles, profile_str);
1084 if (!profile) {
1085 pa_log("No such profile: %s", profile_str);
1086 goto fail;
1087 }
1088
1089 pa_card_set_profile(u->card, profile, false);
1090 }
1091
1092 pa_card_put(u->card);
1093
1094 init_profile(u);
1095 init_eld_ctls(u);
1096
1097 /* Remove all probe only mixers */
1098 if (u->mixers) {
1099 const char *devname;
1100 pa_alsa_mixer *pm;
1101 void *state;
1102 PA_HASHMAP_FOREACH_KV(devname, pm, u->mixers, state)
1103 if (pm->used_for_probe_only)
1104 pa_hashmap_remove_and_free(u->mixers, devname);
1105 }
1106
1107 if (reserve)
1108 pa_reserve_wrapper_unref(reserve);
1109
1110 if (!pa_hashmap_isempty(u->profile_set->decibel_fixes))
1111 pa_log_warn("Card %s uses decibel fixes (i.e. overrides the decibel information for some alsa volume elements). "
1112 "Please note that this feature is meant just as a help for figuring out the correct decibel values. "
1113 "PulseAudio is not the correct place to maintain the decibel mappings! The fixed decibel values "
1114 "should be sent to ALSA developers so that they can fix the driver. If it turns out that this feature "
1115 "is abused (i.e. fixes are not pushed to ALSA), the decibel fix feature may be removed in some future "
1116 "PulseAudio version.", u->card->name);
1117
1118 return 0;
1119
1120 fail:
1121 if (reserve)
1122 pa_reserve_wrapper_unref(reserve);
1123
1124 pa__done(m);
1125
1126 return err;
1127 }
1128
pa__get_n_used(pa_module * m)1129 int pa__get_n_used(pa_module *m) {
1130 struct userdata *u;
1131 int n = 0;
1132 uint32_t idx;
1133 pa_sink *sink;
1134 pa_source *source;
1135
1136 pa_assert(m);
1137 pa_assert_se(u = m->userdata);
1138 pa_assert(u->card);
1139
1140 PA_IDXSET_FOREACH(sink, u->card->sinks, idx)
1141 n += pa_sink_linked_by(sink);
1142
1143 PA_IDXSET_FOREACH(source, u->card->sources, idx)
1144 n += pa_source_linked_by(source);
1145
1146 return n;
1147 }
1148
pa__done(pa_module * m)1149 void pa__done(pa_module*m) {
1150 struct userdata *u;
1151
1152 pa_assert(m);
1153
1154 if (!(u = m->userdata))
1155 goto finish;
1156
1157 if (u->mixers)
1158 pa_hashmap_free(u->mixers);
1159 if (u->jacks)
1160 pa_hashmap_free(u->jacks);
1161
1162 if (u->card && u->card->sinks)
1163 pa_idxset_remove_all(u->card->sinks, (pa_free_cb_t) pa_alsa_sink_free);
1164
1165 if (u->card && u->card->sources)
1166 pa_idxset_remove_all(u->card->sources, (pa_free_cb_t) pa_alsa_source_free);
1167
1168 if (u->card)
1169 pa_card_free(u->card);
1170
1171 if (u->modargs)
1172 pa_modargs_free(u->modargs);
1173
1174 if (u->profile_set)
1175 pa_alsa_profile_set_free(u->profile_set);
1176
1177 pa_alsa_ucm_free(&u->ucm);
1178
1179 pa_xfree(u->device_id);
1180 pa_xfree(u);
1181
1182 finish:
1183 pa_alsa_refcnt_dec();
1184 }
1185