From a937ca5775176177b07e5ebcb7bdc5d4e764e3a3 Mon Sep 17 00:00:00 2001 From: JungEon Kim Date: Sat, 13 Mar 2021 19:29:51 +0900 Subject: [PATCH 1/2] delta_ups-hid: Add support for Delta UPS Amplon R Series --- drivers/Makefile.am | 4 +- drivers/delta_ups-hid.c | 234 ++++++++++++++++++++++++++++++++++++++++ drivers/delta_ups-hid.h | 30 ++++++ drivers/usbhid-ups.c | 2 + 4 files changed, 268 insertions(+), 2 deletions(-) create mode 100644 drivers/delta_ups-hid.c create mode 100644 drivers/delta_ups-hid.h diff --git a/drivers/Makefile.am b/drivers/Makefile.am index 7fbab73423..54901e7078 100644 --- a/drivers/Makefile.am +++ b/drivers/Makefile.am @@ -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 powervar-hid.c + openups-hid.c powervar-hid.c delta_ups-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 @@ -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 powervar-hid.h + hpe-pdu-mib.h powervar-hid.h delta_ups-hid.h # Define a dummy library so that Automake builds rules for the # corresponding object files. This library is not actually built, diff --git a/drivers/delta_ups-hid.c b/drivers/delta_ups-hid.c new file mode 100644 index 0000000000..84ac72b791 --- /dev/null +++ b/drivers/delta_ups-hid.c @@ -0,0 +1,234 @@ +/* delta_ups-hid.c - data to monitor Delta UPS USB/HID devices with NUT + * + * Copyright (C) + * 2021 Jungeon Kim + * + * 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 "delta_ups-hid.h" +#include "usb-common.h" + +#define DELTA_UPS_HID_VERSION "Delta UPS HID 0.1" +#define DELTA_UPS_VENDORID 0x05dd + +static usb_device_id_t delta_ups_usb_device_table[] = { + /* Delta UPS Amplon R Series, Single Phase UPS, 1/2/3 kVA */ + { USB_DEVICE(DELTA_UPS_VENDORID, 0x041b), NULL }, + + /* Terminating entry */ + { -1, -1, NULL } +}; + +static usage_lkp_t delta_ups_usage_lkp[] = { + { "DeltaCustom", 0xffff0010 }, + + { "DeltaConfigTransferLowMax", 0xffff0057 }, + { "DeltaConfigTransferLowMin", 0xffff0058 }, + { "DeltaConfigTransferHighMax", 0xffff0059 }, + { "DeltaConfigTransferHighMin", 0xffff005a }, + { "DeltaConfigStartPowerRestoreDelay", 0xffff0081 }, + { "DeltaOutputSource", 0xffff0091 }, + { "DeltaModelName", 0xffff0075 }, + { "DeltaUPSType", 0xffff007c }, + { "DeltaConfigSensitivity", 0xffff009b }, + { "DeltaConfigStartPowerRestore", 0xffff009c }, + { "DeltaConfigExternalBatteryPack", 0xffff0061 }, + + /* Terminating entry */ + { NULL, 0 } +}; + +static usage_tables_t delta_ups_utab[] = { + delta_ups_usage_lkp, + hid_usage_lkp, + NULL, +}; + +static info_lkp_t delta_ups_sensitivity_info[] = { + { 0, "normal", NULL, NULL }, + { 1, "reduced", NULL, NULL }, + { 2, "low", NULL, NULL }, + + /* Terminating entry */ + { 0, NULL, NULL, NULL } +}; + +static const char *delta_ups_type_fun(double value) +{ + static const char* upstypes[] = { + "online", + "offline", + "line-interactive", + "3-phase", + "split-phase" + }; + + int type = (int)value & 0xf; + if (type == 6) { + type = 4; + } else if (2 < type && type <= 5) { + type -= 2; + } + + if (type < 0 || type > 4) { + return NULL; + } + + return upstypes[type]; +} + +static info_lkp_t delta_ups_type_info[] = { + { 0, NULL, delta_ups_type_fun }, + { 0, NULL, NULL, NULL } +}; + +static info_lkp_t delta_ups_output_source_info[] = { + { 0, "normal", NULL, NULL }, + { 1, "battery", NULL, NULL }, + { 2, "bypass/reserve", NULL, NULL }, + { 3, "reducing", NULL, NULL }, + { 4, "boosting", NULL, NULL }, + { 5, "manual bypass", NULL, NULL }, + { 6, "other", NULL, NULL }, + { 7, "no output", NULL, NULL }, + { 8, "on eco", NULL, NULL }, + { 0, NULL, NULL, NULL } +}; + +static hid_info_t delta_ups_hid2nut[] = { + { "input.sensitivity", ST_FLAG_RW, 0, "UPS.DeltaCustom.[1].DeltaConfigSensitivity", NULL, "%s", 0, delta_ups_sensitivity_info }, + { "input.voltage", 0, 0, "UPS.PowerSummary.Input.Voltage", NULL, "%.1f", HU_FLAG_QUICK_POLL, NULL }, + { "input.transfer.low", ST_FLAG_RW, 0, "UPS.PowerConverter.Output.LowVoltageTransfer", NULL, "%.0f", 0, NULL }, + { "input.transfer.high", ST_FLAG_RW, 0, "UPS.PowerConverter.Output.HighVoltageTransfer", NULL, "%.0f", 0, NULL }, + { "input.transfer.low.min", 0, 0, "UPS.PowerConverter.Output.DeltaConfigTransferLowMin", NULL, "%.0f", HU_FLAG_STATIC, NULL }, + { "input.transfer.low.max", 0, 0, "UPS.PowerConverter.Output.DeltaConfigTransferLowMax", NULL, "%.0f", HU_FLAG_STATIC, NULL }, + { "input.transfer.high.min", 0, 0, "UPS.PowerConverter.Output.DeltaConfigTransferHighMin", NULL, "%.0f", HU_FLAG_STATIC, NULL }, + { "input.transfer.high.max", 0, 0, "UPS.PowerConverter.Output.DeltaConfigTransferHighMax", NULL, "%.0f", HU_FLAG_STATIC, NULL }, + { "input.source", 0, 0, "UPS.OutletSystem.Outlet.DeltaOutputSource", NULL, "%s", 0, delta_ups_output_source_info }, + { "input.frequency", 0, 0, "UPS.PowerConverter.Input.Frequency", NULL, "%.1f", 0, NULL }, + + { "battery.voltage.nominal", 0, 0, "UPS.BatterySystem.Battery.ConfigVoltage", NULL, "%.0f", HU_FLAG_STATIC, NULL }, + { "battery.voltage", 0, 0, "UPS.BatterySystem.Battery.Voltage", NULL, "%.1f", 0, NULL }, + { "battery.charge", 0, 0, "UPS.BatterySystem.Battery.RemainingCapacity", NULL, "%.1f", 0, NULL }, + { "battery.charge.low", ST_FLAG_RW | ST_FLAG_STRING, 5, "UPS.PowerSummary.RemainingCapacityLimit", NULL, "%.0f", HU_FLAG_SEMI_STATIC, NULL }, + { "battery.charge.warning", 0, 0, "UPS.PowerSummary.WarningCapacityLimit", NULL, "%.0f", 0, NULL }, + { "battery.temperature", 0, 0, "UPS.BatterySystem.Temperature", NULL, "%s", 0, kelvin_celsius_conversion }, + { "battery.runtime", 0, 0, "UPS.PowerSummary.RunTimeToEmpty", NULL, "%.0f", 0, NULL }, + { "battery.capacity", 0, 0, "UPS.PowerSummary.FullChargeCapacity", NULL, "%.0f", 0, NULL }, + + { "output.voltage.nominal", 0, 0, "UPS.Flow.ConfigVoltage", NULL, "%.0f", HU_FLAG_STATIC, NULL }, + { "output.frequency.nominal", 0, 0, "UPS.Flow.ConfigFrequency", NULL, "%.0f", HU_FLAG_STATIC, NULL }, + { "output.voltage", 0, 0, "UPS.PowerConverter.Output.Voltage", NULL, "%.1f", 0, NULL }, + { "output.frequency", 0, 0, "UPS.PowerConverter.Output.Frequency", NULL, "%.1f", 0, NULL }, + { "output.current", 0, 0, "UPS.PowerConverter.Output.Current", NULL, "%.1f", 0, NULL }, + + { "ups.beeper.status", 0, 0, "UPS.PowerSummary.AudibleAlarmControl", NULL, "%s", 0, beeper_info }, + { "ups.test.result", 0, 0, "UPS.BatterySystem.Test", NULL, "%s", 0, test_read_info }, + { "ups.type", 0, 0, "UPS.DeltaCustom.[1].DeltaUPSType", NULL, "%s", HU_FLAG_STATIC, delta_ups_type_info }, + { "ups.start.auto", ST_FLAG_RW, 0, "UPS.DeltaCustom.[1].DeltaConfigStartPowerRestore", NULL, "%s", 0, yes_no_info }, + { "ups.power.nominal", 0, 0, "UPS.Flow.ConfigApparentPower", NULL, "%.0f", HU_FLAG_STATIC, NULL }, + { "ups.realpower", 0, 0, "UPS.PowerConverter.Output.ActivePower", NULL, "%.1f", 0, NULL }, + { "ups.load", 0, 0, "UPS.OutletSystem.Outlet.PercentLoad", NULL, "%.1f", 0, NULL }, + { "ups.delay.start", ST_FLAG_RW, 0, "UPS.OutletSystem.Outlet.DeltaConfigStartPowerRestoreDelay", NULL, "%.0f", 0, NULL}, + { "ups.timer.start", 0, 0, "UPS.OutletSystem.Outlet.DelayBeforeStartup", NULL, "%.0f", HU_FLAG_QUICK_POLL, NULL}, + { "ups.timer.shutdown", 0, 0, "UPS.OutletSystem.Outlet.DelayBeforeShutdown", NULL, "%.0f", HU_FLAG_QUICK_POLL, NULL}, + { "ups.timer.reboot", 0, 0, "UPS.OutletSystem.Outlet.DelayBeforeReboot", NULL, "%.0f", HU_FLAG_QUICK_POLL, NULL }, + + { "BOOL", 0, 0, "UPS.PowerSummary.PresentStatus.Good", NULL, NULL, HU_FLAG_QUICK_POLL, off_info }, + { "BOOL", 0, 0, "UPS.PowerSummary.PresentStatus.InternalFailure", NULL, NULL, HU_FLAG_QUICK_POLL, commfault_info}, + { "BOOL", 0, 0, "UPS.PowerSummary.PresentStatus.ShutdownImminent", NULL, NULL, HU_FLAG_QUICK_POLL, shutdownimm_info}, + { "BOOL", 0, 0, "UPS.PowerSummary.PresentStatus.ACPresent", NULL, NULL, HU_FLAG_QUICK_POLL, online_info}, + { "BOOL", 0, 0, "UPS.PowerSummary.PresentStatus.BelowRemainingCapacityLimit", NULL, NULL, HU_FLAG_QUICK_POLL, lowbatt_info}, + { "BOOL", 0, 0, "UPS.PowerSummary.PresentStatus.FullyCharged", NULL, NULL, HU_FLAG_QUICK_POLL, fullycharged_info }, + { "BOOL", 0, 0, "UPS.PowerSummary.PresentStatus.Charging", NULL, NULL, HU_FLAG_QUICK_POLL, charging_info}, + { "BOOL", 0, 0, "UPS.PowerSummary.PresentStatus.Discharging", NULL, NULL, HU_FLAG_QUICK_POLL, discharging_info}, + { "BOOL", 0, 0, "UPS.PowerSummary.PresentStatus.FullyDischarged", NULL, NULL, 0, depleted_info }, + { "BOOL", 0, 0, "UPS.PowerSummary.PresentStatus.NeedReplacement", NULL, NULL, 0, replacebatt_info}, + { "BOOL", 0, 0, "UPS.PowerConverter.PresentStatus.VoltageOutOfRange", NULL, NULL, 0, vrange_info }, + { "BOOL", 0, 0, "UPS.PowerConverter.PresentStatus.Buck", NULL, NULL, 0, trim_info }, + { "BOOL", 0, 0, "UPS.PowerConverter.PresentStatus.Boost", NULL, NULL, 0, boost_info }, + { "BOOL", 0, 0, "UPS.PowerConverter.PresentStatus.Overload", NULL, NULL, 0, overload_info }, + { "BOOL", 0, 0, "UPS.PowerConverter.PresentStatus.Used", NULL, NULL, 0, nobattery_info }, + { "BOOL", 0, 0, "UPS.PowerConverter.PresentStatus.OverTemperature", NULL, NULL, 0, overheat_info }, + { "BOOL", 0, 0, "UPS.PowerConverter.PresentStatus.InternalFailure", NULL, NULL, 0, commfault_info }, + { "BOOL", 0, 0, "UPS.PowerConverter.PresentStatus.AwaitingPower", NULL, NULL, 0, awaitingpower_info }, + + { "beeper.on", 0, 0, "UPS.PowerSummary.AudibleAlarmControl", NULL, "2", HU_TYPE_CMD, NULL }, + { "beeper.off", 0, 0, "UPS.PowerSummary.AudibleAlarmControl", NULL, "3", HU_TYPE_CMD, NULL }, + { "beeper.enable", 0, 0, "UPS.PowerSummary.AudibleAlarmControl", NULL, "2", HU_TYPE_CMD, NULL }, + { "beeper.disable", 0, 0, "UPS.PowerSummary.AudibleAlarmControl", NULL, "1", HU_TYPE_CMD, NULL }, + { "beeper.mute", 0, 0, "UPS.PowerSummary.AudibleAlarmControl", NULL, "3", HU_TYPE_CMD, NULL }, + + /* 10 seoncds battery test */ + { "test.battery.start.quick", 0, 0, "UPS.BatterySystem.Test", NULL, "1", HU_TYPE_CMD, NULL }, + /* test until battery low */ + { "test.battery.start.deep", 0, 0, "UPS.BatterySystem.Test", NULL, "2", HU_TYPE_CMD, NULL }, + { "test.battery.stop", 0, 0, "UPS.BatterySystem.Test", NULL, "3", HU_TYPE_CMD, NULL }, + + { "load.on.delay", 0, 0, "UPS.OutletSystem.Outlet.DelayBeforeStartup", NULL, DEFAULT_ONDELAY, HU_TYPE_CMD, NULL }, + { "load.off.delay", 0, 0, "UPS.OutletSystem.Outlet.DelayBeforeShutdown", NULL, DEFAULT_OFFDELAY, HU_TYPE_CMD, NULL }, + + { "shutdown.stop", 0, 0, "UPS.OutletSystem.Outlet.DelayBeforeShutdown", NULL, "-1", HU_TYPE_CMD, NULL }, + { "shutdown.reboot", 0, 0, "UPS.OutletSystem.Outlet.DelayBeforeReboot", NULL, "10", HU_TYPE_CMD, NULL }, + + /* Terminating entry */ + { NULL, 0, 0, NULL, NULL, NULL, 0, NULL } +}; + +static const char *delta_ups_format_mfr(HIDDevice_t *hd) { + return hd->Vendor; +} + +static const char *delta_ups_format_model(HIDDevice_t *hd) { + static char model[SMALLBUF]; + HIDGetItemString(udev, "UPS.DeltaCustom.[1].DeltaModelName", model, sizeof(model), delta_ups_utab); + + if (strlen(model) < 1) { + return hd->Product; + } + + return model; +} + +static const char *delta_ups_format_serial(HIDDevice_t *hd) { + return hd->Serial; +} + +static int delta_ups_claim(HIDDevice_t *hd) { + int status = is_usb_device_supported(delta_ups_usb_device_table, hd); + + switch (status) { + case SUPPORTED: + return 1; + case POSSIBLY_SUPPORTED: + case NOT_SUPPORTED: + default: + return 0; + } +} + +subdriver_t delta_ups_subdriver = { + DELTA_UPS_HID_VERSION, + delta_ups_claim, + delta_ups_utab, + delta_ups_hid2nut, + delta_ups_format_model, + delta_ups_format_mfr, + delta_ups_format_serial, +}; diff --git a/drivers/delta_ups-hid.h b/drivers/delta_ups-hid.h new file mode 100644 index 0000000000..f3526e03c4 --- /dev/null +++ b/drivers/delta_ups-hid.h @@ -0,0 +1,30 @@ +/* delta_ups-hid.h - data to monitor Delta UPS USB/HID devices with NUT + * + * Copyright (C) + * 2021 Jungeon Kim + * + * 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 DELTA_UPS_HID_H +#define DELTA_UPS_HID_H + +#include "usbhid-ups.h" + +extern subdriver_t delta_ups_subdriver; + +#endif /* DELTA_UPS_HID_H */ diff --git a/drivers/usbhid-ups.c b/drivers/usbhid-ups.c index d0090a56f2..2262037a79 100644 --- a/drivers/usbhid-ups.c +++ b/drivers/usbhid-ups.c @@ -50,6 +50,7 @@ #include "idowell-hid.h" #include "openups-hid.h" #include "powervar-hid.h" + #include "delta_ups-hid.h" #endif /* master list of avaiable subdrivers */ @@ -68,6 +69,7 @@ static subdriver_t *subdriver_list[] = { &idowell_subdriver, &openups_subdriver, &powervar_subdriver, + &delta_ups_subdriver, #endif NULL }; From 22db688a4e9088ff039bec6fd584bd9d964cc405 Mon Sep 17 00:00:00 2001 From: JungEon Kim Date: Sun, 14 Mar 2021 17:33:30 +0900 Subject: [PATCH 2/2] Add Delta UPS Amplon R Series in drivers.list --- data/driver.list.in | 1 + 1 file changed, 1 insertion(+) diff --git a/data/driver.list.in b/data/driver.list.in index 2c9d8bda8d..7985fdf389 100644 --- a/data/driver.list.in +++ b/data/driver.list.in @@ -258,6 +258,7 @@ "Dell" "ups" "5" "Various (XML/HTTP mode)" "UPS Network Management Card" "netxml-ups (experimental)" "Delta" "ups" "1" "GES602N" "" "belkin" +"Delta" "ups" "4" "Delta UPS Amplon R Series" "USB port" "usbhid-ups" "Deltec" "ups" "1" "PowerRite Pro II" "" "genericups upstype=15" "Deltec" "ups" "4" "PRM 450/700/1000/1500" "" "upscode2"