NetBSD-Bugs archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

Re: kern/46545: pad(4):Support for fullduplex playback/recording polling and nonblocking mode



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

From: Nat Sloss <nathanialsloss%yahoo.com.au@localhost>
To: gnats-bugs%netbsd.org@localhost
Cc: 
Subject: Re: kern/46545: pad(4):Support for fullduplex playback/recording 
polling and nonblocking mode
Date: Tue, 5 Jun 2012 23:05:48 +1000

 Hi
 
 Here are my patches:
 
 Index: sys/dev/pad/pad.c
 ===================================================================
 RCS file: /cvsroot/src/sys/dev/pad/pad.c,v
 retrieving revision 1.19
 diff -u -r1.19 pad.c
 --- sys/dev/pad/pad.c  24 Nov 2011 01:54:08 -0000      1.19
 +++ sys/dev/pad/pad.c  5 Jun 2012 12:27:28 -0000
 @@ -33,10 +33,14 @@
  #include <sys/param.h>
  #include <sys/conf.h>
  #include <sys/buf.h>
 +#include <sys/errno.h>
 +#include <sys/fcntl.h>
 +#include <sys/ioctl.h>
  #include <sys/kmem.h>
  #include <sys/kernel.h>
  #include <sys/device.h>
  #include <sys/proc.h>
 +#include <sys/poll.h>
  #include <sys/condvar.h>
  #include <sys/select.h>
  #include <sys/audioio.h>
 @@ -54,7 +58,6 @@
  #define PADUNIT(x)    minor(x)
  
  extern struct cfdriver pad_cd;
 -
  typedef struct pad_block {
        uint8_t         *pb_ptr;
        int             pb_len;
 @@ -63,8 +66,10 @@
  enum {
        PAD_OUTPUT_CLASS,
        PAD_INPUT_CLASS,
 +      PAD_RECORD_CLASS,
        PAD_OUTPUT_MASTER_VOLUME,
        PAD_INPUT_DAC_VOLUME,
 +      PAD_INPUT_MIC_VOLUME,
        PAD_ENUM_LAST,
  };
  
 @@ -84,14 +89,19 @@
  static int    pad_halt_output(void *);
  static int    pad_halt_input(void *);
  static int    pad_getdev(void *, struct audio_device *);
 +static int    pad_setfd(void *, int);
  static int    pad_set_port(void *, mixer_ctrl_t *);
  static int    pad_get_port(void *, mixer_ctrl_t *);
  static int    pad_query_devinfo(void *, mixer_devinfo_t *);
  static int    pad_get_props(void *);
  static int    pad_round_blocksize(void *, int, int, const audio_params_t *);
  static void   pad_get_locks(void *, kmutex_t **, kmutex_t **);
 +static int    pad_audio_open(void *,int);
 +static void   pad_audio_close(void *);
  
  static const struct audio_hw_if pad_hw_if = {
 +      .open = pad_audio_open,
 +      .close = pad_audio_close,
        .query_encoding = pad_query_encoding,
        .set_params = pad_set_params,
        .start_output = pad_start_output,
 @@ -99,6 +109,7 @@
        .halt_output = pad_halt_output,
        .halt_input = pad_halt_input,
        .getdev = pad_getdev,
 +      .setfd = pad_setfd,
        .set_port = pad_set_port,
        .get_port = pad_get_port,
        .query_devinfo = pad_query_devinfo,
 @@ -115,22 +126,28 @@
  
  extern void   padattach(int);
  
 -static int            pad_add_block(pad_softc_t *, uint8_t *, int);
 -static int            pad_get_block(pad_softc_t *, pad_block_t *, int);
 +static int            pad_add_block_out(pad_softc_t *, uint8_t *, int);
 +static int            pad_get_block_out(pad_softc_t *, pad_block_t *, int);
 +
 +static int            pad_add_block_in(pad_softc_t *, uint8_t *, int);
 +static int            pad_get_block_in(pad_softc_t *, pad_block_t *, int);
  
  dev_type_open(pad_open);
  dev_type_close(pad_close);
  dev_type_read(pad_read);
 +dev_type_read(pad_write);
 +dev_type_poll(pad_poll);
 +dev_type_ioctl(pad_ioctl);
  
  const struct cdevsw pad_cdevsw = {
        .d_open = pad_open,
        .d_close = pad_close,
        .d_read = pad_read,
 -      .d_write = nowrite,
 -      .d_ioctl = noioctl,
 +      .d_write = pad_write,
 +      .d_ioctl = pad_ioctl,
        .d_stop = nostop,
        .d_tty = notty,
 -      .d_poll = nopoll,
 +      .d_poll = pad_poll,
        .d_mmap = nommap,
        .d_kqfilter = nokqfilter,
        .d_flag = D_OTHER | D_MPSAFE,
 @@ -174,47 +191,77 @@
  }
  
  static int
 -pad_add_block(pad_softc_t *sc, uint8_t *blk, int blksize)
 +pad_add_block_out(pad_softc_t *sc, uint8_t *blk, int blksize)
  {
        int l;
  
 -      if (sc->sc_open == 0)
 +      if ((sc->sc_open & AUOPEN_READ) == 0)
                return EIO;
  
        KASSERT(mutex_owned(&sc->sc_lock));
  
 -      if (sc->sc_buflen + blksize > PAD_BUFSIZE)
 -              return ENOBUFS;
 +      if (sc->sc_out_buflen + blksize > PAD_BUFSIZE)
 +              return 0;
  
 -      if (sc->sc_wpos + blksize <= PAD_BUFSIZE)
 -              memcpy(sc->sc_audiobuf + sc->sc_wpos, blk, blksize);
 +      if (sc->sc_opos + blksize <= PAD_BUFSIZE)
 +              memcpy(sc->sc_out_audiobuf + sc->sc_opos, blk, blksize);
        else {
 -              l = PAD_BUFSIZE - sc->sc_wpos;
 -              memcpy(sc->sc_audiobuf + sc->sc_wpos, blk, l);
 -              memcpy(sc->sc_audiobuf, blk + l, blksize - l);
 +              l = PAD_BUFSIZE - sc->sc_opos;
 +              memcpy(sc->sc_out_audiobuf + sc->sc_opos, blk, l);
 +              memcpy(sc->sc_out_audiobuf, blk + l, blksize - l);
 +      }
 +
 +      sc->sc_opos += blksize;
 +      if (sc->sc_opos > PAD_BUFSIZE)
 +              sc->sc_opos -= PAD_BUFSIZE;
 +
 +      sc->sc_out_buflen += blksize;
 +
 +      return 0;
 +}
 +
 +static int
 +pad_add_block_in(pad_softc_t *sc, uint8_t *blk, int blksize)
 +{
 +      int l;
 +
 +      if ((sc->sc_open & AUOPEN_WRITE) == 0)
 +              return EIO;
 +
 +      KASSERT(mutex_owned(&sc->sc_lock));
 +
 +      if (sc->sc_in_buflen < PAD_BLKSIZE)
 +              return 0;
 +
 +      if (sc->sc_ipos + blksize <= PAD_BUFSIZE)
 +              memcpy(blk, sc->sc_in_audiobuf + sc->sc_ipos, blksize);
 +      else {
 +              l = PAD_BUFSIZE - sc->sc_ipos;
 +              memcpy(blk, sc->sc_in_audiobuf + sc->sc_ipos, l);
 +              memcpy(blk + l, sc->sc_in_audiobuf, blksize - l);
        }
  
 -      sc->sc_wpos += blksize;
 -      if (sc->sc_wpos > PAD_BUFSIZE)
 -              sc->sc_wpos -= PAD_BUFSIZE;
 +      sc->sc_ipos += blksize;
 +      if (sc->sc_ipos > PAD_BUFSIZE)
 +              sc->sc_ipos -= PAD_BUFSIZE;
  
 -      sc->sc_buflen += blksize;
 +      sc->sc_in_buflen -= blksize;
  
        return 0;
  }
  
  static int
 -pad_get_block(pad_softc_t *sc, pad_block_t *pb, int blksize)
 +pad_get_block_out(pad_softc_t *sc, pad_block_t *pb, int blksize)
  {
        int l;
  
        KASSERT(mutex_owned(&sc->sc_lock));
        KASSERT(pb != NULL);
  
 -      if (sc->sc_buflen < blksize)
 +      if (sc->sc_out_buflen < blksize)
                return ERESTART;
  
 -      pb->pb_ptr = (sc->sc_audiobuf + sc->sc_rpos);
 +      pb->pb_ptr = (sc->sc_out_audiobuf + sc->sc_rpos);
        if (sc->sc_rpos + blksize < PAD_BUFSIZE) {
                pb->pb_len = blksize;
                sc->sc_rpos += blksize;
 @@ -223,7 +270,32 @@
                pb->pb_len = l;
                sc->sc_rpos = 0;
        }
 -      sc->sc_buflen -= pb->pb_len;
 +      sc->sc_out_buflen -= pb->pb_len;
 +
 +      return 0;
 +}
 +
 +static int
 +pad_get_block_in(pad_softc_t *sc, pad_block_t *pb, int blksize)
 +{
 +      int l;
 +
 +      KASSERT(mutex_owned(&sc->sc_lock));
 +      KASSERT(pb != NULL);
 +
 +      if (sc->sc_in_buflen + blksize > PAD_BUFSIZE)
 +              return ENOBUFS;
 +
 +      pb->pb_ptr = (sc->sc_in_audiobuf + sc->sc_wpos);
 +      if (sc->sc_wpos + blksize < PAD_BUFSIZE) {
 +              pb->pb_len = blksize;
 +              sc->sc_wpos += blksize;
 +      } else {
 +              l = PAD_BUFSIZE - sc->sc_wpos;
 +              pb->pb_len = l;
 +              sc->sc_wpos = 0;
 +      }
 +      sc->sc_in_buflen += pb->pb_len;
  
        return 0;
  }
 @@ -252,19 +324,27 @@
  
        sc->sc_dev = self;
        sc->sc_open = 0;
 +      sc->sc_flags = 0;
 +      sc->sc_mode = 0;
        if (auconv_create_encodings(pad_formats, PAD_NFORMATS,
            &sc->sc_encodings) != 0) {
                aprint_error_dev(self, "couldn't create encodings\n");
                return;
        }
  
 -      cv_init(&sc->sc_condvar, device_xname(self));
 +      cv_init(&sc->sc_condvar_in, device_xname(self));
 +      cv_init(&sc->sc_condvar_out, device_xname(self));
        mutex_init(&sc->sc_lock, MUTEX_DEFAULT, IPL_NONE);
        mutex_init(&sc->sc_intr_lock, MUTEX_DEFAULT, IPL_NONE);
  
        sc->sc_swvol = 255;
 -      sc->sc_buflen = 0;
 -      sc->sc_rpos = sc->sc_wpos = 0;
 +      sc->sc_out_buflen = 0;
 +      sc->sc_rpos = sc->sc_opos = 0;
 +
 +      sc->sc_recvol = 255;
 +      sc->sc_in_buflen = 0;
 +      sc->sc_wpos = sc->sc_ipos = 0;
 +
        sc->sc_audiodev = (void *)audio_attach_mi(&pad_hw_if, sc, sc->sc_dev);
  
        if (!pmf_device_register(self, NULL, NULL))
 @@ -290,7 +370,8 @@
  
        mutex_destroy(&sc->sc_lock);
        mutex_destroy(&sc->sc_intr_lock);
 -      cv_destroy(&sc->sc_condvar);
 +      cv_destroy(&sc->sc_condvar_in);
 +      cv_destroy(&sc->sc_condvar_out);
  
        auconv_delete_encodings(sc->sc_encodings);
  
 @@ -306,8 +387,20 @@
        if (sc == NULL)
                return ENXIO;
  
 -      if (atomic_swap_uint(&sc->sc_open, 1) != 0) {
 +      if (((flags & FREAD) && (sc->sc_open & AUOPEN_READ)) ||
 +          ((flags & FWRITE) && (sc->sc_open & AUOPEN_WRITE)))
                return EBUSY;
 +
 +      if (flags & FREAD) {
 +              sc->sc_open |= AUOPEN_READ;
 +              sc->sc_out_buflen = 0;
 +              sc->sc_rpos = sc->sc_opos = 0;
 +      }
 +
 +      if (flags & FWRITE) {
 +              sc->sc_open |= AUOPEN_WRITE;
 +              sc->sc_in_buflen = 0;
 +              sc->sc_wpos = sc->sc_ipos = 0;
        }
  
        return 0;
 @@ -323,7 +416,9 @@
                return ENXIO;
  
        KASSERT(sc->sc_open > 0);
 +
        sc->sc_open = 0;
 +      sc->sc_flags = 0;
  
        return 0;
  }
 @@ -335,20 +430,26 @@
        pad_block_t pb;
        void (*intr)(void *);
        void *intrarg;
 -      int err;
 +      int err, timeout;
  
        sc = device_lookup_private(&pad_cd, PADUNIT(dev));
        if (sc == NULL)
                return ENXIO;
  
 +      if ((sc->sc_open & AUOPEN_READ) == 0)
 +              return EIO;
 +
        err = 0;
 +      timeout = mstohz(1000);
 +      if (timeout == 0)
 +              timeout = 1;
  
        mutex_enter(&sc->sc_lock);
 -      intr = sc->sc_intr;
 -      intrarg = sc->sc_intrarg;
 +      intr = sc->sc_out_intr;
 +      intrarg = sc->sc_out_intrarg;
  
        while (uio->uio_resid > 0 && !err) {
 -              err = pad_get_block(sc, &pb, min(uio->uio_resid, PAD_BLKSIZE));
 +              err = pad_get_block_out(sc, &pb, min(uio->uio_resid, 
PAD_BLKSIZE));
                if (!err) {
                        mutex_exit(&sc->sc_lock);
                        err = uiomove(pb.pb_ptr, pb.pb_len, uio);
 @@ -360,27 +461,84 @@
                        mutex_enter(&sc->sc_intr_lock);
                        (*intr)(intrarg);
                        mutex_exit(&sc->sc_intr_lock);
 -                      intr = sc->sc_intr;
 -                      intrarg = sc->sc_intrarg;
 +                      intr = sc->sc_out_intr;
 +                      intrarg = sc->sc_out_intrarg;
                        err = 0;
                        continue;
                }
 -              err = cv_wait_sig(&sc->sc_condvar, &sc->sc_lock);
 +
 +              if ((sc->sc_flags & O_NONBLOCK) == 0)
 +                      err = cv_wait_sig(&sc->sc_condvar_out, &sc->sc_lock);
 +              else
 +                      err = cv_timedwait_sig(&sc->sc_condvar_out, 
&sc->sc_lock, timeout);
 +
                if (err != 0) {
                        mutex_exit(&sc->sc_lock);
                        return err;
                }
 -              intr = sc->sc_intr;
 -              intrarg = sc->sc_intrarg;
 -      }
 +              intr = sc->sc_out_intr;
 +              intrarg = sc->sc_out_intrarg;
  
 -      if (intr) {
 -              mutex_enter(&sc->sc_intr_lock);
 -              (*intr)(intrarg);
 -              mutex_exit(&sc->sc_intr_lock);
        }
 +
        mutex_exit(&sc->sc_lock);
 +      return err;
 +}
 +
 +int
 +pad_write(dev_t dev, struct uio *uio, int flags)
 +{
 +      pad_softc_t *sc;
 +      pad_block_t pb;
 +      void (*intr)(void *);
 +      void *intrarg;
 +      int err;
 +
 +      sc = device_lookup_private(&pad_cd, PADUNIT(dev));
 +      if (sc == NULL)
 +              return ENXIO;
 +
 +      if ((sc->sc_open & AUOPEN_WRITE) == 0)
 +              return EIO;
 +
 +      err = 0;
 +
 +      mutex_enter(&sc->sc_lock);
 +      intr = sc->sc_in_intr;
 +      intrarg = sc->sc_in_intrarg;
 +
 +      while (uio->uio_resid > 0 && !err) {
 +              err = pad_get_block_in(sc, &pb, min(uio->uio_resid, 
PAD_BLKSIZE));
 +              if (!err) {
 +                      mutex_exit(&sc->sc_lock);
 +                      err = uiomove(pb.pb_ptr, pb.pb_len, uio);
 +                      if (err != 0)
 +                              return err;
 +                      mutex_enter(&sc->sc_lock);
 +                      continue;
 +              }
 +
 +              if (intr) {
 +                      mutex_enter(&sc->sc_intr_lock);
 +                      (*intr)(intrarg);
 +                      mutex_exit(&sc->sc_intr_lock);
 +                      intr = sc->sc_in_intr;
 +                      intrarg = sc->sc_in_intrarg;
 +                      err = 0;
 +                      continue;
 +              }
  
 +              err = cv_wait_sig(&sc->sc_condvar_in, &sc->sc_lock);
 +              if (err != 0) {
 +                      mutex_exit(&sc->sc_lock);
 +                      return err;
 +              }
 +              intr = sc->sc_in_intr;
 +              intrarg = sc->sc_in_intrarg;
 +
 +      }
 +
 +      mutex_exit(&sc->sc_lock);
        return err;
  }
  
 @@ -419,11 +577,26 @@
        switch (play->encoding) {
        case AUDIO_ENCODING_SLINEAR_LE:
                if (play->precision == 16 && play->validbits == 16)
 -                      pfil->prepend(pfil, pad_vol_slinear16_le, play);
 +                      pfil->prepend(pfil, pad_vol_slinear16_le_play, play);
                break;
        case AUDIO_ENCODING_SLINEAR_BE:
                if (play->precision == 16 && play->validbits == 16)
 -                      pfil->prepend(pfil, pad_vol_slinear16_be, play);
 +                      pfil->prepend(pfil, pad_vol_slinear16_be_play, play);
 +              break;
 +      default:
 +              break;
 +      }
 +
 +      if (rfil->req_size > 0)
 +              rec = &rfil->filters[0].param;
 +      switch (rec->encoding) {
 +      case AUDIO_ENCODING_SLINEAR_LE:
 +              if (rec->precision == 16 && rec->validbits == 16)
 +                      rfil->prepend(rfil, pad_vol_slinear16_le_rec, rec);
 +              break;
 +      case AUDIO_ENCODING_SLINEAR_BE:
 +              if (rec->precision == 16 && rec->validbits == 16)
 +                      rfil->prepend(rfil, pad_vol_slinear16_be_rec, rec);
                break;
        default:
                break;
 @@ -443,13 +616,13 @@
  
        KASSERT(mutex_owned(&sc->sc_lock));
  
 -      sc->sc_intr = intr;
 -      sc->sc_intrarg = intrarg;
 +      sc->sc_out_intr = intr;
 +      sc->sc_out_intrarg = intrarg;
        sc->sc_blksize = blksize;
  
 -      err = pad_add_block(sc, block, blksize);
 +      err = pad_add_block_out(sc, block, blksize);
  
 -      cv_broadcast(&sc->sc_condvar);
 +      cv_broadcast(&sc->sc_condvar_out);
  
        return err;
  }
 @@ -459,12 +632,21 @@
      void (*intr)(void *), void *intrarg)
  {
        pad_softc_t *sc;
 +      int err;
  
        sc = (pad_softc_t *)opaque;
  
        KASSERT(mutex_owned(&sc->sc_lock));
  
 -      return EOPNOTSUPP;
 +      sc->sc_in_intr = intr;
 +      sc->sc_in_intrarg = intrarg;
 +      sc->sc_blksize = blksize;
 +
 +      err = pad_add_block_in(sc, block, blksize);
 +
 +      cv_broadcast(&sc->sc_condvar_in);
 +
 +      return err;
  }
  
  static int
 @@ -476,10 +658,10 @@
  
        KASSERT(mutex_owned(&sc->sc_lock));
  
 -      sc->sc_intr = NULL;
 -      sc->sc_intrarg = NULL;
 -      sc->sc_buflen = 0;
 -      sc->sc_rpos = sc->sc_wpos = 0;
 +      sc->sc_out_intr = NULL;
 +      sc->sc_out_intrarg = NULL;
 +      sc->sc_out_buflen = 0;
 +      sc->sc_rpos = sc->sc_opos = 0;
  
        return 0;
  }
 @@ -493,6 +675,11 @@
  
        KASSERT(mutex_owned(&sc->sc_lock));
  
 +      sc->sc_in_intr = NULL;
 +      sc->sc_in_intrarg = NULL;
 +      sc->sc_in_buflen = 0;
 +      sc->sc_wpos = sc->sc_ipos = 0;
 +
        return 0;
  }
  
 @@ -507,6 +694,11 @@
  }
  
  static int
 +pad_setfd(void *hdl, int fd) {
 +      return 0;
 +}
 +
 +static int
  pad_set_port(void *opaque, mixer_ctrl_t *mc)
  {
        pad_softc_t *sc;
 @@ -520,6 +712,9 @@
        case PAD_INPUT_DAC_VOLUME:
                sc->sc_swvol = mc->un.value.level[AUDIO_MIXER_LEVEL_MONO];
                return 0;
 +      case PAD_INPUT_MIC_VOLUME:
 +              sc->sc_recvol = mc->un.value.level[AUDIO_MIXER_LEVEL_MONO];
 +              return 0;
        }
  
        return ENXIO;
 @@ -539,6 +734,9 @@
        case PAD_INPUT_DAC_VOLUME:
                mc->un.value.level[AUDIO_MIXER_LEVEL_MONO] = sc->sc_swvol;
                return 0;
 +      case PAD_INPUT_MIC_VOLUME:
 +              mc->un.value.level[AUDIO_MIXER_LEVEL_MONO] = sc->sc_recvol;
 +              return 0;
        }
  
        return ENXIO;
 @@ -566,6 +764,12 @@
                di->type = AUDIO_MIXER_CLASS;
                di->next = di->prev = AUDIO_MIXER_LAST;
                return 0;
 +      case PAD_RECORD_CLASS:
 +              di->mixer_class = PAD_RECORD_CLASS;
 +              strcpy(di->label.name, AudioCrecord);
 +              di->type = AUDIO_MIXER_CLASS;
 +              di->next = di->prev = AUDIO_MIXER_LAST;
 +              return 0;
        case PAD_OUTPUT_MASTER_VOLUME:
                di->mixer_class = PAD_OUTPUT_CLASS;
                strcpy(di->label.name, AudioNmaster);
 @@ -582,6 +786,14 @@
                di->un.v.num_channels = 1;
                strcpy(di->un.v.units.name, AudioNvolume);
                return 0;
 +      case PAD_INPUT_MIC_VOLUME:
 +              di->mixer_class = PAD_RECORD_CLASS;
 +              strcpy(di->label.name, AudioNmicrophone);
 +              di->type = AUDIO_MIXER_VALUE;
 +              di->next = di->prev = AUDIO_MIXER_LAST;
 +              di->un.v.num_channels = 1;
 +              strcpy(di->un.v.units.name, AudioNvolume);
 +              return 0;
        }
  
        return ENXIO;
 @@ -596,7 +808,7 @@
  
        KASSERT(mutex_owned(&sc->sc_lock));
  
 -      return 0;
 +      return AUDIO_PROP_FULLDUPLEX;
  }
  
  static int
 @@ -622,6 +834,89 @@
        *thread = &sc->sc_lock;
  }
  
 +int
 +pad_poll(dev_t dev, int events, lwp_t *l)
 +{
 +      pad_softc_t *sc;
 +      int revents = 0;
 +
 +      sc = device_lookup_private(&pad_cd, PADUNIT(dev));
 +      if (sc == NULL)
 +              return ENXIO;
 +
 +      mutex_enter(&sc->sc_lock);
 +
 +      if (events & (POLLIN | POLLRDNORM)) {
 +              if ((sc->sc_open & AUOPEN_READ) && (sc->sc_opos > 0)
 +                  && (sc->sc_mode & AUMODE_PLAY))
 +                      revents |= events & (POLLIN | POLLRDNORM);
 +      }
 +
 +      if (events & (POLLOUT | POLLWRNORM)) {
 +              if ((sc->sc_open & AUOPEN_WRITE) && (sc->sc_mode & 
AUMODE_RECORD))
 +                      revents |= events & (POLLOUT | POLLWRNORM);
 +      }
 +
 +      mutex_exit(&sc->sc_lock);
 +
 +      return revents;
 +}
 +
 +static int
 +pad_audio_open(void *hdl, int flags) {
 +      struct pad_softc *sc = hdl;
 +
 +      if (!sc->sc_open)
 +              return EIO;
 +
 +      if (flags & FREAD)
 +              sc->sc_mode |= AUMODE_RECORD;
 +
 +      if (flags & FWRITE)
 +              sc->sc_mode |= AUMODE_PLAY;
 +
 +      sc->sc_out_buflen = 0;
 +      sc->sc_rpos = sc->sc_opos = 0;
 +
 +      sc->sc_in_buflen = 0;
 +      sc->sc_wpos = sc->sc_ipos = 0;
 +
 +      return 0;
 +}
 +
 +static void
 +pad_audio_close(void *hdl) {
 +      struct pad_softc *sc = hdl;
 +
 +      sc->sc_mode = 0;
 +
 +      sc->sc_out_buflen = 0;
 +      sc->sc_rpos = sc->sc_opos = 0;
 +
 +      sc->sc_in_buflen = 0;
 +      sc->sc_wpos = sc->sc_ipos = 0;
 +
 +      return;
 +}
 +
 +int
 +pad_ioctl(dev_t dev, u_long cmd, void *addr, int flag, struct lwp *l)
 +{
 +      pad_softc_t *sc;
 +      sc = device_lookup_private(&pad_cd, PADUNIT(dev));
 +
 +      /* Figure out which lock type we need. */
 +      switch (cmd) {
 +      case FIONBIO:
 +              if (flag == 0)
 +                      sc->sc_flags &= ~O_NONBLOCK;
 +              else
 +                      sc->sc_flags |= O_NONBLOCK;
 +      }
 +
 +      return 0;
 +}
 +
  #ifdef _MODULE
  
  MODULE(MODULE_CLASS_DRIVER, pad, NULL);
 Index: sys/dev/pad/padvar.h
 ===================================================================
 RCS file: /cvsroot/src/sys/dev/pad/padvar.h,v
 retrieving revision 1.4
 diff -u -r1.4 padvar.h
 --- sys/dev/pad/padvar.h       23 Nov 2011 23:07:33 -0000      1.4
 +++ sys/dev/pad/padvar.h       5 Jun 2012 12:27:28 -0000
 @@ -33,11 +33,16 @@
        device_t        sc_dev;
  
        u_int           sc_open;
 +      u_int           sc_flags;
 +      u_char          sc_mode;
        struct audio_encoding_set *sc_encodings;
 -      void            (*sc_intr)(void *);
 -      void            *sc_intrarg;
 +      void            (*sc_out_intr)(void *);
 +      void            *sc_out_intrarg;
 +      void            (*sc_in_intr)(void *);
 +      void            *sc_in_intrarg;
  
 -      kcondvar_t      sc_condvar;
 +      kcondvar_t      sc_condvar_in;
 +      kcondvar_t      sc_condvar_out;
        kmutex_t        sc_lock;
        kmutex_t        sc_intr_lock;
  
 @@ -46,11 +51,15 @@
  
  #define PAD_BLKSIZE   1024
  #define PAD_BUFSIZE   65536
 -      uint8_t         sc_audiobuf[PAD_BUFSIZE];
 -      uint32_t        sc_buflen;
 -      uint32_t        sc_rpos, sc_wpos;
 +      uint8_t         sc_out_audiobuf[PAD_BUFSIZE];
 +      uint8_t         sc_in_audiobuf[PAD_BUFSIZE];
 +      uint32_t        sc_out_buflen;
 +      uint32_t        sc_in_buflen;
 +      uint32_t        sc_rpos, sc_opos;
 +      uint32_t        sc_wpos, sc_ipos;
  
        u_int           sc_swvol;
 +      u_int           sc_recvol;
  } pad_softc_t;
  
  #endif /* !_SYS_DEV_PAD_PADVAR_H */
 Index: sys/dev/pad/padvol.c
 ===================================================================
 RCS file: /cvsroot/src/sys/dev/pad/padvol.c,v
 retrieving revision 1.6
 diff -u -r1.6 padvol.c
 --- sys/dev/pad/padvol.c       23 Nov 2011 23:07:33 -0000      1.6
 +++ sys/dev/pad/padvol.c       5 Jun 2012 12:27:28 -0000
 @@ -72,7 +72,7 @@
        return (stream_filter_t *)this;
  }
  
 -PAD_DEFINE_FILTER(pad_vol_slinear16_le)
 +PAD_DEFINE_FILTER(pad_vol_slinear16_le_play)
  {
        pad_filter_t *pf;
        pad_softc_t *sc;
 @@ -98,7 +98,7 @@
        return 0;
  }
  
 -PAD_DEFINE_FILTER(pad_vol_slinear16_be)
 +PAD_DEFINE_FILTER(pad_vol_slinear16_be_play)
  {
        pad_filter_t *pf;
        pad_softc_t *sc;
 @@ -123,3 +123,55 @@
  
        return 0;
  }
 +
 +PAD_DEFINE_FILTER(pad_vol_slinear16_le_rec)
 +{
 +      pad_filter_t *pf;
 +      pad_softc_t *sc;
 +      stream_filter_t *this;
 +      int16_t j, *wp;
 +      int m, err;
 +
 +      pf = (pad_filter_t *)self;
 +      sc = device_private(pf->audiosc->sc_dev);
 +      this = &pf->base;
 +      max_used = (max_used + 1) & ~1;
 +
 +      if ((err = this->prev->fetch_to(asc, this->prev, this->src, max_used)))
 +              return err;
 +      m = (dst->end - dst->start) & ~1;
 +      m = min(m, max_used);
 +      FILTER_LOOP_PROLOGUE(this->src, 2, dst, 2, m) {
 +              j = le16dec(s);
 +              wp = (int16_t *)d;
 +              le16enc(wp, (j * sc->sc_recvol) / 255);
 +      } FILTER_LOOP_EPILOGUE(this->src, dst);
 +
 +      return 0;
 +}
 +
 +PAD_DEFINE_FILTER(pad_vol_slinear16_be_rec)
 +{
 +      pad_filter_t *pf;
 +      pad_softc_t *sc;
 +      stream_filter_t *this;
 +      int16_t j, *wp;
 +      int m, err;
 +
 +      pf = (pad_filter_t *)self;
 +      sc = device_private(pf->audiosc->sc_dev);
 +      this = &pf->base;
 +      max_used = (max_used + 1) & ~1;
 +
 +      if ((err = this->prev->fetch_to(asc, this->prev, this->src, max_used)))
 +              return err;
 +      m = (dst->end - dst->start) & ~1;
 +      m = min(m, max_used);
 +      FILTER_LOOP_PROLOGUE(this->src, 2, dst, 2, m) {
 +              j = be16dec(s);
 +              wp = (int16_t *)d;
 +              be16enc(wp, (j * sc->sc_recvol) / 255);
 +      } FILTER_LOOP_EPILOGUE(this->src, dst);
 +
 +      return 0;
 +}
 Index: sys/dev/pad/padvol.h
 ===================================================================
 RCS file: /cvsroot/src/sys/dev/pad/padvol.h,v
 retrieving revision 1.3
 diff -u -r1.3 padvol.h
 --- sys/dev/pad/padvol.h       23 Nov 2011 23:07:33 -0000      1.3
 +++ sys/dev/pad/padvol.h       5 Jun 2012 12:27:28 -0000
 @@ -29,9 +29,13 @@
  #ifndef _SYS_DEV_PAD_PADVOL_H
  #define _SYS_DEV_PAD_PADVOL_H
  
 -stream_filter_t *     pad_vol_slinear16_le(struct audio_softc *,
 +stream_filter_t *     pad_vol_slinear16_le_play(struct audio_softc *,
                            const audio_params_t *, const audio_params_t *);
 -stream_filter_t *     pad_vol_slinear16_be(struct audio_softc *,
 +stream_filter_t *     pad_vol_slinear16_be_play(struct audio_softc *,
 +                          const audio_params_t *, const audio_params_t *);
 +stream_filter_t *     pad_vol_slinear16_le_rec(struct audio_softc *,
 +                          const audio_params_t *, const audio_params_t *);
 +stream_filter_t *     pad_vol_slinear16_be_rec(struct audio_softc *,
                            const audio_params_t *, const audio_params_t *);
  
  #define PAD_DEFINE_FILTER(name)                                               
\
 
 Note: These patches are derived from pad/padvol.c and are my own work which I 
 submit under the NetBSD license.
 
 
 Regards,
 
 Nat.
 


Home | Main Index | Thread Index | Old Index