All of lore.kernel.org
 help / color / mirror / Atom feed
From: Takashi Iwai <tiwai@suse.de>
To: Patrick Shirkey <pshirkey@boosthardware.com>
Cc: alsa-devel@lists.sourceforge.net
Subject: Re: status of usb audio driver
Date: Thu, 13 Jun 2002 12:39:14 +0200	[thread overview]
Message-ID: <s5hr8jbzcml.wl@alsa2.suse.de> (raw)
In-Reply-To: <3D078560.4030707@boosthardware.com>

[-- Attachment #1: Type: text/plain, Size: 2126 bytes --]

At Thu, 13 Jun 2002 02:31:12 +0900,
Patrick Shirkey wrote:
> 
> Takashi Iwai wrote:
> > At Thu, 13 Jun 2002 01:48:33 +0900,
> > Patrick Shirkey wrote:
> > 
> >>Patrick Shirkey wrote:
> >>
> >>>Patrick Shirkey wrote:
> >>>
> >>>
> >>>>i have been testing the sound and I am getting playback although at 
> >>>>this point I can get sound out of hw:2,0 and hw:2,2 they are both the 
> >>>>left channels. The sound is scratchy but it is there :)
> >>>>
> >>>
> >>>The sound is actually coming through output 2 and 4 on the sound card 
> >>>even though I'm using hw:2,0 or hw:2,2.
> >>>
> >>
> >>When I use the first two pcm devices the sound is sent through output 2 
> >>on the card and when I use the third the sound is sent through output 4.

actually the endpoints of the first two pcm streams are identical.
is the sound only mono?
on the description, it's defined as stereo streams.
so i guess quattro has two stereo streams, corresponding #0 (or #1)
and #2.
it seems that the stream #0 has only 16bit 44.1kHz at most, while the
stream #1 supports 16/24bit 48kHz (although 24bit-3bytes format is not
supported on alsa yet).


> > i committed a minor change to cvs.
> > now endpoints will be shown in each proc file.
> > could you apply and send me the output of each proc file?
> > i'd like to know whether really endpoints are parsed correctly.
> > 
> > 
> 
>  From the looks of things they are not.

well, it looks ok.  the stream corresponds correctly to the
description.

> 
> > 
> >>I have also tested capture and the card is not working with that yet.
> >>
> >>It will attempt to record for a few seconds but will not write to a file 
> >>or produce any noise either with direct monitoring enabled or not. Also 
> >>  recording locks the mouse until either it has finished or is ctrl+c'd.
> > 
> > 
> > hmm, this sounds bad.
> > i'm not sure whether this is a general capture problem on usb audio.
> > i'll borrow a usb mic tomorrow and test with it.

i've tested usb mic from Labtec, and it works.
so the problem is specific to the hardware, or multi-channels...


anyway, could you try the attached patch?


Takashi

