: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 <[EMAIL PROTECTED]>
:# 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(device_get_unit(sc->sc_dev), 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 &= ~UGEN_ASLP;
:                       DPRINTFN(5, ("ugenread: woke, error=%d\n", error));
:                       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 &= ~UGEN_ASLP;
:                       DPRINTFN(5, ("ugenread: woke, error=%d\n", error));
:                       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(dev));
:+
:+      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(dev));
: 
:+      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(device_get_unit(sc->sc_dev), 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(dev));
:+      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(dev));
: 
:-      if (sc->sc_dying)
:-              return (EIO);
:-
:-      /* XXX always IN */
:-      sce = &sc->sc_endpoints[UGENENDPOINT(dev)][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(dev)][IN];
:+      sce_out = &sc->sc_endpoints[UGENENDPOINT(dev)][OUT];
:+      edesc = (sce_in->edesc != NULL) ? sce_in->edesc : sce_out->edesc;
:+      KASSERT(edesc != NULL, ("ugenpoll: NULL edesc"));
:+
:+      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 
                                        <[EMAIL PROTECTED]>

Reply via email to