diff options
Diffstat (limited to 'sound/usb')
-rw-r--r-- | sound/usb/6fire/firmware.c | 5 | ||||
-rw-r--r-- | sound/usb/card.h | 4 | ||||
-rw-r--r-- | sound/usb/endpoint.c | 8 | ||||
-rw-r--r-- | sound/usb/helper.c | 5 | ||||
-rw-r--r-- | sound/usb/quirks-table.h | 53 | ||||
-rw-r--r-- | sound/usb/quirks.c | 24 | ||||
-rw-r--r-- | sound/usb/quirks.h | 10 |
7 files changed, 104 insertions, 5 deletions
diff --git a/sound/usb/6fire/firmware.c b/sound/usb/6fire/firmware.c index 56ad923..a1d9b07 100644 --- a/sound/usb/6fire/firmware.c +++ b/sound/usb/6fire/firmware.c @@ -346,11 +346,10 @@ static int usb6fire_fw_check(u8 *version) if (!memcmp(version, known_fw_versions + i, 4)) return 0; - snd_printk(KERN_ERR PREFIX "invalid fimware version in device: " - "%02x %02x %02x %02x. " + snd_printk(KERN_ERR PREFIX "invalid fimware version in device: %*ph. " "please reconnect to power. if this failure " "still happens, check your firmware installation.", - version[0], version[1], version[2], version[3]); + 4, version); return -EINVAL; } diff --git a/sound/usb/card.h b/sound/usb/card.h index 2b9ffff..23b6f23 100644 --- a/sound/usb/card.h +++ b/sound/usb/card.h @@ -92,6 +92,8 @@ struct snd_usb_endpoint { unsigned char silence_value; unsigned int stride; int iface, alt_idx; + int skip_packets; /* quirks for devices to ignore the first n packets + in a stream */ spinlock_t lock; struct list_head list; @@ -115,8 +117,6 @@ struct snd_usb_substream { unsigned int hwptr_done; /* processed byte position in the buffer */ unsigned int transfer_done; /* processed frames since last period update */ - unsigned long active_mask; /* bitmask of active urbs */ - unsigned long unlink_mask; /* bitmask of unlinked urbs */ /* data and sync endpoints for this stream */ unsigned int ep_num; /* the endpoint number */ diff --git a/sound/usb/endpoint.c b/sound/usb/endpoint.c index d6e2bb4..a83a18d 100644 --- a/sound/usb/endpoint.c +++ b/sound/usb/endpoint.c @@ -31,6 +31,7 @@ #include "card.h" #include "endpoint.h" #include "pcm.h" +#include "quirks.h" #define EP_FLAG_ACTIVATED 0 #define EP_FLAG_RUNNING 1 @@ -170,6 +171,11 @@ static void retire_inbound_urb(struct snd_usb_endpoint *ep, { struct urb *urb = urb_ctx->urb; + if (unlikely(ep->skip_packets > 0)) { + ep->skip_packets--; + return; + } + if (ep->sync_slave) snd_usb_handle_sync_urb(ep->sync_slave, ep, urb); @@ -822,6 +828,8 @@ int snd_usb_endpoint_start(struct snd_usb_endpoint *ep, int can_sleep) ep->unlink_mask = 0; ep->phase = 0; + snd_usb_endpoint_start_quirk(ep); + /* * If this endpoint has a data endpoint as implicit feedback source, * don't start the urbs here. Instead, mark them all as available, diff --git a/sound/usb/helper.c b/sound/usb/helper.c index 9eed8f4..c1db28f 100644 --- a/sound/usb/helper.c +++ b/sound/usb/helper.c @@ -21,6 +21,7 @@ #include "usbaudio.h" #include "helper.h" +#include "quirks.h" /* * combine bytes and get an integer value @@ -97,6 +98,10 @@ int snd_usb_ctl_msg(struct usb_device *dev, unsigned int pipe, __u8 request, memcpy(data, buf, size); kfree(buf); } + + snd_usb_ctl_msg_quirk(dev, pipe, request, requesttype, + value, index, data, size); + return err; } diff --git a/sound/usb/quirks-table.h b/sound/usb/quirks-table.h index 79780fa..d73ac9b 100644 --- a/sound/usb/quirks-table.h +++ b/sound/usb/quirks-table.h @@ -2781,6 +2781,59 @@ YAMAHA_DEVICE(0x7010, "UB99"), } }, +/* Microsoft XboxLive Headset/Xbox Communicator */ +{ + USB_DEVICE(0x045e, 0x0283), + .bInterfaceClass = USB_CLASS_PER_INTERFACE, + .driver_info = (unsigned long) &(const struct snd_usb_audio_quirk) { + .vendor_name = "Microsoft", + .product_name = "XboxLive Headset/Xbox Communicator", + .ifnum = QUIRK_ANY_INTERFACE, + .type = QUIRK_COMPOSITE, + .data = &(const struct snd_usb_audio_quirk[]) { + { + /* playback */ + .ifnum = 0, + .type = QUIRK_AUDIO_FIXED_ENDPOINT, + .data = &(const struct audioformat) { + .formats = SNDRV_PCM_FMTBIT_S16_LE, + .channels = 1, + .iface = 0, + .altsetting = 0, + .altset_idx = 0, + .attributes = 0, + .endpoint = 0x04, + .ep_attr = 0x05, + .rates = SNDRV_PCM_RATE_CONTINUOUS, + .rate_min = 22050, + .rate_max = 22050 + } + }, + { + /* capture */ + .ifnum = 1, + .type = QUIRK_AUDIO_FIXED_ENDPOINT, + .data = &(const struct audioformat) { + .formats = SNDRV_PCM_FMTBIT_S16_LE, + .channels = 1, + .iface = 1, + .altsetting = 0, + .altset_idx = 0, + .attributes = 0, + .endpoint = 0x85, + .ep_attr = 0x05, + .rates = SNDRV_PCM_RATE_CONTINUOUS, + .rate_min = 16000, + .rate_max = 16000 + } + }, + { + .ifnum = -1 + } + } + } +}, + { /* * Some USB MIDI devices don't have an audio control interface, diff --git a/sound/usb/quirks.c b/sound/usb/quirks.c index 2781726..0f58b4b 100644 --- a/sound/usb/quirks.c +++ b/sound/usb/quirks.c @@ -761,3 +761,27 @@ void snd_usb_set_format_quirk(struct snd_usb_substream *subs, } } +void snd_usb_endpoint_start_quirk(struct snd_usb_endpoint *ep) +{ + /* + * "Playback Design" products send bogus feedback data at the start + * of the stream. Ignore them. + */ + if ((le16_to_cpu(ep->chip->dev->descriptor.idVendor) == 0x23ba) && + ep->type == SND_USB_ENDPOINT_TYPE_SYNC) + ep->skip_packets = 4; +} + +void snd_usb_ctl_msg_quirk(struct usb_device *dev, unsigned int pipe, + __u8 request, __u8 requesttype, __u16 value, + __u16 index, void *data, __u16 size) +{ + /* + * "Playback Design" products need a 20ms delay after each + * class compliant request + */ + if ((le16_to_cpu(dev->descriptor.idVendor) == 0x23ba) && + (requesttype & USB_TYPE_MASK) == USB_TYPE_CLASS) + mdelay(20); +} + diff --git a/sound/usb/quirks.h b/sound/usb/quirks.h index 03e5e94..0ca9e91 100644 --- a/sound/usb/quirks.h +++ b/sound/usb/quirks.h @@ -1,6 +1,10 @@ #ifndef __USBAUDIO_QUIRKS_H #define __USBAUDIO_QUIRKS_H +struct audioformat; +struct snd_usb_endpoint; +struct snd_usb_substream; + int snd_usb_create_quirk(struct snd_usb_audio *chip, struct usb_interface *iface, struct usb_driver *driver, @@ -20,4 +24,10 @@ void snd_usb_set_format_quirk(struct snd_usb_substream *subs, int snd_usb_is_big_endian_format(struct snd_usb_audio *chip, struct audioformat *fp); +void snd_usb_endpoint_start_quirk(struct snd_usb_endpoint *ep); + +void snd_usb_ctl_msg_quirk(struct usb_device *dev, unsigned int pipe, + __u8 request, __u8 requesttype, __u16 value, + __u16 index, void *data, __u16 size); + #endif /* __USBAUDIO_QUIRKS_H */ |