[nut-upsdev] Belkin and newhidups

Peter Selinger selinger at mathstat.dal.ca
Mon Aug 29 04:30:26 UTC 2005


zaid_aj at telus.net wrote:
> 
> Hello Peter,
> 
> That would be great help. I'll wait for your reply and then we can start 
> writing the HID <-> NUT table.

I have added Belkin support to the newhidups driver. I have put the
patch on the tracker at 

https://alioth.debian.org/tracker/index.php?func=detail&aid=302111&group_id=30602&atid=411544

Note that this patch depends on the 5 earlier patches from

https://alioth.debian.org/tracker/index.php?func=detail&aid=302101&group_id=30602&atid=411544

so these must be applied first. All patches are against the CVS
development tree, as of August 24. 

I have mapped most variables that appear to be useful; here is typical
output from upsc. Note that I have mapped all the variables that did
not make sense or seemed useless under zzz. This is for experimental
purposes only.

battery.charge: 75
battery.charge.low: 30
battery.charge.warning: 50
battery.runtime: 210
battery.voltage: 26.1
battery.voltage.nominal: 24
driver.name: newhidups
driver.parameter.port: auto
driver.version: 2.0.2
driver.version.data: Belkin HID 0.1
driver.version.internal: 0.27
input.frequency: 59.9
input.frequency.nominal: 60
input.sensitivity: reduced  /* Note: this value is writable, but must be written numerically as 0, 1, or 2 at the moment */
input.transfer.high: 136
input.transfer.high.max: 0
input.transfer.high.min: 1536  /* Note: this is a garbage value created by a previous crash of the UPS firmware - should be 0 */
input.transfer.low: 90
input.transfer.low.max: 0
input.transfer.low.min: 0
input.voltage: 117.4
input.voltage.nominal: 120
output.frequency: 59.9
output.voltage: 118.1
ups.beeper.status: enabled
ups.delay.restart: 0
ups.delay.shutdown: 2
ups.devicechemistry: PbAc
ups.firmware: 4
ups.load: 0
ups.mfr: Belkin
ups.mfr.date: 2002/03/01
ups.model: UPS
ups.power.nominal: 800
ups.serial: unknown
ups.serial.internal: D2002337105  /* Note: it should be ups.serial, but Belkin has this information in a non-standard place and I have not yet figured out how to read it at init-time */
ups.status: OL CHRG
ups.test.result: Done and passed
ups.type: offline
zzz.ups.belkinbatterysystem.00860060: 16
zzz.ups.belkinconfig.belkinconfigoverloadtransfer: 100
zzz.ups.belkincontrols.belkindefaultshutdown: 0
zzz.ups.belkincontrols.belkinloadoff: 0
zzz.ups.belkincontrols.belkinloadon: 0
zzz.ups.belkincontrols.belkinloadtoggle: 0
zzz.ups.belkindevice.00860031: 0
zzz.ups.belkindevice.00860033: 0
zzz.ups.belkindevice.belkinfrequency: 0.0
zzz.ups.belkindevice.belkinpower: 0
zzz.ups.belkinstatus.belkinbatterystatus: 00000010
zzz.ups.belkinstatus.belkinpowerstatus: 00008000
zzz.ups.powersummary.capacitygranularity1: 1
zzz.ups.powersummary.capacitygranularity2: 1
zzz.ups.powersummary.capacitymode: 0
zzz.ups.powersummary.configvoltage: 1
zzz.ups.powersummary.current: 0
zzz.ups.powersummary.designcapacity: 100
zzz.ups.powersummary.fullchargecapacity: 100
zzz.ups.powersummary.ioeminformation:        
zzz.ups.powersummary.iproduct: UPS
zzz.ups.powersummary.rechargeable: 1
zzz.ups.powersummary.remainingcapacity: 0
zzz.ups.powersummary.voltage: 2

I have also implemented some instant commands:

test.battery.start.quick - Quick battery test
test.battery.start.deep - Deep battery test
test.battery.stop - Stop the battery test
beeper.on - Enable the UPS beeper
beeper.off - Disable the UPS beeper
load.off - Turn off the load immediately

Unfortunately my firmware is unable to do load.on or shutdown.return -
all shutdowns are permanent or timed. I already had the same problem
when writing the serial driver for this UPS, see the belkinunv(8) man
page.

In addition to the Usage mapping, there were some specific issues that
needed to be fixed to get the Belkin UPS to work with newhidups. 

* Zaid had reported some strange output:

   Object: UPS.PowerSummary.RemainingCapacity00860035 = 100

  etc, in his post on August 10. This is caused by a bug in
  libhid.c:lookup_path(): the loop should end when i < hData.Path.Size
  and not i <= hData.Path.Size. The patch fixes this.

* calls of libusb_get_report(ReportID, raw_buf, LEN) caused my Belkin
  USB to crash (!) if LEN was too large or too small. My USB got into
  a state where it could no longer be turned off or reset. Needed lots
  of prodding to get it back to work. I experimentally determined that a
  value of LEN=8 is okay, but the previously-used value of LEN=10 did
  not work. This is obviously due to Belkin's very crappy
  and non-conformant implementation of the USB protocol.

Enjoy! -- Peter

----------------------------------------------------------------------
diff -Naur nut-cvs-ALL-2005-08-24/drivers/Makefile.in nut-cvs-BELKIN-2005-08-29/drivers/Makefile.in
--- nut-cvs-ALL-2005-08-24/drivers/Makefile.in	2005-08-26 22:48:28.000000000 -0300
+++ nut-cvs-BELKIN-2005-08-29/drivers/Makefile.in	2005-08-29 00:47:04.000000000 -0300
@@ -36,7 +36,7 @@
 
 all: $(DRIVER_BUILD_LIST) upsdrvctl
 
-all-drivers: $(PROGS) mge-shut dummy-ups
+all-drivers: $(PROGS) mge-shut 
 
 # ==========================================================================
 # Driver build details
@@ -216,6 +216,7 @@
 etapro.o: main.h dstate.h serial.h
 everups.o: main.h dstate.h serial.h
 fentonups.o: main.h dstate.h serial.h fentonups.h
+gamatronic.o: main.h dstate.h serial.h gamatronic.h
 genericups.o: main.h dstate.h serial.h genericups.h
 hidparser.o: hidparser.h hidtypes.h
 hidups.o: hidups.h main.h dstate.h
