1
/* belkinunv.c - driver for newer Belkin models, such as "Belkin
2
Universal UPS" (ca. 2003)
4
Copyright (C) 2003 Peter Selinger <selinger@users.sourceforge.net>
6
This program is free software; you can redistribute it and/or modify
7
it under the terms of the GNU General Public License as published by
8
the Free Software Foundation; either version 2 of the License, or
9
(at your option) any later version.
11
This program is distributed in the hope that it will be useful,
12
but WITHOUT ANY WARRANTY; without even the implied warranty of
13
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14
GNU General Public License for more details.
16
You should have received a copy of the GNU General Public License
17
along with this program; if not, write to the Free Software
18
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21
/* SOFT SHUTDOWN WORKAROUND
23
One problem with the Belkin Universal UPS is that it cannot enter a
24
soft shutdown (shut down until AC power returns) unless the
25
batteries are completely depleted. Thus, one cannot just shut off
26
the UPS after operating system shutdown; it will not come back on
27
when the power comes back on. The belkinunv driver should never be
28
used with the -k option. Instead, we provide a "standalone" mode
29
for this driver via some -x options, which is intended to be used
30
in startup and shutdown scripts. Please see the belkinunv(8) man
38
battery.voltage.nominal
39
driver.version.internal
41
input.frequency.nominal e.g. 60 for 60Hz
42
input.sensitivity (RW) normal/medium/low
43
input.transfer.high (RW)
44
input.transfer.low (RW)
51
ups.beeper.enable (RW) yes/no
55
ups.power.nominal e.g. 800 for an 800VA system
59
ups.timer.restart read-only: time to restart
60
ups.timer.shutdown read-only: time to shutdown
61
ups.type ONLINE/OFFLINE/LINEINT
68
shutdown.reboot shut down load immediately for 1-2 minutes
69
shutdown.reboot.graceful shut down load after 40 seconds for 1-2 minutes
70
shutdown.stayoff shut down load immediately and stay off
71
test.battery.start start 10-second battery test
73
test.failure.start start "deep" battery test
78
OB load is on battery, including during tests
87
DEPLETED battery depleted
95
#include <sys/ioctl.h>
96
#include <sys/termios.h>
99
#define DRV_VERSION "0.06"
101
/* somewhat arbitrary buffer size - the longest actually occuring
102
message is 18 bytes for the F6C800-UNV. But since message length is
103
arbitrary in principle, we allow for some extra bytes. */
104
#define MAXMSGSIZE 25
106
/* definitions of register numbers for Belkin UPS */
107
#define REG_VOLTRATING 0x01
108
#define REG_FREQRATING 0x02
109
#define REG_POWERRATING 0x03
110
#define REG_BATVOLTRATING 0x04
111
#define REG_XFER_LO 0x06
112
#define REG_XFER_LO_MAX 0x07
113
#define REG_XFER_LO_MIN 0x08
114
#define REG_XFER_HI 0x09
115
#define REG_XFER_HI_MAX 0x0a
116
#define REG_XFER_HI_MIN 0x0b
117
#define REG_VOLTSENS 0x0c
118
#define REG_UPSMODEL 0x0d
119
#define REG_UPSMODEL2 0x0e
120
#define REG_FIRMWARE 0x0f
121
#define REG_TESTSTATUS 0x10
122
#define REG_ALARMSTATUS 0x11
123
#define REG_SHUTDOWNTIMER 0x15
124
#define REG_RESTARTTIMER 0x16
125
#define REG_INPUTVOLT 0x18
126
#define REG_INPUTFREQ 0x19
127
#define REG_TEMPERATURE 0x1a
128
#define REG_OUTPUTVOLT 0x1b
129
#define REG_OUTPUTFREQ 0x1c
130
#define REG_LOAD 0x1e
131
#define REG_BATSTAT2 0x1f
132
#define REG_BATVOLT 0x20
133
#define REG_BATLEVEL 0x21
134
#define REG_UPSSTATUS 0x22
135
#define REG_BATSTATUS 0x23
136
#define REG_TIMELEFT 0x3f
138
/* flags for REG_UPSSTATUS */
139
#define US_ACFAILURE 0x0001
140
#define US_OVERLOAD 0x0010
141
#define US_OFF 0x0020
142
#define US_OVERHEAT 0x0040
143
#define US_UPSFAULT 0x0080
144
#define US_WAITING 0x2000
145
#define US_BUZZER 0x8000
147
/* flags for REG_BATSTATUS */
149
#define BS_CHARGING 0x10
150
#define BS_ONBATTERY 0x20
151
#define BS_DEPLETED 0x40
152
#define BS_REPLACE 0x80
154
/* size of an array */
155
#define asize(x) ((int)(sizeof(x)/sizeof(x[0])))
157
const char *upstype[3] = {
163
const char *voltsens[3] = {
169
const char *teststatus[6] = {
182
static const char *status[] = {
183
"UPS is off", /* ST_OFF */
184
"UPS is on AC power", /* ST_ONLINE */
185
"UPS is on battery" /* ST_BATTERY */
188
/* some useful strings */
190
#define COL0 ESC "[G" ESC "[K" /* terminal control: clear line */
192
static int minutil = -1;
193
static int maxutil = -1;
195
static int xfer_lo_min = -1;
196
static int xfer_lo_max = -1;
197
static int xfer_hi_min = -1;
198
static int xfer_hi_max = -1;
200
int instcmd(const char *cmdname, const char *extra);
201
static int setvar(const char *varname, const char *val);
203
/* ---------------------------------------------------------------------- */
204
/* a general purpose Belkin-specific function: */
206
/* calculate a Belkin checksum, i.e., add buf[0]...buf[n-1] */
207
static unsigned char belkin_checksum(unsigned char *buf, int n) {
211
for (i=0; i<n; i++) {
217
/* ---------------------------------------------------------------------- */
218
/* some private functions for talking to the UPS - "driver mode"
219
versions. The functions in this section have _nut_ in their name,
220
and they use standard NUT components (including NUT error handling)
221
for file i/o. Note that stand-alone versions of these functions are
222
provided in the next section. */
224
/* open serial port and switch to "smart" mode */
225
static void belkin_nut_open_tty(void)
227
int dtr_bit = TIOCM_DTR;
228
int rts_bit = TIOCM_RTS;
230
upsfd = ser_open(device_path);
231
ser_set_speed(upsfd, device_path, B2400);
233
/* must clear DTR and set RTS for 1 second for UPS to go to
235
ioctl(upsfd, TIOCMBIC, &dtr_bit);
236
ioctl(upsfd, TIOCMBIS, &rts_bit);
239
tcflush(upsfd, TCIOFLUSH);
242
/* receive Belkin message from UPS, check for well-formedness (leading
243
byte, checksum). Return length of message, or -1 if not
245
static int belkin_nut_receive(unsigned char *buf, int bufsize) {
254
r = ser_get_buf_len(upsfd, &buf[0], 1, 3, 0);
256
upslogx(LOG_ERR, "No response from UPS");
258
} else if (buf[0]!=0x7e) {
259
upslogx(LOG_ERR, "Garbage read from UPS");
264
/* read instruction, size, and register */
268
r = ser_get_buf_len(upsfd, &buf[1], 3, 3, 0);
270
upslogx(LOG_ERR, "Short read from UPS");
277
/* read data and checksum */
278
if (n+len > bufsize) {
281
r = ser_get_buf_len(upsfd, &buf[4], len, 3, 0);
283
upslogx(LOG_ERR, "Short read from UPS");
289
if (belkin_checksum(buf, len+3) != buf[len+3]) {
290
upslogx(LOG_ERR, "Bad checksum from UPS");
296
/* read the value of a string register from UPS. Return NULL on
297
failure, else an allocated string. */
298
static char *belkin_nut_read_str(int reg) {
299
unsigned char buf[MAXMSGSIZE];
303
/* send the request */
309
buf[5] = belkin_checksum(buf, 5);
311
r = ser_send_buf(upsfd, buf, 6);
313
upslogx(LOG_ERR, "Failed write to UPS");
317
/* receive the answer */
318
r = belkin_nut_receive(buf, MAXMSGSIZE);
322
if ((buf[1]!=0x05 && buf[1]!=0x01) || buf[3] != reg) {
323
upslogx(LOG_ERR, "Invalid response from UPS");
330
/* convert the answer to a string */
332
str = (char *)xmalloc(len+1);
333
memcpy(str, &buf[4], len);
338
/* read the value of an integer register from UPS. Return -1 on
340
static int belkin_nut_read_int(int reg) {
341
unsigned char buf[MAXMSGSIZE];
344
/* send the request */
350
buf[5] = belkin_checksum(buf, 5);
352
r = ser_send_buf(upsfd, buf, 6);
354
upslogx(LOG_ERR, "Failed write to UPS");
358
/* receive the answer */
359
r = belkin_nut_receive(buf, MAXMSGSIZE);
363
if ((buf[1]!=0x05 && buf[1]!=0x01) || buf[3] != reg) {
364
upslogx(LOG_ERR, "Invalid response from UPS");
371
/* convert the answer to an integer */
376
return buf[4] + 256*buf[5];
378
upslogx(LOG_ERR, "Invalid response from UPS");
383
/* write the value of an integer register to UPS. Return -1 on
385
static int belkin_nut_write_int(int reg, int val) {
386
unsigned char buf[MAXMSGSIZE];
389
/* send the request */
395
buf[5] = (val>>8) & 0xff;
396
buf[6] = belkin_checksum(buf, 6);
398
r = ser_send_buf(upsfd, buf, 7);
400
upslogx(LOG_ERR, "Failed write to UPS");
404
/* receive the acknowledgement */
405
r = belkin_nut_receive(buf, MAXMSGSIZE);
409
if ((buf[1]!=0x02 && buf[1]!=0x01) || buf[3] != reg) {
410
upslogx(LOG_ERR, "Invalid response from UPS");
419
/* ---------------------------------------------------------------------- */
420
/* some private functions for talking to the UPS - "standalone"
421
versions. The functions in this section have _std_ in their name,
422
and they do not use default NUT error handling (this would not be
423
desirable during standalone operation, i.e., when the -x wait
424
option is given). These functions also take an additional file
425
descriptor argument. */
427
/* Open and prepare a serial port for communication with a Belkin
428
Universal UPS. DEVICE is the name of the serial port. It will be
429
opened in non-blocking read/write mode, and the appropriate
430
communications parameters will be set. The device will also be
431
sent a special signal (clear DTR, set RTS) to cause the UPS to
432
switch from "dumb" to "smart" mode, and any pending data (=garbage)
433
will be discarded. After this call, the device is ready for reading
434
and writing via read(2) and write(2). Return a valid file
435
descriptor on success, or else -1 with errno set. */
436
static int belkin_std_open_tty(const char *device) {
441
const int tiocm_dtr = TIOCM_DTR;
442
const int tiocm_rts = TIOCM_RTS;
445
/* open the device */
446
fd = open(device, O_RDWR | O_NONBLOCK);
451
/* set communications parameters: 2400 baud, 8 bits, 1 stop bit, no
452
parity, enable reading, hang up when done, ignore modem control
454
memset(&tios, 0, sizeof(tios));
455
tios.c_cflag = B2400 | CS8 | CREAD | HUPCL | CLOCAL;
457
tios.c_cc[VTIME] = 0;
458
r = tcsetattr(fd, TCSANOW, &tios);
464
/* signal the UPS to enter "smart" mode. This is done by setting RTS
465
and dropping DTR for at least 0.25 seconds. RTS and DTR refer to
466
two specific pins in the 9-pin serial connector. Note: this must
467
be done for at least 0.25 seconds for the UPS to react. Ignore
468
any errors, as this probably means we are not on a "real" serial
470
ioctl(fd, TIOCMBIC, &tiocm_dtr);
471
ioctl(fd, TIOCMBIS, &tiocm_rts);
473
/* flush both directions of serial port: throw away all data in
475
r = tcflush(fd, TCIOFLUSH);
482
memset(&flock, 0, sizeof(flock));
483
flock.l_type = F_RDLCK;
484
r = fcntl(fd, F_SETLK, &flock);
490
/* sleep at least 0.25 seconds for the UPS to wake up. Belkin's own
491
software sleeps 1 second, so that's what we do, too. */
494
/* flush incoming data again, and read any remaining garbage
495
bytes. There should not be any. */
496
r = tcflush(fd, TCIFLUSH);
502
r = read(fd, buf, 127);
503
if (r == -1 && errno != EAGAIN) {
508
/* leave port in non-blocking state */
513
/* blocking read with 1-second timeout (use non-blocking i/o) */
514
static int belkin_std_upsread(int fd, char *buf, int n) {
520
r = read(fd, &buf[count], n-count);
521
if (r==-1 && errno==EAGAIN) {
522
/* non-blocking i/o, no data available */
525
} else if (r == -1) {
537
/* blocking write with 1-second timeout (use non-blocking i/o) */
538
static int belkin_std_upswrite(int fd, char *buf, int n) {
544
r = write(fd, &buf[count], n-count);
545
if (r==-1 && errno==EAGAIN) {
546
/* non-blocking i/o, no data available */
549
} else if (r == -1) {
561
/* receive Belkin message from UPS, check for well-formedness (leading
562
byte, checksum). Return length of message, or -1 if not
564
static int belkin_std_receive(int fd, unsigned char *buf, int bufsize) {
573
r = belkin_std_upsread(fd, &buf[0], 1);
574
if (r==-1 || buf[0]!=0x7e) {
579
/* read instruction, size, and register */
583
r = belkin_std_upsread(fd, &buf[1], 3);
591
/* read data and checksum */
592
if (n+len > bufsize) {
595
r = belkin_std_upsread(fd, &buf[4], len);
602
if (belkin_checksum(buf, len+3) != buf[len+3]) {
608
/* read the value of an integer register from UPS. Return -1 on
610
static int belkin_std_read_int(int fd, int reg) {
611
unsigned char buf[MAXMSGSIZE];
614
/* send the request */
620
buf[5] = belkin_checksum(buf, 5);
622
r = belkin_std_upswrite(fd, buf, 6);
627
/* receive the answer */
628
r = belkin_std_receive(fd, buf, MAXMSGSIZE);
632
if ((buf[1]!=0x05 && buf[1]!=0x01) || buf[3] != reg) {
639
/* convert the answer to an integer */
644
return buf[4] + 256*buf[5];
650
/* write the value of an integer register to UPS. Return -1 on
652
static int belkin_std_write_int(int fd, int reg, int val) {
653
unsigned char buf[MAXMSGSIZE];
656
/* send the request */
662
buf[5] = (val>>8) & 0xff;
663
buf[6] = belkin_checksum(buf, 6);
665
r = belkin_std_upswrite(fd, buf, 7);
670
/* receive the acknowledgement */
671
r = belkin_std_receive(fd, buf, MAXMSGSIZE);
675
if ((buf[1]!=0x02 && buf[1]!=0x01) || buf[3] != reg) {
684
/* ---------------------------------------------------------------------- */
685
/* "standalone" program executed when driver is called with the '-x
686
wait' or '-x wait=<level>' flag or option */
688
/* this function updates the status line, as specified by the smode
689
parameter (0=silent, 1=normal, 2=dumbterminal). This is only done
690
if the status has not changed from the previous call */
691
static void updatestatus(int smode, const char *fmt, ...) {
692
char buf[1024]; /* static string limit is OK */
693
static char oldbuf[1024] = { 0 };
706
/* read formatted argument string */
708
vsnprintf(buf, sizeof(buf), fmt, ap);
709
buf[sizeof(buf)-1] = 0;
712
if (strcmp(oldbuf, buf)==0) {
718
/* "dumbterm" version just prints a new line each time */
721
/* "normal" version overwrites same line each time */
722
printf(COL0 "%s", buf);
727
/* switch from status line display to normal output mode */
728
static void endstatus(int smode) {
730
fprintf(stdout, "\n");
735
static int belkin_wait(void)
737
int level = 0; /* battery level to wait for */
738
int smode = 1; /* statusline mode: 0=silent, 1=normal, 2=dumbterm */
739
int nohang = 0; /* nohang flag */
740
int flash = 0; /* flash flag */
743
int failcount = 0; /* count consecutive failed connection attempts */
749
/* read command line '-x' options */
750
val = getval("wait");
755
if (dstate_getinfo("driver.flag.nohang")) {
759
if (dstate_getinfo("driver.flag.flash")) {
763
if (dstate_getinfo("driver.flag.silent")) {
765
} else if (dstate_getinfo("driver.flag.dumbterm")) {
769
updatestatus(smode, "Connecting to UPS...");
774
if (failcount >= 3 && nohang) {
776
printf("UPS is not responding: %s\n", strerror(failerrno));
778
} else if (failcount >= 3) {
779
updatestatus(smode, "UPS is not responding, will keep trying: %s", strerror(failerrno));
782
fd = belkin_std_open_tty(device_path);
791
/* wait until the UPS is online and the battery level
793
bs = belkin_std_read_int(fd, REG_BATSTATUS); /* battery status */
802
ov = belkin_std_read_int(fd, REG_OUTPUTVOLT); /* output voltage */
811
bl = belkin_std_read_int(fd, REG_BATLEVEL); /* battery level */
820
/* successfully got data from UPS */
823
if (bs & BS_ONBATTERY) {
830
updatestatus(smode, "%s, battery level: %d%%", status[st], bl);
831
if (st == ST_ONLINE && bl >= level) {
837
/* termination condition reached */
840
printf("Interrupting UPS load for ca. 2 minutes.\n");
841
r = belkin_std_write_int(fd, REG_RESTARTTIMER, 2);
843
r = belkin_std_write_int(fd, REG_SHUTDOWNTIMER, 1);
846
printf("Timed shutdown operation failed.\n");
855
/* ---------------------------------------------------------------------- */
856
/* functions which interface with main.c */
858
/* read all hardcoded info about this UPS */
859
void upsdrv_initinfo(void)
865
dstate_setinfo("driver.version.internal", "%s", DRV_VERSION);
867
/* read hard-wired values */
868
val = belkin_nut_read_int(REG_VOLTRATING);
870
dstate_setinfo("input.voltage.nominal", "%d", val);
873
val = belkin_nut_read_int(REG_FREQRATING);
875
dstate_setinfo("input.frequency.nominal", "%d", val);
878
val = belkin_nut_read_int(REG_POWERRATING);
880
dstate_setinfo("ups.power.nominal", "%d", val);
883
val = belkin_nut_read_int(REG_BATVOLTRATING);
885
dstate_setinfo("battery.voltage.nominal", "%d", val);
888
xfer_lo_max = belkin_nut_read_int(REG_XFER_LO_MAX);
889
xfer_lo_min = belkin_nut_read_int(REG_XFER_LO_MIN);
890
xfer_hi_max = belkin_nut_read_int(REG_XFER_HI_MAX);
891
xfer_hi_min = belkin_nut_read_int(REG_XFER_HI_MIN);
893
str = belkin_nut_read_str(REG_UPSMODEL);
895
dstate_setinfo("ups.model", "%s", str);
899
val = belkin_nut_read_int(REG_FIRMWARE);
901
dstate_setinfo("ups.firmware", "%d", (val>>4) & 0xf);
902
dstate_setinfo("ups.type", "%s", upstype[(val & 0x0f) % 3]);
905
/* read writable values and declare them writable */
906
val = belkin_nut_read_int(REG_VOLTSENS);
908
dstate_setinfo("input.sensitivity", "%s", (val>=0 && val<asize(voltsens)) ? voltsens[val] : "?");
909
/* declare variable writable */
910
/* note: enumerated variables apparently don't need the ST_FLAG_STRING flag */
911
dstate_setflags("input.sensitivity", ST_FLAG_RW);
912
for (i=0; i<asize(voltsens); i++) {
913
dstate_addenum("input.sensitivity", "%s", voltsens[i]);
917
val = belkin_nut_read_int(REG_ALARMSTATUS);
919
dstate_setinfo("ups.beeper.enable", "%s", val&1 ? "no" : "yes");
921
/* declare variable writable */
922
dstate_setflags("ups.beeper.enable", ST_FLAG_RW);
923
dstate_addenum("ups.beeper.enable", "yes");
924
dstate_addenum("ups.beeper.enable", "no");
927
val = belkin_nut_read_int(REG_XFER_LO);
929
dstate_setinfo("input.transfer.low", "%d", val);
931
/* declare variable writable */
932
dstate_setflags("input.transfer.low", ST_FLAG_RW);
934
if (xfer_lo_min != -1 && xfer_lo_max != -1) {
935
/* make it enumerated */
936
for (i=xfer_lo_min; i<=xfer_lo_max; i++) {
937
dstate_addenum("input.transfer.low", "%d", i);
942
val = belkin_nut_read_int(REG_XFER_HI);
944
dstate_setinfo("input.transfer.high", "%d", val);
946
/* declare variable writable */
947
dstate_setflags("input.transfer.high", ST_FLAG_RW);
949
if (xfer_hi_min != -1 && xfer_hi_max != -1) {
950
/* make it enumerated */
951
for (i=xfer_hi_min; i<=xfer_hi_max; i++) {
952
dstate_addenum("input.transfer.high", "%d", i);
957
/* declare handlers for instand commands and writable variables */
958
upsh.instcmd = instcmd;
959
upsh.setvar = setvar;
961
/* declare instant commands */
962
dstate_addcmd("test.failure.start");
963
dstate_addcmd("test.failure.stop");
964
dstate_addcmd("test.battery.start");
965
dstate_addcmd("test.battery.stop");
966
dstate_addcmd("beeper.on");
967
dstate_addcmd("beeper.off");
968
dstate_addcmd("shutdown.stayoff");
969
dstate_addcmd("shutdown.reboot");
970
dstate_addcmd("shutdown.reboot.graceful");
971
dstate_addcmd("reset.input.minmax");
974
/* update whatever info we can */
975
void upsdrv_updateinfo(void)
979
/* first read "vital" flags */
980
us = belkin_nut_read_int(REG_UPSSTATUS); /* UPS status */
981
bs = belkin_nut_read_int(REG_BATSTATUS); /* battery status */
982
ov = belkin_nut_read_int(REG_OUTPUTVOLT); /* output voltage */
984
if (us==-1 || bs==-1 || ov==-1) {
985
upslogx(LOG_ERR, "Cannot read from UPS");
990
dstate_setinfo("output.voltage", "%.1f", 0.1*ov);
994
if (bs & BS_ONBATTERY) {
995
status_set("OB"); /* on battery, including tests */
997
status_set("OL"); /* online */
999
status_set("OFF"); /* off */
1001
if (us & US_ACFAILURE) {
1002
status_set("ACFAIL"); /* AC failure, self-invented */
1003
/* Note: this is not the same as "on battery", because this
1004
flag makes sense even during a test, or when the load is
1005
off. It simply reflects the status of utility power. A
1006
"critical" situation should be OB && BL && ACFAIL. */
1008
if (us & US_OVERLOAD) {
1009
status_set("OVER"); /* overload */
1011
if (us & US_OVERHEAT) {
1012
status_set("OVERHEAT"); /* overheat, self-invented */
1014
if (us & US_UPSFAULT) {
1015
status_set("COMMFAULT"); /* UPS Fault */
1018
status_set("LB"); /* low battery */
1020
if (bs & BS_CHARGING) {
1021
status_set("CHRG"); /* charging */
1023
if (bs & BS_DEPLETED) {
1024
status_set("DEPLETED"); /* battery depleted, self-invented */
1026
if (bs & BS_REPLACE) {
1027
status_set("RB"); /* replace battery */
1032
/* new read everything else */
1034
val = belkin_nut_read_int(REG_XFER_LO);
1036
dstate_setinfo("input.transfer.low", "%d", val);
1039
val = belkin_nut_read_int(REG_XFER_HI);
1041
dstate_setinfo("input.transfer.high", "%d", val);
1044
val = belkin_nut_read_int(REG_VOLTSENS);
1046
dstate_setinfo("input.sensitivity", "%s", (val>=0 && val<asize(voltsens)) ? voltsens[val] : "?");
1049
val = belkin_nut_read_int(REG_TESTSTATUS);
1051
dstate_setinfo("ups.test.result", "%s", (val>=0 && val<asize(teststatus)) ? teststatus[val] : "?");
1054
val = belkin_nut_read_int(REG_ALARMSTATUS);
1056
dstate_setinfo("ups.beeper.enable", "%s", val&1 ? "no" : "yes");
1059
val = belkin_nut_read_int(REG_SHUTDOWNTIMER);
1061
dstate_setinfo("ups.timer.shutdown", "%d", val);
1064
val = belkin_nut_read_int(REG_RESTARTTIMER);
1066
dstate_setinfo("ups.timer.restart", "%d", 60*val);
1069
val = belkin_nut_read_int(REG_INPUTVOLT);
1071
dstate_setinfo("input.voltage", "%.1f", 0.1*val);
1073
/* UPS does not keep track of min/maxutil, but we can */
1074
if (val>0 && (maxutil==-1 || val>maxutil)) {
1077
if (val>0 && (minutil==-1 || val<minutil)) {
1080
dstate_setinfo("input.voltage.maximum", "%.1f", 0.1*maxutil);
1081
dstate_setinfo("input.voltage.minimum", "%.1f", 0.1*minutil);
1084
val = belkin_nut_read_int(REG_INPUTFREQ);
1086
dstate_setinfo("input.frequency", "%.1f", 0.1*val);
1089
val = belkin_nut_read_int(REG_TEMPERATURE);
1091
dstate_setinfo("ups.temperature", "%d", val);
1094
val = belkin_nut_read_int(REG_OUTPUTFREQ);
1096
dstate_setinfo("output.frequency", "%.1f", 0.1*val);
1099
val = belkin_nut_read_int(REG_LOAD);
1101
dstate_setinfo("ups.load", "%d", val);
1104
val = belkin_nut_read_int(REG_BATVOLT);
1106
dstate_setinfo("battery.voltage", "%.1f", 0.1*val);
1109
val = belkin_nut_read_int(REG_BATLEVEL);
1111
dstate_setinfo("battery.charge", "%d", val);
1114
val = belkin_nut_read_int(REG_TIMELEFT);
1116
dstate_setinfo("battery.runtime", "%d", 60*val);
1122
/* tell the UPS to shut down, then return - DO NOT SLEEP HERE */
1123
void upsdrv_shutdown(void)
1125
/* Note: this UPS cannot (apparently) be put into "soft
1126
shutdown" mode; thus the -k option should not normally be
1127
used; instead, a workaround using the "-x wait" option
1128
should be used; see belkinunv(8) for details.
1130
In case somebody uses the -k option, the best we can do
1131
here is a timed shutdown; this will wake up the attached
1132
load after 10 minutes, come rain come shine. If AC power
1133
does not return, this will probably lead to a few
1134
shutdown/reboot cycles, until the batteries finally die and
1135
possibly cause a system crash.
1137
Don't use this! Use the solution involving the "-x wait"
1138
option instead, as suggested on the belkinunv(8) man
1141
upslogx(LOG_WARNING, "You are using the -k option, which is broken for this driver.\nShutting down for 10 minutes and hoping for the best");
1143
belkin_nut_write_int(REG_RESTARTTIMER, 10); /* 10 minutes */
1144
belkin_nut_write_int(REG_SHUTDOWNTIMER, 1); /* 1 second */
1147
int instcmd(const char *cmdname, const char *extra)
1151
/* We use test.failure.start to initiate a "deep battery test".
1152
This does not really simulate a 'power failure', because we
1153
won't start shutdown procedures during a test.
1155
We use test.battery.start to initiate a "10-second battery test". */
1157
if (!strcasecmp(cmdname, "test.failure.start")) {
1158
r = belkin_nut_write_int(REG_TESTSTATUS, 2);
1159
return STAT_INSTCMD_HANDLED; /* Future: failure if r==-1 */
1161
if (!strcasecmp(cmdname, "test.failure.stop")) {
1162
r = belkin_nut_write_int(REG_TESTSTATUS, 3);
1163
return STAT_INSTCMD_HANDLED; /* Future: failure if r==-1 */
1165
if (!strcasecmp(cmdname, "test.battery.start")) {
1166
r = belkin_nut_write_int(REG_TESTSTATUS, 1);
1167
return STAT_INSTCMD_HANDLED; /* Future: failure if r==-1 */
1169
if (!strcasecmp(cmdname, "test.battery.stop")) {
1170
r = belkin_nut_write_int(REG_TESTSTATUS, 3);
1171
return STAT_INSTCMD_HANDLED; /* Future: failure if r==-1 */
1173
if (!strcasecmp(cmdname, "beeper.on")) {
1174
r = belkin_nut_write_int(REG_ALARMSTATUS, 2);
1175
return STAT_INSTCMD_HANDLED; /* Future: failure if r==-1 */
1177
if (!strcasecmp(cmdname, "beeper.off")) {
1178
r = belkin_nut_write_int(REG_ALARMSTATUS, 3);
1179
return STAT_INSTCMD_HANDLED; /* Future: failure if r==-1 */
1181
if (!strcasecmp(cmdname, "shutdown.stayoff")) {
1182
r = belkin_nut_write_int(REG_RESTARTTIMER, 0);
1183
r |= belkin_nut_write_int(REG_SHUTDOWNTIMER, 1); /* 1 second */
1184
return STAT_INSTCMD_HANDLED; /* Future: failure if r==-1 */
1186
if (!strcasecmp(cmdname, "shutdown.reboot")) {
1187
/* restarttimer is in minutes, shutdowntimer is in
1188
seconds. Still, restarttimer=1 is not safe,
1189
because it might be decremented before
1190
shutdowntimer is set, which would cause the UPS to
1191
stay off. So we need restarttimer=2, which means,
1192
the UPS will stay off between 60 and 120 seconds */
1193
r = belkin_nut_write_int(REG_RESTARTTIMER, 2); /* 2 minutes */
1194
r |= belkin_nut_write_int(REG_SHUTDOWNTIMER, 1); /* 1 second */
1195
return STAT_INSTCMD_HANDLED; /* Future: failure if r==-1 */
1197
if (!strcasecmp(cmdname, "shutdown.reboot.graceful")) {
1198
r = belkin_nut_write_int(REG_RESTARTTIMER, 2); /* 2 minutes */
1199
r |= belkin_nut_write_int(REG_SHUTDOWNTIMER, 40); /* 40 seconds */
1200
return STAT_INSTCMD_HANDLED; /* Future: failure if r==-1 */
1202
if (!strcasecmp(cmdname, "reset.input.minmax")) {
1203
minutil = maxutil = -1;
1204
dstate_setinfo("input.voltage.maximum", "none");
1205
dstate_setinfo("input.voltage.minimum", "none");
1206
return STAT_INSTCMD_HANDLED;
1209
upslogx(LOG_NOTICE, "instcmd: unknown command [%s]", cmdname);
1210
return STAT_INSTCMD_UNKNOWN;
1213
/* set a variable */
1214
static int setvar(const char *varname, const char *val)
1218
if (!strcasecmp(varname, "input.sensitivity")) {
1219
for (i=0; i<asize(voltsens); i++) {
1220
if (!strcasecmp(val, voltsens[i])) {
1221
r = belkin_nut_write_int(REG_VOLTSENS, i);
1222
return STAT_SET_HANDLED; /* Future: failure if r==-1 */
1225
return STAT_SET_HANDLED; /* Future: failure */
1226
} else if (!strcasecmp(varname, "ups.beeper.enable")) {
1227
if (!strcasecmp(val, "yes") ||
1228
!strcasecmp(val, "on") ||
1229
!strcasecmp(val, "true")) {
1234
r = belkin_nut_write_int(REG_ALARMSTATUS, i ? 2 : 3);
1235
return STAT_SET_HANDLED; /* Future: failure if r==-1 */
1236
} else if (!strcasecmp(varname, "input.transfer.low")) {
1237
r = belkin_nut_write_int(REG_XFER_LO, atoi(val));
1238
return STAT_SET_HANDLED; /* Future: failure if r==-1 */
1239
} else if (!strcasecmp(varname, "input.transfer.high")) {
1240
r = belkin_nut_write_int(REG_XFER_HI, atoi(val));
1241
return STAT_SET_HANDLED; /* Future: failure if r==-1 */
1244
upslogx(LOG_NOTICE, "setvar: unknown var [%s]", varname);
1245
return STAT_SET_UNKNOWN;
1248
/* I have no idea what to put here */
1249
void upsdrv_help(void)
1252
printf("Writable variables:\n");
1253
printf(" input.sensitivity: normal, medium, low\n");
1254
printf(" ups.beeper.enable: 0=disabled, 1=enabled\n");
1255
printf(" input.transfer.low: (in V)\n");
1256
printf(" input.transfer.high: (in V)\n");
1259
/* list flags and values that you want to receive via -x */
1260
void upsdrv_makevartable(void)
1262
/* allow '-x wait' and '-x wait=<level>' */
1263
addvar(VAR_FLAG, "wait", "Wait for AC power ");
1264
addvar(VAR_VALUE, "wait", "Wait for AC power and battery level");
1266
/* allow '-x nohang' */
1267
addvar(VAR_FLAG, "nohang", "In wait mode: quit if UPS dead ");
1269
/* allow '-x flash' */
1270
addvar(VAR_FLAG, "flash", "In wait mode: do brief shutdown ");
1272
/* allow '-x silent' */
1273
addvar(VAR_FLAG, "silent", "In wait mode: suppress status line ");
1275
/* allow '-x dumbterm' */
1276
addvar(VAR_FLAG, "dumbterm", "In wait mode: simpler status line ");
1280
void upsdrv_banner(void)
1282
printf("Network UPS Tools - Belkin 'Universal UPS' driver %s (%s)\n\n",
1283
DRV_VERSION, UPS_VERSION);
1286
/* prep the serial port */
1287
void upsdrv_initups(void)
1289
/* If '-x wait' or '-x wait=<level>' option given, branch into
1290
standalone behavior. */
1291
if (getval("wait") || dstate_getinfo("driver.flag.wait")) {
1292
exit(belkin_wait());
1295
belkin_nut_open_tty();
1298
void upsdrv_cleanup(void)
1300
ser_close(upsfd, device_path);