Modern chromebooks expose a debugging interface on one of their USB
Type-C connectors.  Part of this interface are *three* USB serial
devices that connect to microcontrollers and a serial port on the SoC.
It all works nicely with ucom(4) but we need a bit of glue to actually
make that attach.  What I ended up is pretty close to uscom(4) but the
discovery of the descriptors is different and I don't immediately see
a way to fold this into that driver.

Should this be enabled on more architectures than amd64?

ok?


Index: arch/amd64/conf/GENERIC
===================================================================
RCS file: /cvs/src/sys/arch/amd64/conf/GENERIC,v
retrieving revision 1.470
diff -u -p -r1.470 GENERIC
--- arch/amd64/conf/GENERIC     4 May 2019 17:59:40 -0000       1.470
+++ arch/amd64/conf/GENERIC     8 May 2019 22:03:21 -0000
@@ -234,6 +234,8 @@ uslcom*     at uhub?                # Silicon Laboratories
 ucom*  at uslcom?
 uscom* at uhub?                # Simple USB serial adapters
 ucom*  at uscom?
+ucrcom*        at uhub?                # Chromebook serial
+ucom*  at ucrcom?
 uark*  at uhub?                # Arkmicro ARK3116 serial
 ucom*  at uark?
 moscom*        at uhub?                # MosChip MCS7703 serial
Index: dev/usb/files.usb
===================================================================
RCS file: /cvs/src/sys/dev/usb/files.usb,v
retrieving revision 1.137
diff -u -p -r1.137 files.usb
--- dev/usb/files.usb   27 Mar 2019 22:08:51 -0000      1.137
+++ dev/usb/files.usb   8 May 2019 22:02:02 -0000
@@ -342,6 +342,11 @@ device     uscom: ucombus
 attach uscom at uhub
 file   dev/usb/uscom.c                 uscom
 
+# Chromebook serial
+device ucrcom: ucombus
+attach ucrcom at uhub
+file   dev/usb/ucrcom.c                ucrcom
+
 # Exar XR21V1410
 device uxrcom: ucombus
 attach uxrcom at uhub
Index: dev/usb/ucrcom.c
===================================================================
RCS file: dev/usb/ucrcom.c
diff -N dev/usb/ucrcom.c
--- /dev/null   1 Jan 1970 00:00:00 -0000
+++ dev/usb/ucrcom.c    8 May 2019 22:49:57 -0000
@@ -0,0 +1,136 @@
+/*     $OpenBSD$       */
+
+/*
+ * Copyright (c) 2019 Mark Kettenis <kette...@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.
+ */
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/kernel.h>
+#include <sys/tty.h>
+#include <sys/device.h>
+
+#include <dev/usb/usb.h>
+#include <dev/usb/usbdi.h>
+#include <dev/usb/usbdi_util.h>
+#include <dev/usb/usbdevs.h>
+
+#include <dev/usb/ucomvar.h>
+
+#define UCRCOMBUFSZ            64
+
+struct ucrcom_softc {
+       struct device           sc_dev;
+       struct device           *sc_subdev;
+};
+
+struct ucom_methods ucrcom_methods = { NULL };
+
+int ucrcom_match(struct device *, void *, void *);
+void ucrcom_attach(struct device *, struct device *, void *);
+int ucrcom_detach(struct device *, int);
+
+struct cfdriver ucrcom_cd = {
+       NULL, "ucrcom", DV_DULL
+};
+
+const struct cfattach ucrcom_ca = {
+       sizeof(struct ucrcom_softc), ucrcom_match, ucrcom_attach, ucrcom_detach
+};
+
+int
+ucrcom_match(struct device *parent, void *match, void *aux)
+{
+       struct usb_attach_arg *uaa = aux;
+       usb_interface_descriptor_t *id;
+       usb_device_descriptor_t *dd;
+
+       if (uaa->iface == NULL)
+               return UMATCH_NONE;
+
+       id = usbd_get_interface_descriptor(uaa->iface);
+       dd = usbd_get_device_descriptor(uaa->device);
+       if (id == NULL || dd == NULL)
+               return UMATCH_NONE;
+
+       if (UGETW(dd->idVendor) == USB_VENDOR_GOOGLE &&
+           id->bInterfaceClass == UICLASS_VENDOR &&
+           id->bInterfaceSubClass == 0x50 &&
+           id->bInterfaceProtocol == 1)
+               return UMATCH_VENDOR_IFACESUBCLASS_IFACEPROTO;
+
+       return UMATCH_NONE;
+}
+
+void
+ucrcom_attach(struct device *parent, struct device *self, void *aux)
+{
+       struct ucrcom_softc *sc = (struct ucrcom_softc *)self;
+       struct usb_attach_arg *uaa = aux;
+       struct ucom_attach_args uca;
+       usb_interface_descriptor_t *id;
+       usb_endpoint_descriptor_t *ed;
+       int i;
+
+       id = usbd_get_interface_descriptor(uaa->iface);
+
+       memset(&uca, 0, sizeof(uca));
+       uca.bulkin = uca.bulkout = -1;
+       for (i = 0; i < id->bNumEndpoints; i++) {
+               ed = usbd_interface2endpoint_descriptor(uaa->iface, i);
+               if (ed == NULL) {
+                       printf("%s: no endpoint descriptor for %d\n",
+                               sc->sc_dev.dv_xname, i);
+                       usbd_deactivate(uaa->device);
+                       return;
+               }
+
+               if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_IN &&
+                   UE_GET_XFERTYPE(ed->bmAttributes) == UE_BULK)
+                       uca.bulkin = ed->bEndpointAddress;
+               else if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_OUT &&
+                   UE_GET_XFERTYPE(ed->bmAttributes) == UE_BULK)
+                       uca.bulkout = ed->bEndpointAddress;
+        }
+
+       if (uca.bulkin == -1 || uca.bulkout == -1) {
+               printf("%s: missing endpoint\n", sc->sc_dev.dv_xname);
+               usbd_deactivate(uaa->device);
+               return;
+       }
+
+       uca.ibufsize = UCRCOMBUFSZ;
+       uca.ibufsizepad = UCRCOMBUFSZ;
+       uca.obufsize = UCRCOMBUFSZ;
+       uca.opkthdrlen = 0;
+       uca.device = uaa->device;
+       uca.iface = uaa->iface;
+       uca.methods = &ucrcom_methods;
+       uca.arg = sc;
+
+       sc->sc_subdev = config_found_sm(self, &uca, ucomprint, ucomsubmatch);
+}
+
+int
+ucrcom_detach(struct device *self, int flags)
+{
+       struct ucrcom_softc *sc = (struct ucrcom_softc *)self;
+       int rv = 0;
+
+       if (sc->sc_subdev != NULL)
+               rv = config_detach(sc->sc_subdev, flags);
+
+       return rv;
+}
Index: dev/usb/usbdevs
===================================================================
RCS file: /cvs/src/sys/dev/usb/usbdevs,v
retrieving revision 1.698
diff -u -p -r1.698 usbdevs
--- dev/usb/usbdevs     24 Apr 2019 20:28:31 -0000      1.698
+++ dev/usb/usbdevs     8 May 2019 22:46:00 -0000
@@ -576,6 +576,7 @@ vendor LENOVO               0x17ef  Lenovo
 vendor WAVESENSE       0x17f4  WaveSense
 vendor VAISALA         0x1843  VAISALA
 vendor AMIT            0x18c5  AMIT
