34 #if HAVE_DECL_TIOCSRS485 35 #include <sys/ioctl.h> 36 #include <linux/serial.h> 41 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0,
42 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
43 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0,
44 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40,
45 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1,
46 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41,
47 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1,
48 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
49 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0,
50 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40,
51 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1,
52 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40,
53 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0,
54 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40,
55 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0,
56 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40,
57 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0,
58 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
59 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0,
60 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
61 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0,
62 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40,
63 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1,
64 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
65 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0,
66 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40
71 0x00, 0xC0, 0xC1, 0x01, 0xC3, 0x03, 0x02, 0xC2, 0xC6, 0x06,
72 0x07, 0xC7, 0x05, 0xC5, 0xC4, 0x04, 0xCC, 0x0C, 0x0D, 0xCD,
73 0x0F, 0xCF, 0xCE, 0x0E, 0x0A, 0xCA, 0xCB, 0x0B, 0xC9, 0x09,
74 0x08, 0xC8, 0xD8, 0x18, 0x19, 0xD9, 0x1B, 0xDB, 0xDA, 0x1A,
75 0x1E, 0xDE, 0xDF, 0x1F, 0xDD, 0x1D, 0x1C, 0xDC, 0x14, 0xD4,
76 0xD5, 0x15, 0xD7, 0x17, 0x16, 0xD6, 0xD2, 0x12, 0x13, 0xD3,
77 0x11, 0xD1, 0xD0, 0x10, 0xF0, 0x30, 0x31, 0xF1, 0x33, 0xF3,
78 0xF2, 0x32, 0x36, 0xF6, 0xF7, 0x37, 0xF5, 0x35, 0x34, 0xF4,
79 0x3C, 0xFC, 0xFD, 0x3D, 0xFF, 0x3F, 0x3E, 0xFE, 0xFA, 0x3A,
80 0x3B, 0xFB, 0x39, 0xF9, 0xF8, 0x38, 0x28, 0xE8, 0xE9, 0x29,
81 0xEB, 0x2B, 0x2A, 0xEA, 0xEE, 0x2E, 0x2F, 0xEF, 0x2D, 0xED,
82 0xEC, 0x2C, 0xE4, 0x24, 0x25, 0xE5, 0x27, 0xE7, 0xE6, 0x26,
83 0x22, 0xE2, 0xE3, 0x23, 0xE1, 0x21, 0x20, 0xE0, 0xA0, 0x60,
84 0x61, 0xA1, 0x63, 0xA3, 0xA2, 0x62, 0x66, 0xA6, 0xA7, 0x67,
85 0xA5, 0x65, 0x64, 0xA4, 0x6C, 0xAC, 0xAD, 0x6D, 0xAF, 0x6F,
86 0x6E, 0xAE, 0xAA, 0x6A, 0x6B, 0xAB, 0x69, 0xA9, 0xA8, 0x68,
87 0x78, 0xB8, 0xB9, 0x79, 0xBB, 0x7B, 0x7A, 0xBA, 0xBE, 0x7E,
88 0x7F, 0xBF, 0x7D, 0xBD, 0xBC, 0x7C, 0xB4, 0x74, 0x75, 0xB5,
89 0x77, 0xB7, 0xB6, 0x76, 0x72, 0xB2, 0xB3, 0x73, 0xB1, 0x71,
90 0x70, 0xB0, 0x50, 0x90, 0x91, 0x51, 0x93, 0x53, 0x52, 0x92,
91 0x96, 0x56, 0x57, 0x97, 0x55, 0x95, 0x94, 0x54, 0x9C, 0x5C,
92 0x5D, 0x9D, 0x5F, 0x9F, 0x9E, 0x5E, 0x5A, 0x9A, 0x9B, 0x5B,
93 0x99, 0x59, 0x58, 0x98, 0x88, 0x48, 0x49, 0x89, 0x4B, 0x8B,
94 0x8A, 0x4A, 0x4E, 0x8E, 0x8F, 0x4F, 0x8D, 0x4D, 0x4C, 0x8C,
95 0x44, 0x84, 0x85, 0x45, 0x87, 0x47, 0x46, 0x86, 0x82, 0x42,
96 0x43, 0x83, 0x41, 0x81, 0x80, 0x40
104 if (slave >= 0 && slave <= 247) {
119 assert(ctx->
slave != -1);
123 req[3] = addr & 0x00ff;
125 req[5] = nb & 0x00ff;
141 static uint16_t
crc16(uint8_t *buffer, uint16_t buffer_length)
143 uint8_t crc_hi = 0xFF;
144 uint8_t crc_lo = 0xFF;
148 while (buffer_length--) {
149 i = crc_hi ^ *buffer++;
154 return (crc_hi << 8 | crc_lo);
166 uint16_t crc =
crc16(req, req_length);
167 req[req_length++] = crc >> 8;
168 req[req_length++] = crc & 0x00FF;
183 static void win32_ser_init(
struct win32_ser *ws) {
185 memset(ws, 0x00,
sizeof(
struct win32_ser));
188 ws->fd = INVALID_HANDLE_VALUE;
192 static int win32_ser_select(
struct win32_ser *ws,
int max_len,
193 struct timeval *tv) {
194 COMMTIMEOUTS comm_to;
195 unsigned int msec = 0;
198 if (ws->n_bytes > 0) {
210 msec = tv->tv_sec * 1000 + tv->tv_usec / 1000;
215 comm_to.ReadIntervalTimeout = msec;
216 comm_to.ReadTotalTimeoutMultiplier = 0;
217 comm_to.ReadTotalTimeoutConstant = msec;
218 comm_to.WriteTotalTimeoutMultiplier = 0;
219 comm_to.WriteTotalTimeoutConstant = 1000;
220 SetCommTimeouts(ws->fd, &comm_to);
223 if ((max_len > PY_BUF_SIZE) || (max_len < 0)) {
224 max_len = PY_BUF_SIZE;
227 if (ReadFile(ws->fd, &ws->buf, max_len, &ws->n_bytes, NULL)) {
229 if (ws->n_bytes > 0) {
242 static int win32_ser_read(
struct win32_ser *ws, uint8_t *p_msg,
243 unsigned int max_len) {
244 unsigned int n = ws->n_bytes;
251 memcpy(p_msg, ws->buf, n);
265 return (WriteFile(ctx_rtu->w_ser.fd, req, req_length, &n_bytes, NULL)) ? n_bytes : -1;
267 return write(ctx->
s, req, req_length);
276 return read(ctx->
s, rsp, rsp_length);
285 const int msg_length)
287 uint16_t crc_calculated;
288 uint16_t crc_received;
290 crc_calculated =
crc16(msg, msg_length - 2);
291 crc_received = (msg[msg_length - 2] << 8) | msg[msg_length - 1];
294 if (crc_calculated == crc_received) {
298 fprintf(stderr,
"ERROR CRC received %0X != CRC calculated %0X\n",
299 crc_received, crc_calculated);
321 printf(
"Opening %s at %d bauds (%c, %d, %d)\n",
330 win32_ser_init(&ctx_rtu->w_ser);
334 ctx_rtu->w_ser.fd = CreateFileA(ctx_rtu->
device,
335 GENERIC_READ | GENERIC_WRITE,
343 if (ctx_rtu->w_ser.fd == INVALID_HANDLE_VALUE) {
344 fprintf(stderr,
"ERROR Can't open the device %s (%s)\n",
345 ctx_rtu->
device, strerror(errno));
350 ctx_rtu->old_dcb.DCBlength =
sizeof(DCB);
351 if (!GetCommState(ctx_rtu->w_ser.fd, &ctx_rtu->old_dcb)) {
352 fprintf(stderr,
"ERROR Error getting configuration (LastError %d)\n",
353 (
int)GetLastError());
354 CloseHandle(ctx_rtu->w_ser.fd);
355 ctx_rtu->w_ser.fd = INVALID_HANDLE_VALUE;
360 dcb = ctx_rtu->old_dcb;
363 switch (ctx_rtu->
baud) {
365 dcb.BaudRate = CBR_110;
368 dcb.BaudRate = CBR_300;
371 dcb.BaudRate = CBR_600;
374 dcb.BaudRate = CBR_1200;
377 dcb.BaudRate = CBR_2400;
380 dcb.BaudRate = CBR_4800;
383 dcb.BaudRate = CBR_9600;
386 dcb.BaudRate = CBR_19200;
389 dcb.BaudRate = CBR_38400;
392 dcb.BaudRate = CBR_57600;
395 dcb.BaudRate = CBR_115200;
398 dcb.BaudRate = CBR_1152000;
401 dcb.BaudRate = CBR_1250000;
404 dcb.BaudRate = CBR_9600;
405 printf(
"WARNING Unknown baud rate %d for %s (B9600 used)\n",
428 dcb.StopBits = ONESTOPBIT;
430 dcb.StopBits = TWOSTOPBITS;
433 if (ctx_rtu->
parity ==
'N') {
434 dcb.Parity = NOPARITY;
436 }
else if (ctx_rtu->
parity ==
'E') {
437 dcb.Parity = EVENPARITY;
441 dcb.Parity = ODDPARITY;
448 dcb.fTXContinueOnXoff =
TRUE;
456 dcb.fAbortOnError =
FALSE;
461 if (!SetCommState(ctx_rtu->w_ser.fd, &dcb)) {
462 fprintf(stderr,
"ERROR Error setting new configuration (LastError %d)\n",
463 (
int)GetLastError());
464 CloseHandle(ctx_rtu->w_ser.fd);
465 ctx_rtu->w_ser.fd = INVALID_HANDLE_VALUE;
476 ctx->
s = open(ctx_rtu->
device, O_RDWR | O_NOCTTY | O_NDELAY | O_EXCL);
478 fprintf(stderr,
"ERROR Can't open the device %s (%s)\n",
479 ctx_rtu->
device, strerror(errno));
486 memset(&tios, 0,
sizeof(
struct termios));
491 struct serial_struct ss;
492 switch (ctx_rtu->
baud) {
530 ioctl(ctx->
s, TIOCGSERIAL, &ss);
531 ss.flags = (ss.flags & ~ASYNC_SPD_MASK) | ASYNC_SPD_CUST;
532 ss.custom_divisor = (ss.baud_base + (ctx_rtu->
baud / 2)) / ctx_rtu->
baud;
533 int closestSpeed = ss.baud_base / ss.custom_divisor;
535 if (closestSpeed < ctx_rtu->baud * 98 / 100 || closestSpeed > ctx_rtu->
baud * 102 / 100) {
536 fprintf(stderr,
"Cannot set serial port speed to. Closest possible is %i\n", closestSpeed);
539 ioctl(ctx->
s, TIOCSSERIAL, &ss);
541 cfsetispeed(&tios, B38400);
542 cfsetospeed(&tios, B38400);
548 "WARNING Unknown baud rate %d for %s (B9600 used)\n",
552 fprintf(stderr,
"Setting speed to: %i \n", speed);
554 if ((cfsetispeed(&tios, speed) < 0) ||
555 (cfsetospeed(&tios, speed) < 0)) {
565 tios.c_cflag |= (CREAD | CLOCAL);
571 tios.c_cflag &= ~CSIZE;
590 tios.c_cflag &=~ CSTOPB;
592 tios.c_cflag |= CSTOPB;
596 if (ctx_rtu->
parity ==
'N') {
598 tios.c_cflag &=~ PARENB;
599 }
else if (ctx_rtu->
parity ==
'E') {
601 tios.c_cflag |= PARENB;
602 tios.c_cflag &=~ PARODD;
605 tios.c_cflag |= PARENB;
606 tios.c_cflag |= PARODD;
646 tios.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG);
666 if (ctx_rtu->
parity ==
'N') {
668 tios.c_iflag &= ~INPCK;
670 tios.c_iflag |= INPCK;
674 tios.c_iflag &= ~(IXON | IXOFF | IXANY);
684 tios.c_oflag &=~ OPOST;
727 tios.c_cc[VTIME] = 0;
729 if (tcsetattr(ctx->
s, TCSANOW, &tios) < 0) {
736 #if HAVE_DECL_TIOCSRS485 737 fprintf(stderr,
"HAVE_DECL_TIOCSRS485\n");
753 #if HAVE_DECL_TIOCSRS485 755 struct serial_rs485 rs485conf;
758 if (ioctl(ctx->
s, TIOCGRS485, &rs485conf) < 0) {
759 fprintf(stderr,
"Getting serial mode failed\n");
763 rs485conf.flags |= SER_RS485_ENABLED;
764 if (ioctl(ctx->
s, TIOCSRS485, &rs485conf) < 0) {
765 fprintf(stderr,
"Setting serial mode to rs485 failed\n");
772 if (ioctl(ctx->
s, TIOCSRS485, &rs485conf) < 0) {
775 fprintf(stderr,
"Setting to serial mode RTU RS232\n");
781 fprintf(stderr,
"This function isn't supported on your platform\n");
787 fprintf(stderr,
"wrong backed\n");
795 #if HAVE_DECL_TIOCSRS485 797 return ctx_rtu->serial_mode;
800 fprintf(stderr,
"This function isn't supported on your platform\n");
818 if (!SetCommState(ctx_rtu->w_ser.fd, &ctx_rtu->old_dcb))
819 fprintf(stderr,
"ERROR Couldn't revert to configuration (LastError %d)\n",
820 (
int)GetLastError());
822 if (!CloseHandle(ctx_rtu->w_ser.fd))
823 fprintf(stderr,
"ERROR Error while closing handle (LastError %d)\n",
824 (
int)GetLastError());
826 tcsetattr(ctx->
s, TCSANOW, &(ctx_rtu->
old_tios));
835 ctx_rtu->w_ser.n_bytes = 0;
836 return (FlushFileBuffers(ctx_rtu->w_ser.fd) ==
FALSE);
838 return tcflush(ctx->
s, TCIOFLUSH);
843 struct timeval *tv,
int length_to_read)
858 while ((s_rc = select(ctx->
s+1, rfds, NULL, NULL, tv)) == -1) {
859 if (errno == EINTR) {
861 fprintf(stderr,
"A non blocked signal was caught\n");
865 FD_SET(ctx->
s, rfds);
887 printf(
"Request for slave %d ignored (not %d)\n",
918 int baud,
char parity,
int data_bit,
933 dest_size =
sizeof(ctx_rtu->
device);
936 fprintf(stderr,
"The device string is empty\n");
942 if (ret_size >= dest_size) {
943 fprintf(stderr,
"The device string has been truncated\n");
949 ctx_rtu->
baud = baud;
950 if (parity ==
'N' || parity ==
'E' || parity ==
'O') {
static int _modbus_rtu_build_response_basis(sft_t *sft, uint8_t *rsp)
#define _MODBUS_RTU_HEADER_LENGTH
static int _modbus_set_slave(modbus_t *ctx, int slave)
size_t strlcpy(char *dest, const char *src, size_t dest_size)
#define MODBUS_RTU_MAX_ADU_LENGTH
int _modbus_rtu_send_msg_pre(uint8_t *req, int req_length)
static const uint8_t table_crc_hi[]
ssize_t _modbus_rtu_recv(modbus_t *ctx, uint8_t *rsp, int rsp_length)
int _modbus_rtu_filter_request(modbus_t *ctx, int slave)
void modbus_free(modbus_t *ctx)
const modbus_backend_t * backend
#define _MODBUS_RTU_CHECKSUM_LENGTH
int _modbus_rtu_check_integrity(modbus_t *ctx, uint8_t *msg, const int msg_length)
static int _modbus_rtu_build_request_basis(modbus_t *ctx, int function, int addr, int nb, uint8_t *req)
ssize_t _modbus_rtu_send(modbus_t *ctx, const uint8_t *req, int req_length)
#define _MODBUS_RTU_PRESET_RSP_LENGTH
#define MODBUS_BROADCAST_ADDRESS
#define _MODBUS_RTU_PRESET_REQ_LENGTH
static const uint8_t table_crc_lo[]
void _modbus_init_common(modbus_t *ctx)
int _modbus_rtu_prepare_response_tid(const uint8_t *req, int *req_length)
int _modbus_rtu_flush(modbus_t *)
void _modbus_rtu_close(modbus_t *ctx)
int modbus_rtu_get_serial_mode(modbus_t *ctx)
int _modbus_rtu_select(modbus_t *ctx, fd_set *rfds, struct timeval *tv, int length_to_read)
int modbus_rtu_set_serial_mode(modbus_t *ctx, int mode)
static int _modbus_rtu_connect(modbus_t *ctx)
unsigned int backend_type
const modbus_backend_t _modbus_rtu_backend
static uint16_t crc16(uint8_t *buffer, uint16_t buffer_length)
modbus_t * modbus_new_rtu(const char *device, int baud, char parity, int data_bit, int stop_bit)