From: George Hopkins Date: Sat, 30 Apr 2016 20:34:15 +0000 (+0200) Subject: pce-322a: Initial driver implementation. X-Git-Tag: libsigrok-0.5.0~381 X-Git-Url: http://sigrok.org/gitweb/?p=libsigrok.git;a=commitdiff_plain;h=5a2c71ccd7c46b18583dd068a8508e9d93ed9190 pce-322a: Initial driver implementation. --- diff --git a/Makefile.am b/Makefile.am index 16dd83ab..7f61c19b 100644 --- a/Makefile.am +++ b/Makefile.am @@ -407,6 +407,12 @@ libsigrok_la_SOURCES += \ src/hardware/openbench-logic-sniffer/protocol.c \ src/hardware/openbench-logic-sniffer/api.c endif +if HW_PCE_322A +libsigrok_la_SOURCES += \ + src/hardware/pce-322a/protocol.h \ + src/hardware/pce-322a/protocol.c \ + src/hardware/pce-322a/api.c +endif if HW_PIPISTRELLO_OLS libsigrok_la_SOURCES += \ src/hardware/pipistrello-ols/protocol.h \ diff --git a/configure.ac b/configure.ac index fd1b98da..e6a719b8 100644 --- a/configure.ac +++ b/configure.ac @@ -257,6 +257,7 @@ SR_DRIVER([MIC 985xx], [mic-985xx], [libserialport]) SR_DRIVER([Motech LPS 30x], [motech-lps-30x], [libserialport]) SR_DRIVER([Norma DMM], [norma-dmm], [libserialport]) SR_DRIVER([OpenBench Logic Sniffer], [openbench-logic-sniffer], [libserialport]) +SR_DRIVER([PCE PCE-322A], [pce-322a], [libserialport]) SR_DRIVER([Pipistrello-OLS], [pipistrello-ols], [libftdi]) SR_DRIVER([Rigol DS], [rigol-ds]) SR_DRIVER([Saleae Logic16], [saleae-logic16], [libusb]) diff --git a/src/hardware/pce-322a/api.c b/src/hardware/pce-322a/api.c new file mode 100644 index 00000000..8e408c1a --- /dev/null +++ b/src/hardware/pce-322a/api.c @@ -0,0 +1,355 @@ +/* + * This file is part of the libsigrok project. + * + * Copyright (C) 2016 George Hopkins + * + * 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 + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include +#include +#include "protocol.h" + +#define SERIALCOMM "115200/8n1" + +static const uint32_t scanopts[] = { + SR_CONF_CONN, +}; + +static const uint32_t drvopts[] = { + SR_CONF_SOUNDLEVELMETER, +}; + +static const uint32_t devopts[] = { + SR_CONF_CONTINUOUS | SR_CONF_SET, + SR_CONF_LIMIT_SAMPLES | SR_CONF_GET | SR_CONF_SET, + SR_CONF_SPL_WEIGHT_FREQ | SR_CONF_GET | SR_CONF_SET | SR_CONF_LIST, + SR_CONF_SPL_WEIGHT_TIME | SR_CONF_GET | SR_CONF_SET | SR_CONF_LIST, + SR_CONF_SPL_MEASUREMENT_RANGE | SR_CONF_GET | SR_CONF_SET | SR_CONF_LIST, + SR_CONF_POWER_OFF | SR_CONF_GET | SR_CONF_SET, +}; + +static const char *weight_freq[] = { + "A", + "C", +}; + +static const char *weight_time[] = { + "F", + "S", +}; + +static const uint64_t meas_ranges[][2] = { + { 30, 130 }, + { 30, 80 }, + { 50, 100 }, + { 80, 130 }, +}; + +static GSList *scan(struct sr_dev_driver *di, GSList *options) +{ + struct drv_context *drvc; + struct dev_context *devc; + struct sr_config *src; + struct sr_serial_dev_inst *serial; + struct sr_dev_inst *sdi; + GSList *l, *devices; + const char *conn; + + conn = NULL; + for (l = options; l; l = l->next) { + src = l->data; + if (src->key == SR_CONF_CONN) + conn = g_variant_get_string(src->data, NULL); + } + if (!conn) + return NULL; + + serial = sr_serial_dev_inst_new(conn, SERIALCOMM); + + if (serial_open(serial, SERIAL_RDONLY) != SR_OK) + return NULL; + + devices = NULL; + drvc = di->context; + + sdi = g_malloc0(sizeof(struct sr_dev_inst)); + sdi->status = SR_ST_INACTIVE; + sdi->vendor = g_strdup("PCE"); + sdi->model = g_strdup("PCE-322A"); + devc = g_malloc0(sizeof(struct dev_context)); + devc->cur_mqflags = SR_MQFLAG_SPL_TIME_WEIGHT_F | SR_MQFLAG_SPL_FREQ_WEIGHT_A; + sdi->conn = sr_serial_dev_inst_new(conn, SERIALCOMM); + sdi->inst_type = SR_INST_SERIAL; + sdi->priv = devc; + sdi->driver = di; + sr_channel_new(sdi, 0, SR_CHANNEL_ANALOG, TRUE, "SPL"); + drvc->instances = g_slist_append(drvc->instances, sdi); + devices = g_slist_append(devices, sdi); + + serial_close(serial); + + return devices; +} + +static int dev_clear(const struct sr_dev_driver *di) +{ + return std_dev_clear(di, NULL); +} + +static int config_get(uint32_t key, GVariant **data, + const struct sr_dev_inst *sdi, const struct sr_channel_group *cg) +{ + struct dev_context *devc; + GVariant *range[2]; + uint64_t low, high; + uint64_t tmp; + int ret; + + (void)cg; + + if (!sdi) + return SR_ERR_ARG; + + devc = sdi->priv; + ret = SR_OK; + switch (key) { + case SR_CONF_LIMIT_SAMPLES: + *data = g_variant_new_uint64(devc->limit_samples); + break; + case SR_CONF_SPL_WEIGHT_FREQ: + tmp = pce_322a_weight_freq_get(sdi); + if (tmp == SR_MQFLAG_SPL_FREQ_WEIGHT_A) + *data = g_variant_new_string("A"); + else if (tmp == SR_MQFLAG_SPL_FREQ_WEIGHT_C) + *data = g_variant_new_string("C"); + else + return SR_ERR; + break; + case SR_CONF_SPL_WEIGHT_TIME: + tmp = pce_322a_weight_time_get(sdi); + if (tmp == SR_MQFLAG_SPL_TIME_WEIGHT_F) + *data = g_variant_new_string("F"); + else if (tmp == SR_MQFLAG_SPL_TIME_WEIGHT_S) + *data = g_variant_new_string("S"); + else + return SR_ERR; + break; + case SR_CONF_SPL_MEASUREMENT_RANGE: + if ((ret = pce_322a_meas_range_get(sdi, &low, &high)) == SR_OK) { + range[0] = g_variant_new_uint64(low); + range[1] = g_variant_new_uint64(high); + *data = g_variant_new_tuple(range, 2); + } + break; + case SR_CONF_POWER_OFF: + *data = g_variant_new_boolean(FALSE); + break; + default: + return SR_ERR_NA; + } + + return ret; +} + +static int config_set(uint32_t key, GVariant *data, const struct sr_dev_inst *sdi, + const struct sr_channel_group *cg) +{ + struct dev_context *devc; + uint64_t tmp_u64, low, high; + unsigned int i; + int ret; + const char *tmp_str; + + (void)cg; + + if (sdi->status != SR_ST_ACTIVE) + return SR_ERR_DEV_CLOSED; + + devc = sdi->priv; + + ret = SR_OK; + switch (key) { + case SR_CONF_LIMIT_SAMPLES: + tmp_u64 = g_variant_get_uint64(data); + devc->limit_samples = tmp_u64; + ret = SR_OK; + break; + case SR_CONF_SPL_WEIGHT_FREQ: + tmp_str = g_variant_get_string(data, NULL); + if (!strcmp(tmp_str, "A")) + ret = pce_322a_weight_freq_set(sdi, + SR_MQFLAG_SPL_FREQ_WEIGHT_A); + else if (!strcmp(tmp_str, "C")) + ret = pce_322a_weight_freq_set(sdi, + SR_MQFLAG_SPL_FREQ_WEIGHT_C); + else + return SR_ERR_ARG; + break; + case SR_CONF_SPL_WEIGHT_TIME: + tmp_str = g_variant_get_string(data, NULL); + if (!strcmp(tmp_str, "F")) + ret = pce_322a_weight_time_set(sdi, + SR_MQFLAG_SPL_TIME_WEIGHT_F); + else if (!strcmp(tmp_str, "S")) + ret = pce_322a_weight_time_set(sdi, + SR_MQFLAG_SPL_TIME_WEIGHT_S); + else + return SR_ERR_ARG; + break; + case SR_CONF_SPL_MEASUREMENT_RANGE: + g_variant_get(data, "(tt)", &low, &high); + ret = SR_ERR_ARG; + for (i = 0; i < ARRAY_SIZE(meas_ranges); i++) { + if (meas_ranges[i][0] == low && meas_ranges[i][1] == high) { + ret = pce_322a_meas_range_set(sdi, low, high); + break; + } + } + break; + case SR_CONF_POWER_OFF: + if (g_variant_get_boolean(data)) + ret = pce_322a_power_off(sdi); + break; + default: + ret = SR_ERR_NA; + } + + return ret; +} + +static int config_list(uint32_t key, GVariant **data, + const struct sr_dev_inst *sdi, const struct sr_channel_group *cg) +{ + GVariant *tuple, *range[2]; + GVariantBuilder gvb; + unsigned int i; + int ret; + + (void)cg; + + ret = SR_OK; + if (!sdi) { + switch (key) { + case SR_CONF_SCAN_OPTIONS: + *data = g_variant_new_fixed_array(G_VARIANT_TYPE_UINT32, + scanopts, ARRAY_SIZE(scanopts), sizeof(uint32_t)); + break; + case SR_CONF_DEVICE_OPTIONS: + *data = g_variant_new_fixed_array(G_VARIANT_TYPE_UINT32, + drvopts, ARRAY_SIZE(drvopts), sizeof(uint32_t)); + break; + default: + return SR_ERR_NA; + } + } else { + switch (key) { + case SR_CONF_DEVICE_OPTIONS: + *data = g_variant_new_fixed_array(G_VARIANT_TYPE_UINT32, + devopts, ARRAY_SIZE(devopts), sizeof(uint32_t)); + break; + case SR_CONF_SPL_WEIGHT_FREQ: + *data = g_variant_new_strv(weight_freq, ARRAY_SIZE(weight_freq)); + break; + case SR_CONF_SPL_WEIGHT_TIME: + *data = g_variant_new_strv(weight_time, ARRAY_SIZE(weight_time)); + break; + case SR_CONF_SPL_MEASUREMENT_RANGE: + g_variant_builder_init(&gvb, G_VARIANT_TYPE_ARRAY); + for (i = 0; i < ARRAY_SIZE(meas_ranges); i++) { + range[0] = g_variant_new_uint64(meas_ranges[i][0]); + range[1] = g_variant_new_uint64(meas_ranges[i][1]); + tuple = g_variant_new_tuple(range, 2); + g_variant_builder_add_value(&gvb, tuple); + } + *data = g_variant_builder_end(&gvb); + break; + default: + return SR_ERR_NA; + } + } + + return ret; +} + +static int dev_open(struct sr_dev_inst *sdi) +{ + int ret; + + ret = std_serial_dev_open(sdi); + if (ret != SR_OK) + return ret; + + return pce_322a_connect(sdi); +} + +static int dev_close(struct sr_dev_inst *sdi) +{ + /* + * Ensure device gets properly disconnected even when there was + * no acquisition. + */ + pce_322a_disconnect(sdi); + + return std_serial_dev_close(sdi); +} + +static int dev_acquisition_start(const struct sr_dev_inst *sdi) +{ + struct dev_context *devc; + struct sr_serial_dev_inst *serial; + + if (sdi->status != SR_ST_ACTIVE) + return SR_ERR_DEV_CLOSED; + + devc = sdi->priv; + devc->buffer_len = 0; + + std_session_send_df_header(sdi, LOG_PREFIX); + + /* Poll every 150ms, or whenever some data comes in. */ + serial = sdi->conn; + serial_source_add(sdi->session, serial, G_IO_IN, 150, + pce_322a_receive_data, (void *)sdi); + + return SR_OK; +} + +static int dev_acquisition_stop(struct sr_dev_inst *sdi) +{ + pce_322a_disconnect(sdi); + + return std_serial_dev_acquisition_stop(sdi, std_serial_dev_close, + sdi->conn, LOG_PREFIX); +} + +static struct sr_dev_driver pce_322a_driver_info = { + .name = "pce-322a", + .longname = "PCE PCE-322A", + .api_version = 1, + .init = std_init, + .cleanup = std_cleanup, + .scan = scan, + .dev_list = std_dev_list, + .dev_clear = dev_clear, + .config_get = config_get, + .config_set = config_set, + .config_list = config_list, + .dev_open = dev_open, + .dev_close = dev_close, + .dev_acquisition_start = dev_acquisition_start, + .dev_acquisition_stop = dev_acquisition_stop, + .context = NULL, +}; +SR_REGISTER_DEV_DRIVER(pce_322a_driver_info); diff --git a/src/hardware/pce-322a/protocol.c b/src/hardware/pce-322a/protocol.c new file mode 100644 index 00000000..0f822d85 --- /dev/null +++ b/src/hardware/pce-322a/protocol.c @@ -0,0 +1,270 @@ +/* + * This file is part of the libsigrok project. + * + * Copyright (C) 2016 George Hopkins + * + * 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 + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include +#include "protocol.h" + +static int send_command(const struct sr_dev_inst *sdi, uint16_t command) +{ + struct sr_serial_dev_inst *serial; + uint8_t buffer[2]; + + buffer[0] = command >> 8; + buffer[1] = command; + + if (!(serial = sdi->conn)) + return SR_ERR; + + if (serial_write_nonblocking(serial, (const void *)buffer, 2) != 2) + return SR_ERR; + + return SR_OK; +} + +static void send_data(const struct sr_dev_inst *sdi, float sample) +{ + struct dev_context *devc; + struct sr_datafeed_packet packet; + struct sr_datafeed_analog analog; + struct sr_analog_encoding encoding; + struct sr_analog_meaning meaning; + struct sr_analog_spec spec; + + devc = sdi->priv; + + sr_analog_init(&analog, &encoding, &meaning, &spec, 1); + meaning.mq = SR_MQ_SOUND_PRESSURE_LEVEL; + meaning.mqflags = devc->cur_mqflags; + meaning.unit = SR_UNIT_DECIBEL_SPL; + meaning.channels = sdi->channels; + analog.num_samples = 1; + analog.data = &sample; + packet.type = SR_DF_ANALOG; + packet.payload = &analog; + sr_session_send(sdi, &packet); + + devc->num_samples++; + if (devc->limit_samples && devc->num_samples >= devc->limit_samples) + sdi->driver->dev_acquisition_stop((struct sr_dev_inst *)sdi); +} + +static void process_measurement(const struct sr_dev_inst *sdi) +{ + struct dev_context *devc; + unsigned short value; + + devc = sdi->priv; + + if (devc->buffer[3] & (1 << 0)) { + devc->cur_mqflags |= SR_MQFLAG_SPL_FREQ_WEIGHT_C; + devc->cur_mqflags &= ~SR_MQFLAG_SPL_FREQ_WEIGHT_A; + } else { + devc->cur_mqflags |= SR_MQFLAG_SPL_FREQ_WEIGHT_A; + devc->cur_mqflags &= ~SR_MQFLAG_SPL_FREQ_WEIGHT_C; + } + + if (devc->buffer[3] & (1 << 1)) { + devc->cur_mqflags |= SR_MQFLAG_SPL_TIME_WEIGHT_S; + devc->cur_mqflags &= ~SR_MQFLAG_SPL_TIME_WEIGHT_F; + } else { + devc->cur_mqflags |= SR_MQFLAG_SPL_TIME_WEIGHT_F; + devc->cur_mqflags &= ~SR_MQFLAG_SPL_TIME_WEIGHT_S; + } + + devc->cur_meas_range = devc->buffer[4] & 3; + + if (devc->buffer[4] & (1 << 2)) { + devc->cur_mqflags |= SR_MQFLAG_MAX; + devc->cur_mqflags &= ~SR_MQFLAG_MIN; + } else if (devc->buffer[4] & (1 << 3)) { + devc->cur_mqflags |= SR_MQFLAG_MIN; + devc->cur_mqflags &= ~SR_MQFLAG_MAX; + } else { + devc->cur_mqflags &= ~SR_MQFLAG_MIN; + devc->cur_mqflags &= ~SR_MQFLAG_MAX; + } + + value = devc->buffer[1] << 8 | devc->buffer[2]; + send_data(sdi, value / 10.0); +} + +static void process_byte(const struct sr_dev_inst *sdi, const unsigned char c) +{ + struct dev_context *devc; + unsigned int i; + + devc = sdi->priv; + + if (devc->buffer_len < BUFFER_SIZE) { + devc->buffer[devc->buffer_len++] = c; + } else { + for (i = 1; i < BUFFER_SIZE; i++) + devc->buffer[i - 1] = devc->buffer[i]; + devc->buffer[BUFFER_SIZE - 1] = c; + if (devc->buffer[0] == 0x7f && devc->buffer[BUFFER_SIZE - 1] == 0x00) { + process_measurement(sdi); + devc->buffer_len = 0; + } + } +} + +SR_PRIV int pce_322a_receive_data(int fd, int revents, void *cb_data) +{ + const struct sr_dev_inst *sdi; + struct dev_context *devc; + struct sr_serial_dev_inst *serial; + unsigned char c; + + (void)fd; + + if (!(sdi = cb_data)) + return TRUE; + + if (!(devc = sdi->priv)) + return TRUE; + + if (!(serial = sdi->conn)) + return TRUE; + + if (revents == G_IO_IN) { + if (serial_read_nonblocking(serial, &c, 1) != 1) + return TRUE; + process_byte(sdi, c); + } + + return TRUE; +} + +SR_PRIV int pce_322a_connect(const struct sr_dev_inst *sdi) +{ + return send_command(sdi, CMD_CONNECT); +} + +SR_PRIV int pce_322a_disconnect(const struct sr_dev_inst *sdi) +{ + return send_command(sdi, CMD_DISCONNECT); +} + +SR_PRIV uint64_t pce_322a_weight_freq_get(const struct sr_dev_inst *sdi) +{ + struct dev_context *devc; + + devc = sdi->priv; + + return devc->cur_mqflags & (SR_MQFLAG_SPL_FREQ_WEIGHT_A | SR_MQFLAG_SPL_FREQ_WEIGHT_C); +} + +SR_PRIV int pce_322a_weight_freq_set(const struct sr_dev_inst *sdi, uint64_t freqw) +{ + struct dev_context *devc; + + devc = sdi->priv; + + if (devc->cur_mqflags & freqw) + return SR_OK; + + return send_command(sdi, CMD_TOGGLE_WEIGHT_FREQ); +} + +SR_PRIV uint64_t pce_322a_weight_time_get(const struct sr_dev_inst *sdi) +{ + struct dev_context *devc; + + devc = sdi->priv; + + return devc->cur_mqflags & (SR_MQFLAG_SPL_TIME_WEIGHT_F | SR_MQFLAG_SPL_TIME_WEIGHT_S); +} + +SR_PRIV int pce_322a_weight_time_set(const struct sr_dev_inst *sdi, uint64_t timew) +{ + struct dev_context *devc; + + devc = sdi->priv; + + if (devc->cur_mqflags & timew) + return SR_OK; + + return send_command(sdi, CMD_TOGGLE_WEIGHT_TIME); +} + +SR_PRIV int pce_322a_meas_range_get(const struct sr_dev_inst *sdi, + uint64_t *low, uint64_t *high) +{ + struct dev_context *devc; + + devc = sdi->priv; + + switch (devc->cur_meas_range) { + case MEAS_RANGE_30_130: + *low = 30; + *high = 130; + break; + case MEAS_RANGE_30_80: + *low = 30; + *high = 80; + break; + case MEAS_RANGE_50_100: + *low = 50; + *high = 100; + break; + case MEAS_RANGE_80_130: + *low = 80; + *high = 130; + break; + default: + return SR_ERR; + } + + return SR_OK; +} + +SR_PRIV int pce_322a_meas_range_set(const struct sr_dev_inst *sdi, + uint64_t low, uint64_t high) +{ + struct dev_context *devc; + uint8_t range; + int ret = SR_OK; + + devc = sdi->priv; + + if (low == 30 && high == 130) + range = MEAS_RANGE_30_130; + else if (low == 30 && high == 80) + range = MEAS_RANGE_30_80; + else if (low == 50 && high == 100) + range = MEAS_RANGE_50_100; + else if (low == 80 && high == 130) + range = MEAS_RANGE_80_130; + else + return SR_ERR; + + while (range != devc->cur_meas_range) { + ret = send_command(sdi, CMD_TOGGLE_MEAS_RANGE); + if (ret != SR_OK) + break; + range = (range - 1) & 3; + } + + return ret; +} + +SR_PRIV int pce_322a_power_off(const struct sr_dev_inst *sdi) +{ + return send_command(sdi, CMD_POWER_OFF); +} diff --git a/src/hardware/pce-322a/protocol.h b/src/hardware/pce-322a/protocol.h new file mode 100644 index 00000000..679d2a04 --- /dev/null +++ b/src/hardware/pce-322a/protocol.h @@ -0,0 +1,86 @@ +/* + * This file is part of the libsigrok project. + * + * Copyright (C) 2016 George Hopkins + * + * 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 + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#ifndef LIBSIGROK_HARDWARE_PCE_322A_PROTOCOL_H +#define LIBSIGROK_HARDWARE_PCE_322A_PROTOCOL_H + +#include +#include +#include +#include "libsigrok-internal.h" + +#define LOG_PREFIX "pce-322a" + +#define BUFFER_SIZE 13 + +enum { + CMD_CONNECT = 0xacff, + CMD_DISCONNECT = 0xcaff, + CMD_TOGGLE_WEIGHT_FREQ = 0xaaf1, + CMD_TOGGLE_MEAS_RANGE = 0xaaf2, + CMD_TOGGLE_HOLD_MAX_MIN = 0xaaf3, + CMD_TOGGLE_WEIGHT_TIME = 0xaaf4, + CMD_TOGGLE_HOLD = 0xaaf5, + CMD_TOGGLE_BACKLIGHT = 0xaaf6, + CMD_TOGGLE_DATE_TIME = 0xaaf7, + CMD_LOG_START = 0x7e00, + CMD_MEMORY_STATUS = 0xadda, + CMD_MEMORY_TRANSFER = 0xd3da, + CMD_MEMORY_CLEAR = 0xaac1, + CMD_POWER_OFF = 0xaaf8, +}; + +enum { + MEAS_RANGE_30_130 = 0, + MEAS_RANGE_30_80 = 1, + MEAS_RANGE_50_100 = 2, + MEAS_RANGE_80_130 = 3, +}; + +/** Private, per-device-instance driver context. */ +struct dev_context { + /* Model-specific information */ + uint64_t cur_mqflags; + uint8_t cur_meas_range; + + /* Acquisition settings */ + uint64_t limit_samples; + + /* Operational state */ + uint64_t num_samples; + + /* Temporary state across callbacks */ + uint8_t buffer[BUFFER_SIZE]; + int buffer_len; +}; + +SR_PRIV int pce_322a_connect(const struct sr_dev_inst *sdi); +SR_PRIV int pce_322a_disconnect(const struct sr_dev_inst *sdi); +SR_PRIV int pce_322a_receive_data(int fd, int revents, void *cb_data); +SR_PRIV uint64_t pce_322a_weight_freq_get(const struct sr_dev_inst *sdi); +SR_PRIV int pce_322a_weight_freq_set(const struct sr_dev_inst *sdi, uint64_t freqw); +SR_PRIV uint64_t pce_322a_weight_time_get(const struct sr_dev_inst *sdi); +SR_PRIV int pce_322a_weight_time_set(const struct sr_dev_inst *sdi, uint64_t timew); +SR_PRIV int pce_322a_meas_range_get(const struct sr_dev_inst *sdi, + uint64_t *low, uint64_t *high); +SR_PRIV int pce_322a_meas_range_set(const struct sr_dev_inst *sdi, + uint64_t low, uint64_t high); +SR_PRIV int pce_322a_power_off(const struct sr_dev_inst *sdi); + +#endif