summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorhselasky <hselasky@FreeBSD.org>2013-02-07 08:20:03 +0000
committerhselasky <hselasky@FreeBSD.org>2013-02-07 08:20:03 +0000
commitf3d9ee22e48c693e78c1cfbfc37dc911d6f25e3f (patch)
tree1dfd4ee3a9b9d36fdede024b310eaf759285703c
parentf4d6b3f3b9d273db754a1185e8bc0c4b33af75f7 (diff)
downloadFreeBSD-src-f3d9ee22e48c693e78c1cfbfc37dc911d6f25e3f.zip
FreeBSD-src-f3d9ee22e48c693e78c1cfbfc37dc911d6f25e3f.tar.gz
Add support for mute buttons on USB audio devices and
use the hwvol interface to adjust the mixer settings. MFC after: 1 week
-rw-r--r--sys/dev/sound/pcm/mixer.c39
-rw-r--r--sys/dev/sound/pcm/mixer.h2
-rw-r--r--sys/dev/sound/usb/uaudio.c46
3 files changed, 58 insertions, 29 deletions
diff --git a/sys/dev/sound/pcm/mixer.c b/sys/dev/sound/pcm/mixer.c
index eea11e6..8f9a5fb 100644
--- a/sys/dev/sound/pcm/mixer.c
+++ b/sys/dev/sound/pcm/mixer.c
@@ -893,14 +893,8 @@ mixer_hwvol_init(device_t dev)
}
void
-mixer_hwvol_mute(device_t dev)
+mixer_hwvol_mute_locked(struct snd_mixer *m)
{
- struct snd_mixer *m;
- struct cdev *pdev;
-
- pdev = mixer_get_devt(dev);
- m = pdev->si_drv1;
- snd_mtxlock(m->lock);
if (m->hwvol_muted) {
m->hwvol_muted = 0;
mixer_set(m, m->hwvol_mixer, m->hwvol_mute_level);
@@ -909,19 +903,26 @@ mixer_hwvol_mute(device_t dev)
m->hwvol_mute_level = mixer_get(m, m->hwvol_mixer);
mixer_set(m, m->hwvol_mixer, 0);
}
- snd_mtxunlock(m->lock);
}
void
-mixer_hwvol_step(device_t dev, int left_step, int right_step)
+mixer_hwvol_mute(device_t dev)
{
struct snd_mixer *m;
- int level, left, right;
struct cdev *pdev;
pdev = mixer_get_devt(dev);
m = pdev->si_drv1;
snd_mtxlock(m->lock);
+ mixer_hwvol_mute_locked(m);
+ snd_mtxunlock(m->lock);
+}
+
+void
+mixer_hwvol_step_locked(struct snd_mixer *m, int left_step, int right_step)
+{
+ int level, left, right;
+
if (m->hwvol_muted) {
m->hwvol_muted = 0;
level = m->hwvol_mute_level;
@@ -929,15 +930,31 @@ mixer_hwvol_step(device_t dev, int left_step, int right_step)
level = mixer_get(m, m->hwvol_mixer);
if (level != -1) {
left = level & 0xff;
- right = level >> 8;
+ right = (level >> 8) & 0xff;
left += left_step * m->hwvol_step;
if (left < 0)
left = 0;
+ else if (left > 100)
+ left = 100;
right += right_step * m->hwvol_step;
if (right < 0)
right = 0;
+ else if (right > 100)
+ right = 100;
mixer_set(m, m->hwvol_mixer, left | right << 8);
}
+}
+
+void
+mixer_hwvol_step(device_t dev, int left_step, int right_step)
+{
+ struct snd_mixer *m;
+ struct cdev *pdev;
+
+ pdev = mixer_get_devt(dev);
+ m = pdev->si_drv1;
+ snd_mtxlock(m->lock);
+ mixer_hwvol_step_locked(m, left_step, right_step);
snd_mtxunlock(m->lock);
}
diff --git a/sys/dev/sound/pcm/mixer.h b/sys/dev/sound/pcm/mixer.h
index 22780ab..0fb2e91 100644
--- a/sys/dev/sound/pcm/mixer.h
+++ b/sys/dev/sound/pcm/mixer.h
@@ -40,7 +40,9 @@ int mixer_ioctl_cmd(struct cdev *i_dev, u_long cmd, caddr_t arg, int mode, struc
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 mixer_busy(struct snd_mixer *m);
diff --git a/sys/dev/sound/usb/uaudio.c b/sys/dev/sound/usb/uaudio.c
index cc7128e..4c8f2ba 100644
--- a/sys/dev/sound/usb/uaudio.c
+++ b/sys/dev/sound/usb/uaudio.c
@@ -287,14 +287,17 @@ struct uaudio_hid {
struct usb_xfer *xfer[UAUDIO_HID_N_TRANSFER];
struct hid_location volume_up_loc;
struct hid_location volume_down_loc;
+ struct hid_location mute_loc;
uint32_t flags;
#define UAUDIO_HID_VALID 0x0001
#define UAUDIO_HID_HAS_ID 0x0002
#define UAUDIO_HID_HAS_VOLUME_UP 0x0004
#define UAUDIO_HID_HAS_VOLUME_DOWN 0x0008
+#define UAUDIO_HID_HAS_MUTE 0x0010
uint8_t iface_index;
uint8_t volume_up_id;
uint8_t volume_down_id;
+ uint8_t mute_id;
};
struct uaudio_softc {
@@ -1012,6 +1015,8 @@ uaudio_attach_sub(device_t dev, kobj_class_t mixer_class, kobj_class_t chan_clas
goto detach;
sc->sc_mixer_init = 1;
+ mixer_hwvol_init(dev);
+
snprintf(status, sizeof(status), "at ? %s", PCM_KLDSTRING(snd_uaudio));
if (pcm_register(dev, sc,
@@ -5520,9 +5525,6 @@ uaudio_hid_rx_callback(struct usb_xfer *xfer, usb_error_t error)
struct uaudio_softc *sc = usbd_xfer_softc(xfer);
const uint8_t *buffer = usbd_xfer_get_frame_buffer(xfer, 0);
struct snd_mixer *m;
- int v;
- int v_l;
- int v_r;
uint8_t id;
int actlen;
@@ -5543,6 +5545,16 @@ uaudio_hid_rx_callback(struct usb_xfer *xfer, usb_error_t error)
m = sc->sc_mixer_dev;
+ if ((sc->sc_hid.flags & UAUDIO_HID_HAS_MUTE) &&
+ (sc->sc_hid.mute_id == id) &&
+ hid_get_data(buffer, actlen,
+ &sc->sc_hid.mute_loc)) {
+
+ DPRINTF("Mute toggle\n");
+
+ mixer_hwvol_mute_locked(m);
+ }
+
if ((sc->sc_hid.flags & UAUDIO_HID_HAS_VOLUME_UP) &&
(sc->sc_hid.volume_up_id == id) &&
hid_get_data(buffer, actlen,
@@ -5550,13 +5562,7 @@ uaudio_hid_rx_callback(struct usb_xfer *xfer, usb_error_t error)
DPRINTF("Volume Up\n");
- v = mix_get_locked(m, SOUND_MIXER_PCM, &v_l, &v_r);
- if (v == 0) {
- v = ((v_l + v_r) / 2) + 5;
- if (v > 100)
- v = 100;
- mix_set_locked(m, SOUND_MIXER_PCM, v, v);
- }
+ mixer_hwvol_step_locked(m, 1, 1);
}
if ((sc->sc_hid.flags & UAUDIO_HID_HAS_VOLUME_DOWN) &&
@@ -5566,13 +5572,7 @@ uaudio_hid_rx_callback(struct usb_xfer *xfer, usb_error_t error)
DPRINTF("Volume Down\n");
- v = mix_get_locked(m, SOUND_MIXER_PCM, &v_l, &v_r);
- if (v == 0) {
- v = ((v_l + v_r) / 2) - 5;
- if (v < 0)
- v = 0;
- mix_set_locked(m, SOUND_MIXER_PCM, v, v);
- }
+ mixer_hwvol_step_locked(m, -1, -1);
}
case USB_ST_SETUP:
@@ -5641,10 +5641,20 @@ uaudio_hid_probe(struct uaudio_softc *sc,
DPRINTFN(1, "Found Volume Down key\n");
}
+ if (hid_locate(d_ptr, d_len,
+ HID_USAGE2(HUP_CONSUMER, 0xE2 /* Mute */),
+ hid_input, 0, &sc->sc_hid.mute_loc, &flags,
+ &sc->sc_hid.mute_id)) {
+ if (flags & HIO_VARIABLE)
+ sc->sc_hid.flags |= UAUDIO_HID_HAS_MUTE;
+ DPRINTFN(1, "Found Mute key\n");
+ }
+
free(d_ptr, M_TEMP);
if (!(sc->sc_hid.flags & (UAUDIO_HID_HAS_VOLUME_UP |
- UAUDIO_HID_HAS_VOLUME_DOWN))) {
+ UAUDIO_HID_HAS_VOLUME_DOWN |
+ UAUDIO_HID_HAS_MUTE))) {
DPRINTFN(1, "Did not find any volume related keys\n");
return (-1);
}
OpenPOWER on IntegriCloud