~ubuntu-branches/ubuntu/saucy/nut/saucy

« back to all changes in this revision

Viewing changes to drivers/belkinunv.c

  • Committer: Bazaar Package Importer
  • Author(s): Reinhard Tartler
  • Date: 2005-07-20 19:48:50 UTC
  • mto: (16.1.1 squeeze)
  • mto: This revision was merged to the branch mainline in revision 4.
  • Revision ID: james.westby@ubuntu.com-20050720194850-oo61wjr33rrx2mre
Tags: upstream-2.0.2
ImportĀ upstreamĀ versionĀ 2.0.2

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* belkinunv.c - driver for newer Belkin models, such as "Belkin
 
2
   Universal UPS" (ca. 2003)
 
3
 
 
4
   Copyright (C) 2003 Peter Selinger <selinger@users.sourceforge.net>
 
5
 
 
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.
 
10
 
 
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.
 
15
 
 
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
 
19
*/
 
20
 
 
21
/* SOFT SHUTDOWN WORKAROUND
 
22
 
 
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
 
31
   page for details.
 
32
 
 
33
   VARIABLES:
 
34
 
 
35
   battery.charge
 
36
   battery.runtime
 
37
   battery.voltage
 
38
   battery.voltage.nominal
 
39
   driver.version.internal
 
40
   input.frequency
 
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)
 
45
   input.voltage
 
46
   input.voltage.maximum
 
47
   input.voltage.minimum
 
48
   input.voltage.nominal
 
49
   output.frequency
 
50
   output.voltage
 
51
   ups.beeper.enable            (RW) yes/no
 
52
   ups.firmware
 
53
   ups.load
 
54
   ups.model
 
55
   ups.power.nominal            e.g. 800 for an 800VA system
 
56
   ups.status
 
57
   ups.temperature
 
58
   ups.test.result
 
59
   ups.timer.restart            read-only: time to restart
 
60
   ups.timer.shutdown           read-only: time to shutdown
 
61
   ups.type                     ONLINE/OFFLINE/LINEINT
 
62
                                   
 
63
   COMMANDS:
 
64
                                   
 
65
   beeper.off
 
66
   beeper.on
 
67
   reset.input.minmax
 
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
 
72
   test.battery.stop
 
73
   test.failure.start           start "deep" battery test
 
74
   test.failure.stop
 
75
 
 
76
   STATUS FLAGS:
 
77
 
 
78
   OB                           load is on battery, including during tests
 
79
   OFF                          load is off
 
80
   OL                           load is online
 
81
   ACFAIL                       AC failure
 
82
   OVER                         overload
 
83
   OVERHEAT                     overheat
 
84
   COMMFAULT                    UPS Fault
 
85
   LB                           low battery
 
86
   CHRG                         charging
 
87
   DEPLETED                     battery depleted
 
88
   RB                           replace battery
 
89
 
 
90
*/
 
91
 
 
92
 
 
93
#include "main.h"
 
94
#include "serial.h"
 
95
#include <sys/ioctl.h>
 
96
#include <sys/termios.h>
 
97
        
 
98
/* driver version */
 
99
#define DRV_VERSION     "0.06"
 
100
 
 
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
 
105
 
 
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
 
137
 
 
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
 
146
 
 
147
/* flags for REG_BATSTATUS */
 
148
#define BS_LOW       0x04
 
149
#define BS_CHARGING  0x10
 
150
#define BS_ONBATTERY 0x20
 
151
#define BS_DEPLETED  0x40
 
152
#define BS_REPLACE   0x80
 
153
 
 
154
/* size of an array */
 
155
#define asize(x) ((int)(sizeof(x)/sizeof(x[0])))
 
156
 
 
157
const char *upstype[3] = {
 
158
        "ONLINE", 
 
159
        "OFFLINE", 
 
160
        "LINEINT"
 
161
};
 
162
 
 
163
const char *voltsens[3] = {
 
164
        "normal", 
 
165
        "medium", 
 
166
        "low"
 
167
};
 
168
 
 
169
const char *teststatus[6] = {
 
170
        "no test performed", 
 
171
        "test passed", 
 
172
        "test failed", 
 
173
        "test failed", 
 
174
        "test aborted", 
 
175
        "test in progress"
 
176
};
 
177
 
 
178
#define ST_OFF 0
 
179
#define ST_ONLINE 1
 
180
#define ST_BATTERY 2
 
181
 
 
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 */
 
186
};
 
187
 
 
188
/* some useful strings */
 
189
#define ESC     "\033"
 
190
#define COL0    ESC "[G" ESC "[K"  /* terminal control: clear line */
 
191
 
 
192
static int minutil = -1;
 
193
static int maxutil = -1;
 
194
 
 
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;
 
199
 
 
200
int instcmd(const char *cmdname, const char *extra);
 
201
static int setvar(const char *varname, const char *val);
 
202
 
 
203
/* ---------------------------------------------------------------------- */
 
204
/* a general purpose Belkin-specific function: */
 
205
 
 
206
/* calculate a Belkin checksum, i.e., add buf[0]...buf[n-1] */
 
