Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions docs/acknowledgements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,10 @@ provide you with official support from Eaton, or a better level of device
support in NUT.*
================================================================================

* link:https://www.ametek.com/products/businessunits/powersystemsandinstruments/powervar[AMETEK
Powervar], through Andrew McCartney, has added support for all AMETEK Powervar
UPM models as usb-hid UPS.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Note @andrewmccartney : I took the liberty to stub an acknowledgements entry here. Feel free to modify if I got some names or spellings wrong.

* link:http://www.gamatronic.com[Gamatronic], through Nadav Moskovitch, has
revived the 'sec' driver (as gamatronic), and expanded a bit genericups for its
UPSs with alarm interface.
Expand Down
1 change: 1 addition & 0 deletions docs/man/usbhid-ups.txt
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ At the present time, usbhid-ups supports:
- the newer Eaton USB models,
- all MGE USB models,
- all Dell USB models,
- all AMETEK Powervar UPM models,
- some APC models,
- some Belkin models,
- some Cyber Power Systems models,
Expand Down
3 changes: 3 additions & 0 deletions docs/nut.dict
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ AEG
AES
AGM
AIX
AMETEK
APC's
API
APIs
Expand Down Expand Up @@ -801,6 +802,7 @@ PowerVault
PowerWalker
PowerWare
Powerchute
Powervar
Powerwell
Prachi
PresentStatus
Expand Down Expand Up @@ -1075,6 +1077,7 @@ UINT
UNKCOMMAND
UNV
UPGUARDS
UPM
UPOII
UPS's
UPSCONN
Expand Down
4 changes: 2 additions & 2 deletions drivers/Makefile.am
Original file line number Diff line number Diff line change
Expand Up @@ -175,7 +175,7 @@ skel_LDADD = $(LDADD_DRIVERS)
# USB
USBHID_UPS_SUBDRIVERS = apc-hid.c belkin-hid.c cps-hid.c explore-hid.c \
liebert-hid.c mge-hid.c powercom-hid.c tripplite-hid.c idowell-hid.c \
openups-hid.c
openups-hid.c powervar-hid.c
usbhid_ups_SOURCES = usbhid-ups.c libhid.c libusb.c hidparser.c \
usb-common.c $(USBHID_UPS_SUBDRIVERS)
usbhid_ups_LDADD = $(LDADD_DRIVERS) $(LIBUSB_LIBS) -lm
Expand Down Expand Up @@ -287,7 +287,7 @@ dist_noinst_HEADERS = apc-mib.h apc-hid.h baytech-mib.h bcmxcp.h bcmxcp_ser.h \
xppc-mib.h huawei-mib.h eaton-ats16-mib.h apc-ats-mib.h raritan-px2-mib.h eaton-ats30-mib.h \
apc-pdu-mib.h eaton-pdu-genesis2-mib.h eaton-pdu-marlin-mib.h \
eaton-pdu-pulizzi-mib.h eaton-pdu-revelation-mib.h emerson-avocent-pdu-mib.h \
hpe-pdu-mib.h
hpe-pdu-mib.h powervar-hid.h

