diff options
author | Nathan Binkert <nate@cvs.openbsd.org> | 2003-06-27 16:57:15 +0000 |
---|---|---|
committer | Nathan Binkert <nate@cvs.openbsd.org> | 2003-06-27 16:57:15 +0000 |
commit | f3f9a16fca639a1fcc8b608d0f27d970daf174f4 (patch) | |
tree | 05af824bdd5b4ea18ff85c992217c27d77d86b3e | |
parent | c1f3988c88439ff28f11b5818dfb7227817611ef (diff) |
kqueue support for various usb devices including: usb, uhid, ugen,
and uscanner
From NetBSD
-rw-r--r-- | sys/arch/i386/i386/conf.c | 4 | ||||
-rw-r--r-- | sys/arch/macppc/macppc/conf.c | 4 | ||||
-rw-r--r-- | sys/arch/sparc64/sparc64/conf.c | 4 | ||||
-rw-r--r-- | sys/dev/usb/ugen.c | 130 | ||||
-rw-r--r-- | sys/dev/usb/uhid.c | 70 | ||||
-rw-r--r-- | sys/dev/usb/usb.c | 57 | ||||
-rw-r--r-- | sys/dev/usb/usb_port.h | 4 | ||||
-rw-r--r-- | sys/dev/usb/uscanner.c | 54 | ||||
-rw-r--r-- | sys/sys/conf.h | 11 |
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, \ |