This makes the volume and screen brightness keys work, but more 
importantly it keeps the USB data/interrupt pipes open at all times 
because otherwise the Type Cover resets itself (or at least detaches 
and reattaches) when these buttons are pressed.


diff --git share/man/man4/Makefile share/man/man4/Makefile
index 258399f2e7a..3c15cc14285 100644
--- share/man/man4/Makefile
+++ share/man/man4/Makefile
@@ -84,8 +84,8 @@ MAN=  aac.4 abcrtc.4 ac97.4 acphy.4 acrtc.4 \
        uftdi.4 ugen.4 ugl.4 ugold.4 uguru.4 uhci.4 uhid.4 uhidev.4 uipaq.4 \
        uk.4 ukbd.4 \
        ukphy.4 ulpt.4 umass.4 umb.4 umbg.4 umcs.4 umct.4 umidi.4 umodem.4 \
-       ums.4 umsm.4 umt.4 unix.4 uonerng.4 uow.4 uoaklux.4 uoakrh.4 uoakv.4 \
-       upd.4 upgt.4 upl.4 uplcom.4 ural.4 ure.4 url.4 urlphy.4 \
+       ums.4 umsm.4 umstc.4 umt.4 unix.4 uonerng.4 uow.4 uoaklux.4 uoakrh.4 \
+       uoakv.4 upd.4 upgt.4 upl.4 uplcom.4 ural.4 ure.4 url.4 urlphy.4 \
        urndis.4 urng.4 urtw.4 urtwn.4 usb.4 uscom.4 uslcom.4 usps.4 \
        uthum.4 uticom.4 utpms.4 utwitch.4 utrh.4 uts.4 utvfu.4 uvideo.4 \
        uvisor.4 uvscom.4 uwacom.4 uxrcom.4 \
diff --git share/man/man4/umstc.4 share/man/man4/umstc.4
new file mode 100644
index 00000000000..da557c59d1d
--- /dev/null
+++ share/man/man4/umstc.4
@@ -0,0 +1,44 @@
+.\"    $OpenBSD$
+.\"
+.\" Copyright (c) 2020 joshua stein <j...@openbsd.org>
+.\"
+.\" Permission to use, copy, modify, and distribute this software for any
+.\" purpose with or without fee is hereby granted, provided that the above
+.\" copyright notice and this permission notice appear in all copies.
+.\"
+.\" THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+.\" WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+.\" MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+.\" ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+.\" WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+.\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+.\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+.\"
+.Dd $Mdocdate$
+.Dt UMSTC 4
+.Os
+.Sh NAME
+.Nm umstc
+.Nd Microsoft Surface Type Cover driver
+.Sh SYNOPSIS
+.Cd "umstc* at uhidev?"
+.Sh DESCRIPTION
+The
+.Nm
+driver responds to some special keys on the Microsoft Type Cover
+keyboard, such as volume and screen brightness keys.
+.Sh SEE ALSO
+.Xr uhidev 4 ,
+.Xr usb 4 ,
+.Xr sysctl 8
+.Sh HISTORY
+The
+.Nm
+driver first appeared in
+.Ox 6.8 .
+.Sh AUTHORS
+.An -nosplit
+The
+.Nm
+driver was written by
+.An joshua stein Aq Mt j...@jcs.org .
diff --git sys/arch/amd64/conf/GENERIC sys/arch/amd64/conf/GENERIC
index b77a3b4ead5..624f73bb7cc 100644
--- sys/arch/amd64/conf/GENERIC
+++ sys/arch/amd64/conf/GENERIC
@@ -284,6 +284,7 @@ ucom*       at uslhcom?
 uhid*  at uhidev?              # USB generic HID support
 fido*  at uhidev?              # FIDO/U2F security key support
 upd*   at uhidev?              # USB Power Devices sensors
+umstc* at uhidev?              # Microsoft Surface Type Cover
 aue*   at uhub?                # ADMtek AN986 Pegasus Ethernet
 atu*   at uhub?                # Atmel AT76c50x based 802.11b
 axe*   at uhub?                # ASIX Electronics AX88172 USB Ethernet
diff --git sys/dev/hid/hid.h sys/dev/hid/hid.h
index 17de4065e0c..c528ab9551b 100644
--- sys/dev/hid/hid.h
+++ sys/dev/hid/hid.h
@@ -396,6 +396,11 @@ int        hid_is_collection(const void *, int, uint8_t, 
int32_t);
 #define HUL_KANA               0x0005
 
 /* Usages, Consumer */
+#define HUC_CONTROL            0x0001
+#define HUC_PLAY_PAUSE         0x00cd
+#define HUC_MUTE               0x00e2
+#define HUC_VOL_INC            0x00e9
+#define HUC_VOL_DEC            0x00ea
 #define HUC_AC_PAN             0x0238
 
 /* Usages, FIDO */
