From owner-freebsd-multimedia@FreeBSD.ORG Mon Apr 18 06:06:47 2005 Return-Path: Delivered-To: freebsd-multimedia@freebsd.org Received: from mx1.FreeBSD.org (mx1.freebsd.org [216.136.204.125]) by hub.freebsd.org (Postfix) with ESMTP id 8020316A4CE for ; Mon, 18 Apr 2005 06:06:47 +0000 (GMT) Received: from ylpvm43.prodigy.net (ylpvm43-ext.prodigy.net [207.115.57.74]) by mx1.FreeBSD.org (Postfix) with ESMTP id A698343D3F for ; Mon, 18 Apr 2005 06:06:46 +0000 (GMT) (envelope-from julian@elischer.org) Received: from pimout3-ext.prodigy.net (pimout3-ext.prodigy.net [207.115.63.102])j3I66ll8003297 for ; Mon, 18 Apr 2005 02:06:48 -0400 X-ORBL: [68.124.205.128] Received: from [192.168.2.2] (adsl-68-124-205-128.dsl.snfc21.pacbell.net [68.124.205.128])j3I66hxG336894 for ; Mon, 18 Apr 2005 02:06:44 -0400 Message-ID: <42634E72.6090505@elischer.org> Date: Sun, 17 Apr 2005 23:06:42 -0700 From: Julian Elischer User-Agent: Mozilla/5.0 (X11; U; FreeBSD i386; en-US; rv:1.7.5) Gecko/20050214 X-Accept-Language: en, hu MIME-Version: 1.0 To: multimedia@freebsd.org Content-Type: multipart/mixed; boundary="------------020405010100010807080902" Subject: [Fwd: please test uaudio capabilities patch] X-BeenThere: freebsd-multimedia@freebsd.org X-Mailman-Version: 2.1.1 Precedence: list List-Id: Multimedia discussions List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Mon, 18 Apr 2005 06:06:47 -0000 This is a multi-part message in MIME format. --------------020405010100010807080902 Content-Type: text/plain; charset=us-ascii; format=flowed Content-Transfer-Encoding: 7bit mat says he can't send this to the list and asked for me to forward it. FWIW the patch breaks my USB microphone. -------- Original Message -------- Subject: please test uaudio capabilities patch Date: Sun, 17 Apr 2005 13:20:14 -0400 From: Mathew Kanner Organization: I speak for myself, operating in Montreal, CANADA To: freebsd-multimedia@freebsd.org CC: Julian Elischer Hi All, The following patch changes the driver to probe the capabilities. With this patch I can run mplayer with a non-native speed or format and the internal soft-mixer will get the right chain. Without the patch, I get stuck and I have to disconnect. I'm going to commit this soon. This is is against HEAD post my commit to de-dma the driver. --Mat --------------020405010100010807080902 Content-Type: text/plain; name="uaudio_caps.6.diff" Content-Transfer-Encoding: 7bit Content-Disposition: inline; filename="uaudio_caps.6.diff" Index: uaudio.c =================================================================== RCS file: /home/ncvs/src/sys/dev/sound/usb/uaudio.c,v retrieving revision 1.13 diff -u -r1.13 uaudio.c --- uaudio.c 6 Jan 2005 01:43:22 -0000 1.13 +++ uaudio.c 17 Apr 2005 17:11:05 -0000 @@ -3764,83 +3764,127 @@ return (0); } -void -uaudio_query_formats(device_t dev, u_int32_t *pfmt, u_int32_t *rfmt) -{ - int i, pn=0, rn=0; - int prec, dir; +struct uaudio_convesion { + uint8_t uaudio_fmt; + uint8_t uaudio_prec; + uint32_t freebsd_fmt; +}; + +const struct uaudio_convesion const accepted_conversion[] = { + {AUDIO_ENCODING_ULINEAR_LE, 8, AFMT_U8}, + {AUDIO_ENCODING_ULINEAR_LE, 16, AFMT_U16_LE}, + {AUDIO_ENCODING_SLINEAR_LE, 8, AFMT_S8}, + {AUDIO_ENCODING_SLINEAR_LE, 16, AFMT_S16_LE}, + {AUDIO_ENCODING_SLINEAR_BE, 16, AFMT_S16_BE}, + {AUDIO_ENCODING_ALAW, 8, AFMT_A_LAW}, + {AUDIO_ENCODING_ULAW, 8, AFMT_MU_LAW}, + {0,0,0} +}; + +unsigned +uaudio_query_formats(device_t dev, int reqdir, unsigned maxfmt, struct pcmchan_caps *cap) +{ + struct uaudio_softc *sc = device_get_softc(dev); + const struct usb_audio_streaming_type1_descriptor *asf1d; + const struct uaudio_convesion *iterator; + unsigned fmtcount, foundcount; u_int32_t fmt; - struct uaudio_softc *sc; + uint8_t format, numchan, subframesize, prec, dir, iscontinuous; + int freq, freq_min, freq_max; + char *numchannel_descr; + char freq_descr[64]; + int i,r; - const struct usb_audio_streaming_type1_descriptor *a1d; + if ( sc == NULL ) + return 0; - sc = device_get_softc(dev); + cap->minspeed = cap->maxspeed = 0; + foundcount = fmtcount = 0; for (i = 0; i < sc->sc_nalts; i++) { - fmt = 0; - a1d = sc->sc_alts[i].asf1desc; - prec = a1d->bBitResolution; /* precision */ - - switch (sc->sc_alts[i].encoding) { - case AUDIO_ENCODING_ULINEAR_LE: - if (prec == 8) { - fmt = AFMT_U8; - } else if (prec == 16) { - fmt = AFMT_U16_LE; - } - break; - case AUDIO_ENCODING_SLINEAR_LE: - if (prec == 8) { - fmt = AFMT_S8; - } else if (prec == 16) { - fmt = AFMT_S16_LE; - } - break; - case AUDIO_ENCODING_ULINEAR_BE: - if (prec == 16) { - fmt = AFMT_U16_BE; - } - break; - case AUDIO_ENCODING_SLINEAR_BE: - if (prec == 16) { - fmt = AFMT_S16_BE; - } - break; - case AUDIO_ENCODING_ALAW: - if (prec == 8) { - fmt = AFMT_A_LAW; - } - break; - case AUDIO_ENCODING_ULAW: - if (prec == 8) { - fmt = AFMT_MU_LAW; - } - break; - } + dir = UE_GET_DIR(sc->sc_alts[i].edesc->bEndpointAddress); - if (fmt != 0) { - if (a1d->bNrChannels == 2) { /* stereo/mono */ - fmt |= AFMT_STEREO; - } else if (a1d->bNrChannels != 1) { - fmt = 0; - } + if ( (dir == UE_DIR_OUT) != (reqdir == PCMDIR_PLAY) ) + continue; + + asf1d = sc->sc_alts[i].asf1desc; + format = sc->sc_alts[i].encoding; + + numchan = asf1d->bNrChannels; + subframesize = asf1d->bSubFrameSize; + prec = asf1d->bBitResolution; /* precision */ + iscontinuous = asf1d->bSamFreqType == UA_SAMP_CONTNUOUS; + + if (iscontinuous) + snprintf(freq_descr, 64, "continous min %d max %d", UA_SAMP_LO(asf1d), UA_SAMP_HI(asf1d)); + else + snprintf(freq_descr, 64, "fixed frequency (%d listed formats)", asf1d->bSamFreqType); + + if ( numchan == 1) + numchannel_descr = " (mono)"; + else if ( numchan == 2 ) + numchannel_descr = " (stereo)"; + else + numchannel_descr = ""; + + if (bootverbose) { + device_printf( dev, "uaudio_query_formats: found a native %s channel%s %s %dbit %dbytes/subframe X %d channels = %d bytes per sample\n", + (dir==UE_DIR_OUT)?"playback":"record", + numchannel_descr, freq_descr, + prec, subframesize, numchan, subframesize*numchan); } + /* + * Now start rejecting the ones that don't map to FreeBSD + */ + + if (numchan != 1 && numchan != 2) + continue; + + for ( iterator = accepted_conversion ; iterator->uaudio_fmt != 0 ; iterator++ ) + if ( iterator->uaudio_fmt == format && iterator->uaudio_prec == prec ) + break; - if (fmt != 0) { - dir= UE_GET_DIR(sc->sc_alts[i].edesc->bEndpointAddress); - if (dir == UE_DIR_OUT) { - pfmt[pn++] = fmt; - } else if (dir == UE_DIR_IN) { - rfmt[rn++] = fmt; + if ( iterator->uaudio_fmt == 0 ) + continue; + + fmt = iterator->freebsd_fmt; + + if (asf1d->bNrChannels == 2) + fmt |= AFMT_STEREO; + + if ( numchan != 1 && numchan == 2 ) + + foundcount++; + + if (fmtcount >= maxfmt ) + continue; + + cap->fmtlist[fmtcount++] = fmt; + + if (iscontinuous) { + freq_min = UA_SAMP_LO(asf1d); + freq_max = UA_SAMP_HI(asf1d); + + if ( cap->minspeed == 0 || freq_min < cap->minspeed ) + cap->minspeed = freq_min; + if ( cap->maxspeed == 0 ) + cap->maxspeed = cap->minspeed; + if ( freq_max > cap->maxspeed ) + cap->maxspeed = freq_max; + } else { + for (r = 0; r < asf1d->bSamFreqType; r++) { + freq = UA_GETSAMP(asf1d, r); + if (cap->minspeed == 0 || freq < cap->minspeed) + cap->minspeed = freq; + if (cap->maxspeed == 0) + cap->maxspeed = cap->minspeed; + if (freq > cap->maxspeed) + cap->maxspeed = freq; } } - - if ((pn > 8*2) || (rn > 8*2)) - break; } - pfmt[pn] = 0; - rfmt[rn] = 0; - return; + cap->fmtlist[fmtcount] = 0; + return foundcount; } void @@ -3889,25 +3933,53 @@ return; } -void -uaudio_chan_set_param_speed(device_t dev, u_int32_t speed, int dir) +int +uaudio_chan_set_param_speed(device_t dev, u_int32_t speed, int reqdir) { + const struct uaudio_convesion *iterator; struct uaudio_softc *sc; struct chan *ch; + int i, r; sc = device_get_softc(dev); #ifndef NO_RECORDING - if (dir == PCMDIR_PLAY) + if (reqdir == PCMDIR_PLAY) ch = &sc->sc_playchan; else ch = &sc->sc_recchan; #else ch = &sc->sc_playchan; #endif + /* + * We are successful if we find an endpoint that matches our selected format and it + * supports the requested speed. + */ + for (i = 0; i < sc->sc_nalts; i++) { + int dir = UE_GET_DIR(sc->sc_alts[i].edesc->bEndpointAddress); + int format = sc->sc_alts[i].encoding; + const struct usb_audio_streaming_type1_descriptor *asf1d = sc->sc_alts[i].asf1desc; + int iscontinuous = asf1d->bSamFreqType == UA_SAMP_CONTNUOUS; + + if ( (dir == UE_DIR_OUT) != (reqdir == PCMDIR_PLAY) ) + continue; - ch->sample_rate = speed; + for ( iterator = accepted_conversion ; iterator->uaudio_fmt != 0 ; iterator++ ) + if ( iterator->uaudio_fmt == format && iterator->freebsd_fmt == (ch->format&0xfffffff) ) { + if (iscontinuous) { + if ( speed >= UA_SAMP_LO(asf1d) && speed <= UA_SAMP_HI(asf1d)) { + ch->sample_rate = speed; + return 1; + } + } else + for (r = 0; r < asf1d->bSamFreqType; r++) + if ( speed == UA_GETSAMP(asf1d, r) ) { + ch->sample_rate = speed; + return 1; + } + } + } - return; + return 0; } int Index: uaudio.h =================================================================== RCS file: /home/ncvs/src/sys/dev/sound/usb/uaudio.h,v retrieving revision 1.5 diff -u -r1.5 uaudio.h --- uaudio.h 6 Jan 2005 01:43:22 -0000 1.5 +++ uaudio.h 17 Apr 2005 16:42:53 -0000 @@ -41,7 +41,7 @@ #endif void uaudio_chan_set_param(device_t, u_char *, u_char *); void uaudio_chan_set_param_blocksize(device_t dev, u_int32_t blocksize, int dir); -void uaudio_chan_set_param_speed(device_t dev, u_int32_t speed, int dir); +int uaudio_chan_set_param_speed(device_t dev, u_int32_t speed, int reqdir); void uaudio_chan_set_param_format(device_t dev, u_int32_t format,int dir); int uaudio_chan_getptr(device_t dev, int); void uaudio_mixer_set(device_t dev, unsigned type, unsigned left, @@ -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); +unsigned uaudio_query_formats(device_t dev, int dir, unsigned maxfmt, struct pcmchan_caps *fmt); Index: uaudio_pcm.c =================================================================== RCS file: /home/ncvs/src/sys/dev/sound/usb/uaudio_pcm.c,v retrieving revision 1.13 diff -u -r1.13 uaudio_pcm.c --- uaudio_pcm.c 17 Apr 2005 15:26:51 -0000 1.13 +++ uaudio_pcm.c 17 Apr 2005 17:06:38 -0000 @@ -49,16 +49,12 @@ device_t sc_dev; u_int32_t bufsz; struct ua_chinfo pch, rch; + 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_DEFAULT_BUFSZ 16*1024 /************************************************************/ @@ -76,20 +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 (dir == PCMDIR_PLAY) { - if (ua_playfmt[0] == 0) { - printf("play channel supported format list invalid\n"); - return NULL; - } - } else { - if (ua_recfmt[0] == 0) { - printf("record channel supported format list invalid\n"); - return NULL; - } - - } ch->buf = malloc(sc->bufsz, M_DEVBUF, M_NOWAIT); if (ch->buf == NULL) @@ -133,6 +115,9 @@ struct ua_chinfo *ch = data; + /* + * At this point, no need to queury as we shouldn't select an unsorted format + */ ua = ch->parent; pa_dev = device_get_parent(ua->sc_dev); uaudio_chan_set_param_format(pa_dev, format, ch->dir); @@ -144,15 +129,12 @@ static int ua_chan_setspeed(kobj_t obj, void *data, u_int32_t speed) { - device_t pa_dev; - struct ua_info *ua; - struct ua_chinfo *ch = data; - ch->spd = speed; + device_t pa_dev = device_get_parent(ch->parent->sc_dev); + int res; - ua = ch->parent; - pa_dev = device_get_parent(ua->sc_dev); - uaudio_chan_set_param_speed(pa_dev, speed, ch->dir); + if ( (res = uaudio_chan_set_param_speed(pa_dev, speed, ch->dir)) ) + ch->spd = speed; return ch->spd; } @@ -226,7 +208,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[] = { @@ -318,40 +300,62 @@ { struct ua_info *ua; char status[SND_STATUSLEN]; + device_t pa_dev; + u_int32_t nplay, nrec; + int i; - ua = (struct ua_info *)malloc(sizeof *ua, M_DEVBUF, M_NOWAIT); - if (!ua) + ua = (struct ua_info *)malloc(sizeof *ua, M_DEVBUF, M_ZERO | M_NOWAIT); + if ( ua == NULL ) return ENXIO; - bzero(ua, sizeof *ua); ua->sc_dev = dev; + pa_dev = device_get_parent(dev); + ua->bufsz = pcm_getbuffersize(dev, 4096, UAUDIO_DEFAULT_BUFSZ, 65536); if (bootverbose) device_printf(dev, "using a default buffer size of %jd\n", (intmax_t)ua->bufsz); ua->bufsz = pcm_getbuffersize(dev, 4096, UAUDIO_DEFAULT_BUFSZ, 65536); 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)); + + ua->ua_playcaps.fmtlist = ua->ua_playfmt; + ua->ua_reccaps.fmtlist = ua->ua_recfmt; + nplay = uaudio_query_formats(pa_dev, PCMDIR_PLAY, 8, &ua->ua_playcaps); + nrec = uaudio_query_formats(pa_dev, PCMDIR_REC, 8, &ua->ua_reccaps); + + if ( nplay > 1 ) + nplay = 1; + if ( nrec > 1 ) + nrec = 1; #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); + goto bad; + } + + for (i = 0; i < nplay; i++) { + pcm_addchan(dev, PCMDIR_PLAY, &ua_chan_class, ua); } - 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 < nrec; i++) { + pcm_addchan(dev, PCMDIR_REC, &ua_chan_class, ua); + } #endif pcm_setstatus(dev, status); return 0; + +bad: free(ua, M_DEVBUF); + return ENXIO; } static int --------------020405010100010807080902--