207
static unsigned char belkin_checksum(unsigned char *buf, int n) {
 
208
        int i, res;
 
209
 
 
210
        res = 0;
 
211
        for (i=0; i<n; i++) {
 
212
                res += buf[i];
 
213
        }
 
214
        return res & 0xff;
 
215
}
 
216
 
 
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. */
 
223
 
 
224
/* open serial port and switch to "smart" mode */
 
225
static void belkin_nut_open_tty(void)
 
226
{
 
227
        int dtr_bit = TIOCM_DTR;
 
228
        int rts_bit = TIOCM_RTS;
 
229
 
 
230
        upsfd = ser_open(device_path);
 
231
        ser_set_speed(upsfd, device_path, B2400);
 
232
 
 
233
        /* must clear DTR and set RTS for 1 second for UPS to go to
 
234
           "smart" mode */
 
235
        ioctl(upsfd, TIOCMBIC, &dtr_bit);
 
236
        ioctl(upsfd, TIOCMBIS, &rts_bit);
 
237
        sleep(1);
 
238
 
 
239
        tcflush(upsfd, TCIOFLUSH);
 
240
}
 
241
 
 
242
/* receive Belkin message from UPS, check for well-formedness (leading
 
243
   byte, checksum). Return length of message, or -1 if not
 
244
   well-formed */
 
245
static int belkin_nut_receive(unsigned char *buf, int bufsize) {
 
246
        int r;
 
247
        int n=0;
 
248
        int len;
 
249
 
 
250
        /* read 0x7e */
 
251
        if (n+1 > bufsize) {
 
252
                return -1;
 
253
        }
 
254
        r = ser_get_buf_len(upsfd, &buf[0], 1, 3, 0);
 
255
        if (r==-1) {
 
256
                upslogx(LOG_ERR, "No response from UPS");
 
257
                return -1;
 
258
        } else if (buf[0]!=0x7e) {
 
259
                upslogx(LOG_ERR, "Garbage read from UPS");
 
260
                return -1;
 
261
        }
 
262
        n+=r;
 
263
 
 
264
        /* read instruction, size, and register */
 
265
        if (n+3 > bufsize) {
 
266
                return -1;
 
267
        }
 
268
        r = ser_get_buf_len(upsfd, &buf[1], 3, 3, 0);
 
269
        if (r!=3) {
 
270
                upslogx(LOG_ERR, "Short read from UPS");
 
271
                return -1;
 
272
        }
 
273
        n+=r;
 
274
 
 
275
        len = buf[2];
 
276
 
 
277
        /* read data and checksum */
 
278
        if (n+len > bufsize) {
 
279
                return -1;
 
280
        }
 
281
        r = ser_get_buf_len(upsfd, &buf[4], len, 3, 0);
 
282
        if (r!=len) {
 
283
                upslogx(LOG_ERR, "Short read from UPS");
 
284
                return -1;
 
285
        }
 
286
        n+=r;
 
287
 
 
288
        /* check checksum */
 
289
        if (belkin_checksum(buf, len+3) != buf[len+3]) {
 
290
                upslogx(LOG_ERR, "Bad checksum from UPS");
 
291
                return -1;
 
292
        }
 
293
        return n;
 
294
}
 
295
 
 
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];
 
300
        int len, r;
 
301
        char *str;
 
302
 
 
303
        /* send the request */
 
304
        buf[0] = 0x7e;
 
305
        buf[1] = 0x03;
 
306
        buf[2] = 0x02;
 
307
        buf[3] = reg;
 
308
        buf[4] = 0;
 
309
        buf[5] = belkin_checksum(buf, 5);
 
310
 
 
311
        r = ser_send_buf(upsfd, buf, 6);
 
312
        if (r<0) {
 
313
                upslogx(LOG_ERR, "Failed write to UPS");
 
314
                return NULL;
 
315
        }
 
316
 
 
317
        /* receive the answer */
 
318
        r = belkin_nut_receive(buf, MAXMSGSIZE);
 
319
        if (r<0) {
 
320
                return NULL;
 
321
        }
 
322
        if ((buf[1]!=0x05 && buf[1]!=0x01) || buf[3] != reg) {
 
323
                upslogx(LOG_ERR, "Invalid response from UPS");
 
324
                return NULL;
 
325
        }
 
326
        if (buf[1]==0x01) {
 
327
                return NULL;
 
328
        }
 
329
 
 
330
        /* convert the answer to a string */
 
331
        len = buf[2]-1;
 
332
        str = (char *)xmalloc(len+1);
 
333
        memcpy(str, &buf[4], len);
 
334
        str[len]=0;
 
335
        return str;
 
336
}
 
337
 
 
338
/* read the value of an integer register from UPS. Return -1 on
 
339
   failure. */
 
