Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 27d10f56 authored by Clemens Ladisch's avatar Clemens Ladisch Committed by Jaroslav Kysela
Browse files

[ALSA] usb-audio - cache vendor/product IDs



USB generic driver
Cache the decoded values of idVendor/idProduct to get rid of most of
those ugly le16_to_cpu() calls.

Signed-off-by: default avatarClemens Ladisch <clemens@ladisch.de>
parent b259b10c
Loading
Loading
Loading
Loading
+50 −54
Original line number Original line Diff line number Diff line
@@ -2184,16 +2184,14 @@ static int add_audio_endpoint(snd_usb_audio_t *chip, int stream, struct audiofor
/*
/*
 * check if the device uses big-endian samples
 * check if the device uses big-endian samples
 */
 */
static int is_big_endian_format(struct usb_device *dev, struct audioformat *fp)
static int is_big_endian_format(snd_usb_audio_t *chip, struct audioformat *fp)
{
{
	/* M-Audio */
	switch (chip->usb_id) {
	if (le16_to_cpu(dev->descriptor.idVendor) == 0x0763) {
	case USB_ID(0x0763, 0x2001): /* M-Audio Quattro: captured data only */
		/* Quattro: captured data only */
		if (fp->endpoint & USB_DIR_IN)
		if (le16_to_cpu(dev->descriptor.idProduct) == 0x2001 &&
		    fp->endpoint & USB_DIR_IN)
			return 1;
			return 1;
		/* Audiophile USB */
		break;
		if (le16_to_cpu(dev->descriptor.idProduct) == 0x2003)
	case USB_ID(0x0763, 0x2003): /* M-Audio Audiophile USB */
		return 1;
		return 1;
	}
	}
	return 0;
	return 0;
@@ -2208,7 +2206,7 @@ static int is_big_endian_format(struct usb_device *dev, struct audioformat *fp)
 * @format: the format tag (wFormatTag)
 * @format: the format tag (wFormatTag)
 * @fmt: the format type descriptor
 * @fmt: the format type descriptor
 */
 */
static int parse_audio_format_i_type(struct usb_device *dev, struct audioformat *fp,
static int parse_audio_format_i_type(snd_usb_audio_t *chip, struct audioformat *fp,
				     int format, unsigned char *fmt)
				     int format, unsigned char *fmt)
{
{
	int pcm_format;
	int pcm_format;
@@ -2221,12 +2219,12 @@ static int parse_audio_format_i_type(struct usb_device *dev, struct audioformat
	switch (format) {
	switch (format) {
	case 0: /* some devices don't define this correctly... */
	case 0: /* some devices don't define this correctly... */
		snd_printdd(KERN_INFO "%d:%u:%d : format type 0 is detected, processed as PCM\n",
		snd_printdd(KERN_INFO "%d:%u:%d : format type 0 is detected, processed as PCM\n",
			    dev->devnum, fp->iface, fp->altsetting);
			    chip->dev->devnum, fp->iface, fp->altsetting);
		/* fall-through */
		/* fall-through */
	case USB_AUDIO_FORMAT_PCM:
	case USB_AUDIO_FORMAT_PCM:
		if (sample_width > sample_bytes * 8) {
		if (sample_width > sample_bytes * 8) {
			snd_printk(KERN_INFO "%d:%u:%d : sample bitwidth %d in over sample bytes %d\n",
			snd_printk(KERN_INFO "%d:%u:%d : sample bitwidth %d in over sample bytes %d\n",
				   dev->devnum, fp->iface, fp->altsetting,
				   chip->dev->devnum, fp->iface, fp->altsetting,
				   sample_width, sample_bytes);
				   sample_width, sample_bytes);
		}
		}
		/* check the format byte size */
		/* check the format byte size */
@@ -2235,13 +2233,13 @@ static int parse_audio_format_i_type(struct usb_device *dev, struct audioformat
			pcm_format = SNDRV_PCM_FORMAT_S8;
			pcm_format = SNDRV_PCM_FORMAT_S8;
			break;
			break;
		case 2:
		case 2:
			if (is_big_endian_format(dev, fp))
			if (is_big_endian_format(chip, fp))
				pcm_format = SNDRV_PCM_FORMAT_S16_BE; /* grrr, big endian!! */
				pcm_format = SNDRV_PCM_FORMAT_S16_BE; /* grrr, big endian!! */
			else
			else
				pcm_format = SNDRV_PCM_FORMAT_S16_LE;
				pcm_format = SNDRV_PCM_FORMAT_S16_LE;
			break;
			break;
		case 3:
		case 3:
			if (is_big_endian_format(dev, fp))
			if (is_big_endian_format(chip, fp))
				pcm_format = SNDRV_PCM_FORMAT_S24_3BE; /* grrr, big endian!! */
				pcm_format = SNDRV_PCM_FORMAT_S24_3BE; /* grrr, big endian!! */
			else
			else
				pcm_format = SNDRV_PCM_FORMAT_S24_3LE;
				pcm_format = SNDRV_PCM_FORMAT_S24_3LE;
@@ -2251,14 +2249,14 @@ static int parse_audio_format_i_type(struct usb_device *dev, struct audioformat
			break;
			break;
		default:
		default:
			snd_printk(KERN_INFO "%d:%u:%d : unsupported sample bitwidth %d in %d bytes\n",
			snd_printk(KERN_INFO "%d:%u:%d : unsupported sample bitwidth %d in %d bytes\n",
				   dev->devnum, fp->iface, fp->altsetting, sample_width, sample_bytes);
				   chip->dev->devnum, fp->iface,
				   fp->altsetting, sample_width, sample_bytes);
			break;
			break;
		}
		}
		break;
		break;
	case USB_AUDIO_FORMAT_PCM8:
	case USB_AUDIO_FORMAT_PCM8:
		/* Dallas DS4201 workaround */
		/* Dallas DS4201 workaround */
		if (le16_to_cpu(dev->descriptor.idVendor) == 0x04fa &&
		if (chip->usb_id == USB_ID(0x04fa, 0x4201))
		    le16_to_cpu(dev->descriptor.idProduct) == 0x4201)
			pcm_format = SNDRV_PCM_FORMAT_S8;
			pcm_format = SNDRV_PCM_FORMAT_S8;
		else
		else
			pcm_format = SNDRV_PCM_FORMAT_U8;
			pcm_format = SNDRV_PCM_FORMAT_U8;
@@ -2274,7 +2272,7 @@ static int parse_audio_format_i_type(struct usb_device *dev, struct audioformat
		break;
		break;
	default:
	default:
		snd_printk(KERN_INFO "%d:%u:%d : unsupported format type %d\n",
		snd_printk(KERN_INFO "%d:%u:%d : unsupported format type %d\n",
			   dev->devnum, fp->iface, fp->altsetting, format);
			   chip->dev->devnum, fp->iface, fp->altsetting, format);
		break;
		break;
	}
	}
	return pcm_format;
	return pcm_format;
@@ -2291,13 +2289,13 @@ static int parse_audio_format_i_type(struct usb_device *dev, struct audioformat
 * @offset: the start offset of descriptor pointing the rate type
 * @offset: the start offset of descriptor pointing the rate type
 *          (7 for type I and II, 8 for type II)
 *          (7 for type I and II, 8 for type II)
 */
 */
static int parse_audio_format_rates(struct usb_device *dev, struct audioformat *fp,
static int parse_audio_format_rates(snd_usb_audio_t *chip, struct audioformat *fp,
				    unsigned char *fmt, int offset)
				    unsigned char *fmt, int offset)
{
{
	int nr_rates = fmt[offset];
	int nr_rates = fmt[offset];
	if (fmt[0] < offset + 1 + 3 * (nr_rates ? nr_rates : 2)) {
	if (fmt[0] < offset + 1 + 3 * (nr_rates ? nr_rates : 2)) {
		snd_printk(KERN_ERR "%d:%u:%d : invalid FORMAT_TYPE desc\n",
		snd_printk(KERN_ERR "%d:%u:%d : invalid FORMAT_TYPE desc\n",
				   dev->devnum, fp->iface, fp->altsetting);
				   chip->dev->devnum, fp->iface, fp->altsetting);
		return -1;
		return -1;
	}
	}


@@ -2344,7 +2342,7 @@ static int parse_audio_format_rates(struct usb_device *dev, struct audioformat *
/*
/*
 * parse the format type I and III descriptors
 * parse the format type I and III descriptors
 */
 */
static int parse_audio_format_i(struct usb_device *dev, struct audioformat *fp,
static int parse_audio_format_i(snd_usb_audio_t *chip, struct audioformat *fp,
				int format, unsigned char *fmt)
				int format, unsigned char *fmt)
{
{
	int pcm_format;
	int pcm_format;
@@ -2356,7 +2354,7 @@ static int parse_audio_format_i(struct usb_device *dev, struct audioformat *fp,
		 */
		 */
		pcm_format = SNDRV_PCM_FORMAT_S16_LE;
		pcm_format = SNDRV_PCM_FORMAT_S16_LE;
	} else {
	} else {
		pcm_format = parse_audio_format_i_type(dev, fp, format, fmt);
		pcm_format = parse_audio_format_i_type(chip, fp, format, fmt);
		if (pcm_format < 0)
		if (pcm_format < 0)
			return -1;
			return -1;
	}
	}
@@ -2364,16 +2362,16 @@ static int parse_audio_format_i(struct usb_device *dev, struct audioformat *fp,
	fp->channels = fmt[4];
	fp->channels = fmt[4];
	if (fp->channels < 1) {
	if (fp->channels < 1) {
		snd_printk(KERN_ERR "%d:%u:%d : invalid channels %d\n",
		snd_printk(KERN_ERR "%d:%u:%d : invalid channels %d\n",
			   dev->devnum, fp->iface, fp->altsetting, fp->channels);
			   chip->dev->devnum, fp->iface, fp->altsetting, fp->channels);
		return -1;
		return -1;
	}
	}
	return parse_audio_format_rates(dev, fp, fmt, 7);
	return parse_audio_format_rates(chip, fp, fmt, 7);
}
}


/*
/*
 * prase the format type II descriptor
 * prase the format type II descriptor
 */
 */
static int parse_audio_format_ii(struct usb_device *dev, struct audioformat *fp,
static int parse_audio_format_ii(snd_usb_audio_t *chip, struct audioformat *fp,
				 int format, unsigned char *fmt)
				 int format, unsigned char *fmt)
{
{
	int brate, framesize;
	int brate, framesize;
@@ -2388,7 +2386,7 @@ static int parse_audio_format_ii(struct usb_device *dev, struct audioformat *fp,
		break;
		break;
	default:
	default:
		snd_printd(KERN_INFO "%d:%u:%d : unknown format tag 0x%x is detected.  processed as MPEG.\n",
		snd_printd(KERN_INFO "%d:%u:%d : unknown format tag 0x%x is detected.  processed as MPEG.\n",
			   dev->devnum, fp->iface, fp->altsetting, format);
			   chip->dev->devnum, fp->iface, fp->altsetting, format);
		fp->format = SNDRV_PCM_FORMAT_MPEG;
		fp->format = SNDRV_PCM_FORMAT_MPEG;
		break;
		break;
	}
	}
@@ -2397,10 +2395,10 @@ static int parse_audio_format_ii(struct usb_device *dev, struct audioformat *fp,
	framesize = combine_word(&fmt[6]); /* fmt[6,7]: wSamplesPerFrame */
	framesize = combine_word(&fmt[6]); /* fmt[6,7]: wSamplesPerFrame */
	snd_printd(KERN_INFO "found format II with max.bitrate = %d, frame size=%d\n", brate, framesize);
	snd_printd(KERN_INFO "found format II with max.bitrate = %d, frame size=%d\n", brate, framesize);
	fp->frame_size = framesize;
	fp->frame_size = framesize;
	return parse_audio_format_rates(dev, fp, fmt, 8); /* fmt[8..] sample rates */
	return parse_audio_format_rates(chip, fp, fmt, 8); /* fmt[8..] sample rates */
}
}


static int parse_audio_format(struct usb_device *dev, struct audioformat *fp,
static int parse_audio_format(snd_usb_audio_t *chip, struct audioformat *fp,
			      int format, unsigned char *fmt, int stream)
			      int format, unsigned char *fmt, int stream)
{
{
	int err;
	int err;
@@ -2408,14 +2406,14 @@ static int parse_audio_format(struct usb_device *dev, struct audioformat *fp,
	switch (fmt[3]) {
	switch (fmt[3]) {
	case USB_FORMAT_TYPE_I:
	case USB_FORMAT_TYPE_I:
	case USB_FORMAT_TYPE_III:
	case USB_FORMAT_TYPE_III:
		err = parse_audio_format_i(dev, fp, format, fmt);
		err = parse_audio_format_i(chip, fp, format, fmt);
		break;
		break;
	case USB_FORMAT_TYPE_II:
	case USB_FORMAT_TYPE_II:
		err = parse_audio_format_ii(dev, fp, format, fmt);
		err = parse_audio_format_ii(chip, fp, format, fmt);
		break;
		break;
	default:
	default:
		snd_printd(KERN_INFO "%d:%u:%d : format type %d is not supported yet\n",
		snd_printd(KERN_INFO "%d:%u:%d : format type %d is not supported yet\n",
			   dev->devnum, fp->iface, fp->altsetting, fmt[3]);
			   chip->dev->devnum, fp->iface, fp->altsetting, fmt[3]);
		return -1;
		return -1;
	}
	}
	fp->fmt_type = fmt[3];
	fp->fmt_type = fmt[3];
@@ -2426,9 +2424,8 @@ static int parse_audio_format(struct usb_device *dev, struct audioformat *fp,
	/* extigy apparently supports sample rates other than 48k
	/* extigy apparently supports sample rates other than 48k
	 * but not in ordinary way.  so we enable only 48k atm.
	 * but not in ordinary way.  so we enable only 48k atm.
	 */
	 */
	if (le16_to_cpu(dev->descriptor.idVendor) == 0x041e && 
	if (chip->usb_id == USB_ID(0x041e, 0x3000) ||
	    (le16_to_cpu(dev->descriptor.idProduct) == 0x3000 ||
	    chip->usb_id == USB_ID(0x041e, 0x3020)) {
	     le16_to_cpu(dev->descriptor.idProduct) == 0x3020)) {
		if (fmt[3] == USB_FORMAT_TYPE_I &&
		if (fmt[3] == USB_FORMAT_TYPE_I &&
		    stream == SNDRV_PCM_STREAM_PLAYBACK &&
		    stream == SNDRV_PCM_STREAM_PLAYBACK &&
		    fp->rates != SNDRV_PCM_RATE_48000 &&
		    fp->rates != SNDRV_PCM_RATE_48000 &&
@@ -2532,8 +2529,7 @@ static int parse_audio_endpoints(snd_usb_audio_t *chip, int iface_no)
		/* some quirks for attributes here */
		/* some quirks for attributes here */


		/* workaround for AudioTrak Optoplay */
		/* workaround for AudioTrak Optoplay */
		if (le16_to_cpu(dev->descriptor.idVendor) == 0x0a92 &&
		if (chip->usb_id == USB_ID(0x0a92, 0x0053)) {
		    le16_to_cpu(dev->descriptor.idProduct) == 0x0053) {
			/* Optoplay sets the sample rate attribute although
			/* Optoplay sets the sample rate attribute although
			 * it seems not supporting it in fact.
			 * it seems not supporting it in fact.
			 */
			 */
@@ -2541,8 +2537,7 @@ static int parse_audio_endpoints(snd_usb_audio_t *chip, int iface_no)
		}
		}


		/* workaround for M-Audio Audiophile USB */
		/* workaround for M-Audio Audiophile USB */
		if (le16_to_cpu(dev->descriptor.idVendor) == 0x0763 &&
		if (chip->usb_id == USB_ID(0x0763, 0x2003)) {
		    le16_to_cpu(dev->descriptor.idProduct) == 0x2003) {
			/* doesn't set the sample rate attribute, but supports it */
			/* doesn't set the sample rate attribute, but supports it */
			fp->attributes |= EP_CS_ATTR_SAMPLE_RATE;
			fp->attributes |= EP_CS_ATTR_SAMPLE_RATE;
		}
		}
@@ -2551,11 +2546,9 @@ static int parse_audio_endpoints(snd_usb_audio_t *chip, int iface_no)
		 * plantronics headset and Griffin iMic have set adaptive-in
		 * plantronics headset and Griffin iMic have set adaptive-in
		 * although it's really not...
		 * although it's really not...
		 */
		 */
		if ((le16_to_cpu(dev->descriptor.idVendor) == 0x047f &&
		if (chip->usb_id == USB_ID(0x047f, 0x0ca1) ||
		     le16_to_cpu(dev->descriptor.idProduct) == 0x0ca1) ||
		    /* Griffin iMic (note that there is an older model 77d:223) */
		    /* Griffin iMic (note that there is an older model 77d:223) */
		    (le16_to_cpu(dev->descriptor.idVendor) == 0x077d &&
		    chip->usb_id == USB_ID(0x077d, 0x07af)) {
		     le16_to_cpu(dev->descriptor.idProduct) == 0x07af)) {
			fp->ep_attr &= ~EP_ATTR_MASK;
			fp->ep_attr &= ~EP_ATTR_MASK;
			if (stream == SNDRV_PCM_STREAM_PLAYBACK)
			if (stream == SNDRV_PCM_STREAM_PLAYBACK)
				fp->ep_attr |= EP_ATTR_ADAPTIVE;
				fp->ep_attr |= EP_ATTR_ADAPTIVE;
@@ -2564,7 +2557,7 @@ static int parse_audio_endpoints(snd_usb_audio_t *chip, int iface_no)
		}
		}


		/* ok, let's parse further... */
		/* ok, let's parse further... */
		if (parse_audio_format(dev, fp, format, fmt, stream) < 0) {
		if (parse_audio_format(chip, fp, format, fmt, stream) < 0) {
			kfree(fp->rate_table);
			kfree(fp->rate_table);
			kfree(fp);
			kfree(fp);
			continue;
			continue;
@@ -2799,7 +2792,7 @@ static int create_ua700_ua25_quirk(snd_usb_audio_t *chip,
			.type = QUIRK_MIDI_FIXED_ENDPOINT,
			.type = QUIRK_MIDI_FIXED_ENDPOINT,
			.data = &ua25_ep
			.data = &ua25_ep
		};
		};
		if (le16_to_cpu(chip->dev->descriptor.idProduct) == 0x002b)
		if (chip->usb_id == USB_ID(0x0582, 0x002b))
			return snd_usb_create_midi_interface(chip, iface,
			return snd_usb_create_midi_interface(chip, iface,
							     &ua700_quirk);
							     &ua700_quirk);
		else
		else
@@ -3018,8 +3011,8 @@ static void proc_audio_usbid_read(snd_info_entry_t *entry, snd_info_buffer_t *bu
	snd_usb_audio_t *chip = entry->private_data;
	snd_usb_audio_t *chip = entry->private_data;
	if (! chip->shutdown)
	if (! chip->shutdown)
		snd_iprintf(buffer, "%04x:%04x\n", 
		snd_iprintf(buffer, "%04x:%04x\n", 
			    le16_to_cpu(chip->dev->descriptor.idVendor),
			    USB_ID_VENDOR(chip->usb_id),
			    le16_to_cpu(chip->dev->descriptor.idProduct));
			    USB_ID_PRODUCT(chip->usb_id));
}
}


static void snd_usb_audio_create_proc(snd_usb_audio_t *chip)
static void snd_usb_audio_create_proc(snd_usb_audio_t *chip)
@@ -3089,6 +3082,8 @@ static int snd_usb_audio_create(struct usb_device *dev, int idx,
	chip->index = idx;
	chip->index = idx;
	chip->dev = dev;
	chip->dev = dev;
	chip->card = card;
	chip->card = card;
	chip->usb_id = USB_ID(le16_to_cpu(dev->descriptor.idVendor),
			      le16_to_cpu(dev->descriptor.idProduct));
	INIT_LIST_HEAD(&chip->pcm_list);
	INIT_LIST_HEAD(&chip->pcm_list);
	INIT_LIST_HEAD(&chip->midi_list);
	INIT_LIST_HEAD(&chip->midi_list);
	INIT_LIST_HEAD(&chip->mixer_list);
	INIT_LIST_HEAD(&chip->mixer_list);
@@ -3101,8 +3096,7 @@ static int snd_usb_audio_create(struct usb_device *dev, int idx,


	strcpy(card->driver, "USB-Audio");
	strcpy(card->driver, "USB-Audio");
	sprintf(component, "USB%04x:%04x",
	sprintf(component, "USB%04x:%04x",
		le16_to_cpu(dev->descriptor.idVendor),
		USB_ID_VENDOR(chip->usb_id), USB_ID_PRODUCT(chip->usb_id));
		le16_to_cpu(dev->descriptor.idProduct));
	snd_component_add(card, component);
	snd_component_add(card, component);


	/* retrieve the device string as shortname */
	/* retrieve the device string as shortname */
@@ -3114,8 +3108,8 @@ static int snd_usb_audio_create(struct usb_device *dev, int idx,
      			       card->shortname, sizeof(card->shortname)) <= 0) {
      			       card->shortname, sizeof(card->shortname)) <= 0) {
			/* no name available from anywhere, so use ID */
			/* no name available from anywhere, so use ID */
			sprintf(card->shortname, "USB Device %#04x:%#04x",
			sprintf(card->shortname, "USB Device %#04x:%#04x",
				le16_to_cpu(dev->descriptor.idVendor),
				USB_ID_VENDOR(chip->usb_id),
				le16_to_cpu(dev->descriptor.idProduct));
				USB_ID_PRODUCT(chip->usb_id));
		}
		}
	}
	}


@@ -3173,17 +3167,19 @@ static void *snd_usb_audio_probe(struct usb_device *dev,
	snd_usb_audio_t *chip;
	snd_usb_audio_t *chip;
	struct usb_host_interface *alts;
	struct usb_host_interface *alts;
	int ifnum;
	int ifnum;
	u32 id;


	alts = &intf->altsetting[0];
	alts = &intf->altsetting[0];
	ifnum = get_iface_desc(alts)->bInterfaceNumber;
	ifnum = get_iface_desc(alts)->bInterfaceNumber;
	id = USB_ID(le16_to_cpu(dev->descriptor.idVendor),
		    le16_to_cpu(dev->descriptor.idProduct));


	if (quirk && quirk->ifnum >= 0 && ifnum != quirk->ifnum)
	if (quirk && quirk->ifnum >= 0 && ifnum != quirk->ifnum)
		goto __err_val;
		goto __err_val;


	/* SB Extigy needs special boot-up sequence */
	/* SB Extigy needs special boot-up sequence */
	/* if more models come, this will go to the quirk list. */
	/* if more models come, this will go to the quirk list. */
	if (le16_to_cpu(dev->descriptor.idVendor) == 0x041e && 
	if (id == USB_ID(0x041e, 0x3000)) {
	    le16_to_cpu(dev->descriptor.idProduct) == 0x3000) {
		if (snd_usb_extigy_boot_quirk(dev, intf) < 0)
		if (snd_usb_extigy_boot_quirk(dev, intf) < 0)
			goto __err_val;
			goto __err_val;
		config = dev->actconfig;
		config = dev->actconfig;
@@ -3217,8 +3213,8 @@ static void *snd_usb_audio_probe(struct usb_device *dev,
		}
		}
		for (i = 0; i < SNDRV_CARDS; i++)
		for (i = 0; i < SNDRV_CARDS; i++)
			if (enable[i] && ! usb_chip[i] &&
			if (enable[i] && ! usb_chip[i] &&
			    (vid[i] == -1 || vid[i] == le16_to_cpu(dev->descriptor.idVendor)) &&
			    (vid[i] == -1 || vid[i] == USB_ID_VENDOR(id)) &&
			    (pid[i] == -1 || pid[i] == le16_to_cpu(dev->descriptor.idProduct))) {
			    (pid[i] == -1 || pid[i] == USB_ID_PRODUCT(id))) {
				if (snd_usb_audio_create(dev, i, quirk, &chip) < 0) {
				if (snd_usb_audio_create(dev, i, quirk, &chip) < 0) {
					goto __error;
					goto __error;
				}
				}
+6 −0
Original line number Original line Diff line number Diff line
@@ -118,6 +118,11 @@
/* maximum number of endpoints per interface */
/* maximum number of endpoints per interface */
#define MIDI_MAX_ENDPOINTS 2
#define MIDI_MAX_ENDPOINTS 2


/* handling of USB vendor/product ID pairs as 32-bit numbers */
#define USB_ID(vendor, product) (((vendor) << 16) | (product))
#define USB_ID_VENDOR(id) ((id) >> 16)
#define USB_ID_PRODUCT(id) ((u16)(id))

/*
/*
 */
 */


@@ -127,6 +132,7 @@ struct snd_usb_audio {
	int index;
	int index;
	struct usb_device *dev;
	struct usb_device *dev;
	snd_card_t *card;
	snd_card_t *card;
	u32 usb_id;
	int shutdown;
	int shutdown;
	int num_interfaces;
	int num_interfaces;


+59 −64
Original line number Original line Diff line number Diff line
@@ -955,88 +955,87 @@ static snd_rawmidi_substream_t* snd_usbmidi_find_substream(snd_usb_midi_t* umidi
 * such as internal control or synthesizer ports.
 * such as internal control or synthesizer ports.
 */
 */
static struct {
static struct {
	__u16 vendor;
	u32 id;
	__u16 product;
	int port;
	int port;
	const char *name_format;
	const char *name_format;
} snd_usbmidi_port_names[] = {
} snd_usbmidi_port_names[] = {
	/* Roland UA-100 */
	/* Roland UA-100 */
	{0x0582, 0x0000, 2, "%s Control"},
	{ USB_ID(0x0582, 0x0000), 2, "%s Control" },
	/* Roland SC-8850 */
	/* Roland SC-8850 */
	{0x0582, 0x0003, 0, "%s Part A"},
	{ USB_ID(0x0582, 0x0003), 0, "%s Part A" },
	{0x0582, 0x0003, 1, "%s Part B"},
	{ USB_ID(0x0582, 0x0003), 1, "%s Part B" },
	{0x0582, 0x0003, 2, "%s Part C"},
	{ USB_ID(0x0582, 0x0003), 2, "%s Part C" },
	{0x0582, 0x0003, 3, "%s Part D"},
	{ USB_ID(0x0582, 0x0003), 3, "%s Part D" },
	{0x0582, 0x0003, 4, "%s MIDI 1"},
	{ USB_ID(0x0582, 0x0003), 4, "%s MIDI 1" },
	{0x0582, 0x0003, 5, "%s MIDI 2"},
	{ USB_ID(0x0582, 0x0003), 5, "%s MIDI 2" },
	/* Roland U-8 */
	/* Roland U-8 */
	{0x0582, 0x0004, 0, "%s MIDI"},
	{ USB_ID(0x0582, 0x0004), 0, "%s MIDI" },
	{0x0582, 0x0004, 1, "%s Control"},
	{ USB_ID(0x0582, 0x0004), 1, "%s Control" },
	/* Roland SC-8820 */
	/* Roland SC-8820 */
	{0x0582, 0x0007, 0, "%s Part A"},
	{ USB_ID(0x0582, 0x0007), 0, "%s Part A" },
	{0x0582, 0x0007, 1, "%s Part B"},
	{ USB_ID(0x0582, 0x0007), 1, "%s Part B" },
	{0x0582, 0x0007, 2, "%s MIDI"},
	{ USB_ID(0x0582, 0x0007), 2, "%s MIDI" },
	/* Roland SK-500 */
	/* Roland SK-500 */
	{0x0582, 0x000b, 0, "%s Part A"},
	{ USB_ID(0x0582, 0x000b), 0, "%s Part A" },
	{0x0582, 0x000b, 1, "%s Part B"},
	{ USB_ID(0x0582, 0x000b), 1, "%s Part B" },
	{0x0582, 0x000b, 2, "%s MIDI"},
	{ USB_ID(0x0582, 0x000b), 2, "%s MIDI" },
	/* Roland SC-D70 */
	/* Roland SC-D70 */
	{0x0582, 0x000c, 0, "%s Part A"},
	{ USB_ID(0x0582, 0x000c), 0, "%s Part A" },
	{0x0582, 0x000c, 1, "%s Part B"},
	{ USB_ID(0x0582, 0x000c), 1, "%s Part B" },
	{0x0582, 0x000c, 2, "%s MIDI"},
	{ USB_ID(0x0582, 0x000c), 2, "%s MIDI" },
	/* Edirol UM-880 */
	/* Edirol UM-880 */
	{0x0582, 0x0014, 8, "%s Control"},
	{ USB_ID(0x0582, 0x0014), 8, "%s Control" },
	/* Edirol SD-90 */
	/* Edirol SD-90 */
	{0x0582, 0x0016, 0, "%s Part A"},
	{ USB_ID(0x0582, 0x0016), 0, "%s Part A" },
	{0x0582, 0x0016, 1, "%s Part B"},
	{ USB_ID(0x0582, 0x0016), 1, "%s Part B" },
	{0x0582, 0x0016, 2, "%s MIDI 1"},
	{ USB_ID(0x0582, 0x0016), 2, "%s MIDI 1" },
	{0x0582, 0x0016, 3, "%s MIDI 2"},
	{ USB_ID(0x0582, 0x0016), 3, "%s MIDI 2" },
	/* Edirol UM-550 */
	/* Edirol UM-550 */
	{0x0582, 0x0023, 5, "%s Control"},
	{ USB_ID(0x0582, 0x0023), 5, "%s Control" },
	/* Edirol SD-20 */
	/* Edirol SD-20 */
	{0x0582, 0x0027, 0, "%s Part A"},
	{ USB_ID(0x0582, 0x0027), 0, "%s Part A" },
	{0x0582, 0x0027, 1, "%s Part B"},
	{ USB_ID(0x0582, 0x0027), 1, "%s Part B" },
	{0x0582, 0x0027, 2, "%s MIDI"},
	{ USB_ID(0x0582, 0x0027), 2, "%s MIDI" },
	/* Edirol SD-80 */
	/* Edirol SD-80 */
	{0x0582, 0x0029, 0, "%s Part A"},
	{ USB_ID(0x0582, 0x0029), 0, "%s Part A" },
	{0x0582, 0x0029, 1, "%s Part B"},
	{ USB_ID(0x0582, 0x0029), 1, "%s Part B" },
	{0x0582, 0x0029, 2, "%s MIDI 1"},
	{ USB_ID(0x0582, 0x0029), 2, "%s MIDI 1" },
	{0x0582, 0x0029, 3, "%s MIDI 2"},
	{ USB_ID(0x0582, 0x0029), 3, "%s MIDI 2" },
	/* Edirol UA-700 */
	/* Edirol UA-700 */
	{0x0582, 0x002b, 0, "%s MIDI"},
	{ USB_ID(0x0582, 0x002b), 0, "%s MIDI" },
	{0x0582, 0x002b, 1, "%s Control"},
	{ USB_ID(0x0582, 0x002b), 1, "%s Control" },
	/* Roland VariOS */
	/* Roland VariOS */
	{0x0582, 0x002f, 0, "%s MIDI"},
	{ USB_ID(0x0582, 0x002f), 0, "%s MIDI" },
	{0x0582, 0x002f, 1, "%s External MIDI"},
	{ USB_ID(0x0582, 0x002f), 1, "%s External MIDI" },
	{0x0582, 0x002f, 2, "%s Sync"},
	{ USB_ID(0x0582, 0x002f), 2, "%s Sync" },
	/* Edirol PCR */
	/* Edirol PCR */
	{0x0582, 0x0033, 0, "%s MIDI"},
	{ USB_ID(0x0582, 0x0033), 0, "%s MIDI" },
	{0x0582, 0x0033, 1, "%s 1"},
	{ USB_ID(0x0582, 0x0033), 1, "%s 1" },
	{0x0582, 0x0033, 2, "%s 2"},
	{ USB_ID(0x0582, 0x0033), 2, "%s 2" },
	/* BOSS GS-10 */
	/* BOSS GS-10 */
	{0x0582, 0x003b, 0, "%s MIDI"},
	{ USB_ID(0x0582, 0x003b), 0, "%s MIDI" },
	{0x0582, 0x003b, 1, "%s Control"},
	{ USB_ID(0x0582, 0x003b), 1, "%s Control" },
	/* Edirol UA-1000 */
	/* Edirol UA-1000 */
	{0x0582, 0x0044, 0, "%s MIDI"},
	{ USB_ID(0x0582, 0x0044), 0, "%s MIDI" },
	{0x0582, 0x0044, 1, "%s Control"},
	{ USB_ID(0x0582, 0x0044), 1, "%s Control" },
	/* Edirol UR-80 */
	/* Edirol UR-80 */
	{0x0582, 0x0048, 0, "%s MIDI"},
	{ USB_ID(0x0582, 0x0048), 0, "%s MIDI" },
	{0x0582, 0x0048, 1, "%s 1"},
	{ USB_ID(0x0582, 0x0048), 1, "%s 1" },
	{0x0582, 0x0048, 2, "%s 2"},
	{ USB_ID(0x0582, 0x0048), 2, "%s 2" },
	/* Edirol PCR-A */
	/* Edirol PCR-A */
	{0x0582, 0x004d, 0, "%s MIDI"},
	{ USB_ID(0x0582, 0x004d), 0, "%s MIDI" },
	{0x0582, 0x004d, 1, "%s 1"},
	{ USB_ID(0x0582, 0x004d), 1, "%s 1" },
	{0x0582, 0x004d, 2, "%s 2"},
	{ USB_ID(0x0582, 0x004d), 2, "%s 2" },
	/* M-Audio MidiSport 8x8 */
	/* M-Audio MidiSport 8x8 */
	{0x0763, 0x1031, 8, "%s Control"},
	{ USB_ID(0x0763, 0x1031), 8, "%s Control" },
	{0x0763, 0x1033, 8, "%s Control"},
	{ USB_ID(0x0763, 0x1033), 8, "%s Control" },
	/* MOTU Fastlane */
	/* MOTU Fastlane */
	{0x07fd, 0x0001, 0, "%s MIDI A"},
	{ USB_ID(0x07fd, 0x0001), 0, "%s MIDI A" },
	{0x07fd, 0x0001, 1, "%s MIDI B"},
	{ USB_ID(0x07fd, 0x0001), 1, "%s MIDI B" },
	/* Emagic Unitor8/AMT8/MT4 */
	/* Emagic Unitor8/AMT8/MT4 */
	{0x086a, 0x0001, 8, "%s Broadcast"},
	{ USB_ID(0x086a, 0x0001), 8, "%s Broadcast" },
	{0x086a, 0x0002, 8, "%s Broadcast"},
	{ USB_ID(0x086a, 0x0002), 8, "%s Broadcast" },
	{0x086a, 0x0003, 4, "%s Broadcast"},
	{ USB_ID(0x086a, 0x0003), 4, "%s Broadcast" },
};
};


static void snd_usbmidi_init_substream(snd_usb_midi_t* umidi,
static void snd_usbmidi_init_substream(snd_usb_midi_t* umidi,
@@ -1044,7 +1043,6 @@ static void snd_usbmidi_init_substream(snd_usb_midi_t* umidi,
				       snd_rawmidi_substream_t** rsubstream)
				       snd_rawmidi_substream_t** rsubstream)
{
{
	int i;
	int i;
	__u16 vendor, product;
	const char *name_format;
	const char *name_format;


	snd_rawmidi_substream_t* substream = snd_usbmidi_find_substream(umidi, stream, number);
	snd_rawmidi_substream_t* substream = snd_usbmidi_find_substream(umidi, stream, number);
@@ -1055,11 +1053,8 @@ static void snd_usbmidi_init_substream(snd_usb_midi_t* umidi,


	/* TODO: read port name from jack descriptor */
	/* TODO: read port name from jack descriptor */
	name_format = "%s MIDI %d";
	name_format = "%s MIDI %d";
	vendor = le16_to_cpu(umidi->chip->dev->descriptor.idVendor);
	product = le16_to_cpu(umidi->chip->dev->descriptor.idProduct);
	for (i = 0; i < ARRAY_SIZE(snd_usbmidi_port_names); ++i) {
	for (i = 0; i < ARRAY_SIZE(snd_usbmidi_port_names); ++i) {
		if (snd_usbmidi_port_names[i].vendor == vendor &&
		if (snd_usbmidi_port_names[i].id == umidi->chip->usb_id &&
		    snd_usbmidi_port_names[i].product == product &&
		    snd_usbmidi_port_names[i].port == number) {
		    snd_usbmidi_port_names[i].port == number) {
			name_format = snd_usbmidi_port_names[i].name_format;
			name_format = snd_usbmidi_port_names[i].name_format;
			break;
			break;
@@ -1226,7 +1221,7 @@ static int snd_usbmidi_detect_endpoints(snd_usb_midi_t* umidi,
	struct usb_endpoint_descriptor* epd;
	struct usb_endpoint_descriptor* epd;
	int i, out_eps = 0, in_eps = 0;
	int i, out_eps = 0, in_eps = 0;


	if (le16_to_cpu(umidi->chip->dev->descriptor.idVendor) == 0x0582)
	if (USB_ID_VENDOR(umidi->chip->usb_id) == 0x0582)
		snd_usbmidi_switch_roland_altsetting(umidi);
		snd_usbmidi_switch_roland_altsetting(umidi);


	if (endpoint[0].out_ep || endpoint[0].in_ep)
	if (endpoint[0].out_ep || endpoint[0].in_ep)
+18 −20
Original line number Original line Diff line number Diff line
@@ -89,8 +89,6 @@ struct usb_mixer_build {
	struct usb_mixer_interface *mixer;
	struct usb_mixer_interface *mixer;
	unsigned char *buffer;
	unsigned char *buffer;
	unsigned int buflen;
	unsigned int buflen;
	unsigned short vendor;
	unsigned short product;
	DECLARE_BITMAP(unitbitmap, 256);
	DECLARE_BITMAP(unitbitmap, 256);
	usb_audio_term_t oterm;
	usb_audio_term_t oterm;
	const struct usbmix_name_map *map;
	const struct usbmix_name_map *map;
@@ -906,12 +904,17 @@ static void build_feature_ctl(mixer_build_t *state, unsigned char *desc,
	/* note that detection between firmware 2.1.1.7 (N101) and later 2.1.1.21 */
	/* note that detection between firmware 2.1.1.7 (N101) and later 2.1.1.21 */
	/* is not very clear from datasheets */
	/* is not very clear from datasheets */
	/* I hope that the min value is -15360 for newer firmware --jk */
	/* I hope that the min value is -15360 for newer firmware --jk */
	if (((state->vendor == 0x471 && (state->product == 0x104 || state->product == 0x105 || state->product == 0x101)) ||
	switch (state->chip->usb_id) {
	     (state->vendor == 0x672 && state->product == 0x1041)) && !strcmp(kctl->id.name, "PCM Playback Volume") &&
	case USB_ID(0x0471, 0x0101):
	case USB_ID(0x0471, 0x0104):
	case USB_ID(0x0471, 0x0105):
	case USB_ID(0x0672, 0x1041):
		if (!strcmp(kctl->id.name, "PCM Playback Volume") &&
		    cval->min == -15616) {
		    cval->min == -15616) {
		snd_printk("USB Audio: using volume control quirk for the UDA1321/N101 chip\n");
			snd_printk("using volume control quirk for the UDA1321/N101 chip\n");
			cval->max = -256;
			cval->max = -256;
		}
		}
	}


	snd_printdd(KERN_INFO "[%d] FU [%s] ch = %d, val = %d/%d/%d\n",
	snd_printdd(KERN_INFO "[%d] FU [%s] ch = %d, val = %d/%d/%d\n",
		    cval->id, kctl->id.name, cval->channels, cval->min, cval->max, cval->res);
		    cval->id, kctl->id.name, cval->channels, cval->min, cval->max, cval->res);
@@ -1574,7 +1577,6 @@ static int snd_usb_mixer_controls(struct usb_mixer_interface *mixer)
	mixer_build_t state;
	mixer_build_t state;
	int err;
	int err;
	const struct usbmix_ctl_map *map;
	const struct usbmix_ctl_map *map;
	struct usb_device_descriptor *dev = &mixer->chip->dev->descriptor;
	struct usb_host_interface *hostif;
	struct usb_host_interface *hostif;


	hostif = &usb_ifnum_to_if(mixer->chip->dev, mixer->ctrlif)->altsetting[0];
	hostif = &usb_ifnum_to_if(mixer->chip->dev, mixer->ctrlif)->altsetting[0];
@@ -1583,12 +1585,10 @@ static int snd_usb_mixer_controls(struct usb_mixer_interface *mixer)
	state.mixer = mixer;
	state.mixer = mixer;
	state.buffer = hostif->extra;
	state.buffer = hostif->extra;
	state.buflen = hostif->extralen;
	state.buflen = hostif->extralen;
	state.vendor = le16_to_cpu(dev->idVendor);
	state.product = le16_to_cpu(dev->idProduct);


	/* check the mapping table */
	/* check the mapping table */
	for (map = usbmix_ctl_maps; map->vendor; map++) {
	for (map = usbmix_ctl_maps; map->id; map++) {
		if (map->vendor == state.vendor && map->product == state.product) {
		if (map->id == state.chip->usb_id) {
			state.map = map->map;
			state.map = map->map;
			state.selector_map = map->selector_map;
			state.selector_map = map->selector_map;
			mixer->ignore_ctl_error = map->ignore_ctl_error;
			mixer->ignore_ctl_error = map->ignore_ctl_error;
@@ -1766,12 +1766,12 @@ static int snd_usb_soundblaster_remote_init(struct usb_mixer_interface *mixer)
	snd_hwdep_t *hwdep;
	snd_hwdep_t *hwdep;
	int err, len;
	int err, len;


	switch (le16_to_cpu(mixer->chip->dev->descriptor.idProduct)) {
	switch (mixer->chip->usb_id) {
	case 0x3000:
	case USB_ID(0x041e, 0x3000):
		mixer->rc_type = RC_EXTIGY;
		mixer->rc_type = RC_EXTIGY;
		len = 2;
		len = 2;
		break;
		break;
	case 0x3020:
	case USB_ID(0x041e, 0x3020):
		mixer->rc_type = RC_AUDIGY2NX;
		mixer->rc_type = RC_AUDIGY2NX;
		len = 6;
		len = 6;
		break;
		break;
@@ -1844,12 +1844,10 @@ int snd_usb_create_mixer(snd_usb_audio_t *chip, int ctrlif)
		return err;
		return err;
	}
	}


	if (le16_to_cpu(chip->dev->descriptor.idVendor) == 0x041e) {
	if ((err = snd_usb_soundblaster_remote_init(mixer)) < 0) {
	if ((err = snd_usb_soundblaster_remote_init(mixer)) < 0) {
		snd_usb_mixer_free(mixer);
		snd_usb_mixer_free(mixer);
		return err;
		return err;
	}
	}
	}


	err = snd_device_new(chip->card, SNDRV_DEV_LOWLEVEL, mixer, &dev_ops);
	err = snd_device_new(chip->card, SNDRV_DEV_LOWLEVEL, mixer, &dev_ops);
	if (err < 0) {
	if (err < 0) {
+6 −7
Original line number Original line Diff line number Diff line
@@ -33,8 +33,7 @@ struct usbmix_selector_map {
};
};


struct usbmix_ctl_map {
struct usbmix_ctl_map {
	int vendor;
	u32 id;
	int product;
	const struct usbmix_name_map *map;
	const struct usbmix_name_map *map;
	const struct usbmix_selector_map *selector_map;
	const struct usbmix_selector_map *selector_map;
	int ignore_ctl_error;
	int ignore_ctl_error;
@@ -225,26 +224,26 @@ static struct usbmix_name_map justlink_map[] = {


static struct usbmix_ctl_map usbmix_ctl_maps[] = {
static struct usbmix_ctl_map usbmix_ctl_maps[] = {
	{
	{
		.vendor = 0x41e, .product = 0x3000,
		.id = USB_ID(0x041e, 0x3000),
		.map = extigy_map,
		.map = extigy_map,
		.ignore_ctl_error = 1,
		.ignore_ctl_error = 1,
	},
	},
	{
	{
		.vendor = 0x41e, .product = 0x3010,
		.id = USB_ID(0x041e, 0x3010),
		.map = mp3plus_map,
		.map = mp3plus_map,
	},
	},
	{
	{
		.vendor = 0x41e, .product = 0x3020,
		.id = USB_ID(0x041e, 0x3020),
		.map = audigy2nx_map,
		.map = audigy2nx_map,
		.selector_map = audigy2nx_selectors,
		.selector_map = audigy2nx_selectors,
	},
	},
	{
	{
		.vendor = 0x8bb, .product = 0x2702,
		.id = USB_ID(0x08bb, 0x2702),
		.map = linex_map,
		.map = linex_map,
		.ignore_ctl_error = 1,
		.ignore_ctl_error = 1,
	},
	},
	{
	{
		.vendor = 0xc45, .product = 0x1158,
		.id = USB_ID(0x0c45, 0x1158),
		.map = justlink_map,
		.map = justlink_map,
	},
	},
	{ 0 } /* terminator */
	{ 0 } /* terminator */