Define a USB quirk for devices that need to keep their pipes open at
authorjcs <jcs@openbsd.org>
Wed, 24 Mar 2021 02:49:57 +0000 (02:49 +0000)
committerjcs <jcs@openbsd.org>
Wed, 24 Mar 2021 02:49:57 +0000 (02:49 +0000)
all times, before the device is enabled and after the device is
disabled by wscons.

This was originally needed by umt for the Microsoft Surface Type
Cover to avoid it resetting (or at least detaching and reattaching)
when the touchpad was touched while at the console.

A similar problem occurs with the Pinebook Pro's keyboard when
switching from X to the console due to the touchpad getting
disabled, so add it to ums as well.

with and ok kurt

sys/dev/usb/ums.c
sys/dev/usb/umt.c
sys/dev/usb/usb_quirks.c
sys/dev/usb/usb_quirks.h

index 15c777c..bd34bce 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: ums.c,v 1.47 2021/01/29 16:59:41 sthen Exp $ */
+/*     $OpenBSD: ums.c,v 1.48 2021/03/24 02:49:57 jcs Exp $ */
 /*     $NetBSD: ums.c,v 1.60 2003/03/11 16:44:00 augustss Exp $        */
 
 /*
@@ -58,6 +58,7 @@
 struct ums_softc {
        struct uhidev   sc_hdev;
        struct hidms    sc_ms;
+       uint32_t        sc_quirks;
 };
 
 void ums_intr(struct uhidev *addr, void *ibuf, u_int len);
@@ -122,7 +123,7 @@ ums_attach(struct device *parent, struct device *self, void *aux)
        struct usb_attach_arg *uaa = uha->uaa;
        int size, repid;
        void *desc;
-       u_int32_t quirks, qflags = 0;
+       u_int32_t qflags = 0;
 
        sc->sc_hdev.sc_intr = ums_intr;
        sc->sc_hdev.sc_parent = uha->parent;
@@ -131,7 +132,7 @@ ums_attach(struct device *parent, struct device *self, void *aux)
 
        usbd_set_idle(uha->parent->sc_udev, uha->parent->sc_ifaceno, 0, 0);
 
-       quirks = usbd_get_quirks(sc->sc_hdev.sc_udev)->uq_flags;
+       sc->sc_quirks = usbd_get_quirks(sc->sc_hdev.sc_udev)->uq_flags;
        uhidev_get_report_desc(uha->parent, &desc, &size);
 
        if (uaa->vendor == USB_VENDOR_ELECOM)
@@ -142,15 +143,15 @@ ums_attach(struct device *parent, struct device *self, void *aux)
        sc->sc_hdev.sc_osize = hid_report_size(desc, size, hid_output, repid);
        sc->sc_hdev.sc_fsize = hid_report_size(desc, size, hid_feature, repid);
 
-       if (quirks & UQ_MS_REVZ)
+       if (sc->sc_quirks & UQ_MS_REVZ)
                qflags |= HIDMS_REVZ;
-       if (quirks & UQ_SPUR_BUT_UP)
+       if (sc->sc_quirks & UQ_SPUR_BUT_UP)
                qflags |= HIDMS_SPUR_BUT_UP;
-       if (quirks & UQ_MS_BAD_CLASS)
+       if (sc->sc_quirks & UQ_MS_BAD_CLASS)
                qflags |= HIDMS_MS_BAD_CLASS;
-       if (quirks & UQ_MS_LEADING_BYTE)
+       if (sc->sc_quirks & UQ_MS_LEADING_BYTE)
                qflags |= HIDMS_LEADINGBYTE;
-       if (quirks & UQ_MS_VENDOR_BUTTONS)
+       if (sc->sc_quirks & UQ_MS_VENDOR_BUTTONS)
                qflags |= HIDMS_VENDOR_BUTTONS;
 
        if (hidms_setup(self, ms, qflags, uha->reportid, desc, size) != 0)
@@ -177,6 +178,13 @@ ums_attach(struct device *parent, struct device *self, void *aux)
        }
 
        hidms_attach(ms, &ums_accessops);
+
+       if (sc->sc_quirks & UQ_ALWAYS_OPEN) {
+               /* open uhidev and keep it open */
+               ums_enable(sc);
+               /* but mark the hidms not in use */
+               ums_disable(sc);
+       }
 }
 
 int
@@ -211,7 +219,13 @@ ums_enable(void *v)
        if ((rv = hidms_enable(ms)) != 0)
                return rv;
 
-       return uhidev_open(&sc->sc_hdev);
+       if ((sc->sc_quirks & UQ_ALWAYS_OPEN) &&
+           (sc->sc_hdev.sc_state & UHIDEV_OPEN))
+               rv = 0;
+       else
+               rv = uhidev_open(&sc->sc_hdev);
+
+       return rv;
 }
 
 void
@@ -221,6 +235,10 @@ ums_disable(void *v)
        struct hidms *ms = &sc->sc_ms;
 
        hidms_disable(ms);
+
+       if (sc->sc_quirks & UQ_ALWAYS_OPEN)
+               return;
+
        uhidev_close(&sc->sc_hdev);
 }
 