diff --git sys/dev/usb/files.usb sys/dev/usb/files.usb
index c3597c54775..fc5ff46ce76 100644
--- sys/dev/usb/files.usb
+++ sys/dev/usb/files.usb
@@ -473,3 +473,8 @@ file        dev/usb/uwacom.c                uwacom
 
 attach bwfm at uhub with bwfm_usb: firmload
 file   dev/usb/if_bwfm_usb.c           bwfm_usb
+
+# Microsoft Surface Type Cover
+device umstc: hid
+attach umstc at uhidbus
+file   dev/usb/umstc.c                 umstc
diff --git sys/dev/usb/umstc.c sys/dev/usb/umstc.c
new file mode 100644
index 00000000000..df995181bf6
--- /dev/null
+++ sys/dev/usb/umstc.c
@@ -0,0 +1,172 @@
+/*     $OpenBSD$ */
+
+/*
+ * Copyright (c) 2020 joshua stein <j...@jcs.org>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/*
+ * Microsoft Surface Type Cover driver to respond to F1-F7 keys, but also to
+ * keep the USB HID pipes open or else the Type Cover will detach and reattach
+ * each time one of these buttons is pressed.
+ */
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/kernel.h>
+#include <sys/device.h>
+
+#include <dev/usb/usb.h>
+#include <dev/usb/usbhid.h>
+#include <dev/usb/usbdi.h>
+#include <dev/usb/usbdevs.h>
+#include <dev/usb/uhidev.h>
+
+#include <dev/wscons/wsconsio.h>
+#include <dev/wscons/wsdisplayvar.h>
+
+#include "audio.h"
+#include "wsdisplay.h"
+
+struct umstc_softc {
+       struct uhidev sc_hdev;
+};
+
+void   umstc_intr(struct uhidev *addr, void *ibuf, u_int len);
+int    umstc_match(struct device *, void *, void *);
+void   umstc_attach(struct device *, struct device *, void *);
+int    umstc_detach(struct device *, int flags);
+
+extern int wskbd_set_mixervolume(long, long);
+
+struct cfdriver umstc_cd = {
+       NULL, "umstc", DV_DULL
+};
+
+const struct cfattach umstc_ca = {
+       sizeof(struct umstc_softc),
+       umstc_match,
+       umstc_attach,
+       umstc_detach,
+};
+
+static const struct usb_devno umstc_devs[] = {
+       { USB_VENDOR_MICROSOFT, USB_PRODUCT_MICROSOFT_TYPECOVER },
+       { USB_VENDOR_MICROSOFT, USB_PRODUCT_MICROSOFT_TYPECOVER2 },
+};
+
+int
+umstc_match(struct device *parent, void *match, void *aux)
+{
+       struct uhidev_attach_arg *uha = (struct uhidev_attach_arg *)aux;
+       int size;
+       void *desc;
+
+       if (!usb_lookup(umstc_devs, uha->uaa->vendor, uha->uaa->product))
+               return UMATCH_NONE;
+
+       uhidev_get_report_desc(uha->parent, &desc, &size);
+
+       if (hid_is_collection(desc, size, uha->reportid,
+           HID_USAGE2(HUP_CONSUMER, HUC_CONTROL)))
+               return UMATCH_IFACECLASS;
+
+       return UMATCH_NONE;
+}
+
+void
+umstc_attach(struct device *parent, struct device *self, void *aux)
+{
+       struct umstc_softc *sc = (struct umstc_softc *)self;
+       struct uhidev_attach_arg *uha = (struct uhidev_attach_arg *)aux;
+       struct usb_attach_arg *uaa = uha->uaa;
+       int size, repid;
+       void *desc;
+
+       sc->sc_hdev.sc_intr = umstc_intr;
+       sc->sc_hdev.sc_parent = uha->parent;
+       sc->sc_hdev.sc_udev = uaa->device;
+       sc->sc_hdev.sc_report_id = uha->reportid;
+
+       uhidev_get_report_desc(uha->parent, &desc, &size);
+       repid = uha->reportid;
+       sc->sc_hdev.sc_isize = hid_report_size(desc, size, hid_input, repid);
+       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);
+
+       uhidev_open(&sc->sc_hdev);
+
+       printf("\n");
+}
+
+int
+umstc_detach(struct device *self, int flags)
+{
+       struct umstc_softc *sc = (struct umstc_softc *)self;
+
+       uhidev_close(&sc->sc_hdev);
+
+       return 0;
+}
+
+void
+umstc_intr(struct uhidev *addr, void *buf, u_int len)
+{
+       struct umstc_softc *sc = (struct umstc_softc *)addr;
+       int i;
+
+       if (!len)
+               return;
+
+       switch (((unsigned char *)buf)[0]) {
+       case HUC_PLAY_PAUSE:
+               /*
+                * It would be nice to pass this through to userland but we'd
+                * need to attach a wskbd
+                */
+               break;
+       case HUC_MUTE:
+#if NAUDIO > 0
+               wskbd_set_mixervolume(0, 1);
+#endif
+               break;
+       case HUC_VOL_INC:
+#if NAUDIO > 0
+               wskbd_set_mixervolume(1, 1);
+#endif
+               break;
+       case HUC_VOL_DEC:
+#if NAUDIO > 0
+               wskbd_set_mixervolume(-1, 1);
+#endif
+               break;
+       case 0x70: /* brightness down */
+#if NWSDISPLAY > 0
+               wsdisplay_brightness_step(NULL, -1);
+#endif
+               break;
+       case 0x6f: /* brightness up */
+#if NWSDISPLAY > 0
+               wsdisplay_brightness_step(NULL, 1);
+#endif
+               break;
+       case 0:
+               break;
+       default:
+               printf("%s: unhandled key ", sc->sc_hdev.sc_dev.dv_xname);
+               for (i = 0; i < len; i++)
+                       printf(" 0x%02x", ((unsigned char *)buf)[i]);
+               printf("\n");
+       }
+}
diff --git sys/dev/usb/usbdevs sys/dev/usb/usbdevs
index 007ad1a659d..6eefafc85a3 100644
--- sys/dev/usb/usbdevs
+++ sys/dev/usb/usbdevs
@@ -3023,6 +3023,8 @@ product MICROSOFT XBOX360 0x0292  XBOX 360 WLAN
 product MICROSOFT WLMOBILEMOUSE3500 0x0745  Wireless Mobile Mouse 3500
 product MICROSOFT LIFECAM      0x074a  Microsoft LifeCam
 product MICROSOFT WLARCMOUSE   0x074f  Wireless Arc Mouse (Model 1350)
