Page MenuHomeFreeBSD

D59075.id184641.diff
No OneTemporary

D59075.id184641.diff

diff --git a/sys/dev/sound/pcm/mixer.h b/sys/dev/sound/pcm/mixer.h
--- a/sys/dev/sound/pcm/mixer.h
+++ b/sys/dev/sound/pcm/mixer.h
@@ -72,9 +72,7 @@
int mixer_oss_mixerinfo(struct cdev *i_dev, oss_mixerinfo *mi);
int mixer_hwvol_init(device_t dev);
-void mixer_hwvol_mute_locked(struct snd_mixer *m);
void mixer_hwvol_mute(device_t dev);
-void mixer_hwvol_step_locked(struct snd_mixer *m, int l_step, int r_step);
void mixer_hwvol_step(device_t dev, int left_step, int right_step);
int mix_set(struct snd_mixer *m, unsigned int dev, unsigned int left, unsigned int right);
diff --git a/sys/dev/sound/pcm/mixer.c b/sys/dev/sound/pcm/mixer.c
--- a/sys/dev/sound/pcm/mixer.c
+++ b/sys/dev/sound/pcm/mixer.c
@@ -743,12 +743,6 @@
return 0;
}
-void
-mixer_hwvol_mute_locked(struct snd_mixer *m)
-{
- mix_setmutedevs(m, m->mutedevs ^ (1 << m->hwvol_mixer));
-}
-
void
mixer_hwvol_mute(device_t dev)
{
@@ -756,17 +750,19 @@
m = mixer_get_devt(dev);
mtx_lock(m->lock);
- mixer_hwvol_mute_locked(m);
+ mix_setmutedevs(m, m->mutedevs ^ (1 << m->hwvol_mixer));
mtx_unlock(m->lock);
}
void
-mixer_hwvol_step_locked(struct snd_mixer *m, int left_step, int right_step)
+mixer_hwvol_step(device_t dev, int left_step, int right_step)
{
+ struct snd_mixer *m;
int level, left, right;
+ m = mixer_get_devt(dev);
+ mtx_lock(m->lock);
level = mixer_get(m, m->hwvol_mixer);
-
if (level != -1) {
left = level & 0xff;
right = (level >> 8) & 0xff;
@@ -783,16 +779,6 @@
mixer_set(m, m->hwvol_mixer, m->mutedevs, left | right << 8);
}
-}
-
-void
-mixer_hwvol_step(device_t dev, int left_step, int right_step)
-{
- struct snd_mixer *m;
-
- m = mixer_get_devt(dev);
- mtx_lock(m->lock);
- mixer_hwvol_step_locked(m, left_step, right_step);
mtx_unlock(m->lock);
}
diff --git a/sys/dev/sound/usb/uaudio.c b/sys/dev/sound/usb/uaudio.c
--- a/sys/dev/sound/usb/uaudio.c
+++ b/sys/dev/sound/usb/uaudio.c
@@ -6199,9 +6199,13 @@
struct snd_mixer *m;
uint8_t id;
int actlen;
+ bool mute, volume_up, volume_down;
usbd_xfer_status(xfer, &actlen, NULL, NULL, NULL);
+ m = NULL;
+ mute = volume_up = volume_down = false;
+
switch (USB_GET_STATE(xfer)) {
case USB_ST_TRANSFERRED:
DPRINTF("actlen=%d\n", actlen);
@@ -6223,7 +6227,7 @@
&sc->sc_hid.mute_loc)) {
DPRINTF("Mute toggle\n");
- mixer_hwvol_mute_locked(m);
+ mute = true;
}
if ((sc->sc_hid.flags & UAUDIO_HID_HAS_VOLUME_UP) &&
@@ -6232,7 +6236,7 @@
&sc->sc_hid.volume_up_loc)) {
DPRINTF("Volume Up\n");
- mixer_hwvol_step_locked(m, 1, 1);
+ volume_up = true;
}
if ((sc->sc_hid.flags & UAUDIO_HID_HAS_VOLUME_DOWN) &&
@@ -6241,7 +6245,7 @@
&sc->sc_hid.volume_down_loc)) {
DPRINTF("Volume Down\n");
- mixer_hwvol_step_locked(m, -1, -1);
+ volume_down = true;
}
case USB_ST_SETUP:
@@ -6262,6 +6266,27 @@
}
break;
}
+
+ if (!mute && !volume_up && !volume_down)
+ return;
+
+ /*
+ * The mixer_hwvol_*() functions take the mixer lock, which is the PCM
+ * lock, and end up in uaudio_mixer_ctl_set(), which takes the
+ * mixer_lock this callback is entered with. Acquiring the two in that
+ * order here would reverse the order taken by the mixer ioctl path
+ * (PCM lock first, then mixer_lock), so drop mixer_lock for the
+ * duration. The USB stack explicitly allows a callback to drop its
+ * transfer mutex, and usbd_transfer_drain() accounts for it.
+ */
+ mtx_unlock(&sc->sc_child[0].mixer_lock);
+ if (mute)
+ mixer_hwvol_mute(m->dev);
+ if (volume_up)
+ mixer_hwvol_step(m->dev, 1, 1);
+ if (volume_down)
+ mixer_hwvol_step(m->dev, -1, -1);
+ mtx_lock(&sc->sc_child[0].mixer_lock);
}
static int

File Metadata

Mime Type
text/plain
Expires
Sun, Aug 23, 8:37 AM (8 m, 53 s)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
37084982
Default Alt Text
D59075.id184641.diff (3 KB)

Event Timeline