1 /*
2  * Copyright (C) 2015-2018 Alibaba Group Holding Limited
3  */
4 
5 #include <mbmaster.h>
6 #include "../pdu/pdu.h"
7 #include "main_process.h"
8 
9 /* process function code 0x01 0x02 0x03 0x04, they have the same request parameters */
mbmaster_main_type1_process(mb_handler_t * req_handler,uint8_t function_code,uint8_t slave_addr,uint16_t start_addr,uint16_t quantity,uint8_t * respond_buf,uint8_t * respond_count,uint32_t timeout)10 mb_status_t mbmaster_main_type1_process(mb_handler_t *req_handler, uint8_t function_code, uint8_t slave_addr,
11                                         uint16_t start_addr, uint16_t quantity, uint8_t *respond_buf,
12                                         uint8_t *respond_count, uint32_t timeout)
13 {
14     mb_status_t status = MB_SUCCESS;
15 
16     MB_MUTEX_LOCK(&req_handler->mb_mutex);
17 
18     req_handler->slave_addr = slave_addr;
19 
20     switch (function_code) {
21         case FUNC_CODE_READ_COILS:
22         case FUNC_CODE_READ_DISCRETE_INPUTS:
23             /* The modubs protocol limits the maximum number of reads */
24             if ((quantity < 1) || (quantity > QUANTITY_MAX_FUNC01)) {
25                 MB_MUTEX_UNLOCK(&req_handler->mb_mutex);
26                 return MB_INVALID_PARAM;
27             }
28             status = pdu_type122_assemble(req_handler, function_code, start_addr, quantity);
29             break;
30         case FUNC_CODE_READ_HOLDING_REGISTERS:
31         case FUNC_CODE_READ_INPUT_REGISTERS:
32             /* The modubs protocol limits the maximum number of reads */
33             if ((quantity < 1) || (quantity > QUANTITY_MAX_FUNC01)) {
34                 MB_MUTEX_UNLOCK(&req_handler->mb_mutex);
35                 return MB_INVALID_PARAM;
36             }
37             status = pdu_type122_assemble(req_handler, function_code, start_addr, quantity);
38             break;
39         default:
40             status = MB_FUNCTION_CODE_NOT_SUPPORT;
41             LOGE(MODBUS_MOUDLE, "invalid funciton code!\n");
42             break;
43     }
44     if (status != MB_SUCCESS) {
45         MB_MUTEX_UNLOCK(&req_handler->mb_mutex);
46         return status;
47     }
48 
49     req_handler->adu_assemble(req_handler);
50 
51     status = req_handler->frame_send(req_handler, timeout);
52     if (status != MB_SUCCESS) {
53         MB_MUTEX_UNLOCK(&req_handler->mb_mutex);
54         return status;
55     }
56 
57      /* wait slave respond */
58     LOGD(MODBUS_MOUDLE, "waiting for respond\n");
59 
60     status = req_handler->frame_recv(req_handler);
61     if (status != MB_SUCCESS) {
62         MB_MUTEX_UNLOCK(&req_handler->mb_mutex);
63         return status;
64     }
65 
66     req_handler->adu_disassemble(req_handler);
67 
68     switch (function_code) {
69         case FUNC_CODE_READ_COILS:
70         case FUNC_CODE_READ_DISCRETE_INPUTS:
71         case FUNC_CODE_READ_HOLDING_REGISTERS:
72         case FUNC_CODE_READ_INPUT_REGISTERS:
73             status = pdu_type11n_disassemble(req_handler, function_code, respond_buf, respond_count);
74             break;
75     }
76 
77     MB_MUTEX_UNLOCK(&req_handler->mb_mutex);
78 
79     return status;
80 }
81 
82 /* process function code 0x05 0x06, they have the same request parameters */
mbmaster_main_type2_process(mb_handler_t * req_handler,uint8_t function_code,uint8_t slave_addr,uint16_t register_addr,uint16_t register_value,uint16_t * resp_addr,uint16_t * resp_value,uint8_t * exception_code,uint32_t timeout)83 mb_status_t mbmaster_main_type2_process(mb_handler_t *req_handler, uint8_t function_code, uint8_t slave_addr,
84                                         uint16_t register_addr, uint16_t register_value, uint16_t *resp_addr,
85                                         uint16_t *resp_value, uint8_t* exception_code, uint32_t timeout)
86 {
87     mb_status_t status = MB_SUCCESS;
88 
89     MB_MUTEX_LOCK(&req_handler->mb_mutex);
90 
91     req_handler->slave_addr = slave_addr;
92 
93     switch (function_code) {
94         case FUNC_CODE_WRITE_SINGLE_COIL:
95             if ((register_value != 0) && (register_value != 0xFF00)) {
96                 status = MB_INVALID_PARAM;
97                 MB_MUTEX_UNLOCK(&req_handler->mb_mutex);
98                 return status;
99             }
100             status = pdu_type122_assemble(req_handler, function_code, register_addr, register_value);
101             break;
102         case FUNC_CODE_WRITE_SINGLE_REGISTERS:
103             status = pdu_type122_assemble(req_handler, function_code, register_addr, register_value);
104             break;
105         default:
106             status = MB_FUNCTION_CODE_NOT_SUPPORT;
107             LOGE(MODBUS_MOUDLE, "invalid funciton code!\n");
108             break;
109     }
110     if (status != MB_SUCCESS) {
111         MB_MUTEX_UNLOCK(&req_handler->mb_mutex);
112         return status;
113     }
114 
115     req_handler->adu_assemble(req_handler);
116 
117     status = req_handler->frame_send(req_handler, timeout);
118     if (status != MB_SUCCESS) {
119         MB_MUTEX_UNLOCK(&req_handler->mb_mutex);
120         return status;
121     }
122 
123      /* wait slave respond */
124     LOGD(MODBUS_MOUDLE, "waiting for respond\n");
125 
126     status = req_handler->frame_recv(req_handler);
127     if (status != MB_SUCCESS) {
128         MB_MUTEX_UNLOCK(&req_handler->mb_mutex);
129         return status;
130     }
131 
132     req_handler->adu_disassemble(req_handler);
133 
134     switch (function_code) {
135         case FUNC_CODE_WRITE_SINGLE_COIL:
136         case FUNC_CODE_WRITE_SINGLE_REGISTERS:
137             status = pdu_type122_disassemble(req_handler, function_code, resp_addr, resp_value, exception_code);
138             break;
139     }
140 
141     MB_MUTEX_UNLOCK(&req_handler->mb_mutex);
142 
143     return status;
144 }
145 
146 /* process function code 0x0F 0x10, they have the same request parameters */
mbmaster_main_type3_process(mb_handler_t * req_handler,uint8_t function_code,uint8_t slave_addr,uint16_t start_addr,uint16_t quantity,uint8_t * outputs_buf,uint16_t * resp_addr,uint16_t * resp_quantity,uint8_t * exception_code,uint32_t timeout)147 mb_status_t mbmaster_main_type3_process(mb_handler_t *req_handler, uint8_t function_code, uint8_t slave_addr,
148                                         uint16_t start_addr, uint16_t quantity, uint8_t *outputs_buf, uint16_t *resp_addr,
149                                         uint16_t *resp_quantity, uint8_t *exception_code, uint32_t timeout)
150 {
151     uint8_t     byte_count;
152     mb_status_t status = MB_SUCCESS;
153 
154     MB_MUTEX_LOCK(&req_handler->mb_mutex);
155 
156     req_handler->slave_addr = slave_addr;
157 
158     switch (function_code) {
159         case FUNC_CODE_WRITE_MULTIPLE_COILS:
160             byte_count = quantity / 8;
161             byte_count = (quantity % 8)?(byte_count + 1):byte_count;
162             status = pdu_type1221n_assemble(req_handler, function_code, start_addr, quantity, byte_count, outputs_buf);
163             break;
164         case FUNC_CODE_WRITE_MULTIPLE_REGISTERS:
165             byte_count = quantity * 2;
166             status = pdu_type1221n_assemble(req_handler, function_code, start_addr, quantity, byte_count, outputs_buf);
167             break;
168         default:
169             status = MB_FUNCTION_CODE_NOT_SUPPORT;
170             LOGE(MODBUS_MOUDLE, "invalid funciton code!\n");
171             break;
172     }
173     if (status != MB_SUCCESS) {
174         MB_MUTEX_UNLOCK(&req_handler->mb_mutex);
175         return status;
176     }
177 
178     req_handler->adu_assemble(req_handler);
179 
180     status = req_handler->frame_send(req_handler, timeout);
181     if (status != MB_SUCCESS) {
182         MB_MUTEX_UNLOCK(&req_handler->mb_mutex);
183         return status;
184     }
185 
186      /* wait slave respond */
187     LOGD(MODBUS_MOUDLE, "waiting for respond\n");
188 
189     status = req_handler->frame_recv(req_handler);
190     if (status != MB_SUCCESS) {
191         MB_MUTEX_UNLOCK(&req_handler->mb_mutex);
192         return status;
193     }
194 
195     req_handler->adu_disassemble(req_handler);
196 
197     switch (function_code) {
198         case FUNC_CODE_WRITE_MULTIPLE_COILS:
199         case FUNC_CODE_WRITE_MULTIPLE_REGISTERS:
200             status = pdu_type122_disassemble(req_handler, function_code, resp_addr, resp_quantity, exception_code);
201             break;
202     }
203 
204     MB_MUTEX_UNLOCK(&req_handler->mb_mutex);
205 
206     return status;
207 }
208