aboutsummaryrefslogtreecommitdiffstats
path: root/sound
diff options
context:
space:
mode:
authorTakashi Iwai <tiwai@suse.de>2010-05-20 05:59:43 -0400
committerTakashi Iwai <tiwai@suse.de>2010-05-20 05:59:43 -0400
commit9ce3db4e7949a394bad0de91883b5e786c17607a (patch)
tree6b51509ddf78d067d28dc042674f54c1f3434fcd /sound
parent20406f9b67e6fde4fff4639225c7a0e5ea6eaa9b (diff)
parente213e9cf707c51808e372dabd1070a61af17e77b (diff)
Merge branch 'topic/usb' into for-linus
Diffstat (limited to 'sound')
-rw-r--r--sound/usb/mixer.c100
1 files changed, 86 insertions, 14 deletions
diff --git a/sound/usb/mixer.c b/sound/usb/mixer.c
index 21613fe0c1a2..97dd17655104 100644
--- a/sound/usb/mixer.c
+++ b/sound/usb/mixer.c
@@ -656,7 +656,7 @@ static int check_input_term(struct mixer_build *state, int id, struct usb_audio_
656 case UAC_FEATURE_UNIT: { 656 case UAC_FEATURE_UNIT: {
657 /* the header is the same for v1 and v2 */ 657 /* the header is the same for v1 and v2 */
658 struct uac_feature_unit_descriptor *d = p1; 658 struct uac_feature_unit_descriptor *d = p1;
659 id = d->bUnitID; 659 id = d->bSourceID;
660 break; /* continue to parse */ 660 break; /* continue to parse */
661 } 661 }
662 case UAC_MIXER_UNIT: { 662 case UAC_MIXER_UNIT: {
@@ -1443,8 +1443,8 @@ static struct procunit_info procunits[] = {
1443 * predefined data for extension units 1443 * predefined data for extension units
1444 */ 1444 */
1445static struct procunit_value_info clock_rate_xu_info[] = { 1445static struct procunit_value_info clock_rate_xu_info[] = {
1446 { USB_XU_CLOCK_RATE_SELECTOR, "Selector", USB_MIXER_U8, 0 }, 1446 { USB_XU_CLOCK_RATE_SELECTOR, "Selector", USB_MIXER_U8, 0 },
1447 { 0 } 1447 { 0 }
1448}; 1448};
1449static struct procunit_value_info clock_source_xu_info[] = { 1449static struct procunit_value_info clock_source_xu_info[] = {
1450 { USB_XU_CLOCK_SOURCE_SELECTOR, "External", USB_MIXER_BOOLEAN }, 1450 { USB_XU_CLOCK_SOURCE_SELECTOR, "External", USB_MIXER_BOOLEAN },
@@ -1967,26 +1967,98 @@ static void snd_usb_mixer_proc_read(struct snd_info_entry *entry,
1967 } 1967 }
1968} 1968}
1969 1969
1970static void snd_usb_mixer_status_complete(struct urb *urb) 1970static void snd_usb_mixer_interrupt_v2(struct usb_mixer_interface *mixer,
1971 int attribute, int value, int index)
1972{
1973 struct usb_mixer_elem_info *info;
1974 __u8 unitid = (index >> 8) & 0xff;
1975 __u8 control = (value >> 8) & 0xff;
1976 __u8 channel = value & 0xff;
1977
1978 if (channel >= MAX_CHANNELS) {
1979 snd_printk(KERN_DEBUG "%s(): bogus channel number %d\n",
1980 __func__, channel);
1981 return;
1982 }
1983
1984 for (info = mixer->id_elems[unitid]; info; info = info->next_id_elem) {
1985 if (info->control != control)
1986 continue;
1987
1988 switch (attribute) {
1989 case UAC2_CS_CUR:
1990 /* invalidate cache, so the value is read from the device */
1991 if (channel)
1992 info->cached &= ~(1 << channel);
1993 else /* master channel */
1994 info->cached = 0;
1995
1996 snd_ctl_notify(mixer->chip->card, SNDRV_CTL_EVENT_MASK_VALUE,
1997 info->elem_id);
1998 break;
1999
2000 case UAC2_CS_RANGE:
2001 /* TODO */
2002 break;
2003
2004 case UAC2_CS_MEM:
2005 /* TODO */
2006 break;
2007
2008 default:
2009 snd_printk(KERN_DEBUG "unknown attribute %d in interrupt\n",
2010 attribute);
2011 break;
2012 } /* switch */
2013 }
2014}
2015
2016static void snd_usb_mixer_interrupt(struct urb *urb)
1971{ 2017{
1972 struct usb_mixer_interface *mixer = urb->context; 2018 struct usb_mixer_interface *mixer = urb->context;
2019 int len = urb->actual_length;
2020
2021 if (urb->status != 0)
2022 goto requeue;
1973 2023
1974 if (urb->status == 0) { 2024 if (mixer->protocol == UAC_VERSION_1) {
1975 u8 *buf = urb->transfer_buffer; 2025 struct uac1_status_word *status;
1976 int i;
1977 2026
1978 for (i = urb->actual_length; i >= 2; buf += 2, i -= 2) { 2027 for (status = urb->transfer_buffer;
2028 len >= sizeof(*status);
2029 len -= sizeof(*status), status++) {
1979 snd_printd(KERN_DEBUG "status interrupt: %02x %02x\n", 2030 snd_printd(KERN_DEBUG "status interrupt: %02x %02x\n",
1980 buf[0], buf[1]); 2031 status->bStatusType,
2032 status->bOriginator);
2033
1981 /* ignore any notifications not from the control interface */ 2034 /* ignore any notifications not from the control interface */
1982 if ((buf[0] & 0x0f) != 0) 2035 if ((status->bStatusType & UAC1_STATUS_TYPE_ORIG_MASK) !=
2036 UAC1_STATUS_TYPE_ORIG_AUDIO_CONTROL_IF)
1983 continue; 2037 continue;
1984 if (!(buf[0] & 0x40)) 2038
1985 snd_usb_mixer_notify_id(mixer, buf[1]); 2039 if (status->bStatusType & UAC1_STATUS_TYPE_MEM_CHANGED)
2040 snd_usb_mixer_rc_memory_change(mixer, status->bOriginator);
1986 else 2041 else
1987 snd_usb_mixer_rc_memory_change(mixer, buf[1]); 2042 snd_usb_mixer_notify_id(mixer, status->bOriginator);
2043 }
2044 } else { /* UAC_VERSION_2 */
2045 struct uac2_interrupt_data_msg *msg;
2046
2047 for (msg = urb->transfer_buffer;
2048 len >= sizeof(*msg);
2049 len -= sizeof(*msg), msg++) {
2050 /* drop vendor specific and endpoint requests */
2051 if ((msg->bInfo & UAC2_INTERRUPT_DATA_MSG_VENDOR) ||
2052 (msg->bInfo & UAC2_INTERRUPT_DATA_MSG_EP))
2053 continue;
2054
2055 snd_usb_mixer_interrupt_v2(mixer, msg->bAttribute,
2056 le16_to_cpu(msg->wValue),
2057 le16_to_cpu(msg->wIndex));
1988 } 2058 }
1989 } 2059 }
2060
2061requeue:
1990 if (urb->status != -ENOENT && urb->status != -ECONNRESET) { 2062 if (urb->status != -ENOENT && urb->status != -ECONNRESET) {
1991 urb->dev = mixer->chip->dev; 2063 urb->dev = mixer->chip->dev;
1992 usb_submit_urb(urb, GFP_ATOMIC); 2064 usb_submit_urb(urb, GFP_ATOMIC);
@@ -2023,7 +2095,7 @@ static int snd_usb_mixer_status_create(struct usb_mixer_interface *mixer)
2023 usb_fill_int_urb(mixer->urb, mixer->chip->dev, 2095 usb_fill_int_urb(mixer->urb, mixer->chip->dev,
2024 usb_rcvintpipe(mixer->chip->dev, epnum), 2096 usb_rcvintpipe(mixer->chip->dev, epnum),
2025 transfer_buffer, buffer_length, 2097 transfer_buffer, buffer_length,
2026 snd_usb_mixer_status_complete, mixer, ep->bInterval); 2098 snd_usb_mixer_interrupt, mixer, ep->bInterval);
2027 usb_submit_urb(mixer->urb, GFP_KERNEL); 2099 usb_submit_urb(mixer->urb, GFP_KERNEL);
2028 return 0; 2100 return 0;
2029} 2101}