diff --git a/hardware/serial-dmm/api.c b/hardware/serial-dmm/api.c index 4ac923ca..32027770 100644 --- a/hardware/serial-dmm/api.c +++ b/hardware/serial-dmm/api.c @@ -49,30 +49,34 @@ static const char *probe_names[] = { SR_PRIV struct sr_dev_driver digitek_dt4000zc_driver_info; SR_PRIV struct sr_dev_driver tekpower_tp4000zc_driver_info; +SR_PRIV struct sr_dev_driver metex_me31_driver_info; -static struct sr_dev_driver *di_digitek_dt4000zc = &digitek_dt4000zc_driver_info; -static struct sr_dev_driver *di_tekpower_tp4000zc = &tekpower_tp4000zc_driver_info; +static struct sr_dev_driver *di_dt4000zc = &digitek_dt4000zc_driver_info; +static struct sr_dev_driver *di_tp4000zc = &tekpower_tp4000zc_driver_info; +static struct sr_dev_driver *di_me31 = &metex_me31_driver_info; /* After hw_init() this will point to a device-specific entry (see above). */ static struct sr_dev_driver *di = NULL; SR_PRIV struct dmm_info dmms[] = { { - "Digitek", "DT4000ZC", - "2400/8n1", 2400, - FS9721_PACKET_SIZE, - sr_fs9721_packet_valid, - sr_fs9721_parse, + "Digitek", "DT4000ZC", "2400/8n1", 2400, + FS9721_PACKET_SIZE, NULL, + sr_fs9721_packet_valid, sr_fs9721_parse, dmm_details_dt4000zc, }, { - "TekPower", "TP4000ZC", - "2400/8n1", 2400, - FS9721_PACKET_SIZE, - sr_fs9721_packet_valid, - sr_fs9721_parse, + "TekPower", "TP4000ZC", "2400/8n1", 2400, + FS9721_PACKET_SIZE, NULL, + sr_fs9721_packet_valid, sr_fs9721_parse, dmm_details_tp4000zc, }, + { + "Metex", "ME-31", "600/7n2/rts=0/dtr=1", 600, + METEX14_PACKET_SIZE, sr_metex14_packet_request, + sr_metex14_packet_valid, sr_metex14_parse, + NULL, + }, }; /* Properly close and free all devices. */ @@ -111,9 +115,11 @@ static int hw_init(int dmm) } if (dmm == DIGITEK_DT4000ZC) - di = di_digitek_dt4000zc; + di = di_dt4000zc; if (dmm == TEKPOWER_TP4000ZC) - di = di_tekpower_tp4000zc; + di = di_tp4000zc; + if (dmm == METEX_ME31) + di = di_me31; sr_dbg("Selected '%s' subdriver.", di->name); di->priv = drvc; @@ -131,6 +137,11 @@ static int hw_init_tekpower_tp4000zc(void) return hw_init(TEKPOWER_TP4000ZC); } +static int hw_init_metex_me31(void) +{ + return hw_init(METEX_ME31); +} + static GSList *scan(const char *conn, const char *serialcomm, int dmm) { struct sr_dev_inst *sdi; @@ -146,10 +157,10 @@ static GSList *scan(const char *conn, const char *serialcomm, int dmm) if (!(serial = sr_serial_dev_inst_new(conn, serialcomm))) return NULL; - if (serial_open(serial, SERIAL_RDONLY | SERIAL_NONBLOCK) != SR_OK) + if (serial_open(serial, SERIAL_RDWR | SERIAL_NONBLOCK) != SR_OK) return NULL; - sr_info("Probing port %s readonly.", conn); + sr_info("Probing port %s.", conn); drvc = di->priv; devices = NULL; @@ -164,6 +175,14 @@ static GSList *scan(const char *conn, const char *serialcomm, int dmm) /* Let's get a bit of data and see if we can find a packet. */ len = sizeof(buf); + /* Request a packet if the DMM requires this. */ + if (dmms[dmm].packet_request) { + if ((ret = dmms[dmm].packet_request(serial)) < 0) { + sr_err("Failed to request packet: %d.", ret); + return FALSE; + } + } + ret = serial_stream_detect(serial, buf, &len, dmms[dmm].packet_size, dmms[dmm].packet_valid, 1000, dmms[dmm].baudrate); @@ -234,6 +253,8 @@ static GSList *hw_scan(GSList *options) dmm = 0; if (!strcmp(di->name, "tekpower-tp4000zc")) dmm = 1; + if (!strcmp(di->name, "metex-me31")) + dmm = 2; if (serialcomm) { /* Use the provided comm specs. */ @@ -264,7 +285,7 @@ static int hw_dev_open(struct sr_dev_inst *sdi) return SR_ERR_BUG; } - if (serial_open(devc->serial, SERIAL_RDONLY) != SR_OK) + if (serial_open(devc->serial, SERIAL_RDWR | SERIAL_NONBLOCK) != SR_OK) return SR_ERR; sdi->status = SR_ST_ACTIVE; @@ -393,6 +414,8 @@ static int hw_dev_acquisition_start(const struct sr_dev_inst *sdi, receive_data = digitek_dt4000zc_receive_data; if (!strcmp(di->name, "tekpower-tp4000zc")) receive_data = tekpower_tp4000zc_receive_data; + if (!strcmp(di->name, "metex-me31")) + receive_data = metex_me31_receive_data; /* Poll every 50ms, or whenever some data comes in. */ sr_source_add(devc->serial->fd, G_IO_IN, 50, @@ -462,3 +485,21 @@ SR_PRIV struct sr_dev_driver tekpower_tp4000zc_driver_info = { .dev_acquisition_stop = hw_dev_acquisition_stop, .priv = NULL, }; + +SR_PRIV struct sr_dev_driver metex_me31_driver_info = { + .name = "metex-me31", + .longname = "Metex ME-31", + .api_version = 1, + .init = hw_init_metex_me31, + .cleanup = hw_cleanup, + .scan = hw_scan, + .dev_list = hw_dev_list, + .dev_clear = clear_instances, + .dev_open = hw_dev_open, + .dev_close = hw_dev_close, + .info_get = hw_info_get, + .dev_config_set = hw_dev_config_set, + .dev_acquisition_start = hw_dev_acquisition_start, + .dev_acquisition_stop = hw_dev_acquisition_stop, + .priv = NULL, +}; diff --git a/hardware/serial-dmm/core b/hardware/serial-dmm/core new file mode 100644 index 00000000..7dfc1685 Binary files /dev/null and b/hardware/serial-dmm/core differ diff --git a/hardware/serial-dmm/protocol.c b/hardware/serial-dmm/protocol.c index a3f25d0e..479e954e 100644 --- a/hardware/serial-dmm/protocol.c +++ b/hardware/serial-dmm/protocol.c @@ -74,7 +74,8 @@ static void handle_packet(const uint8_t *buf, struct dev_context *devc, dmms[dmm].packet_parse(buf, &floatval, analog, info); analog->data = &floatval; - dmms[dmm].dmm_details(analog, info); + if (dmms[dmm].dmm_details) + dmms[dmm].dmm_details(analog, info); if (analog->mq != -1) { /* Got a measurement. */ @@ -120,6 +121,7 @@ static int receive_data(int fd, int revents, int dmm, void *info, void *cb_data) { struct sr_dev_inst *sdi; struct dev_context *devc; + int ret; (void)fd; @@ -132,6 +134,15 @@ static int receive_data(int fd, int revents, int dmm, void *info, void *cb_data) if (revents == G_IO_IN) { /* Serial data arrived. */ handle_new_data(devc, dmm, info); + } else { + /* Timeout, send another packet request (if DMM needs it). */ + if (dmms[dmm].packet_request) { + ret = dmms[dmm].packet_request(devc->serial); + if (ret < 0) { + sr_err("Failed to request packet: %d.", ret); + return FALSE; + } + } } if (devc->num_samples >= devc->limit_samples) { @@ -156,3 +167,10 @@ SR_PRIV int tekpower_tp4000zc_receive_data(int fd, int revents, void *cb_data) return receive_data(fd, revents, TEKPOWER_TP4000ZC, &info, cb_data); } + +SR_PRIV int metex_me31_receive_data(int fd, int revents, void *cb_data) +{ + struct metex14_info info; + + return receive_data(fd, revents, METEX_ME31, &info, cb_data); +} diff --git a/hardware/serial-dmm/protocol.h b/hardware/serial-dmm/protocol.h index a4333fde..7b676a39 100644 --- a/hardware/serial-dmm/protocol.h +++ b/hardware/serial-dmm/protocol.h @@ -32,6 +32,7 @@ enum { DIGITEK_DT4000ZC, TEKPOWER_TP4000ZC, + METEX_ME31, }; struct dmm_info { @@ -40,13 +41,14 @@ struct dmm_info { char *conn; uint32_t baudrate; int packet_size; + int (*packet_request)(struct sr_serial_dev_inst *); gboolean (*packet_valid)(const uint8_t *); int (*packet_parse)(const uint8_t *, float *, struct sr_datafeed_analog *, void *); void (*dmm_details)(struct sr_datafeed_analog *, void *); }; -SR_PRIV struct dmm_info dmms[2]; +SR_PRIV struct dmm_info dmms[3]; #define DMM_BUFSIZE 256 @@ -70,6 +72,7 @@ struct dev_context { SR_PRIV int digitek_dt4000zc_receive_data(int fd, int revents, void *cb_data); SR_PRIV int tekpower_tp4000zc_receive_data(int fd, int revents, void *cb_data); +SR_PRIV int metex_me31_receive_data(int fd, int revents, void *cb_data); SR_PRIV void dmm_details_tp4000zc(struct sr_datafeed_analog *analog, void *info); SR_PRIV void dmm_details_dt4000zc(struct sr_datafeed_analog *analog, void *info); diff --git a/hwdriver.c b/hwdriver.c index 95bdbbf5..df24f15e 100644 --- a/hwdriver.c +++ b/hwdriver.c @@ -116,6 +116,7 @@ extern SR_PRIV struct sr_dev_driver radioshackdmm_driver_info; #ifdef HAVE_HW_SERIAL_DMM extern SR_PRIV struct sr_dev_driver digitek_dt4000zc_driver_info; extern SR_PRIV struct sr_dev_driver tekpower_tp4000zc_driver_info; +extern SR_PRIV struct sr_dev_driver metex_me31_driver_info; #endif #ifdef HAVE_HW_UNI_T_DMM extern SR_PRIV struct sr_dev_driver uni_t_ut61d_driver_info; @@ -172,6 +173,7 @@ static struct sr_dev_driver *drivers_list[] = { #ifdef HAVE_HW_SERIAL_DMM &digitek_dt4000zc_driver_info, &tekpower_tp4000zc_driver_info, + &metex_me31_driver_info, #endif #ifdef HAVE_HW_UNI_T_DMM &uni_t_ut61d_driver_info, diff --git a/libsigrok-internal.h b/libsigrok-internal.h index 8fc73dc7..bed792b0 100644 --- a/libsigrok-internal.h +++ b/libsigrok-internal.h @@ -200,6 +200,7 @@ struct metex14_info { gboolean is_kilo, is_mega; }; +SR_PRIV int sr_metex14_packet_request(struct sr_serial_dev_inst *serial); SR_PRIV gboolean sr_metex14_packet_valid(const uint8_t *buf); SR_PRIV int sr_metex14_parse(const uint8_t *buf, float *floatval, struct sr_datafeed_analog *analog, void *info);