diff options
author | 2003-06-27 16:57:14 +0000 | |
---|---|---|
committer | 2003-06-27 16:57:14 +0000 | |
commit | b6e65ec1433db2b0c4ff8b8ab6b603296818ea96 (patch) | |
tree | 3231b7ead41995af536cd5352f806a5936d4b11c /sys/dev/usb/ugen.c | |
parent | filter event that simulates seltrue(). From NetBSD (diff) | |
download | wireguard-openbsd-b6e65ec1433db2b0c4ff8b8ab6b603296818ea96.tar.xz wireguard-openbsd-b6e65ec1433db2b0c4ff8b8ab6b603296818ea96.zip |
kqueue support for various usb devices including: usb, uhid, ugen,
and uscanner
From NetBSD
Diffstat (limited to 'sys/dev/usb/ugen.c')
-rw-r--r-- | sys/dev/usb/ugen.c | 130 |
1 files changed, 128 insertions, 2 deletions
diff --git a/sys/dev/usb/ugen.c b/sys/dev/usb/ugen.c index b723a308f15..92ae94c3158 100644 --- a/sys/dev/usb/ugen.c +++ b/sys/dev/usb/ugen.c @@ -1,5 +1,5 @@ -/* $OpenBSD: ugen.c,v 1.27 2003/05/07 04:33:33 deraadt Exp $ */ -/* $NetBSD: ugen.c,v 1.62 2002/10/23 09:13:59 jdolecek Exp $ */ +/* $OpenBSD: ugen.c,v 1.28 2003/06/27 16:57:14 nate Exp $ */ +/* $NetBSD: ugen.c,v 1.63 2002/11/26 18:49:48 christos Exp $ */ /* $FreeBSD: src/sys/dev/usb/ugen.c,v 1.26 1999/11/17 22:33:41 n_hibma Exp $ */ /* @@ -1350,6 +1350,132 @@ ugenpoll(dev_t dev, int events, usb_proc_ptr p) return (revents); } +Static void filt_ugenrdetach(struct knote *); +Static int filt_ugenread_intr(struct knote *, long); +Static int filt_ugenread_isoc(struct knote *, long); +int ugenkqfilter(dev_t, struct knote *); + +Static void +filt_ugenrdetach(struct knote *kn) +{ + struct ugen_endpoint *sce = (void *)kn->kn_hook; + int s; + + s = splusb(); + SLIST_REMOVE(&sce->rsel.sel_klist, kn, knote, kn_selnext); + splx(s); +} + +Static int +filt_ugenread_intr(struct knote *kn, long hint) +{ + struct ugen_endpoint *sce = (void *)kn->kn_hook; + + kn->kn_data = sce->q.c_cc; + return (kn->kn_data > 0); +} + +Static int +filt_ugenread_isoc(struct knote *kn, long hint) +{ + struct ugen_endpoint *sce = (void *)kn->kn_hook; + + if (sce->cur == sce->fill) + return (0); + + if (sce->cur < sce->fill) + kn->kn_data = sce->fill - sce->cur; + else + kn->kn_data = (sce->limit - sce->cur) + + (sce->fill - sce->ibuf); + + return (1); +} + +Static struct filterops ugenread_intr_filtops = + { 1, NULL, filt_ugenrdetach, filt_ugenread_intr }; + +Static struct filterops ugenread_isoc_filtops = + { 1, NULL, filt_ugenrdetach, filt_ugenread_isoc }; + +Static struct filterops ugen_seltrue_filtops = + { 1, NULL, filt_ugenrdetach, filt_seltrue }; + +int +ugenkqfilter(dev_t dev, struct knote *kn) +{ + struct ugen_softc *sc; + struct ugen_endpoint *sce; + struct klist *klist; + int s; + + USB_GET_SC(ugen, UGENUNIT(dev), sc); + + if (sc->sc_dying) + return (1); + + /* XXX always IN */ + sce = &sc->sc_endpoints[UGENENDPOINT(dev)][IN]; + if (sce == NULL) + return (1); + + switch (kn->kn_filter) { + case EVFILT_READ: + klist = &sce->rsel.sel_klist; + switch (sce->edesc->bmAttributes & UE_XFERTYPE) { + case UE_INTERRUPT: + kn->kn_fop = &ugenread_intr_filtops; + break; + case UE_ISOCHRONOUS: + kn->kn_fop = &ugenread_isoc_filtops; + break; + case UE_BULK: + /* + * We have no easy way of determining if a read will + * yield any data or a write will happen. + * So, emulate "seltrue". + */ + kn->kn_fop = &ugen_seltrue_filtops; + break; + default: + return (1); + } + break; + + case EVFILT_WRITE: + klist = &sce->rsel.sel_klist; + switch (sce->edesc->bmAttributes & UE_XFERTYPE) { + case UE_INTERRUPT: + case UE_ISOCHRONOUS: + /* XXX poll doesn't support this */ + return (1); + + case UE_BULK: + /* + * We have no easy way of determining if a read will + * yield any data or a write will happen. + * So, emulate "seltrue". + */ + kn->kn_fop = &ugen_seltrue_filtops; + break; + default: + return (1); + } + break; + + default: + return (1); + } + + kn->kn_hook = (void *)sce; + + s = splusb(); + SLIST_INSERT_HEAD(klist, kn, kn_selnext); + splx(s); + + return (0); +} + #if defined(__FreeBSD__) DRIVER_MODULE(ugen, uhub, ugen_driver, ugen_devclass, usbd_driver_load, 0); #endif |