]> sigrok.org Git - libsigrok.git/blobdiff - src/hardware/rdtech-dps/protocol.c
rdtech-dps: Use big endian register access for DPS devices
[libsigrok.git] / src / hardware / rdtech-dps / protocol.c
index d8bd5e82175fe979312df61909966d534a012938..83090d86ac7c2253c6662a305b7beab10015df67 100644 (file)
 #include "protocol.h"
 
 enum rdtech_dps_register {
-       REG_USET       = 0x00, /* Mirror of 0x50 */
-       REG_ISET       = 0x01, /* Mirror of 0x51 */
-       REG_UOUT       = 0x02,
-       REG_IOUT       = 0x03,
-       REG_POWER      = 0x04,
-       REG_UIN        = 0x05,
-       REG_LOCK       = 0x06,
-       REG_PROTECT    = 0x07,
-       REG_CV_CC      = 0x08,
-       REG_ENABLE     = 0x09,
-       REG_BACKLIGHT  = 0x0A, /* Mirror of 0x55 */
-       REG_MODEL      = 0x0B,
-       REG_VERSION    = 0x0C,
-
-       REG_PRESET     = 0x23, /* Loads a preset into preset 0. */
+       REG_DPS_USET       = 0x00, /* Mirror of 0x50 */
+       REG_DPS_ISET       = 0x01, /* Mirror of 0x51 */
+       REG_DPS_UOUT       = 0x02,
+       REG_DPS_IOUT       = 0x03,
+       REG_DPS_POWER      = 0x04,
+       REG_DPS_UIN        = 0x05,
+       REG_DPS_LOCK       = 0x06,
+       REG_DPS_PROTECT    = 0x07,
+       REG_DPS_CV_CC      = 0x08,
+       REG_DPS_ENABLE     = 0x09,
+       REG_DPS_BACKLIGHT  = 0x0A, /* Mirror of 0x55 */
+       REG_DPS_MODEL      = 0x0B,
+       REG_DPS_VERSION    = 0x0C,
+
+       REG_DPS_PRESET     = 0x23, /* Loads a preset into preset 0. */
 
        /*
         * Add (preset * 0x10) to each of the following, for preset 1-9.
         * Preset 0 regs below are the active output settings.
         */
-       PRE_USET       = 0x50,
-       PRE_ISET       = 0x51,
-       PRE_OVPSET     = 0x52,
-       PRE_OCPSET     = 0x53,
-       PRE_OPPSET     = 0x54,
-       PRE_BACKLIGHT  = 0x55,
-       PRE_DISABLE    = 0x56, /* Disable output if 0 is copied here from a preset (1 is no change). */
-       PRE_BOOT       = 0x57, /* Enable output at boot if 1. */
+       PRE_DPS_USET       = 0x50,
+       PRE_DPS_ISET       = 0x51,
+       PRE_DPS_OVPSET     = 0x52,
+       PRE_DPS_OCPSET     = 0x53,
+       PRE_DPS_OPPSET     = 0x54,
+       PRE_DPS_BACKLIGHT  = 0x55,
+       PRE_DPS_DISABLE    = 0x56, /* Disable output if 0 is copied here from a preset (1 is no change). */
+       PRE_DPS_BOOT       = 0x57, /* Enable output at boot if 1. */
 };
