X-Git-Url: https://sigrok.org/gitweb/?a=blobdiff_plain;f=src%2Fhardware%2Frdtech-um%2Fprotocol.c;h=6c56e245faa5f21576a1354e9fc21c65e8f14d2c;hb=85accbc2e7c14b49039b5a9a3fc8afc169a9acc0;hp=04de768713ac04d2d6c039454e1b7982610466cb;hpb=0988d4ae2d7a47258b1ec3278381a973aa12831e;p=libsigrok.git diff --git a/src/hardware/rdtech-um/protocol.c b/src/hardware/rdtech-um/protocol.c index 04de7687..6c56e245 100644 --- a/src/hardware/rdtech-um/protocol.c +++ b/src/hardware/rdtech-um/protocol.c @@ -18,11 +18,13 @@ */ #include -#include -#include -#include + #include #include +#include +#include +#include + #include "libsigrok-internal.h" #include "protocol.h" @@ -35,19 +37,19 @@ #define UM_CMD_POLL 0xf0 static const struct binary_analog_channel rdtech_default_channels[] = { - { "V", { 2, BVT_BE_UINT16, 0.01, }, 2, SR_MQ_VOLTAGE, SR_UNIT_VOLT }, - { "I", { 4, BVT_BE_UINT16, 0.001, }, 3, SR_MQ_CURRENT, SR_UNIT_AMPERE }, + { "V", { 2, BVT_BE_UINT16, 0.01, }, 2, SR_MQ_VOLTAGE, SR_UNIT_VOLT }, + { "I", { 4, BVT_BE_UINT16, 0.001, }, 3, SR_MQ_CURRENT, SR_UNIT_AMPERE }, { "D+", { 96, BVT_BE_UINT16, 0.01, }, 2, SR_MQ_VOLTAGE, SR_UNIT_VOLT }, { "D-", { 98, BVT_BE_UINT16, 0.01, }, 2, SR_MQ_VOLTAGE, SR_UNIT_VOLT }, - { "T", { 10, BVT_BE_UINT16, 1.0, }, 0, SR_MQ_TEMPERATURE, SR_UNIT_CELSIUS }, + { "T", { 10, BVT_BE_UINT16, 1.0, }, 0, SR_MQ_TEMPERATURE, SR_UNIT_CELSIUS }, /* Threshold-based recording (mWh) */ { "E", { 106, BVT_BE_UINT32, 0.001, }, 3, SR_MQ_ENERGY, SR_UNIT_WATT_HOUR }, ALL_ZERO, }; static const struct binary_analog_channel rdtech_um25c_channels[] = { - { "V", { 2, BVT_BE_UINT16, 0.001, }, 2, SR_MQ_VOLTAGE, SR_UNIT_VOLT }, - { "I", { 4, BVT_BE_UINT16, 0.0001, }, 3, SR_MQ_CURRENT, SR_UNIT_AMPERE }, + { "V", { 2, BVT_BE_UINT16, 0.001, }, 3, SR_MQ_VOLTAGE, SR_UNIT_VOLT }, + { "I", { 4, BVT_BE_UINT16, 0.0001, }, 4, SR_MQ_CURRENT, SR_UNIT_AMPERE }, { "D+", { 96, BVT_BE_UINT16, 0.01, }, 2, SR_MQ_VOLTAGE, SR_UNIT_VOLT }, { "D-", { 98, BVT_BE_UINT16, 0.01, }, 2, SR_MQ_VOLTAGE, SR_UNIT_VOLT }, { "T", { 10, BVT_BE_UINT16, 1.0, }, 0, SR_MQ_TEMPERATURE, SR_UNIT_CELSIUS }, @@ -56,42 +58,54 @@ static const struct binary_analog_channel rdtech_um25c_channels[] = { ALL_ZERO, }; -static int poll_csum_fff1(char buf[], int len) +static gboolean csum_ok_fff1(const uint8_t *buf, size_t len) { + uint16_t csum_recv; + if (len != UM_POLL_LEN) - return 0; - else - return RB16(&buf[len - 2]) == 0xFFF1; + return FALSE; + + csum_recv = read_u16be(&buf[len - sizeof(uint16_t)]); + if (csum_recv != 0xfff1) + return FALSE; + + return TRUE; } -static int poll_csum_um34c(char buf[], int len) +static gboolean csum_ok_um34c(const uint8_t *buf, size_t len) { static const int positions[] = { 1, 3, 7, 9, 15, 17, 19, 23, 31, 39, 41, 45, 49, 53, 55, 57, 59, 63, 67, 69, 73, 79, 83, 89, 97, 99, 109, 111, 113, 119, 121, 127, }; - unsigned int i; - uint8_t csum = 0; + + size_t i; + uint8_t csum_calc, csum_recv; if (len != UM_POLL_LEN) - return 0; + return FALSE; + csum_calc = 0; for (i = 0; i < ARRAY_SIZE(positions); i++) - csum ^= buf[positions[i]]; + csum_calc ^= buf[positions[i]]; + csum_recv = read_u8(&buf[len - sizeof(uint8_t)]); + if (csum_recv != csum_calc) + return FALSE; - return csum == (uint8_t)buf[len - 1]; + return TRUE; } static const struct rdtech_um_profile um_profiles[] = { - { "UM24C", RDTECH_UM24C, rdtech_default_channels, &poll_csum_fff1, }, - { "UM25C", RDTECH_UM25C, rdtech_um25c_channels, &poll_csum_fff1, }, - { "UM34C", RDTECH_UM34C, rdtech_default_channels, &poll_csum_um34c, }, + { "UM24C", RDTECH_UM24C, rdtech_default_channels, csum_ok_fff1, }, + { "UM25C", RDTECH_UM25C, rdtech_um25c_channels, csum_ok_fff1, }, + { "UM34C", RDTECH_UM34C, rdtech_default_channels, csum_ok_um34c, }, }; static const struct rdtech_um_profile *find_profile(uint16_t id) { unsigned int i; + for (i = 0; i < ARRAY_SIZE(um_profiles); i++) { if (um_profiles[i].model_id == id) return &um_profiles[i]; @@ -102,12 +116,13 @@ static const struct rdtech_um_profile *find_profile(uint16_t id) SR_PRIV const struct rdtech_um_profile *rdtech_um_probe(struct sr_serial_dev_inst *serial) { const struct rdtech_um_profile *p; - static const uint8_t request = UM_CMD_POLL; - char buf[RDTECH_UM_BUFSIZE]; + uint8_t request; + uint8_t buf[RDTECH_UM_BUFSIZE]; int len; + request = UM_CMD_POLL; if (serial_write_blocking(serial, &request, sizeof(request), - SERIAL_WRITE_TIMEOUT_MS) < 0) { + SERIAL_WRITE_TIMEOUT_MS) < 0) { sr_err("Unable to send probe request."); return NULL; } @@ -124,7 +139,7 @@ SR_PRIV const struct rdtech_um_profile *rdtech_um_probe(struct sr_serial_dev_ins return NULL; } - if (!p->poll_csum(buf, len)) { + if (!p->csum_ok(buf, len)) { sr_err("Probe response contains illegal checksum or end marker.\n"); return NULL; } @@ -134,16 +149,19 @@ SR_PRIV const struct rdtech_um_profile *rdtech_um_probe(struct sr_serial_dev_ins SR_PRIV int rdtech_um_poll(const struct sr_dev_inst *sdi) { - struct dev_context *devc = sdi->priv; - struct sr_serial_dev_inst *serial = sdi->conn; - static const uint8_t request = UM_CMD_POLL; + struct dev_context *devc; + struct sr_serial_dev_inst *serial; + uint8_t request; + serial = sdi->conn; + request = UM_CMD_POLL; if (serial_write_blocking(serial, &request, sizeof(request), - SERIAL_WRITE_TIMEOUT_MS) < 0) { + 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; @@ -151,31 +169,35 @@ SR_PRIV int rdtech_um_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; int 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 != UM_POLL_LEN) { - sr_err("Unexpected poll packet length: %i", devc->buflen); + sr_err("Unexpected poll packet length: %zu", devc->buflen); return; } - for (ch = sdi->channels, i = 0; ch; ch = g_slist_next(ch), i++) + for (ch = sdi->channels, i = 0; ch; ch = g_slist_next(ch), i++) { bv_send_analog_channel(sdi, ch->data, - &devc->profile->channels[i], - devc->buf, devc->buflen); + &devc->profile->channels[i], + devc->buf, devc->buflen); + } 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; - const struct rdtech_um_profile *p = devc->profile; + struct dev_context *devc; + const struct rdtech_um_profile *p; int len; /* Serial data arrived. */ + devc = sdi->priv; + p = devc->profile; while (devc->buflen < UM_POLL_LEN) { len = serial_read_nonblocking(serial, devc->buf + devc->buflen, 1); if (len < 1) @@ -193,7 +215,7 @@ static void recv_poll_data(struct sr_dev_inst *sdi, struct sr_serial_dev_inst *s } } - if (devc->buflen == UM_POLL_LEN && p->poll_csum(devc->buf, devc->buflen)) + if (devc->buflen == UM_POLL_LEN && p->csum_ok(devc->buf, devc->buflen)) handle_poll_data(sdi); else sr_warn("Skipping packet with illegal checksum / end marker.");