index a3fd5ce..3aa45bf 100644 (file)
@@ -1,9 +1,9 @@
-/* $OpenBSD: umt.c,v 1.3 2021/03/08 14:35:57 jcs Exp $ */
+/* $OpenBSD: umt.c,v 1.4 2021/03/24 02:49:57 jcs Exp $ */
 /*
  * USB multitouch touchpad driver for devices conforming to
  * Windows Precision Touchpad standard
  *
- * https://msdn.microsoft.com/en-us/library/windows/hardware/dn467314%28v=vs.85%29.aspx
+ * https://docs.microsoft.com/en-us/windows-hardware/design/component-guidelines/windows-precision-touchpad-required-hid-top-level-collections
  *
  * Copyright (c) 2016-2018 joshua stein <jcs@openbsd.org>
  *
@@ -31,6 +31,7 @@
 #include <dev/usb/usbdi.h>
 #include <dev/usb/usbdi_util.h>
 #include <dev/usb/usbdevs.h>
+#include <dev/usb/usb_quirks.h>
 #include <dev/usb/uhidev.h>
 
 #include <dev/wscons/wsconsio.h>
@@ -46,6 +47,8 @@ struct umt_softc {
        int             sc_rep_input;
        int             sc_rep_config;
        int             sc_rep_cap;
+
+       u_int32_t       sc_quirks;
 };
 
 int    umt_enable(void *);
@@ -151,14 +154,18 @@ umt_attach(struct device *parent, struct device *self, void *aux)
        struct umt_softc *sc = (struct umt_softc *)self;
        struct hidmt *mt = &sc->sc_mt;
        struct uhidev_attach_arg *uha = (struct uhidev_attach_arg *)aux;
+       struct usb_attach_arg *uaa = uha->uaa;
        int size;
        void *desc;
 
        sc->sc_hdev.sc_intr = umt_intr;
        sc->sc_hdev.sc_parent = uha->parent;
+       sc->sc_hdev.sc_udev = uaa->device;
 
        usbd_set_idle(uha->parent->sc_udev, uha->parent->sc_ifaceno, 0, 0);
 
+       sc->sc_quirks = usbd_get_quirks(sc->sc_hdev.sc_udev)->uq_flags;
+
        uhidev_get_report_desc(uha->parent, &desc, &size);
        umt_find_winptp_reports(uha->parent, desc, size, &sc->sc_rep_input,
            &sc->sc_rep_config, &sc->sc_rep_cap);
@@ -179,6 +186,13 @@ umt_attach(struct device *parent, struct device *self, void *aux)
                return;
 
        hidmt_attach(mt, &umt_accessops);
+
+       if (sc->sc_quirks & UQ_ALWAYS_OPEN) {
+               /* open uhidev and keep it open */
+               umt_enable(sc);
+               /* but mark the hidmt not in use */
+               umt_disable(sc);
+       }
 }
 
 int
@@ -232,7 +246,11 @@ umt_enable(void *v)
        if ((rv = hidmt_enable(mt)) != 0)
                return rv;
 
-       rv = uhidev_open(&sc->sc_hdev);
+       if ((sc->sc_quirks & UQ_ALWAYS_OPEN) &&
+           (sc->sc_hdev.sc_state & UHIDEV_OPEN))
+               rv = 0;
+       else
+               rv = uhidev_open(&sc->sc_hdev);
 
        hidmt_set_input_mode(mt, HIDMT_INPUT_MODE_MT_TOUCHPAD);
 
@@ -246,6 +264,10 @@ umt_disable(void *v)
        struct hidmt *mt = &sc->sc_mt;
 
        hidmt_disable(mt);
+
+       if (sc->sc_quirks & UQ_ALWAYS_OPEN)
+               return;
+
        uhidev_close(&sc->sc_hdev);
 }
 
index bd46552..be65ad0 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: usb_quirks.c,v 1.77 2021/01/10 16:32:48 thfr Exp $ */
+/*     $OpenBSD: usb_quirks.c,v 1.78 2021/03/24 02:49:57 jcs Exp $ */
 /*     $NetBSD: usb_quirks.c,v 1.45 2003/05/10 17:47:14 hamajima Exp $ */
 /*     $FreeBSD: src/sys/dev/usb/usb_quirks.c,v 1.30 2003/01/02 04:15:55 imp Exp $     */
 
@@ -153,6 +153,14 @@ const struct usbd_quirk_entry {
  { USB_VENDOR_KENSINGTON, USB_PRODUCT_KENSINGTON_SLIMBLADE,
        ANY, { UQ_MS_VENDOR_BUTTONS }},
 
+/* Devices that need their data pipe held open */
+ { USB_VENDOR_HAILUCK, USB_PRODUCT_HAILUCK_KEYBOARD,
+       ANY,    { UQ_ALWAYS_OPEN }},
+ { USB_VENDOR_MICROSOFT, USB_PRODUCT_MICROSOFT_TYPECOVER,
+       ANY,    { UQ_ALWAYS_OPEN }},
+ { USB_VENDOR_MICROSOFT, USB_PRODUCT_MICROSOFT_TYPECOVER2,
+       ANY,    { UQ_ALWAYS_OPEN }},
+
  { 0, 0, 0, { 0 } }
 };
 
index bb751f7..86024a8 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: usb_quirks.h,v 1.17 2021/01/10 16:32:48 thfr Exp $ */
+/*     $OpenBSD: usb_quirks.h,v 1.18 2021/03/24 02:49:57 jcs Exp $ */
 /*     $NetBSD: usb_quirks.h,v 1.20 2001/04/15 09:38:01 augustss Exp $ */
 /*     $FreeBSD: src/sys/dev/usb/usb_quirks.h,v 1.9 1999/11/12 23:31:03 n_hibma Exp $  */
 
@@ -51,6 +51,7 @@ struct usbd_quirks {
                                                if attached to EHCI */
 #define UQ_MS_VENDOR_BUTTONS   0x00040000 /* mouse reports extra buttons in
                                                vendor page */
+#define UQ_ALWAYS_OPEN         0x00080000 /* always keep data pipe open */
 };
 
 extern const struct usbd_quirks usbd_no_quirk;