Commit d3aecacf6ff34a7378153e8384346a43f288773c

Authored by Stéphane Raimbault
1 parent 741022ce

Major changes - Added slave functions (not finished)

- (error_treat): used string instead of message
- added a define for each function code supported
- added compute_query_size_header/data functions to read messages
- added new function manage_query to manage queries and send the right
  response
- s/receive_response/receive_msg/
- major changes to receive_msg to handle query
- changed return value of check_crc16
- added response_io_status
- comments
- added functions to allocate/free a modbus mapping
Showing 2 changed files with 565 additions and 230 deletions
src/modbus.c
1 1 /*
2   - Copyright (C) 2001-2005 Stéphane Raimbault <stephane.raimbault@free.fr>
  2 + Copyright (C) 2001-2007 Stéphane Raimbault <stephane.raimbault@gmail.com>
3 3  
4 4 This library is free software; you can redistribute it and/or
5 5 modify it under the terms of the GNU Lesser General Public
... ... @@ -126,11 +126,12 @@ static int read_reg_response(modbus_param_t *mb_param,
126 126 int *data_dest,
127 127 unsigned char *query);
128 128  
129   -static void error_treat(int ret, const char *message, modbus_param_t *mb_param)
  129 +/* Treats errors and flush or close connection if necessary */
  130 +static void error_treat(int ret, const char *string, modbus_param_t *mb_param)
130 131 {
131 132 if (ret == -1)
132   - perror(message);
133   - g_print("\n\nERROR %s\n\n", message);
  133 + perror(string);
  134 + g_print("\n\nERROR %s\n\n", string);
134 135  
135 136 if (mb_param->type_com == RTU) {
136 137 tcflush(mb_param->fd, TCIOFLUSH);
... ... @@ -140,6 +141,7 @@ static void error_treat(int ret, const char *message, modbus_param_t *mb_param)
140 141 }
141 142 }
142 143  
  144 +/* Computes the size of the expected response */
