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_port(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_port(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, od->profile) < 0) {
253 ret = -1;
254 goto finish;
255 }
256 }
257
258 if (nd->profile && nd->profile->output_mappings)
259 PA_IDXSET_FOREACH(am, nd->profile->output_mappings, idx) {
260
261 if (!am->sink)
262 am->sink = pa_alsa_sink_new(c->module, u->modargs, __FILE__, c, am);
263
264 if (sink_inputs && am->sink) {
265 pa_sink_move_all_finish(am->sink, sink_inputs, false);
266 sink_inputs = NULL;
267 }
268 }
269
270 if (nd->profile && nd->profile->input_mappings)
271 PA_IDXSET_FOREACH(am, nd->profile->input_mappings, idx) {
272
273 if (!am->source)
274 am->source = pa_alsa_source_new(c->module, u->modargs, __FILE__, c, am);
275
276 if (source_outputs && am->source) {
277 pa_source_move_all_finish(am->source, source_outputs, false);
278 source_outputs = NULL;
279 }
280 }
281
282 finish:
283 if (sink_inputs)
284 pa_sink_move_all_fail(sink_inputs);
285
286 if (source_outputs)
287 pa_source_move_all_fail(source_outputs);
288
289 return ret;
290 }
291
init_profile(struct userdata * u)292 static void init_profile(struct userdata *u) {
293 uint32_t idx;
294 pa_alsa_mapping *am;
295 struct profile_data *d;
296 pa_alsa_ucm_config *ucm = &u->ucm;
297
298 pa_assert(u);
299
300 d = PA_CARD_PROFILE_DATA(u->card->active_profile);
301
302 if (d->profile && u->use_ucm) {
303 /* Set initial verb */
304 if (pa_alsa_ucm_set_profile(ucm, u->card, d->profile, NULL) < 0) {
305 pa_log("Failed to set ucm profile %s", d->profile->name);
306 return;
307 }
308 }
309
310 if (d->profile && d->profile->output_mappings)
311 PA_IDXSET_FOREACH(am, d->profile->output_mappings, idx)
312 am->sink = pa_alsa_sink_new(u->module, u->modargs, __FILE__, u->card, am);
313
314 if (d->profile && d->profile->input_mappings)
315 PA_IDXSET_FOREACH(am, d->profile->input_mappings, idx)
316 am->source = pa_alsa_source_new(u->module, u->modargs, __FILE__, u->card, am);
317 }
318
calc_port_state(pa_device_port * p,struct userdata * u)319 static pa_available_t calc_port_state(pa_device_port *p, struct userdata *u) {
320 void *state;
321 pa_alsa_jack *jack;
322 pa_available_t pa = PA_AVAILABLE_UNKNOWN;
323 pa_device_port *port;
324
325 PA_HASHMAP_FOREACH(jack, u->jacks, state) {
326 pa_available_t cpa;
327
328 if (u->use_ucm)
329 port = pa_hashmap_get(u->card->ports, jack->name);
330 else {
331 if (jack->path)
332 port = jack->path->port;
333 else
334 continue;
335 }
336
337 if (p != port)
338 continue;
339
340 cpa = jack->plugged_in ? jack->state_plugged : jack->state_unplugged;
341
342 if (cpa == PA_AVAILABLE_NO) {
343 /* If a plugged-in jack causes the availability to go to NO, it
344 * should override all other availability information (like a
345 * blacklist) so set and bail */
346 if (jack->plugged_in) {
347 pa = cpa;
348 break;
349 }
350
351 /* If the current availablility is unknown go the more precise no,
352 * but otherwise don't change state */
353 if (pa == PA_AVAILABLE_UNKNOWN)
354 pa = cpa;
355 } else if (cpa == PA_AVAILABLE_YES) {
356 /* Output is available through at least one jack, so go to that
357 * level of availability. We still need to continue iterating through
358 * the jacks in case a jack is plugged in that forces the state to no
359 */
360 pa = cpa;
361 }
362 }
363 return pa;
364 }
365
366 struct temp_port_avail {
367 pa_device_port *port;
368 pa_available_t avail;
369 };
370
report_jack_state(snd_mixer_elem_t * melem,unsigned int mask)371 static int report_jack_state(snd_mixer_elem_t *melem, unsigned int mask) {
372 struct userdata *u = snd_mixer_elem_get_callback_private(melem);
373 snd_hctl_elem_t **_elem = snd_mixer_elem_get_private(melem), *elem;
374 snd_ctl_elem_value_t *elem_value;
375 bool plugged_in;
376 void *state;
377 pa_alsa_jack *jack;
378 struct temp_port_avail *tp, *tports;
379 pa_card_profile *profile;
380 pa_available_t active_available = PA_AVAILABLE_UNKNOWN;
381
382 pa_assert(u);
383 pa_assert(_elem);
384 elem = *_elem;
385
386 /* Changing the jack state may cause a port change, and a port change will
387 * make the sink or source change the mixer settings. If there are multiple
388 * users having pulseaudio running, the mixer changes done by inactive
389 * users may mess up the volume settings for the active users, because when
390 * the inactive users change the mixer settings, those changes are picked
391 * up by the active user's pulseaudio instance and the changes are
392 * interpreted as if the active user changed the settings manually e.g.
393 * with alsamixer. Even single-user systems suffer from this, because gdm
394 * runs its own pulseaudio instance.
395 *
396 * We rerun this function when being unsuspended to catch up on jack state
397 * changes */
398 if (u->card->suspend_cause & PA_SUSPEND_SESSION)
399 return 0;
400
401 if (mask == SND_CTL_EVENT_MASK_REMOVE)
402 return 0;
403
404 snd_ctl_elem_value_alloca(&elem_value);
405 if (snd_hctl_elem_read(elem, elem_value) < 0) {
406 pa_log_warn("Failed to read jack detection from '%s'", pa_strnull(snd_hctl_elem_get_name(elem)));
407 return 0;
408 }
409
410 plugged_in = !!snd_ctl_elem_value_get_boolean(elem_value, 0);
411
412 pa_log_debug("Jack '%s' is now %s", pa_strnull(snd_hctl_elem_get_name(elem)), plugged_in ? "plugged in" : "unplugged");
413
414 tports = tp = pa_xnew0(struct temp_port_avail, pa_hashmap_size(u->jacks)+1);
415
416 PA_HASHMAP_FOREACH(jack, u->jacks, state)
417 if (jack->melem == melem) {
418 pa_alsa_jack_set_plugged_in(jack, plugged_in);
419
420 if (u->use_ucm) {
421 /* When using UCM, pa_alsa_jack_set_plugged_in() maps the jack
422 * state to port availability. */
423 continue;
424 }
425
426 /* When not using UCM, we have to do the jack state -> port
427 * availability mapping ourselves. */
428 pa_assert_se(tp->port = jack->path->port);
429 tp->avail = calc_port_state(tp->port, u);
430 tp++;
431 }
432
433 /* Report available ports before unavailable ones: in case port 1 becomes available when port 2 becomes unavailable,
434 this prevents an unnecessary switch port 1 -> port 3 -> port 2 */
435
436 for (tp = tports; tp->port; tp++)
437 if (tp->avail != PA_AVAILABLE_NO)
438 pa_device_port_set_available(tp->port, tp->avail);
439 for (tp = tports; tp->port; tp++)
440 if (tp->avail == PA_AVAILABLE_NO)
441 pa_device_port_set_available(tp->port, tp->avail);
442
443 for (tp = tports; tp->port; tp++) {
444 pa_alsa_port_data *data;
445 pa_sink *sink;
446 uint32_t idx;
447
448 data = PA_DEVICE_PORT_DATA(tp->port);
449
450 if (!data->suspend_when_unavailable)
451 continue;
452
453 PA_IDXSET_FOREACH(sink, u->core->sinks, idx) {
454 if (sink->active_port == tp->port)
455 pa_sink_suspend(sink, tp->avail == PA_AVAILABLE_NO, PA_SUSPEND_UNAVAILABLE);
456 }
457 }
458
459 /* Update profile availabilities. Ideally we would mark all profiles
460 * unavailable that contain unavailable devices. We can't currently do that
461 * in all cases, because if there are multiple sinks in a profile, and the
462 * profile contains a mix of available and unavailable ports, we don't know
463 * how the ports are distributed between the different sinks. It's possible
464 * that some sinks contain only unavailable ports, in which case we should
465 * mark the profile as unavailable, but it's also possible that all sinks
466 * contain at least one available port, in which case we should mark the
467 * profile as available. Until the data structures are improved so that we
468 * can distinguish between these two cases, we mark the problematic cases
469 * as available (well, "unknown" to be precise, but there's little
470 * practical difference).
471 *
472 * A profile will be marked unavailable:
473 * only contains output ports and all ports are unavailable
474 * only contains input ports and all ports are unavailable
475 * contains both input and output ports and all ports are unavailable
476 *
477 * A profile will be awarded priority bonus:
478 * only contains output ports and at least one port is available
479 * only contains input ports and at least one port is available
480 * contains both output and input ports and at least one output port
481 * and one input port are available
482 *
483 * The rest profiles will not be marked unavailable and will not be
484 * awarded priority bonus
485 *
486 * If there are no output ports at all, but the profile contains at least
487 * one sink, then the output is considered to be available. */
488 if (u->card->active_profile)
489 active_available = u->card->active_profile->available;
490 PA_HASHMAP_FOREACH(profile, u->card->profiles, state) {
491 pa_device_port *port;
492 void *state2;
493 bool has_input_port = false;
494 bool has_output_port = false;
495 bool found_available_input_port = false;
496 bool found_available_output_port = false;
497 pa_available_t available = PA_AVAILABLE_UNKNOWN;
498
499 profile->priority &= ~PROFILE_PRIO_BONUS;
500 PA_HASHMAP_FOREACH(port, u->card->ports, state2) {
501 if (!pa_hashmap_get(port->profiles, profile->name))
502 continue;
503
504 if (port->direction == PA_DIRECTION_INPUT) {
505 has_input_port = true;
506
507 if (port->available != PA_AVAILABLE_NO)
508 found_available_input_port = true;
509 } else {
510 has_output_port = true;
511
512 if (port->available != PA_AVAILABLE_NO)
513 found_available_output_port = true;
514 }
515 }
516
517 if ((has_input_port && found_available_input_port && !has_output_port) ||
518 (has_output_port && found_available_output_port && !has_input_port) ||
519 (has_input_port && found_available_input_port && has_output_port && found_available_output_port))
520 profile->priority |= PROFILE_PRIO_BONUS;
521
522 if ((has_input_port && !found_available_input_port && has_output_port && !found_available_output_port) ||
523 (has_input_port && !found_available_input_port && !has_output_port) ||
524 (has_output_port && !found_available_output_port && !has_input_port))
525 available = PA_AVAILABLE_NO;
526
527 /* We want to update the active profile's status last, so logic that
528 * may change the active profile based on profile availability status
529 * has an updated view of all profiles' availabilities. */
530 if (profile == u->card->active_profile)
531 active_available = available;
532 else
533 pa_card_profile_set_available(profile, available);
534 }
535
536 if (u->card->active_profile)
537 pa_card_profile_set_available(u->card->active_profile, active_available);
538
539 pa_xfree(tports);
540 return 0;
541 }
542
find_port_with_eld_device(struct userdata * u,int device)543 static pa_device_port* find_port_with_eld_device(struct userdata *u, int device) {
544 void *state;
545 pa_device_port *p;
546
547 if (u->use_ucm) {
548 PA_HASHMAP_FOREACH(p, u->card->ports, state) {
549 pa_alsa_ucm_port_data *data = PA_DEVICE_PORT_DATA(p);
550 pa_assert(data->eld_mixer_device_name);
551 if (device == data->eld_device)
552 return p;
553 }
554 } else {
555 PA_HASHMAP_FOREACH(p, u->card->ports, state) {
556 pa_alsa_port_data *data = PA_DEVICE_PORT_DATA(p);
557 pa_assert(data->path);
558 if (device == data->path->eld_device)
559 return p;
560 }
561 }
562 return NULL;
563 }
564
hdmi_eld_changed(snd_mixer_elem_t * melem,unsigned int mask)565 static int hdmi_eld_changed(snd_mixer_elem_t *melem, unsigned int mask) {
566 struct userdata *u = snd_mixer_elem_get_callback_private(melem);
567 snd_hctl_elem_t **_elem = snd_mixer_elem_get_private(melem), *elem;
568 int device;
569 const char *old_monitor_name;
570 pa_device_port *p;
571 pa_hdmi_eld eld;
572 bool changed = false;
573
574 pa_assert(u);
575 pa_assert(_elem);
576 elem = *_elem;
577 device = snd_hctl_elem_get_device(elem);
578
579 if (mask == SND_CTL_EVENT_MASK_REMOVE)
580 return 0;
581
582 p = find_port_with_eld_device(u, device);
583 if (p == NULL) {
584 pa_log_error("Invalid device changed in ALSA: %d", device);
585 return 0;
586 }
587
588 if (pa_alsa_get_hdmi_eld(elem, &eld) < 0)
589 memset(&eld, 0, sizeof(eld));
590
591 old_monitor_name = pa_proplist_gets(p->proplist, PA_PROP_DEVICE_PRODUCT_NAME);
592 if (eld.monitor_name[0] == '\0') {
593 changed |= old_monitor_name != NULL;
594 pa_proplist_unset(p->proplist, PA_PROP_DEVICE_PRODUCT_NAME);
595 } else {
596 changed |= (old_monitor_name == NULL) || (strcmp(old_monitor_name, eld.monitor_name) != 0);
597 pa_proplist_sets(p->proplist, PA_PROP_DEVICE_PRODUCT_NAME, eld.monitor_name);
598 }
599
600 if (changed && mask != 0)
601 pa_subscription_post(u->core, PA_SUBSCRIPTION_EVENT_CARD|PA_SUBSCRIPTION_EVENT_CHANGE, u->card->index);
602
603 return 0;
604 }
605
init_eld_ctls(struct userdata * u)606 static void init_eld_ctls(struct userdata *u) {
607 void *state;
608 pa_device_port *port;
609
610 /* The code in this function expects ports to have a pa_alsa_port_data
611 * struct as their data, but in UCM mode ports don't have any data. Hence,
612 * the ELD controls can't currently be used in UCM mode. */
613 PA_HASHMAP_FOREACH(port, u->card->ports, state) {
614 snd_mixer_t *mixer_handle;
615 snd_mixer_elem_t* melem;
616 int device;
617
618 if (u->use_ucm) {
619 pa_alsa_ucm_port_data *data = PA_DEVICE_PORT_DATA(port);
620 device = data->eld_device;
621 if (device < 0 || !data->eld_mixer_device_name)
622 continue;
623
624 mixer_handle = pa_alsa_open_mixer_by_name(u->mixers, data->eld_mixer_device_name, true);
625 } else {
626 pa_alsa_port_data *data = PA_DEVICE_PORT_DATA(port);
627
628 pa_assert(data->path);
629
630 device = data->path->eld_device;
631 if (device < 0)
632 continue;
633
634 mixer_handle = pa_alsa_open_mixer(u->mixers, u->alsa_card_index, true);
635 }
636
637 if (!mixer_handle)
638 continue;
639
640 melem = pa_alsa_mixer_find_pcm(mixer_handle, "ELD", device);
641 if (melem) {
642 pa_alsa_mixer_set_fdlist(u->mixers, mixer_handle, u->core->mainloop);
643 snd_mixer_elem_set_callback(melem, hdmi_eld_changed);
644 snd_mixer_elem_set_callback_private(melem, u);
645 hdmi_eld_changed(melem, 0);
646 pa_log_info("ELD device found for port %s (%d).", port->name, device);
647 }
648 else
649 pa_log_debug("No ELD device found for port %s (%d).", port->name, device);
650 }
651 }
652
init_jacks(struct userdata * u)653 static void init_jacks(struct userdata *u) {
654 void *state;
655 pa_alsa_path* path;
656 pa_alsa_jack* jack;
657 char buf[64];
658
659 u->jacks = pa_hashmap_new(pa_idxset_trivial_hash_func, pa_idxset_trivial_compare_func);
660
661 if (u->use_ucm) {
662 PA_LLIST_FOREACH(jack, u->ucm.jacks)
663 if (jack->has_control)
664 pa_hashmap_put(u->jacks, jack, jack);
665 } else {
666 /* See if we have any jacks */
667 if (u->profile_set->output_paths)
668 PA_HASHMAP_FOREACH(path, u->profile_set->output_paths, state)
669 PA_LLIST_FOREACH(jack, path->jacks)
670 if (jack->has_control)
671 pa_hashmap_put(u->jacks, jack, jack);
672
673 if (u->profile_set->input_paths)
674 PA_HASHMAP_FOREACH(path, u->profile_set->input_paths, state)
675 PA_LLIST_FOREACH(jack, path->jacks)
676 if (jack->has_control)
677 pa_hashmap_put(u->jacks, jack, jack);
678 }
679
680 pa_log_debug("Found %d jacks.", pa_hashmap_size(u->jacks));
681
682 if (pa_hashmap_size(u->jacks) == 0)
683 return;
684
685 PA_HASHMAP_FOREACH(jack, u->jacks, state) {
686 if (!jack->mixer_device_name) {
687 jack->mixer_handle = pa_alsa_open_mixer(u->mixers, u->alsa_card_index, false);
688 if (!jack->mixer_handle) {
689 pa_log("Failed to open mixer for card %d for jack detection", u->alsa_card_index);
690 continue;
691 }
692 } else {
693 jack->mixer_handle = pa_alsa_open_mixer_by_name(u->mixers, jack->mixer_device_name, false);
694 if (!jack->mixer_handle) {
695 pa_log("Failed to open mixer '%s' for jack detection", jack->mixer_device_name);
696 continue;
697 }
698 }
699 pa_alsa_mixer_set_fdlist(u->mixers, jack->mixer_handle, u->core->mainloop);
700 jack->melem = pa_alsa_mixer_find_card(jack->mixer_handle, &jack->alsa_id, 0);
701 if (!jack->melem) {
702 pa_alsa_mixer_id_to_string(buf, sizeof(buf), &jack->alsa_id);
703 pa_log_warn("Jack %s seems to have disappeared.", buf);
704 pa_alsa_jack_set_has_control(jack, false);
705 continue;
706 }
707 snd_mixer_elem_set_callback(jack->melem, report_jack_state);
708 snd_mixer_elem_set_callback_private(jack->melem, u);
709 report_jack_state(jack->melem, 0);
710 }
711 }
712
prune_singleton_availability_groups(pa_hashmap * ports)713 static void prune_singleton_availability_groups(pa_hashmap *ports) {
714 pa_device_port *p;
715 pa_hashmap *group_counts;
716 void *state, *count;
717 const char *group;
718
719 /* Collect groups and erase those that don't have more than 1 path */
720 group_counts = pa_hashmap_new(pa_idxset_string_hash_func, pa_idxset_string_compare_func);
721
722 PA_HASHMAP_FOREACH(p, ports, state) {
723 if (p->availability_group) {
724 count = pa_hashmap_get(group_counts, p->availability_group);
725 pa_hashmap_remove(group_counts, p->availability_group);
726 pa_hashmap_put(group_counts, p->availability_group, PA_UINT_TO_PTR(PA_PTR_TO_UINT(count) + 1));
727 }
728 }
729
730 /* Now we have an availability_group -> count map, let's drop all groups
731 * that have only one member */
732 PA_HASHMAP_FOREACH_KV(group, count, group_counts, state) {
733 if (count == PA_UINT_TO_PTR(1))
734 pa_hashmap_remove(group_counts, group);
735 }
736
737 PA_HASHMAP_FOREACH(p, ports, state) {
738 if (p->availability_group && !pa_hashmap_get(group_counts, p->availability_group)) {
739 pa_log_debug("Pruned singleton availability group %s from port %s", p->availability_group, p->name);
740
741 pa_xfree(p->availability_group);
742 p->availability_group = NULL;
743 }
744 }
745
746 pa_hashmap_free(group_counts);
747 }
748
set_card_name(pa_card_new_data * data,pa_modargs * ma,const char * device_id)749 static void set_card_name(pa_card_new_data *data, pa_modargs *ma, const char *device_id) {
750 char *t;
751 const char *n;
752
753 pa_assert(data);
754 pa_assert(ma);
755 pa_assert(device_id);
756
757 if ((n = pa_modargs_get_value(ma, "card_name", NULL))) {
758 pa_card_new_data_set_name(data, n);
759 data->namereg_fail = true;
760 return;
761 }
762
763 if ((n = pa_modargs_get_value(ma, "name", NULL)))
764 data->namereg_fail = true;
765 else {
766 n = device_id;
767 data->namereg_fail = false;
768 }
769
770 t = pa_sprintf_malloc("alsa_card.%s", n);
771 pa_card_new_data_set_name(data, t);
772 pa_xfree(t);
773 }
774
card_suspend_changed(pa_core * c,pa_card * card,struct userdata * u)775 static pa_hook_result_t card_suspend_changed(pa_core *c, pa_card *card, struct userdata *u) {
776 void *state;
777 pa_alsa_jack *jack;
778
779 if (card->suspend_cause == 0) {
780 /* We were unsuspended, update jack state in case it changed while we were suspended */
781 PA_HASHMAP_FOREACH(jack, u->jacks, state) {
782 if (jack->melem)
783 report_jack_state(jack->melem, 0);
784 }
785 }
786
787 return PA_HOOK_OK;
788 }
789
sink_input_put_hook_callback(pa_core * c,pa_sink_input * sink_input,struct userdata * u)790 static pa_hook_result_t sink_input_put_hook_callback(pa_core *c, pa_sink_input *sink_input, struct userdata *u) {
791 const char *role;
792 pa_sink *sink = sink_input->sink;
793
794 pa_assert(sink);
795
796 role = pa_proplist_gets(sink_input->proplist, PA_PROP_MEDIA_ROLE);
797
798 /* new sink input linked to sink of this card */
799 if (role && sink->card == u->card)
800 pa_alsa_ucm_roled_stream_begin(&u->ucm, role, PA_DIRECTION_OUTPUT);
801
802 return PA_HOOK_OK;
803 }
804
source_output_put_hook_callback(pa_core * c,pa_source_output * source_output,struct userdata * u)805 static pa_hook_result_t source_output_put_hook_callback(pa_core *c, pa_source_output *source_output, struct userdata *u) {
806 const char *role;
807 pa_source *source = source_output->source;
808
809 pa_assert(source);
810
811 role = pa_proplist_gets(source_output->proplist, PA_PROP_MEDIA_ROLE);
812
813 /* new source output linked to source of this card */
814 if (role && source->card == u->card)
815 pa_alsa_ucm_roled_stream_begin(&u->ucm, role, PA_DIRECTION_INPUT);
816
817 return PA_HOOK_OK;
818 }
819
sink_input_unlink_hook_callback(pa_core * c,pa_sink_input * sink_input,struct userdata * u)820 static pa_hook_result_t sink_input_unlink_hook_callback(pa_core *c, pa_sink_input *sink_input, struct userdata *u) {
821 const char *role;
822 pa_sink *sink = sink_input->sink;
823
824 pa_assert(sink);
825
826 role = pa_proplist_gets(sink_input->proplist, PA_PROP_MEDIA_ROLE);
827
828 /* new sink input unlinked from sink of this card */
829 if (role && sink->card == u->card)
830 pa_alsa_ucm_roled_stream_end(&u->ucm, role, PA_DIRECTION_OUTPUT);
831
832 return PA_HOOK_OK;
833 }
834
source_output_unlink_hook_callback(pa_core * c,pa_source_output * source_output,struct userdata * u)835 static pa_hook_result_t source_output_unlink_hook_callback(pa_core *c, pa_source_output *source_output, struct userdata *u) {
836 const char *role;
837 pa_source *source = source_output->source;
838
839 pa_assert(source);
840
841 role = pa_proplist_gets(source_output->proplist, PA_PROP_MEDIA_ROLE);
842
843 /* new source output unlinked from source of this card */
844 if (role && source->card == u->card)
845 pa_alsa_ucm_roled_stream_end(&u->ucm, role, PA_DIRECTION_INPUT);
846
847 return PA_HOOK_OK;
848 }
849
pa__init(pa_module * m)850 int pa__init(pa_module *m) {
851 pa_card_new_data data;
852 bool ignore_dB = false;
853 struct userdata *u;
854 pa_reserve_wrapper *reserve = NULL;
855 const char *description;
856 const char *profile_str = NULL;
857 char *fn = NULL;
858 char *udev_args = NULL;
859 bool namereg_fail = false;
860 int err = -PA_MODULE_ERR_UNSPECIFIED, rval;
861
862 pa_alsa_refcnt_inc();
863
864 pa_assert(m);
865
866 m->userdata = u = pa_xnew0(struct userdata, 1);
867 u->core = m->core;
868 u->module = m;
869 u->use_ucm = true;
870 u->ucm.core = m->core;
871
872 u->mixers = pa_hashmap_new_full(pa_idxset_string_hash_func, pa_idxset_string_compare_func,
873 pa_xfree, (pa_free_cb_t) pa_alsa_mixer_free);
874 u->ucm.mixers = u->mixers; /* alias */
875
876 if (!(u->modargs = pa_modargs_new(m->argument, valid_modargs))) {
877 pa_log("Failed to parse module arguments.");
878 goto fail;
879 }
880
881 u->device_id = pa_xstrdup(pa_modargs_get_value(u->modargs, "device_id", DEFAULT_DEVICE_ID));
882
883 if ((u->alsa_card_index = snd_card_get_index(u->device_id)) < 0) {
884 pa_log("Card '%s' doesn't exist: %s", u->device_id, pa_alsa_strerror(u->alsa_card_index));
885 goto fail;
886 }
887
888 #ifdef HAVE_UDEV
889 udev_args = pa_udev_get_property(u->alsa_card_index, PULSE_MODARGS);
890 #endif
891
892 if (udev_args) {
893 bool udev_modargs_success = true;
894 pa_modargs *temp_ma = pa_modargs_new(udev_args, valid_modargs);
895
896 if (temp_ma) {
897 /* do not try to replace device_id */
898
899 if (pa_modargs_remove_key(temp_ma, "device_id") == 0) {
900 pa_log_warn("Unexpected 'device_id' module argument override ignored from udev " PULSE_MODARGS "='%s'", udev_args);
901 }
902
903 /* Implement modargs override by copying original module arguments
904 * over udev entry arguments ignoring duplicates. */
905
906 if (pa_modargs_merge_missing(temp_ma, u->modargs, valid_modargs) == 0) {
907 /* swap module arguments */
908 pa_modargs *old_ma = u->modargs;
909 u->modargs = temp_ma;
910 temp_ma = old_ma;
911
912 pa_log_info("Applied module arguments override from udev " PULSE_MODARGS "='%s'", udev_args);
913 } else {
914 pa_log("Failed to apply module arguments override from udev " PULSE_MODARGS "='%s'", udev_args);
915 udev_modargs_success = false;
916 }
917
918 pa_modargs_free(temp_ma);
919 } else {
920 pa_log("Failed to parse module arguments from udev " PULSE_MODARGS "='%s'", udev_args);
921 udev_modargs_success = false;
922 }
923 pa_xfree(udev_args);
924
925 if (!udev_modargs_success)
926 goto fail;
927 }
928
929 if (pa_modargs_get_value_boolean(u->modargs, "ignore_dB", &ignore_dB) < 0) {
930 pa_log("Failed to parse ignore_dB argument.");
931 goto fail;
932 }
933
934 if (!pa_in_system_mode()) {
935 char *rname;
936
937 if ((rname = pa_alsa_get_reserve_name(u->device_id))) {
938 reserve = pa_reserve_wrapper_get(m->core, rname);
939 pa_xfree(rname);
940
941 if (!reserve)
942 goto fail;
943 }
944 }
945
946 if (pa_modargs_get_value_boolean(u->modargs, "use_ucm", &u->use_ucm) < 0) {
947 pa_log("Failed to parse use_ucm argument.");
948 goto fail;
949 }
950
951 /* Force ALSA to reread its configuration. This matters if our device
952 * was hot-plugged after ALSA has already read its configuration - see
953 * https://bugs.freedesktop.org/show_bug.cgi?id=54029
954 */
955
956 snd_config_update_free_global();
957
958 rval = u->use_ucm ? pa_alsa_ucm_query_profiles(&u->ucm, u->alsa_card_index) : -1;
959 if (rval == -PA_ALSA_ERR_UCM_LINKED) {
960 err = -PA_MODULE_ERR_SKIP;
961 goto fail;
962 }
963 if (rval == 0) {
964 pa_log_info("Found UCM profiles");
965
966 u->profile_set = pa_alsa_ucm_add_profile_set(&u->ucm, &u->core->default_channel_map);
967
968 /* hook start of sink input/source output to enable modifiers */
969 /* A little bit later than module-role-cork */
970 pa_module_hook_connect(m, &m->core->hooks[PA_CORE_HOOK_SINK_INPUT_PUT], PA_HOOK_LATE+10,
971 (pa_hook_cb_t) sink_input_put_hook_callback, u);
972 pa_module_hook_connect(m, &m->core->hooks[PA_CORE_HOOK_SOURCE_OUTPUT_PUT], PA_HOOK_LATE+10,
973 (pa_hook_cb_t) source_output_put_hook_callback, u);
974
975 /* hook end of sink input/source output to disable modifiers */
976 /* A little bit later than module-role-cork */
977 pa_module_hook_connect(m, &m->core->hooks[PA_CORE_HOOK_SINK_INPUT_UNLINK], PA_HOOK_LATE+10,
978 (pa_hook_cb_t) sink_input_unlink_hook_callback, u);
979 pa_module_hook_connect(m, &m->core->hooks[PA_CORE_HOOK_SOURCE_OUTPUT_UNLINK], PA_HOOK_LATE+10,
980 (pa_hook_cb_t) source_output_unlink_hook_callback, u);
981 }
982 else {
983 u->use_ucm = false;
984 #ifdef HAVE_UDEV
985 fn = pa_udev_get_property(u->alsa_card_index, "PULSE_PROFILE_SET");
986 #endif
987
988 if (pa_modargs_get_value(u->modargs, "profile_set", NULL)) {
989 pa_xfree(fn);
990 fn = pa_xstrdup(pa_modargs_get_value(u->modargs, "profile_set", NULL));
991 }
992
993 u->profile_set = pa_alsa_profile_set_new(fn, &u->core->default_channel_map);
994 pa_xfree(fn);
995 }
996
997 if (!u->profile_set)
998 goto fail;
999
1000 u->profile_set->ignore_dB = ignore_dB;
1001
1002 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);
1003 pa_alsa_profile_set_dump(u->profile_set);
1004
1005 pa_card_new_data_init(&data);
1006 data.driver = __FILE__;
1007 data.module = m;
1008
1009 pa_alsa_init_proplist_card(m->core, data.proplist, u->alsa_card_index);
1010
1011 pa_proplist_sets(data.proplist, PA_PROP_DEVICE_STRING, u->device_id);
1012 pa_alsa_init_description(data.proplist, NULL);
1013 set_card_name(&data, u->modargs, u->device_id);
1014
1015 /* We need to give pa_modargs_get_value_boolean() a pointer to a local
1016 * variable instead of using &data.namereg_fail directly, because
1017 * data.namereg_fail is a bitfield and taking the address of a bitfield
1018 * variable is impossible. */
1019 namereg_fail = data.namereg_fail;
1020 if (pa_modargs_get_value_boolean(u->modargs, "namereg_fail", &namereg_fail) < 0) {
1021 pa_log("Failed to parse namereg_fail argument.");
1022 pa_card_new_data_done(&data);
1023 goto fail;
1024 }
1025 data.namereg_fail = namereg_fail;
1026
1027 if (reserve)
1028 if ((description = pa_proplist_gets(data.proplist, PA_PROP_DEVICE_DESCRIPTION)))
1029 pa_reserve_wrapper_set_application_device_name(reserve, description);
1030
1031 add_profiles(u, data.profiles, data.ports);
1032
1033 if (pa_hashmap_isempty(data.profiles)) {
1034 pa_log("Failed to find a working profile.");
1035 pa_card_new_data_done(&data);
1036 goto fail;
1037 }
1038
1039 add_disabled_profile(data.profiles);
1040 prune_singleton_availability_groups(data.ports);
1041
1042 if (pa_modargs_get_proplist(u->modargs, "card_properties", data.proplist, PA_UPDATE_REPLACE) < 0) {
1043 pa_log("Invalid properties");
1044 pa_card_new_data_done(&data);
1045 goto fail;
1046 }
1047
1048 /* The Intel HDMI LPE driver needs some special handling. When the HDMI
1049 * cable is not plugged in, trying to play audio doesn't work. Any written
1050 * audio is immediately discarded and an underrun is reported, and that
1051 * results in an infinite loop of "fill buffer, handle underrun". To work
1052 * around this issue, the suspend_when_unavailable flag is used to stop
1053 * playback when the HDMI cable is unplugged. */
1054 if (!u->use_ucm &&
1055 pa_safe_streq(pa_proplist_gets(data.proplist, "alsa.driver_name"), "snd_hdmi_lpe_audio")) {
1056 pa_device_port *port;
1057 void *state;
1058
1059 PA_HASHMAP_FOREACH(port, data.ports, state) {
1060 pa_alsa_port_data *port_data;
1061
1062 port_data = PA_DEVICE_PORT_DATA(port);
1063 port_data->suspend_when_unavailable = true;
1064 }
1065 }
1066
1067 u->card = pa_card_new(m->core, &data);
1068 pa_card_new_data_done(&data);
1069
1070 if (!u->card)
1071 goto fail;
1072
1073 u->card->userdata = u;
1074 u->card->set_profile = card_set_profile;
1075
1076 pa_module_hook_connect(m, &m->core->hooks[PA_CORE_HOOK_CARD_SUSPEND_CHANGED], PA_HOOK_NORMAL,
1077 (pa_hook_cb_t) card_suspend_changed, u);
1078
1079 init_jacks(u);
1080
1081 pa_card_choose_initial_profile(u->card);
1082
1083 /* If the "profile" modarg is given, we have to override whatever the usual
1084 * policy chose in pa_card_choose_initial_profile(). */
1085 profile_str = pa_modargs_get_value(u->modargs, "profile", NULL);
1086 if (profile_str) {
1087 pa_card_profile *profile;
1088
1089 profile = pa_hashmap_get(u->card->profiles, profile_str);
1090 if (!profile) {
1091 pa_log("No such profile: %s", profile_str);
1092 goto fail;
1093 }
1094
1095 pa_card_set_profile(u->card, profile, false);
1096 }
1097
1098 pa_card_put(u->card);
1099
1100 init_profile(u);
1101 init_eld_ctls(u);
1102
1103 /* Remove all probe only mixers */
1104 if (u->mixers) {
1105 const char *devname;
1106 pa_alsa_mixer *pm;
1107 void *state;
1108 PA_HASHMAP_FOREACH_KV(devname, pm, u->mixers, state)
1109 if (pm->used_for_probe_only)
1110 pa_hashmap_remove_and_free(u->mixers, devname);
1111 }
1112
1113 if (reserve)
1114 pa_reserve_wrapper_unref(reserve);
1115
1116 if (!pa_hashmap_isempty(u->profile_set->decibel_fixes))
1117 pa_log_warn("Card %s uses decibel fixes (i.e. overrides the decibel information for some alsa volume elements). "
1118 "Please note that this feature is meant just as a help for figuring out the correct decibel values. "
1119 "PulseAudio is not the correct place to maintain the decibel mappings! The fixed decibel values "
1120 "should be sent to ALSA developers so that they can fix the driver. If it turns out that this feature "
1121 "is abused (i.e. fixes are not pushed to ALSA), the decibel fix feature may be removed in some future "
1122 "PulseAudio version.", u->card->name);
1123
1124 return 0;
1125
1126 fail:
1127 if (reserve)
1128 pa_reserve_wrapper_unref(reserve);
1129
1130 pa__done(m);
1131
1132 return err;
1133 }
1134
pa__get_n_used(pa_module * m)1135 int pa__get_n_used(pa_module *m) {
1136 struct userdata *u;
1137 int n = 0;
1138 uint32_t idx;
1139 pa_sink *sink;
1140 pa_source *source;
1141
1142 pa_assert(m);
1143 pa_assert_se(u = m->userdata);
1144 pa_assert(u->card);
1145
1146 PA_IDXSET_FOREACH(sink, u->card->sinks, idx)
1147 n += pa_sink_linked_by(sink);
1148
1149 PA_IDXSET_FOREACH(source, u->card->sources, idx)
1150 n += pa_source_linked_by(source);
1151
1152 return n;
1153 }
1154
pa__done(pa_module * m)1155 void pa__done(pa_module*m) {
1156 struct userdata *u;
1157
1158 pa_assert(m);
1159
1160 if (!(u = m->userdata))
1161 goto finish;
1162
1163 if (u->mixers)
1164 pa_hashmap_free(u->mixers);
1165 if (u->jacks)
1166 pa_hashmap_free(u->jacks);
1167
1168 if (u->card && u->card->sinks)
1169 pa_idxset_remove_all(u->card->sinks, (pa_free_cb_t) pa_alsa_sink_free);
1170
1171 if (u->card && u->card->sources)
1172 pa_idxset_remove_all(u->card->sources, (pa_free_cb_t) pa_alsa_source_free);
1173
1174 if (u->card)
1175 pa_card_free(u->card);
1176
1177 if (u->modargs)
1178 pa_modargs_free(u->modargs);
1179
1180 if (u->profile_set)
1181 pa_alsa_profile_set_free(u->profile_set);
1182
1183 pa_alsa_ucm_free(&u->ucm);
1184
1185 pa_xfree(u->device_id);
1186 pa_xfree(u);
1187
1188 finish:
1189 pa_alsa_refcnt_dec();
1190 }
1191