+
+static float binary32_le_to_float(unsigned char *buf)
+{
+ GFloatIEEE754 f;
+
+ f.v_float = 0;
+ f.mpn.sign = (buf[3] & 0x80) ? 1 : 0;
+ f.mpn.biased_exponent = (buf[3] << 1) | (buf[2] >> 7);
+ f.mpn.mantissa = buf[0] | (buf[1] << 8) | ((buf[2] & 0x7f) << 16);
+
+ return f.v_float;
+}
+
+SR_PRIV void testo_receive_packet(const struct sr_dev_inst *sdi)
+{
+ struct dev_context *devc;
+ struct sr_datafeed_packet packet;
+ struct sr_datafeed_analog analog;
+ struct sr_channel *ch;
+ GString *dbg;
+ float value;
+ int i;
+ unsigned char *buf;
+
+ devc = sdi->priv;
+ sr_dbg("Got %d-byte packet.", devc->reply_size);
+
+ if (sr_log_loglevel_get() >= SR_LOG_SPEW) {
+ dbg = g_string_sized_new(128);
+ g_string_printf(dbg, "Packet:");
+ for (i = 0; i < devc->reply_size; i++)
+ g_string_append_printf(dbg, " %.2x", devc->reply[i]);
+ sr_spew("%s", dbg->str);
+ g_string_free(dbg, TRUE);
+ }
+
+ if (!testo_check_packet(devc->reply, devc->reply_size))
+ return;
+
+ packet.type = SR_DF_ANALOG;
+ packet.payload = &analog;
+ analog.num_samples = 1;
+ analog.mqflags = 0;
+ analog.data = &value;
+ /* Decode 7-byte values */
+ for (i = 0; i < devc->reply[6]; i++) {
+ buf = devc->reply + 7 + i * 7;
+ value = binary32_le_to_float(buf);
+ sr_dbg("value: %f unit %d exp %d", value, buf[4], buf[6]);
+ switch (buf[4]) {
+ case 1:
+ analog.mq = SR_MQ_TEMPERATURE;
+ analog.unit = SR_UNIT_CELSIUS;
+ break;
+ case 3:
+ analog.mq = SR_MQ_RELATIVE_HUMIDITY;
+ analog.unit = SR_UNIT_HUMIDITY_293K;
+ break;
+ case 5:
+ analog.mq = SR_MQ_WIND_SPEED;
+ analog.unit = SR_UNIT_METER_SECOND;
+ break;
+ case 24:
+ analog.mq = SR_MQ_PRESSURE;
+ analog.unit = SR_UNIT_HECTOPASCAL;
+ break;
+ default:
+ sr_dbg("Unsupported measurement unit %d", buf[4]);
+ return;
+ }
+
+ /* Match this measurement with its channel. */
+ for (i = 0; i < devc->num_channels; i++) {
+ if (devc->channel_units[i] == buf[4])
+ break;
+ }
+ if (i == devc->num_channels) {
+ /* Shouldn't happen. */
+ sr_err("Some channel hotswapped in!");
+ return;
+ }
+ ch = g_slist_nth_data(sdi->channels, i);
+ sr_dbg("channel %d name %s unit %d", i, ch->name, analog.unit);
+ analog.channels = g_slist_append(NULL, ch);
+ sr_session_send(sdi, &packet);
+ g_slist_free(analog.channels);
+ }
+}
+