On Sat, Feb 05, 2022 at 12:28:08PM +0100, Mark Kettenis wrote: > > Date: Sat, 5 Feb 2022 09:29:42 +0100 > > From: Anton Lindqvist <an...@basename.se> > > > > Hi, > > I recently got a USB headset with physical volume buttons, handled by > > ucc(4). However, after enabling the device in sndiod the volume buttons > > does not cause the volume to change. Turns out wskbd_set_mixervolume() > > is only propagating volume changes to first attached audio device. Is > > their any good not to consider all attached audio devices? > > I think this is tricky. The mixer values of different audio devices > may start out differently and may have different granularity and > probably operate on a different scale. This may lead to situations > where as you turn the volume up and down, the relative output volume > between devices changes considerably. I also think that your > implementation will unmute all audio devices as soon as you touch the > volume control buttons, which is probably not desirable. > > Thinking about other ways to do this, we could: > > - Add a knob that allows the user to control which audio device is > controlled by the volume control buttons. The choice could include > "none" and "all" as well as the individual devices. > > - Add infrastructure to bind specific keyboards to specific audio > devices, a bit like how we support binding specific wskbd devices to > specific wsdisplay devices. > > The first suggestion is probably relatively easy to achieve. The > implementation of the latter would defenitely need more thought and > discussion. > > The "none" choice above would (partly) solve another issue where > userland applications see the key presses and act upon them even > though the kernel already did the volume adjustment.
There is a 3rd option of passing the information to sndiod and let it do the volume scaling. > Cheers, > > Mark > > > The diff below gives me the desired behavior by propagating volume > > changes to all attached audio devices. > > > > diff --git sys/dev/audio.c sys/dev/audio.c > > index ec52ee6ef01..ca19557d39e 100644 > > --- sys/dev/audio.c > > +++ sys/dev/audio.c > > @@ -2452,10 +2452,6 @@ wskbd_mixer_init(struct audio_softc *sc) > > }; > > int i; > > > > - if (sc->dev.dv_unit != 0) { > > - DPRINTF("%s: not configuring wskbd keys\n", DEVNAME(sc)); > > - return; > > - } > > for (i = 0; i < sizeof(spkr_names) / sizeof(spkr_names[0]); i++) { > > if (wskbd_initvol(sc, &sc->spkr, > > spkr_names[i].cn, spkr_names[i].dn)) > > @@ -2569,19 +2565,26 @@ wskbd_set_mixermute(long mute, long out) > > int > > wskbd_set_mixervolume(long dir, long out) > > { > > - struct audio_softc *sc; > > - struct wskbd_vol *vol; > > + int error = ENODEV; > > + int minor; > > > > - sc = (struct audio_softc *)device_lookup(&audio_cd, 0); > > - if (sc == NULL) > > - return ENODEV; > > - vol = out ? &sc->spkr : &sc->mic; > > - if (dir == 0) > > - vol->mute_pending ^= WSKBD_MUTE_TOGGLE; > > - else > > - vol->val_pending += dir; > > - if (!task_add(systq, &sc->wskbd_task)) > > - device_unref(&sc->dev); > > - return 0; > > + for (minor = 0; minor < audio_cd.cd_ndevs; minor++) { > > + struct audio_softc *sc; > > + struct wskbd_vol *vol; > > + > > + sc = (struct audio_softc *)device_lookup(&audio_cd, minor); > > + if (sc == NULL) > > + continue; > > + vol = out ? &sc->spkr : &sc->mic; > > + if (dir == 0) > > + vol->mute_pending ^= WSKBD_MUTE_TOGGLE; > > + else > > + vol->val_pending += dir; > > + if (!task_add(systq, &sc->wskbd_task)) > > + device_unref(&sc->dev); > > + error = 0; > > + } > > + > > + return error; > > } > > #endif /* NWSKBD > 0 */ > > > > > -- :wq Claudio