Coverage Report

Created: 2026-04-01 06:20

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/libmodbus/src/modbus.c
Line
Count
Source
1
/*
2
 * Copyright © Stéphane Raimbault <stephane.raimbault@gmail.com>
3
 *
4
 * SPDX-License-Identifier: LGPL-2.1-or-later
5
 *
6
 * This library implements the Modbus protocol.
7
 * http://libmodbus.org/
8
 */
9
10
#include <errno.h>
11
#include <limits.h>
12
#include <stdarg.h>
13
#include <stdio.h>
14
#include <stdlib.h>
15
#include <string.h>
16
#include <time.h>
17
#ifndef _MSC_VER
18
#include <unistd.h>
19
#endif
20
21
#include <config.h>
22
23
#include "modbus-private.h"
24
#include "modbus.h"
25
26
/* Internal use */
27
0
#define MSG_LENGTH_UNDEFINED -1
28
29
/* Exported version */
30
const unsigned int libmodbus_version_major = LIBMODBUS_VERSION_MAJOR;
31
const unsigned int libmodbus_version_minor = LIBMODBUS_VERSION_MINOR;
32
const unsigned int libmodbus_version_micro = LIBMODBUS_VERSION_MICRO;
33
34
/* Max between RTU and TCP max adu length (so TCP) */
35
#define MAX_MESSAGE_LENGTH 260
36
37
/* 3 steps are used to parse the query */
38
typedef enum {
39
    _STEP_FUNCTION,
40
    _STEP_META,
41
    _STEP_DATA
42
} _step_t;
43
44
const char *modbus_strerror(int errnum)
45
0
{
46
0
    switch (errnum) {
47
0
    case EMBXILFUN:
48
0
        return "Illegal function";
49
0
    case EMBXILADD:
50
0
        return "Illegal data address";
51
0
    case EMBXILVAL:
52
0
        return "Illegal data value";
53
0
    case EMBXSFAIL:
54
0
        return "Slave device or server failure";
55
0
    case EMBXACK:
56
0
        return "Acknowledge";
57
0
    case EMBXSBUSY:
58
0
        return "Slave device or server is busy";
59
0
    case EMBXNACK:
60
0
        return "Negative acknowledge";
61
0
    case EMBXMEMPAR:
62
0
        return "Memory parity error";
63
0
    case EMBXGPATH:
64
0
        return "Gateway path unavailable";
65
0
    case EMBXGTAR:
66
0
        return "Target device failed to respond";
67
0
    case EMBBADCRC:
68
0
        return "Invalid CRC";
69
0
    case EMBBADDATA:
70
0
        return "Invalid data";
71
0
    case EMBBADEXC:
72
0
        return "Invalid exception code";
73
0
    case EMBMDATA:
74
0
        return "Too many data";
75
0
    case EMBBADSLAVE:
76
0
        return "Response not from requested slave";
77
0
    default:
78
0
        return strerror(errnum);
79
0
    }
80
0
}
81
82
void _error_print(modbus_t *ctx, const char *context)
83
0
{
84
0
    if (ctx->debug) {
85
0
        fprintf(stderr, "ERROR %s", modbus_strerror(errno));
86
0
        if (context != NULL) {
87
0
            fprintf(stderr, ": %s\n", context);
88
0
        } else {
89
0
            fprintf(stderr, "\n");
90
0
        }
91
0
    }
92
0
}
93
94
static void _sleep_response_timeout(modbus_t *ctx)
95
0
{
96
    /* Response timeout is always positive */
97
#ifdef _WIN32
98
    /* usleep doesn't exist on Windows */
99
    Sleep((ctx->response_timeout.tv_sec * 1000) + (ctx->response_timeout.tv_usec / 1000));
100
#else
101
    /* usleep source code */
102
0
    struct timespec request, remaining;
103
0
    request.tv_sec = ctx->response_timeout.tv_sec;
104
0
    request.tv_nsec = ((long int) ctx->response_timeout.tv_usec) * 1000;
105
0
    while (nanosleep(&request, &remaining) == -1 && errno == EINTR) {
106
0
        request = remaining;
107
0
    }
108
0
#endif
109
0
}
110
111
int modbus_flush(modbus_t *ctx)
112
0
{
113
0
    int rc;
114
115
0
    if (ctx == NULL) {
116
0
        errno = EINVAL;
117
0
        return -1;
118
0
    }
119
120
0
    rc = ctx->backend->flush(ctx);
121
0
    if (rc != -1 && ctx->debug) {
122
        /* Not all backends are able to return the number of bytes flushed */
123
0
        printf("Bytes flushed (%d)\n", rc);
124
0
    }
125
0
    return rc;
126
0
}
127
128
/* Computes the length of the expected response including checksum */
129
static unsigned int compute_response_length_from_request(modbus_t *ctx, uint8_t *req)
130
0
{
131
0
    int length;
132
0
    const int offset = ctx->backend->header_length;
133
134
0
    switch (req[offset]) {
135
0
    case MODBUS_FC_READ_COILS:
136
0
    case MODBUS_FC_READ_DISCRETE_INPUTS: {
137
        /* Header + nb values (code from write_bits) */
138
0
        int nb = (req[offset + 3] << 8) | req[offset + 4];
139
0
        length = 2 + (nb / 8) + ((nb % 8) ? 1 : 0);
140
0
    } break;
141
0
    case MODBUS_FC_WRITE_AND_READ_REGISTERS:
142
0
    case MODBUS_FC_READ_HOLDING_REGISTERS:
143
0
    case MODBUS_FC_READ_INPUT_REGISTERS:
144
        /* Header + 2 * nb values */
145
0
        length = 2 + 2 * (req[offset + 3] << 8 | req[offset + 4]);
146
0
        break;
147
0
    case MODBUS_FC_READ_EXCEPTION_STATUS:
148
0
        length = 3;
149
0
        break;
150
0
    case MODBUS_FC_REPORT_SLAVE_ID:
151
        /* The response is device specific (the header provides the
152
           length) */
153
0
        return MSG_LENGTH_UNDEFINED;
154
0
    case MODBUS_FC_MASK_WRITE_REGISTER:
155
0
        length = 7;
156
0
        break;
157
0
    default:
158
0
        length = 5;
159
0
    }
160
161
0
    return offset + length + ctx->backend->checksum_length;
162
0
}
163
164
/* Sends a request/response */
165
static int send_msg(modbus_t *ctx, uint8_t *msg, int msg_length)
166
0
{
167
0
    int rc;
168
0
    int i;
169
170
0
    msg_length = ctx->backend->send_msg_pre(msg, msg_length);
171
172
0
    if (ctx->debug) {
173
0
        for (i = 0; i < msg_length; i++)
174
0
            printf("[%.2X]", msg[i]);
175
0
        printf("\n");
176
0
    }
177
178
    /* In recovery mode, the write command will be issued until to be
179
       successful! Disabled by default. */
180
0
    do {
181
0
        rc = ctx->backend->send(ctx, msg, msg_length);
182
0
        if (rc == -1) {
183
0
            _error_print(ctx, NULL);
184
0
            if (ctx->error_recovery & MODBUS_ERROR_RECOVERY_LINK) {
185
#ifdef _WIN32
186
                const int wsa_err = WSAGetLastError();
187
                if (wsa_err == WSAENETRESET || wsa_err == WSAENOTCONN ||
188
                    wsa_err == WSAENOTSOCK || wsa_err == WSAESHUTDOWN ||
189
                    wsa_err == WSAEHOSTUNREACH || wsa_err == WSAECONNABORTED ||
190
                    wsa_err == WSAECONNRESET || wsa_err == WSAETIMEDOUT) {
191
                    modbus_close(ctx);
192
                    _sleep_response_timeout(ctx);
193
                    modbus_connect(ctx);
194
                } else {
195
                    _sleep_response_timeout(ctx);
196
                    modbus_flush(ctx);
197
                }
198
#else
199
0
                int saved_errno = errno;
200
201
0
                if ((errno == EBADF || errno == ECONNRESET || errno == EPIPE)) {
202
0
                    modbus_close(ctx);
203
0
                    _sleep_response_timeout(ctx);
204
0
                    modbus_connect(ctx);
205
0
                } else {
206
0
                    _sleep_response_timeout(ctx);
207
0
                    modbus_flush(ctx);
208
0
                }
209
0
                errno = saved_errno;
210
0
#endif
211
0
            }
212
0
        }
213
0
    } while ((ctx->error_recovery & MODBUS_ERROR_RECOVERY_LINK) && rc == -1);
214
215
0
    if (rc > 0 && rc != msg_length) {
216
0
        errno = EMBBADDATA;
217
0
        return -1;
218
0
    }
219
220
0
    return rc;
221
0
}
222
223
int modbus_send_raw_request_tid(modbus_t *ctx,
224
                                const uint8_t *raw_req,
225
                                int raw_req_length,
226
                                int tid)
227
0
{
228
0
    sft_t sft;
229
0
    uint8_t req[MAX_MESSAGE_LENGTH];
230
0
    int req_length;
231
232
0
    if (ctx == NULL) {
233
0
        errno = EINVAL;
234
0
        return -1;
235
0
    }
236
237
0
    if (raw_req_length < 2 || raw_req_length > (MODBUS_MAX_PDU_LENGTH + 1)) {
238
        /* The raw request must contain function and slave at least and
239
           must not be longer than the maximum pdu length plus the slave
240
           address. */
241
0
        errno = EINVAL;
242
0
        return -1;
243
0
    }
244
245
0
    sft.slave = raw_req[0];
246
0
    sft.function = raw_req[1];
247
    /* The t_id is left to zero */
248
0
    sft.t_id = tid;
249
    /* This response function only set the header so it's convenient here */
250
0
    req_length = ctx->backend->build_response_basis(&sft, req);
251
252
0
    if (raw_req_length > 2) {
253
        /* Copy data after function code */
254
0
        memcpy(req + req_length, raw_req + 2, raw_req_length - 2);
255
0
        req_length += raw_req_length - 2;
256
0
    }
257
258
0
    return send_msg(ctx, req, req_length);
259
0
}
260
261
int modbus_send_raw_request(modbus_t *ctx, const uint8_t *raw_req, int raw_req_length)
262
0
{
263
0
    return modbus_send_raw_request_tid(ctx, raw_req, raw_req_length, 0);
264
0
}
265
266
/*
267
 *  ---------- Request     Indication ----------
268
 *  | Client | ---------------------->| Server |
269
 *  ---------- Confirmation  Response ----------
270
 */
