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
42PA_MODULE_AUTHOR("Lennart Poettering");
43PA_MODULE_DESCRIPTION("ALSA Card");
44PA_MODULE_VERSION(PACKAGE_VERSION);
45PA_MODULE_LOAD_ONCE(false);
46PA_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
75static 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
116struct 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
138struct profile_data {
139    pa_alsa_profile *profile;
140};
141
142static 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
193static 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
205static 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
283finish:
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
293static 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
320static 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
367struct temp_port_avail {
368    pa_device_port *port;
369    pa_available_t avail;
370};
371
372static 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
542static 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
564static 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
600static 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
647static 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
707static 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
743static 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
769static 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
784static 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
799static 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
814static 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
829static 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
844int 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
1120fail:
1121    if (reserve)
1122        pa_reserve_wrapper_unref(reserve);
1123
1124    pa__done(m);
1125
1126    return err;
1127}
1128
1129int 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
1149void 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
1182finish:
1183    pa_alsa_refcnt_dec();
1184}
1185