File: apcsmart.h

package info (click to toggle)
nut 2.4.3-1.1squeeze2
  • links: PTS, VCS
  • area: main
  • in suites: squeeze
  • size: 5,816 kB
  • ctags: 5,658
  • sloc: ansic: 45,735; sh: 11,290; makefile: 668; python: 448; perl: 179
file content (285 lines) | stat: -rw-r--r-- 9,016 bytes parent folder | download
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
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
/* apcsmart.h - command table for APC smart protocol units

   Copyright (C) 1999  Russell Kroll <rkroll@exploits.org>
             (C) 2000  Nigel Metheringham <Nigel.Metheringham@Intechnology.co.uk>

   This program is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
   the Free Software Foundation; either version 2 of the License, or
   (at your option) any later version.

   This program is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   GNU General Public License for more details.

   You should have received a copy of the GNU General Public License
   along with this program; if not, write to the Free Software
   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/

#include <ctype.h>
#include <sys/ioctl.h>
#include "serial.h"
#include "timehead.h"

#define APC_TABLE_VERSION	"version 2.1"

/* Basic UPS reply line structure */
#define ENDCHAR 10		/* APC ends responses with LF */

/* these two are only used during startup */
#define IGNCHARS "\015+$|!~%?=*#&"	/* special characters to ignore */
#define MINIGNCHARS "\015+$|!"	/* minimum set of special characters to ignore */

/* normal polls: characters we don't want to parse (including a few alerts) */
#define POLL_IGNORE "\015?=*&|"

/* alert characters we care about - OL, OB, LB, not LB, RB */
#define POLL_ALERT "$!%+#"

#define UPSDELAY	  50000	/* slow down multicharacter commands        */
#define CMDLONGDELAY	1500000	/* some commands need a 1.5s gap for safety */

#define SER_WAIT_SEC	3	/* wait up to 3.0 sec for ser_get calls */
#define SER_WAIT_USEC	0

/* dangerous instant commands must be reconfirmed within a 12 second window */
#define MINCMDTIME	3
#define MAXCMDTIME	15

/* it only does two strings, and they're both the same length */
#define APC_STRLEN	8

/* --------------- */

/* status bits */

#define APC_STAT_CAL	1	/* calibration */
#define APC_STAT_TRIM	2	/* SmartTrim */
#define APC_STAT_BOOST	4	/* SmartBoost */
#define APC_STAT_OL	8	/* on line */
#define APC_STAT_OB	16	/* on battery */
#define APC_STAT_OVER	32	/* overload */
#define APC_STAT_LB	64	/* low battery */
#define APC_STAT_RB	128	/* replace battery */

/* serial protocol: special commands - initialization and such */
#define APC_STATUS	'Q'
#define APC_GOSMART	'Y'
#define APC_GODUMB	'R'
#define APC_CMDSET	'a'
#define APC_CAPABILITY	26	/* ^Z */
#define APC_NEXTVAL	'-'

/* --------------- */

/* Driver command table flag values */

#define APC_POLL	0x0001	/* Poll this variable regularly		*/
#define APC_IGNORE	0x0002	/* Never poll this			*/
#define APC_PRESENT	0x0004	/* Capability seen on this UPS		*/

#define APC_RW		0x0010	/* read-write variable			*/
#define APC_ENUM	0x0020	/* enumerated type			*/
#define APC_STRING	0x0040	/* string				*/

#define APC_NASTY	0x0100	/* Nasty command - take care		*/
#define APC_REPEAT	0x0200	/* Command needs sending twice		*/

#define APC_FORMATMASK	0xFF0000 /* Mask for apc data formats */

#define APC_F_PERCENT	0x020000 /* Data in a percent format */
#define APC_F_VOLT	0x030000 /* Data in a voltage format */
#define APC_F_AMP	0x040000 /* Data in a current/amp format */
#define APC_F_CELSIUS	0x050000 /* Data in a temp/C format */
#define APC_F_HEX	0x060000 /* Data in a hex number format */
#define APC_F_DEC	0x070000 /* Data in a decimal format */
#define APC_F_SECONDS	0x100000 /* Time in seconds */
#define APC_F_MINUTES	0x110000 /* Time in minutes */
#define APC_F_HOURS	0x120000 /* Time in hours */
#define APC_F_REASON	0x130000 /* Reason of transfer */
#define APC_F_LEAVE	0	/* Just pass this through */

