[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