Commit 754235c2f0187f7de2c1b167b260098cf1909c90

Authored by Stéphane Raimbault
1 parent 66c59d6f

Major - Oh Gosh, it's brand new API!

- more coherent
- namespace
- opaque and smaller context
- usual wording
MIGRATION
... ... @@ -2,37 +2,27 @@
2 2 Migration notes from the 2.0 series (for 2.2)
3 3 =============================================
4 4  
5   -1 - modbus_init_rtu/tcp takes a new argument, the slave number of the device
6   - which established the connection.
  5 +The 2.2 release use a brand new API and this document covers only the general
  6 +changes:
7 7  
8   -2 - modbus_init_listen_tcp() has been renamed to modbus_slave_listen_tcp() and
9   - requires a new argument, the maximal number of connections:
  8 +- the structure modbus_param_t is gone and is replaced by a new opaque and
  9 +dynamically allocated structure modbus_t.
10 10  
11   -int modbus_slave_init_tcp(modbus_param_t *mb_param, int nb_connection);
  11 +- the slave argument is no more an argument of the Modbus functions, you need to
  12 + call modbus_set_slave first.
12 13  
  14 +- the public header file is smaller so some internal defines aren't accessible
  15 + anymore.
13 16  
14   -3 - New function modbus_slave_accept_tcp() to etablish a new connection
15   - (previously in modbus_init_listen_tcp()):
  17 +- all function and constants are respectively prefixed by modbus_ or MODBUS_.
16 18  
17   -int modbus_slave_accept_tcp(modbus_param_t *mb_param, int *socket);
  19 +- the POSIX error conventions are used (if an error occured, -1 or NULL is
  20 + returned and errno is set accordingly).
18 21  
  22 +- coil status and discretes inputs are just bits and force/preset actions have
  23 + been renamed to write actions.
19 24  
20   -4 - modbus_listen() has been renamed to modbus_slave_receive() and requires a
21   - new argument, the socket file descriptor to listen on. If the sockfd is -1,
22   - the internal fd of modbus_param_t is used:
23   -
24   -int modbus_slave_receive(modbus_param_t *mb_param, int sockfd,
25   - uint8_t *query, int *query_length);
26   -
27   -
28   -5 - If you use the HEADER_LENGTH_ defines, their values have been incremented by
29   - 1 to reflect the PDU and ADU of the Modbus protocol and to reduce the CPU
30   - consumption:
31   - - HEADER_LENGTH_RTU 0 -> 1
32   - - HEADER_LENGTH_TCP 6 -> 7
33   -
34   -6 - modbus_mapping_new returns 0 on success and -1 on failure.
35   -
  25 +We hope you'll enjoy the new API to accept the migration burden!
36 26  
37 27 =============================================
38 28 Migration notes from the 1.2 series (for 2.0)
... ...
src/modbus-private.h 0 → 100644
  1 +/*
  2 + * Copyright © 2010 Stéphane Raimbault <stephane.raimbault@gmail.com>
  3 + *
  4 + * This program is free software: you can redistribute it and/or modify
  5 + * it under the terms of the GNU Lesser Public License as published by
  6 + * the Free Software Foundation; either version 3 of the License, or
  7 + * (at your option) any later version.
  8 + *
  9 + * This program is distributed in the hope that it will be useful,
  10 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  11 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12 + * GNU Lesser Public License for more details.
  13 + *
  14 + * You should have received a copy of the GNU Lesser Public License
  15 + * along with this program. If not, see <http://www.gnu.org/licenses/>.
  16 + */
  17 +
  18 +#ifndef _MODBUS_PRIVATE_H_
  19 +#define _MODBUS_PRIVATE_H_
  20 +
  21 +#include "modbus.h"
  22 +
  23 +MODBUS_BEGIN_DECLS
  24 +
  25 +#define HEADER_LENGTH_RTU 1
  26 +#define PRESET_REQ_LENGTH_RTU 6
  27 +#define PRESET_RSP_LENGTH_RTU 2
  28 +
  29 +#define HEADER_LENGTH_TCP 7
  30 +#define PRESET_REQ_LENGTH_TCP 12
  31 +#define PRESET_RSP_LENGTH_TCP 8
  32 +
  33 +#define CHECKSUM_LENGTH_RTU 2
  34 +#define CHECKSUM_LENGTH_TCP 0
  35 +
  36 +/* It's not really the minimal length (the real one is report slave ID
  37 + * in RTU (4 bytes)) but it's a convenient size to use in RTU or TCP
  38 + * communications to read many values or write a single one.
  39 + * Maximum between :
  40 + * - HEADER_LENGTH_TCP (7) + function (1) + address (2) + number (2)
  41 + * - HEADER_LENGTH_RTU (1) + function (1) + address (2) + number (2) + CRC (2)
  42 + */
  43 +#define MIN_REQ_LENGTH 12
  44 +
  45 +#define EXCEPTION_RSP_LENGTH_RTU 5
  46 +
  47 +#define REPORT_SLAVE_ID_LENGTH 75
  48 +
  49 +/* Time out between trames in microsecond */
  50 +#define TIME_OUT_BEGIN_OF_TRAME 500000
  51 +#define TIME_OUT_END_OF_TRAME 500000
  52 +
  53 +/* Function codes */
  54 +#define FC_READ_COILS 0x01
  55 +#define FC_READ_DISCRETE_INPUTS 0x02
  56 +#define FC_READ_HOLDING_REGISTERS 0x03
  57 +#define FC_READ_INPUT_REGISTERS 0x04
  58 +#define FC_WRITE_SINGLE_COIL 0x05
  59 +#define FC_WRITE_SINGLE_REGISTER 0x06
  60 +#define FC_READ_EXCEPTION_STATUS 0x07
  61 +#define FC_WRITE_MULTIPLE_COILS 0x0F
  62 +#define FC_WRITE_MULTIPLE_REGISTERS 0x10
  63 +#define FC_REPORT_SLAVE_ID 0x11
  64 +
  65 +typedef enum { RTU=0, TCP } type_com_t;
  66 +
  67 +struct _modbus {
  68 + /* Communication mode: RTU or TCP */
  69 + type_com_t type_com;
  70 + /* Slave address */
  71 + int slave;
  72 + /* Socket or file descriptor */
  73 + int s;
  74 + int debug;
  75 + int error_recovery;
  76 + struct timeval timeout_begin;
  77 + struct timeval timeout_end;
  78 + void *com;
  79 +};
  80 +
  81 +typedef struct _modbus_rtu {
  82 + /* Device: "/dev/ttyS0", "/dev/ttyUSB0" or "/dev/tty.USA19*" on Mac OS X for
  83 + KeySpan USB<->Serial adapters this string had to be made bigger on OS X
  84 + as the directory+file name was bigger than 19 bytes. Making it 67 bytes
  85 + for now, but OS X does support 256 byte file names. May become a problem
  86 + in the future. */
  87 +#ifdef __APPLE_CC__
  88 + char device[64];
  89 +#else
  90 + char device[16];
  91 +#endif
  92 + /* Bauds: 9600, 19200, 57600, 115200, etc */
  93 + int baud;
  94 + /* Data bit */
  95 + uint8_t data_bit;
  96 + /* Stop bit */
  97 + uint8_t stop_bit;
  98 + /* Parity: 'N', 'O', 'E' */
  99 + char parity;
  100 + /* Save old termios settings */
  101 + struct termios old_tios;
  102 +} modbus_rtu_t;
  103 +
  104 +typedef struct _modbus_tcp {
  105 + /* TCP port */
  106 + int port;
  107 + /* IP address */
  108 + char ip[16];
  109 +} modbus_tcp_t;
  110 +
  111 +MODBUS_END_DECLS
  112 +
  113 +#endif /* _MODBUS_PRIVATE_H_ */
... ...
src/modbus.c
... ... @@ -63,6 +63,10 @@
63 63  
64 64 #include <config.h>
65 65 #include "modbus.h"
  66 +#include "modbus-private.h"
  67 +
  68 +/* Internal use */
  69 +#define MSG_LENGTH_UNDEFINED -1
66 70  
67 71 /* Exported version */
68 72 const unsigned int libmodbus_version_major = LIBMODBUS_VERSION_MAJOR;
... ... @@ -148,10 +152,13 @@ static const int TAB_CHECKSUM_LENGTH[2] = {
148 152 };
149 153  
150 154 static const int TAB_MAX_ADU_LENGTH[2] = {
151   - MAX_ADU_LENGTH_RTU,
152   - MAX_ADU_LENGTH_TCP,
  155 + MODBUS_MAX_ADU_LENGTH_RTU,
  156 + MODBUS_MAX_ADU_LENGTH_TCP,
153 157 };
154 158  
  159 +/* Max between RTU and TCP max adu length */
  160 +#define MAX_MESSAGE_LENGTH MODBUS_MAX_ADU_LENGTH_TCP
  161 +