struct apc_vartab_t {
	const	char	*name;		/* the variable name */
	unsigned int	flags;	 	/* various flags		*/
	char		cmd;		/* command character */

} apc_vartab[] = {

	{ "ups.firmware",  	0,			'b' },
	{ "ups.firmware.aux",	0,			'v' },
	{ "ups.model",		0,			0x01 },

/* FUTURE: depends on variable naming scheme */
#if 0
	{ "ups.model.code",	0,			'V' },
#endif

	{ "ups.serial",		0,			'n' },
	{ "ups.mfr.date", 	0,			'm' },

	{ "ups.temperature", 	APC_POLL|APC_F_CELSIUS, 'C' },
	{ "ups.load",  		APC_POLL|APC_F_PERCENT, 'P' },

	{ "ups.test.interval",  APC_F_HOURS,		'E' },
	{ "ups.test.result", 	APC_POLL,     		'X' },

	{ "ups.delay.start", 	APC_F_SECONDS,		'r' },
	{ "ups.delay.shutdown",	APC_F_SECONDS,		'p' },

	{ "ups.id",  		APC_STRING,		'c' },

	{ "ups.contacts", 	APC_POLL|APC_F_HEX,	'i' },
	{ "ups.display.language",
			 	0,			0x0C },

	{ "input.voltage", 	APC_POLL|APC_F_VOLT,	'L' },
	{ "input.frequency", 	APC_POLL|APC_F_DEC,	'F' },
	{ "input.sensitivity",	0,			's' },
	{ "input.quality",  	APC_POLL|APC_F_HEX,	'9' },

	{ "input.transfer.low",	APC_F_VOLT,		'l' },
	{ "input.transfer.high",
				APC_F_VOLT,		'u' },
	{ "input.transfer.reason", 
				APC_POLL|APC_F_REASON,	'G' },

	{ "input.voltage.maximum",
				APC_POLL|APC_F_VOLT,	'M' },
	{ "input.voltage.minimum",
				APC_POLL|APC_F_VOLT,	'N' },

	{ "output.current", 	APC_POLL|APC_F_AMP,	'/' },
	{ "output.voltage", 	APC_POLL|APC_F_VOLT,	'O' },
	{ "output.voltage.nominal",  
				APC_F_VOLT,		'o' },

	{ "ambient.humidity",  	APC_POLL|APC_F_PERCENT,	'h' },
	{ "ambient.humidity.high", 
				APC_F_PERCENT,		'{' },
	{ "ambient.humidity.low", 
				APC_F_PERCENT,		'}' },

	{ "ambient.temperature", 	
				APC_POLL|APC_F_CELSIUS, 't' },
	{ "ambient.temperature.high",	
				APC_F_CELSIUS,		'[' },
	{ "ambient.temperature.low", 	
				APC_F_CELSIUS,		']' },

	{ "battery.date",	APC_STRING,		'x' },

	{ "battery.charge",  	APC_POLL|APC_F_PERCENT,	'f' },
	{ "battery.charge.restart",  
				APC_F_PERCENT,		'e' },

	{ "battery.voltage", 	APC_POLL|APC_F_VOLT,	'B' },
	{ "battery.voltage.nominal", 
				0,			'g' },

	{ "battery.runtime", 	APC_POLL|APC_F_MINUTES,	'j' },
	{ "battery.runtime.low",
			 	APC_F_MINUTES,		'q' },

	{ "battery.packs", 	APC_F_DEC,		'>' },
	{ "battery.packs.bad", 	APC_F_DEC,		'<' },
	{ "battery.alarm.threshold", 
				0,			'k' },
	/* todo:

	   I = alarm enable (hex field) - split into alarm.n.enable
	   J = alarm status (hex field) - split into alarm.n.status

	0x15 = output voltage selection (APC_F_VOLT)
	0x5C = load power (APC_POLL|APC_F_PERCENT)

	 */

	{NULL,		0,				0},
};

/* ------ instant commands ------ */

#define APC_CMD_FPTEST		'A'
#define APC_CMD_CALTOGGLE	'D'
#define APC_CMD_SHUTDOWN	'K'
#define APC_CMD_SOFTDOWN	'S'
#define APC_CMD_SIMPWF		'U'
#define APC_CMD_BTESTTOGGLE	'W'
#define APC_CMD_OFF		'Z'

#define APC_CMD_ON		0x0E		/* ^N */
#define APC_CMD_BYPTOGGLE	'^'

