----------  Forwarded Message  ----------

Subject: [PATCH] New to nut project
Date: Friday, 6. November 2009
From: Patrick Levesque <patri...@verint.com>
To: Thomas Jarosch <thomas.jaro...@intra2net.com>

As requested, here is my patch file including all my modification to the 
2.4.1 
tarball from the web site.

On Friday 06 November 2009 05:41:29 you wrote:
> Hello Patrick,
> 
> On Wednesday, 4. November 2009 14:12:09 Levesque, Patrick wrote:
> > I have tried to support a TrippLite Internet350SER UPS using a serial
> > cable (The only connection on this model) using the 2.4 code branch.  It
> > uses the Protocol 1004 from the tripplite specification that can be use
> > either used on serial or USB device.  Since my device was only serial, I
> > worked only on the serial integration.  Since I found nothing in
> > tripplite.c, tripplite-hid.c, tripplitesu.c to support my model, I have
> > done trippliteser.c in order to support my unit.  Not all the
> > functionality are there but the core functionality is there.  Since it
> > is licence as GPLv2, I just want to push back my modifs to the community
> > but really don't know the procedure.
> 
> Do you know how diff/patch works? Just send your changes
> as unified diff (diff -u) to the devel list. Might be a good
> idea to prefix your mail subject with "[PATCH]".
> 
> If possible, try to prevent winmail.dat attachments on the mailing list,
> so people with a normal email client can open the attachment.
> 
> Cheers,
> Thomas
diff -crBN a/data/driver.list b/data/driver.list
*** a/data/driver.list	2009-02-17 04:20:45.000000000 -0500
--- b/data/driver.list	2009-09-01 13:53:08.000000000 -0400
***************
*** 627,632 ****
--- 627,633 ----
  "Tripp-Lite"	"AVR750U"	"USB"	"usbhid-ups"
  "Tripp-Lite"	"SmartOnline SU1500RTXL2ua"	"USB"	"usbhid-ups"
  "Tripp-Lite"	"smart2200RMXL2U"	"USB, newer models"	"usbhid-ups"
+ "Tripp-Lite"	"INTERNET350SER"	""	"trippliteser"
  
  "Trust"		"UPS 1000 Management PW-4105"	""	"megatec"
  "Trust"		"UPS 1200VA Management PW-4120M"	""	"megatec"
diff -crBN a/drivers/genericups.c b/drivers/genericups.c
*** a/drivers/genericups.c	2009-02-17 04:20:48.000000000 -0500
--- b/drivers/genericups.c	2009-10-16 15:06:42.000000000 -0400
***************
*** 66,71 ****
--- 66,74 ----
  	if (strstr(value, "RNG")) {
  		fatalx(EXIT_FAILURE, "Can't override output with RNG (not an output)");
  	}
+ 	if (strstr(value, "DSR")) {
+ 		fatalx(EXIT_FAILURE, "Can't override output with DSR (not an output)");
+ 	}
  } 
   
  static void parse_input_signals(const char *value, int *line, int *val)
***************
*** 98,103 ****
--- 101,113 ----
  			*val |= TIOCM_RNG;
  		}
  	}
