23
24
#include <sys/ioctl.h>
24
#include <sys/termios.h>
26
26
#include "timehead.h"
28
#define DRV_VERSION "0.22"
28
#define DRV_VERSION "1.00"
30
30
/* window for repeating dangerous command (shutdown.stayoff) */
34
/* limit the amount of spew that goes in the syslog when we lose the UPS */
35
#define CP_ERR_LIMIT 10 /* start limiting after 10 in a row */
36
#define CP_ERR_RATE 100 /* then only print every 100th error */
40
unsigned int poll_failures = 0;
34
#define UPSDELAY 50000
42
36
/* ups frequency */
43
float frequency(unsigned char in)
37
static float frequency(unsigned char in)
45
float freq[22] = { 63.0, 62.7, 62.4, 62.1, 61.8, 61.4, 61.1, 60.8, 60.5, 60.2, 60.0, 59.7, 59.4, 59.1, 58.8, 58.5, 58.3, 58.0, 57.7, 57.4, 57.2, 57.0 };
39
float freq[22] = { 63.0, 62.7, 62.4, 62.1, 61.8, 61.4, 61.1, 60.8,
40
60.5, 60.2, 60.0, 59.7, 59.4, 59.1, 58.8, 58.5, 58.3, 58.0,
41
57.7, 57.4, 57.2, 57.0 };
48
44
for (i = 0, j = 168; i < 23; j++, i++)
50
46
return (float)freq[i];
55
51
/* adjust bizarre UPS data to observed voltage data */
56
int voltconvert(unsigned char in)
52
static int voltconvert(unsigned char in)
58
int v_end[43] = { 36, 51, 55, 60, 65, 70, 75, 80, 85, 91, 98, 103, 108, 113, 118, 123, 128, 133, 138, 143, 148, 153, 158, 163, 168, 173, 178, 183, 188, 193, 198, 203, 208, 213, 218, 223, 228, 233, 238, 243, 248, 253, 255 };
59
int v_adj[43] = { 3, 4, 5, 4, 3, 2, 1, 0, -1, -2, -3, -4, -5, -6, -7, -8, -9, -10, -11, -12, -13, -14, -15, -16, -17, -18, -19, -20, -21, -22, -23, -24, -25, -26, -27, -28, -29, -30, -31, -32, -33, -34, -35 };
54
int v_end[43] = { 36, 51, 55, 60, 65, 70, 75, 80, 85, 91, 98, 103,
55
108, 113, 118, 123, 128, 133, 138, 143, 148, 153, 158, 163,
56
168, 173, 178, 183, 188, 193, 198, 203, 208, 213, 218, 223,
57
228, 233, 238, 243, 248, 253, 255 };
58
int v_adj[43] = { 3, 4, 5, 4, 3, 2, 1, 0, -1, -2, -3, -4,
59
-5, -6, -7, -8, -9, -10, -11, -12, -13, -14, -15, -16,
60
-17, -18, -19, -20, -21, -22, -23, -24, -25, -26, -27, -28,
61
-29, -30, -31, -32, -33, -34, -35 };
74
76
/* map UPS data to realistic percentages */
75
int battconvert(unsigned char in)
77
static int battconvert(unsigned char in)
77
int b_val[26] = {0, 1, 1, 2, 3, 4, 6, 8, 10, 12, 15, 18, 22, 26, 30, 35, 40, 46, 52, 58, 66, 73, 81, 88, 99, 100 }; /* XXX - for load of 0 */
79
/* these may only be valid for a load of 0 */
80
int b_val[26] = {0, 1, 1, 2, 3, 4, 6, 8, 10, 12, 15, 18, 22, 26, 30,
81
35, 40, 46, 52, 58, 66, 73, 81, 88, 99, 100 };
188
void sendtoups(char ch)
190
write(upsfd, &ch, 1);
194
static void read_timeout(int sig)
200
static int confirm_write(const unsigned char *buf, int buflen)
205
for (i = 0; i < buflen; i++) {
206
ret = write(upsfd, &buf[i], 1);
215
write(upsfd, &ch, 1);
217
for (i = 0; i < buflen; i++) {
220
ret = read(upsfd, &ch, 1);
193
static int confirm_write(const unsigned char *buf, size_t buflen)
199
ret = ser_send_buf_pace(upsfd, UPSDELAY, buf, buflen);
202
upsdebugx(1, "confirm_write: ser_send_buf_pace failed");
206
/* don't try to read back the \r */
207
ret = ser_get_buf_len(upsfd, verify, buflen - 1, 5, 0);
209
if ((ret < 1) || (ret < ((int) buflen - 1))) {
210
upsdebugx(1, "confirm_write: ret=%d, needed %d",
215
for (i = 0; i < buflen - 1; i++) {
216
if (buf[i] != verify[i]) {
224
217
upsdebugx(1, "mismatch at position %d", i);
234
227
/* provide a quick status check to select the right shutdown command */
235
228
static int ups_on_line(void)
238
char buf[SMALLBUF], ch;
245
memset(buf, '\0', sizeof(buf));
249
ret = read(upsfd, &ch, 1);
253
upslogx(LOG_ERR, "Status read failed: assuming on battery");
233
ser_send_pace(upsfd, UPSDELAY, "D\r");
235
/* give it a chance to reply completely */
238
ret = ser_get_buf_len(upsfd, buf, 14, 3, 0);
241
upslogx(LOG_ERR, "Status read failed: assuming on battery");
260
245
if (buf[9] & 128)
263
248
return 1; /* on line */
266
static void setup_sigalrm(void)
268
sigemptyset(&cp_sigmask);
269
sa.sa_mask = cp_sigmask;
271
sa.sa_handler = read_timeout;
272
sigaction(SIGALRM, &sa, NULL);
275
251
/* power down the attached load immediately */
276
252
void upsdrv_shutdown(void)
278
254
int i, ret, sdlen;
280
256
unsigned char sdbuf[16];
284
258
/* get this thing's attention */
285
259
for (i = 0; i < 10; i++) {
286
260
printf("Trying to wake up the ups... ");
292
write(upsfd, &ch, 1);
294
ret = read(upsfd, buf, sizeof(buf));
263
ser_send_char(upsfd, 13);
264
ret = ser_get_buf_len(upsfd, buf, 1, 5, 0);
332
304
printf("On battery: sending 4 byte command (back when line power returns)\n");
341
printf("Sending command...");
344
314
for (i = 0; i < 10; i++) {
315
printf("Sending command...");
346
318
if (confirm_write(sdbuf, sdlen)) {
347
319
printf(" confirmed\n");
351
printf("failed, retrying...");
323
printf("failed, retrying...\n");
356
static void pollfail(const char *why)
360
if ((poll_failures == CP_ERR_LIMIT) ||
361
((poll_failures % CP_ERR_RATE) == 0)) {
362
upslogx(LOG_WARNING, "Warning: excessive poll failures, "
363
"limiting error reporting");
366
if ((poll_failures < CP_ERR_LIMIT) ||
367
((poll_failures % CP_ERR_RATE) == 0)) {
368
upslogx(LOG_ERR, "UPS status unavailable: %s", why);
372
328
void upsdrv_updateinfo(void)
375
char ch, buf[SMALLBUF];
382
memset(buf, '\0', sizeof(buf));
386
ret = read(upsfd, &ch, 1);
390
pollfail("Short read from UPS");
333
ser_send_pace(upsfd, UPSDELAY, "D\r");
335
/* give it a chance to reply completely */
338
ret = ser_get_buf_len(upsfd, buf, 14, 3, 0);
341
ser_comm_fail("Short read from UPS");
398
346
if (buf[0] != '#') {
399
upslogx(LOG_ERR, "Invalid start char 0x%02x", buf[0] & 0xff);
347
ser_comm_fail("Invalid start char 0x%02x", buf[0] & 0xff);
400
348
dstate_datastale();
404
352
if ((buf[4] != 46) || (buf[8] != 46)) {
405
upslogx(LOG_ERR, "Invalid separator in response");
353
ser_comm_fail("Invalid separator in response (0x%02x, 0x%02x)",
406
355
dstate_datastale();
412
dstate_setinfo("input.frequency", "%2.1f", frequency(buf[7]));
361
dstate_setinfo("input.frequency", "%2.1f", frequency(buf[7]));
413
362
dstate_setinfo("ups.temperature", "%2.1f", tempconvert(buf[6]));
414
363
dstate_setinfo("battery.charge", "%03d", battconvert(buf[5]));
415
364
dstate_setinfo("ups.load", "%03d", (buf[3] & 0xff) * 2);
435
384
static int get_ident(char *buf, size_t bufsize)
437
int ret, tries, count;
440
388
for (tries = 0; tries < 3; tries++) {
444
memset(buf, '\0', bufsize);
447
ret = read(upsfd, &ch, 1);
454
if ((buf[0] == '.') && (ch == 13))
457
/* reading way too much */
458
if (count == bufsize) {
459
memset(buf, '\0', bufsize);
464
ret = read(upsfd, &ch, 1);
389
ret = ser_send_pace(upsfd, UPSDELAY, "F\r");
394
/* give it a chance to reply completely */
397
ret = ser_get_line(upsfd, buf, bufsize, '\r', "", 3, 0);
468
405
/* if we got here, then the read failed somehow */
600
537
int dtr_bit = TIOCM_DTR;
601
538
int rts_bit = TIOCM_RTS;
604
open_serial(device_path, B1200);
540
upsfd = ser_open(device_path);
541
ser_set_speed(upsfd, device_path, B1200);
606
543
/* dtr high, rts high */
607
544
ioctl(upsfd, TIOCMBIS, &rts_bit);
608
545
ioctl(upsfd, TIOCMBIS, &dtr_bit);
610
tcgetattr(upsfd, &tio);
611
tio.c_cflag = 0 | CS8 | CLOCAL | ~CRTSCTS | CREAD;
613
tio.c_cflag &= ~(PARODD|CSTOPB|HUPCL|CRTSCTS);
615
cfsetispeed(&tio, B1200);
616
cfsetospeed(&tio, B1200);
617
tcsetattr(upsfd, TCSANOW, &tio);
619
/* avoid getting stuck in read() */
623
548
void upsdrv_initinfo(void)