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 @@
/* 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;
......@@ -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 */
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;
......@@ -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)
{
if (mixer->rc_type == RC_NONE)
if (!mixer->rc_cfg)
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;
/*
* 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;
if (urb->status < 0 || urb->actual_length <= offset)
if (urb->status < 0 || urb->actual_length < rc->packet_length)
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 */
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);
......@@ -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;
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;
}
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)
......
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