diff options
-rw-r--r-- | sys/kern/tty_pts.c | 107 |
1 files changed, 107 insertions, 0 deletions
diff --git a/sys/kern/tty_pts.c b/sys/kern/tty_pts.c index 1f87cba..9e81a6d 100644 --- a/sys/kern/tty_pts.c +++ b/sys/kern/tty_pts.c @@ -254,6 +254,14 @@ done: ttydisc_rint_done(tp); } static int +ptsdev_truncate(struct file *fp, off_t length, struct ucred *active_cred, + struct thread *td) +{ + + return (EINVAL); +} + +static int ptsdev_ioctl(struct file *fp, u_long cmd, void *data, struct ucred *active_cred, struct thread *td) { @@ -423,6 +431,94 @@ ptsdev_poll(struct file *fp, int events, struct ucred *active_cred, return (revents); } +/* + * kqueue support. + */ + +static void +pts_kqops_read_detach(struct knote *kn) +{ + struct file *fp = kn->kn_fp; + struct tty *tp = fp->f_data; + struct pts_softc *psc = tty_softc(tp); + + knlist_remove(&psc->pts_outpoll.si_note, kn, 0); +} + +static int +pts_kqops_read_event(struct knote *kn, long hint) +{ + struct file *fp = kn->kn_fp; + struct tty *tp = fp->f_data; + struct pts_softc *psc = tty_softc(tp); + + if (psc->pts_flags & PTS_FINISHED) { + kn->kn_flags |= EV_EOF; + return (1); + } else { + kn->kn_data = ttydisc_getc_poll(tp); + return (kn->kn_data > 0); + } +} + +static void +pts_kqops_write_detach(struct knote *kn) +{ + struct file *fp = kn->kn_fp; + struct tty *tp = fp->f_data; + struct pts_softc *psc = tty_softc(tp); + + knlist_remove(&psc->pts_inpoll.si_note, kn, 0); +} + +static int +pts_kqops_write_event(struct knote *kn, long hint) +{ + struct file *fp = kn->kn_fp; + struct tty *tp = fp->f_data; + struct pts_softc *psc = tty_softc(tp); + + if (psc->pts_flags & PTS_FINISHED) { + kn->kn_flags |= EV_EOF; + return (1); + } else { + kn->kn_data = ttydisc_rint_poll(tp); + return (kn->kn_data > 0); + } +} + +static struct filterops pts_kqops_read = + { 1, NULL, pts_kqops_read_detach, pts_kqops_read_event }; +static struct filterops pts_kqops_write = + { 1, NULL, pts_kqops_write_detach, pts_kqops_write_event }; + +static int +ptsdev_kqfilter(struct file *fp, struct knote *kn) +{ + struct tty *tp = fp->f_data; + struct pts_softc *psc = tty_softc(tp); + int error = 0; + + tty_lock(tp); + + switch (kn->kn_filter) { + case EVFILT_READ: + kn->kn_fop = &pts_kqops_read; + knlist_add(&psc->pts_outpoll.si_note, kn, 1); + break; + case EVFILT_WRITE: + kn->kn_fop = &pts_kqops_write; + knlist_add(&psc->pts_inpoll.si_note, kn, 1); + break; + default: + error = EINVAL; + break; + } + + tty_unlock(tp); + return (error); +} + static int ptsdev_stat(struct file *fp, struct stat *sb, struct ucred *active_cred, struct thread *td) @@ -475,8 +571,10 @@ ptsdev_close(struct file *fp, struct thread *td) static struct fileops ptsdev_ops = { .fo_read = ptsdev_read, .fo_write = ptsdev_write, + .fo_truncate = ptsdev_truncate, .fo_ioctl = ptsdev_ioctl, .fo_poll = ptsdev_poll, + .fo_kqfilter = ptsdev_kqfilter, .fo_stat = ptsdev_stat, .fo_close = ptsdev_close, .fo_flags = DFLAG_PASSABLE, @@ -493,6 +591,7 @@ ptsdrv_outwakeup(struct tty *tp) cv_broadcast(&psc->pts_outwait); selwakeup(&psc->pts_outpoll); + KNOTE_LOCKED(&psc->pts_outpoll.si_note, 0); } static void @@ -502,6 +601,7 @@ ptsdrv_inwakeup(struct tty *tp) cv_broadcast(&psc->pts_inwait); selwakeup(&psc->pts_inpoll); + KNOTE_LOCKED(&psc->pts_inpoll.si_note, 0); } static int @@ -566,6 +666,9 @@ ptsdrv_free(void *softc) chgptscnt(psc->pts_uidinfo, -1, 0); uifree(psc->pts_uidinfo); + knlist_destroy(&psc->pts_inpoll.si_note); + knlist_destroy(&psc->pts_outpoll.si_note); + #ifdef PTS_EXTERNAL /* Destroy master device as well. */ if (psc->pts_cdev != NULL) @@ -618,6 +721,8 @@ pts_alloc(int fflags, struct thread *td, struct file *fp) uihold(uid); tp = tty_alloc(&pts_class, psc, NULL); + knlist_init(&psc->pts_inpoll.si_note, tp->t_mtx, NULL, NULL, NULL); + knlist_init(&psc->pts_outpoll.si_note, tp->t_mtx, NULL, NULL, NULL); /* Expose the slave device as well. */ tty_makedev(tp, td->td_ucred, "pts/%u", psc->pts_unit); @@ -656,6 +761,8 @@ pts_alloc_external(int fflags, struct thread *td, struct file *fp, uihold(uid); tp = tty_alloc(&pts_class, psc, NULL); + knlist_init(&psc->pts_inpoll.si_note, tp->t_mtx, NULL, NULL, NULL); + knlist_init(&psc->pts_outpoll.si_note, tp->t_mtx, NULL, NULL, NULL); /* Expose the slave device as well. */ tty_makedev(tp, td->td_ucred, "%s", name); |