340
static int belkin_nut_read_int(int reg) {
 
341
        unsigned char buf[MAXMSGSIZE];
 
342
        int len, r;
 
343
 
 
344
        /* send the request */
 
345
        buf[0] = 0x7e;
 
346
        buf[1] = 0x03;
 
347
        buf[2] = 0x02;
 
348
        buf[3] = reg;
 
349
        buf[4] = 0;
 
350
        buf[5] = belkin_checksum(buf, 5);
 
351
 
 
352
        r = ser_send_buf(upsfd, buf, 6);
 
353
        if (r<0) {
 
354
                upslogx(LOG_ERR, "Failed write to UPS");
 
355
                return -1;
 
356
        }
 
357
 
 
358
        /* receive the answer */
 
359
        r = belkin_nut_receive(buf, MAXMSGSIZE);
 
360
        if (r<0) {
 
361
                return -1;
 
362
        }
 
363
        if ((buf[1]!=0x05 && buf[1]!=0x01) || buf[3] != reg) {
 
364
                upslogx(LOG_ERR, "Invalid response from UPS");
 
365
                return -1;
 
366
        }
 
367
        if (buf[1]==0x01) {
 
368
                return -1;
 
369
        }
 
370
 
 
371
        /* convert the answer to an integer */
 
372
        len = buf[2]-1;
 
373
        if (len==1) {
 
374
                return buf[4];
 
375
        } else if (len==2) {
 
376
                return buf[4] + 256*buf[5];
 
377
        } else {
 
378
                upslogx(LOG_ERR, "Invalid response from UPS");
 
379
                return -1;
 
380
        }
 
381
}
 
382
 
 
383
/* write the value of an integer register to UPS. Return -1 on
 
384
   failure, else 0 */
 
385
static int belkin_nut_write_int(int reg, int val) {
 
386
        unsigned char buf[MAXMSGSIZE];
 
387
        int r;
 
388
 
 
389
        /* send the request */
 
390
        buf[0] = 0x7e;
 
391
        buf[1] = 0x04;
 
392
        buf[2] = 0x03;
 
393
        buf[3] = reg;
 
394
        buf[4] = val & 0xff;
 
395
        buf[5] = (val>>8) & 0xff;
 
396
        buf[6] = belkin_checksum(buf, 6);
 
397
  
 
398
        r = ser_send_buf(upsfd, buf, 7);
 
399
        if (r<0) {
 
400
                upslogx(LOG_ERR, "Failed write to UPS");
 
401
                return -1;
 
402
        }
 
403
 
 
404
        /* receive the acknowledgement */
 
405
        r = belkin_nut_receive(buf, MAXMSGSIZE);
 
406
        if (r<0) {
 
407
                return -1;
 
408
        }
 
409
        if ((buf[1]!=0x02 && buf[1]!=0x01) || buf[3] != reg) {
 
410
                upslogx(LOG_ERR, "Invalid response from UPS");
 
411
                return -1;
 
412
        }
 
413
        if (buf[1]==0x01) {
 
414
                return -1;
 
415
        }
 
416
        return 0;
 
417
}
 
418
 
 
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. */
 
426
 
 
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) {
 
437
        int fd;
 
438
        struct termios tios;
 
439
        struct flock flock;
 
440
        char buf[128];
 
441
        const int tiocm_dtr = TIOCM_DTR;
 
442
        const int tiocm_rts = TIOCM_RTS;
 
443
        int r;
 
444
        
 
445
        /* open the device */
 
446
        fd = open(device, O_RDWR | O_NONBLOCK);
 
447
        if (fd == -1) {
 
448
                return -1;
 
449
        }
 
450
        
 
451
        /* set communications parameters: 2400 baud, 8 bits, 1 stop bit, no
 
452
           parity, enable reading, hang up when done, ignore modem control
 
453
           lines. */
 
454
        memset(&tios, 0, sizeof(tios));
 
455
        tios.c_cflag = B2400 | CS8 | CREAD | HUPCL | CLOCAL;
 
456
        tios.c_cc[VMIN] = 1;
 
457
        tios.c_cc[VTIME] = 0;
 
458
        r = tcsetattr(fd, TCSANOW, &tios);
 
459
        if (r == -1) {
 
460
                close(fd);
 
461
                return -1;
 
462
        }
 
463
        
 
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
 
469
           port. */
 
470
        ioctl(fd, TIOCMBIC, &tiocm_dtr);
 
471
        ioctl(fd, TIOCMBIS, &tiocm_rts);
 
472
        
 
473
        /* flush both directions of serial port: throw away all data in
 
474
           transit */
 
475
        r = tcflush(fd, TCIOFLUSH);
 
476
        if (r == -1) {
 
477
                close(fd);
 
478
                return -1;
 
479
        }
 
480
        
 
481
        /* lock the port */
 
482
        memset(&flock, 0, sizeof(flock));
 
483
        flock.l_type = F_RDLCK;
 
484
        r = fcntl(fd, F_SETLK, &flock);
 
485
        if (r == -1) {
 
486
                close(fd);
 
487
                return -1;
 
488
        }
 
489
        
 
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. */
 
492
        usleep(1000000);
 
493
        
 
494
        /* flush incoming data again, and read any remaining garbage
 
495
           bytes. There should not be any. */
 
496
        r = tcflush(fd, TCIFLUSH);
 
497
        if (r == -1) {
 
498
                close(fd);
 
499
                return -1;
 
500
        }
 
501
        
 
502
        r = read(fd, buf, 127);
 
503
        if (r == -1 && errno != EAGAIN) {
 
504
                close(fd);
 
505
                return -1;
 
506
        }
 
507
        
 
508
        /* leave port in non-blocking state */
 
509
        
 
510
        return fd;
 
511
}
 
