Project

General

Profile

Actions

Bug #994

closed

ugen(4) fixes

Added by hasso almost 16 years ago. Updated over 15 years ago.

Status:
Closed
Priority:
Low
Assignee:
-
Category:
-
Target version:
-
Start date:
Due date:
% Done:

0%

Estimated time:

Description

Attached patch contains some assorted fixes for ugen(4) from FreeBSD. It
should be quite straightforward and shouldn't break anything, but please
test and/or review before I'm going to commit this.


Files

ugen-fixes.patch (7.93 KB) ugen-fixes.patch hasso, 04/28/2008 02:44 PM
Actions #1

Updated by dillon almost 16 years ago

:Attached patch contains some assorted fixes for ugen(4) from FreeBSD. It
:should be quite straightforward and shouldn't break anything, but please
:test and/or review before I'm going to commit this.
:
:--
:Hasso Tepper

Those IO_NDELAY > O_NONBLOCK changes look wrong.  That flag is
the ap
>a_ioflag. Non blocking mode is passed as IO_NDELAY.
DragonFly deals with non-blocking I/O differently from FreeBSD.
DragonFly allows non-blocking mode to be controlled on a per-system-call
basis and folds all the various ways of turning on nonblocking mode
into the IO_NDELAY flag to the fileops read and write functions.
-Matt