+ 	if (strstr(value, "DSR")) {
+ 		*line |= TIOCM_DSR;
+ 
+ 		if (!strstr(value, "-DSR")) {
+ 			*val |= TIOCM_DSR;
+ 		}
+ 	}
  
  	if (strstr(value, "DTR")) {
  		fatalx(EXIT_FAILURE, "Can't override input with DTR (not an input)");
diff -crBN a/drivers/Makefile.in b/drivers/Makefile.in
*** a/drivers/Makefile.in	2009-02-17 04:24:10.000000000 -0500
--- b/drivers/Makefile.in	2009-10-16 15:07:30.000000000 -0400
***************
*** 110,116 ****
  	newmge-shut$(EXEEXT) oneac$(EXEEXT) optiups$(EXEEXT) \
  	powercom$(EXEEXT) rhino$(EXEEXT) safenet$(EXEEXT) \
  	skel$(EXEEXT) solis$(EXEEXT) tripplite$(EXEEXT) \
! 	tripplitesu$(EXEEXT) upscode2$(EXEEXT) victronups$(EXEEXT) \
  	powerpanel$(EXEEXT) blazer_ser$(EXEEXT)
  am__EXEEXT_2 = snmp-ups$(EXEEXT)
  am__EXEEXT_3 = usbhid-ups$(EXEEXT) bcmxcp_usb$(EXEEXT) \
--- 110,116 ----
  	newmge-shut$(EXEEXT) oneac$(EXEEXT) optiups$(EXEEXT) \
  	powercom$(EXEEXT) rhino$(EXEEXT) safenet$(EXEEXT) \
  	skel$(EXEEXT) solis$(EXEEXT) tripplite$(EXEEXT) \
! 	tripplitesu$(EXEEXT) trippliteser$(EXEEXT)  upscode2$(EXEEXT) victronups$(EXEEXT) \
  	powerpanel$(EXEEXT) blazer_ser$(EXEEXT)
  am__EXEEXT_2 = snmp-ups$(EXEEXT)
  am__EXEEXT_3 = usbhid-ups$(EXEEXT) bcmxcp_usb$(EXEEXT) \
***************
*** 334,339 ****
--- 334,343 ----
  tripplitesu_OBJECTS = $(am_tripplitesu_OBJECTS)
  tripplitesu_LDADD = $(LDADD)
  tripplitesu_DEPENDENCIES = $(am__DEPENDENCIES_2)
+ am_trippliteser_OBJECTS = trippliteser.$(OBJEXT)
+ trippliteser_OBJECTS = $(am_trippliteser_OBJECTS)
+ trippliteser_LDADD = $(LDADD)
+ trippliteser_DEPENDENCIES = $(am__DEPENDENCIES_2)
  am_upscode2_OBJECTS = upscode2.$(OBJEXT)
  upscode2_OBJECTS = $(am_upscode2_OBJECTS)
  upscode2_DEPENDENCIES = $(am__DEPENDENCIES_3)
***************
*** 381,387 ****
  	$(powerpanel_SOURCES) $(rhino_SOURCES) $(richcomm_usb_SOURCES) \
  	$(safenet_SOURCES) $(skel_SOURCES) $(snmp_ups_SOURCES) \
  	$(solis_SOURCES) $(tripplite_SOURCES) $(tripplite_usb_SOURCES) \
! 	$(tripplitesu_SOURCES) $(upscode2_SOURCES) \
  	$(upsdrvctl_SOURCES) $(usbhid_ups_SOURCES) \
  	$(victronups_SOURCES)
  DIST_SOURCES = $(libdummy_a_SOURCES) $(libnuthalmain_a_SOURCES) \
--- 385,393 ----
  	$(powerpanel_SOURCES) $(rhino_SOURCES) $(richcomm_usb_SOURCES) \
  	$(safenet_SOURCES) $(skel_SOURCES) $(snmp_ups_SOURCES) \
  	$(solis_SOURCES) $(tripplite_SOURCES) $(tripplite_usb_SOURCES) \
! 	$(tripplitesu_SOURCES) \
! 	$(trippliteser_SOURCES) \
! 	$(upscode2_SOURCES) \
  	$(upsdrvctl_SOURCES) $(usbhid_ups_SOURCES) \
  	$(victronups_SOURCES)
  DIST_SOURCES = $(libdummy_a_SOURCES) $(libnuthalmain_a_SOURCES) \
***************
*** 403,409 ****
  	$(powerpanel_SOURCES) $(rhino_SOURCES) $(richcomm_usb_SOURCES) \
  	$(safenet_SOURCES) $(skel_SOURCES) $(snmp_ups_SOURCES) \
  	$(solis_SOURCES) $(tripplite_SOURCES) $(tripplite_usb_SOURCES) \
! 	$(tripplitesu_SOURCES) $(upscode2_SOURCES) \
  	$(upsdrvctl_SOURCES) $(usbhid_ups_SOURCES) \
  	$(victronups_SOURCES)
  HEADERS = $(dist_noinst_HEADERS)
--- 409,417 ----
  	$(powerpanel_SOURCES) $(rhino_SOURCES) $(richcomm_usb_SOURCES) \
  	$(safenet_SOURCES) $(skel_SOURCES) $(snmp_ups_SOURCES) \
  	$(solis_SOURCES) $(tripplite_SOURCES) $(tripplite_usb_SOURCES) \
! 	$(tripplitesu_SOURCES) \
! 	$(trippliteser_SOURCES) \
! 	$(upscode2_SOURCES) \
  	$(upsdrvctl_SOURCES) $(usbhid_ups_SOURCES) \
  	$(victronups_SOURCES)
  HEADERS = $(dist_noinst_HEADERS)
***************
*** 580,586 ****
   bestuferrups bestups cyberpower dummy-ups etapro everups 	\
   gamatronic genericups isbmex liebert masterguard megatec metasys 	\
   mge-shut mge-utalk microdowell newmge-shut oneac optiups powercom rhino 	\
!  safenet skel solis tripplite tripplitesu upscode2 victronups powerpanel \
   blazer_ser
  
  SNMP_DRIVERLIST = snmp-ups
--- 588,594 ----
   bestuferrups bestups cyberpower dummy-ups etapro everups 	\
   gamatronic genericups isbmex liebert masterguard megatec metasys 	\
   mge-shut mge-utalk microdowell newmge-shut oneac optiups powercom rhino 	\
!  safenet skel solis tripplite tripplitesu trippliteser upscode2 victronups powerpanel \
   blazer_ser
  
  SNMP_DRIVERLIST = snmp-ups
***************
*** 638,643 ****
--- 646,652 ----
  tripplite_SOURCES = tripplite.c
  tripplite_LDADD = $(LDADD) -lm
  tripplitesu_SOURCES = tripplitesu.c
+ trippliteser_SOURCES = trippliteser.c
  upscode2_SOURCES = upscode2.c
  upscode2_LDADD = $(LDADD) -lm
  victronups_SOURCES = victronups.c
***************
*** 964,969 ****
--- 973,981 ----
  tripplitesu$(EXEEXT): $(tripplitesu_OBJECTS) $(tripplitesu_DEPENDENCIES) 
  	@rm -f tripplitesu$(EXEEXT)
  	$(LINK) $(tripplitesu_OBJECTS) $(tripplitesu_LDADD) $(LIBS)
+ trippliteser$(EXEEXT): $(trippliteser_OBJECTS) $(trippliteser_DEPENDENCIES) 
+ 	@rm -f trippliteser$(EXEEXT)
+ 	$(LINK) $(trippliteser_OBJECTS) $(trippliteser_LDADD) $(LIBS)
  upscode2$(EXEEXT): $(upscode2_OBJECTS) $(upscode2_DEPENDENCIES) 
  	@rm -f upscode2$(EXEEXT)
  	$(LINK) $(upscode2_OBJECTS) $(upscode2_LDADD) $(LIBS)
***************
*** 1055,1060 ****
--- 1067,1073 ----
  @AMDEP_TRUE@@am__include@ @am__qu...@./$(DEPDIR)/tripplite...@am__quote@
  @AMDEP_TRUE@@am__include@ @am__qu...@./$(DEPDIR)/tripplite_usb...@am__quote@
  @AMDEP_TRUE@@am__include@ @am__qu...@./$(DEPDIR)/tripplitesu...@am__quote@
+ @AMDEP_TRUE@@am__include@ @am__qu...@./$(DEPDIR)/trippliteser...@am__quote@
  @AMDEP_TRUE@@am__include@ @am__qu...@./$(DEPDIR)/upscode2...@am__quote@
  @AMDEP_TRUE@@am__include@ @am__qu...@./$(DEPDIR)/upsdrvctl...@am__quote@
  @AMDEP_TRUE@@am__include@ @am__qu...@./$(DEPDIR)/usb-common...@am__quote@
diff -crBN a/drivers/trippliteser.c b/drivers/trippliteser.c
*** a/drivers/trippliteser.c	1969-12-31 19:00:00.000000000 -0500
--- b/drivers/trippliteser.c	2009-11-02 16:42:52.000000000 -0500
***************
*** 0 ****
--- 1,641 ----
+ /* trippliteser.c - model specific routines for
+                    Tripp Lite INTERNET (SER) models running protocol 1004
+ 
+    Copyright (C) 2009 Patrick Levesque <patri...@verint.com>
+ 
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+ 
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+ 
+    You should have received a copy of the GNU General Public License
+    along with this program; if not, write to the Free Software
+    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+ 
+ /* Notes:
+ 
+    The following parameters (ups.conf) are supported:
+ 	lowbatt
+ 
+    The following variables are supported (RW = read/write):
+ 	ambient.humidity (1)
+ 	ambient.temperature (1)
+ 	battery.charge
+ 	battery.current (1)
+ 	battery.temperature
+ 	battery.voltage
+ 	battery.voltage.nominal
+ 	driver.version.internal
+ 	input.frequency
+ 	input.sensitivity (RW) (1)
+ 	input.transfer.high (RW)
+ 	input.transfer.low (RW)
+ 	input.voltage
+ 	input.voltage.nominal
+ 	output.current (1)
+ 	output.frequency
+ 	output.voltage
+ 	output.voltage.nominal
+ 	ups.firmware
+ 	ups.id (RW) (1)
+ 	ups.load
+ 	ups.mfr
+ 	ups.model
+ 	ups.status
+ 	ups.test.result
+ 	ups.contacts (1)
+ 
+     The following instant commands are supported:
+ 	load.off
+ 	load.on
+ 	shutdown.reboot
+ 	shutdown.reboot.graceful
+ 	shutdown.return
+ 	shutdown.stop
+ 	test.battery.start
+ 	test.battery.stop
+ 
+     The following ups.status values are supported:
+ 	BOOST (1)
+ 	BYPASS
+ 	LB
+ 	OB
+ 	OFF
+ 	OL
+ 	OVER (2)
+ 	RB (2)
+ 	TRIM (1)
+ 
+     (1) these items have not been tested because they are not supported
+     by my SU1000RT2U.
+     (2) these items have not been tested because I haven't tested them.
+ */
+ 
+ 
+ #include "main.h"
+ #include "serial.h"
+ 
+ #define DRIVER_NAME		"Tripp Lite INTERNET SER driver"
+ #define DRIVER_VERSION	"0.01"
+ 
+ #define ENDCHAR		'\r'
+ #define IGNCHAR		'X'
+ 
+ /* driver description structure */
+ upsdrv_info_t upsdrv_info = {
+ 	DRIVER_NAME,
+ 	DRIVER_VERSION,
+ 	"Patrick Levesque <patri...@verint.com>",
+ 	DRV_EXPERIMENTAL,
+ 	{ NULL }
+ };
+ 
+ #define MAX_RESPONSE_LENGTH 8
+ #define MAX_IDNETIFICATION_LENGTH 40
+ 
+ #define DEFAULT_OFFDELAY   64  /*!< seconds (max 2^16) */
+ 
+ static int battery_voltage_nominal = 0,
+ 	   input_voltage_nominal = 0,
+ 	   switchable_load_banks = 0;
+ 
+ /*! Time in seconds to delay before shutting down. */
+ static unsigned int offdelay = DEFAULT_OFFDELAY;
+ #if 0
+ static const char *test_result_names[] = {
+ 	"No test performed",
+ 	"Passed",
+ 	"In progress",
+ 	"General test failed",
+ 	"Battery failed",
+ 	"Deep battery test failed",
+ 	"Aborted"
+ };
+ #endif
+ 
+ # if 0
+ static struct {
+ 	int code;
+ 	const char *name;
+ } sensitivity[] = {
+ 	{0, "Normal"},
+ 	{1, "Reduced"},
+ 	{2, "Low"}
+ };
+ #endif
+ 
+ static struct {
+ 	int outlet_banks;
+ 	unsigned long commands_available;
+ } ups;
+ 
+ 
+ struct proto {
+    char command;
+    size_t req_size;
+    int csum;
+    size_t ans_size;
+ };
+ 
+ static struct proto proto_table[] =
+ {
+    /* Control value */
+    {'C', 4, 1, 2},
+    {'G', 4, 1, 2},
+    {'N', 6, 1, 2},
+    {'I', 5, 1, 2},
+    {'W', 5, 1, 3},
+    /* Command value */
+    {'\0', 4, 1, 8},
+    {'F', 4, 1, 8},
+    {'L', 4, 1, 6},
+    {'P', 4, 1, 8},
+    {'S', 4, 1, 5},
+    {'V', 4, 1, 8},
+    /* Unit identification */
+    {'1', 3, 0, 8},
+    {'2', 3, 0, 8},
+    {'3', 3, 0, 8},
+    {'4', 3, 0, 8},
+    {'5', 3, 0, 8},
+    {'6', 3, 0, 8},
+ };
+ 
+ 
+ #define DEFAULT_RESPONSE_LENGTH     8
+ 
+ /* index of the proto table */
+ 
+ enum trippliteser_command
+ {
+    /* Controls */
+    CANCEL_SHUTDOWN=0,
+    SHUTDOWN,
+    SET_PREDELAY,
+    SET_STATUS_FLAGS,
+    WATCHDOG,
+    /* Commands */
+    PROTOCOL,
+    uC_FIRMWARE,
+    STATUS_FLAGS,
+    POWER_RATING,
+    STATUS,
+    MODEL_VERSION,
+    /* Unit Identification */
+    IDENTIFICATION_1,
+    IDENTIFICATION_2,
+    IDENTIFICATION_3,
+    IDENTIFICATION_4,
+    IDENTIFICATION_5,
+    IDENTIFICATION_6
+ };
+ 
+ /*...@brief Convert N characters from hex to decimal
+  *
+  * @param start		Beginning of string to convert
+  * @param len		Maximum number of characters to consider (max 32)
+  *
+  * @a len characters of @a start are copied to a temporary buffer, then passed
+  * to strtol() to be converted to decimal.
+  *
+  * @return See strtol(3)
+  */
+ static int hex2d(const unsigned char *start, unsigned int len)
+ {
+ 	unsigned char buf[32];
+ 	buf[31] = '\0';
+ 
+ 	strncpy((char *)buf, (char *)start, (len < (sizeof buf) ? len : (sizeof buf - 1)));
+ 	if(len < sizeof(buf)) buf[len] = '\0';
+ 	return strtol((char *)buf, NULL, 16);
+ }
+ 
+ void decode_v(const unsigned char *value)
+ {
+ 	unsigned char ivn, lb;
+ 	int bv = hex2d(value+2, 2);
+ 
+  	ivn = value[1];
+ 	lb = value[4];
+ 
+ 	switch(ivn) {
+ 		case '0': input_voltage_nominal = 100;
+ 			  break;
+ 		case '1': input_voltage_nominal = 120;
+ 			  break;
+ 		case '2': input_voltage_nominal = 208;
+ 			  break;
+ 		case '3': input_voltage_nominal = 230;
+ 			  break;
+       case '4': input_voltage_nominal = 240;
+ 			  break;
+ 		default:
+ 			  upslogx(2, "Unknown input voltage range: 0x%02x", (unsigned int)ivn);
+ 			  break;
+ 	}
+ 
+ 	battery_voltage_nominal = bv * 6;
+ 		
+ 	if( (lb >= '0') && (lb <= '9') ) {
+ 		switchable_load_banks = lb - '0';
+ 	} else {
+ 		if( lb != 'X' ) {
+ 			upslogx(2, "Unknown number of switchable load banks: 0x%02x",
+ 					(unsigned int)lb);
+ 		}
+ 	}
+ }
+ 
+ static int do_command(enum trippliteser_command command, unsigned char *msg, size_t msg_len, unsigned char *reply, size_t reply_len)
+ {
+ 	unsigned char	buffer[MAX_RESPONSE_LENGTH];
+ 	unsigned int i = 0, csum = 0;
+    int ret;
+    
+ 	ser_flush_io(upsfd);
+ 
+    if (reply_len < MAX_RESPONSE_LENGTH) {
+       upsdebugx(3, "do_command: reply do not have minimum size of 8 bytes!");
+       return -1;
+    }
+    
+ 	if (reply) {
+ 		memset(reply, 0, reply_len);
+ 	}
+ 
+    upsdebugx(3, "Performing command %c [0x%02x] with request size %d and answer size %d\n", proto_table[command].command, proto_table[command].command, proto_table[command].req_size, proto_table[command].ans_size);
+    memset(buffer, 0, sizeof(buffer));
+ 
+    /* Now fill the buffer */
+    buffer[0] = ':';
+ 
+    buffer[1] = proto_table[command].command;
+ 
+    if (proto_table[command].csum) {
+       csum = proto_table[command].command;
+ 
+       /* skip : and remove ENDCHAR from the csum computation */
+       for(i=0; i<msg_len; i++) {
+          buffer[i+2] = msg[i];
+          csum += msg[i];
+       }
+       buffer[i+2] = 255-csum;
+       i++;
+    }
+ 	buffer[i+2] = ENDCHAR;
+    
+ 	ret = ser_send_buf_pace(upsfd, 0, buffer, proto_table[command].req_size);
+ 	if (ret <= 0) {
+ 		upsdebug_with_errno(3, "do_command: send [%s]", buffer);
+ 		return -1;
+ 	}
+ 
+ 	upsdebugx(3, "do_command: %d bytes sent [0x%02x%02x%02x%02x] 0x%02x -> OK", ret, buffer[0], buffer[1], buffer[2], buffer[3], '\r');
+ 
+ 	ret = ser_get_buf_len(upsfd, reply, proto_table[command].ans_size, 3, 0);
+ 	if (ret < 0) {
+ 		upsdebug_with_errno(3, "do_command: read");
+ 		return -1;
+ 	}
+ 	if (ret == 0) {
+ 		upsdebugx(3, "do_command: read -> TIMEOUT");
+ 		return -1;
+ 	}
+ 
+ 	upsdebugx(3, "do_command: %d byted read 0x%02x%02x%02x%02x%02x%02x%02x%02x", ret, reply[0], reply[1],reply[2],reply[3],reply[4],reply[5],reply[6],reply[7]);
+ 
+    if (reply[0] != proto_table[command].command) {
+       upsdebugx(3, "do_command: response not expected!");
+       return -1;
+    }
+    return ret;
+ }
+ 
+ static int do_productName(char *productName, size_t productName_len)
+ {
+ 	unsigned char	response[MAX_RESPONSE_LENGTH];
+    unsigned int len = 0;
+    int i = 0, j = 0;
+ 	
+ 	if (productName == NULL) {
+ 		upsdebugx(3, "%s: input buffer is null!", __FUNCTION__);
+       return -1;
+ 	}
+    memset(productName, 0, productName_len);
+    len = 0;
+ 
+    if (do_command(IDENTIFICATION_2, NULL, 0, response, sizeof(response)) <= 0) {
+       upsdebugx(3, "IDENTIFICATION_2 failed\n");
+ 		return -1;
+    }
+    for (j=1;response[j] != '\r' && j < MAX_RESPONSE_LENGTH; i++, j++) {
+       productName[i] = response[j];
+       len++;
+    }
+    if (do_command(IDENTIFICATION_3, NULL, 0, response, sizeof(response)) <= 0) {
+       upsdebugx(3, "IDENTIFICATION_3 failed\n");
+ 		return -1;
+    }
+    for (j=1;response[j] != '\r' && j < MAX_RESPONSE_LENGTH; i++, j++) {
+       productName[i] = response[j];
+       len++;
+    }
+    if (do_command(IDENTIFICATION_4, NULL, 0, response, sizeof(response)) <= 0) {
+       upsdebugx(3, "IDENTIFICATION_4 failed\n");
+ 		return -1;
+    }
+    for (j=1;response[j] != '\r' && j < MAX_RESPONSE_LENGTH; i++, j++) {
+       productName[i] = response[j];
+       len++;
+    }
+    if (do_command(IDENTIFICATION_5, NULL, 0, response, sizeof(response)) <= 0) {
+       upsdebugx(3, "IDENTIFICATION_5 failed\n");
+ 		return -1;
+    }
+    for (j=1;response[j] != '\r' && j < MAX_RESPONSE_LENGTH; i++, j++) {
+       productName[i] = response[j];
+       len++;
+    }
+    if (do_command(IDENTIFICATION_6, NULL, 0, response, sizeof(response)) <= 0) {
+       upsdebugx(3, "IDENTIFICATION_6 failed\n");
+ 		return -1;
+    }
+    for (j=1;response[j] != '\r' && j < MAX_RESPONSE_LENGTH; i++, j++) {
+       productName[i] = response[j];
+       len++;
+    }
+    productName[i] = '\0';
+    len++;
+ 
+    /* Trim trailing spaces */
+ 	for(i--;productName[i] == ' ';i--) {
+ 		productName[i] = '\0';
+       len--;
+ 	}
+ 
+    upsdebugx(3, "Product Name so far %s of size %d\n", productName, len);
+ 
+    return len;
+ }
+ 
+ #if 0
+ static int get_identification(void) {
+ 	unsigned char response[MAX_RESPONSE_LENGTH];
+ 
+ 	if (do_command(IDENTIFICATION_2, NULL, 0, response, sizeof(response)) >= 0) {
+ 		dstate_setinfo("ups.id", "%s", response);
+ 		return 1;
+ 	}
+ 
+ 	return 0;
+ }
+ #endif
+ #if 0
+ static void set_identification(const char *val) {
+ 	char response[MAX_RESPONSE_LENGTH];
+ 
+ 	if (do_command(IDENTIFICATION, "", response) < 0)
+ 		return;
+ 	if (strcmp(val, response)) {
+ 		strncpy(response, val, MAX_RESPONSE_LENGTH);
+ 		response[MAX_RESPONSE_LENGTH - 1] = '\0';
+ 		do_command(IDENTIFICATION, response, NULL);
+ 	}
+ }
+ #endif
+ 
+ #if 0
+ static int get_transfer_voltage_low(void) {
+ 	char response[MAX_RESPONSE_LENGTH];
+ 	char *ptr;
+ 
+ 	if (do_command(TRANSFER_VOLTAGE, "", response) > 0) {
+ 		ptr = field(response, 0);
+ 		if (ptr)
+ 			dstate_setinfo("input.transfer.low", "%d", atoi(ptr));
+ 		return 1;
+ 	}
+ 
+ 	return 0;
+ }
+ #endif
+ 
+ static int instcmd(const char *cmdname, const char *extra)
+ {
+ #if 0
+ 	int i;
+ 
+ 	char parm[20];
+ 
+ 	if (!strcasecmp(cmdname, "load.off")) {
+ 		for (i = 0; i < ups.outlet_banks; i++) {
+ 			snprintf(parm, sizeof(parm), "%d;1", i + 1);
+ 			do_command(SET, RELAY_OFF, parm, NULL);
+ 		}
+ 		return STAT_INSTCMD_HANDLED;
+ 	}
+ 	if (!strcasecmp(cmdname, "load.on")) {
+ 		for (i = 0; i < ups.outlet_banks; i++) {
+ 			snprintf(parm, sizeof(parm), "%d;1", i + 1);
+ 			do_command(SET, RELAY_ON, parm, NULL);
+ 		}
+ 		return STAT_INSTCMD_HANDLED;
+ 	}
+ 	if (!strcasecmp(cmdname, "shutdown.reboot")) {
+ 		auto_reboot(1);
+ 		do_command(SET, SHUTDOWN_RESTART, "1", NULL);
+ 		do_command(SET, SHUTDOWN_ACTION, "10", NULL);
+ 		return STAT_INSTCMD_HANDLED;
+ 	}
+ 	if (!strcasecmp(cmdname, "shutdown.reboot.graceful")) {
+ 		auto_reboot(1);
+ 		do_command(SET, SHUTDOWN_RESTART, "1", NULL);
+ 		do_command(SET, SHUTDOWN_ACTION, "60", NULL);
+ 		return STAT_INSTCMD_HANDLED;
+ 	}
+ 	if (!strcasecmp(cmdname, "shutdown.return")) {
+ 		auto_reboot(1);
+ 		do_command(SET, SHUTDOWN_RESTART, "1", NULL);
+ 		do_command(SET, SHUTDOWN_ACTION, "10", NULL);
+ 		return STAT_INSTCMD_HANDLED;
+ 	}
+ #if 0 /* doesn't seem to work */
+ 	if (!strcasecmp(cmdname, "shutdown.stayoff")) {
+ 		auto_reboot(0);
+ 		do_command(SET, SHUTDOWN_ACTION, "10", NULL);
+ 		return STAT_INSTCMD_HANDLED;
+ 	}
+ #endif
+ 	if (!strcasecmp(cmdname, "shutdown.stop")) {
+ 		do_command(SET, SHUTDOWN_ACTION, "0", NULL);
+ 		return STAT_INSTCMD_HANDLED;
+ 	}
+ 	if (!strcasecmp(cmdname, "test.battery.start")) {
+ 		do_command(SET, TEST, "3", NULL);
+ 		return STAT_INSTCMD_HANDLED;
+ 	}
+ 	if (!strcasecmp(cmdname, "test.battery.stop")) {
+ 		do_command(SET, TEST, "0", NULL);
+ 		return STAT_INSTCMD_HANDLED;
+ 	}
+ 	upslogx(LOG_NOTICE, "instcmd: unknown command [%s]", cmdname);
+ 	return STAT_INSTCMD_UNKNOWN;
+ #endif
+    return STAT_INSTCMD_HANDLED;
+ }
+ 
+ 
+ static int setvar(const char *varname, const char *val)
+ {
+ #if 0
+ 	if (!strcasecmp(varname, "ups.id")) {
+ 		set_identification(val);
+ 		get_identification();
+ 		return STAT_SET_HANDLED;
+ 	}
+ 	upslogx(LOG_NOTICE, "setvar: unknown var [%s]", varname);
+ #endif
+ 	return STAT_SET_UNKNOWN;
+ }
+ 
+ 
+ static int init_comm(void)
+ {
+    unsigned char response[MAX_RESPONSE_LENGTH];
+ 
+    ups.commands_available = 0;
+ 
+    if (do_command(PROTOCOL, NULL, 0, response, sizeof(response)) <= 0) {
+       return 0;
+    }
+ 
+    /* Make sure the control protocol is 0x1004 */
+    if (response[1] != 0x10 || response[2] != 0x04) {
+       return 0;
+    }
+ 
+    return 1;
+ }
+ 
+ void upsdrv_initinfo(void)
+ {
+    unsigned char response[MAX_RESPONSE_LENGTH];
+    char productName[MAX_IDNETIFICATION_LENGTH];
+ //   unsigned int pre_delay, alarm;
+    
+    if (!init_comm())
+ 		fatalx(EXIT_FAILURE, "Unable to detect Tripp Lite SmartOnline UPS on port %s\n",
+ 		        device_path);
+    dstate_setinfo("ups.mfr", "%s", "Tripp Lite");
+    if (do_productName(productName, sizeof(productName)))
+ 		dstate_setinfo("ups.model", "%s", productName);
+    if (do_command(PROTOCOL, NULL, 0, response, sizeof(response)))
+ 		dstate_setinfo("ups.firmware.aux", "%02x%02x", response[1], response[2]);
+ 	if (do_command(uC_FIRMWARE, NULL, 0, response, sizeof(response)))
+ 		dstate_setinfo("ups.firmware", "69-%c%c%c%c Rev %c%c", response[1], response[2], response[3], response[4], response[5], response[6]);
+    if (do_command(MODEL_VERSION, NULL, 0, response, sizeof(response))) {
+       decode_v(response);
+       dstate_setinfo("input.voltage.nominal", "%d", input_voltage_nominal);
+       dstate_setinfo("battery.voltage.nominal", "%d", battery_voltage_nominal);
+       dstate_setinfo("ups.debug.load_banks", "%d", switchable_load_banks);
+    }
+ 
+    dstate_setinfo("ups.delay.shutdown", "%d", offdelay);
+ 	dstate_setflags("ups.delay.shutdown", ST_FLAG_RW | ST_FLAG_STRING);
+ 	dstate_setaux("ups.delay.shutdown", 3);
+ 
+    /* add all the variables that change regularly */
+ 	upsdrv_updateinfo();
+ 
+    upsh.instcmd = instcmd;
+ 	upsh.setvar = setvar;
+ }
+ 
+ void upsdrv_updateinfo(void)
+ {
+ 
+ 	unsigned char response[MAX_RESPONSE_LENGTH];
+ 
+ 	status_init();
+ 	if (do_command(STATUS, NULL, 0, response, sizeof(response)) <= 0) {
+ 		dstate_datastale();
+ 		return;
+ 	}
+ 
+    if (response[1] == '0') {
+       status_set("LB");
+    }
+    
+ 	switch (response[2]) {
+ 	case '0':
+ 		status_set("OL");
+ 		break;
+ 	case '1':
+ 		status_set("OB");
+ 		break;
+ 	case '2':
+ 		status_set("CHRG");
+ 		break;
+ 	case '3':
+ 		status_set("IDLE");
+ 		break;
+ 	default:
+ 		break;
+ 	}
+ 
+    dstate_setinfo("battery.charge", "%d", response[3]);
+ 
+    	/* if we are here, status is valid */
+ 	status_commit();
+ 	dstate_dataok();
+ 
+ }
+ 
+ void upsdrv_shutdown(void)
+ {
+     unsigned char response[MAX_RESPONSE_LENGTH];
+     unsigned char preDelay[2] = {0x00, 0x00};
+    upsdebugx(3, "upsdrv_shutdown is CALLED\n");
+     /* Make sure the system run on battery because the system will not be brought back in case the system is on line */
+    if (do_command(STATUS, NULL, 0, response, sizeof(response)) <= 0)
+       fatalx(EXIT_FAILURE, "Unable to get the line status!");
+ 
+    if (response[2] != '0' ) {
+       upsdebugx(3, "Performing the shutdown\n");
+       if (do_command(SET_PREDELAY, preDelay, sizeof(preDelay), response, sizeof(response)) <= 0)
+ 		    upslogx(LOG_NOTICE, "SET_PREDELAY failed");
+       if (do_command(SHUTDOWN, NULL, 0, response, sizeof(response)) <= 0)
+ 		    upslogx(LOG_NOTICE, "SHUTDOWN failed");
+    }
+    else
+    {
+       upsdebugx(3, "Shutdown bypass because we are on line\n");
+    }
+ }
+ 
+ void upsdrv_help(void)
+ {
+ }
+ 
+ /* list flags and values that you want to receive via -x or ups.conf */
+ void upsdrv_makevartable(void)
+ {
+ 	addvar(VAR_VALUE, "lowbatt", "Set low battery level, in percent");
+ }
+ 
+ void upsdrv_initups(void)
+ {
+ 	upsfd = ser_open(device_path);
+ 	ser_set_speed(upsfd, device_path, B2400);
+ }
+ 
+ void upsdrv_cleanup(void)
+ {
+ 	ser_close(upsfd, device_path);
+ }
_______________________________________________
Nut-upsdev mailing list
Nut-upsdev@lists.alioth.debian.org
http://lists.alioth.debian.org/mailman/listinfo/nut-upsdev

Reply via email to