@@ -231,7 +232,7 @@
 mge-utalk.o: main.h dstate.h serial.h mge-utalk.h
 mustek.o: main.h dstate.h serial.h
 newhidups.o: main.h dstate.h libhid.h hidtypes.h newhidups.h mge-hid.h
-newhidups.o: apc-hid.h
+newhidups.o: apc-hid.h belkin-hid.h
 oneac.o: main.h dstate.h serial.h oneac.h
 powercom.o: main.h dstate.h serial.h powercom.h
 powermust.o: main.h dstate.h serial.h
diff -Naur nut-cvs-ALL-2005-08-24/drivers/belkin-hid.h nut-cvs-BELKIN-2005-08-29/drivers/belkin-hid.h
--- nut-cvs-ALL-2005-08-24/drivers/belkin-hid.h	1969-12-31 20:00:00.000000000 -0400
+++ nut-cvs-BELKIN-2005-08-29/drivers/belkin-hid.h	2005-08-29 00:47:04.000000000 -0300
@@ -0,0 +1,349 @@
+/*  belkin-hid.h - data to monitor Belkin UPS SYSTEMS USB/HID devices with NUT
+ *
+ *  Copyright (C)  
+ *	2003 - 2005	Arnaud Quette <arnaud.quette at free.fr>
+ *	2005		John Stamp <kinsayder at hotmail.com>
+ *      2005            Peter Selinger <selinger at users.sourceforge.net>
+ *
+ *  Sponsored by MGE UPS SYSTEMS <http://www.mgeups.com>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ */
+
+#define BELKIN_HID_VERSION	"Belkin HID 0.1"
+
+/* --------------------------------------------------------------- */
+/*      Model Name formating entries                               */
+/* --------------------------------------------------------------- */
+
+models_name_t belkin_model_names [] =
+{
+  /* is this useful for anything? -PS */
+
+  /* end of structure. */
+  { NULL, NULL, -1, "Generic Belkin HID model" }
+};
+
+/* some conversion functions specific to Belkin */
+
+/* returns statically allocated string - must not use it again before
+   done with result! */
+static char *belkin_firmware_conversion_fun(long value) {
+	static char buf[20];
+	sprintf(buf, "%ld", value >> 4);
+	
+	return buf;
+}
+
+info_lkp_t belkin_firmware_conversion[] = {
+	{ 0, NULL, belkin_firmware_conversion_fun }
+};
+
+static char *belkin_upstype_conversion_fun(long value) {
+	switch (value & 0x0f) {
+	case 0: default:
+		return "online";
+	case 1:
+		return "offline";
+	case 2:
+		return "line-interactive";
+	case 3:
+		return "simple online";
+	case 4: 
+		return "simple offline";
+	case 5:
+		return "simple line-interactive";
+	}
+}
+
+info_lkp_t belkin_upstype_conversion[] = {
+	{ 0, NULL, belkin_upstype_conversion_fun }
+};
+
+static char *belkin_sensitivity_conversion_fun(long value) {
+	switch (value) {
+	case 0: default:
+		return "normal";
+	case 1:
+		return "reduced";
+	case 2:
+		return "low";
+	}
+}
+
+info_lkp_t belkin_sensitivity_conversion[] = {
+	{ 0, NULL, belkin_sensitivity_conversion_fun }
+};
+
+/* returns statically allocated string - must not use it again before
+   done with result! */
+static char *belkin_10_conversion_fun(long value) {
+	static char buf[20];
+	
+	sprintf(buf, "%0.1f", value * 0.1);
+	return buf;
+}
+
+info_lkp_t belkin_10_conversion[] = {
+	{ 0, NULL, belkin_10_conversion_fun }
+};
+
+info_lkp_t belkin_test_info[] = {
+  { 0, "No test initiated", NULL },
+  { 1, "Done and passed", NULL },
+  { 2, "Done and warning", NULL },
+  { 3, "Done and error", NULL },
+  { 4, "Aborted", NULL },
+  { 5, "In progress", NULL },
+  { 0, "NULL", NULL }
+};
+
+static char *belkin_overload_conversion_fun(long value) {
+	if (value & 0x0010) {
+		return "OVER";
+	} else {
+		return "";
+	}		
+}
+
+info_lkp_t belkin_overload_conversion[] = {
+	{ 0, NULL, belkin_overload_conversion_fun }
+};
+
+static char *belkin_overheat_conversion_fun(long value) {
+	if (value & 0x0040) {
+		return "OVERHEAT";
+	} else {
+		return "";
+	}
+}
+
+info_lkp_t belkin_overheat_conversion[] = {
+	{ 0, NULL, belkin_overheat_conversion_fun }
+};
+
+static char *belkin_commfault_conversion_fun(long value) {
+	if (value & 0x0080) {
+		return "COMMFAULT";
+	} else {
+		return "";
+	}
+}
+
+info_lkp_t belkin_commfault_conversion[] = {
+	{ 0, NULL, belkin_commfault_conversion_fun }
+};
+
+static char *belkin_depleted_conversion_fun(long value) {
+	if (value & 0x40) {
+		return "DEPLETED";
+	} else {
+		return "";
+	}
+}
+
+info_lkp_t belkin_depleted_conversion[] = {
+	{ 0, NULL, belkin_depleted_conversion_fun }
+};
+
+static char *belkin_replacebatt_conversion_fun(long value) {
+	if (value & 0x80) {
+		return "RB";
+	} else {
+		return "";
+	}		
+}
+
+info_lkp_t belkin_replacebatt_conversion[] = {
+	{ 0, NULL, belkin_replacebatt_conversion_fun }
+};
+
+
+
+/* HID2NUT lookup table */
+hid_info_t hid_belkin[] = {
+
+#ifdef BELKIN_SHOW_ALL 
+
+  /* all Belkin F6C800-UNV variables */
+  { "zzz.ups.belkinconfig.belkinconfigvoltage", 0, 0, "UPS.BELKINConfig.BELKINConfigVoltage", NULL, "%.0f", HU_FLAG_OK, NULL },
+  { "zzz.ups.belkinconfig.belkinconfigfrequency", 0, 0, "UPS.BELKINConfig.BELKINConfigFrequency", NULL, "%.0f", HU_FLAG_OK, NULL },
+  { "zzz.ups.belkinconfig.belkinconfigapparentpower", 0, 0, "UPS.BELKINConfig.BELKINConfigApparentPower", NULL, "%.0f", HU_FLAG_OK, NULL },
+  { "zzz.ups.belkinconfig.belkinconfigbatteryvoltage", 0, 0, "UPS.BELKINConfig.BELKINConfigBatteryVoltage", NULL, "%.0f", HU_FLAG_OK, NULL },
+  { "zzz.ups.belkinconfig.belkinconfigoverloadtransfer", 0, 0, "UPS.BELKINConfig.BELKINConfigOverloadTransfer", NULL, "%.0f", HU_FLAG_OK, NULL },
+  { "zzz.ups.belkinconfig.belkinlowvoltagetransfer", ST_FLAG_RW, 0, "UPS.BELKINConfig.BELKINLowVoltageTransfer", NULL, "%.0f", HU_FLAG_OK, NULL },
+  { "zzz.ups.belkinconfig.belkinlowvoltagetransfermax", 0, 0, "UPS.BELKINConfig.BELKINLowVoltageTransferMax", NULL, "%.0f", HU_FLAG_OK, NULL },
+  { "zzz.ups.belkinconfig.belkinlowvoltagetransfermin", 0, 0, "UPS.BELKINConfig.BELKINLowVoltageTransferMin", NULL, "%.0f", HU_FLAG_OK, NULL },
+  { "zzz.ups.belkinconfig.belkinhighvoltagetransfer", ST_FLAG_RW, 0, "UPS.BELKINConfig.BELKINHighVoltageTransfer", NULL, "%.0f", HU_FLAG_OK, NULL },
+  { "zzz.ups.belkinconfig.belkinhighvoltagetransfermax", 0, 0, "UPS.BELKINConfig.BELKINHighVoltageTransferMax", NULL, "%.0f", HU_FLAG_OK, NULL },
+  { "zzz.ups.belkinconfig.belkinhighvoltagetransfermin", 0, 0, "UPS.BELKINConfig.BELKINHighVoltageTransferMin", NULL, "%.0f", HU_FLAG_OK, NULL },
+  { "zzz.ups.belkindevice.belkinvoltagesensitivity", ST_FLAG_RW, 0, "UPS.BELKINDevice.BELKINVoltageSensitivity", NULL, "%.0f", HU_FLAG_OK, NULL },
+  { "zzz.ups.belkindevice.belkinmodelstring", 0, 0, "UPS.BELKINDevice.BELKINModelString", NULL, "%s", HU_FLAG_OK, stringid_conversion },
+  { "zzz.ups.belkindevice.belkinmodelstringoffset", 0, 0, "UPS.BELKINDevice.BELKINModelStringOffset", NULL, "%.0f", HU_FLAG_OK, NULL },
+  { "zzz.ups.belkindevice.belkinupstype", 0, 0, "UPS.BELKINDevice.BELKINUPSType", NULL, "%.0f", HU_FLAG_OK, NULL },
+  { "zzz.ups.belkincontrols.belkintest", ST_FLAG_RW, 0, "UPS.BELKINControls.BELKINTest", NULL, "%.0f", HU_FLAG_OK, NULL },
+  { "zzz.ups.belkincontrols.belkinaudiblealarmcontrol", ST_FLAG_RW, 0, "UPS.BELKINControls.BELKINAudibleAlarmControl", NULL, "%.0f", HU_FLAG_OK, NULL },
+  { "zzz.ups.belkincontrols.belkinloadon", ST_FLAG_RW, 0, "UPS.BELKINControls.BELKINLoadOn", NULL, "%.0f", HU_FLAG_OK, NULL }, 
+  { "zzz.ups.belkincontrols.belkinloadoff", ST_FLAG_RW, 0, "UPS.BELKINControls.BELKINLoadOff", NULL, "%.0f", HU_FLAG_OK, NULL },
+  { "zzz.ups.belkincontrols.belkinloadtoggle", ST_FLAG_RW, 0, "UPS.BELKINControls.BELKINLoadToggle", NULL, "%.0f", HU_FLAG_OK, NULL },
+  { "zzz.ups.belkincontrols.belkindelaybeforeshutdown", ST_FLAG_RW, 0, "UPS.BELKINControls.BELKINDelayBeforeShutdown", NULL, "%.0f", HU_FLAG_OK, NULL },
+  { "zzz.ups.belkincontrols.belkindelaybeforestartup", ST_FLAG_RW, 0, "UPS.BELKINControls.BELKINDelayBeforeStartup", NULL, "%.0f", HU_FLAG_OK, NULL },
+  { "zzz.ups.belkincontrols.belkindefaultshutdown", ST_FLAG_RW, 0, "UPS.BELKINControls.BELKINDefaultShutdown", NULL, "%.0f", HU_FLAG_OK, NULL },
+  { "zzz.ups.belkinpowerstate.belkininput.belkinvoltage", 0, 0, "UPS.BELKINPowerState.BELKINInput.BELKINVoltage", NULL, "%s", HU_FLAG_OK, belkin_10_conversion },
+  { "zzz.ups.belkinpowerstate.belkininput.belkinfrequency", 0, 0, "UPS.BELKINPowerState.BELKINInput.BELKINFrequency", NULL, "%s", HU_FLAG_OK, belkin_10_conversion },
+  { "zzz.ups.belkinpowerstate.belkinoutput.belkinvoltage", 0, 0, "UPS.BELKINPowerState.BELKINOutput.BELKINVoltage", NULL, "%s", HU_FLAG_OK, belkin_10_conversion },
+  { "zzz.ups.belkinpowerstate.belkinoutput.belkinfrequency", 0, 0, "UPS.BELKINPowerState.BELKINOutput.BELKINFrequency", NULL, "%s", HU_FLAG_OK, belkin_10_conversion },
+  { "zzz.ups.belkinpowerstate.belkinoutput.belkinpower", 0, 0, "UPS.BELKINPowerState.BELKINOutput.BELKINPower", NULL, "%.0f", HU_FLAG_OK, NULL },
+  { "zzz.ups.belkinpowerstate.belkinoutput.belkinpercentload", 0, 0, "UPS.BELKINPowerState.BELKINOutput.BELKINPercentLoad", NULL, "%.0f", HU_FLAG_OK, NULL },
+  { "zzz.ups.belkinbatterysystem.00860060", 0, 0, "UPS.BELKINBatterySystem.00860060", NULL, "%.0f", HU_FLAG_OK, NULL },
+  { "zzz.ups.belkinbatterysystem.belkinvoltage", 0, 0, "UPS.BELKINBatterySystem.BELKINVoltage", NULL, "%s", HU_FLAG_OK, belkin_10_conversion },
+  { "zzz.ups.belkinbatterysystem.belkincharge", 0, 0, "UPS.BELKINBatterySystem.BELKINCharge", NULL, "%.0f", HU_FLAG_OK, NULL },
+  { "zzz.ups.belkinstatus.belkinpowerstatus", 0, 0, "UPS.BELKINStatus.BELKINPowerStatus", NULL, "%s", HU_FLAG_OK, hex_conversion },
+  { "zzz.ups.belkinstatus.belkinbatterystatus", 0, 0, "UPS.BELKINStatus.BELKINBatteryStatus", NULL, "%s", HU_FLAG_OK, hex_conversion },
+  { "zzz.ups.belkindevice.00860031", 0, 0, "UPS.BELKINDevice.00860031", NULL, "%.0f", HU_FLAG_OK, NULL },
+  { "zzz.ups.belkindevice.belkinfrequency", 0, 0, "UPS.BELKINDevice.BELKINFrequency", NULL, "%s", HU_FLAG_OK, belkin_10_conversion },
+  { "zzz.ups.belkindevice.00860033", 0, 0, "UPS.BELKINDevice.00860033", NULL, "%.0f", HU_FLAG_OK, NULL },
+  { "zzz.ups.belkindevice.belkinpower", 0, 0, "UPS.BELKINDevice.BELKINPower", NULL, "%.0f", HU_FLAG_OK, NULL },
+  { "zzz.ups.powersummary.iproduct", 0, 0, "UPS.PowerSummary.iProduct", NULL, "%s", HU_FLAG_OK, stringid_conversion },
+  { "zzz.ups.powersummary.iserialnumber", 0, 0, "UPS.PowerSummary.iSerialNumber", NULL, "%s", HU_FLAG_OK, stringid_conversion },
+  { "zzz.ups.powersummary.idevicechemistry", 0, 0, "UPS.PowerSummary.iDeviceChemistry", NULL, "%s", HU_FLAG_OK, stringid_conversion },
+  { "zzz.ups.powersummary.ioeminformation", 0, 0, "UPS.PowerSummary.iOEMInformation", NULL, "%s", HU_FLAG_OK, stringid_conversion },
+  { "zzz.ups.powersummary.rechargeable", 0, 0, "UPS.PowerSummary.Rechargeable", NULL, "%.0f", HU_FLAG_OK, NULL },
+  { "zzz.ups.powersummary.charging", 0, 0, "UPS.PowerSummary.Charging", NULL, "%.0f", HU_FLAG_OK, NULL },
+  { "zzz.ups.powersummary.discharging", 0, 0, "UPS.PowerSummary.Discharging", NULL, "%.0f", HU_FLAG_OK, NULL },
+  { "zzz.ups.powersummary.manufacturerdate", 0, 0, "UPS.PowerSummary.ManufacturerDate", NULL, "%s", HU_FLAG_OK, date_conversion },
+  { "zzz.ups.powersummary.configvoltage", 0, 0, "UPS.PowerSummary.ConfigVoltage", NULL, "%.0f", HU_FLAG_OK, NULL },
+  { "zzz.ups.powersummary.voltage", 0, 0, "UPS.PowerSummary.Voltage", NULL, "%.0f", HU_FLAG_OK, NULL },
+  { "zzz.ups.powersummary.current", 0, 0, "UPS.PowerSummary.Current", NULL, "%.0f", HU_FLAG_OK, NULL },
+  { "zzz.ups.powersummary.capacitymode", 0, 0, "UPS.PowerSummary.CapacityMode", NULL, "%.0f", HU_FLAG_OK, NULL },
+  { "zzz.ups.powersummary.remainingcapacity", 0, 0, "UPS.PowerSummary.RemainingCapacity", NULL, "%.0f", HU_FLAG_OK, NULL },
+  { "zzz.ups.powersummary.runtimetoempty", 0, 0, "UPS.PowerSummary.RunTimeToEmpty", NULL, "%.0f", HU_FLAG_OK, NULL },
+  { "zzz.ups.powersummary.designcapacity", 0, 0, "UPS.PowerSummary.DesignCapacity", NULL, "%.0f", HU_FLAG_OK, NULL },
+  { "zzz.ups.powersummary.fullchargecapacity", 0, 0, "UPS.PowerSummary.FullChargeCapacity", NULL, "%.0f", HU_FLAG_OK, NULL },
+  { "zzz.ups.powersummary.warningcapacitylimit", 0, 0, "UPS.PowerSummary.WarningCapacityLimit", NULL, "%.0f", HU_FLAG_OK, NULL },
+  { "zzz.ups.powersummary.capacitygranularity2", 0, 0, "UPS.PowerSummary.CapacityGranularity2", NULL, "%.0f", HU_FLAG_OK, NULL },
+  { "zzz.ups.powersummary.remainingcapacitylimit", 0, 0, "UPS.PowerSummary.RemainingCapacityLimit", NULL, "%.0f", HU_FLAG_OK, NULL },
+  { "zzz.ups.powersummary.capacitygranularity1", 0, 0, "UPS.PowerSummary.CapacityGranularity1", NULL, "%.0f", HU_FLAG_OK, NULL },
+  { "zzz.ups.powersummary.acpresent", 0, 0, "UPS.PowerSummary.ACPresent", NULL, "%.0f", HU_FLAG_OK, NULL },
+  { "zzz.ups.powersummary.belowremainingcapacitylimit", 0, 0, "UPS.PowerSummary.BelowRemainingCapacityLimit", NULL, "%.0f", HU_FLAG_OK, NULL },
+  { "zzz.ups.powersummary.shutdownimminent", 0, 0, "UPS.PowerSummary.ShutdownImminent", NULL, "%.0f", HU_FLAG_OK, NULL },
+
+#endif /* BELKIN_SHOW_ALL */
+
+  /* interpreted Belkin variables */
+  { "battery.charge", 0, 0, "UPS.BELKINBatterySystem.BELKINCharge", NULL, "%.0f", HU_FLAG_OK, NULL },
+  { "battery.charge.low", ST_FLAG_STRING, 5, "UPS.PowerSummary.RemainingCapacityLimit", NULL, "%.0f", HU_FLAG_OK, NULL },
+  { "battery.charge.warning", ST_FLAG_STRING, 5, "UPS.PowerSummary.WarningCapacityLimit", NULL, "%.0f", HU_FLAG_OK, NULL }, /* Read only */
+  { "battery.runtime", 0, 0, "UPS.PowerSummary.RunTimeToEmpty", NULL, "%.0f", HU_FLAG_OK, NULL },
+  { "battery.voltage", 0, 0, "UPS.BELKINBatterySystem.BELKINVoltage", NULL, "%s", HU_FLAG_OK, belkin_10_conversion },
+  { "battery.voltage.nominal", 0, 0, "UPS.BELKINConfig.BELKINConfigBatteryVoltage", NULL, "%.0f", HU_FLAG_OK, NULL },
+  { "ups.serial.internal", 0, 0, "UPS.PowerSummary.iSerialNumber", NULL, "%s", HU_FLAG_OK, stringid_conversion },  
+  { "ups.mfr.date", 0, 0, "UPS.PowerSummary.ManufacturerDate", NULL, "%s", HU_FLAG_OK, date_conversion },
+  { "input.frequency", 0, 0, "UPS.BELKINPowerState.BELKINInput.BELKINFrequency", NULL, "%s", HU_FLAG_OK, belkin_10_conversion },
+  { "input.frequency.nominal", 0, 0, "UPS.BELKINConfig.BELKINConfigFrequency", NULL, "%.0f", HU_FLAG_OK, NULL },
+  { "input.sensitivity", ST_FLAG_RW, 0, "UPS.BELKINDevice.BELKINVoltageSensitivity", NULL, "%s", HU_FLAG_OK, belkin_sensitivity_conversion },
+  { "input.transfer.low", ST_FLAG_RW, 0, "UPS.BELKINConfig.BELKINLowVoltageTransfer", NULL, "%.0f", HU_FLAG_OK, NULL },
+  { "input.transfer.low.max", 0, 0, "UPS.BELKINConfig.BELKINLowVoltageTransferMax", NULL, "%.0f", HU_FLAG_OK, NULL },
+  { "input.transfer.low.min", 0, 0, "UPS.BELKINConfig.BELKINLowVoltageTransferMin", NULL, "%.0f", HU_FLAG_OK, NULL },
+  { "input.transfer.high", ST_FLAG_RW, 0, "UPS.BELKINConfig.BELKINHighVoltageTransfer", NULL, "%.0f", HU_FLAG_OK, NULL },
+  { "input.transfer.high.max", 0, 0, "UPS.BELKINConfig.BELKINHighVoltageTransferMax", NULL, "%.0f", HU_FLAG_OK, NULL },
+  { "input.transfer.high.min", 0, 0, "UPS.BELKINConfig.BELKINHighVoltageTransferMin", NULL, "%.0f", HU_FLAG_OK, NULL },
+  { "input.voltage", 0, 0, "UPS.BELKINPowerState.BELKINInput.BELKINVoltage", NULL, "%s", HU_FLAG_OK, belkin_10_conversion },
+  { "input.voltage.nominal", 0, 0, "UPS.BELKINConfig.BELKINConfigVoltage", NULL, "%.0f", HU_FLAG_OK, NULL },  
+  { "output.frequency", 0, 0, "UPS.BELKINPowerState.BELKINOutput.BELKINFrequency", NULL, "%s", HU_FLAG_OK, belkin_10_conversion },
+  { "output.voltage", 0, 0, "UPS.BELKINPowerState.BELKINOutput.BELKINVoltage", NULL, "%s", HU_FLAG_OK, belkin_10_conversion },
+  { "ups.beeper.status", 0, 0, "UPS.BELKINControls.BELKINAudibleAlarmControl", NULL, "%s", HU_FLAG_OK, beeper_info },
+  { "ups.firmware", 0, 0, "UPS.BELKINDevice.BELKINUPSType", NULL, "%s", HU_FLAG_OK, belkin_firmware_conversion },
+  { "ups.load", 0, 0, "UPS.BELKINPowerState.BELKINOutput.BELKINPercentLoad", NULL, "%.0f", HU_FLAG_OK, NULL },
+  { "ups.power.nominal", 0, 0, "UPS.BELKINConfig.BELKINConfigApparentPower", NULL, "%.0f", HU_FLAG_OK, NULL },
+  { "ups.test.result", ST_FLAG_RW, 0, "UPS.BELKINControls.BELKINTest", NULL, "%s", HU_FLAG_OK, belkin_test_info },
+  { "ups.delay.shutdown", ST_FLAG_RW, 0, "UPS.BELKINControls.BELKINDelayBeforeShutdown", NULL, "%.0f", HU_FLAG_OK, NULL },
+  { "ups.delay.restart", ST_FLAG_RW, 0, "UPS.BELKINControls.BELKINDelayBeforeStartup", NULL, "%.0f", HU_FLAG_OK, NULL },
+  { "ups.devicechemistry", 0, 0, "UPS.PowerSummary.iDeviceChemistry", NULL, "%s", HU_FLAG_OK, stringid_conversion },
+  { "ups.type", 0, 0, "UPS.BELKINDevice.BELKINUPSType", NULL, "%s", HU_FLAG_OK, belkin_upstype_conversion },
+
+  /* status */
+  { "ups.status", 0, 1, "UPS.PowerSummary.Discharging",NULL, "%s", HU_FLAG_OK, discharging_info },
+  { "ups.status", 0, 1, "UPS.PowerSummary.Charging", NULL, "%s", HU_FLAG_OK, charging_info },
+  { "ups.status", 0, 1, "UPS.PowerSummary.ShutdownImminent", NULL, "%s", HU_FLAG_OK, shutdownimm_info },
+  { "ups.status", 0, 1, "UPS.PowerSummary.ACPresent", NULL, "%s", HU_FLAG_OK, onbatt_info },
+  { "ups.status", 0, 1, "UPS.PowerSummary.BelowRemainingCapacityLimit", NULL, "%s", HU_FLAG_OK, lowbatt_info },
+  { "ups.status", 0, 1, "UPS.BELKINStatus.BELKINPowerStatus", NULL, "%s", HU_FLAG_OK, belkin_overload_conversion },
+  { "ups.status", 0, 1, "UPS.BELKINStatus.BELKINPowerStatus", NULL, "%s", HU_FLAG_OK, belkin_overheat_conversion },
+  { "ups.status", 0, 1, "UPS.BELKINStatus.BELKINPowerStatus", NULL, "%s", HU_FLAG_OK, belkin_commfault_conversion },
+  { "ups.status", 0, 1, "UPS.BELKINStatus.BELKINBatteryStatus", NULL, "%s", HU_FLAG_OK, belkin_depleted_conversion },
+  { "ups.status", 0, 1, "UPS.BELKINStatus.BELKINBatteryStatus", NULL, "%s", HU_FLAG_OK, belkin_replacebatt_conversion },
+
+  /* Server side variables */
+  { "driver.version.internal", ST_FLAG_STRING, sizeof(DRIVER_VERSION), NULL, NULL, DRIVER_VERSION, HU_FLAG_ABSENT | HU_FLAG_OK, NULL },
+  { "driver.version.data", ST_FLAG_STRING, sizeof(BELKIN_HID_VERSION), NULL, NULL, BELKIN_HID_VERSION, HU_FLAG_ABSENT | HU_FLAG_OK, NULL },
+  
+  /* non-mapped: the meaning of these variables is either unknown, or
+     the UPS returns non-sensical values for the standard meanings, or
+     (in the case of writable variables) writing them has no
+     effect. In short, the variables in this group are probably
+     useless. */
+  { "zzz.ups.belkinconfig.belkinconfigoverloadtransfer", 0, 0, "UPS.BELKINConfig.BELKINConfigOverloadTransfer", NULL, "%.0f", HU_FLAG_OK, NULL },
+  { "zzz.ups.belkinbatterysystem.00860060", 0, 0, "UPS.BELKINBatterySystem.00860060", NULL, "%.0f", HU_FLAG_OK, NULL },
+  { "zzz.ups.belkinstatus.belkinpowerstatus", 0, 0, "UPS.BELKINStatus.BELKINPowerStatus", NULL, "%s", HU_FLAG_OK, hex_conversion },
+  { "zzz.ups.belkinstatus.belkinbatterystatus", 0, 0, "UPS.BELKINStatus.BELKINBatteryStatus", NULL, "%s", HU_FLAG_OK, hex_conversion },
+  { "zzz.ups.belkindevice.00860031", 0, 0, "UPS.BELKINDevice.00860031", NULL, "%.0f", HU_FLAG_OK, NULL },
+  { "zzz.ups.belkindevice.belkinfrequency", 0, 0, "UPS.BELKINDevice.BELKINFrequency", NULL, "%s", HU_FLAG_OK, belkin_10_conversion },
+  { "zzz.ups.belkindevice.00860033", 0, 0, "UPS.BELKINDevice.00860033", NULL, "%.0f", HU_FLAG_OK, NULL },
+  { "zzz.ups.belkindevice.belkinpower", 0, 0, "UPS.BELKINDevice.BELKINPower", NULL, "%.0f", HU_FLAG_OK, NULL },
+  { "zzz.ups.powersummary.iproduct", 0, 0, "UPS.PowerSummary.iProduct", NULL, "%s", HU_FLAG_OK, stringid_conversion },
+  { "zzz.ups.powersummary.ioeminformation", 0, 0, "UPS.PowerSummary.iOEMInformation", NULL, "%s", HU_FLAG_OK, stringid_conversion },
+  { "zzz.ups.powersummary.rechargeable", 0, 0, "UPS.PowerSummary.Rechargeable", NULL, "%.0f", HU_FLAG_OK, NULL },
+  { "zzz.ups.powersummary.configvoltage", 0, 0, "UPS.PowerSummary.ConfigVoltage", NULL, "%.0f", HU_FLAG_OK, NULL },
+  { "zzz.ups.powersummary.voltage", 0, 0, "UPS.PowerSummary.Voltage", NULL, "%.0f", HU_FLAG_OK, NULL },
+  { "zzz.ups.powersummary.current", 0, 0, "UPS.PowerSummary.Current", NULL, "%.0f", HU_FLAG_OK, NULL },
+  { "zzz.ups.powersummary.capacitymode", 0, 0, "UPS.PowerSummary.CapacityMode", NULL, "%.0f", HU_FLAG_OK, NULL },
+  { "zzz.ups.powersummary.remainingcapacity", 0, 0, "UPS.PowerSummary.RemainingCapacity", NULL, "%.0f", HU_FLAG_OK, NULL },
+  { "zzz.ups.powersummary.designcapacity", 0, 0, "UPS.PowerSummary.DesignCapacity", NULL, "%.0f", HU_FLAG_OK, NULL },
+  { "zzz.ups.powersummary.fullchargecapacity", 0, 0, "UPS.PowerSummary.FullChargeCapacity", NULL, "%.0f", HU_FLAG_OK, NULL },
+  { "zzz.ups.powersummary.capacitygranularity2", 0, 0, "UPS.PowerSummary.CapacityGranularity2", NULL, "%.0f", HU_FLAG_OK, NULL },
+  { "zzz.ups.powersummary.capacitygranularity1", 0, 0, "UPS.PowerSummary.CapacityGranularity1", NULL, "%.0f", HU_FLAG_OK, NULL },
+  { "zzz.ups.belkincontrols.belkinloadon", ST_FLAG_RW, 0, "UPS.BELKINControls.BELKINLoadOn", NULL, "%.0f", HU_FLAG_OK, NULL }, 
+  { "zzz.ups.belkincontrols.belkinloadoff", ST_FLAG_RW, 0, "UPS.BELKINControls.BELKINLoadOff", NULL, "%.0f", HU_FLAG_OK, NULL },
+  { "zzz.ups.belkincontrols.belkinloadtoggle", ST_FLAG_RW, 0, "UPS.BELKINControls.BELKINLoadToggle", NULL, "%.0f", HU_FLAG_OK, NULL },
+  { "zzz.ups.belkincontrols.belkindefaultshutdown", ST_FLAG_RW, 0, "UPS.BELKINControls.BELKINDefaultShutdown", NULL, "%.0f", HU_FLAG_OK, NULL },
+
+  /* non-mapped commands */
+
+
+  /* instant commands. */
+  /* split into subsets while waiting for extradata support
+   * ie: test.battery.start quick
+   */
+  { "test.battery.start.quick", 0, 0, "UPS.BELKINControls.BELKINTest", NULL, "1", HU_TYPE_CMD | HU_FLAG_OK, NULL },
+  { "test.battery.start.deep", 0, 0, "UPS.BELKINControls.BELKINTest", NULL, "2", HU_TYPE_CMD | HU_FLAG_OK, NULL },
+  { "test.battery.stop", 0, 0, "UPS.BELKINControls.BELKINTest", NULL, "3", HU_TYPE_CMD | HU_FLAG_OK, NULL },
+  { "beeper.on", 0, 0, "UPS.BELKINControls.BELKINAudibleAlarmControl", NULL, "2", HU_TYPE_CMD | HU_FLAG_OK, NULL },
+  { "beeper.off", 0, 0, "UPS.BELKINControls.BELKINAudibleAlarmControl", NULL, "3", HU_TYPE_CMD | HU_FLAG_OK, NULL },
+  { "load.off", 0, 0, "UPS.BELKINControls.BELKINDelayBeforeShutdown", NULL, "1", HU_TYPE_CMD | HU_FLAG_OK, NULL },
+
+  /* Note: on my Belkin UPS, there is no way to implement
+     shutdown.return or load.on, even though they should exist in
+     principle. Hopefully other Belkin models will be better
+     designed. Fixme: fill in the appropriate instant commands.  For a
+     more detailed description of the problem and a possible (but not
+     yet implemented) workaround, see the belkinunv(8) man page. 
+     -PS 2005/08/28 */
+
+  /* end of structure. */
+  { NULL, 0, 0, NULL, NULL, NULL, 0, NULL }
+};
diff -Naur nut-cvs-ALL-2005-08-24/drivers/libhid.c nut-cvs-BELKIN-2005-08-29/drivers/libhid.c
--- nut-cvs-ALL-2005-08-24/drivers/libhid.c	2005-08-26 22:48:28.000000000 -0300
+++ nut-cvs-BELKIN-2005-08-29/drivers/libhid.c	2005-08-29 00:47:04.000000000 -0300
@@ -47,6 +47,7 @@
 static HIDParser 	hParser;
 
 unsigned char raw_buf[100];