+vendor GOOGLE          0x18d1  Google
 vendor QCOM            0x18e8  Qcom
 vendor ELV             0x18ef  ELV
 vendor LINKSYS3                0x1915  Linksys
Index: dev/usb/usbdevs.h
===================================================================
RCS file: /cvs/src/sys/dev/usb/usbdevs.h,v
retrieving revision 1.710
diff -u -p -r1.710 usbdevs.h
--- dev/usb/usbdevs.h   24 Apr 2019 20:32:23 -0000      1.710
+++ dev/usb/usbdevs.h   8 May 2019 22:46:51 -0000
@@ -1,4 +1,4 @@
-/*     $OpenBSD: usbdevs.h,v 1.710 2019/04/24 20:32:23 remi Exp $      */
+/*     $OpenBSD$       */
 
 /*
  * THIS FILE IS AUTOMATICALLY GENERATED.  DO NOT EDIT.
@@ -583,6 +583,7 @@
 #define        USB_VENDOR_WAVESENSE    0x17f4          /* WaveSense */
 #define        USB_VENDOR_VAISALA      0x1843          /* VAISALA */
 #define        USB_VENDOR_AMIT 0x18c5          /* AMIT */
+#define        USB_VENDOR_GOOGLE       0x18d1          /* Google */
 #define        USB_VENDOR_QCOM 0x18e8          /* Qcom */
 #define        USB_VENDOR_ELV  0x18ef          /* ELV */
 #define        USB_VENDOR_LINKSYS3     0x1915          /* Linksys */
Index: dev/usb/usbdevs_data.h
===================================================================
RCS file: /cvs/src/sys/dev/usb/usbdevs_data.h,v
retrieving revision 1.704
diff -u -p -r1.704 usbdevs_data.h
--- dev/usb/usbdevs_data.h      24 Apr 2019 20:32:23 -0000      1.704
+++ dev/usb/usbdevs_data.h      8 May 2019 22:46:51 -0000
@@ -1,4 +1,4 @@
-/*     $OpenBSD: usbdevs_data.h,v 1.704 2019/04/24 20:32:23 remi Exp $ */
+/*     $OpenBSD$       */
 
 /*
  * THIS FILE IS AUTOMATICALLY GENERATED.  DO NOT EDIT.
@@ -13812,6 +13812,10 @@ const struct usb_known_vendor usb_known_
        {
            USB_VENDOR_AMIT,
            "AMIT",
+       },
+       {
+           USB_VENDOR_GOOGLE,
+           "Google",
        },
        {
            USB_VENDOR_QCOM,

Reply via email to