uaudio patch, capabilities

Mathew Kanner mat at cnd.mcgill.ca
Fri Mar 11 17:03:26 PST 2005


On Mar 09, Kazuhito HONDA wrote:
> From: Mathew Kanner <mat at cnd.mcgill.ca>
> Subject: Re: uaudio patch, configurable buffer size
> Date: Tue, 8 Mar 2005 07:08:20 -0500
> 
> > 	I'm presently working on moving the ua_playcaps and ua_reccaps
> > into struct ua_info instead of global variables.  
> 
> O.K.  I'm looking forward to your result.

	Hello Kazuhito,
	Please find attached my work in progress to add probing the
min/max rate for the uaudio device.  It does what I described before
(de-globalizes the caps).  It still prints some extra debugging
information and needs some polish thought before commiting.
	I also sneak in some minor changes:
	- add the kld info to /dev/sndstat (like the other sound
	  modules)
        - reduce the default buffer size to 8kb
	- Start to get ready for no playback/ mixer only devices.

	--Mat
-------------- next part --------------
Index: sys/dev/sound/usb/uaudio.c
===================================================================
RCS file: /home/ncvs/src/sys/dev/sound/usb/uaudio.c,v
retrieving revision 1.13
diff -u -r1.13 uaudio.c
--- sys/dev/sound/usb/uaudio.c	6 Jan 2005 01:43:22 -0000	1.13
+++ sys/dev/sound/usb/uaudio.c	11 Mar 2005 20:01:52 -0000
@@ -3764,22 +3764,24 @@
 	return (0);
 }
 
