Apcupsd's Support for USB UPSes

General

Apcupsd version 3.9.8 or later (development version to be released as 3.10.0) provides direct support for USB UPSes on Linux systems only. To run apcupsd with a USB UPS, you need the following things: At the current time (August 2002), apcupsd supports USB on Linux systems only. This is because there is no standard USB programming interface and USB on the majority of machines other than Windows and Linux is currently under development and not stable.

Indirect USB Support -- Connecting a Serial port UPS to a USB port

By using a special adaptor, you can connect your serial UPS to a USB port (note, this works only if you do NOT have a USB enabled UPS). If you would like to free up your serial port and connect your existing serial port UPS to a USB port, it is possible if you have one of the later kernels. You simply get a serial to USB adapter that is supported by the kernel, plug it in and make one minor change to your apcupsd.conf file and away you go. Thanks to Joe Acosta for this out to me.

The device that Joe and I are using is IOgear guc232a USB 2 serial adapter. There may be other adapters that work equally well. If you know of one, please let us know.

At my site, running RedHat 7.1 with kernel 2.4.9-12, I simply changed my /etc/apcupsd/apcupsd.conf configuration line to be:

DEVICE /dev/ttyUSB0

Depending on whether or not you have hotplug working, you may need to explicitly load the kernel modules usbserial and

pl2303. In my case, this was not necessary.

Direct support for USB UPSes

The rest of this chapter concerns making apcupsd work by connecting your USB enabled UPS directly to a USB port on your Linux machine.

Please note if you have cable number 940-0128A, your UPS will be connected to your serial port as a standard serial UPS and the rest of this chapter will not apply to your case.

Getting and Building a Kernel

Please note that a number of Linux packagers are including Alan Cox's patches in their standard releases. This is true for RedHat 7.1, 7.2, and 7.3 if you have the latest kernel updates. As a consequence before getting and building your own kernel, if you are already running a 2.4.5 kernel or later, please check whether or not it already has the necessary USB updates. This can be done by creating the device files and running the USB test program as described below.

For some very brief instructions on how to get and build your kernel, see the Kernel Configuration section of this manual. More information on configuring a kernel can be found in the kernel-HOWTO do.

Making the Device Files

Once you have your kernel installed and working, you need to define the hiddev device files if they are not already present on your system. This can be done by invoking the script in <apcupsd-src>/examples/make-hiddev, which does the following:
#!/bin/sh
mkdir -p /dev/usb/hid
mknod /dev/usb/hid/hiddev0 c 180 96
mknod /dev/usb/hid/hiddev1 c 180 97
mknod /dev/usb/hid/hiddev2 c 180 98
mknod /dev/usb/hid/hiddev3 c 180 99
mknod /dev/usb/hid/hiddev4 c 180 100
mknod /dev/usb/hid/hiddev5 c 180 101
mknod /dev/usb/hid/hiddev6 c 180 102
mknod /dev/usb/hid/hiddev7 c 180 103
mknod /dev/usb/hid/hiddev8 c 180 104
mknod /dev/usb/hid/hiddev9 c 180 105
mknod /dev/usb/hid/hiddev10 c 180 106
mknod /dev/usb/hid/hiddev11 c 180 107
mknod /dev/usb/hid/hiddev12 c 180 108
mknod /dev/usb/hid/hiddev13 c 180 109
mknod /dev/usb/hid/hiddev14 c 180 110
mknod /dev/usb/hid/hiddev15 c 180 111
Note, as of RedHat 8.0, the hiddev devices are defined when the OS is installed, except they are defined as /dev/usb/hiddev0 - 15. Thus you will either need to run the above script and stick with our scheme, or you can choose to use the standard RedHat definitions. If you go with the Red Hat locations, you will probanly have to change the DEVICE entry in your apcupsd.conf file by hand.

Installing the HIDDEV Header File

If you have built the kernel, you must put a copy of hiddev.h into /usr/include. Use the following:
cd /usr/src<kernel-source-directory>/
cp include/linux/hiddev.h /usr/include/linux/
This step should not be necessary if you have a preconfigured kernel as long as you have loaded the kernel-headers rpm.

