Commit 78d301ed68af30e86665e5272ed8f68120be6352

Authored by Martijn de Gouw
Committed by Stéphane Raimbault
1 parent 912953a4

Add support for Mask Write Register

src/modbus-private.h
... ... @@ -62,6 +62,7 @@ MODBUS_BEGIN_DECLS
62 62 #define _FC_WRITE_MULTIPLE_COILS 0x0F
63 63 #define _FC_WRITE_MULTIPLE_REGISTERS 0x10
64 64 #define _FC_REPORT_SLAVE_ID 0x11
  65 +#define _FC_MASK_WRITE_REGISTER 0x16
65 66 #define _FC_WRITE_AND_READ_REGISTERS 0x17
66 67  
67 68 typedef enum {
... ...
src/modbus.c
... ... @@ -157,6 +157,9 @@ static unsigned int compute_response_length_from_request(modbus_t *ctx, uint8_t
157 157 /* The response is device specific (the header provides the
158 158 length) */
159 159 return MSG_LENGTH_UNDEFINED;
  160 + case _FC_MASK_WRITE_REGISTER:
  161 + length = 7;
  162 + break;
160 163 default:
161 164 length = 5;
162 165 }
... ... @@ -253,6 +256,8 @@ static uint8_t compute_meta_length_after_function(int function,
253 256 } else if (function == _FC_WRITE_MULTIPLE_COILS ||
254 257 function == _FC_WRITE_MULTIPLE_REGISTERS) {
255 258 length = 5;
  259 + } else if (function == _FC_MASK_WRITE_REGISTER) {
  260 + length = 6;
256 261 } else if (function == _FC_WRITE_AND_READ_REGISTERS) {
257 262 length = 9;
258 263 } else {
... ... @@ -268,6 +273,9 @@ static uint8_t compute_meta_length_after_function(int function,
268 273 case _FC_WRITE_MULTIPLE_REGISTERS:
269 274 length = 4;
270 275 break;
  276 + case _FC_MASK_WRITE_REGISTER:
  277 + length = 6;
  278 + break;
271 279 default:
272 280 length = 1;
273 281 }
... ... @@ -870,7 +878,26 @@ int modbus_reply(modbus_t *ctx, const uint8_t *req,
870 878 errno = ENOPROTOOPT;
871 879 return -1;
872 880 break;
  881 + case _FC_MASK_WRITE_REGISTER:
  882 + if (address >= mb_mapping->nb_registers) {
  883 + if (ctx->debug) {
  884 + fprintf(stderr, "Illegal data address %0X in write_register\n",
  885 + address);
  886 + }
  887 + rsp_length = response_exception(
  888 + ctx, &sft,
  889 + MODBUS_EXCEPTION_ILLEGAL_DATA_ADDRESS, rsp);
  890 + } else {
  891 + uint16_t data = mb_mapping->tab_registers[address];
  892 + uint16_t and = (req[offset + 3] << 8) + req[offset + 4];
  893 + uint16_t or = (req[offset + 5] << 8) + req[offset + 6];
873 894  
  895 + data = (data & and) | (or & (~and));
  896 + mb_mapping->tab_registers[address] = data;
  897 + memcpy(rsp, req, req_length);
  898 + rsp_length = req_length;
  899 + }
  900 + break;
874 901 case _FC_WRITE_AND_READ_REGISTERS: {
875 902 int nb = (req[offset + 3] << 8) + req[offset + 4];
876 903 uint16_t address_write = (req[offset + 5] << 8) + req[offset + 6];
... ... @@ -1263,6 +1290,37 @@ int modbus_write_registers(modbus_t *ctx, int addr, int nb, const uint16_t *src)
1263 1290 return rc;
1264 1291 }
1265 1292  
  1293 +int modbus_mask_write_register(modbus_t *ctx, int addr, uint16_t and, uint16_t or)
  1294 +{
  1295 + int rc;
  1296 + int req_length;
  1297 + uint8_t req[_MIN_REQ_LENGTH];
  1298 +
  1299 + req_length = ctx->backend->build_request_basis(ctx, _FC_MASK_WRITE_REGISTER, addr, 0, req);
  1300 +
  1301 + /* HACKISH, count is not used */
  1302 + req_length -=2;
  1303 +
  1304 + req[req_length++] = and >> 8;
  1305 + req[req_length++] = and & 0x00ff;
  1306 + req[req_length++] = or >> 8;
  1307 + req[req_length++] = or & 0x00ff;
  1308 +
  1309 + rc = send_msg(ctx, req, req_length);
  1310 + if (rc > 0) {
  1311 + /* Used by write_bit and write_register */
  1312 + uint8_t rsp[_MIN_REQ_LENGTH];
  1313 +
  1314 + rc = _modbus_receive_msg(ctx, rsp, MSG_CONFIRMATION);
  1315 + if (rc == -1)
  1316 + return -1;
  1317 +
  1318 + rc = check_confirmation(ctx, req, rsp, rc);
  1319 + }
  1320 +
  1321 + return rc;
  1322 +}
  1323 +
1266 1324 /* Write multiple registers from src array to remote device and read multiple
1267 1325 registers from remote device to dest array. */
1268 1326 int modbus_write_and_read_registers(modbus_t *ctx,
... ...
src/modbus.h
... ... @@ -185,6 +185,7 @@ EXPORT int modbus_write_bit(modbus_t *ctx, int coil_addr, int status);
185 185 EXPORT int modbus_write_register(modbus_t *ctx, int reg_addr, int value);
186 186 EXPORT int modbus_write_bits(modbus_t *ctx, int addr, int nb, const uint8_t *data);
187 187 EXPORT int modbus_write_registers(modbus_t *ctx, int addr, int nb, const uint16_t *data);
  188 +EXPORT int modbus_mask_write_register(modbus_t *ctx, int addr, uint16_t and, uint16_t or);
188 189 EXPORT int modbus_write_and_read_registers(modbus_t *ctx, int write_addr, int write_nb,
189 190 const uint16_t *src, int read_addr, int read_nb,
190 191 uint16_t *dest);
... ...