audio(4): fix for poll(2) syscall

classic Classic list List threaded Threaded
1 message Options
Reply | Threaded
Open this post in threaded view

audio(4): fix for poll(2) syscall

Alexandre Ratchov-2

the poll(2) syscall doesn't work on an audio(4) device in fullduplex
mode, for instance it may not set POLLIN when samples become
available. The attached patch fixes this by making conditions used by
poll (FILTREAD and FILTWRITE macros) match the blocking conditions in
audio_read() and audio_write().

POLLIN should be set if data may be read without blocking, this
happens if:

        - the driver is recording and samples are available in
          the recording buffer

        - there is some silence to return. The user may request
          both play and record even if the driver is in half-duplex
          mode (in this case it returns silence at the same rate it
          is playing)

POLLOUT should be set if data may be written without blocking, this
happens if:

        - there is some space for new samples in the play buffer

        - some samples have to be dropped in order to do
          the real-time correction (if AUMODE_PLAYALL isn't set)

        - the device is already recording in half-duplex mode; it is
          possible to write samples, but they will be dropped..

tested on i386 with an uaudio(4) device

Index: audio.c
RCS file: /cvs/src/sys/dev/audio.c,v
retrieving revision 1.49
diff -u -r1.49 audio.c
--- audio.c 12 Mar 2006 10:34:50 -0000 1.49
+++ audio.c 26 Apr 2006 06:11:43 -0000
@@ -1797,10 +1797,14 @@
  KNOTE(&si->si_note, 0);
-#define AUDIO_FILTREAD(sc) ((sc->sc_mode & AUMODE_PLAY) ? \
+#define AUDIO_FILTREAD(sc) ( \
+    (!sc->sc_full_duplex && (sc->sc_mode & AUMODE_PLAY)) ? \
     sc->sc_pr.stamp > sc->sc_wstamp : sc->sc_rr.used > sc->sc_rr.usedlow)
-#define AUDIO_FILTWRITE(sc) \
-    (sc->sc_mode & AUMODE_RECORD || sc->sc_pr.used <= sc->sc_pr.usedlow)
+#define AUDIO_FILTWRITE(sc) ( \
+    (!sc->sc_full_duplex && (sc->sc_mode & AUMODE_RECORD)) || \
+    (!(sc->sc_mode & AUMODE_PLAY_ALL) && sc->sc_playdrop > 0) || \
+    (sc->sc_pr.used <= sc->sc_pr.usedlow))
 audio_poll(dev, events, p)