1 /* nutdrv_qx.c - Driver for USB and serial UPS units with Q* protocols
2  *
3  * Copyright (C)
4  *   2013 Daniele Pezzini <hyouko@gmail.com>
5  * Based on:
6  *  usbhid-ups.c - Copyright (C)
7  *    2003-2012 Arnaud Quette <arnaud.quette@gmail.com>
8  *    2005      John Stamp <kinsayder@hotmail.com>
9  *    2005-2006 Peter Selinger <selinger@users.sourceforge.net>
10  *    2007-2009 Arjen de Korte <adkorte-guest@alioth.debian.org>
11  *  blazer.c - Copyright (C)
12  *    2008-2009 Arjen de Korte <adkorte-guest@alioth.debian.org>
13  *    2012      Arnaud Quette <ArnaudQuette@Eaton.com>
14  *  blazer_ser.c - Copyright (C)
15  *    2008      Arjen de Korte <adkorte-guest@alioth.debian.org>
16  *  blazer_usb.c - Copyright (C)
17  *    2003-2009 Arjen de Korte <adkorte-guest@alioth.debian.org>
18  *    2011-2012 Arnaud Quette <arnaud.quette@free.fr>
19  *  Masterguard additions
20  *    2020-2021 Edgar Fuß, Mathematisches Institut der Universität Bonn <ef@math.uni-bonn.de>
21  *
22  * This program is free software; you can redistribute it and/or modify
23  * it under the terms of the GNU General Public License as published by
24  * the Free Software Foundation; either version 2 of the License, or
25  * (at your option) any later version.
26  *
27  * This program is distributed in the hope that it will be useful,
28  * but WITHOUT ANY WARRANTY; without even the implied warranty of
29  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
30  * GNU General Public License for more details.
31  *
32  * You should have received a copy of the GNU General Public License
33  * along with this program; if not, write to the Free Software
34  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
35  *
36  */
37 
38 #define DRIVER_VERSION	"0.30"
39 
40 #include "config.h"
41 #include "main.h"
42 #include "attribute.h"
43 #include "nut_float.h"
44 #include "nut_stdint.h"
45 
46 /* note: QX_USB/QX_SERIAL set through Makefile */
47 #ifdef QX_USB
48 	#include "libusb.h"
49 	#include "usb-common.h"
50 
51 	#ifdef QX_SERIAL
52 		#define DRIVER_NAME	"Generic Q* USB/Serial driver"
53 	#else
54 		#define	DRIVER_NAME	"Generic Q* USB driver"
55 	#endif	/* QX_SERIAL */
56 #else
57 	#define DRIVER_NAME	"Generic Q* Serial driver"
58 #endif	/* QX_USB */
59 
60 #ifdef QX_SERIAL
61 	#include "serial.h"
62 	#define SER_WAIT_SEC	1	/* 3 seconds for Best UPS */
63 #endif	/* QX_SERIAL */
64 
65 #include "nutdrv_qx.h"
66 
67 /* == Subdrivers == */
68 /* Include all known subdrivers */
69 #include "nutdrv_qx_bestups.h"
70 #include "nutdrv_qx_hunnox.h"
71 #include "nutdrv_qx_mecer.h"
72 #include "nutdrv_qx_megatec.h"
73 #include "nutdrv_qx_megatec-old.h"
74 #include "nutdrv_qx_mustek.h"
75 #include "nutdrv_qx_q1.h"
76 #include "nutdrv_qx_voltronic.h"
77 #include "nutdrv_qx_voltronic-qs.h"
78 #include "nutdrv_qx_voltronic-qs-hex.h"
79 #include "nutdrv_qx_zinto.h"
80 #include "nutdrv_qx_masterguard.h"
81 
82 /* Reference list of available subdrivers */
83 static subdriver_t	*subdriver_list[] = {
84 	&voltronic_subdriver,
85 	&voltronic_qs_subdriver,
86 	&voltronic_qs_hex_subdriver,
87 	&mustek_subdriver,
88 	&megatec_old_subdriver,
89 	&bestups_subdriver,
90 	&mecer_subdriver,
91 	&megatec_subdriver,
92 	&zinto_subdriver,
93 	&masterguard_subdriver,
94 	&hunnox_subdriver,
95 	/* Fallback Q1 subdriver */
96 	&q1_subdriver,
97 	NULL
98 };
99 
100 
101 /* == Driver description structure == */
102 upsdrv_info_t	upsdrv_info = {
103 	DRIVER_NAME,
104 	DRIVER_VERSION,
105 	"Daniele Pezzini <hyouko@gmail.com>" \
106 	"Arnaud Quette <arnaud.quette@gmail.com>" \
107 	"John Stamp <kinsayder@hotmail.com>" \
108 	"Peter Selinger <selinger@users.sourceforge.net>" \
109 	"Arjen de Korte <adkorte-guest@alioth.debian.org>" \
110 	"Edgar Fuß <ef@math.uni-bonn.de>",
111 	DRV_BETA,
112 #ifdef QX_USB
113 	{ &comm_upsdrv_info, NULL }
114 #else
115 	{ NULL }
116 #endif	/* QX_USB */
117 };
118 
119 
120 /* == Data walk modes == */
121 typedef enum {
122 	QX_WALKMODE_INIT = 0,
123 	QX_WALKMODE_QUICK_UPDATE,
124 	QX_WALKMODE_FULL_UPDATE
125 } walkmode_t;
126 
127 
128 /* == Global vars == */
129 /* Pointer to the active subdriver object (changed in subdriver_matcher() function) */
130 static subdriver_t	*subdriver = NULL;
131 
132 static long	pollfreq = DEFAULT_POLLFREQ;
133 static unsigned int	ups_status = 0;
134 static bool_t	data_has_changed = FALSE;	/* for SEMI_STATIC data polling */
135 
136 static time_t	lastpoll;	/* Timestamp the last polling */
137 
138 #if defined(QX_USB) && !defined(TESTING)
139 static int	hunnox_step = 0;
140 #endif	/* QX_USB && !TESTING */
141 
142 #if defined(QX_USB) && defined(QX_SERIAL)
143 static int	is_usb = 0;	/* Whether the device is connected through USB (1) or serial (0) */
144 #endif	/* QX_USB && QX_SERIAL */
145 
146 static struct {
147 	char	command[SMALLBUF];	/* Command sent to the UPS to get answer/to execute an instant command */
148 	char	answer[SMALLBUF];	/* Answer from the UPS, filled at runtime */
149 } previous_item = { "", "" };	/* Hold the values of the item processed just before the actual one */
150 
151 
152 /* == Support functions == */
153 static int	subdriver_matcher(void);
154 static ssize_t	qx_command(const char *cmd, char *buf, size_t buflen);
155 static int	qx_process_answer(item_t *item, const size_t len); /* returns just 0 or -1 */
156 static bool_t	qx_ups_walk(walkmode_t mode);
157 static void	ups_status_set(void);
158 static void	ups_alarm_set(void);
159 static void	qx_set_var(item_t *item);
160 
161 
162 /* == Struct & data for status processing == */
163 typedef struct {
164 	const char	*status_str;			/* UPS status string */
165 	const unsigned int	status_mask;	/* UPS status mask */
166 } status_lkp_t;
167 
168 static status_lkp_t	status_info[] = {
169 	/* Map status strings to bit masks */
170 	{ "OL", STATUS(OL) },
171 	{ "LB", STATUS(LB) },
172 	{ "RB", STATUS(RB) },
173 	{ "CHRG", STATUS(CHRG) },
174 	{ "DISCHRG", STATUS(DISCHRG) },
175 	{ "BYPASS", STATUS(BYPASS) },
176 	{ "CAL", STATUS(CAL) },
177 	{ "OFF", STATUS(OFF) },
178 	{ "OVER", STATUS(OVER) },
179 	{ "TRIM", STATUS(TRIM) },
180 	{ "BOOST", STATUS(BOOST) },
181 	{ "FSD", STATUS(FSD) },
182 	{ NULL, 0 },
183 };
184 
185 
186 /* == battery.{charge,runtime} guesstimation == */
187 /* Support functions */
188 static int	qx_battery(void);
189 static int	qx_load(void);
190 static void	qx_initbattery(void);
191 
192 /* Battery data */
193 static struct {
194 	double	packs;	/* Battery voltage multiplier */
195 	struct {
196 		double	act;	/* Actual runtime on battery */
197 		double	nom;	/* Nominal runtime on battery (full load) */
198 		double	est;	/* Estimated runtime remaining (full load) */
199 		double	exp;	/* Load exponent */
200 	} runt;
201 	struct {
202 		double	act;	/* Actual battery voltage */
203 		double	high;	/* Battery float voltage */
204 		double	nom;	/* Nominal battery voltage */
205 		double	low;	/* Battery low voltage */
206 	} volt;
207 	struct {
208 		double	act;	/* Actual battery charge */
209 		long	time;	/* Recharge time from empty to full */
210 	} chrg;
211 } batt = { 1, { -1, -1, 0, 0 }, { -1, -1, -1, -1 }, { -1, 43200 } };
212 
213 /* Load data */
214 static struct {
215 	double	act;	/* Actual load (reported by the UPS) */
216 	double	low;	/* Idle load */
217 	double	eff;	/* Effective load */
218 } load = { 0, 0.1, 1 };
219 
220 static time_t	battery_lastpoll = 0;
221 
222 /* Fill batt.volt.act and guesstimate the battery charge if it isn't already available. */
qx_battery(void)223 static int	qx_battery(void)
224 {
225 	const char	*val = dstate_getinfo("battery.voltage");
226 
227 	if (!val) {
228 		upsdebugx(2, "%s: unable to get battery.voltage", __func__);
229 		return -1;
230 	}
231 
232 	batt.volt.act = batt.packs * strtod(val, NULL);
233 
234 	if (d_equal(batt.chrg.act, -1) && batt.volt.low > 0 && batt.volt.high > batt.volt.low) {
235 
236 		batt.chrg.act = 100 * (batt.volt.act - batt.volt.low) / (batt.volt.high - batt.volt.low);
237 
238 		if (batt.chrg.act < 0) {
239 			batt.chrg.act = 0;
240 		}
241 
242 		if (batt.chrg.act > 100) {
243 			batt.chrg.act = 100;
244 		}
245 
246 		dstate_setinfo("battery.charge", "%.0f", batt.chrg.act);
247 
248 	}
249 
250 	return 0;
251 }
252 
253 /* Load for battery.{charge,runtime} from runtimecal */
qx_load(void)254 static int	qx_load(void)
255 {
256 	const char	*val = dstate_getinfo("ups.load");
257 
258 	if (!val) {
259 		upsdebugx(2, "%s: unable to get ups.load", __func__);
260 		return -1;
261 	}
262 
263 	load.act = strtod(val, NULL);
264 
265 	load.eff = pow(load.act / 100, batt.runt.exp);
266 
267 	if (load.eff < load.low) {
268 		load.eff = load.low;
269 	}
270 
271 	return 0;
272 }
273 
274 /* Guesstimation: init */
qx_initbattery(void)275 static void	qx_initbattery(void)
276 {
277 	if (!dstate_getinfo("battery.charge") || !dstate_getinfo("battery.runtime")) {
278 
279 		const char	*val;
280 
281 		val = dstate_getinfo("battery.voltage.high");
282 		if (val) {
283 			batt.volt.high = strtod(val, NULL);
284 		}
285 
286 		val = dstate_getinfo("battery.voltage.low");
287 		if (val) {
288 			batt.volt.low = strtod(val, NULL);
289 		}
290 
291 		val = dstate_getinfo("battery.voltage.nominal");
292 		if (val) {
293 			batt.volt.nom = strtod(val, NULL);
294 		}
295 
296 		/* If no values are available for both battery.voltage.{low,high} either from the UPS or provided by the user in ups.conf, try to guesstimate them, but announce it! */
297 		if ( (!d_equal(batt.volt.nom, -1)) && (d_equal(batt.volt.low, -1) || d_equal(batt.volt.high, -1))) {
298 
299 			upslogx(LOG_INFO, "No values for battery high/low voltages");
300 
301 			/* Basic formula, which should cover most cases */
302 			batt.volt.low = 104 * batt.volt.nom / 120;
303 			batt.volt.high = 130 * batt.volt.nom / 120;
304 
305 			/* Publish these data too */
306 			dstate_setinfo("battery.voltage.low", "%.2f", batt.volt.low);
307 			dstate_setinfo("battery.voltage.high", "%.2f", batt.volt.high);
308 
309 			upslogx(LOG_INFO, "Using 'guesstimation' (low: %f, high: %f)!", batt.volt.low, batt.volt.high);
310 
311 		}
312 
313 		val = dstate_getinfo("battery.packs");
314 		if (val && (strspn(val, "0123456789 .") == strlen(val))) {
315 			batt.packs = strtod(val, NULL);
316 		} else {
317 
318 			/* qx_battery -> batt.volt.act */
319 			if (!qx_battery() && (!d_equal(batt.volt.nom, -1))) {
320 
321 				const double	packs[] = { 120, 100, 80, 60, 48, 36, 30, 24, 18, 12, 8, 6, 4, 3, 2, 1, 0.5, -1 };
322 				int		i;
323 
324 				/* The battery voltage will quickly return to at least the nominal value after discharging them.
325 				 * For overlapping battery.voltage.low/high ranges therefor choose the one with the highest multiplier. */
326 				for (i = 0; packs[i] > 0; i++) {
327 
328 					if (packs[i] * batt.volt.act > 1.2 * batt.volt.nom) {
329 						continue;
330 					}
331 
332 					if (packs[i] * batt.volt.act < 0.8 * batt.volt.nom) {
333 						upslogx(LOG_INFO, "Can't autodetect number of battery packs [%.0f/%.2f]", batt.volt.nom, batt.volt.act);
334 						break;
335 					}
336 
337 					batt.packs = packs[i];
338 					break;
339 
340 				}
341 
342 			} else {
343 				upslogx(LOG_INFO, "Can't autodetect number of battery packs [%.0f/%.2f]", batt.volt.nom, batt.volt.act);
344 			}
345 
346 		}
347 
348 		/* Update batt.{chrg,volt}.act */
349 		qx_battery();
350 
351 		val = getval("runtimecal");
352 		if (val) {
353 
354 			double	rh, lh, rl, ll;
355 
356 			time(&battery_lastpoll);
357 
358 			if (sscanf(val, "%lf,%lf,%lf,%lf", &rh, &lh, &rl, &ll) < 4) {
359 				fatalx(EXIT_FAILURE, "Insufficient parameters for runtimecal");
360 			}
361 
362 			if ((rl < rh) || (rh <= 0)) {
363 				fatalx(EXIT_FAILURE, "Parameter out of range (runtime)");
364 			}
365 
366 			if ((lh > 100) || (ll > lh) || (ll <= 0)) {
367 				fatalx(EXIT_FAILURE, "Parameter out of range (load)");
368 			}
369 
370 			batt.runt.exp = log(rl / rh) / log(lh / ll);
371 			upsdebugx(2, "%s: battery runtime exponent: %.3f", __func__, batt.runt.exp);
372 
373 			batt.runt.nom = rh * pow(lh / 100, batt.runt.exp);
374 			upsdebugx(2, "%s: battery runtime nominal: %.1f", __func__, batt.runt.nom);
375 
376 		} else {
377 
378 			upslogx(LOG_INFO, "Battery runtime will not be calculated (runtimecal not set)");
379 			return;
380 
381 		}
382 
383 		val = dstate_getinfo("battery.charge");
384 		if (!val && (!d_equal(batt.volt.nom, -1))) {
385 			batt.volt.low = batt.volt.nom;
386 			batt.volt.high = 1.15 * batt.volt.nom;
387 
388 			if (qx_battery())
389 				fatalx(EXIT_FAILURE, "Initial battery charge undetermined");
390 
391 			val = dstate_getinfo("battery.charge");
392 		}
393 
394 		if (val) {
395 			batt.runt.est = batt.runt.nom * strtod(val, NULL) / 100;
396 			upsdebugx(2, "%s: battery runtime estimate: %.1f", __func__, batt.runt.est);
397 		} else {
398 			fatalx(EXIT_FAILURE, "Initial battery charge undetermined");
399 		}
400 
401 		val = getval("chargetime");
402 		if (val) {
403 			batt.chrg.time = strtol(val, NULL, 10);
404 
405 			if (batt.chrg.time <= 0) {
406 				fatalx(EXIT_FAILURE, "Charge time out of range [1..s]");
407 			}
408 
409 			upsdebugx(2, "%s: battery charge time: %ld", __func__, batt.chrg.time);
410 		} else {
411 			upslogx(LOG_INFO, "No charge time specified, using built in default [%ld seconds]", batt.chrg.time);
412 		}
413 
414 		val = getval("idleload");
415 		if (val) {
416 			load.low = strtod(val, NULL) / 100;
417 
418 			if ((load.low <= 0) || (load.low > 1)) {
419 				fatalx(EXIT_FAILURE, "Idle load out of range [0..100]");
420 			}
421 
422 			upsdebugx(2, "%s: minimum load used (idle): %.3f", __func__, load.low);
423 		} else {
424 			upslogx(LOG_INFO, "No idle load specified, using built in default [%.1f %%]", 100 * load.low);
425 		}
426 	}
427 }
428 
429 
430 /* == USB communication subdrivers == */
431 #if defined(QX_USB) && !defined(TESTING)
432 static usb_communication_subdriver_t	*usb = &usb_subdriver;
433 static usb_dev_handle			*udev = NULL;
434 static USBDevice_t			usbdevice;
435 static USBDeviceMatcher_t		*reopen_matcher = NULL;
436 static USBDeviceMatcher_t		*regex_matcher = NULL;
437 static int				langid_fix = -1;
438 
439 static int	(*subdriver_command)(const char *cmd, char *buf, size_t buflen) = NULL;
440 
441 /* Cypress communication subdriver */
cypress_command(const char * cmd,char * buf,size_t buflen)442 static int	cypress_command(const char *cmd, char *buf, size_t buflen)
443 {
444 	char	tmp[SMALLBUF];
445 	int	ret = 0;
446 	size_t	i;
447 
448 	if (buflen > INT_MAX) {
449 		upsdebugx(3, "%s: requested to read too much (%zu), reducing buflen to (INT_MAX-1)",
450 			__func__, buflen);
451 		buflen = (INT_MAX - 1);
452 	}
453 
454 	/* Send command */
455 	memset(tmp, 0, sizeof(tmp));
456 	snprintf(tmp, sizeof(tmp), "%s", cmd);
457 
458 	for (i = 0; i < strlen(tmp); i += (size_t)ret) {
459 
460 		/* Write data in 8-byte chunks */
461 		/* ret = usb->set_report(udev, 0, (unsigned char *)&tmp[i], 8); */
462 		ret = usb_control_msg(udev, USB_ENDPOINT_OUT + USB_TYPE_CLASS + USB_RECIP_INTERFACE, 0x09, 0x200, 0, &tmp[i], 8, 5000);
463 
464 		if (ret <= 0) {
465 			upsdebugx(3, "send: %s (%d)", ret ? usb_strerror() : "timeout", ret);
466 			return ret;
467 		}
468 
469 	}
470 
471 	upsdebugx(3, "send: %.*s", (int)strcspn(tmp, "\r"), tmp);
472 
473 	/* Read reply */
474 	memset(buf, 0, buflen);
475 
476 	for (i = 0; (i <= buflen-8) && (memchr(buf, '\r', buflen) == NULL); i += (size_t)ret) {
477 
478 		/* Read data in 8-byte chunks */
479 		/* ret = usb->get_interrupt(udev, (unsigned char *)&buf[i], 8, 1000); */
480 		ret = usb_interrupt_read(udev, 0x81, &buf[i], 8, 1000);
481 
482 		/* Any errors here mean that we are unable to read a reply (which will happen after successfully writing a command to the UPS) */
483 		if (ret <= 0) {
484 			upsdebugx(3, "read: %s (%d)", ret ? usb_strerror() : "timeout", ret);
485 			return ret;
486 		}
487 
488 		snprintf(tmp, sizeof(tmp), "read [% 3d]", (int)i);
489 		upsdebug_hex(5, tmp, &buf[i], (size_t)ret);
490 
491 	}
492 
493 	upsdebugx(3, "read: %.*s", (int)strcspn(buf, "\r"), buf);
494 
495 	if (i > INT_MAX) {
496 		upsdebugx(3, "%s: read too much (%zu)", __func__, i);
497 		return -1;
498 	}
499 	return (int)i;
500 }
501 
502 /* SGS communication subdriver */
sgs_command(const char * cmd,char * buf,size_t buflen)503 static int	sgs_command(const char *cmd, char *buf, size_t buflen)
504 {
505 	char	tmp[SMALLBUF];
506 	int	ret = 0;
507 	size_t  cmdlen, i;
508 
509 	if (buflen > INT_MAX) {
510 		upsdebugx(3, "%s: requested to read too much (%zu), reducing buflen to (INT_MAX-1)",
511 			__func__, buflen);
512 		buflen = (INT_MAX - 1);
513 	}
514 
515 	/* Send command */
516 	cmdlen = strlen(cmd);
517 
518 	for (i = 0; i < cmdlen; i += (size_t)ret) {
519 
520 		memset(tmp, 0, sizeof(tmp));
521 
522 		/* i and cmdlen are size_t nominally, but diff is not large */
523 		ret = (int)((cmdlen - i) < 7 ? (cmdlen - i) : 7);
524 
525 		/* ret is between 0 and 7 */
526 		tmp[0] = (char)ret;
527 		memcpy(&tmp[1], &cmd[i], (unsigned char)ret);
528 
529 		/* Write data in 8-byte chunks */
530 		ret = usb_control_msg(udev, USB_ENDPOINT_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE, 0x09, 0x200, 0, tmp, 8, 5000);
531 
532 		if (ret <= 0) {
533 			upsdebugx(3, "send: %s (%d)", ret ? usb_strerror() : "timeout", ret);
534 			return ret;
535 		}
536 
537 		ret--;
538 
539 	}
540 
541 	upsdebugx(3, "send: %.*s", (int)strcspn(cmd, "\r"), cmd);
542 
543 	/* Read reply */
544 	memset(buf, 0, buflen);
545 
546 	for (i = 0; i <= buflen - 8; i += (size_t)ret) {
547 
548 		memset(tmp, 0, sizeof(tmp));
549 
550 		/* Read data in 8-byte chunks */
551 		ret = usb_interrupt_read(udev, 0x81, tmp, 8, 1000);
552 
553 		/* No error!!! */
554 		/* TODO: Macro code */
555 		if (ret == -110)
556 			break;
557 
558 		/* Any errors here mean that we are unable to read a reply (which will happen after successfully writing a command to the UPS) */
559 		if (ret <= 0) {
560 			upsdebugx(3, "read: %s (%d)", ret ? usb_strerror() : "timeout", ret);
561 			return ret;
562 		}
563 
564 		/* Every call to read returns 8 bytes
565 		 * -> actually returned bytes: */
566 		ret = tmp[0] <= 7 ? tmp[0] : 7;
567 
568 		if (ret > 0)
569 			memcpy(&buf[i], &tmp[1], (unsigned char)ret);
570 
571 		snprintf(tmp, sizeof(tmp), "read [% 3d]", (int)i);
572 		upsdebug_hex(5, tmp, &buf[i], (size_t)ret);
573 
574 	}
575 
576 	upsdebugx(3, "read: %.*s", (int)strcspn(buf, "\r"), buf);
577 
578 	if (i > INT_MAX) {
579 		upsdebugx(3, "%s: read too much (%zu)", __func__, i);
580 		return -1;
581 	}
582 	return (int)i;
583 }
584 
585 /* Phoenix communication subdriver */
phoenix_command(const char * cmd,char * buf,size_t buflen)586 static int	phoenix_command(const char *cmd, char *buf, size_t buflen)
587 {
588 	char	tmp[SMALLBUF];
589 	int	ret;
590 	size_t	i;
591 
592 	if (buflen > INT_MAX) {
593 		upsdebugx(3, "%s: requested to read too much (%zu), reducing buflen to (INT_MAX-1)",
594 			__func__, buflen);
595 		buflen = (INT_MAX - 1);
596 	}
597 
598 	for (i = 0; i < 8; i++) {
599 
600 		/* Read data in 8-byte chunks */
601 		/* ret = usb->get_interrupt(udev, (unsigned char *)tmp, 8, 1000); */
602 		ret = usb_interrupt_read(udev, 0x81, tmp, 8, 1000);
603 
604 		/* This USB to serial implementation is crappy.
605 		 * In order to read correct replies we need to flush the output buffers of the converter until we get no more data (ie, it times out). */
606 		switch (ret)
607 		{
608 		case -EPIPE:		/* Broken pipe */
609 			usb_clear_halt(udev, 0x81);
610 		case -ETIMEDOUT:	/* Connection timed out */
611 			break;
612 		}
613 
614 		if (ret < 0) {
615 			upsdebugx(3, "flush: %s (%d)", usb_strerror(), ret);
616 			break;
617 		}
618 
619 		upsdebug_hex(4, "dump", tmp, (size_t)ret);
620 
621 	}
622 
623 	/* Send command */
624 	memset(tmp, 0, sizeof(tmp));
625 	snprintf(tmp, sizeof(tmp), "%s", cmd);
626 
627 	for (i = 0; i < strlen(tmp); i += (size_t)ret) {
628 
629 		/* Write data in 8-byte chunks */
630 		/* ret = usb->set_report(udev, 0, (unsigned char *)&tmp[i], 8); */
631 		ret = usb_control_msg(udev,
632 			USB_ENDPOINT_OUT + USB_TYPE_CLASS + USB_RECIP_INTERFACE,
633 			0x09, 0x200, 0, &tmp[i], 8, 1000);
634 
635 		if (ret <= 0) {
636 			upsdebugx(3, "send: %s (%d)",
637 				ret ? usb_strerror() : "timeout", ret);
638 			return ret;
639 		}
640 
641 	}
642 
643 	upsdebugx(3, "send: %.*s", (int)strcspn(tmp, "\r"), tmp);
644 
645 	/* Read reply */
646 	memset(buf, 0, buflen);
647 
648 	for (i = 0; (i <= buflen-8) && (memchr(buf, '\r', buflen) == NULL); i += (size_t)ret) {
649 
650 		/* Read data in 8-byte chunks */
651 		/* ret = usb->get_interrupt(udev, (unsigned char *)&buf[i], 8, 1000); */
652 		ret = usb_interrupt_read(udev, 0x81, &buf[i], 8, 1000);
653 
654 		/* Any errors here mean that we are unable to read a reply
655 		 * (which will happen after successfully writing a command
656 		 * to the UPS) */
657 		if (ret <= 0) {
658 			upsdebugx(3, "read: %s (%d)", ret ? usb_strerror() : "timeout", ret);
659 			return ret;
660 		}
661 
662 		snprintf(tmp, sizeof(tmp), "read [% 3d]", (int)i);
663 		upsdebug_hex(5, tmp, &buf[i], (size_t)ret);
664 
665 	}
666 
667 	upsdebugx(3, "read: %.*s", (int)strcspn(buf, "\r"), buf);
668 
669 	if (i > INT_MAX) {
670 		upsdebugx(3, "%s: read too much (%zu)", __func__, i);
671 		return -1;
672 	}
673 	return (int)i;
674 }
675 
676 /* Ippon communication subdriver */
ippon_command(const char * cmd,char * buf,size_t buflen)677 static int	ippon_command(const char *cmd, char *buf, size_t buflen)
678 {
679 	char	tmp[64];
680 	int	ret;
681 	size_t	i, len;
682 
683 	if (buflen > INT_MAX) {
684 		upsdebugx(3, "%s: requested to read too much (%zu), reducing buflen to (INT_MAX-1)",
685 			__func__, buflen);
686 		buflen = (INT_MAX - 1);
687 	}
688 
689 	/* Send command */
690 	snprintf(tmp, sizeof(tmp), "%s", cmd);
691 
692 	for (i = 0; i < strlen(tmp); i += (size_t)ret) {
693 
694 		/* Write data in 8-byte chunks */
695 		ret = usb_control_msg(udev,
696 			USB_ENDPOINT_OUT + USB_TYPE_CLASS + USB_RECIP_INTERFACE,
697 			0x09, 0x2, 0, &tmp[i], 8, 1000);
698 
699 		if (ret <= 0) {
700 			upsdebugx(3, "send: %s (%d)",
701 				(ret != -ETIMEDOUT) ? usb_strerror() : "Connection timed out",
702 				ret);
703 			return ret;
704 		}
705 
706 	}
707 
708 	upsdebugx(3, "send: %.*s", (int)strcspn(tmp, "\r"), tmp);
709 
710 	/* Read all 64 bytes of the reply in one large chunk */
711 	ret = usb_interrupt_read(udev, 0x81, tmp, sizeof(tmp), 1000);
712 
713 	/* Any errors here mean that we are unable to read a reply
714 	 * (which will happen after successfully writing a command
715 	 * to the UPS) */
716 	if (ret <= 0) {
717 		upsdebugx(3, "read: %s (%d)",
718 			(ret != -ETIMEDOUT) ? usb_strerror() : "Connection timed out",
719 			ret);
720 		return ret;
721 	}
722 
723 	/* As Ippon will always return 64 bytes in response,
724 	 * we have to calculate and return length of actual
725 	 * response data here.
726 	 * Empty response will look like 0x00 0x0D, otherwise
727 	 * it will be data string terminated by 0x0D. */
728 
729 	for (i = 0, len = 0; i < (size_t)ret; i++) {
730 
731 		if (tmp[i] != '\r')
732 			continue;
733 
734 		len = ++i;
735 		break;
736 
737 	}
738 
739 	/* Just in case there wasn't any '\r', fallback to string length, if any */
740 	if (!len)
741 		len = strlen(tmp);
742 
743 	upsdebug_hex(5, "read", tmp, (size_t)len);
744 	upsdebugx(3, "read: %.*s", (int)strcspn(tmp, "\r"), tmp);
745 
746 	len = len < buflen ? len : buflen - 1;
747 
748 	memset(buf, 0, buflen);
749 	memcpy(buf, tmp, len);
750 
751 	if (len > INT_MAX) {
752 		upsdebugx(3, "%s: read too much (%zu)", __func__, len);
753 		return -1;
754 	}
755 	return (int)len;
756 }
757 
hunnox_protocol(int asking_for)758 static int 	hunnox_protocol(int asking_for)
759 {
760 	char	buf[1030];
761 
762 	int langid_fix_local = 0x0409;
763 
764 	if (langid_fix != -1) {
765 		langid_fix_local = langid_fix;
766 	}
767 
768 	switch (hunnox_step) {
769 		case 0:
770 			upsdebugx(3, "asking for: %02X", 0x00);
771 			usb_get_string(udev, 0x00, langid_fix_local, buf, 1026);
772 			usb_get_string(udev, 0x00, langid_fix_local, buf, 1026);
773 			usb_get_string(udev, 0x01, langid_fix_local, buf, 1026);
774 			usleep(10000);
775 			break;
776 		case 1:
777 			if (asking_for != 0x0d) {
778 				upsdebugx(3, "asking for: %02X", 0x0d);
779 				usb_get_string(udev, 0x0d, langid_fix_local, buf, 102);
780 			}
781 			break;
782 		case 2:
783 			if (asking_for != 0x03) {
784 				upsdebugx(3, "asking for: %02X", 0x03);
785 				usb_get_string(udev, 0x03, langid_fix_local, buf, 102);
786 			}
787 			break;
788 		case 3:
789 			if (asking_for != 0x0c) {
790 				upsdebugx(3, "asking for: %02X", 0x0c);
791 				usb_get_string(udev, 0x0c, langid_fix_local, buf, 102);
792 			}
793 			break;
794 		default:
795 			hunnox_step = 0;
796 	}
797 	hunnox_step++;
798 	if (hunnox_step > 3) {
799 		hunnox_step = 1;
800 	}
801 
802 	return 0;
803 }
804 
805 /* Krauler communication subdriver */
krauler_command(const char * cmd,char * buf,size_t buflen)806 static int	krauler_command(const char *cmd, char *buf, size_t buflen)
807 {
808 	/* Still not implemented:
809 	 * 0x6	T<n>	(don't know how to pass the parameter)
810 	 * 0x68 and 0x69 both cause shutdown after an undefined interval */
811 	const struct {
812 		const char	*str;	/* Megatec command */
813 		const int	index;	/* Krauler string index for this command */
814 		const char	prefix;	/* Character to replace the first byte in reply */
815 	} command[] = {
816 		{ "Q1\r", 0x03, '(' },
817 		{ "F\r", 0x0d, '#' },
818 		{ "I\r", 0x0c, '#' },
819 		{ "T\r", 0x04, '\r' },
820 		{ "TL\r", 0x05, '\r' },
821 		{ "Q\r", 0x07, '\r' },
822 		{ "C\r", 0x0b, '\r' },
823 		{ "CT\r", 0x0b, '\r' },
824 		{ NULL, 0, '\0' }
825 	};
826 
827 	int	i;
828 
829 	upsdebugx(3, "send: %.*s", (int)strcspn(cmd, "\r"), cmd);
830 
831 	if (buflen > INT_MAX) {
832 		upsdebugx(3, "%s: requested to read too much (%zu), reducing buflen to (INT_MAX-1)",
833 			__func__, buflen);
834 		buflen = (INT_MAX - 1);
835 	}
836 
837 	for (i = 0; command[i].str; i++) {
838 
839 		int	retry;
840 
841 		if (strcmp(cmd, command[i].str)) {
842 			continue;
843 		}
844 
845 		for (retry = 0; retry < 10; retry++) {
846 
847 			int	ret;
848 
849 			if (langid_fix != -1) {
850 				/* Apply langid_fix value */
851 				ret = usb_get_string(udev, command[i].index, langid_fix, buf, buflen);
852 			} else {
853 				ret = usb_get_string_simple(udev, command[i].index, buf, buflen);
854 			}
855 
856 			if (ret <= 0) {
857 				upsdebugx(3, "read: %s (%d)",
858 					ret ? usb_strerror() : "timeout", ret);
859 				return ret;
860 			}
861 
862 			/* This may serve in the future */
863 			upsdebugx(1, "received %d (%d)", ret, buf[0]);
864 
865 			if (langid_fix != -1) {
866 				/* Limit this check, at least for now */
867 				/* Invalid receive size - message corrupted */
868 				if (ret != buf[0]) {
869 					upsdebugx(1, "size mismatch: %d / %d", ret, buf[0]);
870 					continue;
871 				}
872 
873 				/* Simple unicode -> ASCII inplace conversion
874 				 * FIXME: this code is at least shared with mge-shut/libshut
875 				 * Create a common function? */
876 				unsigned int	di, si, size = (unsigned int)buf[0];
877 				for (di = 0, si = 2; si < size; si += 2) {
878 
879 					if (di >= (buflen - 1))
880 						break;
881 
882 					if (buf[si + 1])	/* high byte */
883 						buf[di++] = '?';
884 					else
885 						buf[di++] = buf[si];
886 
887 				}
888 
889 				/* Note: effective range of di should be unsigned char */
890 				buf[di] = 0;
891 				ret = (int)di;
892 			}
893 
894 			/* "UPS No Ack" has a special meaning */
895 			if (
896 				strcspn(buf, "\r") == 10 &&
897 				!strncasecmp(buf, "UPS No Ack", 10)
898 			) {
899 				upsdebugx(3, "read: %.*s", (int)strcspn(buf, "\r"), buf);
900 				continue;
901 			}
902 
903 			/* Replace the first byte of what we received with the correct one */
904 			buf[0] = command[i].prefix;
905 
906 			upsdebug_hex(5, "read", buf, (size_t)ret);
907 			upsdebugx(3, "read: %.*s", (int)strcspn(buf, "\r"), buf);
908 
909 			return ret;
910 
911 		}
912 
913 		return 0;
914 
915 	}
916 
917 	/* Echo the unknown command back */
918 	upsdebugx(3, "read: %.*s", (int)strcspn(cmd, "\r"), cmd);
919 	return snprintf(buf, buflen, "%s", cmd);
920 }
921 
922 /* Fabula communication subdriver */
fabula_command(const char * cmd,char * buf,size_t buflen)923 static int	fabula_command(const char *cmd, char *buf, size_t buflen)
924 {
925 	const struct {
926 		const char	*str;	/* Megatec command */
927 		const int	index;	/* Fabula string index for this command */
928 	} commands[] = {
929 		{ "Q1\r",	0x03, },	/* Status */
930 		{ "F\r",	0x0d, },	/* Ratings */
931 		{ "I\r",	0x0c, },	/* Vendor infos */
932 		{ "Q\r",	0x07, },	/* Beeper toggle */
933 		{ "C\r",	0x0a, },	/* Cancel shutdown/Load on [0x(0..F)A]*/
934 		{ NULL, 0 }
935 	};
936 	int	i, ret, index = 0;
937 
938 	upsdebugx(3, "send: %.*s", (int)strcspn(cmd, "\r"), cmd);
939 
940 	if (buflen > INT_MAX) {
941 		upsdebugx(3, "%s: requested to read too much (%zu), reducing buflen to (INT_MAX-1)",
942 			__func__, buflen);
943 		buflen = (INT_MAX - 1);
944 	}
945 
946 	for (i = 0; commands[i].str; i++) {
947 
948 		if (strcmp(cmd, commands[i].str))
949 			continue;
950 
951 		index = commands[i].index;
952 		break;
953 
954 	}
955 
956 	if (!index) {
957 
958 		int	val2 = -1;
959 		double	val1 = -1;
960 
961 		/* Shutdowns */
962 		if (
963 			sscanf(cmd, "S%lfR%d\r", &val1, &val2) == 2 ||
964 			sscanf(cmd, "S%lf\r", &val1) == 1
965 		) {
966 
967 			double	delay;
968 
969 			/* 0x(1+)0 -> shutdown.stayoff (SnR0000)
970 			 * 0x(1+)8 -> shutdown.return (Sn[Rm], m != 0) [delay before restart is always 10 seconds]
971 			 * +0x10 (16dec) = next megatec delay (min .5 = hex 0x1*; max 10 = hex 0xF*) -> n < 1 ? -> n += .1; n >= 1 ? -> n += 1 */
972 
973 			/* delay: [.5..10] (-> seconds: [30..600]) */
974 			delay = val1 < .5 ? .5 : val1 > 10 ? 10 : val1;
975 
976 			if (delay < 1)
977 				index = 16 + round((delay - .5) * 10) * 16;
978 			else
979 				index = 96 + (delay - 1) * 16;
980 
981 			/* shutdown.return (Sn[Rm], m != 0) */
982 			if (val2)
983 				index += 8;
984 
985 		/* Unknown commands */
986 		} else {
987 
988 			/* Echo the unknown command back */
989 			upsdebugx(3, "read: %.*s", (int)strcspn(cmd, "\r"), cmd);
990 			return snprintf(buf, buflen, "%s", cmd);
991 
992 		}
993 
994 	}
995 
996 	upsdebugx(4, "command index: 0x%02x", index);
997 
998 	/* Send command/Read reply */
999 	ret = usb_get_string_simple(udev, index, buf, buflen);
1000 
1001 	if (ret <= 0) {
1002 		upsdebugx(3, "read: %s (%d)", ret ? usb_strerror() : "timeout", ret);
1003 		return ret;
1004 	}
1005 
1006 	upsdebug_hex(5, "read", buf, (size_t)ret);
1007 	upsdebugx(3, "read: %.*s", (int)strcspn(buf, "\r"), buf);
1008 
1009 	/* The UPS always replies "UPS No Ack" when a supported command is issued (either if it fails or if it succeeds).. */
1010 	if (
1011 		strcspn(buf, "\r") == 10 &&
1012 		!strncasecmp(buf, "UPS No Ack", 10)
1013 	) {
1014 		/* ..because of that, always return 0 (with buf empty, as if it was a timeout): queries will see it as a failure, instant commands ('megatec' protocol) as a success */
1015 		memset(buf, 0, buflen);
1016 		return 0;
1017 	}
1018 
1019 	return ret;
1020 }
1021 
1022 /* Hunnox communication subdriver, based on Fabula code above so repeats
1023  * much of it currently. Possible future optimization is to refactor shared
1024  * code into new routines to be called from both (or more) methods.*/
hunnox_command(const char * cmd,char * buf,size_t buflen)1025 static int	hunnox_command(const char *cmd, char *buf, size_t buflen)
1026 {
1027 	/* The hunnox_patch was an argument in initial implementation of PR #638
1028 	 * which added "hunnox" support; keeping it fixed here helps to visibly
1029 	 * track the modifications compared to original fabula_command() e.g. to
1030 	 * facilitate refactoring commented above, in the future.
1031 	 */
1032 /*	char hunnox_patch = 1; */
1033 	const struct {
1034 		const char	*str;	/* Megatec command */
1035 		const int	index;	/* Fabula string index for this command */
1036 	} commands[] = {
1037 		{ "Q1\r",	0x03, },	/* Status */
1038 		{ "F\r",	0x0d, },	/* Ratings */
1039 		{ "I\r",	0x0c, },	/* Vendor infos */
1040 		{ "Q\r",	0x07, },	/* Beeper toggle */
1041 		{ "C\r",	0x0a, },	/* Cancel shutdown/Load on [0x(0..F)A]*/
1042 		{ NULL, 0 }
1043 	};
1044 	int	i, ret, index = 0;
1045 
1046 	upsdebugx(3, "send: %.*s", (int)strcspn(cmd, "\r"), cmd);
1047 
1048 	if (buflen > INT_MAX) {
1049 		upsdebugx(3, "%s: requested to read too much (%zu), reducing buflen to (INT_MAX-1)",
1050 			__func__, buflen);
1051 		buflen = (INT_MAX - 1);
1052 	}
1053 
1054 	for (i = 0; commands[i].str; i++) {
1055 
1056 		if (strcmp(cmd, commands[i].str))
1057 			continue;
1058 
1059 		index = commands[i].index;
1060 		break;
1061 
1062 	}
1063 
1064 	if (!index) {
1065 
1066 		int	val2 = -1;
1067 		double	val1 = -1;
1068 
1069 		/* Shutdowns */
1070 		if (
1071 			sscanf(cmd, "S%lfR%d\r", &val1, &val2) == 2 ||
1072 			sscanf(cmd, "S%lf\r", &val1) == 1
1073 		) {
1074 
1075 			double	delay;
1076 
1077 			/* 0x(1+)0 -> shutdown.stayoff (SnR0000)
1078 			 * 0x(1+)8 -> shutdown.return (Sn[Rm], m != 0) [delay before restart is always 10 seconds]
1079 			 * +0x10 (16dec) = next megatec delay (min .5 = hex 0x1*; max 10 = hex 0xF*) -> n < 1 ? -> n += .1; n >= 1 ? -> n += 1 */
1080 
1081 			/* delay: [.5..10] (-> seconds: [30..600]) */
1082 			delay = val1 < .5 ? .5 : val1 > 10 ? 10 : val1;
1083 
1084 			if (delay < 1)
1085 				index = 16 + round((delay - .5) * 10) * 16;
1086 			else
1087 				index = 96 + (delay - 1) * 16;
1088 
1089 			/* shutdown.return (Sn[Rm], m != 0) */
1090 			if (val2)
1091 				index += 8;
1092 
1093 		/* Unknown commands */
1094 		} else {
1095 
1096 			/* Echo the unknown command back */
1097 			upsdebugx(3, "read: %.*s", (int)strcspn(cmd, "\r"), cmd);
1098 			return snprintf(buf, buflen, "%s", cmd);
1099 
1100 		}
1101 
1102 	}
1103 
1104 	upsdebugx(4, "command index: 0x%02x", index);
1105 
1106 /*	if (hunnox_patch) { */
1107 		// Enable lock-step protocol for Hunnox
1108 		if (hunnox_protocol(index) != 0) {
1109 			return 0;
1110 		}
1111 
1112 		// Seems that if we inform a large buffer, the USB locks.
1113 		// This value was captured from the Windows "official" client.
1114 		// Note this should not be a problem programmatically: it just
1115 		// means that the caller reserved a longer buffer that we need
1116 		// in practice to write a response into.
1117 		if (buflen > 102) {
1118 			buflen = 102;
1119 		}
1120 /*	} */
1121 
1122 	/* Send command/Read reply */
1123 	if (langid_fix != -1) {
1124 		ret = usb_get_string(udev, index, langid_fix, buf, buflen);
1125 	} else {
1126 		ret = usb_get_string_simple(udev, index, buf, buflen);
1127 	}
1128 
1129 	if (ret <= 0) {
1130 		upsdebugx(3, "read: %s (%d)", ret ? usb_strerror() : "timeout", ret);
1131 		return ret;
1132 	}
1133 
1134 /*	if (hunnox_patch) { */
1135 		if (langid_fix != -1) {
1136 			/* Limit this check, at least for now */
1137 			/* Invalid receive size - message corrupted */
1138 			if (ret != buf[0]) {
1139 				upsdebugx(1, "size mismatch: %d / %d", ret, buf[0]);
1140 				return 0;
1141 			}
1142 
1143 			/* Simple unicode -> ASCII inplace conversion
1144 			 * FIXME: this code is at least shared with mge-shut/libshut
1145 			 * Create a common function? */
1146 			unsigned int	di, si, size = (unsigned int)buf[0];
1147 			for (di = 0, si = 2; si < size; si += 2) {
1148 				if (di >= (buflen - 1))
1149 					break;
1150 
1151 				if (buf[si + 1])	/* high byte */
1152 					buf[di++] = '?';
1153 				else
1154 					buf[di++] = buf[si];
1155 			}
1156 
1157 			/* Note: effective range of di should be unsigned char */
1158 			buf[di] = 0;
1159 			ret = (int)di;
1160 		}
1161 /*	} */
1162 
1163 	upsdebug_hex(5, "read", buf, (size_t)ret);
1164 	upsdebugx(3, "read: %.*s", (int)strcspn(buf, "\r"), buf);
1165 
1166 	/* The UPS always replies "UPS No Ack" when a supported command is issued (either if it fails or if it succeeds).. */
1167 	if (
1168 		strcspn(buf, "\r") == 10 &&
1169 		!strncasecmp(buf, "UPS No Ack", 10)
1170 	) {
1171 		/* ..because of that, always return 0 (with buf empty, as if it was a timeout): queries will see it as a failure, instant commands ('megatec' protocol) as a success */
1172 		memset(buf, 0, buflen);
1173 		return 0;
1174 	}
1175 
1176 	return ret;
1177 }
1178 
1179 /* Fuji communication subdriver */
fuji_command(const char * cmd,char * buf,size_t buflen)1180 static int	fuji_command(const char *cmd, char *buf, size_t buflen)
1181 {
1182 	unsigned char	tmp[8];
1183 	char		command[SMALLBUF] = "",
1184 			read[SMALLBUF] = "";
1185 	int		ret, val2;
1186 	unsigned char	answer_len;
1187 	double		val1;
1188 	size_t		i;
1189 	const struct {
1190 		const char	*command;	/* Megatec command */
1191 		const unsigned char	answer_len;	/* Expected length of the answer to the ongoing query */
1192 	} query[] = {
1193 		{ "Q1",	47 },
1194 		{ "F",	22 },
1195 		{ "I",	39 },
1196 		{ NULL, 0 }
1197 	};
1198 
1199 	if (buflen > INT_MAX) {
1200 		upsdebugx(3, "%s: requested to read too much (%zu), reducing buflen to (INT_MAX-1)",
1201 			__func__, buflen);
1202 		buflen = (INT_MAX - 1);
1203 	}
1204 
1205 	/*
1206 	 * Queries (b1..b8) sent (as a 8-bytes interrupt) to the UPS adopt the following scheme:
1207 	 *
1208 	 *	b1:		0x80
1209 	 *	b2:		0x06
1210 	 *	b3:		<LEN>
1211 	 *	b4:		0x03
1212 	 *	b5..bn:		<COMMAND>
1213 	 *	bn+1..b7:	[<PADDING>]
1214 	 *	b8:		<ANSWER_LEN>
1215 	 *
1216 	 * Where:
1217 	 *	<LEN>		Length (in Hex) of the command (without the trailing CR) + 1
1218 	 *	<COMMAND>	Command/query (without the trailing CR)
1219 	 *	[<PADDING>]	0x00 padding to the 7th byte
1220 	 *	<ANSWER_LEN>	Expected length (in Hex) of the answer to the ongoing query (0 when no reply is expected, i.e. commands)
1221 	 *
1222 	 * Replies to queries (commands are followed by action without any reply) are sent from the UPS (in 8-byte chunks) with 0x00 padding after the trailing CR to full 8 bytes.
1223 	 *
1224 	 */
1225 
1226 	/* Send command */
1227 
1228 	/* Remove the CR */
1229 	snprintf(command, sizeof(command), "%.*s", (int)strcspn(cmd, "\r"), cmd);
1230 
1231 	/* Length of the command that will be sent to the UPS can be at most: 8 - 5 (0x80, 0x06, <LEN>, 0x03, <ANSWER_LEN>) = 3.
1232 	 * As a consequence also 'SnRm' commands (shutdown.{return,stayoff} and load.off) are not supported.
1233 	 * So, map all the 'SnRm' shutdown.returns (m != 0) as the corresponding 'Sn' commands, meanwhile ignoring ups.delay.start and making the UPS turn on the load as soon as power is back. */
1234 	if (sscanf(cmd, "S%lfR%d\r", &val1, &val2) == 2 && val2) {
1235 		upsdebugx(4, "%s: trimming '%s' to '%.*s'", __func__, command, 3, command);
1236 		command[3] = 0;
1237 	}
1238 	/* Too long command */
1239 	if (strlen(command) > 3) {
1240 		/* Be 'megatec-y': echo the unsupported command back */
1241 		upsdebugx(3, "%s: unsupported command %s", __func__, command);
1242 		return snprintf(buf, buflen, "%s", cmd);
1243 	}
1244 
1245 	/* Expected length of the answer to the ongoing query (0 when no reply is expected, i.e. commands) */
1246 	answer_len = 0;
1247 	for (i = 0; query[i].command; i++) {
1248 
1249 		if (strcmp(command, query[i].command))
1250 			continue;
1251 
1252 		answer_len = query[i].answer_len;
1253 		break;
1254 
1255 	}
1256 
1257 	memset(tmp, 0, sizeof(tmp));
1258 
1259 	/* 0x80 */
1260 	tmp[0] = 0x80;
1261 	/* 0x06 */
1262 	tmp[1] = 0x06;
1263 	/* <LEN>; per above under 3 */
1264 	tmp[2] = (unsigned char)strlen(command) + 1;
1265 	/* 0x03 */
1266 	tmp[3] = 0x03;
1267 	/* <COMMAND> */
1268 	memcpy(&tmp[4], command, strlen(command));
1269 	/* <ANSWER_LEN> */
1270 	tmp[7] = answer_len;
1271 
1272 	upsdebug_hex(4, "command", (char *)tmp, 8);
1273 
1274 	/* Write data */
1275 	ret = usb_interrupt_write(udev, USB_ENDPOINT_OUT | 2, (char *)tmp, 8, USB_TIMEOUT);
1276 
1277 	if (ret <= 0) {
1278 		upsdebugx(3, "send: %s (%d)", ret ? usb_strerror() : "timeout", ret);
1279 		return ret;
1280 	}
1281 
1282 	upsdebugx(3, "send: %s", command);
1283 
1284 	/* Read reply */
1285 
1286 	memset(buf, 0, buflen);
1287 
1288 	for (i = 0; (i <= buflen - 8) && (memchr(buf, '\r', buflen) == NULL); i += (size_t)ret) {
1289 
1290 		/* Read data in 8-byte chunks */
1291 		ret = usb_interrupt_read(udev, USB_ENDPOINT_IN | 1, &buf[i], 8, 1000);
1292 
1293 		/* Any errors here mean that we are unable to read a reply (which will happen after successfully writing a command to the UPS) */
1294 		if (ret <= 0) {
1295 			upsdebugx(3, "read: %s (%d)", ret ? usb_strerror() : "timeout", ret);
1296 			return ret;
1297 		}
1298 
1299 		snprintf(read, sizeof(read), "read [%3d]", (int)i);
1300 		upsdebug_hex(5, read, &buf[i], (size_t)ret);
1301 
1302 	}
1303 
1304 	upsdebugx(3, "read: %.*s", (int)strcspn(buf, "\r"), buf);
1305 
1306 	/* As Fuji units return the reply in 8-byte chunks always padded to the 8th byte with 0x00, we need to calculate and return the length of the actual response here. */
1307 	return (int)strlen(buf);
1308 }
1309 
1310 /* Phoenixtec (Masterguard) communication subdriver */
phoenixtec_command(const char * cmd,char * buf,size_t buflen)1311 static int	phoenixtec_command(const char *cmd, char *buf, size_t buflen)
1312 {
1313 	int ret;
1314 	char *p, *e = NULL;
1315 	char *l[] = { "T", "TL", "S", "C", "CT", "M", "N", "O", "SRC", "FCLR", "SS", "TUD", "SSN", NULL }; /* commands that don't return an answer */
1316 	char **lp;
1317 	size_t cmdlen = strlen(cmd);
1318 
1319 	if (cmdlen > INT_MAX) {
1320 		upsdebugx(3, "%s: requested command is too long (%zu)",
1321 			__func__, cmdlen);
1322 		return 0;
1323 	}
1324 
1325 	if (buflen > INT_MAX) {
1326 		upsdebugx(3, "%s: requested to read too much (%zu), reducing buflen to (INT_MAX-1)",
1327 			__func__, buflen);
1328 		buflen = (INT_MAX - 1);
1329 	}
1330 
1331 	if ((ret = usb_control_msg(udev,
1332 			USB_ENDPOINT_OUT | USB_TYPE_VENDOR | USB_RECIP_ENDPOINT,
1333 			0x0d, 0, 0, (char *)cmd, (int)cmdlen, 1000)) <= 0
1334 	) {
1335 		upsdebugx(3, "send: %s (%d)", ret ? usb_strerror() : "timeout", ret);
1336 		*buf = '\0';
1337 		return ret;
1338 	}
1339 
1340 	for (lp = l; *lp != NULL; lp++) {
1341 		const char *q;
1342 		int b;
1343 
1344 		p = *lp; q = cmd; b = 1;
1345 		while (*p != '\0') {
1346 			if (*p++ != *q++) {
1347 				b = 0;
1348 				break;
1349 			}
1350 		}
1351 		if (b && *q >= 'A' && *q <= 'Z') b = 0; /* "M" not to match "MSO" */
1352 		if (b) {
1353 			upsdebugx(4, "command %s returns no answer", *lp);
1354 			*buf = '\0';
1355 			return 0;
1356 		}
1357 	}
1358 
1359 	for (p = buf; p < buf + buflen; p += ret) {
1360 		/* buflen constrained to INT_MAX above, so we can cast: */
1361 		if ((ret = usb_interrupt_read(udev,
1362 				USB_ENDPOINT_IN | 1,
1363 				p, (int)(buf + buflen - p), 1000)) <= 0
1364 		) {
1365 			upsdebugx(3, "read: %s (%d)", ret ? usb_strerror() : "timeout", ret);
1366 			*buf = '\0';
1367 			return ret;
1368 		}
1369 		if ((e = memchr(p, '\r', (size_t)ret)) != NULL) break;
1370 	}
1371 	if (e != NULL && ++e < buf + buflen) {
1372 		*e = '\0';
1373 		/* buflen constrained to INT_MAX above, so we can cast: */
1374 		return (int)(e - buf);
1375 	} else {
1376 		upsdebugx(3, "read: buflen %zu too small", buflen);
1377 		*buf = '\0';
1378 		return 0;
1379 	}
1380 }
1381 
1382 /* SNR communication subdriver */
snr_command(const char * cmd,char * buf,size_t buflen)1383 static int	snr_command(const char *cmd, char *buf, size_t buflen)
1384 {
1385 	/*ATTENTION: This subdriver uses short buffer with length 102 byte*/
1386 	const struct {
1387 		const char	*str;	/* Megatec command */
1388 		const int	index;	/* String index for this command */
1389 		const char	prefix;	/* Character to replace the first byte in reply */
1390 	} command[] = {
1391 		{ "Q1\r", 0x03, '(' },
1392 		{ "F\r", 0x0d, '#' },
1393 		{ "I\r", 0x0c, '#' },
1394 		{ NULL, 0, '\0' }
1395 	};
1396 
1397 	int	i;
1398 
1399 	upsdebugx(3, "send: %.*s", (int)strcspn(cmd, "\r"), cmd);
1400 
1401 	if (buflen > INT_MAX) {
1402 		upsdebugx(3, "%s: requested to read too much (%zu), reducing buflen to (INT_MAX-1)",
1403 			__func__, buflen);
1404 		buflen = (INT_MAX - 1);
1405 	}
1406 
1407 	if (buflen < 102) {
1408 		upsdebugx(4, "size of buf less than 102 byte!");
1409 		return 0;
1410 	}
1411 
1412 	for (i = 0; command[i].str; i++) {
1413 
1414 		int	retry;
1415 
1416 		if (strcmp(cmd, command[i].str)) {
1417 			continue;
1418 		}
1419 
1420 		for (retry = 0; retry < 10; retry++) {
1421 
1422 			int	ret;
1423 
1424 			ret = usb_get_string(udev, command[i].index, langid_fix, buf, 102);
1425 
1426 			if (ret <= 0) {
1427 				upsdebugx(3, "read: %s (%d)", ret ? usb_strerror() : "timeout", ret);
1428 				return ret;
1429 			}
1430 
1431 			/* This may serve in the future */
1432 			upsdebugx(1, "received %d (%d)", ret, buf[0]);
1433 
1434 
1435 			if (ret != buf[0]) {
1436 				upsdebugx(1, "size mismatch: %d / %d", ret, buf[0]);
1437 				continue;
1438 			}
1439 
1440 			/* Simple unicode -> ASCII inplace conversion
1441 				* FIXME: this code is at least shared with mge-shut/libshut
1442 				* Create a common function? */
1443 			unsigned int	di, si, size = (unsigned int)buf[0];
1444 			for (di = 0, si = 2; si < size; si += 2) {
1445 
1446 				if (di >= (buflen - 1))
1447 					break;
1448 
1449 				if (buf[si + 1])	/* high byte */
1450 					buf[di++] = '?';
1451 				else
1452 					buf[di++] = buf[si];
1453 
1454 			}
1455 
1456 			/* Note: effective range of di should be unsigned char */
1457 			buf[di] = 0;
1458 			ret = (int)di;
1459 
1460 			/* "UPS No Ack" has a special meaning */
1461 			if (
1462 				strcspn(buf, "\r") == 10 &&
1463 				!strncasecmp(buf, "UPS No Ack", 10)
1464 			) {
1465 				upsdebugx(3, "read: %.*s", (int)strcspn(buf, "\r"), buf);
1466 				continue;
1467 			}
1468 
1469 			/* Replace the first byte of what we received with the correct one */
1470 			buf[0] = command[i].prefix;
1471 
1472 			upsdebug_hex(5, "read", buf, (size_t)ret);
1473 			upsdebugx(3, "read: %.*s", (int)strcspn(buf, "\r"), buf);
1474 
1475 			return ret;
1476 
1477 		}
1478 
1479 		return 0;
1480 
1481 	}
1482 
1483 	/* Echo the unknown command back */
1484 	upsdebugx(3, "read: %.*s", (int)strcspn(cmd, "\r"), cmd);
1485 	return snprintf(buf, buflen, "%s", cmd);
1486 }
1487 
cypress_subdriver(USBDevice_t * device)1488 static void	*cypress_subdriver(USBDevice_t *device)
1489 {
1490 	NUT_UNUSED_VARIABLE(device);
1491 
1492 	subdriver_command = &cypress_command;
1493 	return NULL;
1494 }
1495 
sgs_subdriver(USBDevice_t * device)1496 static void	*sgs_subdriver(USBDevice_t *device)
1497 {
1498 	NUT_UNUSED_VARIABLE(device);
1499 
1500 	subdriver_command = &sgs_command;
1501 	return NULL;
1502 }
1503 
ippon_subdriver(USBDevice_t * device)1504 static void	*ippon_subdriver(USBDevice_t *device)
1505 {
1506 	NUT_UNUSED_VARIABLE(device);
1507 
1508 	subdriver_command = &ippon_command;
1509 	return NULL;
1510 }
1511 
krauler_subdriver(USBDevice_t * device)1512 static void	*krauler_subdriver(USBDevice_t *device)
1513 {
1514 	NUT_UNUSED_VARIABLE(device);
1515 
1516 	subdriver_command = &krauler_command;
1517 	return NULL;
1518 }
1519 
phoenix_subdriver(USBDevice_t * device)1520 static void	*phoenix_subdriver(USBDevice_t *device)
1521 {
1522 	NUT_UNUSED_VARIABLE(device);
1523 
1524 	subdriver_command = &phoenix_command;
1525 	return NULL;
1526 }
1527 
fabula_subdriver(USBDevice_t * device)1528 static void	*fabula_subdriver(USBDevice_t *device)
1529 {
1530 	NUT_UNUSED_VARIABLE(device);
1531 
1532 	subdriver_command = &fabula_command;
1533 	return NULL;
1534 }
1535 
phoenixtec_subdriver(USBDevice_t * device)1536 static void	*phoenixtec_subdriver(USBDevice_t *device)
1537 {
1538 	NUT_UNUSED_VARIABLE(device);
1539 
1540 	subdriver_command = &phoenixtec_command;
1541 	return NULL;
1542 }
1543 
1544 /* Note: the "hunnox_subdriver" name is taken by the subdriver_t structure */
fabula_hunnox_subdriver(USBDevice_t * device)1545 static void *fabula_hunnox_subdriver(USBDevice_t *device)
1546 {
1547 	NUT_UNUSED_VARIABLE(device);
1548 
1549 	subdriver_command = &hunnox_command;
1550 	return NULL;
1551 }
1552 
fuji_subdriver(USBDevice_t * device)1553 static void	*fuji_subdriver(USBDevice_t *device)
1554 {
1555 	NUT_UNUSED_VARIABLE(device);
1556 
1557 	subdriver_command = &fuji_command;
1558 	return NULL;
1559 }
1560 
snr_subdriver(USBDevice_t * device)1561 static void	*snr_subdriver(USBDevice_t *device)
1562 {
1563 	NUT_UNUSED_VARIABLE(device);
1564 
1565 	subdriver_command = &snr_command;
1566 	return NULL;
1567 }
1568 
1569 /* USB device match structure */
1570 typedef struct {
1571 	const int	vendorID;		/* USB device's VendorID */
1572 	const int	productID;		/* USB device's ProductID */
1573 	const char	*vendor;		/* USB device's iManufacturer string */
1574 	const char	*product;		/* USB device's iProduct string */
1575 	void		*(*fun)(USBDevice_t *);	/* Handler for specific processing */
1576 } qx_usb_device_id_t;
1577 
1578 /* USB VendorID/ProductID/iManufacturer/iProduct match - note: rightmost comment is used for naming rules by tools/nut-usbinfo.pl */
1579 static qx_usb_device_id_t	qx_usb_id[] = {
1580 	{ USB_DEVICE(0x05b8, 0x0000),	NULL,		NULL,			&cypress_subdriver },	/* Agiler UPS */
1581 	{ USB_DEVICE(0xffff, 0x0000),	NULL,		NULL,			&krauler_subdriver },	/* Ablerex 625L USB */
1582 	{ USB_DEVICE(0x0665, 0x5161),	NULL,		NULL,			&cypress_subdriver },	/* Belkin F6C1200-UNV/Voltronic Power UPSes */
1583 	{ USB_DEVICE(0x06da, 0x0002),	"Phoenixtec Power","USB Cable (V2.00)",	&phoenixtec_subdriver },/* Masterguard A Series */
1584 	{ USB_DEVICE(0x06da, 0x0002),	NULL,		NULL,			&cypress_subdriver },	/* Online Yunto YQ450 */
1585 	{ USB_DEVICE(0x06da, 0x0003),	NULL,		NULL,			&ippon_subdriver },	/* Mustek Powermust */
1586 	{ USB_DEVICE(0x06da, 0x0004),	NULL,		NULL,			&cypress_subdriver },	/* Phoenixtec Innova 3/1 T */
1587 	{ USB_DEVICE(0x06da, 0x0005),	NULL,		NULL,			&cypress_subdriver },	/* Phoenixtec Innova RT */
1588 	{ USB_DEVICE(0x06da, 0x0201),	NULL,		NULL,			&cypress_subdriver },	/* Phoenixtec Innova T */
1589 	{ USB_DEVICE(0x06da, 0x0601),	NULL,		NULL,			&phoenix_subdriver },	/* Online Zinto A */
1590 	{ USB_DEVICE(0x0f03, 0x0001),	NULL,		NULL,			&cypress_subdriver },	/* Unitek Alpha 1200Sx */
1591 	{ USB_DEVICE(0x14f0, 0x00c9),	NULL,		NULL,			&phoenix_subdriver },	/* GE EP series */
1592 	{ USB_DEVICE(0x0483, 0x0035),	NULL,		NULL,			&sgs_subdriver },	/* TS Shara UPSes; vendor ID 0x0483 is from ST Microelectronics - with product IDs delegated to different OEMs */
1593 	{ USB_DEVICE(0x0001, 0x0000),	"MEC",		"MEC0003",		&fabula_subdriver },	/* Fideltronik/MEC LUPUS 500 USB */
1594 	{ USB_DEVICE(0x0001, 0x0000),	NULL,		"MEC0003",		&fabula_hunnox_subdriver },	/* Hunnox HNX 850, reported to also help support Powercool and some other devices; closely related to fabula with tweaks */
1595 	{ USB_DEVICE(0x0001, 0x0000),	"ATCL FOR UPS",	"ATCL FOR UPS",		&fuji_subdriver },	/* Fuji UPSes */
1596 	{ USB_DEVICE(0x0001, 0x0000),	NULL,		NULL,			&krauler_subdriver },	/* Krauler UP-M500VA */
1597 	{ USB_DEVICE(0x0001, 0x0000),	NULL,		"MEC0003",		&snr_subdriver },	/* SNR-UPS-LID-XXXX UPSes */
1598 	/* End of list */
1599 	{ -1,	-1,	NULL,	NULL,	NULL }
1600 };
1601 
qx_is_usb_device_supported(qx_usb_device_id_t * usb_device_id_list,USBDevice_t * device)1602 static int qx_is_usb_device_supported(qx_usb_device_id_t *usb_device_id_list, USBDevice_t *device)
1603 {
1604 	int			retval = NOT_SUPPORTED;
1605 	qx_usb_device_id_t	*usbdev;
1606 
1607 	for (usbdev = usb_device_id_list; usbdev->vendorID != -1; usbdev++) {
1608 
1609 		if (usbdev->vendorID != device->VendorID)
1610 			continue;
1611 
1612 		/* Flag as possibly supported if we see a known vendor */
1613 		retval = POSSIBLY_SUPPORTED;
1614 
1615 		if (usbdev->productID != device->ProductID)
1616 			continue;
1617 
1618 		if (usbdev->vendor && (!device->Vendor || strcasecmp(usbdev->vendor, device->Vendor)))
1619 			continue;
1620 
1621 		if (usbdev->product && (!device->Product || strcasecmp(usbdev->product, device->Product)))
1622 			continue;
1623 
1624 		/* Call the specific handler, if it exists */
1625 		if (usbdev->fun != NULL)
1626 			(*usbdev->fun)(device);
1627 
1628 		return SUPPORTED;
1629 
1630 	}
1631 
1632 	return retval;
1633 }
1634 
device_match_func(USBDevice_t * hd,void * privdata)1635 static int	device_match_func(USBDevice_t *hd, void *privdata)
1636 {
1637 	NUT_UNUSED_VARIABLE(privdata);
1638 
1639 	if (subdriver_command) {
1640 		return 1;
1641 	}
1642 
1643 	switch (qx_is_usb_device_supported(qx_usb_id, hd))
1644 	{
1645 	case SUPPORTED:
1646 		return 1;
1647 
1648 	case POSSIBLY_SUPPORTED:
1649 	case NOT_SUPPORTED:
1650 	default:
1651 		return 0;
1652 	}
1653 }
1654 
1655 static USBDeviceMatcher_t	device_matcher = {
1656 	&device_match_func,
1657 	NULL,
1658 	NULL
1659 };
1660 #endif	/* QX_USB && !TESTING */
1661 
1662 
1663 /* == Driver functions implementations == */
1664 
1665 /* See header file for details. */
instcmd(const char * cmdname,const char * extradata)1666 int	instcmd(const char *cmdname, const char *extradata)
1667 {
1668 	item_t	*item;
1669 	char	value[SMALLBUF];
1670 
1671 	if (!strcasecmp(cmdname, "beeper.off")) {
1672 		/* Compatibility mode for old command */
1673 		upslogx(LOG_WARNING, "The 'beeper.off' command has been renamed to 'beeper.disable'");
1674 		return instcmd("beeper.disable", NULL);
1675 	}
1676 
1677 	if (!strcasecmp(cmdname, "beeper.on")) {
1678 		/* Compatibility mode for old command */
1679 		upslogx(LOG_WARNING, "The 'beeper.on' command has been renamed to 'beeper.enable'");
1680 		return instcmd("beeper.enable", NULL);
1681 	}
1682 
1683 	upslogx(LOG_INFO, "%s(%s, %s)", __func__, cmdname, extradata ? extradata : "[NULL]");
1684 
1685 	/* Retrieve item by command name */
1686 	item = find_nut_info(cmdname, QX_FLAG_CMD, QX_FLAG_SKIP);
1687 
1688 	/* Check for fallback if not found */
1689 	if (item == NULL) {
1690 
1691 		if (!strcasecmp(cmdname, "load.on")) {
1692 			return instcmd("load.on.delay", "0");
1693 		}
1694 
1695 		if (!strcasecmp(cmdname, "load.off")) {
1696 			return instcmd("load.off.delay", "0");
1697 		}
1698 
1699 		if (!strcasecmp(cmdname, "shutdown.return")) {
1700 
1701 			int	ret;
1702 
1703 			/* Ensure "ups.start.auto" is set to "yes", if supported */
1704 			if (dstate_getinfo("ups.start.auto")) {
1705 				if (setvar("ups.start.auto", "yes") != STAT_SET_HANDLED) {
1706 					upslogx(LOG_ERR, "%s: FAILED", __func__);
1707 					return STAT_INSTCMD_FAILED;
1708 				}
1709 			}
1710 
1711 			ret = instcmd("load.on.delay", dstate_getinfo("ups.delay.start"));
1712 			if (ret != STAT_INSTCMD_HANDLED) {
1713 				return ret;
1714 			}
1715 
1716 			return instcmd("load.off.delay", dstate_getinfo("ups.delay.shutdown"));
1717 
1718 		}
1719 
1720 		if (!strcasecmp(cmdname, "shutdown.stayoff")) {
1721 
1722 			int	ret;
1723 
1724 			/* Ensure "ups.start.auto" is set to "no", if supported */
1725 			if (dstate_getinfo("ups.start.auto")) {
1726 				if (setvar("ups.start.auto", "no") != STAT_SET_HANDLED) {
1727 					upslogx(LOG_ERR, "%s: FAILED", __func__);
1728 					return STAT_INSTCMD_FAILED;
1729 				}
1730 			}
1731 
1732 			ret = instcmd("load.on.delay", "-1");
1733 			if (ret != STAT_INSTCMD_HANDLED) {
1734 				return ret;
1735 			}
1736 
1737 			return instcmd("load.off.delay", dstate_getinfo("ups.delay.shutdown"));
1738 
1739 		}
1740 
1741 		upsdebugx(2, "%s: command %s unavailable", __func__, cmdname);
1742 		return STAT_INSTCMD_INVALID;
1743 	}
1744 
1745 	/* If extradata is empty, use the default value from the QX to NUT table, if any */
1746 	extradata = extradata ? extradata : item->dfl;
1747 	snprintf(value, sizeof(value), "%s", extradata ? extradata : "");
1748 
1749 	/* Preprocess command */
1750 	if (item->preprocess != NULL && item->preprocess(item, value, sizeof(value))) {
1751 		/* Something went wrong */
1752 		upslogx(LOG_ERR, "%s: FAILED", __func__);
1753 		return STAT_INSTCMD_FAILED;
1754 	}
1755 
1756 	/* No preprocess function -> nothing to do with extradata */
1757 	if (item->preprocess == NULL)
1758 		snprintf(value, sizeof(value), "%s", "");
1759 
1760 	/* Send the command, get the reply */
1761 	if (qx_process(item, strlen(value) > 0 ? value : NULL)) {
1762 		/* Something went wrong */
1763 		upslogx(LOG_ERR, "%s: FAILED", __func__);
1764 		return STAT_INSTCMD_FAILED;
1765 	}
1766 
1767 	/* We got a reply from the UPS: either subdriver->accepted (-> command handled) or the command itself echoed back (-> command failed) */
1768 	if (strlen(item->value) > 0) {
1769 
1770 		if (subdriver->accepted != NULL && !strcasecmp(item->value, subdriver->accepted)) {
1771 			upslogx(LOG_INFO, "%s: SUCCEED", __func__);
1772 			/* Set the status so that SEMI_STATIC vars are polled */
1773 			data_has_changed = TRUE;
1774 			return STAT_INSTCMD_HANDLED;
1775 		}
1776 
1777 		upslogx(LOG_ERR, "%s: FAILED", __func__);
1778 		return STAT_INSTCMD_FAILED;
1779 
1780 	}
1781 
1782 	/* No reply from the UPS -> command handled */
1783 	upslogx(LOG_INFO, "%s: SUCCEED", __func__);
1784 	/* Set the status so that SEMI_STATIC vars are polled */
1785 	data_has_changed = TRUE;
1786 	return STAT_INSTCMD_HANDLED;
1787 }
1788 
1789 /* See header file for details. */
setvar(const char * varname,const char * val)1790 int	setvar(const char *varname, const char *val)
1791 {
1792 	item_t		*item;
1793 	char		value[SMALLBUF];
1794 	st_tree_t	*root = (st_tree_t *)dstate_getroot();
1795 	int		ok = 0;
1796 
1797 	/* Retrieve variable */
1798 	item = find_nut_info(varname, QX_FLAG_SETVAR, QX_FLAG_SKIP);
1799 
1800 	if (item == NULL) {
1801 		upsdebugx(2, "%s: element %s unavailable", __func__, varname);
1802 		return STAT_SET_UNKNOWN;
1803 	}
1804 
1805 	/* No NUT variable is available for this item, so we're handling a one-time setvar from ups.conf */
1806 	if (item->qxflags & QX_FLAG_NONUT) {
1807 
1808 		const char	*userval;
1809 
1810 		/* Nothing to do */
1811 		if (!testvar(item->info_type)) {
1812 			upsdebugx(2, "%s: nothing to do.. [%s]", __func__, item->info_type);
1813 			return STAT_SET_HANDLED;
1814 		}
1815 
1816 		userval = getval(item->info_type);
1817 
1818 		upslogx(LOG_INFO, "%s(%s, %s)", __func__, varname, userval ? userval : "[NULL]");
1819 
1820 		snprintf(value, sizeof(value), "%s", userval ? userval : "");
1821 
1822 	/* This item is available in NUT */
1823 	} else {
1824 
1825 		upslogx(LOG_INFO, "%s(%s, %s)", __func__, varname, strlen(val) ? val : "[NULL]");
1826 
1827 		if (!strlen(val)) {
1828 			upslogx(LOG_ERR, "%s: value not given for %s", __func__, item->info_type);
1829 			return STAT_SET_UNKNOWN;	/* TODO: HANDLED but FAILED, not UNKNOWN! */
1830 		}
1831 
1832 		snprintf(value, sizeof(value), "%s", val);
1833 
1834 		/* Nothing to do */
1835 		if (!strcasecmp(dstate_getinfo(item->info_type), value)) {
1836 			upslogx(LOG_INFO, "%s: nothing to do.. [%s]", __func__, item->info_type);
1837 			return STAT_SET_HANDLED;
1838 		}
1839 
1840 	}
1841 
1842 	/* Check if given value is in the range of accepted values (range) */
1843 	if (item->qxflags & QX_FLAG_RANGE) {
1844 
1845 		long	valuetoset, min, max;
1846 
1847 		if (strspn(value, "0123456789 .") != strlen(value)) {
1848 			upslogx(LOG_ERR, "%s: non numerical value [%s: %s]", __func__, item->info_type, value);
1849 			return STAT_SET_UNKNOWN;	/* TODO: HANDLED but FAILED, not UNKNOWN! */
1850 		}
1851 
1852 		valuetoset = strtol(value, NULL, 10);
1853 
1854 		/* No NUT var is available for this item, so take its range from qx2nut table */
1855 		if (item->qxflags & QX_FLAG_NONUT) {
1856 
1857 			info_rw_t	*rvalue;
1858 
1859 			if (!strlen(value)) {
1860 				upslogx(LOG_ERR, "%s: value not given for %s", __func__, item->info_type);
1861 				return STAT_SET_UNKNOWN;	/* TODO: HANDLED but FAILED, not UNKNOWN! */
1862 			}
1863 
1864 			min = max = -1;
1865 
1866 			/* Loop on all existing values */
1867 			for (rvalue = item->info_rw; rvalue != NULL && strlen(rvalue->value) > 0; rvalue++) {
1868 
1869 				if (rvalue->preprocess && rvalue->preprocess(rvalue->value, sizeof(rvalue->value)))
1870 					continue;
1871 
1872 				if (min < 0) {
1873 					min = strtol(rvalue->value, NULL, 10);
1874 					continue;
1875 				}
1876 
1877 				max = strtol(rvalue->value, NULL, 10);
1878 
1879 				/* valuetoset is in the range */
1880 				if (min <= valuetoset && valuetoset <= max) {
1881 					ok = 1;
1882 					break;
1883 				}
1884 
1885 				min = -1;
1886 				max = -1;
1887 
1888 			}
1889 
1890 		/* We have a NUT var for this item, so check given value against the already set range */
1891 		} else {
1892 
1893 			const range_t	*range = state_getrangelist(root, item->info_type);
1894 
1895 			/* Unable to find tree node for var */
1896 			if (!range) {
1897 				upsdebugx(2, "%s: unable to find tree node for %s", __func__, item->info_type);
1898 				return STAT_SET_UNKNOWN;
1899 			}
1900 
1901 			while (range) {
1902 
1903 				min = range->min;
1904 				max = range->max;
1905 
1906 				/* valuetoset is in the range */
1907 				if (min <= valuetoset && valuetoset <= max) {
1908 					ok = 1;
1909 					break;
1910 				}
1911 				range = range->next;
1912 			}
1913 
1914 		}
1915 
1916 		if (!ok) {
1917 			upslogx(LOG_ERR, "%s: value out of range [%s: %s]", __func__, item->info_type, value);
1918 			return STAT_SET_UNKNOWN;	/* TODO: HANDLED but FAILED, not UNKNOWN! */
1919 		}
1920 
1921 	/* Check if given value is in the range of accepted values (enum) */
1922 	} else if (item->qxflags & QX_FLAG_ENUM) {
1923 
1924 		/* No NUT var is available for this item, so take its range from qx2nut table */
1925 		if (item->qxflags & QX_FLAG_NONUT) {
1926 
1927 			info_rw_t	*envalue;
1928 
1929 			if (!strlen(value)) {
1930 				upslogx(LOG_ERR, "%s: value not given for %s", __func__, item->info_type);
1931 				return STAT_SET_UNKNOWN;	/* TODO: HANDLED but FAILED, not UNKNOWN! */
1932 			}
1933 
1934 			/* Loop on all existing values */
1935 			for (envalue = item->info_rw; envalue != NULL && strlen(envalue->value) > 0; envalue++) {
1936 
1937 				if (envalue->preprocess && envalue->preprocess(envalue->value, sizeof(envalue->value)))
1938 					continue;
1939 
1940 				if (strcasecmp(envalue->value, value))
1941 					continue;
1942 
1943 				/* value found */
1944 				ok = 1;
1945 				break;
1946 
1947 			}
1948 
1949 		/* We have a NUT var for this item, so check given value against the already set range */
1950 		} else {
1951 
1952 			const enum_t	*enumlist = state_getenumlist(root, item->info_type);
1953 
1954 			/* Unable to find tree node for var */
1955 			if (!enumlist) {
1956 				upsdebugx(2, "%s: unable to find tree node for %s", __func__, item->info_type);
1957 				return STAT_SET_UNKNOWN;
1958 			}
1959 
1960 			while (enumlist) {
1961 
1962 				/* If this is not the right value, go on to the next */
1963 				if (strcasecmp(enumlist->val, value)) {
1964 					enumlist = enumlist->next;
1965 					continue;
1966 				}
1967 
1968 				/* value found in enumlist */
1969 				ok = 1;
1970 				break;
1971 			}
1972 
1973 		}
1974 
1975 		if (!ok) {
1976 			upslogx(LOG_ERR, "%s: value out of range [%s: %s]", __func__, item->info_type, value);
1977 			return STAT_SET_UNKNOWN;	/* TODO: HANDLED but FAILED, not UNKNOWN! */
1978 		}
1979 
1980 	/* Check if given value is not too long (string) */
1981 	} else if (item->info_flags & ST_FLAG_STRING) {
1982 
1983 		const long	aux = state_getaux(root, item->info_type);
1984 
1985 		/* Unable to find tree node for var */
1986 		if (aux < 0) {
1987 			upsdebugx(2, "%s: unable to find tree node for %s", __func__, item->info_type);
1988 			return STAT_SET_UNKNOWN;
1989 		}
1990 
1991 		/* FIXME? Should this cast to "long"?
1992 		 * An int-size string is quite a lot already,
1993 		 * even on architectures with a moderate INTMAX
1994 		 */
1995 		if (aux < (int)strlen(value)) {
1996 			upslogx(LOG_ERR, "%s: value is too long [%s: %s]", __func__, item->info_type, value);
1997 			return STAT_SET_UNKNOWN;	/* TODO: HANDLED but FAILED, not UNKNOWN! */
1998 		}
1999 
2000 	}
2001 
2002 	/* Preprocess value: from NUT-compliant to UPS-compliant */
2003 	if (item->preprocess != NULL && item->preprocess(item, value, sizeof(value))) {
2004 		/* Something went wrong */
2005 		upslogx(LOG_ERR, "%s: FAILED", __func__);
2006 		return STAT_SET_UNKNOWN;	/* TODO: HANDLED but FAILED, not UNKNOWN! */
2007 	}
2008 
2009 	/* Handle server side variable */
2010 	if (item->qxflags & QX_FLAG_ABSENT) {
2011 		upsdebugx(2, "%s: setting server side variable %s", __func__, item->info_type);
2012 		dstate_setinfo(item->info_type, "%s", value);
2013 		upslogx(LOG_INFO, "%s: SUCCEED", __func__);
2014 		return STAT_SET_HANDLED;
2015 	}
2016 
2017 	/* No preprocess function -> nothing to do with val */
2018 	if (item->preprocess == NULL)
2019 		snprintf(value, sizeof(value), "%s", "");
2020 
2021 	/* Actual variable setting */
2022 	if (qx_process(item, strlen(value) > 0 ? value : NULL)) {
2023 		/* Something went wrong */
2024 		upslogx(LOG_ERR, "%s: FAILED", __func__);
2025 		return STAT_SET_UNKNOWN;	/* TODO: HANDLED but FAILED, not UNKNOWN! */
2026 	}
2027 
2028 	/* We got a reply from the UPS: either subdriver->accepted (-> command handled) or the command itself echoed back (-> command failed) */
2029 	if (strlen(item->value) > 0) {
2030 
2031 		if (subdriver->accepted != NULL && !strcasecmp(item->value, subdriver->accepted)) {
2032 			upslogx(LOG_INFO, "%s: SUCCEED", __func__);
2033 			/* Set the status so that SEMI_STATIC vars are polled */
2034 			data_has_changed = TRUE;
2035 			return STAT_SET_HANDLED;
2036 		}
2037 
2038 		upslogx(LOG_ERR, "%s: FAILED", __func__);
2039 		return STAT_SET_UNKNOWN;	/* TODO: HANDLED but FAILED, not UNKNOWN! */
2040 
2041 	}
2042 
2043 	/* No reply from the UPS -> command handled */
2044 	upslogx(LOG_INFO, "%s: SUCCEED", __func__);
2045 	/* Set the status so that SEMI_STATIC vars are polled */
2046 	data_has_changed = TRUE;
2047 	return STAT_SET_HANDLED;
2048 }
2049 
2050 /* Try to shutdown the UPS */
2051 void	upsdrv_shutdown(void)
2052 	__attribute__((noreturn));
2053 
upsdrv_shutdown(void)2054 void	upsdrv_shutdown(void)
2055 {
2056 	int		retry;
2057 	item_t		*item;
2058 	const char	*val;
2059 
2060 	upsdebugx(1, "%s...", __func__);
2061 
2062 	/* Get user-defined delays */
2063 
2064 	/* Start delay */
2065 	item = find_nut_info("ups.delay.start", 0, QX_FLAG_SKIP);
2066 
2067 	/* Don't know what happened */
2068 	if (!item)
2069 		fatalx(EXIT_FAILURE, "Unable to set start delay");
2070 
2071 	/* Set the default value */
2072 	dstate_setinfo(item->info_type, "%s", item->dfl);
2073 
2074 	/* Set var flags/range/enum */
2075 	qx_set_var(item);
2076 
2077 	/* Retrieve user defined delay settings */
2078 	val = getval(QX_VAR_ONDELAY);
2079 
2080 	if (val && setvar(item->info_type, val) != STAT_SET_HANDLED) {
2081 		fatalx(EXIT_FAILURE, "Start delay '%s' out of range", val);
2082 	}
2083 
2084 	/* Shutdown delay */
2085 	item = find_nut_info("ups.delay.shutdown", 0, QX_FLAG_SKIP);
2086 
2087 	/* Don't know what happened */
2088 	if (!item)
2089 		fatalx(EXIT_FAILURE, "Unable to set shutdown delay");
2090 
2091 	/* Set the default value */
2092 	dstate_setinfo(item->info_type, "%s", item->dfl);
2093 
2094 	/* Set var flags/range/enum */
2095 	qx_set_var(item);
2096 
2097 	/* Retrieve user defined delay settings */
2098 	val = getval(QX_VAR_OFFDELAY);
2099 
2100 	if (val && setvar(item->info_type, val) != STAT_SET_HANDLED) {
2101 		fatalx(EXIT_FAILURE, "Shutdown delay '%s' out of range", val);
2102 	}
2103 
2104 	/* Stop pending shutdowns */
2105 	if (find_nut_info("shutdown.stop", QX_FLAG_CMD, QX_FLAG_SKIP)) {
2106 
2107 		for (retry = 1; retry <= MAXTRIES; retry++) {
2108 
2109 			if (instcmd("shutdown.stop", NULL) != STAT_INSTCMD_HANDLED) {
2110 				continue;
2111 			}
2112 
2113 			break;
2114 
2115 		}
2116 
2117 		if (retry > MAXTRIES) {
2118 			upslogx(LOG_NOTICE, "No shutdown pending");
2119 		}
2120 
2121 	}
2122 
2123 	/* Shutdown */
2124 	for (retry = 1; retry <= MAXTRIES; retry++) {
2125 
2126 		if (testvar("stayoff")) {
2127 
2128 			if (instcmd("shutdown.stayoff", NULL) != STAT_INSTCMD_HANDLED) {
2129 				continue;
2130 			}
2131 
2132 		} else {
2133 
2134 			if (instcmd("shutdown.return", NULL) != STAT_INSTCMD_HANDLED) {
2135 				continue;
2136 			}
2137 
2138 		}
2139 
2140 		fatalx(EXIT_SUCCESS, "Shutting down in %s seconds", dstate_getinfo("ups.delay.shutdown"));
2141 	}
2142 
2143 	fatalx(EXIT_FAILURE, "Shutdown failed!");
2144 }
2145 
2146 #ifdef QX_USB
2147 	#ifndef TESTING
2148 		static const struct {
2149 			const char	*name;
2150 			int		(*command)(const char *cmd, char *buf, size_t buflen);
2151 		} usbsubdriver[] = {
2152 			{ "cypress", &cypress_command },
2153 			{ "phoenixtec", &phoenixtec_command },
2154 			{ "phoenix", &phoenix_command },
2155 			{ "ippon", &ippon_command },
2156 			{ "krauler", &krauler_command },
2157 			{ "fabula", &fabula_command },
2158 			{ "hunnox", &hunnox_command },
2159 			{ "fuji", &fuji_command },
2160 			{ "sgs", &sgs_command },
2161 			{ "snr", &snr_command },
2162 			{ NULL, NULL }
2163 		};
2164 	#endif
2165 #endif
2166 
2167 
upsdrv_help(void)2168 void	upsdrv_help(void)
2169 {
2170 #ifdef QX_USB
2171 	#ifndef TESTING
2172 	printf("\nAcceptable values for 'subdriver' via -x or ups.conf in this driver: ");
2173 	size_t i;
2174 
2175 	for (i = 0; usbsubdriver[i].name != NULL; i++) {
2176 		if (i>0)
2177 			printf(", ");
2178 		printf("%s", usbsubdriver[i].name);
2179 	}
2180 	printf("\n\n");
2181 	#endif
2182 #endif
2183 
2184 	printf("Read The Fine Manual ('man 8 nutdrv_qx')\n");
2185 }
2186 
2187 /* Adding flags/vars */
upsdrv_makevartable(void)2188 void	upsdrv_makevartable(void)
2189 {
2190 	char	temp[SMALLBUF];
2191 	int	i;
2192 
2193 	upsdebugx(1, "%s...", __func__);
2194 
2195 	snprintf(temp, sizeof(temp), "Set shutdown delay, in seconds (default=%s)", DEFAULT_OFFDELAY);
2196 	addvar(VAR_VALUE, QX_VAR_OFFDELAY, temp);
2197 
2198 	snprintf(temp, sizeof(temp), "Set startup delay, in seconds (default=%s)", DEFAULT_ONDELAY);
2199 	addvar(VAR_VALUE, QX_VAR_ONDELAY, temp);
2200 
2201 	addvar(VAR_FLAG, "stayoff", "If invoked the UPS won't return after a shutdown when FSD arises");
2202 
2203 	snprintf(temp, sizeof(temp), "Set polling frequency, in seconds, to reduce data flow (default=%d)", DEFAULT_POLLFREQ);
2204 	addvar(VAR_VALUE, QX_VAR_POLLFREQ, temp);
2205 
2206 	addvar(VAR_VALUE, "protocol", "Preselect communication protocol (skip autodetection)");
2207 
2208 	/* battery.{charge,runtime} guesstimation */
2209 	addvar(VAR_VALUE, "runtimecal", "Parameters used for runtime calculation");
2210 	addvar(VAR_VALUE, "chargetime", "Nominal charge time for UPS battery");
2211 	addvar(VAR_VALUE, "idleload", "Minimum load to be used for runtime calculation");
2212 
2213 #ifdef QX_USB
2214 	addvar(VAR_VALUE, "subdriver", "Serial-over-USB subdriver selection");
2215 	/* allow -x vendor=X, vendorid=X, product=X, productid=X, serial=X */
2216 	nut_usb_addvars();
2217 
2218 	addvar(VAR_VALUE, "langid_fix", "Apply the language ID workaround to the krauler subdriver (0x409 or 0x4095)");
2219 	addvar(VAR_FLAG, "noscanlangid", "Don't autoscan valid range for langid");
2220 #endif	/* QX_USB */
2221 
2222 #ifdef QX_SERIAL
2223 	addvar(VAR_VALUE, "cablepower", "Set cable power for serial interface");
2224 #endif	/* QX_SERIAL */
2225 
2226 	/* Subdrivers flags/vars */
2227 	for (i = 0; subdriver_list[i] != NULL; i++) {
2228 
2229 		if (subdriver_list[i]->makevartable != NULL)
2230 			subdriver_list[i]->makevartable();
2231 
2232 	}
2233 }
2234 
2235 /* Update UPS status/infos */
upsdrv_updateinfo(void)2236 void	upsdrv_updateinfo(void)
2237 {
2238 	time_t		now;
2239 	static int	retry = 0;
2240 
2241 	upsdebugx(1, "%s...", __func__);
2242 
2243 	time(&now);
2244 
2245 	/* Clear status buffer before beginning */
2246 	status_init();
2247 
2248 	/* Do a full update (polling) every pollfreq or upon data change (i.e. setvar/instcmd) */
2249 	if ((now > (lastpoll + pollfreq)) || (data_has_changed == TRUE)) {
2250 
2251 		upsdebugx(1, "Full update...");
2252 
2253 		/* Clear ups_status */
2254 		ups_status = 0;
2255 
2256 		alarm_init();
2257 
2258 		if (qx_ups_walk(QX_WALKMODE_FULL_UPDATE) == FALSE) {
2259 
2260 			if (retry < MAXTRIES || retry == MAXTRIES) {
2261 				upsdebugx(1, "Communications with the UPS lost: status read failed!");
2262 				retry++;
2263 			} else {
2264 				dstate_datastale();
2265 			}
2266 
2267 			return;
2268 		}
2269 
2270 		lastpoll = now;
2271 		data_has_changed = FALSE;
2272 
2273 		ups_alarm_set();
2274 		alarm_commit();
2275 
2276 	} else {
2277 
2278 		upsdebugx(1, "Quick update...");
2279 
2280 		/* Quick poll data only to see if the UPS is still connected */
2281 		if (qx_ups_walk(QX_WALKMODE_QUICK_UPDATE) == FALSE) {
2282 
2283 			if (retry < MAXTRIES || retry == MAXTRIES) {
2284 				upsdebugx(1, "Communications with the UPS lost: status read failed!");
2285 				retry++;
2286 			} else {
2287 				dstate_datastale();
2288 			}
2289 
2290 			return;
2291 		}
2292 
2293 	}
2294 
2295 	ups_status_set();
2296 	status_commit();
2297 
2298 	if (retry > MAXTRIES) {
2299 		upslogx(LOG_NOTICE, "Communications with the UPS re-established");
2300 	}
2301 
2302 	retry = 0;
2303 
2304 	dstate_dataok();
2305 }
2306 
2307 /* Initialise data from UPS */
upsdrv_initinfo(void)2308 void	upsdrv_initinfo(void)
2309 {
2310 	char	*val;
2311 
2312 	upsdebugx(1, "%s...", __func__);
2313 
2314 	dstate_setinfo("driver.version.data", "%s", subdriver->name);
2315 
2316 	/* Initialise data */
2317 	if (qx_ups_walk(QX_WALKMODE_INIT) == FALSE) {
2318 		fatalx(EXIT_FAILURE, "Can't initialise data from the UPS");
2319 	}
2320 
2321 	/* Init battery guesstimation */
2322 	qx_initbattery();
2323 
2324 	if (dstate_getinfo("ups.delay.start")) {
2325 
2326 		/* Retrieve user defined delay settings */
2327 		val = getval(QX_VAR_ONDELAY);
2328 
2329 		if (val && setvar("ups.delay.start", val) != STAT_SET_HANDLED) {
2330 			fatalx(EXIT_FAILURE, "Start delay '%s' out of range", val);
2331 		}
2332 
2333 	}
2334 
2335 	if (dstate_getinfo("ups.delay.shutdown")) {
2336 
2337 		/* Retrieve user defined delay settings */
2338 		val = getval(QX_VAR_OFFDELAY);
2339 
2340 		if (val && setvar("ups.delay.shutdown", val) != STAT_SET_HANDLED) {
2341 			fatalx(EXIT_FAILURE, "Shutdown delay '%s' out of range", val);
2342 		}
2343 
2344 	}
2345 
2346 	if (!find_nut_info("load.off", QX_FLAG_CMD, QX_FLAG_SKIP) && find_nut_info("load.off.delay", QX_FLAG_CMD, QX_FLAG_SKIP)) {
2347 		/* Adds default with a delay value of '0' (= immediate) */
2348 		dstate_addcmd("load.off");
2349 	}
2350 
2351 	if (!find_nut_info("load.on", QX_FLAG_CMD, QX_FLAG_SKIP) && find_nut_info("load.on.delay", QX_FLAG_CMD, QX_FLAG_SKIP)) {
2352 		/* Adds default with a delay value of '0' (= immediate) */
2353 		dstate_addcmd("load.on");
2354 	}
2355 
2356 	/* Init polling frequency */
2357 	val = getval(QX_VAR_POLLFREQ);
2358 	if (val)
2359 		pollfreq = strtol(val, NULL, 10);
2360 
2361 	dstate_setinfo("driver.parameter.pollfreq", "%ld", pollfreq);
2362 
2363 	time(&lastpoll);
2364 
2365 	/* Install handlers */
2366 	upsh.setvar = setvar;
2367 	upsh.instcmd = instcmd;
2368 
2369 	/* Subdriver initinfo */
2370 	if (subdriver->initinfo != NULL)
2371 		subdriver->initinfo();
2372 }
2373 
2374 /* Open the port and the like and choose the subdriver */
upsdrv_initups(void)2375 void	upsdrv_initups(void)
2376 {
2377 	upsdebugx(1, "%s...", __func__);
2378 
2379 #if defined(QX_SERIAL) && defined(QX_USB)
2380 
2381 	/* Whether the device is connected through USB or serial */
2382 	if (
2383 		!strcasecmp(dstate_getinfo("driver.parameter.port"), "auto") ||
2384 		getval("subdriver") ||
2385 		getval("vendorid") ||
2386 		getval("productid") ||
2387 		getval("vendor") ||
2388 		getval("product") ||
2389 		getval("serial") ||
2390 		getval("bus") ||
2391 		getval("langid_fix")
2392 	) {
2393 		/* USB */
2394 		is_usb = 1;
2395 	} else {
2396 		/* Serial */
2397 		is_usb = 0;
2398 	}
2399 
2400 #endif	/* QX_SERIAL && QX_USB */
2401 
2402 /* Serial */
2403 #ifdef QX_SERIAL
2404 
2405 	#ifdef QX_USB
2406 	if (!is_usb) {
2407 	#endif	/* QX_USB */
2408 
2409 	#ifndef TESTING
2410 
2411 		const struct {
2412 			const char	*val;
2413 			const int	dtr;
2414 			const int	rts;
2415 		} cablepower[] = {
2416 			{ "normal",	1, 0 },	/* Default */
2417 			{ "reverse",	0, 1 },
2418 			{ "both",	1, 1 },
2419 			{ "none",	0, 0 },
2420 			{ NULL, 0, 0 }
2421 		};
2422 
2423 		int		i;
2424 		const char	*val;
2425 		struct termios	tio;
2426 
2427 		/* Open and lock the serial port and set the speed to 2400 baud. */
2428 		upsfd = ser_open(device_path);
2429 		ser_set_speed(upsfd, device_path, B2400);
2430 
2431 		if (tcgetattr(upsfd, &tio)) {
2432 			fatal_with_errno(EXIT_FAILURE, "tcgetattr");
2433 		}
2434 
2435 		/* Use canonical mode input processing (to read reply line) */
2436 		tio.c_lflag |= ICANON;	/* Canonical input (erase and kill processing) */
2437 
2438 		tio.c_cc[VEOF] = _POSIX_VDISABLE;
2439 		tio.c_cc[VEOL] = '\r';
2440 		tio.c_cc[VERASE] = _POSIX_VDISABLE;
2441 		tio.c_cc[VINTR] = _POSIX_VDISABLE;
2442 		tio.c_cc[VKILL] = _POSIX_VDISABLE;
2443 		tio.c_cc[VQUIT] = _POSIX_VDISABLE;
2444 		tio.c_cc[VSUSP] = _POSIX_VDISABLE;
2445 		tio.c_cc[VSTART] = _POSIX_VDISABLE;
2446 		tio.c_cc[VSTOP] = _POSIX_VDISABLE;
2447 
2448 		if (tcsetattr(upsfd, TCSANOW, &tio)) {
2449 			fatal_with_errno(EXIT_FAILURE, "tcsetattr");
2450 		}
2451 
2452 		val = getval("cablepower");
2453 		for (i = 0; val && cablepower[i].val; i++) {
2454 
2455 			if (!strcasecmp(val, cablepower[i].val)) {
2456 				break;
2457 			}
2458 		}
2459 
2460 		if (!cablepower[i].val) {
2461 			fatalx(EXIT_FAILURE, "Value '%s' not valid for 'cablepower'", val);
2462 		}
2463 
2464 		ser_set_dtr(upsfd, cablepower[i].dtr);
2465 		ser_set_rts(upsfd, cablepower[i].rts);
2466 
2467 		/* Allow some time to settle for the cablepower */
2468 		usleep(100000);
2469 
2470 	#endif	/* TESTING */
2471 
2472 	#ifdef QX_USB
2473 	} else {	/* is_usb */
2474 	#endif	/* QX_USB */
2475 
2476 #endif	/* QX_SERIAL */
2477 
2478 /* USB */
2479 #ifdef QX_USB
2480 
2481 	#ifndef TESTING
2482 		int	ret, langid;
2483 		char	tbuf[255];	/* Some devices choke on size > 255 */
2484 		char	*regex_array[7];
2485 
2486 		char	*subdrv = getval("subdriver");
2487 
2488 		regex_array[0] = getval("vendorid");
2489 		regex_array[1] = getval("productid");
2490 		regex_array[2] = getval("vendor");
2491 		regex_array[3] = getval("product");
2492 		regex_array[4] = getval("serial");
2493 		regex_array[5] = getval("bus");
2494 		regex_array[6] = getval("device");
2495 
2496 		/* Check for language ID workaround (#1) */
2497 		if (getval("langid_fix")) {
2498 			/* Skip "0x" prefix and set back to hexadecimal */
2499 			unsigned int u_langid_fix;
2500 			if ( (sscanf(getval("langid_fix") + 2, "%x", &u_langid_fix) != 1)
2501 			||   (u_langid_fix > INT_MAX)
2502 			) {
2503 				upslogx(LOG_NOTICE, "Error enabling language ID workaround");
2504 			} else {
2505 				langid_fix = (int)u_langid_fix;
2506 				upsdebugx(2, "Language ID workaround enabled (using '0x%x')", langid_fix);
2507 			}
2508 		}
2509 
2510 		/* Pick up the subdriver name if set explicitly */
2511 		if (subdrv) {
2512 
2513 			int	i;
2514 
2515 			if (!regex_array[0] || !regex_array[1]) {
2516 				fatalx(EXIT_FAILURE, "When specifying a subdriver, 'vendorid' and 'productid' are mandatory.");
2517 			}
2518 
2519 			for (i = 0; usbsubdriver[i].name; i++) {
2520 
2521 				if (strcasecmp(subdrv, usbsubdriver[i].name)) {
2522 					continue;
2523 				}
2524 
2525 				subdriver_command = usbsubdriver[i].command;
2526 				break;
2527 			}
2528 
2529 			if (!subdriver_command) {
2530 				fatalx(EXIT_FAILURE, "Subdriver '%s' not found!", subdrv);
2531 			}
2532 
2533 		}
2534 
2535 		ret = USBNewRegexMatcher(&regex_matcher, regex_array, REG_ICASE | REG_EXTENDED);
2536 		switch (ret)
2537 		{
2538 		case -1:
2539 			fatal_with_errno(EXIT_FAILURE, "USBNewRegexMatcher");
2540 		case 0:
2541 			break;	/* All is well */
2542 		default:
2543 			fatalx(EXIT_FAILURE, "Invalid regular expression: %s", regex_array[ret]);
2544 		}
2545 
2546 		/* Link the matchers */
2547 		regex_matcher->next = &device_matcher;
2548 
2549 		ret = usb->open(&udev, &usbdevice, regex_matcher, NULL);
2550 		if (ret < 0) {
2551 			fatalx(EXIT_FAILURE,
2552 				"No supported devices found. Please check your device availability with 'lsusb'\n"
2553 				"and make sure you have an up-to-date version of NUT. If this does not help,\n"
2554 				"try running the driver with at least 'subdriver', 'vendorid' and 'productid'\n"
2555 				"options specified. Please refer to the man page for details about these options\n"
2556 				"(man 8 nutdrv_qx).\n");
2557 		}
2558 
2559 		if (!subdriver_command) {
2560 			fatalx(EXIT_FAILURE, "No subdriver selected");
2561 		}
2562 
2563 		/* Create a new matcher for later reopening */
2564 		ret = USBNewExactMatcher(&reopen_matcher, &usbdevice);
2565 		if (ret) {
2566 			fatal_with_errno(EXIT_FAILURE, "USBNewExactMatcher");
2567 		}
2568 
2569 		/* Link the matchers */
2570 		reopen_matcher->next = regex_matcher;
2571 
2572 		dstate_setinfo("ups.vendorid", "%04x", usbdevice.VendorID);
2573 		dstate_setinfo("ups.productid", "%04x", usbdevice.ProductID);
2574 
2575 		/* Check for language ID workaround (#2) */
2576 		if ((langid_fix != -1) && (!getval("noscanlangid"))) {
2577 			/* Future improvement:
2578 			 *   Asking for the zero'th index is special - it returns a string descriptor that contains all the language IDs supported by the device.
2579 			 *   Typically there aren't many - often only one.
2580 			 *   The language IDs are 16 bit numbers, and they start at the third byte in the descriptor.
2581 			 *   See USB 2.0 specification, section 9.6.7, for more information on this.
2582 			 * This should allow automatic application of the workaround */
2583 			ret = usb_get_string(udev, 0, 0, tbuf, sizeof(tbuf));
2584 			if (ret >= 4) {
2585 				langid = tbuf[2] | (tbuf[3] << 8);
2586 				upsdebugx(1, "First supported language ID: 0x%x (please report to the NUT maintainer!)", langid);
2587 			}
2588 		}
2589 
2590 	#endif	/* TESTING */
2591 
2592 	#ifdef QX_SERIAL
2593 	}	/* is_usb */
2594 	#endif	/* QX_SERIAL */
2595 
2596 #endif	/* QX_USB */
2597 
2598 	/* Choose subdriver */
2599 	if (!subdriver_matcher())
2600 		fatalx(EXIT_FAILURE, "Device not supported!");
2601 
2602 	/* Subdriver initups */
2603 	if (subdriver->initups != NULL)
2604 		subdriver->initups();
2605 }
2606 
2607 /* Close the ports and the like */
upsdrv_cleanup(void)2608 void	upsdrv_cleanup(void)
2609 {
2610 	upsdebugx(1, "%s...", __func__);
2611 
2612 #ifndef TESTING
2613 
2614 #ifdef QX_SERIAL
2615 
2616 	#ifdef QX_USB
2617 	if (!is_usb) {
2618 	#endif	/* QX_USB */
2619 
2620 		ser_set_dtr(upsfd, 0);
2621 		ser_close(upsfd, device_path);
2622 
2623 	#ifdef QX_USB
2624 	} else {	/* is_usb */
2625 	#endif	/* QX_USB */
2626 
2627 #endif	/* QX_SERIAL */
2628 
2629 #ifdef QX_USB
2630 
2631 		usb->close(udev);
2632 		USBFreeExactMatcher(reopen_matcher);
2633 		USBFreeRegexMatcher(regex_matcher);
2634 		free(usbdevice.Vendor);
2635 		free(usbdevice.Product);
2636 		free(usbdevice.Serial);
2637 		free(usbdevice.Bus);
2638 		free(usbdevice.Device);
2639 
2640 	#ifdef QX_SERIAL
2641 	}	/* is_usb */
2642 	#endif	/* QX_SERIAL */
2643 
2644 #endif	/* QX_USB */
2645 
2646 #endif	/* TESTING */
2647 
2648 }
2649 
2650 
2651 /* == Support functions == */
2652 
2653 /* Generic command processing function: send a command and read a reply.
2654  * Returns < 0 on error, 0 on timeout and the number of bytes read on success. */
qx_command(const char * cmd,char * buf,size_t buflen)2655 static ssize_t	qx_command(const char *cmd, char *buf, size_t buflen)
2656 {
2657 /* NOTE: Could not find in which ifdef-ed codepath, but clang complained
2658  * about unused parameters here. Reference them just in case...
2659  */
2660 	NUT_UNUSED_VARIABLE(cmd);
2661 	NUT_UNUSED_VARIABLE(buf);
2662 	NUT_UNUSED_VARIABLE(buflen);
2663 
2664 #ifndef TESTING
2665 
2666 	ssize_t	ret = -1;
2667 
2668 # ifdef QX_USB
2669 
2670 #  ifdef QX_SERIAL
2671 	/* Communication: USB */
2672 	if (is_usb) {
2673 #  endif	/* QX_SERIAL (&& QX_USB)*/
2674 
2675 		if (udev == NULL) {
2676 			ret = usb->open(&udev, &usbdevice, reopen_matcher, NULL);
2677 
2678 			if (ret < 1) {
2679 				return ret;
2680 			}
2681 		}
2682 
2683 		ret = (*subdriver_command)(cmd, buf, buflen);
2684 
2685 		if (ret >= 0) {
2686 			return ret;
2687 		}
2688 
2689 		switch (ret)
2690 		{
2691 		case -EBUSY:		/* Device or resource busy */
2692 			fatal_with_errno(EXIT_FAILURE, "Got disconnected by another driver");
2693 #ifndef HAVE___ATTRIBUTE__NORETURN
2694 # if (defined HAVE_PRAGMA_GCC_DIAGNOSTIC_PUSH_POP) && (defined HAVE_PRAGMA_GCC_DIAGNOSTIC_IGNORED_UNREACHABLE_CODE)
2695 #  pragma GCC diagnostic push
2696 #  pragma GCC diagnostic ignored "-Wunreachable-code"
2697 # endif
2698 			exit(EXIT_FAILURE);	/* Should not get here in practice, but compiler is afraid we can fall through */
2699 # if (defined HAVE_PRAGMA_GCC_DIAGNOSTIC_PUSH_POP) && (defined HAVE_PRAGMA_GCC_DIAGNOSTIC_IGNORED_UNREACHABLE_CODE)
2700 #  pragma GCC diagnostic pop
2701 # endif
2702 #endif
2703 
2704 		case -EPERM:		/* Operation not permitted */
2705 			fatal_with_errno(EXIT_FAILURE, "Permissions problem");
2706 #ifndef HAVE___ATTRIBUTE__NORETURN
2707 # if (defined HAVE_PRAGMA_GCC_DIAGNOSTIC_PUSH_POP) && (defined HAVE_PRAGMA_GCC_DIAGNOSTIC_IGNORED_UNREACHABLE_CODE)
2708 #  pragma GCC diagnostic push
2709 #  pragma GCC diagnostic ignored "-Wunreachable-code"
2710 # endif
2711 			exit(EXIT_FAILURE);	/* Should not get here in practice, but compiler is afraid we can fall through */
2712 # if (defined HAVE_PRAGMA_GCC_DIAGNOSTIC_PUSH_POP) && (defined HAVE_PRAGMA_GCC_DIAGNOSTIC_IGNORED_UNREACHABLE_CODE)
2713 #  pragma GCC diagnostic pop
2714 # endif
2715 #endif
2716 
2717 		case -EPIPE:		/* Broken pipe */
2718 			if (usb_clear_halt(udev, 0x81) == 0) {
2719 				upsdebugx(1, "Stall condition cleared");
2720 				break;
2721 			}
2722 #ifdef ETIME
2723 			goto fallthrough_case_ETIME;
2724 		case -ETIME:		/* Timer expired */
2725 		fallthrough_case_ETIME:
2726 #endif	/* ETIME */
2727 			if (usb_reset(udev) == 0) {
2728 				upsdebugx(1, "Device reset handled");
2729 			}
2730 			goto fallthrough_case_reconnect;
2731 		case -ENODEV:		/* No such device */
2732 		case -EACCES:		/* Permission denied */
2733 		case -EIO:  		/* I/O error */
2734 		case -ENXIO:		/* No such device or address */
2735 		case -ENOENT:		/* No such file or directory */
2736 		fallthrough_case_reconnect:
2737 			/* Uh oh, got to reconnect! */
2738 			usb->close(udev);
2739 			udev = NULL;
2740 			break;
2741 
2742 		case -ETIMEDOUT:	/* Connection timed out */
2743 		case -EOVERFLOW:	/* Value too large for defined data type */
2744 #ifdef EPROTO
2745 		case -EPROTO:		/* Protocol error */
2746 #endif
2747 		default:
2748 			break;
2749 		}
2750 
2751 #  ifdef QX_SERIAL
2752 	/* Communication: serial */
2753 	} else {	/* !is_usb */
2754 #  endif	/* QX_SERIAL (&& QX_USB) */
2755 
2756 # endif	/* QX_USB (&& TESTING) */
2757 
2758 # ifdef QX_SERIAL
2759 
2760 		ser_flush_io(upsfd);
2761 
2762 		ret = ser_send(upsfd, "%s", cmd);
2763 
2764 		if (ret <= 0) {
2765 			upsdebugx(3, "send: %s (%zd)", ret ? strerror(errno) : "timeout", ret);
2766 			return ret;
2767 		}
2768 
2769 		upsdebugx(3, "send: '%.*s'", (int)strcspn(cmd, "\r"), cmd);
2770 
2771 		ret = ser_get_buf(upsfd, buf, buflen, SER_WAIT_SEC, 0);
2772 
2773 		if (ret <= 0) {
2774 			upsdebugx(3, "read: %s (%zd)", ret ? strerror(errno) : "timeout", ret);
2775 			return ret;
2776 		}
2777 
2778 		upsdebug_hex(5, "read", buf, (size_t)ret);
2779 		upsdebugx(3, "read: '%.*s'", (int)strcspn(buf, "\r"), buf);
2780 
2781 #  ifdef QX_USB
2782 	}	/* !is_usb */
2783 #  endif	/* QX_USB (&& QX_SERIAL) */
2784 
2785 # endif	/* QX_SERIAL (&& TESTING) */
2786 
2787 	return ret;
2788 
2789 #else	/* TESTING */
2790 
2791 	testing_t	*testing = subdriver->testing;
2792 	int		i;
2793 
2794 	memset(buf, 0, buflen);
2795 
2796 	upsdebugx(3, "send: '%.*s'", (int)strcspn(cmd, "\r"), cmd);
2797 
2798 	for (i = 0; cmd && testing[i].cmd; i++) {
2799 
2800 		if (strcasecmp(cmd, testing[i].cmd)) {
2801 			continue;
2802 		}
2803 
2804 		upsdebugx(3, "read: '%.*s'", (int)strcspn(testing[i].answer, "\r"), testing[i].answer);
2805 
2806 		/* If requested to do so and this is the case, try to preserve inner '\0's (treat answer as a sequence of bytes) */
2807 		if (testing[i].answer_len > 0 && strlen(testing[i].answer) < (size_t)testing[i].answer_len) {
2808 
2809 			size_t	len;
2810 
2811 			len = buflen <= (size_t)testing[i].answer_len ? buflen - 1 : (size_t)testing[i].answer_len;
2812 			len = len <= sizeof(testing[i].answer) ? len : sizeof(testing[i].answer);
2813 
2814 			memcpy(buf, testing[i].answer, len);
2815 			upsdebug_hex(4, "read", buf, (int)len);
2816 
2817 			return len;
2818 
2819 		}
2820 
2821 		return snprintf(buf, buflen, "%s", testing[i].answer);
2822 
2823 	}
2824 
2825 	/* If the driver expects some kind of reply in case of error.. */
2826 	if (subdriver->rejected != NULL) {
2827 
2828 		/* ..fulfill its expectations.. */
2829 		upsdebugx(3, "read: '%.*s'", (int)strcspn(subdriver->rejected, "\r"), subdriver->rejected);
2830 		return snprintf(buf, buflen, "%s", subdriver->rejected);
2831 
2832 	/* ..otherwise.. */
2833 	} else {
2834 
2835 		/* ..echo back the command */
2836 		upsdebugx(3, "read: '%.*s'", (int)strcspn(cmd, "\r"), cmd);
2837 		return snprintf(buf, buflen, "%s", cmd);
2838 
2839 	}
2840 
2841 #endif	/* TESTING */
2842 }
2843 
2844 /* See header file for details.
2845  * Interpretation is done in ups_status_set(). */
update_status(const char * value)2846 void	update_status(const char *value)
2847 {
2848 	status_lkp_t	*status_item;
2849 	int		clear = 0;
2850 
2851 	upsdebugx(5, "%s: %s", __func__, value);
2852 
2853 	if (*value == '!') {
2854 		value++;
2855 		clear = 1;
2856 	}
2857 
2858 	for (status_item = status_info; status_item->status_str != NULL ; status_item++) {
2859 
2860 		if (strcasecmp(status_item->status_str, value))
2861 			continue;
2862 
2863 		if (clear) {
2864 			ups_status &= ~status_item->status_mask;
2865 		} else {
2866 			ups_status |= status_item->status_mask;
2867 		}
2868 
2869 		return;
2870 	}
2871 
2872 	upsdebugx(5, "%s: Warning! %s not in list of known values", __func__, value);
2873 }
2874 
2875 /* Choose subdriver */
subdriver_matcher(void)2876 static int	subdriver_matcher(void)
2877 {
2878 	const char	*protocol = getval("protocol");
2879 	int		i;
2880 
2881 	/* Select the subdriver for this device */
2882 	for (i = 0; subdriver_list[i] != NULL; i++) {
2883 
2884 		int	j;
2885 
2886 		/* If protocol is set in ups.conf, use it */
2887 		if (protocol) {
2888 
2889 			char	subdrv_name[SMALLBUF];
2890 
2891 			/* Get rid of subdriver version */
2892 			snprintf(subdrv_name, sizeof(subdrv_name), "%.*s", (int)strcspn(subdriver_list[i]->name, " "), subdriver_list[i]->name);
2893 
2894 			if (strcasecmp(subdrv_name, protocol)) {
2895 				upsdebugx(2, "Skipping protocol %s", subdriver_list[i]->name);
2896 				continue;
2897 			}
2898 
2899 		}
2900 
2901 		/* Give every subdriver some tries */
2902 		for (j = 0; j < MAXTRIES; j++) {
2903 
2904 			subdriver = subdriver_list[i];
2905 
2906 			if (subdriver->claim()) {
2907 				break;
2908 			}
2909 
2910 			subdriver = NULL;
2911 
2912 		}
2913 
2914 		if (subdriver != NULL)
2915 			break;
2916 
2917 	}
2918 
2919 	if (!subdriver) {
2920 		upslogx(LOG_ERR, "Device not supported!");
2921 		return 0;
2922 	}
2923 
2924 	upslogx(LOG_INFO, "Using protocol: %s", subdriver->name);
2925 
2926 	return 1;
2927 }
2928 
2929 /* Set vars boundaries */
qx_set_var(item_t * item)2930 static void	qx_set_var(item_t *item)
2931 {
2932 	if (!(item->qxflags & QX_FLAG_NONUT))
2933 		dstate_setflags(item->info_type, item->info_flags);
2934 
2935 	/* Set max length for strings, if needed */
2936 	if (item->info_flags & ST_FLAG_STRING && !(item->qxflags & QX_FLAG_NONUT))
2937 		dstate_setaux(item->info_type, strtol(item->info_rw[0].value, NULL, 10));
2938 
2939 	/* Set enum list */
2940 	if (item->qxflags & QX_FLAG_ENUM) {
2941 
2942 		info_rw_t	*envalue;
2943 		char		buf[LARGEBUF] = "";
2944 
2945 		/* Loop on all existing values */
2946 		for (envalue = item->info_rw; envalue != NULL && strlen(envalue->value) > 0; envalue++) {
2947 
2948 			if (envalue->preprocess && envalue->preprocess(envalue->value, sizeof(envalue->value)))
2949 				continue;
2950 
2951 			/* This item is not available yet in NUT, so publish these data in the logs */
2952 			if (item->qxflags & QX_FLAG_NONUT) {
2953 
2954 				snprintfcat(buf, sizeof(buf), " %s", envalue->value);
2955 
2956 			/* This item is available in NUT, add its enum to the variable */
2957 			} else {
2958 
2959 				dstate_addenum(item->info_type, "%s", envalue->value);
2960 
2961 			}
2962 
2963 		}
2964 
2965 		if (item->qxflags & QX_FLAG_NONUT)
2966 			upslogx(LOG_INFO, "%s, settable values:%s", item->info_type, strlen(buf) > 0 ? buf : " none");
2967 
2968 	}
2969 
2970 	/* Set range */
2971 	if (item->qxflags & QX_FLAG_RANGE) {
2972 
2973 		info_rw_t	*rvalue, *from = NULL, *to = NULL;
2974 		int		ok = 0;
2975 
2976 		/* Loop on all existing values */
2977 		for (rvalue = item->info_rw; rvalue != NULL && strlen(rvalue->value) > 0; rvalue++) {
2978 
2979 			if (rvalue->preprocess && rvalue->preprocess(rvalue->value, sizeof(rvalue->value)))
2980 				continue;
2981 
2982 			if (!from) {
2983 				from = rvalue;
2984 				continue;
2985 			}
2986 
2987 			to = rvalue;
2988 
2989 			/* This item is not available yet in NUT, so publish these data in the logs */
2990 			if (item->qxflags & QX_FLAG_NONUT) {
2991 
2992 				upslogx(LOG_INFO, "%s, settable range: %s..%s",
2993 					item->info_type, from->value, to->value);
2994 				ok++;
2995 
2996 			/* This item is available in NUT, add its range to the variable */
2997 			} else {
2998 				long lFrom = strtol(from->value, NULL, 10),
2999 					lTo = strtol(to->value, NULL, 10);
3000 
3001 				if (lFrom > INT_MAX || lTo > INT_MAX) {
3002 					upslogx(LOG_INFO,
3003 						"%s, settable range exceeds INT_MAX: %ld..%ld",
3004 						item->info_type, lFrom, lTo);
3005 				} else {
3006 					dstate_addrange(item->info_type, (int)lFrom, (int)lTo);
3007 				}
3008 			}
3009 
3010 			from = NULL;
3011 			to = NULL;
3012 
3013 		}
3014 
3015 		/* This item is not available yet in NUT and we weren't able to get its range; let people know it */
3016 		if ((item->qxflags & QX_FLAG_NONUT) && !ok)
3017 			upslogx(LOG_INFO, "%s, settable range: none", item->info_type);
3018 
3019 	}
3020 }
3021 
3022 /* Walk UPS variables and set elements of the qx2nut array. */
qx_ups_walk(walkmode_t mode)3023 static bool_t	qx_ups_walk(walkmode_t mode)
3024 {
3025 	item_t	*item;
3026 	int	retcode;
3027 
3028 	/* Clear batt.{chrg,runt}.act for guesstimation */
3029 	if (mode == QX_WALKMODE_FULL_UPDATE) {
3030 		batt.runt.act = -1;
3031 		batt.chrg.act = -1;
3032 	}
3033 
3034 	/* Clear data from previous_item */
3035 	memset(previous_item.command, 0, sizeof(previous_item.command));
3036 	memset(previous_item.answer, 0, sizeof(previous_item.answer));
3037 
3038 	/* 3 modes: QX_WALKMODE_INIT, QX_WALKMODE_QUICK_UPDATE and QX_WALKMODE_FULL_UPDATE */
3039 
3040 	/* Device data walk */
3041 	for (item = subdriver->qx2nut; item->info_type != NULL; item++) {
3042 
3043 		/* Skip this item */
3044 		if (item->qxflags & QX_FLAG_SKIP)
3045 			continue;
3046 
3047 		upsdebugx(10, "%s: processing: %s", __func__, item->info_type);
3048 
3049 		/* Filter data according to mode */
3050 		switch (mode)
3051 		{
3052 		/* Device capabilities enumeration */
3053 		case QX_WALKMODE_INIT:
3054 
3055 			/* Special case for handling server side variables */
3056 			if (item->qxflags & QX_FLAG_ABSENT) {
3057 
3058 				/* Already set */
3059 				if (dstate_getinfo(item->info_type))
3060 					continue;
3061 
3062 				dstate_setinfo(item->info_type, "%s", item->dfl);
3063 
3064 				/* Set var flags/range/enum */
3065 				qx_set_var(item);
3066 
3067 				continue;
3068 			}
3069 
3070 			/* Allow duplicates for these NUT variables */
3071 			if (!strncmp(item->info_type, "ups.alarm", 9) || !strncmp(item->info_type, "ups.status", 10))
3072 				break;
3073 
3074 			/* This one doesn't exist yet */
3075 			if (dstate_getinfo(item->info_type) == NULL)
3076 				break;
3077 
3078 			continue;
3079 
3080 		case QX_WALKMODE_QUICK_UPDATE:
3081 
3082 			/* Quick update only deals with status and alarms! */
3083 			if (!(item->qxflags & QX_FLAG_QUICK_POLL))
3084 				continue;
3085 
3086 			break;
3087 
3088 		case QX_WALKMODE_FULL_UPDATE:
3089 
3090 			/* These don't need polling after initinfo() */
3091 			if (item->qxflags & (QX_FLAG_ABSENT | QX_FLAG_CMD | QX_FLAG_SETVAR | QX_FLAG_STATIC))
3092 				continue;
3093 
3094 			/* These need to be polled after user changes (setvar / instcmd) */
3095 			if ((item->qxflags & QX_FLAG_SEMI_STATIC) && (data_has_changed == FALSE))
3096 				continue;
3097 
3098 			break;
3099 
3100 #if (defined HAVE_PRAGMA_GCC_DIAGNOSTIC_PUSH_POP) && (defined HAVE_PRAGMA_GCC_DIAGNOSTIC_IGNORED_COVERED_SWITCH_DEFAULT)
3101 # pragma GCC diagnostic push
3102 # pragma GCC diagnostic ignored "-Wcovered-switch-default"
3103 #endif
3104 	/* All enum cases defined as of the time of coding
3105 	 * have been covered above. Handle later definitions,
3106 	 * memory corruptions and buggy inputs below...
3107 	 */
3108 		default:
3109 			fatalx(EXIT_FAILURE, "%s: unknown update mode!", __func__);
3110 #if (defined HAVE_PRAGMA_GCC_DIAGNOSTIC_PUSH_POP) && (defined HAVE_PRAGMA_GCC_DIAGNOSTIC_IGNORED_COVERED_SWITCH_DEFAULT)
3111 # pragma GCC diagnostic pop
3112 #endif
3113 
3114 		}
3115 
3116 		/* Instant commands */
3117 		if (item->qxflags & QX_FLAG_CMD) {
3118 			dstate_addcmd(item->info_type);
3119 			continue;
3120 		}
3121 
3122 		/* Setvars */
3123 		if (item->qxflags & QX_FLAG_SETVAR) {
3124 
3125 			if (item->qxflags & QX_FLAG_NONUT) {
3126 				setvar(item->info_type, NULL);
3127 				item->qxflags |= QX_FLAG_SKIP;
3128 			}
3129 
3130 			continue;
3131 
3132 		}
3133 
3134 		/* Check whether the previous item uses the same command and then use its answer, if available.. */
3135 		if (strlen(previous_item.command) > 0 && strlen(previous_item.answer) > 0 && !strcasecmp(previous_item.command, item->command)) {
3136 
3137 			snprintf(item->answer, sizeof(item->answer), "%s", previous_item.answer);
3138 
3139 			/* Process the answer */
3140 			retcode = qx_process_answer(item, strlen(item->answer));
3141 
3142 		/* ..otherwise: execute command to get answer from the UPS */
3143 		} else {
3144 
3145 			retcode = qx_process(item, NULL);
3146 
3147 		}
3148 
3149 		/* Record item as previous_item */
3150 		snprintf(previous_item.command, sizeof(previous_item.command), "%s", item->command);
3151 		snprintf(previous_item.answer, sizeof(previous_item.answer), "%s", item->answer);
3152 
3153 		if (retcode) {
3154 
3155 			/* Clear data from the item */
3156 			memset(item->answer, 0, sizeof(item->answer));
3157 			memset(item->value, 0, sizeof(item->value));
3158 
3159 			if (item->qxflags & QX_FLAG_QUICK_POLL)
3160 				return FALSE;
3161 
3162 			if (mode == QX_WALKMODE_INIT)
3163 				/* Skip this item from now on */
3164 				item->qxflags |= QX_FLAG_SKIP;
3165 
3166 			/* Don't know what happened, try again later... */
3167 			continue;
3168 
3169 		}
3170 
3171 		/* Process the value we got back (set status bits and set the value of other parameters) */
3172 		retcode = ups_infoval_set(item);
3173 
3174 		/* Clear data from the item */
3175 		memset(item->answer, 0, sizeof(item->answer));
3176 		memset(item->value, 0, sizeof(item->value));
3177 
3178 		/* Uh-oh! Some error! */
3179 		if (retcode == -1) {
3180 
3181 			if (item->qxflags & QX_FLAG_QUICK_POLL)
3182 				return FALSE;
3183 
3184 			continue;
3185 
3186 		}
3187 
3188 		/* Set var flags/range/enum (not for ups.{alarm.status}, hence the retcode check) */
3189 		if (retcode && mode == QX_WALKMODE_INIT) {
3190 			qx_set_var(item);
3191 		}
3192 
3193 	}
3194 
3195 	/* Update battery guesstimation */
3196 	if (mode == QX_WALKMODE_FULL_UPDATE && (d_equal(batt.runt.act, -1) || d_equal(batt.chrg.act, -1))) {
3197 
3198 		if (getval("runtimecal")) {
3199 
3200 			time_t	battery_now;
3201 
3202 			time(&battery_now);
3203 
3204 			/* OL */
3205 			if (ups_status & STATUS(OL)) {
3206 
3207 				batt.runt.est += batt.runt.nom * difftime(battery_now, battery_lastpoll) / batt.chrg.time;
3208 				if (batt.runt.est > batt.runt.nom) {
3209 					batt.runt.est = batt.runt.nom;
3210 				}
3211 
3212 			/* OB */
3213 			} else {
3214 
3215 				batt.runt.est -= load.eff * difftime(battery_now, battery_lastpoll);
3216 				if (batt.runt.est < 0) {
3217 					batt.runt.est = 0;
3218 				}
3219 
3220 			}
3221 
3222 			if (d_equal(batt.chrg.act, -1))
3223 				dstate_setinfo("battery.charge", "%.0f", 100 * batt.runt.est / batt.runt.nom);
3224 
3225 			if (d_equal(batt.runt.act, -1) && !qx_load())
3226 				dstate_setinfo("battery.runtime", "%.0f", batt.runt.est / load.eff);
3227 
3228 			battery_lastpoll = battery_now;
3229 
3230 		} else {
3231 
3232 			qx_battery();
3233 
3234 		}
3235 	}
3236 
3237 	return TRUE;
3238 }
3239 
3240 /* Convert the local status information to NUT format and set NUT alarms. */
ups_alarm_set(void)3241 static void	ups_alarm_set(void)
3242 {
3243 	if (ups_status & STATUS(RB)) {
3244 		alarm_set("Replace battery!");
3245 	}
3246 	if (ups_status & STATUS(FSD)) {
3247 		alarm_set("Shutdown imminent!");
3248 	}
3249 }
3250 
3251 /* Convert the local status information to NUT format and set NUT status. */
ups_status_set(void)3252 static void	ups_status_set(void)
3253 {
3254 	if (ups_status & STATUS(OL)) {
3255 		status_set("OL");		/* On line */
3256 	} else {
3257 		status_set("OB");		/* On battery */
3258 	}
3259 	if (ups_status & STATUS(DISCHRG)) {
3260 		status_set("DISCHRG");		/* Discharging */
3261 	}
3262 	if (ups_status & STATUS(CHRG)) {
3263 		status_set("CHRG");		/* Charging */
3264 	}
3265 	if (ups_status & STATUS(LB)) {
3266 		status_set("LB");		/* Low battery */
3267 	}
3268 	if (ups_status & STATUS(OVER)) {
3269 		status_set("OVER");		/* Overload */
3270 	}
3271 	if (ups_status & STATUS(RB)) {
3272 		status_set("RB");		/* Replace battery */
3273 	}
3274 	if (ups_status & STATUS(TRIM)) {
3275 		status_set("TRIM");		/* SmartTrim */
3276 	}
3277 	if (ups_status & STATUS(BOOST)) {
3278 		status_set("BOOST");		/* SmartBoost */
3279 	}
3280 	if (ups_status & STATUS(BYPASS)) {
3281 		status_set("BYPASS");		/* On bypass */
3282 	}
3283 	if (ups_status & STATUS(OFF)) {
3284 		status_set("OFF");		/* UPS is off */
3285 	}
3286 	if (ups_status & STATUS(CAL)) {
3287 		status_set("CAL");		/* Calibration */
3288 	}
3289 	if (ups_status & STATUS(FSD)) {
3290 		status_set("FSD");		/* Forced shutdown */
3291 	}
3292 }
3293 
3294 /* See header file for details. */
find_nut_info(const char * varname,const unsigned long flag,const unsigned long noflag)3295 item_t	*find_nut_info(const char *varname, const unsigned long flag, const unsigned long noflag)
3296 {
3297 	item_t	*item;
3298 
3299 	for (item = subdriver->qx2nut; item->info_type != NULL; item++) {
3300 
3301 		if (strcasecmp(item->info_type, varname))
3302 			continue;
3303 
3304 		if (flag && ((item->qxflags & flag) != flag))
3305 			continue;
3306 
3307 		if (noflag && (item->qxflags & noflag))
3308 			continue;
3309 
3310 		return item;
3311 	}
3312 
3313 	upsdebugx(2, "%s: info type %s not found", __func__, varname);
3314 	return NULL;
3315 }
3316 
3317 /* Process the answer we got back from the UPS
3318  * Return -1 on errors, 0 on success */
qx_process_answer(item_t * item,const size_t len)3319 static int	qx_process_answer(item_t *item, const size_t len)
3320 {
3321 	/* Query rejected by the UPS */
3322 	if (subdriver->rejected && !strcasecmp(item->answer, subdriver->rejected)) {
3323 		upsdebugx(2, "%s: query rejected by the UPS (%s)", __func__, item->info_type);
3324 		return -1;
3325 	}
3326 
3327 	/* Short reply */
3328 	if (item->answer_len && len < item->answer_len) {
3329 		upsdebugx(2, "%s: short reply (%s)", __func__, item->info_type);
3330 		return -1;
3331 	}
3332 
3333 	/* Wrong leading character */
3334 	if (item->leading && item->answer[0] != item->leading) {
3335 		upsdebugx(2, "%s: %s - invalid start character [%02x], expected [%02x]", __func__, item->info_type, item->answer[0], item->leading);
3336 		return -1;
3337 	}
3338 
3339 	/* Check boundaries */
3340 	if (item->to && item->to < item->from) {
3341 		upsdebugx(1, "%s: in %s, starting char's position (%d) follows ending char's one (%d)", __func__, item->info_type, item->from, item->to);
3342 		return -1;
3343 	}
3344 
3345 	/* Get value */
3346 	if (strlen(item->answer)) {
3347 		snprintf(item->value, sizeof(item->value), "%.*s", item->to ? 1 + item->to - item->from : (int)strcspn(item->answer, "\r") - item->from, item->answer + item->from);
3348 	} else {
3349 		snprintf(item->value, sizeof(item->value), "%s", "");
3350 	}
3351 
3352 	return 0;
3353 }
3354 
3355 /* See header file for details. */
qx_process(item_t * item,const char * command)3356 int	qx_process(item_t *item, const char *command)
3357 {
3358 	char	buf[sizeof(item->answer) - 1] = "", *cmd;
3359 	ssize_t	len;
3360 	size_t cmdlen = command ?
3361 		(strlen(command) >= SMALLBUF ? strlen(command) + 1 : SMALLBUF) :
3362 		(item->command && strlen(item->command) >= SMALLBUF ? strlen(item->command) + 1 : SMALLBUF);
3363 	size_t cmdsz = (sizeof(char) * cmdlen); /* in bytes, to be pedantic */
3364 
3365 	if ( !(cmd = xmalloc(cmdsz)) ) {
3366 		upslogx(LOG_ERR, "qx_process() failed to allocate buffer");
3367 		return -1;
3368 	}
3369 
3370 	/* Prepare the command to be used */
3371 	memset(cmd, 0, cmdsz);
3372 	snprintf(cmd, cmdsz, "%s", command ? command : item->command);
3373 
3374 	/* Preprocess the command */
3375 	if (
3376 		item->preprocess_command != NULL &&
3377 		item->preprocess_command(item, cmd, cmdsz) == -1
3378 	) {
3379 		upsdebugx(4, "%s: failed to preprocess command [%s]", __func__, item->info_type);
3380 		free (cmd);
3381 		return -1;
3382 	}
3383 
3384 	/* Send the command */
3385 	len = qx_command(cmd, buf, sizeof(buf));
3386 
3387 	memset(item->answer, 0, sizeof(item->answer));
3388 
3389 	if (len < 0 || len > INT_MAX) {
3390 		upsdebugx(4, "%s: failed to preprocess answer [%s]", __func__, item->info_type);
3391 		free (cmd);
3392 		return -1;
3393 	}
3394 
3395 	memcpy(item->answer, buf, sizeof(buf));
3396 
3397 	/* Preprocess the answer */
3398 	if (item->preprocess_answer != NULL) {
3399 		len = item->preprocess_answer(item, (int)len);
3400 		if (len < 0 || len > INT_MAX) {
3401 			upsdebugx(4, "%s: failed to preprocess answer [%s]", __func__, item->info_type);
3402 			/* Clear answer, preventing it from being reused by next items with same command */
3403 			memset(item->answer, 0, sizeof(item->answer));
3404 			free (cmd);
3405 			return -1;
3406 		}
3407 	}
3408 
3409 	free (cmd);
3410 
3411 	/* Process the answer to get the value */
3412 	return qx_process_answer(item, (size_t)len);
3413 }
3414 
3415 /* See header file for details. */
ups_infoval_set(item_t * item)3416 int	ups_infoval_set(item_t *item)
3417 {
3418 	char	value[SMALLBUF] = "";
3419 
3420 	/* Item need to be preprocessed? */
3421 	if (item->preprocess != NULL){
3422 
3423 		/* Process the value returned by the UPS to NUT standards */
3424 		if (item->preprocess(item, value, sizeof(value))) {
3425 			upsdebugx(4, "%s: failed to preprocess value [%s: %s]", __func__, item->info_type, item->value);
3426 			return -1;
3427 		}
3428 
3429 		/* Deal with status items */
3430 		if (!strncmp(item->info_type, "ups.status", 10)) {
3431 			if (strlen(value) > 0)
3432 				update_status(value);
3433 			return 0;
3434 		}
3435 
3436 		/* Deal with alarm items */
3437 		if (!strncmp(item->info_type, "ups.alarm", 9)) {
3438 			if (strlen(value) > 0)
3439 				alarm_set(value);
3440 			return 0;
3441 		}
3442 
3443 	} else {
3444 
3445 		snprintf(value, sizeof(value), "%s", item->value);
3446 
3447 		/* Cover most of the cases: either left/right filled with hashes, spaces or a mix of both */
3448 		if (item->qxflags & QX_FLAG_TRIM)
3449 			str_trim_m(value, "# ");
3450 
3451 		if (strncasecmp(item->dfl, "%s", 2)) {
3452 
3453 			if (strspn(value, "0123456789 .") != strlen(value)) {
3454 				upsdebugx(2, "%s: non numerical value [%s: %s]", __func__, item->info_type, value);
3455 				return -1;
3456 			}
3457 
3458 #ifdef HAVE_PRAGMAS_FOR_GCC_DIAGNOSTIC_IGNORED_FORMAT_NONLITERAL
3459 #pragma GCC diagnostic push
3460 #endif
3461 #ifdef HAVE_PRAGMA_GCC_DIAGNOSTIC_IGNORED_FORMAT_NONLITERAL
3462 #pragma GCC diagnostic ignored "-Wformat-nonliteral"
3463 #endif
3464 #ifdef HAVE_PRAGMA_GCC_DIAGNOSTIC_IGNORED_FORMAT_SECURITY
3465 #pragma GCC diagnostic ignored "-Wformat-security"
3466 #endif
3467 			snprintf(value, sizeof(value), item->dfl, strtod(value, NULL));
3468 #ifdef HAVE_PRAGMAS_FOR_GCC_DIAGNOSTIC_IGNORED_FORMAT_NONLITERAL
3469 #pragma GCC diagnostic pop
3470 #endif
3471 		}
3472 
3473 	}
3474 
3475 	if (item->qxflags & QX_FLAG_NONUT) {
3476 		upslogx(LOG_INFO, "%s: %s", item->info_type, value);
3477 		return 1;
3478 	}
3479 
3480 	if (!strlen(value)) {
3481 		upsdebugx(1, "%s: non significant value [%s]", __func__, item->info_type);
3482 		return -1;
3483 	}
3484 
3485 	dstate_setinfo(item->info_type, "%s", value);
3486 
3487 	/* Fill batt.{chrg,runt}.act for guesstimation */
3488 	if (!strcasecmp(item->info_type, "battery.charge"))
3489 		batt.chrg.act = strtol(value, NULL, 10);
3490 	else if (!strcasecmp(item->info_type, "battery.runtime"))
3491 		batt.runt.act = strtol(value, NULL, 10);
3492 
3493 	return 1;
3494 }
3495 
3496 /* See header file for details. */
qx_status(void)3497 unsigned int	qx_status(void)
3498 {
3499 	return ups_status;
3500 }
3501