upgrade to linux 2.6.10-1.12_FC2
[linux-2.6.git] / sound / usb / usbaudio.c
index 1f3548c..18efa78 100644 (file)
@@ -68,17 +68,16 @@ static int vid[SNDRV_CARDS] = { [0 ... (SNDRV_CARDS-1)] = -1 }; /* Vendor ID for
 static int pid[SNDRV_CARDS] = { [0 ... (SNDRV_CARDS-1)] = -1 }; /* Product ID for this card */
 static int nrpacks = 4;                /* max. number of packets per urb */
 static int async_unlink = 1;
-static int boot_devs;
 
-module_param_array(index, int, boot_devs, 0444);
+module_param_array(index, int, NULL, 0444);
 MODULE_PARM_DESC(index, "Index value for the USB audio adapter.");
-module_param_array(id, charp, boot_devs, 0444);
+module_param_array(id, charp, NULL, 0444);
 MODULE_PARM_DESC(id, "ID string for the USB audio adapter.");
-module_param_array(enable, bool, boot_devs, 0444);
+module_param_array(enable, bool, NULL, 0444);
 MODULE_PARM_DESC(enable, "Enable USB audio adapter.");
-module_param_array(vid, int, boot_devs, 0444);
+module_param_array(vid, int, NULL, 0444);
 MODULE_PARM_DESC(vid, "Vendor ID for the USB audio device.");
-module_param_array(pid, int, boot_devs, 0444);
+module_param_array(pid, int, NULL, 0444);
 MODULE_PARM_DESC(pid, "Product ID for the USB audio device.");
 module_param(nrpacks, int, 0444);
 MODULE_PARM_DESC(nrpacks, "Max. number of packets per URB.");
@@ -726,7 +725,7 @@ static int deactivate_urbs(snd_usb_substream_t *subs, int force, int can_sleep)
        subs->running = 0;
 
        if (!force && subs->stream->chip->shutdown) /* to be sure... */
-               return 0;
+               return -EBADFD;
 
        async = !can_sleep && async_unlink;
 
@@ -737,11 +736,11 @@ static int deactivate_urbs(snd_usb_substream_t *subs, int force, int can_sleep)
                if (test_bit(i, &subs->active_mask)) {
                        if (! test_and_set_bit(i, &subs->unlink_mask)) {
                                struct urb *u = subs->dataurb[i].urb;
-                               if (async)
+                               if (async) {
                                        u->transfer_flags |= URB_ASYNC_UNLINK;
-                               else
-                                       u->transfer_flags &= ~URB_ASYNC_UNLINK;
-                               usb_unlink_urb(u);
+                                       usb_unlink_urb(u);
+                               } else
+                                       usb_kill_urb(u);
                        }
                }
        }
@@ -750,11 +749,11 @@ static int deactivate_urbs(snd_usb_substream_t *subs, int force, int can_sleep)
                        if (test_bit(i+16, &subs->active_mask)) {
                                if (! test_and_set_bit(i+16, &subs->unlink_mask)) {
                                        struct urb *u = subs->syncurb[i].urb;
-                                       if (async)
+                                       if (async) {
                                                u->transfer_flags |= URB_ASYNC_UNLINK;
-                                       else
-                                               u->transfer_flags &= ~URB_ASYNC_UNLINK;
-                                       usb_unlink_urb(u);
+                                               usb_unlink_urb(u);
+                                       } else
+                                               usb_kill_urb(u);
                                }
                        }
                }
@@ -771,6 +770,9 @@ static int start_urbs(snd_usb_substream_t *subs, snd_pcm_runtime_t *runtime)
        unsigned int i;
        int err;
 
