Add uhidev_set_report_dev() allowing usb drivers to early on install a
authoranton <anton@openbsd.org>
Thu, 4 Feb 2021 16:18:34 +0000 (16:18 +0000)
committeranton <anton@openbsd.org>
Thu, 4 Feb 2021 16:18:34 +0000 (16:18 +0000)
handler for a specific report id. Needed by an upcoming driver in order
to communicate with the device already in the attach routine.

ok mglocker@ as part of a larger diff

sys/dev/usb/uhidev.c
sys/dev/usb/uhidev.h

index 16f4407..9915b66 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: uhidev.c,v 1.85 2021/01/29 16:59:41 sthen Exp $       */
+/*     $OpenBSD: uhidev.c,v 1.86 2021/02/04 16:18:34 anton Exp $       */
 /*     $NetBSD: uhidev.c,v 1.14 2003/03/11 16:44:00 augustss Exp $     */
 
 /*
@@ -256,8 +256,13 @@ uhidev_attach(struct device *parent, struct device *self, void *aux)
        /* Look for a driver claiming all report IDs first. */
        dev = config_found_sm(self, &uha, NULL, uhidevsubmatch);
        if (dev != NULL) {
-               for (repid = 0; repid < nrepid; repid++)
-                       sc->sc_subdevs[repid] = (struct uhidev *)dev;
+               for (repid = 0; repid < nrepid; repid++) {
+                       /*
+                        * Could already be assigned by uhidev_set_report_dev().
+                        */
+                       if (sc->sc_subdevs[repid] == NULL)
+                               sc->sc_subdevs[repid] = (struct uhidev *)dev;
+               }
                return;
        }
 
@@ -270,7 +275,9 @@ uhidev_attach(struct device *parent, struct device *self, void *aux)
 
                uha.reportid = repid;
                dev = config_found_sm(self, &uha, uhidevprint, uhidevsubmatch);
-               sc->sc_subdevs[repid] = (struct uhidev *)dev;
+               /* Could already be assigned by uhidev_set_report_dev(). */
+               if (sc->sc_subdevs[repid] == NULL)
+                       sc->sc_subdevs[repid] = (struct uhidev *)dev;
        }
 }
 
@@ -992,3 +999,15 @@ uhidev_clear_iface_eps(struct uhidev_softc *sc, struct usbd_interface *iface)
 bad:
        printf("%s: clear endpoints failed!\n", __func__);
 }
+
+int
+uhidev_set_report_dev(struct uhidev_softc *sc, struct uhidev *dev, int repid)
+{
+       if ((dev->sc_state & UHIDEV_OPEN) == 0)
+               return ENODEV;
+       if (repid >= sc->sc_nrepid)
+               return EINVAL;
+
+       sc->sc_subdevs[repid] = dev;
+       return 0;
+}
index 16657f1..5caba3d 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: uhidev.h,v 1.25 2018/08/25 18:32:05 jcs Exp $ */
+/*     $OpenBSD: uhidev.h,v 1.26 2021/02/04 16:18:34 anton Exp $       */
 /*     $NetBSD: uhidev.h,v 1.3 2002/10/08 09:56:17 dan Exp $   */
 
 /*
@@ -95,3 +95,4 @@ int uhidev_get_report(struct uhidev_softc *, int, int, void *, int);
 int uhidev_get_report_async(struct uhidev_softc *, int, int, void *, int,
     void *, void (*)(void *, int, void *, int));
 usbd_status uhidev_write(struct uhidev_softc *, void *, int);
+int uhidev_set_report_dev(struct uhidev_softc *, struct uhidev *, int);