SR_PRIV int bv_send_analog_channel(const struct sr_dev_inst *sdi, struct sr_channel *ch,
const struct binary_analog_channel *spec, const void *data, size_t length);
+/*--- crc.c -----------------------------------------------------------------*/
+
+#define SR_CRC16_DEFAULT_INIT 0xffffU
+
+/**
+ * Calculate a CRC16 checksum using the 0x8005 polynomial.
+ *
+ * This CRC16 flavor is also known as CRC16-ANSI or CRC16-MODBUS.
+ *
+ * @param crc Initial value (typically 0xffff)
+ * @param buffer Input buffer
+ * @param len Buffer length
+ * @return Checksum
+ */
+SR_PRIV uint16_t sr_crc16(uint16_t crc, const uint8_t *buffer, int len);
+
/*--- modbus/modbus.c -------------------------------------------------------*/
struct sr_modbus_dev_inst {
return serial_source_remove(session, serial);
}
-static uint16_t modbus_serial_rtu_crc(uint16_t crc,
- const uint8_t *buffer, int len)
-{
- int i;
-
- if (!buffer || len < 0)
- return crc;
-
- while (len--) {
- crc ^= *buffer++;
- for (i = 0; i < 8; i++) {
- int carry = crc & 1;
- crc >>= 1;
- if (carry)
- crc ^= 0xA001;
- }
- }
-
- return crc;
-}
-
static int modbus_serial_rtu_send(void *priv,
const uint8_t *buffer, int buffer_size)
{
if (result < 0)
return SR_ERR;
- crc = modbus_serial_rtu_crc(0xFFFF, &slave_addr, sizeof(slave_addr));
- crc = modbus_serial_rtu_crc(crc, buffer, buffer_size);
+ crc = sr_crc16(SR_CRC16_DEFAULT_INIT, &slave_addr, sizeof(slave_addr));
+ crc = sr_crc16(crc, buffer, buffer_size);
result = serial_write_blocking(serial, &crc, sizeof(crc), 0);
if (result < 0)
if (ret != 1)
return SR_ERR;
- modbus->crc = modbus_serial_rtu_crc(0xFFFF, &slave_addr, sizeof(slave_addr));
- modbus->crc = modbus_serial_rtu_crc(modbus->crc, function_code, 1);
+ modbus->crc = sr_crc16(SR_CRC16_DEFAULT_INIT, &slave_addr, sizeof(slave_addr));
+ modbus->crc = sr_crc16(modbus->crc, function_code, 1);
return SR_OK;
}
ret = serial_read_nonblocking(modbus->serial, buf, maxlen);
if (ret < 0)
return ret;
- modbus->crc = modbus_serial_rtu_crc(modbus->crc, buf, ret);
+ modbus->crc = sr_crc16(modbus->crc, buf, ret);
return ret;
}