Add functions for simple and advanced shutdown control.

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

diff --git a/drivers/apcsmart.c b/drivers/apcsmart.c
index eb261d9..3ebbc50 100644
--- a/drivers/apcsmart.c
+++ b/drivers/apcsmart.c
@@ -958,6 +958,106 @@ static int (*sdlist[])(int) = {
 
 #define SDCNT          6
 
+static void upsdrv_shutdown_simple(int status)
+{
+       unsigned int sdtype = 0;
+       char *strval;
+
+       if ((strval = getval("sdtype"))) {
+               errno = 0;
+               sdtype = strtol(strval, NULL, 10);
+               if (errno || sdtype < 0 || sdtype > 6)
+                       sdtype = 0;
+       }
+
+       switch (sdtype) {
+
+       case 6:         /* hard hibernate */
+               sdcmd_ATn(3);
+               break;
+       case 5:         /* "hack nn" hard hibernate */
+               sdcmd_ATn(2);
+               break;
+       case 4:         /* special hack for CS 350 and similar models */
+               sdcmd_CS(status);
+               break;
+
+       case 3:         /* delayed poweroff */
+               sdcmd_K(0);
+               break;
+
+       case 2:         /* instant poweroff */
+               sdcmd_Z(0);
+               break;
+       case 1:
+               /*
+                * Send a combined set of shutdown commands which can work
+                * better if the UPS gets power during shutdown process
+                * Specifically it sends both the soft shutdown 'S' and the
+                * hard hibernate '@nnn' commands
+                */
+               upsdebugx(1, "UPS - currently %s - sending soft/hard hibernate 
commands",
+                       (status & APC_STAT_OL) ? "on-line" : "on battery");
+
+               /* S works only when OB */
+               if ((status & APC_STAT_OB) && sdcmd_S(0))
+                       break;
+               sdcmd_ATn(3);
+               break;
+
+       default:
+               /*
+                * Send @nnn or S, depending on OB / OL status
+                */
+               if (status & APC_STAT_OL)               /* on line */
+                       sdcmd_ATn(3);
+               else
+                       sdcmd_S(0);
+       }
+}
+
+static void upsdrv_shutdown_advanced(int status)
+{
+       const char *strval;
+       const char deforder[] = {48 + SDIDX_S,
+                                48 + SDIDX_AT3N,
+                                48 + SDIDX_K,
+                                48 + SDIDX_Z,
+                                 0};
+       size_t i;
+       int n;
+
+       strval = getval("advorder");
+
+       /* sanitize advorder */
+
+       if (!strval || !strlen(strval) || strlen(strval) > SDCNT)
+               strval = deforder;
+       for (i = 0; i < strlen(strval); i++) {
+               if (strval[i] - 48 < 0 || strval[i] - 48 >= SDCNT) {
+                       strval = deforder;
+                       break;
+               }
+       }
+
+       /*
+        * try each method in the list with a little bit of handling in certain
+        * cases
+        */
+
+       for (i = 0; i < strlen(strval); i++) {
+               if (strval[i] - 48 == SDIDX_CS) {
+                       n = status;
+               } else if (strval[i] - 48 == SDIDX_AT3N) {
+                       n = 3;
+               } else if (strval[i] - 48 == SDIDX_AT2N) {
+                       n = 2;
+               }
+               if (sdlist[strval[i] - 48](n))
+                       break;  /* finish if command succeeded */
+       }
+}
+
 /* 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