271
272
/* Computes the length to read after the function received */
273
static uint8_t compute_meta_length_after_function(int function, msg_type_t msg_type)
274
1
{
275
1
    int length;
276
277
1
    if (msg_type == MSG_INDICATION) {
278
1
        if (function <= MODBUS_FC_WRITE_SINGLE_REGISTER) {
279
0
            length = 4;
280
1
        } else if (function == MODBUS_FC_WRITE_MULTIPLE_COILS ||
281
1
                   function == MODBUS_FC_WRITE_MULTIPLE_REGISTERS) {
282
0
            length = 5;
283
1
        } else if (function == MODBUS_FC_MASK_WRITE_REGISTER) {
284
0
            length = 6;
285
1
        } else if (function == MODBUS_FC_WRITE_AND_READ_REGISTERS) {
286
0
            length = 9;
287
1
        } else {
288
            /* MODBUS_FC_READ_EXCEPTION_STATUS, MODBUS_FC_REPORT_SLAVE_ID */
289
1
            length = 0;
290
1
        }
291
1
    } else {
292
        /* MSG_CONFIRMATION */
293
0
        switch (function) {
294
0
        case MODBUS_FC_WRITE_SINGLE_COIL:
295
0
        case MODBUS_FC_WRITE_SINGLE_REGISTER:
296
0
        case MODBUS_FC_WRITE_MULTIPLE_COILS:
297
0
        case MODBUS_FC_WRITE_MULTIPLE_REGISTERS:
298
0
            length = 4;
299
0
            break;
300
0
        case MODBUS_FC_MASK_WRITE_REGISTER:
301
0
            length = 6;
302
0
            break;
303
0
        default:
304
0
            length = 1;
305
0
        }
306
0
    }
307
308
1
    return length;
309
1
}
310
311
/* Computes the length to read after the meta information (address, count, etc) */
312
static int
313
compute_data_length_after_meta(modbus_t *ctx, uint8_t *msg, msg_type_t msg_type)
314
1
{
315
1
    int function = msg[ctx->backend->header_length];
316
1
    int length;
317
318
1
    if (msg_type == MSG_INDICATION) {
319
1
        switch (function) {
320
0
        case MODBUS_FC_WRITE_MULTIPLE_COILS:
321
0
        case MODBUS_FC_WRITE_MULTIPLE_REGISTERS:
322
0
            length = msg[ctx->backend->header_length + 5];
323
0
            break;
324
0
        case MODBUS_FC_WRITE_AND_READ_REGISTERS:
325
0
            length = msg[ctx->backend->header_length + 9];
326
0
            break;
327
1
        default:
328
1
            length = 0;
329
1
        }
330
1
    } else {
331
        /* MSG_CONFIRMATION */
332
0
        if (function <= MODBUS_FC_READ_INPUT_REGISTERS ||
333
0
            function == MODBUS_FC_REPORT_SLAVE_ID ||
334
0
            function == MODBUS_FC_WRITE_AND_READ_REGISTERS) {
335
0
            length = msg[ctx->backend->header_length + 1];
336
0
        } else {
337
0
            length = 0;
338
0
        }
339
0
    }
340
341
1
    length += ctx->backend->checksum_length;
342
343
1
    return length;
344
1
}
345
346
/* Waits a response from a modbus server or a request from a modbus client.
347
   This function blocks if there is no replies (3 timeouts).
348
349
   The function shall return the number of received characters and the received
350
   message in an array of uint8_t if successful. Otherwise it shall return -1
351
   and errno is set to one of the values defined below:
352
   - ECONNRESET
353
   - EMBBADDATA
354
   - ETIMEDOUT
355
   - read() or recv() error codes
356
*/
357
358
int _modbus_receive_msg(modbus_t *ctx, uint8_t *msg, msg_type_t msg_type)
359
1
{
360
1
    int rc;
361
1
    fd_set rset;
362
1
    struct timeval tv;
363
1
    struct timeval *p_tv;
364
1
    unsigned int length_to_read;
365
1
    int msg_length = 0;
366
1
    _step_t step;
367
#ifdef _WIN32
368
    int wsa_err;
369
#endif
370
371
1
    if (ctx->debug) {
372
0
        if (msg_type == MSG_INDICATION) {
373
0
            printf("Waiting for an indication...\n");
374
0
        } else {
375
0
            printf("Waiting for a confirmation...\n");
376
0
        }
377
0
    }
378
379
1
    if (!ctx->backend->is_connected(ctx)) {
380
0
        if (ctx->debug) {
381
0
            fprintf(stderr, "ERROR The connection is not established.\n");
382
0
        }
383
0
        return -1;
384
0
    }
385
386
    /* Add a file descriptor to the set */
387
1
    FD_ZERO(&rset);
388
1
    if (ctx->s < 0 || ctx->s >= FD_SETSIZE) {
389
0
        if (ctx->debug) {
390
0
            fprintf(stderr, "ERROR Invalid socket descriptor %d\n", ctx->s);
391
0
        }
392
0
        errno = EINVAL;
393
0
        return -1;
394
0
    }
395
1
    FD_SET(ctx->s, &rset);
396
397
    /* We need to analyse the message step by step.  At the first step, we want
398
     * to reach the function code because all packets contain this
399
     * information. */
400
1
    step = _STEP_FUNCTION;
401
1
    length_to_read = ctx->backend->header_length + 1;
402
403
1
    if (msg_type == MSG_INDICATION) {
404
        /* Wait for a message, we don't know when the message will be received */
405
1
        if (ctx->indication_timeout.tv_sec == 0 && ctx->indication_timeout.tv_usec == 0) {
406
            /* By default, the indication timeout isn't set */
407
1
            p_tv = NULL;
408
1
        } else {
409
            /* Wait for an indication (name of a received request by a server, see schema)
410
             */
411
0
            tv.tv_sec = ctx->indication_timeout.tv_sec;
412
0
            tv.tv_usec = ctx->indication_timeout.tv_usec;
413
0
            p_tv = &tv;
414
0
        }
415
1
    } else {
416
0
        tv.tv_sec = ctx->response_timeout.tv_sec;
417
0
        tv.tv_usec = ctx->response_timeout.tv_usec;
418
0
        p_tv = &tv;
419
0
    }
420
421
2
    while (length_to_read != 0) {
422
1
        rc = ctx->backend->select(ctx, &rset, p_tv, length_to_read);
423
1
        if (rc == -1) {
424
0
            _error_print(ctx, "select");
425
0
            if (ctx->error_recovery & MODBUS_ERROR_RECOVERY_LINK) {
426
#ifdef _WIN32
427
                wsa_err = WSAGetLastError();
428
429
                // no equivalent to ETIMEDOUT when select fails on Windows
430
                if (wsa_err == WSAENETDOWN || wsa_err == WSAENOTSOCK) {
431
                    modbus_close(ctx);
432
                    modbus_connect(ctx);
433
                }
434
#else
435
0
                int saved_errno = errno;
436
437
0
                if (errno == ETIMEDOUT) {
438
0
                    _sleep_response_timeout(ctx);
439
0
                    modbus_flush(ctx);
440
0
                } else if (errno == EBADF) {
441
0
                    modbus_close(ctx);
442
0
                    modbus_connect(ctx);
443
0
                }
444
0
                errno = saved_errno;
445
0
#endif
446
0
            }
447
0
            return -1;
448
0
        }
449
450
1
        rc = ctx->backend->recv(ctx, msg + msg_length, length_to_read);
451
1
        if (rc == 0) {
452
0
            errno = ECONNRESET;
453
0
            rc = -1;
454
0
        }
455
456
1
        if (rc == -1) {
457
0
            _error_print(ctx, "read");
458
#ifdef _WIN32
459
            wsa_err = WSAGetLastError();
460
            if ((ctx->error_recovery & MODBUS_ERROR_RECOVERY_LINK) &&
461
                (wsa_err == WSAENOTCONN || wsa_err == WSAENETRESET ||
462
                 wsa_err == WSAENOTSOCK || wsa_err == WSAESHUTDOWN ||
463
                 wsa_err == WSAECONNABORTED || wsa_err == WSAETIMEDOUT ||
464
                 wsa_err == WSAECONNRESET)) {
465
                modbus_close(ctx);
466
                modbus_connect(ctx);
467
            }
468
#else
469
0
            if ((ctx->error_recovery & MODBUS_ERROR_RECOVERY_LINK) &&
470
0
                (errno == ECONNRESET || errno == ECONNREFUSED || errno == EBADF)) {
471
0
                int saved_errno = errno;
472
0
                modbus_close(ctx);
473
0
                modbus_connect(ctx);
474
                /* Could be removed by previous calls */
475
0
                errno = saved_errno;
476
0
            }
477
0
#endif
478
0
            return -1;
479
0
        }
480
481
        /* Display the hex code of each character received */
482
1
        if (ctx->debug) {
483
0
            int i;
484
0
            for (i = 0; i < rc; i++)
485
0
                printf("<%.2X>", msg[msg_length + i]);
486
0
        }
487
488
        /* Sums bytes received */
489
1
        msg_length += rc;
490
        /* Computes remaining bytes */
491
1
        length_to_read -= rc;
492
493
1
        if (length_to_read == 0) {
494
1
            switch (step) {
495
1
            case _STEP_FUNCTION:
496
                /* Function code position */
497
1
                length_to_read = compute_meta_length_after_function(
498
1
                    msg[ctx->backend->header_length], msg_type);
499
1
                if (length_to_read != 0) {
500
0
                    step = _STEP_META;
501
0
                    break;
502
0
                } /* else switches straight to the next step */
503
1
            case _STEP_META:
504
1
                length_to_read = compute_data_length_after_meta(ctx, msg, msg_type);
505
1
                if ((msg_length + length_to_read) > ctx->backend->max_adu_length) {
506
0
                    errno = EMBBADDATA;
507
0
                    _error_print(ctx, "too many data");
508
0
                    return -1;
509
0
                }
510
1
                step = _STEP_DATA;
511
1
                break;
512
0
            default:
513
0
                break;
514
1
            }
515
1
        }
516
517
1
        if (length_to_read > 0 &&
518
0
            (ctx->byte_timeout.tv_sec > 0 || ctx->byte_timeout.tv_usec > 0)) {
519
            /* If there is no character in the buffer, the allowed timeout
520
               interval between two consecutive bytes is defined by
521
               byte_timeout */
522
0
            tv.tv_sec = ctx->byte_timeout.tv_sec;
523
0
            tv.tv_usec = ctx->byte_timeout.tv_usec;
524
0
            p_tv = &tv;
525
0
        }
526
        /* else timeout isn't set again, the full response must be read before
527
           expiration of response timeout (for CONFIRMATION only) */
528
1
    }
529
530
1
    if (ctx->debug)
531
0
        printf("\n");
532
533
1
    return ctx->backend->check_integrity(ctx, msg, msg_length);
534
1
}
535
536
/* Receive the request from a modbus master */
537
int modbus_receive(modbus_t *ctx, uint8_t *req)
538
1
{
539
1
    if (ctx == NULL) {
540
0
        errno = EINVAL;
541
0
        return -1;
542
0
    }
543
544
1
    return ctx->backend->receive(ctx, req);
545
1
}
546
547
/* Receives the confirmation.
548
549
   The function shall store the read response in rsp and return the number of
550
   values (bits or words). Otherwise, its shall return -1 and errno is set.
551
552
   The function doesn't check the confirmation is the expected response to the
553
   initial request.
554
*/
555
int modbus_receive_confirmation(modbus_t *ctx, uint8_t *rsp)
556
0
{
557
0
    if (ctx == NULL) {
558
0
        errno = EINVAL;
559
0
        return -1;
560
0
    }
561
562
0
    return _modbus_receive_msg(ctx, rsp, MSG_CONFIRMATION);
563
0
}
564
565
static int check_confirmation(modbus_t *ctx, uint8_t *req, uint8_t *rsp, int rsp_length)
566
0
{
567
0
    int rc;
568
0
    int rsp_length_computed;
569
0
    const unsigned int offset = ctx->backend->header_length;
570
0
    const int function = rsp[offset];
571
572
0
    if (ctx->backend->pre_check_confirmation) {
573
0
        rc = ctx->backend->pre_check_confirmation(ctx, req, rsp, rsp_length);
574
0
        if (rc == -1) {
575
0
            if (ctx->error_recovery & MODBUS_ERROR_RECOVERY_PROTOCOL) {
576
0
                _sleep_response_timeout(ctx);
577
0
                modbus_flush(ctx);
578
0
            }
579
0
            return -1;
580
0
        }
581
0
    }
582
583
0
    rsp_length_computed = compute_response_length_from_request(ctx, req);
584
585
    /* Exception code */
586
0
    if (function >= 0x80) {
587
0
        if (rsp_length == (int) (offset + 2 + ctx->backend->checksum_length) &&
588
0
            req[offset] == (rsp[offset] - 0x80)) {
589
            /* Valid exception code received */
590
591
0
            int exception_code = rsp[offset + 1];
592
0
            if (exception_code < MODBUS_EXCEPTION_MAX) {
593
0
                errno = MODBUS_ENOBASE + exception_code;
594
0
            } else {
595
0
                errno = EMBBADEXC;
596
0
            }
597
0
            _error_print(ctx, NULL);
598
0
            return -1;
599
0
        } else {
600
0
            errno = EMBBADEXC;
601
0
            _error_print(ctx, NULL);
602
0
            return -1;
603
0
        }
604
0
    }
605
606
    /* Check length */
607
0
    if ((rsp_length == rsp_length_computed ||
608
0
         rsp_length_computed == MSG_LENGTH_UNDEFINED) &&
609
0
        function < 0x80) {
610
0
        int req_nb_value;
611
0
        int rsp_nb_value;
612
0
        int resp_addr_ok = TRUE;
613
0
        int resp_data_ok = TRUE;
614
615
        /* Check function code */
616
0
        if (function != req[offset]) {
617
0
            if (ctx->debug) {
618
0
                fprintf(
619
0
                    stderr,
620
0
                    "Received function not corresponding to the request (0x%X != 0x%X)\n",
621
0
                    function,
622
0
                    req[offset]);
623
0
            }
624
0
            if (ctx->error_recovery & MODBUS_ERROR_RECOVERY_PROTOCOL) {
625
0
                _sleep_response_timeout(ctx);
626
0
                modbus_flush(ctx);
627
0
            }
628
0
            errno = EMBBADDATA;
629
0
            return -1;
630
0
        }
631
632
        /* Check the number of values is corresponding to the request */
633
0
        switch (function) {
634
0
        case MODBUS_FC_READ_COILS:
635
0
        case MODBUS_FC_READ_DISCRETE_INPUTS:
636
            /* Read functions, 8 values in a byte (nb
637
             * of values in the request and byte count in
638
             * the response. */
639
0
            req_nb_value = (req[offset + 3] << 8) + req[offset + 4];
640
0
            req_nb_value = (req_nb_value / 8) + ((req_nb_value % 8) ? 1 : 0);
641
0
            rsp_nb_value = rsp[offset + 1];
642
0
            break;
643
0
        case MODBUS_FC_WRITE_AND_READ_REGISTERS:
644
0
        case MODBUS_FC_READ_HOLDING_REGISTERS:
645
0
        case MODBUS_FC_READ_INPUT_REGISTERS:
646
            /* Read functions 1 value = 2 bytes */
647
0
            req_nb_value = (req[offset + 3] << 8) + req[offset + 4];
648
0
            rsp_nb_value = (rsp[offset + 1] / 2);
649
0
            break;
650
0
        case MODBUS_FC_WRITE_MULTIPLE_COILS:
651
0
        case MODBUS_FC_WRITE_MULTIPLE_REGISTERS:
652
            /* address in request and response must be equal */
653
0
            if ((req[offset + 1] != rsp[offset + 1]) ||
654
0
                (req[offset + 2] != rsp[offset + 2])) {
655
0
                resp_addr_ok = FALSE;
656
0
            }
657
            /* N Write functions */
658
0
            req_nb_value = (req[offset + 3] << 8) + req[offset + 4];
659
0
            rsp_nb_value = (rsp[offset + 3] << 8) | rsp[offset + 4];
660
0
            break;
661
0
        case MODBUS_FC_REPORT_SLAVE_ID:
662
            /* Report slave ID (bytes received) */
663
0
            req_nb_value = rsp_nb_value = rsp[offset + 1];
664
0
            break;
665
0
        case MODBUS_FC_WRITE_SINGLE_COIL:
666
0
        case MODBUS_FC_WRITE_SINGLE_REGISTER:
667
            /* address in request and response must be equal */
668
0
            if ((req[offset + 1] != rsp[offset + 1]) ||
669
0
                (req[offset + 2] != rsp[offset + 2])) {
670
0
                resp_addr_ok = FALSE;
671
0
            }
672
            /* data in request and response must be equal */
673
0
            if ((req[offset + 3] != rsp[offset + 3]) ||
674
0
                (req[offset + 4] != rsp[offset + 4])) {
675
0
                resp_data_ok = FALSE;
676
0
            }
677
            /* 1 Write functions & others */
678
0
            req_nb_value = rsp_nb_value = 1;
679
0
            break;
680
0
        default:
681
            /* 1 Write functions & others */
682
0
            req_nb_value = rsp_nb_value = 1;
683
0
            break;
684
0
        }
685
686
0
        if ((req_nb_value == rsp_nb_value) && (resp_addr_ok == TRUE) &&
687
0
            (resp_data_ok == TRUE)) {
688
0
            rc = rsp_nb_value;
689
0
        } else {
690
0
            if (ctx->debug) {
691
0
                fprintf(stderr,
692
0
                        "Received data not corresponding to the request (%d != %d)\n",
693
0
                        rsp_nb_value,
694
0
                        req_nb_value);
695
0
            }
696
697
0
            if (ctx->error_recovery & MODBUS_ERROR_RECOVERY_PROTOCOL) {
698
0
                _sleep_response_timeout(ctx);
699
0
                modbus_flush(ctx);
700
0
            }
701
702
0
            errno = EMBBADDATA;
703
0
            rc = -1;
704
0
        }
705
0
    } else {
706
0
        if (ctx->debug) {
707
0
            fprintf(
708
0
                stderr,
709
0
                "Message length not corresponding to the computed length (%d != %d)\n",
710
0
                rsp_length,
711
0
                rsp_length_computed);
712
0
        }
713
0
        if (ctx->error_recovery & MODBUS_ERROR_RECOVERY_PROTOCOL) {
714
0
            _sleep_response_timeout(ctx);
715
0
            modbus_flush(ctx);
716
0
        }
717
0
        errno = EMBBADDATA;
718
0
        rc = -1;
719
0
    }
720
721
0
    return rc;
722
0
}
723
724
static int
725
response_io_status(uint8_t *tab_io_status, int address, int nb, uint8_t *rsp, int offset)
726
0
{
727
0
    int shift = 0;
728
    /* Instead of byte (not allowed in Win32) */
729
0
    int one_byte = 0;
730
0
    int i;
731
732
0
    for (i = address; i < address + nb; i++) {
733
0
        one_byte |= tab_io_status[i] << shift;
734
0
        if (shift == 7) {
735
            /* Byte is full */
736
0
            rsp[offset++] = one_byte;
737
0
            one_byte = shift = 0;
738
0
        } else {
739
0
            shift++;
740
0
        }
741
0
    }
742
743
0
    if (shift != 0)
744
0
        rsp[offset++] = one_byte;
745
746
0
    return offset;
747
0
}
748
749
/* Build the exception response */
750
static int response_exception(modbus_t *ctx,
751
                              sft_t *sft,
752
                              int exception_code,
753
                              uint8_t *rsp,
754
                              unsigned int to_flush,
755
                              const char *template,
756
                              ...)
