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,