Filter:   InfoImg
download bcmxcp_ser.c
Language: C
LOC: 229
Project Info
nut
Server: Debian-SVN
Type: svn
...an‑SVN\n\nut\trunk\drivers\
   al175.c
   al175.h
   apc-hid.c
   apc-hid.h
   apccmib.h
   apcsmart.c
   apcsmart.h
   bcmxcp.c
   bcmxcp.h
   bcmxcp_io.h
   bcmxcp_ser.c
   bcmxcp_usb.c
   belkin-hid.c
   belkin-hid.h
   belkin.c
   belkin.h
   belkinunv.c
   belkinunv.h
   bestfcom.c
   bestfcom.h
   bestuferrups.c
   bestuferrups.h
   bestups.c
   bestups.h
   cpsups.c
   cpsups.h
   cyberpower.c
   cyberpower.h
   dstate-hal.c
   dstate-hal.h
   dstate.c
   dstate.h
   dummy-ups.c
   dummy-ups.h
   energizerups.c
   etapro.c
   etapro.h
   everups.c
   everups.h
   explore-hid.c
   explore-hid.h
   gamatronic.c
   gamatronic.h
   genericups.c
   genericups.h
   hidparser.c
   hidparser.h
   hidtypes.h
   ietfmib.h
   isbmex.c
   isbmex.h
   libhid.c
   libhid.h
   libshut.c
   libshut.h
   libusb.c
   libusb.h
   liebert.c
   liebert.h
   main-hal.c
   main-hal.h
   main.c
   main.h
   Makefile.am
   masterguard.c
   masterguard.h
   megatec.c
   megatec.h
   megatec_usb.c
   metasys.c
   metasys.h
   mge-hid.c
   mge-hid.h
   mge-shut.c
   mge-shut.h
   mge-utalk.c
   mge-utalk.h
   mgemib.h
   netvisionmib.h
   nitram.c
   nitram.h
   nut_usb.c
   nut_usb.h
   oneac.c
   oneac.h
   optiups.c
   optiups.h
   powercom.c
   powercom.h
   powerpanel.c
   powerpanel.h
   pwmib.h
   rhino.c
   safenet.c
   safenet.h
   serial.c
   serial.h
   skel.c
   snmp-ups.c
   snmp-ups.h
   solis.c
   solis.h
   tripplite-hid.c
   tripplite-hid.h
   tripplite.c
   tripplite.h
   tripplite_usb.c
   tripplitesu.c
   tripplitesu.h
   upscode2.c
   upscode2.h
   upsdrvctl.c
   usbhid-ups.c
   usbhid-ups.h
   victronups.c
   victronups.h

#include "main.h"
#include "bcmxcp.h"
#include "bcmxcp_io.h"
#include "serial.h"

#define PW_MAX_BAUD 5
struct pw_baud_rate {
	int rate;
	int name;
} pw_baud_rates[] = {
	{ B1200,  1200 },
	{ B2400,  2400 },
	{ B4800,  4800 },
	{ B9600,  9600 },
	{ B19200, 19200 },
};

unsigned char AUT[4] = {0xCF, 0x69, 0xE8, 0xD5};		/* Autorisation	command	*/

void send_read_command(unsigned char command)
{
	int retry, sent;
	unsigned char buf[4];
	retry = 0;
	sent = 0;
	
	while ((sent != 4) && (retry < PW_MAX_TRY)) {
		buf[0]=PW_COMMAND_START_BYTE;
		buf[1]=0x01;			/* data length */
		buf[2]=command;			/* command to send */
		buf[3]=calc_checksum(buf);	/* checksum */
		
		if (retry == 4) ser_send_char(upsfd, 0x1d);	/* last retry is preceded by a ESC.*/
			sent = ser_send_buf(upsfd, buf, 4);
		retry += 1;
	}
}


void send_write_command(unsigned char *command, int command_length)
{
	int  retry, sent;
	unsigned char sbuf[128];

	/* Prepare the send buffer */
	sbuf[0] = PW_COMMAND_START_BYTE;
	sbuf[1] = (unsigned char)(command_length);
	memcpy(sbuf+2, command, command_length);
	command_length += 2;

	/* Add checksum */
	sbuf[command_length] = calc_checksum(sbuf);
	command_length += 1;

	/* Try to send the command */
	retry = 0;
	sent = 0;

	while ((sent != (command_length)) && (retry < PW_MAX_TRY)) {
		sent = ser_send_buf(upsfd, sbuf, (command_length));
		if (sent != (command_length)) printf("Error sending command %x\n", (unsigned char)sbuf[2]);
			retry += 1;
	}
}

