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

[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
Loading
Loading
Loading
Loading
+40 −28
Original line number Diff line number Diff line
@@ -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,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)
{
	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;
	for (i = 0; i < ARRAY_SIZE(rc_configs); ++i)
		if (rc_configs[i].usb_id == mixer->chip->usb_id)
			break;
	default:
	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);