summaryrefslogtreecommitdiffstats
path: root/sys/dev/usb/ugen.c
diff options
context:
space:
mode:
authornate <nate@openbsd.org>2003-06-27 16:57:14 +0000
committernate <nate@openbsd.org>2003-06-27 16:57:14 +0000
commitb6e65ec1433db2b0c4ff8b8ab6b603296818ea96 (patch)
tree3231b7ead41995af536cd5352f806a5936d4b11c /sys/dev/usb/ugen.c
parentfilter event that simulates seltrue(). From NetBSD (diff)
downloadwireguard-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.c130
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