/* get the answer of a command from the ups. And check that the answer is for this command */
int get_answer(unsigned char *data, unsigned char command)
{
	unsigned char my_buf[128];	/* packet has a maximum length of 121+5 bytes */
	int length, end_length, res, endblock, start;
	unsigned char block_number, sequence, pre_sequence;

	end_length = 0;
	endblock = 0;
	pre_sequence = 0;
	start = 0;

	while (endblock != 1){

		do {
			/* Read PW_COMMAND_START_BYTE byte */
			res = ser_get_char(upsfd, my_buf, 1, 0);
			if (res != 1) {
				upsdebugx(1,"Receive error (PW_COMMAND_START_BYTE): %d!!!\n", res);
				return -1;
			}
			start++;

		} while ((my_buf[0] != PW_COMMAND_START_BYTE) || start == 128);
		
		if (start == 128) {
			ser_comm_fail("Receive error (PW_COMMAND_START_BYTE): packet not on start!!%x\n", my_buf[0]);
			return -1;
		}

		/* Read block number byte */
		res = ser_get_char(upsfd, my_buf+1, 1, 0);
		if (res != 1) {
			ser_comm_fail("Receive error (Block number): %d!!!\n", res);
			return -1;
		}
		block_number = (unsigned char)my_buf[1];

		if (command <= 0x43) {
			if ((command - 0x30) != block_number){
				ser_comm_fail("Receive error (Request command): %x!!!\n", block_number);
				return -1;
			}
		}

		if (command >= 0x89) {
			if ((command == 0xA0) && (block_number != 0x01)){
				ser_comm_fail("Receive error (Requested only mode command): %x!!!\n", block_number);
				return -1;
			}
			else if ((command != 0xA0) && (block_number != 0x09)){
				ser_comm_fail("Receive error (Control command): %x!!!\n", block_number);
				return -1;
			}
		}

		/* Read data length byte */
		res = ser_get_char(upsfd, my_buf+2, 1, 0);
		if (res != 1) {
			ser_comm_fail("Receive error (length): %d!!!\n", res);
			return -1;
		}
		length = (unsigned char)my_buf[2];

		if (length < 1) {
			ser_comm_fail("Receive error (length): packet length %x!!!\n", length);
			return -1;
		}

		/* Read sequence byte */
		res = ser_get_char(upsfd, my_buf+3, 1, 0);
		if (res != 1) {
			ser_comm_fail("Receive error (sequence): %d!!!\n", res);
			return -1;
		}

		sequence = (unsigned char)my_buf[3];
		if ((sequence & 0x80) == 0x80) {
			endblock = 1;
		}

		if ((sequence & 0x07) != (pre_sequence + 1)) {
			ser_comm_fail("Not the right sequence received %x!!!\n", sequence);
			return -1;
		}

		pre_sequence = sequence;

		/* Try to read all the remainig bytes */
		res = ser_get_buf_len(upsfd, my_buf+4, length, 1, 0);
		if (res != length) {
			ser_comm_fail("Receive error (data): got %d bytes instead of %d!!!\n", res, length);
			return -1;
		}

		/* Get the checksum byte */
		res = ser_get_char(upsfd, my_buf+(4+length), 1, 0);

		if (res != 1) {
			ser_comm_fail("Receive error (checksum): %x!!!\n", res);
			return -1;
		}

		/* now we have the whole answer from the ups, we can checksum it */
		if (!checksum_test(my_buf)) {
			ser_comm_fail("checksum error! ");
		return -1;
		}

		memcpy(data+end_length, my_buf+4, length);
		end_length += length;

	}
	return end_length;
}

/* Sends a single command (length=1). and get the answer */
int command_read_sequence(unsigned char command, unsigned char *data)
{
	int bytes_read = 0;
	int retry = 0;
	
	while ((bytes_read < 1) && (retry < 3)) {
		send_read_command(command);
		bytes_read = get_answer(data, command);
		
		if (retry > 2) 
			ser_flush_in(upsfd, "", 0);
		retry++;
	}

	if (bytes_read < 1) {
		ser_comm_fail("Error executing command");
		dstate_datastale();
		return -1;
	}

	ser_comm_good();

	return bytes_read;
}

/* Sends a setup command (length > 1) */
int command_write_sequence(unsigned char *command, int command_length, unsigned	char *answer)
{
	int bytes_read = 0;
	int retry = 0;
	
	while ((bytes_read < 1) && (retry < 3)) {
		send_write_command(command, command_length);
		bytes_read = get_answer(answer, command[0]);
		
		if (retry > 2) 
			ser_flush_in(upsfd, "", 0);
		retry ++;
	}

	if (bytes_read < 1) {
		ser_comm_fail("Error executing command");
		dstate_datastale();
		return -1;
	}

	ser_comm_good();

	return bytes_read;
}

void upsdrv_comm_good()
{
	ser_comm_good();
}

void pw_comm_setup(const char *port)
{
    unsigned char answer[256];
    int i = 0, baud, mybaud = 0, ret = -1 ;

	if (getval("baud_rate") != NULL)
	{
		baud = atoi(getval("baud_rate"));
		
		for(i = 0; i < PW_MAX_BAUD; i++)
			if(baud == pw_baud_rates[i].name){
				mybaud = pw_baud_rates[i].rate;
				break;
			}

        ser_set_speed(upsfd, device_path,mybaud);
        	ser_send_char(upsfd, 0x1d);	/* send ESC to take it out of menu */
        	usleep(90000);
        	send_write_command(AUT, 4);
        	usleep(500000);
        	ret = command_read_sequence(PW_SET_REQ_ONLY_MODE, answer);
	}

	if (ret == -1)
	{
		for (i=0; i<PW_MAX_BAUD; i++) {

			ser_set_speed(upsfd, device_path,pw_baud_rates[i].rate);
        		ser_send_char(upsfd, 0x1d);	/* send ESC to take it out of menu */
        		usleep(90000);
        		send_write_command(AUT, 4);
        		usleep(500000);
        		ret = command_read_sequence(PW_SET_REQ_ONLY_MODE, answer);

        		if (ret != -1) break;
		}
	}

    if (i == 5) {
	printf("Can't find the UPS on port %s!\n",port);
	ser_close(upsfd, device_path);
	exit (1);
    }
printf("Connected to UPS on %s baudrate: %d\n",port, pw_baud_rates[i].name);
}

void upsdrv_initups(void)
{
	upsfd = ser_open(device_path);
	pw_comm_setup(device_path);
}

void upsdrv_cleanup(void)
{
	/* free(dynamic_mem); */
	ser_close(upsfd, device_path);
}

void upsdrv_reconnect(void)
{
}