1 /*
2  * Copyright (C) 2015-2018 Alibaba Group Holding Limited
3  */
4 
5 #include <mbmaster.h>
6 #include "rtu.h"
7 #include "../../pdu/pdu.h"
8 #include "mbcrc.h"
9 
10 #if (MBMASTER_CONFIG_RTU_ENABLED > 0)
rtu_assemble(mb_handler_t * handler)11 mb_status_t rtu_assemble(mb_handler_t *handler)
12 {
13     uint16_t    crc_16;
14     mb_status_t status = MB_SUCCESS;
15     uint8_t    *send_buf;
16 #ifdef DEBUG
17     uint8_t     debug_buf[256];
18     uint8_t     debug_hex[6];
19 #endif
20 
21     // // ?? why we need to fix timeout to 1000/200
22     // if (handler->slave_addr == SLAVE_ADDR_BROADCAST) {
23     //     handler->respond_timeout = 1000;
24     // } else {
25     //     handler->respond_timeout = 200;
26     // }
27 
28     send_buf = handler->mb_frame_buff;
29 
30     send_buf[ADU_SER_ADDR_OFF] = handler->slave_addr;
31     handler->mb_frame_length   = handler->pdu_length + 1;
32     crc_16 = mb_crc16((uint8_t *) send_buf, handler->mb_frame_length);
33 
34     send_buf[handler->mb_frame_length++] = (uint8_t)(crc_16 & 0xFF);
35     send_buf[handler->mb_frame_length++] = (uint8_t)(crc_16 >> 8);
36 
37 #ifdef DEBUG
38     uint32_t debug_len = 0;
39     LOGD(MODBUS_MOUDLE, "start to send data len=%u, data is: ", (unsigned int)handler->mb_frame_length);
40     memset(debug_buf, 0, sizeof(debug_buf));
41     for (int i = 0; i < handler->mb_frame_length; i++) {
42         debug_len += snprintf(debug_hex, sizeof(debug_hex),"0x%02x ", send_buf[i]);
43         if (debug_len >= (sizeof(debug_buf))) {
44             LOGD(MODBUS_MOUDLE, "assemble debug buf is not enough\n");
45             break;
46         }
47         strncat(debug_buf, debug_hex, sizeof(debug_buf) - strlen(debug_buf) -1);
48     }
49     LOGD(MODBUS_MOUDLE, "%s\n", debug_buf);
50 #endif
51 
52     return status;
53 }
54 
rtu_disassemble(mb_handler_t * handler)55 mb_status_t rtu_disassemble(mb_handler_t *handler)
56 {
57     mb_status_t status = MB_SUCCESS;
58     uint8_t    *recv_buf;
59 #ifdef DEBUG
60     uint8_t     debug_buf[256];
61     uint8_t     debug_hex[6];
62 #endif
63 
64     recv_buf = handler->mb_frame_buff;
65 
66 #ifdef DEBUG
67     uint32_t debug_len = 0;
68     LOGD(MODBUS_MOUDLE, "rev data len =%u, data is :", (unsigned int)handler->mb_frame_length);
69     memset(debug_buf, 0, sizeof(debug_buf));
70     for (int i = 0; i < handler->mb_frame_length; i++) {
71         debug_len += snprintf(debug_hex, sizeof(debug_hex),"0x%02x ", recv_buf[i]);
72         if (debug_len >= (sizeof(debug_buf))) {
73             LOGD(MODBUS_MOUDLE, "disassemble debug buf is not enough\n");
74             break;
75         }
76         strncat(debug_buf, debug_hex, sizeof(debug_buf) - strlen(debug_buf) -1);
77     }
78     LOGD(MODBUS_MOUDLE, "%s\n", debug_buf);
79 #endif
80 
81     if ((handler->mb_frame_length >= ADU_SER_LENGTH_MIN)
82         && (mb_crc16(( uint8_t *) recv_buf, handler->mb_frame_length) == 0)) {
83         handler->slave_addr = recv_buf[ADU_SER_ADDR_OFF];
84         handler->pdu_length = handler->mb_frame_length - ADU_SER_PDU_OFF - ADU_SER_LENGTH_CRC;
85         handler->pdu_offset = ADU_SER_PDU_OFF;
86     } else {
87         LOGE(MODBUS_MOUDLE, "frame is too short or CRC error\n");
88         status = MB_RESPOND_FRAME_ERR;
89     }
90     return status;
91 }
92 #endif /* MBMASTER_CONFIG_RTU_ENABLED */
93