|
@@ -166,30 +166,38 @@ int _modbus_rtu_send_msg_pre(uint8_t *req, int req_length)
|
|
|
|
|
|
static void win32_ser_init(struct win32_ser *ws) {
|
|
|
/* Clear everything */
|
|
|
- memset(ws,0x00,sizeof(struct win32_ser));
|
|
|
+ memset(ws, 0x00, sizeof(struct win32_ser));
|
|
|
+
|
|
|
/* Set file handle to invalid */
|
|
|
ws->fd = INVALID_HANDLE_VALUE;
|
|
|
}
|
|
|
|
|
|
static int win32_ser_select(struct win32_ser *ws, int max_len, struct timeval *tv) {
|
|
|
- COMMTIMEOUTS comm_to; unsigned int msec = 0;
|
|
|
+ COMMTIMEOUTS comm_to;
|
|
|
+ unsigned int msec = 0;
|
|
|
+
|
|
|
/* Check if some data still in the buffer to be consumed */
|
|
|
if (ws->n_bytes> 0) {
|
|
|
return 1;
|
|
|
}
|
|
|
+
|
|
|
/* Setup timeouts like select() would do */
|
|
|
msec = tv->tv_sec * 1000 + tv->tv_usec / 1000;
|
|
|
- if (msec < 1) msec = 1;
|
|
|
+ if (msec < 1)
|
|
|
+ msec = 1;
|
|
|
+
|
|
|
comm_to.ReadIntervalTimeout = msec;
|
|
|
comm_to.ReadTotalTimeoutMultiplier = 0;
|
|
|
comm_to.ReadTotalTimeoutConstant = msec;
|
|
|
comm_to.WriteTotalTimeoutMultiplier = 0;
|
|
|
comm_to.WriteTotalTimeoutConstant = 1000;
|
|
|
- SetCommTimeouts(ws->fd,&comm_to);
|
|
|
+ SetCommTimeouts(ws->fd, &comm_to);
|
|
|
+
|
|
|
/* Read some bytes */
|
|
|
if ((max_len > PY_BUF_SIZE) || (max_len < 0)) {
|
|
|
max_len = PY_BUF_SIZE;
|
|
|
}
|
|
|
+
|
|
|
if (ReadFile(ws->fd, &ws->buf, max_len, &ws->n_bytes, NULL)) {
|
|
|
/* Check if some bytes available */
|
|
|
if (ws->n_bytes > 0) {
|
|
@@ -207,14 +215,18 @@ static int win32_ser_select(struct win32_ser *ws, int max_len, struct timeval *t
|
|
|
|
|
|
static int win32_ser_read(struct win32_ser *ws, uint8_t *p_msg, unsigned int max_len) {
|
|
|
unsigned int n = ws->n_bytes;
|
|
|
+
|
|
|
if (max_len < n) {
|
|
|
n = max_len;
|
|
|
}
|
|
|
+
|
|
|
if (n > 0) {
|
|
|
- memcpy(p_msg,ws->buf,n);
|
|
|
+ memcpy(p_msg, ws->buf, n);
|
|
|
}
|
|
|
+
|
|
|
ws->n_bytes -= n;
|
|
|
- return(n);
|
|
|
+
|
|
|
+ return n;
|
|
|
}
|
|
|
#endif
|
|
|
|
|
@@ -290,12 +302,12 @@ static int _modbus_rtu_connect(modbus_t *ctx)
|
|
|
|
|
|
/* ctx_rtu->device should contain a string like "COMxx:" xx being a decimal number */
|
|
|
ctx_rtu->w_ser.fd = CreateFileA(ctx_rtu->device,
|
|
|
- GENERIC_READ | GENERIC_WRITE,
|
|
|
- 0,
|
|
|
- NULL,
|
|
|
- OPEN_EXISTING,
|
|
|
- 0,
|
|
|
- NULL);
|
|
|
+ GENERIC_READ | GENERIC_WRITE,
|
|
|
+ 0,
|
|
|
+ NULL,
|
|
|
+ OPEN_EXISTING,
|
|
|
+ 0,
|
|
|
+ NULL);
|
|
|
|
|
|
/* Error checking */
|
|
|
if (ctx_rtu->w_ser.fd == INVALID_HANDLE_VALUE) {
|
|
@@ -317,102 +329,102 @@ static int _modbus_rtu_connect(modbus_t *ctx)
|
|
|
|
|
|
/* Speed setting */
|
|
|
switch (ctx_rtu->baud) {
|
|
|
- case 110:
|
|
|
- dcb.BaudRate = CBR_110;
|
|
|
- break;
|
|
|
- case 300:
|
|
|
- dcb.BaudRate = CBR_300;
|
|
|
- break;
|
|
|
- case 600:
|
|
|
- dcb.BaudRate = CBR_600;
|
|
|
- break;
|
|
|
- case 1200:
|
|
|
- dcb.BaudRate = CBR_1200;
|
|
|
- break;
|
|
|
- case 2400:
|
|
|
- dcb.BaudRate = CBR_2400;
|
|
|
- break;
|
|
|
- case 4800:
|
|
|
- dcb.BaudRate = CBR_4800;
|
|
|
- break;
|
|
|
- case 9600:
|
|
|
- dcb.BaudRate = CBR_9600;
|
|
|
- break;
|
|
|
- case 19200:
|
|
|
- dcb.BaudRate = CBR_19200;
|
|
|
- break;
|
|
|
- case 38400:
|
|
|
- dcb.BaudRate = CBR_38400;
|
|
|
- break;
|
|
|
- case 57600:
|
|
|
- dcb.BaudRate = CBR_57600;
|
|
|
- break;
|
|
|
- case 115200:
|
|
|
- dcb.BaudRate = CBR_115200;
|
|
|
- break;
|
|
|
- default:
|
|
|
- dcb.BaudRate = CBR_9600;
|
|
|
- printf("WARNING Unknown baud rate %d for %s (B9600 used)\n",
|
|
|
- ctx_rtu->baud, ctx_rtu->device);
|
|
|
- }
|
|
|
+ case 110:
|
|
|
+ dcb.BaudRate = CBR_110;
|
|
|
+ break;
|
|
|
+ case 300:
|
|
|
+ dcb.BaudRate = CBR_300;
|
|
|
+ break;
|
|
|
+ case 600:
|
|
|
+ dcb.BaudRate = CBR_600;
|
|
|
+ break;
|
|
|
+ case 1200:
|
|
|
+ dcb.BaudRate = CBR_1200;
|
|
|
+ break;
|
|
|
+ case 2400:
|
|
|
+ dcb.BaudRate = CBR_2400;
|
|
|
+ break;
|
|
|
+ case 4800:
|
|
|
+ dcb.BaudRate = CBR_4800;
|
|
|
+ break;
|
|
|
+ case 9600:
|
|
|
+ dcb.BaudRate = CBR_9600;
|
|
|
+ break;
|
|
|
+ case 19200:
|
|
|
+ dcb.BaudRate = CBR_19200;
|
|
|
+ break;
|
|
|
+ case 38400:
|
|
|
+ dcb.BaudRate = CBR_38400;
|
|
|
+ break;
|
|
|
+ case 57600:
|
|
|
+ dcb.BaudRate = CBR_57600;
|
|
|
+ break;
|
|
|
+ case 115200:
|
|
|
+ dcb.BaudRate = CBR_115200;
|
|
|
+ break;
|
|
|
+ default:
|
|
|
+ dcb.BaudRate = CBR_9600;
|
|
|
+ printf("WARNING Unknown baud rate %d for %s (B9600 used)\n",
|
|
|
+ ctx_rtu->baud, ctx_rtu->device);
|
|
|
+ }
|
|
|
|
|
|
- /* Data bits */
|
|
|
- switch (ctx_rtu->data_bit) {
|
|
|
- case 5:
|
|
|
- dcb.ByteSize = 5;
|
|
|
- break;
|
|
|
- case 6:
|
|
|
- dcb.ByteSize = 6;
|
|
|
- break;
|
|
|
- case 7:
|
|
|
- dcb.ByteSize = 7;
|
|
|
- break;
|
|
|
- case 8:
|
|
|
- default:
|
|
|
- dcb.ByteSize = 8;
|
|
|
- break;
|
|
|
- }
|
|
|
+ /* Data bits */
|
|
|
+ switch (ctx_rtu->data_bit) {
|
|
|
+ case 5:
|
|
|
+ dcb.ByteSize = 5;
|
|
|
+ break;
|
|
|
+ case 6:
|
|
|
+ dcb.ByteSize = 6;
|
|
|
+ break;
|
|
|
+ case 7:
|
|
|
+ dcb.ByteSize = 7;
|
|
|
+ break;
|
|
|
+ case 8:
|
|
|
+ default:
|
|
|
+ dcb.ByteSize = 8;
|
|
|
+ break;
|
|
|
+ }
|
|
|
|
|
|
- /* Stop bits */
|
|
|
- if (ctx_rtu->stop_bit == 1)
|
|
|
- dcb.StopBits = ONESTOPBIT;
|
|
|
- else /* 2 */
|
|
|
- dcb.StopBits = TWOSTOPBITS;
|
|
|
-
|
|
|
- /* Parity */
|
|
|
- if (ctx_rtu->parity == 'N') {
|
|
|
- dcb.Parity = NOPARITY;
|
|
|
- dcb.fParity = FALSE;
|
|
|
- } else if (ctx_rtu->parity == 'E') {
|
|
|
- dcb.Parity = EVENPARITY;
|
|
|
- dcb.fParity = TRUE;
|
|
|
- } else {
|
|
|
- /* odd */
|
|
|
- dcb.Parity = ODDPARITY;
|
|
|
- dcb.fParity = TRUE;
|
|
|
- }
|
|
|
+ /* Stop bits */
|
|
|
+ if (ctx_rtu->stop_bit == 1)
|
|
|
+ dcb.StopBits = ONESTOPBIT;
|
|
|
+ else /* 2 */
|
|
|
+ dcb.StopBits = TWOSTOPBITS;
|
|
|
|
|
|
- /* Hardware handshaking left as default settings retrieved */
|
|
|
+ /* Parity */
|
|
|
+ if (ctx_rtu->parity == 'N') {
|
|
|
+ dcb.Parity = NOPARITY;
|
|
|
+ dcb.fParity = FALSE;
|
|
|
+ } else if (ctx_rtu->parity == 'E') {
|
|
|
+ dcb.Parity = EVENPARITY;
|
|
|
+ dcb.fParity = TRUE;
|
|
|
+ } else {
|
|
|
+ /* odd */
|
|
|
+ dcb.Parity = ODDPARITY;
|
|
|
+ dcb.fParity = TRUE;
|
|
|
+ }
|
|
|
|
|
|
- /* No software handshaking */
|
|
|
- dcb.fTXContinueOnXoff = TRUE;
|
|
|
- dcb.fOutX = FALSE;
|
|
|
- dcb.fInX = FALSE;
|
|
|
+ /* Hardware handshaking left as default settings retrieved */
|
|
|
|
|
|
- /* Binary mode (it's the only supported on Windows anyway) */
|
|
|
- dcb.fBinary = TRUE;
|
|
|
+ /* No software handshaking */
|
|
|
+ dcb.fTXContinueOnXoff = TRUE;
|
|
|
+ dcb.fOutX = FALSE;
|
|
|
+ dcb.fInX = FALSE;
|
|
|
|
|
|
- /* Don't want errors to be blocking */
|
|
|
- dcb.fAbortOnError = FALSE;
|
|
|
+ /* Binary mode (it's the only supported on Windows anyway) */
|
|
|
+ dcb.fBinary = TRUE;
|
|
|
|
|
|
- /* TODO: any other flags !? */
|
|
|
+ /* Don't want errors to be blocking */
|
|
|
+ dcb.fAbortOnError = FALSE;
|
|
|
|
|
|
- /* Setup port */
|
|
|
- if (!SetCommState(ctx_rtu->w_ser.fd, &dcb)) {
|
|
|
- fprintf(stderr, "ERROR Error setting new configuration (LastError %d)\n",
|
|
|
- (int)GetLastError());
|
|
|
- return -1;
|
|
|
- }
|
|
|
+ /* TODO: any other flags!? */
|
|
|
+
|
|
|
+ /* Setup port */
|
|
|
+ if (!SetCommState(ctx_rtu->w_ser.fd, &dcb)) {
|
|
|
+ fprintf(stderr, "ERROR Error setting new configuration (LastError %d)\n",
|
|
|
+ (int)GetLastError());
|
|
|
+ return -1;
|
|
|
+ }
|
|
|
#else
|
|
|
/* The O_NOCTTY flag tells UNIX that this program doesn't want
|
|
|
to be the "controlling terminal" for that port. If you
|