757
0
{
758
0
    int rsp_length;
759
760
    /* Print debug message */
761
0
    if (ctx->debug) {
762
0
        va_list ap;
763
764
0
        va_start(ap, template);
765
0
        vfprintf(stderr, template, ap);
766
0
        va_end(ap);
767
0
    }
768
769
    /* Flush if required */
770
0
    if (to_flush) {
771
0
        _sleep_response_timeout(ctx);
772
0
        modbus_flush(ctx);
773
0
    }
774
775
    /* Build exception response */
776
0
    sft->function = sft->function + 0x80;
777
0
    rsp_length = ctx->backend->build_response_basis(sft, rsp);
778
0
    rsp[rsp_length++] = exception_code;
779
780
0
    return rsp_length;
781
0
}
782
783
/* Send a response to the received request.
784
   Analyses the request and constructs a response.
785
786
   If an error occurs, this function construct the response
787
   accordingly.
788
*/
789
int modbus_reply(modbus_t *ctx,
790
                 const uint8_t *req,
791
                 int req_length,
792
                 modbus_mapping_t *mb_mapping)
793
0
{
794
0
    unsigned int offset;
795
0
    int slave;
796
0
    int function;
797
0
    uint16_t address;
798
0
    uint8_t rsp[MAX_MESSAGE_LENGTH];
799
0
    int rsp_length = 0;
800
0
    sft_t sft;
801
802
0
    if (ctx == NULL) {
803
0
        errno = EINVAL;
804
0
        return -1;
805
0
    }
806
807
0
    offset = ctx->backend->header_length;
808
0
    slave = req[offset - 1];
809
0
    function = req[offset];
810
811
    /* Some function codes (eg. FC_READ_EXCEPTION_STATUS, FC_REPORT_SLAVE_ID)
812
       carry no address in the request PDU, so only read when available. Reading
813
       them is safe as it fits within MODBUS_MAX_ADU_LENGTH, it's just for
814
       coherency.
815
    */
816
0
    if (req_length >= (int) (offset + 3))
817
0
        address = (req[offset + 1] << 8) + req[offset + 2];
818
0
    else
819
0
        address = 0;
820
821
0
    sft.slave = slave;
822
0
    sft.function = function;
823
0
    sft.t_id = ctx->backend->get_response_tid(req);
824
825
    /* Data are flushed on illegal number of values errors. */
826
0
    switch (function) {
827
0
    case MODBUS_FC_READ_COILS:
828
0
    case MODBUS_FC_READ_DISCRETE_INPUTS: {
829
0
        unsigned int is_input = (function == MODBUS_FC_READ_DISCRETE_INPUTS);
830
0
        int start_bits = is_input ? mb_mapping->start_input_bits : mb_mapping->start_bits;
831
0
        int nb_bits = is_input ? mb_mapping->nb_input_bits : mb_mapping->nb_bits;
832
0
        uint8_t *tab_bits = is_input ? mb_mapping->tab_input_bits : mb_mapping->tab_bits;
833
0
        const char *const name = is_input ? "read_input_bits" : "read_bits";
834
0
        int nb = (req[offset + 3] << 8) + req[offset + 4];
835
        /* The mapping can be shifted to reduce memory consumption and it
836
           doesn't always start at address zero. */
837
0
        int mapping_address = address - start_bits;
838
839
0
        if (nb < 1 || MODBUS_MAX_READ_BITS < nb) {
840
0
            rsp_length = response_exception(ctx,
841
0
                                            &sft,
842
0
                                            MODBUS_EXCEPTION_ILLEGAL_DATA_VALUE,
843
0
                                            rsp,
844
0
                                            TRUE,
845
0
                                            "Illegal nb of values %d in %s (max %d)\n",
846
0
                                            nb,
847
0
                                            name,
848
0
                                            MODBUS_MAX_READ_BITS);
849
0
        } else if (mapping_address < 0 || (mapping_address + nb) > nb_bits) {
850
0
            rsp_length = response_exception(ctx,
851
0
                                            &sft,
852
0
                                            MODBUS_EXCEPTION_ILLEGAL_DATA_ADDRESS,
853
0
                                            rsp,
854
0
                                            FALSE,
855
0
                                            "Illegal data address 0x%0X in %s\n",
856
0
                                            mapping_address < 0 ? address : address + nb,
857
0
                                            name);
858
0
        } else {
859
0
            rsp_length = ctx->backend->build_response_basis(&sft, rsp);
860
0
            rsp[rsp_length++] = (nb / 8) + ((nb % 8) ? 1 : 0);
861
0
            rsp_length =
862
0
                response_io_status(tab_bits, mapping_address, nb, rsp, rsp_length);
863
0
        }
864
0
    } break;
865
0
    case MODBUS_FC_READ_HOLDING_REGISTERS:
866
0
    case MODBUS_FC_READ_INPUT_REGISTERS: {
867
0
        unsigned int is_input = (function == MODBUS_FC_READ_INPUT_REGISTERS);
868
0
        int start_registers =
869
0
            is_input ? mb_mapping->start_input_registers : mb_mapping->start_registers;
870
0
        int nb_registers =
871
0
            is_input ? mb_mapping->nb_input_registers : mb_mapping->nb_registers;
872
0
        uint16_t *tab_registers =
873
0
            is_input ? mb_mapping->tab_input_registers : mb_mapping->tab_registers;
874
0
        const char *const name = is_input ? "read_input_registers" : "read_registers";
875
0
        int nb = (req[offset + 3] << 8) + req[offset + 4];
876
        /* The mapping can be shifted to reduce memory consumption and it
877
           doesn't always start at address zero. */
878
0
        int mapping_address = address - start_registers;
879
880
0
        if (nb < 1 || MODBUS_MAX_READ_REGISTERS < nb) {
881
0
            rsp_length = response_exception(ctx,
882
0
                                            &sft,
883
0
                                            MODBUS_EXCEPTION_ILLEGAL_DATA_VALUE,
884
0
                                            rsp,
885
0
                                            TRUE,
886
0
                                            "Illegal nb of values %d in %s (max %d)\n",
887
0
                                            nb,
888
0
                                            name,
889
0
                                            MODBUS_MAX_READ_REGISTERS);
890
0
        } else if (mapping_address < 0 || (mapping_address + nb) > nb_registers) {
891
0
            rsp_length = response_exception(ctx,
892
0
                                            &sft,
893
0
                                            MODBUS_EXCEPTION_ILLEGAL_DATA_ADDRESS,
894
0
                                            rsp,
895
0
                                            FALSE,
896
0
                                            "Illegal data address 0x%0X in %s\n",
897
0
                                            mapping_address < 0 ? address : address + nb,
898
0
                                            name);
899
0
        } else {
900
0
            int i;
901
902
0
            rsp_length = ctx->backend->build_response_basis(&sft, rsp);
903
0
            rsp[rsp_length++] = nb << 1;
904
0
            for (i = mapping_address; i < mapping_address + nb; i++) {
905
0
                rsp[rsp_length++] = tab_registers[i] >> 8;
906
0
                rsp[rsp_length++] = tab_registers[i] & 0xFF;
907
0
            }
908
0
        }
909
0
    } break;
910
0
    case MODBUS_FC_WRITE_SINGLE_COIL: {
911
0
        int mapping_address = address - mb_mapping->start_bits;
912
913
0
        if (mapping_address < 0 || mapping_address >= mb_mapping->nb_bits) {
914
0
            rsp_length = response_exception(ctx,
915
0
                                            &sft,
916
0
                                            MODBUS_EXCEPTION_ILLEGAL_DATA_ADDRESS,
917
0
                                            rsp,
918
0
                                            FALSE,
919
0
                                            "Illegal data address 0x%0X in write bit\n",
920
0
                                            address);
921
0
            break;
922
0
        }
923
924
        /* This check is only done here to ensure using memcpy is safe. */
925
0
        rsp_length = compute_response_length_from_request(ctx, (uint8_t *) req);
926
0
        if (rsp_length != req_length) {
927
            /* Bad use of modbus_reply */
928
0
            rsp_length = response_exception(
929
0
                ctx,
930
0
                &sft,
931
0
                MODBUS_EXCEPTION_ILLEGAL_DATA_VALUE,
932
0
                rsp,
933
0
                FALSE,
934
0
                "Invalid request length in modbus_reply to write bit (%d)\n",
935
0
                req_length);
936
0
            break;
937
0
        }
938
939
        /* Don't copy the CRC, if any, it will be computed later (even if identical to the
940
         * request) */
941
0
        rsp_length -= ctx->backend->checksum_length;
942
943
0
        int data = (req[offset + 3] << 8) + req[offset + 4];
944
0
        if (data == 0xFF00 || data == 0x0) {
945
            /* Apply the change to mapping */
946
0
            mb_mapping->tab_bits[mapping_address] = data ? ON : OFF;
947
            /* Prepare response */
948
0
            memcpy(rsp, req, rsp_length);
949
0
        } else {
950
0
            rsp_length = response_exception(
951
0
                ctx,
952
0
                &sft,
953
0
                MODBUS_EXCEPTION_ILLEGAL_DATA_VALUE,
954
0
                rsp,
955
0
                FALSE,
956
0
                "Illegal data value 0x%0X in write_bit request at address %0X\n",
957
0
                data,
958
0
                address);
959
0
        }
960
0
    } break;
961
0
    case MODBUS_FC_WRITE_SINGLE_REGISTER: {
962
0
        int mapping_address = address - mb_mapping->start_registers;
963
964
0
        if (mapping_address < 0 || mapping_address >= mb_mapping->nb_registers) {
965
0
            rsp_length =
966
0
                response_exception(ctx,
967
0
                                   &sft,
968
0
                                   MODBUS_EXCEPTION_ILLEGAL_DATA_ADDRESS,
969
0
                                   rsp,
970
0
                                   FALSE,
971
0
                                   "Illegal data address 0x%0X in write_register\n",
972
0
                                   address);
973
0
            break;
974
0
        }
975
976
0
        rsp_length = compute_response_length_from_request(ctx, (uint8_t *) req);
977
0
        if (rsp_length != req_length) {
978
            /* Bad use of modbus_reply */
979
0
            rsp_length = response_exception(
980
0
                ctx,
981
0
                &sft,
982
0
                MODBUS_EXCEPTION_ILLEGAL_DATA_VALUE,
983
0
                rsp,
984
0
                FALSE,
985
0
                "Invalid request length in modbus_reply to write register (%d)\n",
986
0
                req_length);
987
0
            break;
988
0
        }
989
0
        int data = (req[offset + 3] << 8) + req[offset + 4];
990
991
0
        mb_mapping->tab_registers[mapping_address] = data;
992
993
0
        rsp_length -= ctx->backend->checksum_length;
994
0
        memcpy(rsp, req, rsp_length);
995
0
    } break;
996
0
    case MODBUS_FC_WRITE_MULTIPLE_COILS: {
997
0
        int nb = (req[offset + 3] << 8) + req[offset + 4];
998
0
        int nb_bits = req[offset + 5];
999
0
        int mapping_address = address - mb_mapping->start_bits;
1000
1001
0
        if (nb < 1 || MODBUS_MAX_WRITE_BITS < nb || nb_bits * 8 < nb) {
1002
            /* May be the indication has been truncated on reading because of
1003
             * invalid address (eg. nb is 0 but the request contains values to
1004
             * write) so it's necessary to flush. */
1005
0
            rsp_length =
1006
0
                response_exception(ctx,
1007
0
                                   &sft,
1008
0
                                   MODBUS_EXCEPTION_ILLEGAL_DATA_VALUE,
1009
0
                                   rsp,
1010
0
                                   TRUE,
1011
0
                                   "Illegal number of values %d in write_bits (max %d)\n",
1012
0
                                   nb,
1013
0
                                   MODBUS_MAX_WRITE_BITS);
1014
0
        } else if (mapping_address < 0 || (mapping_address + nb) > mb_mapping->nb_bits) {
1015
0
            rsp_length = response_exception(ctx,
1016
0
                                            &sft,
1017
0
                                            MODBUS_EXCEPTION_ILLEGAL_DATA_ADDRESS,
1018
0
                                            rsp,
1019
0
                                            FALSE,
1020
0
                                            "Illegal data address 0x%0X in write_bits\n",
1021
0
                                            mapping_address < 0 ? address : address + nb);
1022
0
        } else {
1023
            /* 6 = byte count */
1024
0
            modbus_set_bits_from_bytes(
1025
0
                mb_mapping->tab_bits, mapping_address, nb, &req[offset + 6]);
1026
1027
0
            rsp_length = ctx->backend->build_response_basis(&sft, rsp);
1028
            /* 4 to copy the bit address (2) and the quantity of bits */
1029
0
            memcpy(rsp + rsp_length, req + rsp_length, 4);
1030
0
            rsp_length += 4;
1031
0
        }
1032
0
    } break;
1033
0
    case MODBUS_FC_WRITE_MULTIPLE_REGISTERS: {
1034
0
        int nb = (req[offset + 3] << 8) + req[offset + 4];
1035
0
        int nb_bytes = req[offset + 5];
1036
0
        int mapping_address = address - mb_mapping->start_registers;
1037
1038
0
        if (nb < 1 || MODBUS_MAX_WRITE_REGISTERS < nb || nb_bytes != nb * 2) {
1039
0
            rsp_length = response_exception(
1040
0
                ctx,
1041
0
                &sft,
1042
0
                MODBUS_EXCEPTION_ILLEGAL_DATA_VALUE,
1043
0
                rsp,
1044
0
                TRUE,
1045
0
                "Illegal number of values %d in write_registers (max %d)\n",
1046
0
                nb,
1047
0
                MODBUS_MAX_WRITE_REGISTERS);
1048
0
        } else if (mapping_address < 0 ||
1049
0
                   (mapping_address + nb) > mb_mapping->nb_registers) {
1050
0
            rsp_length =
1051
0
                response_exception(ctx,
1052
0
                                   &sft,
1053
0
                                   MODBUS_EXCEPTION_ILLEGAL_DATA_ADDRESS,
1054
0
                                   rsp,
1055
0
                                   FALSE,
1056
0
                                   "Illegal data address 0x%0X in write_registers\n",
1057
0
                                   mapping_address < 0 ? address : address + nb);
1058
0
        } else {
1059
0
            int i, j;
1060
0
            for (i = mapping_address, j = 6; i < mapping_address + nb; i++, j += 2) {
1061
                /* 6 and 7 = first value */
1062
0
                mb_mapping->tab_registers[i] =
1063
0
                    (req[offset + j] << 8) + req[offset + j + 1];
1064
0
            }
1065
1066
0
            rsp_length = ctx->backend->build_response_basis(&sft, rsp);
1067
            /* 4 to copy the address (2) and the no. of registers */
1068
0
            memcpy(rsp + rsp_length, req + rsp_length, 4);
1069
0
            rsp_length += 4;
1070
0
        }
1071
0
    } break;
1072
0
    case MODBUS_FC_REPORT_SLAVE_ID: {
1073
0
        int str_len;
1074
0
        int byte_count_pos;
1075
1076
0
        rsp_length = ctx->backend->build_response_basis(&sft, rsp);
1077
        /* Skip byte count for now */
1078
0
        byte_count_pos = rsp_length++;
1079
0
        rsp[rsp_length++] = _REPORT_SLAVE_ID;
1080
        /* Run indicator status to ON */
1081
0
        rsp[rsp_length++] = 0xFF;
1082
        /* LMB + length of LIBMODBUS_VERSION_STRING */
1083
0
        str_len = 3 + strlen(LIBMODBUS_VERSION_STRING);
1084
0
        memcpy(rsp + rsp_length, "LMB" LIBMODBUS_VERSION_STRING, str_len);
1085
0
        rsp_length += str_len;
1086
0
        rsp[byte_count_pos] = rsp_length - byte_count_pos - 1;
1087
0
    } break;
1088
0
    case MODBUS_FC_READ_EXCEPTION_STATUS:
1089
0
        rsp_length = response_exception(ctx,
1090
0
                                        &sft,
1091
0
                                        MODBUS_EXCEPTION_ILLEGAL_FUNCTION,
1092
0
                                        rsp,
1093
0
                                        TRUE,
1094
0
                                        "Unsupported function: READ EXCEPTION STATUS (0x07)\n");
1095
0
        break;
1096
0
    case MODBUS_FC_MASK_WRITE_REGISTER: {
1097
0
        int mapping_address = address - mb_mapping->start_registers;
1098
1099
0
        if (mapping_address < 0 || mapping_address >= mb_mapping->nb_registers) {
1100
0
            rsp_length =
1101
0
                response_exception(ctx,
1102
0
                                   &sft,
1103
0
                                   MODBUS_EXCEPTION_ILLEGAL_DATA_ADDRESS,
1104
0
                                   rsp,
1105
0
                                   FALSE,
1106
0
                                   "Illegal data address 0x%0X in write_register\n",
1107
0
                                   address);
1108
0
        } else {
1109
0
            uint16_t data = mb_mapping->tab_registers[mapping_address];
1110
0
            uint16_t and = (req[offset + 3] << 8) + req[offset + 4];
1111
0
            uint16_t or = (req[offset + 5] << 8) + req[offset + 6];
1112
1113
0
            data = (data & and) | (or & (~and));
1114
0
            mb_mapping->tab_registers[mapping_address] = data;
1115
1116
0
            rsp_length = compute_response_length_from_request(ctx, (uint8_t *) req);
1117
0
            if (rsp_length != req_length) {
1118
                /* Bad use of modbus_reply */
1119
0
                rsp_length = response_exception(ctx,
1120
0
                                                &sft,
1121
0
                                                MODBUS_EXCEPTION_ILLEGAL_DATA_VALUE,
1122
0
                                                rsp,
1123
0
                                                FALSE,
1124
0
                                                "Invalid request length in modbus_reply "
1125
0
                                                "to mask write register (%d)\n",
1126
0
                                                req_length);
1127
0
                break;
1128
0
            }
1129
1130
0
            rsp_length -= ctx->backend->checksum_length;
1131
0
            memcpy(rsp, req, rsp_length);
1132
0
        }
1133
0
    } break;
1134
0
    case MODBUS_FC_WRITE_AND_READ_REGISTERS: {
1135
0
        int nb = (req[offset + 3] << 8) + req[offset + 4];
1136
0
        uint16_t address_write = (req[offset + 5] << 8) + req[offset + 6];
1137
0
        int nb_write = (req[offset + 7] << 8) + req[offset + 8];
1138
0
        int nb_write_bytes = req[offset + 9];
1139
0
        int mapping_address = address - mb_mapping->start_registers;
1140
0
        int mapping_address_write = address_write - mb_mapping->start_registers;
1141
1142
0
        if (nb_write < 1 || MODBUS_MAX_WR_WRITE_REGISTERS < nb_write || nb < 1 ||
1143
0
            MODBUS_MAX_WR_READ_REGISTERS < nb || nb_write_bytes != nb_write * 2) {
1144
0
            rsp_length = response_exception(
1145
0
                ctx,
1146
0
                &sft,
1147
0
                MODBUS_EXCEPTION_ILLEGAL_DATA_VALUE,
1148
0
                rsp,
1149
0
                TRUE,
1150
0
                "Illegal nb of values (W%d, R%d) in write_and_read_registers (max W%d, "
1151
0
                "R%d)\n",
1152
0
                nb_write,
1153
0
                nb,
1154
0
                MODBUS_MAX_WR_WRITE_REGISTERS,
1155
0
                MODBUS_MAX_WR_READ_REGISTERS);
1156
0
        } else if (mapping_address < 0 ||
1157
0
                   (mapping_address + nb) > mb_mapping->nb_registers ||
1158
0
                   mapping_address_write < 0 ||
1159
0
                   (mapping_address_write + nb_write) > mb_mapping->nb_registers) {
1160
0
            rsp_length = response_exception(
1161
0
                ctx,
1162
0
                &sft,
1163
0
                MODBUS_EXCEPTION_ILLEGAL_DATA_ADDRESS,
1164
0
                rsp,
1165
0
                FALSE,
1166
0
                "Illegal data read address 0x%0X or write address 0x%0X "
1167
0
                "write_and_read_registers\n",
1168
0
                mapping_address < 0 ? address : address + nb,
1169
0
                mapping_address_write < 0 ? address_write : address_write + nb_write);
1170
0
        } else {
1171
0
            int i, j;
1172
0
            rsp_length = ctx->backend->build_response_basis(&sft, rsp);
1173
0
            rsp[rsp_length++] = nb << 1;
1174
1175
            /* Write first.
1176
               10 and 11 are the offset of the first values to write */
1177
0
            for (i = mapping_address_write, j = 10; i < mapping_address_write + nb_write;
1178
0
                 i++, j += 2) {
1179
0
                mb_mapping->tab_registers[i] =
1180
0
                    (req[offset + j] << 8) + req[offset + j + 1];
1181
0
            }
1182
1183
            /* and read the data for the response */
1184
0
            for (i = mapping_address; i < mapping_address + nb; i++) {
1185
0
                rsp[rsp_length++] = mb_mapping->tab_registers[i] >> 8;
1186
0
                rsp[rsp_length++] = mb_mapping->tab_registers[i] & 0xFF;
1187
0
            }
1188
0
        }
1189
0
    } break;
1190
1191
0
    default:
1192
0
        rsp_length = response_exception(ctx,
1193
0
                                        &sft,
1194
0
                                        MODBUS_EXCEPTION_ILLEGAL_FUNCTION,
1195
0
                                        rsp,
1196
0
                                        TRUE,
1197
0
                                        "Unknown Modbus function code: 0x%0X\n",
1198
0
                                        function);
1199
0
        break;
1200
0
    }
1201
1202
    /* Suppress any responses in RTU when the request was a broadcast, excepted when
1203
     * quirk is enabled. */
1204
0
    if (ctx->backend->backend_type == _MODBUS_BACKEND_TYPE_RTU &&
1205
0
        slave == MODBUS_BROADCAST_ADDRESS &&
1206
0
        !(ctx->quirks & MODBUS_QUIRK_REPLY_TO_BROADCAST)) {
1207
0
        return 0;
1208
0
    }
1209
0
    return send_msg(ctx, rsp, rsp_length);
1210
0
}
1211
1212
int modbus_reply_exception(modbus_t *ctx, const uint8_t *req, unsigned int exception_code)
1213
0
{
1214
0
    unsigned int offset;
1215
0
    int slave;
1216
0
    int function;
1217
0
    uint8_t rsp[MAX_MESSAGE_LENGTH];
1218
0
    int rsp_length;
1219
0
    sft_t sft;
1220
1221
0
    if (ctx == NULL) {
1222
0
        errno = EINVAL;
1223
0
        return -1;
1224
0
    }
1225
1226
0
    offset = ctx->backend->header_length;
1227
0
    slave = req[offset - 1];
1228
0
    function = req[offset];
1229
1230
0
    sft.slave = slave;
1231
0
    sft.function = function + 0x80;
1232
0
    sft.t_id = ctx->backend->get_response_tid(req);
1233
0
    rsp_length = ctx->backend->build_response_basis(&sft, rsp);
1234
1235
    /* Positive exception code */
1236
0
    if (exception_code < MODBUS_EXCEPTION_MAX) {
1237
0
        rsp[rsp_length++] = exception_code;
1238
0
        return send_msg(ctx, rsp, rsp_length);
1239
0
    } else {
1240
0
        errno = EINVAL;
1241
0
        return -1;
1242
0
    }
1243
0
}
1244
1245
/* Reads IO status */
1246
static int read_io_status(modbus_t *ctx, int function, int addr, int nb, uint8_t *dest)
1247
0
{
1248
0
    int rc;
1249
0
    int req_length;
1250
1251
0
    uint8_t req[_MIN_REQ_LENGTH];
1252
0
    uint8_t rsp[MAX_MESSAGE_LENGTH];
1253
1254
0
    req_length = ctx->backend->build_request_basis(ctx, function, addr, nb, req);
1255
1256
0
    rc = send_msg(ctx, req, req_length);
1257
0
    if (rc > 0) {
1258
0
        int temp, bit;
1259
0
        int pos = 0;
1260
0
        unsigned int offset;
1261
0
        unsigned int offset_end;
1262
0
        unsigned int i;
1263
1264
0
        rc = _modbus_receive_msg(ctx, rsp, MSG_CONFIRMATION);
1265
0
        if (rc == -1)
1266
0
            return -1;
1267
1268
0
        rc = check_confirmation(ctx, req, rsp, rc);
1269
0
        if (rc == -1)
1270
0
            return -1;
1271
1272
0
        offset = ctx->backend->header_length + 2;
1273
0
        offset_end = offset + rc;
1274
0
        for (i = offset; i < offset_end; i++) {
1275
            /* Shift reg hi_byte to temp */
1276
0
            temp = rsp[i];
1277
1278
0
            for (bit = 0x01; (bit & 0xff) && (pos < nb);) {
1279
0
                dest[pos++] = (temp & bit) ? TRUE : FALSE;
1280
0
                bit = bit << 1;
1281
0
            }
1282
0
        }
1283
0
    }
1284
1285
0
    return rc;
1286
0
}
1287
1288
/* Reads the boolean status of bits and sets the array elements
1289
   in the destination to TRUE or FALSE (single bits). */
