|
@@ -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 {
|
|
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 {
|
|
|
|
- RC_NONE,
|
|
|
|
- RC_EXTIGY,
|
|
|
|
- RC_AUDIGY2NX,
|
|
|
|
- } rc_type;
|
|
|
|
|
|
+ const struct rc_config *rc_cfg;
|
|
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,
|
|
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,
|
|
struct pt_regs *regs)
|
|
struct pt_regs *regs)
|
|
{
|
|
{
|
|
struct usb_mixer_interface *mixer = urb->context;
|
|
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;
|
|
mixer->rc_code = code;
|
|
wmb();
|
|
wmb();
|
|
wake_up(&mixer->rc_waitq);
|
|
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)
|
|
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) {
|
|
|
|
- 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);
|
|
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);
|
|
if (err < 0)
|
|
if (err < 0)
|