usb/78028: The system must tell users information of a USB sound device.

Kazuhito HONDA kazuhito at ph.noda.tus.ac.jp
Tue Mar 1 18:40:04 GMT 2005


The following reply was made to PR usb/78028; it has been noted by GNATS.

From: Kazuhito HONDA <kazuhito at ph.noda.tus.ac.jp>
To: Alexander at Leidinger.net
Cc: FreeBSD-gnats-submit at freebsd.org, kazuhito at ph.noda.tus.ac.jp
Subject: Re: usb/78028: The system must tell users information of a USB
 sound device.
Date: Wed, 02 Mar 2005 03:39:13 +0900 (JST)

 From: Alexander Leidinger <Alexander at Leidinger.net>
 Subject: Re: usb/78028: The system must tell users information of a USB sound device.
 Date: Fri, 25 Feb 2005 11:54:16 +0100
 
 > Don't you think this information is better suited in the otput of
 > /dev/sndstat?
 
 Right.  But I don't know the management of /dev/sndstat.
 are three patches bellow correct?
 
 Sincerely tours,
 Kazuhito HONDA
 
 --- uaudio.c.orig	Thu Jan  6 10:43:22 2005
 +++ uaudio.c	Wed Mar  2 03:12:46 2005
 @@ -72,6 +72,7 @@
  #include <sys/poll.h>
  #if defined(__FreeBSD__)
  #include <sys/sysctl.h>
 +#include <sys/sbuf.h>
  #endif
  
  #if defined(__NetBSD__) || defined(__OpenBSD__)
 @@ -83,6 +84,7 @@
  #elif defined(__FreeBSD__)
  #include <dev/sound/pcm/sound.h>	/* XXXXX */
  #include <dev/sound/chip.h>
 +#include "feeder_if.h"
  #endif
  
  #include <dev/usb/usb.h>
 @@ -234,6 +236,10 @@
  	int		sc_nctls;	/* # of mixer controls */
  	device_ptr_t	sc_audiodev;
  	char		sc_dying;
 +#if defined(__FreeBSD__)
 +	struct sbuf	uaudio_sndstat;
 +	int		uaudio_sndstat_flag;
 +#endif
  };
  
  struct terminal_list {
 @@ -444,6 +450,7 @@
  #elif defined(__FreeBSD__)
  Static int	audio_attach_mi(device_t);
  Static int	uaudio_init_params(struct uaudio_softc * sc, struct chan *ch, int mode);
 +static int 	uaudio_sndstat_prepare_pcm(struct sbuf *s, device_t dev, int verbose);
  
  /* for NetBSD compatibirity */
  #define	AUMODE_PLAY	0x01
 @@ -642,6 +649,9 @@
  {
  	USB_DETACH_START(uaudio, sc);
  
 +	sbuf_delete(&(sc->uaudio_sndstat));
 +	sc->uaudio_sndstat_flag = 0;
 +
  	sc->sc_dying = 1;
  
  #if 0 /* XXX */
 @@ -2068,6 +2078,27 @@
  		printf("Hz\n");
  	}
  #endif
 +#if defined(__FreeBSD__)
 +	if (sc->uaudio_sndstat_flag != 0) {
 +		sbuf_printf(&(sc->uaudio_sndstat), "\n\t");
 +		sbuf_printf(&(sc->uaudio_sndstat), 
 +		       "%s: %dch, %d/%dbit, %s,", 
 +		       dir == UE_DIR_IN ? "recording" : "playback",
 +		       chan, prec, asf1d->bSubFrameSize * 8, format_str);
 +		if (asf1d->bSamFreqType == UA_SAMP_CONTNUOUS) {
 +			sbuf_printf(&(sc->uaudio_sndstat), " %d-%dHz", 
 +			       UA_SAMP_LO(asf1d), UA_SAMP_HI(asf1d));
 +		} else {
 +			int r;
 +			sbuf_printf(&(sc->uaudio_sndstat), 
 +			       " %d", UA_GETSAMP(asf1d, 0));
 +			for (r = 1; r < asf1d->bSamFreqType; r++)
 +				sbuf_printf(&(sc->uaudio_sndstat), 
 +				       ",%d", UA_GETSAMP(asf1d, r));
 +			sbuf_printf(&(sc->uaudio_sndstat), "Hz");
 +		}
 +	}
 +#endif
  	ai.alt = id->bAlternateSetting;
  	ai.encoding = enc;
  	ai.attributes = sed->bmAttributes;
 @@ -2106,6 +2137,11 @@
  	if (id == NULL)
  		return (USBD_INVAL);
  
 +#if defined(__FreeBSD__)
 +	sc->uaudio_sndstat_flag = 0;
 +	if (sbuf_new(&(sc->uaudio_sndstat), NULL, 4096, SBUF_AUTOEXTEND) != NULL)
 +		sc->uaudio_sndstat_flag = 1;
 +#endif
  	/* Loop through all the alternate settings. */
  	while (offs <= size) {
  		DPRINTFN(2, ("uaudio_identify: interface=%d offset=%d\n",
 @@ -2132,6 +2168,9 @@
  		if (id == NULL)
  			break;
  	}
 +#if defined(__FreeBSD__)
 +	sbuf_finish(&(sc->uaudio_sndstat));
 +#endif
  	if (offs > size)
  		return (USBD_INVAL);
  	DPRINTF(("uaudio_identify_as: %d alts available\n", sc->sc_nalts));
 @@ -4171,6 +4210,118 @@
  	return (1 << mc->slctrtype[mc->minval - 1]);
  }
  
 +static int
 +uaudio_sndstat_prepare_pcm(struct sbuf *s, device_t dev, int verbose)
 +{
 +    	struct snddev_info *d;
 +    	struct snddev_channel *sce;
 +	struct pcm_channel *c;
 +	struct pcm_feeder *f;
 +    	int pc, rc, vc;
 +	device_t pa_dev = device_get_parent(dev);
 +	struct uaudio_softc *sc = device_get_softc(pa_dev);
 +
 +	if (verbose < 1)
 +		return 0;
 +
 +	d = device_get_softc(dev);
 +	if (!d)
 +		return ENXIO;
 +
 +	snd_mtxlock(d->lock);
 +	if (SLIST_EMPTY(&d->channels)) {
 +		sbuf_printf(s, " (mixer only)");
 +		snd_mtxunlock(d->lock);
 +		return 0;
 +	}
 +	pc = rc = vc = 0;
 +	SLIST_FOREACH(sce, &d->channels, link) {
 +		c = sce->channel;
 +		if (c->direction == PCMDIR_PLAY) {
 +			if (c->flags & CHN_F_VIRTUAL)
 +				vc++;
 +			else
 +				pc++;
 +		} else
 +			rc++;
 +	}
 +	sbuf_printf(s, " (%dp/%dr/%dv channels%s%s)", 
 +			d->playcount, d->reccount, d->vchancount,
 +			(d->flags & SD_F_SIMPLEX)? "" : " duplex",
 +#ifdef USING_DEVFS
 +			(device_get_unit(dev) == snd_unit)? " default" : ""
 +#else
 +			""
 +#endif
 +			);
 +
 +	if (sc->uaudio_sndstat_flag != 0) {
 +		sbuf_cat(s, sbuf_data(&(sc->uaudio_sndstat)));
 +	}
 +
 +	if (verbose <= 1) {
 +		snd_mtxunlock(d->lock);
 +		return 0;
 +	}
 +
 +	SLIST_FOREACH(sce, &d->channels, link) {
 +		c = sce->channel;
 +		sbuf_printf(s, "\n\t");
 +
 +		/* it would be better to indent child channels */
 +		sbuf_printf(s, "%s[%s]: ", c->parentchannel? c->parentchannel->name : "", c->name);
 +		sbuf_printf(s, "spd %d", c->speed);
 +		if (c->speed != sndbuf_getspd(c->bufhard))
 +			sbuf_printf(s, "/%d", sndbuf_getspd(c->bufhard));
 +		sbuf_printf(s, ", fmt 0x%08x", c->format);
 +		if (c->format != sndbuf_getfmt(c->bufhard))
 +			sbuf_printf(s, "/0x%08x", sndbuf_getfmt(c->bufhard));
 +		sbuf_printf(s, ", flags 0x%08x, 0x%08x", c->flags, c->feederflags);
 +		if (c->pid != -1)
 +			sbuf_printf(s, ", pid %d", c->pid);
 +		sbuf_printf(s, "\n\t");
 +
 +		if (c->bufhard != NULL && c->bufsoft != NULL) {
 +			sbuf_printf(s, "interrupts %d, ", c->interrupts);
 +			if (c->direction == PCMDIR_REC)
 +				sbuf_printf(s, "overruns %d, hfree %d, sfree %d",
 +					c->xruns, sndbuf_getfree(c->bufhard), sndbuf_getfree(c->bufsoft));
 +			else
 +				sbuf_printf(s, "underruns %d, ready %d",
 +					c->xruns, sndbuf_getready(c->bufsoft));
 +			sbuf_printf(s, "\n\t");
 +		}
 +
 +		sbuf_printf(s, "{%s}", (c->direction == PCMDIR_REC)? "hardware" : "userland");
 +		sbuf_printf(s, " -> ");
 +		f = c->feeder;
 +		while (f->source != NULL)
 +			f = f->source;
 +		while (f != NULL) {
 +			sbuf_printf(s, "%s", f->class->name);
 +			if (f->desc->type == FEEDER_FMT)
 +				sbuf_printf(s, "(0x%08x -> 0x%08x)", f->desc->in, f->desc->out);
 +			if (f->desc->type == FEEDER_RATE)
 +				sbuf_printf(s, "(%d -> %d)", FEEDER_GET(f, FEEDRATE_SRC), FEEDER_GET(f, FEEDRATE_DST));
 +			if (f->desc->type == FEEDER_ROOT || f->desc->type == FEEDER_MIXER)
 +				sbuf_printf(s, "(0x%08x)", f->desc->out);
 +			sbuf_printf(s, " -> ");
 +			f = f->parent;
 +		}
 +		sbuf_printf(s, "{%s}", (c->direction == PCMDIR_REC)? "userland" : "hardware");
 +	}
 +	snd_mtxunlock(d->lock);
 +
 +	return 0;
 +}
 +
 +void
 +uaudio_sndstat_register(device_t dev)
 +{
 +	struct snddev_info *d = device_get_softc(dev);
 +	sndstat_register(dev, d->status, uaudio_sndstat_prepare_pcm);
 +}
 +	
  Static int
  audio_attach_mi(device_t dev)
  {
 --- uaudio_pcm.c.orig	Thu Feb 24 00:38:11 2005
 +++ uaudio_pcm.c	Wed Mar  2 02:40:07 2005
 @@ -336,6 +336,9 @@
  		return(ENXIO);
  	}
  
 +	sndstat_unregister(dev);
 +	uaudio_sndstat_register(dev);
 +
  	pcm_addchan(dev, PCMDIR_PLAY, &ua_chan_class, ua);
  #ifndef NO_RECORDING
  	pcm_addchan(dev, PCMDIR_REC, &ua_chan_class, ua);
 --- uaudio.h.orig	Thu Feb 24 00:38:03 2005
 +++ uaudio.h	Wed Mar  2 02:50:20 2005
 @@ -50,3 +50,4 @@
  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);
 +void	uaudio_sndstat_register(device_t dev);


More information about the freebsd-usb mailing list