[Nut-upsdev] Liebert PowerSure PSA 500

Peter Selinger selinger at mathstat.dal.ca
Wed Sep 7 14:51:01 UTC 2005


Jochen Bern wrote:
> 
> Hello everyone, Charles suggested (about a week ago) that I repost to 
> this list. I took a moment to run some additional tests ...
> 
> The basics:
> -- UPS: Liebert PowerSure PSA 500 (from the 230 VAC / 50 Hz line)
> -- Kernel: 2.6.11.5 (from sources), USB support (down to and including
>     CONFIG_USB_HIDDEV) compiled in statically (not as a module)
> -- Rest of OS: Basically still from the original SuSE 9.1 install :-/
> -- Connection: USB cable (as supplied by Liebert)
> -- NUT: Tried both 2.0.2 and 2.1.0
> 
> The situation:
> 
> 1. INITIAL STATE (e.g., after reboot):
> 
> -- /proc/bus/usb/devices (excerpt below) lists kernel (usbhid) as the
>     driver in use.

This means that the kernel has attached a driver to your USB. At any
time, at most one driver can be attached to a USB device, which is
either a kernel driver or a user-space driver (such as NUT). 

> -- lsusb -v claims it "cannot get report descriptor".

This is because the kernel driver is attached, and lsusb can't attach
itself to this device. 

> -- newhidups driver doesn't recognize the UPS:
> 	# bin/newhidups -DD -a PowerSure
> 	Network UPS Tools: New USB/HID UPS driver 0.27 (2.1.0)
> 
> 	debug level is '2'
> 	Opening new device (0000/0000)
> 	Opening new device (0000/0000)
> 	Opening new device (0000/0000)
> 	Opening new device (10AF/0001)
> 	Opening new device (0000/0000)
> 	Opening new device (0000/0000)
> 	found 0 (-1)
> 	No USB/HID UPS found
>     (Changes to /etc/hotplug/ have been made as instructed. Note that
>     the UPS *does* get probed (the non-zero device ID).)

This is to be expected. The newhidups / libusb code is fairly ugly in
that it is not modular - when you add support for a new device, you
need to edit a million files. You should first look at the file
driver/libusb.c. In line 116 or thereabouts, you will see a statement
such as:

                          if ((dev->descriptor.idVendor == MGE_UPS_SYSTEMS)
                                  || (dev->descriptor.idVendor == APC))

This means that in nut-2.0.2, *only* MGE and APC devices will be
opened. Maybe in nut-2.1.0 there could be additional vendors listed
there. The first thing you should do is change this to

                          if ((dev->descriptor.idVendor == MGE_UPS_SYSTEMS)
                                  || (dev->descriptor.idVendor == APC)
                                  || (dev->descriptor.idVendor == LIEBERT)
					)

and then you should also add a line under "Supported Nanufacturers
IDs" in drivers/newhidups.h:

#define LIEBERT                   0x10af          /* All models */

At this point, at least your device should be opened, although not
much useful will happen yet. If you run your "bin/newhidups -DD -a
PowerSure", at least you should get a listing of the UPS's Usage Tree. 

Next, look at line 391 (or thereabouts) of drivers/newhidups.c. You
will see a case distinction:

        switch (hd->VendorID)
        {
                case MGE_UPS_SYSTEMS:
			...
                break;
                case APC:
                        ...
                break;
                case MUSTEK:
                case TRIPPLITE:
                case UNITEK:
                default:
                        ...
                        fatalx("Aborting");
                break;
        }

You should add your vendor here as well. Then you also need to add a
new file drivers/liebert-hid.h, modeled on drivers/apc-hid.h, changing
APC to LIEBERT everywhere, and making sure this new file is also
#include'd in drivers/newhidups.c. Then you have to customize that file.

> -- hidups driver can connect to the UPS, but *dies* whenever it changes
>     state:
> 	# bin/hidups -DD -a PowerSure
> 	[...]
> 	Detected Liebert Liebert PSA 500 FW:09
> 	on port /dev/usb/hiddev0
> 	addhidvalue(850066, battery.charge): obtained 0
> 	addhidvalue(850068, battery.runtime): obtained 0
> 	[... pulling mains cable]
> 	read: Input/output error
>     (I'm still trying to obtain info from Liebert whether those two
>     values plus ups.status are actually *all* the data the UPS offers.)
> -- UPS has changed bus ID from 2:2 to 2:6 after the experiment. (Note
>     that I pulled the cable *twice* to verify some detail ...)

