From: Uwe Hermann Date: Sat, 26 Jan 2013 22:39:24 +0000 (+0100) Subject: uni-t-dmm: Do proper detection of packets in the stream. X-Git-Tag: dsupstream~56 X-Git-Url: https://sigrok.org/gitaction?a=commitdiff_plain;h=bc653a56781de54f90e9fb08b39e6c9a596cc6af;p=libsigrok.git uni-t-dmm: Do proper detection of packets in the stream. Also, various fixups in the driver. --- diff --git a/hardware/uni-t-dmm/api.c b/hardware/uni-t-dmm/api.c index cfb6ae6b..cf1e4df5 100644 --- a/hardware/uni-t-dmm/api.c +++ b/hardware/uni-t-dmm/api.c @@ -1,7 +1,7 @@ /* * This file is part of the libsigrok project. * - * Copyright (C) 2012 Uwe Hermann + * Copyright (C) 2012-2013 Uwe Hermann * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -42,14 +42,14 @@ SR_PRIV struct sr_dev_driver voltcraft_vc820_driver_info; SR_PRIV struct dmm_info udmms[] = { { - "UNI-T", "UT61D", 19230 /* TODO */, + "UNI-T", "UT61D", 19230, FS9922_PACKET_SIZE, NULL, sr_fs9922_packet_valid, sr_fs9922_parse, NULL, &uni_t_ut61d_driver_info, receive_data_UNI_T_UT61D, }, { - "Voltcraft VC-820", "VC-820", 19200 /* TODO */, + "Voltcraft", "VC-820", 2400, FS9721_PACKET_SIZE, NULL, sr_fs9721_packet_valid, sr_fs9721_parse, NULL, @@ -70,7 +70,7 @@ static int hw_init(struct sr_context *sr_ctx, int dmm) { sr_dbg("Selected '%s' subdriver.", udmms[dmm].di->name); - return std_hw_init(sr_ctx, uddms[dmm].di, DRIVER_LOG_DOMAIN); + return std_hw_init(sr_ctx, udmms[dmm].di, DRIVER_LOG_DOMAIN); } static GSList *hw_scan(GSList *options, int dmm) @@ -84,8 +84,6 @@ static GSList *hw_scan(GSList *options, int dmm) struct sr_probe *probe; const char *conn; - (void)options; - drvc = udmms[dmm].di->priv; /* USB scan is always authoritative. */ @@ -117,6 +115,8 @@ static GSList *hw_scan(GSList *options, int dmm) return NULL; } + devc->first_run = TRUE; + if (!(sdi = sr_dev_inst_new(0, SR_ST_INACTIVE, udmms[dmm].vendor, udmms[dmm].device, NULL))) { sr_err("sr_dev_inst_new returned NULL."); @@ -139,22 +139,22 @@ static GSList *hw_scan(GSList *options, int dmm) static GSList *hw_dev_list(int dmm) { - return ((struct drv_context *)(udmms[dmm]->priv))->instances; + return ((struct drv_context *)(udmms[dmm].di->priv))->instances; } static int hw_dev_open(struct sr_dev_inst *sdi, int dmm) { struct drv_context *drvc; struct dev_context *devc; - int ret; + int ret; drvc = udmms[dmm].di->priv; devc = sdi->priv; - if ((ret = sr_usb_open(drvc->sr_ctx->libusb_ctx, devc->usb)) == SR_OK) - sdi->status = SR_ST_ACTIVE; + if ((ret = sr_usb_open(drvc->sr_ctx->libusb_ctx, devc->usb)) == SR_OK) + sdi->status = SR_ST_ACTIVE; - return ret; + return ret; } static int hw_dev_close(struct sr_dev_inst *sdi) @@ -163,7 +163,7 @@ static int hw_dev_close(struct sr_dev_inst *sdi) /* TODO */ - sdi->status = SR_ST_INACTIVE; + sdi->status = SR_ST_INACTIVE; return SR_OK; } @@ -210,7 +210,6 @@ static int config_set(int id, GVariant *data, const struct sr_dev_inst *sdi) static int config_list(int key, GVariant **data, const struct sr_dev_inst *sdi) { - (void)sdi; switch (key) { diff --git a/hardware/uni-t-dmm/protocol.c b/hardware/uni-t-dmm/protocol.c index 2d644dad..4e2c6b2d 100644 --- a/hardware/uni-t-dmm/protocol.c +++ b/hardware/uni-t-dmm/protocol.c @@ -1,7 +1,7 @@ /* * This file is part of the libsigrok project. * - * Copyright (C) 2012 Uwe Hermann + * Copyright (C) 2012-2013 Uwe Hermann * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -70,9 +70,9 @@ static void decode_packet(struct sr_dev_inst *sdi, int dmm, const uint8_t *buf, void *info) { + struct dev_context *devc; struct sr_datafeed_packet packet; struct sr_datafeed_analog analog; - /// struct fs9721_info info; float floatval; int ret; @@ -80,9 +80,9 @@ static void decode_packet(struct sr_dev_inst *sdi, int dmm, const uint8_t *buf, memset(&analog, 0, sizeof(struct sr_datafeed_analog)); /* Parse the protocol packet. */ - ret = udmms[dmm].packet_parse(buf, &floatval, &analog, &info); + ret = udmms[dmm].packet_parse(buf, &floatval, &analog, info); if (ret != SR_OK) { - sr_err("Invalid DMM packet, ignoring."); + sr_dbg("Invalid DMM packet, ignoring."); return; } @@ -128,7 +128,7 @@ static int hid_chip_init(struct dev_context *devc, uint16_t baudrate) } sr_dbg("Successfully claimed interface 0."); - /* Baudrate example: 19230 baud -> HEX(19230) == 0x4b1e */ + /* Set data for the HID feature report (e.g. baudrate). */ buf[0] = baudrate & 0xff; /* Baudrate, LSB */ buf[1] = (baudrate >> 8) & 0xff; /* Baudrate, MSB */ buf[2] = 0x00; /* Unknown/unused (?) */ @@ -182,33 +182,23 @@ static void log_dmm_packet(const uint8_t *buf) buf[7], buf[8], buf[9], buf[10], buf[11], buf[12], buf[13]); } -static int receive_data(int fd, int revents, int dmm, void *info, void *cb_data) +static int get_and_handle_data(struct sr_dev_inst *sdi, int dmm, void *info) { - struct sr_dev_inst *sdi; struct dev_context *devc; + uint8_t buf[CHUNK_SIZE], *pbuf; int i, ret, len, num_databytes_in_chunk; - uint8_t buf[CHUNK_SIZE]; - uint8_t *pbuf; - static gboolean first_run = TRUE, synced_on_first_packet = FALSE; - static uint64_t data_byte_counter = 0; - - (void)fd; - (void)revents; - sdi = cb_data; devc = sdi->priv; - pbuf = devc->protocol_buf; /* On the first run, we need to init the HID chip. */ - if (first_run) { - /* Note: The baudrate is DMM-specific (UT61D: 19230). */ + if (devc->first_run) { if ((ret = hid_chip_init(devc, udmms[dmm].baudrate)) != SR_OK) { sr_err("HID chip init failed: %d.", ret); - return FALSE; + return SR_ERR; } - memset(pbuf, 0x00, NUM_DATA_BYTES); - first_run = FALSE; + memset(pbuf, 0x00, DMM_BUFSIZE); + devc->first_run = FALSE; } memset(&buf, 0x00, CHUNK_SIZE); @@ -224,45 +214,61 @@ static int receive_data(int fd, int revents, int dmm, void *info, void *cb_data) if (ret < 0) { sr_err("USB receive error: %s.", libusb_error_name(ret)); - return FALSE; + return SR_ERR; } if (len != CHUNK_SIZE) { sr_err("Short packet: received %d/%d bytes.", len, CHUNK_SIZE); /* TODO: Print the bytes? */ - return FALSE; + return SR_ERR; } log_8byte_chunk((const uint8_t *)&buf); - if (buf[0] != 0xf0) { - /* First time: Synchronize to the start of a packet. */ - if (!synced_on_first_packet) { - if (!udmms[dmm].packet_valid(buf)) - return TRUE; - synced_on_first_packet = TRUE; - sr_spew("Successfully synchronized on first packet."); + /* If there are no data bytes just return (without error). */ + if (buf[0] == 0xf0) + return SR_OK; + + devc->bufoffset = 0; + + /* Append the 1-7 data bytes of this chunk to pbuf. */ + num_databytes_in_chunk = buf[0] & 0x0f; + for (i = 0; i < num_databytes_in_chunk; i++) + pbuf[devc->buflen++] = buf[1 + i]; + + /* Now look for packets in that data. */ + while ((devc->buflen - devc->bufoffset) >= udmms[dmm].packet_size) { + if (udmms[dmm].packet_valid(pbuf + devc->bufoffset)) { + log_dmm_packet(pbuf + devc->bufoffset); + decode_packet(sdi, dmm, pbuf + devc->bufoffset, info); + devc->bufoffset += udmms[dmm].packet_size; + } else { + devc->bufoffset++; } + } - num_databytes_in_chunk = buf[0] & 0x0f; - for (i = 0; i < num_databytes_in_chunk; i++) - pbuf[data_byte_counter++] = buf[1 + i]; + /* Move remaining bytes to beginning of buffer. */ + for (i = 0; i < devc->buflen - devc->bufoffset; i++) + pbuf[i] = pbuf[devc->bufoffset + i]; + devc->buflen -= devc->bufoffset; - /* TODO: Handle > 14 bytes in pbuf? Can this happen? */ - if (data_byte_counter == NUM_DATA_BYTES) { - log_dmm_packet(pbuf); - data_byte_counter = 0; + return SR_OK; +} + +static int receive_data(int fd, int revents, int dmm, void *info, void *cb_data) +{ + int ret; + struct sr_dev_inst *sdi; + struct dev_context *devc; - if (!udmms[dmm].packet_valid(pbuf)) { - sr_err("Invalid packet."); - return TRUE; - } + (void)fd; + (void)revents; - decode_packet(sdi, dmm, pbuf, info); + sdi = cb_data; + devc = sdi->priv; - memset(pbuf, 0x00, NUM_DATA_BYTES); - } - } + if ((ret = get_and_handle_data(sdi, dmm, info)) != SR_OK) + return FALSE; /* Abort acquisition if we acquired enough samples. */ if (devc->limit_samples && devc->num_samples >= devc->limit_samples) { diff --git a/hardware/uni-t-dmm/protocol.h b/hardware/uni-t-dmm/protocol.h index 73fa7582..4c753000 100644 --- a/hardware/uni-t-dmm/protocol.h +++ b/hardware/uni-t-dmm/protocol.h @@ -1,7 +1,7 @@ /* * This file is part of the libsigrok project. * - * Copyright (C) 2012 Uwe Hermann + * Copyright (C) 2012-2013 Uwe Hermann * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -60,11 +60,9 @@ struct dmm_info { extern SR_PRIV struct dmm_info udmms[DMM_COUNT]; -#define UT_D04_CABLE_USB_VID 0x1a86 -#define UT_D04_CABLE_USB_DID 0xe008 - #define CHUNK_SIZE 8 -#define NUM_DATA_BYTES 14 + +#define DMM_BUFSIZE 256 /** Private, per-device-instance driver context. */ struct dev_context { @@ -82,7 +80,11 @@ struct dev_context { struct sr_usb_dev_inst *usb; - uint8_t protocol_buf[14]; + gboolean first_run; + + uint8_t protocol_buf[DMM_BUFSIZE]; + uint8_t bufoffset; + uint8_t buflen; }; SR_PRIV int receive_data_UNI_T_UT61D(int fd, int revents, void *cb_data);