Module Name:    src
Committed By:   thorpej
Date:           Tue Mar 26 03:38:02 UTC 2024

Modified Files:
        src/sys/dev/usb: uftdi.c usbdevices.config

Log Message:
Add a "match quirk" mechanism to the uftdi driver that allows it to
selectively reject individual interfaces based on the combination of
- Vendor ID
- Product ID
- Interface number
- Vendor string
- Product string

This is necessary[*] to allow some devices that would otherwise match
uftdi (and thus instantiate a ucom) to be matched by ugenif instead,
which is required to make the device available to libusb1.

[*] ...due to a deficiency in the USB stack that does not provide a
mechanism for a user-space driver to claim a device from a kernel driver
and then return it back at a later time.

Use this new match quirk mechanism to reject "interface 1" of the
FTDI 2232C-based Tigard debug board; On this board, "interface 0"
is brought out to regular TTL-level UART pins, but "interface 1" is
brought out to SWD and JTAG headers, and is really only useful when
used with something like openocd.  Because the FTDI 2232C on this board
just uses the standard FTDI vendor and product IDs, it can only be
distinguished by the strings, which cannot be specified usbdevices.config,
thus necessitating the match quirk entry (that works in combination
with the ugenif entry added in usbdevices.config).


To generate a diff of this commit:
cvs rdiff -u -r1.76 -r1.77 src/sys/dev/usb/uftdi.c
cvs rdiff -u -r1.42 -r1.43 src/sys/dev/usb/usbdevices.config

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: src/sys/dev/usb/uftdi.c
diff -u src/sys/dev/usb/uftdi.c:1.76 src/sys/dev/usb/uftdi.c:1.77
--- src/sys/dev/usb/uftdi.c:1.76	Sat Aug  7 16:19:17 2021
+++ src/sys/dev/usb/uftdi.c	Tue Mar 26 03:38:02 2024
@@ -1,4 +1,4 @@
-/*	$NetBSD: uftdi.c,v 1.76 2021/08/07 16:19:17 thorpej Exp $	*/
+/*	$NetBSD: uftdi.c,v 1.77 2024/03/26 03:38:02 thorpej Exp $	*/
 
 /*
  * Copyright (c) 2000 The NetBSD Foundation, Inc.
@@ -30,7 +30,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: uftdi.c,v 1.76 2021/08/07 16:19:17 thorpej Exp $");
+__KERNEL_RCSID(0, "$NetBSD: uftdi.c,v 1.77 2024/03/26 03:38:02 thorpej Exp $");
 
 #ifdef _KERNEL_OPT
 #include "opt_usb.h"
@@ -47,6 +47,7 @@ __KERNEL_RCSID(0, "$NetBSD: uftdi.c,v 1.
 
 #include <dev/usb/usbdi.h>
 #include <dev/usb/usbdi_util.h>
+#include <dev/usb/usbdivar.h>
 #include <dev/usb/usbdevs.h>
 
 #include <dev/usb/ucomvar.h>
@@ -184,10 +185,72 @@ static int	uftdi_detach(device_t, int);
 CFATTACH_DECL2_NEW(uftdi, sizeof(struct uftdi_softc), uftdi_match,
     uftdi_attach, uftdi_detach, NULL, NULL, uftdi_childdet);
 
+struct uftdi_match_quirk_entry {
+	uint16_t	vendor_id;
+	uint16_t	product_id;
+	int		iface_no;
+	const char *	vendor_str;
+	const char *	product_str;
+	int		match_ret;
+};
+
+static const struct uftdi_match_quirk_entry uftdi_match_quirks[] = {
+	/*
+	 * The Tigard board (https://github.com/tigard-tools/tigard)
+	 * has two interfaces, one of which is meant to act as a
+	 * regular USB serial port (interface 0), the other of which
+	 * is meant for other protocols (SWD, JTAG, etc.).  We must
+	 * reject interface 1 so that ugenif matches, thus allowing
+	 * full user-space control of that port.
+	 */
+	{
+	  .vendor_id	= USB_VENDOR_FTDI,
+	  .product_id	= USB_PRODUCT_FTDI_SERIAL_2232C,
+	  .iface_no	= 1,
+	  .vendor_str	= "SecuringHardware.com",
+	  .product_str	= "Tigard V1.1",
+	  .match_ret	= UMATCH_NONE,
+	}
+};
+
+static int
+uftdi_quirk_match(struct usbif_attach_arg *uiaa, int rv)
+{
+	struct usbd_device *dev = uiaa->uiaa_device;
+	const struct uftdi_match_quirk_entry *q;
+	int i;
+
+	for (i = 0; i < __arraycount(uftdi_match_quirks); i++) {
+		q = &uftdi_match_quirks[i];
+		if (uiaa->uiaa_vendor != q->vendor_id ||
+		    uiaa->uiaa_product != q->product_id ||
+		    uiaa->uiaa_ifaceno != q->iface_no) {
+			continue;
+		}
+		if (q->vendor_str != NULL &&
+		    (dev->ud_vendor == NULL ||
+		     strcmp(dev->ud_vendor, q->vendor_str) != 0)) {
+			continue;
+		}
+		if (q->product_str != NULL &&
+		    (dev->ud_product == NULL ||
+		     strcmp(dev->ud_product, q->product_str) != 0)) {
+			continue;
+		}
+		/*
+		 * Got a match!
+		 */
+		rv = q->match_ret;
+		break;
+	}
+	return rv;
+}
+
 static int
 uftdi_match(device_t parent, cfdata_t match, void *aux)
 {
 	struct usbif_attach_arg *uiaa = aux;
+	int rv;
 
 	DPRINTFN(20,("uftdi: vendor=%#x, product=%#x\n",
 		     uiaa->uiaa_vendor, uiaa->uiaa_product));
@@ -195,8 +258,12 @@ uftdi_match(device_t parent, cfdata_t ma
 	if (uiaa->uiaa_configno != UFTDI_CONFIG_NO)
 		return UMATCH_NONE;
 
-	return uftdi_lookup(uiaa->uiaa_vendor, uiaa->uiaa_product) != NULL ?
+	rv = uftdi_lookup(uiaa->uiaa_vendor, uiaa->uiaa_product) != NULL ?
 		UMATCH_VENDOR_PRODUCT_CONF_IFACE : UMATCH_NONE;
+	if (rv != UMATCH_NONE) {
+		rv = uftdi_quirk_match(uiaa, rv);
+	}
+	return rv;
 }
 
 static void

Index: src/sys/dev/usb/usbdevices.config
diff -u src/sys/dev/usb/usbdevices.config:1.42 src/sys/dev/usb/usbdevices.config:1.43
--- src/sys/dev/usb/usbdevices.config:1.42	Tue Jun 29 10:22:37 2021
+++ src/sys/dev/usb/usbdevices.config	Tue Mar 26 03:38:02 2024
@@ -1,4 +1,4 @@
-#	$NetBSD: usbdevices.config,v 1.42 2021/06/29 10:22:37 nia Exp $
+#	$NetBSD: usbdevices.config,v 1.43 2024/03/26 03:38:02 thorpej Exp $
 #
 # This file contains all USB related configuration.
 # It is suitable for inclusion in a kernel config(5) file.
@@ -259,3 +259,10 @@ ugenif* at uhub? vendor 0x1050 product 0
 ugenif* at uhub? vendor 0x1050 product 0x0405 configuration 1 interface 1
 ugenif* at uhub? vendor 0x1050 product 0x0406 configuration 1 interface 1
 ugenif* at uhub? vendor 0x1050 product 0x0407 configuration 1 interface 2
+
+# Tigard debug board (FT2232C-based).  This line is used in conjunction
+# with a match quirk in uftdi.c.  The "flags 1" is important; normally
+# ugenif matches with higest priority, but we don't want that for all
+# FT2232C interfaces, only interfaces that go unclaimed by uftdi (which
+# is what the match quirk ensures).
+ugenif* at uhub? vendor 0x0403 product 0x6010 configuration 1 interface 1 flags 1

Reply via email to