Add functions that will be used for improved shutdown controls in next
patches.

Signed-off-by: Michal Soltys <[email protected]>
---
 drivers/apcsmart.c |  132 ++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 132 insertions(+), 0 deletions(-)

diff --git a/drivers/apcsmart.c b/drivers/apcsmart.c
index bb8d394..eb261d9 100644
--- a/drivers/apcsmart.c
+++ b/drivers/apcsmart.c
@@ -826,6 +826,138 @@ static int smartmode(void)
        return 0;       /* failure */
 }
 
+/*
+ * all shutdown commands should respond with 'OK' or '*'
+ */
+static int sdok(void)
+{
+       char temp[16];
+
+       ser_get_line(upsfd, temp, sizeof(temp), ENDCHAR, IGNCHARS, 
SER_WAIT_SEC, SER_WAIT_USEC);
+       upsdebugx(4, "sdok: got \"%s\"", temp);
+
+       if (!strcmp(temp, "*") || !strcmp(temp, "OK")) {
+               upsdebugx(4, "Last issued shutdown command succeeded");
+               return 1;
+       }
+
+       upsdebugx(1, "Last issued shutdown command failed");
+       return 0;
+}
+
+/* soft hibernate: S - working only when OB, otherwise ignored */
+static int sdcmd_S(int dummy)
+{
+       ser_flush_in(upsfd, IGNCHARS, nut_debug_level);
+
+       upsdebugx(1, "Issuing soft hibernate");
+       ser_send_char(upsfd, APC_CMD_SOFTDOWN);
+
+       return sdok();
+}
+
+/* soft hibernate, hack version for CS 350 */
+static int sdcmd_CS(int tval)
+{
+       upsdebugx(1, "Using CS 350 'force OB' shutdown method");
+       if (tval & APC_STAT_OL) {
+               upsdebugx(1, "On-line - forcing OB temporarily");
+               ser_send_char(upsfd, 'U');
+               usleep(UPSDELAY);
+       }
+       return sdcmd_S(tval);
+}
+
+/*
+ * hard hibernate: @nnn / @nn
+ * note: works differently for older and new models, see help function for
+ * detailed info
+ */
+static int sdcmd_ATn(int cnt)
+{
+       int n = 0, mmax, ret;
+       const char *strval;
+       char timer[4];
+
+       mmax = cnt == 2 ? 99 : 999;
+
+       if ((strval = getval("wugrace"))) {
+               errno = 0;
+               n = strtol(strval, NULL, 10);
+               if (errno || n < 0 || n > mmax)
+                       n = 0;
+       }
+
+       snprintf(timer, sizeof(timer), "%.*d", cnt, n);
+
+       ser_flush_in(upsfd, IGNCHARS, nut_debug_level);
+       upsdebugx(1, "Issuing hard hibernate with %d minutes additional wakeup 
delay", n*6);
+
+       ser_send_char(upsfd, APC_CMD_GRACEDOWN);
+       usleep(CMDLONGDELAY);
+       ser_send_pace(upsfd, UPSDELAY, timer);
+
+       ret = sdok();
+       if (ret || cnt == 3)
+               return ret;
+
+       /*
+        * "tricky" part - we tried @nn variation and it (unsurprisingly)
+        * failed; we have to abort the sequence with something bogus to have
+        * the clean state; newer upses will respond with 'NO', older will be
+        * silent (YMMV);
+        */
+       ser_send_char(upsfd, APC_CMD_GRACEDOWN);
+       usleep(UPSDELAY);
+       ser_flush_in(upsfd, IGNCHARS, nut_debug_level);
+
+       return 0;
+}
+
+/* shutdown: K - delayed poweroff */
+static int sdcmd_K(int dummy)
+{
+       ser_flush_in(upsfd, IGNCHARS, nut_debug_level);
+       upsdebugx(1, "Issuing delayed poweroff");
+
+       ser_send_char(upsfd, APC_CMD_SHUTDOWN);
+       usleep(CMDLONGDELAY);
+       ser_send_char(upsfd, APC_CMD_SHUTDOWN);
+
+       return sdok();
+}
+
+/* shutdown: Z - immediate poweroff */
+static int sdcmd_Z(int dummy)
+{
+       ser_flush_in(upsfd, IGNCHARS, nut_debug_level);
+       upsdebugx(1, "Issuing immediate poweroff");
+
+       ser_send_char(upsfd, APC_CMD_OFF);
+       usleep(CMDLONGDELAY);
+       ser_send_char(upsfd, APC_CMD_OFF);
+
+       return sdok();
+}
+
+static int (*sdlist[])(int) = {
+       sdcmd_S,
+       sdcmd_ATn,      /* for @nnn version */
+       sdcmd_K,
+       sdcmd_Z,
+       sdcmd_CS,
+       sdcmd_ATn,      /* for @nn version */
+};
+
+#define SDIDX_S                0
+#define SDIDX_AT3N     1
+#define SDIDX_K                2
+#define SDIDX_Z                3
+#define SDIDX_CS       4
+#define SDIDX_AT2N     5
+
+#define SDCNT          6
+
 /* power down the attached load immediately */
 void upsdrv_shutdown(void)
 {
-- 
1.7.2.1


_______________________________________________
Nut-upsdev mailing list
[email protected]
http://lists.alioth.debian.org/mailman/listinfo/nut-upsdev

Reply via email to