:--Boundary-00=_PEeFIXgOPpnMVqd
:Content-Type: text/x-diff;
: charset="iso 8859-13";
: name="ugen-fixes.patch"
:Content-Transfer-Encoding: 7bit
:Content-Disposition: attachment;
: filename="ugen-fixes.patch"
:
:# HG changeset patch
:# User Hasso Tepper <>
:# Date 1209385630 10800
:# Branch HEAD
:# Node ID 172a4bc22c661b8a202e4575f8367710897275aa
:# Parent 370bed0112470e3f559bc0051d719faba980e22a
:[mq]: ugen-fixes.patch
:
:diff --git a/sys/dev/usbmisc/ugen/ugen.c b/sys/dev/usbmisc/ugen/ugen.c
:--
a/sys/dev/usbmisc/ugen/ugen.c
:+++ b/sys/dev/usbmisc/ugen/ugen.c
:@ -250,6 +250,7 @
: make_dev(&ugen_ops, UGENMINOR, 0),
: UID_ROOT, GID_OPERATOR, 0644, "%s", device_get_nameunit(sc->sc_dev));
:
:+ usbd_add_drv_event(USB_EVENT_DRIVER_ATTACH, sc->sc_udev, sc->sc_dev);
: return 0;
: }
:
:@ -294,8 +295,11 @
: static void
: ugen_destroy_devnodes(struct ugen_softc sc)
: {
:- int endptno;
:+ int endptno, prev_sc_dying;
: cdev_t dev;
:+
:+ prev_sc_dying = sc->sc_dying;
:+ sc->sc_dying = 1;
:
: /
destroy all devices for the other (existing) endpoints as well /
: for (endptno = 1; endptno < USB_MAX_ENDPOINTS; endptno++) {
:@ -321,6 +325,7 @
: }
: }
: }
:+ sc->sc_dying = prev_sc_dying;
: }
:
: static int
:@ -413,7 +418,7 @
: DPRINTFN(5, ("ugenopen: flag=%d, mode=%d, unit=%d endpt=%d\n",
: ap->a_oflags, ap->a_devtype, unit, endpt));
:
:- if (sc NULL || sc->sc_dying)
:+ if (sc->sc_dying)
: return (ENXIO);
:
: if (sc->sc_is_open[endpt])
:@ -567,7 +572,7 @
: if (!(ap->a_fflag & (dir OUT ? FWRITE : FREAD)))
: continue;
: sce = &sc->sc_endpoints[endpt][dir];
:- if (sce NULL || sce->pipeh NULL)
:+ if (sce->pipeh == NULL)
: continue;
: DPRINTFN(5, ("ugenclose: endpt=%d dir=%d sce=%p\n",
: endpt, dir, sce));
:@ -619,9 +624,7 @
: if (endpt USB_CONTROL_ENDPOINT)
: return (ENODEV);
:
:- if (sce NULL)
:- return (EINVAL);
:-
:+#ifdef DIAGNOSTIC
: if (sce->edesc == NULL) {
: kprintf("ugenread: no edesc\n");
: return (EIO);
:@ -630,6 +633,7 @
: kprintf("ugenread: no pipe\n");
: return (EIO);
: }
:+#endif
:
: buf = getugenbuf(ugen_bufsize, &ugen_bbsize);
:
:@ -638,21 +642,25 @
: /
Block until activity occurred. /
: crit_enter();
: while (sce->q.c_cc == 0) {
:- if (flag & IO_NDELAY) {
:+ if (flag & O_NONBLOCK) {
: crit_exit();
: error = EWOULDBLOCK;
: goto done;
: }
: sce->state |= UGEN_ASLP;
: DPRINTFN(5, ("ugenread: sleep on p\n", sce));
:- error = tsleep(sce, PCATCH, "ugenri", 0);
:+ error = tsleep(sce, PCATCH, "ugenri",
:+ (sce->timeout * hz + 999) / 1000);
:+ sce->state x%x
= ~UGEN_ASLP;
: DPRINTFN);
: if (sc->sc_dying)
: error = EIO;
:- if (error) {
:- sce->state &= ~UGEN_ASLP;
:+ if (error == EAGAIN) {
:+ error = 0; /
timeout, return 0 bytes /
: break;
: }
:+ if (error)
:+ break;
: }
: crit_exit();
:
:@ -705,25 +713,29 @
: case UE_ISOCHRONOUS:
: crit_enter();
: while (sce->cur == sce->fill) {
:- if (flag & IO_NDELAY) {
:+ if (flag & O_NONBLOCK) {
: crit_exit();
: error = EWOULDBLOCK;
: goto done;
: }
: sce->state |= UGEN_ASLP;
: DPRINTFN(5, ("ugenread: sleep on p\n", sce));
:- error = tsleep(sce, PCATCH, "ugenri", 0);
:+ error = tsleep(sce, PCATCH, "ugenri",
:+ (sce->timeout * hz + 999) / 1000);
:+ sce->state x%x
= ~UGEN_ASLP;
: DPRINTFN);
: if (sc->sc_dying)
: error = EIO;
:- if (error) {
:- sce->state &= ~UGEN_ASLP;
:+ if (error == EAGAIN) {
:+ error = 0; /
timeout, return 0 bytes /
: break;
: }
:+ if (error)
:+ break;
: }
:
: while (sce->cur != sce->fill && uio->uio_resid > 0 && !error) {
:- if(sce->fill > sce->cur)
:+ if (sce->fill > sce->cur)
: n = min(sce->fill - sce->cur, uio->uio_resid);
: else
: n = min(sce->limit - sce->cur, uio->uio_resid);
:@ -760,6 +772,9 @
: int error;
:
: sc = devclass_get_softc(ugen_devclass, UGENUNIT);
:+
:+ if (sc->sc_dying)
:+ return (EIO);
:
: sc->sc_refcnt++;
: error = ugen_do_read(sc, endpt, ap->a_uio, ap->a_ioflag);
:@ -787,9 +802,7 @
: if (endpt USB_CONTROL_ENDPOINT)
: return (ENODEV);
:
:- if (sce NULL)
:- return (EINVAL);
:-
:+#ifdef DIAGNOSTIC
: if (sce->edesc == NULL) {
: kprintf("ugenwrite: no edesc\n");
: return (EIO);
:@ -798,6 +811,7 @
: kprintf("ugenwrite: no pipe\n");
: return (EIO);
: }
:+#endif
:
: buf = getugenbuf(ugen_bufsize, &ugen_bbsize);
:
:@ -872,6 +886,9 @
:
: sc = devclass_get_softc(ugen_devclass, UGENUNIT);
:
:+ if (sc->sc_dying)
:+ return (EIO);
:+
: sc->sc_refcnt++;
: error = ugen_do_write(sc, endpt, ap->a_uio, ap->a_ioflag);
: if (--sc->sc_refcnt < 0)
:@ -895,6 +912,7 @
: sce = &sc->sc_endpoints[i][dir];
: if (sce && sce->pipeh)
: usbd_abort_pipe(sce->pipeh);
:+ selwakeup(&sce->rsel);
: }
: }
: crit_enter();
:@ -911,6 +929,7 @
: ugen_destroy_devnodes(sc);
: dev_ops_remove(&ugen_ops,
: UGENUNITMASK, UGENMINOR, 0));
:+ usbd_add_drv_event(USB_EVENT_DRIVER_DETACH, sc->sc_udev, sc->sc_dev);
: return (0);
: }
:
:@ -1146,8 +1165,6 @
: if (endpt == USB_CONTROL_ENDPOINT)
: return (EINVAL);
: sce = &sc->sc_endpoints[endpt][IN];
:- if (sce NULL)
:- return (EINVAL);
:
: if (sce->pipeh NULL) {
: kprintf("ugenioctl: USB_SET_SHORT_XFER, no pipe\n");
:@ -1161,8 +1178,8 @
: return (0);
: case USB_SET_TIMEOUT:
: sce = &sc->sc_endpoints[endpt][IN];
:- if (sce == NULL)
:- return (EINVAL);
:+ sce->timeout = *(int *)addr;
:+ sce = &sc->sc_endpoints[endpt][OUT];
: sce->timeout = *(int *)addr;
: return (0);
: default:
:@ -1397,6 +1414,8 @
: int error;
:
: sc = devclass_get_softc(ugen_devclass, UGENUNIT);
:+ if (sc->sc_dying)
:+ return (EIO);
:
: sc->sc_refcnt++;
: error = ugen_do_ioctl(sc, endpt, ap->a_cmd, ap->a_data, ap->a_fflag);
:@ -1410,44 +1429,61 @
: {
: cdev_t dev = ap->a_head.a_dev;
: struct ugen_softc *sc;
:- struct ugen_endpoint *sce;
:+ struct ugen_endpoint *sce_in, *sce_out;
:+ usb_endpoint_descriptor_t *edesc;
: int revents = 0;
:
: sc = devclass_get_softc(ugen_devclass, UGENUNIT);
:
:- if (sc->sc_dying)
:- return (EIO);
:-
:- /
XXX always IN /
:- sce = &sc->sc_endpoints[UGENENDPOINT][IN];
:- if (sce NULL)
:- return (EINVAL);
:-
:- if (!sce->edesc) {
:- kprintf("ugenpoll: no edesc\n");
:- return (EIO);
:- }
:- if (!sce->pipeh) {
:- kprintf("ugenpoll: no pipe\n");
:- return (EIO);
:+ if (sc->sc_dying) {
:+ return ((ap->a_events & (POLLIN | POLLOUT | POLLRDNORM |
:+ POLLWRNORM)) | POLLHUP);
: }
:
:+ /
Do not allow to poll a control endpoint */
:+ if (UGENENDPOINT(dev) USB_CONTROL_ENDPOINT) {
:+ return (ap->a_events & (POLLIN | POLLOUT | POLLRDNORM |
:+ POLLWRNORM));
:+ }
:+
:+ sce_in = &sc->sc_endpoints[UGENENDPOINT][IN];
:+ sce_out = &sc->sc_endpoints[UGENENDPOINT][OUT];
:+ edesc = (sce_in->edesc != NULL) ? sce_in->edesc : sce_out->edesc;
:+ KASSERT);
:+
:+ if (sce_in->edesc NULL || sce_in->pipeh NULL)
:+ sce_in = NULL;
:+ if (sce_out->edesc NULL || sce_out->pipeh NULL)
:+ sce_out = NULL;
:+
: crit_enter();
:- switch (sce->edesc->bmAttributes & UE_XFERTYPE) {
:+ switch (edesc->bmAttributes & UE_XFERTYPE) {
: case UE_INTERRUPT:
:- if (ap->a_events & (POLLIN | POLLRDNORM)) {
:- if (sce->q.c_cc > 0)
:+ if (sce_in != NULL && (ap->a_events & (POLLIN | POLLRDNORM))) {
:+ if (sce_in->q.c_cc > 0)
: revents |= ap->a_events & (POLLIN | POLLRDNORM);
: else
:- selrecord(curthread, &sce->rsel);
:+ selrecord(curthread, &sce_in->rsel);
:+ }
:+ if (sce_out != NULL && (ap->a_events & (POLLOUT | POLLWRNORM))) {
:+ if (sce_out->q.c_cc > 0)
:+ revents |= ap->a_events & (POLLOUT | POLLWRNORM);
:+ else
:+ selrecord(curthread, &sce_out->rsel);
: }
: break;
: case UE_ISOCHRONOUS:
:- if (ap->a_events & (POLLIN | POLLRDNORM)) {
:- if (sce->cur != sce->fill)
:+ if (sce_in != NULL && (ap->a_events & (POLLIN | POLLRDNORM))) {
:+ if (sce_in->cur != sce_in->fill)
: revents |= ap->a_events & (POLLIN | POLLRDNORM);
: else
:- selrecord(curthread, &sce->rsel);
:+ selrecord(curthread, &sce_in->rsel);
:+ }
:+ if (sce_out != NULL && (ap->a_events & (POLLOUT | POLLWRNORM))) {
:+ if (sce_out->cur != sce_out->fill)
:+ revents |= ap->a_events & (POLLOUT | POLLWRNORM);
:+ else
:+ selrecord(curthread, &sce_out->rsel);
: }
: break;
: case UE_BULK:
:
:--Boundary-00=_PEeFIXgOPpnMVqd--
:

Matthew Dillon 
&lt;&gt;
Actions #2

Updated by hasso almost 16 years ago

Hmmm. It's a second time you have to say to me it AFAIK ... I hope I'll
learn from it this time ;).

Actions

Also available in: Atom PDF