~iheino+ub/+junk/nut-upsconf-docfix

« back to all changes in this revision

Viewing changes to drivers/nutdrv_qx_blazer-common.c

  • Committer: Tuomas Heino
  • Author(s): Laurent Bigonville
  • Date: 2014-04-22 20:46:12 UTC
  • Revision ID: iheino+ub@cc.hut.fi-20140422204612-1x2gh3nkezfsdao4
Tags: upstream-2.7.2
ImportĀ upstreamĀ versionĀ 2.7.2

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* nutdrv_qx_blazer-common.c - Common functions/settings for nutdrv_qx_{mecer,megatec,megatec-old,mustek,q1,voltronic-qs,zinto}.{c,h}
 
2
 *
 
3
 * Copyright (C)
 
4
 *   2013 Daniele Pezzini <hyouko@gmail.com>
 
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
 
 
22
#include "main.h"
 
23
#include "nutdrv_qx.h"
 
24
#include "nutdrv_qx_blazer-common.h"
 
25
 
 
26
/* == Ranges == */
 
27
 
 
28
/* Range for ups.delay.start */
 
29
info_rw_t       blazer_r_ondelay[] = {
 
30
        { "0", 0 },
 
31
        { "599940", 0 },
 
32
        { "", 0 }
 
33
};
 
34
 
 
35
/* Range for ups.delay.shutdown */
 
36
info_rw_t       blazer_r_offdelay[] = {
 
37
        { "12", 0 },
 
38
        { "600", 0 },
 
39
        { "", 0 }
 
40
};
 
41
 
 
42
/* == Support functions == */
 
43
 
 
44
/* This function allows the subdriver to "claim" a device: return 1 if the device is supported by this subdriver, else 0. */
 
45
int     blazer_claim(void) {
 
46
 
 
47
        /* To tell whether the UPS is supported or not, we'll check both status (Q1/QS/D) and vendor (I/FW?) - provided that we were not told not to do it with the ups.conf flag 'novendor'. */
 
48
 
 
49
        item_t  *item = find_nut_info("input.voltage", 0, 0);
 
50
 
 
51
        /* Don't know what happened */
 
52
        if (!item)
 
53
                return 0;
 
54
 
 
55
        /* No reply/Unable to get value */
 
56
        if (qx_process(item, NULL))
 
57
                return 0;
 
58
 
 
59
        /* Unable to process value */
 
60
        if (ups_infoval_set(item) != 1)
 
61
                return 0;
 
62
 
 
63
        if (testvar("novendor"))
 
64
                return 1;
 
65
 
 
66
        /* Vendor */
 
67
        item = find_nut_info("ups.firmware", 0, 0);
 
68
 
 
69
        /* Don't know what happened */
 
70
        if (!item) {
 
71
                dstate_delinfo("input.voltage");
 
72
                return 0;
 
73
        }
 
74
 
 
75
        /* No reply/Unable to get value */
 
76
        if (qx_process(item, NULL)) {
 
77
                dstate_delinfo("input.voltage");
 
78
                return 0;
 
79
        }
 
80
 
 
81
        /* Unable to process value */
 
82
        if (ups_infoval_set(item) != 1) {
 
83
                dstate_delinfo("input.voltage");
 
84
                return 0;
 
85
        }
 
86
 
 
87
        return 1;
 
88
 
 
89
}
 
90
 
 
91
/* This function allows the subdriver to "claim" a device: return 1 if the device is supported by this subdriver, else 0.
 
92
 * NOTE: this 'light' version only checks for status (Q1/QS/D/..) */
 
93
int     blazer_claim_light(void) {
 
94
 
 
95
        /* To tell whether the UPS is supported or not, we'll check just status (Q1/QS/D/..). */
 
96
 
 
97
        item_t  *item = find_nut_info("input.voltage", 0, 0);
 
98
 
 
99
        /* Don't know what happened */
 
100
        if (!item)
 
101
                return 0;
 
102
 
 
103
        /* No reply/Unable to get value */
 
104
        if (qx_process(item, NULL))
 
105
                return 0;
 
106
 
 
107
        /* Unable to process value */
 
108
        if (ups_infoval_set(item) != 1)
 
109
                return 0;
 
110
 
 
111
        return 1;
 
112
 
 
113
}
 
114
 
 
115
/* Subdriver-specific flags/vars */
 
116
void    blazer_makevartable(void)
 
117
{
 
118
        addvar(VAR_FLAG, "norating", "Skip reading rating information from UPS");
 
119
        addvar(VAR_FLAG, "novendor", "Skip reading vendor information from UPS");
 
120
}
 
121
 
 
122
/* Subdriver-specific initups */
 
123
void    blazer_initups(item_t *qx2nut)
 