143 145 static unsigned int compute_response_size(modbus_param_t *mb_param,
144 146 unsigned char *query)
145 147 {
... ... @@ -149,18 +151,21 @@ static unsigned int compute_response_size(modbus_param_t *mb_param,
149 151 offset = mb_param->header_length;
150 152  
151 153 switch (query[offset + 1]) {
152   - case 0x01: {
  154 + case FC_READ_COIL_STATUS:
  155 + case FC_READ_INPUT_STATUS: {
153 156 /* Header + nb values (code from force_multiple_coils) */
154 157 int coil_count = (query[offset + 4] << 8) | query[offset + 5];
155 158 response_size_computed = 3 +
156 159 (coil_count / 8) + ((coil_count % 8) ? 1 : 0);
157   - } break;
158   - case 0x03:
  160 + }
  161 + break;
  162 + case FC_READ_HOLDING_REGISTERS:
  163 + case FC_READ_INPUT_REGISTERS:
159 164 /* Header + 2 * nb values */
160 165 response_size_computed = 3 +
161 166 2 * (query[offset + 4] << 8 | query[offset + 5]);
162 167 break;
163   - case 0x07:
  168 + case FC_READ_EXCEPTION_STATUS:
164 169 response_size_computed = 4;
165 170 break;
166 171 default:
... ... @@ -172,10 +177,9 @@ static unsigned int compute_response_size(modbus_param_t *mb_param,
172 177 return response_size_computed;
173 178 }
174 179  
175   -/* The following functions construct the required query into
176   - a modbus query packet */
177   -int build_request_packet_rtu(int slave, int function, int start_addr,
178   - int count, unsigned char *packet)
  180 +/* Buils a RTU header */
  181 +int build_query_packet_rtu(int slave, int function, int start_addr,
  182 + int count, unsigned char *packet)
179 183 {
180 184 packet[0] = slave;
181 185 packet[1] = function;
... ... @@ -187,8 +191,9 @@ int build_request_packet_rtu(int slave, int function, int start_addr,
187 191 return PRESET_QUERY_SIZE_RTU;
188 192 }
189 193  
190   -int build_request_packet_tcp(int slave, int function, int start_addr,
191   - int count, unsigned char *packet)
  194 +/* Builds a TCP header */
  195 +int build_query_packet_tcp(int slave, int function, int start_addr,
  196 + int count, unsigned char *packet)
192 197 {
193 198 static unsigned short t_id = 0;
194 199  
... ... @@ -206,7 +211,7 @@ int build_request_packet_tcp(int slave, int function, int start_addr,
206 211  
207 212 /* Length to fix later with set_packet_length_tcp (4 and 5) */
208 213  
209   - packet[6] = 0xFF;
  214 + packet[6] = slave;
210 215 packet[7] = function;
211 216 packet[8] = start_addr >> 8;
212 217 packet[9] = start_addr & 0x00ff;
... ... @@ -216,6 +221,66 @@ int build_request_packet_tcp(int slave, int function, int start_addr,
216 221 return PRESET_QUERY_SIZE_TCP;
217 222 }
218 223  
  224 +int build_query_packet(modbus_param_t *mb_param, int slave,
  225 + int function, int start_addr,
  226 + int count, unsigned char *packet)
  227 +{
  228 + if (mb_param->type_com == RTU)
  229 + return build_query_packet_rtu(slave, function, start_addr,
  230 + count, packet);
  231 + else
  232 + return build_query_packet_tcp(slave, function, start_addr,
  233 + count, packet);
  234 +}
  235 +
  236 +
  237 +int build_response_packet_rtu(int slave, int function, int byte_count, unsigned char *packet)
  238 +{
  239 + packet[0] = slave;
  240 + packet[1] = function;
  241 + packet[2] = byte_count;
  242 +
  243 + /* FIXME +1 */
  244 + return PRESET_RESPONSE_SIZE_RTU+1;
  245 +}
  246 +
  247 +int build_response_packet_tcp(int slave, int function, int byte_count, unsigned char *packet)
  248 +{
  249 + static unsigned short t_id = 0;
  250 +
  251 + /* Transaction ID */
  252 + if (t_id < USHRT_MAX)
  253 + t_id++;
  254 + else
  255 + t_id = 0;
  256 + packet[0] = t_id >> 8;
  257 + packet[1] = t_id & 0x00ff;
  258 +
  259 + /* Protocol Modbus */
  260 + packet[2] = 0;
  261 + packet[3] = 0;
  262 +
  263 + /* Length to fix later with set_packet_length_tcp (4 and 5) */
  264 +
  265 + packet[6] = slave;
  266 + packet[7] = function;
  267 +
  268 + packet[8] = byte_count;
  269 +
  270 + /* FIXME +1 */
  271 + return PRESET_RESPONSE_SIZE_TCP+1;
  272 +}
  273 +
  274 +int build_response_packet(modbus_param_t *mb_param, int slave,
  275 + int function, int byte_count, unsigned char *packet)
  276 +{
  277 + if (mb_param->type_com == RTU)
  278 + return build_response_packet_rtu(slave, function, byte_count, packet);
  279 + else
  280 + return build_response_packet_tcp(slave, function, byte_count, packet);
  281 +}
  282 +
  283 +/* Sets the length of TCP message in the message */
219 284 void set_packet_length_tcp(unsigned char *packet, size_t packet_size)
220 285 {
221 286 unsigned short mbap_length;
... ... @@ -227,18 +292,6 @@ void set_packet_length_tcp(unsigned char *packet, size_t packet_size)
227 292 packet[5] = mbap_length & 0x00FF;
228 293 }
229 294  
230   -int build_request_packet(modbus_param_t *mb_param, int slave,
231   - int function, int start_addr,
232   - int count, unsigned char *packet)
233   -{
234   - if (mb_param->type_com == RTU)
235   - return build_request_packet_rtu(slave, function, start_addr,
236   - count, packet);
237   - else
238   - return build_request_packet_tcp(slave, function, start_addr,
239   - count, packet);
240   -}
241   -
242 295 /* Fast CRC */
243 296 static unsigned short crc16(unsigned char *buffer,
244 297 unsigned short buffer_length)
... ... @@ -257,9 +310,51 @@ static unsigned short crc16(unsigned char *buffer,
257 310 return (crc_hi << 8 | crc_lo);
258 311 }
259 312  
260   -/* Function to send a query out to a modbus slave */
261   -static int modbus_query(modbus_param_t *mb_param, unsigned char *query,
262   - size_t query_size)
  313 +/* If CRC is correct returns 0 else returns INVALID_CRC */
  314 +int check_crc16(modbus_param_t *mb_param,
  315 + unsigned char *msg,
  316 + int msg_size)
  317 +{
  318 + int ret;
  319 +
  320 + if (mb_param->type_com == RTU) {
  321 + unsigned short crc_calc;
  322 + unsigned short crc_received;
  323 + unsigned char recv_crc_hi;
  324 + unsigned char recv_crc_lo;
  325 +
  326 + crc_calc = crc16(msg, msg_size - 2);
  327 +
  328 + recv_crc_hi = msg[msg_size - 2];
  329 + recv_crc_lo = msg[msg_size - 1];
  330 +
  331 + crc_received = msg[msg_size - 2];
  332 + crc_received = crc_received << 8;
  333 + crc_received = crc_received | msg[msg_size - 1];
  334 +
  335 + /* Check CRC of msg */
  336 + if (crc_calc == crc_received) {
  337 + ret = 0;
  338 + } else {
  339 + char *s_error;
  340 + s_error = g_strdup_printf(
  341 + "invalid crc received %0X - crc_calc %0X",
  342 + crc_received, crc_calc);
  343 + error_treat(0, s_error, mb_param);
  344 + g_free(s_error);
  345 + ret = INVALID_CRC;
  346 + }
  347 + } else {
  348 + /* In TCP, the modbus CRC is not present (see HDLC level) */
  349 + ret = 0;
  350 + }
  351 +
  352 + return ret;
  353 +}
  354 +
  355 +/* Sends a query/response over a serial or a TCP communication */
  356 +static int modbus_send(modbus_param_t *mb_param, unsigned char *query,
  357 + size_t query_size)
263 358 {
264 359 int write_ret;
265 360 unsigned short s_crc;
... ... @@ -296,6 +391,44 @@ static int modbus_query(modbus_param_t *mb_param, unsigned char *query,
296 391 return write_ret;
297 392 }
298 393  
  394 +/* Computes the size of the header following the function code */
  395 +int compute_query_size_header(int function)
  396 +{
  397 + int byte;
  398 +
  399 + if (function <= FC_FORCE_SINGLE_COIL)
  400 + /* Read and single write */
  401 + byte = 4;
  402 + else if (function == FC_FORCE_MULTIPLE_COILS ||
  403 + function == FC_PRESET_MULTIPLE_REGISTERS)
  404 + /* Multiple write */
  405 + byte = 5;
  406 + else
  407 + byte = 0;
  408 +
  409 + g_print("compute_query_size_header FC %d, B%d\n", function, byte);
  410 +
  411 + return byte;
  412 +}
  413 +
  414 +/* Computes the size of the data to write in the query */
  415 +int compute_query_size_data(modbus_param_t *mb_param, unsigned char *msg)
  416 +{
  417 + int function = msg[mb_param->header_length + 1];
  418 + int byte;
  419 +
  420 + if (function == FC_FORCE_MULTIPLE_COILS ||
  421 + function == FC_PRESET_MULTIPLE_REGISTERS)
  422 + byte = msg[mb_param->header_length + 6];
  423 + else
  424 + byte = 0;
  425 +
  426 + byte += mb_param->checksum_size;
  427 + g_print("compute_query_size_data FC %d, B %d\n", function, byte);
  428 +
  429 + return byte;
  430 +}
  431 +
299 432 #define WAIT_DATA() \
300 433 { \
301 434 while ((select_ret = select(mb_param->fd+1, &rfds, NULL, NULL, &tv)) == -1) { \
... ... @@ -316,77 +449,119 @@ static int modbus_query(modbus_param_t *mb_param, unsigned char *query,
316 449 } \
317 450 }
318 451  
319   -/* Function to monitor for the reply from the modbus slave.
  452 +/* Monitors for the reply from the modbus slave or to receive query
  453 + from a modbus master.
320 454 This function blocks for timeout seconds if there is no reply.
321 455  
  456 + msg_size_computed must be set to MSG_SIZE_COMPUTED if undefined
  457 +
322 458 Returns:
323   - - error_code 0 == OK, < 0 == error
324   - - (arg) total number of characters received.
325   -*/
326   -int receive_response(modbus_param_t *mb_param,
327   - int response_size_computed,
328   - unsigned char *response,
329   - int *response_size)
  459 + - 0: OK, <0: error
  460 + - msg_size: number of characters received. */
  461 +int receive_msg(modbus_param_t *mb_param,
  462 + int msg_size_computed,
  463 + unsigned char *msg,
  464 + int *msg_size)
330 465 {
331 466 int select_ret;
332 467 int read_ret;
333 468 fd_set rfds;
334 469 struct timeval tv;
335 470 int size_to_read;
336   - unsigned char *p_response;
  471 + unsigned char *p_msg;
  472 + enum { FUNCTION, BYTE, COMPLETE };
  473 + int state;
337 474  
338   - if (mb_param->debug)
339   - g_print("Waiting for response (%d)...\n", response_size_computed);
  475 + if (mb_param->debug) {
  476 + if (msg_size_computed == MSG_SIZE_UNDEFINED)
  477 + g_print("Waiting for a message...\n");
  478 + else
  479 + g_print("Waiting for a message (%d bytes)...\n", msg_size_computed);
  480 + }
340 481  
341 482 /* Add a file descriptor to the set */
342 483 FD_ZERO(&rfds);
343 484 FD_SET(mb_param->fd, &rfds);
344   -
345   - /* Wait for a response */
346   - tv.tv_sec = 0;
347   - tv.tv_usec = TIME_OUT_BEGIN_OF_TRAME;
348 485  
  486 + if (msg_size_computed == MSG_SIZE_UNDEFINED) {
  487 + /* Wait for a message */
  488 + tv.tv_sec = 60;
  489 + tv.tv_usec = 0;
  490 +
  491 + /* The message size is undefined (query receiving) so
  492 + * we need to analyse the message step by step.
  493 + * In the first step, we want to reach the function code */
  494 + msg_size_computed = mb_param->header_length + 2;
  495 + state = FUNCTION;
  496 + } else {
  497 + tv.tv_sec = 0;
  498 + tv.tv_usec = TIME_OUT_BEGIN_OF_TRAME;
  499 + state = COMPLETE;
  500 + }
  501 +
  502 + size_to_read = msg_size_computed;
349 503 WAIT_DATA();
350 504  
351   - /* Read the trame */
352   - (*response_size) = 0;
353   - size_to_read = response_size_computed;
354   - p_response = response;
  505 + /* Read the msg */
  506 + (*msg_size) = 0;
  507 + p_msg = msg;
355 508  
356 509 while (select_ret) {
357 510 if (mb_param->type_com == RTU)
358   - read_ret = read(mb_param->fd, p_response, size_to_read);
  511 + read_ret = read(mb_param->fd, p_msg, size_to_read);
359 512 else
360   - read_ret = recv(mb_param->fd, p_response, size_to_read, 0);
  513 + read_ret = recv(mb_param->fd, p_msg, size_to_read, 0);
361 514  
362 515 if (read_ret == -1) {
363 516 error_treat(read_ret, "Read port/socket failure", mb_param);
364 517 return PORT_SOCKET_FAILURE;
365   - } else {
366   - /* Sums bytes received */
367   - (*response_size) += read_ret;
  518 + }
368 519  
369   - /* Display the hex code of each
370   - * character received */
371   - if (mb_param->debug) {
372   - int i;
373   - for (i=0; i < read_ret; i++)
374   - g_print("<%.2X>", p_response[i]);
375   - }
376   - /* Moves the pointer to receive other datas */
377   - p_response = &(p_response[read_ret]);
378   - size_to_read = response_size_computed - (*response_size);
  520 + /* Sums bytes received */
  521 + (*msg_size) += read_ret;
  522 + if ((*msg_size) > MAX_PACKET_SIZE) {
  523 + error_treat(0, "Too many datas", mb_param);
  524 + return TOO_MANY_DATAS;
  525 + }
  526 +
  527 + /* Display the hex code of each character received */
  528 + if (mb_param->debug) {
  529 + int i;
  530 + for (i=0; i < read_ret; i++)
  531 + g_print("<%.2X>", p_msg[i]);
  532 + }
379 533  
380   - if ((*response_size) > MAX_PACKET_SIZE) {
381   - error_treat(0, "Too many datas", mb_param);
382   - return TOO_MANY_DATAS;
  534 + if ((*msg_size) < msg_size_computed) {
  535 + /* Message incomplete */
  536 + size_to_read = msg_size_computed - (*msg_size);
  537 + } else {
  538 + switch (state) {
  539 + case FUNCTION:
  540 + /* Function code position */
  541 + size_to_read = compute_query_size_header(msg[mb_param->header_length + 1]);
  542 + msg_size_computed += size_to_read;
  543 + state = BYTE;
  544 + g_print("\nBYTE:");
  545 + break;
  546 + case BYTE:
  547 + size_to_read = compute_query_size_data(mb_param, msg);
  548 + msg_size_computed += size_to_read;
  549 + state = COMPLETE;
  550 + g_print("\nCOMPLETE:");
  551 + break;
  552 + case COMPLETE:
  553 + size_to_read = 0;
  554 + break;
383 555 }
384 556 }
  557 + g_print(" size to read %d\n", size_to_read);
  558 +
  559 + /* Moves the pointer to receive other datas */
  560 + p_msg = &(p_msg[read_ret]);
385 561  
386 562 if (size_to_read > 0) {
387 563 /* If no character at the buffer wait
388   - TIME_OUT_END_OF_TRAME before to generate an error.
389   - */
  564 + TIME_OUT_END_OF_TRAME before to generate an error. */
390 565 tv.tv_sec = 0;
391 566 tv.tv_usec = TIME_OUT_END_OF_TRAME;
392 567  
... ... @@ -404,99 +579,50 @@ int receive_response(modbus_param_t *mb_param,
404 579 return 0;
405 580 }
406 581  
407   -static int check_crc16(modbus_param_t *mb_param,
408   - unsigned char *response,
409   - int response_size)
410   -{
411   - int ret;
412   -
413   - if (mb_param->type_com == RTU) {
414   - unsigned short crc_calc;
415   - unsigned short crc_received;
416   - unsigned char recv_crc_hi;
417   - unsigned char recv_crc_lo;
418   -
419   - crc_calc = crc16(response, response_size - 2);
420   -
421   - recv_crc_hi = (unsigned) response[response_size - 2];
422   - recv_crc_lo = (unsigned) response[response_size - 1];
423   -
424   - crc_received = response[response_size - 2];
425   - crc_received = (unsigned) crc_received << 8;
426   - crc_received = crc_received |
427   - (unsigned) response[response_size - 1];
428   -
429   - /* Check CRC of response */
430   - if (crc_calc == crc_received) {
431   - ret = TRUE;
432   - } else {
433   - char *message;
434   - message = g_strdup_printf(
435   - "invalid crc received %0X - crc_calc %0X",
436   - crc_received, crc_calc);
437   - error_treat(0, message, mb_param);
438   - g_free(message);
439   - ret = INVALID_CRC;
440   - }
441   - } else {
442   - /* In TCP, CRC doesn't exist but it doesn't check
443   - length because it's not really useful */
444   - ret = TRUE;
445   - }
446   -
447   - return ret;
448   -}
449 582  
450   -/* Function to the correct response is returned and that the checksum
451   - is correct.
  583 +/* Checks whether the right response is returned with good checksum.
452 584  
453 585 Returns:
454 586 - the numbers of values (bits or word) if success
455 587 - less than 0 for exception errors
456 588  
457   - Note: All functions used for sending or receiving data via modbus
458   - return these values.
459   -*/
460   -
461   -static int modbus_response(modbus_param_t *mb_param,
462   - unsigned char *query,
463   - unsigned char *response)
  589 + Note: All functions used to send or receive data with modbus return
  590 + these values. */
  591 +static int modbus_check_response(modbus_param_t *mb_param,
  592 + unsigned char *query,
  593 + unsigned char *response)
464 594 {
465 595 int response_size;
466   - int response_size_computed;
467   - int offset = mb_param->header_length;
468   - int error_code;
  596 + int response_size_computed; int offset = mb_param->header_length;
  597 + int ret;
469 598  
470 599 response_size_computed = compute_response_size(mb_param, query);
471   - error_code = receive_response(mb_param, response_size_computed,
472   - response, &response_size);
473   - if (error_code == 0) {
474   - /* No error */
475   - int ret;
476   -
  600 + ret = receive_msg(mb_param, response_size_computed, response, &response_size);
  601 + if (ret == 0) {
  602 + /* Check message */
477 603 ret = check_crc16(mb_param, response, response_size);
478   - if (ret != TRUE)
  604 + if (ret != 0)
479 605 return ret;
480 606  
481 607 /* Good response */
482 608 switch (response[offset + 1]) {
483   - case 0x01:
484   - case 0x02:
  609 + case FC_READ_COIL_STATUS:
  610 + case FC_READ_INPUT_STATUS:
485 611 /* Read functions 1 value = 1 byte */
486 612 response_size = response[offset + 2];
487 613 break;
488   - case 0x03:
489   - case 0x04:
  614 + case FC_READ_HOLDING_REGISTERS:
  615 + case FC_READ_INPUT_REGISTERS:
490 616 /* Read functions 1 value = 2 bytes */
491 617 response_size = response[offset + 2] / 2;
492 618 break;
493   - case 0x0F:
494   - case 0x10:
  619 + case FC_FORCE_MULTIPLE_COILS:
  620 + case FC_PRESET_MULTIPLE_REGISTERS:
495 621 /* N Write functions */
496 622 response_size = response[offset + 4] << 8 |
497 623 response[offset + 5];
498 624 break;
499   - case 0x11:
  625 + case FC_REPORT_SLAVE_ID:
500 626 /* Report slave ID (bytes received) */
501 627 break;
502 628 default:
... ... @@ -504,16 +630,14 @@ static int modbus_response(modbus_param_t *mb_param,
504 630 response_size = 1;
505 631 }
506 632  
507   - } else if (error_code == COMM_TIME_OUT &&
  633 + } else if (ret == COMM_TIME_OUT &&
508 634 response_size == offset + 3 + mb_param->checksum_size) {
509 635 /* Optimisation allowed because exception response is
510 636 the smallest trame in modbus protocol (3) so always
511 637 raise an timeout error */
512   - int ret;
513   -
514 638 /* CRC */
515 639 ret = check_crc16(mb_param, response, response_size);
516   - if (ret != TRUE)
  640 + if (ret != 0)
517 641 return ret;
518 642  
519 643 /* Check for exception response
... ... @@ -530,26 +654,148 @@ static int modbus_response(modbus_param_t *mb_param,
530 654 /* The chances are low to hit this
531 655 case but can avoid a vicious
532 656 segfault */
533   - char *message;
534   - message = g_strdup_printf(
  657 + char *s_error;
  658 + s_error = g_strdup_printf(
535 659 "Invalid exception code %d",
536 660 response[offset + 2]);
537   - error_treat(0, message, mb_param);
538   - g_free(message);
  661 + error_treat(0, s_error, mb_param);
  662 + g_free(s_error);
539 663 return INVALID_EXCEPTION_CODE;
540 664 }
541 665 }
542   - } else if (error_code == COMM_TIME_OUT) {
  666 + } else if (ret == COMM_TIME_OUT) {
543 667 error_treat(0, "Communication time out", mb_param);
544 668 return COMM_TIME_OUT;
545 669 } else {
546   - return error_code;
  670 + return ret;
547 671 }
548 672  
549 673 return response_size;
550 674 }
551 675  
552   -/* Read IO status */
  676 +int response_io_status(int address, int count,
  677 + int nb_io_status, unsigned char *tab_io_status,
  678 + unsigned char *response, int offset)
  679 +{
  680 + unsigned char shift = 0;
  681 + unsigned char byte = 0;
  682 + int i;
  683 +
  684 + for (i = address; i < address+count; i++) {
  685 + byte |= tab_io_status[i] << shift;
  686 + if (shift == 7) {
  687 + /* Byte is full */
  688 + response[offset++] = byte;
  689 + byte = shift = 0;
  690 + } else {
  691 + shift++;
  692 + }
  693 + }
  694 +
  695 + if (shift != 0)
  696 + response[offset++] = byte;
  697 +
  698 + return offset;
  699 +}
  700 +
  701 +/* Manages the received query.
  702 + Analyses the query and constructs a response */
  703 +void manage_query(modbus_param_t *mb_param, unsigned char *query,
  704 + int query_size, modbus_mapping_t *mb_mapping)
  705 +{
  706 + int offset = mb_param->header_length;
  707 + int slave = query[offset];
  708 + int function = query[offset+1];
  709 + int address = (query[offset+2] << 8) + query[offset+3];
  710 + /* FIXME count/data */
  711 + int count;
  712 + int data;
  713 + unsigned char response[MAX_PACKET_SIZE];
  714 + int byte_count;
  715 + int i;
  716 +
  717 + /* FIXME address illegal used in mb_mapping->tab_X */
  718 +
  719 + switch (function) {
  720 + case FC_READ_COIL_STATUS:
  721 + count = (query[offset+4] << 8) + query[offset+5];
  722 + byte_count = (count / 8.0) + ((count % 8) ? 1 : 0);
  723 + offset = build_response_packet(mb_param, slave, function, byte_count, response);
  724 + offset = response_io_status(address, count,
  725 + mb_mapping->nb_coil_status, mb_mapping->tab_coil_status,
  726 + response, offset);
  727 + break;
  728 + case FC_READ_INPUT_STATUS:
  729 + count = (query[offset+4] << 8) + query[offset+5];
  730 + byte_count = (count / 8.0) + ((count % 8) ? 1 : 0);
  731 + offset = build_response_packet(mb_param, slave, function, byte_count, response);
  732 + offset = response_io_status(address, count,
  733 + mb_mapping->nb_input_status, mb_mapping->tab_input_status,
  734 + response, offset);
  735 + break;
  736 + case FC_READ_HOLDING_REGISTERS:
  737 + count = (query[offset+4] << 8) + query[offset+5];
  738 + byte_count = 2 * count;
  739 + offset = build_response_packet(mb_param, slave, function, byte_count, response);
  740 + g_print("offset %d\n", offset);
  741 + for (i = address; i < address + count; i++) {
  742 + response[offset++] = mb_mapping->tab_holding_registers[i] >> 8;
  743 + response[offset++] = mb_mapping->tab_holding_registers[i] & 0xFF;
  744 + }
  745 + g_print("fin offset %d\n", offset);
  746 + break;
  747 + case FC_READ_INPUT_REGISTERS:
  748 + count = (query[offset+4] << 8) + query[offset+5];
  749 + byte_count = 2 * count;
  750 + offset = build_response_packet(mb_param, slave, function, byte_count, response);
  751 + for (i = address; i < address + count; i++) {
  752 + response[offset++] = mb_mapping->tab_input_registers[i] >> 8;
  753 + response[offset++] = mb_mapping->tab_input_registers[i] & 0xFF;
  754 + }
  755 + break;
  756 + case FC_FORCE_SINGLE_COIL:
  757 + data = (query[offset+4] << 8) + query[offset+5];
  758 + if (data == 0xFF00)
  759 + mb_mapping->tab_coil_status[address] = ON;
  760 + else if (data == 0x0)
  761 + mb_mapping->tab_coil_status[address] = OFF;
  762 + else
  763 + g_print("FIXME Error %d\n", data);
  764 + g_print("FIXME works only in TCP mode (CRC)");
  765 + memcpy(response, query, query_size);
  766 + offset = query_size;
  767 + break;
  768 + case FC_PRESET_SINGLE_REGISTER:
  769 + case FC_READ_EXCEPTION_STATUS:
  770 + case FC_FORCE_MULTIPLE_COILS:
  771 + case FC_PRESET_MULTIPLE_REGISTERS:
  772 + case FC_REPORT_SLAVE_ID:
  773 + g_print("Not implemented\n");
  774 + break;
  775 + }
  776 +
  777 + modbus_send(mb_param, response, offset);
  778 +}
  779 +
  780 +/* Listens any message on a socket or file descriptor.
  781 + Returns:
  782 + - 0 if OK, or a negative error number if the request fails
  783 + - query, message received
  784 + - query_size, size in bytes of the message */
  785 +int modbus_listen(modbus_param_t *mb_param, unsigned char *query, int *query_size)
  786 +{
  787 + int offset = mb_param->header_length;
  788 + int ret;
  789 +
  790 + ret = receive_msg(mb_param, MSG_SIZE_UNDEFINED, query, query_size);
  791 + if (ret == 0) {
  792 + ret = check_crc16(mb_param, query, *query_size);
  793 + }
  794 +
  795 + return ret;
  796 +}
  797 +
  798 +/* Reads IO status */
553 799 static int read_io_status(modbus_param_t *mb_param, int slave, int function,
554 800 int start_addr, int count, int *data_dest)
555 801 {
... ... @@ -560,10 +806,10 @@ static int read_io_status(modbus_param_t *mb_param, int slave, int function,
560 806 unsigned char query[MIN_QUERY_SIZE];
561 807 unsigned char response[MAX_PACKET_SIZE];
562 808  
563   - query_size = build_request_packet(mb_param, slave, function,
564   - start_addr, count, query);
  809 + query_size = build_query_packet(mb_param, slave, function,
  810 + start_addr, count, query);
565 811  
566   - query_ret = modbus_query(mb_param, query, query_size);
  812 + query_ret = modbus_send(mb_param, query, query_size);
567 813 if (query_ret > 0) {
568 814 int i, temp, bit;
569 815 int pos = 0;
... ... @@ -571,7 +817,7 @@ static int read_io_status(modbus_param_t *mb_param, int slave, int function,
571 817 int offset;
572 818 int offset_length;
573 819  
574   - response_ret = modbus_response(mb_param, query, response);
  820 + response_ret = modbus_check_response(mb_param, query, response);
575 821 offset = mb_param->header_length;
576 822  
577 823 offset_length = offset + response_ret;
... ... @@ -579,10 +825,8 @@ static int read_io_status(modbus_param_t *mb_param, int slave, int function,
579 825 /* Shift reg hi_byte to temp */
580 826 temp = response[3 + i];
581 827  
582   - for (bit = 0x01;
583   - (bit & 0xff) && (processed < count);) {
584   - data_dest[pos++] =
585   - (temp & bit) ? TRUE : FALSE;
  828 + for (bit = 0x01; (bit & 0xff) && (processed < count);) {
  829 + data_dest[pos++] = (temp & bit) ? TRUE : FALSE;
586 830 processed++;
587 831 bit = bit << 1;
588 832 }
... ... @@ -596,15 +840,14 @@ static int read_io_status(modbus_param_t *mb_param, int slave, int function,
596 840 }
597 841  
598 842 /* Reads the boolean status of coils and sets the array elements
599   - in the destination to TRUE or FALSE */
  843 + in the destination to TRUE or FALSE. */
600 844 int read_coil_status(modbus_param_t *mb_param, int slave, int start_addr,
601 845 int count, int *data_dest)
602 846 {
603   - int function = 0x01;
604 847 int status;
605 848  
606   - status = read_io_status(mb_param, slave, function, start_addr,
607   - count, data_dest);
  849 + status = read_io_status(mb_param, slave, FC_READ_COIL_STATUS,
  850 + start_addr, count, data_dest);
608 851  
609 852 if (status > 0)
610 853 status = count;
... ... @@ -612,15 +855,15 @@ int read_coil_status(modbus_param_t *mb_param, int slave, int start_addr,
612 855 return status;
613 856 }
614 857  
  858 +
615 859 /* Same as read_coil_status but reads the slaves input table */
616 860 int read_input_status(modbus_param_t *mb_param, int slave, int start_addr,
617 861 int count, int *data_dest)
618 862 {
619   - int function = 0x02;
620 863 int status;
621 864  
622   - status = read_io_status(mb_param, slave, function, start_addr,
623   - count, data_dest);
  865 + status = read_io_status(mb_param, slave, FC_READ_INPUT_STATUS,
  866 + start_addr, count, data_dest);
624 867  
625 868 if (status > 0)
626 869 status = count;
... ... @@ -628,7 +871,7 @@ int read_input_status(modbus_param_t *mb_param, int slave, int start_addr,
628 871 return status;
629 872 }
630 873  
631   -/* Read the data from a modbus slave and put that data into an array */
  874 +/* Reads the data from a modbus slave and put that data into an array */
632 875 static int read_registers(modbus_param_t *mb_param, int slave, int function,
633 876 int start_addr, int count, int *data_dest)
634 877 {
... ... @@ -637,10 +880,10 @@ static int read_registers(modbus_param_t *mb_param, int slave, int function,
637 880 int query_ret;
638 881 unsigned char query[MIN_QUERY_SIZE];
639 882  
640   - query_size = build_request_packet(mb_param, slave, function,
641   - start_addr, count, query);
  883 + query_size = build_query_packet(mb_param, slave, function,
  884 + start_addr, count, query);
642 885  
643   - query_ret = modbus_query(mb_param, query, query_size);
  886 + query_ret = modbus_send(mb_param, query, query_size);
644 887 if (query_ret > 0)
645 888 status = read_reg_response(mb_param, data_dest, query);
646 889 else
... ... @@ -649,12 +892,11 @@ static int read_registers(modbus_param_t *mb_param, int slave, int function,
649 892 return status;
650 893 }
651 894  
652   -/* Read the holding registers in a slave and put the data into an
  895 +/* Reads the holding registers in a slave and put the data into an
653 896 array */
654 897 int read_holding_registers(modbus_param_t *mb_param, int slave,
655 898 int start_addr, int count, int *data_dest)
656 899 {
657   - int function = 0x03;
658 900 int status;
659 901  
660 902 if (count > MAX_READ_HOLD_REGS) {
... ... @@ -662,17 +904,16 @@ int read_holding_registers(modbus_param_t *mb_param, int slave,
662 904 count = MAX_READ_HOLD_REGS;
663 905 }
664 906  
665   - status = read_registers(mb_param, slave, function,
  907 + status = read_registers(mb_param, slave, FC_READ_HOLDING_REGISTERS,
666 908 start_addr, count, data_dest);
667 909 return status;
668 910 }
669 911  
670   -/* Read the input registers in a slave and put the data into
  912 +/* Reads the input registers in a slave and put the data into
671 913 an array */
672 914 int read_input_registers(modbus_param_t *mb_param, int slave,
673 915 int start_addr, int count, int *data_dest)
674 916 {
675   - int function = 0x04;
676 917 int status;
677 918  
678 919 if (count > MAX_READ_INPUT_REGS) {
... ... @@ -680,7 +921,7 @@ int read_input_registers(modbus_param_t *mb_param, int slave,
680 921 count = MAX_READ_INPUT_REGS;
681 922 }
682 923  
683   - status = read_registers(mb_param, slave, function,
  924 + status = read_registers(mb_param, slave, FC_READ_INPUT_REGISTERS,
684 925 start_addr, count, data_dest);
685 926  
686 927 return status;
... ... @@ -696,7 +937,7 @@ static int read_reg_response(modbus_param_t *mb_param, int *data_dest,
696 937 int offset;
697 938 int i;
698 939  
699   - response_ret = modbus_response(mb_param, query, response);
  940 + response_ret = modbus_check_response(mb_param, query, response);
700 941  
701 942 offset = mb_param->header_length;
702 943  
... ... @@ -716,7 +957,7 @@ static int preset_response(modbus_param_t *mb_param, unsigned char *query)
716 957 int ret;
717 958 unsigned char response[MAX_PACKET_SIZE];
718 959  
719   - ret = modbus_response(mb_param, query, response);
  960 + ret = modbus_check_response(mb_param, query, response);
720 961  
721 962 return ret;
722 963 }
... ... @@ -730,10 +971,10 @@ static int set_single(modbus_param_t *mb_param, int slave, int function,
730 971 int query_ret;
731 972 unsigned char query[MAX_PACKET_SIZE];
732 973  
733   - query_size = build_request_packet(mb_param, slave, function,
734   - addr, value, query);
  974 + query_size = build_query_packet(mb_param, slave, function,
  975 + addr, value, query);
735 976  
736   - query_ret = modbus_query(mb_param, query, query_size);
  977 + query_ret = modbus_send(mb_param, query, query_size);
737 978 if (query_ret > 0)
738 979 status = preset_response(mb_param, query);
739 980 else
... ... @@ -743,17 +984,16 @@ static int set_single(modbus_param_t *mb_param, int slave, int function,
743 984 }
744 985  
745 986  
746   -/* Turn on or off a single coil on the slave device */
  987 +/* Turns on or off a single coil on the slave device */
747 988 int force_single_coil(modbus_param_t *mb_param, int slave,
748 989 int coil_addr, int state)
749 990 {
750   - int function = 0x05;
751 991 int status;
752 992  
753 993 if (state)
754 994 state = 0xFF00;
755 995  
756   - status = set_single(mb_param, slave, function, coil_addr, state);
  996 + status = set_single(mb_param, slave, FC_FORCE_SINGLE_COIL, coil_addr, state);
757 997  
758 998 return status;
759 999 }
... ... @@ -762,10 +1002,9 @@ int force_single_coil(modbus_param_t *mb_param, int slave,
762 1002 int preset_single_register(modbus_param_t *mb_param, int slave,
763 1003 int reg_addr, int value)
764 1004 {
765   - int function = 0x06;
766 1005 int status;
767 1006  
768   - status = set_single(mb_param, slave, function, reg_addr, value);
  1007 + status = set_single(mb_param, slave, FC_PRESET_SINGLE_REGISTER, reg_addr, value);
769 1008  
770 1009 return status;
771 1010 }
... ... @@ -776,7 +1015,6 @@ int force_multiple_coils(modbus_param_t *mb_param, int slave,
776 1015 int start_addr, int coil_count,
777 1016 int *data_src)
778 1017 {
779   - int function = 0x0F;
780 1018 int i;
781 1019 int byte_count;
782 1020 int query_size;
... ... @@ -791,8 +1029,8 @@ int force_multiple_coils(modbus_param_t *mb_param, int slave,
791 1029 coil_count = MAX_WRITE_COILS;
792 1030 }
793 1031  
794   - query_size = build_request_packet(mb_param, slave, function,
795   - start_addr, coil_count, query);
  1032 + query_size = build_query_packet(mb_param, slave, FC_FORCE_MULTIPLE_COILS,
  1033 + start_addr, coil_count, query);
796 1034 byte_count = (coil_count / 8) + ((coil_count % 8) ? 1 : 0);
797 1035 query[query_size++] = byte_count;
798 1036  
... ... @@ -814,7 +1052,7 @@ int force_multiple_coils(modbus_param_t *mb_param, int slave,
814 1052 query_size++;
815 1053 }
816 1054  
817   - query_ret = modbus_query(mb_param, query, query_size);
  1055 + query_ret = modbus_send(mb_param, query, query_size);
818 1056 if (query_ret > 0)
819 1057 status = preset_response(mb_param, query);
820 1058 else
... ... @@ -823,11 +1061,10 @@ int force_multiple_coils(modbus_param_t *mb_param, int slave,
823 1061 return status;
824 1062 }
825 1063  
826   -/* Copy the values in an array to an array on the slave */
  1064 +/* Copies the values in an array to an array on the slave */
827 1065 int preset_multiple_registers(modbus_param_t *mb_param, int slave,
828 1066 int start_addr, int reg_count, int *data_src)
829 1067 {
830   - int function = 0x10;
831 1068 int i;
832 1069 int query_size;
833 1070 int byte_count;
... ... @@ -841,8 +1078,9 @@ int preset_multiple_registers(modbus_param_t *mb_param, int slave,
841 1078 reg_count = MAX_WRITE_REGS;
842 1079 }
843 1080  
844   - query_size = build_request_packet(mb_param, slave, function,
845   - start_addr, reg_count, query);
  1081 + query_size = build_query_packet(mb_param, slave,
  1082 + FC_PRESET_MULTIPLE_REGISTERS,
  1083 + start_addr, reg_count, query);
846 1084 byte_count = reg_count * 2;
847 1085 query[query_size++] = byte_count;
848 1086  
... ... @@ -851,7 +1089,7 @@ int preset_multiple_registers(modbus_param_t *mb_param, int slave,
851 1089 query[query_size++] = data_src[i] & 0x00FF;
852 1090 }
853 1091  
854   - query_ret = modbus_query(mb_param, query, query_size);
  1092 + query_ret = modbus_send(mb_param, query, query_size);
855 1093 if (query_ret > 0)
856 1094 status = preset_response(mb_param, query);
857 1095 else
... ... @@ -864,7 +1102,6 @@ int preset_multiple_registers(modbus_param_t *mb_param, int slave,
864 1102 int report_slave_id(modbus_param_t *mb_param, int slave,
865 1103 unsigned char *data_dest)
866 1104 {
867   - int function = 0x11;
868 1105 int query_size;
869 1106 int query_ret;
870 1107 int response_ret;
... ... @@ -872,13 +1109,13 @@ int report_slave_id(modbus_param_t *mb_param, int slave,
872 1109 unsigned char query[MIN_QUERY_SIZE];
873 1110 unsigned char response[MAX_PACKET_SIZE];
874 1111  
875   - query_size = build_request_packet(mb_param, slave, function,
876   - 0, 0, query);
  1112 + query_size = build_query_packet(mb_param, slave, FC_REPORT_SLAVE_ID,
  1113 + 0, 0, query);
877 1114  
878 1115 /* start_addr and count are not used */
879 1116 query_size -= 4;
880 1117  
881   - query_ret = modbus_query(mb_param, query, query_size);
  1118 + query_ret = modbus_send(mb_param, query, query_size);
882 1119 if (query_ret > 0) {
883 1120 int i;
884 1121 int offset;
... ... @@ -886,7 +1123,7 @@ int report_slave_id(modbus_param_t *mb_param, int slave,
886 1123  
887 1124 /* Byte count, slave id, run indicator status,
888 1125 additional data */
889   - response_ret = modbus_response(mb_param, query, response);
  1126 + response_ret = modbus_check_response(mb_param, query, response);
890 1127  
891 1128 offset = mb_param->header_length;
892 1129 offset_length = offset + response_ret;
... ... @@ -1181,6 +1418,7 @@ static int modbus_connect_rtu(modbus_param_t *mb_param)
1181 1418 return 0;
1182 1419 }
1183 1420  
  1421 +/* Establishes a modbus connection with a modbus slave */
1184 1422 static int modbus_connect_tcp(modbus_param_t *mb_param)
1185 1423 {
1186 1424 int ret;
... ... @@ -1232,6 +1470,7 @@ static int modbus_connect_tcp(modbus_param_t *mb_param)
1232 1470 return 0;
1233 1471 }
1234 1472  
  1473 +/* Establishes a modbus connexion */
1235 1474 int modbus_connect(modbus_param_t *mb_param)
1236 1475 {
1237 1476 int ret;
... ... @@ -1244,7 +1483,63 @@ int modbus_connect(modbus_param_t *mb_param)
1244 1483 return ret;
1245 1484 }
1246 1485  
1247   -void modbus_listen_tcp(modbus_param_t *mb_param)
  1486 +/* Allocates 4 arrays to store coils, input status, input registers and
  1487 + holding registers. The pointers are stored in modbus_mapping structure.
  1488 +
  1489 + Returns: TRUE if ok, FALSE on failure
  1490 +
  1491 + */
  1492 +int modbus_mapping_new(modbus_mapping_t *mb_mapping,
  1493 + int nb_coil_status, int nb_input_status,
  1494 + int nb_input_registers, int nb_holding_registers)
  1495 +{
  1496 + /* 0X */
  1497 + mb_mapping->nb_coil_status = nb_coil_status;
  1498 + mb_mapping->tab_coil_status = (unsigned char *) g_malloc0(nb_coil_status * sizeof(unsigned char));
  1499 + if (mb_mapping->tab_coil_status == NULL)
  1500 + return FALSE;
  1501 +
  1502 + /* 1X */
  1503 + mb_mapping->nb_input_status = nb_input_status;
  1504 + mb_mapping->tab_input_status = (unsigned char *) g_malloc0(nb_input_status * sizeof(unsigned char));
  1505 + if (mb_mapping->tab_input_status == NULL) {
  1506 + g_free(mb_mapping->tab_coil_status);
  1507 + return FALSE;
  1508 + }
  1509 +
  1510 + /* 3X */
  1511 + mb_mapping->nb_input_registers = nb_input_registers;
  1512 + mb_mapping->tab_input_registers = (unsigned short *) g_malloc0(nb_input_registers * sizeof(unsigned short));
  1513 + if (mb_mapping->tab_input_registers == NULL) {
  1514 + g_free(mb_mapping->tab_coil_status);
  1515 + g_free(mb_mapping->tab_input_status);
  1516 + return FALSE;
  1517 + }
  1518 +
  1519 + /* 4X */
  1520 + mb_mapping->nb_holding_registers = nb_holding_registers;
  1521 + mb_mapping->tab_holding_registers = (unsigned short *) g_malloc0(nb_holding_registers * sizeof(unsigned short));
  1522 + if (mb_mapping->tab_holding_registers == NULL) {
  1523 + g_free(mb_mapping->tab_coil_status);
  1524 + g_free(mb_mapping->tab_input_status);
  1525 + g_free(mb_mapping->tab_input_registers);
  1526 + return FALSE;
  1527 + }
  1528 +
  1529 + return TRUE;
  1530 +}
  1531 +
  1532 +/* Frees the 4 arrays */
  1533 +void modbus_mapping_free(modbus_mapping_t *mb_mapping)
  1534 +{
  1535 + g_free(mb_mapping->tab_coil_status);
  1536 + g_free(mb_mapping->tab_input_status);
  1537 + g_free(mb_mapping->tab_input_registers);
  1538 + g_free(mb_mapping->tab_holding_registers);
  1539 +}
  1540 +
  1541 +/* Listens for any query from a modbus master */
  1542 +int modbus_init_listen_tcp(modbus_param_t *mb_param)
1248 1543 {
1249 1544 int ret;
1250 1545 int new_socket;
... ... @@ -1290,22 +1585,17 @@ void modbus_listen_tcp(modbus_param_t *mb_param)
1290 1585 if (ret < 0) {
1291 1586 perror("accept");
1292 1587 close(new_socket);
1293   - exit(1);
  1588 + new_socket = 0;
  1589 + exit(1);
1294 1590 } else {
1295   - unsigned char response[MAX_PACKET_SIZE];
1296   - int response_size;
1297   -
1298 1591 g_print("The client %s is connected\n",
1299 1592 inet_ntoa(addr.sin_addr));
1300   -
1301   - receive_response(mb_param, MAX_PACKET_SIZE,
1302   - response, &response_size);
1303 1593 }
1304 1594  
1305   - close(new_socket);
  1595 + return new_socket;
1306 1596 }
1307 1597  
1308   -/* Close the file descriptor */
  1598 +/* Closes the file descriptor in RTU mode */
1309 1599 static void modbus_close_rtu(modbus_param_t *mb_param)
1310 1600 {
1311 1601 if (tcsetattr(mb_param->fd, TCSANOW, &(mb_param->old_tios)) < 0)
... ... @@ -1314,12 +1604,14 @@ static void modbus_close_rtu(modbus_param_t *mb_param)
1314 1604 close(mb_param->fd);
1315 1605 }
1316 1606  
  1607 +/* Closes the network connection and socket in TCP mode */
1317 1608 static void modbus_close_tcp(modbus_param_t *mb_param)
1318 1609 {
1319 1610 shutdown(mb_param->fd, SHUT_RDWR);
1320 1611 close(mb_param->fd);
1321 1612 }
1322 1613  
  1614 +/* Closes a modbus connection */
1323 1615 void modbus_close(modbus_param_t *mb_param)
1324 1616 {
1325 1617 if (mb_param->type_com == RTU)
... ... @@ -1328,6 +1620,7 @@ void modbus_close(modbus_param_t *mb_param)
1328 1620 modbus_close_tcp(mb_param);
1329 1621 }
1330 1622  
  1623 +/* Activates the debug messages */
1331 1624 void modbus_set_debug(modbus_param_t *mb_param, int boolean)
1332 1625 {
1333 1626 mb_param->debug = boolean;
... ...
src/modbus.h
1 1 /*
2   - Copyright (C) 2001-2005 Stéphane Raimbault <stephane.raimbault@free.fr>
  2 + Copyright (C) 2001-2007 Stéphane Raimbault <stephane.raimbault@gmail.com>
3 3  
4 4 This library is free software; you can redistribute it and/or
5 5 modify it under the terms of the GNU Lesser General Public
... ... @@ -27,11 +27,13 @@
27 27  
28 28 #define MODBUS_TCP_PORT 502
29 29  
30   -#define HEADER_LENGTH_RTU 0
31   -#define PRESET_QUERY_SIZE_RTU 6
  30 +#define HEADER_LENGTH_RTU 0
  31 +#define PRESET_QUERY_SIZE_RTU 6
  32 +#define PRESET_RESPONSE_SIZE_RTU 2
32 33  
33   -#define HEADER_LENGTH_TCP 6
34   -#define PRESET_QUERY_SIZE_TCP 12
  34 +#define HEADER_LENGTH_TCP 6
  35 +#define PRESET_QUERY_SIZE_TCP 12
  36 +#define PRESET_RESPONSE_SIZE_TCP 8
35 37  
36 38 #define CHECKSUM_SIZE_RTU 2
37 39 #define CHECKSUM_SIZE_TCP 0
... ... @@ -62,6 +64,26 @@
62 64 #define TRUE 1
63 65 #endif
64 66  
  67 +#ifndef OFF
  68 +#define OFF 0
  69 +#endif
  70 +
  71 +#ifndef ON
  72 +#define ON 1
  73 +#endif
  74 +
  75 +/* Function codes */
  76 +#define FC_READ_COIL_STATUS 0x01 /* discretes inputs */
  77 +#define FC_READ_INPUT_STATUS 0x02 /* discretes outputs */
  78 +#define FC_READ_HOLDING_REGISTERS 0x03
  79 +#define FC_READ_INPUT_REGISTERS 0x04
  80 +#define FC_FORCE_SINGLE_COIL 0x05
  81 +#define FC_PRESET_SINGLE_REGISTER 0x06
  82 +#define FC_READ_EXCEPTION_STATUS 0x07
  83 +#define FC_FORCE_MULTIPLE_COILS 0x0F
  84 +#define FC_PRESET_MULTIPLE_REGISTERS 0x10
  85 +#define FC_REPORT_SLAVE_ID 0x11
  86 +
65 87 /* Protocol exceptions */
66 88 #define ILLEGAL_FUNCTION -0x01
67 89 #define ILLEGAL_DATA_ADDRESS -0x02
... ... @@ -84,17 +106,20 @@
84 106 #define INVALID_CRC -0x10
85 107 #define INVALID_EXCEPTION_CODE -0x11
86 108  
  109 +/* Internal using */
  110 +#define MSG_SIZE_UNDEFINED -1
  111 +
87 112 typedef enum { RTU, TCP } type_com_t;
88 113  
89   -typedef struct _modbus_param_t {
  114 +typedef struct {
90 115 /* Communication : RTU or TCP */
91 116 type_com_t type_com;
92 117 /* Device: "/dev/ttyS0" */
93 118 char device[11];
94   - /* Bauds: 19200 */
95   - int baud_i;
96 119 /* Parity: "even", "odd", "none" */
97 120 char parity[5];
  121 + /* Bauds: 19200 */
  122 + int baud_i;
98 123 /* Data bit */
99 124 int data_bit;
100 125 /* Stop bit */
... ... @@ -113,6 +138,17 @@ typedef struct _modbus_param_t {
113 138 int checksum_size;
114 139 } modbus_param_t;
115 140  
  141 +typedef struct {
  142 + int nb_coil_status;
  143 + int nb_input_status;
  144 + int nb_input_registers;
  145 + int nb_holding_registers;
  146 + unsigned char *tab_coil_status;
  147 + unsigned char *tab_input_status;
  148 + unsigned short *tab_input_registers;
  149 + unsigned short *tab_holding_registers;
  150 +} modbus_mapping_t;
  151 +
116 152 /* All functions used for sending or receiving data return :
117 153 - the numbers of values (bits or word) if success (0 or more)
118 154 - less than 0 for exceptions errors
... ... @@ -127,18 +163,18 @@ int read_coil_status(modbus_param_t *mb_param, int slave,
127 163 int read_input_status(modbus_param_t *mb_param, int slave,
128 164 int start_addr, int count, int *dest);
129 165  
130   -/* Read the holding registers in a slave and put the data into an
  166 +/* Reads the holding registers in a slave and put the data into an
131 167 array */
132 168 int read_holding_registers(modbus_param_t *mb_param, int slave,
133 169 int start_addr, int count, int *dest);
134 170  
135 171  
136   -/* Read the input registers in a slave and put the data into an
  172 +/* Reads the input registers in a slave and put the data into an
137 173 array */
138 174 int read_input_registers(modbus_param_t *mb_param, int slave,
139 175 int start_addr, int count, int *dest);
140 176  
141   -/* Turn on or off a single coil on the slave device */
  177 +/* Turns on or off a single coil on the slave device */
142 178 int force_single_coil(modbus_param_t *mb_param, int slave,
143 179 int coil_addr, int state);
144 180  
... ... @@ -174,26 +210,32 @@ void modbus_init_rtu(modbus_param_t *mb_param, char *device,
174 210 void modbus_init_tcp(modbus_param_t *mb_param, char *ip_address);
175 211  
176 212  
177   -/* This function sets up a serial port for RTU communications to
178   - modbus or a TCP connexion */
  213 +/* Sets up a serial port for RTU communications to modbus or a TCP
  214 + connexion */
179 215 int modbus_connect(modbus_param_t *mb_param);
180 216  
181   -/* This function closes the serial port and restores the previous port
182   - configuration or close the TCP connexion */
  217 +/* Closes the serial port and restores the previous port configuration
  218 + or close the TCP connexion */
183 219 void modbus_close(modbus_param_t *mb_param);
184 220  
185   -/* Set in debug mode */
  221 +/* Sets debug mode */
186 222 void modbus_set_debug(modbus_param_t *mb_param, int boolean);
187 223  
188   -/* Useful for a 'daemon' */
189   -void modbus_listen_tcp(modbus_param_t *mb_param);
  224 +/* Slave/client functions */
  225 +int modbus_mapping_new(modbus_mapping_t *mb_mapping,
  226 + int nb_coil_status, int nb_input_status,
  227 + int nb_input_registers, int nb_holding_registers);
  228 +void modbus_mapping_free(modbus_mapping_t *mb_mapping);
  229 +
  230 +int modbus_init_listen_tcp(modbus_param_t *mb_param);
190 231  
191   -/* Non implemented :
  232 +int modbus_listen(modbus_param_t *mb_param, unsigned char *query, int *query_size);
  233 +
  234 +void manage_query(modbus_param_t *mb_param, unsigned char *query,
  235 + int query_size, modbus_mapping_t *mb_mapping);
  236 +
  237 +/* Not implemented :
192 238 - read_exception_status()
193 239 */
194 240  
195   -/* Find out what a master is trying to ask this slave device */
196   -int get_slave_query_tcp(modbus_param_t *mb_param, int *slave_addr, int *query,
197   - int *start_addr, int *point_count, int *data);
198   -
199 241 #endif /* _MODBUS_H_ */
... ...