+#define REPREQLEN 8
 unsigned char **report_buf;
 int replen; /* size of the last report retrieved */
 static int prev_report; /* previously retrieved report ID */
@@ -78,7 +79,7 @@
 /* support functions */
 void logical_to_physical(HIDData *Data);
 void physical_to_logical(HIDData *Data);
-const char *hid_lookup_path(int usage);
+const char *hid_lookup_path(unsigned int usage);
 int hid_lookup_usage(char *name);
 ushort lookup_path(char *HIDpath, HIDData *data);
 void dump_hex (const char *msg, const unsigned char *buf, int len);
@@ -227,7 +228,7 @@
 			raw_buf, MAX_REPORT_SIZE)) > 0) { => doesn't work! */
 			/* Bufferize at least the last report */
 			if ( ( (prev_report == hData.ReportID) && (time(NULL) <= (prev_report_ts + MAX_TS)) )
-				|| ((replen=libusb_get_report(hData.ReportID, raw_buf, 10)) > 0) )
+				|| ((replen=libusb_get_report(hData.ReportID, raw_buf, REPREQLEN)) > 0) )
 			{
 				/* Extract the data value */
 				GetValue((const unsigned char *) raw_buf, &hData);
@@ -291,7 +292,7 @@
     
     /* Get info on object (reportID, offset and size) */
     if (FindObject(&hParser,&hData) == 1) {
-      if (libusb_get_report(hData.ReportID, raw_buf, 8) > 0) { /* MAX_REPORT_SIZE) > 0) { */
+      if (libusb_get_report(hData.ReportID, raw_buf, REPREQLEN) > 0) { /* MAX_REPORT_SIZE) > 0) { */
 	GetValue((const unsigned char *) raw_buf, &hData);
 
 	/* now get string */
@@ -523,7 +524,7 @@
 	  strcat(HIDpath, "UPS.");
 
 	  // Numeric to String
-	  for (i = 1; i <= hData.Path.Size; i++)
+	  for (i = 1; i < hData.Path.Size; i++)
 		{
 		  /* Deal with ?bogus? */
 		  if ( ((hData.Path.Node[i].UPage * 0x10000) + hData.Path.Node[i].Usage) == 0)
@@ -684,8 +685,57 @@
 	{ "APCForceShutdown",			0xff86007c },
 	{ "APCDelayBeforeShutdown",		0xff86007d },
 	{ "APCDelayBeforeStartup",		0xff86007e }, /* FIXME: need to be exploited */
-	/* FIXME: The below one seems to have been wrongly encoded by APC */
+
+	/* FIXME: The below one seems to have been wrongly encoded by Belkin */
 	/* Pages 84 to 88 are reserved for official HID definition! */
+
+	{ "BELKINConfig",                       0x00860026 },
+	{ "BELKINConfigVoltage",                0x00860040 }, /* (V) */
+	{ "BELKINConfigFrequency",              0x00860042 }, /* (Hz) */
+	{ "BELKINConfigApparentPower",          0x00860043 }, /* (VA) */
+	{ "BELKINConfigBatteryVoltage",         0x00860044 }, /* (V) */
+	{ "BELKINConfigOverloadTransfer",       0x00860045 }, /* (%) */
+	{ "BELKINLowVoltageTransfer",           0x00860053 }, /* R/W (V) */
+	{ "BELKINHighVoltageTransfer",          0x00860054 }, /* R/W (V)*/
+	{ "BELKINLowVoltageTransferMax",        0x0086005b }, /* (V) */
+	{ "BELKINLowVoltageTransferMin",        0x0086005c }, /* (V) */
+	{ "BELKINHighVoltageTransferMax",       0x0086005d }, /* (V) */
+        { "BELKINHighVoltageTransferMin",       0x0086005e }, /* (V) */
+
+	{ "BELKINControls",                     0x00860027 },
+	{ "BELKINLoadOn",                       0x00860050 }, /* R/W: write: 1=do action. Read: 0=none, 1=started, 2=in progress, 3=complete */
+	{ "BELKINLoadOff",                      0x00860051 }, /* R/W: ditto */
+	{ "BELKINLoadToggle",                   0x00860052 }, /* R/W: ditto */
+	{ "BELKINDefaultShutdown",              0x00860055 }, /* R/W: write: 0=start shutdown using default delay. */
+	{ "BELKINDelayBeforeStartup",           0x00860056 }, /* R/W (minutes) */
+	{ "BELKINDelayBeforeShutdown",          0x00860057 }, /* R/W (seconds) */
+	{ "BELKINTest",                         0x00860058 }, /* R/W: write: 0=no test, 1=quick test, 2=deep test, 3=abort test. Read: 0=no test, 1=passed, 2=warning, 3=error, 4=abort, 5=in progress */
+	{ "BELKINAudibleAlarmControl",          0x0086005a }, /* R/W: 1=disabled, 2=enabled, 3=muted */
+	
+	{ "BELKINDevice",                       0x00860029 },
+	{ "BELKINVoltageSensitivity",           0x00860074 }, /* R/W: 0=normal, 1=reduced, 2=low */
+        { "BELKINModelString",                  0x00860075 },
+        { "BELKINModelStringOffset",            0x00860076 }, /* offset of Model name in Model String */
+        { "BELKINUPSType",                      0x0086007c }, /* high nibble: firmware version. Low nibble: 0=online, 1=offline, 2=line-interactive, 3=simple online, 4=simple offline, 5=simple line-interactive */
+
+	{ "BELKINPowerState",                   0x0086002a },
+        { "BELKINInput",                        0x0086001a },
+        { "BELKINOutput",                       0x0086001c },
+	{ "BELKINBatterySystem",                0x00860010 },
+	{ "BELKINVoltage",                      0x00860030 }, /* (0.1 Volt) */
+	{ "BELKINFrequency",                    0x00860032 }, /* (0.1 Hz) */
+	{ "BELKINPower",                        0x00860034 }, /* (Watt) */
+	{ "BELKINPercentLoad",                  0x00860035 }, /* (%) */
+	{ "BELKINTemperature",                  0x00860036 }, /* (Celsius) */
+	{ "BELKINCharge",                       0x00860039 }, /* (%) */
+	{ "BELKINRunTimeToEmpty",               0x0086006c }, /* (minutes) */
+
+	{ "BELKINStatus",                       0x00860028 },
+	{ "BELKINBatteryStatus",                0x00860022 }, /* 1 byte: bit2=low battery, bit4=charging, bit5=discharging, bit6=battery empty, bit7=replace battery */
+	{ "BELKINPowerStatus",                  0x00860021 }, /* 2 bytes: bit0=ac failure, bit4=overload, bit5=load is off, bit6=overheat, bit7=UPS fault, bit13=awaiting power, bit15=alarm status */
+
+	/* FIXME: The below one seems to have been wrongly encoded by APC */
+	/* FIXME: This also overlaps with Belkin */
 	{ "BUPHibernate",			0x00850058 }, /* FIXME: need to be exploited */
 	{ "BUPBattCapBeforeStartup",		0x00860012 }, /* FIXME: need to be exploited */
 	{ "BUPDelayBeforeStartup",		0x00860076 }, /* FIXME: need to be exploited */
diff -Naur nut-cvs-ALL-2005-08-24/drivers/libusb.c nut-cvs-BELKIN-2005-08-29/drivers/libusb.c
--- nut-cvs-ALL-2005-08-24/drivers/libusb.c	2005-08-26 22:48:28.000000000 -0300
+++ nut-cvs-BELKIN-2005-08-29/drivers/libusb.c	2005-08-29 00:47:04.000000000 -0300
@@ -126,8 +126,7 @@
 			  /* FIXME: temporary method, not generic/flexible enough */
 			  if ( (dev->descriptor.idVendor == MGE_UPS_SYSTEMS)
 				  || (dev->descriptor.idVendor == APC)
-				  || ( (dev->descriptor.idVendor == BELKIN)
-					&& (dev->descriptor.idProduct == 0x0551) )
+				  || (dev->descriptor.idVendor == BELKIN)
 				  || (dev->descriptor.idVendor == MUSTEK)
 				  || (dev->descriptor.idVendor == TRIPPLITE)
 				  || (dev->descriptor.idVendor == UNITEK) )
diff -Naur nut-cvs-ALL-2005-08-24/drivers/newhidups.c nut-cvs-BELKIN-2005-08-29/drivers/newhidups.c
--- nut-cvs-ALL-2005-08-24/drivers/newhidups.c	2005-08-26 22:48:28.000000000 -0300
+++ nut-cvs-BELKIN-2005-08-29/drivers/newhidups.c	2005-08-29 00:47:04.000000000 -0300
@@ -28,6 +28,7 @@
 /* include all known hid2nut lookup tables */
 #include "mge-hid.h"
 #include "apc-hid.h"
+#include "belkin-hid.h"
 
 /* pointer to the good lookup tables */
 static hid_info_t *hid_ups;
@@ -415,6 +416,10 @@
       			HIDDumpTree(NULL);
 		break;
 		case BELKIN:
+	  	        hid_ups = hid_belkin;
+			model_names = belkin_model_names;
+			HIDDumpTree(NULL);
+		break;
 		case MUSTEK:
 		case TRIPPLITE:
 		case UNITEK:
@@ -491,6 +496,16 @@
 			}
 			finalname = str;
 			break;
+		case BELKIN:
+		        finalname = hd->Product;
+		        /* FIXME: this is a stub */
+		        if (strncmp(hd->Vendor, "          ", strlen(hd->Vendor)) == 0) {
+			        hd->Vendor = "Belkin";
+			}
+			if (strlen(hd->Product) == 0) {
+			        finalname = "unknown";
+                        }
+			break;
 		default: /* Nothing to do */
 		break;
 	}
diff -Naur nut-cvs-ALL-2005-08-24/drivers/newhidups.h nut-cvs-BELKIN-2005-08-29/drivers/newhidups.h
--- nut-cvs-ALL-2005-08-24/drivers/newhidups.h	2005-08-26 22:48:28.000000000 -0300
+++ nut-cvs-BELKIN-2005-08-29/drivers/newhidups.h	2005-08-29 00:47:04.000000000 -0300
@@ -26,6 +26,8 @@
 #include <string.h>
 #include <unistd.h>
 #include "config.h"
+/* there is not file libusb.h, so we have to declare this "by hand": */
+int libusb_get_string(int StringIdx, char *string);
 
 #define DRIVER_VERSION		"0.27"
 
@@ -233,6 +235,32 @@
   { 0, NULL, date_conversion_fun }
 };
 
+/* returns statically allocated string - must not use it again before
+   done with result! */
+static char *hex_conversion_fun(long value) {
+	static char buf[20];
+	
+	sprintf(buf, "%08lx", value);
+	return buf;
+}
+
+info_lkp_t hex_conversion[] = {
+	{ 0, NULL, hex_conversion_fun }
+};
+
+/* returns statically allocated string - must not use it again before
+   done with result! */
+static char *stringid_conversion_fun(long value) {
+	static char buf[20];
+	libusb_get_string(value, buf);	
+	
+	return buf;
+}
+
+info_lkp_t stringid_conversion[] = {
+	{ 0, NULL, stringid_conversion_fun }
+};
+
 /* --------------------------------------------------------------- */
 /* Structure containing information about how to get/set data      */
 /* from/to the UPS and convert these to/from NUT standard          */





More information about the Nut-upsdev mailing list