-#define REG_PRESET_STRIDE 0x10
+#define PRE_DPS_STRIDE 0x10
 
 enum rdtech_dps_protect_state {
        STATE_NORMAL = 0,
@@ -69,6 +69,37 @@ enum rdtech_dps_regulation_mode {
        MODE_CC      = 1,
 };
 
+enum rdtech_rd_register {
+       REG_RD_MODEL = 0, /* u16 */
+       REG_RD_SERIAL = 1, /* u32 */
+       REG_RD_FIRMWARE = 3, /* u16 */
+       REG_RD_TEMP_INT = 4, /* 2x u16 */
+       REG_RD_TEMP_INT_F = 6, /* 2x u16 */
+       REG_RD_VOLT_TGT = 8, /* u16 */
+       REG_RD_CURR_LIM = 9, /* u16 */
+       REG_RD_VOLTAGE = 10, /* u16 */
+       REG_RD_CURRENT = 11, /* u16 */
+       REG_RD_ENERGY = 12, /* u16 */
+       REG_RD_POWER = 13, /* u16 */
+       REG_RD_VOLT_IN = 14, /* u16 */
+       REG_RD_PROTECT = 16, /* u16 */
+       REG_RD_REGULATION = 17, /* u16 */
+       REG_RD_ENABLE = 18, /* u16 */
+       /*
+        * Battery at 32 == 0x20 pp:
+        * Mode, voltage, temperature, capacity, energy.
+        */
+       /*
+        * Date/time at 48 == 0x30 pp:
+        * Year, month, day, hour, minute, second.
+        */
+       /* Backlight at 72 == 0x48. */
+       REG_RD_OVP_THR = 82, /* 0x52 */
+       REG_RD_OCP_THR = 83, /* 0x53 */
+       /* One "live" slot and 9 "memory" positions. */
+       REG_RD_START_MEM = 84, /* 0x54 */
+};
+
 /* Retries failed modbus read attempts for improved reliability. */
 static int rdtech_dps_read_holding_registers(struct sr_modbus_dev_inst *modbus,
        int address, int nb_registers, uint16_t *registers)
@@ -87,32 +118,32 @@ static int rdtech_dps_read_holding_registers(struct sr_modbus_dev_inst *modbus,
        return ret;
 }
 
-/* Get one 16bit register. */
-static int rdtech_dps_get_reg(const struct sr_dev_inst *sdi,
-       uint16_t address, uint16_t *value)
+/* Set one 16bit register. LE format for DPS devices. */
+static int rdtech_dps_set_reg(const struct sr_dev_inst *sdi,
+       uint16_t address, uint16_t value)
 {
        struct dev_context *devc;
        struct sr_modbus_dev_inst *modbus;
        uint16_t registers[1];
        int ret;
-       const uint8_t *rdptr;
+       uint8_t *wrptr;
 
        devc = sdi->priv;
        modbus = sdi->conn;
 
+       wrptr = (void *)registers;
+       write_u16be(wrptr, value);
+
        g_mutex_lock(&devc->rw_mutex);
-       ret = rdtech_dps_read_holding_registers(modbus,
-               address, ARRAY_SIZE(registers), registers);
+       ret = sr_modbus_write_multiple_registers(modbus, address,
+               ARRAY_SIZE(registers), registers);
        g_mutex_unlock(&devc->rw_mutex);
 
-       rdptr = (void *)registers;
-       *value = read_u16le(rdptr);
-
        return ret;
 }
 
-/* Set one 16bit register. */
-static int rdtech_dps_set_reg(const struct sr_dev_inst *sdi,
+/* Set one 16bit register. BE format for RD devices. */
+static int rdtech_rd_set_reg(const struct sr_dev_inst *sdi,
        uint16_t address, uint16_t value)
 {
        struct dev_context *devc;
@@ -125,7 +156,7 @@ static int rdtech_dps_set_reg(const struct sr_dev_inst *sdi,
        modbus = sdi->conn;
 
        wrptr = (void *)registers;
-       write_u16le(wrptr, value);
+       write_u16be(wrptr, value);
 
        g_mutex_lock(&devc->rw_mutex);
        ret = sr_modbus_write_multiple_registers(modbus, address,
@@ -137,30 +168,49 @@ static int rdtech_dps_set_reg(const struct sr_dev_inst *sdi,
 
 /* Get DPS model number and firmware version from a connected device. */
 SR_PRIV int rdtech_dps_get_model_version(struct sr_modbus_dev_inst *modbus,
-       uint16_t *model, uint16_t *version)
+       enum rdtech_dps_model_type model_type,
+       uint16_t *model, uint16_t *version, uint32_t *serno)
 {
-       uint16_t registers[REG_VERSION + 1 - REG_MODEL];
+       uint16_t registers[4];
        int ret;
        const uint8_t *rdptr;
 
-       /* Silence a compiler warning about an unused routine. */
-       (void)rdtech_dps_get_reg;
-
        /*
-        * Get the MODEL and VERSION registers. No mutex here, because
-        * there is no sr_dev_inst when this function is called.
+        * No mutex here because when the routine executes then the
+        * device instance was not created yet (probe phase).
         */
-       ret = rdtech_dps_read_holding_registers(modbus,
-               REG_MODEL, ARRAY_SIZE(registers), registers);
-       if (ret != SR_OK)
-               return ret;
-
-       rdptr = (void *)registers;
-       *model = read_u16le_inc(&rdptr);
-       *version = read_u16le_inc(&rdptr);
-       sr_info("RDTech DPS PSU model: %u version: %u", *model, *version);
-
-       return ret;
+       switch (model_type) {
+       case MODEL_DPS:
+               /* Get the MODEL and VERSION registers. */
+               ret = rdtech_dps_read_holding_registers(modbus,
+                       REG_DPS_MODEL, 2, registers);
+               if (ret != SR_OK)
+                       return ret;
+               rdptr = (void *)registers;
+               *model = read_u16be_inc(&rdptr);
+               *version = read_u16be_inc(&rdptr);
+               *serno = 0;
+               sr_info("RDTech DPS/DPH model: %u version: %u",
+                       *model, *version);
+               return SR_OK;
+       case MODEL_RD:
+               /* Get the MODEL, SERIAL, and FIRMWARE registers. */
+               ret = rdtech_dps_read_holding_registers(modbus,
+                       REG_RD_MODEL, 4, registers);
+               if (ret != SR_OK)
+                       return ret;
+               rdptr = (void *)registers;
+               *model = read_u16be_inc(&rdptr) / 10;
+               *serno = read_u32be_inc(&rdptr);
+               *version = read_u16be_inc(&rdptr);
+               sr_info("RDTech RD model: %u version: %u, serno %u",
+                       *model, *version, *serno);
+               return SR_OK;
+       default:
+               sr_err("Unexpected RDTech PSU device type. Programming error?");
+               return SR_ERR_ARG;
+       }
+       /* UNREACH */
 }
 
 /* Send a measured value to the session feed. */
@@ -204,11 +254,12 @@ static int send_value(const struct sr_dev_inst *sdi,
  * when the UART bitrate is only 9600bps?
  */
 SR_PRIV int rdtech_dps_get_state(const struct sr_dev_inst *sdi,
-       struct rdtech_dps_state *state)
+       struct rdtech_dps_state *state, enum rdtech_dps_state_context reason)
 {
        struct dev_context *devc;
        struct sr_modbus_dev_inst *modbus;
-       uint16_t registers[REG_ENABLE + 1 - REG_USET];
+       gboolean get_config, get_init_state, get_curr_meas;
+       uint16_t registers[12];
        int ret;
        const uint8_t *rdptr;
        uint16_t uset_raw, iset_raw, uout_raw, iout_raw, power_raw;
@@ -226,59 +277,158 @@ SR_PRIV int rdtech_dps_get_state(const struct sr_dev_inst *sdi,
        if (!state)
                return SR_ERR_ARG;
 
-       /* Transfer a chunk of registers in a single call. */
-       g_mutex_lock(&devc->rw_mutex);
-       ret = rdtech_dps_read_holding_registers(modbus,
-               REG_USET, ARRAY_SIZE(registers), registers);
-       g_mutex_unlock(&devc->rw_mutex);
-       if (ret != SR_OK)
-               return ret;
-
-       /* Interpret the registers' values. */
-       rdptr = (const void *)registers;
-       uset_raw = read_u16le_inc(&rdptr);
-       volt_target = uset_raw / devc->voltage_multiplier;
-       iset_raw = read_u16le_inc(&rdptr);
-       curr_limit = iset_raw / devc->current_multiplier;
-       uout_raw = read_u16le_inc(&rdptr);
-       curr_voltage = uout_raw / devc->voltage_multiplier;
-       iout_raw = read_u16le_inc(&rdptr);
-       curr_current = iout_raw / devc->current_multiplier;
-       power_raw = read_u16le_inc(&rdptr);
-       curr_power = power_raw / 100.0f;
-       (void)read_u16le_inc(&rdptr); /* UIN */
-       reg_val = read_u16le_inc(&rdptr); /* LOCK */
-       is_lock = reg_val != 0;
-       reg_val = read_u16le_inc(&rdptr); /* PROTECT */
-       uses_ovp = reg_val == STATE_OVP;
-       uses_ocp = reg_val == STATE_OCP;
-       reg_state = read_u16le_inc(&rdptr); /* CV_CC */
-       is_reg_cc = reg_state == MODE_CC;
-       out_state = read_u16le_inc(&rdptr); /* ENABLE */
-       is_out_enabled = out_state != 0;
-
+       /* Determine the requested level of response detail. */
+       get_config = FALSE;
+       get_init_state = FALSE;
+       get_curr_meas = FALSE;
+       switch (reason) {
+       case ST_CTX_CONFIG:
+               get_config = TRUE;
+               get_init_state = TRUE;
+               get_curr_meas = TRUE;
+               break;
+       case ST_CTX_PRE_ACQ:
+               get_init_state = TRUE;
+               get_curr_meas = TRUE;
+               break;
+       case ST_CTX_IN_ACQ:
+               get_curr_meas = TRUE;
+               break;
+       default:
+               /* EMPTY */
+               break;
+       }
        /*
-        * Transfer another chunk of registers in a single call.
-        * TODO Unfortunately this call site open codes a fixed number
-        * of registers to read. But there is already some leakage of
-        * the register layout in this routine, and adding more device
-        * types in the future will make things "worse". So accept it.
+        * TODO Make use of this information to reduce the transfer
+        * volume, especially on low bitrate serial connections. Though
+        * the device firmware's samplerate is probably more limiting
+        * than communication bandwidth is.
         */
-       g_mutex_lock(&devc->rw_mutex);
-       ret = rdtech_dps_read_holding_registers(modbus,
-               PRE_OVPSET, 2, registers);
-       g_mutex_unlock(&devc->rw_mutex);
-       if (ret != SR_OK)
-               return ret;
+       (void)get_config;
+       (void)get_init_state;
+       (void)get_curr_meas;
+
+       switch (devc->model->model_type) {
+       case MODEL_DPS:
+               /*
+                * Transfer a chunk of registers in a single call. It's
+                * unfortunate that the model dependency and the sparse
+                * register map force us to open code addresses, sizes,
+                * and the sequence of the registers and how to interpret
+                * their bit fields. But then this is not too unusual for
+                * a hardware specific device driver ...
+                */
+               g_mutex_lock(&devc->rw_mutex);
+               ret = rdtech_dps_read_holding_registers(modbus,
+                       REG_DPS_USET, 10, registers);
+               g_mutex_unlock(&devc->rw_mutex);
+               if (ret != SR_OK)
+                       return ret;
+
+               /* Interpret the registers' values. */
+               rdptr = (const void *)registers;
+               uset_raw = read_u16be_inc(&rdptr);
+               volt_target = uset_raw / devc->voltage_multiplier;
+               iset_raw = read_u16be_inc(&rdptr);
+               curr_limit = iset_raw / devc->current_multiplier;
+               uout_raw = read_u16be_inc(&rdptr);
+               curr_voltage = uout_raw / devc->voltage_multiplier;
+               iout_raw = read_u16be_inc(&rdptr);
+               curr_current = iout_raw / devc->current_multiplier;
+               power_raw = read_u16be_inc(&rdptr);
+               curr_power = power_raw / 100.0f;
+               (void)read_u16be_inc(&rdptr); /* UIN */
+               reg_val = read_u16be_inc(&rdptr); /* LOCK */
+               is_lock = reg_val != 0;
+               reg_val = read_u16be_inc(&rdptr); /* PROTECT */
+               uses_ovp = reg_val == STATE_OVP;
+               uses_ocp = reg_val == STATE_OCP;
+               reg_state = read_u16be_inc(&rdptr); /* CV_CC */
+               is_reg_cc = reg_state == MODE_CC;
+               out_state = read_u16be_inc(&rdptr); /* ENABLE */
+               is_out_enabled = out_state != 0;
+
+               /* Transfer another chunk of registers in a single call. */
+               g_mutex_lock(&devc->rw_mutex);
+               ret = rdtech_dps_read_holding_registers(modbus,
+                       PRE_DPS_OVPSET, 2, registers);
+               g_mutex_unlock(&devc->rw_mutex);
+               if (ret != SR_OK)
+                       return ret;
+
+               /* Interpret the second registers chunk's values. */
+               rdptr = (const void *)registers;
+               ovpset_raw = read_u16be_inc(&rdptr); /* PRE OVPSET */
+               ovp_threshold = ovpset_raw * devc->voltage_multiplier;
+               ocpset_raw = read_u16be_inc(&rdptr); /* PRE OCPSET */
+               ocp_threshold = ocpset_raw * devc->current_multiplier;
+
+               break;
+
+       case MODEL_RD:
+               /* Retrieve a set of adjacent registers. */
+               g_mutex_lock(&devc->rw_mutex);
+               ret = rdtech_dps_read_holding_registers(modbus,
+                       REG_RD_VOLT_TGT, 11, registers);
+               g_mutex_unlock(&devc->rw_mutex);
+               if (ret != SR_OK)
+                       return ret;
+
+               /* Interpret the registers' raw content. */
+               rdptr = (const void *)registers;
+               uset_raw = read_u16be_inc(&rdptr); /* USET */
+               volt_target = uset_raw / devc->voltage_multiplier;
+               iset_raw = read_u16be_inc(&rdptr); /* ISET */
+               curr_limit = iset_raw / devc->current_multiplier;
+               uout_raw = read_u16be_inc(&rdptr); /* UOUT */
+               curr_voltage = uout_raw / devc->voltage_multiplier;
+               iout_raw = read_u16be_inc(&rdptr); /* IOUT */
+               curr_current = iout_raw / devc->current_multiplier;
+               (void)read_u16be_inc(&rdptr); /* ENERGY */
+               power_raw = read_u16be_inc(&rdptr); /* POWER */
+               curr_power = power_raw / 100.0f;
+               (void)read_u16be_inc(&rdptr); /* VOLT_IN */
+               (void)read_u16be_inc(&rdptr);
+               reg_val = read_u16be_inc(&rdptr); /* PROTECT */
+               uses_ovp = reg_val == STATE_OVP;
+               uses_ocp = reg_val == STATE_OCP;
+               reg_state = read_u16be_inc(&rdptr); /* REGULATION */
+               is_reg_cc = reg_state == MODE_CC;
+               out_state = read_u16be_inc(&rdptr); /* ENABLE */
+               is_out_enabled = out_state != 0;
+
+               /* Retrieve a set of adjacent registers. */
+               g_mutex_lock(&devc->rw_mutex);
+               ret = rdtech_dps_read_holding_registers(modbus,
+                       REG_RD_OVP_THR, 2, registers);
+               g_mutex_unlock(&devc->rw_mutex);
+               if (ret != SR_OK)
+                       return ret;
 
-       /* Interpret the registers' values. */
-       rdptr = (const void *)registers;
-       ovpset_raw = read_u16le_inc(&rdptr); /* PRE OVPSET */
-       ovp_threshold = ovpset_raw * devc->voltage_multiplier;
-       ocpset_raw = read_u16le_inc(&rdptr); /* PRE OCPSET */
-       ocp_threshold = ocpset_raw * devc->current_multiplier;
+               /* Interpret the registers' raw content. */
+               rdptr = (const void *)registers;
+               ovpset_raw = read_u16be_inc(&rdptr); /* OVP THR */
+               ovp_threshold = ovpset_raw / devc->voltage_multiplier;
+               ocpset_raw = read_u16be_inc(&rdptr); /* OCP THR */
+               ocp_threshold = ocpset_raw / devc->current_multiplier;
+
+               /* Details which we cannot query from the device. */
+               is_lock = FALSE;
+
+               break;
+
+       default:
+               /* ShouldNotHappen(TM). Probe should have failed. */
+               return SR_ERR_ARG;
+       }
 
-       /* Store gathered details in the high level container. */
+       /*
+        * Store gathered details in the high level container.
+        *
+        * TODO Make use of the caller's context. The register access
+        * code path above need not have gathered every detail in every
+        * invocation.
+        */
        memset(state, 0, sizeof(*state));
        state->lock = is_lock;
        state->mask |= STATE_LOCK;
@@ -327,39 +477,103 @@ SR_PRIV int rdtech_dps_set_state(const struct sr_dev_inst *sdi,
        /* Only a subset of known values is settable. */
        if (state->mask & STATE_OUTPUT_ENABLED) {
                reg_value = state->output_enabled ? 1 : 0;
-               ret = rdtech_dps_set_reg(sdi, REG_ENABLE, reg_value);
-               if (ret != SR_OK)
-                       return ret;
+               switch (devc->model->model_type) {
+               case MODEL_DPS:
+                       ret = rdtech_dps_set_reg(sdi, REG_DPS_ENABLE, reg_value);
+                       if (ret != SR_OK)
+                               return ret;
+                       break;
+               case MODEL_RD:
+                       ret = rdtech_rd_set_reg(sdi, REG_RD_ENABLE, reg_value);
+                       if (ret != SR_OK)
+                               return ret;
+                       break;
+               default:
+                       return SR_ERR_ARG;
+               }
        }
        if (state->mask & STATE_VOLTAGE_TARGET) {
                reg_value = state->voltage_target * devc->voltage_multiplier;
-               ret = rdtech_dps_set_reg(sdi, REG_USET, reg_value);
-               if (ret != SR_OK)
-                       return ret;
+               switch (devc->model->model_type) {
+               case MODEL_DPS:
+                       ret = rdtech_dps_set_reg(sdi, REG_DPS_USET, reg_value);
+                       if (ret != SR_OK)
+                               return ret;
+                       break;
+               case MODEL_RD:
+                       ret = rdtech_rd_set_reg(sdi, REG_RD_VOLT_TGT, reg_value);
+                       if (ret != SR_OK)
+                               return ret;
+                       break;
+               default:
+                       return SR_ERR_ARG;
+               }
        }
        if (state->mask & STATE_CURRENT_LIMIT) {
                reg_value = state->current_limit * devc->current_multiplier;
-               ret = rdtech_dps_set_reg(sdi, REG_ISET, reg_value);
-               if (ret != SR_OK)
-                       return ret;
+               switch (devc->model->model_type) {
+               case MODEL_DPS:
+                       ret = rdtech_dps_set_reg(sdi, REG_DPS_ISET, reg_value);
+                       if (ret != SR_OK)
+                               return ret;
+                       break;
+               case MODEL_RD:
+                       ret = rdtech_rd_set_reg(sdi, REG_RD_CURR_LIM, reg_value);
+                       if (ret != SR_OK)
+                               return ret;
+                       break;
+               default:
+                       return SR_ERR_ARG;
+               }
        }
        if (state->mask & STATE_OVP_THRESHOLD) {
                reg_value = state->ovp_threshold * devc->voltage_multiplier;
-               ret = rdtech_dps_set_reg(sdi, PRE_OVPSET, reg_value);
-               if (ret != SR_OK)
-                       return ret;
+               switch (devc->model->model_type) {
+               case MODEL_DPS:
+                       ret = rdtech_dps_set_reg(sdi, PRE_DPS_OVPSET, reg_value);
+                       if (ret != SR_OK)
+                               return ret;
+                       break;
+               case MODEL_RD:
+                       ret = rdtech_rd_set_reg(sdi, REG_RD_OVP_THR, reg_value);
+                       if (ret != SR_OK)
+                               return ret;
+                       break;
+               default:
+                       return SR_ERR_ARG;
+               }
        }
        if (state->mask & STATE_OCP_THRESHOLD) {
                reg_value = state->ocp_threshold * devc->current_multiplier;
-               ret = rdtech_dps_set_reg(sdi, PRE_OCPSET, reg_value);
-               if (ret != SR_OK)
-                       return ret;
+               switch (devc->model->model_type) {
+               case MODEL_DPS:
+                       ret = rdtech_dps_set_reg(sdi, PRE_DPS_OCPSET, reg_value);
+                       if (ret != SR_OK)
+                               return ret;
+                       break;
+               case MODEL_RD:
+                       ret = rdtech_rd_set_reg(sdi, REG_RD_OCP_THR, reg_value);
+                       if (ret != SR_OK)
+                               return ret;
+                       break;
+               default:
+                       return SR_ERR_ARG;
+               }
        }
        if (state->mask & STATE_LOCK) {
-               reg_value = state->lock ? 1 : 0;
-               ret = rdtech_dps_set_reg(sdi, REG_LOCK, reg_value);
-               if (ret != SR_OK)
-                       return ret;
+               switch (devc->model->model_type) {
+               case MODEL_DPS:
+                       reg_value = state->lock ? 1 : 0;
+                       ret = rdtech_dps_set_reg(sdi, REG_DPS_LOCK, reg_value);
+                       if (ret != SR_OK)
+                               return ret;
+                       break;
+               case MODEL_RD:
+                       /* Do nothing, _and_ silently succeed. */
+                       break;
+               default:
+                       return SR_ERR_ARG;
+               }
        }
 
        return SR_OK;
@@ -372,7 +586,11 @@ SR_PRIV int rdtech_dps_seed_receive(const struct sr_dev_inst *sdi)
        struct rdtech_dps_state state;
        int ret;
 
-       ret = rdtech_dps_get_state(sdi, &state);
+       if (!sdi || !sdi->priv)
+               return SR_ERR_ARG;
+       devc = sdi->priv;
+
+       ret = rdtech_dps_get_state(sdi, &state, ST_CTX_PRE_ACQ);
        if (ret != SR_OK)
                return ret;
 
@@ -407,7 +625,7 @@ SR_PRIV int rdtech_dps_receive_data(int fd, int revents, void *cb_data)
        devc = sdi->priv;
 
        /* Get the device's current state. */
-       ret = rdtech_dps_get_state(sdi, &state);
+       ret = rdtech_dps_get_state(sdi, &state, ST_CTX_IN_ACQ);
        if (ret != SR_OK)
                return ret;