Building the Test Program

Next, we recommend that you build and run the hid-ups test program. To build it enter:
cd <apcupsd-src>/examples
make hid-ups
There should be no errors.

Now assuming that everything has gone well to this point and that you have connected your USB UPS, enter:
./hid-ups
It should print a sample report of the information that it has obtained from your UPS. CAUTION! Do not run two copies of this program at the same time, or your kernel will freeze.

The report that is printed should look very similar to the report in <src>/hid-ups.rpt.

If the program reports that the device was not found ensure that all the appropriate modules are loaded as described in the Kernel Configuration section of this manual, then unplug your UPS and plug it back in. This should permit the kernel to recognize the UPS.

If ./hid-ups tells you "No permission, try this as root", you know what to try. If it says "Couldn't find USB UPS device, check your /dev.", then it is very unlikely that apcupsd will work. You probably need to run the script "make-hiddev" before continuing.

Building and Installing apcupsd

If you have gotten this far successfully, the last step should go fairly easily. You need a beta version 3.9.4 or later of apcupsd. We recommend version 3.10.5 or later. Follow the instructions in the Installation Chapter of this manual, being sure to include the following options (in addition to any others you need) on the ./configure line:
  ./configure \
  --with-serial-dev=/dev/usb/hid/hiddev[0-15] \
  --with-upstype=usb \
  --with-upscable=usb \
  --enable-pthreads \
  --enable-usb
Please note, it is IMPORTANT to include the --with-serial-dev=/dev/usb/hid/hiddev[0-15] \ line. This will cause the apcupsd.conf file to contain:
DEVICE /dev/usb/hid/hiddev[0-15]
If you are on a Red Hat system and sticking to the Red Hat naming scheme, however, the --with0serial-dev option needs to be /dev/usb/hiddev[0-15]. The [0-15] is not a typo, but should be entered exactly as shown. This is because the UPS can change device numbers while it is running. Every time there is a blip or slowdown on the USB line, the kernel will invalidate the UPS connection, then a few moments later, it will reconnect but with a different device number. Not very Unix like, but that is what happens. This bizarre syntax allows apcupsd to try a range of devices until it finds or re-finds the UPS device.

USB Specific Information

The UPS has an internal set of timers and remaining capacity counters, which it uses to determine when to shutdown. These are in addition to the apcupsd counters BATTERYLEVEL and MINUTES. As a consequence, apcupsd will shutdown on the first limit that triggers (either an apcupsd limit, or a UPS limit).

The UPS internal counter equivalent to BATTERYLEVEL can be found in the hid-ups report as RemainingCapacityLimit, which is typically factory set to 10 percent. In addition, the Low Battery signal is normally given by the UPS when less than 2 minutes of run time remain.

If you are technically inclined, you may want to look at the /proc file system to see what devices are attached to your USB ports. The most interesting information will be found by listing the contents of /proc/bus/usb/devices. This information is updated by the kernel whenever a device is plugged in or unplugged, irrespective of whether apcupsd is running or not. To interpret the codes in this file, please see http://www.linuxhq.com/kernel/v2.4/doc/usb/proc_usb_info.txt.html

As a reference, on my system, I have the following entry for my Back-UPS 350 direct connected USB device:

T:  Bus=01 Lev=01 Prnt=01 Port=00 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=051d ProdID=0002 Rev= 1.00
S:  Manufacturer=American Power Conversion
S:  Product=Back-UPS 350 FW: 5.2.I USB FW: c1 
S:  SerialNumber=BB0115017954
C:* #Ifs= 1 Cfg#= 1 Atr=a0 MxPwr= 30mA
I:  If#= 0 Alt= 0 #EPs= 1 Cls=03(HID  ) Sub=00 Prot=00 Driver=hid
E:  Ad=81(I) Atr=03(Int.) MxPS=   8 Ivl= 10ms

And for my IOgear that runs my serial SmartUPS 1000 (plugged into a USB port):

