Example #1
0
/*
 * parse the format type I and III descriptors
 */
static int parse_audio_format_i(struct snd_usb_audio *chip,
				struct audioformat *fp, int format,
				struct uac_format_type_i_continuous_descriptor *fmt,
				struct usb_host_interface *iface)
{
	struct usb_interface_descriptor *altsd = get_iface_desc(iface);
	int protocol = altsd->bInterfaceProtocol;
	int pcm_format, ret;

	if (fmt->bFormatType == UAC_FORMAT_TYPE_III) {
		/* FIXME: the format type is really IECxxx
		 *        but we give normal PCM format to get the existing
		 *        apps working...
		 */
		switch (chip->usb_id) {

		case USB_ID(0x0763, 0x2003): /* M-Audio Audiophile USB */
			if (chip->setup == 0x00 &&
			    fp->altsetting == 6)
				pcm_format = SNDRV_PCM_FORMAT_S16_BE;
			else
				pcm_format = SNDRV_PCM_FORMAT_S16_LE;
			break;
		default:
			pcm_format = SNDRV_PCM_FORMAT_S16_LE;
		}
		fp->formats = 1uLL << pcm_format;
	} else {
		fp->formats = parse_audio_format_i_type(chip, fp, format,
							fmt, protocol);
		if (!fp->formats)
			return -1;
	}

	/* gather possible sample rates */
	/* audio class v1 reports possible sample rates as part of the
	 * proprietary class specific descriptor.
	 * audio class v2 uses class specific EP0 range requests for that.
	 */
	switch (protocol) {
	default:
		/* fall through */
	case UAC_VERSION_1:
		fp->channels = fmt->bNrChannels;
		ret = parse_audio_format_rates_v1(chip, fp, (unsigned char *) fmt, 7);
		break;
	case UAC_VERSION_2:
		/* fp->channels is already set in this case */
		ret = parse_audio_format_rates_v2(chip, fp);
		break;
	}

	if (fp->channels < 1) {
		snd_printk(KERN_ERR "%d:%u:%d : invalid channels %d\n",
			   chip->dev->devnum, fp->iface, fp->altsetting, fp->channels);
		return -1;
	}

	return ret;
}
Example #2
0
/*
 * parse the format type I and III descriptors
 */
static int parse_audio_format_i(struct snd_usb_audio *chip,
				struct audioformat *fp, u64 format,
				void *_fmt)
{
	snd_pcm_format_t pcm_format;
	unsigned int fmt_type;
	int ret;

	switch (fp->protocol) {
	default:
	case UAC_VERSION_1:
	case UAC_VERSION_2: {
		struct uac_format_type_i_continuous_descriptor *fmt = _fmt;

		fmt_type = fmt->bFormatType;
		break;
	}
	case UAC_VERSION_3: {
		/* fp->fmt_type is already set in this case */
		fmt_type = fp->fmt_type;
		break;
	}
	}

	if (fmt_type == UAC_FORMAT_TYPE_III) {
		/* FIXME: the format type is really IECxxx
		 *        but we give normal PCM format to get the existing
		 *        apps working...
		 */
		switch (chip->usb_id) {

		case USB_ID(0x0763, 0x2003): /* M-Audio Audiophile USB */
			if (chip->setup == 0x00 && 
			    fp->altsetting == 6)
				pcm_format = SNDRV_PCM_FORMAT_S16_BE;
			else
				pcm_format = SNDRV_PCM_FORMAT_S16_LE;
			break;
		default:
			pcm_format = SNDRV_PCM_FORMAT_S16_LE;
		}
		fp->formats = pcm_format_to_bits(pcm_format);
	} else {
		fp->formats = parse_audio_format_i_type(chip, fp, format, _fmt);
		if (!fp->formats)
			return -EINVAL;
	}

	/* gather possible sample rates */
	/* audio class v1 reports possible sample rates as part of the
	 * proprietary class specific descriptor.
	 * audio class v2 uses class specific EP0 range requests for that.
	 */
	switch (fp->protocol) {
	default:
	case UAC_VERSION_1: {
		struct uac_format_type_i_continuous_descriptor *fmt = _fmt;

		fp->channels = fmt->bNrChannels;
		ret = parse_audio_format_rates_v1(chip, fp, (unsigned char *) fmt, 7);
		break;
	}
	case UAC_VERSION_2:
	case UAC_VERSION_3: {
		/* fp->channels is already set in this case */
		ret = parse_audio_format_rates_v2v3(chip, fp);
		break;
	}
	}

	if (fp->channels < 1) {
		usb_audio_err(chip,
			"%u:%d : invalid channels %d\n",
			fp->iface, fp->altsetting, fp->channels);
		return -EINVAL;
	}

	return ret;
}