X-Git-Url: https://sigrok.org/gitweb/?a=blobdiff_plain;f=src%2Fhardware%2Frdtech-tc%2Fprotocol.c;h=39d52ba5c3ea6935e127f6f48e68a1a992b79f67;hb=63f46e3e6f1b3b0a20a1da45ad10a1cd0a8937ab;hp=93e479819a15aea4dc36c6023283be6572138688;hpb=ea5fc667dc3d8595e8a22e9cc7e83dea06ef0fdf;p=libsigrok.git diff --git a/src/hardware/rdtech-tc/protocol.c b/src/hardware/rdtech-tc/protocol.c index 93e47981..39d52ba5 100644 --- a/src/hardware/rdtech-tc/protocol.c +++ b/src/hardware/rdtech-tc/protocol.c @@ -31,25 +31,31 @@ #define SERIAL_WRITE_TIMEOUT_MS 1 -#define TC_POLL_LEN 192 #define TC_POLL_PERIOD_MS 100 #define TC_TIMEOUT_MS 1000 -static const char POLL_CMD[] = "getva"; +static const char *poll_cmd = "getva"; -#define MAGIC_PAC1 0x31636170UL -#define MAGIC_PAC2 0x32636170UL -#define MAGIC_PAC3 0x33636170UL +/* + * Response data (raw sample data) consists of three adjacent chunks + * of 64 bytes each. These chunks start with their magic string, and + * end in a 32bit checksum field. Measurement values are scattered + * across these 192 bytes total size. All multi-byte integer values + * are represented in little endian format. Typical size is 32 bits. + */ + +#define MAGIC_PAC1 0x70616331 /* 'pac1' */ +#define MAGIC_PAC2 0x70616332 /* 'pac2' */ +#define MAGIC_PAC3 0x70616333 /* 'pac3' */ -/* Length of PAC block excluding CRC */ -#define PAC_DATA_LEN 60 -/* Length of PAC block including CRC */ #define PAC_LEN 64 +#define PAC_CRC_POS (PAC_LEN - sizeof(uint32_t)) /* Offset to PAC block from start of poll data */ #define OFF_PAC1 (0 * PAC_LEN) #define OFF_PAC2 (1 * PAC_LEN) #define OFF_PAC3 (2 * PAC_LEN) +#define TC_POLL_LEN (3 * PAC_LEN) #define OFF_MODEL 4 #define LEN_MODEL 4 @@ -76,55 +82,58 @@ static const struct binary_analog_channel rdtech_tc_channels[] = { ALL_ZERO, }; -static int check_pac_crc(uint8_t *data) +static gboolean check_pac_crc(uint8_t *data) { uint16_t crc; uint32_t crc_field; - crc = sr_crc16(SR_CRC16_DEFAULT_INIT, data, PAC_DATA_LEN); - crc_field = RL32(data + PAC_DATA_LEN); - + crc = sr_crc16(SR_CRC16_DEFAULT_INIT, data, PAC_CRC_POS); + crc_field = read_u32le(&data[PAC_CRC_POS]); if (crc != crc_field) { sr_spew("CRC error. Calculated: %0x" PRIx16 ", expected: %0x" PRIx32, crc, crc_field); - return 0; - } else { - return 1; + return FALSE; } + + return TRUE; } -static int process_poll_pkt(struct dev_context *devc, uint8_t *dst) +static int process_poll_pkt(struct dev_context *devc, uint8_t *dst) { struct aes256_ctx ctx; + gboolean ok; aes256_set_decrypt_key(&ctx, AES_KEY); aes256_decrypt(&ctx, TC_POLL_LEN, dst, devc->buf); - if (RL32(dst + OFF_PAC1) != MAGIC_PAC1 || - RL32(dst + OFF_PAC2) != MAGIC_PAC2 || - RL32(dst + OFF_PAC3) != MAGIC_PAC3) { - sr_err("Invalid poll packet magic values!"); - return SR_ERR; + ok = TRUE; + ok &= read_u32be(&dst[OFF_PAC1]) == MAGIC_PAC1; + ok &= read_u32be(&dst[OFF_PAC2]) == MAGIC_PAC2; + ok &= read_u32be(&dst[OFF_PAC3]) == MAGIC_PAC3; + if (!ok) { + sr_err("Invalid poll response packet (magic values)."); + return SR_ERR_DATA; } - if (!check_pac_crc(dst + OFF_PAC1) || - !check_pac_crc(dst + OFF_PAC2) || - !check_pac_crc(dst + OFF_PAC3)) { - sr_err("Invalid poll checksum!"); - return SR_ERR; + ok &= check_pac_crc(&dst[OFF_PAC1]); + ok &= check_pac_crc(&dst[OFF_PAC2]); + ok &= check_pac_crc(&dst[OFF_PAC3]); + if (!ok) { + sr_err("Invalid poll response packet (checksum)."); + return SR_ERR_DATA; } return SR_OK; } -SR_PRIV int rdtech_tc_probe(struct sr_serial_dev_inst *serial, struct dev_context *devc) +SR_PRIV int rdtech_tc_probe(struct sr_serial_dev_inst *serial, struct dev_context *devc) { int len; uint8_t poll_pkt[TC_POLL_LEN]; - if (serial_write_blocking(serial, &POLL_CMD, sizeof(POLL_CMD) - 1, - SERIAL_WRITE_TIMEOUT_MS) < 0) { - sr_err("Unable to send probe request."); + if (serial_write_blocking(serial, poll_cmd, strlen(poll_cmd), + SERIAL_WRITE_TIMEOUT_MS) < 0) { + sr_err("Failed to send probe request."); return SR_ERR; } @@ -140,24 +149,26 @@ SR_PRIV int rdtech_tc_probe(struct sr_serial_dev_inst *serial, struct dev_contex } devc->channels = rdtech_tc_channels; - devc->dev_info.model_name = g_strndup((const char *)poll_pkt + OFF_MODEL, LEN_MODEL); - devc->dev_info.fw_ver = g_strndup((const char *)poll_pkt + OFF_FW_VER, LEN_FW_VER); - devc->dev_info.serial_num = RL32(poll_pkt + OFF_SERIAL); + devc->dev_info.model_name = g_strndup((const char *)&poll_pkt[OFF_MODEL], LEN_MODEL); + devc->dev_info.fw_ver = g_strndup((const char *)&poll_pkt[OFF_FW_VER], LEN_FW_VER); + devc->dev_info.serial_num = read_u32le(&poll_pkt[OFF_SERIAL]); return SR_OK; } SR_PRIV int rdtech_tc_poll(const struct sr_dev_inst *sdi) { - struct dev_context *devc = sdi->priv; - struct sr_serial_dev_inst *serial = sdi->conn; + struct dev_context *devc; + struct sr_serial_dev_inst *serial; - if (serial_write_blocking(serial, &POLL_CMD, sizeof(POLL_CMD) - 1, - SERIAL_WRITE_TIMEOUT_MS) < 0) { + serial = sdi->conn; + if (serial_write_blocking(serial, poll_cmd, strlen(poll_cmd), + SERIAL_WRITE_TIMEOUT_MS) < 0) { sr_err("Unable to send poll request."); return SR_ERR; } + devc = sdi->priv; devc->cmd_sent_at = g_get_monotonic_time() / 1000; return SR_OK; @@ -165,14 +176,15 @@ SR_PRIV int rdtech_tc_poll(const struct sr_dev_inst *sdi) static void handle_poll_data(const struct sr_dev_inst *sdi) { - struct dev_context *devc = sdi->priv; + struct dev_context *devc; uint8_t poll_pkt[TC_POLL_LEN]; - int i; + size_t i; GSList *ch; - sr_spew("Received poll packet (len: %d).", devc->buflen); + devc = sdi->priv; + sr_spew("Received poll packet (len: %zu).", devc->buflen); if (devc->buflen != TC_POLL_LEN) { - sr_err("Unexpected poll packet length: %i", devc->buflen); + sr_err("Unexpected poll packet length: %zu", devc->buflen); return; } @@ -183,18 +195,19 @@ static void handle_poll_data(const struct sr_dev_inst *sdi) for (ch = sdi->channels, i = 0; ch; ch = g_slist_next(ch), i++) { bv_send_analog_channel(sdi, ch->data, - &devc->channels[i], poll_pkt, TC_POLL_LEN); - } + &devc->channels[i], poll_pkt, TC_POLL_LEN); + } sr_sw_limits_update_samples_read(&devc->limits, 1); } static void recv_poll_data(struct sr_dev_inst *sdi, struct sr_serial_dev_inst *serial) { - struct dev_context *devc = sdi->priv; + struct dev_context *devc; int len; /* Serial data arrived. */ + devc = sdi->priv; while (devc->buflen < TC_POLL_LEN) { len = serial_read_nonblocking(serial, devc->buf + devc->buflen, 1); if (len < 1) @@ -220,7 +233,6 @@ SR_PRIV int rdtech_tc_receive_data(int fd, int revents, void *cb_data) if (!(sdi = cb_data)) return TRUE; - if (!(devc = sdi->priv)) return TRUE; @@ -235,7 +247,6 @@ SR_PRIV int rdtech_tc_receive_data(int fd, int revents, void *cb_data) now = g_get_monotonic_time() / 1000; elapsed = now - devc->cmd_sent_at; - if (elapsed > TC_POLL_PERIOD_MS) rdtech_tc_poll(sdi);