[-- Attachment #2: usb-fix2.dif --]
[-- Type: application/octet-stream, Size: 10786 bytes --]

Index: alsa-driver/usb/usbaudio.c
===================================================================
RCS file: /suse/tiwai/cvs/alsa/alsa-driver/usb/usbaudio.c,v
retrieving revision 1.11
diff -u -r1.11 usbaudio.c
--- alsa-driver/usb/usbaudio.c	12 Jun 2002 16:56:40 -0000	1.11
+++ alsa-driver/usb/usbaudio.c	13 Jun 2002 10:36:04 -0000
@@ -42,7 +42,7 @@
 #include "usbaudio.h"
 
 
-EXPORT_NO_SYMBOLS;
+EXPORT_NO_SYMBOLS; /* for kernels < 2.5 */
 
 MODULE_AUTHOR("Takashi Iwai <tiwai@suse.de>");
 MODULE_DESCRIPTION("USB Audio");
@@ -84,6 +84,7 @@
 	unsigned char altset_idx;	/* array index of altenate setting */
 	unsigned char attributes;	/* corresponding attributes of cs endpoint */
 	unsigned char endpoint;		/* endpoint */
+	unsigned char ep_attr;		/* endpoint attributes */
 	unsigned int rates;		/* rate bitmasks */
 	int rate_min, rate_max;		/* min/max rates */
 	int nr_rates;			/* number of rate table entries */
@@ -257,7 +258,7 @@
 {
 	unsigned long flags;
 	unsigned char *cp;
-	int stride, i, len;
+	int stride, i, len, oldptr;
 
 	stride = runtime->frame_bits >> 3;
 
@@ -268,20 +269,25 @@
 		len = urb->iso_frame_desc[i].actual_length / stride;
 		if (! len)
 			continue;
+		/* update the current pointer */
 		spin_lock_irqsave(&subs->lock, flags);
+		oldptr = subs->hwptr_done;
+		subs->hwptr_done += len;
+		if (subs->hwptr_done >= runtime->buffer_size)
+			subs->hwptr_done -= runtime->buffer_size;
+		subs->transfer_done += len;
+		spin_unlock_irqrestore(&subs->lock, flags);
 		/* copy a data chunk */
-		if (subs->hwptr_done + len >= runtime->buffer_size) {
-			int cnt = runtime->buffer_size - subs->hwptr_done;
+		if (oldptr + len >= runtime->buffer_size) {
+			int cnt = runtime->buffer_size - oldptr;
 			int blen = cnt * stride;
-			memcpy(runtime->dma_area + subs->hwptr_done * stride, cp, blen);
+			memcpy(runtime->dma_area + oldptr * stride, cp, blen);
 			memcpy(runtime->dma_area, cp + blen, len * stride - blen);
-			subs->hwptr_done = len - cnt;
 		} else {
 			memcpy(runtime->dma_area + subs->hwptr_done * stride, cp, len * stride);
-			subs->hwptr_done += len;
 		}
 		/* update the pointer, call callback if necessary */
-		subs->transfer_done += len;
+		spin_lock_irqsave(&subs->lock, flags);
 		if (subs->transfer_done >= runtime->period_size) {
 			subs->transfer_done -= runtime->period_size;
 			spin_unlock_irqrestore(&subs->lock, flags);
@@ -727,8 +733,8 @@
 	/* calculate the max. size of packet */
 	maxsize = ((subs->freqmax + 0x3fff) * (runtime->frame_bits >> 3)) >> 14;
 	if (subs->maxpacksize && maxsize > subs->maxpacksize) {
-		snd_printd(KERN_DEBUG "maxsize %d is greater than defined size %d\n",
-			   maxsize, subs->maxpacksize);
+		//snd_printd(KERN_DEBUG "maxsize %d is greater than defined size %d\n",
+		//	   maxsize, subs->maxpacksize);
 		maxsize = subs->maxpacksize;
 	}
 
@@ -851,6 +857,63 @@
 	return NULL;
 }
 
+
+/* FIXME: stolen from usb/message.c
+ *    alternate setting value doesn't match always with the array index.
+ *    let's see whether this works...
+ */
+static void hack_usb_set_maxpacket(struct usb_device *dev)
+{
+	int i, b;
+
+	for (i=0; i<dev->actconfig->bNumInterfaces; i++) {
+		struct usb_interface *ifp = dev->actconfig->interface + i;
+		struct usb_interface_descriptor *as = ifp->altsetting + ifp->act_altsetting;
+		struct usb_endpoint_descriptor *ep = as->endpoint;
+		int e;
+
+		for (e=0; e<as->bNumEndpoints; e++) {
+			b = ep[e].bEndpointAddress & USB_ENDPOINT_NUMBER_MASK;
+			if (usb_endpoint_out(ep[e].bEndpointAddress)) {
+				if (ep[e].wMaxPacketSize > dev->epmaxpacketout[b])
+					dev->epmaxpacketout[b] = ep[e].wMaxPacketSize;
+			}
+			else {
+				if (ep[e].wMaxPacketSize > dev->epmaxpacketin [b])
+					dev->epmaxpacketin [b] = ep[e].wMaxPacketSize;
+			}
+		}
+	}
+}
+
+static int hack_usb_set_interface(struct usb_device *dev, int interface, int alt_idx, int alternate)
+{
+	struct usb_interface *iface;
+	struct usb_interface_descriptor *iface_as;
+	int i, ret;
+
+	iface = usb_ifnum_to_if(dev, interface);
+	if (!iface)
+		return -EINVAL;
+	if (iface->num_altsetting == 1)
+		return 0;
+
+	if ((ret = usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
+				   USB_REQ_SET_INTERFACE, USB_RECIP_INTERFACE,
+				   alternate,
+				   interface, NULL, 0, HZ * 5)) < 0)
+		return ret;
+
+	iface->act_altsetting = alt_idx;
+	iface_as = &iface->altsetting[alt_idx];
+	for (i = 0; i < iface_as->bNumEndpoints; i++) {
+		u8 ep = iface_as->endpoint[i].bEndpointAddress;
+		usb_settoggle(dev, ep&USB_ENDPOINT_NUMBER_MASK, usb_endpoint_out(ep), 0);
+	}
+	hack_usb_set_maxpacket(dev);
+	return 0;
+}
+
 /*
  * find a matching format and set up the interface
  */
@@ -868,8 +931,8 @@
 
 	fmt = find_format(subs, runtime);
 	if (! fmt) {
-		snd_printd(KERN_DEBUG "cannot set format: format = %d, rate = %d, channels = %d\n",
-			   runtime->format, runtime->rate, runtime->channels);
+		snd_printd(KERN_DEBUG "cannot set format: format = %s, rate = %d, channels = %d\n",
+			   snd_pcm_format_name(runtime->format), runtime->rate, runtime->channels);
 		return -EINVAL;
 	}
 
@@ -916,7 +979,7 @@
 	}
 
 	/* set interface */
-	if (usb_set_interface(dev, iface->altsetting->bInterfaceNumber, fmt->altset_idx) < 0) {
+	if (hack_usb_set_interface(dev, subs->interface, fmt->altset_idx, fmt->altsetting) < 0) {
 		snd_printk(KERN_ERR "%d:%d:%d: usb_set_interface failed\n",
 			   dev->devnum, subs->interface, fmt->altsetting);
 		return -EIO;
@@ -926,7 +989,8 @@
 	/* if endpoint has pitch control, enable it */
 	if (fmt->attributes & EP_CS_ATTR_PITCH_CONTROL) {
 		data[0] = 1;
-		if ((err = usb_control_msg(dev, usb_sndctrlpipe(dev, 0), SET_CUR, USB_TYPE_CLASS|USB_RECIP_ENDPOINT|USB_DIR_OUT, 
+		if ((err = usb_control_msg(dev, usb_sndctrlpipe(dev, 0), SET_CUR,
+					   USB_TYPE_CLASS|USB_RECIP_ENDPOINT|USB_DIR_OUT, 
 					   PITCH_CONTROL << 8, ep, data, 1, HZ)) < 0) {
 			snd_printk(KERN_ERR "%d:%d:%d: cannot set enable PITCH\n",
 				   dev->devnum, subs->interface, ep);
@@ -938,16 +1002,18 @@
 		data[0] = runtime->rate;
 		data[1] = runtime->rate >> 8;
 		data[2] = runtime->rate >> 16;
-		if ((err = usb_control_msg(dev, usb_sndctrlpipe(dev, 0), SET_CUR, USB_TYPE_CLASS|USB_RECIP_ENDPOINT|USB_DIR_OUT, 
+		if ((err = usb_control_msg(dev, usb_sndctrlpipe(dev, 0), SET_CUR,
+					   USB_TYPE_CLASS|USB_RECIP_ENDPOINT|USB_DIR_OUT, 
 					   SAMPLING_FREQ_CONTROL << 8, ep, data, 3, HZ)) < 0) {
-			snd_printk(KERN_ERR "%d:%d:%d: cannot set freq %d\n",
-				   dev->devnum, subs->interface, ep, runtime->rate);
+			snd_printk(KERN_ERR "%d:%d:%d: cannot set freq %d to ep 0x%x\n",
+				   dev->devnum, subs->interface, fmt->altsetting, runtime->rate, ep);
 			return err;
 		}
-		if ((err = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), GET_CUR, USB_TYPE_CLASS|USB_RECIP_ENDPOINT|USB_DIR_IN,
+		if ((err = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), GET_CUR,
+					   USB_TYPE_CLASS|USB_RECIP_ENDPOINT|USB_DIR_IN,
 					   SAMPLING_FREQ_CONTROL << 8, ep, data, 3, HZ)) < 0) {
-			snd_printk(KERN_ERR "%d:%d:%d: cannot get freq\n",
-				   dev->devnum, subs->interface, ep);
+			snd_printk(KERN_ERR "%d:%d:%d: cannot get freq at ep 0x%x\n",
+				   dev->devnum, subs->interface, fmt->altsetting, ep);
 			return err;
 		}
 		runtime->rate = data[0] | (data[1] << 8) | (data[2] << 16);
@@ -1091,9 +1157,7 @@
 {
 	snd_usb_stream_t *as = snd_pcm_substream_chip(substream);
 	snd_usb_substream_t *subs = &as->substream[direction];
-	struct usb_interface *iface;	
-	iface = &subs->dev->actconfig->interface[subs->interface];
-	usb_set_interface(subs->dev, iface->altsetting->bInterfaceNumber, 0);
+	usb_set_interface(subs->dev, subs->interface, 0);
 	release_substream_urbs(subs);
 	subs->pcm_substream = NULL;
 	return 0;
@@ -1223,7 +1287,8 @@
 
 static struct usb_device_id usb_audio_ids [] = {
     { match_flags: (USB_DEVICE_ID_MATCH_INT_CLASS | USB_DEVICE_ID_MATCH_INT_SUBCLASS),
-      bInterfaceClass: USB_CLASS_AUDIO, bInterfaceSubClass: 1},
+      bInterfaceClass: USB_CLASS_AUDIO,
+      bInterfaceSubClass: USB_SUBCLASS_AUDIO_CONTROL },
     { }						/* Terminating entry */
 };
 
@@ -1284,7 +1349,7 @@
 		alts = &iface->altsetting[i];
 		/* skip invalid one */
 		if (alts->bInterfaceClass != USB_CLASS_AUDIO ||
-		    alts->bInterfaceSubClass != 2 ||
+		    alts->bInterfaceSubClass != USB_SUBCLASS_AUDIO_STREAMING ||
 		    alts->bNumEndpoints < 1)
 			continue;
 		/* must be isochronous */
@@ -1460,6 +1525,7 @@
 		fp->altsetting = altno;
 		fp->altset_idx = i;
 		fp->endpoint = alts->endpoint[0].bEndpointAddress;
+		fp->ep_attr = alts->endpoint[0].bmAttributes;
 		fp->channels = channels;
 		fp->attributes = csep[3];
 
@@ -1538,15 +1604,19 @@
 static void proc_dump_substream_formats(snd_usb_substream_t *subs, snd_info_buffer_t *buffer)
 {
 	struct list_head *p;
+	static char *sync_types[4] = {
+		"NONE", "ASYNC", "ADAPTIVE", "SYNC"
+	};
 
 	list_for_each(p, &subs->fmt_list) {
 		struct audioformat *fp;
 		fp = list_entry(p, struct audioformat, list);
 		snd_iprintf(buffer, "  Format: %s\n", snd_pcm_format_name(fp->format));
 		snd_iprintf(buffer, "  Channels: %d\n", fp->channels);
-		snd_iprintf(buffer, "  Endpoint: %d %s\n",
+		snd_iprintf(buffer, "  Endpoint: %d %s (%s)\n",
 			    fp->endpoint & USB_ENDPOINT_NUMBER_MASK,
-			    fp->endpoint & USB_DIR_IN ? "IN" : "OUT");
+			    fp->endpoint & USB_DIR_IN ? "IN" : "OUT",
+			    sync_types[(fp->ep_attr & EP_ATTR_MASK) >> 2]);
 		if (fp->rates & SNDRV_PCM_RATE_CONTINUOUS) {
 			snd_iprintf(buffer, "  Rates: %d - %d (continous)\n",
 				    fp->rate_min, fp->rate_max);
@@ -1724,7 +1794,7 @@
 		}
 		iface = &config->interface[j];
 		if (iface->altsetting[0].bInterfaceClass != USB_CLASS_AUDIO ||
-		    iface->altsetting[0].bInterfaceSubClass != 2) {
+		    iface->altsetting[0].bInterfaceSubClass != USB_SUBCLASS_AUDIO_STREAMING) {
 			snd_printdd(KERN_ERR "%d:%u:%d: skipping non-supported interface %d\n", dev->devnum, ctrlif, j, iface->altsetting[0].bInterfaceClass);
 			/* skip non-supported classes */
 			continue;
@@ -1787,7 +1857,6 @@
 
 static int snd_usb_audio_free(snd_usb_audio_t *chip)
 {
-	//snd_usb_proc_done(chip);
 	down(&register_mutex);
 	usb_chip[chip->index] = NULL;
 	up(&register_mutex);
Index: alsa-driver/usb/usbaudio.h
===================================================================
RCS file: /suse/tiwai/cvs/alsa/alsa-driver/usb/usbaudio.h,v
retrieving revision 1.6
diff -u -r1.6 usbaudio.h
--- alsa-driver/usb/usbaudio.h	12 Jun 2002 12:56:14 -0000	1.6
+++ alsa-driver/usb/usbaudio.h	13 Jun 2002 09:31:24 -0000
@@ -27,6 +27,9 @@
 /*
  */
 
+#define USB_SUBCLASS_AUDIO_CONTROL	0x01
+#define USB_SUBCLASS_AUDIO_STREAMING	0x02
+
 #define USB_DT_CS_DEVICE                0x21
 #define USB_DT_CS_CONFIG                0x22
 #define USB_DT_CS_STRING                0x23

  reply	other threads:[~2002-06-13 10:39 UTC|newest]

Thread overview: 22+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2002-06-04 16:57 status of usb audio driver Takashi Iwai
2002-06-12  5:16 ` Patrick Shirkey
2002-06-12 13:24   ` Takashi Iwai
2002-06-12 14:10     ` Patrick Shirkey
2002-06-12 14:13       ` Takashi Iwai
2002-06-12 14:19         ` Niklas Werner
2002-06-12 14:36           ` Takashi Iwai
2002-06-12 16:00             ` Niklas Werner
2002-06-12 14:55         ` Patrick Shirkey
2002-06-12 16:12           ` Patrick Shirkey
2002-06-12 16:48             ` Patrick Shirkey
2002-06-12 16:59               ` Takashi Iwai
2002-06-12 17:31                 ` Patrick Shirkey
2002-06-13 10:39                   ` Takashi Iwai [this message]
2002-06-13 12:54                     ` Patrick Shirkey
2002-06-13 13:05                       ` Takashi Iwai
2002-06-13 13:21                         ` Niklas Werner
2002-06-13 14:05                           ` Takashi Iwai
2002-06-14  8:58                             ` Niklas Werner
2002-06-13 13:35                         ` Patrick Shirkey
2002-06-13 13:43                           ` Takashi Iwai
2002-06-13 14:58                             ` Patrick Shirkey

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=s5hr8jbzcml.wl@alsa2.suse.de \
    --to=tiwai@suse.de \
    --cc=alsa-devel@lists.sourceforge.net \
    --cc=pshirkey@boosthardware.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.