diff options
Diffstat (limited to 'sound/usb')
-rw-r--r-- | sound/usb/usbmixer.c | 68 |
1 files changed, 40 insertions, 28 deletions
diff --git a/sound/usb/usbmixer.c b/sound/usb/usbmixer.c index ab921aa9d77a..491e975a0c87 100644 --- a/sound/usb/usbmixer.c +++ b/sound/usb/usbmixer.c | |||
@@ -46,6 +46,27 @@ | |||
46 | /* ignore error from controls - for debugging */ | 46 | /* ignore error from controls - for debugging */ |
47 | /* #define IGNORE_CTL_ERROR */ | 47 | /* #define IGNORE_CTL_ERROR */ |
48 | 48 | ||
49 | /* | ||
50 | * Sound Blaster remote control configuration | ||
51 | * | ||
52 | * format of remote control data: | ||
53 | * Extigy: xx 00 | ||
54 | * Audigy 2 NX: 06 80 xx 00 00 00 | ||
55 | * Live! 24-bit: 06 80 xx yy 22 83 | ||
56 | */ | ||
57 | static const struct rc_config { | ||
58 | u32 usb_id; | ||
59 | u8 offset; | ||
60 | u8 length; | ||
61 | u8 packet_length; | ||
62 | u8 mute_mixer_id; | ||
63 | u32 mute_code; | ||
64 | } rc_configs[] = { | ||
65 | { USB_ID(0x041e, 0x3000), 0, 1, 2, 18, 0x0013 }, /* Extigy */ | ||
66 | { USB_ID(0x041e, 0x3020), 2, 1, 6, 18, 0x0013 }, /* Audigy 2 NX */ | ||
67 | { USB_ID(0x041e, 0x3040), 2, 2, 6, 2, 0x6e91 }, /* Live! 24-bit */ | ||
68 | }; | ||
69 | |||
49 | struct usb_mixer_interface { | 70 | struct usb_mixer_interface { |
50 | struct snd_usb_audio *chip; | 71 | struct snd_usb_audio *chip; |
51 | unsigned int ctrlif; | 72 | unsigned int ctrlif; |
@@ -55,11 +76,7 @@ struct usb_mixer_interface { | |||
55 | struct usb_mixer_elem_info **id_elems; /* array[256], indexed by unit id */ | 76 | struct usb_mixer_elem_info **id_elems; /* array[256], indexed by unit id */ |
56 | 77 | ||
57 | /* Sound Blaster remote control stuff */ | 78 | /* Sound Blaster remote control stuff */ |
58 | enum { | 79 | const struct rc_config *rc_cfg; |
59 | RC_NONE, | ||
60 | RC_EXTIGY, | ||
61 | RC_AUDIGY2NX, | ||
62 | } rc_type; | ||
63 | unsigned long rc_hwdep_open; | 80 | unsigned long rc_hwdep_open; |
64 | u32 rc_code; | 81 | u32 rc_code; |
65 | wait_queue_head_t rc_waitq; | 82 | wait_queue_head_t rc_waitq; |
@@ -1647,7 +1664,7 @@ static void snd_usb_mixer_notify_id(struct usb_mixer_interface *mixer, | |||
1647 | static void snd_usb_mixer_memory_change(struct usb_mixer_interface *mixer, | 1664 | static void snd_usb_mixer_memory_change(struct usb_mixer_interface *mixer, |
1648 | int unitid) | 1665 | int unitid) |
1649 | { | 1666 | { |
1650 | if (mixer->rc_type == RC_NONE) | 1667 | if (!mixer->rc_cfg) |
1651 | return; | 1668 | return; |
1652 | /* unit ids specific to Extigy/Audigy 2 NX: */ | 1669 | /* unit ids specific to Extigy/Audigy 2 NX: */ |
1653 | switch (unitid) { | 1670 | switch (unitid) { |
@@ -1732,20 +1749,19 @@ static void snd_usb_soundblaster_remote_complete(struct urb *urb, | |||
1732 | struct pt_regs *regs) | 1749 | struct pt_regs *regs) |
1733 | { | 1750 | { |
1734 | struct usb_mixer_interface *mixer = urb->context; | 1751 | struct usb_mixer_interface *mixer = urb->context; |
1735 | /* | 1752 | const struct rc_config *rc = mixer->rc_cfg; |
1736 | * format of remote control data: | ||
1737 | * Extigy: xx 00 | ||
1738 | * Audigy 2 NX: 06 80 xx 00 00 00 | ||
1739 | */ | ||
1740 | int offset = mixer->rc_type == RC_EXTIGY ? 0 : 2; | ||
1741 | u32 code; | 1753 | u32 code; |
1742 | 1754 | ||
1743 | if (urb->status < 0 || urb->actual_length <= offset) | 1755 | if (urb->status < 0 || urb->actual_length < rc->packet_length) |
1744 | return; | 1756 | return; |
1745 | code = mixer->rc_buffer[offset]; | 1757 | |
1758 | code = mixer->rc_buffer[rc->offset]; | ||
1759 | if (rc->length == 2) | ||
1760 | code |= mixer->rc_buffer[rc->offset + 1] << 8; | ||
1761 | |||
1746 | /* the Mute button actually changes the mixer control */ | 1762 | /* the Mute button actually changes the mixer control */ |
1747 | if (code == 13) | 1763 | if (code == rc->mute_code) |
1748 | snd_usb_mixer_notify_id(mixer, 18); | 1764 | snd_usb_mixer_notify_id(mixer, rc->mute_mixer_id); |
1749 | mixer->rc_code = code; | 1765 | mixer->rc_code = code; |
1750 | wmb(); | 1766 | wmb(); |
1751 | wake_up(&mixer->rc_waitq); | 1767 | wake_up(&mixer->rc_waitq); |
@@ -1801,21 +1817,17 @@ static unsigned int snd_usb_sbrc_hwdep_poll(struct snd_hwdep *hw, struct file *f | |||
1801 | static int snd_usb_soundblaster_remote_init(struct usb_mixer_interface *mixer) | 1817 | static int snd_usb_soundblaster_remote_init(struct usb_mixer_interface *mixer) |
1802 | { | 1818 | { |
1803 | struct snd_hwdep *hwdep; | 1819 | struct snd_hwdep *hwdep; |
1804 | int err, len; | 1820 | int err, len, i; |
1805 | 1821 | ||
1806 | switch (mixer->chip->usb_id) { | 1822 | for (i = 0; i < ARRAY_SIZE(rc_configs); ++i) |
1807 | case USB_ID(0x041e, 0x3000): | 1823 | if (rc_configs[i].usb_id == mixer->chip->usb_id) |
1808 | mixer->rc_type = RC_EXTIGY; | 1824 | break; |
1809 | len = 2; | 1825 | if (i >= ARRAY_SIZE(rc_configs)) |
1810 | break; | ||
1811 | case USB_ID(0x041e, 0x3020): | ||
1812 | mixer->rc_type = RC_AUDIGY2NX; | ||
1813 | len = 6; | ||
1814 | break; | ||
1815 | default: | ||
1816 | return 0; | 1826 | return 0; |
1817 | } | 1827 | mixer->rc_cfg = &rc_configs[i]; |
1818 | 1828 | ||
1829 | len = mixer->rc_cfg->packet_length; | ||
1830 | |||
1819 | init_waitqueue_head(&mixer->rc_waitq); | 1831 | init_waitqueue_head(&mixer->rc_waitq); |
1820 | err = snd_hwdep_new(mixer->chip->card, "SB remote control", 0, &hwdep); | 1832 | err = snd_hwdep_new(mixer->chip->card, "SB remote control", 0, &hwdep); |
1821 | if (err < 0) | 1833 | if (err < 0) |