+product MICROSOFT TYPECOVER    0x096f  Surface Go Type Cover
+product MICROSOFT TYPECOVER2   0x09b5  Surface Go Type Cover
 
 /* Microtech products */
 product MICROTECH SCSIDB25     0x0004  SCSI-DB25
diff --git sys/dev/usb/usbdevs.h sys/dev/usb/usbdevs.h
index 8cad9fa072e..1cb4932b9de 100644
--- sys/dev/usb/usbdevs.h
+++ sys/dev/usb/usbdevs.h
@@ -1,4 +1,4 @@
-/*     $OpenBSD: usbdevs.h,v 1.726 2020/05/26 06:03:39 jsg Exp $       */
+/*     $OpenBSD$       */
 
 /*
  * THIS FILE IS AUTOMATICALLY GENERATED.  DO NOT EDIT.
@@ -3030,6 +3030,8 @@
 #define        USB_PRODUCT_MICROSOFT_WLMOBILEMOUSE3500 0x0745          /* 
Wireless Mobile Mouse 3500 */
 #define        USB_PRODUCT_MICROSOFT_LIFECAM   0x074a          /* Microsoft 
LifeCam */
 #define        USB_PRODUCT_MICROSOFT_WLARCMOUSE        0x074f          /* 
Wireless Arc Mouse (Model 1350) */
+#define        USB_PRODUCT_MICROSOFT_TYPECOVER 0x096f          /* Surface Go 
Type Cover */
+#define        USB_PRODUCT_MICROSOFT_TYPECOVER2        0x09b5          /* 
Surface Go Type Cover */
 
 /* Microtech products */
 #define        USB_PRODUCT_MICROTECH_SCSIDB25  0x0004          /* SCSI-DB25 */
diff --git sys/dev/usb/usbdevs_data.h sys/dev/usb/usbdevs_data.h
index d3b9b83161f..9a2512f3e24 100644
--- sys/dev/usb/usbdevs_data.h
+++ sys/dev/usb/usbdevs_data.h
@@ -1,4 +1,4 @@
-/*     $OpenBSD: usbdevs_data.h,v 1.720 2020/05/26 06:03:39 jsg Exp $  */
+/*     $OpenBSD$       */
 
 /*
  * THIS FILE IS AUTOMATICALLY GENERATED.  DO NOT EDIT.
@@ -7305,6 +7305,14 @@ const struct usb_known_product usb_known_products[] = {
            USB_VENDOR_MICROSOFT, USB_PRODUCT_MICROSOFT_WLARCMOUSE,
            "Wireless Arc Mouse (Model 1350)",
        },
+       {
+           USB_VENDOR_MICROSOFT, USB_PRODUCT_MICROSOFT_TYPECOVER,
+           "Surface Go Type Cover",
+       },
+       {
+           USB_VENDOR_MICROSOFT, USB_PRODUCT_MICROSOFT_TYPECOVER2,
+           "Surface Go Type Cover",
+       },
        {
            USB_VENDOR_MICROTECH, USB_PRODUCT_MICROTECH_SCSIDB25,
            "SCSI-DB25",

Reply via email to