Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src/sys/dev/usb uhidev(9): New uhidev_write_async.



details:   https://anonhg.NetBSD.org/src/rev/855c6263c2f9
branches:  trunk
changeset: 364536:855c6263c2f9
user:      riastradh <riastradh%NetBSD.org@localhost>
date:      Mon Mar 28 12:43:03 2022 +0000

description:
uhidev(9): New uhidev_write_async.

Like uhidev_write but issues the transfer asynchronously with a
callback.

Use it in ucycom(4).

Also, clear endpoint stalls asynchronously -- can't do them
synchronously in xfer callbacks which run at softint and therefore
can't wait in cv_wait as usbd_do_request does.

diffstat:

 sys/dev/usb/ucycom.c |  11 ++----
 sys/dev/usb/uhidev.c |  75 ++++++++++++++++++++++++++++++++++++++++++++++++++-
 sys/dev/usb/uhidev.h |   6 +++-
 3 files changed, 82 insertions(+), 10 deletions(-)

diffs (160 lines):

diff -r 9585c70dfa7f -r 855c6263c2f9 sys/dev/usb/ucycom.c
--- a/sys/dev/usb/ucycom.c      Mon Mar 28 12:42:54 2022 +0000
+++ b/sys/dev/usb/ucycom.c      Mon Mar 28 12:43:03 2022 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: ucycom.c,v 1.52 2022/03/28 12:42:54 riastradh Exp $    */
+/*     $NetBSD: ucycom.c,v 1.53 2022/03/28 12:43:03 riastradh Exp $    */
 
 /*
  * Copyright (c) 2005 The NetBSD Foundation, Inc.
@@ -38,7 +38,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: ucycom.c,v 1.52 2022/03/28 12:42:54 riastradh Exp $");
+__KERNEL_RCSID(0, "$NetBSD: ucycom.c,v 1.53 2022/03/28 12:43:03 riastradh Exp $");
 
 #ifdef _KERNEL_OPT
 #include "opt_usb.h"
@@ -592,11 +592,9 @@
        }
 #endif
        DPRINTFN(4,("ucycomstart: %d chars\n", len));
-       usbd_setup_xfer(sc->sc_hdev.sc_parent->sc_oxfer, sc, sc->sc_obuf,
-           sc->sc_olen, 0, USBD_NO_TIMEOUT, ucycomwritecb);
-
        /* What can we do on error? */
-       err = usbd_transfer(sc->sc_hdev.sc_parent->sc_oxfer);
+       err = uhidev_write_async(&sc->sc_hdev, sc->sc_obuf, sc->sc_olen, 0,
+           USBD_NO_TIMEOUT, ucycomwritecb, sc);
 
 #ifdef UCYCOM_DEBUG
        if (err != USBD_IN_PROGRESS)
@@ -621,7 +619,6 @@
 
        if (status) {
                DPRINTF(("ucycomwritecb: status=%d\n", status));
-               usbd_clear_endpoint_stall(sc->sc_hdev.sc_parent->sc_opipe);
                /* XXX we should restart after some delay. */
                goto error;
        }
