summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNathan Binkert <nate@cvs.openbsd.org>2003-06-27 16:57:15 +0000
committerNathan Binkert <nate@cvs.openbsd.org>2003-06-27 16:57:15 +0000
commitf3f9a16fca639a1fcc8b608d0f27d970daf174f4 (patch)
tree05af824bdd5b4ea18ff85c992217c27d77d86b3e
parentc1f3988c88439ff28f11b5818dfb7227817611ef (diff)
kqueue support for various usb devices including: usb, uhid, ugen,
and uscanner From NetBSD
-rw-r--r--sys/arch/i386/i386/conf.c4
-rw-r--r--sys/arch/macppc/macppc/conf.c4
-rw-r--r--sys/arch/sparc64/sparc64/conf.c4
-rw-r--r--sys/dev/usb/ugen.c130
-rw-r--r--sys/dev/usb/uhid.c70
-rw-r--r--sys/dev/usb/usb.c57
-rw-r--r--sys/dev/usb/usb_port.h4
-rw-r--r--sys/dev/usb/uscanner.c54
-rw-r--r--sys/sys/conf.h11
9 files changed, 322 insertions, 16 deletions
diff --git a/sys/arch/i386/i386/conf.c b/sys/arch/i386/i386/conf.c
index 85189f95e66..a8d775969d8 100644
--- a/sys/arch/i386/i386/conf.c
+++ b/sys/arch/i386/i386/conf.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: conf.c,v 1.102 2003/05/14 00:20:37 tedu Exp $ */
+/* $OpenBSD: conf.c,v 1.103 2003/06/27 16:57:14 nate Exp $ */
/* $NetBSD: conf.c,v 1.75 1996/05/03 19:40:20 christos Exp $ */
/*
@@ -291,7 +291,7 @@ struct cdevsw cdevsw[] =
cdev_usbdev_init(NUHID,uhid), /* 62: USB generic HID */
cdev_usbdev_init(NUGEN,ugen), /* 63: USB generic driver */
cdev_ulpt_init(NULPT,ulpt), /* 64: USB printers */
- cdev_usbdev_init(NURIO,urio), /* 65: USB Diamond Rio 500 */
+ cdev_urio_init(NURIO,urio), /* 65: USB Diamond Rio 500 */
cdev_tty_init(NUCOM,ucom), /* 66: USB tty */
cdev_mouse_init(NWSKBD, wskbd), /* 67: keyboards */
cdev_mouse_init(NWSMOUSE, /* 68: mice */
diff --git a/sys/arch/macppc/macppc/conf.c b/sys/arch/macppc/macppc/conf.c
index 30a3d334e31..2943b3f124d 100644
--- a/sys/arch/macppc/macppc/conf.c
+++ b/sys/arch/macppc/macppc/conf.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: conf.c,v 1.22 2003/05/14 00:20:37 tedu Exp $ */
+/* $OpenBSD: conf.c,v 1.23 2003/06/27 16:57:14 nate Exp $ */
/*
* Copyright (c) 1997 Per Fogelstrom
@@ -217,7 +217,7 @@ struct cdevsw cdevsw[] = {
cdev_usbdev_init(NUHID,uhid), /* 62: USB generic HID */
cdev_usbdev_init(NUGEN,ugen), /* 63: USB generic driver */
cdev_ulpt_init(NULPT,ulpt), /* 64: USB printers */
- cdev_usbdev_init(NURIO,urio), /* 65: USB Diamond Rio 500 */
+ cdev_urio_init(NURIO,urio), /* 65: USB Diamond Rio 500 */
cdev_tty_init(NUCOM,ucom), /* 66: USB tty */
cdev_wsdisplay_init(NWSDISPLAY, /* 67: frame buffers, etc. */
wsdisplay),
diff --git a/sys/arch/sparc64/sparc64/conf.c b/sys/arch/sparc64/sparc64/conf.c
index 006f60a3aad..ea5151d85d3 100644
--- a/sys/arch/sparc64/sparc64/conf.c
+++ b/sys/arch/sparc64/sparc64/conf.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: conf.c,v 1.35 2003/06/02 23:27:56 millert Exp $ */
+/* $OpenBSD: conf.c,v 1.36 2003/06/27 16:57:14 nate Exp $ */
/* $NetBSD: conf.c,v 1.17 2001/03/26 12:33:26 lukem Exp $ */
/*
@@ -258,7 +258,7 @@ struct cdevsw cdevsw[] =
cdev_usbdev_init(NUHID,uhid), /* 91: USB generic HID */
cdev_usbdev_init(NUGEN,ugen), /* 92: USB generic driver */
cdev_ulpt_init(NULPT,ulpt), /* 93: USB printers */
- cdev_usbdev_init(NURIO,urio), /* 94: USB Diamond Rio 500 */
+ cdev_urio_init(NURIO,urio), /* 94: USB Diamond Rio 500 */
cdev_tty_init(NUCOM,ucom), /* 95: USB tty */
cdev_usbdev_init(NUSCANNER,uscanner), /* 96: USB scanners */
cdev_notdef(), /* 97 */
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
diff --git a/sys/dev/usb/uhid.c b/sys/dev/usb/uhid.c
index 3baa3601185..e168efb4d69 100644
--- a/sys/dev/usb/uhid.c
+++ b/sys/dev/usb/uhid.c
@@ -1,5 +1,5 @@
-/* $OpenBSD: uhid.c,v 1.25 2003/05/19 04:17:53 nate Exp $ */
-/* $NetBSD: uhid.c,v 1.55 2002/10/23 09:14:00 jdolecek Exp $ */
+/* $OpenBSD: uhid.c,v 1.26 2003/06/27 16:57:14 nate Exp $ */
+/* $NetBSD: uhid.c,v 1.57 2003/03/11 16:44:00 augustss Exp $ */
/*
* Copyright (c) 1998 The NetBSD Foundation, Inc.
@@ -564,3 +564,69 @@ uhidpoll(dev_t dev, int events, usb_proc_ptr p)
splx(s);
return (revents);
}
+
+Static void filt_uhidrdetach(struct knote *);
+Static int filt_uhidread(struct knote *, long);
+int uhidkqfilter(dev_t, struct knote *);
+
+Static void
+filt_uhidrdetach(struct knote *kn)
+{
+ struct uhid_softc *sc = (void *)kn->kn_hook;
+ int s;
+
+ s = splusb();
+ SLIST_REMOVE(&sc->sc_rsel.sel_klist, kn, knote, kn_selnext);
+ splx(s);
+}
+
+Static int
+filt_uhidread(struct knote *kn, long hint)
+{
+ struct uhid_softc *sc = (void *)kn->kn_hook;
+
+ kn->kn_data = sc->sc_q.c_cc;
+ return (kn->kn_data > 0);
+}
+
+Static struct filterops uhidread_filtops =
+ { 1, NULL, filt_uhidrdetach, filt_uhidread };
+
+Static struct filterops uhid_seltrue_filtops =
+ { 1, NULL, filt_uhidrdetach, filt_seltrue };
+
+int
+uhidkqfilter(dev_t dev, struct knote *kn)
+{
+ struct uhid_softc *sc;
+ struct klist *klist;
+ int s;
+
+ USB_GET_SC(uhid, UHIDUNIT(dev), sc);
+
+ if (sc->sc_dying)
+ return (EIO);
+
+ switch (kn->kn_filter) {
+ case EVFILT_READ:
+ klist = &sc->sc_rsel.sel_klist;
+ kn->kn_fop = &uhidread_filtops;
+ break;
+
+ case EVFILT_WRITE:
+ klist = &sc->sc_rsel.sel_klist;
+ kn->kn_fop = &uhid_seltrue_filtops;
+ break;
+
+ default:
+ return (1);
+ }
+
+ kn->kn_hook = (void *)sc;
+
+ s = splusb();
+ SLIST_INSERT_HEAD(klist, kn, kn_selnext);
+ splx(s);
+
+ return (0);
+}
diff --git a/sys/dev/usb/usb.c b/sys/dev/usb/usb.c
index 2d703ec4e33..1d6d14fa377 100644
--- a/sys/dev/usb/usb.c
+++ b/sys/dev/usb/usb.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: usb.c,v 1.23 2002/07/25 02:18:11 nate Exp $ */
+/* $OpenBSD: usb.c,v 1.24 2003/06/27 16:57:14 nate Exp $ */
/* $NetBSD: usb.c,v 1.53 2001/01/23 17:04:30 augustss Exp $ */
/* $FreeBSD: src/sys/dev/usb/usb.c,v 1.20 1999/11/17 22:33:46 n_hibma Exp $ */
@@ -515,6 +515,61 @@ usbpoll(dev_t dev, int events, struct proc *p)
}
}
+Static void filt_usbrdetach(struct knote *);
+Static int filt_usbread(struct knote *, long);
+int usbkqfilter(dev_t, struct knote *);
+
+Static void
+filt_usbrdetach(struct knote *kn)
+{
+ int s;
+
+ s = splusb();
+ SLIST_REMOVE(&usb_selevent.sel_klist, kn, knote, kn_selnext);
+ splx(s);
+}
+
+Static int
+filt_usbread(struct knote *kn, long hint)
+{
+
+ if (usb_nevents == 0)
+ return (0);
+
+ kn->kn_data = sizeof(struct usb_event);
+ return (1);
+}
+
+Static struct filterops usbread_filtops =
+ { 1, NULL, filt_usbrdetach, filt_usbread };
+
+int
+usbkqfilter(dev_t dev, struct knote *kn)
+{
+ struct klist *klist;
+ int s;
+
+ switch (kn->kn_filter) {
+ case EVFILT_READ:
+ if (minor(dev) != USB_DEV_MINOR)
+ return (1);
+ klist = &usb_selevent.sel_klist;
+ kn->kn_fop = &usbread_filtops;
+ break;
+
+ default:
+ return (1);
+ }
+
+ kn->kn_hook = NULL;
+
+ s = splusb();
+ SLIST_INSERT_HEAD(klist, kn, kn_selnext);
+ splx(s);
+
+ return (0);
+}
+
/* Explore device tree from the root. */
Static void
usb_discover(void *v)
diff --git a/sys/dev/usb/usb_port.h b/sys/dev/usb/usb_port.h
index 2bdd1ef61e4..2cccb2f543d 100644
--- a/sys/dev/usb/usb_port.h
+++ b/sys/dev/usb/usb_port.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: usb_port.h,v 1.41 2003/05/17 06:07:57 nate Exp $ */
+/* $OpenBSD: usb_port.h,v 1.42 2003/06/27 16:57:14 nate Exp $ */
/* $NetBSD: usb_port.h,v 1.44 2001/05/14 20:35:29 bouyer Exp $ */
/* $FreeBSD: src/sys/dev/usb/usb_port.h,v 1.21 1999/11/17 22:33:47 n_hibma Exp $ */
@@ -247,6 +247,8 @@ __CONCAT(dname,_detach)(self, flags) \
#define le16toh(x) letoh16(x)
#endif
+#define sel_klist si_note
+
#define usb_kthread_create1 kthread_create
#define usb_kthread_create kthread_create_deferred
diff --git a/sys/dev/usb/uscanner.c b/sys/dev/usb/uscanner.c
index fd26d49f9ba..193cb61e12e 100644
--- a/sys/dev/usb/uscanner.c
+++ b/sys/dev/usb/uscanner.c
@@ -1,5 +1,5 @@
-/* $OpenBSD: uscanner.c,v 1.15 2003/05/17 17:22:58 nate Exp $ */
-/* $NetBSD: uscanner.c,v 1.34 2002/10/23 09:14:03 jdolecek Exp $ */
+/* $OpenBSD: uscanner.c,v 1.16 2003/06/27 16:57:14 nate Exp $ */
+/* $NetBSD: uscanner.c,v 1.40 2003/01/27 00:32:44 wiz Exp $ */
/*
* Copyright (c) 2000 The NetBSD Foundation, Inc.
@@ -232,6 +232,8 @@ struct uscanner_softc {
int sc_bulkout_bufferlen;
int sc_bulkout_datalen;
+ struct selinfo sc_selq;
+
u_char sc_state;
#define USCANNER_OPEN 0x01 /* opened */
@@ -710,6 +712,54 @@ uscannerioctl(dev_t dev, u_long cmd, caddr_t addr, int flag, usb_proc_ptr p)
return (EINVAL);
}
+Static void filt_uscannerdetach(struct knote *);
+int uscannerkqfilter(dev_t, struct knote *);
+
+Static void
+filt_uscannerdetach(struct knote *kn)
+{
+ struct uscanner_softc *sc = (void *)kn->kn_hook;
+
+ SLIST_REMOVE(&sc->sc_selq.sel_klist, kn, knote, kn_selnext);
+}
+
+Static struct filterops uscanner_seltrue_filtops =
+ { 1, NULL, filt_uscannerdetach, filt_seltrue };
+
+int
+uscannerkqfilter(dev_t dev, struct knote *kn)
+{
+ struct uscanner_softc *sc;
+ struct klist *klist;
+
+ USB_GET_SC(uscanner, USCANNERUNIT(dev), sc);
+
+ if (sc->sc_dying)
+ return (1);
+
+ switch (kn->kn_filter) {
+ case EVFILT_READ:
+ case EVFILT_WRITE:
+ /*
+ * We have no easy way of determining if a read will
+ * yield any data or a write will happen.
+ * Pretend they will.
+ */
+ klist = &sc->sc_selq.sel_klist;
+ kn->kn_fop = &uscanner_seltrue_filtops;
+ break;
+
+ default:
+ return (1);
+ }
+
+ kn->kn_hook = (void *)sc;
+
+ SLIST_INSERT_HEAD(klist, kn, kn_selnext);
+
+ return (0);
+}
+
#if defined(__FreeBSD__)
DRIVER_MODULE(uscanner, uhub, uscanner_driver, uscanner_devclass, usbd_driver_load, 0);
#endif
diff --git a/sys/sys/conf.h b/sys/sys/conf.h
index e4b8174fe93..e05d9753879 100644
--- a/sys/sys/conf.h
+++ b/sys/sys/conf.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: conf.h,v 1.70 2003/06/14 23:14:30 mickey Exp $ */
+/* $OpenBSD: conf.h,v 1.71 2003/06/27 16:57:14 nate Exp $ */
/* $NetBSD: conf.h,v 1.33 1996/05/03 20:03:32 christos Exp $ */
/*-
@@ -408,11 +408,18 @@ void randomattach(void);
(dev_type_mmap((*))) enodev }
/* open, close, read, write, ioctl, select, nokqfilter */
-#define cdev_usbdev_init(c,n) { \
+#define cdev_urio_init(c,n) { \
dev_init(c,n,open), dev_init(c,n,close), dev_init(c,n,read), \
dev_init(c,n,write), dev_init(c,n,ioctl), (dev_type_stop((*))) enodev, \
0, dev_init(c,n,select), (dev_type_mmap((*))) enodev }
+/* open, close, read, write, ioctl, select, kqfilter */
+#define cdev_usbdev_init(c,n) { \
+ dev_init(c,n,open), dev_init(c,n,close), dev_init(c,n,read), \
+ dev_init(c,n,write), dev_init(c,n,ioctl), (dev_type_stop((*))) enodev, \
+ 0, dev_init(c,n,select), (dev_type_mmap((*))) enodev, D_KQFILTER, \
+ dev_init(c,n,kqfilter) }
+
/* open, close, init */
#define cdev_pci_init(c,n) { \
dev_init(c,n,open), dev_init(c,n,close), (dev_type_read((*))) enodev, \