512
 
 
513
/* blocking read with 1-second timeout (use non-blocking i/o) */
 
514
static int belkin_std_upsread(int fd, char *buf, int n) {
 
515
        int count = 0;
 
516
        int r;
 
517
        int tries = 0;
 
518
        
 
519
        while (count < n) {
 
520
                r = read(fd, &buf[count], n-count);
 
521
                if (r==-1 && errno==EAGAIN) { 
 
522
                        /* non-blocking i/o, no data available */
 
523
                        usleep(100000);
 
524
                        tries++;
 
525
                } else if (r == -1) {
 
526
                        return -1;
 
527
                } else {
 
528
                        count += r;
 
529
                }
 
530
                if (tries > 10) {
 
531
                        return -1;
 
532
                }
 
533
        }
 
534
        return count;
 
535
}
 
536
 
 
537
/* blocking write with 1-second timeout (use non-blocking i/o) */
 
538
static int belkin_std_upswrite(int fd, char *buf, int n) {
 
539
        int count = 0;
 
540
        int r;
 
541
        int tries = 0;
 
542
 
 
543
        while (count < n) {
 
544
                r = write(fd, &buf[count], n-count);
 
545
                if (r==-1 && errno==EAGAIN) { 
 
546
                        /* non-blocking i/o, no data available */
 
547
                        usleep(100000);
 
548
                        tries++;
 
549
                } else if (r == -1) {
 
550
                        return -1;
 
551
                } else {
 
552
                        count += r;
 
553
                }
 
554
                if (tries > 10) {
 
555
                        return -1;
 
556
                }
 
557
        }
 
558
        return count;
 
559
}
 
560
 
 
561
/* receive Belkin message from UPS, check for well-formedness (leading
 
562
   byte, checksum). Return length of message, or -1 if not
 
563
   well-formed */
 
564
static int belkin_std_receive(int fd, unsigned char *buf, int bufsize) {
 
565
        int r;
 
566
        int n=0;
 
567
        int len;
 
568
 
 
569
        /* read 0x7e */
 
570
        if (n+1 > bufsize) {
 
571
                return -1;
 
572
        }
 
573
        r = belkin_std_upsread(fd, &buf[0], 1);
 
574
        if (r==-1 || buf[0]!=0x7e) {
 
575
                return -1;
 
576
        }
 
577
        n+=r;
 
578
 
 
579
        /* read instruction, size, and register */
 
580
        if (n+3 > bufsize) {
 
581
                return -1;
 
582
        }
 
583
        r = belkin_std_upsread(fd, &buf[1], 3);
 
584
        if (r!=3) {
 
585
                return -1;
 
586
        }
 
587
        n+=r;
 
588
 
 
589
        len = buf[2];
 
590
 
 
591
        /* read data and checksum */
 
592
        if (n+len > bufsize) {
 
593
                return -1;
 
594
        }
 
595
        r = belkin_std_upsread(fd, &buf[4], len);
 
596
        if (r!=len) {
 
597
                return -1;
 
598
        }
 
599
        n+=r;
 
600
 
 
601
        /* check checksum */
 
602
        if (belkin_checksum(buf, len+3) != buf[len+3]) {
 
603
                return -1;
 
604
        }
 
605
        return n;
 
606
}
 
607
 
 
608
/* read the value of an integer register from UPS. Return -1 on
 
609
   failure. */
 
610
static int belkin_std_read_int(int fd, int reg) {
 
611
        unsigned char buf[MAXMSGSIZE];
 
612
        int len, r;
 
613
 
 
614
        /* send the request */
 
615
        buf[0] = 0x7e;
 
616
        buf[1] = 0x03;
 
617
        buf[2] = 0x02;
 
618
        buf[3] = reg;
 
619
        buf[4] = 0;
 
620
        buf[5] = belkin_checksum(buf, 5);
 
621
 
 
622
        r = belkin_std_upswrite(fd, buf, 6);
 
623
        if (r<0) {
 
624
                return -1;
 
625
        }
 
626
 
 
627
        /* receive the answer */
 
628
        r = belkin_std_receive(fd, buf, MAXMSGSIZE);
 
629
        if (r<0) {
 
630
                return -1;
 
631
        }
 
632
        if ((buf[1]!=0x05 && buf[1]!=0x01) || buf[3] != reg) {
 
633
                return -1;
 
634
        }
 
635
        if (buf[1]==0x01) {
 
636
                return -1;
 
637
        }
 
638
 
 
639
        /* convert the answer to an integer */
 
640
        len = buf[2]-1;
 
641
        if (len==1) {
 
642
                return buf[4];
 
643
        } else if (len==2) {
 
644
                return buf[4] + 256*buf[5];
 
645
        } else {
 
646
                return -1;
 
647
        }
 
648
}
 
649
 
 
650
/* write the value of an integer register to UPS. Return -1 on
 
651
   failure, else 0 */
 
