[Nut-upsdev] Device argument for USB matching

Edgar Fuß ef at math.uni-bonn.de
Thu Feb 4 18:05:16 GMT 2021


I needed a "device" argument for USB matching in order to indepedently match two identical UPSen attached to the same bus.

I'll attach a patch. Is that the preferred way of proposing such a change?

The changes to usb-common.[hc] and libusb.c are straightforward (sans the DEBUG_EXACT_MATCH_DEVICE, which I modeled after DEBUG_EXACT_MATCH_BUS, whatever that is used for).
The changes to the various USB drivers are mechanical. Maybe some #define for the regex array size (or even seven more #defines for the magical index values) would be useful.
The line numbers in nutdrv.qx.c will not match yours; I've a much larger change (new driver) in there.
No changes to documentation yet.
-------------- next part --------------
diff -ru /tmp/nut-2.7.4/drivers/usb-common.h ./usb-common.h
--- /tmp/nut-2.7.4/drivers/usb-common.h	2015-12-29 13:08:34.000000000 +0100
+++ ./usb-common.h	2021-01-29 15:41:13.000000000 +0100
@@ -30,7 +30,7 @@
 
 /*!
  * USBDevice_t: Describe a USB device. This structure contains exactly
- * the 5 pieces of information by which a USB device identifies
+ * the pieces of information by which a USB device identifies
  * itself, so it serves as a kind of "fingerprint" of the device. This
  * information must be matched exactly when reopening a device, and
  * therefore must not be "improved" or updated by a client
@@ -44,6 +44,7 @@
 	char		*Product;  /*!< Device's Product Name */
 	char		*Serial;   /*!< Product serial number */
 	char		*Bus;      /*!< Bus name, e.g. "003"  */
+	char		*Device;   /*!< Device name, e.g. "001"  */
 	uint16_t	bcdDevice; /*!< Device release number */
 } USBDevice_t;
 
diff -ru /tmp/nut-2.7.4/drivers/usb-common.c ./usb-common.c
--- /tmp/nut-2.7.4/drivers/usb-common.c	2015-12-29 09:42:34.000000000 +0100
+++ ./usb-common.c	2021-01-29 15:40:26.000000000 +0100
@@ -103,6 +103,11 @@
 		return 0;
 	}
 #endif
+#ifdef DEBUG_EXACT_MATCH_DEVICE
+	if (strcmp_null(hd->Device, data->Device) != 0) {
+		return 0;
+	}
+#endif
 	return 1;
 }
 
@@ -138,6 +143,9 @@
 #ifdef DEBUG_EXACT_MATCH_BUS
 	data->Bus = hd->Bus ? strdup(hd->Bus) : NULL;
 #endif
+#ifdef DEBUG_EXACT_MATCH_DEVICE
+	data->Device = hd->Device ? strdup(hd->Device) : NULL;
+#endif
 	*matcher = m;
 
 	return 0;
@@ -160,6 +168,9 @@
 #ifdef DEBUG_EXACT_MATCH_BUS
 	free(data->Bus);
 #endif
+#ifdef DEBUG_EXACT_MATCH_DEVICE
+	free(data->Device);
+#endif
 	free(data);
 	free(matcher);
 }
@@ -271,7 +282,7 @@
 
 /* private data type: hold a set of compiled regular expressions. */
 typedef struct regex_matcher_data_s {
-	regex_t	*regex[6];
+	regex_t	*regex[7];
 } regex_matcher_data_t;
 
 /* private callback function for regex matches */
@@ -309,18 +320,23 @@
 	if (r != 1) {
 		return r;
 	}
