Thanks Arjen,

I hadn't previously looked into libusb, but is there a reason why the filename 
member of usb_device is't matched on?  On linux, they may not be unique or 
deterministic in theory --- but in practice they are, particularly for 
servers where you're not constantly plugging in and out devices.

Am I missing something in the logic, or do I just have an unusual case?

I've written up a patch that works for me -- it pulls out the filename from 
the usb_device, and matches it with a file= parameter for ups.conf. I'd guess 
that a better long-term solution would be to have upsdrv listen to hal for 
ups's that are connecting -- but that would obviously be a lot more work, and 
it requires mucking up the server with hal stuff.

Regards,
Alex Peyser

On Thursday 05 June 2008 08:01:32 am 
[EMAIL PROTECTED] wrote:

> Message: 1
> Date: Wed, 4 Jun 2008 19:22:56 -0400
> From: Alex Peyser <[EMAIL PROTECTED]>
> Subject: [Nut-upsuser] Multiple ups/Belkin 1500VA no serial number
> To: [email protected]
> Message-ID: <[EMAIL PROTECTED]>
> Content-Type: text/plain; charset="us-ascii"
>
> I'm setting up a cluster with multiple ups's using nut 2.2. The ups's are
> Belkin 1500 (ID 050d:0751) which don't appear to report a serial number. Is
> there any other way I can setup ups.conf with multiple of these ups over
> usb on Linux?
>
> If I just setup the vendor and product id's, every definition in ups.conf
> appears to match the first one, and therefore all of them but the first one
> fails. Is there some undocumented matcher I can use to distinguish them, or
> some flag to tell the ups to simple skip ups that have already been
> matched?
>
> Regards,
> Alex Peyser
> -------------- next part --------------
> A non-text attachment was scrubbed...
> Name: not available
> Type: application/pgp-signature
> Size: 189 bytes
> Desc: This is a digitally signed message part.
> Url :
> http://lists.alioth.debian.org/pipermail/nut-upsuser/attachments/20080604/8
>597976d/attachment-0001.pgp
>
> ------------------------------
>
> Message: 2
> Date: Thu, 5 Jun 2008 08:45:11 +0200 (CEST)
> From: "Arjen de Korte" <[EMAIL PROTECTED]>
> Subject: Re: [Nut-upsuser] Multiple ups/Belkin 1500VA no serial number
> To: "Alex Peyser" <[EMAIL PROTECTED]>
> Cc: [email protected]
> Message-ID:
>       <[EMAIL PROTECTED]>
> Content-Type: text/plain;charset=iso-8859-1
>
> > I'm setting up a cluster with multiple ups's using nut 2.2. The ups's are
> > Belkin 1500 (ID 050d:0751) which don't appear to report a serial number.
> > Is there any other way I can setup ups.conf with multiple of these ups
> > over usb on Linux?
> >
> > If I just setup the vendor and product id's, every definition in ups.conf
> > appears to match the first one, and therefore all of them but the first
> > one  fails. Is there some undocumented matcher I can use to distinguish
> > them, or some flag to tell the ups to simple skip ups that have already
> > been matched?
>
> The 'libusb' library doesn't provide the physical port number these
> devices are connected to, so if you can't tell them apart through the
> regular expressions, this isn't possible. Which in your case means, that
> each UPS must have its own USB *root* device, as the only difference will
> be the USB bus they're connected to. You can't monitor two devices that
> are looking identical from the same USB bus.
>
> Best regards, Arjen


diff -Naur nut-2.2.2/drivers/libshut.c nut-2.2.2-new/drivers/libshut.c
--- nut-2.2.2/drivers/libshut.c	2007-12-16 14:46:35.000000000 -0500
+++ nut-2.2.2-new/drivers/libshut.c	2008-06-05 11:14:12.000000000 -0400
@@ -347,12 +347,14 @@
 	free(curDevice->Product);
 	free(curDevice->Serial);
 	free(curDevice->Bus);
+	free(curDevice->File);
 	memset(curDevice, '\0', sizeof(*curDevice));
 
 	curDevice->VendorID = dev_descriptor->idVendor;
 	curDevice->ProductID = dev_descriptor->idProduct;
 	curDevice->Vendor = strdup("MGE UPS SYSTEMS");
 	curDevice->Bus = strdup("serial");