652
static int belkin_std_write_int(int fd, int reg, int val) {
 
653
        unsigned char buf[MAXMSGSIZE];
 
654
        int r;
 
655
  
 
656
        /* send the request */
 
657
        buf[0] = 0x7e;
 
658
        buf[1] = 0x04;
 
659
        buf[2] = 0x03;
 
660
        buf[3] = reg;
 
661
        buf[4] = val & 0xff;
 
662
        buf[5] = (val>>8) & 0xff;
 
663
        buf[6] = belkin_checksum(buf, 6);
 
664
  
 
665
        r = belkin_std_upswrite(fd, buf, 7);
 
666
        if (r<0) {
 
667
                return -1;
 
668
        }
 
669
  
 
670
        /* receive the acknowledgement */
 
671
        r = belkin_std_receive(fd, buf, MAXMSGSIZE);
 
672
        if (r<0) {
 
673
                return -1;
 
674
        }
 
675
        if ((buf[1]!=0x02 && buf[1]!=0x01) || buf[3] != reg) {
 
676
                return -1;
 
677
        }
 
678
        if (buf[1]==0x01) {
 
679
                return -1;
 
680
        }
 
681
        return 0;
 
682
}
 
683
 
 
684
/* ---------------------------------------------------------------------- */
 
685
/* "standalone" program executed when driver is called with the '-x
 
686
   wait' or '-x wait=<level>' flag or option */
 
687
 
 
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 };
 
694
        static int init = 1;
 
695
        va_list ap;
 
696
 
 
697
        if (smode==0) {
 
698
                return;
 
699
        }
 
700
 
 
701
        if (init) {
 
702
                init = 0;
 
703
                oldbuf[0] = 0;
 
704
        }
 
705
 
 
706
        /* read formatted argument string */
 
707
        va_start(ap, fmt);
 
708
        vsnprintf(buf, sizeof(buf), fmt, ap);
 
709
        buf[sizeof(buf)-1] = 0;
 
710
        va_end(ap);
 
711
 
 
712
        if (strcmp(oldbuf, buf)==0) {
 
713
                return;
 
714
        }
 
715
        strcpy(oldbuf, buf);
 
716
 
 
717
        if (smode==2) {
 
718
                /* "dumbterm" version just prints a new line each time */
 
719
                printf("%s\n", buf);
 
720
        } else {
 
721
                /* "normal" version overwrites same line each time */
 
722
                printf(COL0 "%s", buf);
 
723
        }
 
724
        fflush(stdout);
 
725
}
 
726
 
 
727
/* switch from status line display to normal output mode */
 
728
static void endstatus(int smode) {
 
729
        if (smode==1) {
 
730
                fprintf(stdout, "\n");
 
731
                fflush(stdout);
 
732
        }
 
733
}
 
734
 
 
735
static int belkin_wait(void)
 
736
{
 
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 */
 
741
 
 
742
        char *val;
 
743
        int failcount = 0;  /* count consecutive failed connection attempts */
 
744
        int failerrno = 0;
 
745
        int fd;
 
746
        int r;
 
747
        int bs, ov, bl, st;
 
748
 
 
749
        /* read command line '-x' options */
 
750
        val = getval("wait");
 
751
        if (val) {
 
752
                level = atoi(val);
 
753
        }
 
754
 
 
755
        if (dstate_getinfo("driver.flag.nohang")) {
 
756
                nohang = 1;
 
757
        }
 
758
 
 
759
        if (dstate_getinfo("driver.flag.flash")) {
 
760
                flash = 1;
 
761
        }
 
762
        
 
763
        if (dstate_getinfo("driver.flag.silent")) {
 
764
                smode = 0;
 
765
        } else if (dstate_getinfo("driver.flag.dumbterm")) {
 
766
                smode = 2;
 
767
        }
 
768
        
 
769
        updatestatus(smode, "Connecting to UPS...");
 
770
        failcount = 0;
 
771
        fd = -1;
 
772
 
 
773
        while (1) {
 
774
                if (failcount >= 3 && nohang) {
 
775
                        endstatus(smode);
 
776
                        printf("UPS is not responding: %s\n", strerror(failerrno));
 
777
                        return 1;
 
778
                } else if (failcount >= 3) {
 
779
                        updatestatus(smode, "UPS is not responding, will keep trying: %s", strerror(failerrno));
 
780
                }
 
781
                if (fd == -1) {
 
782
                        fd = belkin_std_open_tty(device_path);
 
783
                }
 
784
                if (fd == -1) {
 
785
                        failcount++;
 
786
                        failerrno = errno;
 
787
                        sleep(1);
 
788
                        continue;
 
789
                }
 
790
 
 
791
                /* wait until the UPS is online and the battery level
 
792
                   is >= level */
 
793
                bs = belkin_std_read_int(fd, REG_BATSTATUS);  /* battery status */
 
794
                if (bs==-1) {
 
795
                        failcount++;
 
796
                        failerrno = errno;
 
797
                        close(fd);
 
798
                        fd = -1;
 
799
                        sleep(1);
 
800
                        continue;
 
801
                }
 
802
                ov = belkin_std_read_int(fd, REG_OUTPUTVOLT); /* output voltage */
 
803
                if (ov==-1) {
 
804
                        failcount++;
 
805
                        failerrno = errno;
 
806
                        close(fd);
 
807
                        fd = -1;
 
808
                        sleep(1);
 
809
                        continue;
 
810
                }
 
811
                bl = belkin_std_read_int(fd, REG_BATLEVEL);   /* battery level */
 
812
                if (bl==-1) {
 
813
                        failcount++;
 
814
                        failerrno = errno;
 
815
                        close(fd);
 
816
                        fd = -1;
 
817
                        sleep(1);
 
818
                        continue;
 
819
                }
 
820
                /* successfully got data from UPS */
 
821
                failcount = 0;
 
822
                
 
823
                if (bs & BS_ONBATTERY) {
 
824
                        st = ST_BATTERY;
 
825
                } else if (ov>0) {
 
826
                        st = ST_ONLINE;
 
827
                } else {
 
828
                        st = ST_OFF;
 
829
                }
 
830
                updatestatus(smode, "%s, battery level: %d%%", status[st], bl);
 
831
                if (st == ST_ONLINE && bl >= level) {
 
832
                        break;
 
833
                }
 
834
                sleep(1);
 
835
        }
 
836
 
 
837
        /* termination condition reached */
 
838
        endstatus(smode);
 
839
        if (flash) {
 
840
                printf("Interrupting UPS load for ca. 2 minutes.\n");
 
841
                r = belkin_std_write_int(fd, REG_RESTARTTIMER, 2);
 
842
                if (r==0) {
 
843
                        r = belkin_std_write_int(fd, REG_SHUTDOWNTIMER, 1);
 
844
                }
 
845
                if (r) {
 
846
                        printf("Timed shutdown operation failed.\n");
 
847
                        close(fd);
 
848
                        return 2;
 
849
                }
 
850
        }
 
851
        close(fd);
 
852
        return 0;
 
853
}
 
