+ int ret;
+
+ if ((ret = serial_write(serial, cmd, strlen(cmd))) < 0) {
+ sr_err("Error sending '%s' command: %d.", cmd, ret);
+ return SR_ERR;
+ }
+
+ return SR_OK;
+}
+
+SR_PRIV gboolean center_3xx_packet_valid(const uint8_t *buf)
+{
+ return (buf[0] == 0x02 && buf[44] == 0x03);
+}
+
+static void log_packet(const uint8_t *buf, int idx)
+{
+ int i;
+ GString *s;
+
+ s = g_string_sized_new(100);
+ g_string_printf(s, "Packet: ");
+ for (i = 0; i < center_devs[idx].packet_size; i++)
+ g_string_append_printf(s, "%02x ", buf[i]);
+ sr_spew("%s", s->str);
+ g_string_free(s, TRUE);
+}
+
+static int packet_parse(const uint8_t *buf, int idx, struct center_info *info)
+{
+ int i;
+ uint16_t temp_u16;
+
+ log_packet(buf, idx);
+
+ /* Byte 0: Always 0x02. */
+
+ /* Byte 1: Various status bits. */
+ info->rec = (buf[1] & (1 << 0)) != 0;
+ info->mode_std = (((buf[1] >> 1) & 0x3) == 0);
+ info->mode_max = (((buf[1] >> 1) & 0x3) == 1);
+ info->mode_min = (((buf[1] >> 1) & 0x3) == 2);
+ info->mode_maxmin = (((buf[1] >> 1) & 0x3) == 3);
+ /* TODO: Rel. Not available on all models. */
+ info->t1t2 = (buf[1] & (1 << 3)) != 0;
+ info->rel = (buf[1] & (1 << 4)) != 0;
+ info->hold = (buf[1] & (1 << 5)) != 0;
+ info->lowbat = (buf[1] & (1 << 6)) != 0;
+ info->celsius = (buf[1] & (1 << 7)) != 0;
+
+ /* Byte 2: Further status bits. */
+ info->memfull = (buf[2] & (1 << 0)) != 0;
+ info->autooff = (buf[2] & (1 << 7)) != 0;
+
+ /* Byte 7+8/9+10/11+12/13+14: channel T1/T2/T3/T4 temperature. */
+ for (i = 0; i < 4; i++) {
+ temp_u16 = buf[8 + (i * 2)];
+ temp_u16 |= ((uint16_t)buf[7 + (i * 2)] << 8);
+ info->temp[i] = (float)temp_u16;
+ }
+
+ /* Byte 43: Specifies whether we need to divide the value(s) by 10. */
+ for (i = 0; i < 4; i++) {
+ /* Bit = 0: Divide by 10. Bit = 1: Don't divide by 10. */
+ if ((buf[43] & (1 << i)) == 0)
+ info->temp[i] /= 10;
+ }
+
+ /* Bytes 39-42: Overflow/overlimit bits, depending on mode. */
+ for (i = 0; i < 4; i++) {
+ if (info->mode_std && ((buf[39] & (1 << i)) != 0))
+ info->temp[i] = INFINITY;
+ /* TODO: Rel. Not available on all models. */
+ // if (info->mode_rel && ((buf[40] & (1 << i)) != 0))
+ // info->temp[i] = INFINITY;
+ if (info->mode_max && ((buf[41] & (1 << i)) != 0))
+ info->temp[i] = INFINITY;
+ if (info->mode_min && ((buf[42] & (1 << i)) != 0))
+ info->temp[i] = INFINITY;
+ /* TODO: Minmax? */
+ }
+
+ /* Byte 44: Always 0x03. */
+
+ return SR_OK;
+}
+
+static int handle_packet(const uint8_t *buf, struct sr_dev_inst *sdi, int idx)
+{
+ struct sr_datafeed_packet packet;
+ struct sr_datafeed_analog analog;
+ struct dev_context *devc;
+ struct center_info info;
+ GSList *l;
+ int i, ret;
+
+ devc = sdi->priv;