1 /* cps-hid.c - subdriver to monitor CPS USB/HID devices with NUT
4 * 2003 - 2008 Arnaud Quette <arnaud.quette@free.fr>
5 * 2005 - 2006 Peter Selinger <selinger@users.sourceforge.net>
7 * Note: this subdriver was initially generated as a "stub" by the
8 * gen-usbhid-subdriver script. It must be customized.
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by
12 * the Free Software Foundation; either version 2 of the License, or
13 * (at your option) any later version.
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
20 * You should have received a copy of the GNU General Public License
21 * along with this program; if not, write to the Free Software
22 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
26 #include "main.h" /* for getval() */
27 #include "usbhid-ups.h"
29 #include "usb-common.h"
31 #define CPS_HID_VERSION "CyberPower HID 0.3"
33 /* Cyber Power Systems */
34 #define CPS_VENDORID 0x0764
37 * For some devices, the reported battery voltage is off by factor
38 * of 1.5 so we need to apply a scale factor to it to get the real
39 * battery voltage. By default, the factor is 1 (no scaling).
41 static double battery_scale
= 1;
43 static void *cps_battery_scale(USBDevice_t
*device
)
45 battery_scale
= 0.667;
49 /* USB IDs device table */
50 static usb_device_id_t cps_usb_device_table
[] = {
51 /* 900AVR/BC900D, CP1200AVR/BC1200D */
52 { USB_DEVICE(CPS_VENDORID
, 0x0005), NULL
},
54 { USB_DEVICE(CPS_VENDORID
, 0x0501), &cps_battery_scale
},
55 /* OR2200LCDRM2U, OR700LCDRM1U, PR6000LCDRTXL5U */
56 { USB_DEVICE(CPS_VENDORID
, 0x0601), NULL
},
58 /* Terminating entry */
62 /* returns statically allocated string - must not use it again before
64 static const char *cps_battvolt_fun(double value
)
68 snprintf(buf
, sizeof(buf
), "%.1f", battery_scale
* value
);
73 static info_lkp_t cps_battvolt
[] = {
74 { 0, NULL
, &cps_battvolt_fun
}
77 /* returns statically allocated string - must not use it again before
79 static const char *cps_battcharge_fun(double value
)
83 /* clamp battery charge to 100% */
84 snprintf(buf
, sizeof(buf
), "%.0f", value
< 100.0 ? value
: 100.0);
89 static info_lkp_t cps_battcharge
[] = {
90 { 0, NULL
, &cps_battcharge_fun
}
93 /* --------------------------------------------------------------- */
94 /* Vendor-specific usage table */
95 /* --------------------------------------------------------------- */
98 static usage_lkp_t cps_usage_lkp
[] = {
102 static usage_tables_t cps_utab
[] = {
108 /* --------------------------------------------------------------- */
109 /* HID2NUT lookup table */
110 /* --------------------------------------------------------------- */
112 static hid_info_t cps_hid2nut
[] = {
113 /* { "unmapped.ups.powersummary.rechargeable", 0, 0, "UPS.PowerSummary.Rechargeable", NULL, "%.0f", 0, NULL }, */
114 /* { "unmapped.ups.powersummary.capacitymode", 0, 0, "UPS.PowerSummary.CapacityMode", NULL, "%.0f", 0, NULL }, */
115 /* { "unmapped.ups.powersummary.designcapacity", 0, 0, "UPS.PowerSummary.DesignCapacity", NULL, "%.0f", 0, NULL }, */
116 /* { "unmapped.ups.powersummary.capacitygranularity1", 0, 0, "UPS.PowerSummary.CapacityGranularity1", NULL, "%.0f", 0, NULL }, */
117 /* { "unmapped.ups.powersummary.capacitygranularity2", 0, 0, "UPS.PowerSummary.CapacityGranularity2", NULL, "%.0f", 0, NULL }, */
118 /* { "unmapped.ups.powersummary.fullchargecapacity", 0, 0, "UPS.PowerSummary.FullChargeCapacity", NULL, "%.0f", 0, NULL }, */
121 { "battery.type", 0, 0, "UPS.PowerSummary.iDeviceChemistry", NULL
, "%s", 0, stringid_conversion
},
122 { "battery.mfr.date", 0, 0, "UPS.PowerSummary.iOEMInformation", NULL
, "%s", 0, stringid_conversion
},
123 { "battery.charge.warning", 0, 0, "UPS.PowerSummary.WarningCapacityLimit", NULL
, "%.0f", 0, NULL
},
124 { "battery.charge.low", ST_FLAG_RW
| ST_FLAG_STRING
, 10, "UPS.PowerSummary.RemainingCapacityLimit", NULL
, "%.0f", HU_FLAG_SEMI_STATIC
, NULL
},
125 { "battery.charge", 0, 0, "UPS.PowerSummary.RemainingCapacity", NULL
, "%s", 0, cps_battcharge
},
126 { "battery.runtime", 0, 0, "UPS.PowerSummary.RunTimeToEmpty", NULL
, "%.0f", 0, NULL
},
127 { "battery.runtime.low", ST_FLAG_RW
| ST_FLAG_STRING
, 10, "UPS.PowerSummary.RemainingTimeLimit", NULL
, "%.0f", HU_FLAG_SEMI_STATIC
, NULL
},
128 { "battery.voltage.nominal", 0, 0, "UPS.PowerSummary.ConfigVoltage", NULL
, "%.0f", 0, NULL
},
129 { "battery.voltage", 0, 0, "UPS.PowerSummary.Voltage", NULL
, "%s", 0, cps_battvolt
},
132 { "ups.load", 0, 0, "UPS.Output.PercentLoad", NULL
, "%.0f", 0, NULL
},
133 { "ups.beeper.status", 0, 0, "UPS.PowerSummary.AudibleAlarmControl", NULL
, "%s", 0, beeper_info
},
134 { "ups.test.result", 0, 0, "UPS.Output.Test", NULL
, "%s", 0, test_read_info
},
135 { "ups.realpower.nominal", 0, 0, "UPS.Output.ConfigActivePower", NULL
, "%.0f", 0, NULL
},
136 { "ups.delay.start", ST_FLAG_RW
| ST_FLAG_STRING
, 10, "UPS.Output.DelayBeforeStartup", NULL
, DEFAULT_ONDELAY
, HU_FLAG_ABSENT
, NULL
},
137 { "ups.delay.shutdown", ST_FLAG_RW
| ST_FLAG_STRING
, 10, "UPS.Output.DelayBeforeShutdown", NULL
, DEFAULT_OFFDELAY
, HU_FLAG_ABSENT
, NULL
},
138 { "ups.timer.start", 0, 0, "UPS.Output.DelayBeforeStartup", NULL
, "%.0f", HU_FLAG_QUICK_POLL
, NULL
},
139 { "ups.timer.shutdown", 0, 0, "UPS.Output.DelayBeforeShutdown", NULL
, "%.0f", HU_FLAG_QUICK_POLL
, NULL
},
140 { "ups.timer.reboot", 0, 0, "UPS.Output.DelayBeforeReboot", NULL
, "%.0f", HU_FLAG_QUICK_POLL
, NULL
},
142 /* Special case: ups.status & ups.alarm */
143 { "BOOL", 0, 0, "UPS.PowerSummary.PresentStatus.ACPresent", NULL
, NULL
, HU_FLAG_QUICK_POLL
, online_info
},
144 { "BOOL", 0, 0, "UPS.PowerSummary.PresentStatus.Charging", NULL
, NULL
, HU_FLAG_QUICK_POLL
, charging_info
},
145 { "BOOL", 0, 0, "UPS.PowerSummary.PresentStatus.Discharging", NULL
, NULL
, HU_FLAG_QUICK_POLL
, discharging_info
},
146 { "BOOL", 0, 0, "UPS.PowerSummary.PresentStatus.BelowRemainingCapacityLimit", NULL
, NULL
, HU_FLAG_QUICK_POLL
, lowbatt_info
},
147 { "BOOL", 0, 0, "UPS.PowerSummary.PresentStatus.FullyCharged", NULL
, NULL
, 0, fullycharged_info
},
148 { "BOOL", 0, 0, "UPS.PowerSummary.PresentStatus.RemainingTimeLimitExpired", NULL
, NULL
, 0, timelimitexpired_info
},
149 { "BOOL", 0, 0, "UPS.Output.Boost", NULL
, NULL
, 0, boost_info
},
150 { "BOOL", 0, 0, "UPS.Output.Overload", NULL
, NULL
, 0, overload_info
},
153 { "input.voltage.nominal", 0, 0, "UPS.Input.ConfigVoltage", NULL
, "%.0f", 0, NULL
},
154 { "input.voltage", 0, 0, "UPS.Input.Voltage", NULL
, "%.1f", 0, NULL
},
155 { "input.transfer.low", ST_FLAG_RW
| ST_FLAG_STRING
, 10, "UPS.Input.LowVoltageTransfer", NULL
, "%.0f", HU_FLAG_SEMI_STATIC
, NULL
},
156 { "input.transfer.high", ST_FLAG_RW
| ST_FLAG_STRING
, 10, "UPS.Input.HighVoltageTransfer", NULL
, "%.0f", HU_FLAG_SEMI_STATIC
, NULL
},
159 { "output.voltage", 0, 0, "UPS.Output.Voltage", NULL
, "%.1f", 0, NULL
},
160 { "output.voltage.nominal", 0, 0, "UPS.Output.ConfigVoltage", NULL
, "%.0f", 0, NULL
},
162 /* instant commands. */
163 { "test.battery.start.quick", 0, 0, "UPS.Output.Test", NULL
, "1", HU_TYPE_CMD
, NULL
},
164 { "test.battery.start.deep", 0, 0, "UPS.Output.Test", NULL
, "2", HU_TYPE_CMD
, NULL
},
165 { "test.battery.stop", 0, 0, "UPS.Output.Test", NULL
, "3", HU_TYPE_CMD
, NULL
},
166 { "load.off.delay", 0, 0, "UPS.Output.DelayBeforeShutdown", NULL
, DEFAULT_OFFDELAY
, HU_TYPE_CMD
, NULL
},
167 { "load.on.delay", 0, 0, "UPS.Output.DelayBeforeStartup", NULL
, DEFAULT_ONDELAY
, HU_TYPE_CMD
, NULL
},
168 { "shutdown.stop", 0, 0, "UPS.Output.DelayBeforeShutdown", NULL
, "-1", HU_TYPE_CMD
, NULL
},
169 { "shutdown.reboot", 0, 0, "UPS.Output.DelayBeforeReboot", NULL
, "10", HU_TYPE_CMD
, NULL
},
170 { "beeper.on", 0, 0, "UPS.PowerSummary.AudibleAlarmControl", NULL
, "2", HU_TYPE_CMD
, NULL
},
171 { "beeper.off", 0, 0, "UPS.PowerSummary.AudibleAlarmControl", NULL
, "3", HU_TYPE_CMD
, NULL
},
172 { "beeper.enable", 0, 0, "UPS.PowerSummary.AudibleAlarmControl", NULL
, "2", HU_TYPE_CMD
, NULL
},
173 { "beeper.disable", 0, 0, "UPS.PowerSummary.AudibleAlarmControl", NULL
, "1", HU_TYPE_CMD
, NULL
},
174 { "beeper.mute", 0, 0, "UPS.PowerSummary.AudibleAlarmControl", NULL
, "3", HU_TYPE_CMD
, NULL
},
176 /* end of structure. */
177 { NULL
, 0, 0, NULL
, NULL
, NULL
, 0, NULL
}
180 static const char *cps_format_model(HIDDevice_t
*hd
) {
184 static const char *cps_format_mfr(HIDDevice_t
*hd
) {
185 return hd
->Vendor
? hd
->Vendor
: "CPS";
188 static const char *cps_format_serial(HIDDevice_t
*hd
) {
192 /* this function allows the subdriver to "claim" a device: return 1 if
193 * the device is supported by this subdriver, else 0. */
194 static int cps_claim(HIDDevice_t
*hd
) {
196 int status
= is_usb_device_supported(cps_usb_device_table
, hd
);
200 case POSSIBLY_SUPPORTED
:
201 /* by default, reject, unless the productid option is given */
202 if (getval("productid")) {
205 possibly_supported("CyberPower", hd
);
217 subdriver_t cps_subdriver
= {