854
 
 
855
/* ---------------------------------------------------------------------- */
 
856
/* functions which interface with main.c */
 
857
 
 
858
/* read all hardcoded info about this UPS */
 
859
void upsdrv_initinfo(void)
 
860
{
 
861
        char *str;
 
862
        int val;
 
863
        int i;
 
864
 
 
865
        dstate_setinfo("driver.version.internal", "%s", DRV_VERSION);
 
866
 
 
867
        /* read hard-wired values */
 
868
        val = belkin_nut_read_int(REG_VOLTRATING);
 
869
        if (val!=-1) {
 
870
                dstate_setinfo("input.voltage.nominal", "%d", val);
 
871
        }
 
872
 
 
873
        val = belkin_nut_read_int(REG_FREQRATING);
 
874
        if (val!=-1) {
 
875
                dstate_setinfo("input.frequency.nominal", "%d", val);
 
876
        }
 
877
 
 
878
        val = belkin_nut_read_int(REG_POWERRATING);
 
879
        if (val!=-1) {
 
880
                dstate_setinfo("ups.power.nominal", "%d", val);
 
881
        }
 
882
 
 
883
        val = belkin_nut_read_int(REG_BATVOLTRATING);
 
884
        if (val!=-1) {
 
885
                dstate_setinfo("battery.voltage.nominal", "%d", val);
 
886
        }
 
887
 
 
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);
 
892
 
 
893
        str = belkin_nut_read_str(REG_UPSMODEL);
 
894
        if (str) {
 
895
                dstate_setinfo("ups.model", "%s", str);
 
896
                free(str);
 
897
        }
 
898
 
 
899
        val = belkin_nut_read_int(REG_FIRMWARE);
 
900
        if (val!=-1) {
 
901
                dstate_setinfo("ups.firmware", "%d", (val>>4) & 0xf);
 
902
                dstate_setinfo("ups.type", "%s", upstype[(val & 0x0f) % 3]);
 
903
        }
 
904
 
 
905
        /* read writable values and declare them writable */
 
906
        val = belkin_nut_read_int(REG_VOLTSENS);
 
907
        if (val!=-1) {
 
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]);
 
914
          }
 
915
        }
 
916
 
 
917
        val = belkin_nut_read_int(REG_ALARMSTATUS);
 
918
        if (val!=-1) {
 
919
          dstate_setinfo("ups.beeper.enable", "%s", val&1 ? "no" : "yes");
 
920
 
 
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");
 
925
        }
 
926
 
 
927
        val = belkin_nut_read_int(REG_XFER_LO);
 
928
        if (val!=-1) {
 
929
                dstate_setinfo("input.transfer.low", "%d", val);
 
930
 
 
931
                /* declare variable writable */
 
932
                dstate_setflags("input.transfer.low", ST_FLAG_RW);
 
933
 
 
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);
 
938
                        }
 
939
                }
 
940
        }
 
941
 
 
942
        val = belkin_nut_read_int(REG_XFER_HI);
 
943
        if (val!=-1) {
 
944
                dstate_setinfo("input.transfer.high", "%d", val);
 
945
 
 
946
                /* declare variable writable */
 
947
                dstate_setflags("input.transfer.high", ST_FLAG_RW);
 
948
 
 
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);
 
953
                        }
 
954
                }
 
955
        }
 
956
 
 
957
        /* declare handlers for instand commands and writable variables */
 
