diff --git a/include/sound/version.h b/include/sound/version.h index bafde4fbc0703666a53c198d16f6b66f3090b3fa..ba48af7a3099e9817ddc54bf028419f975cb793f 100644 --- a/include/sound/version.h +++ b/include/sound/version.h @@ -1,3 +1,3 @@ /* include/version.h. Generated automatically by configure. */ #define CONFIG_SND_VERSION "0.9.0rc3" -#define CONFIG_SND_DATE " (Tue Oct 01 14:40:23 2002 UTC)" +#define CONFIG_SND_DATE " (Fri Oct 04 13:09:13 2002 UTC)" diff --git a/sound/core/info.c b/sound/core/info.c index 750bf080115e9cc5554f4fd3bab9e05075fb630a..96dbae13331d91a509aa76b7287f51c7d925ba19 100644 --- a/sound/core/info.c +++ b/sound/core/info.c @@ -960,7 +960,6 @@ void snd_info_free_device(snd_info_entry_t * entry) { #ifdef CONFIG_DEVFS_FS char dname[32]; - devfs_handle_t master; #endif snd_runtime_check(entry, return); @@ -970,12 +969,7 @@ void snd_info_free_device(snd_info_entry_t * entry) #ifdef CONFIG_DEVFS_FS if (entry->p && strncmp(entry->name, "controlC", 8)) { sprintf(dname, "snd/%s", entry->name); -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,3,0) - master = devfs_find_handle(NULL, dname, strlen(dname), 0, 0, DEVFS_SPECIAL_CHR, 0); - devfs_unregister(master); -#else devfs_find_and_unregister(NULL, dname, 0, 0, DEVFS_SPECIAL_CHR, 0); -#endif } #endif snd_info_free_entry(entry); diff --git a/sound/core/sound.c b/sound/core/sound.c index 7fbf2bd70dfb4b21fbe4131667c9da600ad15b3e..6a7056336c57967de186a519dda740ba9e922a73 100644 --- a/sound/core/sound.c +++ b/sound/core/sound.c @@ -358,21 +358,12 @@ static int __init alsa_sound_init(void) static void __exit alsa_sound_exit(void) { #ifdef CONFIG_DEVFS_FS - devfs_handle_t master; char controlname[24]; short controlnum; for (controlnum = 0; controlnum < snd_cards_limit; controlnum++) { sprintf(controlname, "snd/controlC%d", controlnum); -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,3,0) - master = devfs_find_handle(NULL, controlname, strlen(controlname), 0, 0, DEVFS_SPECIAL_CHR, 0); - devfs_unregister(master); -#elif LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) - master = devfs_find_handle(NULL, controlname, 0, 0, DEVFS_SPECIAL_CHR, 0); - devfs_unregister(master); -#else devfs_find_and_unregister(NULL, controlname, 0, 0, DEVFS_SPECIAL_CHR, 0); -#endif } #endif diff --git a/sound/pci/Config.in b/sound/pci/Config.in index 4f7cb24ec97a579c7e90b80f6a26ccd242fe3247..e020e40443387a9a91aabd838d7e15a950f96bd1 100644 --- a/sound/pci/Config.in +++ b/sound/pci/Config.in @@ -7,7 +7,7 @@ dep_tristate 'ALi PCI Audio M5451' CONFIG_SND_ALI5451 $CONFIG_SND dep_tristate 'Cirrus Logic (Sound Fusion) CS4280/CS461x/CS462x/CS463x' CONFIG_SND_CS46XX $CONFIG_SND dep_mbool ' Cirrus Logic (Sound Fusion) New DSP support (EXPERIMENTAL)' CONFIG_SND_CS46XX_NEW_DSP $CONFIG_SND_CS46XX $CONFIG_EXPERIMENTAL dep_tristate 'Cirrus Logic (Sound Fusion) CS4281' CONFIG_SND_CS4281 $CONFIG_SND -dep_tristate 'EMU10K1 (SB Live!, E-mu APS)' CONFIG_SND_EMU10K1 $CONFIG_SND +dep_tristate 'EMU10K1 (SB Live! & Audigy, E-mu APS)' CONFIG_SND_EMU10K1 $CONFIG_SND dep_tristate 'Korg 1212 IO' CONFIG_SND_KORG1212 $CONFIG_SND dep_tristate 'NeoMagic NM256AV/ZX' CONFIG_SND_NM256 $CONFIG_SND dep_tristate 'RME Digi32, 32/8, 32 PRO' CONFIG_SND_RME32 $CONFIG_SND @@ -25,7 +25,7 @@ dep_tristate 'ESS ES1968/1978 (Maestro-1/2/2E)' CONFIG_SND_ES1968 $CONFIG_SND dep_tristate 'ESS Allegro/Maestro3' CONFIG_SND_MAESTRO3 $CONFIG_SND dep_tristate 'ForteMedia FM801' CONFIG_SND_FM801 $CONFIG_SND dep_tristate 'ICEnsemble ICE1712 (Envy24)' CONFIG_SND_ICE1712 $CONFIG_SND -dep_tristate 'Intel i810/i820/i830/i840/MX440 integrated audio' CONFIG_SND_INTEL8X0 $CONFIG_SND +dep_tristate 'Intel i8x0/MX440, SiS 7012; Ali 5455; NForce Audio; AMD768/8111' CONFIG_SND_INTEL8X0 $CONFIG_SND dep_tristate 'S3 SonicVibes' CONFIG_SND_SONICVIBES $CONFIG_SND dep_tristate 'VIA 82C686A/B, 8233 South Bridge' CONFIG_SND_VIA82XX $CONFIG_SND diff --git a/sound/pci/cs46xx/dsp_spos.c b/sound/pci/cs46xx/dsp_spos.c index ac8cf40803ba0779d5f6a59b7a22bd572cb1a4c7..c2c120bc77940a1ce69dbdffd31f16a36562f375 100644 --- a/sound/pci/cs46xx/dsp_spos.c +++ b/sound/pci/cs46xx/dsp_spos.c @@ -1577,7 +1577,6 @@ int cs46xx_dsp_disable_spdif_out (cs46xx_t *chip) int cs46xx_dsp_enable_spdif_in (cs46xx_t *chip) { dsp_spos_instance_t * ins = chip->dsp_spos_instance; - unsigned int flags; /* turn on amplifier */ chip->active_ctrl(chip, 1); diff --git a/sound/pci/cs46xx/dsp_spos_scb_lib.c b/sound/pci/cs46xx/dsp_spos_scb_lib.c index 4edfd66ced929c13e0b6aeec3957025c4419d9b6..28a6dfa0b5510c1ec9df4eb2a732c14fe4186c10 100644 --- a/sound/pci/cs46xx/dsp_spos_scb_lib.c +++ b/sound/pci/cs46xx/dsp_spos_scb_lib.c @@ -1410,7 +1410,6 @@ int cs46xx_src_link(cs46xx_t *chip,dsp_scb_descriptor_t * src) { dsp_spos_instance_t * ins = chip->dsp_spos_instance; dsp_scb_descriptor_t * parent_scb; - unsigned int flags; snd_assert (src->parent_scb_ptr == NULL, return -EINVAL ); snd_assert(ins->master_mix_scb !=NULL, return -EINVAL ); diff --git a/sound/sound_core.c b/sound/sound_core.c index 3fa15e955e195d7fbee9179ae74e52f471e70f02..728ffff4135fca72a5fdd699d4e05d8547a13244 100644 --- a/sound/sound_core.c +++ b/sound/sound_core.c @@ -122,7 +122,7 @@ static int __sound_insert_unit(struct sound_unit * s, struct sound_unit **list, * Remove a node from the chain. Called with the lock asserted */ -static void __sound_remove_unit(struct sound_unit **list, int unit) +static struct sound_unit *__sound_remove_unit(struct sound_unit **list, int unit) { while(*list) { @@ -130,13 +130,12 @@ static void __sound_remove_unit(struct sound_unit **list, int unit) if(p->unit_minor==unit) { *list=p->next; - devfs_unregister (p->de); - kfree(p); - return; + return p; } list=&(p->next); } printk(KERN_ERR "Sound device %d went missing!\n", unit); + return NULL; } /* @@ -189,9 +188,15 @@ static int sound_insert_unit(struct sound_unit **list, struct file_operations *f static void sound_remove_unit(struct sound_unit **list, int unit) { + struct sound_unit *p; + spin_lock(&sound_loader_lock); - __sound_remove_unit(list, unit); + p = __sound_remove_unit(list, unit); spin_unlock(&sound_loader_lock); + if (p) { + devfs_unregister (p->de); + kfree(p); + } } /* diff --git a/sound/usb/usbaudio.c b/sound/usb/usbaudio.c index 67b4ffc6934e33004114ae815fbfe3b9faad6bfa..a71a1586543e990f6cc1df62ae0932d6341024e7 100644 --- a/sound/usb/usbaudio.c +++ b/sound/usb/usbaudio.c @@ -284,6 +284,16 @@ static int prepare_capture_urb(snd_usb_substream_t *subs, urb->transfer_buffer = ctx->buf; urb->transfer_buffer_length = offs; urb->interval = 1; +#if 0 // for check + if (! urb->bandwidth) { + int bustime; + bustime = usb_check_bandwidth(urb->dev, urb); + if (bustime < 0) + return bustime; + printk("urb %d: bandwidth = %d (packets = %d)\n", ctx->index, bustime, urb->number_of_packets); + usb_claim_bandwidth(urb->dev, urb, bustime, 1); + } +#endif // for check return 0; } @@ -305,8 +315,10 @@ static int retire_capture_urb(snd_usb_substream_t *subs, for (i = 0; i < urb->number_of_packets; i++) { cp = (unsigned char *)urb->transfer_buffer + urb->iso_frame_desc[i].offset; - if (urb->iso_frame_desc[i].status) /* active? hmm, skip this */ - continue; + if (urb->iso_frame_desc[i].status) { + snd_printd(KERN_ERR "frame %d active: %d\n", i, urb->iso_frame_desc[i].status); + // continue; + } len = urb->iso_frame_desc[i].actual_length / stride; if (! len) continue; @@ -1009,6 +1021,7 @@ static int set_format(snd_usb_substream_t *subs, snd_pcm_runtime_t *runtime) } /* if endpoint has sampling rate control, set it */ if (fmt->attributes & EP_CS_ATTR_SAMPLE_RATE) { + int crate; data[0] = runtime->rate; data[1] = runtime->rate >> 8; data[2] = runtime->rate >> 16; @@ -1026,8 +1039,11 @@ static int set_format(snd_usb_substream_t *subs, snd_pcm_runtime_t *runtime) dev->devnum, subs->interface, fmt->altsetting, ep); return err; } - runtime->rate = data[0] | (data[1] << 8) | (data[2] << 16); - // printk("ok, getting back rate to %d\n", runtime->rate); + crate = data[0] | (data[1] << 8) | (data[2] << 16); + if (crate != runtime->rate) { + snd_printd(KERN_WARNING "current rate %d is different from the runtime rate %d\n", crate, runtime->rate); + // runtime->rate = crate; + } } /* always fill max packet size */ if (fmt->attributes & EP_CS_ATTR_FILL_MAX) @@ -1292,14 +1308,14 @@ void *snd_usb_find_csint_desc(void *buffer, int buflen, void *after, u8 dsubtype * entry point for linux usb interface */ -#ifndef OLD_USB +#ifdef OLD_USB +static void * usb_audio_probe(struct usb_device *dev, unsigned int ifnum, + const struct usb_device_id *id); +static void usb_audio_disconnect(struct usb_device *dev, void *ptr); +#else static int usb_audio_probe(struct usb_interface *intf, const struct usb_device_id *id); static void usb_audio_disconnect(struct usb_interface *intf); -#else -static void * usb_audio_probe(usb_device *dev, unsigned int ifnum, - const struct usb_device_id *id); -static void usb_audio_disconnect(struct usb_device *dev, void *ptr); #endif static struct usb_device_id usb_audio_ids [] = { @@ -1810,7 +1826,8 @@ static int parse_audio_endpoints(snd_usb_audio_t *chip, unsigned char *buffer, i * parse audio control descriptor and create pcm/midi streams */ -static int snd_usb_create_midi_interface(snd_usb_audio_t *chip, int ifnum, +static int snd_usb_create_midi_interface(snd_usb_audio_t *chip, + struct usb_interface *iface, const snd_usb_audio_quirk_t *quirk); static int snd_usb_create_streams(snd_usb_audio_t *chip, int ctrlif, @@ -1850,7 +1867,7 @@ static int snd_usb_create_streams(snd_usb_audio_t *chip, int ctrlif, } if (iface->altsetting[0].bInterfaceClass == USB_CLASS_AUDIO && iface->altsetting[0].bInterfaceSubClass == USB_SUBCLASS_MIDI_STREAMING) { - if (snd_usb_create_midi_interface(chip, j, NULL) < 0) { + if (snd_usb_create_midi_interface(chip, iface, NULL) < 0) { snd_printk(KERN_ERR "%d:%u:%d: cannot create sequencer device\n", dev->devnum, ctrlif, j); continue; } @@ -1871,7 +1888,8 @@ static int snd_usb_create_streams(snd_usb_audio_t *chip, int ctrlif, return 0; } -static int snd_usb_create_midi_interface(snd_usb_audio_t *chip, int ifnum, +static int snd_usb_create_midi_interface(snd_usb_audio_t *chip, + struct usb_interface *iface, const snd_usb_audio_quirk_t *quirk) { #if defined(CONFIG_SND_SEQUENCER) || defined(CONFIG_SND_SEQUENCER_MODULE) @@ -1888,18 +1906,20 @@ static int snd_usb_create_midi_interface(snd_usb_audio_t *chip, int ifnum, strcpy(seq_device->name, chip->card->shortname); umidi = (snd_usb_midi_t *)SNDRV_SEQ_DEVICE_ARGPTR(seq_device); umidi->chip = chip; - umidi->ifnum = ifnum; + umidi->iface = iface; + umidi->ifnum = iface->altsetting->bInterfaceNumber; umidi->quirk = quirk; umidi->seq_client = -1; #endif return 0; } -static inline int snd_usb_create_quirk(snd_usb_audio_t *chip, int ifnum, +static inline int snd_usb_create_quirk(snd_usb_audio_t *chip, + struct usb_interface *iface, const snd_usb_audio_quirk_t *quirk) { /* in the future, there may be quirks for PCM devices */ - return snd_usb_create_midi_interface(chip, ifnum, quirk); + return snd_usb_create_midi_interface(chip, iface, quirk); } @@ -2050,27 +2070,18 @@ static int alloc_desc_buffer(struct usb_device *dev, int index, unsigned char ** * only at the first time. the successive calls of this function will * append the pcm interface to the corresponding card. */ -#ifndef OLD_USB -static int usb_audio_probe(struct usb_interface *intf, - const struct usb_device_id *id) -#else -static void *usb_audio_probe(struct usb_device *dev, unsigned int ifnum, - const struct usb_device_id *id) -#endif +static void *snd_usb_audio_probe(struct usb_device *dev, + struct usb_interface *intf, + const struct usb_device_id *id) { -#ifndef OLD_USB - struct usb_device *dev = interface_to_usbdev(intf); - int ifnum = intf->altsetting->bInterfaceNumber; -#endif struct usb_config_descriptor *config = dev->actconfig; const snd_usb_audio_quirk_t *quirk = (const snd_usb_audio_quirk_t *)id->driver_info; - unsigned char *buffer; - unsigned int index; - int i, buflen; + int i; snd_card_t *card; snd_usb_audio_t *chip; + int ifnum = intf->altsetting->bInterfaceNumber; - if (quirk && ifnum != quirk->ifnum) + if (quirk && quirk->ifnum != QUIRK_ANY_INTERFACE && ifnum != quirk->ifnum) goto __err_val; if (usb_set_configuration(dev, config->bConfigurationValue) < 0) { @@ -2078,11 +2089,6 @@ static void *usb_audio_probe(struct usb_device *dev, unsigned int ifnum, goto __err_val; } - index = dev->actconfig - config; - buflen = alloc_desc_buffer(dev, index, &buffer); - if (buflen <= 0) - goto __err_val; - /* * found a config. now register to ALSA */ @@ -2124,12 +2130,24 @@ static void *usb_audio_probe(struct usb_device *dev, unsigned int ifnum, } if (!quirk) { - if (snd_usb_create_streams(chip, ifnum, buffer, buflen) < 0) + /* USB audio interface */ + unsigned char *buffer; + unsigned int index; + int buflen; + + index = dev->actconfig - config; + buflen = alloc_desc_buffer(dev, index, &buffer); + if (buflen <= 0) goto __error; - if (snd_usb_create_mixer(chip, ifnum, buffer, buflen) < 0) + if (snd_usb_create_streams(chip, ifnum, buffer, buflen) < 0 || + snd_usb_create_mixer(chip, ifnum, buffer, buflen) < 0) { + kfree(buffer); goto __error; + } + kfree(buffer); } else { - if (snd_usb_create_quirk(chip, ifnum, quirk) < 0) + /* USB midi interface */ + if (snd_usb_create_quirk(chip, intf, quirk) < 0) goto __error; } @@ -2142,38 +2160,20 @@ static void *usb_audio_probe(struct usb_device *dev, unsigned int ifnum, chip->num_interfaces++; up(®ister_mutex); - kfree(buffer); -#ifndef OLD_USB - return 0; -#else return chip; -#endif __error: up(®ister_mutex); - kfree(buffer); __err_val: -#ifndef OLD_USB - return -EIO; -#else return NULL; -#endif } - /* * we need to take care of counter, since disconnection can be called also * many times as well as usb_audio_probe(). */ -#ifndef OLD_USB -static void usb_audio_disconnect(struct usb_interface *intf) -#else -static void usb_audio_disconnect(struct usb_device *dev, void *ptr) -#endif +static void snd_usb_audio_disconnect(struct usb_device *dev, void *ptr) { -#ifndef OLD_USB - void *ptr = dev_get_drvdata(&intf->dev); -#endif snd_usb_audio_t *chip; if (ptr == (void *)-1) @@ -2185,6 +2185,49 @@ static void usb_audio_disconnect(struct usb_device *dev, void *ptr) snd_card_free(chip->card); } + +#ifdef OLD_USB + +/* + * 2.4 USB kernel API + */ +static void *usb_audio_probe(struct usb_device *dev, unsigned int ifnum, + const struct usb_device_id *id) +{ + return snd_usb_audio_probe(dev, usb_ifnum_to_if(dev, ifnum), id); +} + +static void usb_audio_disconnect(struct usb_device *dev, void *ptr) +{ + snd_usb_audio_disconnect(dev, ptr); +} + +#else + +/* + * new 2.5 USB kernel API + */ +static int usb_audio_probe(struct usb_interface *intf, + const struct usb_device_id *id) +{ + void *chip; + chip = snd_usb_audio_probe(interface_to_usbdev(intf), intf, id); + if (chip) { + dev_set_drvdata(&intf->dev, chip); + return 0; + } else + return -EIO; +} + +static void usb_audio_disconnect(struct usb_interface *intf) +{ + snd_usb_audio_disconnect(interface_to_usbdev(intf), + dev_get_drvdata(&intf->dev)); +} +#endif + + + static int __init snd_usb_audio_init(void) { usb_register(&usb_audio_driver); diff --git a/sound/usb/usbaudio.h b/sound/usb/usbaudio.h index ae40a9b4ecd9fcfdf9c9eb69d34c7451cdd765fc..208033a871894f6a05353f08a303d74690ea33ef 100644 --- a/sound/usb/usbaudio.h +++ b/sound/usb/usbaudio.h @@ -58,6 +58,8 @@ #define EP_GENERAL 0x01 #define MS_GENERAL 0x01 +#define MIDI_IN_JACK 0x02 +#define MIDI_OUT_JACK 0x03 /* endpoint attributes */ #define EP_ATTR_MASK 0x0c @@ -146,22 +148,34 @@ struct snd_usb_audio { /* * Information about devices with broken descriptors */ +#define QUIRK_ANY_INTERFACE -1 + +#define QUIRK_MIDI_FIXED_ENDPOINT 0 +#define QUIRK_MIDI_YAMAHA 1 +#define QUIRK_MIDI_MIDIMAN 2 + typedef struct snd_usb_audio_quirk snd_usb_audio_quirk_t; typedef struct snd_usb_midi_endpoint_info snd_usb_midi_endpoint_info_t; struct snd_usb_audio_quirk { const char *vendor_name; const char *product_name; - int ifnum; + int16_t ifnum; + int16_t type; + const void *data; +}; - /* MIDI specific */ - struct snd_usb_midi_endpoint_info { - int16_t epnum; /* ep number, -1 autodetect */ - uint16_t out_cables; /* bitmask */ - uint16_t in_cables; /* bitmask */ - } endpoints[MIDI_MAX_ENDPOINTS]; +/* data for QUIRK_MIDI_FIXED_ENDPOINT */ +struct snd_usb_midi_endpoint_info { + int16_t epnum; /* ep number, -1 autodetect */ + uint16_t out_cables; /* bitmask */ + uint16_t in_cables; /* bitmask */ }; +/* for QUIRK_MIDI_YAMAHA, data is NULL */ + +/* for QUIRK_MIDI_MIDIMAN, data is the number of ports */ + /* * USB MIDI sequencer device data */ @@ -173,6 +187,7 @@ typedef struct snd_usb_midi_in_endpoint snd_usb_midi_in_endpoint_t; struct snd_usb_midi { /* filled by usbaudio.c */ snd_usb_audio_t *chip; + struct usb_interface *iface; int ifnum; const snd_usb_audio_quirk_t *quirk; diff --git a/sound/usb/usbmidi.c b/sound/usb/usbmidi.c index 98e5656a4b5262207336d3d83a42adf7b4aa179e..a0b54139e7c47b60dc92844baceddccd29dd91b6 100644 --- a/sound/usb/usbmidi.c +++ b/sound/usb/usbmidi.c @@ -4,6 +4,10 @@ * Copyright (c) 2002 Clemens Ladisch * All rights reserved. * + * Based on the OSS usb-midi driver by NAGANO Daisuke, + * NetBSD's umidi driver by Takuya SHIOZAKI, + * the "USB Device Class Definition for MIDI Devices" by Roland + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: @@ -120,6 +124,10 @@ struct snd_usb_midi_in_endpoint { static void snd_usbmidi_do_output(snd_usb_midi_out_endpoint_t* ep); +static const uint8_t snd_usbmidi_cin_length[] = { + 0, 0, 2, 3, 3, 1, 2, 3, 3, 3, 3, 3, 2, 2, 3, 1 +}; + /* * Submits the URB, with error handling. */ @@ -152,9 +160,6 @@ static int snd_usbmidi_urb_error(int status) static void snd_usbmidi_input_packet(snd_usb_midi_in_endpoint_t* ep, uint8_t packet[4]) { - static const uint8_t cin_length[] = { - 0, 0, 2, 3, 3, 1, 2, 3, 3, 3, 3, 3, 2, 2, 3, 1 - }; int cable = packet[0] >> 4; usbmidi_in_port_t* port = &ep->ports[cable]; snd_seq_event_t ev; @@ -163,7 +168,7 @@ static void snd_usbmidi_input_packet(snd_usb_midi_in_endpoint_t* ep, return; memset(&ev, 0, sizeof(ev)); if (snd_midi_event_encode(port->midi_event, &packet[1], - cin_length[packet[0] & 0x0f], &ev) > 0 + snd_usbmidi_cin_length[packet[0] & 0x0f], &ev) > 0 && ev.type != SNDRV_SEQ_EVENT_NONE) { ev.source.port = port->seq_port; ev.dest.client = SNDRV_SEQ_ADDRESS_SUBSCRIBERS; @@ -199,6 +204,38 @@ static void snd_usbmidi_in_urb_complete(struct urb* urb) } } +/* + * Converts the data read from a Midiman device to standard USB MIDI packets. + */ +static void snd_usbmidi_in_midiman_complete(struct urb* urb) +{ + if (urb->status == 0) { + uint8_t* buffer = (uint8_t*)urb->transfer_buffer; + int i; + + for (i = 0; i + 4 <= urb->actual_length; i += 4) { + if (buffer[i + 3] != 0) { + /* + * snd_usbmidi_input_packet() doesn't check the + * contents of the message, so we simply use + * some random CIN with the desired length. + */ + static const uint8_t cin[4] = { + 0x0, 0xf, 0x2, 0x3 + }; + uint8_t ctl = buffer[i + 3]; + buffer[i + 3] = buffer[i + 2]; + buffer[i + 2] = buffer[i + 1]; + buffer[i + 1] = buffer[i + 0]; + buffer[i + 0] = (ctl & 0xf0) | cin[ctl & 3]; + } else { + buffer[i + 0] = 0; + } + } + } + snd_usbmidi_in_urb_complete(urb); +} + static void snd_usbmidi_out_urb_complete(struct urb* urb) { snd_usb_midi_out_endpoint_t* ep = snd_magic_cast(snd_usb_midi_out_endpoint_t, urb->context, return); @@ -213,6 +250,23 @@ static void snd_usbmidi_out_urb_complete(struct urb* urb) spin_unlock_irqrestore(&ep->buffer_lock, flags); } +/* + * Converts standard USB MIDI packets to what Midman devices expect. + */ +static void snd_usbmidi_convert_to_midiman(struct urb* urb) +{ + uint8_t* buffer = (uint8_t*)urb->transfer_buffer; + int i; + + for (i = 0; i + 4 <= urb->transfer_buffer_length; i += 4) { + uint8_t cin = buffer[i]; + buffer[i + 0] = buffer[i + 1]; + buffer[i + 1] = buffer[i + 2]; + buffer[i + 2] = buffer[i + 3]; + buffer[i + 3] = (cin & 0xf0) | snd_usbmidi_cin_length[cin & 0x0f]; + } +} + /* * This is called when some data should be transferred to the device * (after the reception of one or more sequencer events, or after completion @@ -255,6 +309,9 @@ static void snd_usbmidi_do_output(snd_usb_midi_out_endpoint_t* ep) } if (len > 0) { + if (ep->umidi->quirk && ep->umidi->quirk->type == QUIRK_MIDI_MIDIMAN) + snd_usbmidi_convert_to_midiman(ep->urb); + ep->urb->dev = ep->umidi->chip->dev; snd_usbmidi_submit_urb(ep->urb, GFP_ATOMIC); } @@ -479,22 +536,6 @@ static void snd_usbmidi_in_endpoint_delete(snd_usb_midi_in_endpoint_t* ep) snd_magic_kfree(ep); } -#ifndef OLD_USB -/* this code is not exported from USB core anymore */ -struct usb_interface *local_usb_ifnum_to_if(struct usb_device *dev, unsigned ifnum) -{ - int i; - - for (i = 0; i < dev->actconfig->bNumInterfaces; i++) - if (dev->actconfig->interface[i].altsetting[0].bInterfaceNumber == ifnum) - return &dev->actconfig->interface[i]; - - return NULL; -} -#else -#define local_usb_ifnum_to_if usb_ifnum_to_if -#endif - /* * For Roland devices, use the alternate setting which uses interrupt * transfers for input. @@ -507,7 +548,7 @@ static usb_endpoint_descriptor_t* snd_usbmidi_get_int_epd(snd_usb_midi_t* umidi, if (umidi->chip->dev->descriptor.idVendor != 0x0582) return NULL; - intf = local_usb_ifnum_to_if(umidi->chip->dev, umidi->ifnum); + intf = umidi->iface; if (!intf || intf->num_altsetting != 2) return NULL; @@ -528,6 +569,14 @@ static usb_endpoint_descriptor_t* snd_usbmidi_get_int_epd(snd_usb_midi_t* umidi, return &intfd->endpoint[1]; } +static usb_endpoint_descriptor_t* snd_usbmidi_get_midiman_int_epd(snd_usb_midi_t* umidi) +{ + usb_interface_t* intf = umidi->iface; + if (!intf) + return NULL; + return &intf->altsetting[0].endpoint[0]; +} + /* * Creates an input endpoint, and initalizes input ports. * ALSA ports are created later. @@ -551,7 +600,10 @@ static int snd_usbmidi_in_endpoint_create(snd_usb_midi_t* umidi, for (i = 0; i < 0x10; ++i) ep->ports[i].seq_port = -1; - int_epd = snd_usbmidi_get_int_epd(umidi, ep_info->epnum); + if (umidi->quirk && umidi->quirk->type == QUIRK_MIDI_MIDIMAN) + int_epd = snd_usbmidi_get_midiman_int_epd(umidi); + else + int_epd = snd_usbmidi_get_int_epd(umidi, ep_info->epnum); ep->urb = usb_alloc_urb(0, GFP_KERNEL); if (!ep->urb) { @@ -696,73 +748,107 @@ static int snd_usbmidi_seq_device_delete(snd_seq_device_t* seq_device) return 0; } +/* + * Creates a sequencer port for an input/output cable pair. + */ +static int snd_usbmidi_create_port(snd_usb_midi_t* umidi, + snd_usb_midi_out_endpoint_t* out_ep, + snd_usb_midi_in_endpoint_t* in_ep, + int cable, int port_idx) +{ + int cap, type, port; + snd_seq_port_callback_t port_callback; + char port_name[48]; + + cap = 0; + memset(&port_callback, 0, sizeof(port_callback)); + port_callback.owner = THIS_MODULE; + if (out_ep) { + port_callback.event_input = snd_usbmidi_event_input; + port_callback.private_data = &out_ep->ports[cable]; + cap |= SNDRV_SEQ_PORT_CAP_WRITE | SNDRV_SEQ_PORT_CAP_SUBS_WRITE; + } + if (in_ep) { + cap |= SNDRV_SEQ_PORT_CAP_READ | SNDRV_SEQ_PORT_CAP_SUBS_READ; + } + if (out_ep && in_ep) { + cap |= SNDRV_SEQ_PORT_CAP_DUPLEX; + } + /* TODO: read type bits from element descriptor */ + type = SNDRV_SEQ_PORT_TYPE_MIDI_GENERIC; + /* TODO: read port name from jack descriptor */ + snprintf(port_name, sizeof(port_name), "%s Port %d", + umidi->chip->card->shortname, port_idx); + port = snd_seq_event_port_attach(umidi->seq_client, &port_callback, + cap, type, port_name); + if (port < 0) { + snd_printk(KERN_ERR "cannot create port (error code %d)\n", port); + return port; + } + if (in_ep) + in_ep->ports[cable].seq_port = port; + return port; +} + +/* + * Creates a virmidi port emulating rawmidi for the sequencer port. + */ +static int snd_usbmidi_create_virmidi(snd_usb_midi_t* umidi, int port, + int port_idx, snd_rawmidi_t** rrmidi) +{ + snd_rawmidi_t *rmidi; + snd_virmidi_dev_t *rdev; + int err; + + *rrmidi = NULL; + err = snd_virmidi_new(umidi->chip->card, port_idx, &rmidi); + if (err < 0) + return err; + sprintf(rmidi->name, "%s MIDI %d", umidi->chip->card->shortname, port_idx); + rdev = snd_magic_cast(snd_virmidi_dev_t, rmidi->private_data, return -ENXIO); + rdev->seq_mode = SNDRV_VIRMIDI_SEQ_ATTACH; + rdev->client = umidi->seq_client; + rdev->port = port; + err = snd_device_register(umidi->chip->card, rmidi); + if (err < 0) { + snd_device_free(umidi->chip->card, rmidi); + return err; + } + *rrmidi = rmidi; + return 0; +} + /* * After input and output endpoints have been initialized, create * the ALSA port for each input/output port pair in the endpoint. * *port_idx is the port number, which must be unique over all endpoints. */ -static int snd_usbmidi_create_endpoint_ports(snd_usb_midi_t* umidi, int ep, int* port_idx, +static int snd_usbmidi_create_endpoint_ports(snd_usb_midi_t* umidi, + snd_usb_midi_endpoint_t* endpoint, + int* port_idx, snd_usb_midi_endpoint_info_t* ep_info) { - int c, err; - int cap, type, port; - int out, in; - snd_seq_port_callback_t port_callback; - char port_name[48]; + int cable; - for (c = 0; c < 0x10; ++c) { - out = ep_info->out_cables & (1 << c); - in = ep_info->in_cables & (1 << c); + for (cable = 0; cable < 0x10; ++cable) { + int port, err; + int out = ep_info->out_cables & (1 << cable); + int in = ep_info->in_cables & (1 << cable); if (!(in || out)) continue; - cap = 0; - memset(&port_callback, 0, sizeof(port_callback)); - port_callback.owner = THIS_MODULE; - if (out) { - port_callback.event_input = snd_usbmidi_event_input; - port_callback.private_data = &umidi->endpoints[ep].out->ports[c]; - cap |= SNDRV_SEQ_PORT_CAP_WRITE | - SNDRV_SEQ_PORT_CAP_SUBS_WRITE; - } - if (in) { - cap |= SNDRV_SEQ_PORT_CAP_READ | - SNDRV_SEQ_PORT_CAP_SUBS_READ; - } - if (out && in) { - cap |= SNDRV_SEQ_PORT_CAP_DUPLEX; - } - /* TODO: read type bits from element descriptor */ - type = SNDRV_SEQ_PORT_TYPE_MIDI_GENERIC; - /* TODO: read port name from jack descriptor */ - snprintf(port_name, sizeof(port_name), "%s Port %d", - umidi->chip->card->shortname, *port_idx); - port = snd_seq_event_port_attach(umidi->seq_client, - &port_callback, - cap, type, port_name); - if (port < 0) { - snd_printk(KERN_ERR "cannot create port (error code %d)\n", port); + + port = snd_usbmidi_create_port(umidi, + out ? endpoint->out : NULL, + in ? endpoint->in : NULL, + cable, *port_idx); + if (port < 0) return port; - } - if (in) - umidi->endpoints[ep].in->ports[c].seq_port = port; if (*port_idx < SNDRV_MINOR_RAWMIDIS) { - snd_rawmidi_t *rmidi; - snd_virmidi_dev_t *rdev; - err = snd_virmidi_new(umidi->chip->card, *port_idx, &rmidi); + err = snd_usbmidi_create_virmidi(umidi, port, *port_idx, + &endpoint->rmidi[cable]); if (err < 0) return err; - rdev = snd_magic_cast(snd_virmidi_dev_t, rmidi->private_data, return -ENXIO); - strcpy(rmidi->name, port_name); - rdev->seq_mode = SNDRV_VIRMIDI_SEQ_ATTACH; - rdev->client = umidi->seq_client; - rdev->port = port; - err = snd_device_register(umidi->chip->card, rmidi); - if (err < 0) { - snd_device_free(umidi->chip->card, rmidi); - return err; - } - umidi->endpoints[ep].rmidi[c] = rmidi; } ++*port_idx; } @@ -792,8 +878,8 @@ static int snd_usbmidi_create_endpoints(snd_usb_midi_t* umidi, if (err < 0) return err; } - err = snd_usbmidi_create_endpoint_ports(umidi, i, &port_idx, - &endpoints[i]); + err = snd_usbmidi_create_endpoint_ports(umidi, &umidi->endpoints[i], + &port_idx, &endpoints[i]); if (err < 0) return err; printk(KERN_INFO "snd-usb-midi: endpoint %d: created %d output and %d input ports\n", @@ -817,9 +903,7 @@ static int snd_usbmidi_get_ms_info(snd_usb_midi_t* umidi, usb_ms_endpoint_descriptor_t* ms_ep; int i, epidx; - memset(endpoints, 0, sizeof(*endpoints) * MIDI_MAX_ENDPOINTS); - - intf = local_usb_ifnum_to_if(umidi->chip->dev, umidi->ifnum); + intf = umidi->iface; if (!intf) return -ENXIO; intfd = &intf->altsetting[0]; @@ -878,7 +962,7 @@ static int snd_usbmidi_detect_endpoint(snd_usb_midi_t* umidi, usb_endpoint_descriptor_t* epd; if (endpoint->epnum == -1) { - intf = local_usb_ifnum_to_if(umidi->chip->dev, umidi->ifnum); + intf = umidi->iface; if (!intf || intf->num_altsetting < 1) return -ENOENT; intfd = intf->altsetting; @@ -890,6 +974,120 @@ static int snd_usbmidi_detect_endpoint(snd_usb_midi_t* umidi, return 0; } +/* + * Detects the endpoints and ports of Yamaha devices. + */ +static int snd_usbmidi_detect_yamaha(snd_usb_midi_t* umidi, + snd_usb_midi_endpoint_info_t* endpoint) +{ + usb_interface_t* intf; + usb_interface_descriptor_t* intfd; + uint8_t* cs_desc; + + intf = umidi->iface; + if (!intf) + return -ENOENT; + intfd = intf->altsetting; + if (intfd->bNumEndpoints < 1) + return -ENOENT; + + for (cs_desc = intfd->extra; + cs_desc < intfd->extra + intfd->extralen && cs_desc[0] >= 2; + cs_desc += cs_desc[0]) { + if (cs_desc[1] == CS_AUDIO_INTERFACE) { + if (cs_desc[2] == MIDI_IN_JACK) + endpoint->in_cables = (endpoint->in_cables << 1) | 1; + else if (cs_desc[2] == MIDI_OUT_JACK) + endpoint->out_cables = (endpoint->out_cables << 1) | 1; + } + } + if (!endpoint->in_cables && !endpoint->out_cables) + return -ENOENT; + + endpoint->epnum = -1; + return snd_usbmidi_detect_endpoint(umidi, endpoint); +} + +/* + * Creates the endpoints and their ports for Midiman devices. + */ +static int snd_usbmidi_create_endpoints_midiman(snd_usb_midi_t* umidi, int ports) +{ + snd_usb_midi_endpoint_info_t ep_info; + usb_interface_t* intf; + usb_interface_descriptor_t* intfd; + usb_endpoint_descriptor_t* epd; + int cable, err; + + intf = umidi->iface; + if (!intf) + return -ENOENT; + intfd = intf->altsetting; + if (intfd->bNumEndpoints < (ports > 1 ? 5 : 3)) { + snd_printdd(KERN_ERR "not enough endpoints\n"); + return -ENOENT; + } + + epd = &intfd->endpoint[0]; + if ((epd->bEndpointAddress & USB_ENDPOINT_DIR_MASK) != USB_DIR_IN || + (epd->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) != USB_ENDPOINT_XFER_INT) { + snd_printdd(KERN_ERR "endpoint[0] isn't interrupt\n"); + return -ENXIO; + } + epd = &intfd->endpoint[2]; + if ((epd->bEndpointAddress & USB_ENDPOINT_DIR_MASK) != USB_DIR_OUT || + (epd->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) != USB_ENDPOINT_XFER_BULK) { + snd_printdd(KERN_ERR "endpoint[2] isn't bulk output\n"); + return -ENXIO; + } + if (ports > 1) { + epd = &intfd->endpoint[4]; + if ((epd->bEndpointAddress & USB_ENDPOINT_DIR_MASK) != USB_DIR_OUT || + (epd->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) != USB_ENDPOINT_XFER_BULK) { + snd_printdd(KERN_ERR "endpoint[4] isn't bulk output\n"); + return -ENXIO; + } + } + + ep_info.epnum = intfd->endpoint[2].bEndpointAddress & USB_ENDPOINT_NUMBER_MASK; + ep_info.out_cables = 0x5555 & ((1 << ports) - 1); + err = snd_usbmidi_out_endpoint_create(umidi, &ep_info, &umidi->endpoints[0]); + if (err < 0) + return err; + + ep_info.epnum = intfd->endpoint[0].bEndpointAddress & USB_ENDPOINT_NUMBER_MASK; + ep_info.in_cables = (1 << ports) - 1; + err = snd_usbmidi_in_endpoint_create(umidi, &ep_info, &umidi->endpoints[0]); + if (err < 0) + return err; + umidi->endpoints[0].in->urb->complete = snd_usbmidi_in_midiman_complete; + + if (ports > 1) { + ep_info.epnum = intfd->endpoint[4].bEndpointAddress & USB_ENDPOINT_NUMBER_MASK; + ep_info.out_cables = 0xaaaa & ((1 << ports) - 1); + err = snd_usbmidi_out_endpoint_create(umidi, &ep_info, &umidi->endpoints[1]); + if (err < 0) + return err; + } + + for (cable = 0; cable < ports; ++cable) { + int port = snd_usbmidi_create_port(umidi, + umidi->endpoints[cable & 1].out, + umidi->endpoints[0].in, + cable, cable); + if (port < 0) + return port; + + if (cable < SNDRV_MINOR_RAWMIDIS) { + int err = snd_usbmidi_create_virmidi(umidi, port, cable, + &umidi->endpoints[0].rmidi[cable]); + if (err < 0) + return err; + } + } + return 0; +} + /* * Initialize the sequencer device. */ @@ -912,6 +1110,7 @@ static int snd_usbmidi_seq_device_new(snd_seq_device_t* seq_device) if (umidi->seq_client < 0) return umidi->seq_client; + /* set the client name */ memset(&client_info, 0, sizeof(client_info)); client_info.client = umidi->seq_client; client_info.type = KERNEL_CLIENT; @@ -935,17 +1134,37 @@ static int snd_usbmidi_seq_device_new(snd_seq_device_t* seq_device) SNDRV_SEQ_IOCTL_SET_CLIENT_INFO, &client_info); - if (umidi->quirk) { - memcpy(endpoints, umidi->quirk->endpoints, sizeof(endpoints)); - err = snd_usbmidi_detect_endpoint(umidi, &endpoints[0]); - } else { + /* detect the endpoint(s) to use */ + memset(endpoints, 0, sizeof(endpoints)); + if (!umidi->quirk) { err = snd_usbmidi_get_ms_info(umidi, endpoints); + } else { + switch (umidi->quirk->type) { + case QUIRK_MIDI_FIXED_ENDPOINT: + memcpy(&endpoints[0], umidi->quirk->data, + sizeof(snd_usb_midi_endpoint_info_t)); + err = snd_usbmidi_detect_endpoint(umidi, &endpoints[0]); + break; + case QUIRK_MIDI_YAMAHA: + err = snd_usbmidi_detect_yamaha(umidi, &endpoints[0]); + break; + case QUIRK_MIDI_MIDIMAN: + err = 0; + break; + default: + snd_printd(KERN_ERR "invalid quirk type %d\n", umidi->quirk->type); + err = -ENXIO; + break; + } } - if (err < 0) { - snd_usbmidi_seq_device_delete(seq_device); - return err; + + /* create ports */ + if (err >= 0) { + if (umidi->quirk && umidi->quirk->type == QUIRK_MIDI_MIDIMAN) + err = snd_usbmidi_create_endpoints_midiman(umidi, (int)umidi->quirk->data); + else + err = snd_usbmidi_create_endpoints(umidi, endpoints); } - err = snd_usbmidi_create_endpoints(umidi, endpoints); if (err < 0) { snd_usbmidi_seq_device_delete(seq_device); return err; diff --git a/sound/usb/usbquirks.h b/sound/usb/usbquirks.h index 74336ec8841d054c52dea98a88d6bc53d67e4f2d..87348c929f59dce507a288a5de48ab531aee2f42 100644 --- a/sound/usb/usbquirks.h +++ b/sound/usb/usbquirks.h @@ -26,45 +26,143 @@ * In a perfect world, this file would be empty. */ +#define USB_DEVICE_VENDOR_SPEC(vend, prod) \ + .match_flags = USB_DEVICE_ID_MATCH_VENDOR | \ + USB_DEVICE_ID_MATCH_PRODUCT | \ + USB_DEVICE_ID_MATCH_INT_CLASS, \ + .idVendor = vend, \ + .idProduct = prod, \ + .bInterfaceClass = USB_CLASS_VENDOR_SPEC + #if defined(CONFIG_SND_SEQUENCER) || defined(CONFIG_SND_SEQUENCER_MODULE) +/* Yamaha devices */ { - /* from NetBSD's umidi driver */ - USB_DEVICE(0x0499, 0x1000), /* Yamaha UX256 */ + USB_DEVICE_VENDOR_SPEC(0x0499, 0x1000), .driver_info = (unsigned long) & (const snd_usb_audio_quirk_t) { - .ifnum = 0, - .endpoints = { - { - .epnum = -1, - .out_cables = 0xffff, - .in_cables = 0x00ff - } - } + .vendor_name = "Yamaha", + .product_name = "UX256", + .ifnum = QUIRK_ANY_INTERFACE, + .type = QUIRK_MIDI_YAMAHA } }, { - /* from Nagano Daisuke's usb-midi driver */ - USB_DEVICE(0x0499, 0x1001), /* Yamaha MU1000 */ + USB_DEVICE_VENDOR_SPEC(0x0499, 0x1001), .driver_info = (unsigned long) & (const snd_usb_audio_quirk_t) { - .ifnum = 0, - .endpoints = { - { - .epnum = 1, - .out_cables = 0x000f, - .in_cables = 0x0001 - } - } + .vendor_name = "Yamaha", + .product_name = "MU1000", + .ifnum = QUIRK_ANY_INTERFACE, + .type = QUIRK_MIDI_YAMAHA + } +}, +{ + USB_DEVICE_VENDOR_SPEC(0x0499, 0x1002), + .driver_info = (unsigned long) & (const snd_usb_audio_quirk_t) { + .vendor_name = "Yamaha", + .product_name = "MU2000", + .ifnum = QUIRK_ANY_INTERFACE, + .type = QUIRK_MIDI_YAMAHA + } +}, +{ + USB_DEVICE_VENDOR_SPEC(0x0499, 0x1003), + .driver_info = (unsigned long) & (const snd_usb_audio_quirk_t) { + .vendor_name = "Yamaha", + .product_name = "MU500", + .ifnum = QUIRK_ANY_INTERFACE, + .type = QUIRK_MIDI_YAMAHA + } +}, +{ + USB_DEVICE_VENDOR_SPEC(0x0499, 0x1004), + .driver_info = (unsigned long) & (const snd_usb_audio_quirk_t) { + .vendor_name = "Yamaha", + .product_name = "UW500", + .ifnum = 3, + .type = QUIRK_MIDI_YAMAHA + } +}, +{ + USB_DEVICE_VENDOR_SPEC(0x0499, 0x1005), + .driver_info = (unsigned long) & (const snd_usb_audio_quirk_t) { + .vendor_name = "Yamaha", + .product_name = "MOTIF6", + .ifnum = QUIRK_ANY_INTERFACE, + .type = QUIRK_MIDI_YAMAHA + } +}, +{ + USB_DEVICE_VENDOR_SPEC(0x0499, 0x1006), + .driver_info = (unsigned long) & (const snd_usb_audio_quirk_t) { + .vendor_name = "Yamaha", + .product_name = "MOTIF7", + .ifnum = QUIRK_ANY_INTERFACE, + .type = QUIRK_MIDI_YAMAHA + } +}, +{ + USB_DEVICE_VENDOR_SPEC(0x0499, 0x1007), + .driver_info = (unsigned long) & (const snd_usb_audio_quirk_t) { + .vendor_name = "Yamaha", + .product_name = "MOTIF8", + .ifnum = QUIRK_ANY_INTERFACE, + .type = QUIRK_MIDI_YAMAHA + } +}, +{ + USB_DEVICE_VENDOR_SPEC(0x0499, 0x1008), + .driver_info = (unsigned long) & (const snd_usb_audio_quirk_t) { + .vendor_name = "Yamaha", + .product_name = "UX96", + .ifnum = QUIRK_ANY_INTERFACE, + .type = QUIRK_MIDI_YAMAHA + } +}, +{ + USB_DEVICE_VENDOR_SPEC(0x0499, 0x1009), + .driver_info = (unsigned long) & (const snd_usb_audio_quirk_t) { + .vendor_name = "Yamaha", + .product_name = "UX16", + .ifnum = QUIRK_ANY_INTERFACE, + .type = QUIRK_MIDI_YAMAHA + } +}, +{ + USB_DEVICE_VENDOR_SPEC(0x0499, 0x100a), + .driver_info = (unsigned long) & (const snd_usb_audio_quirk_t) { + .vendor_name = "Yamaha", + .product_name = "EOS BX", + .ifnum = 3, + .type = QUIRK_MIDI_YAMAHA + } +}, +{ + USB_DEVICE_VENDOR_SPEC(0x0499, 0x100e), + .driver_info = (unsigned long) & (const snd_usb_audio_quirk_t) { + .vendor_name = "Yamaha", + .product_name = "S08", + .ifnum = QUIRK_ANY_INTERFACE, + .type = QUIRK_MIDI_YAMAHA + } +}, +{ + USB_DEVICE_VENDOR_SPEC(0x0499, 0x100f), + .driver_info = (unsigned long) & (const snd_usb_audio_quirk_t) { + .vendor_name = "Yamaha", + .product_name = "CLP-150", + .ifnum = QUIRK_ANY_INTERFACE, + .type = QUIRK_MIDI_YAMAHA + } +}, +{ + USB_DEVICE_VENDOR_SPEC(0x0499, 0x1010), + .driver_info = (unsigned long) & (const snd_usb_audio_quirk_t) { + .vendor_name = "Yamaha", + .product_name = "CLP-170", + .ifnum = QUIRK_ANY_INTERFACE, + .type = QUIRK_MIDI_YAMAHA } }, -/* - * I don't know whether the following Yamaha devices need entries or not: - * 0x1002 MU2000 0x1008 UX96 - * 0x1003 MU500 0x1009 UX16 - * 0x1004 UW500 0x100e S08 - * 0x1005 MOTIF6 0x100f CLP-150 - * 0x1006 MOTIF7 0x1010 CLP-170 - * 0x1007 MOTIF8 - */ /* * Once upon a time people thought, "Wouldn't it be nice if there was a @@ -79,259 +177,316 @@ * class-specific descriptors. */ { - USB_DEVICE(0x0582, 0x0000), + USB_DEVICE_VENDOR_SPEC(0x0582, 0x0000), .driver_info = (unsigned long) & (const snd_usb_audio_quirk_t) { .vendor_name = "Roland", .product_name = "UA-100", .ifnum = 2, - .endpoints = { - { - .epnum = -1, - .out_cables = 0x0007, - .in_cables = 0x0007 - } + .type = QUIRK_MIDI_FIXED_ENDPOINT, + .data = & (const snd_usb_midi_endpoint_info_t) { + .epnum = -1, + .out_cables = 0x0007, + .in_cables = 0x0007 } } }, { - USB_DEVICE(0x0582, 0x0002), + USB_DEVICE_VENDOR_SPEC(0x0582, 0x0002), .driver_info = (unsigned long) & (const snd_usb_audio_quirk_t) { .vendor_name = "EDIROL", .product_name = "UM-4", .ifnum = 2, - .endpoints = { - { - .epnum = -1, - .out_cables = 0x000f, - .in_cables = 0x000f - } + .type = QUIRK_MIDI_FIXED_ENDPOINT, + .data = & (const snd_usb_midi_endpoint_info_t) { + .epnum = -1, + .out_cables = 0x000f, + .in_cables = 0x000f } } }, { - USB_DEVICE(0x0582, 0x0003), + USB_DEVICE_VENDOR_SPEC(0x0582, 0x0003), .driver_info = (unsigned long) & (const snd_usb_audio_quirk_t) { .vendor_name = "Roland", .product_name = "SC-8850", .ifnum = 2, - .endpoints = { - { - .epnum = -1, - .out_cables = 0x003f, - .in_cables = 0x003f - } + .type = QUIRK_MIDI_FIXED_ENDPOINT, + .data = & (const snd_usb_midi_endpoint_info_t) { + .epnum = -1, + .out_cables = 0x003f, + .in_cables = 0x003f } } }, { - USB_DEVICE(0x0582, 0x0004), + USB_DEVICE_VENDOR_SPEC(0x0582, 0x0004), .driver_info = (unsigned long) & (const snd_usb_audio_quirk_t) { .vendor_name = "Roland", .product_name = "U-8", .ifnum = 2, - .endpoints = { - { - .epnum = -1, - .out_cables = 0x0003, - .in_cables = 0x0003 - } + .type = QUIRK_MIDI_FIXED_ENDPOINT, + .data = & (const snd_usb_midi_endpoint_info_t) { + .epnum = -1, + .out_cables = 0x0003, + .in_cables = 0x0003 } } }, { - USB_DEVICE(0x0582, 0x0005), + USB_DEVICE_VENDOR_SPEC(0x0582, 0x0005), .driver_info = (unsigned long) & (const snd_usb_audio_quirk_t) { .vendor_name = "EDIROL", .product_name = "UM-2", .ifnum = 2, - .endpoints = { - { - .epnum = -1, - .out_cables = 0x0003, - .in_cables = 0x0003 - } + .type = QUIRK_MIDI_FIXED_ENDPOINT, + .data = & (const snd_usb_midi_endpoint_info_t) { + .epnum = -1, + .out_cables = 0x0003, + .in_cables = 0x0003 } } }, { - USB_DEVICE(0x0582, 0x0007), + USB_DEVICE_VENDOR_SPEC(0x0582, 0x0007), .driver_info = (unsigned long) & (const snd_usb_audio_quirk_t) { .vendor_name = "Roland", .product_name = "SC-8820", .ifnum = 2, - .endpoints = { - { - .epnum = -1, - .out_cables = 0x0013, - .in_cables = 0x0013 - } + .type = QUIRK_MIDI_FIXED_ENDPOINT, + .data = & (const snd_usb_midi_endpoint_info_t) { + .epnum = -1, + .out_cables = 0x0013, + .in_cables = 0x0013 } } }, { - USB_DEVICE(0x0582, 0x0008), + USB_DEVICE_VENDOR_SPEC(0x0582, 0x0008), .driver_info = (unsigned long) & (const snd_usb_audio_quirk_t) { .vendor_name = "Roland", .product_name = "PC-300", .ifnum = 2, - .endpoints = { - { - .epnum = -1, - .out_cables = 0x0001, - .in_cables = 0x0001 - } + .type = QUIRK_MIDI_FIXED_ENDPOINT, + .data = & (const snd_usb_midi_endpoint_info_t) { + .epnum = -1, + .out_cables = 0x0001, + .in_cables = 0x0001 } } }, { - USB_DEVICE(0x0582, 0x0009), + USB_DEVICE_VENDOR_SPEC(0x0582, 0x0009), .driver_info = (unsigned long) & (const snd_usb_audio_quirk_t) { .vendor_name = "EDIROL", .product_name = "UM-1", .ifnum = 2, - .endpoints = { - { - .epnum = -1, - .out_cables = 0x0001, - .in_cables = 0x0001 - } + .type = QUIRK_MIDI_FIXED_ENDPOINT, + .data = & (const snd_usb_midi_endpoint_info_t) { + .epnum = -1, + .out_cables = 0x0001, + .in_cables = 0x0001 } } }, { - USB_DEVICE(0x0582, 0x000b), + USB_DEVICE_VENDOR_SPEC(0x0582, 0x000b), .driver_info = (unsigned long) & (const snd_usb_audio_quirk_t) { .vendor_name = "Roland", .product_name = "SK-500", .ifnum = 2, - .endpoints = { - { - .epnum = -1, - .out_cables = 0x0013, - .in_cables = 0x0013 - } + .type = QUIRK_MIDI_FIXED_ENDPOINT, + .data = & (const snd_usb_midi_endpoint_info_t) { + .epnum = -1, + .out_cables = 0x0013, + .in_cables = 0x0013 } } }, { - USB_DEVICE(0x0582, 0x000c), + USB_DEVICE_VENDOR_SPEC(0x0582, 0x000c), .driver_info = (unsigned long) & (const snd_usb_audio_quirk_t) { .vendor_name = "Roland", .product_name = "SC-D70", .ifnum = 2, - .endpoints = { - { - .epnum = -1, - .out_cables = 0x0007, - .in_cables = 0x0007 - } + .type = QUIRK_MIDI_FIXED_ENDPOINT, + .data = & (const snd_usb_midi_endpoint_info_t) { + .epnum = -1, + .out_cables = 0x0007, + .in_cables = 0x0007 } } }, { - USB_DEVICE(0x0582, 0x0012), + USB_DEVICE_VENDOR_SPEC(0x0582, 0x0012), .driver_info = (unsigned long) & (const snd_usb_audio_quirk_t) { .vendor_name = "Roland", .product_name = "XV-5050", .ifnum = 0, - .endpoints = { - { - .epnum = -1, - .out_cables = 0x0001, - .in_cables = 0x0001 - } + .type = QUIRK_MIDI_FIXED_ENDPOINT, + .data = & (const snd_usb_midi_endpoint_info_t) { + .epnum = -1, + .out_cables = 0x0001, + .in_cables = 0x0001 } } }, { - USB_DEVICE(0x0582, 0x0014), + USB_DEVICE_VENDOR_SPEC(0x0582, 0x0014), .driver_info = (unsigned long) & (const snd_usb_audio_quirk_t) { .vendor_name = "EDIROL", .product_name = "UM-880", .ifnum = 0, - .endpoints = { - { - .epnum = -1, - .out_cables = 0x01ff, - .in_cables = 0x01ff - } + .type = QUIRK_MIDI_FIXED_ENDPOINT, + .data = & (const snd_usb_midi_endpoint_info_t) { + .epnum = -1, + .out_cables = 0x01ff, + .in_cables = 0x01ff } } }, { - USB_DEVICE(0x0582, 0x0016), + USB_DEVICE_VENDOR_SPEC(0x0582, 0x0016), .driver_info = (unsigned long) & (const snd_usb_audio_quirk_t) { .vendor_name = "EDIROL", .product_name = "SD-90", .ifnum = 2, - .endpoints = { - { - .epnum = -1, - .out_cables = 0x000f, - .in_cables = 0x000f - } + .type = QUIRK_MIDI_FIXED_ENDPOINT, + .data = & (const snd_usb_midi_endpoint_info_t) { + .epnum = -1, + .out_cables = 0x000f, + .in_cables = 0x000f } } }, { - USB_DEVICE(0x0582, 0x0023), + USB_DEVICE_VENDOR_SPEC(0x0582, 0x0023), .driver_info = (unsigned long) & (const snd_usb_audio_quirk_t) { .vendor_name = "EDIROL", .product_name = "UM-550", .ifnum = 0, - .endpoints = { - { - .epnum = -1, - .out_cables = 0x003f, - .in_cables = 0x003f - } + .type = QUIRK_MIDI_FIXED_ENDPOINT, + .data = & (const snd_usb_midi_endpoint_info_t) { + .epnum = -1, + .out_cables = 0x003f, + .in_cables = 0x003f } } }, { - USB_DEVICE(0x0582, 0x0027), + USB_DEVICE_VENDOR_SPEC(0x0582, 0x0027), .driver_info = (unsigned long) & (const snd_usb_audio_quirk_t) { .vendor_name = "EDIROL", .product_name = "SD-20", .ifnum = 0, - .endpoints = { - { - .epnum = -1, - .out_cables = 0x0003, - .in_cables = 0x0007 - } + .type = QUIRK_MIDI_FIXED_ENDPOINT, + .data = & (const snd_usb_midi_endpoint_info_t) { + .epnum = -1, + .out_cables = 0x0003, + .in_cables = 0x0007 } } }, { - USB_DEVICE(0x0582, 0x0029), + USB_DEVICE_VENDOR_SPEC(0x0582, 0x0029), .driver_info = (unsigned long) & (const snd_usb_audio_quirk_t) { .vendor_name = "EDIROL", .product_name = "SD-80", .ifnum = 0, - .endpoints = { - { - .epnum = -1, - .out_cables = 0x000f, - .in_cables = 0x000f - } + .type = QUIRK_MIDI_FIXED_ENDPOINT, + .data = & (const snd_usb_midi_endpoint_info_t) { + .epnum = -1, + .out_cables = 0x000f, + .in_cables = 0x000f } } }, { - USB_DEVICE(0x0582, 0x002b), + USB_DEVICE_VENDOR_SPEC(0x0582, 0x002b), .driver_info = (unsigned long) & (const snd_usb_audio_quirk_t) { .vendor_name = "EDIROL", .product_name = "UA-700", .ifnum = 3, - .endpoints = { - { - .epnum = -1, - .out_cables = 0x0003, - .in_cables = 0x0003 - } + .type = QUIRK_MIDI_FIXED_ENDPOINT, + .data = & (const snd_usb_midi_endpoint_info_t) { + .epnum = -1, + .out_cables = 0x0003, + .in_cables = 0x0003 } } }, +/* Midiman/M-Audio devices */ +{ + USB_DEVICE_VENDOR_SPEC(0x0763, 0x1002), + .driver_info = (unsigned long) & (const snd_usb_audio_quirk_t) { + .vendor_name = "M-Audio", + .product_name = "MidiSport 2x2", + .ifnum = QUIRK_ANY_INTERFACE, + .type = QUIRK_MIDI_MIDIMAN, + .data = (void*) 2 + } +}, +{ + USB_DEVICE_VENDOR_SPEC(0x0763, 0x1011), + .driver_info = (unsigned long) & (const snd_usb_audio_quirk_t) { + .vendor_name = "M-Audio", + .product_name = "MidiSport 1x1", + .ifnum = QUIRK_ANY_INTERFACE, + .type = QUIRK_MIDI_MIDIMAN, + .data = (void*) 1 + } +}, +{ + USB_DEVICE_VENDOR_SPEC(0x0763, 0x1015), + .driver_info = (unsigned long) & (const snd_usb_audio_quirk_t) { + .vendor_name = "M-Audio", + .product_name = "Keystation", + .ifnum = QUIRK_ANY_INTERFACE, + .type = QUIRK_MIDI_MIDIMAN, + .data = (void*) 1 + } +}, +{ + USB_DEVICE_VENDOR_SPEC(0x0763, 0x1021), + .driver_info = (unsigned long) & (const snd_usb_audio_quirk_t) { + .vendor_name = "M-Audio", + .product_name = "MidiSport 4x4", + .ifnum = QUIRK_ANY_INTERFACE, + .type = QUIRK_MIDI_MIDIMAN, + .data = (void*) 4 + } +}, +{ + USB_DEVICE_VENDOR_SPEC(0x0763, 0x1033), + .driver_info = (unsigned long) & (const snd_usb_audio_quirk_t) { + .vendor_name = "M-Audio", + .product_name = "MidiSport 8x8", + .ifnum = QUIRK_ANY_INTERFACE, + .type = QUIRK_MIDI_MIDIMAN, + .data = (void*) 9 + } +}, +{ + USB_DEVICE_VENDOR_SPEC(0x0763, 0x2001), + .driver_info = (unsigned long) & (const snd_usb_audio_quirk_t) { + .vendor_name = "M-Audio", + .product_name = "Quattro", + .ifnum = 9, + .type = QUIRK_MIDI_MIDIMAN, + .data = (void*) 1 + } +}, +{ + USB_DEVICE_VENDOR_SPEC(0x0763, 0x2003), + .driver_info = (unsigned long) & (const snd_usb_audio_quirk_t) { + .vendor_name = "M-Audio", + .product_name = "AudioPhile", + .ifnum = 9, + .type = QUIRK_MIDI_MIDIMAN, + .data = (void*) 1 + } +}, + #endif /* CONFIG_SND_SEQUENCER(_MODULE) */ + +#undef USB_DEVICE_VENDOR_SPEC