[ALSA] add support for SB Live! 24-Bit External remote control
authorRaimonds Cicans <ray@vardes.lv>
Fri, 5 May 2006 07:49:53 +0000 (09:49 +0200)
committerJaroslav Kysela <perex@suse.cz>
Thu, 22 Jun 2006 19:33:30 +0000 (21:33 +0200)
This patch rewrites the remote control code to use a table for
the peculiarities of the various SB models, and adds support
for a third model.

Signed-off-by: Raimonds Cicans <ray@vardes.lv>
Signed-off-by: Clemens Ladisch <clemens@ladisch.de>
sound/usb/usbmixer.c

index ab921aa9d77a34cac51152440c1a3a20e642797b..491e975a0c87ef8d2a5a820beba42da61150cdac 100644 (file)
 /* ignore error from controls - for debugging */
 /* #define IGNORE_CTL_ERROR */
 
 /* ignore error from controls - for debugging */
 /* #define IGNORE_CTL_ERROR */
 
+/*
+ * Sound Blaster remote control configuration
+ *
+ * format of remote control data:
+ * Extigy:       xx 00
+ * Audigy 2 NX:  06 80 xx 00 00 00
+ * Live! 24-bit: 06 80 xx yy 22 83
+ */
+static const struct rc_config {
+       u32 usb_id;
+       u8  offset;
+       u8  length;
+       u8  packet_length;
+       u8  mute_mixer_id;
+       u32 mute_code;
+} rc_configs[] = {
+       { USB_ID(0x041e, 0x3000), 0, 1, 2,  18, 0x0013 }, /* Extigy       */
+       { USB_ID(0x041e, 0x3020), 2, 1, 6,  18, 0x0013 }, /* Audigy 2 NX  */
+       { USB_ID(0x041e, 0x3040), 2, 2, 6,  2,  0x6e91 }, /* Live! 24-bit */
+};
+
 struct usb_mixer_interface {
        struct snd_usb_audio *chip;
        unsigned int ctrlif;
 struct usb_mixer_interface {
        struct snd_usb_audio *chip;
        unsigned int ctrlif;
@@ -55,11 +76,7 @@ struct usb_mixer_interface {
        struct usb_mixer_elem_info **id_elems; /* array[256], indexed by unit id */
 
        /* Sound Blaster remote control stuff */
        struct usb_mixer_elem_info **id_elems; /* array[256], indexed by unit id */
 
        /* Sound Blaster remote control stuff */
-       enum {
-               RC_NONE,
-               RC_EXTIGY,
-               RC_AUDIGY2NX,
-       } rc_type;
+       const struct rc_config *rc_cfg;
        unsigned long rc_hwdep_open;
        u32 rc_code;
        wait_queue_head_t rc_waitq;
        unsigned long rc_hwdep_open;
        u32 rc_code;
        wait_queue_head_t rc_waitq;
@@ -1647,7 +1664,7 @@ static void snd_usb_mixer_notify_id(struct usb_mixer_interface *mixer,
 static void snd_usb_mixer_memory_change(struct usb_mixer_interface *mixer,
                                        int unitid)
 {
 static void snd_usb_mixer_memory_change(struct usb_mixer_interface *mixer,
                                        int unitid)
 {
-       if (mixer->rc_type == RC_NONE)
+       if (!mixer->rc_cfg)
                return;
        /* unit ids specific to Extigy/Audigy 2 NX: */
        switch (unitid) {
                return;
        /* unit ids specific to Extigy/Audigy 2 NX: */
        switch (unitid) {
@@ -1732,20 +1749,19 @@ static void snd_usb_soundblaster_remote_complete(struct urb *urb,
                                                 struct pt_regs *regs)
 {
        struct usb_mixer_interface *mixer = urb->context;
                                                 struct pt_regs *regs)
 {
        struct usb_mixer_interface *mixer = urb->context;
-       /*
-        * format of remote control data:
-        * Extigy:      xx 00
-        * Audigy 2 NX: 06 80 xx 00 00 00
-        */
-       int offset = mixer->rc_type == RC_EXTIGY ? 0 : 2;
+       const struct rc_config *rc = mixer->rc_cfg;
        u32 code;
 
        u32 code;
 
-       if (urb->status < 0 || urb->actual_length <= offset)
+       if (urb->status < 0 || urb->actual_length < rc->packet_length)
                return;
                return;
-       code = mixer->rc_buffer[offset];
+
+       code = mixer->rc_buffer[rc->offset];
+       if (rc->length == 2)
+               code |= mixer->rc_buffer[rc->offset + 1] << 8;
+
        /* the Mute button actually changes the mixer control */
        /* the Mute button actually changes the mixer control */
-       if (code == 13)
-               snd_usb_mixer_notify_id(mixer, 18);
+       if (code == rc->mute_code)
+               snd_usb_mixer_notify_id(mixer, rc->mute_mixer_id);
        mixer->rc_code = code;
        wmb();
        wake_up(&mixer->rc_waitq);
        mixer->rc_code = code;
        wmb();
        wake_up(&mixer->rc_waitq);
@@ -1801,21 +1817,17 @@ static unsigned int snd_usb_sbrc_hwdep_poll(struct snd_hwdep *hw, struct file *f
 static int snd_usb_soundblaster_remote_init(struct usb_mixer_interface *mixer)
 {
        struct snd_hwdep *hwdep;
 static int snd_usb_soundblaster_remote_init(struct usb_mixer_interface *mixer)
 {
        struct snd_hwdep *hwdep;
-       int err, len;
+       int err, len, i;
 
 
-       switch (mixer->chip->usb_id) {
-       case USB_ID(0x041e, 0x3000):
-               mixer->rc_type = RC_EXTIGY;
-               len = 2;
-               break;
-       case USB_ID(0x041e, 0x3020):
-               mixer->rc_type = RC_AUDIGY2NX;
-               len = 6;
-               break;
-       default:
+       for (i = 0; i < ARRAY_SIZE(rc_configs); ++i)
+               if (rc_configs[i].usb_id == mixer->chip->usb_id)
+                       break;
+       if (i >= ARRAY_SIZE(rc_configs))
                return 0;
                return 0;
-       }
+       mixer->rc_cfg = &rc_configs[i];
 
 
+       len = mixer->rc_cfg->packet_length;
+       
        init_waitqueue_head(&mixer->rc_waitq);
        err = snd_hwdep_new(mixer->chip->card, "SB remote control", 0, &hwdep);
        if (err < 0)
        init_waitqueue_head(&mixer->rc_waitq);
        err = snd_hwdep_new(mixer->chip->card, "SB remote control", 0, &hwdep);
        if (err < 0)