124
{
 
125
        int     nr, nv;
 
126
        item_t  *item;
 
127
 
 
128
        nr = testvar("norating");
 
129
        nv = testvar("novendor");
 
130
 
 
131
        if (!nr && !nv)
 
132
                return;
 
133
 
 
134
        for (item = qx2nut; item->info_type != NULL; item++) {
 
135
 
 
136
                if (!item->command)
 
137
                        continue;
 
138
 
 
139
                /* norating */
 
140
                if (nr && !strcasecmp(item->command, "F\r")) {
 
141
                        upsdebugx(2, "%s: skipping %s", __func__, item->info_type);
 
142
                        item->qxflags |= QX_FLAG_SKIP;
 
143
                }
 
144
 
 
145
                /* novendor */
 
146
                if (nv && (!strcasecmp(item->command, "I\r") || !strcasecmp(item->command, "FW?\r"))) {
 
147
                        upsdebugx(2, "%s: skipping %s", __func__, item->info_type);
 
148
                        item->qxflags |= QX_FLAG_SKIP;
 
149
                }
 
150
 
 
151
        }
 
152
}
 
153
 
 
154
/* == Preprocess functions == */
 
155
 
 
156
/* Preprocess setvars */
 
157
int     blazer_process_setvar(item_t *item, char *value, size_t valuelen)
 
158
{
 
159
        if (!strlen(value)) {
 
160
                upsdebugx(2, "%s: value not given for %s", __func__, item->info_type);
 
161
                return -1;
 
162
        }
 
163
 
 
164
        if (!strcasecmp(item->info_type, "ups.delay.start")) {
 
165
 
 
166
                int     ondelay = strtol(value, NULL, 10);
 
167
 
 
168
                /* Truncate to minute */
 
169
                ondelay -= (ondelay % 60);
 
170
 
 
171
                snprintf(value, valuelen, "%d", ondelay);
 
172
 
 
173
        } else if (!strcasecmp(item->info_type, "ups.delay.shutdown")) {
 
174
 
 
175
                int     offdelay = strtol(value, NULL, 10);
 
176
 
 
177
                /* Truncate to nearest settable value */
 
178
                if (offdelay < 60) {
 
179
                        offdelay -= (offdelay % 6);
 
180
                } else {
 
181
                        offdelay -= (offdelay % 60);
 
182
                }
 
183
 
 
184
                snprintf(value, valuelen, "%d", offdelay);
 
185
 
 
186
        } else {
 
187
 
 
188
                /* Don't know what happened */
 
189
                return -1;
 
190
 
 
191
        }
 
192
 
 
193
        return 0;
 
194
}
 
195
 
 
196
/* Preprocess instant commands */
 
197
int     blazer_process_command(item_t *item, char *value, size_t valuelen)
 
198
{
 
199
        if (!strcasecmp(item->info_type, "shutdown.return")) {
 
200
 
 
201
                /* Sn: Shutdown after n minutes and then turn on when mains is back
 
202
                 * SnRm: Shutdown after n minutes and then turn on after m minutes
 
203
                 * Accepted values for n: .2 -> .9 , 01 -> 10
 
204
                 * Accepted values for m: 0001 -> 9999
 
205
                 * Note: "S01R0001" and "S01R0002" may not work on early (GE) firmware versions.
 
206
                 * The failure mode is that the UPS turns off and never returns.
 
207
                 * The fix is to push the return value up by 2, i.e. S01R0003, and it will return online properly.
 
208
                 * (thus the default of ondelay=3 mins) */
 
209
 
 
210
                int     offdelay = strtol(dstate_getinfo("ups.delay.shutdown"), NULL, 10),
 
211
                        ondelay = strtol(dstate_getinfo("ups.delay.start"), NULL, 10) / 60;
 
212
                char    buf[SMALLBUF] = "";
 
213
 
 
214
                if (ondelay == 0) {
 
215
 
 
216
                        if (offdelay < 60) {
 
217
                                snprintf(buf, sizeof(buf), ".%d", offdelay / 6);
 
218
                        } else {
 
219
                                snprintf(buf, sizeof(buf), "%02d", offdelay / 60);
 
220
                        }
 
221
 
 
222
                } else if (offdelay < 60) {
 
223
 
 
224
                        snprintf(buf, sizeof(buf), ".%dR%04d", offdelay / 6, ondelay);
 
225
 
 
226
                } else {
 
227
 
 
228
                        snprintf(buf, sizeof(buf), "%02dR%04d", offdelay / 60, ondelay);
 
229
 
 
230
                }
 
231
 
 
232
                snprintf(value, valuelen, item->command, buf);
 
233
 
 
234
        } else if (!strcasecmp(item->info_type, "shutdown.stayoff")) {
 
235
 
 
236
                /* SnR0000
 
237
                 * Shutdown after n minutes and stay off
 
238
                 * Accepted values for n: .2 -> .9 , 01 -> 10 */
 
239
 
 
240
                int     offdelay = strtol(dstate_getinfo("ups.delay.shutdown"), NULL, 10);
 
241
                char    buf[SMALLBUF] = "";
 
242
 
 
243
                if (offdelay < 60) {
 
244
                        snprintf(buf, sizeof(buf), ".%d", offdelay / 6);
 
245
                } else {
 
246
                        snprintf(buf, sizeof(buf), "%02d", offdelay / 60);
 
247
                }
 
248
 
 
249
                snprintf(value, valuelen, item->command, buf);
 
250
 
 
251
        } else if (!strcasecmp(item->info_type, "test.battery.start")) {
 
252
 
 
253
                int     delay = strlen(value) > 0 ? strtol(value, NULL, 10) : 600;
 
254
 
 
255
                if ((delay < 60) || (delay > 5940)) {
 
256
                        upslogx(LOG_ERR, "%s: battery test time '%d' out of range [60..5940] seconds", item->info_type, delay);
 
257
                        return -1;
 
258
                }
 
259
 
 
260
                delay = delay / 60;
 
261
 
 
262
                snprintf(value, valuelen, item->command, delay);
 
263
 
 
264
        } else {
 
265
 
 
266
                /* Don't know what happened */
 
267
                return -1;
 
268
 
 
269
        }
 
270
 
 
271
        return 0;
 
272
}
 
