[Nut-upsdev] [RFC apcsmart V3 11/18] drivers/apcsmart.c: add upsdrv_shutdown_advanced() and upsdrv_shutdown_simple()

Michal Soltys soltys at ziu.info
Sat Mar 5 10:38:28 UTC 2011


Add functions for simple and advanced shutdown control.

Signed-off-by: Michal Soltys <soltys at ziu.info>
---
 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




More information about the Nut-upsdev mailing list