diff options
Diffstat (limited to 'sound/usb/usbmixer.c')
| -rw-r--r-- | sound/usb/usbmixer.c | 70 |
1 files changed, 41 insertions, 29 deletions
diff --git a/sound/usb/usbmixer.c b/sound/usb/usbmixer.c index ce86283ee0fa..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) |
| @@ -1998,7 +2010,7 @@ int snd_usb_create_mixer(struct snd_usb_audio *chip, int ctrlif) | |||
| 1998 | if ((err = snd_audigy2nx_controls_create(mixer)) < 0) | 2010 | if ((err = snd_audigy2nx_controls_create(mixer)) < 0) |
| 1999 | goto _error; | 2011 | goto _error; |
| 2000 | if (!snd_card_proc_new(chip->card, "audigy2nx", &entry)) | 2012 | if (!snd_card_proc_new(chip->card, "audigy2nx", &entry)) |
| 2001 | snd_info_set_text_ops(entry, mixer, 1024, | 2013 | snd_info_set_text_ops(entry, mixer, |
| 2002 | snd_audigy2nx_proc_read); | 2014 | snd_audigy2nx_proc_read); |
| 2003 | } | 2015 | } |
| 2004 | 2016 | ||
