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);
        }
_______________________________________________
svn-src-head@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-head
To unsubscribe, send any mail to "svn-src-head-unsubscr...@freebsd.org"

Reply via email to