/* get the answer of a command from the ups */ int get_answer(unsigned char *data) { unsigned char my_buf[255]; /* packet has a maximum length of 256 bytes */ int packet_length, checksum, i, res; /* Read STX byte */ res = ser_get_char(upsfd, my_buf, 1, 0); if (res < 1) { ser_comm_fail("Receive error (STX): %d!!!\n", res); return -1; } if (my_buf[0] != 0x02) { ser_comm_fail("Receive error (STX): packet not on start!!\n"); return -1; } /* Read data length byte */ res = ser_get_char(upsfd, my_buf, 1, 0); if (res < 1) { ser_comm_fail("Receive error (length): %d!!!\n", res); return -1; } packet_length = my_buf[0]; if (packet_length < 2) { ser_comm_fail("Receive error (length): packet length %d!!!\n", packet_length); return -1; } /* Try to read all the remainig bytes (packet_length) */ res = ser_get_buf_len(upsfd, my_buf, packet_length, 1, 0); if (res != packet_length) { ser_comm_fail("Receive error (data): got %d bytes instead of %d!!!\n", res, packet_length); return -1; } /* now we have the whole answer from the ups, we can checksum it checksum byte is equal to the sum modulus 256 of all the data bytes + packet_length (no STX no checksum byte itself) */ checksum = packet_length; for (i = 0; i < (packet_length - 1); i++) checksum += my_buf[i]; checksum = checksum % 256; if (my_buf[packet_length-1] != checksum) { ser_comm_fail("checksum error! got %x instad of %x, received %d bytes \n", my_buf[packet_length - 1], checksum, packet_length); dump_buffer(my_buf, packet_length); return -1; } packet_length-=1; /* get rid of the checksum byte */ memcpy(data, my_buf, packet_length); return packet_length; }
void test_EOL() { char ch; while(TRUE){ do { ser_get_char(upsfd,&ch, SER_WAIT_SEC,SER_WAIT_USEC); } while(ch!='\n'); ser_get_char(upsfd,&ch, SER_WAIT_SEC,SER_WAIT_USEC); if(ch == '\r') return; } }
/* 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 = 0, res, endblock = 0, start = 0; unsigned char block_number, sequence, pre_sequence = 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, cmd=%x!!!\n", res, command); 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; } 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; } upsdebug_hex (5, "get_answer", data, end_length); ser_comm_good(); return end_length; }
unsigned char * CmdSerial(unsigned char *OutBuffer, int Len, unsigned char *RetBuffer) { #define TMP_BUFF_LEN 1024 unsigned char InpBuff[TMP_BUFF_LEN+1] ; unsigned char TmpBuff[3] ; int i, ErrCode ; unsigned char *p ; int BuffLen ; /* The default error code (no received character) */ ErrCode = ERR_COM_NO_CHARS ; SendCmdToSerial(OutBuffer, Len) ; usleep(10000) ; /* small delay (1/100 s) */ /* get chars until timeout */ BuffLen = 0 ; while (ser_get_char(upsfd, TmpBuff, 0, 10000) == 1) { InpBuff[BuffLen++] = TmpBuff[0] ; if (BuffLen > TMP_BUFF_LEN) break ; } upsdebug_hex(4, "UPS->", InpBuff, BuffLen) ; if (BuffLen > 0) { ErrCode = CheckDataChecksum(InpBuff, BuffLen) ; /* upsdebugx(4, "ErrCode = %d / Len = %d", ErrCode, BuffLen); */ if (!ErrCode) { /* FramePointer to valid data! */ p = InpBuff + ups.FramePointer ; /* p now point to valid data. check if it is a error code. */ ErrCode = CheckErrCode(p) ; if (!ErrCode) { /* I copy the data read in the buffer */ for(i=0 ; i<(int) (p[1])+3 ; i++) RetBuffer[i] = p[i] ; ups.ErrCode = ups.ErrCount = ups.CommStatus = 0 ; return(RetBuffer) ; } } } /* if they have arrived here, wants to say that I have found an error.... */ ups.ErrCode = ErrCode ; ups.ErrCount++ ; if (ups.ErrCount > 3) { ups.CommStatus &= 0x80 ; ups.CommStatus |= (unsigned char) (ups.ErrCount & 0x7F) ; if (ups.ErrCount > 100) ups.ErrCount = 100 ; } return(NULL) ; /* There have been errors in the reading of the data */ }
/* normal idle loop - keep up with the current state of the UPS */ void upsdrv_updateinfo(void) { unsigned char c; unsigned int ob, lb; static unsigned int ob_state = 0, ob_last = 0, ob_ctr = 0; static unsigned int lb_state = 0, lb_last = 0, lb_ctr = 0; ob = lb = 0; /* the UPS connects RX to TX when on battery, so test for loopback */ ser_flush_in(upsfd, "", 0); c = ML_ONBATTERY; ser_send_char(upsfd, c); if (ser_get_char(upsfd, &c, 1, 0) == 1) { while (ser_get_char(upsfd, &c, 1, 0) == 1) continue; if (c == ML_ONBATTERY) ob = 1; } if (ser_get_dcd(upsfd)) lb = 1; /* state machine below to ensure status changes are debounced */ /* OB/OL state change: reset counter */ if (ob_last != ob) ob_ctr = 0; else ob_ctr++; upsdebugx(2, "OB: state %d last %d now %d ctr %d", ob_state, ob_last, ob, ob_ctr); if (ob_ctr >= DEBOUNCE) { if (ob != ob_state) { upsdebugx(2, "OB: toggling state"); if (ob_state == 0) ob_state = 1; else ob_state = 0; } } ob_last = ob; /* now do it again for LB */ /* state change: reset counter */ if (lb_last != lb) lb_ctr = 0; else lb_ctr++; upsdebugx(2, "LB: state %d last %d now %d ctr %d", lb_state, lb_last, lb, lb_ctr); if (lb_ctr >= DEBOUNCE) { if (lb != lb_state) { upsdebugx(2, "LB: toggling state"); if (lb_state == 0) lb_state = 1; else lb_state = 0; } } lb_last = lb; status_init(); if (ob_state == 1) status_set("OB"); /* on battery */ else status_set("OL"); /* on line */ if (lb_state == 1) status_set("LB"); /* low battery */ status_commit(); dstate_dataok(); }