Agile Modbus  1.1.4
Lightweight modbus protocol stack.
agile_modbus.c
Go to the documentation of this file.
1 
39 #include "agile_modbus.h"
40 #include <string.h>
41 
49 #define AGILE_MODBUS_MSG_LENGTH_UNDEFINED -1
89 {
90  int length;
91 
92  if (msg_type == AGILE_MODBUS_MSG_INDICATION) {
93  if (function <= AGILE_MODBUS_FC_WRITE_SINGLE_REGISTER) {
94  length = 4;
95  } else if (function == AGILE_MODBUS_FC_WRITE_MULTIPLE_COILS ||
97  length = 5;
98  } else if (function == AGILE_MODBUS_FC_MASK_WRITE_REGISTER) {
99  length = 6;
100  } else if (function == AGILE_MODBUS_FC_WRITE_AND_READ_REGISTERS) {
101  length = 9;
102  } else {
103  /* MODBUS_FC_READ_EXCEPTION_STATUS, MODBUS_FC_REPORT_SLAVE_ID */
104  length = 0;
106  length = ctx->compute_meta_length_after_function(ctx, function, msg_type);
107  }
108  } else {
109  /* MSG_CONFIRMATION */
110  switch (function) {
117  length = 1;
118  break;
119 
124  length = 4;
125  break;
126 
128  length = 6;
129  break;
130 
131  default:
132  length = 1;
134  length = ctx->compute_meta_length_after_function(ctx, function, msg_type);
135  }
136  }
137 
138  return length;
139 }
140 
177 static int agile_modbus_compute_data_length_after_meta(agile_modbus_t *ctx, uint8_t *msg, int msg_length, agile_modbus_msg_type_t msg_type)
178 {
179  int function = msg[ctx->backend->header_length];
180  int length;
181 
182  if (msg_type == AGILE_MODBUS_MSG_INDICATION) {
183  switch (function) {
186  length = msg[ctx->backend->header_length + 5];
187  break;
188 
190  length = msg[ctx->backend->header_length + 9];
191  break;
192 
193  default:
194  length = 0;
196  length = ctx->compute_data_length_after_meta(ctx, msg, msg_length, msg_type);
197  }
198  } else {
199  /* MSG_CONFIRMATION */
200  if (function <= AGILE_MODBUS_FC_READ_INPUT_REGISTERS ||
201  function == AGILE_MODBUS_FC_REPORT_SLAVE_ID ||
203  length = msg[ctx->backend->header_length + 1];
204  } else {
205  length = 0;
207  length = ctx->compute_data_length_after_meta(ctx, msg, msg_length, msg_type);
208  }
209  }
210 
211  length += ctx->backend->checksum_length;
212 
213  return length;
214 }
215 
224 static int agile_modbus_receive_msg_judge(agile_modbus_t *ctx, uint8_t *msg, int msg_length, agile_modbus_msg_type_t msg_type)
225 {
226  int remain_len = msg_length;
227 
228  remain_len -= (ctx->backend->header_length + 1);
229  if (remain_len < 0)
230  return -1;
231  remain_len -= agile_modbus_compute_meta_length_after_function(ctx, msg[ctx->backend->header_length], msg_type);
232  if (remain_len < 0)
233  return -1;
234  remain_len -= agile_modbus_compute_data_length_after_meta(ctx, msg, msg_length, msg_type);
235  if (remain_len < 0)
236  return -1;
237 
238  return ctx->backend->check_integrity(ctx, msg, msg_length - remain_len);
239 }
240 
257 void agile_modbus_common_init(agile_modbus_t *ctx, uint8_t *send_buf, int send_bufsz, uint8_t *read_buf, int read_bufsz)
258 {
259  memset(ctx, 0, sizeof(agile_modbus_t));
260  ctx->slave = -1;
261  ctx->send_buf = send_buf;
262  ctx->send_bufsz = send_bufsz;
263  ctx->read_buf = read_buf;
264  ctx->read_bufsz = read_bufsz;
265 }
266 
274 {
275  return ctx->backend->set_slave(ctx, slave);
276 }
277 
285  uint8_t (*cb)(agile_modbus_t *ctx, int function,
286  agile_modbus_msg_type_t msg_type))
287 {
289 }
290 
298  int (*cb)(agile_modbus_t *ctx, uint8_t *msg,
299  int msg_length, agile_modbus_msg_type_t msg_type))
300 {
302 }
303 
313 {
314  if ((msg_length <= 0) || (msg_length > ctx->read_bufsz))
315  return -1;
316 
317  int rc = agile_modbus_receive_msg_judge(ctx, ctx->read_buf, msg_length, msg_type);
318 
319  return rc;
320 }
321 
343 static int agile_modbus_check_confirmation(agile_modbus_t *ctx, uint8_t *req,
344  uint8_t *rsp, int rsp_length)
345 {
346  int rc;
347  int rsp_length_computed;
348  const int offset = ctx->backend->header_length;
349  const int function = rsp[offset];
350 
351  if (ctx->backend->pre_check_confirmation) {
352  rc = ctx->backend->pre_check_confirmation(ctx, req, rsp, rsp_length);
353  if (rc < 0)
354  return -1;
355  }
356 
357  rsp_length_computed = agile_modbus_compute_response_length_from_request(ctx, req);
358 
359  /* Exception code */
360  if (function >= 0x80) {
361  if (rsp_length == (offset + 2 + (int)ctx->backend->checksum_length) && req[offset] == (rsp[offset] - 0x80))
362  return (-128 - rsp[offset + 1]);
363  else
364  return -1;
365  }
366 
367  /* Check length */
368  if ((rsp_length == rsp_length_computed || rsp_length_computed == AGILE_MODBUS_MSG_LENGTH_UNDEFINED) && function < 0x80) {
369  int req_nb_value;
370  int rsp_nb_value;
371 
372  /* Check function code */
373  if (function != req[offset])
374  return -1;
375 
376  /* Check the number of values is corresponding to the request */
377  switch (function) {
380  /* Read functions, 8 values in a byte (nb
381  * of values in the request and byte count in
382  * the response. */
383  req_nb_value = (req[offset + 3] << 8) + req[offset + 4];
384  req_nb_value = (req_nb_value / 8) + ((req_nb_value % 8) ? 1 : 0);
385  rsp_nb_value = rsp[offset + 1];
386  break;
387 
391  /* Read functions 1 value = 2 bytes */
392  req_nb_value = (req[offset + 3] << 8) + req[offset + 4];
393  rsp_nb_value = (rsp[offset + 1] / 2);
394  break;
395 
398  /* N Write functions */
399  req_nb_value = (req[offset + 3] << 8) + req[offset + 4];
400  rsp_nb_value = (rsp[offset + 3] << 8) | rsp[offset + 4];
401  break;
402 
404  /* Report slave ID (bytes received) */
405  req_nb_value = rsp_nb_value = rsp[offset + 1];
406  break;
407 
408  default:
409  /* 1 Write functions & others */
410  req_nb_value = rsp_nb_value = 1;
411  }
412 
413  if (req_nb_value == rsp_nb_value)
414  rc = rsp_nb_value;
415  else
416  rc = -1;
417  } else
418  rc = -1;
419 
420  return rc;
421 }
422 
446 {
447  int min_req_length = ctx->backend->header_length + 5 + ctx->backend->checksum_length;
448  if (ctx->send_bufsz < min_req_length)
449  return -1;
450 
452  return -1;
453 
454  int req_length = 0;
455  req_length = ctx->backend->build_request_basis(ctx, AGILE_MODBUS_FC_READ_COILS, addr, nb, ctx->send_buf);
456  req_length = ctx->backend->send_msg_pre(ctx->send_buf, req_length);
457 
458  return req_length;
459 }
460 
461 int agile_modbus_deserialize_read_bits(agile_modbus_t *ctx, int msg_length, uint8_t *dest)
462 {
463  int min_req_length = ctx->backend->header_length + 5 + ctx->backend->checksum_length;
464  if (ctx->send_bufsz < min_req_length)
465  return -1;
466  if ((msg_length <= 0) || (msg_length > ctx->read_bufsz))
467  return -1;
468 
470  if (rc < 0)
471  return -1;
472 
473  rc = agile_modbus_check_confirmation(ctx, ctx->send_buf, ctx->read_buf, rc);
474  if (rc < 0)
475  return rc;
476 
477  int i, temp, bit;
478  int pos = 0;
479  int offset;
480  int offset_end;
481  int nb;
482 
483  offset = ctx->backend->header_length + 2;
484  offset_end = offset + rc;
485  nb = (ctx->send_buf[ctx->backend->header_length + 3] << 8) + ctx->send_buf[ctx->backend->header_length + 4];
486 
487  for (i = offset; i < offset_end; i++) {
488  /* Shift reg hi_byte to temp */
489  temp = ctx->read_buf[i];
490 
491  for (bit = 0x01; (bit & 0xff) && (pos < nb);) {
492  dest[pos++] = (temp & bit) ? 1 : 0;
493  bit = bit << 1;
494  }
495  }
496 
497  return nb;
498 }
499 
501 {
502  int min_req_length = ctx->backend->header_length + 5 + ctx->backend->checksum_length;
503  if (ctx->send_bufsz < min_req_length)
504  return -1;
505 
507  return -1;
508 
509  int req_length = 0;
510  req_length = ctx->backend->build_request_basis(ctx, AGILE_MODBUS_FC_READ_DISCRETE_INPUTS, addr, nb, ctx->send_buf);
511  req_length = ctx->backend->send_msg_pre(ctx->send_buf, req_length);
512 
513  return req_length;
514 }
515 
516 int agile_modbus_deserialize_read_input_bits(agile_modbus_t *ctx, int msg_length, uint8_t *dest)
517 {
518  int min_req_length = ctx->backend->header_length + 5 + ctx->backend->checksum_length;
519  if (ctx->send_bufsz < min_req_length)
520  return -1;
521  if ((msg_length <= 0) || (msg_length > ctx->read_bufsz))
522  return -1;
523 
525  if (rc < 0)
526  return -1;
527 
528  rc = agile_modbus_check_confirmation(ctx, ctx->send_buf, ctx->read_buf, rc);
529  if (rc < 0)
530  return rc;
531 
532  int i, temp, bit;
533  int pos = 0;
534  int offset;
535  int offset_end;
536  int nb;
537 
538  offset = ctx->backend->header_length + 2;
539  offset_end = offset + rc;
540  nb = (ctx->send_buf[ctx->backend->header_length + 3] << 8) + ctx->send_buf[ctx->backend->header_length + 4];
541 
542  for (i = offset; i < offset_end; i++) {
543  /* Shift reg hi_byte to temp */
544  temp = ctx->read_buf[i];
545 
546  for (bit = 0x01; (bit & 0xff) && (pos < nb);) {
547  dest[pos++] = (temp & bit) ? 1 : 0;
548  bit = bit << 1;
549  }
550  }
551 
552  return nb;
553 }
554 
556 {
557  int min_req_length = ctx->backend->header_length + 5 + ctx->backend->checksum_length;
558  if (ctx->send_bufsz < min_req_length)
559  return -1;
560 
562  return -1;
563 
564  int req_length = 0;
565  req_length = ctx->backend->build_request_basis(ctx, AGILE_MODBUS_FC_READ_HOLDING_REGISTERS, addr, nb, ctx->send_buf);
566  req_length = ctx->backend->send_msg_pre(ctx->send_buf, req_length);
567 
568  return req_length;
569 }
570 
571 int agile_modbus_deserialize_read_registers(agile_modbus_t *ctx, int msg_length, uint16_t *dest)
572 {
573  int min_req_length = ctx->backend->header_length + 5 + ctx->backend->checksum_length;
574  if (ctx->send_bufsz < min_req_length)
575  return -1;
576  if ((msg_length <= 0) || (msg_length > ctx->read_bufsz))
577  return -1;
578 
580  if (rc < 0)
581  return -1;
582 
583  rc = agile_modbus_check_confirmation(ctx, ctx->send_buf, ctx->read_buf, rc);
584  if (rc < 0)
585  return rc;
586 
587  int offset;
588  int i;
589 
590  offset = ctx->backend->header_length;
591  for (i = 0; i < rc; i++) {
592  /* shift reg hi_byte to temp OR with lo_byte */
593  dest[i] = (ctx->read_buf[offset + 2 + (i << 1)] << 8) | ctx->read_buf[offset + 3 + (i << 1)];
594  }
595 
596  return rc;
597 }
598 
600 {
601  int min_req_length = ctx->backend->header_length + 5 + ctx->backend->checksum_length;
602  if (ctx->send_bufsz < min_req_length)
603  return -1;
604 
606  return -1;
607 
608  int req_length = 0;
609  req_length = ctx->backend->build_request_basis(ctx, AGILE_MODBUS_FC_READ_INPUT_REGISTERS, addr, nb, ctx->send_buf);
610  req_length = ctx->backend->send_msg_pre(ctx->send_buf, req_length);
611 
612  return req_length;
613 }
614 
615 int agile_modbus_deserialize_read_input_registers(agile_modbus_t *ctx, int msg_length, uint16_t *dest)
616 {
617  int min_req_length = ctx->backend->header_length + 5 + ctx->backend->checksum_length;
618  if (ctx->send_bufsz < min_req_length)
619  return -1;
620  if ((msg_length <= 0) || (msg_length > ctx->read_bufsz))
621  return -1;
622 
624  if (rc < 0)
625  return -1;
626 
627  rc = agile_modbus_check_confirmation(ctx, ctx->send_buf, ctx->read_buf, rc);
628  if (rc < 0)
629  return rc;
630 
631  int offset;
632  int i;
633 
634  offset = ctx->backend->header_length;
635  for (i = 0; i < rc; i++) {
636  /* shift reg hi_byte to temp OR with lo_byte */
637  dest[i] = (ctx->read_buf[offset + 2 + (i << 1)] << 8) | ctx->read_buf[offset + 3 + (i << 1)];
638  }
639 
640  return rc;
641 }
642 
643 int agile_modbus_serialize_write_bit(agile_modbus_t *ctx, int addr, int status)
644 {
645  int min_req_length = ctx->backend->header_length + 5 + ctx->backend->checksum_length;
646  if (ctx->send_bufsz < min_req_length)
647  return -1;
648 
649  int req_length = 0;
650  req_length = ctx->backend->build_request_basis(ctx, AGILE_MODBUS_FC_WRITE_SINGLE_COIL, addr, status ? 0xFF00 : 0, ctx->send_buf);
651  req_length = ctx->backend->send_msg_pre(ctx->send_buf, req_length);
652 
653  return req_length;
654 }
655 
657 {
658  int min_req_length = ctx->backend->header_length + 5 + ctx->backend->checksum_length;
659  if (ctx->send_bufsz < min_req_length)
660  return -1;
661  if ((msg_length <= 0) || (msg_length > ctx->read_bufsz))
662  return -1;
663 
665  if (rc < 0)
666  return -1;
667 
668  rc = agile_modbus_check_confirmation(ctx, ctx->send_buf, ctx->read_buf, rc);
669 
670  return rc;
671 }
672 
673 int agile_modbus_serialize_write_register(agile_modbus_t *ctx, int addr, const uint16_t value)
674 {
675  int min_req_length = ctx->backend->header_length + 5 + ctx->backend->checksum_length;
676  if (ctx->send_bufsz < min_req_length)
677  return -1;
678 
679  int req_length = 0;
680  req_length = ctx->backend->build_request_basis(ctx, AGILE_MODBUS_FC_WRITE_SINGLE_REGISTER, addr, (int)value, ctx->send_buf);
681  req_length = ctx->backend->send_msg_pre(ctx->send_buf, req_length);
682 
683  return req_length;
684 }
685 
687 {
688  int min_req_length = ctx->backend->header_length + 5 + ctx->backend->checksum_length;
689  if (ctx->send_bufsz < min_req_length)
690  return -1;
691  if ((msg_length <= 0) || (msg_length > ctx->read_bufsz))
692  return -1;
693 
695  if (rc < 0)
696  return -1;
697 
698  rc = agile_modbus_check_confirmation(ctx, ctx->send_buf, ctx->read_buf, rc);
699 
700  return rc;
701 }
702 
703 int agile_modbus_serialize_write_bits(agile_modbus_t *ctx, int addr, int nb, const uint8_t *src)
704 {
705  int min_req_length = ctx->backend->header_length + 5 + ctx->backend->checksum_length;
706  if (ctx->send_bufsz < min_req_length)
707  return -1;
708 
710  return -1;
711 
712  int i;
713  int byte_count;
714  int req_length;
715  int bit_check = 0;
716  int pos = 0;
717 
718  req_length = ctx->backend->build_request_basis(ctx, AGILE_MODBUS_FC_WRITE_MULTIPLE_COILS, addr, nb, ctx->send_buf);
719  byte_count = (nb / 8) + ((nb % 8) ? 1 : 0);
720 
721  min_req_length += (1 + byte_count);
722  if (ctx->send_bufsz < min_req_length)
723  return -1;
724 
725  ctx->send_buf[req_length++] = byte_count;
726  for (i = 0; i < byte_count; i++) {
727  int bit;
728 
729  bit = 0x01;
730  ctx->send_buf[req_length] = 0;
731 
732  while ((bit & 0xFF) && (bit_check++ < nb)) {
733  if (src[pos++])
734  ctx->send_buf[req_length] |= bit;
735  else
736  ctx->send_buf[req_length] &= ~bit;
737 
738  bit = bit << 1;
739  }
740  req_length++;
741  }
742 
743  req_length = ctx->backend->send_msg_pre(ctx->send_buf, req_length);
744 
745  return req_length;
746 }
747 
749 {
750  int min_req_length = ctx->backend->header_length + 5 + ctx->backend->checksum_length;
751  if (ctx->send_bufsz < min_req_length)
752  return -1;
753  if ((msg_length <= 0) || (msg_length > ctx->read_bufsz))
754  return -1;
755 
757  if (rc < 0)
758  return -1;
759 
760  rc = agile_modbus_check_confirmation(ctx, ctx->send_buf, ctx->read_buf, rc);
761 
762  return rc;
763 }
764 
765 int agile_modbus_serialize_write_registers(agile_modbus_t *ctx, int addr, int nb, const uint16_t *src)
766 {
767  int min_req_length = ctx->backend->header_length + 5 + ctx->backend->checksum_length;
768  if (ctx->send_bufsz < min_req_length)
769  return -1;
770 
772  return -1;
773 
774  int i;
775  int req_length;
776  int byte_count;
777 
778  req_length = ctx->backend->build_request_basis(ctx, AGILE_MODBUS_FC_WRITE_MULTIPLE_REGISTERS, addr, nb, ctx->send_buf);
779  byte_count = nb * 2;
780 
781  min_req_length += (1 + byte_count);
782  if (ctx->send_bufsz < min_req_length)
783  return -1;
784 
785  ctx->send_buf[req_length++] = byte_count;
786  for (i = 0; i < nb; i++) {
787  ctx->send_buf[req_length++] = src[i] >> 8;
788  ctx->send_buf[req_length++] = src[i] & 0x00FF;
789  }
790 
791  req_length = ctx->backend->send_msg_pre(ctx->send_buf, req_length);
792 
793  return req_length;
794 }
795 
797 {
798  int min_req_length = ctx->backend->header_length + 5 + ctx->backend->checksum_length;
799  if (ctx->send_bufsz < min_req_length)
800  return -1;
801  if ((msg_length <= 0) || (msg_length > ctx->read_bufsz))
802  return -1;
803 
805  if (rc < 0)
806  return -1;
807 
808  rc = agile_modbus_check_confirmation(ctx, ctx->send_buf, ctx->read_buf, rc);
809 
810  return rc;
811 }
812 
813 int agile_modbus_serialize_mask_write_register(agile_modbus_t *ctx, int addr, uint16_t and_mask, uint16_t or_mask)
814 {
815  int min_req_length = ctx->backend->header_length + 5 + ctx->backend->checksum_length + 2;
816  if (ctx->send_bufsz < min_req_length)
817  return -1;
818 
819  int req_length = 0;
820  req_length = ctx->backend->build_request_basis(ctx, AGILE_MODBUS_FC_MASK_WRITE_REGISTER, addr, 0, ctx->send_buf);
821 
822  /* HACKISH, count is not used */
823  req_length -= 2;
824 
825  ctx->send_buf[req_length++] = and_mask >> 8;
826  ctx->send_buf[req_length++] = and_mask & 0x00ff;
827  ctx->send_buf[req_length++] = or_mask >> 8;
828  ctx->send_buf[req_length++] = or_mask & 0x00ff;
829 
830  req_length = ctx->backend->send_msg_pre(ctx->send_buf, req_length);
831 
832  return req_length;
833 }
834 
836 {
837  int min_req_length = ctx->backend->header_length + 5 + ctx->backend->checksum_length;
838  if (ctx->send_bufsz < min_req_length)
839  return -1;
840  if ((msg_length <= 0) || (msg_length > ctx->read_bufsz))
841  return -1;
842 
844  if (rc < 0)
845  return -1;
846 
847  rc = agile_modbus_check_confirmation(ctx, ctx->send_buf, ctx->read_buf, rc);
848 
849  return rc;
850 }
851 
853  int write_addr, int write_nb,
854  const uint16_t *src,
855  int read_addr, int read_nb)
856 {
857  int min_req_length = ctx->backend->header_length + 5 + ctx->backend->checksum_length;
858  if (ctx->send_bufsz < min_req_length)
859  return -1;
860 
862  return -1;
863 
865  return -1;
866 
867  int req_length;
868  int i;
869  int byte_count;
870 
871  req_length = ctx->backend->build_request_basis(ctx, AGILE_MODBUS_FC_WRITE_AND_READ_REGISTERS, read_addr, read_nb, ctx->send_buf);
872  byte_count = write_nb * 2;
873 
874  min_req_length += (5 + byte_count);
875  if (ctx->send_bufsz < min_req_length)
876  return -1;
877 
878  ctx->send_buf[req_length++] = write_addr >> 8;
879  ctx->send_buf[req_length++] = write_addr & 0x00ff;
880  ctx->send_buf[req_length++] = write_nb >> 8;
881  ctx->send_buf[req_length++] = write_nb & 0x00ff;
882  ctx->send_buf[req_length++] = byte_count;
883  for (i = 0; i < write_nb; i++) {
884  ctx->send_buf[req_length++] = src[i] >> 8;
885  ctx->send_buf[req_length++] = src[i] & 0x00FF;
886  }
887 
888  req_length = ctx->backend->send_msg_pre(ctx->send_buf, req_length);
889 
890  return req_length;
891 }
892 
893 int agile_modbus_deserialize_write_and_read_registers(agile_modbus_t *ctx, int msg_length, uint16_t *dest)
894 {
895  int min_req_length = ctx->backend->header_length + 5 + ctx->backend->checksum_length;
896  if (ctx->send_bufsz < min_req_length)
897  return -1;
898  if ((msg_length <= 0) || (msg_length > ctx->read_bufsz))
899  return -1;
900 
902  if (rc < 0)
903  return -1;
904 
905  rc = agile_modbus_check_confirmation(ctx, ctx->send_buf, ctx->read_buf, rc);
906  if (rc < 0)
907  return rc;
908 
909  int offset;
910  int i;
911 
912  offset = ctx->backend->header_length;
913  for (i = 0; i < rc; i++) {
914  /* shift reg hi_byte to temp OR with lo_byte */
915  dest[i] = (ctx->read_buf[offset + 2 + (i << 1)] << 8) | ctx->read_buf[offset + 3 + (i << 1)];
916  }
917 
918  return rc;
919 }
920 
922 {
923  int min_req_length = ctx->backend->header_length + 5 + ctx->backend->checksum_length;
924  if (ctx->send_bufsz < min_req_length)
925  return -1;
926 
927  int req_length = 0;
928  req_length = ctx->backend->build_request_basis(ctx, AGILE_MODBUS_FC_REPORT_SLAVE_ID, 0, 0, ctx->send_buf);
929  /* HACKISH, addr and count are not used */
930  req_length -= 4;
931  req_length = ctx->backend->send_msg_pre(ctx->send_buf, req_length);
932 
933  return req_length;
934 }
935 
936 int agile_modbus_deserialize_report_slave_id(agile_modbus_t *ctx, int msg_length, int max_dest, uint8_t *dest)
937 {
938  int min_req_length = ctx->backend->header_length + 5 + ctx->backend->checksum_length;
939  if (ctx->send_bufsz < min_req_length)
940  return -1;
941  if ((msg_length <= 0) || (msg_length > ctx->read_bufsz))
942  return -1;
943  if (max_dest <= 0)
944  return -1;
945 
947  if (rc < 0)
948  return -1;
949 
950  rc = agile_modbus_check_confirmation(ctx, ctx->send_buf, ctx->read_buf, rc);
951  if (rc < 0)
952  return rc;
953 
954  int i;
955  int offset;
956 
957  offset = ctx->backend->header_length + 2;
958 
959  /* Byte count, slave id, run indicator status and
960  additional data. Truncate copy to max_dest. */
961  for (i = 0; i < rc && i < max_dest; i++) {
962  dest[i] = ctx->read_buf[offset + i];
963  }
964 
965  return rc;
966 }
967 
985 {
986  int length;
987  const int offset = ctx->backend->header_length;
988 
989  switch (req[offset]) {
992  /* Header + nb values (code from write_bits) */
993  int nb = (req[offset + 3] << 8) | req[offset + 4];
994  length = 2 + (nb / 8) + ((nb % 8) ? 1 : 0);
995  } break;
996 
1000  /* Header + 2 * nb values */
1001  length = 2 + 2 * (req[offset + 3] << 8 | req[offset + 4]);
1002  break;
1003 
1008  length = 5;
1009  break;
1010 
1012  length = 7;
1013  break;
1014 
1015  default:
1016  /* The response is device specific (the header provides the
1017  length) */
1019  }
1020 
1021  return offset + length + ctx->backend->checksum_length;
1022 }
1023 
1031 int agile_modbus_serialize_raw_request(agile_modbus_t *ctx, const uint8_t *raw_req, int raw_req_length)
1032 {
1033  if (raw_req_length < 2) {
1034  /* The raw request must contain function and slave at least and
1035  must not be longer than the maximum pdu length plus the slave
1036  address. */
1037 
1038  return -1;
1039  }
1040 
1041  int min_req_length = ctx->backend->header_length + 1 + ctx->backend->checksum_length + raw_req_length - 2;
1042  if (ctx->send_bufsz < min_req_length)
1043  return -1;
1044 
1045  agile_modbus_sft_t sft;
1046  int req_length;
1047 
1048  sft.slave = raw_req[0];
1049  sft.function = raw_req[1];
1050  /* The t_id is left to zero */
1051  sft.t_id = 0;
1052  /* This response function only set the header so it's convenient here */
1053  req_length = ctx->backend->build_response_basis(&sft, ctx->send_buf);
1054 
1055  if (raw_req_length > 2) {
1056  /* Copy data after function code */
1057  memcpy(ctx->send_buf + req_length, raw_req + 2, raw_req_length - 2);
1058  req_length += raw_req_length - 2;
1059  }
1060 
1061  req_length = ctx->backend->send_msg_pre(ctx->send_buf, req_length);
1062 
1063  return req_length;
1064 }
1065 
1074 {
1075  int min_req_length = ctx->backend->header_length + 5 + ctx->backend->checksum_length;
1076  if (ctx->send_bufsz < min_req_length)
1077  return -1;
1078  if ((msg_length <= 0) || (msg_length > ctx->read_bufsz))
1079  return -1;
1080 
1082  if (rc < 0)
1083  return -1;
1084 
1085  rc = agile_modbus_check_confirmation(ctx, ctx->send_buf, ctx->read_buf, rc);
1086 
1087  return rc;
1088 }
1089 
1114 {
1115  int rsp_length;
1116 
1117  /* Build exception response */
1118  sft->function = sft->function + 0x80;
1119  rsp_length = ctx->backend->build_response_basis(sft, ctx->send_buf);
1120  ctx->send_buf[rsp_length++] = exception_code;
1121 
1122  return rsp_length;
1123 }
1124 
1139 void agile_modbus_slave_io_set(uint8_t *buf, int index, int status)
1140 {
1141  int offset = index / 8;
1142  int shift = index % 8;
1143 
1144  if (status)
1145  buf[offset] |= (0x01 << shift);
1146  else
1147  buf[offset] &= ~(0x01 << shift);
1148 }
1149 
1156 uint8_t agile_modbus_slave_io_get(uint8_t *buf, int index)
1157 {
1158  int offset = index / 8;
1159  int shift = index % 8;
1160 
1161  uint8_t status = (buf[offset] & (0x01 << shift)) ? 1 : 0;
1162 
1163  return status;
1164 }
1165 
1172 void agile_modbus_slave_register_set(uint8_t *buf, int index, uint16_t data)
1173 {
1174  buf[index * 2] = data >> 8;
1175  buf[index * 2 + 1] = data & 0xFF;
1176 }
1177 
1184 uint16_t agile_modbus_slave_register_get(uint8_t *buf, int index)
1185 {
1186  uint16_t data = (buf[index * 2] << 8) + buf[index * 2 + 1];
1187 
1188  return data;
1189 }
1190 
1203 int agile_modbus_slave_handle(agile_modbus_t *ctx, int msg_length, uint8_t slave_strict,
1204  agile_modbus_slave_callback_t slave_cb, const void *slave_data, int *frame_length)
1205 {
1206  int min_rsp_length = ctx->backend->header_length + 5 + ctx->backend->checksum_length;
1207  if (ctx->send_bufsz < min_rsp_length)
1208  return -1;
1209 
1210  int req_length = agile_modbus_receive_judge(ctx, msg_length, AGILE_MODBUS_MSG_INDICATION);
1211  if (req_length < 0)
1212  return -1;
1213  if (frame_length)
1214  *frame_length = req_length;
1215 
1216  int offset;
1217  int slave;
1218  int function;
1219  uint16_t address;
1220  int rsp_length = 0;
1221  int exception_code = 0;
1222  int reg_data = 0;
1223  agile_modbus_sft_t sft;
1224  uint8_t *req = ctx->read_buf;
1225  uint8_t *rsp = ctx->send_buf;
1226 
1227  memset(rsp, 0, ctx->send_bufsz);
1228  offset = ctx->backend->header_length;
1229  slave = req[offset - 1];
1230  function = req[offset];
1231  address = (req[offset + 1] << 8) + req[offset + 2];
1232 
1233  sft.slave = slave;
1234  sft.function = function;
1235  sft.t_id = ctx->backend->prepare_response_tid(req, &req_length);
1236 
1237  struct agile_modbus_slave_info slave_info = {0};
1238  slave_info.sft = &sft;
1239  slave_info.rsp_length = &rsp_length;
1240  slave_info.address = address;
1241 
1242  if (slave_strict) {
1243  if ((slave != ctx->slave) && (slave != AGILE_MODBUS_BROADCAST_ADDRESS))
1244  return 0;
1245  }
1246 
1247  switch (function) {
1250  int nb = (req[offset + 3] << 8) + req[offset + 4];
1251  if (nb < 1 || AGILE_MODBUS_MAX_READ_BITS < nb) {
1253  break;
1254  }
1255 
1256  int end_address = (int)address + nb - 1;
1257  if (end_address > 0xFFFF) {
1259  break;
1260  }
1261 
1262  rsp_length = ctx->backend->build_response_basis(&sft, rsp);
1263  slave_info.nb = (nb / 8) + ((nb % 8) ? 1 : 0);
1264  rsp[rsp_length++] = slave_info.nb;
1265  slave_info.send_index = rsp_length;
1266  rsp_length += slave_info.nb;
1267  slave_info.nb = nb;
1268  if (ctx->send_bufsz < (int)(rsp_length + ctx->backend->checksum_length)) {
1270  break;
1271  }
1272  } break;
1273 
1276  int nb = (req[offset + 3] << 8) + req[offset + 4];
1277  if (nb < 1 || AGILE_MODBUS_MAX_READ_REGISTERS < nb) {
1279  break;
1280  }
1281 
1282  int end_address = (int)address + nb - 1;
1283  if (end_address > 0xFFFF) {
1285  break;
1286  }
1287 
1288  rsp_length = ctx->backend->build_response_basis(&sft, rsp);
1289  slave_info.nb = nb << 1;
1290  rsp[rsp_length++] = slave_info.nb;
1291  slave_info.send_index = rsp_length;
1292  rsp_length += slave_info.nb;
1293  slave_info.nb = nb;
1294  if (ctx->send_bufsz < (int)(rsp_length + ctx->backend->checksum_length)) {
1296  break;
1297  }
1298  } break;
1299 
1302  #if 0
1303  if (address > 0xFFFF) {
1305  break;
1306  }
1307  #endif
1308 
1309  reg_data = (req[offset + 3] << 8) + req[offset + 4];
1310  if (reg_data == 0xFF00 || reg_data == 0x0)
1311  reg_data = reg_data ? 1 : 0;
1312  else {
1314  break;
1315  }
1316 
1317  slave_info.buf = (uint8_t *)&reg_data;
1318  rsp_length = req_length;
1319  if (ctx->send_bufsz < (int)(rsp_length + ctx->backend->checksum_length)) {
1321  break;
1322  }
1323  memcpy(rsp, req, req_length);
1324  } break;
1325 
1328  #if 0
1329  if (address > 0xFFFF) {
1331  break;
1332  }
1333  #endif
1334 
1335  reg_data = (req[offset + 3] << 8) + req[offset + 4];
1336 
1337  slave_info.buf = (uint8_t *)&reg_data;
1338  rsp_length = req_length;
1339  if (ctx->send_bufsz < (int)(rsp_length + ctx->backend->checksum_length)) {
1341  break;
1342  }
1343  memcpy(rsp, req, req_length);
1344  } break;
1345 
1347  int nb = (req[offset + 3] << 8) + req[offset + 4];
1348  int nb_bits = req[offset + 5];
1349  if (nb < 1 || AGILE_MODBUS_MAX_WRITE_BITS < nb || nb_bits * 8 < nb) {
1351  break;
1352  }
1353 
1354  int end_address = (int)address + nb - 1;
1355  if (end_address > 0xFFFF) {
1357  break;
1358  }
1359 
1360  rsp_length = ctx->backend->build_response_basis(&sft, rsp);
1361  slave_info.nb = nb;
1362  slave_info.buf = &req[offset + 6];
1363  if (ctx->send_bufsz < (int)(rsp_length + ctx->backend->checksum_length + 4)) {
1365  break;
1366  }
1367  /* 4 to copy the bit address (2) and the quantity of bits */
1368  memcpy(rsp + rsp_length, req + rsp_length, 4);
1369  rsp_length += 4;
1370  } break;
1371 
1373  int nb = (req[offset + 3] << 8) + req[offset + 4];
1374  int nb_bytes = req[offset + 5];
1375  if (nb < 1 || AGILE_MODBUS_MAX_WRITE_REGISTERS < nb || nb_bytes != nb * 2) {
1377  break;
1378  }
1379 
1380  int end_address = (int)address + nb - 1;
1381  if (end_address > 0xFFFF) {
1383  break;
1384  }
1385 
1386  rsp_length = ctx->backend->build_response_basis(&sft, rsp);
1387  slave_info.nb = nb;
1388  slave_info.buf = &req[offset + 6];
1389  if (ctx->send_bufsz < (int)(rsp_length + ctx->backend->checksum_length + 4)) {
1391  break;
1392  }
1393  /* 4 to copy the address (2) and the no. of registers */
1394  memcpy(rsp + rsp_length, req + rsp_length, 4);
1395  rsp_length += 4;
1396 
1397  } break;
1398 
1400  int str_len;
1401  int byte_count_pos;
1402 
1403  slave_cb = NULL;
1404  rsp_length = ctx->backend->build_response_basis(&sft, rsp);
1405  /* Skip byte count for now */
1406  byte_count_pos = rsp_length++;
1407  rsp[rsp_length++] = ctx->slave;
1408  /* Run indicator status to ON */
1409  rsp[rsp_length++] = 0xFF;
1410 
1411  str_len = strlen(AGILE_MODBUS_VERSION_STRING);
1412  if (ctx->send_bufsz < (int)(rsp_length + ctx->backend->checksum_length + str_len)) {
1414  break;
1415  }
1416  memcpy(rsp + rsp_length, AGILE_MODBUS_VERSION_STRING, str_len);
1417  rsp_length += str_len;
1418  rsp[byte_count_pos] = rsp_length - byte_count_pos - 1;
1419  } break;
1420 
1422  exception_code = AGILE_MODBUS_EXCEPTION_ILLEGAL_FUNCTION;
1423  break;
1424 
1427  #if 0
1428  if (address > 0xFFFF) {
1430  break;
1431  }
1432  #endif
1433 
1434  slave_info.buf = &req[offset + 3];
1435  rsp_length = req_length;
1436  if (ctx->send_bufsz < (int)(rsp_length + ctx->backend->checksum_length)) {
1438  break;
1439  }
1440  memcpy(rsp, req, req_length);
1441  } break;
1442 
1444  int nb = (req[offset + 3] << 8) + req[offset + 4];
1445  uint16_t address_write = (req[offset + 5] << 8) + req[offset + 6];
1446  int nb_write = (req[offset + 7] << 8) + req[offset + 8];
1447  int nb_write_bytes = req[offset + 9];
1448  if (nb_write < 1 || AGILE_MODBUS_MAX_WR_WRITE_REGISTERS < nb_write ||
1450  nb_write_bytes != nb_write * 2) {
1452  break;
1453  }
1454 
1455  int end_address = (int)address + nb - 1;
1456  int end_address_write = (int)address_write + nb_write - 1;
1457  if (end_address > 0xFFFF || end_address_write > 0xFFFF) {
1459  break;
1460  }
1461 
1462  rsp_length = ctx->backend->build_response_basis(&sft, rsp);
1463  rsp[rsp_length++] = nb << 1;
1464  slave_info.buf = &req[offset + 3];
1465  slave_info.send_index = rsp_length;
1466  rsp_length += (nb << 1);
1467  if (ctx->send_bufsz < (int)(rsp_length + ctx->backend->checksum_length)) {
1469  break;
1470  }
1471  } break;
1472 
1473  default: {
1474  if (slave_cb == NULL)
1475  exception_code = AGILE_MODBUS_EXCEPTION_ILLEGAL_FUNCTION;
1476  else {
1477  rsp_length = ctx->backend->build_response_basis(&sft, rsp);
1478  slave_info.send_index = rsp_length;
1479  slave_info.buf = &req[offset + 1];
1480  slave_info.nb = req_length - offset - 1;
1481  }
1482  } break;
1483  }
1484 
1485  if (exception_code)
1486  rsp_length = agile_modbus_serialize_response_exception(ctx, &sft, exception_code);
1487  else {
1488  if (slave_cb) {
1489  int ret = slave_cb(ctx, &slave_info, slave_data);
1490 
1491  if (ret < 0) {
1492  if (ret == -AGILE_MODBUS_EXCEPTION_UNKNOW)
1493  rsp_length = 0;
1494  else
1496  }
1497  }
1498  }
1499 
1500  if (rsp_length) {
1502  return 0;
1503 
1504  rsp_length = ctx->backend->send_msg_pre(rsp, rsp_length);
1505  }
1506 
1507  return rsp_length;
1508 }
1509 
Agile Modbus software package common header file.
void agile_modbus_set_compute_data_length_after_meta_cb(agile_modbus_t *ctx, int(*cb)(agile_modbus_t *ctx, uint8_t *msg, int msg_length, agile_modbus_msg_type_t msg_type))
sets the data length callback function to be received after calculating the data element of the modbu...
Definition: agile_modbus.c:297
void agile_modbus_common_init(agile_modbus_t *ctx, uint8_t *send_buf, int send_bufsz, uint8_t *read_buf, int read_bufsz)
initialize modbus handle
Definition: agile_modbus.c:257
int agile_modbus_receive_judge(agile_modbus_t *ctx, int msg_length, agile_modbus_msg_type_t msg_type)
Verify the correctness of received data.
Definition: agile_modbus.c:312
int agile_modbus_set_slave(agile_modbus_t *ctx, int slave)
set address
Definition: agile_modbus.c:273
void agile_modbus_set_compute_meta_length_after_function_cb(agile_modbus_t *ctx, uint8_t(*cb)(agile_modbus_t *ctx, int function, agile_modbus_msg_type_t msg_type))
sets the data element length callback function to be received after calculating the function code of ...
Definition: agile_modbus.c:284
agile_modbus_msg_type_t
Modbus received message type.
Definition: agile_modbus.h:179
@ AGILE_MODBUS_EXCEPTION_UNKNOW
Definition: agile_modbus.h:158
@ AGILE_MODBUS_EXCEPTION_ILLEGAL_FUNCTION
Definition: agile_modbus.h:147
@ AGILE_MODBUS_EXCEPTION_ILLEGAL_DATA_VALUE
Definition: agile_modbus.h:149
@ AGILE_MODBUS_EXCEPTION_ILLEGAL_DATA_ADDRESS
Definition: agile_modbus.h:148
@ AGILE_MODBUS_EXCEPTION_NEGATIVE_ACKNOWLEDGE
Definition: agile_modbus.h:153
@ AGILE_MODBUS_BACKEND_TYPE_RTU
RTU.
Definition: agile_modbus.h:165
@ AGILE_MODBUS_MSG_CONFIRMATION
Server-side request message.
Definition: agile_modbus.h:181
@ AGILE_MODBUS_MSG_INDICATION
Host-side request message.
Definition: agile_modbus.h:180
#define AGILE_MODBUS_MSG_LENGTH_UNDEFINED
The corresponding function code data length is undefined.
Definition: agile_modbus.c:49
static int agile_modbus_receive_msg_judge(agile_modbus_t *ctx, uint8_t *msg, int msg_length, agile_modbus_msg_type_t msg_type)
Check the correctness of received data.
Definition: agile_modbus.c:224
static uint8_t agile_modbus_compute_meta_length_after_function(agile_modbus_t *ctx, int function, agile_modbus_msg_type_t msg_type)
The length of the data element to be received after calculating the function code.
Definition: agile_modbus.c:88
static int agile_modbus_compute_data_length_after_meta(agile_modbus_t *ctx, uint8_t *msg, int msg_length, agile_modbus_msg_type_t msg_type)
The length of data to be received after calculating the data element.
Definition: agile_modbus.c:177
int agile_modbus_serialize_write_register(agile_modbus_t *ctx, int addr, const uint16_t value)
Definition: agile_modbus.c:673
int agile_modbus_serialize_write_and_read_registers(agile_modbus_t *ctx, int write_addr, int write_nb, const uint16_t *src, int read_addr, int read_nb)
Definition: agile_modbus.c:852
int agile_modbus_deserialize_write_and_read_registers(agile_modbus_t *ctx, int msg_length, uint16_t *dest)
Definition: agile_modbus.c:893
int agile_modbus_deserialize_mask_write_register(agile_modbus_t *ctx, int msg_length)
Definition: agile_modbus.c:835
int agile_modbus_deserialize_write_registers(agile_modbus_t *ctx, int msg_length)
Definition: agile_modbus.c:796
int agile_modbus_deserialize_write_bit(agile_modbus_t *ctx, int msg_length)
Definition: agile_modbus.c:656
int agile_modbus_serialize_read_registers(agile_modbus_t *ctx, int addr, int nb)
Definition: agile_modbus.c:555
int agile_modbus_deserialize_read_input_bits(agile_modbus_t *ctx, int msg_length, uint8_t *dest)
Definition: agile_modbus.c:516
int agile_modbus_serialize_write_bits(agile_modbus_t *ctx, int addr, int nb, const uint8_t *src)
Definition: agile_modbus.c:703
int agile_modbus_serialize_read_bits(agile_modbus_t *ctx, int addr, int nb)
Definition: agile_modbus.c:445
int agile_modbus_serialize_write_registers(agile_modbus_t *ctx, int addr, int nb, const uint16_t *src)
Definition: agile_modbus.c:765
int agile_modbus_deserialize_report_slave_id(agile_modbus_t *ctx, int msg_length, int max_dest, uint8_t *dest)
Definition: agile_modbus.c:936
int agile_modbus_deserialize_read_input_registers(agile_modbus_t *ctx, int msg_length, uint16_t *dest)
Definition: agile_modbus.c:615
int agile_modbus_deserialize_read_bits(agile_modbus_t *ctx, int msg_length, uint8_t *dest)
Definition: agile_modbus.c:461
int agile_modbus_serialize_write_bit(agile_modbus_t *ctx, int addr, int status)
Definition: agile_modbus.c:643
int agile_modbus_deserialize_write_register(agile_modbus_t *ctx, int msg_length)
Definition: agile_modbus.c:686
int agile_modbus_serialize_mask_write_register(agile_modbus_t *ctx, int addr, uint16_t and_mask, uint16_t or_mask)
Definition: agile_modbus.c:813
int agile_modbus_deserialize_write_bits(agile_modbus_t *ctx, int msg_length)
Definition: agile_modbus.c:748
int agile_modbus_serialize_read_input_registers(agile_modbus_t *ctx, int addr, int nb)
Definition: agile_modbus.c:599
int agile_modbus_deserialize_read_registers(agile_modbus_t *ctx, int msg_length, uint16_t *dest)
Definition: agile_modbus.c:571
int agile_modbus_serialize_report_slave_id(agile_modbus_t *ctx)
Definition: agile_modbus.c:921
int agile_modbus_serialize_read_input_bits(agile_modbus_t *ctx, int addr, int nb)
Definition: agile_modbus.c:500
static int agile_modbus_check_confirmation(agile_modbus_t *ctx, uint8_t *req, uint8_t *rsp, int rsp_length)
Check and confirm the slave response data.
Definition: agile_modbus.c:343
int agile_modbus_compute_response_length_from_request(agile_modbus_t *ctx, uint8_t *req)
Calculate the expected response data length.
Definition: agile_modbus.c:984
int agile_modbus_deserialize_raw_response(agile_modbus_t *ctx, int msg_length)
parses the original response data
int agile_modbus_serialize_raw_request(agile_modbus_t *ctx, const uint8_t *raw_req, int raw_req_length)
Pack the original data into a request message.
#define AGILE_MODBUS_BROADCAST_ADDRESS
Modbus broadcast address.
Definition: agile_modbus.h:69
#define AGILE_MODBUS_MAX_READ_BITS
Definition: agile_modbus.h:81
#define AGILE_MODBUS_VERSION_STRING
Agile Modbus version number.
Definition: agile_modbus.h:67
#define AGILE_MODBUS_MAX_WRITE_REGISTERS
Definition: agile_modbus.h:100
#define AGILE_MODBUS_MAX_WRITE_BITS
Definition: agile_modbus.h:82
#define AGILE_MODBUS_MAX_WR_WRITE_REGISTERS
Definition: agile_modbus.h:101
#define AGILE_MODBUS_MAX_READ_REGISTERS
Definition: agile_modbus.h:99
#define AGILE_MODBUS_MAX_WR_READ_REGISTERS
Definition: agile_modbus.h:102
#define AGILE_MODBUS_FC_MASK_WRITE_REGISTER
Definition: agile_modbus.h:58
#define AGILE_MODBUS_FC_READ_COILS
Definition: agile_modbus.h:48
#define AGILE_MODBUS_FC_WRITE_SINGLE_REGISTER
Definition: agile_modbus.h:53
#define AGILE_MODBUS_FC_WRITE_MULTIPLE_COILS
Definition: agile_modbus.h:55
#define AGILE_MODBUS_FC_WRITE_SINGLE_COIL
Definition: agile_modbus.h:52
#define AGILE_MODBUS_FC_READ_HOLDING_REGISTERS
Definition: agile_modbus.h:50
#define AGILE_MODBUS_FC_WRITE_AND_READ_REGISTERS
Definition: agile_modbus.h:59
#define AGILE_MODBUS_FC_READ_INPUT_REGISTERS
Definition: agile_modbus.h:51
#define AGILE_MODBUS_FC_REPORT_SLAVE_ID
Definition: agile_modbus.h:57
#define AGILE_MODBUS_FC_WRITE_MULTIPLE_REGISTERS
Definition: agile_modbus.h:56
#define AGILE_MODBUS_FC_READ_EXCEPTION_STATUS
Definition: agile_modbus.h:54
#define AGILE_MODBUS_FC_READ_DISCRETE_INPUTS
Definition: agile_modbus.h:49
int(* agile_modbus_slave_callback_t)(agile_modbus_t *ctx, struct agile_modbus_slave_info *slave_info, const void *data)
Slave callback function.
Definition: agile_modbus.h:265
int agile_modbus_slave_handle(agile_modbus_t *ctx, int msg_length, uint8_t slave_strict, agile_modbus_slave_callback_t slave_cb, const void *slave_data, int *frame_length)
slave data processing
uint8_t agile_modbus_slave_io_get(uint8_t *buf, int index)
Read slave IO status.
void agile_modbus_slave_io_set(uint8_t *buf, int index, int status)
slave IO settings
uint16_t agile_modbus_slave_register_get(uint8_t *buf, int index)
Read slave register data.
void agile_modbus_slave_register_set(uint8_t *buf, int index, uint16_t data)
slave register settings
static int agile_modbus_serialize_response_exception(agile_modbus_t *ctx, agile_modbus_sft_t *sft, int exception_code)
packaged exception response data
int(* check_integrity)(agile_modbus_t *ctx, uint8_t *msg, const int msg_length)
Check the receive data integrity interface.
Definition: agile_modbus.h:209
int(* set_slave)(agile_modbus_t *ctx, int slave)
Set address interface.
Definition: agile_modbus.h:203
int(* pre_check_confirmation)(agile_modbus_t *ctx, const uint8_t *req, const uint8_t *rsp, int rsp_length)
Pre-check confirmation interface.
Definition: agile_modbus.h:210
int(* build_response_basis)(agile_modbus_sft_t *sft, uint8_t *rsp)
Build a basic response message interface.
Definition: agile_modbus.h:206
uint32_t header_length
Header length, excluding function code.
Definition: agile_modbus.h:200
uint32_t backend_type
Backend type.
Definition: agile_modbus.h:199
int(* send_msg_pre)(uint8_t *req, int req_length)
Pre-send data interface.
Definition: agile_modbus.h:208
int(* prepare_response_tid)(const uint8_t *req, int *req_length)
Prepare response interface.
Definition: agile_modbus.h:207
int(* build_request_basis)(agile_modbus_t *ctx, int function, int addr, int nb, uint8_t *req)
Build a basic request message interface.
Definition: agile_modbus.h:204
uint32_t checksum_length
Check data length.
Definition: agile_modbus.h:201
contains the modbus header parameter structure
Definition: agile_modbus.h:187
int slave
slave address
Definition: agile_modbus.h:188
int t_id
Transaction identifier.
Definition: agile_modbus.h:190
int function
function code
Definition: agile_modbus.h:189
Agile Modbus slave information structure.
Definition: agile_modbus.h:246
uint8_t * buf
Data fields required for different function codes.
Definition: agile_modbus.h:251
int send_index
Current index of sending buffer.
Definition: agile_modbus.h:252
agile_modbus_sft_t * sft
sft structure pointer
Definition: agile_modbus.h:247
int address
Register address.
Definition: agile_modbus.h:249
int * rsp_length
Response data length pointer.
Definition: agile_modbus.h:248
Agile Modbus structure.
Definition: agile_modbus.h:217
int(* compute_data_length_after_meta)(agile_modbus_t *ctx, uint8_t *msg, int msg_length, agile_modbus_msg_type_t msg_type)
Customized calculation data length interface.
Definition: agile_modbus.h:225
uint8_t(* compute_meta_length_after_function)(agile_modbus_t *ctx, int function, agile_modbus_msg_type_t msg_type)
Customized calculation data element length interface.
Definition: agile_modbus.h:223
int send_bufsz
Send buffer size.
Definition: agile_modbus.h:220
uint8_t * send_buf
Send buffer.
Definition: agile_modbus.h:219
uint8_t * read_buf
Receive buffer.
Definition: agile_modbus.h:221
const agile_modbus_backend_t * backend
Backend interface.
Definition: agile_modbus.h:227
int slave
slave address
Definition: agile_modbus.h:218
int read_bufsz
Receive buffer size.
Definition: agile_modbus.h:222