aboutsummaryrefslogtreecommitdiffstats
path: root/sound/usb/card.c
diff options
context:
space:
mode:
authorDaniel Mack <daniel@caiaq.de>2010-03-04 13:46:13 -0500
committerTakashi Iwai <tiwai@suse.de>2010-03-05 02:17:14 -0500
commite5779998bf8b70e48a6cc208c8b61b33bd6117ea (patch)
tree512568f0fc4b81eac8019522c10df5b81483bcca /sound/usb/card.c
parent3e1aebef6fb55e35668d2d7cf608cf03f30c904f (diff)
ALSA: usb-audio: refactor code
Clean up the usb audio driver by factoring out a lot of functions to separate files. Code for procfs, quirks, urbs, format parsers etc all got a new home now. Moved almost all special quirk handling to quirks.c and introduced new generic functions to handle them, so the exceptions do not pollute the whole driver. Renamed usbaudio.c to card.c because this is what it actually does now. Renamed usbmidi.c to midi.c for namespace clarity. Removed more things from usbaudio.h. The non-standard drivers were adopted accordingly. Signed-off-by: Daniel Mack <daniel@caiaq.de> Cc: Clemens Ladisch <clemens@ladisch.de> Signed-off-by: Takashi Iwai <tiwai@suse.de>
Diffstat (limited to 'sound/usb/card.c')
-rw-r--r--sound/usb/card.c648
1 files changed, 648 insertions, 0 deletions
diff --git a/sound/usb/card.c b/sound/usb/card.c
new file mode 100644
index 000000000000..426aabc729d9
--- /dev/null
+++ b/sound/usb/card.c
@@ -0,0 +1,648 @@
1/*
2 * (Tentative) USB Audio Driver for ALSA
3 *
4 * Copyright (c) 2002 by Takashi Iwai <tiwai@suse.de>
5 *
6 * Many codes borrowed from audio.c by
7 * Alan Cox (alan@lxorguk.ukuu.org.uk)
8 * Thomas Sailer (sailer@ife.ee.ethz.ch)
9 *
10 *
11 * This program is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License as published by
13 * the Free Software Foundation; either version 2 of the License, or
14 * (at your option) any later version.
15 *
16 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
20 *
21 * You should have received a copy of the GNU General Public License
22 * along with this program; if not, write to the Free Software
23 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
24 *
25 *
26 * NOTES:
27 *
28 * - async unlink should be used for avoiding the sleep inside lock.
29 * 2.4.22 usb-uhci seems buggy for async unlinking and results in
30 * oops. in such a cse, pass async_unlink=0 option.
31 * - the linked URBs would be preferred but not used so far because of
32 * the instability of unlinking.
33 * - type II is not supported properly. there is no device which supports
34 * this type *correctly*. SB extigy looks as if it supports, but it's
35 * indeed an AC3 stream packed in SPDIF frames (i.e. no real AC3 stream).
36 */
37
38
39#include <linux/bitops.h>
40#include <linux/init.h>
41#include <linux/list.h>
42#include <linux/slab.h>
43#include <linux/string.h>
44#include <linux/usb.h>
45#include <linux/moduleparam.h>
46#include <linux/mutex.h>
47#include <linux/usb/audio.h>
48
49#include <sound/core.h>
50#include <sound/info.h>
51#include <sound/pcm.h>
52#include <sound/pcm_params.h>
53#include <sound/initval.h>
54
55#include "usbaudio.h"
56#include "card.h"
57#include "midi.h"
58#include "usbmixer.h"
59#include "proc.h"
60#include "quirks.h"
61#include "endpoint.h"
62#include "helper.h"
63#include "debug.h"
64#include "pcm.h"
65#include "urb.h"
66#include "format.h"
67
68MODULE_AUTHOR("Takashi Iwai <tiwai@suse.de>");
69MODULE_DESCRIPTION("USB Audio");
70MODULE_LICENSE("GPL");
71MODULE_SUPPORTED_DEVICE("{{Generic,USB Audio}}");
72
73
74static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; /* Index 0-MAX */
75static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; /* ID for this card */
76static int enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP;/* Enable this card */
77/* Vendor/product IDs for this card */
78static int vid[SNDRV_CARDS] = { [0 ... (SNDRV_CARDS-1)] = -1 };
79static int pid[SNDRV_CARDS] = { [0 ... (SNDRV_CARDS-1)] = -1 };
80static int nrpacks = 8; /* max. number of packets per urb */
81static int async_unlink = 1;
82static int device_setup[SNDRV_CARDS]; /* device parameter for this card */
83static int ignore_ctl_error;
84
85module_param_array(index, int, NULL, 0444);
86MODULE_PARM_DESC(index, "Index value for the USB audio adapter.");
87module_param_array(id, charp, NULL, 0444);
88MODULE_PARM_DESC(id, "ID string for the USB audio adapter.");
89module_param_array(enable, bool, NULL, 0444);
90MODULE_PARM_DESC(enable, "Enable USB audio adapter.");
91module_param_array(vid, int, NULL, 0444);
92MODULE_PARM_DESC(vid, "Vendor ID for the USB audio device.");
93module_param_array(pid, int, NULL, 0444);
94MODULE_PARM_DESC(pid, "Product ID for the USB audio device.");
95module_param(nrpacks, int, 0644);
96MODULE_PARM_DESC(nrpacks, "Max. number of packets per URB.");
97module_param(async_unlink, bool, 0444);
98MODULE_PARM_DESC(async_unlink, "Use async unlink mode.");
99module_param_array(device_setup, int, NULL, 0444);
100MODULE_PARM_DESC(device_setup, "Specific device setup (if needed).");
101module_param(ignore_ctl_error, bool, 0444);
102MODULE_PARM_DESC(ignore_ctl_error,
103 "Ignore errors from USB controller for mixer interfaces.");
104
105/*
106 * we keep the snd_usb_audio_t instances by ourselves for merging
107 * the all interfaces on the same card as one sound device.
108 */
109
110static DEFINE_MUTEX(register_mutex);
111static struct snd_usb_audio *usb_chip[SNDRV_CARDS];
112static struct usb_driver usb_audio_driver;
113
114/*
115 * disconnect streams
116 * called from snd_usb_audio_disconnect()
117 */
118static void snd_usb_stream_disconnect(struct list_head *head)
119{
120 int idx;
121 struct snd_usb_stream *as;
122 struct snd_usb_substream *subs;
123
124 as = list_entry(head, struct snd_usb_stream, list);
125 for (idx = 0; idx < 2; idx++) {
126 subs = &as->substream[idx];
127 if (!subs->num_formats)
128 return;
129 snd_usb_release_substream_urbs(subs, 1);
130 subs->interface = -1;
131 }
132}
133
134static int snd_usb_create_stream(struct snd_usb_audio *chip, int ctrlif, int interface)
135{
136 struct usb_device *dev = chip->dev;
137 struct usb_host_interface *alts;
138 struct usb_interface_descriptor *altsd;
139 struct usb_interface *iface = usb_ifnum_to_if(dev, interface);
140
141 if (!iface) {
142 snd_printk(KERN_ERR "%d:%u:%d : does not exist\n",
143 dev->devnum, ctrlif, interface);
144 return -EINVAL;
145 }
146
147 if (usb_interface_claimed(iface)) {
148 snd_printdd(KERN_INFO "%d:%d:%d: skipping, already claimed\n",
149 dev->devnum, ctrlif, interface);
150 return -EINVAL;
151 }
152
153 alts = &iface->altsetting[0];
154 altsd = get_iface_desc(alts);
155 if ((altsd->bInterfaceClass == USB_CLASS_AUDIO ||
156 altsd->bInterfaceClass == USB_CLASS_VENDOR_SPEC) &&
157 altsd->bInterfaceSubClass == USB_SUBCLASS_MIDISTREAMING) {
158 int err = snd_usbmidi_create(chip->card, iface,
159 &chip->midi_list, NULL);
160 if (err < 0) {
161 snd_printk(KERN_ERR "%d:%u:%d: cannot create sequencer device\n",
162 dev->devnum, ctrlif, interface);
163 return -EINVAL;
164 }
165 usb_driver_claim_interface(&usb_audio_driver, iface, (void *)-1L);
166
167 return 0;
168 }
169
170 if ((altsd->bInterfaceClass != USB_CLASS_AUDIO &&
171 altsd->bInterfaceClass != USB_CLASS_VENDOR_SPEC) ||
172 altsd->bInterfaceSubClass != USB_SUBCLASS_AUDIOSTREAMING) {
173 snd_printdd(KERN_ERR "%d:%u:%d: skipping non-supported interface %d\n",
174 dev->devnum, ctrlif, interface, altsd->bInterfaceClass);
175 /* skip non-supported classes */
176 return -EINVAL;
177 }
178
179 if (snd_usb_get_speed(dev) == USB_SPEED_LOW) {
180 snd_printk(KERN_ERR "low speed audio streaming not supported\n");
181 return -EINVAL;
182 }
183
184 if (! snd_usb_parse_audio_endpoints(chip, interface)) {
185 usb_set_interface(dev, interface, 0); /* reset the current interface */
186 usb_driver_claim_interface(&usb_audio_driver, iface, (void *)-1L);
187 return -EINVAL;
188 }
189
190 return 0;
191}
192
193/*
194 * parse audio control descriptor and create pcm/midi streams
195 */
196static int snd_usb_create_streams(struct snd_usb_audio *chip, int ctrlif)
197{
198 struct usb_device *dev = chip->dev;
199 struct usb_host_interface *host_iface;
200 struct usb_interface_descriptor *altsd;
201 void *control_header;
202 int i, protocol;
203
204 /* find audiocontrol interface */
205 host_iface = &usb_ifnum_to_if(dev, ctrlif)->altsetting[0];
206 control_header = snd_usb_find_csint_desc(host_iface->extra,
207 host_iface->extralen,
208 NULL, UAC_HEADER);
209 altsd = get_iface_desc(host_iface);
210 protocol = altsd->bInterfaceProtocol;
211
212 if (!control_header) {
213 snd_printk(KERN_ERR "cannot find UAC_HEADER\n");
214 return -EINVAL;
215 }
216
217 switch (protocol) {
218 case UAC_VERSION_1: {
219 struct uac_ac_header_descriptor_v1 *h1 = control_header;
220
221 if (!h1->bInCollection) {
222 snd_printk(KERN_INFO "skipping empty audio interface (v1)\n");
223 return -EINVAL;
224 }
225
226 if (h1->bLength < sizeof(*h1) + h1->bInCollection) {
227 snd_printk(KERN_ERR "invalid UAC_HEADER (v1)\n");
228 return -EINVAL;
229 }
230
231 for (i = 0; i < h1->bInCollection; i++)
232 snd_usb_create_stream(chip, ctrlif, h1->baInterfaceNr[i]);
233
234 break;
235 }
236
237 case UAC_VERSION_2: {
238 struct uac_clock_source_descriptor *cs;
239 struct usb_interface_assoc_descriptor *assoc =
240 usb_ifnum_to_if(dev, ctrlif)->intf_assoc;
241
242 if (!assoc) {
243 snd_printk(KERN_ERR "Audio class v2 interfaces need an interface association\n");
244 return -EINVAL;
245 }
246
247 /* FIXME: for now, we expect there is at least one clock source
248 * descriptor and we always take the first one.
249 * We should properly support devices with multiple clock sources,
250 * clock selectors and sample rate conversion units. */
251
252 cs = snd_usb_find_csint_desc(host_iface->extra, host_iface->extralen,
253 NULL, UAC_CLOCK_SOURCE);
254
255 if (!cs) {
256 snd_printk(KERN_ERR "CLOCK_SOURCE descriptor not found\n");
257 return -EINVAL;
258 }
259
260 chip->clock_id = cs->bClockID;
261
262 for (i = 0; i < assoc->bInterfaceCount; i++) {
263 int intf = assoc->bFirstInterface + i;
264
265 if (intf != ctrlif)
266 snd_usb_create_stream(chip, ctrlif, intf);
267 }
268
269 break;
270 }
271
272 default:
273 snd_printk(KERN_ERR "unknown protocol version 0x%02x\n", protocol);
274 return -EINVAL;
275 }
276
277 return 0;
278}
279
280/*
281 * free the chip instance
282 *
283 * here we have to do not much, since pcm and controls are already freed
284 *
285 */
286
287static int snd_usb_audio_free(struct snd_usb_audio *chip)
288{
289 kfree(chip);
290 return 0;
291}
292
293static int snd_usb_audio_dev_free(struct snd_device *device)
294{
295 struct snd_usb_audio *chip = device->device_data;
296 return snd_usb_audio_free(chip);
297}
298
299
300/*
301 * create a chip instance and set its names.
302 */
303static int snd_usb_audio_create(struct usb_device *dev, int idx,
304 const struct snd_usb_audio_quirk *quirk,
305 struct snd_usb_audio **rchip)
306{
307 struct snd_card *card;
308 struct snd_usb_audio *chip;
309 int err, len;
310 char component[14];
311 static struct snd_device_ops ops = {
312 .dev_free = snd_usb_audio_dev_free,
313 };
314
315 *rchip = NULL;
316
317 if (snd_usb_get_speed(dev) != USB_SPEED_LOW &&
318 snd_usb_get_speed(dev) != USB_SPEED_FULL &&
319 snd_usb_get_speed(dev) != USB_SPEED_HIGH) {
320 snd_printk(KERN_ERR "unknown device speed %d\n", snd_usb_get_speed(dev));
321 return -ENXIO;
322 }
323
324 err = snd_card_create(index[idx], id[idx], THIS_MODULE, 0, &card);
325 if (err < 0) {
326 snd_printk(KERN_ERR "cannot create card instance %d\n", idx);
327 return err;
328 }
329
330 chip = kzalloc(sizeof(*chip), GFP_KERNEL);
331 if (! chip) {
332 snd_card_free(card);
333 return -ENOMEM;
334 }
335
336 chip->index = idx;
337 chip->dev = dev;
338 chip->card = card;
339 chip->setup = device_setup[idx];
340 chip->nrpacks = nrpacks;
341 chip->async_unlink = async_unlink;
342
343 chip->usb_id = USB_ID(le16_to_cpu(dev->descriptor.idVendor),
344 le16_to_cpu(dev->descriptor.idProduct));
345 INIT_LIST_HEAD(&chip->pcm_list);
346 INIT_LIST_HEAD(&chip->midi_list);
347 INIT_LIST_HEAD(&chip->mixer_list);
348
349 if ((err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops)) < 0) {
350 snd_usb_audio_free(chip);
351 snd_card_free(card);
352 return err;
353 }
354
355 strcpy(card->driver, "USB-Audio");
356 sprintf(component, "USB%04x:%04x",
357 USB_ID_VENDOR(chip->usb_id), USB_ID_PRODUCT(chip->usb_id));
358 snd_component_add(card, component);
359
360 /* retrieve the device string as shortname */
361 if (quirk && quirk->product_name) {
362 strlcpy(card->shortname, quirk->product_name, sizeof(card->shortname));
363 } else {
364 if (!dev->descriptor.iProduct ||
365 usb_string(dev, dev->descriptor.iProduct,
366 card->shortname, sizeof(card->shortname)) <= 0) {
367 /* no name available from anywhere, so use ID */
368 sprintf(card->shortname, "USB Device %#04x:%#04x",
369 USB_ID_VENDOR(chip->usb_id),
370 USB_ID_PRODUCT(chip->usb_id));
371 }
372 }
373
374 /* retrieve the vendor and device strings as longname */
375 if (quirk && quirk->vendor_name) {
376 len = strlcpy(card->longname, quirk->vendor_name, sizeof(card->longname));
377 } else {
378 if (dev->descriptor.iManufacturer)
379 len = usb_string(dev, dev->descriptor.iManufacturer,
380 card->longname, sizeof(card->longname));
381 else
382 len = 0;
383 /* we don't really care if there isn't any vendor string */
384 }
385 if (len > 0)
386 strlcat(card->longname, " ", sizeof(card->longname));
387
388 strlcat(card->longname, card->shortname, sizeof(card->longname));
389
390 len = strlcat(card->longname, " at ", sizeof(card->longname));
391
392 if (len < sizeof(card->longname))
393 usb_make_path(dev, card->longname + len, sizeof(card->longname) - len);
394
395 strlcat(card->longname,
396 snd_usb_get_speed(dev) == USB_SPEED_LOW ? ", low speed" :
397 snd_usb_get_speed(dev) == USB_SPEED_FULL ? ", full speed" :
398 ", high speed",
399 sizeof(card->longname));
400
401 snd_usb_audio_create_proc(chip);
402
403 *rchip = chip;
404 return 0;
405}
406
407/*
408 * probe the active usb device
409 *
410 * note that this can be called multiple times per a device, when it
411 * includes multiple audio control interfaces.
412 *
413 * thus we check the usb device pointer and creates the card instance
414 * only at the first time. the successive calls of this function will
415 * append the pcm interface to the corresponding card.
416 */
417static void *snd_usb_audio_probe(struct usb_device *dev,
418 struct usb_interface *intf,
419 const struct usb_device_id *usb_id)
420{
421 const struct snd_usb_audio_quirk *quirk = (const struct snd_usb_audio_quirk *)usb_id->driver_info;
422 int i, err;
423 struct snd_usb_audio *chip;
424 struct usb_host_interface *alts;
425 int ifnum;
426 u32 id;
427
428 alts = &intf->altsetting[0];
429 ifnum = get_iface_desc(alts)->bInterfaceNumber;
430 id = USB_ID(le16_to_cpu(dev->descriptor.idVendor),
431 le16_to_cpu(dev->descriptor.idProduct));
432 if (quirk && quirk->ifnum >= 0 && ifnum != quirk->ifnum)
433 goto __err_val;
434
435 if (snd_usb_apply_boot_quirk(dev, intf, quirk) < 0)
436 goto __err_val;
437
438 /*
439 * found a config. now register to ALSA
440 */
441
442 /* check whether it's already registered */
443 chip = NULL;
444 mutex_lock(&register_mutex);
445 for (i = 0; i < SNDRV_CARDS; i++) {
446 if (usb_chip[i] && usb_chip[i]->dev == dev) {
447 if (usb_chip[i]->shutdown) {
448 snd_printk(KERN_ERR "USB device is in the shutdown state, cannot create a card instance\n");
449 goto __error;
450 }
451 chip = usb_chip[i];
452 break;
453 }
454 }
455 if (! chip) {
456 /* it's a fresh one.
457 * now look for an empty slot and create a new card instance
458 */
459 for (i = 0; i < SNDRV_CARDS; i++)
460 if (enable[i] && ! usb_chip[i] &&
461 (vid[i] == -1 || vid[i] == USB_ID_VENDOR(id)) &&
462 (pid[i] == -1 || pid[i] == USB_ID_PRODUCT(id))) {
463 if (snd_usb_audio_create(dev, i, quirk, &chip) < 0) {
464 goto __error;
465 }
466 snd_card_set_dev(chip->card, &intf->dev);
467 break;
468 }
469 if (!chip) {
470 printk(KERN_ERR "no available usb audio device\n");
471 goto __error;
472 }
473 }
474
475 chip->txfr_quirk = 0;
476 err = 1; /* continue */
477 if (quirk && quirk->ifnum != QUIRK_NO_INTERFACE) {
478 /* need some special handlings */
479 if ((err = snd_usb_create_quirk(chip, intf, &usb_audio_driver, quirk)) < 0)
480 goto __error;
481 }
482
483 if (err > 0) {
484 /* create normal USB audio interfaces */
485 if (snd_usb_create_streams(chip, ifnum) < 0 ||
486 snd_usb_create_mixer(chip, ifnum, ignore_ctl_error) < 0) {
487 goto __error;
488 }
489 }
490
491 /* we are allowed to call snd_card_register() many times */
492 if (snd_card_register(chip->card) < 0) {
493 goto __error;
494 }
495
496 usb_chip[chip->index] = chip;
497 chip->num_interfaces++;
498 mutex_unlock(&register_mutex);
499 return chip;
500
501 __error:
502 if (chip && !chip->num_interfaces)
503 snd_card_free(chip->card);
504 mutex_unlock(&register_mutex);
505 __err_val:
506 return NULL;
507}
508
509/*
510 * we need to take care of counter, since disconnection can be called also
511 * many times as well as usb_audio_probe().
512 */
513static void snd_usb_audio_disconnect(struct usb_device *dev, void *ptr)
514{
515 struct snd_usb_audio *chip;
516 struct snd_card *card;
517 struct list_head *p;
518
519 if (ptr == (void *)-1L)
520 return;
521
522 chip = ptr;
523 card = chip->card;
524 mutex_lock(&register_mutex);
525 chip->shutdown = 1;
526 chip->num_interfaces--;
527 if (chip->num_interfaces <= 0) {
528 snd_card_disconnect(card);
529 /* release the pcm resources */
530 list_for_each(p, &chip->pcm_list) {
531 snd_usb_stream_disconnect(p);
532 }
533 /* release the midi resources */
534 list_for_each(p, &chip->midi_list) {
535 snd_usbmidi_disconnect(p);
536 }
537 /* release mixer resources */
538 list_for_each(p, &chip->mixer_list) {
539 snd_usb_mixer_disconnect(p);
540 }
541 usb_chip[chip->index] = NULL;
542 mutex_unlock(&register_mutex);
543 snd_card_free_when_closed(card);
544 } else {
545 mutex_unlock(&register_mutex);
546 }
547}
548
549/*
550 * new 2.5 USB kernel API
551 */
552static int usb_audio_probe(struct usb_interface *intf,
553 const struct usb_device_id *id)
554{
555 void *chip;
556 chip = snd_usb_audio_probe(interface_to_usbdev(intf), intf, id);
557 if (chip) {
558 usb_set_intfdata(intf, chip);
559 return 0;
560 } else
561 return -EIO;
562}
563
564static void usb_audio_disconnect(struct usb_interface *intf)
565{
566 snd_usb_audio_disconnect(interface_to_usbdev(intf),
567 usb_get_intfdata(intf));
568}
569
570#ifdef CONFIG_PM
571static int usb_audio_suspend(struct usb_interface *intf, pm_message_t message)
572{
573 struct snd_usb_audio *chip = usb_get_intfdata(intf);
574 struct list_head *p;
575 struct snd_usb_stream *as;
576
577 if (chip == (void *)-1L)
578 return 0;
579
580 snd_power_change_state(chip->card, SNDRV_CTL_POWER_D3hot);
581 if (!chip->num_suspended_intf++) {
582 list_for_each(p, &chip->pcm_list) {
583 as = list_entry(p, struct snd_usb_stream, list);
584 snd_pcm_suspend_all(as->pcm);
585 }
586 }
587
588 return 0;
589}
590
591static int usb_audio_resume(struct usb_interface *intf)
592{
593 struct snd_usb_audio *chip = usb_get_intfdata(intf);
594
595 if (chip == (void *)-1L)
596 return 0;
597 if (--chip->num_suspended_intf)
598 return 0;
599 /*
600 * ALSA leaves material resumption to user space
601 * we just notify
602 */
603
604 snd_power_change_state(chip->card, SNDRV_CTL_POWER_D0);
605
606 return 0;
607}
608#endif /* CONFIG_PM */
609
610static struct usb_device_id usb_audio_ids [] = {
611#include "quirks-table.h"
612 { .match_flags = (USB_DEVICE_ID_MATCH_INT_CLASS | USB_DEVICE_ID_MATCH_INT_SUBCLASS),
613 .bInterfaceClass = USB_CLASS_AUDIO,
614 .bInterfaceSubClass = USB_SUBCLASS_AUDIOCONTROL },
615 { } /* Terminating entry */
616};
617
618MODULE_DEVICE_TABLE (usb, usb_audio_ids);
619
620/*
621 * entry point for linux usb interface
622 */
623
624static struct usb_driver usb_audio_driver = {
625 .name = "snd-usb-audio",
626 .probe = usb_audio_probe,
627 .disconnect = usb_audio_disconnect,
628 .suspend = usb_audio_suspend,
629 .resume = usb_audio_resume,
630 .id_table = usb_audio_ids,
631};
632
633static int __init snd_usb_audio_init(void)
634{
635 if (nrpacks < 1 || nrpacks > MAX_PACKS) {
636 printk(KERN_WARNING "invalid nrpacks value.\n");
637 return -EINVAL;
638 }
639 return usb_register(&usb_audio_driver);
640}
641
642static void __exit snd_usb_audio_cleanup(void)
643{
644 usb_deregister(&usb_audio_driver);
645}
646
647module_init(snd_usb_audio_init);
648module_exit(snd_usb_audio_cleanup);