958
        upsh.instcmd = instcmd;
 
959
        upsh.setvar = setvar;
 
960
 
 
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");
 
972
}
 
973
 
 
974
/* update whatever info we can */
 
975
void upsdrv_updateinfo(void)
 
976
{
 
977
        int val, bs, us, ov;
 
978
 
 
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 */
 
983
 
 
984
        if (us==-1 || bs==-1 || ov==-1) {
 
985
                upslogx(LOG_ERR, "Cannot read from UPS");
 
986
                dstate_datastale();
 
987
                return;
 
988
        }
 
989
 
 
990
        dstate_setinfo("output.voltage", "%.1f", 0.1*ov);
 
991
 
 
992
        status_init();
 
993
        
 
994
        if (bs & BS_ONBATTERY) {
 
995
                status_set("OB");        /* on battery, including tests */
 
996
        } else if (ov > 0) {
 
997
                status_set("OL");        /* online */
 
998
        } else {
 
999
                status_set("OFF");       /* off */
 
1000
        }
 
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. */
 
1007
        }
 
1008
        if (us & US_OVERLOAD) {
 
1009
                status_set("OVER");      /* overload */
 
1010
        }
 
1011
        if (us & US_OVERHEAT) {
 
1012
                status_set("OVERHEAT");  /* overheat, self-invented */
 
1013
        }
 
1014
        if (us & US_UPSFAULT) {
 
1015
                status_set("COMMFAULT"); /* UPS Fault */
 
1016
        }
 
1017
        if (bs & BS_LOW) {
 
1018
                status_set("LB");        /* low battery */
 
1019
        }
 
1020
        if (bs & BS_CHARGING) {
 
1021
                status_set("CHRG");      /* charging */
 
1022
        }
 
1023
        if (bs & BS_DEPLETED) {
 
1024
                status_set("DEPLETED");  /* battery depleted, self-invented */
 
1025
        }
 
1026
        if (bs & BS_REPLACE) {
 
1027
                status_set("RB");        /* replace battery */
 
1028
        }
 
1029
 
 
1030
        status_commit();
 
1031
 
 
1032
        /* new read everything else */
 
1033
 
 
1034
        val = belkin_nut_read_int(REG_XFER_LO);
 
1035
        if (val!=-1) {
 
1036
                dstate_setinfo("input.transfer.low", "%d", val);
 
1037
        }
 
1038
 
 
1039
        val = belkin_nut_read_int(REG_XFER_HI);
 
1040
        if (val!=-1) {
 
1041
                dstate_setinfo("input.transfer.high", "%d", val);
 
1042
        }
 
1043
 
 
1044
        val = belkin_nut_read_int(REG_VOLTSENS);
 
1045
        if (val!=-1) {
 
1046
                dstate_setinfo("input.sensitivity", "%s", (val>=0 && val<asize(voltsens)) ? voltsens[val] : "?");
 
1047
        }
 
1048
 
 
1049
        val = belkin_nut_read_int(REG_TESTSTATUS);
 
1050
        if (val!=-1) {
 
1051
                dstate_setinfo("ups.test.result", "%s", (val>=0 && val<asize(teststatus)) ? teststatus[val] : "?");
 
1052
        }
 
1053
 
 
1054
        val = belkin_nut_read_int(REG_ALARMSTATUS);
 
1055
        if (val!=-1) {
 
1056
                dstate_setinfo("ups.beeper.enable", "%s", val&1 ? "no" : "yes");
 
1057
        }
 
1058
 
 
1059
        val = belkin_nut_read_int(REG_SHUTDOWNTIMER);
 
1060
        if (val!=-1) {
 
1061
                dstate_setinfo("ups.timer.shutdown", "%d", val);
 
1062
        }
 
1063
 
 
1064
        val = belkin_nut_read_int(REG_RESTARTTIMER);
 
1065
        if (val!=-1) {
 
1066
                dstate_setinfo("ups.timer.restart", "%d", 60*val);
 
1067
        }
 
1068
 
 
1069
        val = belkin_nut_read_int(REG_INPUTVOLT);
 
1070
        if (val!=-1) {
 
1071
                dstate_setinfo("input.voltage", "%.1f", 0.1*val);
 
1072
 
 
1073
                /* UPS does not keep track of min/maxutil, but we can */
 
1074
                if (val>0 && (maxutil==-1 || val>maxutil)) {
 
1075
                        maxutil = val;
 
1076
                }
 
1077
                if (val>0 && (minutil==-1 || val<minutil)) {
 
1078
                        minutil = val;
 
1079
                }
 
1080
                dstate_setinfo("input.voltage.maximum", "%.1f", 0.1*maxutil);
 
1081
                dstate_setinfo("input.voltage.minimum", "%.1f", 0.1*minutil);
 
1082
        }
 
1083
 
 
1084
        val = belkin_nut_read_int(REG_INPUTFREQ);
 
1085
        if (val!=-1) {
 
1086
                dstate_setinfo("input.frequency", "%.1f", 0.1*val);
 
1087
        }
 
1088
 
 
1089
        val = belkin_nut_read_int(REG_TEMPERATURE);
 