1290
int modbus_read_bits(modbus_t *ctx, int addr, int nb, uint8_t *dest)
1291
0
{
1292
0
    int rc;
1293
1294
0
    if (ctx == NULL || dest == NULL) {
1295
0
        errno = EINVAL;
1296
0
        return -1;
1297
0
    }
1298
1299
0
    if (nb < 1 || nb > MODBUS_MAX_READ_BITS) {
1300
0
        if (ctx->debug) {
1301
0
            fprintf(stderr,
1302
0
                    "ERROR Too many bits requested (%d > %d)\n",
1303
0
                    nb,
1304
0
                    MODBUS_MAX_READ_BITS);
1305
0
        }
1306
0
        errno = EMBXILVAL;
1307
0
        return -1;
1308
0
    }
1309
1310
0
    rc = read_io_status(ctx, MODBUS_FC_READ_COILS, addr, nb, dest);
1311
1312
0
    if (rc == -1)
1313
0
        return -1;
1314
0
    else
1315
0
        return nb;
1316
0
}
1317
1318
/* Same as modbus_read_bits but reads the remote device input table */
1319
int modbus_read_input_bits(modbus_t *ctx, int addr, int nb, uint8_t *dest)
1320
0
{
1321
0
    int rc;
1322
1323
0
    if (ctx == NULL || dest == NULL) {
1324
0
        errno = EINVAL;
1325
0
        return -1;
1326
0
    }
1327
1328
0
    if (nb < 1 || nb > MODBUS_MAX_READ_BITS) {
1329
0
        if (ctx->debug) {
1330
0
            fprintf(stderr,
1331
0
                    "ERROR Too many discrete inputs requested (%d > %d)\n",
1332
0
                    nb,
1333
0
                    MODBUS_MAX_READ_BITS);
1334
0
        }
1335
0
        errno = EMBXILVAL;
1336
0
        return -1;
1337
0
    }
1338
1339
0
    rc = read_io_status(ctx, MODBUS_FC_READ_DISCRETE_INPUTS, addr, nb, dest);
1340
1341
0
    if (rc == -1)
1342
0
        return -1;
1343
0
    else
1344
0
        return nb;
1345
0
}
1346
1347
/* Reads the data from a remote device and put that data into an array */
1348
static int read_registers(modbus_t *ctx, int function, int addr, int nb, uint16_t *dest)
1349
0
{
1350
0
    int rc;
1351
0
    int req_length;
1352
0
    uint8_t req[_MIN_REQ_LENGTH];
1353
0
    uint8_t rsp[MAX_MESSAGE_LENGTH];
1354
1355
0
    if (nb > MODBUS_MAX_READ_REGISTERS) {
1356
0
        if (ctx->debug) {
1357
0
            fprintf(stderr,
1358
0
                    "ERROR Too many registers requested (%d > %d)\n",
1359
0
                    nb,
1360
0
                    MODBUS_MAX_READ_REGISTERS);
1361
0
        }
1362
0
        errno = EMBXILVAL;
1363
0
        return -1;
1364
0
    }
1365
1366
0
    req_length = ctx->backend->build_request_basis(ctx, function, addr, nb, req);
1367
1368
0
    rc = send_msg(ctx, req, req_length);
1369
0
    if (rc > 0) {
1370
0
        unsigned int offset;
1371
0
        int i;
1372
1373
0
        rc = _modbus_receive_msg(ctx, rsp, MSG_CONFIRMATION);
1374
0
        if (rc == -1)
1375
0
            return -1;
1376
1377
0
        rc = check_confirmation(ctx, req, rsp, rc);
1378
0
        if (rc == -1)
1379
0
            return -1;
1380
1381
0
        offset = ctx->backend->header_length;
1382
1383
0
        for (i = 0; i < rc; i++) {
1384
            /* shift reg hi_byte to temp OR with lo_byte */
1385
0
            dest[i] = (rsp[offset + 2 + (i << 1)] << 8) | rsp[offset + 3 + (i << 1)];
1386
0
        }
1387
0
    }
1388
1389
0
    return rc;
1390
0
}
1391
1392
/* Reads the holding registers of remote device and put the data into an
1393
   array */
