Imported Upstream version 2.6.4

This commit is contained in:
Arnaud Quette 2012-06-01 15:55:19 +02:00
parent fad6ced6f6
commit fefe62b2bd
257 changed files with 6020 additions and 1394 deletions

View file

@ -6,8 +6,10 @@
* emes -at- geomer.de *
* All rights reserved.*
Copyright (C) 2004 Kjell Claesson <kjell.claesson-at-epost.tidanet.se>
and Tore Ørpetveit <tore-at-orpetveit.net>
Copyright (C)
2004 Kjell Claesson <kjell.claesson-at-epost.tidanet.se>
2004 Tore Ørpetveit <tore-at-orpetveit.net>
2011 - 2012 Arnaud Quette <ArnaudQuette@Eaton.com>
Thanks to Tore Ørpetveit <tore-at-orpetveit.net> that sent me the
manuals for bcm/xcp.
@ -124,7 +126,7 @@ TODO List:
#include "bcmxcp.h"
#define DRIVER_NAME "BCMXCP UPS driver"
#define DRIVER_VERSION "0.25"
#define DRIVER_VERSION "0.26"
#define MAX_NUT_NAME_LENGTH 128
#define NUT_OUTLET_POSITION 7
@ -157,6 +159,7 @@ static int init_outlet(unsigned char len);
static int instcmd(const char *cmdname, const char *extra);
static int setvar (const char *varname, const char *val);
static const char *nut_find_infoval(info_lkp_t *xcp2info, const double value);
const char *FreqTol[3] = {"+/-2%", "+/-5%", "+/-7"};
const char *ABMStatus[4] = {"Charging", "Discharging", "Floating", "Resting"};
@ -166,6 +169,32 @@ int nphases = 0;
int outlet_block_len = 0;
const char *cpu_name[5] = {"Cont:", "Inve:", "Rect:", "Netw:", "Disp:"};
/* Battery test results */
info_lkp_t batt_test_info[] = {
{ 0, "No test initiated", NULL },
{ 1, "In progress", NULL },
{ 2, "Done and passed", NULL },
{ 3, "Aborted", NULL },
{ 4, "Done and error", NULL },
{ 5, "Test scheduled", NULL },
/* Not sure about the meaning of the below ones! */
{ 6, NULL, NULL }, /* The string was present but it has now been removed */
{ 7, NULL, NULL }, /* The string was not installed at the last power up */
{ 0, NULL, NULL }
};
/* allocate storage for shared variables (extern in bcmxcp.h) */
BCMXCP_METER_MAP_ENTRY_t
bcmxcp_meter_map[BCMXCP_METER_MAP_MAX];
BCMXCP_ALARM_MAP_ENTRY_t
bcmxcp_alarm_map[BCMXCP_ALARM_MAP_MAX];
BCMXCP_STATUS_t
bcmxcp_status;
/* get_word function from nut driver metasys.c */
int get_word(const unsigned char *buffer) /* return an integer reading a word in the supplied buffer */
{
@ -583,7 +612,12 @@ void init_alarm_map()
bcmxcp_alarm_map[BCMXCP_ALARM_CHARGER_ON_COMMAND].alarm_desc = "CHARGER_ON_COMMAND";
bcmxcp_alarm_map[BCMXCP_ALARM_CHARGER_OFF_COMMAND].alarm_desc = "CHARGER_OFF_COMMAND";
bcmxcp_alarm_map[BCMXCP_ALARM_UPS_NORMAL].alarm_desc = "UPS_NORMAL";
bcmxcp_alarm_map[BCMXCP_ALARM_INVERTER_PHASE_ROTATION].alarm_desc = "INVERTER_PHASE_ROTATION";
bcmxcp_alarm_map[BCMXCP_ALARM_UPS_OFF].alarm_desc = "UPS_OFF";
bcmxcp_alarm_map[BCMXCP_ALARM_EXTERNAL_COMMUNICATION_FAILURE].alarm_desc = "EXTERNAL_COMMUNICATION_FAILURE";
bcmxcp_alarm_map[BCMXCP_ALARM_BATTERY_TEST_INPROGRESS].alarm_desc = "BATTERY_TEST_INPROGRESS";
bcmxcp_alarm_map[BCMXCP_ALARM_SYSTEM_TEST_INPROGRESS].alarm_desc = "SYSTEM_TEST_INPROGRESS";
bcmxcp_alarm_map[BCMXCP_ALARM_BATTERY_TEST_ABORTED].alarm_desc = "BATTERY_TEST_ABORTED";
}
@ -936,7 +970,7 @@ void init_config(void)
int voltage = 0, res, len;
char sValue[17];
res = command_read_sequence(PW_CONFIG_BLOC_REQ, answer);
res = command_read_sequence(PW_CONFIG_BLOCK_REQ, answer);
if (res <= 0)
fatal_with_errno(EXIT_FAILURE, "Could not communicate with the ups");
@ -1104,12 +1138,12 @@ void upsdrv_initinfo(void)
dstate_setinfo("ups.firmware", "%s", pTmp);
free(pTmp);
/* Increment index to point at end of CPU bytes. */
iIndex += len * 2;
}
free(pTmp);
/* Get rating in kVA, if present */
if ((iRating = answer[iIndex++]) > 0)
iRating *= 1000;
@ -1244,6 +1278,8 @@ void upsdrv_updateinfo(void)
char sValue[128];
int iIndex, res;
float output, max_output, fValue = 0.0f;
int batt_status = 0;
const char *nutvalue;
/* Get info from UPS */
res = command_read_sequence(PW_METER_BLOCK_REQ, answer);
@ -1332,6 +1368,14 @@ void upsdrv_updateinfo(void)
if (iIndex == BCMXCP_ALARM_BATTERY_LOW) {
bcmxcp_status.alarm_low_battery = 1;
}
if (iIndex == BCMXCP_ALARM_BATTERY_TEST_FAILED) {
bcmxcp_status.alarm_replace_battery = 1;
}
if (iIndex == BCMXCP_ALARM_BATTERY_NEEDS_SERVICE) {
bcmxcp_status.alarm_replace_battery = 1;
}
}
}
}
@ -1404,10 +1448,38 @@ void upsdrv_updateinfo(void)
status_set("OB");
if (bcmxcp_status.alarm_low_battery)
status_set("LB");
if (bcmxcp_status.alarm_replace_battery)
status_set("RB");
status_commit();
}
/* Get battery info from UPS, if exist */
res = command_read_sequence(PW_BATTERY_REQ, answer);
if (res <= 0)
{
upsdebugx(1, "Failed to read Battery Status from UPS");
}
else
{
/* Only parse the status (first byte)
* Powerware 5115 RM output:
* 02 00 78 1d 42 00 e0 17 42 1e 00 00 00 00 00 00 00 00 00 01 03
* Powerware 9130 output:
* 03 0a d7 25 42 0a d7 25 42 00 9a 19 6d 43 cd cc 4c 3e 01 00 01 03
*/
upsdebug_hex(2, "Battery Status", answer, res);
batt_status = answer[0];
if ((nutvalue = nut_find_infoval(batt_test_info, batt_status)) != NULL) {
dstate_setinfo("ups.test.result", "%s", nutvalue);
upsdebugx(2, "Battery Status = %s (%i)", nutvalue, batt_status);
}
else {
upsdebugx(1, "Failed to extract Battery Status from answer");
}
}
dstate_dataok();
}
@ -1428,7 +1500,7 @@ void upsdrv_shutdown(void)
it doesn't respond at first if possible */
send_write_command(AUTHOR, 4);
sleep(1); /* Need to. Have to wait at least 0,25 sec max 16 sec */
sleep(PW_SLEEP); /* Need to. Have to wait at least 0,25 sec max 16 sec */
cbuf[0] = PW_LOAD_OFF_RESTART;
cbuf[1] = (unsigned char)(bcmxcp_status.shutdowndelay & 0x00ff); /* "delay" sec delay for shutdown, */
@ -1493,12 +1565,12 @@ static int instcmd(const char *cmdname, const char *extra)
) {
send_write_command(AUTHOR, 4);
sleep(1); /* Need to. Have to wait at least 0,25 sec max 16 sec */
sleep(PW_SLEEP); /* Need to. Have to wait at least 0,25 sec max 16 sec */
/* Get the shutdown delay, if any */
snprintf(varname, sizeof(varname)-1, "outlet.%c.delay.shutdown", cmdname[7]);
if ((varvalue = dstate_getinfo(varname)) != NULL) {
sddelay = atoi(dstate_getinfo(varname));
sddelay = atoi(varvalue);
}
cbuf[0] = PW_LOAD_OFF_RESTART;
@ -1546,7 +1618,7 @@ static int instcmd(const char *cmdname, const char *extra)
if (!strcasecmp(cmdname, "shutdown.return")) {
send_write_command(AUTHOR, 4);
sleep(1); /* Need to. Have to wait at least 0,25 sec max 16 sec */
sleep(PW_SLEEP); /* Need to. Have to wait at least 0,25 sec max 16 sec */
cbuf[0] = PW_LOAD_OFF_RESTART;
cbuf[1] = (unsigned char)(bcmxcp_status.shutdowndelay & 0x00ff); /* "delay" sec delay for shutdown, */
@ -1590,7 +1662,7 @@ static int instcmd(const char *cmdname, const char *extra)
if (!strcasecmp(cmdname, "shutdown.stayoff")) {
send_write_command(AUTHOR, 4);
sleep(1); /* Need to. Have to wait at least 0,25 sec max 16 sec */
sleep(PW_SLEEP); /* Need to. Have to wait at least 0,25 sec max 16 sec */
res = command_read_sequence(PW_UPS_OFF, answer);
if (res <= 0) {
@ -1626,10 +1698,13 @@ static int instcmd(const char *cmdname, const char *extra)
}
/* Note: test result will be parsed from Battery status block,
* part of the update loop, and published into ups.test.result
*/
if (!strcasecmp(cmdname, "test.battery.start")) {
send_write_command(AUTHOR, 4);
sleep(1); /* Need to. Have to wait at least 0,25 sec max 16 sec */
sleep(PW_SLEEP); /* Need to. Have to wait at least 0,25 sec max 16 sec */
cbuf[0] = PW_INIT_BAT_TEST;
cbuf[1] = 0x0A; /* 10 sec start delay for test.*/
@ -1665,12 +1740,6 @@ static int instcmd(const char *cmdname, const char *extra)
break;
}
}
/* Get test info from UPS ?
Should we wait for 50 sec and get the
answer from the test.
Or return, as we may lose line power
and need to do a shutdown.*/
}
upslogx(LOG_NOTICE, "instcmd: unknown command [%s]", cmdname);
@ -1715,8 +1784,7 @@ int setvar (const char *varname, const char *val)
}
send_write_command(AUTHOR, 4);
/* Need to. Have to wait at least 0.25 sec max 16 sec */
sleep (1);
sleep(PW_SLEEP); /* Need to. Have to wait at least 0,25 sec max 16 sec */
outlet_num = varname[NUT_OUTLET_POSITION] - '0';
if (outlet_num < 1 || outlet_num > 9) {
@ -1781,4 +1849,28 @@ int setvar (const char *varname, const char *val)
return STAT_SET_INVALID;
}
/*******************************
* Extracted from usbhid-ups.c *
*******************************/
/* find the NUT value matching that XCP Item value */
static const char *nut_find_infoval(info_lkp_t *xcp2info, const double value)
{
info_lkp_t *info_lkp;
/* if a conversion function is defined, use 'value' as argument for it */
if (xcp2info->fun != NULL) {
return xcp2info->fun(value);
}
/* use 'value' as an index for a lookup in an array */
for (info_lkp = xcp2info; info_lkp->nut_value != NULL; info_lkp++) {
if (info_lkp->xcp_value == (long)value) {
upsdebugx(5, "nut_find_infoval: found %s (value: %ld)", info_lkp->nut_value, (long)value);
return info_lkp->nut_value;
}
}
upsdebugx(3, "hu_find_infoval: no matching INFO_* value for this XCP value (%g)", value);
return NULL;
}