Commit 78d301ed68af30e86665e5272ed8f68120be6352
Committed by
Stéphane Raimbault
1 parent
912953a4
Add support for Mask Write Register
Showing
3 changed files
with
60 additions
and
0 deletions
src/modbus-private.h
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); | ... | ... |