T:  Bus=01 Lev=01 Prnt=01 Port=01 Cnt=02 Dev#=  4 Spd=12  MxCh= 0
D:  Ver= 1.10 Cls=00(>ifc ) Sub=00 Prot=00 MxPS= 8 #Cfgs=  1
P:  Vendor=0557 ProdID=2008 Rev= 0.01
C:* #Ifs= 1 Cfg#= 1 Atr=a0 MxPwr=100mA
I:  If#= 0 Alt= 0 #EPs= 3 Cls=ff(vend.) Sub=00 Prot=00 Driver=serial
E:  Ad=81(I) Atr=03(Int.) MxPS=  10 Ivl=  1ms
E:  Ad=02(O) Atr=02(Bulk) MxPS=  64 Ivl=  0ms
E:  Ad=83(I) Atr=02(Bulk) MxPS=  64 Ivl=  0ms

Note that the IOgear device is using the serial driver (the I: line) while the Back-UPS 350 is using the hid driver.

Here is an example of a cat /proc/modules on my machine (RedHat 7.1 - kernel 2.4.9-12). Note, I am running both an IOGear serial USB device and a standard USB device.

nfs                    77312   9 (autoclean)
es1371                 26816   0 (autoclean)
ac97_codec              9376   0 (autoclean) [es1371]
gameport                1856   0 (autoclean) [es1371]
soundcore               4144   4 (autoclean) [es1371]
nfsd                   69920   4 (autoclean)
lockd                  51664   1 (autoclean) [nfs nfsd]
sunrpc                 62832   1 (autoclean) [nfs nfsd lockd]
parport_pc             14736   1 (autoclean)
lp                      6176   0 (autoclean)
parport                24832   1 (autoclean) [parport_pc lp]
autofs                 10784   1 (autoclean)
nls_iso8859-1           2880   1 (autoclean)
smbfs                  35344   1 (autoclean)
3c59x                  26336   1 (autoclean)
ipchains               36704   0
pl2303                  7648   1
hid                    18576   1
usbserial              18288   1 [pl2303]
input                   3648   0 [hid]
usb-uhci               21568   0 (unused)
usbcore                50784   1 [pl2303 hid usbserial usb-uhci]

I am not a kernel expert, but for a standard USB connection, I believe that you need the following modules loaded:

usbcore
input
hid

For the IOGear serial USB connection, you need:

usbcore
usbserial
pl2303

Known Problems

Lock File not Released if UPS Disconnected

If either you disconnect the UPS or it disconnects because of some electrical problem, it will most certainly reconnect with a different device number. Apcupsd will detect this and reconnect properly. However, apcupsd does not release the old device (serial port) lock file and create a new one. This is not too serious.

Reinitialization If You Connect a Different UPS

If you disconnect the UPS and plug in a different one or a different model, it will continue to function properly, but in apcupsd version 3.9.4 the static data such as the UPS name, model, serial number, and firmware will not be updated. Versions 3.9.6 and greater detect the change and do a complete reinitialization of the UPS and so do not have this problem.

Power Off (killpower) of UPS Does Not Work

Currently (as of 3.10.5) the code to power off the UPS does not function properly. It does not look like a solution to this problem will be available until 2.5 of the kernel is released. In the mean time, the UPS will normally power itself down one to two minutes after the machine is shutdown.

Apcupsd Cannot Reconnect After a Reboot

If apcupsd does not connect to the USB port when you reboot, it is probably the appropriate kernel modules are not getting loaded correctly.

You can check this by bringing up your system, fiddling around until you get apcupsd to work with the UPS, then do:

cat /proc/modules

and save the output some place. Then reboot your computer and before you do anything else, do the cat /proc/modules again. Most likely you will find some of the usb modules are missing in the second listing.

There are two solutions:

Normally, the modules you will need loaded are the following:
usbcore
hid
input

Disclaimer

First, please rememeber this is beta software. It is not yet complete and there are sure to be some problems. We would appreciate hearing about your experiences.
Back Next Home