1 /* genericups.c - support for generic contact-closure UPS models
3 Copyright (C) 1999 Russell Kroll <rkroll@exploits.org>
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 2 of the License, or
8 (at your option) any later version.
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 #include <sys/ioctl.h>
24 #include "genericups.h"
26 #define DRIVER_NAME "Generic contact-closure UPS driver"
27 #define DRIVER_VERSION "1.36"
29 /* driver description structure */
30 upsdrv_info_t upsdrv_info
= {
33 "Russell Kroll <rkroll@exploits.org>",
38 static int upstype
= -1;
40 static void parse_output_signals(const char *value
, int *line
)
42 /* parse signals the serial port can output */
46 if (strstr(value
, "DTR") && !strstr(value
, "-DTR")) {
50 if (strstr(value
, "RTS") && !strstr(value
, "-RTS")) {
54 if (strstr(value
, "ST")) {
58 if (strstr(value
, "CTS")) {
59 fatalx(EXIT_FAILURE
, "Can't override output with CTS (not an output)");
62 if (strstr(value
, "DCD")) {
63 fatalx(EXIT_FAILURE
, "Can't override output with DCD (not an output)");
66 if (strstr(value
, "RNG")) {
67 fatalx(EXIT_FAILURE
, "Can't override output with RNG (not an output)");
70 if (strstr(value
, "DSR")) {
71 fatalx(EXIT_FAILURE
, "Can't override output with DSR (not an output)");
75 static void parse_input_signals(const char *value
, int *line
, int *val
)
77 /* parse signals the serial port can input */
82 if (strstr(value
, "CTS")) {
85 if (!strstr(value
, "-CTS")) {
90 if (strstr(value
, "DCD")) {
93 if (!strstr(value
, "-DCD")) {
98 if (strstr(value
, "RNG")) {
101 if (!strstr(value
, "-RNG")) {
106 if (strstr(value
, "DSR")) {
109 if (!strstr(value
, "-DSR")) {
114 if (strstr(value
, "DTR")) {
115 fatalx(EXIT_FAILURE
, "Can't override input with DTR (not an input)");
118 if (strstr(value
, "RTS")) {
119 fatalx(EXIT_FAILURE
, "Can't override input with RTS (not an input)");
122 if (strstr(value
, "ST")) {
123 fatalx(EXIT_FAILURE
, "Can't override input with ST (not an input)");
127 void upsdrv_initinfo(void)
131 /* setup the basics */
133 dstate_setinfo("ups.mfr", "%s", ((v
= getval("mfr")) != NULL
) ? v
: upstab
[upstype
].mfr
);
134 dstate_setinfo("ups.model", "%s", ((v
= getval("model")) != NULL
) ? v
: upstab
[upstype
].model
);
136 if ((v
= getval("serial")) != NULL
) {
137 dstate_setinfo("ups.serial", "%s", v
);
141 User wants to override the input signal definitions. See also upsdrv_initups().
143 if ((v
= getval("OL")) != NULL
) {
144 parse_input_signals(v
, &upstab
[upstype
].line_ol
, &upstab
[upstype
].val_ol
);
145 upsdebugx(2, "parse_input_signals: OL overridden with %s\n", v
);
148 if ((v
= getval("LB")) != NULL
) {
149 parse_input_signals(v
, &upstab
[upstype
].line_bl
, &upstab
[upstype
].val_bl
);
150 upsdebugx(2, "parse_input_signals: LB overridden with %s\n", v
);
154 /* normal idle loop - keep up with the current state of the UPS */
155 void upsdrv_updateinfo(void)
157 int flags
, ol
, bl
, ret
;
159 ret
= ioctl(upsfd
, TIOCMGET
, &flags
);
162 upslog_with_errno(LOG_INFO
, "ioctl failed");
163 ser_comm_fail("Status read failed");
168 ol
= ((flags
& upstab
[upstype
].line_ol
) == upstab
[upstype
].val_ol
);
169 bl
= ((flags
& upstab
[upstype
].line_bl
) == upstab
[upstype
].val_bl
);
174 status_set("LB"); /* low battery */
178 status_set("OL"); /* on line */
180 status_set("OB"); /* on battery */
185 upsdebugx(5, "ups.status: %s %s\n", ol
? "OL" : "OB", bl
? "BL" : "");
191 /* show all possible UPS types */
192 static void listtypes(void)
196 printf("Valid UPS types:\n\n");
198 for (i
= 0; upstab
[i
].mfr
!= NULL
; i
++) {
199 printf("%i: %s\n", i
, upstab
[i
].desc
);
203 /* set the flags for this UPS type */
204 static void set_ups_type(void)
208 if (!getval("upstype")) {
209 fatalx(EXIT_FAILURE
, "No upstype set - see help text / man page!");
212 upstype
= atoi(getval("upstype"));
214 for (i
= 0; upstab
[i
].mfr
!= NULL
; i
++) {
217 upslogx(LOG_INFO
, "UPS type: %s\n", upstab
[i
].desc
);
224 fatalx(EXIT_FAILURE
, "\nFatal error: unknown UPS type number");
227 /* power down the attached load immediately */
228 void upsdrv_shutdown(void)
233 fatalx(EXIT_FAILURE
, "No upstype set - see help text / man page!");
236 flags
= upstab
[upstype
].line_sd
;
239 fatalx(EXIT_FAILURE
, "No shutdown command defined for this model!");
242 if (flags
== TIOCM_ST
) {
244 #ifndef HAVE_TCSENDBREAK
245 fatalx(EXIT_FAILURE
, "Need to send a BREAK, but don't have tcsendbreak!");
248 ret
= tcsendbreak(upsfd
, 4901);
251 fatal_with_errno(EXIT_FAILURE
, "tcsendbreak");
257 ret
= ioctl(upsfd
, TIOCMSET
, &flags
);
260 fatal_with_errno(EXIT_FAILURE
, "ioctl TIOCMSET");
263 if (getval("sdtime")) {
266 sdtime
= strtol(getval("sdtime"), (char **) NULL
, 10);
268 upslogx(LOG_INFO
, "Holding shutdown signal for %d seconds...\n",
275 void upsdrv_help(void)
280 void upsdrv_makevartable(void)
282 addvar(VAR_VALUE
, "upstype", "Set UPS type (required)");
283 addvar(VAR_VALUE
, "mfr", "Override manufacturer name");
284 addvar(VAR_VALUE
, "model", "Override model name");
285 addvar(VAR_VALUE
, "serial", "Specify the serial number");
286 addvar(VAR_VALUE
, "CP", "Override cable power setting");
287 addvar(VAR_VALUE
, "OL", "Override on line signal");
288 addvar(VAR_VALUE
, "LB", "Override low battery signal");
289 addvar(VAR_VALUE
, "SD", "Override shutdown setting");
290 addvar(VAR_VALUE
, "sdtime", "Hold time for shutdown value (seconds)");
293 void upsdrv_initups(void)
300 upsfd
= ser_open(device_path
);
302 if (tcgetattr(upsfd
, &tio
)) {
303 fatal_with_errno(EXIT_FAILURE
, "tcgetattr");
306 /* don't hang up on last close */
307 tio
.c_cflag
&= ~HUPCL
;
309 if (tcsetattr(upsfd
, TCSANOW
, &tio
)) {
310 fatal_with_errno(EXIT_FAILURE
, "tcsetattr");
314 See if the user wants to override the output signal definitions
315 this must be done here, since we might go to upsdrv_shutdown()
316 immediately. Input signal definition override is handled in
319 if ((v
= getval("CP")) != NULL
) {
320 parse_output_signals(v
, &upstab
[upstype
].line_norm
);
321 upsdebugx(2, "parse_output_signals: CP overridden with %s\n", v
);
324 if ((v
= getval("SD")) != NULL
) {
325 parse_output_signals(v
, &upstab
[upstype
].line_sd
);
326 upsdebugx(2, "parse_output_signals: SD overridden with %s\n", v
);
329 if (ioctl(upsfd
, TIOCMSET
, &upstab
[upstype
].line_norm
)) {
330 fatal_with_errno(EXIT_FAILURE
, "ioctl TIOCMSET");
334 void upsdrv_cleanup(void)
336 ser_close(upsfd
, device_path
);