273
 
 
274
/* Process status bits */
 
275
int     blazer_process_status_bits(item_t *item, char *value, size_t valuelen)
 
276
{
 
277
        char    *val = "";
 
278
 
 
279
        if (strspn(item->value, "01") != 1) {
 
280
                upsdebugx(3, "%s: unexpected value %s@%d->%s", __func__, item->value, item->from, item->value);
 
281
                return -1;
 
282
        }
 
283
 
 
284
        switch (item->from)
 
285
        {
 
286
        case 38:        /* Utility Fail (Immediate) */
 
287
 
 
288
                if (item->value[0] == '1')
 
289
                        val = "!OL";
 
290
                else
 
291
                        val = "OL";
 
292
                break;
 
293
 
 
294
        case 39:        /* Battery Low */
 
295
 
 
296
                if (item->value[0] == '1')
 
297
                        val = "LB";
 
298
                else
 
299
                        val = "!LB";
 
300
                break;
 
301
 
 
302
        case 40:        /* Bypass/Boost or Buck Active */
 
303
 
 
304
                if (item->value[0] == '1') {
 
305
 
 
306
                        double  vi, vo;
 
307
 
 
308
                        vi = strtod(dstate_getinfo("input.voltage"), NULL);
 
309
                        vo = strtod(dstate_getinfo("output.voltage"), NULL);
 
310
 
 
311
                        if (vo < 0.5 * vi) {
 
312
                                upsdebugx(2, "%s: output voltage too low", __func__);
 
313
                                return -1;
 
314
                        } else if (vo < 0.95 * vi) {
 
315
                                val = "TRIM";
 
316
                        } else if (vo < 1.05 * vi) {
 
317
                                val = "BYPASS";
 
318
                        } else if (vo < 1.5 * vi) {
 
319
                                val = "BOOST";
 
320
                        } else {
 
321
                                upsdebugx(2, "%s: output voltage too high", __func__);
 
322
                                return -1;
 
323
                        }
 
324
 
 
325
                }
 
326
 
 
327
                break;
 
328
 
 
329
        case 41:        /* UPS Failed - ups.alarm */
 
330
 
 
331
                if (item->value[0] == '1')
 
332
                        val = "UPS selftest failed!";
 
333
                break;
 
334
 
 
335
        case 42:        /* UPS Type - ups.type */
 
336
 
 
337
                if (item->value[0] == '1')
 
338
                        val = "offline / line interactive";
 
339
                else
 
340
                        val = "online";
 
341
                break;
 
342
 
 
343
        case 43:        /* Test in Progress */
 
344
 
 
345
                if (item->value[0] == '1')
 
346
                        val = "CAL";
 
347
                else
 
348
                        val = "!CAL";
 
349
                break;
 
350
 
 
351
        case 44:        /* Shutdown Active */
 
352
 
 
353
                if (item->value[0] == '1') {
 
354
                        if (!strcasecmp(item->info_type, "ups.status"))
 
355
                                val = "FSD";
 
356
                        else    /* ups.alarm */
 
357
                                val = "Shutdown imminent!";
 
358
                } else if (!strcasecmp(item->info_type, "ups.status")) {
 
359
                        val = "!FSD";
 
360
                }
 
361
                break;
 
362
 
 
363
        case 45:        /* Beeper status - ups.beeper.status */
 
364
 
 
365
                if (item->value[0] == '1')
 
366
                        val = "enabled";
 
367
                else
 
368
                        val = "disabled";
 
369
                break;
 
370
 
 
371
        default:
 
372
                /* Don't know what happened */
 
373
                return -1;
 
374
        }
 
375
 
 
376
        snprintf(value, valuelen, "%s", val);
 
377
 
 
378
        return 0;
 
379
}