Subject: uaudio: full duplex changes
To: None <current-users@NetBSD.org>
From: Jaromir Dolecek <jaromir.dolecek@artisys.cz>
List: current-users
Date: 01/21/2002 13:06:51
--ELM717424042-26155-0_
Content-Transfer-Encoding: 7bit
Content-Type: text/plain; charset=US-ASCII
Hi,
I've done necessary changes to make the driver support full duplex,
independant operation of uaudio. It works as fine for replay
as it did before and recording seems to also (kind of) work.
However, the recording contains only silence for me. I don't
have any good microphone awailable tho, so this might be more problem
with my microphone.
Can anyone who uses recording with uaudio try appended patch and
tell me whether the recording works as well as before? I'd also
be interested if simultaneous replay and recording works
as expected.
Jaromir
--ELM717424042-26155-0_
Content-Transfer-Encoding: 7bit
Content-Type: text/plain; charset=ISO-8859-2
Content-Disposition: attachment; filename=au.diff
Index: uaudio.c
===================================================================
RCS file: /cvsroot/syssrc/sys/dev/usb/uaudio.c,v
retrieving revision 1.44
diff -u -p -b -r1.44 uaudio.c
--- uaudio.c 2001/11/13 06:24:54 1.44
+++ uaudio.c 2002/01/21 12:03:13
@@ -117,11 +117,9 @@ struct as_info {
};
struct chan {
- int terminal; /* terminal id */
void (*intr)(void *); /* dma completion intr handler */
void *arg; /* arg for intr() */
usbd_pipe_handle pipe;
- int dir; /* direction */
u_int sample_size;
u_int sample_rate;
@@ -135,7 +133,7 @@ struct chan {
int blksize; /* chunk size to report up */
int transferred; /* transferred bytes not reported up */
- char nofrac; /* don't do sample rate adjustment */
+ int altidx; /* currently used altidx */
int curchanbuf;
struct chanbuf {
@@ -156,10 +154,9 @@ struct uaudio_softc {
int sc_ac_iface; /* Audio Control interface */
usbd_interface_handle sc_ac_ifaceh;
- struct chan sc_chan;
+ struct chan sc_playchan; /* play channel */
+ struct chan sc_recchan; /* record channel */
- int sc_curaltidx;
-
int sc_nullalt;
int sc_audio_rev;
@@ -174,6 +171,9 @@ struct uaudio_softc {
#define HAS_8U 0x04
#define HAS_ALAW 0x08
#define HAS_MULAW 0x10
+#define UA_NOFRAC 0x20 /* don't do sample rate adjustment */
+
+ int sc_mode; /* play/record capability */
struct mixerctl *sc_ctls;
int sc_nctls;
@@ -395,10 +395,10 @@ USB_ATTACH(uaudio)
printf("%s: audio rev %d.%02x\n", USBDEVNAME(sc->sc_dev),
sc->sc_audio_rev >> 8, sc->sc_audio_rev & 0xff);
- sc->sc_chan.sc = sc;
+ sc->sc_playchan.sc = sc->sc_recchan.sc = sc;
if (usbd_get_quirks(sc->sc_udev)->uq_flags & UQ_AU_NO_FRAC)
- sc->sc_chan.nofrac = 1;
+ sc->sc_altflags |= UA_NOFRAC;
#ifndef UAUDIO_DEBUG
if (bootverbose)
@@ -1026,7 +1026,7 @@ void
uaudio_add_alt(struct uaudio_softc *sc, struct as_info *ai)
{
size_t len = sizeof(*ai) * (sc->sc_nalts + 1);
- struct as_info *nai = sc->sc_nalts == 0 ?
+ struct as_info *nai = (sc->sc_nalts == 0) ?
malloc(len, M_USBDEV, M_NOWAIT) :
realloc(sc->sc_alts, len, M_USBDEV, M_NOWAIT);
@@ -1153,8 +1153,8 @@ uaudio_process_as(struct uaudio_softc *s
ai.edesc = ed;
ai.asf1desc = asf1d;
uaudio_add_alt(sc, &ai);
- sc->sc_chan.terminal = asid->bTerminalLink; /* XXX */
- sc->sc_chan.dir |= dir == UE_DIR_OUT ? AUMODE_PLAY : AUMODE_RECORD;
+ sc->sc_mode |= (dir == UE_DIR_OUT) ? AUMODE_PLAY : AUMODE_RECORD;
+
return (USBD_NORMAL_COMPLETION);
}
#undef offs
@@ -1176,9 +1176,6 @@ uaudio_identify_as(struct uaudio_softc *
if (id == NULL)
return (USBD_INVAL);
- sc->sc_chan.terminal = -1;
- sc->sc_chan.dir = 0;
-
/* Loop through all the alternate settings. */
while (offs <= size) {
DPRINTFN(2, ("uaudio_identify: interface %d\n",
@@ -1207,15 +1204,16 @@ uaudio_identify_as(struct uaudio_softc *
if (offs > size)
return (USBD_INVAL);
DPRINTF(("uaudio_identify_as: %d alts available\n", sc->sc_nalts));
- if (sc->sc_chan.terminal < 0) {
- printf("%s: no useable endpoint found\n",
+
+ if ((sc->sc_mode & (AUMODE_PLAY | AUMODE_RECORD)) == 0) {
+ printf("%s: no usable endpoint found\n",
USBDEVNAME(sc->sc_dev));
return (USBD_INVAL);
}
-#if 0
- if (sc->sc_chan.dir == (AUMODE_PLAY | AUMODE_RECORD))
- sc->sc_props |= AUDIO_PROP_FULLDUPLEX;
-#endif
+
+ if (sc->sc_mode == (AUMODE_PLAY | AUMODE_RECORD))
+ sc->sc_props |= AUDIO_PROP_FULLDUPLEX | AUDIO_PROP_INDEPENDENT;
+
return (USBD_NORMAL_COMPLETION);
}
@@ -1395,15 +1393,20 @@ uaudio_open(void *addr, int flags)
if (sc->sc_dying)
return (EIO);
- if (sc->sc_chan.terminal < 0)
+ if (sc->sc_mode == 0)
return (ENXIO);
- if ((flags & FREAD) && !(sc->sc_chan.dir & AUMODE_RECORD))
+ if (flags & FREAD) {
+ if ((sc->sc_mode & AUMODE_RECORD) == 0)
return (EACCES);
- if ((flags & FWRITE) && !(sc->sc_chan.dir & AUMODE_PLAY))
- return (EACCES);
+ sc->sc_recchan.intr = NULL;
+ }
- sc->sc_chan.intr = 0;
+ if (flags & FWRITE) {
+ if ((sc->sc_mode & AUMODE_PLAY) == 0)
+ return (EACCES);
+ sc->sc_playchan.intr = NULL;
+ }
return (0);
}
@@ -1420,7 +1423,7 @@ uaudio_close(void *addr)
uaudio_halt_in_dma(sc);
uaudio_halt_out_dma(sc);
- sc->sc_chan.intr = 0;
+ sc->sc_playchan.intr = sc->sc_recchan.intr = NULL;
}
int
@@ -1439,10 +1442,10 @@ uaudio_halt_out_dma(void *addr)
struct uaudio_softc *sc = addr;
DPRINTF(("uaudio_halt_out_dma: enter\n"));
- if (sc->sc_chan.pipe != NULL) {
- uaudio_chan_close(sc, &sc->sc_chan);
- sc->sc_chan.pipe = 0;
- uaudio_chan_free_buffers(sc, &sc->sc_chan);
+ if (sc->sc_playchan.pipe != NULL) {
+ uaudio_chan_close(sc, &sc->sc_playchan);
+ sc->sc_playchan.pipe = NULL;
+ uaudio_chan_free_buffers(sc, &sc->sc_playchan);
}
return (0);
}
@@ -1453,10 +1456,10 @@ uaudio_halt_in_dma(void *addr)
struct uaudio_softc *sc = addr;
DPRINTF(("uaudio_halt_in_dma: enter\n"));
- if (sc->sc_chan.pipe != NULL) {
- uaudio_chan_close(sc, &sc->sc_chan);
- sc->sc_chan.pipe = 0;
- uaudio_chan_free_buffers(sc, &sc->sc_chan);
+ if (sc->sc_recchan.pipe != NULL) {
+ uaudio_chan_close(sc, &sc->sc_recchan);
+ sc->sc_recchan.pipe = NULL;
+ uaudio_chan_free_buffers(sc, &sc->sc_recchan);
}
return (0);
}
@@ -1483,7 +1486,13 @@ uaudio_round_blocksize(void *addr, int b
struct uaudio_softc *sc = addr;
int bpf;
- bpf = sc->sc_chan.bytes_per_frame + sc->sc_chan.sample_size;
+ if (sc->sc_playchan.bytes_per_frame > sc->sc_recchan.bytes_per_frame) {
+ bpf = sc->sc_playchan.bytes_per_frame
+ + sc->sc_playchan.sample_size;
+ } else {
+ bpf = sc->sc_recchan.bytes_per_frame
+ + sc->sc_recchan.sample_size;
+ }
/* XXX */
bpf *= UAUDIO_NFRAMES * UAUDIO_NCHANBUFS;
@@ -1531,7 +1540,7 @@ uaudio_get(struct uaudio_softc *sc, int
DPRINTFN(2,("uaudio_get: type=0x%02x req=0x%02x wValue=0x%04x "
"wIndex=0x%04x len=%d\n",
type, which, wValue, wIndex, len));
- err = usbd_do_request(sc->sc_udev, &req, &data);
+ err = usbd_do_request(sc->sc_udev, &req, data);
if (err) {
DPRINTF(("uaudio_get: err=%s\n", usbd_errstr(err)));
return (-1);
@@ -1581,7 +1590,7 @@ uaudio_set(struct uaudio_softc *sc, int
DPRINTFN(2,("uaudio_set: type=0x%02x req=0x%02x wValue=0x%04x "
"wIndex=0x%04x len=%d, val=%d\n",
type, which, wValue, wIndex, len, val & 0xffff));
- err = usbd_do_request(sc->sc_udev, &req, &data);
+ err = usbd_do_request(sc->sc_udev, &req, data);
#ifdef UAUDIO_DEBUG
if (err)
DPRINTF(("uaudio_set: err=%d\n", err));
@@ -1606,7 +1615,7 @@ uaudio_value2bsd(struct mixerctl *mc, in
DPRINTFN(5, ("uaudio_value2bsd: type=%03x val=%d min=%d max=%d ",
mc->type, val, mc->minval, mc->maxval));
if (mc->type == MIX_ON_OFF)
- val = val != 0;
+ val = (val != 0);
else
val = ((uaudio_signext(mc->type, val) - mc->minval) * 256
+ mc->mul/2) / mc->mul;
@@ -1620,7 +1629,7 @@ uaudio_bsd2value(struct mixerctl *mc, in
DPRINTFN(5,("uaudio_bsd2value: type=%03x val=%d min=%d max=%d ",
mc->type, val, mc->minval, mc->maxval));
if (mc->type == MIX_ON_OFF)
- val = val != 0;
+ val = (val != 0);
else
val = (val + mc->delta/2) * mc->mul / 256 + mc->minval;
DPRINTFN(5, ("val'=%d\n", val));
@@ -1732,7 +1741,7 @@ uaudio_trigger_input(void *addr, void *s
struct audio_params *param)
{
struct uaudio_softc *sc = addr;
- struct chan *ch = &sc->sc_chan;
+ struct chan *ch = &sc->sc_recchan;
usbd_status err;
int i, s;
@@ -1757,8 +1766,8 @@ uaudio_trigger_input(void *addr, void *s
return (EIO);
}
- sc->sc_chan.intr = intr;
- sc->sc_chan.arg = arg;
+ ch->intr = intr;
+ ch->arg = arg;
s = splusb();
for (i = 0; i < UAUDIO_NCHANBUFS-1; i++) /* XXX -1 shouldn't be needed */
@@ -1774,7 +1783,7 @@ uaudio_trigger_output(void *addr, void *
struct audio_params *param)
{
struct uaudio_softc *sc = addr;
- struct chan *ch = &sc->sc_chan;
+ struct chan *ch = &sc->sc_playchan;
usbd_status err;
int i, s;
@@ -1799,8 +1808,8 @@ uaudio_trigger_output(void *addr, void *
return (EIO);
}
- sc->sc_chan.intr = intr;
- sc->sc_chan.arg = arg;
+ ch->intr = intr;
+ ch->arg = arg;
s = splusb();
for (i = 0; i < UAUDIO_NCHANBUFS-1; i++) /* XXX */
@@ -1814,11 +1823,11 @@ uaudio_trigger_output(void *addr, void *
usbd_status
uaudio_chan_open(struct uaudio_softc *sc, struct chan *ch)
{
- struct as_info *as = &sc->sc_alts[sc->sc_curaltidx];
+ struct as_info *as = &sc->sc_alts[ch->altidx];
int endpt = as->edesc->bEndpointAddress;
usbd_status err;
- DPRINTF(("uaudio_open_chan: endpt=0x%02x, speed=%d, alt=%d\n",
+ DPRINTF(("uaudio_chan_open: endpt=0x%02x, speed=%d, alt=%d\n",
endpt, ch->sample_rate, as->alt));
/* Set alternate interface corresponding to the mode. */
@@ -1836,7 +1845,7 @@ uaudio_chan_open(struct uaudio_softc *sc
(void)uaudio_set_speed(sc, endpt, ch->sample_rate);
#endif
- DPRINTF(("uaudio_open_chan: create pipe to 0x%02x\n", endpt));
+ DPRINTF(("uaudio_chan_open: create pipe to 0x%02x\n", endpt));
err = usbd_open_pipe(as->ifaceh, endpt, 0, &ch->pipe);
return (err);
}
@@ -1844,10 +1853,10 @@ uaudio_chan_open(struct uaudio_softc *sc
void
uaudio_chan_close(struct uaudio_softc *sc, struct chan *ch)
{
- struct as_info *as = &sc->sc_alts[sc->sc_curaltidx];
+ struct as_info *as = &sc->sc_alts[ch->altidx];
if (sc->sc_nullalt >= 0) {
- DPRINTF(("uaudio_close_chan: set null alt=%d\n",
+ DPRINTF(("uaudio_chan_close: set null alt=%d\n",
sc->sc_nullalt));
usbd_set_interface(as->ifaceh, sc->sc_nullalt);
}
@@ -1917,7 +1926,7 @@ uaudio_chan_ptransfer(struct chan *ch)
size = ch->bytes_per_frame;
residue += ch->fraction;
if (residue >= USB_FRAMES_PER_SECOND) {
- if (!ch->nofrac)
+ if ((ch->sc->sc_altflags & UA_NOFRAC) == 0)
size += ch->sample_size;
residue -= USB_FRAMES_PER_SECOND;
}
@@ -2021,7 +2030,7 @@ uaudio_chan_rtransfer(struct chan *ch)
size = ch->bytes_per_frame;
residue += ch->fraction;
if (residue >= USB_FRAMES_PER_SECOND) {
- if (!ch->nofrac)
+ if ((ch->sc->sc_altflags & UA_NOFRAC) == 0)
size += ch->sample_size;
residue -= USB_FRAMES_PER_SECOND;
}
@@ -2148,17 +2157,24 @@ uaudio_set_params(void *addr, int setmod
if (sc->sc_dying)
return (EIO);
- if (sc->sc_chan.pipe != NULL)
+ if ((mode == AUMODE_RECORD && sc->sc_recchan.pipe != NULL)
+ || (mode == AUMODE_PLAY && sc->sc_playchan.pipe != NULL))
return (EBUSY);
+ if (usemode & AUMODE_PLAY)
+ sc->sc_playchan.altidx = -1;
+ else
+ sc->sc_playchan.altidx = -1;
+
for (mode = AUMODE_RECORD; mode != -1;
mode = mode == AUMODE_RECORD ? AUMODE_PLAY : -1) {
if ((setmode & mode) == 0)
continue;
- if ((sc->sc_chan.dir & mode) == 0)
+
+ if ((sc->sc_mode & mode) == 0)
continue;
- p = mode == AUMODE_PLAY ? play : rec;
+ p = (mode == AUMODE_PLAY) ? play : rec;
factor = 1;
swcode = 0;
@@ -2285,13 +2301,22 @@ uaudio_set_params(void *addr, int setmod
found:
p->sw_code = swcode;
p->factor = factor;
- if (usemode == mode)
- sc->sc_curaltidx = i;
+ if (usemode & mode) {
+ if (mode == AUMODE_PLAY)
+ sc->sc_playchan.altidx = i;
+ else
+ sc->sc_recchan.altidx = i;
+ }
}
- DPRINTF(("uaudio_set_params: use altidx=%d, altno=%d\n",
- sc->sc_curaltidx,
- sc->sc_alts[sc->sc_curaltidx].idesc->bAlternateSetting));
+ DPRINTF(("uaudio_set_params: use altidx=p%d/r%d, altno=p%d/r%d\n",
+ sc->sc_playchan.altidx, sc->sc_recchan.altidx,
+ (sc->sc_playchan.altidx >= 0)
+ ?sc->sc_alts[sc->sc_playchan.altidx].idesc->bAlternateSetting
+ : -1,
+ (sc->sc_recchan.altidx >= 0)
+ ? sc->sc_alts[sc->sc_recchan.altidx].idesc->bAlternateSetting
+ : -1));
return (0);
}
@@ -2312,6 +2337,6 @@ uaudio_set_speed(struct uaudio_softc *sc
data[1] = speed >> 8;
data[2] = speed >> 16;
- return (usbd_do_request(sc->sc_udev, &req, &data));
+ return (usbd_do_request(sc->sc_udev, &req, data));
}
--ELM717424042-26155-0_--