diff --git a/doc/modbus_get_byte_timeout.txt b/doc/modbus_get_byte_timeout.txt index 41f4ae0..f207ecb 100644 --- a/doc/modbus_get_byte_timeout.txt +++ b/doc/modbus_get_byte_timeout.txt @@ -9,7 +9,7 @@ modbus_get_byte_timeout - get timeout between bytes SYNOPSIS -------- -*void modbus_get_byte_timeout(modbus_t *'ctx', struct timeval *'timeout');* +*int modbus_get_byte_timeout(modbus_t *'ctx', struct timeval *'timeout');* DESCRIPTION @@ -20,7 +20,7 @@ between two consecutive bytes of the same message in the 'timeout' argument. RETURN VALUE ------------ -There is no return values. +The function shall return 0 if successful. Otherwise it shall return -1 and set errno. EXAMPLE diff --git a/doc/modbus_get_response_timeout.txt b/doc/modbus_get_response_timeout.txt index f48898f..65bf5a0 100644 --- a/doc/modbus_get_response_timeout.txt +++ b/doc/modbus_get_response_timeout.txt @@ -9,7 +9,7 @@ modbus_get_response_timeout - get timeout for response SYNOPSIS -------- -*void modbus_get_response_timeout(modbus_t *'ctx', struct timeval *'timeout');* +*int modbus_get_response_timeout(modbus_t *'ctx', struct timeval *'timeout');* DESCRIPTION @@ -20,7 +20,7 @@ used to wait for a response in the 'timeout' argument. RETURN VALUE ------------ -There is no return values. +The function shall return 0 if successful. Otherwise it shall return -1 and set errno. EXAMPLE diff --git a/doc/modbus_get_socket.txt b/doc/modbus_get_socket.txt index 3284a3b..8ceeb9c 100644 --- a/doc/modbus_get_socket.txt +++ b/doc/modbus_get_socket.txt @@ -20,7 +20,8 @@ descriptor of the libmodbus context. RETURN VALUE ------------ -The current socket or file descriptor of the context. +The function returns the current socket or file descriptor of the context if +successful. Otherwise it shall return -1 and set errno. SEE ALSO diff --git a/doc/modbus_set_byte_timeout.txt b/doc/modbus_set_byte_timeout.txt index 90db5f4..6b689df 100644 --- a/doc/modbus_set_byte_timeout.txt +++ b/doc/modbus_set_byte_timeout.txt @@ -22,9 +22,10 @@ If the timeout value has a tv_sec of -1 then this timeout will not be used at all. This results in modbus_set_response_timeout governing the entire timeout duration of an operation. + RETURN VALUE ------------ -There is no return values. +The function shall return 0 if successful. Otherwise it shall return -1 and set errno. SEE ALSO diff --git a/doc/modbus_set_debug.txt b/doc/modbus_set_debug.txt index 9ca161f..9e6a2e9 100644 --- a/doc/modbus_set_debug.txt +++ b/doc/modbus_set_debug.txt @@ -8,7 +8,7 @@ modbus_set_debug - set debug flag of the context SYNOPSIS -------- -*void modbus_set_debug(modbus_t *'ctx', int 'boolean');* +*int modbus_set_debug(modbus_t *'ctx', int 'boolean');* DESCRIPTION @@ -28,7 +28,7 @@ ___________________ RETURN VALUE ------------ -There is no return values. +The function shall return 0 if successful. Otherwise it shall return -1 and set errno. AUTHORS diff --git a/doc/modbus_set_response_timeout.txt b/doc/modbus_set_response_timeout.txt index 9baf03d..f5803bf 100644 --- a/doc/modbus_set_response_timeout.txt +++ b/doc/modbus_set_response_timeout.txt @@ -9,7 +9,7 @@ modbus_set_response_timeout - set timeout for response SYNOPSIS -------- -*void modbus_set_response_timeout(modbus_t *'ctx', struct timeval *'timeout');* +*int modbus_set_response_timeout(modbus_t *'ctx', struct timeval *'timeout');* DESCRIPTION @@ -21,7 +21,7 @@ the given timeout, an error will be raised. RETURN VALUE ------------ -There is no return values. +The function shall return 0 if successful. Otherwise it shall return -1 and set errno. EXAMPLE diff --git a/doc/modbus_set_socket.txt b/doc/modbus_set_socket.txt index 4734a8f..4f7d80e 100644 --- a/doc/modbus_set_socket.txt +++ b/doc/modbus_set_socket.txt @@ -9,7 +9,7 @@ modbus_set_socket - set socket of the context SYNOPSIS -------- -*void modbus_set_socket(modbus_t *'ctx', int 'socket');* +*int modbus_set_socket(modbus_t *'ctx', int 'socket');* DESCRIPTION @@ -21,7 +21,7 @@ connections to the same server. RETURN VALUE ------------ -There is no return values. +The function shall return 0 if successful. Otherwise it shall return -1 and set errno. EXAMPLE diff --git a/src/modbus-rtu.c b/src/modbus-rtu.c index 9beeee9..fed44a7 100644 --- a/src/modbus-rtu.c +++ b/src/modbus-rtu.c @@ -567,8 +567,6 @@ static int _modbus_rtu_connect(modbus_t *ctx) /* Don't want errors to be blocking */ dcb.fAbortOnError = FALSE; - /* TODO: any other flags!? */ - /* Setup port */ if (!SetCommState(ctx_rtu->w_ser.fd, &dcb)) { fprintf(stderr, "ERROR Error setting new configuration (LastError %d)\n", @@ -900,6 +898,11 @@ static int _modbus_rtu_connect(modbus_t *ctx) int modbus_rtu_set_serial_mode(modbus_t *ctx, int mode) { + if (ctx == NULL) { + errno = EINVAL; + return -1; + } + if (ctx->backend->backend_type == _MODBUS_BACKEND_TYPE_RTU) { #if HAVE_DECL_TIOCSRS485 modbus_rtu_t *ctx_rtu = ctx->backend_data; @@ -939,7 +942,13 @@ int modbus_rtu_set_serial_mode(modbus_t *ctx, int mode) return -1; } -int modbus_rtu_get_serial_mode(modbus_t *ctx) { +int modbus_rtu_get_serial_mode(modbus_t *ctx) +{ + if (ctx == NULL) { + errno = EINVAL; + return -1; + } + if (ctx->backend->backend_type == _MODBUS_BACKEND_TYPE_RTU) { #if HAVE_DECL_TIOCSRS485 modbus_rtu_t *ctx_rtu = ctx->backend_data; @@ -959,6 +968,11 @@ int modbus_rtu_get_serial_mode(modbus_t *ctx) { int modbus_rtu_set_rts(modbus_t *ctx, int mode) { + if (ctx == NULL) { + errno = EINVAL; + return -1; + } + if (ctx->backend->backend_type == _MODBUS_BACKEND_TYPE_RTU) { #if HAVE_DECL_TIOCM_RTS modbus_rtu_t *ctx_rtu = ctx->backend_data; @@ -985,7 +999,13 @@ int modbus_rtu_set_rts(modbus_t *ctx, int mode) return -1; } -int modbus_rtu_get_rts(modbus_t *ctx) { +int modbus_rtu_get_rts(modbus_t *ctx) +{ + if (ctx == NULL) { + errno = EINVAL; + return -1; + } + if (ctx->backend->backend_type == _MODBUS_BACKEND_TYPE_RTU) { #if HAVE_DECL_TIOCM_RTS modbus_rtu_t *ctx_rtu = ctx->backend_data; diff --git a/src/modbus-tcp.c b/src/modbus-tcp.c index ef8ea4b..0d3a64e 100644 --- a/src/modbus-tcp.c +++ b/src/modbus-tcp.c @@ -467,7 +467,14 @@ int modbus_tcp_listen(modbus_t *ctx, int nb_connection) int new_socket; int yes; struct sockaddr_in addr; - modbus_tcp_t *ctx_tcp = ctx->backend_data; + modbus_tcp_t *ctx_tcp; + + if (ctx == NULL) { + errno = EINVAL; + return -1; + } + + ctx_tcp = ctx->backend_data; #ifdef OS_WIN32 if (_modbus_tcp_init_win32() == -1) { @@ -514,7 +521,14 @@ int modbus_tcp_pi_listen(modbus_t *ctx, int nb_connection) const char *node; const char *service; int new_socket; - modbus_tcp_pi_t *ctx_tcp_pi = ctx->backend_data; + modbus_tcp_pi_t *ctx_tcp_pi; + + if (ctx == NULL) { + errno = EINVAL; + return -1; + } + + ctx_tcp_pi = ctx->backend_data; if (ctx_tcp_pi->node[0] == 0) node = NULL; /* == any */ @@ -609,6 +623,11 @@ int modbus_tcp_accept(modbus_t *ctx, int *socket) struct sockaddr_in addr; socklen_t addrlen; + if (ctx == NULL) { + errno = EINVAL; + return -1; + } + addrlen = sizeof(addr); #ifdef HAVE_ACCEPT4 /* Inherit socket flags and use accept4 call */ @@ -636,6 +655,11 @@ int modbus_tcp_pi_accept(modbus_t *ctx, int *socket) struct sockaddr_storage addr; socklen_t addrlen; + if (ctx == NULL) { + errno = EINVAL; + return -1; + } + addrlen = sizeof(addr); ctx->s = accept(*socket, (void *)&addr, &addrlen); if (ctx->s == -1) { diff --git a/src/modbus.c b/src/modbus.c index 6871ab0..e8cf909 100644 --- a/src/modbus.c +++ b/src/modbus.c @@ -121,6 +121,11 @@ static void _sleep_response_timeout(modbus_t *ctx) int modbus_flush(modbus_t *ctx) { + if (ctx == NULL) { + errno = EINVAL; + return -1; + } + int rc = ctx->backend->flush(ctx); if (rc != -1 && ctx->debug) { /* Not all backends are able to return the number of bytes flushed */ @@ -217,6 +222,11 @@ int modbus_send_raw_request(modbus_t *ctx, uint8_t *raw_req, int raw_req_length) uint8_t req[MAX_MESSAGE_LENGTH]; int req_length; + if (ctx == NULL) { + errno = EINVAL; + return -1; + } + if (raw_req_length < 2) { /* The raw request must contain function and slave at least */ errno = EINVAL; @@ -468,6 +478,11 @@ int _modbus_receive_msg(modbus_t *ctx, uint8_t *msg, msg_type_t msg_type) /* Receive the request from a modbus master */ int modbus_receive(modbus_t *ctx, uint8_t *req) { + if (ctx == NULL) { + errno = EINVAL; + return -1; + } + return ctx->backend->receive(ctx, req); } @@ -481,6 +496,11 @@ int modbus_receive(modbus_t *ctx, uint8_t *req) */ int modbus_receive_confirmation(modbus_t *ctx, uint8_t *rsp) { + if (ctx == NULL) { + errno = EINVAL; + return -1; + } + return _modbus_receive_msg(ctx, rsp, MSG_CONFIRMATION); } @@ -672,6 +692,11 @@ int modbus_reply(modbus_t *ctx, const uint8_t *req, int rsp_length = 0; sft_t sft; + if (ctx == NULL) { + errno = EINVAL; + return -1; + } + sft.slave = slave; sft.function = function; sft.t_id = ctx->backend->prepare_response_tid(req, &req_length); @@ -960,6 +985,11 @@ int modbus_reply_exception(modbus_t *ctx, const uint8_t *req, int dummy_length = 99; sft_t sft; + if (ctx == NULL) { + errno = EINVAL; + return -1; + } + sft.slave = slave; sft.function = function + 0x80;; sft.t_id = ctx->backend->prepare_response_tid(req, &dummy_length); @@ -1025,6 +1055,11 @@ int modbus_read_bits(modbus_t *ctx, int addr, int nb, uint8_t *dest) { int rc; + if (ctx == NULL) { + errno = EINVAL; + return -1; + } + if (nb > MODBUS_MAX_READ_BITS) { if (ctx->debug) { fprintf(stderr, @@ -1049,6 +1084,11 @@ int modbus_read_input_bits(modbus_t *ctx, int addr, int nb, uint8_t *dest) { int rc; + if (ctx == NULL) { + errno = EINVAL; + return -1; + } + if (nb > MODBUS_MAX_READ_BITS) { if (ctx->debug) { fprintf(stderr, @@ -1119,6 +1159,11 @@ int modbus_read_registers(modbus_t *ctx, int addr, int nb, uint16_t *dest) { int status; + if (ctx == NULL) { + errno = EINVAL; + return -1; + } + if (nb > MODBUS_MAX_READ_REGISTERS) { if (ctx->debug) { fprintf(stderr, @@ -1140,6 +1185,11 @@ int modbus_read_input_registers(modbus_t *ctx, int addr, int nb, { int status; + if (ctx == NULL) { + errno = EINVAL; + return -1; + } + if (nb > MODBUS_MAX_READ_REGISTERS) { fprintf(stderr, "ERROR Too many input registers requested (%d > %d)\n", @@ -1162,6 +1212,11 @@ static int write_single(modbus_t *ctx, int function, int addr, int value) int req_length; uint8_t req[_MIN_REQ_LENGTH]; + if (ctx == NULL) { + errno = EINVAL; + return -1; + } + req_length = ctx->backend->build_request_basis(ctx, function, addr, value, req); rc = send_msg(ctx, req, req_length); @@ -1182,6 +1237,11 @@ static int write_single(modbus_t *ctx, int function, int addr, int value) /* Turns ON or OFF a single bit of the remote device */ int modbus_write_bit(modbus_t *ctx, int addr, int status) { + if (ctx == NULL) { + errno = EINVAL; + return -1; + } + return write_single(ctx, _FC_WRITE_SINGLE_COIL, addr, status ? 0xFF00 : 0); } @@ -1189,6 +1249,11 @@ int modbus_write_bit(modbus_t *ctx, int addr, int status) /* Writes a value in one register of the remote device */ int modbus_write_register(modbus_t *ctx, int addr, int value) { + if (ctx == NULL) { + errno = EINVAL; + return -1; + } + return write_single(ctx, _FC_WRITE_SINGLE_REGISTER, addr, value); } @@ -1201,9 +1266,13 @@ int modbus_write_bits(modbus_t *ctx, int addr, int nb, const uint8_t *src) int req_length; int bit_check = 0; int pos = 0; - uint8_t req[MAX_MESSAGE_LENGTH]; + if (ctx == NULL) { + errno = EINVAL; + return -1; + } + if (nb > MODBUS_MAX_WRITE_BITS) { if (ctx->debug) { fprintf(stderr, "ERROR Writing too many bits (%d > %d)\n", @@ -1258,9 +1327,13 @@ int modbus_write_registers(modbus_t *ctx, int addr, int nb, const uint16_t *src) int i; int req_length; int byte_count; - uint8_t req[MAX_MESSAGE_LENGTH]; + if (ctx == NULL) { + errno = EINVAL; + return -1; + } + if (nb > MODBUS_MAX_WRITE_REGISTERS) { if (ctx->debug) { fprintf(stderr, @@ -1341,6 +1414,11 @@ int modbus_write_and_read_registers(modbus_t *ctx, uint8_t req[MAX_MESSAGE_LENGTH]; uint8_t rsp[MAX_MESSAGE_LENGTH]; + if (ctx == NULL) { + errno = EINVAL; + return -1; + } + if (write_nb > MODBUS_MAX_RW_WRITE_REGISTERS) { if (ctx->debug) { fprintf(stderr, @@ -1409,6 +1487,11 @@ int modbus_report_slave_id(modbus_t *ctx, uint8_t *dest) int req_length; uint8_t req[_MIN_REQ_LENGTH]; + if (ctx == NULL) { + errno = EINVAL; + return -1; + } + req_length = ctx->backend->build_request_basis(ctx, _FC_REPORT_SLAVE_ID, 0, 0, req); @@ -1460,56 +1543,111 @@ void _modbus_init_common(modbus_t *ctx) /* Define the slave number */ int modbus_set_slave(modbus_t *ctx, int slave) { + if (ctx == NULL) { + errno = EINVAL; + return -1; + } + return ctx->backend->set_slave(ctx, slave); } int modbus_set_error_recovery(modbus_t *ctx, modbus_error_recovery_mode error_recovery) { + if (ctx == NULL) { + errno = EINVAL; + return -1; + } + /* The type of modbus_error_recovery_mode is unsigned enum */ ctx->error_recovery = (uint8_t) error_recovery; return 0; } -void modbus_set_socket(modbus_t *ctx, int socket) +int modbus_set_socket(modbus_t *ctx, int socket) { + if (ctx == NULL) { + errno = EINVAL; + return -1; + } + ctx->s = socket; + return 0; } int modbus_get_socket(modbus_t *ctx) { + if (ctx == NULL) { + errno = EINVAL; + return -1; + } + return ctx->s; } /* Get the timeout interval used to wait for a response */ -void modbus_get_response_timeout(modbus_t *ctx, struct timeval *timeout) +int modbus_get_response_timeout(modbus_t *ctx, struct timeval *timeout) { + if (ctx == NULL) { + errno = EINVAL; + return -1; + } + *timeout = ctx->response_timeout; + return 0; } -void modbus_set_response_timeout(modbus_t *ctx, const struct timeval *timeout) +int modbus_set_response_timeout(modbus_t *ctx, const struct timeval *timeout) { + if (ctx == NULL) { + errno = EINVAL; + return -1; + } + ctx->response_timeout = *timeout; + return 0; } /* Get the timeout interval between two consecutive bytes of a message */ -void modbus_get_byte_timeout(modbus_t *ctx, struct timeval *timeout) +int modbus_get_byte_timeout(modbus_t *ctx, struct timeval *timeout) { + if (ctx == NULL) { + errno = EINVAL; + return -1; + } + *timeout = ctx->byte_timeout; + return 0; } -void modbus_set_byte_timeout(modbus_t *ctx, const struct timeval *timeout) +int modbus_set_byte_timeout(modbus_t *ctx, const struct timeval *timeout) { + if (ctx == NULL) { + errno = EINVAL; + return -1; + } + ctx->byte_timeout = *timeout; + return 0; } int modbus_get_header_length(modbus_t *ctx) { + if (ctx == NULL) { + errno = EINVAL; + return -1; + } + return ctx->backend->header_length; } int modbus_connect(modbus_t *ctx) { + if (ctx == NULL) { + errno = EINVAL; + return -1; + } + return ctx->backend->connect(ctx); } @@ -1529,9 +1667,15 @@ void modbus_free(modbus_t *ctx) ctx->backend->free(ctx); } -void modbus_set_debug(modbus_t *ctx, int boolean) +int modbus_set_debug(modbus_t *ctx, int boolean) { + if (ctx == NULL) { + errno = EINVAL; + return -1; + } + ctx->debug = boolean; + return 0; } /* Allocates 4 arrays to store bits, input bits, registers and inputs diff --git a/src/modbus.h b/src/modbus.h index ced3583..33a46f9 100644 --- a/src/modbus.h +++ b/src/modbus.h @@ -156,14 +156,14 @@ typedef enum EXPORT int modbus_set_slave(modbus_t* ctx, int slave); EXPORT int modbus_set_error_recovery(modbus_t *ctx, modbus_error_recovery_mode error_recovery); -EXPORT void modbus_set_socket(modbus_t *ctx, int socket); +EXPORT int modbus_set_socket(modbus_t *ctx, int socket); EXPORT int modbus_get_socket(modbus_t *ctx); -EXPORT void modbus_get_response_timeout(modbus_t *ctx, struct timeval *timeout); -EXPORT void modbus_set_response_timeout(modbus_t *ctx, const struct timeval *timeout); +EXPORT int modbus_get_response_timeout(modbus_t *ctx, struct timeval *timeout); +EXPORT int modbus_set_response_timeout(modbus_t *ctx, const struct timeval *timeout); -EXPORT void modbus_get_byte_timeout(modbus_t *ctx, struct timeval *timeout); -EXPORT void modbus_set_byte_timeout(modbus_t *ctx, const struct timeval *timeout); +EXPORT int modbus_get_byte_timeout(modbus_t *ctx, struct timeval *timeout); +EXPORT int modbus_set_byte_timeout(modbus_t *ctx, const struct timeval *timeout); EXPORT int modbus_get_header_length(modbus_t *ctx); @@ -173,7 +173,7 @@ EXPORT void modbus_close(modbus_t *ctx); EXPORT void modbus_free(modbus_t *ctx); EXPORT int modbus_flush(modbus_t *ctx); -EXPORT void modbus_set_debug(modbus_t *ctx, int boolean); +EXPORT int modbus_set_debug(modbus_t *ctx, int boolean); EXPORT const char *modbus_strerror(int errnum);