-void
-uaudio_query_formats(device_t dev, u_int32_t *pfmt, u_int32_t *rfmt)
+int
+uaudio_query_formats(device_t dev, u_int32_t *min, u_int32_t *max, u_int32_t *pfmt, u_int32_t *rfmt)
 {
 	int i, pn=0, rn=0;
 	int prec, dir;
 	u_int32_t fmt;
 	struct uaudio_softc *sc;
 
-	const struct usb_audio_streaming_type1_descriptor *a1d;
+ 	const struct usb_audio_streaming_type1_descriptor *asf1d;
 
 	sc = device_get_softc(dev);
 
+	*min = *max = 0;
+
 	for (i = 0; i < sc->sc_nalts; i++) {
 		fmt = 0;
-		a1d = sc->sc_alts[i].asf1desc;
-		prec = a1d->bBitResolution;	/* precision */
+		asf1d = sc->sc_alts[i].asf1desc;
+		prec = asf1d->bBitResolution;	/* precision */
 
 		switch (sc->sc_alts[i].encoding) {
 		case AUDIO_ENCODING_ULINEAR_LE:
@@ -3819,28 +3821,58 @@
 		}
 
 		if (fmt != 0) {
-			if (a1d->bNrChannels == 2) {	/* stereo/mono */
+			if (asf1d->bNrChannels == 2) {	/* stereo/mono */
 				fmt |= AFMT_STEREO;
-			} else if (a1d->bNrChannels != 1) {
+			} else if (asf1d->bNrChannels != 1) {
 				fmt = 0;
 			}
 		}
 
 		if (fmt != 0) {
 			dir= UE_GET_DIR(sc->sc_alts[i].edesc->bEndpointAddress);
-			if (dir == UE_DIR_OUT) {
+			if (dir == UE_DIR_OUT && pn <= 8*2) {
 				pfmt[pn++] = fmt;
-			} else if (dir == UE_DIR_IN) {
+			} else if (dir == UE_DIR_IN && rn <= 8*2 ) {
 				rfmt[rn++] = fmt;
 			}
 		}
 
-		if ((pn > 8*2) || (rn > 8*2))
-			break;
+                /*
+                 *  Sadly, for now, we will only look for the min/max
+                 *  of playback channels as this is more important to
+                 *  report correctly.  I don't know of a way to report
+                 *  caps of playback and record seperately
+                 */
+                if ( fmt == 0 || dir != UE_DIR_OUT )
+                    continue;
+		if ( asf1d->bSamFreqType == UA_SAMP_CONTNUOUS) {
+                        int it = UA_SAMP_LO(asf1d);
+                        printf( " Testing continuous lo %d min %d max %d\n", it, *min, *max);
+			if ( *min == 0 || it <= *min )
+				*min = it;
+			if ( *max == 0 )
+				*max = *min;
+                        it  = UA_SAMP_HI(asf1d);
+                        printf( " Testing continuous hi %d min %d max %d\n", it, *min, *max);
+			if ( it >= *max )
+				*max = it;
+		} else {
+			int r, it;
+			for (r = 0; r < asf1d->bSamFreqType; r++) {
+				it = UA_GETSAMP(asf1d, r);
+                        printf( " Testing fixed %d min %d max %d\n", it, *min, *max);
+				if ( *min == 0 || it <= *min )
+					*min = it;
+				if ( *max == 0 )
+					*max = *min;
+				if ( it >= *max )
+					*max = it;
+                        }
+		}
 	}
 	pfmt[pn] = 0;
 	rfmt[rn] = 0;
-	return;
+	return 1;
 }
 
 void
Index: sys/dev/sound/usb/uaudio.h
===================================================================
RCS file: /home/ncvs/src/sys/dev/sound/usb/uaudio.h,v
retrieving revision 1.5
diff -u -r1.5 uaudio.h
--- sys/dev/sound/usb/uaudio.h	6 Jan 2005 01:43:22 -0000	1.5
+++ sys/dev/sound/usb/uaudio.h	11 Mar 2005 20:04:51 -0000
@@ -49,4 +49,4 @@
 u_int32_t uaudio_mixer_setrecsrc(device_t dev, u_int32_t src);
 u_int32_t uaudio_query_mix_info(device_t dev);
 u_int32_t uaudio_query_recsrc_info(device_t dev);
-void	uaudio_query_formats(device_t dev, u_int32_t *pfmt, u_int32_t *rfmt);
+int uaudio_query_formats(device_t dev, u_int32_t *min, u_int32_t *max, u_int32_t *pfmt, u_int32_t *rfmt);
Index: sys/dev/sound/usb/uaudio_pcm.c
===================================================================
RCS file: /home/ncvs/src/sys/dev/sound/usb/uaudio_pcm.c,v
retrieving revision 1.10
diff -u -r1.10 uaudio_pcm.c
--- sys/dev/sound/usb/uaudio_pcm.c	1 Mar 2005 08:58:06 -0000	1.10
+++ sys/dev/sound/usb/uaudio_pcm.c	11 Mar 2005 20:03:03 -0000
@@ -48,17 +48,13 @@
 	device_t sc_dev;
 	struct ua_chinfo pch, rch;
 	bus_dma_tag_t	parent_dmat;
+	u_int32_t ua_playfmt[8*2+1]; /* 8 format * (stereo or mono) + endptr */
+	u_int32_t ua_recfmt[8*2+1]; /* 8 format * (stereo or mono) + endptr */
+	struct pcmchan_caps ua_playcaps;
+	struct pcmchan_caps ua_reccaps;
 };
 
-static u_int32_t ua_playfmt[8*2+1]; /* 8 format * (stereo or mono) + endptr */
-
-static struct pcmchan_caps ua_playcaps = {8000, 48000, ua_playfmt, 0};
-
-static u_int32_t ua_recfmt[8*2+1]; /* 8 format * (stereo or mono) + endptr */
-
-static struct pcmchan_caps ua_reccaps = {8000, 48000, ua_recfmt, 0};
-
-#define UAUDIO_PCM_BUFF_SIZE	16*1024
+#define UAUDIO_PCM_BUFF_SIZE	8*1024
 
 /************************************************************/
 static void *
@@ -76,12 +72,6 @@
 	ch->dir = dir;
 
 	pa_dev = device_get_parent(sc->sc_dev);
-     	/* Create ua_playfmt[] & ua_recfmt[] */
-	uaudio_query_formats(pa_dev, (u_int32_t *)&ua_playfmt, (u_int32_t *)&ua_recfmt);
-	if (ua_playfmt[0] == 0) {
-		printf("%s channel supported format list invalid\n", dir == PCMDIR_PLAY? "play" : "record");
-		return NULL;
-	}
 
 	/* allocate PCM side DMA buffer */
 	if (sndbuf_alloc(ch->buffer, sc->parent_dmat, UAUDIO_PCM_BUFF_SIZE) != 0) {
@@ -207,7 +197,7 @@
 {
 	struct ua_chinfo *ch = data;
 
-	return (ch->dir == PCMDIR_PLAY) ? &ua_playcaps : & ua_reccaps;
+	return (ch->dir == PCMDIR_PLAY) ? &(ch->parent->ua_playcaps) : &(ch->parent->ua_reccaps);
 }
 
 static kobj_method_t ua_chan_methods[] = {
@@ -299,6 +289,9 @@
 	struct ua_info *ua;
 	char status[SND_STATUSLEN];
 	unsigned int bufsz;
+        u_int32_t nplay, nrec;
+        u_int32_t min, max;
+        int i;
 
 	ua = (struct ua_info *)malloc(sizeof *ua, M_DEVBUF, M_NOWAIT);
 	if (!ua)
@@ -323,22 +316,40 @@
 	}
 
 	if (mixer_init(dev, &ua_mixer_class, ua)) {
-		return(ENXIO);
+		goto bad;
 	}
 
-	snprintf(status, SND_STATUSLEN, "at addr ?");
+	snprintf(status, SND_STATUSLEN, "%s", PCM_KLDSTRING(snd_uaudio));
 
+	uaudio_query_formats(device_get_parent(dev), &min, &max, ua->ua_playfmt, ua->ua_recfmt);
+        ua->ua_playcaps.minspeed = min;
+        ua->ua_playcaps.maxspeed = max;
+        ua->ua_playcaps.fmtlist = ua->ua_playfmt;
+        ua->ua_reccaps.minspeed = min;
+        ua->ua_reccaps.maxspeed = max;
+        ua->ua_reccaps.fmtlist = ua->ua_recfmt;
+   
+        nplay = 1;
+        nrec = 1; 
+        /*
+         * XXX Should really check if we have playback and record channels
+         */ 
 #ifndef NO_RECORDING
-	if (pcm_register(dev, ua, 1, 1)) {
+	if (pcm_register(dev, ua, nplay, nrec)) {
 #else
-	if (pcm_register(dev, ua, 1, 0)) {
+	if (pcm_register(dev, ua, nplay, 0)) {
 #endif
 		return(ENXIO);
 	}
 
-	pcm_addchan(dev, PCMDIR_PLAY, &ua_chan_class, ua);
+        for (i = 0; i < nplay; i++) {
+		pcm_addchan(dev, PCMDIR_PLAY, &ua_chan_class, ua);
+        }
+
 #ifndef NO_RECORDING
-	pcm_addchan(dev, PCMDIR_REC, &ua_chan_class, ua);
+        for (i = 0; i < nplay; i++) {
+		pcm_addchan(dev, PCMDIR_REC, &ua_chan_class, ua);
+        }
 #endif
 	pcm_setstatus(dev, status);
 


More information about the freebsd-multimedia mailing list