1394
int modbus_read_registers(modbus_t *ctx, int addr, int nb, uint16_t *dest)
1395
0
{
1396
0
    int status;
1397
1398
0
    if (ctx == NULL || dest == NULL) {
1399
0
        errno = EINVAL;
1400
0
        return -1;
1401
0
    }
1402
1403
0
    if (nb < 1 || nb > MODBUS_MAX_READ_REGISTERS) {
1404
0
        if (ctx->debug) {
1405
0
            fprintf(stderr,
1406
0
                    "ERROR Too many registers requested (%d > %d)\n",
1407
0
                    nb,
1408
0
                    MODBUS_MAX_READ_REGISTERS);
1409
0
        }
1410
0
        errno = EMBXILVAL;
1411
0
        return -1;
1412
0
    }
1413
1414
0
    status = read_registers(ctx, MODBUS_FC_READ_HOLDING_REGISTERS, addr, nb, dest);
1415
0
    return status;
1416
0
}
1417
1418
/* Reads the input registers of remote device and put the data into an array */
1419
int modbus_read_input_registers(modbus_t *ctx, int addr, int nb, uint16_t *dest)
1420
0
{
1421
0
    int status;
1422
1423
0
    if (ctx == NULL || dest == NULL) {
1424
0
        errno = EINVAL;
1425
0
        return -1;
1426
0
    }
1427
1428
0
    if (nb < 1 || nb > MODBUS_MAX_READ_REGISTERS) {
1429
0
        if (ctx->debug) {
1430
0
            fprintf(stderr,
1431
0
                    "ERROR Too many input registers requested (%d > %d)\n",
1432
0
                    nb,
1433
0
                    MODBUS_MAX_READ_REGISTERS);
1434
0
        }
1435
0
        errno = EMBXILVAL;
1436
0
        return -1;
1437
0
    }
1438
1439
0
    status = read_registers(ctx, MODBUS_FC_READ_INPUT_REGISTERS, addr, nb, dest);
1440
1441
0
    return status;
1442
0
}
1443
1444
/* Write a value to the specified register of the remote device.
1445
   Used by write_bit and write_register */
