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;

Reply via email to