diff -r 9585c70dfa7f -r 855c6263c2f9 sys/dev/usb/uhidev.c
--- a/sys/dev/usb/uhidev.c      Mon Mar 28 12:42:54 2022 +0000
+++ b/sys/dev/usb/uhidev.c      Mon Mar 28 12:43:03 2022 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: uhidev.c,v 1.83 2022/03/28 12:42:54 riastradh Exp $    */
+/*     $NetBSD: uhidev.c,v 1.84 2022/03/28 12:43:03 riastradh Exp $    */
 
 /*
  * Copyright (c) 2001, 2012 The NetBSD Foundation, Inc.
@@ -35,7 +35,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: uhidev.c,v 1.83 2022/03/28 12:42:54 riastradh Exp $");
+__KERNEL_RCSID(0, "$NetBSD: uhidev.c,v 1.84 2022/03/28 12:43:03 riastradh Exp $");
 
 #ifdef _KERNEL_OPT
 #include "opt_usb.h"
@@ -1025,3 +1025,74 @@
 out:   mutex_exit(&sc->sc_lock);
        return err;
 }
+
+static void
+uhidev_write_callback(struct usbd_xfer *xfer, void *cookie, usbd_status err)
+{
+       struct uhidev_softc *sc = cookie;
+       usbd_callback writecallback;
+       void *writecookie;
+
+       if (err) {
+               if (err != USBD_CANCELLED)
+                       usbd_clear_endpoint_stall_async(sc->sc_opipe);
+       }
+
+       mutex_enter(&sc->sc_lock);
+       KASSERT(sc->sc_writelock == (void *)1);
+       writecallback = sc->sc_writecallback;
+       writecookie = sc->sc_writecookie;
+       sc->sc_writereportid = -1;
+       sc->sc_writelock = NULL;
+       sc->sc_writecallback = NULL;
+       sc->sc_writecookie = NULL;
+       cv_broadcast(&sc->sc_cv);
+       mutex_exit(&sc->sc_lock);
+
+       (*writecallback)(xfer, writecookie, err);
+}
+
+usbd_status
+uhidev_write_async(struct uhidev *scd, void *data, int len, int flags,
+    int timo, usbd_callback writecallback, void *writecookie)
+{
+       struct uhidev_softc *sc = scd->sc_parent;
+       usbd_status err;
+
+       DPRINTF(("%s: data=%p, len=%d\n", __func__, data, len));
+
+       if (sc->sc_opipe == NULL)
+               return USBD_INVAL;
+
+       mutex_enter(&sc->sc_lock);
+       KASSERT(sc->sc_refcnt);
+       if (sc->sc_dying) {
+               err = USBD_IOERROR;
+               goto out;
+       }
+       if (sc->sc_writelock != NULL) {
+               err = USBD_IN_USE;
+               goto out;
+       }
+       sc->sc_writelock = (void *)1; /* XXX no lwp to attribute async xfer */
+       sc->sc_writereportid = scd->sc_report_id;
+       sc->sc_writecallback = writecallback;
+       sc->sc_writecookie = writecookie;
+       usbd_setup_xfer(sc->sc_oxfer, sc, data, len, flags, timo,
+           uhidev_write_callback);
+       err = usbd_transfer(sc->sc_oxfer);
+       switch (err) {
+       case USBD_IN_PROGRESS:
+               break;
+       case USBD_NORMAL_COMPLETION:
+               panic("unexpected normal completion of async xfer under lock");
+       default:                /* error */
+               sc->sc_writelock = NULL;
+               sc->sc_writereportid = -1;
+               sc->sc_writecallback = NULL;
+               sc->sc_writecookie = NULL;
+               cv_broadcast(&sc->sc_cv);
+       }
+out:   mutex_exit(&sc->sc_lock);
+       return err;
+}
diff -r 9585c70dfa7f -r 855c6263c2f9 sys/dev/usb/uhidev.h
--- a/sys/dev/usb/uhidev.h      Mon Mar 28 12:42:54 2022 +0000
+++ b/sys/dev/usb/uhidev.h      Mon Mar 28 12:43:03 2022 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: uhidev.h,v 1.22 2022/03/28 12:42:54 riastradh Exp $    */
+/*     $NetBSD: uhidev.h,v 1.23 2022/03/28 12:43:03 riastradh Exp $    */
 
 /*
  * Copyright (c) 2001 The NetBSD Foundation, Inc.
@@ -68,6 +68,8 @@
        struct usbd_pipe *sc_ipipe;     /* input interrupt pipe */
        struct usbd_pipe *sc_opipe;     /* output interrupt pipe */
        struct usbd_xfer *sc_oxfer;     /* write request */
+       usbd_callback sc_writecallback; /* async write request callback */
+       void *sc_writecookie;
 
        u_int sc_flags;
 #define UHIDEV_F_XB1   0x0001  /* Xbox 1 controller */
@@ -98,6 +100,8 @@
 usbd_status uhidev_set_report(struct uhidev *, int, void *, int);
 usbd_status uhidev_get_report(struct uhidev *, int, void *, int);
 usbd_status uhidev_write(struct uhidev *, void *, int);
+usbd_status uhidev_write_async(struct uhidev *, void *, int, int, int,
+    usbd_callback, void *);
 
 #define        UHIDEV_OSIZE    64
 



Home | Main Index | Thread Index | Old Index