1446
static int write_single(modbus_t *ctx, int function, int addr, const uint16_t value)
1447
0
{
1448
0
    int rc;
1449
0
    int req_length;
1450
0
    uint8_t req[_MIN_REQ_LENGTH];
1451
1452
0
    if (ctx == NULL) {
1453
0
        errno = EINVAL;
1454
0
        return -1;
1455
0
    }
1456
1457
0
    req_length = ctx->backend->build_request_basis(ctx, function, addr, (int) value, req);
1458
1459
0
    rc = send_msg(ctx, req, req_length);
1460
0
    if (rc > 0) {
1461
        /* Used by write_bit and write_register */
1462
0
        uint8_t rsp[MAX_MESSAGE_LENGTH];
1463
1464
0
        rc = _modbus_receive_msg(ctx, rsp, MSG_CONFIRMATION);
1465
0
        if (rc == -1)
1466
0
            return -1;
1467
1468
0
        rc = check_confirmation(ctx, req, rsp, rc);
1469
0
    }
1470
1471
0
    return rc;
1472
0
}
1473
1474
/* Turns ON or OFF a single bit of the remote device */
1475
int modbus_write_bit(modbus_t *ctx, int addr, int status)
1476
0
{
1477
0
    if (ctx == NULL) {
1478
0
        errno = EINVAL;
1479
0
        return -1;
1480
0
    }
1481
1482
0
    return write_single(ctx, MODBUS_FC_WRITE_SINGLE_COIL, addr, status ? 0xFF00 : 0);
1483
0
}
1484
1485
/* Writes a value in one register of the remote device */
1486
int modbus_write_register(modbus_t *ctx, int addr, const uint16_t value)
1487
0
{
1488
0
    if (ctx == NULL) {
1489
0
        errno = EINVAL;
1490
0
        return -1;
1491
0
    }
1492
1493
0
    return write_single(ctx, MODBUS_FC_WRITE_SINGLE_REGISTER, addr, value);
1494
0
}
1495
1496
/* Write the bits of the array in the remote device */
1497
int modbus_write_bits(modbus_t *ctx, int addr, int nb, const uint8_t *src)
1498
0
{
1499
0
    int rc;
1500
0
    int i;
1501
0
    int byte_count;
1502
0
    int req_length;
1503
0
    int bit_check = 0;
1504
0
    int pos = 0;
1505
0
    uint8_t req[MAX_MESSAGE_LENGTH];
1506
1507
0
    if (ctx == NULL || src == NULL) {
1508
0
        errno = EINVAL;
1509
0
        return -1;
1510
0
    }
1511
1512
0
    if (nb < 1 || nb > MODBUS_MAX_WRITE_BITS) {
1513
0
        if (ctx->debug) {
1514
0
            fprintf(stderr,
1515
0
                    "ERROR Writing too many bits (%d > %d)\n",
1516
0
                    nb,
1517
0
                    MODBUS_MAX_WRITE_BITS);
1518
0
        }
1519
0
        errno = EMBXILVAL;
1520
0
        return -1;
1521
0
    }
1522
1523
0
    req_length = ctx->backend->build_request_basis(
1524
0
        ctx, MODBUS_FC_WRITE_MULTIPLE_COILS, addr, nb, req);
1525
0
    byte_count = (nb / 8) + ((nb % 8) ? 1 : 0);
1526
0
    req[req_length++] = byte_count;
1527
1528
0
    for (i = 0; i < byte_count; i++) {
1529
0
        int bit;
1530
1531
0
        bit = 0x01;
1532
0
        req[req_length] = 0;
1533
1534
0
        while ((bit & 0xFF) && (bit_check++ < nb)) {
1535
0
            if (src[pos++])
1536
0
                req[req_length] |= bit;
1537
0
            else
1538
0
                req[req_length] &= ~bit;
1539
1540
0
            bit = bit << 1;
1541
0
        }
1542
0
        req_length++;
1543
0
    }
1544
1545
0
    rc = send_msg(ctx, req, req_length);
1546
0
    if (rc > 0) {
1547
0
        uint8_t rsp[MAX_MESSAGE_LENGTH];
1548
1549
0
        rc = _modbus_receive_msg(ctx, rsp, MSG_CONFIRMATION);
1550
0
        if (rc == -1)
1551
0
            return -1;
1552
1553
0
        rc = check_confirmation(ctx, req, rsp, rc);
1554
0
    }
1555
1556
0
    return rc;
1557
0
}
1558
1559
/* Write the values from the array to the registers of the remote device */
1560
int modbus_write_registers(modbus_t *ctx, int addr, int nb, const uint16_t *src)
1561
0
{
1562
0
    int rc;
1563
0
    int i;
1564
0
    int req_length;
1565
0
    int byte_count;
1566
0
    uint8_t req[MAX_MESSAGE_LENGTH];
1567
1568
0
    if (ctx == NULL || src == NULL) {
1569
0
        errno = EINVAL;
1570
0
        return -1;
1571
0
    }
1572
1573
0
    if (nb < 1 || nb > MODBUS_MAX_WRITE_REGISTERS) {
1574
0
        if (ctx->debug) {
1575
0
            fprintf(stderr,
1576
0
                    "ERROR Trying to write to too many registers (%d > %d)\n",
1577
0
                    nb,
1578
0
                    MODBUS_MAX_WRITE_REGISTERS);
1579
0
        }
1580
0
        errno = EMBXILVAL;
1581
0
        return -1;
1582
0
    }
1583
1584
0
    req_length = ctx->backend->build_request_basis(
1585
0
        ctx, MODBUS_FC_WRITE_MULTIPLE_REGISTERS, addr, nb, req);
1586
0
    byte_count = nb * 2;
1587
0
    req[req_length++] = byte_count;
1588
1589
0
    for (i = 0; i < nb; i++) {
1590
0
        req[req_length++] = src[i] >> 8;
1591
0
        req[req_length++] = src[i] & 0x00FF;
1592
0
    }
1593
1594
0
    rc = send_msg(ctx, req, req_length);
1595
0
    if (rc > 0) {
1596
0
        uint8_t rsp[MAX_MESSAGE_LENGTH];
1597
1598
0
        rc = _modbus_receive_msg(ctx, rsp, MSG_CONFIRMATION);
1599
0
        if (rc == -1)
1600
0
            return -1;
1601
1602
0
        rc = check_confirmation(ctx, req, rsp, rc);
1603
0
    }
1604
1605
0
    return rc;
1606
0
}
1607
1608
int modbus_mask_write_register(modbus_t *ctx,
1609
                               int addr,
1610
                               uint16_t and_mask,
1611
                               uint16_t or_mask)