+       if (subs->stream->chip->shutdown)
+               return -EBADFD;
+
        for (i = 0; i < subs->nurbs; i++) {
                snd_assert(subs->dataurb[i].urb, return -EINVAL);
                if (subs->ops.prepare(subs, runtime, subs->dataurb[i].urb) < 0) {
@@ -2747,12 +2749,13 @@ static int create_standard_interface_quirk(snd_usb_audio_t *chip,
 }
 
 /*
- * Create a stream for an Edirol UA-700 interface.  The only way
+ * Create a stream for an Edirol UA-700/UA-25 interface.  The only way
  * to detect the sample rate is by looking at wMaxPacketSize.
  */
-static int create_ua700_quirk(snd_usb_audio_t *chip, struct usb_interface *iface)
+static int create_ua700_ua25_quirk(snd_usb_audio_t *chip,
+                                  struct usb_interface *iface)
 {
-       static const struct audioformat ua700_format = {
+       static const struct audioformat ua_format = {
                .format = SNDRV_PCM_FORMAT_S24_3LE,
                .channels = 2,
                .fmt_type = USB_FORMAT_TYPE_I,
@@ -2772,15 +2775,28 @@ static int create_ua700_quirk(snd_usb_audio_t *chip, struct usb_interface *iface
        altsd = get_iface_desc(alts);
 
        if (altsd->bNumEndpoints == 2) {
-               static const snd_usb_midi_endpoint_info_t ep = {
+               static const snd_usb_midi_endpoint_info_t ua700_ep = {
                        .out_cables = 0x0003,
                        .in_cables  = 0x0003
                };
-               static const snd_usb_audio_quirk_t quirk = {
+               static const snd_usb_audio_quirk_t ua700_quirk = {
+                       .type = QUIRK_MIDI_FIXED_ENDPOINT,
+                       .data = &ua700_ep
+               };
+               static const snd_usb_midi_endpoint_info_t ua25_ep = {
+                       .out_cables = 0x0001,
+                       .in_cables  = 0x0001
+               };
+               static const snd_usb_audio_quirk_t ua25_quirk = {
                        .type = QUIRK_MIDI_FIXED_ENDPOINT,
-                       .data = &ep
+                       .data = &ua25_ep
                };
-               return snd_usb_create_midi_interface(chip, iface, &quirk);
+               if (chip->dev->descriptor.idProduct == 0x002b)
+                       return snd_usb_create_midi_interface(chip, iface,
+                                                            &ua700_quirk);
+               else
+                       return snd_usb_create_midi_interface(chip, iface,
+                                                            &ua25_quirk);
        }
 
        if (altsd->bNumEndpoints != 1)
@@ -2789,7 +2805,7 @@ static int create_ua700_quirk(snd_usb_audio_t *chip, struct usb_interface *iface
        fp = kmalloc(sizeof(*fp), GFP_KERNEL);
        if (!fp)
                return -ENOMEM;
-       memcpy(fp, &ua700_format, sizeof(*fp));
+       memcpy(fp, &ua_format, sizeof(*fp));
 
        fp->iface = altsd->bInterfaceNumber;
        fp->endpoint = get_endpoint(alts, 0)->bEndpointAddress;
@@ -2801,9 +2817,11 @@ static int create_ua700_quirk(snd_usb_audio_t *chip, struct usb_interface *iface
                fp->rate_max = fp->rate_min = 44100;
                break;
        case 0x138:
+       case 0x140:
                fp->rate_max = fp->rate_min = 48000;
                break;
        case 0x258:
+       case 0x260:
                fp->rate_max = fp->rate_min = 96000;
                break;
        default:
@@ -2823,6 +2841,56 @@ static int create_ua700_quirk(snd_usb_audio_t *chip, struct usb_interface *iface
        return 0;
 }
 
+/*
+ * Create a stream for an Edirol UA-1000 interface.
+ */
+static int create_ua1000_quirk(snd_usb_audio_t *chip, struct usb_interface *iface)
+{
+       static const struct audioformat ua1000_format = {
+               .format = SNDRV_PCM_FORMAT_S32_LE,
+               .fmt_type = USB_FORMAT_TYPE_I,
+               .altsetting = 1,
+               .altset_idx = 1,
+               .attributes = 0,
+               .rates = SNDRV_PCM_RATE_CONTINUOUS,
+       };
+       struct usb_host_interface *alts;
+       struct usb_interface_descriptor *altsd;
+       struct audioformat *fp;
+       int stream, err;
+
+       if (iface->num_altsetting != 2)
+               return -ENXIO;
+       alts = &iface->altsetting[1];
+       altsd = get_iface_desc(alts);
+       if (alts->extralen != 11 || alts->extra[1] != CS_AUDIO_INTERFACE ||
+           altsd->bNumEndpoints != 1)
+               return -ENXIO;
+
+       fp = kmalloc(sizeof(*fp), GFP_KERNEL);
+       if (!fp)
+               return -ENOMEM;
+       memcpy(fp, &ua1000_format, sizeof(*fp));
+
+       fp->channels = alts->extra[4];
+       fp->iface = altsd->bInterfaceNumber;
+       fp->endpoint = get_endpoint(alts, 0)->bEndpointAddress;
+       fp->ep_attr = get_endpoint(alts, 0)->bmAttributes;
+       fp->maxpacksize = get_endpoint(alts, 0)->wMaxPacketSize;
+       fp->rate_max = fp->rate_min = combine_triple(&alts->extra[8]);
+
+       stream = (fp->endpoint & USB_DIR_IN)
+               ? SNDRV_PCM_STREAM_CAPTURE : SNDRV_PCM_STREAM_PLAYBACK;
+       err = add_audio_endpoint(chip, stream, fp);
+       if (err < 0) {
+               kfree(fp);
+               return err;
+       }
+       /* FIXME: playback must be synchronized to capture */
+       usb_set_interface(chip->dev, fp->iface, 0);
+       return 0;
+}
+
 static int snd_usb_create_quirk(snd_usb_audio_t *chip,
                                struct usb_interface *iface,
                                const snd_usb_audio_quirk_t *quirk);
@@ -2910,8 +2978,10 @@ static int snd_usb_create_quirk(snd_usb_audio_t *chip,
        case QUIRK_AUDIO_STANDARD_INTERFACE:
        case QUIRK_MIDI_STANDARD_INTERFACE:
                return create_standard_interface_quirk(chip, iface, quirk);
-       case QUIRK_AUDIO_EDIROL_UA700:
-               return create_ua700_quirk(chip, iface);
+       case QUIRK_AUDIO_EDIROL_UA700_UA25:
+               return create_ua700_ua25_quirk(chip, iface);
+       case QUIRK_AUDIO_EDIROL_UA1000:
+               return create_ua1000_quirk(chip, iface);
        default:
                snd_printd(KERN_ERR "invalid quirk type %d\n", quirk->type);
                return -ENXIO;