That is normal. When you unplug and re-plug the UPS, it gets assigned
a new bus ID. This can also sometimes be caused by software that
"resets" the device.

> 2. RECLAIMED STATE
> 
> -- entered by running "get_descriptor 002 006 0 0 0 128 0x22 0" (code at
>     lists.alioth.debian.org/pipermail/nut-upsdev/2005-August/000088.html,
>     output below)

The get_descriptor program detaches the kernel driver (see above)
before it opens the device. This is the reason that *after* running
get_descriptor, you suddenly get a lot more useful output from lsusb
and other such programs.

> -- /proc/bus/usb/devices (excerpt below) now lists "(none)" as driver

Yes, because the kernel driver has been detached by get_descriptor.

> -- lsusb -v now lists the entire spiel (output below)
> -- no change for newhidups driver (still doesn't recognize the UPS)
> -- hidups driver can't connect to the UPS anymore:
> 	# bin/hidups -DD -a PowerSure
> 	Network UPS Tools: HID UPS driver 0.13 (2.1.0)
> 
> 	Warning: This is an experimental driver.
> 	Some features may not function correctly.
> 
> 	debug level is '2'
> 	hiddev path open /dev/usb/hiddev0: No such device

I suspect that unlike newhidups, the old hidups actually relies on the
kernel driver, as it is probably the kernel driver that provides the
/dev/usb/hiddev0 interface.

> 3. FUBARED STATE
> 
> -- Entered by once more pulling&reinserting mains cable, which again
>     changes the device ID (to 2:8). (Will have to do more testing to see
>     whether it can cause a direct Initial->FUBARed state change, too.)
> -- /proc/bus/usb/devices (excerpt below) is back to "usbhid"
> -- a simple "lsusb -v" lists the UPS (again with "cannot get report
>     descriptor"), while "lsusb -v -s 2:8" gives no output at all :-?
> -- still no change with the newhidups driver
> -- hidups driver is back to initial state behavior, including the I/O
>     error as soon as I pull the mains (which takes the device ID to 2:10,
>     with no further change of state)
> 
> I could probably have the hidups driver started from inittab with a 
> "respawn" label to get NUT running reliably (sorta), but that's as ugly 
> as a kludge can get. ;-) Does anyone have an idea for an alternative?
> 
> Kind regards,
> 								J. Bern
> 
> ========================================================================
> 
> [initial state] # grep -A 4 -B 3 Liebert /proc/bus/usb/devices
> T:  Bus=02 Lev=01 Prnt=01 Port=01 Cnt=01 Dev#=  2 Spd=1.5 MxCh= 0
> D:  Ver= 1.10 Cls=00(>ifc ) Sub=00 Prot=00 MxPS= 8 #Cfgs=  1
> P:  Vendor=10af ProdID=0001 Rev= 5.00
> S:  Manufacturer=Liebert
> S:  Product=Liebert PSA 500 FW:09
> S:  SerialNumber=0507600440BA069
> C:* #Ifs= 1 Cfg#= 1 Atr=c0 MxPwr= 20mA
> I:  If#= 0 Alt= 0 #EPs= 1 Cls=03(HID  ) Sub=00 Prot=00 Driver=usbhid
> E:  Ad=81(I) Atr=03(Int.) MxPS=   8 Ivl=248ms
> 
> ========================================================================
> 
> [initial state] # ./get_descriptor 002 006 0 0 0 128 0x22 0
> Bus 002 device 006 configuration 0 interface 0 altsetting 0 endpoint 128 
> descriptor 0x22 index 0:
> 
>   05 84 09 04 a1 01 05 86 09 26 a1 02 85 01 75 08 95 01 15 00 26 ff 00 09
>   40 b1 02 85 02 09 42 b1 02 85 03 75 10 15 00 27 ff ff 00 00 09 43 b1 02
>   85 04 09 44 b1 02 c0 05 86 09 29 a1 02 75 08 95 01 15 00 26 ff 00 85 0d
>   09 75 b1 02 85 0e 09 76 b1 02 85 0f 09 7c b1 02 c0 05 86 09 27 a1 02 85
>   10 75 08 95 01 15 00 26 ff 00 09 58 b1 02 85 11 09 5a b1 02 85 15 75 10
>   95 01 15 00 27 ff ff 00 00 09 57 b1 02 85 16 09 56 b1 02 85 40 75 08 95
>   01 15 00 26 ff 00 09 80 b1 02 85 41 09 81 b1 02 85 42 09 82 b1 02 85 43
>   09 83 b1 02 85 44 09 84 b1 02 c0 05 86 09 2a a1 02 09 1a a1 02 85 18 75
>   10 95 01 65 00 55 00 15 00 27 ff ff 00 00 09 30 b1 02 85 19 09 32 b1 02
>   85 1a 75 08 15 00 26 ff 00 09 36 b1 02 c0 09 1c a1 02 85 1b 75 10 95 01
>   15 00 27 ff ff 00 00 09 30 b1 02 85 1c 09 32 b1 02 85 1e 75 08 95 01 15
>   00 26 ff 00 09 35 b1 02 c0 c0 05 86 09 10 a1 02 05 86 85 20 75 10 95 01
>   15 00 27 ff ff 00 00 09 30 b1 02 85 21 75 08 95 01 15 00 26 ff 00 09 39
>   b1 02 c0 05 86 09 28 a1 02 85 22 75 10 95 01 15 00 27 ff ff 00 00 09 21
>   b1 02 85 23 75 08 95 01 15 00 26 ff 00 09 22 b1 02 c0 05 84 09 24 a1 00
>   85 28 09 fe 79 14 75 08 95 01 15 00 26 ff 00 b1 02 85 29 09 ff 79 16 b1
>   02 05 85 85 2a 09 89 79 1a b1 02 85 2b 09 8f 79 04 b1 02 85 2c 09 8b b1
>   02 85 2d 09 44 75 08 95 01 81 82 09 44 b1 82 85 2e 09 45 81 82 09 45 b1
>   82 05 84 85 30 09 40 75 10 95 01 27 fe ff 00 00 b1 02 85 31 09 30 b1 02
>   85 32 09 31 75 08 95 01 26 ff 00 b1 02 05 85 85 33 09 2c b1 02 85 34 09
>   66 81 82 09 66 b1 82 85 35 09 68 75 10 95 01 27 fe ff 00 00 81 82 09 68
>   b1 82 85 36 75 08 95 01 26 ff 00 09 83 b1 02 85 37 09 67 b1 02 85 38 09
>   8c b1 02 85 39 09 8e b1 02 85 3a 09 29 b1 82 85 3b 09 8d b1 02 85 3c 09
>   d0 b1 82 09 d0 81 82 85 3d 09 42 81 82 09 42 b1 82 85 3e 05 84 09 69 81
>   82 09 69 b1 82 05 85 85 3f 09 6c 75 10 95 01 27 fe ff 00 00 15 00 b1 82
>   c0 c0

This is a good report descriptor. You should be able to get a useable
Usage Tree if you run newhidups with debug level 2 as above, after
making the above modifications.


Comment to newhidups developers:
--------------------------------

The usage tree that he will generate will contain a lot of Usages such
as 00860044, which are (1) wrongly encoded (the manufacturer should
have used ff86XXXX), and (2) already taken (probably with different
meanings) by Belkin. Perhaps it is time to modularize the newhidups.c
code, so that all manufacturer specific code goes in a single file
(say XXX-hid.c), rather than being spread out over several case
distrinctions sprinkled throughout the code (newhidups.h, newhidups.c,
libusb.c, libhid.c, ...). In particular, the manufacturer specific
Usage tags most definitely do not belong in libhid.c; soon these tags
will start to overlap between different manufacturers.

Re-organizing the code along these lines would not be too difficult,
but it would make adding new devices much easier. Also, the structure
of *.c and *.h files should probably be cleaned up so that *.h files
contain only headers (rather than code and data, as is currently the
case). 

I guess any decision on that will have to wait until Arnaud gets back
from vacation. 

-- Peter



More information about the Nut-upsdev mailing list