1090
        if (val!=-1) {
 
1091
                dstate_setinfo("ups.temperature", "%d", val);
 
1092
        }
 
1093
 
 
1094
        val = belkin_nut_read_int(REG_OUTPUTFREQ);
 
1095
        if (val!=-1) {
 
1096
                dstate_setinfo("output.frequency", "%.1f", 0.1*val);
 
1097
        }
 
1098
 
 
1099
        val = belkin_nut_read_int(REG_LOAD);
 
1100
        if (val!=-1) {
 
1101
                dstate_setinfo("ups.load", "%d", val);
 
1102
        }
 
1103
 
 
1104
        val = belkin_nut_read_int(REG_BATVOLT);
 
1105
        if (val!=-1) {
 
1106
                dstate_setinfo("battery.voltage", "%.1f", 0.1*val);
 
1107
        }
 
1108
 
 
1109
        val = belkin_nut_read_int(REG_BATLEVEL);
 
1110
        if (val!=-1) {
 
1111
                dstate_setinfo("battery.charge", "%d", val);
 
1112
        }
 
1113
 
 
1114
        val = belkin_nut_read_int(REG_TIMELEFT);
 
1115
        if (val!=-1) {
 
1116
                dstate_setinfo("battery.runtime", "%d", 60*val);
 
1117
        }
 
1118
 
 
1119
        dstate_dataok();
 
1120
}
 
1121
 
 
1122
/* tell the UPS to shut down, then return - DO NOT SLEEP HERE */
 
1123
void upsdrv_shutdown(void)
 
1124
{
 
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. 
 
1129
 
 
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.
 
1136
 
 
1137
           Don't use this! Use the solution involving the "-x wait"
 
1138
           option instead, as suggested on the belkinunv(8) man
 
1139
           page. */
 
1140
 
 
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");
 
1142
 
 
1143
        belkin_nut_write_int(REG_RESTARTTIMER, 10);  /* 10 minutes */
 
1144
        belkin_nut_write_int(REG_SHUTDOWNTIMER, 1);  /* 1 second */
 
1145
}
 
1146
 
 
1147
int instcmd(const char *cmdname, const char *extra)
 
1148
{
 
1149
        int r;
 
1150
 
 
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.
 
1154
 
 
1155
           We use test.battery.start to initiate a "10-second battery test".  */
 
1156
 
 
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 */
 
1160
        }
 
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 */
 
1164
        }
 
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 */
 
1168
        }
 
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 */
 
1172
        }
 
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 */
 
1176
        }
 
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 */
 
1180
        }
 
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 */
 
1185
        }
 
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 */
 
1196
        }
 
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 */
 
1201
        }
 
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;
 
1207
        }
 
1208
 
 
1209
        upslogx(LOG_NOTICE, "instcmd: unknown command [%s]", cmdname);
 
1210
        return STAT_INSTCMD_UNKNOWN;
 
1211
}
 
1212
 
 
1213
/* set a variable */
 
1214
static int setvar(const char *varname, const char *val)
 
1215
{
 
1216
        int i, r;
 
1217
 
 
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 */
 
1223
                        }
 
1224
                }
 
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")) {
 
1230
                        i=1;
 
1231
                } else {
 
1232
                        i=atoi(val);
 
1233
                }
 
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 */
 
1242
        }
 
1243
 
 
1244
        upslogx(LOG_NOTICE, "setvar: unknown var [%s]", varname);
 
1245
        return STAT_SET_UNKNOWN;
 
1246
}
 
1247
 
 
1248
/* I have no idea what to put here */
 
1249
void upsdrv_help(void)
 
1250
{
 
1251
        printf("\n");
 
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");
 
1257
}
 
1258
 
 
1259
/* list flags and values that you want to receive via -x */
 
1260
void upsdrv_makevartable(void)
 
1261
{
 
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");
 
1265
 
 
1266
        /* allow '-x nohang' */
 
1267
        addvar(VAR_FLAG, "nohang",   "In wait mode: quit if UPS dead     ");
 
1268
 
 
1269
        /* allow '-x flash' */
 
1270
        addvar(VAR_FLAG, "flash",    "In wait mode: do brief shutdown    ");
 
1271
 
 
1272
        /* allow '-x silent' */
 
1273
        addvar(VAR_FLAG, "silent",   "In wait mode: suppress status line ");
 
1274
 
 
1275
        /* allow '-x dumbterm' */
 
1276
        addvar(VAR_FLAG, "dumbterm", "In wait mode: simpler status line  ");
 
1277
 
 
1278
}
 
1279
 
 
1280
void upsdrv_banner(void)
 
1281
{
 
1282
        printf("Network UPS Tools - Belkin 'Universal UPS' driver %s (%s)\n\n", 
 
1283
               DRV_VERSION, UPS_VERSION);
 
1284
}
 
1285
 
 
1286
/* prep the serial port */
 
1287
void upsdrv_initups(void)
 
1288
{
 
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());
 
1293
        }
 
1294
 
 
1295
        belkin_nut_open_tty();
 
1296
}
 
1297
 
 
1298
void upsdrv_cleanup(void)
 
1299
{
 
1300
        ser_close(upsfd, device_path);
 
1301
}