Commit 4d1a70da authored by Raimonds Cicans's avatar Raimonds Cicans Committed by Jaroslav Kysela

[ALSA] add support for SB Live! 24-Bit External remote control

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: default avatarRaimonds Cicans <ray@vardes.lv>
Signed-off-by: default avatarClemens Ladisch <clemens@ladisch.de>
parent cab5c4c9
...@@ -46,6 +46,27 @@ ...@@ -46,6 +46,27 @@
/* ignore error from controls - for debugging */ /* ignore error from controls - for debugging */
/* #define IGNORE_CTL_ERROR */ /* #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 usb_mixer_interface {
struct snd_usb_audio *chip; struct snd_usb_audio *chip;
unsigned int ctrlif; unsigned int ctrlif;
...@@ -55,11 +76,7 @@ struct usb_mixer_interface { ...@@ -55,11 +76,7 @@ struct usb_mixer_interface {
struct usb_mixer_elem_info **id_elems; /* array[256], indexed by unit id */ struct usb_mixer_elem_info **id_elems; /* array[256], indexed by unit id */
/* Sound Blaster remote control stuff */ /* Sound Blaster remote control stuff */
enum { const struct rc_config *rc_cfg;
RC_NONE,
RC_EXTIGY,
RC_AUDIGY2NX,
} rc_type;
unsigned long rc_hwdep_open; unsigned long rc_hwdep_open;
u32 rc_code; u32 rc_code;
wait_queue_head_t rc_waitq; wait_queue_head_t rc_waitq;
...@@ -1647,7 +1664,7 @@ static void snd_usb_mixer_notify_id(struct usb_mixer_interface *mixer, ...@@ -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, static void snd_usb_mixer_memory_change(struct usb_mixer_interface *mixer,
int unitid) int unitid)
{ {
if (mixer->rc_type == RC_NONE) if (!mixer->rc_cfg)
return; return;
/* unit ids specific to Extigy/Audigy 2 NX: */ /* unit ids specific to Extigy/Audigy 2 NX: */
switch (unitid) { switch (unitid) {
...@@ -1732,20 +1749,19 @@ static void snd_usb_soundblaster_remote_complete(struct urb *urb, ...@@ -1732,20 +1749,19 @@ static void snd_usb_soundblaster_remote_complete(struct urb *urb,
struct pt_regs *regs) struct pt_regs *regs)
{ {
struct usb_mixer_interface *mixer = urb->context; struct usb_mixer_interface *mixer = urb->context;
/* const struct rc_config *rc = mixer->rc_cfg;
* 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;
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) if (code == rc->mute_code)
snd_usb_mixer_notify_id(mixer, 18); snd_usb_mixer_notify_id(mixer, rc->mute_mixer_id);
mixer->rc_code = code; mixer->rc_code = code;
wmb(); wmb();
wake_up(&mixer->rc_waitq); wake_up(&mixer->rc_waitq);
...@@ -1801,20 +1817,16 @@ static unsigned int snd_usb_sbrc_hwdep_poll(struct snd_hwdep *hw, struct file *f ...@@ -1801,20 +1817,16 @@ 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) static int snd_usb_soundblaster_remote_init(struct usb_mixer_interface *mixer)
{ {
struct snd_hwdep *hwdep; struct snd_hwdep *hwdep;
int err, len; int err, len, i;
switch (mixer->chip->usb_id) { for (i = 0; i < ARRAY_SIZE(rc_configs); ++i)
case USB_ID(0x041e, 0x3000): if (rc_configs[i].usb_id == mixer->chip->usb_id)
mixer->rc_type = RC_EXTIGY;
len = 2;
break; break;
case USB_ID(0x041e, 0x3020): if (i >= ARRAY_SIZE(rc_configs))
mixer->rc_type = RC_AUDIGY2NX;
len = 6;
break;
default:
return 0; return 0;
} mixer->rc_cfg = &rc_configs[i];
len = mixer->rc_cfg->packet_length;
init_waitqueue_head(&mixer->rc_waitq); init_waitqueue_head(&mixer->rc_waitq);
err = snd_hwdep_new(mixer->chip->card, "SB remote control", 0, &hwdep); err = snd_hwdep_new(mixer->chip->card, "SB remote control", 0, &hwdep);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment