Commit e2f59e9e54b7b1eefe023d67387adb4366ab29d6
Committed by
Stéphane Raimbault
1 parent
31577bbb
Added support for native Win32
Added support for native Win32 based on https://code.launchpad.net/~thepyper/libmodbus/win32-native This mainly affects the RTU implementation as the TCP/IP socket interface is the same thanks to the winsocks library. The interface for using the serial port is completely different on Win32 and is now implemented accordingly. Signed-off-by: Stéphane Raimbault <stephane.raimbault@gmail.com>
Showing
5 changed files
with
299 additions
and
6 deletions
src/modbus-rtu-private.h
| @@ -24,6 +24,23 @@ | @@ -24,6 +24,23 @@ | ||
| 24 | 24 | ||
| 25 | #define _MODBUS_RTU_CHECKSUM_LENGTH 2 | 25 | #define _MODBUS_RTU_CHECKSUM_LENGTH 2 |
| 26 | 26 | ||
| 27 | +#ifdef NATIVE_WIN32 | ||
| 28 | + | ||
| 29 | +#define WIN32_LEAN_AND_MEAN | ||
| 30 | +#include <windows.h> | ||
| 31 | + | ||
| 32 | +/* WIN32: struct containing serial handle and a receive buffer */ | ||
| 33 | +#define PY_BUF_SIZE 512 | ||
| 34 | +struct win32_ser { | ||
| 35 | + /* File handle */ | ||
| 36 | + HANDLE fd; | ||
| 37 | + /* Receive buffer */ | ||
| 38 | + uint8_t buf[PY_BUF_SIZE]; | ||
| 39 | + /* Received chars */ | ||
| 40 | + DWORD n_bytes; | ||
| 41 | +}; | ||
| 42 | +#endif /* NATIVE_WIN32 */ | ||
| 43 | + | ||
| 27 | typedef struct _modbus_rtu { | 44 | typedef struct _modbus_rtu { |
| 28 | /* Device: "/dev/ttyS0", "/dev/ttyUSB0" or "/dev/tty.USA19*" on Mac OS X for | 45 | /* Device: "/dev/ttyS0", "/dev/ttyUSB0" or "/dev/tty.USA19*" on Mac OS X for |
| 29 | KeySpan USB<->Serial adapters this string had to be made bigger on OS X | 46 | KeySpan USB<->Serial adapters this string had to be made bigger on OS X |
| @@ -43,8 +60,13 @@ typedef struct _modbus_rtu { | @@ -43,8 +60,13 @@ typedef struct _modbus_rtu { | ||
| 43 | uint8_t stop_bit; | 60 | uint8_t stop_bit; |
| 44 | /* Parity: 'N', 'O', 'E' */ | 61 | /* Parity: 'N', 'O', 'E' */ |
| 45 | char parity; | 62 | char parity; |
| 63 | +#ifdef NATIVE_WIN32 | ||
| 64 | + struct win32_ser w_ser; | ||
| 65 | + DCB old_dcb; | ||
| 66 | +#else | ||
| 46 | /* Save old termios settings */ | 67 | /* Save old termios settings */ |
| 47 | struct termios old_tios; | 68 | struct termios old_tios; |
| 69 | +#endif | ||
| 48 | } modbus_rtu_t; | 70 | } modbus_rtu_t; |
| 49 | 71 | ||
| 50 | #endif /* _MODBUS_RTU_PRIVATE_H_ */ | 72 | #endif /* _MODBUS_RTU_PRIVATE_H_ */ |
src/modbus-rtu.c
| @@ -155,14 +155,87 @@ int _modbus_rtu_send_msg_pre(uint8_t *req, int req_length) | @@ -155,14 +155,87 @@ int _modbus_rtu_send_msg_pre(uint8_t *req, int req_length) | ||
| 155 | return req_length; | 155 | return req_length; |
| 156 | } | 156 | } |
| 157 | 157 | ||
| 158 | +#ifdef NATIVE_WIN32 | ||
| 159 | +/* This simple implementation is sort of a substitute of the select() call, working | ||
| 160 | + * this way: the win32_ser_select() call tries to read some data from the serial port, | ||
| 161 | + * setting the timeout as the select() call would. Data read is stored into the | ||
| 162 | + * receive buffer, that is then consumed by the win32_ser_read() call. | ||
| 163 | + * So win32_ser_select() does both the event waiting and the reading, | ||
| 164 | + * while win32_ser_read() only consumes the receive buffer. | ||
| 165 | + */ | ||
| 166 | + | ||
| 167 | +static void win32_ser_init(struct win32_ser *ws) { | ||
| 168 | + /* Clear everything */ | ||
| 169 | + memset(ws,0x00,sizeof(struct win32_ser)); | ||
| 170 | + /* Set file handle to invalid */ | ||
| 171 | + ws->fd = INVALID_HANDLE_VALUE; | ||
| 172 | +} | ||
| 173 | + | ||
| 174 | +static int win32_ser_select(struct win32_ser *ws, int max_len, struct timeval *tv) { | ||
| 175 | + COMMTIMEOUTS comm_to; unsigned int msec = 0; | ||
| 176 | + /* Check if some data still in the buffer to be consumed */ | ||
| 177 | + if (ws->n_bytes> 0) { | ||
| 178 | + return 1; | ||
| 179 | + } | ||
| 180 | + /* Setup timeouts like select() would do */ | ||
| 181 | + msec = tv->tv_sec * 1000 + tv->tv_usec / 1000; | ||
| 182 | + if (msec < 1) msec = 1; | ||
| 183 | + comm_to.ReadIntervalTimeout = msec; | ||
| 184 | + comm_to.ReadTotalTimeoutMultiplier = 0; | ||
| 185 | + comm_to.ReadTotalTimeoutConstant = msec; | ||
| 186 | + comm_to.WriteTotalTimeoutMultiplier = 0; | ||
| 187 | + comm_to.WriteTotalTimeoutConstant = 1000; | ||
| 188 | + SetCommTimeouts(ws->fd,&comm_to); | ||
| 189 | + /* Read some bytes */ | ||
| 190 | + if ((max_len > PY_BUF_SIZE) || (max_len < 0)) { | ||
| 191 | + max_len = PY_BUF_SIZE; | ||
| 192 | + } | ||
| 193 | + if (ReadFile(ws->fd, &ws->buf, max_len, &ws->n_bytes, NULL)) { | ||
| 194 | + /* Check if some bytes available */ | ||
| 195 | + if (ws->n_bytes > 0) { | ||
| 196 | + /* Some bytes read */ | ||
| 197 | + return 1; | ||
| 198 | + } else { | ||
| 199 | + /* Just timed out */ | ||
| 200 | + return 0; | ||
| 201 | + } | ||
| 202 | + } else { | ||
| 203 | + /* Some kind of error */ | ||
| 204 | + return -1; | ||
| 205 | + } | ||
| 206 | +} | ||
| 207 | + | ||
| 208 | +static int win32_ser_read(struct win32_ser *ws, uint8_t *p_msg, unsigned int max_len) { | ||
| 209 | + unsigned int n = ws->n_bytes; | ||
| 210 | + if (max_len < n) { | ||
| 211 | + n = max_len; | ||
| 212 | + } | ||
| 213 | + if (n > 0) { | ||
| 214 | + memcpy(p_msg,ws->buf,n); | ||
| 215 | + } | ||
| 216 | + ws->n_bytes -= n; | ||
| 217 | + return(n); | ||
| 218 | +} | ||
| 219 | +#endif | ||
| 220 | + | ||
| 158 | ssize_t _modbus_rtu_send(modbus_t *ctx, const uint8_t *req, int req_length) | 221 | ssize_t _modbus_rtu_send(modbus_t *ctx, const uint8_t *req, int req_length) |
| 159 | { | 222 | { |
| 223 | +#ifdef NATIVE_WIN32 | ||
| 224 | + modbus_rtu_t *ctx_rtu = ctx->backend_data; | ||
| 225 | + DWORD n_bytes = 0; | ||
| 226 | + return (WriteFile(ctx_rtu->w_ser.fd, req, req_length, &n_bytes, NULL)) ? n_bytes : -1; | ||
| 227 | +#else | ||
| 160 | return write(ctx->s, req, req_length); | 228 | return write(ctx->s, req, req_length); |
| 229 | +#endif | ||
| 161 | } | 230 | } |
| 162 | 231 | ||
| 163 | ssize_t _modbus_rtu_recv(modbus_t *ctx, uint8_t *rsp, int rsp_length) | 232 | ssize_t _modbus_rtu_recv(modbus_t *ctx, uint8_t *rsp, int rsp_length) |
| 164 | { | 233 | { |
| 234 | +#ifdef NATIVE_WIN32 | ||
| 235 | + return win32_ser_read(&((modbus_rtu_t *)ctx->backend_data)->w_ser, rsp, rsp_length); | ||
| 236 | +#else | ||
| 165 | return read(ctx->s, rsp, rsp_length); | 237 | return read(ctx->s, rsp, rsp_length); |
| 238 | +#endif | ||
| 166 | } | 239 | } |
| 167 | 240 | ||
| 168 | /* The check_crc16 function shall return the message length if the CRC is | 241 | /* The check_crc16 function shall return the message length if the CRC is |
| @@ -195,8 +268,12 @@ int _modbus_rtu_check_integrity(modbus_t *ctx, uint8_t *msg, | @@ -195,8 +268,12 @@ int _modbus_rtu_check_integrity(modbus_t *ctx, uint8_t *msg, | ||
| 195 | /* Sets up a serial port for RTU communications */ | 268 | /* Sets up a serial port for RTU communications */ |
| 196 | static int _modbus_rtu_connect(modbus_t *ctx) | 269 | static int _modbus_rtu_connect(modbus_t *ctx) |
| 197 | { | 270 | { |
| 271 | +#ifdef NATIVE_WIN32 | ||
| 272 | + DCB dcb; | ||
| 273 | +#else | ||
| 198 | struct termios tios; | 274 | struct termios tios; |
| 199 | speed_t speed; | 275 | speed_t speed; |
| 276 | +#endif | ||
| 200 | modbus_rtu_t *ctx_rtu = ctx->backend_data; | 277 | modbus_rtu_t *ctx_rtu = ctx->backend_data; |
| 201 | 278 | ||
| 202 | if (ctx->debug) { | 279 | if (ctx->debug) { |
| @@ -205,6 +282,138 @@ static int _modbus_rtu_connect(modbus_t *ctx) | @@ -205,6 +282,138 @@ static int _modbus_rtu_connect(modbus_t *ctx) | ||
| 205 | ctx_rtu->data_bit, ctx_rtu->stop_bit); | 282 | ctx_rtu->data_bit, ctx_rtu->stop_bit); |
| 206 | } | 283 | } |
| 207 | 284 | ||
| 285 | +#ifdef NATIVE_WIN32 | ||
| 286 | + /* Some references here: | ||
| 287 | + * http://msdn.microsoft.com/en-us/library/aa450602.aspx | ||
| 288 | + */ | ||
| 289 | + win32_ser_init(&ctx_rtu->w_ser); | ||
| 290 | + | ||
| 291 | + /* ctx_rtu->device should contain a string like "COMxx:" xx being a decimal number */ | ||
| 292 | + ctx_rtu->w_ser.fd = CreateFileA(ctx_rtu->device, | ||
| 293 | + GENERIC_READ | GENERIC_WRITE, | ||
| 294 | + 0, | ||
| 295 | + NULL, | ||
| 296 | + OPEN_EXISTING, | ||
| 297 | + 0, | ||
| 298 | + NULL); | ||
| 299 | + | ||
| 300 | + /* Error checking */ | ||
| 301 | + if (ctx_rtu->w_ser.fd == INVALID_HANDLE_VALUE) { | ||
| 302 | + fprintf(stderr, "ERROR Can't open the device %s (%s)\n", | ||
| 303 | + ctx_rtu->device, strerror(errno)); | ||
| 304 | + return -1; | ||
| 305 | + } | ||
| 306 | + | ||
| 307 | + /* Save params */ | ||
| 308 | + ctx_rtu->old_dcb.DCBlength = sizeof(DCB); | ||
| 309 | + if (!GetCommState(ctx_rtu->w_ser.fd, &ctx_rtu->old_dcb)) { | ||
| 310 | + fprintf(stderr, "ERROR Error getting configuration (LastError %d)\n", | ||
| 311 | + (int)GetLastError()); | ||
| 312 | + return -1; | ||
| 313 | + } | ||
| 314 | + | ||
| 315 | + /* Build new configuration (starting from current settings) */ | ||
| 316 | + dcb = ctx_rtu->old_dcb; | ||
| 317 | + | ||
| 318 | + /* Speed setting */ | ||
| 319 | + switch (ctx_rtu->baud) { | ||
| 320 | + case 110: | ||
| 321 | + dcb.BaudRate = CBR_110; | ||
| 322 | + break; | ||
| 323 | + case 300: | ||
| 324 | + dcb.BaudRate = CBR_300; | ||
| 325 | + break; | ||
| 326 | + case 600: | ||
| 327 | + dcb.BaudRate = CBR_600; | ||
| 328 | + break; | ||
| 329 | + case 1200: | ||
| 330 | + dcb.BaudRate = CBR_1200; | ||
| 331 | + break; | ||
| 332 | + case 2400: | ||
| 333 | + dcb.BaudRate = CBR_2400; | ||
| 334 | + break; | ||
| 335 | + case 4800: | ||
| 336 | + dcb.BaudRate = CBR_4800; | ||
| 337 | + break; | ||
| 338 | + case 9600: | ||
| 339 | + dcb.BaudRate = CBR_9600; | ||
| 340 | + break; | ||
| 341 | + case 19200: | ||
| 342 | + dcb.BaudRate = CBR_19200; | ||
| 343 | + break; | ||
| 344 | + case 38400: | ||
| 345 | + dcb.BaudRate = CBR_38400; | ||
| 346 | + break; | ||
| 347 | + case 57600: | ||
| 348 | + dcb.BaudRate = CBR_57600; | ||
| 349 | + break; | ||
| 350 | + case 115200: | ||
| 351 | + dcb.BaudRate = CBR_115200; | ||
| 352 | + break; | ||
| 353 | + default: | ||
| 354 | + dcb.BaudRate = CBR_9600; | ||
| 355 | + printf("WARNING Unknown baud rate %d for %s (B9600 used)\n", | ||
| 356 | + ctx_rtu->baud, ctx_rtu->device); | ||
| 357 | + } | ||
| 358 | + | ||
| 359 | + /* Data bits */ | ||
| 360 | + switch (ctx_rtu->data_bit) { | ||
| 361 | + case 5: | ||
| 362 | + dcb.ByteSize = 5; | ||
| 363 | + break; | ||
| 364 | + case 6: | ||
| 365 | + dcb.ByteSize = 6; | ||
| 366 | + break; | ||
| 367 | + case 7: | ||
| 368 | + dcb.ByteSize = 7; | ||
| 369 | + break; | ||
| 370 | + case 8: | ||
| 371 | + default: | ||
| 372 | + dcb.ByteSize = 8; | ||
| 373 | + break; | ||
| 374 | + } | ||
| 375 | + | ||
| 376 | + /* Stop bits */ | ||
| 377 | + if (ctx_rtu->stop_bit == 1) | ||
| 378 | + dcb.StopBits = ONESTOPBIT; | ||
| 379 | + else /* 2 */ | ||
| 380 | + dcb.StopBits = TWOSTOPBITS; | ||
| 381 | + | ||
| 382 | + /* Parity */ | ||
| 383 | + if (ctx_rtu->parity == 'N') { | ||
| 384 | + dcb.Parity = NOPARITY; | ||
| 385 | + dcb.fParity = FALSE; | ||
| 386 | + } else if (ctx_rtu->parity == 'E') { | ||
| 387 | + dcb.Parity = EVENPARITY; | ||
| 388 | + dcb.fParity = TRUE; | ||
| 389 | + } else { | ||
| 390 | + /* odd */ | ||
| 391 | + dcb.Parity = ODDPARITY; | ||
| 392 | + dcb.fParity = TRUE; | ||
| 393 | + } | ||
| 394 | + | ||
| 395 | + /* Hardware handshaking left as default settings retrieved */ | ||
| 396 | + | ||
| 397 | + /* No software handshaking */ | ||
| 398 | + dcb.fTXContinueOnXoff = TRUE; | ||
| 399 | + dcb.fOutX = FALSE; | ||
| 400 | + dcb.fInX = FALSE; | ||
| 401 | + | ||
| 402 | + /* Binary mode (it's the only supported on Windows anyway) */ | ||
| 403 | + dcb.fBinary = TRUE; | ||
| 404 | + | ||
| 405 | + /* Don't want errors to be blocking */ | ||
| 406 | + dcb.fAbortOnError = FALSE; | ||
| 407 | + | ||
| 408 | + /* TODO: any other flags !? */ | ||
| 409 | + | ||
| 410 | + /* Setup port */ | ||
| 411 | + if (!SetCommState(ctx_rtu->w_ser.fd, &dcb)) { | ||
| 412 | + fprintf(stderr, "ERROR Error setting new configuration (LastError %d)\n", | ||
| 413 | + (int)GetLastError()); | ||
| 414 | + return -1; | ||
| 415 | + } | ||
| 416 | +#else | ||
| 208 | /* The O_NOCTTY flag tells UNIX that this program doesn't want | 417 | /* The O_NOCTTY flag tells UNIX that this program doesn't want |
| 209 | to be the "controlling terminal" for that port. If you | 418 | to be the "controlling terminal" for that port. If you |
| 210 | don't specify this then any input (such as keyboard abort | 419 | don't specify this then any input (such as keyboard abort |
| @@ -447,6 +656,7 @@ static int _modbus_rtu_connect(modbus_t *ctx) | @@ -447,6 +656,7 @@ static int _modbus_rtu_connect(modbus_t *ctx) | ||
| 447 | if (tcsetattr(ctx->s, TCSANOW, &tios) < 0) { | 656 | if (tcsetattr(ctx->s, TCSANOW, &tios) < 0) { |
| 448 | return -1; | 657 | return -1; |
| 449 | } | 658 | } |
| 659 | +#endif | ||
| 450 | 660 | ||
| 451 | return 0; | 661 | return 0; |
| 452 | } | 662 | } |
| @@ -456,13 +666,30 @@ void _modbus_rtu_close(modbus_t *ctx) | @@ -456,13 +666,30 @@ void _modbus_rtu_close(modbus_t *ctx) | ||
| 456 | /* Closes the file descriptor in RTU mode */ | 666 | /* Closes the file descriptor in RTU mode */ |
| 457 | modbus_rtu_t *ctx_rtu = ctx->backend_data; | 667 | modbus_rtu_t *ctx_rtu = ctx->backend_data; |
| 458 | 668 | ||
| 669 | +#ifdef NATIVE_WIN32 | ||
| 670 | + /* Revert settings */ | ||
| 671 | + if (!SetCommState(ctx_rtu->w_ser.fd, &ctx_rtu->old_dcb)) | ||
| 672 | + fprintf(stderr, "ERROR Couldn't revert to configuration (LastError %d)\n", | ||
| 673 | + (int)GetLastError()); | ||
| 674 | + | ||
| 675 | + if (!CloseHandle(ctx_rtu->w_ser.fd)) | ||
| 676 | + fprintf(stderr, "ERROR Error while closing handle (LastError %d)\n", | ||
| 677 | + (int)GetLastError()); | ||
| 678 | +#else | ||
| 459 | tcsetattr(ctx->s, TCSANOW, &(ctx_rtu->old_tios)); | 679 | tcsetattr(ctx->s, TCSANOW, &(ctx_rtu->old_tios)); |
| 460 | close(ctx->s); | 680 | close(ctx->s); |
| 681 | +#endif | ||
| 461 | } | 682 | } |
| 462 | 683 | ||
| 463 | int _modbus_rtu_flush(modbus_t *ctx) | 684 | int _modbus_rtu_flush(modbus_t *ctx) |
| 464 | { | 685 | { |
| 686 | +#ifdef NATIVE_WIN32 | ||
| 687 | + modbus_rtu_t *ctx_rtu = ctx->backend_data; | ||
| 688 | + ctx_rtu->w_ser.n_bytes = 0; | ||
| 689 | + return ( FlushFileBuffers(ctx_rtu->w_ser.fd) == FALSE ); | ||
| 690 | +#else | ||
| 465 | return tcflush(ctx->s, TCIOFLUSH); | 691 | return tcflush(ctx->s, TCIOFLUSH); |
| 692 | +#endif | ||
| 466 | } | 693 | } |
| 467 | 694 | ||
| 468 | int _modbus_rtu_listen(modbus_t *ctx, int nb_connection) | 695 | int _modbus_rtu_listen(modbus_t *ctx, int nb_connection) |
| @@ -488,6 +715,25 @@ int _modbus_rtu_accept(modbus_t *ctx, int *socket) | @@ -488,6 +715,25 @@ int _modbus_rtu_accept(modbus_t *ctx, int *socket) | ||
| 488 | int _modbus_rtu_select(modbus_t *ctx, fd_set *rfds, struct timeval *tv, int msg_length_computed, int msg_length) | 715 | int _modbus_rtu_select(modbus_t *ctx, fd_set *rfds, struct timeval *tv, int msg_length_computed, int msg_length) |
| 489 | { | 716 | { |
| 490 | int s_rc; | 717 | int s_rc; |
| 718 | +#ifdef NATIVE_WIN32 | ||
| 719 | + s_rc = win32_ser_select(&(((modbus_rtu_t*)ctx->backend_data)->w_ser), msg_length_computed, tv); | ||
| 720 | + if (s_rc == 0) { | ||
| 721 | + errno = ETIMEDOUT; | ||
| 722 | + return -1; | ||
| 723 | + } | ||
| 724 | + | ||
| 725 | + if (s_rc < 0) { | ||
| 726 | + _error_print(ctx, "select"); | ||
| 727 | + if (ctx->error_recovery && (errno == EBADF)) { | ||
| 728 | + modbus_close(ctx); | ||
| 729 | + modbus_connect(ctx); | ||
| 730 | + errno = EBADF; | ||
| 731 | + return -1; | ||
| 732 | + } else { | ||
| 733 | + return -1; | ||
| 734 | + } | ||
| 735 | + } | ||
| 736 | +#else | ||
| 491 | while ((s_rc = select(ctx->s+1, rfds, NULL, NULL, tv)) == -1) { | 737 | while ((s_rc = select(ctx->s+1, rfds, NULL, NULL, tv)) == -1) { |
| 492 | if (errno == EINTR) { | 738 | if (errno == EINTR) { |
| 493 | if (ctx->debug) { | 739 | if (ctx->debug) { |
| @@ -524,6 +770,7 @@ int _modbus_rtu_select(modbus_t *ctx, fd_set *rfds, struct timeval *tv, int msg_ | @@ -524,6 +770,7 @@ int _modbus_rtu_select(modbus_t *ctx, fd_set *rfds, struct timeval *tv, int msg_ | ||
| 524 | } | 770 | } |
| 525 | return -1; | 771 | return -1; |
| 526 | } | 772 | } |
| 773 | +#endif | ||
| 527 | 774 | ||
| 528 | return s_rc; | 775 | return s_rc; |
| 529 | } | 776 | } |
src/modbus-tcp.c
| @@ -15,17 +15,21 @@ | @@ -15,17 +15,21 @@ | ||
| 15 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | 15 | * along with this program. If not, see <http://www.gnu.org/licenses/>. |
| 16 | */ | 16 | */ |
| 17 | 17 | ||
| 18 | +#include "modbus.h" | ||
| 19 | +#include "modbus-private.h" | ||
| 20 | + | ||
| 18 | #include <stdio.h> | 21 | #include <stdio.h> |
| 19 | #include <stdlib.h> | 22 | #include <stdlib.h> |
| 20 | #include <string.h> | 23 | #include <string.h> |
| 21 | #include <errno.h> | 24 | #include <errno.h> |
| 22 | 25 | ||
| 23 | #include <sys/types.h> | 26 | #include <sys/types.h> |
| 27 | +#ifdef NATIVE_WIN32 | ||
| 28 | +#include <ws2tcpip.h> | ||
| 29 | +#else | ||
| 24 | #include <sys/socket.h> | 30 | #include <sys/socket.h> |
| 25 | #include <sys/ioctl.h> | 31 | #include <sys/ioctl.h> |
| 26 | - | ||
| 27 | -#include "modbus.h" | ||
| 28 | -#include "modbus-private.h" | 32 | +#endif |
| 29 | 33 | ||
| 30 | #include "modbus-tcp.h" | 34 | #include "modbus-tcp.h" |
| 31 | #include "modbus-tcp-private.h" | 35 | #include "modbus-tcp-private.h" |
| @@ -164,7 +168,7 @@ static int _modbus_tcp_connect(modbus_t *ctx) | @@ -164,7 +168,7 @@ static int _modbus_tcp_connect(modbus_t *ctx) | ||
| 164 | return -1; | 168 | return -1; |
| 165 | } | 169 | } |
| 166 | 170 | ||
| 167 | -#if (!HAVE_DECL___CYGWIN__) | 171 | +#ifndef NATIVE_WIN32 |
| 168 | /** | 172 | /** |
| 169 | * Cygwin defines IPTOS_LOWDELAY but can't handle that flag so it's | 173 | * Cygwin defines IPTOS_LOWDELAY but can't handle that flag so it's |
| 170 | * necessary to workaround that problem. | 174 | * necessary to workaround that problem. |
| @@ -210,10 +214,10 @@ int _modbus_tcp_flush(modbus_t *ctx) | @@ -210,10 +214,10 @@ int _modbus_tcp_flush(modbus_t *ctx) | ||
| 210 | do { | 214 | do { |
| 211 | /* Extract the garbage from the socket */ | 215 | /* Extract the garbage from the socket */ |
| 212 | char devnull[MODBUS_TCP_MAX_ADU_LENGTH]; | 216 | char devnull[MODBUS_TCP_MAX_ADU_LENGTH]; |
| 213 | -#if (!HAVE_DECL___CYGWIN__) | 217 | +#ifndef NATIVE_WIN32 |
| 214 | rc = recv(ctx->s, devnull, MODBUS_TCP_MAX_ADU_LENGTH, MSG_DONTWAIT); | 218 | rc = recv(ctx->s, devnull, MODBUS_TCP_MAX_ADU_LENGTH, MSG_DONTWAIT); |
| 215 | #else | 219 | #else |
| 216 | - /* On Cygwin, it's a bit more complicated to not wait */ | 220 | + /* On Win32, it's a bit more complicated to not wait */ |
| 217 | fd_set rfds; | 221 | fd_set rfds; |
| 218 | struct timeval tv; | 222 | struct timeval tv; |
| 219 | 223 |
src/modbus.h
| @@ -18,11 +18,26 @@ | @@ -18,11 +18,26 @@ | ||
| 18 | #ifndef _MODBUS_H_ | 18 | #ifndef _MODBUS_H_ |
| 19 | #define _MODBUS_H_ | 19 | #define _MODBUS_H_ |
| 20 | 20 | ||
| 21 | +#include <config.h> | ||
| 22 | + | ||
| 23 | +/* If win32 and no cygwin, suppose it's MinGW or any other native windows compiler. */ | ||
| 24 | +#if defined(WIN32) && !defined(__CYGWIN__) | ||
| 25 | +#define NATIVE_WIN32 | ||
| 26 | +#define MSG_NOSIGNAL 0 | ||
| 27 | +#define ECONNRESET WSAECONNRESET | ||
| 28 | +#define ECONNREFUSED WSAECONNREFUSED | ||
| 29 | +#define ETIMEDOUT WSAETIMEDOUT | ||
| 30 | +#define ENOPROTOOPT WSAENOPROTOOPT | ||
| 31 | +#define SHUT_RDWR 2 | ||
| 32 | +#include <winsock2.h> | ||
| 33 | +#endif /* win32 and no cygwin */ | ||
| 34 | + | ||
| 21 | /* Add this for macros that defined unix flavor */ | 35 | /* Add this for macros that defined unix flavor */ |
| 22 | #if (defined(__unix__) || defined(unix)) && !defined(USG) | 36 | #if (defined(__unix__) || defined(unix)) && !defined(USG) |
| 23 | #include <sys/param.h> | 37 | #include <sys/param.h> |
| 24 | #endif | 38 | #endif |
| 25 | #include <stdint.h> | 39 | #include <stdint.h> |
| 40 | +#ifndef NATIVE_WIN32 | ||
| 26 | #include <termios.h> | 41 | #include <termios.h> |
| 27 | #if defined(OpenBSD) || (defined(__FreeBSD__) && __FreeBSD__ < 5) | 42 | #if defined(OpenBSD) || (defined(__FreeBSD__) && __FreeBSD__ < 5) |
| 28 | #include <netinet/in_systm.h> | 43 | #include <netinet/in_systm.h> |
| @@ -31,6 +46,7 @@ | @@ -31,6 +46,7 @@ | ||
| 31 | #include <netinet/ip.h> | 46 | #include <netinet/ip.h> |
| 32 | #include <netinet/tcp.h> | 47 | #include <netinet/tcp.h> |
| 33 | #include <arpa/inet.h> | 48 | #include <arpa/inet.h> |
| 49 | +#endif | ||
| 34 | #include <sys/time.h> | 50 | #include <sys/time.h> |
| 35 | 51 | ||
| 36 | #include "modbus-version.h" | 52 | #include "modbus-version.h" |
tests/bandwidth-server-many-up.c