1612
0
{
1613
0
    int rc;
1614
0
    int req_length;
1615
    /* The request length can not exceed _MIN_REQ_LENGTH - 2 and 4 bytes to
1616
     * store the masks. The ugly substraction is there to remove the 'nb' value
1617
     * (2 bytes) which is not used. */
1618
0
    uint8_t req[_MIN_REQ_LENGTH + 2];
1619
1620
0
    req_length = ctx->backend->build_request_basis(
1621
0
        ctx, MODBUS_FC_MASK_WRITE_REGISTER, addr, 0, req);
1622
1623
    /* HACKISH, count is not used */
1624
0
    req_length -= 2;
1625
1626
0
    req[req_length++] = and_mask >> 8;
1627
0
    req[req_length++] = and_mask & 0x00ff;
1628
0
    req[req_length++] = or_mask >> 8;
1629
0
    req[req_length++] = or_mask & 0x00ff;
1630
1631
0
    rc = send_msg(ctx, req, req_length);
1632
0
    if (rc > 0) {
1633
        /* Used by write_bit and write_register */
1634
0
        uint8_t rsp[MAX_MESSAGE_LENGTH];
1635
1636
0
        rc = _modbus_receive_msg(ctx, rsp, MSG_CONFIRMATION);
1637
0
        if (rc == -1)
1638
0
            return -1;
1639
1640
0
        rc = check_confirmation(ctx, req, rsp, rc);
1641
0
    }
1642
1643
0
    return rc;
1644
0
}
1645
1646
/* Write multiple registers from src array to remote device and read multiple
1647
   registers from remote device to dest array. */
1648
int modbus_write_and_read_registers(modbus_t *ctx,
1649
                                    int write_addr,
1650
                                    int write_nb,
1651
                                    const uint16_t *src,
1652
                                    int read_addr,
1653
                                    int read_nb,
1654
                                    uint16_t *dest)
1655
1656
0
{
1657
0
    int rc;
1658
0
    int req_length;
1659
0
    int i;
1660
0
    int byte_count;
1661
0
    uint8_t req[MAX_MESSAGE_LENGTH];
1662
0
    uint8_t rsp[MAX_MESSAGE_LENGTH];
1663
1664
0
    if (ctx == NULL) {
1665
0
        errno = EINVAL;
1666
0
        return -1;
1667
0
    }
1668
1669
0
    if (write_nb > MODBUS_MAX_WR_WRITE_REGISTERS) {
1670
0
        if (ctx->debug) {
1671
0
            fprintf(stderr,
1672
0
                    "ERROR Too many registers to write (%d > %d)\n",
1673
0
                    write_nb,
1674
0
                    MODBUS_MAX_WR_WRITE_REGISTERS);
1675
0
        }
1676
0
        errno = EMBXILVAL;
1677
0
        return -1;
1678
0
    }
1679
1680
0
    if (read_nb > MODBUS_MAX_WR_READ_REGISTERS) {
1681
0
        if (ctx->debug) {
1682
0
            fprintf(stderr,
1683
0
                    "ERROR Too many registers requested (%d > %d)\n",
1684
0
                    read_nb,
1685
0
                    MODBUS_MAX_WR_READ_REGISTERS);
1686
0
        }
1687
0
        errno = EMBXILVAL;
1688
0
        return -1;
1689
0
    }
1690
0
    req_length = ctx->backend->build_request_basis(
1691
0
        ctx, MODBUS_FC_WRITE_AND_READ_REGISTERS, read_addr, read_nb, req);
1692
1693
0
    req[req_length++] = write_addr >> 8;
1694
0
    req[req_length++] = write_addr & 0x00ff;
1695
0
    req[req_length++] = write_nb >> 8;
1696
0
    req[req_length++] = write_nb & 0x00ff;
1697
0
    byte_count = write_nb * 2;
1698
0
    req[req_length++] = byte_count;
1699
1700
0
    for (i = 0; i < write_nb; i++) {
1701
0
        req[req_length++] = src[i] >> 8;
1702
0
        req[req_length++] = src[i] & 0x00FF;
1703
0
    }
1704
1705
0
    rc = send_msg(ctx, req, req_length);
1706
0
    if (rc > 0) {
1707
0
        unsigned int offset;
1708
1709
0
        rc = _modbus_receive_msg(ctx, rsp, MSG_CONFIRMATION);
1710
0
        if (rc == -1)
1711
0
            return -1;
1712
1713
0
        rc = check_confirmation(ctx, req, rsp, rc);
1714
0
        if (rc == -1)
1715
0
            return -1;
1716
1717
0
        offset = ctx->backend->header_length;
1718
0
        for (i = 0; i < rc; i++) {
1719
            /* shift reg hi_byte to temp OR with lo_byte */
1720
0
            dest[i] = (rsp[offset + 2 + (i << 1)] << 8) | rsp[offset + 3 + (i << 1)];
1721
0
        }
1722
0
    }
1723
1724
0
    return rc;
1725
0
}
1726
1727
/* Send a request to get the slave ID of the device (only available in serial
1728
   communication). */
1729
int modbus_report_slave_id(modbus_t *ctx, int max_dest, uint8_t *dest)
1730
0
{
1731
0
    int rc;
1732
0
    int req_length;
1733
0
    uint8_t req[_MIN_REQ_LENGTH];
1734
1735
0
    if (ctx == NULL || max_dest <= 0) {
1736
0
        errno = EINVAL;
1737
0
        return -1;
1738
0
    }
1739
1740
0
    req_length =
1741
0
        ctx->backend->build_request_basis(ctx, MODBUS_FC_REPORT_SLAVE_ID, 0, 0, req);
1742
1743
    /* HACKISH, addr and count are not used */
1744
0
    req_length -= 4;
1745
1746
0
    rc = send_msg(ctx, req, req_length);
1747
0
    if (rc > 0) {
1748
0
        int i;
1749
0
        unsigned int offset;
1750
0
        uint8_t rsp[MAX_MESSAGE_LENGTH];
1751
1752
0
        rc = _modbus_receive_msg(ctx, rsp, MSG_CONFIRMATION);
1753
0
        if (rc == -1)
1754
0
            return -1;
1755
1756
0
        rc = check_confirmation(ctx, req, rsp, rc);
1757
0
        if (rc == -1)
1758
0
            return -1;
1759
1760
0
        offset = ctx->backend->header_length + 2;
1761
1762
        /* Byte count, slave id, run indicator status and
1763
           additional data. Truncate copy to max_dest. */
1764
0
        for (i = 0; i < rc && i < max_dest; i++) {
1765
0
            dest[i] = rsp[offset + i];
1766
0
        }
1767
0
    }
1768
1769
0
    return rc;
1770
0
}
1771
1772
void _modbus_init_common(modbus_t *ctx)
1773
1
{
1774
    /* Slave and socket are initialized to -1 */
1775
1
    ctx->slave = -1;
1776
1
    ctx->s = -1;
1777
1778
1
    ctx->debug = FALSE;
1779
1
    ctx->error_recovery = MODBUS_ERROR_RECOVERY_NONE;
1780
1
    ctx->quirks = MODBUS_QUIRK_NONE;
1781
1782
1
    ctx->response_timeout.tv_sec = 0;
1783
1
    ctx->response_timeout.tv_usec = _RESPONSE_TIMEOUT;
1784
1785
1
    ctx->byte_timeout.tv_sec = 0;
1786
1
    ctx->byte_timeout.tv_usec = _BYTE_TIMEOUT;
1787
1788
1
    ctx->indication_timeout.tv_sec = 0;
1789
1
    ctx->indication_timeout.tv_usec = 0;
1790
1
}
1791
1792
/* Define the slave number */
1793
int modbus_set_slave(modbus_t *ctx, int slave)
1794
0
{
1795
0
    if (ctx == NULL) {
1796
0
        errno = EINVAL;
1797
0
        return -1;
1798
0
    }
1799
1800
0
    return ctx->backend->set_slave(ctx, slave);
1801
0
}
1802
1803
int modbus_get_slave(modbus_t *ctx)
1804
0
{
1805
0
    if (ctx == NULL) {
1806
0
        errno = EINVAL;
1807
0
        return -1;
1808
0
    }
1809
1810
0
    return ctx->slave;
1811
0
}
1812
1813
int modbus_set_error_recovery(modbus_t *ctx, modbus_error_recovery_mode error_recovery)
1814
0
{
1815
0
    if (ctx == NULL) {
1816
0
        errno = EINVAL;
1817
0
        return -1;
1818
0
    }
1819
1820
    /* The type of modbus_error_recovery_mode is unsigned enum */
1821
0
    ctx->error_recovery = (uint8_t) error_recovery;
1822
0
    return 0;
1823
0
}
1824
1825
// FIXME Doesn't work under Windows RTU
1826
int modbus_set_socket(modbus_t *ctx, int s)
1827
0
{
1828
0
    if (ctx == NULL) {
1829
0
        errno = EINVAL;
1830
0
        return -1;
1831
0
    }
1832
1833
0
    ctx->s = s;
1834
0
    return 0;
1835
0
}
1836
1837
int modbus_get_socket(modbus_t *ctx)
1838
0
{
1839
0
    if (ctx == NULL) {
1840
0
        errno = EINVAL;
1841
0
        return -1;
1842
0
    }
1843
1844
0
    return ctx->s;
1845
0
}
1846
1847
/* Get the timeout interval used to wait for a response */
1848
int modbus_get_response_timeout(modbus_t *ctx, uint32_t *to_sec, uint32_t *to_usec)
1849
0
{
1850
0
    if (ctx == NULL) {
1851
0
        errno = EINVAL;
1852
0
        return -1;
1853
0
    }
1854
1855
0
    *to_sec = ctx->response_timeout.tv_sec;
1856
0
    *to_usec = ctx->response_timeout.tv_usec;
1857
0
    return 0;
1858
0
}
1859
1860
int modbus_set_response_timeout(modbus_t *ctx, uint32_t to_sec, uint32_t to_usec)
1861
0
{
1862
0
    if (ctx == NULL || (to_sec == 0 && to_usec == 0) || to_usec > 999999) {
1863
0
        errno = EINVAL;
1864
0
        return -1;
1865
0
    }
1866
1867
0
    ctx->response_timeout.tv_sec = to_sec;
1868
0
    ctx->response_timeout.tv_usec = to_usec;
1869
0
    return 0;
1870
0
}
1871
1872
/* Get the timeout interval between two consecutive bytes of a message */
1873
int modbus_get_byte_timeout(modbus_t *ctx, uint32_t *to_sec, uint32_t *to_usec)
1874
0
{
1875
0
    if (ctx == NULL) {
1876
0
        errno = EINVAL;
1877
0
        return -1;
1878
0
    }
1879
1880
0
    *to_sec = ctx->byte_timeout.tv_sec;
1881
0
    *to_usec = ctx->byte_timeout.tv_usec;
1882
0
    return 0;
1883
0
}
1884
1885
int modbus_set_byte_timeout(modbus_t *ctx, uint32_t to_sec, uint32_t to_usec)
1886
0
{
1887
    /* Byte timeout can be disabled when both values are zero */
1888
0
    if (ctx == NULL || to_usec > 999999) {
1889
0
        errno = EINVAL;
1890
0
        return -1;
1891
0
    }
1892
1893
0
    ctx->byte_timeout.tv_sec = to_sec;
1894
0
    ctx->byte_timeout.tv_usec = to_usec;
1895
0
    return 0;
1896
0
}
1897
1898
/* Get the timeout interval used by the server to wait for an indication from a client
1899
 */
