Desc: How to make a new subdriver to support another USB/HID UPS
File: hid-subdrivers.txt
Date: 23 September 2005
Auth: Peter Selinger <selinger@users.sourceforge.net>

Overall concept
===============

USB (Universal Serial Port) devices can be divided into several
different classes (audio, imaging, mass storage etc). Almost all UPS
devices belong to the "HID" class, which means "Human Interface
Device", and also includes things like keyboards and mice. What HID
devices have in common is a particular (and very flexible) interface
for reading and writing information (such as x/y coordinates and
button states, in case of a mouse, or voltages and status information,
in case of a UPS).

The Nut "newhidups" driver is a meta-driver that handles all HID UPS
devices. It consists of a core driver that handles most of the work of
talking to the USB hardware, and several sub-drivers to handle
specific UPS manufacturers (MGE, APC, and Belkin are currently
supported).  Adding support for a new HID UPS device is easy, because
it requires only the creation of a new sub-driver.

There are a few USB UPS devices that are not HID devices. These
devices typically implement some version of the manufacturer's serial
protocol over USB (which is a really dumb idea, by the way). An
example is the Tripplite USB. Such devices are *not* supported by the
newhidups driver, and are not covered in this document. If you need to
add support for such a device, read new-drivers.txt and see the
tripplite_usb driver for inspiration.

HID Usage Tree
==============

From the point of view of writing a HID subdriver, a HID device
consists of a bunch of variables.  Some variables (such as the current
input voltage) are read-only, whereas other variables (such as the
beeper on/off status) can be read and written. These variables are
usually grouped together and arranged in a hierarchical tree shape,
similar to directories in a file system. This tree is called the
"usage" tree. For example, here is part of the usage tree for a
typical APC device. Variable components are separated by ".". Typical
values for each variable are also shown for illustrative purposes.

UPS.Battery.Voltage            11.4 V
UPS.Battery.ConfigVoltage      12 V
UPS.Input.Voltage              117 V
UPS.Input.ConfigVoltage        120 V
UPS.AudibleAlarmControl        2 (=on)
UPS.PresentStatus.Charging     1 (=yes)
UPS.PresentStatus.Discharging  0 (=no)
UPS.PresentStatus.ACPresent    1 (=yes)

As you can see, variables that describe the battery status might be
grouped together under "Battery", variables that describe the input
power might be grouped together under "Input", and variables that
describe the current UPS status might be grouped together under
"PresentStatus". All of these variables are grouped together under
"UPS".

This hierarchical organization of data has the advantage of being very
flexible; for example, if some device has more than one battery, then
similar information about each battery could be grouped under
"Battery1", "Battery2" and so forth. If your UPS can also be used as a
toaster, then information about the toaster function might be grouped
under "Toaster", rather than "UPS".

However, the disadvantage is that each manufacturer will have their
own idea about how the usage tree should be organized, and newhidups
needs to know about all of them. This is why manufacturer specific
subdrivers are needed.

To make matters more complicated, usage tree components (such as
"UPS", "Battery", or "Voltage") are internally represented not as
strings, but as numbers (called "usages" in HID terminology). These
numbers are defined in the "HID Usage Tables", available from
http://www.usb.org/developers/hidpage/.  The standard usages for UPS
devices are defined in a document called "Usage Tables for HID Power
Devices".

For example,

 0x00840010 = UPS
 0x00840012 = Battery
 0x00840030 = Voltage
 0x00840040 = ConfigVoltage
 0x0084001a = Input
 0x0084005a = AudibleAlarmControl
 0x00840002 = PresentStatus
 0x00850044 = Charging 
 0x00850045 = Discharging
 0x008500d0 = ACPresent

Thus, the above usage tree is internally represented as

00840010.00840012.00840030
00840010.00840012.00840040
00840010.0084001a.00840030
00840010.0084001a.00840040
00840010.0084005a
00840010.00840002.00850044
00840010.00840002.00850045
00840010.00840002.008500d0

To make matters worse, most manufacturers define their own additional
usages, even in cases where standard usages could have been used. for
example Belkin defines 00860040 = ConfigVoltage (which is incidentally
a violation of the USB specification, as 00860040 is reserved for
future use).

Thus, subdrivers generally need to provide: 

- manufacturer-specific usage definitions,
- a mapping of HID variables to NUT variables.

Moreover, subdrivers might have to provide additional functionality,
such as custom implementations of specific instant commands (load.off,
shutdown.restart), and conversions of manufacturer specific data
formats.

Writing a subdriver
===================

There are no step-by-step instructions yet. Look at the files

mge-hid.c/h
apc-hid.c/h
belkin-hid.c/h

to see how the currently implemented subdrivers are written. The point
is that each subdriver exports a subdriver_t structure (defined in
newhidups.h), which contains various functions and data for
interacting with the subdriver. You also need to update the definition
of subdriver_list in newhidups.c.



