sound: Add kqueue support
Co-authored by: meka@tilda.center Sponsored by: The FreeBSD Foundation MFC after: 2 weeks Reviewed by: markj Differential Revision: https://reviews.freebsd.org/D53029
This commit is contained in:
@@ -271,7 +271,7 @@ chn_lockdestroy(struct pcm_channel *c)
|
||||
* @retval 1 = ready for I/O
|
||||
* @retval 0 = not ready for I/O
|
||||
*/
|
||||
static int
|
||||
int
|
||||
chn_polltrigger(struct pcm_channel *c)
|
||||
{
|
||||
struct snd_dbuf *bs = c->bufsoft;
|
||||
@@ -313,6 +313,7 @@ chn_wakeup(struct pcm_channel *c)
|
||||
bs = c->bufsoft;
|
||||
|
||||
if (CHN_EMPTY(c, children.busy)) {
|
||||
KNOTE_LOCKED(&bs->sel.si_note, 0);
|
||||
if (SEL_WAITING(sndbuf_getsel(bs)) && chn_polltrigger(c))
|
||||
selwakeuppri(sndbuf_getsel(bs), PRIBIO);
|
||||
CHN_BROADCAST(&c->intr_cv);
|
||||
@@ -1277,6 +1278,7 @@ chn_init(struct snddev_info *d, struct pcm_channel *parent, kobj_class_t cls,
|
||||
}
|
||||
c->bufhard = b;
|
||||
c->bufsoft = bs;
|
||||
knlist_init_mtx(&bs->sel.si_note, c->lock);
|
||||
|
||||
c->devinfo = CHANNEL_INIT(c->methods, devinfo, b, c, direction);
|
||||
if (c->devinfo == NULL) {
|
||||
@@ -1373,8 +1375,11 @@ chn_kill(struct pcm_channel *c)
|
||||
feeder_remove(c);
|
||||
if (c->devinfo && CHANNEL_FREE(c->methods, c->devinfo))
|
||||
sndbuf_free(b);
|
||||
if (bs)
|
||||
if (bs) {
|
||||
knlist_clear(&bs->sel.si_note, 0);
|
||||
knlist_destroy(&bs->sel.si_note);
|
||||
sndbuf_destroy(bs);
|
||||
}
|
||||
if (b)
|
||||
sndbuf_destroy(b);
|
||||
CHN_LOCK(c);
|
||||
|
||||
@@ -261,6 +261,7 @@ int chn_read(struct pcm_channel *c, struct uio *buf);
|
||||
u_int32_t chn_start(struct pcm_channel *c, int force);
|
||||
int chn_sync(struct pcm_channel *c, int threshold);
|
||||
int chn_flush(struct pcm_channel *c);
|
||||
int chn_polltrigger(struct pcm_channel *c);
|
||||
int chn_poll(struct pcm_channel *c, int ev, struct thread *td);
|
||||
|
||||
char *chn_mkname(char *buf, size_t len, struct pcm_channel *c);
|
||||
|
||||
@@ -81,6 +81,7 @@ static d_ioctl_t dsp_ioctl;
|
||||
static d_poll_t dsp_poll;
|
||||
static d_mmap_t dsp_mmap;
|
||||
static d_mmap_single_t dsp_mmap_single;
|
||||
static d_kqfilter_t dsp_kqfilter;
|
||||
|
||||
struct cdevsw dsp_cdevsw = {
|
||||
.d_version = D_VERSION,
|
||||
@@ -89,6 +90,7 @@ struct cdevsw dsp_cdevsw = {
|
||||
.d_write = dsp_write,
|
||||
.d_ioctl = dsp_ioctl,
|
||||
.d_poll = dsp_poll,
|
||||
.d_kqfilter = dsp_kqfilter,
|
||||
.d_mmap = dsp_mmap,
|
||||
.d_mmap_single = dsp_mmap_single,
|
||||
.d_name = "dsp",
|
||||
@@ -2962,6 +2964,86 @@ dsp_oss_getchannelmask(struct pcm_channel *wrch, struct pcm_channel *rdch,
|
||||
return (ret);
|
||||
}
|
||||
|
||||
static void
|
||||
dsp_kqdetach(struct knote *kn)
|
||||
{
|
||||
struct pcm_channel *ch = kn->kn_hook;
|
||||
|
||||
if (ch == NULL)
|
||||
return;
|
||||
CHN_LOCK(ch);
|
||||
knlist_remove(&ch->bufsoft->sel.si_note, kn, 1);
|
||||
CHN_UNLOCK(ch);
|
||||
}
|
||||
|
||||
static int
|
||||
dsp_kqevent(struct knote *kn, long hint)
|
||||
{
|
||||
struct pcm_channel *ch = kn->kn_hook;
|
||||
|
||||
CHN_LOCKASSERT(ch);
|
||||
if (ch->flags & CHN_F_DEAD) {
|
||||
kn->kn_flags |= EV_EOF;
|
||||
return (1);
|
||||
}
|
||||
kn->kn_data = 0;
|
||||
if (chn_polltrigger(ch)) {
|
||||
if (kn->kn_filter == EVFILT_READ)
|
||||
kn->kn_data = sndbuf_getready(ch->bufsoft);
|
||||
else
|
||||
kn->kn_data = sndbuf_getfree(ch->bufsoft);
|
||||
}
|
||||
|
||||
return (kn->kn_data > 0);
|
||||
}
|
||||
|
||||
static const struct filterops dsp_filtops = {
|
||||
.f_isfd = 1,
|
||||
.f_detach = dsp_kqdetach,
|
||||
.f_event = dsp_kqevent,
|
||||
};
|
||||
|
||||
static int
|
||||
dsp_kqfilter(struct cdev *dev, struct knote *kn)
|
||||
{
|
||||
struct dsp_cdevpriv *priv;
|
||||
struct snddev_info *d;
|
||||
struct pcm_channel *ch;
|
||||
int err = 0;
|
||||
|
||||
if ((err = devfs_get_cdevpriv((void **)&priv)) != 0)
|
||||
return (err);
|
||||
|
||||
d = priv->sc;
|
||||
if (!DSP_REGISTERED(d))
|
||||
return (EBADF);
|
||||
PCM_GIANT_ENTER(d);
|
||||
switch (kn->kn_filter) {
|
||||
case EVFILT_READ:
|
||||
ch = priv->rdch;
|
||||
break;
|
||||
case EVFILT_WRITE:
|
||||
ch = priv->wrch;
|
||||
break;
|
||||
default:
|
||||
kn->kn_hook = NULL;
|
||||
err = EINVAL;
|
||||
ch = NULL;
|
||||
break;
|
||||
}
|
||||
if (ch != NULL) {
|
||||
kn->kn_fop = &dsp_filtops;
|
||||
CHN_LOCK(ch);
|
||||
knlist_add(&ch->bufsoft->sel.si_note, kn, 1);
|
||||
CHN_UNLOCK(ch);
|
||||
kn->kn_hook = ch;
|
||||
} else
|
||||
err = EINVAL;
|
||||
PCM_GIANT_LEAVE(d);
|
||||
|
||||
return (err);
|
||||
}
|
||||
|
||||
#ifdef OSSV4_EXPERIMENT
|
||||
/**
|
||||
* @brief Retrieve an audio device's label
|
||||
|
||||
Reference in New Issue
Block a user