155 162 const char *modbus_strerror(int errnum) {
156 163 switch (errnum) {
157 164 case EMBXILFUN:
... ... @@ -187,9 +194,9 @@ const char *modbus_strerror(int errnum) {
187 194 }
188 195 }
189 196  
190   -static void error_print(modbus_param_t *mb_param, const char *context)
  197 +static void error_print(modbus_t *ctx, const char *context)
191 198 {
192   - if (mb_param->debug) {
  199 + if (ctx->debug) {
193 200 fprintf(stderr, "ERROR %s", modbus_strerror(errno));
194 201 if (context != NULL) {
195 202 fprintf(stderr, ": %s\n", context);
... ... @@ -199,18 +206,18 @@ static void error_print(modbus_param_t *mb_param, const char *context)
199 206 }
200 207 }
201 208  
202   -int modbus_flush(modbus_param_t *mb_param)
  209 +int modbus_flush(modbus_t *ctx)
203 210 {
204 211 int rc;
205 212  
206   - if (mb_param->type_com == RTU) {
207   - rc = tcflush(mb_param->fd, TCIOFLUSH);
  213 + if (ctx->type_com == RTU) {
  214 + rc = tcflush(ctx->s, TCIOFLUSH);
208 215 } else {
209 216 do {
210 217 /* Extract the garbage from the socket */
211   - char devnull[MAX_ADU_LENGTH_TCP];
  218 + char devnull[MODBUS_MAX_ADU_LENGTH_TCP];
212 219 #if (!HAVE_DECL___CYGWIN__)
213   - rc = recv(mb_param->fd, devnull, MAX_ADU_LENGTH_TCP, MSG_DONTWAIT);
  220 + rc = recv(ctx->s, devnull, MODBUS_MAX_ADU_LENGTH_TCP, MSG_DONTWAIT);
214 221 #else
215 222 /* On Cygwin, it's a bit more complicated to not wait */
216 223 fd_set rfds;
... ... @@ -219,15 +226,15 @@ int modbus_flush(modbus_param_t *mb_param)
219 226 tv.tv_sec = 0;
220 227 tv.tv_usec = 0;
221 228 FD_ZERO(&rfds);
222   - FD_SET(mb_param->fd, &rfds);
223   - rc = select(mb_param->fd+1, &rfds, NULL, NULL, &tv);
  229 + FD_SET(ctx->s, &rfds);
  230 + rc = select(ctx->s+1, &rfds, NULL, NULL, &tv);
224 231 if (rc == -1) {
225 232 return -1;
226 233 }
227 234  
228   - rc = recv(mb_param->fd, devnull, MAX_ADU_LENGTH_TCP, 0);
  235 + rc = recv(ctx->s, devnull, MODBUS_MAX_ADU_LENGTH_TCP, 0);
229 236 #endif
230   - if (mb_param->debug && rc != -1) {
  237 + if (ctx->debug && rc != -1) {
231 238 printf("\n%d bytes flushed\n", rc);
232 239 }
233 240 } while (rc > 0);
... ... @@ -237,27 +244,26 @@ int modbus_flush(modbus_param_t *mb_param)
237 244 }
238 245  
239 246 /* Computes the length of the expected response */
240   -static unsigned int compute_response_length(modbus_param_t *mb_param,
241   - uint8_t *query)
  247 +static unsigned int compute_response_length(modbus_t *ctx, uint8_t *req)
242 248 {
243 249 int length;
244 250 int offset;
245 251  
246   - offset = TAB_HEADER_LENGTH[mb_param->type_com];
  252 + offset = TAB_HEADER_LENGTH[ctx->type_com];
247 253  
248   - switch (query[offset]) {
249   - case FC_READ_COIL_STATUS:
250   - case FC_READ_INPUT_STATUS: {
251   - /* Header + nb values (code from force_multiple_coils) */
252   - int nb = (query[offset + 3] << 8) | query[offset + 4];
  254 + switch (req[offset]) {
  255 + case FC_READ_COILS:
  256 + case FC_READ_DISCRETE_INPUTS: {
  257 + /* Header + nb values (code from write_bits) */
  258 + int nb = (req[offset + 3] << 8) | req[offset + 4];
253 259 length = 2 + (nb / 8) + ((nb % 8) ? 1 : 0);
254 260 }
255 261 break;
256 262 case FC_READ_HOLDING_REGISTERS:
257 263 case FC_READ_INPUT_REGISTERS:
258 264 /* Header + 2 * nb values */
259   - length = 2 + 2 * (query[offset + 3] << 8 |
260   - query[offset + 4]);
  265 + length = 2 + 2 * (req[offset + 3] << 8 |
  266 + req[offset + 4]);
261 267 break;
262 268 case FC_READ_EXCEPTION_STATUS:
263 269 length = 3;
... ... @@ -270,28 +276,28 @@ static unsigned int compute_response_length(modbus_param_t *mb_param,
270 276 length = 5;
271 277 }
272 278  
273   - return length + offset + TAB_CHECKSUM_LENGTH[mb_param->type_com];
  279 + return length + offset + TAB_CHECKSUM_LENGTH[ctx->type_com];
274 280 }
275 281  
276   -/* Builds a RTU query header */
277   -static int build_query_basis_rtu(int slave, int function,
278   - int start_addr, int nb,
279   - uint8_t *query)
  282 +/* Builds a RTU request header */
  283 +static int build_request_basis_rtu(int slave, int function,
  284 + int addr, int nb,
  285 + uint8_t *req)
280 286 {
281   - query[0] = slave;
282   - query[1] = function;
283   - query[2] = start_addr >> 8;
284   - query[3] = start_addr & 0x00ff;
285   - query[4] = nb >> 8;
286   - query[5] = nb & 0x00ff;
287   -
288   - return PRESET_QUERY_LENGTH_RTU;
  287 + req[0] = slave;
  288 + req[1] = function;
  289 + req[2] = addr >> 8;
  290 + req[3] = addr & 0x00ff;
  291 + req[4] = nb >> 8;
  292 + req[5] = nb & 0x00ff;
  293 +
  294 + return PRESET_REQ_LENGTH_RTU;
289 295 }
290 296  
291   -/* Builds a TCP query header */
292   -static int build_query_basis_tcp(int slave, int function,
293   - int start_addr, int nb,
294   - uint8_t *query)
  297 +/* Builds a TCP request header */
  298 +static int build_request_basis_tcp(int slave, int function,
  299 + int addr, int nb,
  300 + uint8_t *req)
295 301 {
296 302  
297 303 /* Extract from MODBUS Messaging on TCP/IP Implementation Guide V1.0b
... ... @@ -306,76 +312,72 @@ static int build_query_basis_tcp(int slave, int function,
306 312 t_id++;
307 313 else
308 314 t_id = 0;
309   - query[0] = t_id >> 8;
310   - query[1] = t_id & 0x00ff;
  315 + req[0] = t_id >> 8;
  316 + req[1] = t_id & 0x00ff;
311 317  
312 318 /* Protocol Modbus */
313   - query[2] = 0;
314   - query[3] = 0;
  319 + req[2] = 0;
  320 + req[3] = 0;
315 321  
316   - /* Length will be defined later by set_query_length_tcp at offsets 4
  322 + /* Length will be defined later by set_req_length_tcp at offsets 4
317 323 and 5 */
318 324  
319   - query[6] = slave;
320   - query[7] = function;
321   - query[8] = start_addr >> 8;
322   - query[9] = start_addr & 0x00ff;
323   - query[10] = nb >> 8;
324   - query[11] = nb & 0x00ff;
  325 + req[6] = slave;
  326 + req[7] = function;
  327 + req[8] = addr >> 8;
  328 + req[9] = addr & 0x00ff;
  329 + req[10] = nb >> 8;
  330 + req[11] = nb & 0x00ff;
325 331  
326   - return PRESET_QUERY_LENGTH_TCP;
  332 + return PRESET_REQ_LENGTH_TCP;
327 333 }
328 334  
329   -static int build_query_basis(modbus_param_t *mb_param, int slave,
330   - int function, int start_addr,
331   - int nb, uint8_t *query)
  335 +static int build_request_basis(modbus_t *ctx, int function, int addr,
  336 + int nb, uint8_t *req)
332 337 {
333   - if (mb_param->type_com == RTU)
334   - return build_query_basis_rtu(slave, function,
335   - start_addr, nb, query);
  338 + if (ctx->type_com == RTU)
  339 + return build_request_basis_rtu(ctx->slave, function, addr, nb, req);
336 340 else
337   - return build_query_basis_tcp(slave, function,
338   - start_addr, nb, query);
  341 + return build_request_basis_tcp(ctx->slave, function, addr, nb, req);
339 342 }
340 343  
341 344 /* Builds a RTU response header */
342   -static int build_response_basis_rtu(sft_t *sft, uint8_t *response)
  345 +static int build_response_basis_rtu(sft_t *sft, uint8_t *rsp)
343 346 {
344   - response[0] = sft->slave;
345   - response[1] = sft->function;
  347 + rsp[0] = sft->slave;
  348 + rsp[1] = sft->function;
346 349  
347   - return PRESET_RESPONSE_LENGTH_RTU;
  350 + return PRESET_RSP_LENGTH_RTU;
348 351 }
349 352  
350 353 /* Builds a TCP response header */
351   -static int build_response_basis_tcp(sft_t *sft, uint8_t *response)
  354 +static int build_response_basis_tcp(sft_t *sft, uint8_t *rsp)
352 355 {
353 356 /* Extract from MODBUS Messaging on TCP/IP Implementation
354 357 Guide V1.0b (page 23/46):
355 358 The transaction identifier is used to associate the future
356 359 response with the request. */
357   - response[0] = sft->t_id >> 8;
358   - response[1] = sft->t_id & 0x00ff;
  360 + rsp[0] = sft->t_id >> 8;
  361 + rsp[1] = sft->t_id & 0x00ff;
359 362  
360 363 /* Protocol Modbus */
361   - response[2] = 0;
362   - response[3] = 0;
  364 + rsp[2] = 0;
  365 + rsp[3] = 0;
363 366  
364   - /* Length will be set later by modbus_send (4 and 5) */
  367 + /* Length will be set later by send_msg (4 and 5) */
365 368  
366   - response[6] = 0xFF;
367   - response[7] = sft->function;
  369 + rsp[6] = 0xFF;
  370 + rsp[7] = sft->function;
368 371  
369   - return PRESET_RESPONSE_LENGTH_TCP;
  372 + return PRESET_RSP_LENGTH_TCP;
370 373 }
371 374  
372   -static int build_response_basis(modbus_param_t *mb_param, sft_t *sft,
373   - uint8_t *response)
  375 +static int build_response_basis(modbus_t *ctx, sft_t *sft, uint8_t *rsp)
374 376 {
375   - if (mb_param->type_com == RTU)
376   - return build_response_basis_rtu(sft, response);
  377 + if (ctx->type_com == RTU)
  378 + return build_response_basis_rtu(sft, rsp);
377 379 else
378   - return build_response_basis_tcp(sft, response);
  380 + return build_response_basis_tcp(sft, rsp);
379 381 }
380 382  
381 383 /* Fast CRC */
... ... @@ -397,9 +399,7 @@ static uint16_t crc16(uint8_t *buffer, uint16_t buffer_length)
397 399  
398 400 /* The check_crc16 function shall return the message length if the CRC is
399 401 valid. Otherwise it shall return -1 and set errno to EMBADCRC. */
400   -static int check_crc16(modbus_param_t *mb_param,
401   - uint8_t *msg,
402   - const int msg_length)
  402 +static int check_crc16(modbus_t *ctx, uint8_t *msg, const int msg_length)
403 403 {
404 404 uint16_t crc_calculated;
405 405 uint16_t crc_received;
... ... @@ -411,68 +411,66 @@ static int check_crc16(modbus_param_t *mb_param,
411 411 if (crc_calculated == crc_received) {
412 412 return msg_length;
413 413 } else {
414   - if (mb_param->debug) {
  414 + if (ctx->debug) {
415 415 fprintf(stderr, "ERROR CRC received %0X != CRC calculated %0X\n",
416 416 crc_received, crc_calculated);
417 417 }
418   - if (mb_param->error_recovery) {
419   - modbus_flush(mb_param);
  418 + if (ctx->error_recovery) {
  419 + modbus_flush(ctx);
420 420 }
421 421 errno = EMBBADCRC;
422 422 return -1;
423 423 }
424 424 }
425 425  
426   -/* Sends a query/response over a serial or a TCP communication */
427   -static int modbus_send(modbus_param_t *mb_param, uint8_t *query,
428   - int query_length)
  426 +/* Sends a req/response over a serial or a TCP communication */
  427 +static int send_msg(modbus_t *ctx, uint8_t *req, int req_length)
429 428 {
430 429 int rc;
431 430 uint16_t s_crc;
432 431 int i;
433 432  
434   - if (mb_param->type_com == RTU) {
435   - s_crc = crc16(query, query_length);
436   - query[query_length++] = s_crc >> 8;
437   - query[query_length++] = s_crc & 0x00FF;
  433 + if (ctx->type_com == RTU) {
  434 + s_crc = crc16(req, req_length);
  435 + req[req_length++] = s_crc >> 8;
  436 + req[req_length++] = s_crc & 0x00FF;
438 437 } else {
439 438 /* Substract the header length to the message length */
440   - int mbap_length = query_length - 6;
  439 + int mbap_length = req_length - 6;
441 440  
442   - query[4] = mbap_length >> 8;
443   - query[5] = mbap_length & 0x00FF;
  441 + req[4] = mbap_length >> 8;
  442 + req[5] = mbap_length & 0x00FF;
444 443 }
445 444  
446   - if (mb_param->debug) {
447   - for (i = 0; i < query_length; i++)
448   - printf("[%.2X]", query[i]);
  445 + if (ctx->debug) {
  446 + for (i = 0; i < req_length; i++)
  447 + printf("[%.2X]", req[i]);
449 448 printf("\n");
450 449 }
451 450  
452 451 /* In recovery mode, the write command will be issued until to be
453   - successful! Disabled by default.
454   - */
  452 + successful! Disabled by default. */
455 453 do {
456   - if (mb_param->type_com == RTU)
457   - rc = write(mb_param->fd, query, query_length);
  454 + if (ctx->type_com == RTU)
  455 + rc = write(ctx->s, req, req_length);
458 456 else
459 457 /* MSG_NOSIGNAL
460 458 Requests not to send SIGPIPE on errors on stream oriented
461 459 sockets when the other end breaks the connection. The EPIPE
462 460 error is still returned. */
463   - rc = send(mb_param->fd, query, query_length, MSG_NOSIGNAL);
  461 + rc = send(ctx->s, req, req_length, MSG_NOSIGNAL);
464 462  
465 463 if (rc == -1) {
466   - error_print(mb_param, NULL);
467   - if (mb_param->error_recovery &&
  464 + error_print(ctx, NULL);
  465 + if (ctx->error_recovery &&
468 466 (errno == EBADF || errno == ECONNRESET || errno == EPIPE)) {
469   - modbus_close(mb_param);
470   - modbus_connect(mb_param);
  467 + modbus_close(ctx);
  468 + modbus_connect(ctx);
471 469 }
472 470 }
473   - } while (mb_param->error_recovery && rc == -1);
  471 + } while (ctx->error_recovery && rc == -1);
474 472  
475   - if (rc > 0 && rc != query_length) {
  473 + if (rc > 0 && rc != req_length) {
476 474 errno = EMBBADDATA;
477 475 return -1;
478 476 }
... ... @@ -481,16 +479,16 @@ static int modbus_send(modbus_param_t *mb_param, uint8_t *query,
481 479 }
482 480  
483 481 /* Computes the length of the header following the function code */
484   -static uint8_t compute_query_length_header(int function)
  482 +static uint8_t compute_req_length_header(int function)
485 483 {
486 484 int length;
487 485  
488   - if (function <= FC_FORCE_SINGLE_COIL ||
489   - function == FC_PRESET_SINGLE_REGISTER)
  486 + if (function <= FC_WRITE_SINGLE_COIL ||
  487 + function == FC_WRITE_SINGLE_REGISTER)
490 488 /* Read and single write */
491 489 length = 4;
492   - else if (function == FC_FORCE_MULTIPLE_COILS ||
493   - function == FC_PRESET_MULTIPLE_REGISTERS)
  490 + else if (function == FC_WRITE_MULTIPLE_COILS ||
  491 + function == FC_WRITE_MULTIPLE_REGISTERS)
494 492 /* Multiple write */
495 493 length = 5;
496 494 else if (function == FC_REPORT_SLAVE_ID)
... ... @@ -501,66 +499,66 @@ static uint8_t compute_query_length_header(int function)
501 499 return length;
502 500 }
503 501  
504   -/* Computes the length of the data to write in the query */
505   -static int compute_query_length_data(modbus_param_t *mb_param, uint8_t *msg)
  502 +/* Computes the length of the data to write in the request */
  503 +static int compute_req_length_data(modbus_t *ctx, uint8_t *msg)
506 504 {
507   - int function = msg[TAB_HEADER_LENGTH[mb_param->type_com]];
  505 + int function = msg[TAB_HEADER_LENGTH[ctx->type_com]];
508 506 int length;
509 507  
510   - if (function == FC_FORCE_MULTIPLE_COILS ||
511   - function == FC_PRESET_MULTIPLE_REGISTERS)
512   - length = msg[TAB_HEADER_LENGTH[mb_param->type_com] + 5];
  508 + if (function == FC_WRITE_MULTIPLE_COILS ||
  509 + function == FC_WRITE_MULTIPLE_REGISTERS)
  510 + length = msg[TAB_HEADER_LENGTH[ctx->type_com] + 5];
513 511 else if (function == FC_REPORT_SLAVE_ID)
514   - length = msg[TAB_HEADER_LENGTH[mb_param->type_com] + 1];
  512 + length = msg[TAB_HEADER_LENGTH[ctx->type_com] + 1];
515 513 else
516 514 length = 0;
517 515  
518   - length += TAB_CHECKSUM_LENGTH[mb_param->type_com];
  516 + length += TAB_CHECKSUM_LENGTH[ctx->type_com];
519 517  
520 518 return length;
521 519 }
522 520  
523 521 #define WAIT_DATA() { \
524   - while ((s_rc = select(mb_param->fd+1, &rfds, NULL, NULL, &tv)) == -1) { \
525   - if (errno == EINTR) { \
526   - if (mb_param->debug) { \
527   - fprintf(stderr, \
528   - "A non blocked signal was caught\n"); \
529   - } \
530   - /* Necessary after an error */ \
531   - FD_ZERO(&rfds); \
532   - FD_SET(mb_param->fd, &rfds); \
533   - } else { \
534   - error_print(mb_param, "select"); \
535   - if (mb_param->error_recovery && (errno == EBADF)) { \
536   - modbus_close(mb_param); \
537   - modbus_connect(mb_param); \
538   - errno = EBADF; \
539   - return -1; \
  522 + while ((s_rc = select(ctx->s+1, &rfds, NULL, NULL, &tv)) == -1) { \
  523 + if (errno == EINTR) { \
  524 + if (ctx->debug) { \
  525 + fprintf(stderr, \
  526 + "A non blocked signal was caught\n"); \
  527 + } \
  528 + /* Necessary after an error */ \
  529 + FD_ZERO(&rfds); \
  530 + FD_SET(ctx->s, &rfds); \
540 531 } else { \
541   - return -1; \
  532 + error_print(ctx, "select"); \
  533 + if (ctx->error_recovery && (errno == EBADF)) { \
  534 + modbus_close(ctx); \
  535 + modbus_connect(ctx); \
  536 + errno = EBADF; \
  537 + return -1; \
  538 + } else { \
  539 + return -1; \
  540 + } \
542 541 } \
543 542 } \
544   - } \
545 543 \
546   - if (s_rc == 0) { \
547   - /* Timeout */ \
548   - if (msg_length == (TAB_HEADER_LENGTH[mb_param->type_com] + 2 + \
549   - TAB_CHECKSUM_LENGTH[mb_param->type_com])) { \
550   - /* Optimization allowed because exception response is \
551   - the smallest trame in modbus protocol (3) so always \
552   - raise a timeout error. \
553   - Temporary error before exception analyze. */ \
554   - errno = EMBUNKEXC; \
555   - } else { \
556   - errno = ETIMEDOUT; \
557   - error_print(mb_param, "select"); \
  544 + if (s_rc == 0) { \
  545 + /* Timeout */ \
  546 + if (msg_length == (TAB_HEADER_LENGTH[ctx->type_com] + 2 + \
  547 + TAB_CHECKSUM_LENGTH[ctx->type_com])) { \
  548 + /* Optimization allowed because exception response is \
  549 + the smallest trame in modbus protocol (3) so always \
  550 + raise a timeout error. \
  551 + Temporary error before exception analyze. */ \
  552 + errno = EMBUNKEXC; \
  553 + } else { \
  554 + errno = ETIMEDOUT; \
  555 + error_print(ctx, "select"); \
  556 + } \
  557 + return -1; \
558 558 } \
559   - return -1; \
560   - } \
561   -}
  559 + }
562 560  
563   -/* Waits a reply from a modbus slave or a query from a modbus master.
  561 +/* Waits a reply from a modbus server or a request from a modbus client.
564 562 This function blocks if there is no replies (3 timeouts).
565 563  
566 564 The argument msg_length_computed must be set to MSG_LENGTH_UNDEFINED if
... ... @@ -575,9 +573,7 @@ static int compute_query_length_data(modbus_param_t *mb_param, uint8_t *msg)
575 573 - ETIMEDOUT
576 574 - read() or recv() error codes
577 575 */
578   -static int receive_msg(modbus_param_t *mb_param,
579   - int msg_length_computed,
580   - uint8_t *msg)
  576 +static int receive_msg(modbus_t *ctx, int msg_length_computed, uint8_t *msg)
581 577 {
582 578 int s_rc;
583 579 int read_rc;
... ... @@ -587,10 +583,9 @@ static int receive_msg(modbus_param_t *mb_param,
587 583 uint8_t *p_msg;
588 584 enum { FUNCTION, BYTE, COMPLETE };
589 585 int state;
590   -
591 586 int msg_length = 0;
592 587  
593   - if (mb_param->debug) {
  588 + if (ctx->debug) {
594 589 if (msg_length_computed == MSG_LENGTH_UNDEFINED)
595 590 printf("Waiting for a message...\n");
596 591 else
... ... @@ -600,22 +595,21 @@ static int receive_msg(modbus_param_t *mb_param,
600 595  
601 596 /* Add a file descriptor to the set */
602 597 FD_ZERO(&rfds);
603   - FD_SET(mb_param->fd, &rfds);
  598 + FD_SET(ctx->s, &rfds);
604 599  
605 600 if (msg_length_computed == MSG_LENGTH_UNDEFINED) {
606 601 /* Wait for a message */
607 602 tv.tv_sec = 60;
608 603 tv.tv_usec = 0;
609 604  
610   - /* The message length is undefined (query receiving) so
611   - * we need to analyse the message step by step.
612   - * At the first step, we want to reach the function
613   - * code because all packets have that information. */
  605 + /* The message length is undefined (request receiving) so we need to
  606 + * analyse the message step by step. At the first step, we want to
  607 + * reach the function code because all packets have that information. */
614 608 state = FUNCTION;
615   - msg_length_computed = TAB_HEADER_LENGTH[mb_param->type_com] + 1;
  609 + msg_length_computed = TAB_HEADER_LENGTH[ctx->type_com] + 1;
616 610 } else {
617   - tv.tv_sec = mb_param->timeout_begin.tv_sec;
618   - tv.tv_usec = mb_param->timeout_begin.tv_usec;
  611 + tv.tv_sec = ctx->timeout_begin.tv_sec;
  612 + tv.tv_usec = ctx->timeout_begin.tv_usec;
619 613 state = COMPLETE;
620 614 }
621 615  
... ... @@ -626,10 +620,10 @@ static int receive_msg(modbus_param_t *mb_param,
626 620  
627 621 p_msg = msg;
628 622 while (s_rc) {
629   - if (mb_param->type_com == RTU)
630   - read_rc = read(mb_param->fd, p_msg, length_to_read);
  623 + if (ctx->type_com == RTU)
  624 + read_rc = read(ctx->s, p_msg, length_to_read);
631 625 else
632   - read_rc = recv(mb_param->fd, p_msg, length_to_read, 0);
  626 + read_rc = recv(ctx->s, p_msg, length_to_read, 0);
633 627  
634 628 if (read_rc == 0) {
635 629 errno = ECONNRESET;
... ... @@ -637,11 +631,11 @@ static int receive_msg(modbus_param_t *mb_param,
637 631 }
638 632  
639 633 if (read_rc == -1) {
640   - error_print(mb_param, "read");
641   - if (mb_param->error_recovery && (errno == ECONNRESET ||
642   - errno == ECONNREFUSED)) {
643   - modbus_close(mb_param);
644   - modbus_connect(mb_param);
  634 + error_print(ctx, "read");
  635 + if (ctx->error_recovery && (errno == ECONNRESET ||
  636 + errno == ECONNREFUSED)) {
  637 + modbus_close(ctx);
  638 + modbus_connect(ctx);
645 639 /* Could be removed by previous calls */
646 640 errno = ECONNRESET;
647 641 return -1;
... ... @@ -653,7 +647,7 @@ static int receive_msg(modbus_param_t *mb_param,
653 647 msg_length += read_rc;
654 648  
655 649 /* Display the hex code of each character received */
656   - if (mb_param->debug) {
  650 + if (ctx->debug) {
657 651 int i;
658 652 for (i=0; i < read_rc; i++)
659 653 printf("<%.2X>", p_msg[i]);
... ... @@ -666,8 +660,8 @@ static int receive_msg(modbus_param_t *mb_param,
666 660 switch (state) {
667 661 case FUNCTION:
668 662 /* Function code position */
669   - length_to_read = compute_query_length_header(
670   - msg[TAB_HEADER_LENGTH[mb_param->type_com]]);
  663 + length_to_read = compute_req_length_header(
  664 + msg[TAB_HEADER_LENGTH[ctx->type_com]]);
671 665 msg_length_computed += length_to_read;
672 666 /* It's useless to check the value of
673 667 msg_length_computed in this case (only
... ... @@ -675,11 +669,11 @@ static int receive_msg(modbus_param_t *mb_param,
675 669 state = BYTE;
676 670 break;
677 671 case BYTE:
678   - length_to_read = compute_query_length_data(mb_param, msg);
  672 + length_to_read = compute_req_length_data(ctx, msg);
679 673 msg_length_computed += length_to_read;
680   - if (msg_length_computed > TAB_MAX_ADU_LENGTH[mb_param->type_com]) {
  674 + if (msg_length_computed > TAB_MAX_ADU_LENGTH[ctx->type_com]) {
681 675 errno = EMBBADDATA;
682   - error_print(mb_param, "too many data");
  676 + error_print(ctx, "too many data");
683 677 return -1;
684 678 }
685 679 state = COMPLETE;
... ... @@ -696,8 +690,8 @@ static int receive_msg(modbus_param_t *mb_param,
696 690 if (length_to_read > 0) {
697 691 /* If no character at the buffer wait
698 692 TIME_OUT_END_OF_TRAME before to generate an error. */
699   - tv.tv_sec = mb_param->timeout_end.tv_sec;
700   - tv.tv_usec = mb_param->timeout_end.tv_usec;
  693 + tv.tv_sec = ctx->timeout_end.tv_sec;
  694 + tv.tv_usec = ctx->timeout_end.tv_usec;
701 695  
702 696 WAIT_DATA();
703 697 } else {
... ... @@ -706,33 +700,33 @@ static int receive_msg(modbus_param_t *mb_param,
706 700 }
707 701 }
708 702  
709   - if (mb_param->debug)
  703 + if (ctx->debug)
710 704 printf("\n");
711 705  
712   - if (mb_param->type_com == RTU) {
  706 + if (ctx->type_com == RTU) {
713 707 /* Returns msg_length on success and a negative value on
714 708 failure */
715   - return check_crc16(mb_param, msg, msg_length);
  709 + return check_crc16(ctx, msg, msg_length);
716 710 } else {
717 711 /* OK */
718 712 return msg_length;
719 713 }
720 714 }
721 715  
722   -/* Listens for any query from a modbus master in TCP, requires the socket file
723   - descriptor etablished with the master device in argument or -1 to use the
724   - internal one of modbus_param_t.
  716 +/* Receive the request from a modbus master, requires the socket file descriptor
  717 + etablished with the master device in argument or -1 to use the internal one
  718 + of modbus_t.
725 719  
726   - The modbus_slave_receive function shall return the request received and its
  720 + The receive_msg_req function shall return the request received and its
727 721 byte length if successul. Otherwise, it shall return -1 and errno is set. */
728   -int modbus_slave_receive(modbus_param_t *mb_param, int sockfd, uint8_t *query)
  722 +int modbus_receive(modbus_t *ctx, int sockfd, uint8_t *req)
729 723 {
730 724 if (sockfd != -1) {
731   - mb_param->fd = sockfd;
  725 + ctx->s = sockfd;
732 726 }
733 727  
734   - /* The length of the query to receive isn't known. */
735   - return receive_msg(mb_param, MSG_LENGTH_UNDEFINED, query);
  728 + /* The length of the request to receive isn't known. */
  729 + return receive_msg(ctx, MSG_LENGTH_UNDEFINED, req);
736 730 }
737 731  
738 732 /* Receives the response and checks values (and checksum in RTU).
... ... @@ -742,61 +736,59 @@ int modbus_slave_receive(modbus_param_t *mb_param, int sockfd, uint8_t *query)
742 736  
743 737 Note: all functions used to send or receive data with modbus return
744 738 these values. */
745   -static int modbus_receive(modbus_param_t *mb_param,
746   - uint8_t *query,
747   - uint8_t *response)
  739 +static int receive_msg_req(modbus_t *ctx, uint8_t *req, uint8_t *rsp)
748 740 {
749 741 int rc;
750   - int response_length_computed;
751   - int offset = TAB_HEADER_LENGTH[mb_param->type_com];
  742 + int rsp_length_computed;
  743 + int offset = TAB_HEADER_LENGTH[ctx->type_com];
752 744  
753   - response_length_computed = compute_response_length(mb_param, query);
754   - rc = receive_msg(mb_param, response_length_computed, response);
  745 + rsp_length_computed = compute_response_length(ctx, req);
  746 + rc = receive_msg(ctx, rsp_length_computed, rsp);
755 747 if (rc != -1) {
756 748 /* GOOD RESPONSE */
757   - int query_nb_value;
758   - int response_nb_value;
  749 + int req_nb_value;
  750 + int rsp_nb_value;
759 751  
760 752 /* The number of values is returned if it's corresponding
761   - * to the query */
762   - switch (response[offset]) {
763   - case FC_READ_COIL_STATUS:
764   - case FC_READ_INPUT_STATUS:
  753 + * to the request */
  754 + switch (rsp[offset]) {
  755 + case FC_READ_COILS:
  756 + case FC_READ_DISCRETE_INPUTS:
765 757 /* Read functions, 8 values in a byte (nb
766   - * of values in the query and byte count in
  758 + * of values in the request and byte count in
767 759 * the response. */
768   - query_nb_value = (query[offset + 3] << 8) + query[offset + 4];
769   - query_nb_value = (query_nb_value / 8) + ((query_nb_value % 8) ? 1 : 0);
770   - response_nb_value = response[offset + 1];
  760 + req_nb_value = (req[offset + 3] << 8) + req[offset + 4];
  761 + req_nb_value = (req_nb_value / 8) + ((req_nb_value % 8) ? 1 : 0);
  762 + rsp_nb_value = rsp[offset + 1];
771 763 break;
772 764 case FC_READ_HOLDING_REGISTERS:
773 765 case FC_READ_INPUT_REGISTERS:
774 766 /* Read functions 1 value = 2 bytes */
775   - query_nb_value = (query[offset + 3] << 8) + query[offset + 4];
776   - response_nb_value = (response[offset + 1] / 2);
  767 + req_nb_value = (req[offset + 3] << 8) + req[offset + 4];
  768 + rsp_nb_value = (rsp[offset + 1] / 2);
777 769 break;
778   - case FC_FORCE_MULTIPLE_COILS:
779   - case FC_PRESET_MULTIPLE_REGISTERS:
  770 + case FC_WRITE_MULTIPLE_COILS:
  771 + case FC_WRITE_MULTIPLE_REGISTERS:
780 772 /* N Write functions */
781   - query_nb_value = (query[offset + 3] << 8) + query[offset + 4];
782   - response_nb_value = (response[offset + 3] << 8) | response[offset + 4];
  773 + req_nb_value = (req[offset + 3] << 8) + req[offset + 4];
  774 + rsp_nb_value = (rsp[offset + 3] << 8) | rsp[offset + 4];
783 775 break;
784 776 case FC_REPORT_SLAVE_ID:
785 777 /* Report slave ID (bytes received) */
786   - query_nb_value = response_nb_value = rc;
  778 + req_nb_value = rsp_nb_value = rc;
787 779 break;
788 780 default:
789 781 /* 1 Write functions & others */
790   - query_nb_value = response_nb_value = 1;
  782 + req_nb_value = rsp_nb_value = 1;
791 783 }
792 784  
793   - if (query_nb_value == response_nb_value) {
794   - rc = response_nb_value;
  785 + if (req_nb_value == rsp_nb_value) {
  786 + rc = rsp_nb_value;
795 787 } else {
796   - if (mb_param->debug) {
  788 + if (ctx->debug) {
797 789 fprintf(stderr,
798   - "Quantity not corresponding to the query (%d != %d)\n",
799   - response_nb_value, query_nb_value);
  790 + "Quantity not corresponding to the request (%d != %d)\n",
  791 + rsp_nb_value, req_nb_value);
800 792 }
801 793 errno = EMBBADDATA;
802 794 rc = -1;
... ... @@ -805,8 +797,8 @@ static int modbus_receive(modbus_param_t *mb_param,
805 797 /* EXCEPTION CODE RECEIVED */
806 798  
807 799 /* CRC must be checked here (not done in receive_msg) */
808   - if (mb_param->type_com == RTU) {
809   - rc = check_crc16(mb_param, response, EXCEPTION_RESPONSE_LENGTH_RTU);
  800 + if (ctx->type_com == RTU) {
  801 + rc = check_crc16(ctx, rsp, EXCEPTION_RSP_LENGTH_RTU);
810 802 if (rc == -1)
811 803 return -1;
812 804 }
... ... @@ -814,14 +806,14 @@ static int modbus_receive(modbus_param_t *mb_param,
814 806 /* Check for exception response.
815 807 0x80 + function is stored in the exception
816 808 response. */
817   - if (0x80 + query[offset] == response[offset]) {
818   - int exception_code = response[offset + 1];
  809 + if (0x80 + req[offset] == rsp[offset]) {
  810 + int exception_code = rsp[offset + 1];
819 811 if (exception_code < MODBUS_EXCEPTION_MAX) {
820 812 errno = MODBUS_ENOBASE + exception_code;
821 813 } else {
822 814 errno = EMBBADEXC;
823 815 }
824   - error_print(mb_param, NULL);
  816 + error_print(ctx, NULL);
825 817 return -1;
826 818 }
827 819 }
... ... @@ -831,7 +823,7 @@ static int modbus_receive(modbus_param_t *mb_param,
831 823  
832 824 static int response_io_status(int address, int nb,
833 825 uint8_t *tab_io_status,
834   - uint8_t *response, int offset)
  826 + uint8_t *rsp, int offset)
835 827 {
836 828 int shift = 0;
837 829 int byte = 0;
... ... @@ -841,7 +833,7 @@ static int response_io_status(int address, int nb,
841 833 byte |= tab_io_status[i] << shift;
842 834 if (shift == 7) {
843 835 /* Byte is full */
844   - response[offset++] = byte;
  836 + rsp[offset++] = byte;
845 837 byte = shift = 0;
846 838 } else {
847 839 shift++;
... ... @@ -849,254 +841,255 @@ static int response_io_status(int address, int nb,
849 841 }
850 842  
851 843 if (shift != 0)
852   - response[offset++] = byte;
  844 + rsp[offset++] = byte;
853 845  
854 846 return offset;
855 847 }
856 848  
857 849 /* Build the exception response */
858   -static int response_exception(modbus_param_t *mb_param, sft_t *sft,
859   - int exception_code, uint8_t *response)
  850 +static int response_exception(modbus_t *ctx, sft_t *sft,
  851 + int exception_code, uint8_t *rsp)
860 852 {
861   - int response_length;
  853 + int rsp_length;
862 854  
863 855 sft->function = sft->function + 0x80;
864   - response_length = build_response_basis(mb_param, sft, response);
  856 + rsp_length = build_response_basis(ctx, sft, rsp);
865 857  
866 858 /* Positive exception code */
867   - response[response_length++] = exception_code;
  859 + rsp[rsp_length++] = exception_code;
868 860  
869   - return response_length;
  861 + return rsp_length;
870 862 }
871 863  
872   -/* Manages the received query.
873   - Analyses the query and constructs a response.
  864 +/* Send a response to the receive request.
  865 + Analyses the request and constructs a response.
874 866  
875 867 If an error occurs, this function construct the response
876 868 accordingly.
877 869 */
878   -int modbus_slave_manage(modbus_param_t *mb_param, const uint8_t *query,
879   - int query_length, modbus_mapping_t *mb_mapping)
  870 +int modbus_reply(modbus_t *ctx, const uint8_t *req,
  871 + int req_length, modbus_mapping_t *mb_mapping)
880 872 {
881   - int offset = TAB_HEADER_LENGTH[mb_param->type_com];
882   - int slave = query[offset - 1];
883   - int function = query[offset];
884   - uint16_t address = (query[offset + 1] << 8) + query[offset + 2];
885   - uint8_t response[MAX_MESSAGE_LENGTH];
  873 + int offset = TAB_HEADER_LENGTH[ctx->type_com];
  874 + int slave = req[offset - 1];
  875 + int function = req[offset];
  876 + uint16_t address = (req[offset + 1] << 8) + req[offset + 2];
  877 + uint8_t rsp[MAX_MESSAGE_LENGTH];
886 878 int resp_length = 0;
887 879 sft_t sft;
888 880  
889 881 /* Filter on the Modbus unit identifier (slave) in RTU mode */
890   - if (mb_param->type_com == RTU &&
891   - slave != mb_param->slave && slave != MODBUS_BROADCAST_ADDRESS) {
892   - /* Ignores the query (not for me) */
893   - if (mb_param->debug) {
  882 + if (ctx->type_com == RTU &&
  883 + slave != ctx->slave && slave != MODBUS_BROADCAST_ADDRESS) {
  884 + /* Ignores the request (not for me) */
  885 + if (ctx->debug) {
894 886 printf("Request for slave %d ignored (not %d)\n",
895   - slave, mb_param->slave);
  887 + slave, ctx->slave);
896 888 }
897 889 return 0;
898 890 }
899 891  
900 892 sft.slave = slave;
901 893 sft.function = function;
902   - if (mb_param->type_com == TCP) {
903   - sft.t_id = (query[0] << 8) + query[1];
  894 + if (ctx->type_com == TCP) {
  895 + sft.t_id = (req[0] << 8) + req[1];
904 896 } else {
905 897 sft.t_id = 0;
906   - query_length -= CHECKSUM_LENGTH_RTU;
  898 + req_length -= CHECKSUM_LENGTH_RTU;
907 899 }
908 900  
909 901 switch (function) {
910   - case FC_READ_COIL_STATUS: {
911   - int nb = (query[offset + 3] << 8) + query[offset + 4];
  902 + case FC_READ_COILS: {
  903 + int nb = (req[offset + 3] << 8) + req[offset + 4];
912 904  
913   - if ((address + nb) > mb_mapping->nb_coil_status) {
914   - if (mb_param->debug) {
915   - fprintf(stderr, "Illegal data address %0X in read_coil_status\n",
  905 + if ((address + nb) > mb_mapping->nb_bits) {
  906 + if (ctx->debug) {
  907 + fprintf(stderr, "Illegal data address %0X in read_bits\n",
916 908 address + nb);
917 909 }
918 910 resp_length = response_exception(
919   - mb_param, &sft,
920   - MODBUS_EXCEPTION_ILLEGAL_DATA_ADDRESS, response);
  911 + ctx, &sft,
  912 + MODBUS_EXCEPTION_ILLEGAL_DATA_ADDRESS, rsp);
921 913 } else {
922   - resp_length = build_response_basis(mb_param, &sft, response);
923   - response[resp_length++] = (nb / 8) + ((nb % 8) ? 1 : 0);
  914 + resp_length = build_response_basis(ctx, &sft, rsp);
  915 + rsp[resp_length++] = (nb / 8) + ((nb % 8) ? 1 : 0);
924 916 resp_length = response_io_status(address, nb,
925   - mb_mapping->tab_coil_status,
926   - response, resp_length);
  917 + mb_mapping->tab_bits,
  918 + rsp, resp_length);
927 919 }
928 920 }
929 921 break;
930   - case FC_READ_INPUT_STATUS: {
931   - /* Similar to coil status (but too much arguments to use a
  922 + case FC_READ_DISCRETE_INPUTS: {
  923 + /* Similar to coil status (but too many arguments to use a
932 924 * function) */
933   - int nb = (query[offset + 3] << 8) + query[offset + 4];
  925 + int nb = (req[offset + 3] << 8) + req[offset + 4];
934 926  
935   - if ((address + nb) > mb_mapping->nb_input_status) {
936   - if (mb_param->debug) {
937   - fprintf(stderr, "Illegal data address %0X in read_input_status\n",
  927 + if ((address + nb) > mb_mapping->nb_input_bits) {
  928 + if (ctx->debug) {
  929 + fprintf(stderr, "Illegal data address %0X in read_input_bits\n",
938 930 address + nb);
939 931 }
940 932 resp_length = response_exception(
941   - mb_param, &sft,
942   - MODBUS_EXCEPTION_ILLEGAL_DATA_ADDRESS, response);
  933 + ctx, &sft,
  934 + MODBUS_EXCEPTION_ILLEGAL_DATA_ADDRESS, rsp);
943 935 } else {
944   - resp_length = build_response_basis(mb_param, &sft, response);
945   - response[resp_length++] = (nb / 8) + ((nb % 8) ? 1 : 0);
  936 + resp_length = build_response_basis(ctx, &sft, rsp);
  937 + rsp[resp_length++] = (nb / 8) + ((nb % 8) ? 1 : 0);
946 938 resp_length = response_io_status(address, nb,
947   - mb_mapping->tab_input_status,
948   - response, resp_length);
  939 + mb_mapping->tab_input_bits,
  940 + rsp, resp_length);
949 941 }
950 942 }
951 943 break;
952 944 case FC_READ_HOLDING_REGISTERS: {
953   - int nb = (query[offset + 3] << 8) + query[offset + 4];
  945 + int nb = (req[offset + 3] << 8) + req[offset + 4];
954 946  
955   - if ((address + nb) > mb_mapping->nb_holding_registers) {
956   - if (mb_param->debug) {
957   - fprintf(stderr, "Illegal data address %0X in read_holding_registers\n",
  947 + if ((address + nb) > mb_mapping->nb_registers) {
  948 + if (ctx->debug) {
  949 + fprintf(stderr, "Illegal data address %0X in read_registers\n",
958 950 address + nb);
959 951 }
960 952 resp_length = response_exception(
961   - mb_param, &sft,
962   - MODBUS_EXCEPTION_ILLEGAL_DATA_ADDRESS, response);
  953 + ctx, &sft,
  954 + MODBUS_EXCEPTION_ILLEGAL_DATA_ADDRESS, rsp);
963 955 } else {
964 956 int i;
965 957  
966   - resp_length = build_response_basis(mb_param, &sft, response);
967   - response[resp_length++] = nb << 1;
  958 + resp_length = build_response_basis(ctx, &sft, rsp);
  959 + rsp[resp_length++] = nb << 1;
968 960 for (i = address; i < address + nb; i++) {
969   - response[resp_length++] = mb_mapping->tab_holding_registers[i] >> 8;
970   - response[resp_length++] = mb_mapping->tab_holding_registers[i] & 0xFF;
  961 + rsp[resp_length++] = mb_mapping->tab_registers[i] >> 8;
  962 + rsp[resp_length++] = mb_mapping->tab_registers[i] & 0xFF;
971 963 }
972 964 }
973 965 }
974 966 break;
975 967 case FC_READ_INPUT_REGISTERS: {
976   - /* Similar to holding registers (but too much arguments to use a
  968 + /* Similar to holding registers (but too many arguments to use a
977 969 * function) */
978   - int nb = (query[offset + 3] << 8) + query[offset + 4];
  970 + int nb = (req[offset + 3] << 8) + req[offset + 4];
979 971  
980 972 if ((address + nb) > mb_mapping->nb_input_registers) {
981   - if (mb_param->debug) {
  973 + if (ctx->debug) {
982 974 fprintf(stderr, "Illegal data address %0X in read_input_registers\n",
983 975 address + nb);
984 976 }
985 977 resp_length = response_exception(
986   - mb_param, &sft,
987   - MODBUS_EXCEPTION_ILLEGAL_DATA_ADDRESS, response);
  978 + ctx, &sft,
  979 + MODBUS_EXCEPTION_ILLEGAL_DATA_ADDRESS, rsp);
988 980 } else {
989 981 int i;
990 982  
991   - resp_length = build_response_basis(mb_param, &sft, response);
992   - response[resp_length++] = nb << 1;
  983 + resp_length = build_response_basis(ctx, &sft, rsp);
  984 + rsp[resp_length++] = nb << 1;
993 985 for (i = address; i < address + nb; i++) {
994   - response[resp_length++] = mb_mapping->tab_input_registers[i] >> 8;
995   - response[resp_length++] = mb_mapping->tab_input_registers[i] & 0xFF;
  986 + rsp[resp_length++] = mb_mapping->tab_input_registers[i] >> 8;
  987 + rsp[resp_length++] = mb_mapping->tab_input_registers[i] & 0xFF;
996 988 }
997 989 }
998 990 }
999 991 break;
1000   - case FC_FORCE_SINGLE_COIL:
1001   - if (address >= mb_mapping->nb_coil_status) {
1002   - if (mb_param->debug) {
1003   - fprintf(stderr, "Illegal data address %0X in force_singe_coil\n",
  992 + case FC_WRITE_SINGLE_COIL:
  993 + if (address >= mb_mapping->nb_bits) {
  994 + if (ctx->debug) {
  995 + fprintf(stderr, "Illegal data address %0X in write_bit\n",
1004 996 address);
1005 997 }
1006 998 resp_length = response_exception(
1007   - mb_param, &sft,
1008   - MODBUS_EXCEPTION_ILLEGAL_DATA_ADDRESS, response);
  999 + ctx, &sft,
  1000 + MODBUS_EXCEPTION_ILLEGAL_DATA_ADDRESS, rsp);
1009 1001 } else {
1010   - int data = (query[offset + 3] << 8) + query[offset + 4];
  1002 + int data = (req[offset + 3] << 8) + req[offset + 4];
1011 1003  
1012 1004 if (data == 0xFF00 || data == 0x0) {
1013   - mb_mapping->tab_coil_status[address] = (data) ? ON : OFF;
  1005 + mb_mapping->tab_bits[address] = (data) ? ON : OFF;
1014 1006  
1015 1007 /* In RTU mode, the CRC is computed and added
1016   - to the query by modbus_send, the computed
  1008 + to the request by send_msg, the computed
1017 1009 CRC will be same and optimisation is
1018 1010 possible here (FIXME). */
1019   - memcpy(response, query, query_length);
1020   - resp_length = query_length;
  1011 + memcpy(rsp, req, req_length);
  1012 + resp_length = req_length;
1021 1013 } else {
1022   - if (mb_param->debug) {
1023   - fprintf(stderr, "Illegal data value %0X in force_single_coil request at address %0X\n",
  1014 + if (ctx->debug) {
  1015 + fprintf(stderr,
  1016 + "Illegal data value %0X in write_bit request at address %0X\n",
1024 1017 data, address);
1025 1018 }
1026 1019 resp_length = response_exception(
1027   - mb_param, &sft,
1028   - MODBUS_EXCEPTION_ILLEGAL_DATA_VALUE, response);
  1020 + ctx, &sft,
  1021 + MODBUS_EXCEPTION_ILLEGAL_DATA_VALUE, rsp);
1029 1022 }
1030 1023 }
1031 1024 break;
1032   - case FC_PRESET_SINGLE_REGISTER:
1033   - if (address >= mb_mapping->nb_holding_registers) {
1034   - if (mb_param->debug) {
1035   - fprintf(stderr, "Illegal data address %0X in preset_holding_register\n",
  1025 + case FC_WRITE_SINGLE_REGISTER:
  1026 + if (address >= mb_mapping->nb_registers) {
  1027 + if (ctx->debug) {
  1028 + fprintf(stderr, "Illegal data address %0X in write_register\n",
1036 1029 address);
1037 1030 }
1038 1031 resp_length = response_exception(
1039   - mb_param, &sft,
1040   - MODBUS_EXCEPTION_ILLEGAL_DATA_ADDRESS, response);
  1032 + ctx, &sft,
  1033 + MODBUS_EXCEPTION_ILLEGAL_DATA_ADDRESS, rsp);
1041 1034 } else {
1042   - int data = (query[offset + 3] << 8) + query[offset + 4];
  1035 + int data = (req[offset + 3] << 8) + req[offset + 4];
1043 1036  
1044   - mb_mapping->tab_holding_registers[address] = data;
1045   - memcpy(response, query, query_length);
1046   - resp_length = query_length;
  1037 + mb_mapping->tab_registers[address] = data;
  1038 + memcpy(rsp, req, req_length);
  1039 + resp_length = req_length;
1047 1040 }
1048 1041 break;
1049   - case FC_FORCE_MULTIPLE_COILS: {
1050   - int nb = (query[offset + 3] << 8) + query[offset + 4];
  1042 + case FC_WRITE_MULTIPLE_COILS: {
  1043 + int nb = (req[offset + 3] << 8) + req[offset + 4];
1051 1044  
1052   - if ((address + nb) > mb_mapping->nb_coil_status) {
1053   - if (mb_param->debug) {
1054   - fprintf(stderr, "Illegal data address %0X in force_multiple_coils\n",
  1045 + if ((address + nb) > mb_mapping->nb_bits) {
  1046 + if (ctx->debug) {
  1047 + fprintf(stderr, "Illegal data address %0X in write_bits\n",
1055 1048 address + nb);
1056 1049 }
1057 1050 resp_length = response_exception(
1058   - mb_param, &sft,
1059   - MODBUS_EXCEPTION_ILLEGAL_DATA_ADDRESS, response);
  1051 + ctx, &sft,
  1052 + MODBUS_EXCEPTION_ILLEGAL_DATA_ADDRESS, rsp);
1060 1053 } else {
1061 1054 /* 6 = byte count */
1062   - set_bits_from_bytes(mb_mapping->tab_coil_status, address, nb, &query[offset + 6]);
  1055 + modbus_set_bits_from_bytes(mb_mapping->tab_bits, address, nb, &req[offset + 6]);
1063 1056  
1064   - resp_length = build_response_basis(mb_param, &sft, response);
1065   - /* 4 to copy the coil address (2) and the quantity of coils */
1066   - memcpy(response + resp_length, query + resp_length, 4);
  1057 + resp_length = build_response_basis(ctx, &sft, rsp);
  1058 + /* 4 to copy the bit address (2) and the quantity of bits */
  1059 + memcpy(rsp + resp_length, req + resp_length, 4);
1067 1060 resp_length += 4;
1068 1061 }
1069 1062 }
1070 1063 break;
1071   - case FC_PRESET_MULTIPLE_REGISTERS: {
1072   - int nb = (query[offset + 3] << 8) + query[offset + 4];
  1064 + case FC_WRITE_MULTIPLE_REGISTERS: {
  1065 + int nb = (req[offset + 3] << 8) + req[offset + 4];
1073 1066  
1074   - if ((address + nb) > mb_mapping->nb_holding_registers) {
1075   - if (mb_param->debug) {
1076   - fprintf(stderr, "Illegal data address %0X in preset_multiple_registers\n",
  1067 + if ((address + nb) > mb_mapping->nb_registers) {
  1068 + if (ctx->debug) {
  1069 + fprintf(stderr, "Illegal data address %0X in write_registers\n",
1077 1070 address + nb);
1078 1071 }
1079 1072 resp_length = response_exception(
1080   - mb_param, &sft,
1081   - MODBUS_EXCEPTION_ILLEGAL_DATA_ADDRESS, response);
  1073 + ctx, &sft,
  1074 + MODBUS_EXCEPTION_ILLEGAL_DATA_ADDRESS, rsp);
1082 1075 } else {
1083 1076 int i, j;
1084 1077 for (i = address, j = 6; i < address + nb; i++, j += 2) {
1085 1078 /* 6 and 7 = first value */
1086   - mb_mapping->tab_holding_registers[i] =
1087   - (query[offset + j] << 8) + query[offset + j + 1];
  1079 + mb_mapping->tab_registers[i] =
  1080 + (req[offset + j] << 8) + req[offset + j + 1];
1088 1081 }
1089 1082  
1090   - resp_length = build_response_basis(mb_param, &sft, response);
  1083 + resp_length = build_response_basis(ctx, &sft, rsp);
1091 1084 /* 4 to copy the address (2) and the no. of registers */
1092   - memcpy(response + resp_length, query + resp_length, 4);
  1085 + memcpy(rsp + resp_length, req + resp_length, 4);
1093 1086 resp_length += 4;
1094 1087 }
1095 1088 }
1096 1089 break;
1097 1090 case FC_READ_EXCEPTION_STATUS:
1098 1091 case FC_REPORT_SLAVE_ID:
1099   - if (mb_param->debug) {
  1092 + if (ctx->debug) {
1100 1093 fprintf(stderr, "FIXME Not implemented\n");
1101 1094 }
1102 1095 errno = ENOPROTOOPT;
... ... @@ -1107,38 +1100,37 @@ int modbus_slave_manage(modbus_param_t *mb_param, const uint8_t *query,
1107 1100 break;
1108 1101 }
1109 1102  
1110   - return modbus_send(mb_param, response, resp_length);
  1103 + return send_msg(ctx, rsp, resp_length);
1111 1104 }
1112 1105  
1113 1106 /* Reads IO status */
1114   -static int read_io_status(modbus_param_t *mb_param, int slave, int function,
1115   - int start_addr, int nb, uint8_t *data_dest)
  1107 +static int read_io_status(modbus_t *ctx, int function,
  1108 + int addr, int nb, uint8_t *data_dest)
1116 1109 {
1117 1110 int rc;
1118   - int query_length;
  1111 + int req_length;
1119 1112  
1120   - uint8_t query[MIN_QUERY_LENGTH];
1121   - uint8_t response[MAX_MESSAGE_LENGTH];
  1113 + uint8_t req[MIN_REQ_LENGTH];
  1114 + uint8_t rsp[MAX_MESSAGE_LENGTH];
1122 1115  
1123   - query_length = build_query_basis(mb_param, slave, function,
1124   - start_addr, nb, query);
  1116 + req_length = build_request_basis(ctx, function, addr, nb, req);
1125 1117  
1126   - rc = modbus_send(mb_param, query, query_length);
  1118 + rc = send_msg(ctx, req, req_length);
1127 1119 if (rc > 0) {
1128 1120 int i, temp, bit;
1129 1121 int pos = 0;
1130 1122 int offset;
1131 1123 int offset_end;
1132 1124  
1133   - rc = modbus_receive(mb_param, query, response);
  1125 + rc = receive_msg_req(ctx, req, rsp);
1134 1126 if (rc == -1)
1135 1127 return -1;
1136 1128  
1137   - offset = TAB_HEADER_LENGTH[mb_param->type_com];
  1129 + offset = TAB_HEADER_LENGTH[ctx->type_com];
1138 1130 offset_end = offset + rc;
1139 1131 for (i = offset; i < offset_end; i++) {
1140 1132 /* Shift reg hi_byte to temp */
1141   - temp = response[i + 2];
  1133 + temp = rsp[i + 2];
1142 1134  
1143 1135 for (bit = 0x01; (bit & 0xff) && (pos < nb);) {
1144 1136 data_dest[pos++] = (temp & bit) ? TRUE : FALSE;
... ... @@ -1151,25 +1143,23 @@ static int read_io_status(modbus_param_t *mb_param, int slave, int function,
1151 1143 return rc;
1152 1144 }
1153 1145  
1154   -/* Reads the boolean status of coils and sets the array elements
1155   - in the destination to TRUE or FALSE. */
1156   -int read_coil_status(modbus_param_t *mb_param, int slave, int start_addr,
1157   - int nb, uint8_t *data_dest)
  1146 +/* Reads the boolean status of bits and sets the array elements
  1147 + in the destination to TRUE or FALSE (single bits). */
  1148 +int modbus_read_bits(modbus_t *ctx, int addr, int nb, uint8_t *data_dest)
1158 1149 {
1159 1150 int rc;
1160 1151  
1161   - if (nb > MAX_STATUS) {
1162   - if (mb_param->debug) {
  1152 + if (nb > MODBUS_MAX_BITS) {
  1153 + if (ctx->debug) {
1163 1154 fprintf(stderr,
1164   - "ERROR Too many coils status requested (%d > %d)\n",
1165   - nb, MAX_STATUS);
  1155 + "ERROR Too many bits requested (%d > %d)\n",
  1156 + nb, MODBUS_MAX_BITS);
1166 1157 }
1167 1158 errno = EMBMDATA;
1168 1159 return -1;
1169 1160 }
1170 1161  
1171   - rc = read_io_status(mb_param, slave, FC_READ_COIL_STATUS, start_addr,
1172   - nb, data_dest);
  1162 + rc = read_io_status(ctx, FC_READ_COILS, addr, nb, data_dest);
1173 1163  
1174 1164 if (rc == -1)
1175 1165 return -1;
... ... @@ -1178,24 +1168,22 @@ int read_coil_status(modbus_param_t *mb_param, int slave, int start_addr,
1178 1168 }
1179 1169  
1180 1170  
1181   -/* Same as read_coil_status but reads the slaves input table */
1182   -int read_input_status(modbus_param_t *mb_param, int slave, int start_addr,
1183   - int nb, uint8_t *data_dest)
  1171 +/* Same as modbus_read_bits but reads the remote device input table */
  1172 +int modbus_read_input_bits(modbus_t *ctx, int addr, int nb, uint8_t *data_dest)
1184 1173 {
1185 1174 int rc;
1186 1175  
1187   - if (nb > MAX_STATUS) {
1188   - if (mb_param->debug) {
  1176 + if (nb > MODBUS_MAX_BITS) {
  1177 + if (ctx->debug) {
1189 1178 fprintf(stderr,
1190   - "ERROR Too many input status requested (%d > %d)\n",
1191   - nb, MAX_STATUS);
  1179 + "ERROR Too many discrete inputs requested (%d > %d)\n",
  1180 + nb, MODBUS_MAX_BITS);
1192 1181 }
1193 1182 errno = EMBMDATA;
1194 1183 return -1;
1195 1184 }
1196 1185  
1197   - rc = read_io_status(mb_param, slave, FC_READ_INPUT_STATUS, start_addr,
1198   - nb, data_dest);
  1186 + rc = read_io_status(ctx, FC_READ_DISCRETE_INPUTS, addr, nb, data_dest);
1199 1187  
1200 1188 if (rc == -1)
1201 1189 return -1;
... ... @@ -1203,311 +1191,318 @@ int read_input_status(modbus_param_t *mb_param, int slave, int start_addr,
1203 1191 return nb;
1204 1192 }
1205 1193  
1206   -/* Reads the data from a modbus slave and put that data into an array */
1207   -static int read_registers(modbus_param_t *mb_param, int slave, int function,
1208   - int start_addr, int nb, uint16_t *data_dest)
  1194 +/* Reads the data from a remove device and put that data into an array */
  1195 +static int read_registers(modbus_t *ctx, int function, int addr, int nb,
  1196 + uint16_t *data_dest)
1209 1197 {
1210 1198 int rc;
1211   - int query_length;
1212   - uint8_t query[MIN_QUERY_LENGTH];
1213   - uint8_t response[MAX_MESSAGE_LENGTH];
  1199 + int req_length;
  1200 + uint8_t req[MIN_REQ_LENGTH];
  1201 + uint8_t rsp[MAX_MESSAGE_LENGTH];
1214 1202  
1215   - if (nb > MAX_REGISTERS) {
1216   - if (mb_param->debug) {
  1203 + if (nb > MODBUS_MAX_REGISTERS) {
  1204 + if (ctx->debug) {
1217 1205 fprintf(stderr,
1218   - "ERROR Too many holding registers requested (%d > %d)\n",
1219   - nb, MAX_REGISTERS);
  1206 + "ERROR Too many registers requested (%d > %d)\n",
  1207 + nb, MODBUS_MAX_REGISTERS);
1220 1208 }
1221 1209 errno = EMBMDATA;
1222 1210 return -1;
1223 1211 }
1224 1212  
1225   - query_length = build_query_basis(mb_param, slave, function,
1226   - start_addr, nb, query);
  1213 + req_length = build_request_basis(ctx, function, addr, nb, req);
1227 1214  
1228   - rc = modbus_send(mb_param, query, query_length);
  1215 + rc = send_msg(ctx, req, req_length);
1229 1216 if (rc > 0) {
1230 1217 int offset;
1231 1218 int i;
1232 1219  
1233   - rc = modbus_receive(mb_param, query, response);
  1220 + rc = receive_msg_req(ctx, req, rsp);
1234 1221  
1235   - offset = TAB_HEADER_LENGTH[mb_param->type_com];
  1222 + offset = TAB_HEADER_LENGTH[ctx->type_com];
1236 1223  
1237 1224 /* If rc is negative, the loop is jumped ! */
1238 1225 for (i = 0; i < rc; i++) {
1239 1226 /* shift reg hi_byte to temp OR with lo_byte */
1240   - data_dest[i] = (response[offset + 2 + (i << 1)] << 8) |
1241   - response[offset + 3 + (i << 1)];
  1227 + data_dest[i] = (rsp[offset + 2 + (i << 1)] << 8) |
  1228 + rsp[offset + 3 + (i << 1)];
1242 1229 }
1243 1230 }
1244 1231  
1245 1232 return rc;
1246 1233 }
1247 1234  
1248   -/* Reads the holding registers in a slave and put the data into an
  1235 +/* Reads the holding registers of remote device and put the data into an
1249 1236 array */
1250   -int read_holding_registers(modbus_param_t *mb_param, int slave,
1251   - int start_addr, int nb, uint16_t *data_dest)
  1237 +int modbus_read_registers(modbus_t *ctx, int addr, int nb, uint16_t *data_dest)
1252 1238 {
1253 1239 int status;
1254 1240  
1255   - if (nb > MAX_REGISTERS) {
1256   - if (mb_param->debug) {
  1241 + if (nb > MODBUS_MAX_REGISTERS) {
  1242 + if (ctx->debug) {
1257 1243 fprintf(stderr,
1258   - "ERROR Too many holding registers requested (%d > %d)\n",
1259   - nb, MAX_REGISTERS);
  1244 + "ERROR Too many registers requested (%d > %d)\n",
  1245 + nb, MODBUS_MAX_REGISTERS);
1260 1246 }
1261 1247 errno = EMBMDATA;
1262 1248 return -1;
1263 1249 }
1264 1250  
1265   - status = read_registers(mb_param, slave, FC_READ_HOLDING_REGISTERS,
1266   - start_addr, nb, data_dest);
  1251 + status = read_registers(ctx, FC_READ_HOLDING_REGISTERS,
  1252 + addr, nb, data_dest);
1267 1253 return status;
1268 1254 }
1269 1255  
1270   -/* Reads the input registers in a slave and put the data into
1271   - an array */
1272   -int read_input_registers(modbus_param_t *mb_param, int slave, int start_addr,
1273   - int nb, uint16_t *data_dest)
  1256 +/* Reads the input registers of remote device and put the data into an array */
  1257 +int modbus_read_input_registers(modbus_t *ctx, int addr, int nb,
  1258 + uint16_t *data_dest)
1274 1259 {
1275 1260 int status;
1276 1261  
1277   - if (nb > MAX_REGISTERS) {
  1262 + if (nb > MODBUS_MAX_REGISTERS) {
1278 1263 fprintf(stderr,
1279 1264 "ERROR Too many input registers requested (%d > %d)\n",
1280   - nb, MAX_REGISTERS);
  1265 + nb, MODBUS_MAX_REGISTERS);
1281 1266 errno = EMBMDATA;
1282 1267 return -1;
1283 1268 }
1284 1269  
1285   - status = read_registers(mb_param, slave, FC_READ_INPUT_REGISTERS,
1286   - start_addr, nb, data_dest);
  1270 + status = read_registers(ctx, FC_READ_INPUT_REGISTERS,
  1271 + addr, nb, data_dest);
1287 1272  
1288 1273 return status;
1289 1274 }
1290 1275  
1291   -/* Sends a value to a register in a slave.
1292   - Used by force_single_coil and preset_single_register */
1293   -static int set_single(modbus_param_t *mb_param, int slave, int function,
1294   - int addr, int value)
  1276 +/* Write a value to the specified register of the remote device.
  1277 + Used by write_bit and write_register */
  1278 +static int write_single(modbus_t *ctx, int function, int addr, int value)
1295 1279 {
1296 1280 int rc;
1297   - int query_length;
1298   - uint8_t query[MIN_QUERY_LENGTH];
  1281 + int req_length;
  1282 + uint8_t req[MIN_REQ_LENGTH];
1299 1283  
1300   - query_length = build_query_basis(mb_param, slave, function,
1301   - addr, value, query);
  1284 + req_length = build_request_basis(ctx, function, addr, value, req);
1302 1285  
1303   - rc = modbus_send(mb_param, query, query_length);
  1286 + rc = send_msg(ctx, req, req_length);
1304 1287 if (rc > 0) {
1305   - /* Used by force_single_coil and
1306   - * preset_single_register */
1307   - uint8_t response[MIN_QUERY_LENGTH];
1308   - rc = modbus_receive(mb_param, query, response);
  1288 + /* Used by write_bit and write_register */
  1289 + uint8_t rsp[MIN_REQ_LENGTH];
  1290 + rc = receive_msg_req(ctx, req, rsp);
1309 1291 }
1310 1292  
1311 1293 return rc;
1312 1294 }
1313 1295  
1314   -/* Turns ON or OFF a single coil in the slave device */
1315   -int force_single_coil(modbus_param_t *mb_param, int slave, int coil_addr, int state)
  1296 +/* Turns ON or OFF a single bit of the remote device */
  1297 +int modbus_write_bit(modbus_t *ctx, int addr, int state)
1316 1298 {
1317 1299 int status;
1318 1300  
1319 1301 if (state)
1320 1302 state = 0xFF00;
1321 1303  
1322   - status = set_single(mb_param, slave, FC_FORCE_SINGLE_COIL,
1323   - coil_addr, state);
  1304 + status = write_single(ctx, FC_WRITE_SINGLE_COIL, addr, state);
1324 1305  
1325 1306 return status;
1326 1307 }
1327 1308  
1328   -/* Sets a value in one holding register in the slave device */
1329   -int preset_single_register(modbus_param_t *mb_param, int slave, int reg_addr,
1330   - int value)
  1309 +/* Writes a value in one register of the remote device */
  1310 +int modbus_write_register(modbus_t *ctx, int addr, int value)
1331 1311 {
1332 1312 int status;
1333 1313  
1334   - status = set_single(mb_param, slave, FC_PRESET_SINGLE_REGISTER,
1335   - reg_addr, value);
  1314 + status = write_single(ctx, FC_WRITE_SINGLE_REGISTER, addr, value);
1336 1315  
1337 1316 return status;
1338 1317 }
1339 1318  
1340   -/* Sets/resets the coils in the slave from an array in argument */
1341   -int force_multiple_coils(modbus_param_t *mb_param, int slave, int start_addr,
1342   - int nb, const uint8_t *data_src)
  1319 +/* Write the bits of the array in the remote device */
  1320 +int modbus_write_bits(modbus_t *ctx, int addr, int nb, const uint8_t *data_src)
1343 1321 {
1344 1322 int rc;
1345 1323 int i;
1346 1324 int byte_count;
1347   - int query_length;
1348   - int coil_check = 0;
  1325 + int req_length;
  1326 + int bit_check = 0;
1349 1327 int pos = 0;
1350 1328  
1351   - uint8_t query[MAX_MESSAGE_LENGTH];
  1329 + uint8_t req[MAX_MESSAGE_LENGTH];
1352 1330  
1353   - if (nb > MAX_STATUS) {
1354   - if (mb_param->debug) {
1355   - fprintf(stderr, "ERROR Writing to too many coils (%d > %d)\n",
1356   - nb, MAX_STATUS);
  1331 + if (nb > MODBUS_MAX_BITS) {
  1332 + if (ctx->debug) {
  1333 + fprintf(stderr, "ERROR Writing too many bits (%d > %d)\n",
  1334 + nb, MODBUS_MAX_BITS);
1357 1335 }
1358 1336 errno = EMBMDATA;
1359 1337 return -1;
1360 1338 }
1361 1339  
1362   - query_length = build_query_basis(mb_param, slave, FC_FORCE_MULTIPLE_COILS,
1363   - start_addr, nb, query);
  1340 + req_length = build_request_basis(ctx, FC_WRITE_MULTIPLE_COILS,
  1341 + addr, nb, req);
1364 1342 byte_count = (nb / 8) + ((nb % 8) ? 1 : 0);
1365   - query[query_length++] = byte_count;
  1343 + req[req_length++] = byte_count;
1366 1344  
1367 1345 for (i = 0; i < byte_count; i++) {
1368 1346 int bit;
1369 1347  
1370 1348 bit = 0x01;
1371   - query[query_length] = 0;
  1349 + req[req_length] = 0;
1372 1350  
1373   - while ((bit & 0xFF) && (coil_check++ < nb)) {
  1351 + while ((bit & 0xFF) && (bit_check++ < nb)) {
1374 1352 if (data_src[pos++])
1375   - query[query_length] |= bit;
  1353 + req[req_length] |= bit;
1376 1354 else
1377   - query[query_length] &=~ bit;
  1355 + req[req_length] &=~ bit;
1378 1356  
1379 1357 bit = bit << 1;
1380 1358 }
1381   - query_length++;
  1359 + req_length++;
1382 1360 }
1383 1361  
1384   - rc = modbus_send(mb_param, query, query_length);
  1362 + rc = send_msg(ctx, req, req_length);
1385 1363 if (rc > 0) {
1386   - uint8_t response[MAX_MESSAGE_LENGTH];
1387   - rc = modbus_receive(mb_param, query, response);
  1364 + uint8_t rsp[MAX_MESSAGE_LENGTH];
  1365 + rc = receive_msg_req(ctx, req, rsp);
1388 1366 }
1389 1367  
1390 1368  
1391 1369 return rc;
1392 1370 }
1393 1371  
1394   -/* Copies the values in the slave from the array given in argument */
1395   -int preset_multiple_registers(modbus_param_t *mb_param, int slave, int start_addr,
1396   - int nb, const uint16_t *data_src)
  1372 +/* Write the values from the array to the registers of the remote device */
  1373 +int modbus_write_registers(modbus_t *ctx, int addr, int nb, const uint16_t *data_src)
1397 1374 {
1398 1375 int rc;
1399 1376 int i;
1400   - int query_length;
  1377 + int req_length;
1401 1378 int byte_count;
1402 1379  
1403   - uint8_t query[MAX_MESSAGE_LENGTH];
  1380 + uint8_t req[MAX_MESSAGE_LENGTH];
1404 1381  
1405   - if (nb > MAX_REGISTERS) {
1406   - if (mb_param->debug) {
  1382 + if (nb > MODBUS_MAX_REGISTERS) {
  1383 + if (ctx->debug) {
1407 1384 fprintf(stderr,
1408 1385 "ERROR Trying to write to too many registers (%d > %d)\n",
1409   - nb, MAX_REGISTERS);
  1386 + nb, MODBUS_MAX_REGISTERS);
1410 1387 }
1411 1388 errno = EMBMDATA;
1412 1389 return -1;
1413 1390 }
1414 1391  
1415   - query_length = build_query_basis(mb_param, slave, FC_PRESET_MULTIPLE_REGISTERS,
1416   - start_addr, nb, query);
  1392 + req_length = build_request_basis(ctx, FC_WRITE_MULTIPLE_REGISTERS,
  1393 + addr, nb, req);
1417 1394 byte_count = nb * 2;
1418   - query[query_length++] = byte_count;
  1395 + req[req_length++] = byte_count;
1419 1396  
1420 1397 for (i = 0; i < nb; i++) {
1421   - query[query_length++] = data_src[i] >> 8;
1422   - query[query_length++] = data_src[i] & 0x00FF;
  1398 + req[req_length++] = data_src[i] >> 8;
  1399 + req[req_length++] = data_src[i] & 0x00FF;
1423 1400 }
1424 1401  
1425   - rc = modbus_send(mb_param, query, query_length);
  1402 + rc = send_msg(ctx, req, req_length);
1426 1403 if (rc > 0) {
1427   - uint8_t response[MAX_MESSAGE_LENGTH];
1428   - rc = modbus_receive(mb_param, query, response);
  1404 + uint8_t rsp[MAX_MESSAGE_LENGTH];
  1405 + rc = receive_msg_req(ctx, req, rsp);
1429 1406 }
1430 1407  
1431 1408 return rc;
1432 1409 }
1433 1410  
1434   -/* Request the slave ID */
1435   -int report_slave_id(modbus_param_t *mb_param, int slave, uint8_t *data_dest)
  1411 +/* Send a request to get the slave ID of the device (only available in serial
  1412 + * communication) */
  1413 +int modbus_report_slave_id(modbus_t *ctx, uint8_t *data_dest)
1436 1414 {
1437 1415 int rc;
1438   - int query_length;
1439   - uint8_t query[MIN_QUERY_LENGTH];
  1416 + int req_length;
  1417 + uint8_t req[MIN_REQ_LENGTH];
1440 1418  
1441   - query_length = build_query_basis(mb_param, slave,
1442   - FC_REPORT_SLAVE_ID, 0, 0, query);
  1419 + if (ctx->type_com != RTU) {
  1420 + /* Only for serial communications */
  1421 + errno = EINVAL;
  1422 + return -1;
  1423 + }
  1424 +
  1425 + req_length = build_request_basis(ctx, FC_REPORT_SLAVE_ID, 0, 0, req);
1443 1426  
1444   - /* HACKISH, start_addr and count are not used */
1445   - query_length -= 4;
  1427 + /* HACKISH, addr and count are not used */
  1428 + req_length -= 4;
1446 1429  
1447   - rc = modbus_send(mb_param, query, query_length);
  1430 + rc = send_msg(ctx, req, req_length);
1448 1431 if (rc > 0) {
1449 1432 int i;
1450 1433 int offset;
1451 1434 int offset_end;
1452   - uint8_t response[MAX_MESSAGE_LENGTH];
  1435 + uint8_t rsp[MAX_MESSAGE_LENGTH];
1453 1436  
1454 1437 /* Byte count, slave id, run indicator status,
1455 1438 additional data */
1456   - rc = modbus_receive(mb_param, query, response);
  1439 + rc = receive_msg_req(ctx, req, rsp);
1457 1440 if (rc == -1)
1458 1441 return rc;
1459 1442  
1460   - offset = TAB_HEADER_LENGTH[mb_param->type_com] - 1;
  1443 + offset = TAB_HEADER_LENGTH[ctx->type_com] - 1;
1461 1444 offset_end = offset + rc;
1462 1445  
1463 1446 for (i = offset; i < offset_end; i++)
1464   - data_dest[i] = response[i];
  1447 + data_dest[i] = rsp[i];
1465 1448 }
1466 1449  
1467 1450 return rc;
1468 1451 }
1469 1452  
1470   -void init_common(modbus_param_t *mb_param)
  1453 +static void init_common(modbus_t *ctx)
1471 1454 {
1472   - mb_param->timeout_begin.tv_sec = 0;
1473   - mb_param->timeout_begin.tv_usec = TIME_OUT_BEGIN_OF_TRAME;
  1455 + ctx->timeout_begin.tv_sec = 0;
  1456 + ctx->timeout_begin.tv_usec = TIME_OUT_BEGIN_OF_TRAME;
  1457 +
  1458 + ctx->timeout_end.tv_sec = 0;
  1459 + ctx->timeout_end.tv_usec = TIME_OUT_END_OF_TRAME;
1474 1460  
1475   - mb_param->timeout_end.tv_sec = 0;
1476   - mb_param->timeout_end.tv_usec = TIME_OUT_END_OF_TRAME;
  1461 + ctx->error_recovery = FALSE;
  1462 + ctx->debug = FALSE;
1477 1463 }
1478 1464  
1479   -/* Initializes the modbus_param_t structure for RTU
  1465 +/* Allocate and initialize the modbus_t structure for RTU
1480 1466 - device: "/dev/ttyS0"
1481 1467 - baud: 9600, 19200, 57600, 115200, etc
1482 1468 - parity: 'N' stands for None, 'E' for Even and 'O' for odd
1483 1469 - data_bits: 5, 6, 7, 8
1484 1470 - stop_bits: 1, 2
1485   - - slave: slave number
  1471 + - slave: slave number of the caller
1486 1472 */
1487   -int modbus_init_rtu(modbus_param_t *mb_param, const char *device,
1488   - int baud, char parity, int data_bit,
1489   - int stop_bit, int slave)
  1473 +modbus_t* modbus_new_rtu(const char *device,
  1474 + int baud, char parity, int data_bit,
  1475 + int stop_bit, int slave)
1490 1476 {
1491   - memset(mb_param, 0, sizeof(modbus_param_t));
1492   - init_common(mb_param);
  1477 + modbus_t *ctx;
  1478 + modbus_rtu_t *ctx_rtu;
1493 1479  
1494   - strcpy(mb_param->device, device);
1495   - mb_param->baud = baud;
  1480 + ctx = (modbus_t *) malloc(sizeof(modbus_t));
  1481 + init_common(ctx);
  1482 + if (modbus_set_slave(ctx, slave) == -1) {
  1483 + return NULL;
  1484 + }
  1485 +
  1486 + ctx->type_com = RTU;
  1487 +
  1488 + ctx->com = (modbus_rtu_t *) malloc(sizeof(modbus_rtu_t));
  1489 + ctx_rtu = (modbus_rtu_t *)ctx->com;
  1490 +
  1491 + strcpy(ctx_rtu->device, device);
  1492 + ctx_rtu->baud = baud;
1496 1493 if (parity == 'N' || parity == 'E' || parity == 'O') {
1497   - mb_param->parity = parity;
  1494 + ctx_rtu->parity = parity;
1498 1495 } else {
1499 1496 errno = EINVAL;
1500   - return -1;
  1497 + return NULL;
1501 1498 }
1502   - mb_param->debug = FALSE;
1503   - mb_param->data_bit = data_bit;
1504   - mb_param->stop_bit = stop_bit;
1505   - mb_param->type_com = RTU;
1506   - mb_param->error_recovery = FALSE;
1507   - return modbus_set_slave(mb_param, slave);
  1499 + ctx_rtu->data_bit = data_bit;
  1500 + ctx_rtu->stop_bit = stop_bit;
  1501 +
  1502 + return ctx;
1508 1503 }
1509 1504  
1510   -/* Initializes the modbus_param_t structure for TCP.
  1505 +/* Allocates and initializes the modbus_t structure for TCP.
1511 1506 - ip : "192.168.0.5"
1512 1507 - port : 1099
1513 1508  
... ... @@ -1516,29 +1511,35 @@ int modbus_init_rtu(modbus_param_t *mb_param, const char *device,
1516 1511 to 1024 because it's not necessary to be root to use this port
1517 1512 number.
1518 1513 */
1519   -int modbus_init_tcp(modbus_param_t *mb_param, const char *ip, int port)
  1514 +modbus_t* modbus_new_tcp(const char *ip, int port)
1520 1515 {
1521   - memset(mb_param, 0, sizeof(modbus_param_t));
1522   - init_common(mb_param);
  1516 + modbus_t *ctx;
  1517 + modbus_tcp_t *ctx_tcp;
1523 1518  
1524   - strncpy(mb_param->ip, ip, sizeof(char)*16);
1525   - mb_param->port = port;
1526   - mb_param->type_com = TCP;
1527   - mb_param->error_recovery = FALSE;
1528   - /* Can be changed after to reach remote serial Modbus device */
1529   - mb_param->slave = 0xFF;
  1519 + ctx = (modbus_t *) malloc(sizeof(modbus_t));
  1520 + init_common(ctx);
  1521 + ctx->slave = MODBUS_TCP_SLAVE;
1530 1522  
1531   - return 0;
  1523 + ctx->type_com = TCP;
  1524 +
  1525 + ctx->com = (modbus_tcp_t *) malloc(sizeof(modbus_tcp_t));
  1526 + ctx_tcp = (modbus_tcp_t *)ctx->com;
  1527 +
  1528 + strncpy(ctx_tcp->ip, ip, sizeof(char)*16);
  1529 + ctx_tcp->port = port;
  1530 +
  1531 + /* Can be changed after to reach remote serial Modbus device */
  1532 + return ctx;
1532 1533 }
1533 1534  
1534 1535 /* Define the slave number, the special value MODBUS_TCP_SLAVE (0xFF) can be
1535 1536 * used in TCP mode to restore the default value. */
1536   -int modbus_set_slave(modbus_param_t *mb_param, int slave)
  1537 +int modbus_set_slave(modbus_t *ctx, int slave)
1537 1538 {
1538 1539 if (slave >= 1 && slave <= 247) {
1539   - mb_param->slave = slave;
1540   - } else if (mb_param->type_com == TCP && slave == MODBUS_TCP_SLAVE) {
1541   - mb_param->slave = slave;
  1540 + ctx->slave = slave;
  1541 + } else if (ctx->type_com == TCP && slave == MODBUS_TCP_SLAVE) {
  1542 + ctx->slave = slave;
1542 1543 } else {
1543 1544 errno = EINVAL;
1544 1545 return -1;
... ... @@ -1560,10 +1561,10 @@ int modbus_set_slave(modbus_param_t *mb_param, int slave)
1560 1561 will return an error (if the connecton was down, the values to read are
1561 1562 certainly not available anymore after reconnection, except for slave/server).
1562 1563 */
1563   -int modbus_set_error_recovery(modbus_param_t *mb_param, int enabled)
  1564 +int modbus_set_error_recovery(modbus_t *ctx, int enabled)
1564 1565 {
1565 1566 if (enabled == TRUE || enabled == FALSE) {
1566   - mb_param->error_recovery = (uint8_t) enabled;
  1567 + ctx->error_recovery = (uint8_t) enabled;
1567 1568 } else {
1568 1569 errno = EINVAL;
1569 1570 return -1;
... ... @@ -1573,39 +1574,40 @@ int modbus_set_error_recovery(modbus_param_t *mb_param, int enabled)
1573 1574 }
1574 1575  
1575 1576 /* Get the timeout of begin of trame */
1576   -void modbus_get_timeout_begin(modbus_param_t *mb_param, struct timeval *timeout)
  1577 +void modbus_get_timeout_begin(modbus_t *ctx, struct timeval *timeout)
1577 1578 {
1578   - *timeout = mb_param->timeout_begin;
  1579 + *timeout = ctx->timeout_begin;
1579 1580 }
1580 1581  
1581 1582 /* Set timeout when waiting the beginning of a trame */
1582   -void modbus_set_timeout_begin(modbus_param_t *mb_param, const struct timeval *timeout)
  1583 +void modbus_set_timeout_begin(modbus_t *ctx, const struct timeval *timeout)
1583 1584 {
1584   - mb_param->timeout_begin = *timeout;
  1585 + ctx->timeout_begin = *timeout;
1585 1586 }
1586 1587  
1587 1588 /* Get the timeout of end of trame */
1588   -void modbus_get_timeout_end(modbus_param_t *mb_param, struct timeval *timeout)
  1589 +void modbus_get_timeout_end(modbus_t *ctx, struct timeval *timeout)
1589 1590 {
1590   - *timeout = mb_param->timeout_end;
  1591 + *timeout = ctx->timeout_end;
1591 1592 }
1592 1593  
1593 1594 /* Set timeout when waiting the end of a trame */
1594   -void modbus_set_timeout_end(modbus_param_t *mb_param, const struct timeval *timeout)
  1595 +void modbus_set_timeout_end(modbus_t *ctx, const struct timeval *timeout)
1595 1596 {
1596   - mb_param->timeout_end = *timeout;
  1597 + ctx->timeout_end = *timeout;
1597 1598 }
1598 1599  
1599 1600 /* Sets up a serial port for RTU communications */
1600   -static int modbus_connect_rtu(modbus_param_t *mb_param)
  1601 +static int modbus_connect_rtu(modbus_t *ctx)
1601 1602 {
1602 1603 struct termios tios;
1603 1604 speed_t speed;
  1605 + modbus_rtu_t *ctx_rtu = ctx->com;
1604 1606  
1605   - if (mb_param->debug) {
  1607 + if (ctx->debug) {
1606 1608 printf("Opening %s at %d bauds (%c, %d, %d)\n",
1607   - mb_param->device, mb_param->baud, mb_param->parity,
1608   - mb_param->data_bit, mb_param->stop_bit);
  1609 + ctx_rtu->device, ctx_rtu->baud, ctx_rtu->parity,
  1610 + ctx_rtu->data_bit, ctx_rtu->stop_bit);
1609 1611 }
1610 1612  
1611 1613 /* The O_NOCTTY flag tells UNIX that this program doesn't want
... ... @@ -1615,22 +1617,22 @@ static int modbus_connect_rtu(modbus_param_t *mb_param)
1615 1617  
1616 1618 Timeouts are ignored in canonical input mode or when the
1617 1619 NDELAY option is set on the file via open or fcntl */
1618   - mb_param->fd = open(mb_param->device, O_RDWR | O_NOCTTY | O_NDELAY | O_EXCL);
1619   - if (mb_param->fd == -1) {
  1620 + ctx->s = open(ctx_rtu->device, O_RDWR | O_NOCTTY | O_NDELAY | O_EXCL);
  1621 + if (ctx->s == -1) {
1620 1622 fprintf(stderr, "ERROR Can't open the device %s (%s)\n",
1621   - mb_param->device, strerror(errno));
  1623 + ctx_rtu->device, strerror(errno));
1622 1624 return -1;
1623 1625 }
1624 1626  
1625 1627 /* Save */
1626   - tcgetattr(mb_param->fd, &(mb_param->old_tios));
  1628 + tcgetattr(ctx->s, &(ctx_rtu->old_tios));
1627 1629  
1628 1630 memset(&tios, 0, sizeof(struct termios));
1629 1631  
1630 1632 /* C_ISPEED Input baud (new interface)
1631 1633 C_OSPEED Output baud (new interface)
1632 1634 */
1633   - switch (mb_param->baud) {
  1635 + switch (ctx_rtu->baud) {
1634 1636 case 110:
1635 1637 speed = B110;
1636 1638 break;
... ... @@ -1666,10 +1668,10 @@ static int modbus_connect_rtu(modbus_param_t *mb_param)
1666 1668 break;
1667 1669 default:
1668 1670 speed = B9600;
1669   - if (mb_param->debug) {
  1671 + if (ctx->debug) {
1670 1672 fprintf(stderr,
1671 1673 "WARNING Unknown baud rate %d for %s (B9600 used)\n",
1672   - mb_param->baud, mb_param->device);
  1674 + ctx_rtu->baud, ctx_rtu->device);
1673 1675 }
1674 1676 }
1675 1677  
... ... @@ -1690,7 +1692,7 @@ static int modbus_connect_rtu(modbus_param_t *mb_param)
1690 1692 CSIZE Bit mask for data bits
1691 1693 */
1692 1694 tios.c_cflag &= ~CSIZE;
1693   - switch (mb_param->data_bit) {
  1695 + switch (ctx_rtu->data_bit) {
1694 1696 case 5:
1695 1697 tios.c_cflag |= CS5;
1696 1698 break;
... ... @@ -1707,17 +1709,17 @@ static int modbus_connect_rtu(modbus_param_t *mb_param)
1707 1709 }
1708 1710  
1709 1711 /* Stop bit (1 or 2) */
1710   - if (mb_param->stop_bit == 1)
  1712 + if (ctx_rtu->stop_bit == 1)
1711 1713 tios.c_cflag &=~ CSTOPB;
1712 1714 else /* 2 */
1713 1715 tios.c_cflag |= CSTOPB;
1714 1716  
1715 1717 /* PARENB Enable parity bit
1716 1718 PARODD Use odd parity instead of even */
1717   - if (mb_param->parity == 'N') {
  1719 + if (ctx_rtu->parity == 'N') {
1718 1720 /* None */
1719 1721 tios.c_cflag &=~ PARENB;
1720   - } else if (mb_param->parity == 'E') {
  1722 + } else if (ctx_rtu->parity == 'E') {
1721 1723 /* Even */
1722 1724 tios.c_cflag |= PARENB;
1723 1725 tios.c_cflag &=~ PARODD;
... ... @@ -1784,7 +1786,7 @@ static int modbus_connect_rtu(modbus_param_t *mb_param)
1784 1786 IUCLC Map uppercase to lowercase
1785 1787 IMAXBEL Echo BEL on input line too long
1786 1788 */
1787   - if (mb_param->parity == 'N') {
  1789 + if (ctx_rtu->parity == 'N') {
1788 1790 /* None */
1789 1791 tios.c_iflag &= ~INPCK;
1790 1792 } else {
... ... @@ -1847,32 +1849,33 @@ static int modbus_connect_rtu(modbus_param_t *mb_param)
1847 1849 tios.c_cc[VMIN] = 0;
1848 1850 tios.c_cc[VTIME] = 0;
1849 1851  
1850   - if (tcsetattr(mb_param->fd, TCSANOW, &tios) < 0) {
  1852 + if (tcsetattr(ctx->s, TCSANOW, &tios) < 0) {
1851 1853 return -1;
1852 1854 }
1853 1855  
1854 1856 return 0;
1855 1857 }
1856 1858  
1857   -/* Establishes a modbus TCP connection with a modbus slave */
1858   -static int modbus_connect_tcp(modbus_param_t *mb_param)
  1859 +/* Establishes a modbus TCP connection with a Modbus server. */
  1860 +static int modbus_connect_tcp(modbus_t *ctx)
1859 1861 {
1860 1862 int rc;
1861 1863 int option;
1862 1864 struct sockaddr_in addr;
  1865 + modbus_tcp_t *ctx_tcp = ctx->com;
1863 1866  
1864   - mb_param->fd = socket(PF_INET, SOCK_STREAM, 0);
1865   - if (mb_param->fd == -1) {
  1867 + ctx->s = socket(PF_INET, SOCK_STREAM, 0);
  1868 + if (ctx->s == -1) {
1866 1869 return -1;
1867 1870 }
1868 1871  
1869 1872 /* Set the TCP no delay flag */
1870 1873 /* SOL_TCP = IPPROTO_TCP */
1871 1874 option = 1;
1872   - rc = setsockopt(mb_param->fd, IPPROTO_TCP, TCP_NODELAY,
  1875 + rc = setsockopt(ctx->s, IPPROTO_TCP, TCP_NODELAY,
1873 1876 (const void *)&option, sizeof(int));
1874 1877 if (rc == -1) {
1875   - close(mb_param->fd);
  1878 + close(ctx->s);
1876 1879 return -1;
1877 1880 }
1878 1881  
... ... @@ -1883,152 +1886,181 @@ static int modbus_connect_tcp(modbus_param_t *mb_param)
1883 1886 **/
1884 1887 /* Set the IP low delay option */
1885 1888 option = IPTOS_LOWDELAY;
1886   - rc = setsockopt(mb_param->fd, IPPROTO_IP, IP_TOS,
  1889 + rc = setsockopt(ctx->s, IPPROTO_IP, IP_TOS,
1887 1890 (const void *)&option, sizeof(int));
1888 1891 if (rc == -1) {
1889   - close(mb_param->fd);
  1892 + close(ctx->s);
1890 1893 return -1;
1891 1894 }
1892 1895 #endif
1893 1896  
1894   - if (mb_param->debug) {
1895   - printf("Connecting to %s\n", mb_param->ip);
  1897 + if (ctx->debug) {
  1898 + printf("Connecting to %s\n", ctx_tcp->ip);
1896 1899 }
1897 1900  
1898 1901 addr.sin_family = AF_INET;
1899   - addr.sin_port = htons(mb_param->port);
1900   - addr.sin_addr.s_addr = inet_addr(mb_param->ip);
1901   - rc = connect(mb_param->fd, (struct sockaddr *)&addr,
  1902 + addr.sin_port = htons(ctx_tcp->port);
  1903 + addr.sin_addr.s_addr = inet_addr(ctx_tcp->ip);
  1904 + rc = connect(ctx->s, (struct sockaddr *)&addr,
1902 1905 sizeof(struct sockaddr_in));
1903 1906 if (rc == -1) {
1904   - close(mb_param->fd);
  1907 + close(ctx->s);
1905 1908 return -1;
1906 1909 }
1907 1910  
1908 1911 return 0;
1909 1912 }
1910 1913  
1911   -/* Establishes a modbus connexion.
  1914 +/* Establishes a modbus connection.
1912 1915 Returns 0 on success or -1 on failure. */
1913   -int modbus_connect(modbus_param_t *mb_param)
  1916 +int modbus_connect(modbus_t *ctx)
1914 1917 {
1915 1918 int rc;
1916 1919  
1917   - if (mb_param->type_com == RTU)
1918   - rc = modbus_connect_rtu(mb_param);
  1920 + if (ctx->type_com == RTU)
  1921 + rc = modbus_connect_rtu(ctx);
1919 1922 else
1920   - rc = modbus_connect_tcp(mb_param);
  1923 + rc = modbus_connect_tcp(ctx);
1921 1924  
1922 1925 return rc;
1923 1926 }
1924 1927  
1925 1928 /* Closes the file descriptor in RTU mode */
1926   -static void modbus_close_rtu(modbus_param_t *mb_param)
  1929 +static void modbus_close_rtu(modbus_t *ctx)
1927 1930 {
1928   - tcsetattr(mb_param->fd, TCSANOW, &(mb_param->old_tios));
1929   - close(mb_param->fd);
  1931 + modbus_rtu_t *ctx_rtu = ctx->com;
  1932 +
  1933 + tcsetattr(ctx->s, TCSANOW, &(ctx_rtu->old_tios));
  1934 + close(ctx->s);
1930 1935 }
1931 1936  
1932 1937 /* Closes the network connection and socket in TCP mode */
1933   -static void modbus_close_tcp(modbus_param_t *mb_param)
  1938 +static void modbus_close_tcp(modbus_t *ctx)
1934 1939 {
1935   - shutdown(mb_param->fd, SHUT_RDWR);
1936   - close(mb_param->fd);
  1940 + shutdown(ctx->s, SHUT_RDWR);
  1941 + close(ctx->s);
1937 1942 }
1938 1943  
1939   -/* Closes a modbus connection */
1940   -void modbus_close(modbus_param_t *mb_param)
  1944 +/* Closes a connection */
  1945 +void modbus_close(modbus_t *ctx)
1941 1946 {
1942   - if (mb_param->type_com == RTU)
1943   - modbus_close_rtu(mb_param);
  1947 + if (ctx == NULL)
  1948 + return;
  1949 +
  1950 + if (ctx->type_com == RTU)
  1951 + modbus_close_rtu(ctx);
1944 1952 else
1945   - modbus_close_tcp(mb_param);
  1953 + modbus_close_tcp(ctx);
  1954 +}
  1955 +
  1956 +/* Free an initialized modbus_t */
  1957 +void modbus_free(modbus_t *ctx)
  1958 +{
  1959 + if (ctx == NULL)
  1960 + return;
  1961 +
  1962 + free(ctx->com);
  1963 + free(ctx);
1946 1964 }
1947 1965  
1948 1966 /* Activates the debug messages */
1949   -void modbus_set_debug(modbus_param_t *mb_param, int boolean)
  1967 +void modbus_set_debug(modbus_t *ctx, int boolean)
1950 1968 {
1951   - mb_param->debug = boolean;
  1969 + ctx->debug = boolean;
1952 1970 }
1953 1971  
1954   -/* Allocates 4 arrays to store coils, input status, input registers and
1955   - holding registers. The pointers are stored in modbus_mapping structure.
  1972 +/* Allocates 4 arrays to store bits, input bits, registers and inputs
  1973 + registers. The pointers are stored in modbus_mapping structure.
1956 1974  
1957   - The modbus_mapping_new() function shall return 0 if successful. Otherwise it
1958   - shall return -1 and set errno to ENOMEM.
1959   -*/
1960   -int modbus_mapping_new(modbus_mapping_t *mb_mapping,
1961   - int nb_coil_status, int nb_input_status,
1962   - int nb_holding_registers, int nb_input_registers)
  1975 + The modbus_mapping_new() function shall return the new allocated structure if
  1976 + successful. Otherwise it shall return NULL and set errno to ENOMEM. */
  1977 +modbus_mapping_t* modbus_mapping_new(int nb_bits, int nb_input_bits,
  1978 + int nb_registers, int nb_input_registers)
1963 1979 {
  1980 + modbus_mapping_t *mb_mapping;
  1981 +
  1982 + mb_mapping = (modbus_mapping_t *)malloc(sizeof(modbus_mapping_t));
  1983 + if (mb_mapping == NULL) {
  1984 + return NULL;
  1985 + }
  1986 +
1964 1987 /* 0X */
1965   - mb_mapping->nb_coil_status = nb_coil_status;
1966   - mb_mapping->tab_coil_status =
1967   - (uint8_t *) malloc(nb_coil_status * sizeof(uint8_t));
1968   - if (mb_mapping->tab_coil_status == NULL) {
1969   - errno = ENOMEM;
1970   - return -1;
  1988 + mb_mapping->nb_bits = nb_bits;
  1989 + mb_mapping->tab_bits =
  1990 + (uint8_t *) malloc(nb_bits * sizeof(uint8_t));
  1991 + if (mb_mapping->tab_bits == NULL) {
  1992 + free(mb_mapping);
  1993 + return NULL;
1971 1994 }
1972   - memset(mb_mapping->tab_coil_status, 0,
1973   - nb_coil_status * sizeof(uint8_t));
  1995 + memset(mb_mapping->tab_bits, 0,
  1996 + nb_bits * sizeof(uint8_t));
1974 1997  
1975 1998 /* 1X */
1976   - mb_mapping->nb_input_status = nb_input_status;
1977   - mb_mapping->tab_input_status =
1978   - (uint8_t *) malloc(nb_input_status * sizeof(uint8_t));
1979   - if (mb_mapping->tab_input_status == NULL) {
1980   - free(mb_mapping->tab_coil_status);
1981   - errno = ENOMEM;
1982   - return -1;
  1999 + mb_mapping->nb_input_bits = nb_input_bits;
  2000 + mb_mapping->tab_input_bits =
  2001 + (uint8_t *) malloc(nb_input_bits * sizeof(uint8_t));
  2002 + if (mb_mapping->tab_input_bits == NULL) {
  2003 + free(mb_mapping);
  2004 + free(mb_mapping->tab_bits);
  2005 + return NULL;
1983 2006 }
1984   - memset(mb_mapping->tab_input_status, 0,
1985   - nb_input_status * sizeof(uint8_t));
  2007 + memset(mb_mapping->tab_input_bits, 0,
  2008 + nb_input_bits * sizeof(uint8_t));
1986 2009  
1987 2010 /* 4X */
1988   - mb_mapping->nb_holding_registers = nb_holding_registers;
1989   - mb_mapping->tab_holding_registers =
1990   - (uint16_t *) malloc(nb_holding_registers * sizeof(uint16_t));
1991   - if (mb_mapping->tab_holding_registers == NULL) {
1992   - free(mb_mapping->tab_coil_status);
1993   - free(mb_mapping->tab_input_status);
1994   - errno = ENOMEM;
1995   - return -1;
1996   - }
1997   - memset(mb_mapping->tab_holding_registers, 0,
1998   - nb_holding_registers * sizeof(uint16_t));
  2011 + mb_mapping->nb_registers = nb_registers;
  2012 + mb_mapping->tab_registers =
  2013 + (uint16_t *) malloc(nb_registers * sizeof(uint16_t));
  2014 + if (mb_mapping->tab_registers == NULL) {
  2015 + free(mb_mapping);
  2016 + free(mb_mapping->tab_bits);
  2017 + free(mb_mapping->tab_input_bits);
  2018 + return NULL;
  2019 + }
  2020 + memset(mb_mapping->tab_registers, 0,
  2021 + nb_registers * sizeof(uint16_t));
1999 2022  
2000 2023 /* 3X */
2001 2024 mb_mapping->nb_input_registers = nb_input_registers;
2002 2025 mb_mapping->tab_input_registers =
2003 2026 (uint16_t *) malloc(nb_input_registers * sizeof(uint16_t));
2004 2027 if (mb_mapping->tab_input_registers == NULL) {
2005   - free(mb_mapping->tab_coil_status);
2006   - free(mb_mapping->tab_input_status);
2007   - free(mb_mapping->tab_holding_registers);
2008   - errno = ENOMEM;
2009   - return -1;
  2028 + free(mb_mapping);
  2029 + free(mb_mapping->tab_bits);
  2030 + free(mb_mapping->tab_input_bits);
  2031 + free(mb_mapping->tab_registers);
  2032 + return NULL;
2010 2033 }
2011 2034 memset(mb_mapping->tab_input_registers, 0,
2012 2035 nb_input_registers * sizeof(uint16_t));
2013 2036  
2014   - return 0;
  2037 + return mb_mapping;
2015 2038 }
2016 2039  
2017 2040 /* Frees the 4 arrays */
2018 2041 void modbus_mapping_free(modbus_mapping_t *mb_mapping)
2019 2042 {
2020   - free(mb_mapping->tab_coil_status);
2021   - free(mb_mapping->tab_input_status);
2022   - free(mb_mapping->tab_holding_registers);
  2043 + free(mb_mapping->tab_bits);
  2044 + free(mb_mapping->tab_input_bits);
  2045 + free(mb_mapping->tab_registers);
2023 2046 free(mb_mapping->tab_input_registers);
  2047 + free(mb_mapping);
2024 2048 }
2025 2049  
2026   -/* Listens for any query from one or many modbus masters in TCP */
2027   -int modbus_slave_listen_tcp(modbus_param_t *mb_param, int nb_connection)
  2050 +/* Listens for any request from one or many modbus masters in TCP */
  2051 +int modbus_listen(modbus_t *ctx, int nb_connection)
2028 2052 {
2029 2053 int new_socket;
2030 2054 int yes;
2031 2055 struct sockaddr_in addr;
  2056 + modbus_tcp_t *ctx_tcp = ctx->com;
  2057 +
  2058 + if (ctx->type_com != TCP) {
  2059 + if (ctx->debug)
  2060 + fprintf(stderr, "Not implemented");
  2061 + errno = EINVAL;
  2062 + return -1;
  2063 + }
2032 2064  
2033 2065 new_socket = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
2034 2066 if (new_socket == -1) {
... ... @@ -2045,7 +2077,7 @@ int modbus_slave_listen_tcp(modbus_param_t *mb_param, int nb_connection)
2045 2077 memset(&addr, 0, sizeof(addr));
2046 2078 addr.sin_family = AF_INET;
2047 2079 /* If the modbus port is < to 1024, we need the setuid root. */
2048   - addr.sin_port = htons(mb_param->port);
  2080 + addr.sin_port = htons(ctx_tcp->port);
2049 2081 addr.sin_addr.s_addr = INADDR_ANY;
2050 2082 if (bind(new_socket, (struct sockaddr *)&addr, sizeof(addr)) == -1) {
2051 2083 close(new_socket);
... ... @@ -2063,39 +2095,38 @@ int modbus_slave_listen_tcp(modbus_param_t *mb_param, int nb_connection)
2063 2095 /* On success, the function return a non-negative integer that is a descriptor
2064 2096 for the accepted socket. On error, -1 is returned, and errno is set
2065 2097 appropriately. */
2066   -int modbus_slave_accept_tcp(modbus_param_t *mb_param, int *socket)
  2098 +int modbus_accept(modbus_t *ctx, int *socket)
2067 2099 {
2068 2100 struct sockaddr_in addr;
2069 2101 socklen_t addrlen;
2070 2102  
  2103 + if (ctx->type_com != TCP) {
  2104 + if (ctx->debug)
  2105 + fprintf(stderr, "Not implemented");
  2106 + errno = EINVAL;
  2107 + return -1;
  2108 + }
  2109 +
2071 2110 addrlen = sizeof(struct sockaddr_in);
2072   - mb_param->fd = accept(*socket, (struct sockaddr *)&addr, &addrlen);
2073   - if (mb_param->fd == -1) {
  2111 + ctx->s = accept(*socket, (struct sockaddr *)&addr, &addrlen);
  2112 + if (ctx->s == -1) {
2074 2113 close(*socket);
2075 2114 *socket = 0;
2076 2115 return -1;
2077 2116 }
2078 2117  
2079   - if (mb_param->debug) {
2080   - printf("The client %s is connected\n",
2081   - inet_ntoa(addr.sin_addr));
  2118 + if (ctx->debug) {
  2119 + printf("The client %s is connected\n", inet_ntoa(addr.sin_addr));
2082 2120 }
2083 2121  
2084   - return mb_param->fd;
2085   -}
2086   -
2087   -/* Closes a TCP socket */
2088   -void modbus_slave_close_tcp(int socket)
2089   -{
2090   - shutdown(socket, SHUT_RDWR);
2091   - close(socket);
  2122 + return ctx->s;
2092 2123 }
2093 2124  
2094 2125 /** Utils **/
2095 2126  
2096   -/* Sets many input/coil status from a single byte value (all 8 bits of
2097   - the byte value are set) */
2098   -void set_bits_from_byte(uint8_t *dest, int address, const uint8_t value)
  2127 +/* Sets many bits from a single byte value (all 8 bits of the byte value are
  2128 + set) */
  2129 +void modbus_set_bits_from_byte(uint8_t *dest, int address, const uint8_t value)
2099 2130 {
2100 2131 int i;
2101 2132  
... ... @@ -2104,10 +2135,10 @@ void set_bits_from_byte(uint8_t *dest, int address, const uint8_t value)
2104 2135 }
2105 2136 }
2106 2137  
2107   -/* Sets many input/coil status from a table of bytes (only the bits
2108   - between address and address + nb_bits are set) */
2109   -void set_bits_from_bytes(uint8_t *dest, int address, unsigned int nb_bits,
2110   - const uint8_t tab_byte[])
  2138 +/* Sets many bits from a table of bytes (only the bits between address and
  2139 + address + nb_bits are set) */
  2140 +void modbus_set_bits_from_bytes(uint8_t *dest, int address, unsigned int nb_bits,
  2141 + const uint8_t tab_byte[])
2111 2142 {
2112 2143 int i;
2113 2144 int shift = 0;
... ... @@ -2120,9 +2151,9 @@ void set_bits_from_bytes(uint8_t *dest, int address, unsigned int nb_bits,
2120 2151 }
2121 2152 }
2122 2153  
2123   -/* Gets the byte value from many input/coil status.
  2154 +/* Gets the byte value from many bits.
2124 2155 To obtain a full byte, set nb_bits to 8. */
2125   -uint8_t get_byte_from_bits(const uint8_t *src, int address, unsigned int nb_bits)
  2156 +uint8_t modbus_get_byte_from_bits(const uint8_t *src, int address, unsigned int nb_bits)
2126 2157 {
2127 2158 int i;
2128 2159 uint8_t value = 0;
... ... @@ -2139,8 +2170,8 @@ uint8_t get_byte_from_bits(const uint8_t *src, int address, unsigned int nb_bits
2139 2170 return value;
2140 2171 }
2141 2172  
2142   -/* Read a float from 4 bytes in Modbus format */
2143   -float modbus_read_float(const uint16_t *src)
  2173 +/* Get a float from 4 bytes in Modbus format */
  2174 +float modbus_get_float(const uint16_t *src)
2144 2175 {
2145 2176 float r = 0.0f;
2146 2177 uint32_t i;
... ... @@ -2150,8 +2181,8 @@ float modbus_read_float(const uint16_t *src)
2150 2181 return r;
2151 2182 }
2152 2183  
2153   -/* Write a float to 4 bytes in Modbus format */
2154   -void modbus_write_float(float real, uint16_t *dest)
  2184 +/* Set a float to 4 bytes in Modbus format */
  2185 +void modbus_set_float(float real, uint16_t *dest)
2155 2186 {
2156 2187 uint32_t i = 0;
2157 2188  
... ...
src/modbus.h.in
... ... @@ -33,63 +33,15 @@
33 33 #include <netinet/tcp.h>
34 34 #include <arpa/inet.h>
35 35  
36   -#ifdef __cplusplus
37   -extern "C" {
  36 +#ifdef __cplusplus
  37 +# define MODBUS_BEGIN_DECLS extern "C" {
  38 +# define MODBUS_END_DECLS }
  39 +#else
  40 +# define MODBUS_BEGIN_DECLS
  41 +# define MODBUS_END_DECLS
38 42 #endif
39 43  
40   -#define MODBUS_TCP_DEFAULT_PORT 502
41   -#define MODBUS_BROADCAST_ADDRESS 0
42   -#define MODBUS_TCP_SLAVE 0xFF
43   -
44   -/* Slave index */
45   -#define HEADER_LENGTH_RTU 1
46   -#define PRESET_QUERY_LENGTH_RTU 6
47   -#define PRESET_RESPONSE_LENGTH_RTU 2
48   -
49   -#define HEADER_LENGTH_TCP 7
50   -#define PRESET_QUERY_LENGTH_TCP 12
51   -#define PRESET_RESPONSE_LENGTH_TCP 8
52   -
53   -#define CHECKSUM_LENGTH_RTU 2
54   -#define CHECKSUM_LENGTH_TCP 0
55   -
56   -/* It's not really the minimal length (the real one is report slave ID
57   - * in RTU (4 bytes)) but it's a convenient size to use in RTU or TCP
58   - * communications to read many values or write a single one.
59   - * Maximum between :
60   - * - HEADER_LENGTH_TCP (7) + function (1) + address (2) + number (2)
61   - * - HEADER_LENGTH_RTU (1) + function (1) + address (2) + number (2) + CRC (2)
62   - */
63   -#define MIN_QUERY_LENGTH 12
64   -
65   -/* Modbus_Application_Protocol_V1_1b.pdf Chapter 4 Section 1 Page 5:
66   - * - RS232 / RS485 ADU = 253 bytes + slave (1 byte) + CRC (2 bytes) = 256 bytes
67   - * - TCP MODBUS ADU = 253 bytes + MBAP (7 bytes) = 260 bytes
68   - */
69   -#define MAX_PDU_LENGTH 253
70   -#define MAX_ADU_LENGTH_RTU 256
71   -#define MAX_ADU_LENGTH_TCP 260
72   -
73   -/* Kept for compatibility reasons (deprecated) */
74   -#define MAX_MESSAGE_LENGTH 260
75   -
76   -#define EXCEPTION_RESPONSE_LENGTH_RTU 5
77   -
78   -/* Modbus_Application_Protocol_V1_1b.pdf (chapter 6 section 1 page 12)
79   - * Quantity of Coils (2 bytes): 1 to 2000 (0x7D0)
80   - */
81   -#define MAX_STATUS 2000
82   -
83   -/* Modbus_Application_Protocol_V1_1b.pdf (chapter 6 section 3 page 15)
84   - * Quantity of Registers (2 bytes): 1 to 125 (0x7D)
85   - */
86   -#define MAX_REGISTERS 125
87   -
88   -#define REPORT_SLAVE_ID_LENGTH 75
89   -
90   -/* Time out between trames in microsecond */
91   -#define TIME_OUT_BEGIN_OF_TRAME 500000
92   -#define TIME_OUT_END_OF_TRAME 500000
  44 +MODBUS_BEGIN_DECLS
93 45  
94 46 #ifndef FALSE
95 47 #define FALSE 0
... ... @@ -107,23 +59,32 @@ extern &quot;C&quot; {
107 59 #define ON 1
108 60 #endif
109 61  
110   -/* Function codes */
111   -#define FC_READ_COIL_STATUS 0x01 /* discretes inputs */
112   -#define FC_READ_INPUT_STATUS 0x02 /* discretes outputs */
113   -#define FC_READ_HOLDING_REGISTERS 0x03
114   -#define FC_READ_INPUT_REGISTERS 0x04
115   -#define FC_FORCE_SINGLE_COIL 0x05
116   -#define FC_PRESET_SINGLE_REGISTER 0x06
117   -#define FC_READ_EXCEPTION_STATUS 0x07
118   -#define FC_FORCE_MULTIPLE_COILS 0x0F
119   -#define FC_PRESET_MULTIPLE_REGISTERS 0x10
120   -#define FC_REPORT_SLAVE_ID 0x11
  62 +#define MODBUS_TCP_DEFAULT_PORT 502
  63 +#define MODBUS_BROADCAST_ADDRESS 0
  64 +#define MODBUS_TCP_SLAVE 0xFF
  65 +
  66 +/* Modbus_Application_Protocol_V1_1b.pdf Chapter 4 Section 1 Page 5:
  67 + * - RS232 / RS485 ADU = 253 bytes + slave (1 byte) + CRC (2 bytes) = 256 bytes
  68 + * - TCP MODBUS ADU = 253 bytes + MBAP (7 bytes) = 260 bytes
  69 + */
  70 +#define MODBUS_MAX_ADU_LENGTH_RTU 256
  71 +#define MODBUS_MAX_ADU_LENGTH_TCP 260
  72 +
  73 +/* Modbus_Application_Protocol_V1_1b.pdf (chapter 6 section 1 page 12)
  74 + * Quantity of Coils (2 bytes): 1 to 2000 (0x7D0)
  75 + */
  76 +#define MODBUS_MAX_BITS 2000
  77 +
  78 +/* Modbus_Application_Protocol_V1_1b.pdf (chapter 6 section 3 page 15)
  79 + * Quantity of Registers (2 bytes): 1 to 125 (0x7D)
  80 + */
  81 +#define MODBUS_MAX_REGISTERS 125
121 82  
122 83 /* Random number to avoid errno conflicts */
123 84 #define MODBUS_ENOBASE 112345678
124 85  
125 86 /* Protocol exceptions */
126   -typedef enum {
  87 +enum {
127 88 MODBUS_EXCEPTION_ILLEGAL_FUNCTION = 0x01,
128 89 MODBUS_EXCEPTION_ILLEGAL_DATA_ADDRESS,
129 90 MODBUS_EXCEPTION_ILLEGAL_DATA_VALUE,
... ... @@ -136,7 +97,7 @@ typedef enum {
136 97 MODBUS_EXCEPTION_GATEWAY_PATH,
137 98 MODBUS_EXCEPTION_GATEWAY_TARGET,
138 99 MODBUS_EXCEPTION_MAX
139   -} modbus_exception_t;
  100 +};
140 101  
141 102 #define EMBXILFUN (MODBUS_ENOBASE + MODBUS_EXCEPTION_ILLEGAL_FUNCTION)
142 103 #define EMBXILADD (MODBUS_ENOBASE + MODBUS_EXCEPTION_ILLEGAL_DATA_ADDRESS)
... ... @@ -156,33 +117,28 @@ typedef enum {
156 117 #define EMBUNKEXC (EMBXGTAR + 4)
157 118 #define EMBMDATA (EMBXGTAR + 5)
158 119  
159   -/* Internal use */
160   -#define MSG_LENGTH_UNDEFINED -1
161   -
162   -/* The major version of libmb, (1, if %LIBMODBUS_VERSION is 1.2.3) */
  120 +/* The major version, (1, if %LIBMODBUS_VERSION is 1.2.3) */
163 121 #define LIBMODBUS_VERSION_MAJOR (@LIBMODBUS_VERSION_MAJOR@)
164 122  
165   -/* The minor version of libmb (2, if %LIBMODBUS_VERSION is 1.2.3) */
  123 +/* The minor version (2, if %LIBMODBUS_VERSION is 1.2.3) */
166 124 #define LIBMODBUS_VERSION_MINOR (@LIBMODBUS_VERSION_MINOR@)
167 125  
168   -/* The micro version of libmb (3, if %LIBMODBUS_VERSION is 1.2.3) */
  126 +/* The micro version (3, if %LIBMODBUS_VERSION is 1.2.3) */
169 127 #define LIBMODBUS_VERSION_MICRO (@LIBMODBUS_VERSION_MICRO@)
170 128  
171   -/* The full version of libmb, like 1.2.3 */
  129 +/* The full version, like 1.2.3 */
172 130 #define LIBMODBUS_VERSION @LIBMODBUS_VERSION@
173 131  
174   -/* The full version of libmb, in string form (suited for
175   - * string concatenation)
  132 +/* The full version, in string form (suited for string concatenation)
176 133 */
177 134 #define LIBMODBUS_VERSION_STRING "@LIBMODBUS_VERSION@"
178 135  
179   -/* Numerically encoded version libmb, like 0x010203 */
  136 +/* Numerically encoded version, like 0x010203 */
180 137 #define LIBMODBUS_VERSION_HEX ((LIBMODBUS_MAJOR_VERSION << 24) | \
181 138 (LIBMODBUS_MINOR_VERSION << 16) | \
182 139 (LIBMODBUS_MICRO_VERSION << 8))
183 140  
184   -/* Evaluates to True if the version of libmb is greater than @major, @minor and
185   - * @micro
  141 +/* Evaluates to True if the version is greater than @major, @minor and @micro
186 142 */
187 143 #define LIBMODBUS_VERSION_CHECK(major,minor,micro) \
188 144 (LIBMODBUS_VERSION_MAJOR > (major) || \
... ... @@ -196,123 +152,77 @@ extern const unsigned int libmodbus_version_major;
196 152 extern const unsigned int libmodbus_version_minor;
197 153 extern const unsigned int libmodbus_version_micro;
198 154  
199   -typedef enum { RTU=0, TCP } type_com_t;
  155 +typedef struct _modbus modbus_t;
200 156  
201   -/* This structure is byte-aligned */
202 157 typedef struct {
203   - /* Slave address */
204   - int slave;
205   - /* Descriptor (tty or socket) */
206   - int fd;
207   - /* Communication mode: RTU or TCP */
208   - type_com_t type_com;
209   - /* Flag debug */
210   - int debug;
211   - /* TCP port */
212   - int port;
213   - /* Device: "/dev/ttyS0", "/dev/ttyUSB0" or "/dev/tty.USA19*" on Mac OS X for
214   - KeySpan USB<->Serial adapters this string had to be made bigger on OS X
215   - as the directory+file name was bigger than 19 bytes. Making it 67 bytes
216   - for now, but OS X does support 256 byte file names. May become a problem
217   - in the future. */
218   -#ifdef __APPLE_CC__
219   - char device[64];
220   -#else
221   - char device[16];
222   -#endif
223   - /* Bauds: 9600, 19200, 57600, 115200, etc */
224   - int baud;
225   - /* Data bit */
226   - uint8_t data_bit;
227   - /* Stop bit */
228   - uint8_t stop_bit;
229   - /* Parity: 'N', 'O', 'E' */
230   - char parity;
231   - /* In error_treat with TCP, do a reconnect or just dump the error */
232   - uint8_t error_recovery;
233   - /* IP address */
234   - char ip[16];
235   - /* Save old termios settings */
236   - struct termios old_tios;
237   - struct timeval timeout_begin;
238   - struct timeval timeout_end;
239   -} modbus_param_t;
240   -
241   -typedef struct {
242   - int nb_coil_status;
243   - int nb_input_status;
  158 + int nb_bits;
  159 + int nb_input_bits;
244 160 int nb_input_registers;
245   - int nb_holding_registers;
246   - uint8_t *tab_coil_status;
247   - uint8_t *tab_input_status;
  161 + int nb_registers;
  162 + uint8_t *tab_bits;
  163 + uint8_t *tab_input_bits;
248 164 uint16_t *tab_input_registers;
249   - uint16_t *tab_holding_registers;
  165 + uint16_t *tab_registers;
250 166 } modbus_mapping_t;
251 167  
252   -int modbus_init_rtu(modbus_param_t *mb_param, const char *device,
253   - int baud, char parity, int data_bit,
254   - int stop_bit, int slave);
255   -int modbus_init_tcp(modbus_param_t *mb_param, const char *ip_address, int port);
256   -int modbus_set_slave(modbus_param_t *mb_param, int slave);
257   -int modbus_set_error_recovery(modbus_param_t *mb_param, int enabled);
  168 +modbus_t* modbus_new_rtu(const char *device, int baud, char parity, int data_bit,
  169 + int stop_bit, int slave);
  170 +int modbus_set_slave(modbus_t* ctx, int slave);
  171 +
  172 +modbus_t* modbus_new_tcp(const char *ip_address, int port);
  173 +
  174 +int modbus_set_error_recovery(modbus_t *ctx, int enabled);
258 175  
259   -void modbus_get_timeout_begin(modbus_param_t *mb_param, struct timeval *timeout);
260   -void modbus_set_timeout_begin(modbus_param_t *mb_param, const struct timeval *timeout);
  176 +void modbus_get_timeout_begin(modbus_t *ctx, struct timeval *timeout);
  177 +void modbus_set_timeout_begin(modbus_t *ctx, const struct timeval *timeout);
261 178  
262   -void modbus_get_timeout_end(modbus_param_t *mb_param, struct timeval *timeout);
263   -void modbus_set_timeout_end(modbus_param_t *mb_param, const struct timeval *timeout);
  179 +void modbus_get_timeout_end(modbus_t *ctx, struct timeval *timeout);
  180 +void modbus_set_timeout_end(modbus_t *ctx, const struct timeval *timeout);
264 181  
265   -int modbus_connect(modbus_param_t *mb_param);
266   -void modbus_close(modbus_param_t *mb_param);
  182 +int modbus_connect(modbus_t *ctx);
  183 +void modbus_close(modbus_t *ctx);
267 184  
268   -int modbus_flush(modbus_param_t *mb_param);
269   -void modbus_set_debug(modbus_param_t *mb_param, int boolean);
  185 +void modbus_free(modbus_t *ctx);
  186 +
  187 +int modbus_flush(modbus_t *ctx);
  188 +void modbus_set_debug(modbus_t *ctx, int boolean);
270 189  
271 190 const char *modbus_strerror(int errnum);
272 191  
273   -int read_coil_status(modbus_param_t *mb_param, int slave, int start_addr,
274   - int nb, uint8_t *dest);
275   -int read_input_status(modbus_param_t *mb_param, int slave, int start_addr,
276   - int nb, uint8_t *dest);
277   -int read_holding_registers(modbus_param_t *mb_param, int slave, int start_addr,
278   - int nb, uint16_t *dest);
279   -int read_input_registers(modbus_param_t *mb_param, int slave, int start_addr,
280   - int nb, uint16_t *dest);
281   -int force_single_coil(modbus_param_t *mb_param, int slave, int coil_addr,
282   - int state);
283   -int preset_single_register(modbus_param_t *mb_param, int slave, int reg_addr,
284   - int value);
285   -int force_multiple_coils(modbus_param_t *mb_param, int slave, int start_addr,
286   - int nb, const uint8_t *data);
287   -int preset_multiple_registers(modbus_param_t *mb_param, int slave, int start_addr,
288   - int nb, const uint16_t *data);
289   -int report_slave_id(modbus_param_t *mb_param, int slave, uint8_t *dest);
290   -
291   -int modbus_mapping_new(modbus_mapping_t *mb_mapping,
292   - int nb_coil_status, int nb_input_status,
293   - int nb_holding_registers, int nb_input_registers);
  192 +int modbus_read_bits(modbus_t *ctx, int addr, int nb, uint8_t *dest);
  193 +int modbus_read_input_bits(modbus_t *ctx, int addr, int nb, uint8_t *dest);
  194 +int modbus_read_registers(modbus_t *ctx, int addr, int nb, uint16_t *dest);
  195 +int modbus_read_input_registers(modbus_t *ctx, int addr, int nb, uint16_t *dest);
  196 +int modbus_write_bit(modbus_t *ctx, int coil_addr, int state);
  197 +int modbus_write_register(modbus_t *ctx, int reg_addr, int value);
  198 +int modbus_write_bits(modbus_t *ctx, int addr, int nb, const uint8_t *data);
  199 +int modbus_write_registers(modbus_t *ctx, int addr, int nb, const uint16_t *data);
  200 +int modbus_report_slave_id(modbus_t *ctx, uint8_t *dest);
  201 +
  202 +modbus_mapping_t* modbus_mapping_new(int nb_coil_status, int nb_input_status,
  203 + int nb_holding_registers, int nb_input_registers);
294 204 void modbus_mapping_free(modbus_mapping_t *mb_mapping);
295 205  
296   -int modbus_slave_listen_tcp(modbus_param_t *mb_param, int nb_connection);
297   -int modbus_slave_accept_tcp(modbus_param_t *mb_param, int *socket);
298   -int modbus_slave_receive(modbus_param_t *mb_param, int sockfd, uint8_t *query);
299   -int modbus_slave_manage(modbus_param_t *mb_param, const uint8_t *query,
300   - int query_length, modbus_mapping_t *mb_mapping);
301   -void modbus_slave_close_tcp(int socket);
  206 +int modbus_listen(modbus_t *ctx, int nb_connection);
  207 +int modbus_accept(modbus_t *ctx, int *socket);
  208 +int modbus_receive(modbus_t *ctx, int sockfd, uint8_t *req);
  209 +int modbus_reply(modbus_t *ctx, const uint8_t *req,
  210 + int req_length, modbus_mapping_t *mb_mapping);
302 211  
303 212 /**
304 213 * UTILS FUNCTIONS
305 214 **/
306 215  
307   -void set_bits_from_byte(uint8_t *dest, int address, const uint8_t value);
308   -void set_bits_from_bytes(uint8_t *dest, int address, unsigned int nb_bits,
309   - const uint8_t *tab_byte);
310   -uint8_t get_byte_from_bits(const uint8_t *src, int address, unsigned int nb_bits);
311   -float modbus_read_float(const uint16_t *src);
312   -void modbus_write_float(float real, uint16_t *dest);
  216 +#define MODBUS_GET_HIGH_BYTE(data) ((data >> 8) & 0xFF)
  217 +#define MODBUS_GET_LOW_BYTE(data) (data & 0xFF)
313 218  
314   -#ifdef __cplusplus
315   -}
316   -#endif
  219 +void modbus_set_bits_from_byte(uint8_t *dest, int address, const uint8_t value);
  220 +void modbus_set_bits_from_bytes(uint8_t *dest, int address, unsigned int nb_bits,
  221 + const uint8_t *tab_byte);
  222 +uint8_t modbus_get_byte_from_bits(const uint8_t *src, int address, unsigned int nb_bits);
  223 +float modbus_get_float(const uint16_t *src);
  224 +void modbus_set_float(float real, uint16_t *dest);
  225 +
  226 +MODBUS_END_DECLS
317 227  
318 228 #endif /* _MODBUS_H_ */
... ...
tests/bandwidth-master.c
... ... @@ -26,7 +26,6 @@
26 26 #include <modbus.h>
27 27  
28 28 /* Tests based on PI-MBUS-300 documentation */
29   -#define SERVER_ID 17
30 29 #define NB_LOOPS 100000
31 30  
32 31 #define G_MSEC_PER_SEC 1000
... ... @@ -41,9 +40,9 @@ uint32_t gettime_ms(void)
41 40  
42 41 int main(void)
43 42 {
44   - uint8_t *tab_rp_status;
45   - uint16_t *tab_rp_registers;
46   - modbus_param_t mb_param;
  43 + uint8_t *tab_bit;
  44 + uint16_t *tab_reg;
  45 + modbus_t *ctx;
47 46 int i;
48 47 int nb_points;
49 48 double elapsed;
... ... @@ -54,28 +53,28 @@ int main(void)
54 53 int rc;
55 54  
56 55 /* TCP */
57   - modbus_init_tcp(&mb_param, "127.0.0.1", 1502);
58   - rc = modbus_connect(&mb_param);
59   - if (rc == -1) {
  56 + ctx = modbus_new_tcp("127.0.0.1", 1502);
  57 + if (modbus_connect(ctx) == -1) {
60 58 fprintf(stderr, "Connexion failed: %s\n",
61 59 modbus_strerror(errno));
  60 + modbus_free(ctx);
62 61 return -1;
63 62 }
64 63  
65 64 /* Allocate and initialize the memory to store the status */
66   - tab_rp_status = (uint8_t *) malloc(MAX_STATUS * sizeof(uint8_t));
67   - memset(tab_rp_status, 0, MAX_STATUS * sizeof(uint8_t));
  65 + tab_bit = (uint8_t *) malloc(MODBUS_MAX_BITS * sizeof(uint8_t));
  66 + memset(tab_bit, 0, MODBUS_MAX_BITS * sizeof(uint8_t));
68 67  
69 68 /* Allocate and initialize the memory to store the registers */
70   - tab_rp_registers = (uint16_t *) malloc(MAX_REGISTERS * sizeof(uint16_t));
71   - memset(tab_rp_registers, 0, MAX_REGISTERS * sizeof(uint16_t));
  69 + tab_reg = (uint16_t *) malloc(MODBUS_MAX_REGISTERS * sizeof(uint16_t));
  70 + memset(tab_reg, 0, MODBUS_MAX_REGISTERS * sizeof(uint16_t));
72 71  
73   - printf("READ COIL STATUS\n\n");
  72 + printf("READ BITS\n\n");
74 73  
75   - nb_points = MAX_STATUS;
  74 + nb_points = MODBUS_MAX_BITS;
76 75 start = gettime_ms();
77 76 for (i=0; i<NB_LOOPS; i++) {
78   - rc = read_coil_status(&mb_param, SERVER_ID, 0, nb_points, tab_rp_status);
  77 + rc = modbus_read_bits(ctx, 0, nb_points, tab_bit);
79 78 if (rc == -1) {
80 79 fprintf(stderr, "%s\n", modbus_strerror(errno));
81 80 return -1;
... ... @@ -107,12 +106,12 @@ int main(void)
107 106 printf("* %'d KiB/s\n", rate);
108 107 printf("\n\n");
109 108  
110   - printf("READ HOLDING REGISTERS\n\n");
  109 + printf("READ REGISTERS\n\n");
111 110  
112   - nb_points = MAX_REGISTERS;
  111 + nb_points = MODBUS_MAX_REGISTERS;
113 112 start = gettime_ms();
114 113 for (i=0; i<NB_LOOPS; i++) {
115   - rc = read_holding_registers(&mb_param, SERVER_ID, 0, nb_points, tab_rp_registers);
  114 + rc = modbus_read_registers(ctx, 0, nb_points, tab_reg);
116 115 if (rc == -1) {
117 116 fprintf(stderr, "%s\n", modbus_strerror(errno));
118 117 return -1;
... ... @@ -145,11 +144,12 @@ int main(void)
145 144 printf("\n");
146 145  
147 146 /* Free the memory */
148   - free(tab_rp_status);
149   - free(tab_rp_registers);
  147 + free(tab_bit);
  148 + free(tab_reg);
150 149  
151 150 /* Close the connection */
152   - modbus_close(&mb_param);
  151 + modbus_close(ctx);
  152 + modbus_free(ctx);
153 153  
154 154 return 0;
155 155 }
... ...
tests/bandwidth-slave-many-up.c
... ... @@ -26,13 +26,15 @@
26 26  
27 27 #define NB_CONNECTION 5
28 28  
  29 +modbus_t *ctx = NULL;
29 30 int slave_socket;
30   -modbus_mapping_t mb_mapping;
  31 +modbus_mapping_t *mb_mapping;
31 32  
32 33 static void close_sigint(int dummy)
33 34 {
34   - modbus_slave_close_tcp(slave_socket);
35   - modbus_mapping_free(&mb_mapping);
  35 + close(slave_socket);
  36 + modbus_free(ctx);
  37 + modbus_mapping_free(mb_mapping);
36 38  
37 39 exit(dummy);
38 40 }
... ... @@ -40,7 +42,6 @@ static void close_sigint(int dummy)
40 42 int main(void)
41 43 {
42 44 int master_socket;
43   - modbus_param_t mb_param;
44 45 int rc;
45 46 fd_set refset;
46 47 fd_set rdset;
... ... @@ -48,16 +49,18 @@ int main(void)
48 49 /* Maximum file descriptor number */
49 50 int fdmax;
50 51  
51   - modbus_init_tcp(&mb_param, "127.0.0.1", 1502);
  52 + ctx = modbus_new_tcp("127.0.0.1", 1502);
52 53  
53   - rc = modbus_mapping_new(&mb_mapping, MAX_STATUS, 0, MAX_REGISTERS, 0);
54   - if (rc == -1) {
  54 + mb_mapping = modbus_mapping_new(MODBUS_MAX_BITS, 0,
  55 + MODBUS_MAX_REGISTERS, 0);
  56 + if (mb_mapping == NULL) {
55 57 fprintf(stderr, "Failed to allocate the mapping: %s\n",
56 58 modbus_strerror(errno));
  59 + modbus_free(ctx);
57 60 return -1;
58 61 }
59 62  
60   - slave_socket = modbus_slave_listen_tcp(&mb_param, NB_CONNECTION);
  63 + slave_socket = modbus_listen(ctx, NB_CONNECTION);
61 64  
62 65 signal(SIGINT, close_sigint);
63 66  
... ... @@ -105,15 +108,15 @@ int main(void)
105 108 }
106 109 } else {
107 110 /* An already connected master has sent a new query */
108   - uint8_t query[MAX_MESSAGE_LENGTH];
  111 + uint8_t query[MODBUS_MAX_ADU_LENGTH_TCP];
109 112  
110   - rc = modbus_slave_receive(&mb_param, master_socket, query);
  113 + rc = modbus_receive(ctx, master_socket, query);
111 114 if (rc != -1) {
112   - modbus_slave_manage(&mb_param, query, rc, &mb_mapping);
  115 + modbus_reply(ctx, query, rc, mb_mapping);
113 116 } else {
114 117 /* Connection closed by the client, end of server */
115 118 printf("Connection closed on socket %d\n", master_socket);
116   - modbus_slave_close_tcp(master_socket);
  119 + close(master_socket);
117 120  
118 121 /* Remove from reference set */
119 122 FD_CLR(master_socket, &refset);
... ...
tests/bandwidth-slave-one.c
... ... @@ -26,28 +26,30 @@
26 26 int main(void)
27 27 {
28 28 int socket;
29   - modbus_param_t mb_param;
30   - modbus_mapping_t mb_mapping;
  29 + modbus_t *ctx;
  30 + modbus_mapping_t *mb_mapping;
31 31 int rc;
32 32  
33   - modbus_init_tcp(&mb_param, "127.0.0.1", 1502);
  33 + ctx = modbus_new_tcp("127.0.0.1", 1502);
34 34  
35   - rc = modbus_mapping_new(&mb_mapping, MAX_STATUS, 0, MAX_REGISTERS, 0);
36   - if (rc == -1) {
  35 + mb_mapping = modbus_mapping_new(MODBUS_MAX_BITS, 0,
  36 + MODBUS_MAX_REGISTERS, 0);
  37 + if (mb_mapping == NULL) {
37 38 fprintf(stderr, "Failed to allocate the mapping: %s\n",
38 39 modbus_strerror(errno));
  40 + modbus_free(ctx);
39 41 return -1;
40 42 }
41 43  
42   - socket = modbus_slave_listen_tcp(&mb_param, 1);
43   - modbus_slave_accept_tcp(&mb_param, &socket);
  44 + socket = modbus_listen(ctx, 1);
  45 + modbus_accept(ctx, &socket);
44 46  
45 47 for(;;) {
46   - uint8_t query[MAX_MESSAGE_LENGTH];
  48 + uint8_t query[MODBUS_MAX_ADU_LENGTH_TCP];
47 49  
48   - rc = modbus_slave_receive(&mb_param, -1, query);
  50 + rc = modbus_receive(ctx, -1, query);
49 51 if (rc >= 0) {
50   - modbus_slave_manage(&mb_param, query, rc, &mb_mapping);
  52 + modbus_reply(ctx, query, rc, mb_mapping);
51 53 } else {
52 54 /* Connection closed by the client or server */
53 55 break;
... ... @@ -56,9 +58,9 @@ int main(void)
56 58  
57 59 printf("Quit the loop: %s\n", modbus_strerror(errno));
58 60  
  61 + modbus_mapping_free(mb_mapping);
59 62 close(socket);
60   - modbus_mapping_free(&mb_mapping);
61   - modbus_close(&mb_param);
  63 + modbus_free(ctx);
62 64  
63 65 return 0;
64 66 }
... ...
tests/random-test-master.c
... ... @@ -25,13 +25,13 @@
25 25  
26 26 /* The goal of this program is to check all major functions of
27 27 libmodbus:
28   - - force_single_coil
29   - - read_coil_status
30   - - force_multiple_coils
31   - - preset_single_register
32   - - read_holding_registers
33   - - preset_multiple_registers
34   - - read_holding_registers
  28 + - write_coil
  29 + - read_bits
  30 + - write_coils
  31 + - write_register
  32 + - read_registers
  33 + - write_registers
  34 + - read_registers
35 35  
36 36 All these functions are called with random values on a address
37 37 range defined by the following defines.
... ... @@ -47,38 +47,40 @@
47 47 */
48 48 int main(void)
49 49 {
  50 + modbus_t *ctx;
50 51 int rc;
51 52 int nb_fail;
52 53 int nb_loop;
53 54 int addr;
54 55 int nb;
55   - uint8_t *tab_rq_status;
56   - uint8_t *tab_rp_status;
  56 + uint8_t *tab_rq_bits;
  57 + uint8_t *tab_rp_bits;
57 58 uint16_t *tab_rq_registers;
58 59 uint16_t *tab_rp_registers;
59   - modbus_param_t mb_param;
60 60  
61 61 /*
62   - modbus_init_rtu(&mb_param, "/dev/ttyS0", 19200, 'N', 8, 1, MY_ID);
  62 + ctx = modbus_new_rtu("/dev/ttyS0", 19200, 'N', 8, 1, MY_ID);
  63 + modbus_set_slave(ctx, SERVER_ID);
63 64 */
64 65  
65 66 /* TCP */
66   - modbus_init_tcp(&mb_param, "127.0.0.1", 1502);
67   - modbus_set_debug(&mb_param, TRUE);
68   - if (modbus_connect(&mb_param) == -1) {
  67 + ctx = modbus_new_tcp("127.0.0.1", 1502);
  68 + modbus_set_debug(ctx, TRUE);
  69 + if (modbus_connect(ctx) == -1) {
69 70 fprintf(stderr, "Connection failed: %s\n",
70 71 modbus_strerror(errno));
  72 + modbus_free(ctx);
71 73 return -1;
72 74 }
73 75  
74 76 /* Allocate and initialize the different memory spaces */
75 77 nb = ADDRESS_END - ADDRESS_START;
76 78  
77   - tab_rq_status = (uint8_t *) malloc(nb * sizeof(uint8_t));
78   - memset(tab_rq_status, 0, nb * sizeof(uint8_t));
  79 + tab_rq_bits = (uint8_t *) malloc(nb * sizeof(uint8_t));
  80 + memset(tab_rq_bits, 0, nb * sizeof(uint8_t));
79 81  
80   - tab_rp_status = (uint8_t *) malloc(nb * sizeof(uint8_t));
81   - memset(tab_rp_status, 0, nb * sizeof(uint8_t));
  82 + tab_rp_bits = (uint8_t *) malloc(nb * sizeof(uint8_t));
  83 + memset(tab_rp_bits, 0, nb * sizeof(uint8_t));
82 84  
83 85 tab_rq_registers = (uint16_t *) malloc(nb * sizeof(uint16_t));
84 86 memset(tab_rq_registers, 0, nb * sizeof(uint16_t));
... ... @@ -94,49 +96,44 @@ int main(void)
94 96 /* Random numbers (short) */
95 97 for (i=0; i<nb; i++) {
96 98 tab_rq_registers[i] = (uint16_t) (65535.0*rand() / (RAND_MAX + 1.0));
97   - tab_rq_status[i] = tab_rq_registers[i] % 2;
  99 + tab_rq_bits[i] = tab_rq_registers[i] % 2;
98 100 }
99 101 nb = ADDRESS_END - addr;
100 102  
101   - /* SINGLE COIL */
102   - rc = force_single_coil(&mb_param, SERVER_ID, addr, tab_rq_status[0]);
  103 + /* WRITE BIT */
  104 + rc = modbus_write_bit(ctx, addr, tab_rq_bits[0]);
103 105 if (rc != 1) {
104   - printf("ERROR force_single_coil (%d)\n", rc);
105   - printf("Slave = %d, address = %d, value = %d\n",
106   - SERVER_ID, addr, tab_rq_status[0]);
  106 + printf("ERROR modbus_write_bit (%d)\n", rc);
  107 + printf("Address = %d, value = %d\n", addr, tab_rq_bits[0]);
107 108 nb_fail++;
108 109 } else {
109   - rc = read_coil_status(&mb_param, SERVER_ID, addr, 1, tab_rp_status);
110   - if (rc != 1 || tab_rq_status[0] != tab_rp_status[0]) {
111   - printf("ERROR read_coil_status single (%d)\n", rc);
112   - printf("Slave = %d, address = %d\n",
113   - SERVER_ID, addr);
  110 + rc = modbus_read_bits(ctx, addr, 1, tab_rp_bits);
  111 + if (rc != 1 || tab_rq_bits[0] != tab_rp_bits[0]) {
  112 + printf("ERROR modbus_read_bits single (%d)\n", rc);
  113 + printf("address = %d\n", addr);
114 114 nb_fail++;
115 115 }
116 116 }
117 117  
118   - /* MULTIPLE COILS */
119   - rc = force_multiple_coils(&mb_param, SERVER_ID, addr, nb, tab_rq_status);
  118 + /* MULTIPLE BITS */
  119 + rc = modbus_write_bits(ctx, addr, nb, tab_rq_bits);
120 120 if (rc != nb) {
121   - printf("ERROR force_multiple_coils (%d)\n", rc);
122   - printf("Slave = %d, address = %d, nb = %d\n",
123   - SERVER_ID, addr, nb);
  121 + printf("ERROR modbus_write_bits (%d)\n", rc);
  122 + printf("Address = %d, nb = %d\n", addr, nb);
124 123 nb_fail++;
125 124 } else {
126   - rc = read_coil_status(&mb_param, SERVER_ID, addr, nb, tab_rp_status);
  125 + rc = modbus_read_bits(ctx, addr, nb, tab_rp_bits);
127 126 if (rc != nb) {
128   - printf("ERROR read_coil_status\n");
129   - printf("Slave = %d, address = %d, nb = %d\n",
130   - SERVER_ID, addr, nb);
  127 + printf("ERROR modbus_read_bits\n");
  128 + printf("Address = %d, nb = %d\n", addr, nb);
131 129 nb_fail++;
132 130 } else {
133 131 for (i=0; i<nb; i++) {
134   - if (tab_rp_status[i] != tab_rq_status[i]) {
135   - printf("ERROR read_coil_status\n");
136   - printf("Slave = %d, address = %d, value %d (0x%X) != %d (0x%X)\n",
137   - SERVER_ID, addr,
138   - tab_rq_status[i], tab_rq_status[i],
139   - tab_rp_status[i], tab_rp_status[i]);
  132 + if (tab_rp_bits[i] != tab_rq_bits[i]) {
  133 + printf("ERROR modbus_read_bits\n");
  134 + printf("Address = %d, value %d (0x%X) != %d (0x%X)\n",
  135 + addr, tab_rq_bits[i], tab_rq_bits[i],
  136 + tab_rp_bits[i], tab_rp_bits[i]);
140 137 nb_fail++;
141 138 }
142 139 }
... ... @@ -144,25 +141,23 @@ int main(void)
144 141 }
145 142  
146 143 /* SINGLE REGISTER */
147   - rc = preset_single_register(&mb_param, SERVER_ID, addr, tab_rq_registers[0]);
  144 + rc = modbus_write_register(ctx, addr, tab_rq_registers[0]);
148 145 if (rc != 1) {
149   - printf("ERROR preset_single_register (%d)\n", rc);
150   - printf("Slave = %d, address = %d, value = %d (0x%X)\n",
151   - SERVER_ID, addr, tab_rq_registers[0], tab_rq_registers[0]);
  146 + printf("ERROR modbus_write_register (%d)\n", rc);
  147 + printf("Address = %d, value = %d (0x%X)\n",
  148 + addr, tab_rq_registers[0], tab_rq_registers[0]);
152 149 nb_fail++;
153 150 } else {
154   - rc = read_holding_registers(&mb_param, SERVER_ID, addr, 1, tab_rp_registers);
  151 + rc = modbus_read_registers(ctx, addr, 1, tab_rp_registers);
155 152 if (rc != 1) {
156   - printf("ERROR read_holding_registers single (%d)\n", rc);
157   - printf("Slave = %d, address = %d\n",
158   - SERVER_ID, addr);
  153 + printf("ERROR modbus_read_registers single (%d)\n", rc);
  154 + printf("Address = %d\n", addr);
159 155 nb_fail++;
160 156 } else {
161 157 if (tab_rq_registers[0] != tab_rp_registers[0]) {
162   - printf("ERROR read_holding_registers single\n");
163   - printf("Slave = %d, address = %d, value = %d (0x%X) != %d (0x%X)\n",
164   - SERVER_ID, addr,
165   - tab_rq_registers[0], tab_rq_registers[0],
  158 + printf("ERROR modbus_read_registers single\n");
  159 + printf("Address = %d, value = %d (0x%X) != %d (0x%X)\n",
  160 + addr, tab_rq_registers[0], tab_rq_registers[0],
166 161 tab_rp_registers[0], tab_rp_registers[0]);
167 162 nb_fail++;
168 163 }
... ... @@ -170,28 +165,23 @@ int main(void)
170 165 }
171 166  
172 167 /* MULTIPLE REGISTERS */
173   - rc = preset_multiple_registers(&mb_param, SERVER_ID, addr, nb,
174   - tab_rq_registers);
  168 + rc = modbus_write_registers(ctx, addr, nb, tab_rq_registers);
175 169 if (rc != nb) {
176   - printf("ERROR preset_multiple_registers (%d)\n", rc);
177   - printf("Slave = %d, address = %d, nb = %d\n",
178   - SERVER_ID, addr, nb);
  170 + printf("ERROR modbus_write_registers (%d)\n", rc);
  171 + printf("Address = %d, nb = %d\n", addr, nb);
179 172 nb_fail++;
180 173 } else {
181   - rc = read_holding_registers(&mb_param, SERVER_ID, addr, nb,
182   - tab_rp_registers);
  174 + rc = modbus_read_registers(ctx, addr, nb, tab_rp_registers);
183 175 if (rc != nb) {
184   - printf("ERROR read_holding_registers (%d)\n", rc);
185   - printf("Slave = %d, address = %d, nb = %d\n",
186   - SERVER_ID, addr, nb);
  176 + printf("ERROR modbus_read_registers (%d)\n", rc);
  177 + printf("Address = %d, nb = %d\n", addr, nb);
187 178 nb_fail++;
188 179 } else {
189 180 for (i=0; i<nb; i++) {
190 181 if (tab_rq_registers[i] != tab_rp_registers[i]) {
191   - printf("ERROR read_holding_registers\n");
192   - printf("Slave = %d, address = %d, value %d (0x%X) != %d (0x%X)\n",
193   - SERVER_ID, addr,
194   - tab_rq_registers[i], tab_rq_registers[i],
  182 + printf("ERROR modbus_read_registers\n");
  183 + printf("Address = %d, value %d (0x%X) != %d (0x%X)\n",
  184 + addr, tab_rq_registers[i], tab_rq_registers[i],
195 185 tab_rp_registers[i], tab_rp_registers[i]);
196 186 nb_fail++;
197 187 }
... ... @@ -209,13 +199,14 @@ int main(void)
209 199 }
210 200  
211 201 /* Free the memory */
212   - free(tab_rq_status);
213   - free(tab_rp_status);
  202 + free(tab_rq_bits);
  203 + free(tab_rp_bits);
214 204 free(tab_rq_registers);
215 205 free(tab_rp_registers);
216 206  
217 207 /* Close the connection */
218   - modbus_close(&mb_param);
  208 + modbus_close(ctx);
  209 + modbus_free(ctx);
219 210  
220 211 return 0;
221 212 }
... ...
tests/random-test-slave.c
... ... @@ -25,31 +25,31 @@
25 25 int main(void)
26 26 {
27 27 int socket;
28   - modbus_param_t mb_param;
29   - modbus_mapping_t mb_mapping;
30   - int rc;
  28 + modbus_t *ctx;
  29 + modbus_mapping_t *mb_mapping;
31 30  
32   - modbus_init_tcp(&mb_param, "127.0.0.1", 1502);
33   - /* modbus_set_debug(&mb_param, TRUE); */
  31 + ctx = modbus_new_tcp("127.0.0.1", 1502);
  32 + /* modbus_set_debug(ctx, TRUE); */
34 33  
35   - rc = modbus_mapping_new(&mb_mapping, 500, 500, 500, 500);
36   - if (rc == -1) {
  34 + mb_mapping = modbus_mapping_new(500, 500, 500, 500);
  35 + if (mb_mapping == NULL) {
37 36 fprintf(stderr, "Failed to allocate the mapping: %s\n",
38 37 modbus_strerror(errno));
  38 + modbus_free(ctx);
39 39 return -1;
40 40 }
41 41  
42   - socket = modbus_slave_listen_tcp(&mb_param, 1);
43   - modbus_slave_accept_tcp(&mb_param, &socket);
  42 + socket = modbus_listen(ctx, 1);
  43 + modbus_accept(ctx, &socket);
44 44  
45 45 for (;;) {
46   - uint8_t query[MAX_MESSAGE_LENGTH];
  46 + uint8_t query[MODBUS_MAX_ADU_LENGTH_TCP];
47 47 int rc;
48 48  
49   - rc = modbus_slave_receive(&mb_param, -1, query);
  49 + rc = modbus_receive(ctx, -1, query);
50 50 if (rc != -1) {
51 51 /* rc is the query size */
52   - modbus_slave_manage(&mb_param, query, rc, &mb_mapping);
  52 + modbus_reply(ctx, query, rc, mb_mapping);
53 53 } else {
54 54 /* Connection closed by the client or error */
55 55 break;
... ... @@ -58,9 +58,9 @@ int main(void)
58 58  
59 59 printf("Quit the loop: %s\n", modbus_strerror(errno));
60 60  
61   - close(socket);
62   - modbus_mapping_free(&mb_mapping);
63   - modbus_close(&mb_param);
  61 + modbus_mapping_free(mb_mapping);
  62 + modbus_close(ctx);
  63 + modbus_free(ctx);
64 64  
65 65 return 0;
66 66 }
... ...
tests/unit-test-master.c
... ... @@ -26,10 +26,11 @@
26 26  
27 27 int main(void)
28 28 {
29   - uint8_t *tab_rp_status;
  29 + uint8_t *tab_rp_bits;
30 30 uint16_t *tab_rp_registers;
31 31 uint16_t *tab_rp_registers_bad;
32   - modbus_param_t mb_param;
  32 + modbus_t *ctx;
  33 + int is_mode_rtu = FALSE;
33 34 int i;
34 35 uint8_t value;
35 36 int address;
... ... @@ -40,30 +41,32 @@ int main(void)
40 41 struct timeval timeout_begin_new;
41 42  
42 43 /*
43   - modbus_init_rtu(&mb_param, "/dev/ttyS0", 19200, 'N', 8, 1,
44   - CLIENT_ID);
  44 + ctx = modbus_new_rtu("/dev/ttyS0", 19200, 'N', 8, 1, CLIENT_ID);
  45 + modbus_set_slave(ctx, SERVER_ID);
  46 + is_mode_rtu = TRUE;
45 47 */
46 48  
47 49 /* TCP */
48   - modbus_init_tcp(&mb_param, "127.0.0.1", 1502);
49   - modbus_set_debug(&mb_param, TRUE);
  50 + ctx = modbus_new_tcp("127.0.0.1", 1502);
  51 + modbus_set_debug(ctx, TRUE);
50 52  
51   - if (modbus_connect(&mb_param) == -1) {
  53 + if (modbus_connect(ctx) == -1) {
52 54 fprintf(stderr, "Connection failed: %s\n",
53 55 modbus_strerror(errno));
  56 + modbus_free(ctx);
54 57 return -1;
55 58 }
56 59  
57   - /* Allocate and initialize the memory to store the status */
58   - nb_points = (UT_COIL_STATUS_NB_POINTS > UT_INPUT_STATUS_NB_POINTS) ?
59   - UT_COIL_STATUS_NB_POINTS : UT_INPUT_STATUS_NB_POINTS;
60   - tab_rp_status = (uint8_t *) malloc(nb_points * sizeof(uint8_t));
61   - memset(tab_rp_status, 0, nb_points * sizeof(uint8_t));
  60 + /* Allocate and initialize the memory to store the bits */
  61 + nb_points = (UT_BITS_NB_POINTS > UT_INPUT_BITS_NB_POINTS) ?
  62 + UT_BITS_NB_POINTS : UT_INPUT_BITS_NB_POINTS;
  63 + tab_rp_bits = (uint8_t *) malloc(nb_points * sizeof(uint8_t));
  64 + memset(tab_rp_bits, 0, nb_points * sizeof(uint8_t));
62 65  
63 66 /* Allocate and initialize the memory to store the registers */
64   - nb_points = (UT_HOLDING_REGISTERS_NB_POINTS >
  67 + nb_points = (UT_REGISTERS_NB_POINTS >
65 68 UT_INPUT_REGISTERS_NB_POINTS) ?
66   - UT_HOLDING_REGISTERS_NB_POINTS : UT_INPUT_REGISTERS_NB_POINTS;
  69 + UT_REGISTERS_NB_POINTS : UT_INPUT_REGISTERS_NB_POINTS;
67 70 tab_rp_registers = (uint16_t *) malloc(nb_points * sizeof(uint16_t));
68 71 memset(tab_rp_registers, 0, nb_points * sizeof(uint16_t));
69 72  
... ... @@ -71,11 +74,11 @@ int main(void)
71 74  
72 75 printf("\nTEST WRITE/READ:\n");
73 76  
74   - /** COIL STATUS **/
  77 + /** COIL BITS **/
75 78  
76 79 /* Single */
77   - rc = force_single_coil(&mb_param, SERVER_ID, UT_COIL_STATUS_ADDRESS, ON);
78   - printf("1/2 force_single_coil: ");
  80 + rc = modbus_write_bit(ctx, UT_BITS_ADDRESS, ON);
  81 + printf("1/2 modbus_write_bit: ");
79 82 if (rc == 1) {
80 83 printf("OK\n");
81 84 } else {
... ... @@ -83,33 +86,30 @@ int main(void)
83 86 goto close;
84 87 }
85 88  
86   - rc = read_coil_status(&mb_param, SERVER_ID, UT_COIL_STATUS_ADDRESS, 1,
87   - tab_rp_status);
88   - printf("2/2 read_coil_status: ");
  89 + rc = modbus_read_bits(ctx, UT_BITS_ADDRESS, 1, tab_rp_bits);
  90 + printf("2/2 modbus_read_bits: ");
89 91 if (rc != 1) {
90 92 printf("FAILED (nb points %d)\n", rc);
91 93 goto close;
92 94 }
93 95  
94   - if (tab_rp_status[0] != ON) {
95   - printf("FAILED (%0X = != %0X)\n", tab_rp_status[0], ON);
  96 + if (tab_rp_bits[0] != ON) {
  97 + printf("FAILED (%0X = != %0X)\n", tab_rp_bits[0], ON);
96 98 goto close;
97 99 }
98 100 printf("OK\n");
99 101 /* End single */
100 102  
101   - /* Multiple coils */
  103 + /* Multiple bits */
102 104 {
103   - uint8_t tab_value[UT_COIL_STATUS_NB_POINTS];
104   -
105   - set_bits_from_bytes(tab_value, 0, UT_COIL_STATUS_NB_POINTS,
106   - UT_COIL_STATUS_TAB);
107   - rc = force_multiple_coils(&mb_param, SERVER_ID,
108   - UT_COIL_STATUS_ADDRESS,
109   - UT_COIL_STATUS_NB_POINTS,
110   - tab_value);
111   - printf("1/2 force_multiple_coils: ");
112   - if (rc == UT_COIL_STATUS_NB_POINTS) {
  105 + uint8_t tab_value[UT_BITS_NB_POINTS];
  106 +
  107 + modbus_set_bits_from_bytes(tab_value, 0, UT_BITS_NB_POINTS,
  108 + UT_BITS_TAB);
  109 + rc = modbus_write_bits(ctx, UT_BITS_ADDRESS,
  110 + UT_BITS_NB_POINTS, tab_value);
  111 + printf("1/2 modbus_write_bits: ");
  112 + if (rc == UT_BITS_NB_POINTS) {
113 113 printf("OK\n");
114 114 } else {
115 115 printf("FAILED\n");
... ... @@ -117,24 +117,24 @@ int main(void)
117 117 }
118 118 }
119 119  
120   - rc = read_coil_status(&mb_param, SERVER_ID, UT_COIL_STATUS_ADDRESS,
121   - UT_COIL_STATUS_NB_POINTS, tab_rp_status);
122   - printf("2/2 read_coil_status: ");
123   - if (rc != UT_COIL_STATUS_NB_POINTS) {
  120 + rc = modbus_read_bits(ctx, UT_BITS_ADDRESS,
  121 + UT_BITS_NB_POINTS, tab_rp_bits);
  122 + printf("2/2 modbus_read_bits: ");
  123 + if (rc != UT_BITS_NB_POINTS) {
124 124 printf("FAILED (nb points %d)\n", rc);
125 125 goto close;
126 126 }
127 127  
128 128 i = 0;
129   - address = UT_COIL_STATUS_ADDRESS;
130   - nb_points = UT_COIL_STATUS_NB_POINTS;
  129 + address = UT_BITS_ADDRESS;
  130 + nb_points = UT_BITS_NB_POINTS;
131 131 while (nb_points > 0) {
132 132 int nb_bits = (nb_points > 8) ? 8 : nb_points;
133 133  
134   - value = get_byte_from_bits(tab_rp_status, i*8, nb_bits);
135   - if (value != UT_COIL_STATUS_TAB[i]) {
  134 + value = modbus_get_byte_from_bits(tab_rp_bits, i*8, nb_bits);
  135 + if (value != UT_BITS_TAB[i]) {
136 136 printf("FAILED (%0X != %0X)\n",
137   - value, UT_COIL_STATUS_TAB[i]);
  137 + value, UT_BITS_TAB[i]);
138 138 goto close;
139 139 }
140 140  
... ... @@ -142,28 +142,28 @@ int main(void)
142 142 i++;
143 143 }
144 144 printf("OK\n");
145   - /* End of multiple coils */
  145 + /* End of multiple bits */
146 146  
147   - /** INPUT STATUS **/
148   - rc = read_input_status(&mb_param, SERVER_ID, UT_INPUT_STATUS_ADDRESS,
149   - UT_INPUT_STATUS_NB_POINTS, tab_rp_status);
150   - printf("1/1 read_input_status: ");
  147 + /** DISCRETE INPUTS **/
  148 + rc = modbus_read_input_bits(ctx, UT_INPUT_BITS_ADDRESS,
  149 + UT_INPUT_BITS_NB_POINTS, tab_rp_bits);
  150 + printf("1/1 modbus_read_input_bits: ");
151 151  
152   - if (rc != UT_INPUT_STATUS_NB_POINTS) {
  152 + if (rc != UT_INPUT_BITS_NB_POINTS) {
153 153 printf("FAILED (nb points %d)\n", rc);
154 154 goto close;
155 155 }
156 156  
157 157 i = 0;
158   - address = UT_INPUT_STATUS_ADDRESS;
159   - nb_points = UT_INPUT_STATUS_NB_POINTS;
  158 + address = UT_INPUT_BITS_ADDRESS;
  159 + nb_points = UT_INPUT_BITS_NB_POINTS;
160 160 while (nb_points > 0) {
161 161 int nb_bits = (nb_points > 8) ? 8 : nb_points;
162 162  
163   - value = get_byte_from_bits(tab_rp_status, i*8, nb_bits);
164   - if (value != UT_INPUT_STATUS_TAB[i]) {
  163 + value = modbus_get_byte_from_bits(tab_rp_bits, i*8, nb_bits);
  164 + if (value != UT_INPUT_BITS_TAB[i]) {
165 165 printf("FAILED (%0X != %0X)\n",
166   - value, UT_INPUT_STATUS_TAB[i]);
  166 + value, UT_INPUT_BITS_TAB[i]);
167 167 goto close;
168 168 }
169 169  
... ... @@ -175,9 +175,8 @@ int main(void)
175 175 /** HOLDING REGISTERS **/
176 176  
177 177 /* Single register */
178   - rc = preset_single_register(&mb_param, SERVER_ID,
179   - UT_HOLDING_REGISTERS_ADDRESS, 0x1234);
180   - printf("1/2 preset_single_register: ");
  178 + rc = modbus_write_register(ctx, UT_REGISTERS_ADDRESS, 0x1234);
  179 + printf("1/2 modbus_write_register: ");
181 180 if (rc == 1) {
182 181 printf("OK\n");
183 182 } else {
... ... @@ -185,10 +184,9 @@ int main(void)
185 184 goto close;
186 185 }
187 186  
188   - rc = read_holding_registers(&mb_param, SERVER_ID,
189   - UT_HOLDING_REGISTERS_ADDRESS,
190   - 1, tab_rp_registers);
191   - printf("2/2 read_holding_registers: ");
  187 + rc = modbus_read_registers(ctx, UT_REGISTERS_ADDRESS,
  188 + 1, tab_rp_registers);
  189 + printf("2/2 modbus_read_registers: ");
192 190 if (rc != 1) {
193 191 printf("FAILED (nb points %d)\n", rc);
194 192 goto close;
... ... @@ -203,33 +201,31 @@ int main(void)
203 201 /* End of single register */
204 202  
205 203 /* Many registers */
206   - rc = preset_multiple_registers(&mb_param, SERVER_ID,
207   - UT_HOLDING_REGISTERS_ADDRESS,
208   - UT_HOLDING_REGISTERS_NB_POINTS,
209   - UT_HOLDING_REGISTERS_TAB);
210   - printf("1/2 preset_multiple_registers: ");
211   - if (rc == UT_HOLDING_REGISTERS_NB_POINTS) {
  204 + rc = modbus_write_registers(ctx, UT_REGISTERS_ADDRESS,
  205 + UT_REGISTERS_NB_POINTS,
  206 + UT_REGISTERS_TAB);
  207 + printf("1/2 modbus_write_registers: ");
  208 + if (rc == UT_REGISTERS_NB_POINTS) {
212 209 printf("OK\n");
213 210 } else {
214 211 printf("FAILED\n");
215 212 goto close;
216 213 }
217 214  
218   - rc = read_holding_registers(&mb_param, SERVER_ID,
219   - UT_HOLDING_REGISTERS_ADDRESS,
220   - UT_HOLDING_REGISTERS_NB_POINTS,
221   - tab_rp_registers);
222   - printf("2/2 read_holding_registers: ");
223   - if (rc != UT_HOLDING_REGISTERS_NB_POINTS) {
  215 + rc = modbus_read_registers(ctx, UT_REGISTERS_ADDRESS,
  216 + UT_REGISTERS_NB_POINTS,
  217 + tab_rp_registers);
  218 + printf("2/2 modbus_read_registers: ");
  219 + if (rc != UT_REGISTERS_NB_POINTS) {
224 220 printf("FAILED (nb points %d)\n", rc);
225 221 goto close;
226 222 }
227 223  
228   - for (i=0; i < UT_HOLDING_REGISTERS_NB_POINTS; i++) {
229   - if (tab_rp_registers[i] != UT_HOLDING_REGISTERS_TAB[i]) {
  224 + for (i=0; i < UT_REGISTERS_NB_POINTS; i++) {
  225 + if (tab_rp_registers[i] != UT_REGISTERS_TAB[i]) {
230 226 printf("FAILED (%0X != %0X)\n",
231 227 tab_rp_registers[i],
232   - UT_HOLDING_REGISTERS_TAB[i]);
  228 + UT_REGISTERS_TAB[i]);
233 229 goto close;
234 230 }
235 231 }
... ... @@ -238,11 +234,10 @@ int main(void)
238 234  
239 235  
240 236 /** INPUT REGISTERS **/
241   - rc = read_input_registers(&mb_param, SERVER_ID,
242   - UT_INPUT_REGISTERS_ADDRESS,
243   - UT_INPUT_REGISTERS_NB_POINTS,
244   - tab_rp_registers);
245   - printf("1/1 read_input_registers: ");
  237 + rc = modbus_read_input_registers(ctx, UT_INPUT_REGISTERS_ADDRESS,
  238 + UT_INPUT_REGISTERS_NB_POINTS,
  239 + tab_rp_registers);
  240 + printf("1/1 modbus_read_input_registers: ");
246 241 if (rc != UT_INPUT_REGISTERS_NB_POINTS) {
247 242 printf("FAILED (nb points %d)\n", rc);
248 243 goto close;
... ... @@ -257,11 +252,10 @@ int main(void)
257 252 }
258 253 printf("OK\n");
259 254  
260   -
261 255 printf("\nTEST FLOATS\n");
262 256 /** FLOAT **/
263   - printf("1/2 Write float: ");
264   - modbus_write_float(UT_REAL, tab_rp_registers);
  257 + printf("1/2 Set float: ");
  258 + modbus_set_float(UT_REAL, tab_rp_registers);
265 259 if (tab_rp_registers[1] == (UT_IREAL >> 16) &&
266 260 tab_rp_registers[0] == (UT_IREAL & 0xFFFF)) {
267 261 printf("OK\n");
... ... @@ -271,8 +265,8 @@ int main(void)
271 265 goto close;
272 266 }
273 267  
274   - printf("2/2 Read float: ");
275   - real = modbus_read_float(tab_rp_registers);
  268 + printf("2/2 Get float: ");
  269 + real = modbus_get_float(tab_rp_registers);
276 270 if (real == UT_REAL) {
277 271 printf("OK\n");
278 272 } else {
... ... @@ -288,23 +282,21 @@ int main(void)
288 282 /* The mapping begins at 0 and ending at address + nb_points so
289 283 * the addresses below are not valid. */
290 284  
291   - rc = read_coil_status(&mb_param, SERVER_ID,
292   - UT_COIL_STATUS_ADDRESS,
293   - UT_COIL_STATUS_NB_POINTS + 1,
294   - tab_rp_status);
295   - printf("* read_coil_status: ");
296   - if (rc == -1 && errno == EMBXILADD)
  285 + rc = modbus_read_bits(ctx, UT_BITS_ADDRESS,
  286 + UT_BITS_NB_POINTS + 1,
  287 + tab_rp_bits);
  288 + printf("* modbus_read_bits: ");
  289 + if (rc == -1 && errno == EMBXILADD) {
297 290 printf("OK\n");
298   - else {
  291 + } else {
299 292 printf("FAILED\n");
300 293 goto close;
301 294 }
302 295  
303   - rc = read_input_status(&mb_param, SERVER_ID,
304   - UT_INPUT_STATUS_ADDRESS,
305   - UT_INPUT_STATUS_NB_POINTS + 1,
306   - tab_rp_status);
307   - printf("* read_input_status: ");
  296 + rc = modbus_read_input_bits(ctx, UT_INPUT_BITS_ADDRESS,
  297 + UT_INPUT_BITS_NB_POINTS + 1,
  298 + tab_rp_bits);
  299 + printf("* modbus_read_input_bits: ");
308 300 if (rc == -1 && errno == EMBXILADD)
309 301 printf("OK\n");
310 302 else {
... ... @@ -312,11 +304,10 @@ int main(void)
312 304 goto close;
313 305 }
314 306  
315   - rc = read_holding_registers(&mb_param, SERVER_ID,
316   - UT_HOLDING_REGISTERS_ADDRESS,
317   - UT_HOLDING_REGISTERS_NB_POINTS + 1,
318   - tab_rp_registers);
319   - printf("* read_holding_registers: ");
  307 + rc = modbus_read_registers(ctx, UT_REGISTERS_ADDRESS,
  308 + UT_REGISTERS_NB_POINTS + 1,
  309 + tab_rp_registers);
  310 + printf("* modbus_read_registers: ");
320 311 if (rc == -1 && errno == EMBXILADD)
321 312 printf("OK\n");
322 313 else {
... ... @@ -324,11 +315,10 @@ int main(void)
324 315 goto close;
325 316 }
326 317  
327   - rc = read_input_registers(&mb_param, SERVER_ID,
328   - UT_INPUT_REGISTERS_ADDRESS,
329   - UT_INPUT_REGISTERS_NB_POINTS + 1,
330   - tab_rp_registers);
331   - printf("* read_input_registers: ");
  318 + rc = modbus_read_input_registers(ctx, UT_INPUT_REGISTERS_ADDRESS,
  319 + UT_INPUT_REGISTERS_NB_POINTS + 1,
  320 + tab_rp_registers);
  321 + printf("* modbus_read_input_registers: ");
332 322 if (rc == -1 && errno == EMBXILADD)
333 323 printf("OK\n");
334 324 else {
... ... @@ -336,10 +326,8 @@ int main(void)
336 326 goto close;
337 327 }
338 328  
339   - rc = force_single_coil(&mb_param, SERVER_ID,
340   - UT_COIL_STATUS_ADDRESS + UT_COIL_STATUS_NB_POINTS,
341   - ON);
342   - printf("* force_single_coil: ");
  329 + rc = modbus_write_bit(ctx, UT_BITS_ADDRESS + UT_BITS_NB_POINTS, ON);
  330 + printf("* modbus_write_bit: ");
343 331 if (rc == -1 && errno == EMBXILADD) {
344 332 printf("OK\n");
345 333 } else {
... ... @@ -347,11 +335,10 @@ int main(void)
347 335 goto close;
348 336 }
349 337  
350   - rc = force_multiple_coils(&mb_param, SERVER_ID,
351   - UT_COIL_STATUS_ADDRESS + UT_COIL_STATUS_NB_POINTS,
352   - UT_COIL_STATUS_NB_POINTS,
353   - tab_rp_status);
354   - printf("* force_multiple_coils: ");
  338 + rc = modbus_write_bits(ctx, UT_BITS_ADDRESS + UT_BITS_NB_POINTS,
  339 + UT_BITS_NB_POINTS,
  340 + tab_rp_bits);
  341 + printf("* modbus_write_coils: ");
355 342 if (rc == -1 && errno == EMBXILADD) {
356 343 printf("OK\n");
357 344 } else {
... ... @@ -359,11 +346,11 @@ int main(void)
359 346 goto close;
360 347 }
361 348  
362   - rc = preset_multiple_registers(&mb_param, SERVER_ID,
363   - UT_HOLDING_REGISTERS_ADDRESS + UT_HOLDING_REGISTERS_NB_POINTS,
364   - UT_HOLDING_REGISTERS_NB_POINTS,
365   - tab_rp_registers);
366   - printf("* preset_multiple_registers: ");
  349 + rc = modbus_write_registers(ctx, UT_REGISTERS_ADDRESS +
  350 + UT_REGISTERS_NB_POINTS,
  351 + UT_REGISTERS_NB_POINTS,
  352 + tab_rp_registers);
  353 + printf("* modbus_write_registers: ");
367 354 if (rc == -1 && errno == EMBXILADD) {
368 355 printf("OK\n");
369 356 } else {
... ... @@ -375,11 +362,9 @@ int main(void)
375 362 /** TOO MANY DATA **/
376 363 printf("\nTEST TOO MANY DATA ERROR:\n");
377 364  
378   - rc = read_coil_status(&mb_param, SERVER_ID,
379   - UT_COIL_STATUS_ADDRESS,
380   - MAX_STATUS + 1,
381   - tab_rp_status);
382   - printf("* read_coil_status: ");
  365 + rc = modbus_read_bits(ctx, UT_BITS_ADDRESS, MODBUS_MAX_BITS + 1,
  366 + tab_rp_bits);
  367 + printf("* modbus_read_bits: ");
383 368 if (rc == -1 && errno == EMBMDATA) {
384 369 printf("OK\n");
385 370 } else {
... ... @@ -387,11 +372,10 @@ int main(void)
387 372 goto close;
388 373 }
389 374  
390   - rc = read_input_status(&mb_param, SERVER_ID,
391   - UT_INPUT_STATUS_ADDRESS,
392   - MAX_STATUS + 1,
393   - tab_rp_status);
394   - printf("* read_input_status: ");
  375 + rc = modbus_read_input_bits(ctx, UT_INPUT_BITS_ADDRESS,
  376 + MODBUS_MAX_BITS + 1,
  377 + tab_rp_bits);
  378 + printf("* modbus_read_input_bits: ");
395 379 if (rc == -1 && errno == EMBMDATA) {
396 380 printf("OK\n");
397 381 } else {
... ... @@ -399,11 +383,10 @@ int main(void)
399 383 goto close;
400 384 }
401 385  
402   - rc = read_holding_registers(&mb_param, SERVER_ID,
403   - UT_HOLDING_REGISTERS_ADDRESS,
404   - MAX_REGISTERS + 1,
405   - tab_rp_registers);
406   - printf("* read_holding_registers: ");
  386 + rc = modbus_read_registers(ctx, UT_REGISTERS_ADDRESS,
  387 + MODBUS_MAX_REGISTERS + 1,
  388 + tab_rp_registers);
  389 + printf("* modbus_read_registers: ");
407 390 if (rc == -1 && errno == EMBMDATA) {
408 391 printf("OK\n");
409 392 } else {
... ... @@ -411,11 +394,10 @@ int main(void)
411 394 goto close;
412 395 }
413 396  
414   - rc = read_input_registers(&mb_param, SERVER_ID,
415   - UT_INPUT_REGISTERS_ADDRESS,
416   - MAX_REGISTERS + 1,
417   - tab_rp_registers);
418   - printf("* read_input_registers: ");
  397 + rc = modbus_read_input_registers(ctx, UT_INPUT_REGISTERS_ADDRESS,
  398 + MODBUS_MAX_REGISTERS + 1,
  399 + tab_rp_registers);
  400 + printf("* modbus_read_input_registers: ");
419 401 if (rc == -1 && errno == EMBMDATA) {
420 402 printf("OK\n");
421 403 } else {
... ... @@ -423,11 +405,10 @@ int main(void)
423 405 goto close;
424 406 }
425 407  
426   - rc = force_multiple_coils(&mb_param, SERVER_ID,
427   - UT_COIL_STATUS_ADDRESS,
428   - MAX_STATUS + 1,
429   - tab_rp_status);
430   - printf("* force_multiple_coils: ");
  408 + rc = modbus_write_bits(ctx, UT_BITS_ADDRESS,
  409 + MODBUS_MAX_BITS + 1,
  410 + tab_rp_bits);
  411 + printf("* modbus_write_bits: ");
431 412 if (rc == -1 && errno == EMBMDATA) {
432 413 printf("OK\n");
433 414 } else {
... ... @@ -435,11 +416,10 @@ int main(void)
435 416 printf("FAILED\n");
436 417 }
437 418  
438   - rc = preset_multiple_registers(&mb_param, SERVER_ID,
439   - UT_HOLDING_REGISTERS_ADDRESS,
440   - MAX_REGISTERS + 1,
441   - tab_rp_registers);
442   - printf("* preset_multiple_registers: ");
  419 + rc = modbus_write_registers(ctx, UT_REGISTERS_ADDRESS,
  420 + MODBUS_MAX_REGISTERS + 1,
  421 + tab_rp_registers);
  422 + printf("* modbus_write_registers: ");
443 423 if (rc == -1 && errno == EMBMDATA) {
444 424 printf("OK\n");
445 425 } else {
... ... @@ -449,13 +429,12 @@ int main(void)
449 429  
450 430 /** SLAVE REPLY **/
451 431 printf("\nTEST SLAVE REPLY:\n");
452   -
453   - rc = read_holding_registers(&mb_param, 18,
454   - UT_HOLDING_REGISTERS_ADDRESS,
455   - UT_HOLDING_REGISTERS_NB_POINTS,
456   - tab_rp_registers);
  432 + modbus_set_slave(ctx, 18);
  433 + rc = modbus_read_registers(ctx, UT_REGISTERS_ADDRESS,
  434 + UT_REGISTERS_NB_POINTS,
  435 + tab_rp_registers);
457 436 printf("1/3 No or response from slave %d: ", 18);
458   - if (mb_param.type_com == RTU) {
  437 + if (is_mode_rtu) {
459 438 /* No response in RTU mode */
460 439 if (rc == -1 && errno == ETIMEDOUT) {
461 440 printf("OK\n");
... ... @@ -465,7 +444,7 @@ int main(void)
465 444 }
466 445 } else {
467 446 /* Response in TCP mode */
468   - if (rc == UT_HOLDING_REGISTERS_NB_POINTS) {
  447 + if (rc == UT_REGISTERS_NB_POINTS) {
469 448 printf("OK\n");
470 449 } else {
471 450 printf("FAILED\n");
... ... @@ -473,30 +452,36 @@ int main(void)
473 452 }
474 453 }
475 454  
476   - rc = read_holding_registers(&mb_param, MODBUS_BROADCAST_ADDRESS,
477   - UT_HOLDING_REGISTERS_ADDRESS,
478   - UT_HOLDING_REGISTERS_NB_POINTS,
479   - tab_rp_registers);
  455 + modbus_set_slave(ctx, MODBUS_BROADCAST_ADDRESS);
  456 + rc = modbus_read_registers(ctx, UT_REGISTERS_ADDRESS,
  457 + UT_REGISTERS_NB_POINTS,
  458 + tab_rp_registers);
480 459 printf("2/3 Reply after a broadcast query: ");
481   - if (rc == UT_HOLDING_REGISTERS_NB_POINTS) {
  460 + if (rc == UT_REGISTERS_NB_POINTS) {
482 461 printf("OK\n");
483 462 } else {
484 463 printf("FAILED\n");
485 464 goto close;
486 465 }
487 466  
  467 + /* Restore slave */
  468 + if (is_mode_rtu) {
  469 + modbus_set_slave(ctx, SERVER_ID);
  470 + } else {
  471 + modbus_set_slave(ctx, MODBUS_TCP_SLAVE);
  472 + }
  473 +
488 474 /* Save original timeout */
489   - modbus_get_timeout_begin(&mb_param, &timeout_begin_old);
  475 + modbus_get_timeout_begin(ctx, &timeout_begin_old);
490 476  
491 477 /* Define a new and too short timeout */
492 478 timeout_begin_new.tv_sec = 0;
493 479 timeout_begin_new.tv_usec = 0;
494   - modbus_set_timeout_begin(&mb_param, &timeout_begin_new);
  480 + modbus_set_timeout_begin(ctx, &timeout_begin_new);
495 481  
496   - rc = read_holding_registers(&mb_param, SERVER_ID,
497   - UT_HOLDING_REGISTERS_ADDRESS,
498   - UT_HOLDING_REGISTERS_NB_POINTS,
499   - tab_rp_registers);
  482 + rc = modbus_read_registers(ctx, UT_REGISTERS_ADDRESS,
  483 + UT_REGISTERS_NB_POINTS,
  484 + tab_rp_registers);
500 485 printf("3/3 Too short timeout: ");
501 486 if (rc == -1 && errno == ETIMEDOUT) {
502 487 printf("OK\n");
... ... @@ -506,19 +491,18 @@ int main(void)
506 491 }
507 492  
508 493 /* Restore original timeout */
509   - modbus_set_timeout_begin(&mb_param, &timeout_begin_old);
  494 + modbus_set_timeout_begin(ctx, &timeout_begin_old);
510 495  
511 496 /** BAD RESPONSE **/
512 497 printf("\nTEST BAD RESPONSE ERROR:\n");
513 498  
514 499 /* Allocate only the required space */
515 500 tab_rp_registers_bad = (uint16_t *) malloc(
516   - UT_HOLDING_REGISTERS_NB_POINTS_SPECIAL * sizeof(uint16_t));
517   - rc = read_holding_registers(&mb_param, SERVER_ID,
518   - UT_HOLDING_REGISTERS_ADDRESS,
519   - UT_HOLDING_REGISTERS_NB_POINTS_SPECIAL,
520   - tab_rp_registers_bad);
521   - printf("* read_holding_registers: ");
  501 + UT_REGISTERS_NB_POINTS_SPECIAL * sizeof(uint16_t));
  502 + rc = modbus_read_registers(ctx, UT_REGISTERS_ADDRESS,
  503 + UT_REGISTERS_NB_POINTS_SPECIAL,
  504 + tab_rp_registers_bad);
  505 + printf("* modbus_read_registers: ");
522 506 if (rc == -1 && errno == EMBBADDATA) {
523 507 printf("OK\n");
524 508 } else {
... ... @@ -531,11 +515,12 @@ int main(void)
531 515  
532 516 close:
533 517 /* Free the memory */
534   - free(tab_rp_status);
  518 + free(tab_rp_bits);
535 519 free(tab_rp_registers);
536 520  
537 521 /* Close the connection */
538   - modbus_close(&mb_param);
  522 + modbus_close(ctx);
  523 + modbus_free(ctx);
539 524  
540 525 return 0;
541 526 }
... ...
tests/unit-test-slave.c
... ... @@ -24,26 +24,29 @@
24 24  
25 25 #include "unit-test.h"
26 26  
  27 +/* Copied from modbus-private.h */
  28 +#define HEADER_LENGTH_TCP 7
  29 +
27 30 int main(void)
28 31 {
29 32 int socket;
30   - modbus_param_t mb_param;
31   - modbus_mapping_t mb_mapping;
  33 + modbus_t *ctx;
  34 + modbus_mapping_t *mb_mapping;
32 35 int rc;
33 36 int i;
34 37  
35   - modbus_init_tcp(&mb_param, "127.0.0.1", 1502);
36   - modbus_set_debug(&mb_param, TRUE);
37   - modbus_set_error_recovery(&mb_param, TRUE);
  38 + ctx = modbus_new_tcp("127.0.0.1", 1502);
  39 + modbus_set_debug(ctx, TRUE);
  40 + modbus_set_error_recovery(ctx, TRUE);
38 41  
39   - rc = modbus_mapping_new(&mb_mapping,
40   - UT_COIL_STATUS_ADDRESS + UT_COIL_STATUS_NB_POINTS,
41   - UT_INPUT_STATUS_ADDRESS + UT_INPUT_STATUS_NB_POINTS,
42   - UT_HOLDING_REGISTERS_ADDRESS + UT_HOLDING_REGISTERS_NB_POINTS,
43   - UT_INPUT_REGISTERS_ADDRESS + UT_INPUT_REGISTERS_NB_POINTS);
44   - if (rc == -1) {
  42 + mb_mapping = modbus_mapping_new(UT_BITS_ADDRESS + UT_BITS_NB_POINTS,
  43 + UT_INPUT_BITS_ADDRESS + UT_INPUT_BITS_NB_POINTS,
  44 + UT_REGISTERS_ADDRESS + UT_REGISTERS_NB_POINTS,
  45 + UT_INPUT_REGISTERS_ADDRESS + UT_INPUT_REGISTERS_NB_POINTS);
  46 + if (mb_mapping == NULL) {
45 47 fprintf(stderr, "Failed to allocate the mapping: %s\n",
46 48 modbus_strerror(errno));
  49 + modbus_free(ctx);
47 50 return -1;
48 51 }
49 52  
... ... @@ -51,33 +54,33 @@ int main(void)
51 54 Only the read-only input values are assigned. */
52 55  
53 56 /** INPUT STATUS **/
54   - set_bits_from_bytes(mb_mapping.tab_input_status,
55   - UT_INPUT_STATUS_ADDRESS, UT_INPUT_STATUS_NB_POINTS,
56   - UT_INPUT_STATUS_TAB);
  57 + modbus_set_bits_from_bytes(mb_mapping->tab_input_bits,
  58 + UT_INPUT_BITS_ADDRESS, UT_INPUT_BITS_NB_POINTS,
  59 + UT_INPUT_BITS_TAB);
57 60  
58 61 /** INPUT REGISTERS **/
59 62 for (i=0; i < UT_INPUT_REGISTERS_NB_POINTS; i++) {
60   - mb_mapping.tab_input_registers[UT_INPUT_REGISTERS_ADDRESS+i] =
  63 + mb_mapping->tab_input_registers[UT_INPUT_REGISTERS_ADDRESS+i] =
61 64 UT_INPUT_REGISTERS_TAB[i];;
62 65 }
63 66  
64   - socket = modbus_slave_listen_tcp(&mb_param, 1);
65   - modbus_slave_accept_tcp(&mb_param, &socket);
  67 + socket = modbus_listen(ctx, 1);
  68 + modbus_accept(ctx, &socket);
66 69  
67 70 for (;;) {
68   - uint8_t query[MAX_MESSAGE_LENGTH];
  71 + uint8_t query[MODBUS_MAX_ADU_LENGTH_TCP];
69 72  
70   - rc = modbus_slave_receive(&mb_param, -1, query);
  73 + rc = modbus_receive(ctx, -1, query);
71 74 if (rc > 0) {
72 75 if (((query[HEADER_LENGTH_TCP + 3] << 8) + query[HEADER_LENGTH_TCP + 4])
73   - == UT_HOLDING_REGISTERS_NB_POINTS_SPECIAL) {
  76 + == UT_REGISTERS_NB_POINTS_SPECIAL) {
74 77 /* Change the number of values (offset
75 78 TCP = 6) */
76 79 query[HEADER_LENGTH_TCP + 3] = 0;
77   - query[HEADER_LENGTH_TCP + 4] = UT_HOLDING_REGISTERS_NB_POINTS;
  80 + query[HEADER_LENGTH_TCP + 4] = UT_REGISTERS_NB_POINTS;
78 81 }
79 82  
80   - rc = modbus_slave_manage(&mb_param, query, rc, &mb_mapping);
  83 + rc = modbus_reply(ctx, query, rc, mb_mapping);
81 84 if (rc == -1) {
82 85 return -1;
83 86 }
... ... @@ -90,8 +93,8 @@ int main(void)
90 93 printf("Quit the loop: %s\n", modbus_strerror(errno));
91 94  
92 95 close(socket);
93   - modbus_mapping_free(&mb_mapping);
94   - modbus_close(&mb_param);
  96 + modbus_mapping_free(mb_mapping);
  97 + modbus_free(ctx);
95 98  
96 99 return 0;
97 100 }
... ...
tests/unit-test.h
... ... @@ -28,21 +28,21 @@
28 28 #define CLIENT_ID 15
29 29 #define SERVER_ID 17
30 30  
31   -const uint16_t UT_COIL_STATUS_ADDRESS = 0x13;
32   -const uint16_t UT_COIL_STATUS_NB_POINTS = 0x25;
33   -const uint8_t UT_COIL_STATUS_TAB[] = { 0xCD, 0x6B, 0xB2, 0x0E, 0x1B };
  31 +const uint16_t UT_BITS_ADDRESS = 0x13;
  32 +const uint16_t UT_BITS_NB_POINTS = 0x25;
  33 +const uint8_t UT_BITS_TAB[] = { 0xCD, 0x6B, 0xB2, 0x0E, 0x1B };
34 34  
35   -const uint16_t UT_INPUT_STATUS_ADDRESS = 0xC4;
36   -const uint16_t UT_INPUT_STATUS_NB_POINTS = 0x16;
37   -const uint8_t UT_INPUT_STATUS_TAB[] = { 0xAC, 0xDB, 0x35 };
  35 +const uint16_t UT_INPUT_BITS_ADDRESS = 0xC4;
  36 +const uint16_t UT_INPUT_BITS_NB_POINTS = 0x16;
  37 +const uint8_t UT_INPUT_BITS_TAB[] = { 0xAC, 0xDB, 0x35 };
38 38  
39   -const uint16_t UT_HOLDING_REGISTERS_ADDRESS = 0x6B;
40   -const uint16_t UT_HOLDING_REGISTERS_NB_POINTS = 0x3;
41   -const uint16_t UT_HOLDING_REGISTERS_TAB[] = { 0x022B, 0x0000, 0x0064 };
  39 +const uint16_t UT_REGISTERS_ADDRESS = 0x6B;
  40 +const uint16_t UT_REGISTERS_NB_POINTS = 0x3;
  41 +const uint16_t UT_REGISTERS_TAB[] = { 0x022B, 0x0000, 0x0064 };
42 42 /* If the following value is used, a bad response is sent.
43 43 It's better to test with a lower value than
44   - UT_HOLDING_REGISTERS_NB_POINTS to try to raise a segfault. */
45   -const uint16_t UT_HOLDING_REGISTERS_NB_POINTS_SPECIAL = 0x2;
  44 + UT_REGISTERS_NB_POINTS to try to raise a segfault. */
  45 +const uint16_t UT_REGISTERS_NB_POINTS_SPECIAL = 0x2;
46 46  
47 47 const uint16_t UT_INPUT_REGISTERS_ADDRESS = 0x08;
48 48 const uint16_t UT_INPUT_REGISTERS_NB_POINTS = 0x1;
... ...
tests/version.c
... ... @@ -25,7 +25,12 @@ int main(void)
25 25 libmodbus_version_major, libmodbus_version_minor, libmodbus_version_micro);
26 26  
27 27 if (LIBMODBUS_VERSION_CHECK(2, 1, 0)) {
28   - printf("The functions to read/write float values are available.\n");
  28 + printf("The functions to read/write float values are available (2.1.0).\n");
29 29 }
  30 +
  31 + if (LIBMODBUS_VERSION_CHECK(2, 1, 1)) {
  32 + printf("Oh gosh, brand new API (2.1.1)!\n");
  33 + }
  34 +
30 35 return 0;
31 36 }
... ...