# Define a dummy library so that Automake builds rules for the
# corresponding object files. This library is not actually built,
Expand Down
24 changes: 16 additions & 8 deletions drivers/libusb.c
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,9 @@ upsdrv_info_t comm_upsdrv_info = {

#define MAX_REPORT_SIZE 0x1800

/* Used for Powervar UPS to make sure we use the right interface in the Composite device */
int hid_rep_index = 0;

static void libusb_close(usb_dev_handle *udev);

/*! Add USB-related driver variables with addvar().
Expand Down Expand Up @@ -239,6 +242,11 @@ static int libusb_open(usb_dev_handle **udevp, USBDevice_t *curDevice, USBDevice
upsdebugx(2, "- Bus: %s", curDevice->Bus ? curDevice->Bus : "unknown");
upsdebugx(2, "- Device release number: %04x", curDevice->bcdDevice);

/* Powervar UPS is a composite device. Index must be 1 to select the right interface */
if ((curDevice->VendorID == 0x4234) && (curDevice->ProductID == 0x0002)) {
hid_rep_index = 1;
upsdebugx(2, "Set rep index to 1");
}
if ((curDevice->VendorID == 0x463) && (curDevice->bcdDevice == 0x0202)) {
hid_desc_index = 1;
}
Expand Down Expand Up @@ -275,11 +283,11 @@ static int libusb_open(usb_dev_handle **udevp, USBDevice_t *curDevice, USBDevice
* it force device claiming by unbinding
* attached driver... From libhid */
retries = 3;
while (usb_claim_interface(udev, 0) < 0) {
while (usb_claim_interface(udev, hid_rep_index) < 0) {

upsdebugx(2, "failed to claim USB device: %s", usb_strerror());

if (usb_detach_kernel_driver_np(udev, 0) < 0) {
if (usb_detach_kernel_driver_np(udev, hid_rep_index) < 0) {
upsdebugx(2, "failed to detach kernel driver from USB device: %s", usb_strerror());
} else {
upsdebugx(2, "detached kernel driver from USB device...");
Expand All @@ -292,7 +300,7 @@ static int libusb_open(usb_dev_handle **udevp, USBDevice_t *curDevice, USBDevice
fatalx(EXIT_FAILURE, "Can't claim USB device [%04x:%04x]: %s", curDevice->VendorID, curDevice->ProductID, usb_strerror());
}
#else
if (usb_claim_interface(udev, 0) < 0) {
if (usb_claim_interface(udev, hid_rep_index) < 0) {
fatalx(EXIT_FAILURE, "Can't claim USB device [%04x:%04x]: %s", curDevice->VendorID, curDevice->ProductID, usb_strerror());
}
#endif
Expand All @@ -316,7 +324,7 @@ static int libusb_open(usb_dev_handle **udevp, USBDevice_t *curDevice, USBDevice
/* FIRST METHOD: ask for HID descriptor directly. */
/* res = usb_get_descriptor(udev, USB_DT_HID, hid_desc_index, buf, 0x9); */
res = usb_control_msg(udev, USB_ENDPOINT_IN+1, USB_REQ_GET_DESCRIPTOR,
(USB_DT_HID << 8) + hid_desc_index, 0, buf, 0x9, USB_TIMEOUT);
(USB_DT_HID << 8) + hid_desc_index, hid_rep_index, buf, 0x9, USB_TIMEOUT);

if (res < 0) {
upsdebugx(2, "Unable to get HID descriptor (%s)", usb_strerror());
Expand All @@ -343,7 +351,7 @@ static int libusb_open(usb_dev_handle **udevp, USBDevice_t *curDevice, USBDevice

/* for now, we always assume configuration 0, interface 0,
altsetting 0, as above. */
iface = &dev->config[0].interface[0].altsetting[0];
iface = &dev->config[0].interface[hid_rep_index].altsetting[0];
for (i=0; i<iface->extralen; i+=iface->extra[i]) {
upsdebugx(4, "i=%d, extra[i]=%02x, extra[i+1]=%02x", i,
iface->extra[i], iface->extra[i+1]);
Expand Down Expand Up @@ -389,7 +397,7 @@ static int libusb_open(usb_dev_handle **udevp, USBDevice_t *curDevice, USBDevice

/* res = usb_get_descriptor(udev, USB_DT_REPORT, hid_desc_index, bigbuf, rdlen); */
res = usb_control_msg(udev, USB_ENDPOINT_IN+1, USB_REQ_GET_DESCRIPTOR,
(USB_DT_REPORT << 8) + hid_desc_index, 0, rdbuf, rdlen, USB_TIMEOUT);
(USB_DT_REPORT << 8) + hid_desc_index, hid_rep_index, rdbuf, rdlen, USB_TIMEOUT);

if (res < 0)
{
Expand Down Expand Up @@ -486,7 +494,7 @@ static int libusb_get_report(usb_dev_handle *udev, int ReportId, unsigned char *
USB_ENDPOINT_IN + USB_TYPE_CLASS + USB_RECIP_INTERFACE,
0x01, /* HID_REPORT_GET */
ReportId+(0x03<<8), /* HID_REPORT_TYPE_FEATURE */
0, raw_buf, ReportSize, USB_TIMEOUT);
hid_rep_index, raw_buf, ReportSize, USB_TIMEOUT);

/* Ignore "protocol stall" (for unsupported request) on control endpoint */
if (ret == -EPIPE) {
Expand All @@ -508,7 +516,7 @@ static int libusb_set_report(usb_dev_handle *udev, int ReportId, unsigned char *
USB_ENDPOINT_OUT + USB_TYPE_CLASS + USB_RECIP_INTERFACE,
0x09, /* HID_REPORT_SET = 0x09*/
ReportId+(0x03<<8), /* HID_REPORT_TYPE_FEATURE */
0, raw_buf, ReportSize, USB_TIMEOUT);
hid_rep_index, raw_buf, ReportSize, USB_TIMEOUT);

/* Ignore "protocol stall" (for unsupported request) on control endpoint */
if (ret == -EPIPE) {
Expand Down
141 changes: 141 additions & 0 deletions drivers/powervar-hid.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,141 @@
/* powervar-hid.c - subdriver to monitor Powervar USB/HID devices with NUT
*
* Copyright (C)
* 2003 - 2012 Arnaud Quette <ArnaudQuette@Eaton.com>
* 2005 - 2006 Peter Selinger <selinger@users.sourceforge.net>
* 2008 - 2009 Arjen de Korte <adkorte-guest@alioth.debian.org>
* 2013 Charles Lepple <clepple+nut@gmail.com>
Comment thread
jimklimov marked this conversation as resolved.
* 2019 AMETEK Powervar - Andrew McCartney <andrew.mccartney@ametek.com>
*
* Note: this subdriver was initially generated as a "stub" by the
* gen-usbhid-subdriver script. It must be customized.
*
* 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
*/

#include "usbhid-ups.h"
#include "powervar-hid.h"
#include "main.h" /* for getval() */
#include "usb-common.h"

#define POWERVAR_HID_VERSION "Powervar HID 0.19"
/* FIXME: experimental flag to be put in upsdrv_info */

/* Powervar */
#define POWERVAR_VENDORID 0x4234

/* USB IDs device table */
static usb_device_id_t powervar_usb_device_table[] = {
/* Powervar */
{ USB_DEVICE(POWERVAR_VENDORID, 0x0002), NULL },

/* Terminating entry */
{ -1, -1, NULL }
};


/* --------------------------------------------------------------- */
/* Vendor-specific usage table */
/* --------------------------------------------------------------- */

/* POWERVAR usage table */
static usage_lkp_t powervar_usage_lkp[] = {
{ "POWERVAR1", 0xff000001 },
{ NULL, 0 }
};

static usage_tables_t powervar_utab[] = {
powervar_usage_lkp,
hid_usage_lkp,
NULL,
};

/* --------------------------------------------------------------- */
/* HID2NUT lookup table */
/* --------------------------------------------------------------- */

static hid_info_t powervar_hid2nut[] = {

/* Battery page */
{ "battery.type", 0, 0, "UPS.PowerSummary.iDeviceChemistry", NULL, "%s", 0, stringid_conversion },
{ "battery.charge", 0, 0, "UPS.PowerSummary.RemainingCapacity", NULL, "%.0f", 0, NULL },
{ "battery.capacity", 0, 0, "UPS.PowerSummary.FullChargeCapacity", NULL, "%.0f", 0, NULL },
{ "battery.runtime", 0, 0, "UPS.PowerSummary.RuntimeToEmpty", NULL, "%.0f", 0, NULL },

/* Special case: ups.status & ups.alarm */
{ "BOOL", 0, 0, "UPS.PowerSummary.PresentStatus.ACPresent", NULL, NULL, HU_FLAG_QUICK_POLL, online_info },
{ "BOOL", 0, 0, "UPS.PowerSummary.PresentStatus.Discharging", NULL, NULL, HU_FLAG_QUICK_POLL, discharging_info },
{ "BOOL", 0, 0, "UPS.PowerSummary.PresentStatus.Charging", NULL, NULL, HU_FLAG_QUICK_POLL, charging_info },
{ "BOOL", 0, 0, "UPS.PowerSummary.PresentStatus.ShutdownImminent", NULL, NULL, 0, shutdownimm_info },
{ "BOOL", 0, 0, "UPS.PowerSummary.PresentStatus.BelowRemainingCapacityLimit", NULL, NULL, 0, lowbatt_info },
{ "BOOL", 0, 0, "UPS.PowerSummary.PresentStatus.Overload", NULL, NULL, 0, overload_info },
{ "BOOL", 0, 0, "UPS.PowerSummary.PresentStatus.NeedReplacement", NULL, NULL, 0, replacebatt_info },
{ "BOOL", 0, 0, "UPS.PowerSummary.PresentStatus.RemainingTimeLimitExpired", NULL, NULL, 0, timelimitexpired_info },
{ "BOOL", 0, 0, "UPS.PowerSummary.PresentStatus.InternalFailure", NULL, NULL, 0, yes_no_info },
{ "BOOL", 0, 0, "UPS.PowerSummary.PresentStatus.Good", NULL, NULL, 0, yes_no_info },
{ "BOOL", 0, 0, "UPS.PowerSummary.PresentStatus.OverTemperature", NULL, NULL, 0, overheat_info },
{ "BOOL", 0, 0, "UPS.PowerSummary.PresentStatus.FullyCharged", NULL, NULL, 0, fullycharged_info },
{ "BOOL", 0, 0, "UPS.PowerSummary.PresentStatus.FullyDischarged", NULL, NULL, 0, depleted_info },
Comment thread
aquette marked this conversation as resolved.

/* end of structure. */
{ NULL, 0, 0, NULL, NULL, NULL, 0, NULL }
};

static const char *powervar_format_model(HIDDevice_t *hd) {
return hd->Product;
}

static const char *powervar_format_mfr(HIDDevice_t *hd) {
return hd->Vendor ? hd->Vendor : "Powervar";
}

static const char *powervar_format_serial(HIDDevice_t *hd) {
return hd->Serial;
}

/* this function allows the subdriver to "claim" a device: return 1 if
* the device is supported by this subdriver, else 0. */
static int powervar_claim(HIDDevice_t *hd)
{
int status = is_usb_device_supported(powervar_usb_device_table, hd);

switch (status)
{
case POSSIBLY_SUPPORTED:
/* by default, reject, unless the productid option is given */
if (getval("productid")) {
return 1;
}
possibly_supported("Powervar", hd);
return 0;

case SUPPORTED:
return 1;

case NOT_SUPPORTED:
default:
return 0;
}
}

subdriver_t powervar_subdriver = {
POWERVAR_HID_VERSION,
powervar_claim,
powervar_utab,
powervar_hid2nut,
powervar_format_model,
powervar_format_mfr,
powervar_format_serial,
};
30 changes: 30 additions & 0 deletions drivers/powervar-hid.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
/* powervar-hid.h - subdriver to monitor Powervar USB/HID devices with NUT
*
* Copyright (C)
* 2003 - 2009 Arnaud Quette <ArnaudQuette@Eaton.com>
* 2005 - 2006 Peter Selinger <selinger@users.sourceforge.net>
* 2008 - 2009 Arjen de Korte <adkorte-guest@alioth.debian.org>
*
* 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
*/

#ifndef POWERVAR_HID_H
#define POWERVAR_HID_H

#include "usbhid-ups.h"

extern subdriver_t powervar_subdriver;

#endif /* POWERVAR_HID_H */
2 changes: 2 additions & 0 deletions drivers/usbhid-ups.c
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@
#include "tripplite-hid.h"
#include "idowell-hid.h"
#include "openups-hid.h"
#include "powervar-hid.h"
#endif

/* master list of avaiable subdrivers */
Expand All @@ -66,6 +67,7 @@ static subdriver_t *subdriver_list[] = {
&tripplite_subdriver,
&idowell_subdriver,
&openups_subdriver,
&powervar_subdriver,
#endif
NULL
};
Expand Down