Hi, The AX88179A, which has the same product ID as AX88179, shows up as axen(4), but doesn't work:
"axen0: invalid buffer(pkt#1), continue" https://marc.info/?l=openbsd-bugs&m=164832882524713&w=2 gerhard@ sent a diff in that thread that checks the revision and makes this device fall back to cdce(4). It's gotten a couple of positive test reports, and works on my device as well (Steam Deck Dock). A downside is that cdce(4) leaves performance on the table. A CDC/NCM interface could be better, but there's no driver for it. In their current state, these devices have zero performance. Given that, does it make sense to commit this diff? Index: dev/usb/if_cdce.c =================================================================== RCS file: /cvs/src/sys/dev/usb/if_cdce.c,v retrieving revision 1.80 diff -u -p -r1.80 if_cdce.c --- dev/usb/if_cdce.c 29 Jan 2021 17:12:19 -0000 1.80 +++ dev/usb/if_cdce.c 24 Apr 2023 10:31:34 -0000 @@ -59,8 +59,11 @@ #include <netinet/in.h> #include <netinet/if_ether.h> +#include <machine/bus.h> + #include <dev/usb/usb.h> #include <dev/usb/usbdi.h> +#include <dev/usb/usbdivar.h> #include <dev/usb/usbdi_util.h> #include <dev/usb/usbdevs.h> #include <dev/usb/usbcdc.h> @@ -90,18 +93,19 @@ void cdce_stop(struct cdce_softc *); void cdce_intr(struct usbd_xfer *, void *, usbd_status); const struct cdce_type cdce_devs[] = { - {{ USB_VENDOR_ACERLABS, USB_PRODUCT_ACERLABS_M5632 }, 0 }, - {{ USB_VENDOR_PROLIFIC, USB_PRODUCT_PROLIFIC_PL2501 }, 0 }, - {{ USB_VENDOR_SHARP, USB_PRODUCT_SHARP_SL5500 }, CDCE_CRC32 }, - {{ USB_VENDOR_SHARP, USB_PRODUCT_SHARP_A300 }, CDCE_CRC32 }, - {{ USB_VENDOR_SHARP, USB_PRODUCT_SHARP_SL5600 }, CDCE_CRC32 }, - {{ USB_VENDOR_SHARP, USB_PRODUCT_SHARP_C700 }, CDCE_CRC32 }, - {{ USB_VENDOR_SHARP, USB_PRODUCT_SHARP_C750 }, CDCE_CRC32 }, - {{ USB_VENDOR_MOTOROLA2, USB_PRODUCT_MOTOROLA2_USBLAN }, CDCE_CRC32 }, - {{ USB_VENDOR_MOTOROLA2, USB_PRODUCT_MOTOROLA2_USBLAN2 }, CDCE_CRC32 }, - {{ USB_VENDOR_GMATE, USB_PRODUCT_GMATE_YP3X00 }, 0 }, - {{ USB_VENDOR_COMPAQ, USB_PRODUCT_COMPAQ_IPAQLINUX }, 0 }, - {{ USB_VENDOR_AMBIT, USB_PRODUCT_AMBIT_NTL_250 }, CDCE_SWAPUNION }, + {{ USB_VENDOR_ACERLABS, USB_PRODUCT_ACERLABS_M5632 }, 0, 0, -1 }, + {{ USB_VENDOR_PROLIFIC, USB_PRODUCT_PROLIFIC_PL2501 }, 0, 0, -1 }, + {{ USB_VENDOR_SHARP, USB_PRODUCT_SHARP_SL5500 }, 0, CDCE_CRC32, -1 }, + {{ USB_VENDOR_SHARP, USB_PRODUCT_SHARP_A300 }, 0, CDCE_CRC32, -1 }, + {{ USB_VENDOR_SHARP, USB_PRODUCT_SHARP_SL5600 }, 0, CDCE_CRC32, -1 }, + {{ USB_VENDOR_SHARP, USB_PRODUCT_SHARP_C700 }, 0, CDCE_CRC32, -1 }, + {{ USB_VENDOR_SHARP, USB_PRODUCT_SHARP_C750 }, 0, CDCE_CRC32, -1 }, + {{ USB_VENDOR_MOTOROLA2, USB_PRODUCT_MOTOROLA2_USBLAN }, 0, CDCE_CRC32, -1 }, + {{ USB_VENDOR_MOTOROLA2, USB_PRODUCT_MOTOROLA2_USBLAN2 }, 0, CDCE_CRC32, -1 }, + {{ USB_VENDOR_GMATE, USB_PRODUCT_GMATE_YP3X00 }, 0, 0, -1 }, + {{ USB_VENDOR_COMPAQ, USB_PRODUCT_COMPAQ_IPAQLINUX }, 0, 0, -1 }, + {{ USB_VENDOR_AMBIT, USB_PRODUCT_AMBIT_NTL_250 }, 0, CDCE_SWAPUNION, -1 }, + {{ USB_VENDOR_ASIX, USB_PRODUCT_ASIX_AX88179 }, 0x0200, CDCE_MATCHREV, 3 }, }; #define cdce_lookup(v, p) \ ((const struct cdce_type *)usb_lookup(cdce_devs, v, p)) @@ -123,6 +127,15 @@ cdce_match(struct device *parent, void * { struct usb_attach_arg *uaa = aux; usb_interface_descriptor_t *id; + const struct cdce_type *type; + + if ((type = cdce_lookup(uaa->vendor, uaa->product)) != NULL) { + if (type->cdce_flags & CDCE_MATCHREV) { + if (type->cdce_rev == uaa->release) + return (UMATCH_VENDOR_PRODUCT_REV); + } else + return (UMATCH_VENDOR_PRODUCT); + } if (uaa->iface == NULL) return (UMATCH_NONE); @@ -131,9 +144,6 @@ cdce_match(struct device *parent, void * if (id == NULL) return (UMATCH_NONE); - if (cdce_lookup(uaa->vendor, uaa->product) != NULL) - return (UMATCH_VENDOR_PRODUCT); - if (id->bInterfaceClass == UICLASS_CDC && (id->bInterfaceSubClass == UISUBCLASS_ETHERNET_NETWORKING_CONTROL_MODEL || @@ -150,7 +160,6 @@ cdce_attach(struct device *parent, struc struct usb_attach_arg *uaa = aux; int s; struct ifnet *ifp = GET_IFP(sc); - struct usbd_device *dev = uaa->device; const struct cdce_type *t; usb_interface_descriptor_t *id; usb_endpoint_descriptor_t *ed; @@ -163,19 +172,51 @@ cdce_attach(struct device *parent, struc int i, j, numalts, len; int ctl_ifcno = -1; int data_ifcno = -1; + usbd_status err; + + t = cdce_lookup(uaa->vendor, uaa->product); + if (uaa->configno < 0) { + if (t == NULL || t->cdce_cfgno < 0) { + printf("%s: unknown configuration for vid/pid match\n", + sc->cdce_dev.dv_xname); + return; + } + uaa->configno = t->cdce_cfgno; + DPRINTF(("%s: switching to config #%d\n", + sc->cdce_dev.dv_xname)); + err = usbd_set_config_no(uaa->device, uaa->configno, 1); + if (err) { + printf("%s: failed to switch to config #%d: %s\n", + sc->cdce_dev.dv_xname, uaa->configno, + usbd_errstr(err)); + return; + } + for (i = 0; i < uaa->device->cdesc->bNumInterfaces; i++) { + if (usbd_iface_claimed(uaa->device, i)) + continue; + id = usbd_get_interface_descriptor( + &uaa->device->ifaces[i]); + if (id != NULL && id->bInterfaceClass == UICLASS_CDC && + id->bInterfaceSubClass == + UISUBCLASS_ETHERNET_NETWORKING_CONTROL_MODEL) { + uaa->iface = &uaa->device->ifaces[i]; + uaa->ifaceno = uaa->iface->idesc->bInterfaceNumber; + break; + } + } + } sc->cdce_udev = uaa->device; sc->cdce_ctl_iface = uaa->iface; id = usbd_get_interface_descriptor(sc->cdce_ctl_iface); ctl_ifcno = id->bInterfaceNumber; - t = cdce_lookup(uaa->vendor, uaa->product); if (t) sc->cdce_flags = t->cdce_flags; /* Get the data interface no. and capabilities */ ethd = NULL; - usbd_desc_iter_init(dev, &iter); + usbd_desc_iter_init(sc->cdce_udev, &iter); desc = usbd_desc_iter_next(&iter); while (desc) { if (desc->bDescriptorType != UDESC_CS_INTERFACE) { @@ -210,12 +251,13 @@ cdce_attach(struct device *parent, struc } else { DPRINTF(("cdce_attach: union interface: ctl=%d, data=%d\n", ctl_ifcno, data_ifcno)); - for (i = 0; i < uaa->nifaces; i++) { + for (i = 0; i < uaa->device->cdesc->bNumInterfaces; i++) { if (usbd_iface_claimed(sc->cdce_udev, i)) continue; - id = usbd_get_interface_descriptor(uaa->ifaces[i]); + id = usbd_get_interface_descriptor( + &uaa->device->ifaces[i]); if (id != NULL && id->bInterfaceNumber == data_ifcno) { - sc->cdce_data_iface = uaa->ifaces[i]; + sc->cdce_data_iface = &uaa->device->ifaces[i]; usbd_claim_iface(sc->cdce_udev, i); } } @@ -303,8 +345,8 @@ cdce_attach(struct device *parent, struc found: s = splnet(); - if (!ethd || usbd_get_string_desc(sc->cdce_udev, ethd->iMacAddress, 0, - &eaddr_str, &len)) { + if (!ethd || usbd_get_string_desc(sc->cdce_udev, ethd->iMacAddress, + sc->cdce_udev->langid, &eaddr_str, &len)) { ether_fakeaddr(ifp); } else { for (i = 0; i < ETHER_ADDR_LEN * 2; i++) { Index: dev/usb/if_cdcereg.h =================================================================== RCS file: /cvs/src/sys/dev/usb/if_cdcereg.h,v retrieving revision 1.7 diff -u -p -r1.7 if_cdcereg.h --- dev/usb/if_cdcereg.h 12 Oct 2016 21:51:11 -0000 1.7 +++ dev/usb/if_cdcereg.h 24 Apr 2023 10:31:34 -0000 @@ -40,9 +40,12 @@ struct cdce_type { struct usb_devno cdce_dev; + u_int16_t cdce_rev; u_int16_t cdce_flags; #define CDCE_CRC32 1 #define CDCE_SWAPUNION 2 +#define CDCE_MATCHREV 4 + int cdce_cfgno; }; struct cdce_softc;