UPS: apcupsd clean sources
[tomato.git] / release / src / router / apcupsd / src / drivers / usb / usb.c
blob446fbc2bdffea62a6f810676d4ecf30c8e7dc28d
1 /*
2 * usb.c
4 * Public driver interface for all platform USB drivers.
6 * Based on linux-usb.c by Kern Sibbald
7 */
9 /*
10 * Copyright (C) 2001-2004 Kern Sibbald
11 * Copyright (C) 2004-2005 Adam Kropelin
13 * This program is free software; you can redistribute it and/or
14 * modify it under the terms of version 2 of the GNU General
15 * Public License as published by the Free Software Foundation.
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
20 * General Public License for more details.
22 * You should have received a copy of the GNU General Public
23 * License along with this program; if not, write to the Free
24 * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
25 * MA 02111-1307, USA.
28 #include "apc.h"
29 #include "usb.h"
30 #include "usb_common.h"
31 #include <math.h>
33 /* Implemented in platform-specific code */
34 int pusb_ups_get_capabilities(UPSINFO *ups, const struct s_known_info *known_info);
35 int pusb_ups_open(UPSINFO *ups);
36 int pusb_ups_close(UPSINFO *ups);
37 int pusb_get_value(UPSINFO *ups, int ci, USB_VALUE *uval);
38 int pusb_ups_check_state(UPSINFO *ups);
39 int pusb_ups_setup(UPSINFO *ups);
40 int pusb_write_int_to_ups(UPSINFO *ups, int ci, int value, const char *name);
41 int pusb_read_int_from_ups(UPSINFO *ups, int ci, int *value);
44 * A certain semi-ancient BackUPS Pro model breaks the USB spec in a
45 * particularly creative way: Some reports read back in ASCII instead of
46 * binary. And one value that should be in seconds is returned in minutes
47 * instead, just for fun. We detect and work around the breakage.
49 #define QUIRK_OLD_BACKUPS_PRO_MODEL_STRING "BackUPS Pro 500 FW:16.3.D USB FW:4"
50 static bool quirk_old_backups_pro = false;
53 * This table is used when walking through the USB reports to see
54 * what information found in the UPS that we want. If the usage_code
55 * and the physical code match, then we make an entry in the command
56 * index table containing the usage information provided by the UPS
57 * as well as the data type from this table. Entries in the table
58 * with ci == CI_NONE are not used, for the moment, they are
59 * retained just so they are not forgotten.
61 const struct s_known_info known_info[] = {
62 /* Page 0x84 is the Power Device Page */
63 /* CI USAGE PHYSICAL LOGICAL TYPE VOLATILE? */
64 {CI_NONE, 0x00840001, P_ANY, P_ANY, T_INDEX, false}, /* iName */
65 {CI_VLINE, 0x00840030, P_INPUT, P_ANY, T_UNITS, true }, /* Line Voltage */
66 {CI_VOUT, 0x00840030, P_OUTPUT, P_ANY, T_UNITS, true }, /* Output Voltage */
67 {CI_VBATT, 0x00840030, P_BATTERY, P_ANY, T_UNITS, true }, /* Battery Voltage */
68 {CI_VBATT, 0x00840030, P_ANY, P_PWSUM, T_UNITS, true }, /* Battery Voltage (alternative) */
69 {CI_NONE, 0x00840031, P_ANY, P_ANY, T_UNITS, false}, /* Current */
70 {CI_FREQ, 0x00840032, P_OUTPUT, P_ANY, T_UNITS, true }, /* Frequency */
71 {CI_NONE, 0x00840033, P_ANY, P_ANY, T_UNITS, false}, /* ApparentPower */
72 {CI_NONE, 0x00840034, P_ANY, P_ANY, T_UNITS, false}, /* ActivePower */
73 {CI_LOAD, 0x00840035, P_ANY, P_ANY, T_UNITS, true }, /* PercentLoad */
74 {CI_ITEMP, 0x00840036, P_BATTERY, P_ANY, T_UNITS, true }, /* Internal Temperature */
75 {CI_ATEMP, 0x00840036, P_APC1, P_ANY, T_UNITS, true }, /* Ambient Temperature */
76 {CI_HUMID, 0x00840037, P_ANY, P_ANY, T_UNITS, true }, /* Humidity */
77 {CI_NOMBATTV, 0x00840040, P_BATTERY, P_ANY, T_UNITS, false}, /* ConfigVoltage (battery) */
78 {CI_NOMBATTV, 0x00840040, P_ANY, P_PWSUM, T_UNITS, false}, /* ConfigVoltage (battery, alternate) */
79 {CI_NOMOUTV, 0x00840040, P_OUTPUT, P_ANY, T_UNITS, false}, /* ConfigVoltage (output) */
80 {CI_NOMINV, 0x00840040, P_INPUT, P_ANY, T_UNITS, false}, /* ConfigVoltage (input) */
81 {CI_NONE, 0x00840042, P_ANY, P_ANY, T_UNITS, false}, /* ConfigFrequency */
82 {CI_NONE, 0x00840043, P_ANY, P_ANY, T_UNITS, false}, /* ConfigApparentPower */
83 {CI_NOMPOWER, 0x00840044, P_ANY, P_ANY, T_UNITS, false}, /* ConfigActivePower */
84 {CI_LTRANS, 0x00840053, P_ANY, P_ANY, T_UNITS, false}, /* LowVoltageTransfer */
85 {CI_HTRANS, 0x00840054, P_ANY, P_ANY, T_UNITS, false}, /* HighVoltageTransfer */
86 {CI_DelayBeforeReboot, 0x00840055, P_ANY, P_ANY, T_UNITS, false}, /* DelayBeforeReboot */
87 {CI_DWAKE, 0x00840056, P_ANY, P_ANY, T_UNITS, false}, /* DelayBeforeStartup */
88 {CI_DelayBeforeShutdown, 0x00840057, P_ANY, P_ANY, T_UNITS, false}, /* DelayBeforeShutdown */
89 {CI_ST_STAT, 0x00840058, P_ANY, P_ANY, T_NONE, false}, /* Test */
90 {CI_DALARM, 0x0084005a, P_ANY, P_ANY, T_NONE, true }, /* AudibleAlarmControl */
91 {CI_NONE, 0x00840061, P_ANY, P_ANY, T_NONE, false}, /* Good */
92 {CI_IFailure, 0x00840062, P_ANY, P_ANY, T_NONE, false}, /* InternalFailure */
93 {CI_PWVoltageOOR, 0x00840063, P_ANY, P_ANY, T_NONE, false}, /* Volt out-of-range */
94 {CI_PWFrequencyOOR, 0x00840064, P_ANY, P_ANY, T_NONE, false}, /* Freq out-of-range */
95 {CI_Overload, 0x00840065, P_ANY, P_ANY, T_NONE, true }, /* Overload */
96 {CI_OverCharged, 0x00840066, P_ANY, P_ANY, T_NONE, false}, /* Overcharged */
97 {CI_OverTemp, 0x00840067, P_ANY, P_ANY, T_NONE, false}, /* Overtemp */
98 {CI_ShutdownRequested, 0x00840068, P_ANY, P_ANY, T_NONE, false}, /* ShutdownRequested */
99 {CI_ShutdownImminent, 0x00840069, P_ANY, P_ANY, T_NONE, true }, /* ShutdownImminent */
100 {CI_NONE, 0x0084006b, P_ANY, P_ANY, T_NONE, false}, /* Switch On/Off */
101 {CI_NONE, 0x0084006c, P_ANY, P_ANY, T_NONE, false}, /* Switchable */
102 {CI_Boost, 0x0084006e, P_ANY, P_ANY, T_NONE, true }, /* Boost */
103 {CI_Trim, 0x0084006f, P_ANY, P_ANY, T_NONE, true }, /* Buck */
104 {CI_CommunicationLost, 0x00840073, P_ANY, P_ANY, T_NONE, false}, /* CommunicationLost */
105 {CI_Manufacturer, 0x008400fd, P_ANY, P_ANY, T_INDEX, false}, /* iManufacturer */
106 {CI_UPSMODEL, 0x008400fe, P_ANY, P_ANY, T_INDEX, false}, /* iProduct */
107 {CI_SERNO, 0x008400ff, P_ANY, P_ANY, T_INDEX, false}, /* iSerialNumber */
108 {CI_MANDAT, 0x00850085, P_ANY, P_PWSUM, T_DATE, false}, /* ManufactureDate */
110 /* Page 0x85 is the Battery System Page */
111 /* CI USAGE PHYSICAL LOGICAL TYPE VOLATILE? */
112 {CI_RemCapLimit, 0x00850029, P_ANY, P_ANY, T_CAPACITY, false}, /* RemCapLimit */
113 {CI_RemTimeLimit, 0x0085002a, P_ANY, P_ANY, T_UNITS, false}, /* RemTimeLimit */
114 {CI_NONE, 0x0085002c, P_ANY, P_ANY, T_CAPACITY, false}, /* CapacityMode */
115 {CI_BelowRemCapLimit, 0x00850042, P_ANY, P_ANY, T_NONE, true }, /* BelowRemCapLimit */
116 {CI_RemTimeLimitExpired, 0x00850043, P_ANY, P_ANY, T_NONE, true }, /* RemTimeLimitExpired */
117 {CI_Charging, 0x00850044, P_ANY, P_ANY, T_NONE, false}, /* Charging */
118 {CI_Discharging, 0x00850045, P_ANY, P_ANY, T_NONE , true }, /* Discharging */
119 {CI_NeedReplacement, 0x0085004b, P_ANY, P_ANY, T_NONE , true }, /* NeedReplacement */
120 {CI_BATTLEV, 0x00850066, P_ANY, P_ANY, T_CAPACITY, true }, /* RemainingCapacity */
121 {CI_NONE, 0x00850067, P_ANY, P_ANY, T_CAPACITY, false}, /* FullChargeCapacity */
122 {CI_RUNTIM, 0x00850068, P_ANY, P_ANY, T_UNITS, true }, /* RunTimeToEmpty */
123 {CI_CycleCount, 0x0085006b, P_ANY, P_ANY, T_NONE, false},
124 {CI_BattPackLevel, 0x00850080, P_ANY, P_ANY, T_NONE, false}, /* BattPackLevel */
125 {CI_NONE, 0x00850083, P_ANY, P_ANY, T_CAPACITY, false}, /* DesignCapacity */
126 {CI_BATTDAT, 0x00850085, P_BATTERY, P_ANY, T_DATE, false}, /* ManufactureDate */
127 {CI_IDEN, 0x00850088, P_ANY, P_ANY, T_INDEX, false}, /* iDeviceName */
128 {CI_NONE, 0x00850089, P_ANY, P_ANY, T_INDEX, false}, /* iDeviceChemistry */
129 {CI_NONE, 0x0085008b, P_ANY, P_ANY, T_NONE, false}, /* Rechargeable */
130 {CI_WarningCapacityLimit, 0x0085008c, P_ANY, P_ANY, T_CAPACITY, false}, /* WarningCapacityLimit */
131 {CI_NONE, 0x0085008d, P_ANY, P_ANY, T_CAPACITY, false}, /* CapacityGranularity1 */
132 {CI_NONE, 0x0085008e, P_ANY, P_ANY, T_CAPACITY, false}, /* CapacityGranularity2 */
133 {CI_NONE, 0x0085008f, P_ANY, P_ANY, T_INDEX, false}, /* iOEMInformation */
134 {CI_ACPresent, 0x008500d0, P_ANY, P_ANY, T_NONE, true }, /* ACPresent */
135 {CI_BatteryPresent, 0x008500d1, P_ANY, P_ANY, T_NONE, true }, /* BatteryPresent */
136 {CI_ChargerVoltageOOR, 0x008500d8, P_ANY, P_ANY, T_NONE, false}, /* Volt out-of-range */
137 {CI_ChargerCurrentOOR, 0x008500d9, P_ANY, P_ANY, T_NONE, false}, /* Current out-of-range */
138 {CI_CurrentNotRegulated, 0x008500da, P_ANY, P_ANY, T_NONE, false}, /* Current not regulated */
139 {CI_VoltageNotRegulated, 0x008500db, P_ANY, P_ANY, T_NONE, false}, /* VoltageNotRegulated */
141 /* Pages 0xFF00 to 0xFFFF are vendor specific */
142 /* CI USAGE PHYSICAL LOGICAL TYPE VOLATILE? */
143 {CI_STESTI, 0xFF86001a, P_ANY, P_ANY, T_NONE, false}, /* APCSelfTestInterval */
144 {CI_STATUS, 0xFF860060, P_ANY, P_ANY, T_BITS, true }, /* APCStatusFlag */
145 {CI_DSHUTD, 0xFF860076, P_ANY, P_ANY, T_UNITS, false}, /* APCShutdownAfterDelay */
146 {CI_NONE, 0xFF860005, P_ANY, P_ANY, T_NONE, false}, /* APCGeneralCollection */
147 {CI_APCForceShutdown, 0xFF86007C, P_ANY, P_ANY, T_NONE, false}, /* APCForceShutdown */
148 {CI_TESTALARM, 0xFF860072, P_ANY, P_ANY, T_NONE, false}, /* APCTestAlarm */
149 // Removed the below due to all recent UPSes having the same garbage in this field
150 // {CI_BattReplaceDate, 0xFF860016, P_ANY, P_ANY, T_APCDATE, false}, /* APCBattReplaceDate */
151 {CI_NONE, 0xFF860042, P_ANY, P_ANY, T_NONE, false}, /* APC_UPS_FirmwareRevision */
152 {CI_NONE, 0xFF860079, P_ANY, P_ANY, T_NONE, false}, /* APC_USB_FirmwareRevision */
153 {CI_RETPCT, 0xFF860019, P_ANY, P_ANY, T_CAPACITY, false}, /* APCBattCapBeforeStartup */
154 {CI_APCDelayBeforeStartup, 0xFF86007E, P_ANY, P_ANY, T_UNITS, false}, /* APCDelayBeforeStartup */
155 {CI_APCDelayBeforeShutdown, 0xFF86007D, P_ANY, P_ANY, T_UNITS, false}, /* APCDelayBeforeShutdown */
156 {CI_APCLineFailCause, 0xFF860052, P_ANY, P_ANY, T_NONE, true}, /* APCLineFailCause */
157 {CI_SENS, 0xFF860061, P_ANY, P_ANY, T_NONE, false}, /* APCSensitivity */
158 {CI_BUPBattCapBeforeStartup, 0x00860012, P_ANY, P_ANY, T_NONE, false}, /* BUPBattCapBeforeStartup */
159 {CI_BUPDelayBeforeStartup, 0x00860076, P_ANY, P_ANY, T_NONE, false}, /* BUPDelayBeforeStartup */
160 {CI_BUPSelfTest, 0x00860010, P_ANY, P_ANY, T_NONE, false}, /* BUPSelfTest */
161 {CI_BUPHibernate, 0x00850058, P_ANY, P_ANY, T_NONE, false}, /* BUPHibernate */
163 /* END OF TABLE */
164 {CI_NONE, 0x00000000, P_ANY, P_ANY, T_NONE, false} /* END OF TABLE */
168 * USB USAGE NOTES
170 * From the NUT project
172 * 0x860060 == "441HMLL" - looks like a 'capability' string
173 * == locale 4, 4 choices, 1 byte each
174 * == line sensitivity (high, medium, low, low)
175 * NOTE! the above does not seem to correspond to my info
177 * 0x860013 == 44200155090 - capability again
178 * == locale 4, 4 choices, 2 bytes, 00, 15, 50, 90
179 * == minimum charge to return online
181 * 0x860062 == D43133136127130
182 * == locale D, 4 choices, 3 bytes, 133, 136, 127, 130
183 * == high transfer voltage
185 * 0x860064 == D43103100097106
186 * == locale D, 4 choices, 3 bytes, 103, 100, 097, 106
187 * == low transfer voltage
189 * 0x860066 == 441HMLL (see 860060)
191 * 0x860074 == 4410TLN
192 * == locale 4, 4 choices, 1 byte, 0, T, L, N
193 * == alarm setting (5s, 30s, low battery, none)
195 * 0x860077 == 443060180300600
196 * == locale 4, 4 choices, 3 bytes, 060,180,300,600
197 * == wake-up delay (after power returns)
200 * From MGE -- MGE specific items
202 * TestPeriod 0xffff0045
203 * RemainingCapacityLimitSetting 0xffff004d
204 * LowVoltageBoostTransfer 0xffff0050
205 * HighVoltageBoostTransfer 0xffff0051
206 * LowVoltageBuckTransfer 0xffff0052
207 * HighVoltageBuckTransfer 0xffff0053
208 * iModel 0xffff00f0
213 * Operations that must be handled by platform-specific code
216 int usb_ups_check_state(UPSINFO *ups)
218 return pusb_ups_check_state(ups);
221 int usb_ups_open(UPSINFO *ups)
223 return pusb_ups_open(ups);
226 int usb_ups_close(UPSINFO *ups)
228 return pusb_ups_close(ups);
231 int usb_ups_setup(UPSINFO *ups)
233 return pusb_ups_setup(ups);
236 int usb_write_int_to_ups(UPSINFO *ups, int ci, int value, const char *name)
238 return pusb_write_int_to_ups(ups, ci, value, name);
241 int usb_read_int_from_ups(UPSINFO *ups, int ci, int *value)
243 return pusb_read_int_from_ups(ups, ci, value);
246 /* Fetch the given CI from the UPS */
247 #define URB_DELAY_MS 20
248 static bool usb_get_value(UPSINFO *ups, int ci, USB_VALUE *uval)
250 static struct timeval prev = {0};
251 struct timeval now;
252 struct timespec delay;
253 int diff;
256 * Some UPSes (650 CS and 800 RS, possibly others) lock up if
257 * control transfers are issued too quickly, so we throttle a
258 * bit here.
260 if (prev.tv_sec) {
261 gettimeofday(&now, NULL);
262 diff = TV_DIFF_MS(prev, now);
263 if (diff >= 0 && diff < URB_DELAY_MS) {
264 delay.tv_sec = 0;
265 delay.tv_nsec = (URB_DELAY_MS-diff)*1000000;
266 nanosleep(&delay, NULL);
269 gettimeofday(&prev, NULL);
271 return pusb_get_value(ups, ci, uval);
274 int usb_ups_get_capabilities(UPSINFO *ups)
276 int rc;
278 /* Run platform-specific capabilities code */
279 rc = pusb_ups_get_capabilities(ups, known_info);
280 if (!rc)
281 return 0;
284 * If the hardware supports CI_Discharging, ignore CI_ACPresent.
285 * Some hardware (RS 1500, possibly others) reports confusing
286 * values for these during self test. (Discharging=1 && ACPresent=1)
288 if (ups->UPS_Cap[CI_Discharging])
289 ups->UPS_Cap[CI_ACPresent] = false;
292 * Disable CI_NOMPOWER if UPS does not report it accurately.
293 * Several models appear to always return 0 for this value.
295 USB_VALUE uval;
296 if (ups->UPS_Cap[CI_NOMPOWER] &&
297 (!usb_get_value(ups, CI_NOMPOWER, &uval) ||
298 ((int)uval.dValue == 0))) {
299 Dmsg0(100, "NOMPOWER disabled due to invalid reading from UPS\n");
300 ups->UPS_Cap[CI_NOMPOWER] = false;
303 /* Detect broken BackUPS Pro model */
304 quirk_old_backups_pro = false;
305 if (ups->UPS_Cap[CI_UPSMODEL] && usb_get_value(ups, CI_UPSMODEL, &uval)) {
306 Dmsg1(250, "Checking for BackUPS Pro quirk \"%s\"\n", uval.sValue);
307 if (!strcmp(uval.sValue, QUIRK_OLD_BACKUPS_PRO_MODEL_STRING)) {
308 quirk_old_backups_pro = true;
309 Dmsg0(100, "BackUPS Pro quirk enabled\n");
313 return 1;
318 * Operations that are not supported
321 int usb_ups_program_eeprom(UPSINFO *ups, int command, const char *data)
323 /* We don't support this for USB */
324 return 0;
329 * Operations which are platform agnostic and therefore can be
330 * implemented here
334 * Given a CI and a raw uval, update the UPSINFO structure with the
335 * new value. Special handling for certain BackUPS Pro reports.
337 * Thanks to David Fries <David@Fries.net> for this code.
339 static bool usb_process_value_bup(UPSINFO* ups, int ci, USB_VALUE* uval)
341 int val = (int)uval->dValue;
342 char digits[] = { (val>>16) & 0xff, (val>>8) & 0xff, val & 0xff, 0 };
344 /* UPS_RUNTIME_LEFT */
345 if(ci == CI_RUNTIM)
347 ups->TimeLeft = uval->dValue; /* already minutes */
348 Dmsg1(200, "TimeLeft = %d\n", (int)ups->TimeLeft);
349 return true;
352 /* Bail if this value doesn't look to be ASCII encoded */
353 if(!isdigit(digits[0]) || !isdigit(digits[1]) || !isdigit(digits[2]))
354 return false;
356 switch(ci)
358 /* UPS_LOAD */
359 case CI_LOAD:
360 ups->UPSLoad = atoi(digits);
361 Dmsg1(200, "UPSLoad = %d\n", (int)ups->UPSLoad);
362 return true;
364 /* LOW_TRANSFER_LEVEL */
365 case CI_LTRANS:
366 ups->lotrans = atoi(digits);
367 return true;
369 /* HIGH_TRANSFER_LEVEL */
370 case CI_HTRANS:
371 ups->hitrans = atoi(digits);
372 return true;
374 /* LINE_FREQ */
375 case CI_FREQ:
376 ups->LineFreq = atoi(digits);
377 return true;
379 default:
380 return false;
385 * Given a CI and a raw uval, update the UPSINFO structure with the
386 * new value.
388 static void usb_process_value(UPSINFO* ups, int ci, USB_VALUE* uval)
390 int v, yy, mm, dd;
391 char *p;
392 static int bpcnt = 0;
395 * If BackUPS Pro quirk is enabled, try special decoding. If special decode
396 * fails, we continue with the normal protocol.
398 if (quirk_old_backups_pro && usb_process_value_bup(ups, ci, uval))
399 return;
402 * ADK FIXME: This switch statement is really excessive. Consider
403 * breaking it into volatile vs. non-volatile or perhaps an array
404 * of function pointers with handler functions for each CI.
407 switch(ci)
409 /* UPS_STATUS -- this is the most important status for apcupsd */
410 case CI_STATUS:
411 ups->Status &= ~0xff;
412 ups->Status |= uval->iValue & 0xff;
413 Dmsg1(200, "Status=0x%08x\n", ups->Status);
414 break;
416 case CI_ACPresent:
417 if (uval->iValue)
418 ups->set_online();
419 Dmsg1(200, "ACPresent=%d\n", uval->iValue);
420 break;
422 case CI_Discharging:
423 ups->set_online(!uval->iValue);
424 Dmsg1(200, "Discharging=%d\n", uval->iValue);
425 break;
427 case CI_BelowRemCapLimit:
428 if (uval->iValue)
429 ups->set_battlow();
430 Dmsg1(200, "BelowRemCapLimit=%d\n", uval->iValue);
431 break;
433 case CI_RemTimeLimitExpired:
434 if (uval->iValue)
435 ups->set_battlow();
436 Dmsg1(200, "RemTimeLimitExpired=%d\n", uval->iValue);
437 break;
439 case CI_ShutdownImminent:
440 if (uval->iValue)
441 ups->set_battlow();
442 Dmsg1(200, "ShutdownImminent=%d\n", uval->iValue);
443 break;
445 case CI_Boost:
446 if (uval->iValue)
447 ups->set_boost();
448 Dmsg1(200, "Boost=%d\n", uval->iValue);
449 break;
451 case CI_Trim:
452 if (uval->iValue)
453 ups->set_trim();
454 Dmsg1(200, "Trim=%d\n", uval->iValue);
455 break;
457 case CI_Overload:
458 if (uval->iValue)
459 ups->set_overload();
460 Dmsg1(200, "Overload=%d\n", uval->iValue);
461 break;
463 case CI_NeedReplacement:
464 if (uval->iValue)
465 ups->set_replacebatt(uval->iValue);
466 Dmsg1(200, "ReplaceBatt=%d\n", uval->iValue);
467 break;
469 /* LINE_VOLTAGE */
470 case CI_VLINE:
471 ups->LineVoltage = uval->dValue;
472 Dmsg1(200, "LineVoltage = %d\n", (int)ups->LineVoltage);
473 break;
475 /* OUTPUT_VOLTAGE */
476 case CI_VOUT:
477 ups->OutputVoltage = uval->dValue;
478 Dmsg1(200, "OutputVoltage = %d\n", (int)ups->OutputVoltage);
479 break;
481 /* BATT_FULL Battery level percentage */
482 case CI_BATTLEV:
483 ups->BattChg = uval->dValue;
484 Dmsg1(200, "BattCharge = %d\n", (int)ups->BattChg);
485 break;
487 /* BATT_VOLTAGE */
488 case CI_VBATT:
489 ups->BattVoltage = uval->dValue;
490 Dmsg1(200, "BattVoltage = %d\n", (int)ups->BattVoltage);
491 break;
493 /* UPS_LOAD */
494 case CI_LOAD:
495 ups->UPSLoad = uval->dValue;
496 Dmsg1(200, "UPSLoad = %d\n", (int)ups->UPSLoad);
497 break;
499 /* LINE_FREQ */
500 case CI_FREQ:
501 ups->LineFreq = uval->dValue;
502 Dmsg1(200, "LineFreq = %d\n", (int)ups->LineFreq);
503 break;
505 /* UPS_RUNTIME_LEFT */
506 case CI_RUNTIM:
507 ups->TimeLeft = uval->dValue / 60; /* convert to minutes */
508 Dmsg1(200, "TimeLeft = %d\n", (int)ups->TimeLeft);
509 break;
511 /* UPS_TEMP */
512 case CI_ITEMP:
513 ups->UPSTemp = uval->dValue - 273.15; /* convert to deg C. */
514 Dmsg1(200, "ITemp = %d\n", (int)ups->UPSTemp);
515 break;
517 /* Humidity percentage */
518 case CI_HUMID:
519 ups->humidity = uval->dValue;
520 Dmsg1(200, "Humidity = %d\n", (int)ups->humidity);
521 break;
523 /* Ambient temperature */
524 case CI_ATEMP:
525 ups->ambtemp = uval->dValue - 273.15; /* convert to deg C. */;
526 Dmsg1(200, "ATemp = %d\n", (int)ups->ambtemp);
527 break;
529 /* Self test results */
530 case CI_ST_STAT:
531 switch (uval->iValue) {
532 case 1: /* Passed */
533 ups->testresult = TEST_PASSED;
534 break;
535 case 2: /* Warning */
536 ups->testresult = TEST_WARNING;
537 break;
538 case 3: /* Error */
539 case 4: /* Aborted */
540 ups->testresult = TEST_FAILED;
541 break;
542 case 5: /* In progress */
543 ups->testresult = TEST_INPROGRESS;
544 break;
545 case 6: /* None */
546 ups->testresult = TEST_NONE;
547 break;
548 default:
549 ups->testresult = TEST_UNKNOWN;
550 break;
552 break;
554 /* Self test interval */
555 case CI_STESTI:
556 switch (uval->iValue) {
557 case 0:
558 astrncpy(ups->selftest, "None", sizeof(ups->selftest));
559 break;
560 case 1:
561 astrncpy(ups->selftest, "Power On", sizeof(ups->selftest));
562 break;
563 case 2:
564 astrncpy(ups->selftest, "7 days", sizeof(ups->selftest));
565 break;
566 default:
567 astrncpy(ups->selftest, "14 days", sizeof(ups->selftest));
568 break;
570 break;
572 /* Reason for last xfer to battery */
573 case CI_APCLineFailCause:
574 Dmsg1(100, "CI_APCLineFailCause=%d\n", uval->iValue);
575 switch (uval->iValue) {
576 case 0: /* No transfers have ocurred */
577 ups->lastxfer = XFER_NONE;
578 break;
579 case 2: /* High line voltage */
580 ups->lastxfer = XFER_OVERVOLT;
581 break;
582 case 3: /* Ripple */
583 ups->lastxfer = XFER_RIPPLE;
584 break;
585 case 1: /* Low line voltage */
586 case 4: /* notch, spike, or blackout */
587 case 8: /* Notch or blackout */
588 case 9: /* Spike or blackout */
589 ups->lastxfer = XFER_UNDERVOLT;
590 break;
591 case 6: /* DelayBeforeShutdown or APCDelayBeforeShutdown */
592 case 10: /* Graceful shutdown by accessories */
593 ups->lastxfer = XFER_FORCED;
594 break;
595 case 7: /* Input frequency out of range */
596 ups->lastxfer = XFER_FREQ;
597 break;
598 case 5: /* Self Test or Discharge Calibration commanded thru */
599 /* Test usage, front button, or 2 week self test */
600 case 11: /* Test usage invoked */
601 case 12: /* Front button initiated self test */
602 case 13: /* 2 week self test */
603 ups->lastxfer = XFER_SELFTEST;
604 break;
605 default:
606 ups->lastxfer = XFER_UNKNOWN;
607 break;
609 break;
611 /* Battery connected/disconnected */
612 case CI_BatteryPresent:
614 * Work around a firmware bug in some models (RS 1500,
615 * possibly others) where BatteryPresent=1 is sporadically
616 * reported while the battery is disconnected. The work-
617 * around is to ignore BatteryPresent=1 until we see it
618 * at least twice in a row. The down side of this approach
619 * is that legitimate BATTATTCH events are unnecessarily
620 * delayed. C'est la vie.
622 * ADK FIXME: 'bpcnt' should be kept in the UPS structure
623 * in order to allow multiple UPSes to be managed by this
624 * driver. To avoid bloating UPSINFO with USB-specific
625 * junk we really need a USB private structure akin to
626 * USB_INFO in the platform specific drivers. The URB
627 * delay timer in usb_get_value() could also live in such
628 * a structure.
630 if (uval->iValue) {
631 if (bpcnt++)
632 ups->set_battpresent();
633 } else {
634 bpcnt = 0;
635 ups->clear_battpresent();
637 Dmsg1(200, "BatteryPresent=%d\n", uval->iValue);
638 break;
640 /* UPS_NAME */
641 case CI_IDEN:
642 if (ups->upsname[0] == 0 && uval->sValue[0] != 0)
643 astrncpy(ups->upsname, uval->sValue, sizeof(ups->upsname));
644 break;
646 /* model, firmware */
647 case CI_UPSMODEL:
648 /* Truncate Firmware info on APC Product string */
649 if ((p = strstr(uval->sValue, "FW:"))) {
650 *p = '\0'; // Terminate model name
651 p += 3; // Skip "FW:"
652 while (isspace(*p)) // Skip whitespace after "FW:"
653 p++;
654 astrncpy(ups->firmrev, p, sizeof(ups->firmrev));
655 ups->UPS_Cap[CI_REVNO] = true;
658 /* Kill leading whitespace on model name */
659 p = uval->sValue;
660 while (isspace(*p))
661 p++;
663 astrncpy(ups->upsmodel, p, sizeof(ups->upsmodel));
664 break;
666 /* WAKEUP_DELAY */
667 case CI_DWAKE:
668 ups->dwake = (int)uval->dValue;
669 break;
671 /* SLEEP_DELAY */
672 case CI_DSHUTD:
673 ups->dshutd = (int)uval->dValue;
674 break;
676 /* LOW_TRANSFER_LEVEL */
677 case CI_LTRANS:
678 ups->lotrans = (int)uval->dValue;
679 break;
681 /* HIGH_TRANSFER_LEVEL */
682 case CI_HTRANS:
683 ups->hitrans = (int)uval->dValue;
684 break;
686 /* UPS_BATT_CAP_RETURN */
687 case CI_RETPCT:
688 ups->rtnpct = (int)uval->dValue;
689 break;
691 /* LOWBATT_SHUTDOWN_LEVEL */
692 case CI_DLBATT:
693 ups->dlowbatt = (int)uval->dValue;
694 break;
696 /* UPS_MANUFACTURE_DATE */
697 case CI_MANDAT:
698 asnprintf(ups->birth, sizeof(ups->birth), "%4d-%02d-%02d",
699 (uval->iValue >> 9) + 1980, (uval->iValue >> 5) & 0xF,
700 uval->iValue & 0x1F);
701 break;
703 /* Last UPS_BATTERY_REPLACE */
704 case CI_BATTDAT:
705 asnprintf(ups->battdat, sizeof(ups->battdat), "%4d-%02d-%02d",
706 (uval->iValue >> 9) + 1980, (uval->iValue >> 5) & 0xF,
707 uval->iValue & 0x1F);
708 break;
710 /* APC_BATTERY_DATE */
711 case CI_BattReplaceDate:
712 v = uval->iValue;
713 yy = ((v >> 4) & 0xF) * 10 + (v & 0xF) + 2000;
714 v >>= 8;
715 dd = ((v >> 4) & 0xF) * 10 + (v & 0xF);
716 v >>= 8;
717 mm = ((v >> 4) & 0xF) * 10 + (v & 0xF);
718 asnprintf(ups->battdat, sizeof(ups->battdat), "%4d-%02d-%02d", yy, mm, dd);
719 break;
721 /* UPS_SERIAL_NUMBER */
722 case CI_SERNO:
723 astrncpy(ups->serial, uval->sValue, sizeof(ups->serial));
726 * If serial number has garbage, trash it.
728 for (p = ups->serial; *p; p++) {
729 if (*p < ' ' || *p > 'z') {
730 *ups->serial = 0;
731 ups->UPS_Cap[CI_SERNO] = false;
734 break;
736 /* Nominal output voltage when on batteries */
737 case CI_NOMOUTV:
738 ups->NomOutputVoltage = (int)uval->dValue;
739 while (ups->NomOutputVoltage > 1000)
740 ups->NomOutputVoltage /= 10; // Some UPSes get the units wrong
741 break;
743 /* Nominal input voltage */
744 case CI_NOMINV:
745 ups->NomInputVoltage = (int)uval->dValue;
746 while (ups->NomInputVoltage > 1000)
747 ups->NomInputVoltage /= 10; // Some UPSes get the units wrong
748 break;
750 /* Nominal battery voltage */
751 case CI_NOMBATTV:
752 ups->nombattv = uval->dValue;
753 break;
755 /* Nominal power */
756 case CI_NOMPOWER:
757 ups->NomPower = (int)uval->dValue;
758 break;
760 /* Sensitivity */
761 case CI_SENS:
762 switch (uval->iValue) {
763 case 0:
764 astrncpy(ups->sensitivity, "Low", sizeof(ups->sensitivity));
765 break;
766 case 1:
767 astrncpy(ups->sensitivity, "Medium", sizeof(ups->sensitivity));
768 break;
769 case 2:
770 astrncpy(ups->sensitivity, "High", sizeof(ups->sensitivity));
771 break;
772 default:
773 astrncpy(ups->sensitivity, "Unknown", sizeof(ups->sensitivity));
774 break;
776 break;
778 case CI_DALARM:
779 switch (uval->iValue) {
780 case 1: // Never
781 astrncpy(ups->beepstate, "N", sizeof(ups->beepstate));
782 break;
783 case 2: // 30 seconds
784 default:
785 astrncpy(ups->beepstate, "T", sizeof(ups->beepstate));
786 break;
788 break;
790 default:
791 break;
795 /* Fetch the given CI from the UPS and update the UPSINFO structure */
796 static bool usb_update_value(UPSINFO* ups, int ci)
798 USB_VALUE uval;
800 if (!usb_get_value(ups, ci, &uval))
801 return false;
803 usb_process_value(ups, ci, &uval);
804 return true;
807 /* Process commands from the main loop */
808 int usb_ups_entry_point(UPSINFO *ups, int command, void *data)
810 struct timespec delay = {0, 40000000};
812 switch (command) {
813 case DEVICE_CMD_CHECK_SELFTEST:
814 Dmsg0(80, "Checking self test.\n");
816 * XXX FIXME
818 * One day we will do this test inside the driver and not as an
819 * entry point.
821 /* Reason for last transfer to batteries */
822 nanosleep(&delay, NULL); /* Give UPS a chance to update the value */
823 if (usb_update_value(ups, CI_WHY_BATT) ||
824 usb_update_value(ups, CI_APCLineFailCause))
826 Dmsg1(80, "Transfer reason: %d\n", ups->lastxfer);
828 /* See if this is a self test rather than power failure */
829 if (ups->lastxfer == XFER_SELFTEST) {
831 * set Self Test start time
833 ups->SelfTest = time(NULL);
834 Dmsg1(80, "Self Test time: %s", ctime(&ups->SelfTest));
837 break;
839 case DEVICE_CMD_GET_SELFTEST_MSG:
840 nanosleep(&delay, NULL); /* Give UPS a chance to update the value */
841 return usb_update_value(ups, CI_ST_STAT);
843 default:
844 return FAILURE;
847 return SUCCESS;
851 * Read UPS info that changes -- e.g. voltage, temperature, etc.
853 * This routine is called once every N seconds to get a current
854 * idea of what the UPS is doing.
856 int usb_ups_read_volatile_data(UPSINFO *ups)
858 time_t last_poll = ups->poll_time;
859 time_t now = time(NULL);
861 Dmsg0(200, "Enter usb_ups_read_volatile_data\n");
864 * If we are not on batteries, update this maximum once every
865 * MAX_VOLATILE_POLL_RATE seconds. This prevents flailing around
866 * too much if the UPS state is rapidly changing while on mains.
868 if (ups->is_onbatt() && last_poll &&
869 (now - last_poll < MAX_VOLATILE_POLL_RATE)) {
870 return 1;
873 write_lock(ups);
874 ups->poll_time = now; /* save time stamp */
876 /* Clear APC status bits; let the various CIs set them again */
877 ups->Status &= ~0xFF;
879 /* Loop through all known data, polling those marked volatile */
880 for (int i=0; known_info[i].usage_code; i++) {
881 if (known_info[i].isvolatile && known_info[i].ci != CI_NONE)
882 usb_update_value(ups, known_info[i].ci);
885 write_unlock(ups);
886 return 1;
890 * Read UPS info that remains unchanged -- e.g. transfer voltages,
891 * shutdown delay, etc.
893 * This routine is called once when apcupsd is starting.
895 int usb_ups_read_static_data(UPSINFO *ups)
897 write_lock(ups);
899 /* Loop through all known data, polling those marked non-volatile */
900 for (int i=0; known_info[i].usage_code; i++) {
901 if (!known_info[i].isvolatile && known_info[i].ci != CI_NONE)
902 usb_update_value(ups, known_info[i].ci);
905 write_unlock(ups);
906 return 1;
910 * How long to wait before killing output power.
911 * This value is NOT used on BackUPS Pro models.
913 #define SHUTDOWN_DELAY 60
916 * How many seconds of good utility power before turning output back on.
917 * This value is NOT used on BackUPS Pro models.
919 #define STARTUP_DELAY 10
922 * What percentage battery charge before turning output back on.
923 * On at least some models this must be a multiple of 15%.
924 * This value is NOT used on BackUPS Pro models.
926 #define STARTUP_PERCENT 0
928 int usb_ups_kill_power(UPSINFO *ups)
930 const char *func;
931 int hibernate = 0;
932 int val;
934 Dmsg0(200, "Enter usb_ups_kill_power\n");
937 * We try various different ways to put the UPS into hibernation
938 * mode (i.e. killpower). Some of these commands are not supported
939 * on all UPSes, but that should cause no harm.
943 * First, set required battery capacity before startup to 0 so UPS
944 * will not wait for the battery to charge before turning back on.
945 * Not all UPSes have this capability, so this setting is allowed
946 * to fail. The value we program here should be made configurable
947 * some day.
949 if (UPS_HAS_CAP(CI_RETPCT)) {
950 func = "CI_RETPCT";
951 if (!usb_write_int_to_ups(ups, CI_RETPCT, STARTUP_PERCENT, func))
952 Dmsg1(100, "Unable to set %s (not an error)\n", func);
956 * BackUPS Pro uses an enumerated setting (reads percent in
957 * ASCII). The value advances to the next higher setting by
958 * writing a '1' and to the next lower setting when writing a
959 * '2'. The value wraps around when advanced past the max or min
960 * setting.
962 * We walk the setting down to the minimum of 0.
964 * Credit goes to John Zielinski <grim@undead.cc> for figuring
965 * this out.
967 if (UPS_HAS_CAP(CI_BUPBattCapBeforeStartup)) {
968 if (pusb_read_int_from_ups(ups, CI_BUPBattCapBeforeStartup, &val)) {
969 func = "CI_BUPBattCapBeforeStartup";
970 switch (val) {
971 case 0x3930: /* 90% */
972 pusb_write_int_to_ups(ups, CI_BUPBattCapBeforeStartup, 2, func);
973 /* Falls thru... */
974 case 0x3630: /* 60% */
975 pusb_write_int_to_ups(ups, CI_BUPBattCapBeforeStartup, 2, func);
976 /* Falls thru... */
977 case 0x3135: /* 15% */
978 pusb_write_int_to_ups(ups, CI_BUPBattCapBeforeStartup, 2, func);
979 /* Falls thru... */
980 case 0x3030: /* 00% */
981 break;
983 default:
984 Dmsg1(100, "Unknown BUPBattCapBeforeStartup value (%04x)\n", val);
985 break;
991 * Second, set the length of time to wait after power returns
992 * before starting up. We set it to something pretty low, but it
993 * seems the UPS rounds this value up to the nearest multiple of
994 * 60 seconds. Not all UPSes have this capability, so this setting
995 * is allowed to fail. The value we program here should be made
996 * configurable some day.
998 if (UPS_HAS_CAP(CI_APCDelayBeforeStartup)) {
999 func = "CI_APCDelayBeforeStartup";
1000 if (!usb_write_int_to_ups(ups, CI_APCDelayBeforeStartup, STARTUP_DELAY, func)) {
1001 Dmsg1(100, "Unable to set %s (not an error)\n", func);
1006 * BackUPS Pro uses an enumerated setting (reads seconds in ASCII).
1007 * The value advances to the next higher setting by writing a '1'
1008 * and to the next lower setting when writing a '2'. The value
1009 * wraps around when advanced past the max or min setting.
1011 * We walk the setting down to the minimum of 60.
1013 * Credit goes to John Zielinski <grim@undead.cc> for figuring
1014 * this out.
1016 if (UPS_HAS_CAP(CI_BUPDelayBeforeStartup)) {
1017 if (pusb_read_int_from_ups(ups, CI_BUPDelayBeforeStartup, &val)) {
1018 func = "CI_BUPDelayBeforeStartup";
1019 switch (val) {
1020 case 0x363030: /* 600 sec */
1021 pusb_write_int_to_ups(ups, CI_BUPDelayBeforeStartup, 2, func);
1022 /* Falls thru... */
1023 case 0x333030: /* 300 sec */
1024 pusb_write_int_to_ups(ups, CI_BUPDelayBeforeStartup, 2, func);
1025 /* Falls thru... */
1026 case 0x313830: /* 180 sec */
1027 pusb_write_int_to_ups(ups, CI_BUPDelayBeforeStartup, 2, func);
1028 /* Falls thru... */
1029 case 0x3630: /* 60 sec */
1030 break;
1032 default:
1033 Dmsg1(100, "Unknown CI_BUPDelayBeforeStartup value (%04x)\n", val);
1034 break;
1040 * BackUPS hibernate
1042 * Alternately, if APCDelayBeforeShutdown is available, setting
1043 * it will start a countdown after which the UPS will hibernate.
1045 if (!hibernate && UPS_HAS_CAP(CI_APCDelayBeforeShutdown)) {
1046 Dmsg0(000, "UPS appears to support BackUPS style hibernate.\n");
1047 func = "CI_APCDelayBeforeShutdown";
1048 if (!usb_write_int_to_ups(ups, CI_APCDelayBeforeShutdown,
1049 SHUTDOWN_DELAY, func)) {
1050 Dmsg1(000, "Kill power function \"%s\" failed.\n", func);
1051 } else {
1052 hibernate = 1;
1057 * SmartUPS hibernate
1059 * If both DWAKE and DelayBeforeShutdown are available, trigger
1060 * a hibernate by writing DWAKE a few seconds longer than
1061 * DelayBeforeShutdown. ORDER IS IMPORTANT. The write to
1062 * DelayBeforeShutdown starts both timers ticking down and the
1063 * UPS will hibernate when DelayBeforeShutdown hits zero.
1065 if (!hibernate && UPS_HAS_CAP(CI_DWAKE) && UPS_HAS_CAP(CI_DelayBeforeShutdown)) {
1066 Dmsg0(000, "UPS appears to support SmartUPS style hibernate.\n");
1067 func = "CI_DWAKE";
1068 if (!usb_write_int_to_ups(ups, CI_DWAKE, SHUTDOWN_DELAY + 4, func)) {
1069 Dmsg1(000, "Kill power function \"%s\" failed.\n", func);
1070 } else {
1071 func = "CI_DelayBeforeShutdown";
1072 if (!usb_write_int_to_ups(ups, CI_DelayBeforeShutdown,
1073 SHUTDOWN_DELAY, func)) {
1074 Dmsg1(000, "Kill power function \"%s\" failed.\n", func);
1075 /* reset prev timer */
1076 usb_write_int_to_ups(ups, CI_DWAKE, -1, "CI_DWAKE");
1077 } else {
1078 hibernate = 1;
1084 * BackUPS Pro shutdown
1086 * Here we see the BackUPS Pro further distinguish itself as
1087 * having the most broken firmware of any APC product yet. We have
1088 * to trigger two magic boolean flags using APC custom usages.
1089 * First we hit BUPHibernate and follow that with a write to
1090 * BUPSelfTest (!).
1092 * Credit goes to John Zielinski <grim@undead.cc> for figuring
1093 * this out.
1095 if (!hibernate && UPS_HAS_CAP(CI_BUPHibernate) && UPS_HAS_CAP(CI_BUPSelfTest)) {
1096 Dmsg0(000, "UPS appears to support BackUPS Pro style hibernate.\n");
1097 func = "CI_BUPHibernate";
1098 if (!pusb_write_int_to_ups(ups, CI_BUPHibernate, 1, func)) {
1099 Dmsg1(000, "Kill power function \"%s\" failed.\n", func);
1100 } else {
1101 func = "CI_BUPSelfTest";
1102 if (!pusb_write_int_to_ups(ups, CI_BUPSelfTest, 1, func)) {
1103 Dmsg1(000, "Kill power function \"%s\" failed.\n", func);
1104 pusb_write_int_to_ups(ups, CI_BUPHibernate, 0, "CI_BUPHibernate");
1105 } else {
1106 hibernate = 1;
1112 * All UPSes tested so far are covered by one of the above cases.
1113 * However, there are a some other ways to hibernate.
1117 * Misc method A
1119 * Writing CI_DelayBeforeReboot starts a countdown timer, after
1120 * which the UPS will hibernate. If utility power is out, the UPS
1121 * will stay hibernating until power is restored. SmartUPSes seem
1122 * to support this method, but PowerChute uses the dual countdown
1123 * method above, so we prefer that one. UPSes seem to round the
1124 * value up to 90 seconds if it is any lower. Note that the
1125 * behavior described here DOES NOT comply with the standard set
1126 * out in the HID Usage Tables for Power Devices spec.
1128 if (!hibernate && UPS_HAS_CAP(CI_DelayBeforeReboot)) {
1129 Dmsg0(000, "UPS appears to support DelayBeforeReboot style hibernate.\n");
1131 func = "CI_DelayBeforeReboot";
1132 if (!usb_write_int_to_ups(ups, CI_DelayBeforeReboot, SHUTDOWN_DELAY, func))
1133 Dmsg1(000, "Kill power function \"%s\" failed.\n", func);
1134 else
1135 hibernate = 1;
1139 * Misc method B
1141 * We can set CI_APCForceShutdown to true (it's a boolean flag).
1142 * We have no control over how long the UPS waits before turning
1143 * off. Experimentally it seems to be about 60 seconds. Some
1144 * BackUPS models support this in addition to the preferred
1145 * BackUPS method above. It's included here "just in case".
1147 if (!hibernate && UPS_HAS_CAP(CI_APCForceShutdown)) {
1148 Dmsg0(000, "UPS appears to support ForceShutdown style hibernate.\n");
1150 func = "CI_APCForceShutdown";
1151 if (!usb_write_int_to_ups(ups, CI_APCForceShutdown, 1, func))
1152 Dmsg1(000, "Kill power function \"%s\" failed.\n", func);
1153 else
1154 hibernate = 1;
1157 if (!hibernate) {
1158 Dmsg0(000, "Couldn't put UPS into hibernation mode. Attempting shutdown.\n");
1159 hibernate = usb_ups_shutdown(ups);
1162 Dmsg0(200, "Leave usb_ups_kill_power\n");
1163 return hibernate;
1166 int usb_ups_shutdown(UPSINFO *ups)
1168 const char *func;
1169 int shutdown = 0;
1171 Dmsg0(200, "Enter usb_ups_shutdown\n");
1174 * Complete shutdown
1176 * This method turns off the UPS off completely after a given delay.
1177 * The only way to power the UPS back on is to manually hit the
1178 * power button.
1180 if (!shutdown && UPS_HAS_CAP(CI_DelayBeforeShutdown)) {
1181 Dmsg0(000, "UPS appears to support DelayBeforeShutdown style shutdown.\n");
1183 func = "CI_DelayBeforeShutdown";
1184 if (!usb_write_int_to_ups(ups, CI_DelayBeforeShutdown, SHUTDOWN_DELAY, func))
1185 Dmsg1(000, "Kill power function \"%s\" failed.\n", func);
1186 else
1187 shutdown = 1;
1191 * I give up.
1193 if (!shutdown) {
1194 Dmsg0(000, "I don't know how to turn off this UPS...sorry.\n"
1195 "Please report this, along with the output from\n"
1196 "running examples/hid-ups, to the apcupsd-users\n"
1197 "mailing list (apcupsd-users@lists.sourceforge.net).\n");
1201 * Note that there are a couple other CIs that look interesting
1202 * for shutdown, but they're not what we want.
1204 * APCShutdownAfterDelay: Tells the UPS how many seconds to wait
1205 * after power goes out before asserting ShutdownRequested
1206 * (see next item).
1208 * CI_ShutdownRequested: This is an indicator from the UPS to the
1209 * server that it would like the server to begin shutting
1210 * down. In conjunction with APCShutdownAfterDelay this can be
1211 * used to offload the decision of when to shut down the
1212 * server to the UPS.
1215 Dmsg0(200, "Leave usb_ups_shutdown\n");
1216 return shutdown;
1220 * Helper functions for use by platform specific code
1223 double pow_ten(int exponent)
1225 int i;
1226 double val = 1;
1228 if (exponent < 0) {
1229 exponent = -exponent;
1230 for (i = 0; i < exponent; i++)
1231 val = val / 10;
1232 return val;
1233 } else {
1234 for (i = 0; i < exponent; i++)
1235 val = val * 10;
1238 return val;
1241 /* Called by platform-specific code to report an interrupt event */
1242 int usb_report_event(UPSINFO *ups, int ci, USB_VALUE *uval)
1244 Dmsg2(200, "USB driver reported event ci=%d, val=%f\n",
1245 ci, uval->dValue);
1247 /* Got an event: go process it */
1248 usb_process_value(ups, ci, uval);
1250 switch (ci) {
1252 * Some important usages cause us to abort interrupt waiting
1253 * so immediate action can be taken.
1255 case CI_Discharging:
1256 case CI_ACPresent:
1257 case CI_BelowRemCapLimit:
1258 case CI_BATTLEV:
1259 case CI_RUNTIM:
1260 case CI_NeedReplacement:
1261 case CI_ShutdownImminent:
1262 case CI_BatteryPresent:
1263 return true;
1266 * We don't handle these directly, but rather use them as a
1267 * signal to go poll the full set of volatile data.
1269 case CI_IFailure:
1270 case CI_Overload:
1271 case CI_PWVoltageOOR:
1272 case CI_PWFrequencyOOR:
1273 case CI_OverCharged:
1274 case CI_OverTemp:
1275 case CI_CommunicationLost:
1276 case CI_ChargerVoltageOOR:
1277 case CI_ChargerCurrentOOR:
1278 case CI_CurrentNotRegulated:
1279 case CI_VoltageNotRegulated:
1280 return true;
1283 * Anything else is relatively unimportant, so we can
1284 * keep gathering data until the timeout.
1286 default:
1287 return false;