--- /n/downloads/devusb.c Tue Feb 14 20:42:27 2023 +++ /sys/src/9/bcm/devusb.c Tue Feb 14 11:31:28 2023 @@ -88,6 +88,7 @@ CMdebugep, /* debug n (set/clear debug for this ep) */ CMname, /* name str (show up as #u/name as well) */ CMtmout, /* timeout n (activate timeouts for ep) */ + CMsampledelay, /* maximum delay introduced by buffering (iso) */ CMpreset, /* reset the port */ /* Hub feature selectors */ @@ -128,6 +129,7 @@ {CMclrhalt, "clrhalt", 1}, {CMname, "name", 2}, {CMtmout, "timeout", 2}, + {CMsampledelay, "sampledelay", 2}, {CMpreset, "reset", 1}, }; @@ -1387,6 +1389,11 @@ ep->tmout = strtoul(cb->f[1], nil, 0); if(ep->tmout != 0 && ep->tmout < Xfertmout) ep->tmout = Xfertmout; + break; + case CMsampledelay: + if(ep->ttype != Tiso) + error("ctl ignored for this endpoint type"); + ep->sampledelay = strtoul(cb->f[1], nil, 0); break; case CMpreset: deprint("usb epctl %s\n", cb->f[0]); --- /n/downloads/usbxhci.c Tue Feb 14 20:41:33 2023 +++ /sys/src/9/bcm/usbxhci.c Tue Feb 14 11:24:53 2023 @@ -194,6 +194,7 @@ int stopped; + int *residue; Wait *pending; Lock; }; @@ -277,6 +278,10 @@ u32int incr; u32int tdsz; + /* isoread */ + u32int rp0; + u32int frame0; + int nleft; }; @@ -1100,10 +1105,17 @@ { if(io->ring == nil) return; - io->frame = 0; - io->period = ep->pollival<<3*(ep->dev->speed == Fullspeed); - io->incr = (ep->hz*io->period<<8)/8000; - io->tdsz = (io->incr+255>>8)*ep->samplesz; + io->rp0 = io->ring->wp; + io->frame0 = io->frame = 0; + io->period = ep->pollival << 3*(ep->dev->speed == Fullspeed || ep->dev->speed == Lowspeed); + if(io->ring->id & 1){ + io->ring->residue = smalloc((io->ring->mask+1)*sizeof(io->ring->residue[0])); + io->incr = 0; + io->tdsz = ep->maxpkt*ep->ntds; + } else { + io->incr = ((vlong)ep->hz*ep->pollival<<8)/1000; + io->tdsz = (io->incr+255>>8)*ep->samplesz; + } io->b = allocb((io->ring->mask+1)*io->tdsz); } @@ -1336,10 +1348,10 @@ } µ = io->period; ctlr = ep->hp->aux; - if(needrecover(ctlr)) - error(Erecover); for(i = io->frame;; i++){ for(;;){ + if(needrecover(ctlr)) + error(Erecover); m = (int)(io->ring->wp - io->ring->rp); if(m <= 0) i = (80 + µframe(ctlr))/µ; @@ -1367,11 +1379,13 @@ io->frame = i; while(io->ring->rp != io->ring->wp){ int d = (int)(i*µ - µframe(ctlr))/8; - //d -= ep->sampledelay*1000 / ep->hz; + d -= ep->sampledelay*1000 / ep->hz; if(d < 5) break; *io->ring->doorbell = io->ring->id; tsleep(&up->sleep, return0, nil, d); + if(needrecover(ctlr)) + error(Erecover); } qunlock(io); poperror(); --- /n/downloads/audio.h Tue Feb 14 23:52:55 2023 +++ /sys/src/cmd/usb/audio/audio.h Tue Feb 14 23:29:03 2023 @@ -39,6 +39,11 @@ #define SAMPLING_FREQ_CONTROL 0x01 +#define DSPEEDPLAY 44100 +#define DSPEEDREC 44100 +/* 40ms */ +#define DDELAY 1764 + typedef struct Audioalt Audioalt; struct Audioalt { --- /n/downloads/audio.c Tue Feb 14 23:52:36 2023 +++ /sys/src/cmd/usb/audio/audio.c Wed Feb 15 01:00:51 2023 @@ -25,7 +25,7 @@ int verbose; int setrec = 0; -int defaultspeed[2] = {44100, 44100}; +int defaultspeed[2]= { DSPEEDPLAY, DSPEEDREC}; Dev *buttondev; Dev *epdev[2]; @@ -372,6 +372,8 @@ value[0] = defaultspeed[Record]; if(endpt[Record] >= 0 && setcontrol(Record, "speed", value) < 0) fprint(2, "%s: can't set record speed\n", argv0); + value[0] = DDELAY; + setcontrol(Play, "delay", value); value[0] = 0; setcontrol(Play, "mute", value); --- /n/downloads/audioctl.c Tue Feb 14 20:43:26 2023 +++ /sys/src/cmd/usb/audio/audioctl.c Wed Feb 15 01:13:48 2023 @@ -18,7 +18,7 @@ Audiocontrol controls[2][Ncontrol] = { { - [Speed_control] = { "speed", 0, {0}, 0, 44100, Undef}, + [Speed_control] = { "speed", 0, {0}, 0, DSPEEDPLAY, Undef}, [Mute_control] = { "mute", 0, {0}, 0, 0, Undef}, [Volume_control] = { "volume", 0, {0}, 0, 0, Undef}, [Bass_control] = { "bass", 0, {0}, 0, 0, Undef}, @@ -26,14 +26,14 @@ [Treble_control] = { "treble", 0, {0}, 0, 0, Undef}, [Equalizer_control] = { "equalizer", 0, {0}, 0, 0, Undef}, [Agc_control] = { "agc", 0, {0}, 0, 0, Undef}, - [Delay_control] = { "delay", 0, {0}, 0, 0, Undef}, + [Delay_control] = { "delay", 1, {1}, 0, DDELAY, Undef}, [Bassboost_control] = { "bassboost", 0, {0}, 0, 0, Undef}, [Loudness_control] = { "loudness", 0, {0}, 0, 0, Undef}, [Channel_control] = { "channels", 0, {0}, 0, 2, Undef}, [Resolution_control] = { "resolution", 0, {0}, 0, 16, Undef}, // [Selector_control] = { "selector", 0, {0}, 0, 0, Undef}, }, { - [Speed_control] = { "speed", 0, {0}, 0, 44100, Undef}, + [Speed_control] = { "speed", 0, {0}, 0, DSPEEDREC, Undef}, [Mute_control] = { "mute", 0, {0}, 0, 0, Undef}, [Volume_control] = { "volume", 0, {0}, 0, 0, Undef}, [Bass_control] = { "bass", 0, {0}, 0, 0, Undef}, @@ -129,6 +129,15 @@ } int +setdelay(int rec, int delay) +{ + if(rec == Record && !setrec) + return Undef; + devctl(epdev[rec], "sampledelay %ld", delay); + return delay; +} + +int setspeed(int rec, int speed) { int ps, n, no, dist, i; @@ -226,10 +235,11 @@ } dprint(2, "Configuring %s endpoint for %d Hz\n", rec?"record":"playback", speed); - epdev[rec] = openep(ad, endpt[rec]); - if(epdev[rec] == nil) - sysfatal("openep rec %d: %r", rec); - + if(epdev[rec] == nil){ + epdev[rec] = openep(ad, endpt[rec]); + if(epdev[rec] == nil) + sysfatal("openep rec %d: %r", rec); + } devctl(epdev[rec], "pollival %d", da->interval); devctl(epdev[rec], "samplesz %ld", controls[rec][Channel_control].value[0] * controls[rec][Resolution_control].value[0]/8); @@ -391,8 +401,11 @@ c->value[0] = value[0]; controls[rec][Speed_control].value[0] = defaultspeed[rec]; return 0; - case Volume_control: case Delay_control: + setdelay(rec, value[0]); + c->value[0] = value[0]; + return 0; + case Volume_control: count = 2; /* fall through */ case Mute_control: @@ -480,8 +493,12 @@ if(req == Rgetcur) value[0] = controls[rec][ctl].value[0]; return 0; - case Volume_control: case Delay_control: + if(req != Rgetcur) + return Undef; + value[0] = controls[rec][ctl].value[0]; + return 0; + case Volume_control: count = 2; /* fall through */ case Bass_control: