ALSA: usb-audio: fix endianness bug in snd_nativeinstruments_*
[linux-2.6.git] / sound / usb / quirks.c
index 77762c9..b7fa802 100644 (file)
@@ -34,6 +34,7 @@
 #include "endpoint.h"
 #include "pcm.h"
 #include "clock.h"
+#include "stream.h"
 
 /*
  * handle the quirks for the contained interfaces
@@ -106,7 +107,7 @@ static int create_standard_audio_quirk(struct snd_usb_audio *chip,
 
        alts = &iface->altsetting[0];
        altsd = get_iface_desc(alts);
-       err = snd_usb_parse_audio_endpoints(chip, altsd->bInterfaceNumber);
+       err = snd_usb_parse_audio_interface(chip, altsd->bInterfaceNumber);
        if (err < 0) {
                snd_printk(KERN_ERR "cannot setup if %d: error %d\n",
                           altsd->bInterfaceNumber, err);
@@ -131,23 +132,27 @@ static int create_fixed_stream_quirk(struct snd_usb_audio *chip,
        unsigned *rate_table = NULL;
 
        fp = kmemdup(quirk->data, sizeof(*fp), GFP_KERNEL);
-       if (! fp) {
+       if (!fp) {
                snd_printk(KERN_ERR "cannot memdup\n");
                return -ENOMEM;
        }
+       if (fp->nr_rates > MAX_NR_RATES) {
+               kfree(fp);
+               return -EINVAL;
+       }
        if (fp->nr_rates > 0) {
-               rate_table = kmalloc(sizeof(int) * fp->nr_rates, GFP_KERNEL);
+               rate_table = kmemdup(fp->rate_table,
+                                    sizeof(int) * fp->nr_rates, GFP_KERNEL);
                if (!rate_table) {
                        kfree(fp);
                        return -ENOMEM;
                }
-               memcpy(rate_table, fp->rate_table, sizeof(int) * fp->nr_rates);
                fp->rate_table = rate_table;
        }
 
        stream = (fp->endpoint & USB_DIR_IN)
                ? SNDRV_PCM_STREAM_CAPTURE : SNDRV_PCM_STREAM_PLAYBACK;
-       err = snd_usb_add_audio_endpoint(chip, stream, fp);
+       err = snd_usb_add_audio_stream(chip, stream, fp);
        if (err < 0) {
                kfree(fp);
                kfree(rate_table);
@@ -223,10 +228,9 @@ static int create_uaxx_quirk(struct snd_usb_audio *chip,
        if (altsd->bNumEndpoints != 1)
                return -ENXIO;
 
-       fp = kmalloc(sizeof(*fp), GFP_KERNEL);
+       fp = kmemdup(&ua_format, sizeof(*fp), GFP_KERNEL);
        if (!fp)
                return -ENOMEM;
-       memcpy(fp, &ua_format, sizeof(*fp));
 
        fp->iface = altsd->bInterfaceNumber;
        fp->endpoint = get_endpoint(alts, 0)->bEndpointAddress;
@@ -254,7 +258,7 @@ static int create_uaxx_quirk(struct snd_usb_audio *chip,
 
        stream = (fp->endpoint & USB_DIR_IN)
                ? SNDRV_PCM_STREAM_CAPTURE : SNDRV_PCM_STREAM_PLAYBACK;
-       err = snd_usb_add_audio_endpoint(chip, stream, fp);
+       err = snd_usb_add_audio_stream(chip, stream, fp);
        if (err < 0) {
                kfree(fp);
                return err;
@@ -306,6 +310,7 @@ int snd_usb_create_quirk(struct snd_usb_audio *chip,
                [QUIRK_MIDI_EMAGIC] = create_any_midi_quirk,
                [QUIRK_MIDI_CME] = create_any_midi_quirk,
                [QUIRK_MIDI_AKAI] = create_any_midi_quirk,
+               [QUIRK_MIDI_FTDI] = create_any_midi_quirk,
                [QUIRK_AUDIO_STANDARD_INTERFACE] = create_standard_audio_quirk,
                [QUIRK_AUDIO_FIXED_ENDPOINT] = create_fixed_stream_quirk,
                [QUIRK_AUDIO_EDIROL_UAXX] = create_uaxx_quirk,
@@ -338,7 +343,7 @@ static int snd_usb_extigy_boot_quirk(struct usb_device *dev, struct usb_interfac
                snd_printdd("sending Extigy boot sequence...\n");
                /* Send message to force it to reconnect with full interface. */
                err = snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev,0),
-                                     0x10, 0x43, 0x0001, 0x000a, NULL, 0, 1000);
+                                     0x10, 0x43, 0x0001, 0x000a, NULL, 0);
                if (err < 0) snd_printdd("error sending boot message: %d\n", err);
                err = usb_get_descriptor(dev, USB_DT_DEVICE, 0,
                                &dev->descriptor, sizeof(dev->descriptor));
@@ -359,11 +364,11 @@ static int snd_usb_audigy2nx_boot_quirk(struct usb_device *dev)
 
        snd_usb_ctl_msg(dev, usb_rcvctrlpipe(dev, 0), 0x2a,
                        USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_OTHER,
-                       0, 0, &buf, 1, 1000);
+                       0, 0, &buf, 1);
        if (buf == 0) {
                snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), 0x29,
                                USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_OTHER,
-                               1, 2000, NULL, 0, 1000);
+                               1, 2000, NULL, 0);
                return -ENODEV;
        }
        return 0;
@@ -382,11 +387,13 @@ static int snd_usb_fasttrackpro_boot_quirk(struct usb_device *dev)
                 * rules
                 */
                err = usb_driver_set_configuration(dev, 2);
-               if (err < 0) {
+               if (err < 0)
                        snd_printdd("error usb_driver_set_configuration: %d\n",
                                    err);
-                       return -ENODEV;
-               }
+               /* Always return an error, so that we stop creating a device
+                  that will just be destroyed and recreated with a new
+                  configuration */
+               return -ENODEV;
        } else
                snd_printk(KERN_INFO "usb-audio: Fast Track Pro config OK\n");
 
@@ -406,7 +413,7 @@ static int snd_usb_cm106_write_int_reg(struct usb_device *dev, int reg, u16 valu
        buf[3] = reg;
        return snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), USB_REQ_SET_CONFIGURATION,
                               USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_ENDPOINT,
-                              0, 0, &buf, 4, 1000);
+                              0, 0, &buf, 4);
 }
 
 static int snd_usb_cm106_boot_quirk(struct usb_device *dev)
@@ -426,7 +433,7 @@ static int snd_usb_cm106_boot_quirk(struct usb_device *dev)
  */
 static int snd_usb_cm6206_boot_quirk(struct usb_device *dev)
 {
-       int err, reg;
+       int err  = 0, reg;
        int val[] = {0x2004, 0x3000, 0xf800, 0x143f, 0x0000, 0x3000};
 
        for (reg = 0; reg < ARRAY_SIZE(val); reg++) {
@@ -479,7 +486,7 @@ static int snd_usb_nativeinstruments_boot_quirk(struct usb_device *dev)
 {
        int ret = usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
                                  0xaf, USB_TYPE_VENDOR | USB_RECIP_DEVICE,
-                                 cpu_to_le16(1), 0, NULL, 0, 1000);
+                                 1, 0, NULL, 0, 1000);
 
        if (ret < 0)
                return ret;