+
+	r = match_regex(data->regex[6], hd->Device);
+	if (r != 1) {
+		return r;
+	}
 	return 1;
 }
 
 /* constructor: create a regular expression matcher. This matcher is
- * based on six regular expression strings in regex_array[0..5],
+ * based on seven regular expression strings in regex_array[0..6],
  * corresponding to: vendorid, productid, vendor, product, serial,
- * bus. Any of these strings can be NULL, which matches
+ * bus, device. Any of these strings can be NULL, which matches
  * everything. Cflags are as in regcomp(3). Typical values for cflags
  * are REG_ICASE (case insensitive matching) and REG_EXTENDED (use
  * extended regular expressions).  On success, return 0 and store the
  * matcher in *matcher. On error, return -1 with errno set, or return
- * i=1--6 to indicate that the regular expression regex_array[i-1] was
+ * i=1--7 to indicate that the regular expression regex_array[i-1] was
  * ill-formed (an error message can then be retrieved with
  * regerror(3)).
  */
@@ -345,7 +361,7 @@
 	m->privdata = (void *)data;
 	m->next = NULL;
 
-	for (i=0; i<6; i++) {
+	for (i=0; i<7; i++) {
 		r = compile_regex(&data->regex[i], regex[i], cflags);
 		if (r == -2) {
 			r = i+1;
@@ -372,7 +388,7 @@
 
 	data = (regex_matcher_data_t *)matcher->privdata;
 
-	for (i = 0; i < 6; i++) {
+	for (i = 0; i < 7; i++) {
 		if (!data->regex[i]) {
 			continue;
 		}
diff -ru /tmp/nut-2.7.4/drivers/libusb.c ./libusb.c
--- /tmp/nut-2.7.4/drivers/libusb.c	2015-12-29 13:08:34.000000000 +0100
+++ ./libusb.c	2021-01-29 15:31:33.000000000 +0100
@@ -63,6 +63,7 @@
 	addvar(VAR_VALUE, "productid", "Regular expression to match UPS Product numerical ID (4 digits hexadecimal)");
 
 	addvar(VAR_VALUE, "bus", "Regular expression to match USB bus name");
+	addvar(VAR_VALUE, "device", "Regular expression to match USB device name");
 	addvar(VAR_VALUE, "usb_set_altinterface", "Force redundant call to usb_set_altinterface() (value=bAlternateSetting; default=0)");
 }
 
@@ -198,11 +199,13 @@
 			free(curDevice->Product);
 			free(curDevice->Serial);
 			free(curDevice->Bus);
+			free(curDevice->Device);
 			memset(curDevice, '\0', sizeof(*curDevice));
 
 			curDevice->VendorID = dev->descriptor.idVendor;
 			curDevice->ProductID = dev->descriptor.idProduct;
 			curDevice->Bus = strdup(bus->dirname);
+			curDevice->Device = strdup(dev->filename);
 			curDevice->bcdDevice = dev->descriptor.bcdDevice;
 
 			if (dev->descriptor.iManufacturer) {
@@ -235,6 +238,7 @@
 			upsdebugx(2, "- Product: %s", curDevice->Product ? curDevice->Product : "unknown");
 			upsdebugx(2, "- Serial Number: %s", curDevice->Serial ? curDevice->Serial : "unknown");
 			upsdebugx(2, "- Bus: %s", curDevice->Bus ? curDevice->Bus : "unknown");
+			upsdebugx(2, "- Device: %s", curDevice->Device ? curDevice->Device : "unknown");
 			upsdebugx(2, "- Device release number: %04x", curDevice->bcdDevice);
 
 			if ((curDevice->VendorID == 0x463) && (curDevice->bcdDevice == 0x0202)) {
diff -ru /tmp/nut-2.7.4/drivers/blazer_usb.c ./blazer_usb.c
--- /tmp/nut-2.7.4/drivers/blazer_usb.c	2015-12-29 13:08:34.000000000 +0100
+++ ./blazer_usb.c	2021-01-29 15:20:42.000000000 +0100
@@ -522,7 +522,7 @@
 
 	int	ret, langid;
 	char	tbuf[255]; /* Some devices choke on size > 255 */
-	char	*regex_array[6];
+	char	*regex_array[7];
 
 	char	*subdrv = getval("subdriver");
 
@@ -532,6 +532,7 @@
 	regex_array[3] = getval("product");
 	regex_array[4] = getval("serial");
 	regex_array[5] = getval("bus");
+	regex_array[6] = getval("device");
 
 	/* check for language ID workaround (#1) */
 	if (getval("langid_fix")) {
diff -ru /tmp/nut-2.7.4/drivers/nutdrv_qx.c ./nutdrv_qx.c
--- /tmp/nut-2.7.4/drivers/nutdrv_qx.c	2016-03-08 13:01:11.000000000 +0100
+++ ./nutdrv_qx.c	2021-02-01 14:58:02.000000000 +0100
@@ -1930,7 +2006,7 @@
 
 		int	ret, langid;
 		char	tbuf[255];	/* Some devices choke on size > 255 */
-		char	*regex_array[6];
+		char	*regex_array[7];
 
 		char	*subdrv = getval("subdriver");
 
@@ -1940,6 +2016,7 @@
 		regex_array[3] = getval("product");
 		regex_array[4] = getval("serial");
 		regex_array[5] = getval("bus");
+		regex_array[6] = getval("device");
 
 		/* Check for language ID workaround (#1) */
 		if (getval("langid_fix")) {
diff -ru /tmp/nut-2.7.4/drivers/riello_usb.c ./riello_usb.c
--- /tmp/nut-2.7.4/drivers/riello_usb.c	2015-12-29 13:08:34.000000000 +0100
+++ ./riello_usb.c	2021-01-29 15:21:07.000000000 +0100
@@ -793,7 +793,7 @@
 	};
 
 	int	ret;
-	char	*regex_array[6];
+	char	*regex_array[7];
 
 	char	*subdrv = getval("subdriver");
 
@@ -803,6 +803,7 @@
 	regex_array[3] = getval("product");
 	regex_array[4] = getval("serial");
 	regex_array[5] = getval("bus");
+	regex_array[6] = getval("device");
 
 	/* pick up the subdriver name if set explicitly */
 	if (subdrv) {
diff -ru /tmp/nut-2.7.4/drivers/tripplite_usb.c ./tripplite_usb.c
--- /tmp/nut-2.7.4/drivers/tripplite_usb.c	2015-12-29 13:08:34.000000000 +0100
+++ ./tripplite_usb.c	2021-01-29 15:21:26.000000000 +0100
@@ -1429,7 +1429,7 @@
  */
 void upsdrv_initups(void)
 {
-	char *regex_array[6];
+	char *regex_array[7];
 	char *value;
 	int r;
 
@@ -1440,6 +1440,7 @@
 	regex_array[3] = getval("product"); /* product string */
 	regex_array[4] = getval("serial"); /* probably won't see this */
 	regex_array[5] = getval("bus");
+	regex_array[6] = getval("device");
 
 	r = USBNewRegexMatcher(&regex_matcher, regex_array, REG_ICASE | REG_EXTENDED);
 	if (r==-1) {
diff -ru /tmp/nut-2.7.4/drivers/usbhid-ups.c ./usbhid-ups.c
--- /tmp/nut-2.7.4/drivers/usbhid-ups.c	2015-12-29 13:08:34.000000000 +0100
+++ ./usbhid-ups.c	2021-01-29 15:21:44.000000000 +0100
@@ -920,7 +920,7 @@
 
 	subdriver_matcher = device_path;
 #else
-	char *regex_array[6];
+	char *regex_array[7];
 
 	upsdebugx(1, "upsdrv_initups...");
 
@@ -943,6 +943,7 @@
 	regex_array[3] = getval("product");
 	regex_array[4] = getval("serial");
 	regex_array[5] = getval("bus");
+	regex_array[6] = getval("device");
 
 	ret = USBNewRegexMatcher(&regex_matcher, regex_array, REG_ICASE | REG_EXTENDED);
 	switch(ret)


More information about the Nut-upsdev mailing list