struct apc_cmdtab_t {
	const	char	*name;
	int	flags;
	char	cmd;
} apc_cmdtab[] =
{
	{ "load.off",		APC_NASTY|APC_REPEAT,	APC_CMD_OFF       },
	{ "load.on",		APC_REPEAT,		APC_CMD_ON        },

	{ "test.panel.start",	0,			APC_CMD_FPTEST	  },

	{ "test.failure.start",	0,			APC_CMD_SIMPWF    },

	{ "test.battery.start",	0,			APC_CMD_BTESTTOGGLE },
	{ "test.battery.stop",	0,			APC_CMD_BTESTTOGGLE },

	{ "shutdown.return",	APC_NASTY,		APC_CMD_SOFTDOWN  },
	{ "shutdown.stayoff",	APC_NASTY|APC_REPEAT,	APC_CMD_SHUTDOWN  },

	{ "calibrate.start",	0,			APC_CMD_CALTOGGLE },
	{ "calibrate.stop",	0,			APC_CMD_CALTOGGLE },

	{ "bypass.start",	0,			APC_CMD_BYPTOGGLE },
	{ "bypass.stop",	0,			APC_CMD_BYPTOGGLE },

	{ NULL, 0, 0					}
};

/* things to ignore in protocol_verify - useless variables, etc. */
#define CMD_IGN_CHARS "\032-78@.,~\047\177QHRTYayz)1IJ"

/* compatibility with hardware that doesn't do APC_CMDSET ('a') */

struct {
	const	char	*firmware;
	const	char	*cmdchars;
	int	flags;
} compat_tab[] =
{
	/* APC Matrix */
	{ "0ZI",	"79ABCDEFGKLMNOPQRSUVWXYZcefgjklmnopqrsuxz/<>", 0 },
	{ "5UI",	"79ABCDEFGKLMNOPQRSUVWXYZcefgjklmnopqrsuxz/<>", 0 },
	{ "5ZM",	"79ABCDEFGKLMNOPQRSUVWXYZcefgjklmnopqrsuxz/<>", 0 },
	/* APC600 */
	{ "6QD",	"79ABCDEFGKLMNOPQRSUVWXYZcefgjklmnopqrsuxz", 0 },
	{ "6QI",    "79ABCDEFGKLMNOPQRSUVWXYZcefgjklmnopqrsuxz", 0 },
	{ "6TD",	"79ABCDEFGKLMNOPQRSUVWXYZcefgjklmnopqrsuxz", 0 },
	{ "6TI",	"79ABCDEFGKLMNOPQRSUVWXYZcefgjklmnopqrsuxz", 0 },
	/* SmartUPS 900 */
	{ "7QD",    "79ABCDEFGKLMNOPQRSUVWXYZcefgjklmnopqrsuxz", 0 },
	{ "7QI",    "79ABCDEFGKLMNOPQRSUVWXYZcefgjklmnopqrsuxz", 0 },
	{ "7TD",    "79ABCDEFGKLMNOPQRSUVWXYZcefgjklmnopqrsuxz", 0 },
	{ "7TI",    "79ABCDEFGKLMNOPQRSUVWXYZcefgjklmnopqrsuxz", 0 },
	/* SmartUPS 1250. */
	{ "8QD",	"79ABCDEFGKLMNOPQRSUVWXYZcefgjklmnopqrsuxz", 0 },
	{ "8QI",	"79ABCDEFGKLMNOPQRSUVWXYZcefgjklmnopqrsuxz", 0 },
	{ "8TD",    "79ABCDEFGKLMNOPQRSUVWXYZcefgjklmnopqrsuxz", 0 },
	{ "8TI",    "79ABCDEFGKLMNOPQRSUVWXYZcefgjklmnopqrsuxz", 0 },
	/* CS 350 */
	{ "5.4.D",	"\1ABPQRSUYbdfgjmnx9",	0 },
	/* Smart-UPS 600 */
	{ "D9",     "789ABCEFGKLMNOPQRSUVWXYZ", 0 },
	{ "D8",     "789ABCEFGKLMNOPQRSUVWXYZ", 0 },
	{ "D7",     "789ABCEFGKLMNOPQRSUVWXYZ", 0 },
	{ "D6",     "789ABCEFGKLMNOPQRSUVWXYZ", 0 },
	{ "D5",     "789ABCEFGKLMNOPQRSUVWXYZ", 0 },
	{ "D4",     "789ABCEFGKLMNOPQRSUVWXYZ", 0 },

	{ NULL,		NULL,			0 },
};