svn commit: r246454 - in head/sys/dev/sound: pcm usb

Hans Petter Selasky hselasky at FreeBSD.org
Thu Feb 7 08:20:04 UTC 2013


Author: hselasky
Date: Thu Feb  7 08:20:03 2013
New Revision: 246454
URL: http://svnweb.freebsd.org/changeset/base/246454

Log:
  Add support for mute buttons on USB audio devices and
  use the hwvol interface to adjust the mixer settings.
  
  MFC after:	1 week

Modified:
  head/sys/dev/sound/pcm/mixer.c
  head/sys/dev/sound/pcm/mixer.h
  head/sys/dev/sound/usb/uaudio.c

Modified: head/sys/dev/sound/pcm/mixer.c
==============================================================================
--- head/sys/dev/sound/pcm/mixer.c	Thu Feb  7 07:50:16 2013	(r246453)
+++ head/sys/dev/sound/pcm/mixer.c	Thu Feb  7 08:20:03 2013	(r246454)
@@ -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_
 		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);
 }
 

Modified: head/sys/dev/sound/pcm/mixer.h
==============================================================================
--- head/sys/dev/sound/pcm/mixer.h	Thu Feb  7 07:50:16 2013	(r246453)
+++ head/sys/dev/sound/pcm/mixer.h	Thu Feb  7 08:20:03 2013	(r246454)
@@ -40,7 +40,9 @@ int mixer_ioctl_cmd(struct cdev *i_dev, 
 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);

Modified: head/sys/dev/sound/usb/uaudio.c
==============================================================================
--- head/sys/dev/sound/usb/uaudio.c	Thu Feb  7 07:50:16 2013	(r246453)
+++ head/sys/dev/sound/usb/uaudio.c	Thu Feb  7 08:20:03 2013	(r246454)
@@ -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_cla
 		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 *
 	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 *
 
 		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 *
 
 			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 *
 
 			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);
 	}


More information about the svn-src-head mailing list