25
26
#include "newhidups.h"
27
28
/* include all known hid2nut lookup tables */
30
/* pointer to the good HidNut lookup table */
32
/* pointer to the good lookup tables */
31
33
static hid_info_t *hid_ups;
34
static models_name_t *model_names;
34
37
static HIDDevice *hd;
38
static MatchFlags flg;
35
39
static int offdelay = DEFAULT_OFFDELAY;
36
40
static int ondelay = DEFAULT_ONDELAY;
41
static int pollfreq = DEFAULT_POLLFREQ;
42
static int ups_status = 0;
43
static bool data_has_changed = FALSE; /* for SEMI_STATIC data polling */
44
static time_t lastpoll; /* Timestamp the last polling */
38
46
/* support functions */
47
static int instcmd(const char *cmdname, const char *extradata);
39
48
static int setvar(const char *varname, const char *val);
40
static hid_info_t *find_info(const char *varname);
49
static hid_info_t *find_nut_info(const char *varname);
50
static hid_info_t *find_hid_info(const char *hidname);
41
51
static char *hu_find_infoval(info_lkp_t *hid2info, long value);
42
static char *format_model_name(char *iProduct, char *iModel);
52
static char *get_model_name(char *iProduct, char *iModel);
53
static void process_status_info(char *nutvalue);
54
static void ups_status_set(void);
55
static void identify_ups ();
56
static bool hid_ups_walk(int mode);
57
static void reconnect_ups(void);
44
59
/* ---------------------------------------------
45
60
* driver functions implementations
46
61
* --------------------------------------------- */
47
62
void upsdrv_shutdown(void)
51
/* 1) set DelayBeforeStartup */
52
if (getval ("ondelay"))
53
ondelay = atoi (getval ("ondelay"));
55
// HIDSetItemValue(find_info("ups.delay.start")->hidpath, ondelay);
56
sprintf(&delay[0], "%i", ondelay);
57
if (setvar("ups.delay.start", &delay[0])!= STAT_SET_HANDLED)
58
fatalx("Shutoff command failed (setting ondelay)");
60
/* 2) set DelayBeforeShutdown */
61
if (getval ("offdelay"))
62
offdelay = atoi (getval ("offdelay"));
64
//HIDSetItemValue(find_info("ups.delay.shutdown")->hidpath, offdelay);
65
sprintf(&delay[0], "%i", offdelay);
66
if (setvar("ups.delay.shutdown", &delay[0])!= STAT_SET_HANDLED)
67
fatalx("Shutoff command failed (setting offdelay)");
66
/* Retrieve user defined delay settings */
67
if ( getval(HU_VAR_ONDELAY) )
68
ondelay = atoi( getval(HU_VAR_ONDELAY) );
70
if ( getval(HU_VAR_OFFDELAY) )
71
offdelay = atoi( getval(HU_VAR_OFFDELAY) );
73
/* Apply specific method(s) */
77
/* FIXME: the data (or command) should appear in
78
* the hid2nut table, so that it can be autodetected
79
* upon startup, and then calable through setvar()
80
* or instcmd(), ie below
83
/* From apcupsd, usb.c/killpower() */
84
/* 1) APCBattCapBeforeStartup */
85
/* 2) BackUPS Pro => */
88
upsdebugx(2, "upsdrv_shutdown: APC ForceShutdown style shutdown.\n");
89
if (instcmd("shutdown.return", NULL) != STAT_INSTCMD_HANDLED)
90
upsdebugx(2, "ForceShutdown command failed");
93
/* Don't "break" as the general method might also be supported! */;
96
/* 1) set DelayBeforeStartup */
97
sprintf(&delay[0], "%i", ondelay);
98
if (setvar("ups.delay.start", &delay[0])!= STAT_SET_HANDLED)
99
fatalx("Shutoff command failed (setting ondelay)");
101
/* 2) set DelayBeforeShutdown */
102
sprintf(&delay[0], "%i", offdelay);
103
if (setvar("ups.delay.shutdown", &delay[0])!= STAT_SET_HANDLED)
104
fatalx("Shutoff command failed (setting offdelay)");
70
109
/* process instant command and take action. */
71
110
static int instcmd(const char *cmdname, const char *extradata)
73
hid_info_t *hidups_item;
75
/* 1) retrieve and check netvar & item_path */
76
hidups_item = find_info(cmdname);
78
if (hidups_item == NULL || hidups_item->info_type == NULL ||
79
!(hidups_item->hidflags & HU_FLAG_OK))
81
upsdebugx(2, "instcmd: info element unavailable %s\n", cmdname);
82
/* TODO: manage items handled "manually" */
83
return STAT_INSTCMD_UNKNOWN;
86
/* Checking if item is an instant command */
87
if (!hidups_item->hidflags & HU_TYPE_CMD) {
88
upsdebugx(2, "instcmd: %s is not an instant command\n", cmdname);
89
return STAT_INSTCMD_UNKNOWN;
92
/* Actual variable setting */
93
if (HIDSetItemValue(hidups_item->hidpath, atol(hidups_item->dfl))) {
95
upsdebugx(3, "SUCCEED\n");
96
return STAT_INSTCMD_HANDLED;
99
upsdebugx(3, "FAILED\n"); /* TODO: HANDLED but FAILED, not UNKNOWN! */
101
/* TODO: to be completed */
102
return STAT_INSTCMD_UNKNOWN;
112
hid_info_t *hidups_item;
114
upsdebugx(2, "entering instcmd(%s, %s)\n", cmdname, extradata);
116
/* Retrieve and check netvar & item_path */
117
hidups_item = find_nut_info(cmdname);
119
/* Check validity of the found the item */
120
if (hidups_item == NULL || hidups_item->info_type == NULL ||
121
!(hidups_item->hidflags & HU_FLAG_OK))
123
upsdebugx(2, "instcmd: info element unavailable %s\n", cmdname);
124
/* TODO: manage items handled "manually" */
125
return STAT_INSTCMD_UNKNOWN;
128
/* Check if the item is an instant command */
129
if (!hidups_item->hidflags & HU_TYPE_CMD)
131
upsdebugx(2, "instcmd: %s is not an instant command\n", cmdname);
132
return STAT_INSTCMD_UNKNOWN;
135
/* Actual variable setting */
136
if (HIDSetItemValue(hidups_item->hidpath, atol(hidups_item->dfl)))
138
upsdebugx(3, "SUCCEED\n");
139
/* Set the status so that SEMI_STATIC vars are polled */
140
data_has_changed = TRUE;
141
return STAT_INSTCMD_HANDLED;
144
upsdebugx(3, "FAILED\n"); /* TODO: HANDLED but FAILED, not UNKNOWN! */
146
/* TODO: to be completed */
147
return STAT_INSTCMD_UNKNOWN;
105
/* set r/w INFO_ element to a value. */
150
/* set r/w variable to a value. */
106
151
static int setvar(const char *varname, const char *val)
108
hid_info_t *hidups_item;
110
upsdebugx(2, "============== entering setvar(%s, %s) ==============\n", varname, val);
112
/* 1) retrieve and check netvar & item_path */
113
hidups_item = find_info(varname);
115
if (hidups_item == NULL || hidups_item->info_type == NULL ||
116
!(hidups_item->hidflags & HU_FLAG_OK))
118
upsdebugx(2, "setvar: info element unavailable %s\n", varname);
119
return STAT_SET_UNKNOWN;
122
/* Checking item writability and HID Path */
123
if (!hidups_item->info_flags & ST_FLAG_RW) {
124
upsdebugx(2, "setvar: not writable %s\n", varname);
125
return STAT_SET_UNKNOWN;
128
/* handle server side variable */
129
if (hidups_item->hidflags & HU_FLAG_ABSENT) {
130
upsdebugx(2, "setvar: setting server side variable %s\n", varname);
131
dstate_setinfo(hidups_item->info_type, val);
132
return STAT_SET_HANDLED;
134
/* SHUT_FLAG_ABSENT is the only case of HID Path == NULL */
135
if (hidups_item->hidpath == NULL) {
136
upsdebugx(2, "setvar: ID Path is NULL for %s\n", varname);
137
return STAT_SET_UNKNOWN;
141
/* Actual variable setting */
142
if (HIDSetItemValue(hidups_item->hidpath, atol(val))) {
144
/* TODO: GetValue(hidups_item->hidpath) to ensure success */
145
upsdebugx(3, "SUCCEED\n");
146
/* Delay a bit not to flood the device */
148
return STAT_SET_HANDLED;
151
upsdebugx(3, "FAILED\n"); /* TODO: HANDLED but FAILED, not UNKNOWN! */
153
return STAT_SET_UNKNOWN;
156
void upsdrv_help(void) { /* TODO: to be completed */ }
153
hid_info_t *hidups_item;
155
upsdebugx(2, "entering setvar(%s, %s)\n", varname, val);
157
/* 1) retrieve and check netvar & item_path */
158
hidups_item = find_nut_info(varname);
160
if (hidups_item == NULL || hidups_item->info_type == NULL ||
161
!(hidups_item->hidflags & HU_FLAG_OK))
163
upsdebugx(2, "setvar: info element unavailable %s\n", varname);
164
return STAT_SET_UNKNOWN;
167
/* Checking item writability and HID Path */
168
if (!hidups_item->info_flags & ST_FLAG_RW)
170
upsdebugx(2, "setvar: not writable %s\n", varname);
171
return STAT_SET_UNKNOWN;
174
/* handle server side variable */
175
if (hidups_item->hidflags & HU_FLAG_ABSENT)
177
upsdebugx(2, "setvar: setting server side variable %s\n", varname);
178
dstate_setinfo(hidups_item->info_type, "%s", val);
179
return STAT_SET_HANDLED;
183
/* SHUT_FLAG_ABSENT is the only case of HID Path == NULL */
184
if (hidups_item->hidpath == NULL)
186
upsdebugx(2, "setvar: ID Path is NULL for %s\n", varname);
187
return STAT_SET_UNKNOWN;
191
/* Actual variable setting */
192
if (HIDSetItemValue(hidups_item->hidpath, atol(val)))
194
/* FIXME: GetValue(hidups_item->hidpath) to ensure success on non volatile */
195
upsdebugx(3, "SUCCEED\n");
196
/* Delay a bit not to flood the device */
198
/* Set the status so that SEMI_STATIC vars are polled */
199
data_has_changed = TRUE;
200
return STAT_SET_HANDLED;
203
upsdebugx(3, "FAILED\n"); /* FIXME: HANDLED but FAILED, not UNKNOWN! */
205
return STAT_SET_UNKNOWN;
208
void upsdrv_help(void)
210
/* FIXME: to be completed */
158
213
void upsdrv_makevartable(void)
162
/* add command line/conf variables */
163
sprintf(temp, "Set shutdown delay, in seconds (default=%d).",
165
addvar (VAR_VALUE, "offdelay", temp);
167
sprintf(temp, "Set startup delay, in ten seconds units for MGE (default=%d).",
169
addvar (VAR_VALUE, "ondelay", temp);
171
/* TODO: getval (Mfr, Prod, Idx) */
215
char temp [MAX_STRING_SIZE];
217
sprintf(temp, "Set shutdown delay, in seconds (default=%d).",
219
addvar (VAR_VALUE, HU_VAR_OFFDELAY, temp);
221
sprintf(temp, "Set startup delay, in ten seconds units for MGE (default=%d).",
223
addvar (VAR_VALUE, HU_VAR_ONDELAY, temp);
225
sprintf(temp, "Set polling frequency, in seconds, to reduce USB flow (default=%i).",
227
addvar(VAR_VALUE, HU_VAR_POLLFREQ, temp);
229
/* FIXME: autodetection values (Mfr, Product, Index, ...) */
174
232
void upsdrv_banner(void)
176
printf("Network UPS Tools: New HID UPS driver %s (%s)\n\n",
177
DRIVER_VERSION, UPS_VERSION);
179
experimental_driver = 1;
234
printf("Network UPS Tools: New USB/HID UPS driver %s (%s)\n\n",
235
DRIVER_VERSION, UPS_VERSION);
182
/* TODO: merge {init,update}info in hidups_walk() */
183
238
void upsdrv_updateinfo(void)
189
upsdebugx(1, "Updating...\n");
191
/* clear status buffer before begining */
194
/* Process pending events (HID notifications on Interrupt pipe) */
195
/* TODO: process "HIDItem HIDGetNextEvent(HIDDevice *dev);" */
197
/* Device data walk ----------------------------- */
198
for ( item = hid_ups ; item->info_type != NULL ; item++ ) {
200
if ((item->hidflags & HU_FLAG_ABSENT)
201
|| (item->hidflags & HU_TYPE_CMD))
204
if (item->hidflags & HU_FLAG_OK) {
206
/* TODO: 3 tryes before giving up (needed when OnBattery!) */
207
if ((value = HIDGetItemValue(item->hidpath)) != -2 ) {
209
/* deal with status items */
210
if (!strncmp(item->info_type, "ups.status", 10)) {
212
nutvalue = hu_find_infoval(item->hid2info, (long)value);
213
if (nutvalue != NULL)
214
status_set(nutvalue);
216
} else { /* standard items */
217
/* need lookup'ed translation */
218
if (item->hid2info != NULL) {
219
nutvalue = hu_find_infoval(item->hid2info, (long)value);
220
if (nutvalue != NULL)
221
dstate_setinfo(item->info_type, item->dfl, nutvalue);
224
dstate_setinfo(item->info_type, item->dfl, value);
226
dstate_dataok(); /* atomic "commit" call */
242
int retcode, evtCount = 0;
243
HIDItem *eventsList[10];
245
upsdebugx(1, "upsdrv_updateinfo...");
248
/* FIXME: check for device availability */
249
/* to set datastale! */
252
upsdebugx(1, "\n=>Got to reconnect!\n");
256
/* Only do a full update (polling) every pollfreq
257
* or upon data change (ie setvar/instcmd) */
258
if ( (time(NULL) <= (lastpoll + pollfreq))
259
&& (data_has_changed != TRUE) )
261
/* Wait for HID notifications on Interrupt pipe */
262
if ((evtCount = HIDGetEvents(NULL, eventsList)) > 0)
264
upsdebugx(1, "\n=>Got %i HID Objects...", evtCount);
266
/* Process pending events (HID notifications on Interrupt pipe) */
269
/* Check if we are asked to stop (reactivity++) */
273
upsdebugx(3, "Object: %s = %ld",
274
eventsList[evtCount-1]->Path,
275
eventsList[evtCount-1]->Value);
277
if ((item = find_hid_info(eventsList[evtCount-1]->Path)) != NULL)
279
/* Does it need value lookup? */
280
if (item->hid2info != NULL)
282
nutvalue = hu_find_infoval(item->hid2info, (long)eventsList[evtCount-1]->Value);
283
if (nutvalue != NULL)
285
upsdebugx(2, "%s = %s", item->info_type,nutvalue);
287
/* Is it ups.status? */
288
if (!strncmp(item->info_type, "ups.status", 10))
290
/* bitwise status to process it globally */
291
process_status_info(nutvalue);
295
dstate_setinfo(item->info_type, item->dfl, nutvalue);
297
/* FIXME: else => revert the status, ie -LB == reset LB... */
300
upsdebugx(2, "%s = %ld", item->info_type, eventsList[evtCount-1]->Value);
302
free(eventsList[evtCount-1]);
308
retcode = evtCount; /* propagate error code */
310
/* Quick poll on main ups.status data */
311
hid_ups_walk(HU_WALKMODE_QUICK_UPDATE);
313
else /* Polling update */
315
hid_ups_walk(HU_WALKMODE_FULL_UPDATE);
318
/* Reset SEMI_STATIC flag */
319
data_has_changed = FALSE;
323
/* Process status info globally to avoid inconsistencies */
324
static void process_status_info(char *nutvalue)
326
status_lkp_t *status_item;
328
upsdebugx(2, "process_status_info: %s\n", nutvalue);
330
for (status_item = status_info; status_item->status_value != 0 ; status_item++)
332
if (!strcasecmp(status_item->status_str, nutvalue))
334
switch (status_item->status_value)
336
case STATUS_OL: /* clear OB, set OL */
337
ups_status &= ~STATUS_OB;
338
ups_status |= STATUS_OL;
340
case STATUS_OB: /* clear OL, set OB */
341
ups_status &= ~STATUS_OL;
342
ups_status |= STATUS_OB;
344
case STATUS_LB: /* set LB */ /* FIXME: ?clear OL? */
345
ups_status |= STATUS_LB; /* else, put in default! */
347
case STATUS_CHRG: /* clear DISCHRG, set CHRG */
348
ups_status &= ~STATUS_DISCHRG;
349
ups_status |= STATUS_CHRG;
351
case STATUS_DISCHRG: /* clear CHRG, set DISCHRG */
352
ups_status &= ~STATUS_CHRG;
353
ups_status |= STATUS_DISCHRG;
355
/* FIXME: to be checked */
356
default: /* CAL, TRIM, BOOST, OVER, RB, BYPASS, OFF */
357
ups_status |= status_item->status_value;
358
/* FIXME: When do we reset these? */
233
/* Commit the status buffer */
237
365
void upsdrv_initinfo(void)
243
/* identify unit: fill ups.{mfr, model, serial} */
244
dstate_setinfo("ups.mfr", hd->Vendor);
245
dstate_setinfo("ups.model", format_model_name(hd->Product, NULL));
246
dstate_setinfo("ups.serial", (hd->Serial != NULL)?hd->Serial:"unknown");
248
/* TODO: load lookup file (WARNING: should be in initups()
249
because of -k segfault (=> not calling upsdrv_initinfo())
252
/* clear status buffer before begining */
255
/* Device capabilities enumeration ----------------------------- */
256
for ( item = hid_ups ; item->info_type != NULL ; item++ ) {
258
/* Avoid redundancy when multiple defines (RO/RW)
259
* Not applicable to "ups.status" items!
261
if ((dstate_getinfo(item->info_type) != NULL)
262
&& (strncmp(item->info_type, "ups.status", 10))) {
263
item->hidflags &= ~HU_FLAG_OK;
267
/* Special case for handling instant commands */
268
if (item->hidflags & HU_TYPE_CMD) {
269
/* Check actual availability */
270
if (HIDGetItemValue(item->hidpath) != -2 ) {
271
dstate_addcmd(item->info_type);
276
/* Special case for handling server side variables */
277
if (item->hidflags & HU_FLAG_ABSENT) {
278
dstate_setinfo(item->info_type, item->dfl);
279
dstate_setflags(item->info_type, item->info_flags);
280
/* disable reading now => needed?!
281
item->shut_flags &= ~HU_FLAG_OK;*/
283
/* TODO: 3 tryes before giving up (needed when OnBattery!) */
284
if ((value = HIDGetItemValue(item->hidpath)) != -2 ) {
286
item->hidflags &= HU_FLAG_OK;
288
/* deal with status items */
289
if (!strncmp(item->info_type, "ups.status", 10)) {
290
nutvalue = hu_find_infoval(item->hid2info, (long)value);
291
if (nutvalue != NULL)
292
status_set(nutvalue);
294
} else { /* standard items */
295
/* need lookup'ed translation */
296
if (item->hid2info != NULL) {
297
nutvalue = hu_find_infoval(item->hid2info, (long)value);
298
if (nutvalue != NULL)
299
dstate_setinfo(item->info_type, item->dfl, nutvalue);
302
dstate_setinfo(item->info_type, item->dfl, value);
304
/* TODO: verify setability/RW with (hData.Attribute != ATTR_DATA_CST) */
305
dstate_setflags(item->info_type, item->info_flags);
308
/* Set max length for strings */
309
if (item->info_flags & ST_FLAG_STRING)
310
dstate_setaux(item->info_type, item->info_len);
312
dstate_dataok(); /* atomic call */
315
/* invalidate item */
316
item->hidflags &= ~HU_FLAG_OK;
321
/* Commit the status buffer */
324
/* install handlers */
325
upsh.new_setvar = setvar;
326
upsh.new_instcmd = instcmd;
367
/* identify unit: fill ups.{mfr, model, serial} */
370
/* TODO: load lookup file (WARNING: should be in initups()
371
because of -k segfault (=> not calling upsdrv_initinfo())
374
/* Device capabilities enumeration */
375
hid_ups_walk(HU_WALKMODE_INIT);
377
/* install handlers */
378
upsh.setvar = setvar;
379
upsh.instcmd = instcmd;
329
382
void upsdrv_initups(void)
333
/* Search for the first UPS, no matter Mfr or exact product */
334
/* TODO: add vartable for VID, PID, Idx => getval*/
335
flg.VendorID = MGE_UPS_SYSTEMS; /* limiting to MGE is enough for now! */
337
flg.UsageCode = hid_lookup_usage("UPS");
340
if ((hd = HIDOpenDevice(device_path, &flg)) == NULL)
341
fatalx("No USB/HID UPS found");
343
upslogx(1, "Detected an UPS: %s/%s\n", hd->Vendor, hd->Product);
345
/* See initinfo for WARNING */
346
switch (hd->VendorID)
348
case MGE_UPS_SYSTEMS:
353
fatalx("Manufacturer not supported. Contact driver author <arnaud.quette@free.fr>");
354
/* TODO: call dump_tree() */
384
/* Search for the first supported UPS, no matter Mfr or exact product */
385
if ((hd = HIDOpenDevice(device_path, &flg, MODE_OPEN)) == NULL)
386
fatalx("No USB/HID UPS found");
388
upslogx(1, "Detected an UPS: %s/%s\n", hd->Vendor, hd->Product);
390
/* See initinfo for WARNING */
391
switch (hd->VendorID)
393
case MGE_UPS_SYSTEMS:
395
model_names = mge_models_names;
399
model_names = apc_models_names;
406
upslogx(1, "Manufacturer not supported!");
407
upslogx(1, "Contact the driver author <arnaud.quette@free.fr / @mgeups.com> with the below information");
413
/* init polling frequency */
414
if ( getval(HU_VAR_POLLFREQ) )
415
pollfreq = atoi ( getval(HU_VAR_POLLFREQ) );
359
418
void upsdrv_cleanup(void)
365
424
/**********************************************************************
366
425
* Support functions
367
426
*********************************************************************/
369
/* find info element definition in my info array. */
370
static hid_info_t *find_info(const char *varname)
431
char *ptr1, *ptr2, *str;
432
char *finalname = NULL;
435
upsdebugx (2, "entering identify_ups(0x%04x, 0x%04x)\n",
436
hd->VendorID, /*FIXME: iManufacturer? */
439
switch (hd->VendorID)
441
case MGE_UPS_SYSTEMS:
442
/* Get iModel and iProduct strings */
443
if ((string = HIDGetItemString("UPS.PowerSummary.iModel")) != NULL)
444
finalname = get_model_name(hd->Product, string);
447
/* Try with ConfigApparentPower */
448
if (HIDGetItemValue("UPS.Flow.[4].ConfigApparentPower", &appPower) != 0 )
450
string = xmalloc(16);
451
sprintf(string, "%i", (int)appPower);
452
finalname = get_model_name(hd->Product, string);
456
finalname = hd->Product;
460
/* FIXME?: what is the path "UPS.APC_UPS_FirmwareRevision"? */
462
ptr1 = strstr(str, "FW:");
466
ptr1 += strlen("FW:");
467
ptr2 = strstr(ptr1, "USB FW:");
471
ptr2 += strlen("USB FW:");
472
dstate_setinfo("ups.firmware.aux", "%s", ptr2);
474
dstate_setinfo("ups.firmware", "%s", ptr1);
478
default: /* Nothing to do */
482
/* Actual information setting */
483
dstate_setinfo("ups.mfr", "%s", hd->Vendor);
484
dstate_setinfo("ups.model", "%s", finalname);
485
dstate_setinfo("ups.serial", "%s", (hd->Serial != NULL)?hd->Serial:"unknown");
488
/* walk ups variables and set elements of the info array. */
489
static bool hid_ups_walk(int mode)
496
/* 3 modes: HU_WALKMODE_INIT, HU_WALKMODE_QUICK_UPDATE and HU_WALKMODE_FULL_UPDATE */
498
/* Device data walk ----------------------------- */
499
for ( item = hid_ups ; item->info_type != NULL ; item++ )
501
/* Check if we are asked to stop (reactivity++) */
505
/* filter data according to mode */
508
/* Device capabilities enumeration */
509
case HU_WALKMODE_INIT:
511
/* Avoid redundancy when multiple defines (RO/RW)
512
* Not applicable to "ups.status" items! */
513
if ((dstate_getinfo(item->info_type) != NULL)
514
&& (strncmp(item->info_type, "ups.status", 10)))
516
item->hidflags &= ~HU_FLAG_OK;
520
/* Check instant commands availability */
521
if (item->hidflags & HU_TYPE_CMD)
523
if (HIDGetItemValue(item->hidpath, &value) == 1 )
524
dstate_addcmd(item->info_type);
528
/* Special case for handling server side variables */
529
if (item->hidflags & HU_FLAG_ABSENT)
531
/* Check if exists (if necessary) before creation */
532
if (item->hidpath != NULL)
534
if ((retcode = HIDGetItemValue(item->hidpath, &value)) != 1 )
539
/* Simply set the default value */
540
dstate_setinfo(item->info_type, "%s", item->dfl);
541
dstate_setflags(item->info_type, item->info_flags);
545
dstate_setinfo(item->info_type, "%s", item->dfl);
546
dstate_setflags(item->info_type, item->info_flags);
548
/* Set max length for strings, if needed */
549
if (item->info_flags & ST_FLAG_STRING)
550
dstate_setaux(item->info_type, item->info_len);
552
/* disable reading now
553
item->shut_flags &= ~SHUT_FLAG_OK;*/
557
case HU_WALKMODE_QUICK_UPDATE:
559
/* Quick update only deals with status! */
560
if ( !(item->hidflags & HU_FLAG_QUICK_POLL))
565
case HU_WALKMODE_FULL_UPDATE:
567
/* These doesn't need polling after initinfo() */
568
if ((item->hidflags & HU_FLAG_ABSENT)
569
|| (item->hidflags & HU_TYPE_CMD)
570
|| (item->hidflags & HU_FLAG_STATIC)
571
/* These need to be polled after user changes (setvar / instcmd) */
572
|| ( (item->hidflags & HU_FLAG_SEMI_STATIC) && (data_has_changed == FALSE) ) )
573
/* FIXME: external condition might change these, ie pushing the HW On/Off button! */
579
/* Standard variables */
580
/* skip elements we shouldn't process / show. */
581
if ( ( (mode == HU_WALKMODE_QUICK_UPDATE) || (mode == HU_WALKMODE_FULL_UPDATE) )
582
&& !(item->hidflags & HU_FLAG_OK) )
585
if ((retcode = HIDGetItemValue(item->hidpath, &value)) == 1 )
587
/* deal with status items */
588
if (!strncmp(item->info_type, "ups.status", 10))
590
nutvalue = hu_find_infoval(item->hid2info, (long)value);
591
if (nutvalue != NULL)
593
/* bitwise status to process it globally */
594
process_status_info(nutvalue);
598
else /* standard items */
600
/* need lookup'ed translation? */
601
if (item->hid2info != NULL)
603
nutvalue = hu_find_infoval(item->hid2info, (long)value);
604
if (nutvalue != NULL)
605
dstate_setinfo(item->info_type, item->dfl, nutvalue);
608
dstate_setinfo(item->info_type, item->dfl, value);
610
if (mode == HU_WALKMODE_INIT)
612
/* TODO: verify setability/RW with (hData.Attribute != ATTR_DATA_CST) */
613
dstate_setflags(item->info_type, item->info_flags);
616
if (mode == HU_WALKMODE_INIT)
618
/* Set max length for strings */
619
if (item->info_flags & ST_FLAG_STRING)
620
dstate_setaux(item->info_type, item->info_len);
624
/* dstate_dataok(); */
626
/* store timestamp */
627
/* lastpoll = time(NULL); */
631
if ( (retcode == -EPERM) || (retcode == -EPIPE)
632
|| (retcode == -ENODEV) || (retcode == -EACCES) )
639
if (mode == HU_WALKMODE_INIT)
641
/* invalidate item */
642
item->hidflags &= ~HU_FLAG_OK;
647
if (mode == HU_WALKMODE_FULL_UPDATE)
649
/* store timestamp */
650
lastpoll = time(NULL);
653
/* Reserved values: -1/-10 for nul delay, -2 can't get value */
654
/* device has been disconnected, try to reconnect */
655
if ( (retcode == -EPERM) || (retcode == -EPIPE)
656
|| (retcode == -ENODEV) || (retcode == -EACCES) )
669
static void reconnect_ups(void)
673
upsdebugx(2, "==================================================");
674
upsdebugx(2, "= device has been disconnected, try to reconnect =");
675
upsdebugx(2, "==================================================");
677
/* Not really useful as the device is no more reachable */
678
HIDCloseDevice(NULL);
680
if ((hd = HIDOpenDevice(device_path, &flg, MODE_REOPEN)) == NULL)
685
/* Process the whole ups.status */
686
static void ups_status_set(void)
688
/* clear status buffer before begining */
691
if (ups_status & STATUS_CAL)
692
status_set("CAL"); /* calibration */
693
if (ups_status & STATUS_TRIM)
694
status_set("TRIM"); /* SmartTrim */
695
if (ups_status & STATUS_BOOST)
696
status_set("BOOST"); /* SmartBoost */
697
if (ups_status & STATUS_OL)
698
status_set("OL"); /* on line */
699
if (ups_status & STATUS_OB)
700
status_set("OB"); /* on battery */
701
if (ups_status & STATUS_OVER)
702
status_set("OVER"); /* overload */
703
if (ups_status & STATUS_LB)
704
status_set("LB"); /* low battery */
705
if (ups_status & STATUS_RB)
706
status_set("RB"); /* replace batt */
707
if (ups_status & STATUS_BYPASS)
708
status_set("BYPASS"); /* on bypass */
709
if (ups_status & STATUS_CHRG)
710
status_set("CHRG"); /* charging */
711
if (ups_status & STATUS_DISCHRG)
712
status_set("DISCHRG"); /* discharging */
713
if ( (ups_status & STATUS_OFF) || (ups_status == 0) )
716
/* Commit the status buffer */
720
/* find info element definition in info array
723
static hid_info_t *find_nut_info(const char *varname)
372
725
hid_info_t *hidups_item;