1900
int modbus_get_indication_timeout(modbus_t *ctx, uint32_t *to_sec, uint32_t *to_usec)
1901
0
{
1902
0
    if (ctx == NULL) {
1903
0
        errno = EINVAL;
1904
0
        return -1;
1905
0
    }
1906
1907
0
    *to_sec = ctx->indication_timeout.tv_sec;
1908
0
    *to_usec = ctx->indication_timeout.tv_usec;
1909
0
    return 0;
1910
0
}
1911
1912
int modbus_set_indication_timeout(modbus_t *ctx, uint32_t to_sec, uint32_t to_usec)
1913
0
{
1914
    /* Indication timeout can be disabled when both values are zero */
1915
0
    if (ctx == NULL || to_usec > 999999) {
1916
0
        errno = EINVAL;
1917
0
        return -1;
1918
0
    }
1919
1920
0
    ctx->indication_timeout.tv_sec = to_sec;
1921
0
    ctx->indication_timeout.tv_usec = to_usec;
1922
0
    return 0;
1923
0
}
1924
1925
int modbus_get_header_length(modbus_t *ctx)
1926
0
{
1927
0
    if (ctx == NULL) {
1928
0
        errno = EINVAL;
1929
0
        return -1;
1930
0
    }
1931
1932
0
    return ctx->backend->header_length;
1933
0
}
1934
1935
int modbus_enable_quirks(modbus_t *ctx, unsigned int quirks_mask)
1936
0
{
1937
0
    if (ctx == NULL) {
1938
0
        errno = EINVAL;
1939
0
        return -1;
1940
0
    }
1941
1942
    /* Enable quirks that have a true value at their index in the mask */
1943
0
    ctx->quirks |= quirks_mask;
1944
0
    return 0;
1945
0
}
1946
1947
int modbus_disable_quirks(modbus_t *ctx, unsigned int quirks_mask)
1948
0
{
1949
0
    if (ctx == NULL) {
1950
0
        errno = EINVAL;
1951
0
        return -1;
1952
0
    }
1953
1954
    /* Disable quirks that have a true value at ther index in the mask */
1955
0
    ctx->quirks &= ~quirks_mask;
1956
0
    return 0;
1957
0
}
1958
1959
int modbus_connect(modbus_t *ctx)
1960
0
{
1961
0
    if (ctx == NULL) {
1962
0
        errno = EINVAL;
1963
0
        return -1;
1964
0
    }
1965
1966
0
    return ctx->backend->connect(ctx);
1967
0
}
1968
1969
void modbus_close(modbus_t *ctx)
1970
1
{
1971
1
    if (ctx == NULL)
1972
0
        return;
1973
1974
1
    ctx->backend->close(ctx);
1975
1
}
1976
1977
void modbus_free(modbus_t *ctx)
1978
1
{
1979
1
    if (ctx == NULL)
1980
0
        return;
1981
1982
1
    ctx->backend->free(ctx);
1983
1
}
1984
1985
int modbus_set_debug(modbus_t *ctx, int flag)
1986
0
{
1987
0
    if (ctx == NULL) {
1988
0
        errno = EINVAL;
1989
0
        return -1;
1990
0
    }
1991
1992
0
    ctx->debug = flag;
1993
0
    return 0;
1994
0
}
1995
1996
/* Allocates 4 arrays to store bits, input bits, registers and inputs
1997
   registers. The pointers are stored in modbus_mapping structure.
1998
1999
   The modbus_mapping_new_start_address() function shall return the new allocated
2000
   structure if successful. Otherwise it shall return NULL and set errno to
2001
   ENOMEM. */
2002
modbus_mapping_t *modbus_mapping_new_start_address(unsigned int start_bits,
2003
                                                   unsigned int nb_bits,
2004
                                                   unsigned int start_input_bits,
2005
                                                   unsigned int nb_input_bits,
2006
                                                   unsigned int start_registers,
2007
                                                   unsigned int nb_registers,
2008
                                                   unsigned int start_input_registers,
2009
                                                   unsigned int nb_input_registers)
2010
1
{
2011
1
    modbus_mapping_t *mb_mapping;
2012
2013
1
    mb_mapping = (modbus_mapping_t *) malloc(sizeof(modbus_mapping_t));
2014
1
    if (mb_mapping == NULL) {
2015
0
        return NULL;
2016
0
    }
2017
2018
    /* 0X */
2019
1
    mb_mapping->nb_bits = nb_bits;
2020
1
    mb_mapping->start_bits = start_bits;
2021
1
    if (nb_bits == 0) {
2022
0
        mb_mapping->tab_bits = NULL;
2023
1
    } else {
2024
        /* Negative number raises a POSIX error */
2025
1
        mb_mapping->tab_bits = (uint8_t *) malloc(nb_bits * sizeof(uint8_t));
2026
1
        if (mb_mapping->tab_bits == NULL) {
2027
0
            free(mb_mapping);
2028
0
            return NULL;
2029
0
        }
2030
1
        memset(mb_mapping->tab_bits, 0, nb_bits * sizeof(uint8_t));
2031
1
    }
2032
2033
    /* 1X */
2034
1
    mb_mapping->nb_input_bits = nb_input_bits;
2035
1
    mb_mapping->start_input_bits = start_input_bits;
2036
1
    if (nb_input_bits == 0) {
2037
0
        mb_mapping->tab_input_bits = NULL;
2038
1
    } else {
2039
1
        mb_mapping->tab_input_bits = (uint8_t *) malloc(nb_input_bits * sizeof(uint8_t));
2040
1
        if (mb_mapping->tab_input_bits == NULL) {
2041
0
            free(mb_mapping->tab_bits);
2042
0
            free(mb_mapping);
2043
0
            return NULL;
2044
0
        }
2045
1
        memset(mb_mapping->tab_input_bits, 0, nb_input_bits * sizeof(uint8_t));
2046
1
    }
2047
2048
    /* 4X */
2049
1
    mb_mapping->nb_registers = nb_registers;
2050
1
    mb_mapping->start_registers = start_registers;
2051
1
    if (nb_registers == 0) {
2052
0
        mb_mapping->tab_registers = NULL;
2053
1
    } else {
2054
1
        mb_mapping->tab_registers = (uint16_t *) malloc(nb_registers * sizeof(uint16_t));
2055
1
        if (mb_mapping->tab_registers == NULL) {
2056
0
            free(mb_mapping->tab_input_bits);
2057
0
            free(mb_mapping->tab_bits);
2058
0
            free(mb_mapping);
2059
0
            return NULL;
2060
0
        }
2061
1
        memset(mb_mapping->tab_registers, 0, nb_registers * sizeof(uint16_t));
2062
1
    }
2063
2064
    /* 3X */
2065
1
    mb_mapping->nb_input_registers = nb_input_registers;
2066
1
    mb_mapping->start_input_registers = start_input_registers;
2067
1
    if (nb_input_registers == 0) {
2068
0
        mb_mapping->tab_input_registers = NULL;
2069
1
    } else {
2070
1
        mb_mapping->tab_input_registers =
2071
1
            (uint16_t *) malloc(nb_input_registers * sizeof(uint16_t));
2072
1
        if (mb_mapping->tab_input_registers == NULL) {
2073
0
            free(mb_mapping->tab_registers);
2074
0
            free(mb_mapping->tab_input_bits);
2075
0
            free(mb_mapping->tab_bits);
2076
0
            free(mb_mapping);
2077
0
            return NULL;
2078
0
        }
2079
1
        memset(mb_mapping->tab_input_registers, 0, nb_input_registers * sizeof(uint16_t));
2080
1
    }
2081
2082
1
    return mb_mapping;
2083
1
}
2084
2085
modbus_mapping_t *modbus_mapping_new(int nb_bits,
2086
                                     int nb_input_bits,
2087
                                     int nb_registers,
2088
                                     int nb_input_registers)
2089
0
{
2090
0
    return modbus_mapping_new_start_address(
2091
0
        0, nb_bits, 0, nb_input_bits, 0, nb_registers, 0, nb_input_registers);
2092
0
}
2093
2094
/* Frees the 4 arrays */
2095
void modbus_mapping_free(modbus_mapping_t *mb_mapping)
2096
1
{
2097
1
    if (mb_mapping == NULL) {
2098
0
        return;
2099
0
    }
2100
2101
1
    free(mb_mapping->tab_input_registers);
2102
1
    free(mb_mapping->tab_registers);
2103
1
    free(mb_mapping->tab_input_bits);
2104
1
    free(mb_mapping->tab_bits);
2105
1
    free(mb_mapping);
2106
1
}
2107
2108
#ifndef HAVE_STRLCPY
2109
/*
2110
 * Function strlcpy was originally developed by
2111
 * Todd C. Miller <Todd.Miller@courtesan.com> to simplify writing secure code.
2112
 * See ftp://ftp.openbsd.org/pub/OpenBSD/src/lib/libc/string/strlcpy.3
2113
 * for more information.
2114
 *
2115
 * Thank you Ulrich Drepper... not!
2116
 *
2117
 * Copy src to string dest of size dest_size.  At most dest_size-1 characters
2118
 * will be copied.  Always NUL terminates (unless dest_size == 0).  Returns
2119
 * strlen(src); if retval >= dest_size, truncation occurred.
2120
 */
2121
size_t strlcpy(char *dest, const char *src, size_t dest_size)
2122
1
{
2123
1
    register char *d = dest;
2124
1
    register const char *s = src;
2125
1
    register size_t n = dest_size;
2126
2127
    /* Copy as many bytes as will fit */
2128
1
    if (n != 0 && --n != 0) {
2129
10
        do {
2130
10
            if ((*d++ = *s++) == 0)
2131
1
                break;
2132
10
        } while (--n != 0);
2133
1
    }
2134
2135
    /* Not enough room in dest, add NUL and traverse rest of src */
2136
1
    if (n == 0) {
2137
0
        if (dest_size != 0)
2138
0
            *d = '\0'; /* NUL-terminate dest */
2139
0
        while (*s++)
2140
0
            ;
2141
0
    }
2142
2143
1
    return (s - src - 1); /* count does not include NUL */
2144
1
}
2145
#endif