+	curDevice->File = strdup("serial");
 
 	if (dev_descriptor->iProduct) {
 		ret = shut_get_string_simple(*upsfd, dev_descriptor->iProduct, string, 0x25);
@@ -384,6 +386,7 @@
 	upsdebugx(2, "- Product: %s", curDevice->Product);
 	upsdebugx(2, "- Serial Number: %s", curDevice->Serial);
 	upsdebugx(2, "- Bus: %s", curDevice->Bus);
+	upsdebugx(2, "- File: %s", curDevice->File);
 	upsdebugx(2, "Device matches");
 
 	/* Get HID descriptor */
diff -Naur nut-2.2.2/drivers/libshut.h nut-2.2.2-new/drivers/libshut.h
--- nut-2.2.2/drivers/libshut.h	2007-12-16 14:46:35.000000000 -0500
+++ nut-2.2.2-new/drivers/libshut.h	2008-06-05 11:19:20.000000000 -0400
@@ -31,7 +31,7 @@
 
 /*!
  * SHUTDevice_t: Describe a SHUT device. This structure contains exactly
- * the 5 pieces of information by which a SHUT device identifies
+ * the 6 pieces of information by which a SHUT 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
@@ -45,6 +45,7 @@
 	char*		Product; /*!< Device's Product Name */
 	char*		Serial; /* Product serial number */
 	char*		Bus;    /* Bus name, e.g. "003" */
+	char*		File;    /* File name, e.g. "003" */
 } SHUTDevice_t;
 
 /*!
diff -Naur nut-2.2.2/drivers/libusb.c nut-2.2.2-new/drivers/libusb.c
--- nut-2.2.2/drivers/libusb.c	2007-12-11 15:15:47.000000000 -0500
+++ nut-2.2.2-new/drivers/libusb.c	2008-06-05 11:12:56.000000000 -0400
@@ -131,11 +131,13 @@
 			free(curDevice->Product);
 			free(curDevice->Serial);
 			free(curDevice->Bus);
+			free(curDevice->File);
 			memset(curDevice, '\0', sizeof(*curDevice));
 
 			curDevice->VendorID = dev->descriptor.idVendor;
 			curDevice->ProductID = dev->descriptor.idProduct;
 			curDevice->Bus = strdup(bus->dirname);
+			curDevice->File = strdup(dev->filename);
 			
 			if (dev->descriptor.iManufacturer) {
 				ret = usb_get_string_simple(udev, dev->descriptor.iManufacturer,
@@ -167,6 +169,8 @@
 			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, "- File: %s", curDevice->File ? curDevice->File : "unknown");
+
 
 			upsdebugx(2, "Trying to match device");
 			for (m = matcher; m; m=m->next) {
@@ -482,6 +486,10 @@
 		return 0;
 	}
 #endif
+	if (strcmp_null(hd->File, data->File) != 0) {
+		return 0;
+	}
+
 	return 1;
 }
 
@@ -517,6 +525,7 @@
 #ifdef DEBUG_EXACT_MATCH_BUS
 	data->Bus = hd->Bus ? strdup(hd->Bus) : NULL;
 #endif
+	data->File = hd->File ? strdup(hd->File) : NULL;
 	*matcher = m;
 
 	return 0;
@@ -539,6 +548,7 @@
 #ifdef DEBUG_EXACT_MATCH_BUS
 	free(data->Bus);
 #endif
+	free(data->File);
 	free(data);
 	free(matcher);
 }
@@ -691,13 +701,18 @@
 	if (r != 1) {
 		return r;
 	}
+
+	r = match_regex(data->regex[6], hd->File);
+	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, file. 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
@@ -727,7 +742,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;
diff -Naur nut-2.2.2/drivers/libusb.h nut-2.2.2-new/drivers/libusb.h
--- nut-2.2.2/drivers/libusb.h	2007-12-16 14:46:35.000000000 -0500
+++ nut-2.2.2-new/drivers/libusb.h	2008-06-05 11:18:22.000000000 -0400
@@ -52,6 +52,7 @@
 	char*		Product; /*!< Device's Product Name */
 	char*		Serial; /* Product serial number */
 	char*		Bus;    /* Bus name, e.g. "003" */
+        char*           File; /* File name, e.g. "003" */
 } USBDevice_t;
 
 /*!
diff -Naur nut-2.2.2/drivers/usbhid-ups.c nut-2.2.2-new/drivers/usbhid-ups.c
--- nut-2.2.2/drivers/usbhid-ups.c	2008-04-22 14:04:43.000000000 -0400
+++ nut-2.2.2-new/drivers/usbhid-ups.c	2008-06-05 11:15:41.000000000 -0400
@@ -73,7 +73,7 @@
 
 /* Global vars */
 static HIDDevice_t *hd = NULL;
-static HIDDevice_t curDevice = { 0x0000, 0x0000, NULL, NULL, NULL, NULL };
+static HIDDevice_t curDevice = { 0x0000, 0x0000, NULL, NULL, NULL, NULL, NULL};
 static HIDDeviceMatcher_t *subdriver_matcher = NULL;
 #ifndef SHUT_MODE
 static HIDDeviceMatcher_t *exact_matcher = NULL;
@@ -699,6 +699,7 @@
 	addvar(VAR_VALUE, "vendorid", "Regular expression to match UPS Manufacturer numerical ID (4 digits hexadecimal)");
 	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, "file", "Regular expression to match USB file name");
 	addvar(VAR_VALUE, "matching", "Use 'normal' or 'delayed' matching");
 	addvar(VAR_FLAG, "explore", "Diagnostic matching of unsupported UPS");
 #endif
@@ -864,7 +865,7 @@
 
 	subdriver_matcher = device_path;
 #else
-	char *regex_array[6];
+	char *regex_array[7];
 	matching_lkp_t	*key;
 
 	upsdebugx(1, "upsdrv_initups...");
@@ -883,6 +884,7 @@
 	regex_array[3] = getval("product");
 	regex_array[4] = getval("serial");
 	regex_array[5] = getval("bus");
+	regex_array[6] = getval("file");
 
 	ret = USBNewRegexMatcher(&regex_matcher, regex_array, REG_ICASE | REG_EXTENDED);
 	switch(ret)
@@ -955,6 +957,7 @@
 	free(curDevice.Product);
 	free(curDevice.Serial);
 	free(curDevice.Bus);
+	free(curDevice.File);
 #endif
 }
 
@@ -1096,6 +1099,7 @@
 		upsdebugx(2, "- Product: %s", hd->Product ? hd->Product : "unknown");
 		upsdebugx(2, "- Serial Number: %s", hd->Serial ? hd->Serial : "unknown");
 		upsdebugx(2, "- Bus: %s", hd->Bus ? hd->Bus : "unknown");
+		upsdebugx(2, "- File: %s", hd->File ? hd->File : "unknown");
 
 		for (m = regex_matcher; m; m = m->next) {
 			ret = matches(m, hd);

Attachment: signature.asc
Description: This is a digitally signed message part.

_______________________________________________
Nut-upsuser mailing list
[email protected]
http://lists.alioth.debian.org/mailman/listinfo/nut-upsuser

Reply via email to