2 * This file is part of the libsigrok project.
4 * Copyright (C) 2019 Derek Hageman <hageman@inthat.cloud>
6 * This program is free software: you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation, either version 3 of the License, or
9 * (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program. If not, see <http://www.gnu.org/licenses/>.
27 * The Mooshimeter protocol is broken down into several layers in a
28 * communication stack.
30 * The lowest layer is the BLE GATT stack, which provides two characteristics:
31 * one to write packets to the meter and one to receive them from it. The
32 * MTU for a packet in either direction is 20 bytes. This is implemented
33 * in the GATT abstraction, so we can talk to it via simple write commands
34 * and a read callback.
37 * The next layer is the serial stream: each BLE packet in either direction
38 * has a 1-byte header of a sequence number. Despite what the documentation
39 * says, this is present in both directions (not just meter output) and is
40 * NOT reset on the meter output on BLE connection. So the implementation
41 * here needs to provide an output sequence number and incoming reassembly
42 * for out of order packets (I haven't actually observed this, but
43 * supposedly it happens, which is why the sequence number is present).
44 * So the structure of packets received looks like:
46 * | 1 byte | 1-19 bytes |
47 * |--------|-------------|
48 * | SeqNum | Serial Data |
51 * On top of the serial layer is the "config tree" layer. This is how
52 * the meter actually exposes data and configuration. The tree itself
53 * is composed of nodes, each with a string name, data type, and a list
54 * of children (zero or more). For value containing (non-informational)
55 * nodes, they also contain a 7-bit unique identifier. Access to the
56 * config tree is provided by packets on the serial stream, each packet
57 * has a 1-byte header, where the uppermost bit (0x80) is set when writing
58 * (i.e. never by the meter) and the remaining 7 bits are the node identifier.
59 * The length of the packets varies based on the datatype of the tree node.
60 * This means that any lost/dropped packets can make the stream unrecoverable
61 * (i.e. there's no defined sync method other than reconnection). Packets
62 * are emitted by the meter in response to a read or write command (write
63 * commands simply back the value) and at unsolicited times by the meter
64 * (e.g. continuous sampling and periodic battery voltage). A read packet
65 * send to the meter looks like:
71 * In response to the read, the meter will send:
73 * | 1 bit | 7 bits | 1-N bytes |
74 * |-------|--------|-----------|
75 * | 0 | NodeID | NodeValue |
77 * A write packet sent to the meter:
79 * | 1 bit | 7 bits | 1-N bytes |
80 * |-------|--------|-----------|
81 * | 1 | NodeID | NodeValue |
83 * In response to the write, the meter will send a read response:
85 * | 1 bit | 7 bits | 1-N bytes |
86 * |-------|--------|-----------|
87 * | 0 | NodeID | NodeValue |
90 * For the data in the tree, all values are little endian (least significant
91 * bytes first). The supported type codes are:
93 * | Code | Description | Wire Format |
94 * |------|-------------|----------------------------------------|
97 * | 2 | Chooser | uint8_t |
98 * | 3 | U8 | uint8_t |
99 * | 4 | U16 | uint16_t |
100 * | 5 | U32 | uint32_t |
101 * | 6 | S8 | int8_t |
102 * | 7 | S16 | int16_t |
103 * | 8 | S32 | int32_t |
104 * | 9 | String | uint16_t length; char value[length] |
105 * | 10 | Binary | uint16_t length; uint8_t value[length] |
106 * | 11 | Float | float |
108 * Plain and Link nodes are present to provide information and/or choices
109 * but do not provide commands codes for direct access (see serialization
110 * below). Chooser nodes are written with indices described by their Plain
111 * type children (e.g. to select a choice identified by the second child
112 * of a chooser, write 1 to the chooser node itself).
114 * On initial connection only three nodes at fixed identifiers are available:
116 * | Node | ID | Type |
117 * |------------------|----|--------|
118 * | ADMIN:CRC32 | 0 | U32 |
119 * | ADMIN:TREE | 1 | Binary |
120 * | ADMIN:DIAGNOSTIC | 2 | String |
123 * The handshake sequence is to read the contents of ADMIN:TREE, which contains
124 * the zlib compressed tree serialization, then write the CRC of the compressed
125 * data back to ADMIN:CRC32 (which the meter will echo back). Only after
126 * that is done will the meter accept access to the rest of the tree.
128 * After zlib decompression the tree serialization is as follows:
130 * | Type | Description |
131 * |--------------|-------------------------------------|
132 * | uint8_t | The node data type code from above |
133 * | uint8_t | Name length |
134 * | char[length] | Node name (e.g. "ADMIN" or "CRC32") |
135 * | uint8_t | Number of children |
136 * | Node[count] | Child serialization (length varies) |
138 * Once the tree has been deserialized, each node needs its identifier
139 * assigned. This is a depth first tree walk, assigning sequential identifiers
140 * first the the current node (if it needs one), then repeating recursively
141 * for each of its children. Plain and Link nodes are skipped in assignment
142 * but not the walk (so the recursion still happens, but the identifier
143 * is not incremented).
146 * So, for example a write to the ADMIN:CRC32 as part of the handshake would
147 * be a write by us (the host):
149 * | SerSeq | NodeID | U32 (CRC) |
150 * | 1 byte | 1 byte | 4 bytes |
151 * ---------|--------|------------|
152 * | 0x01 | 0x80 | 0xDEADBEEF |
154 * The meter will respond with a packet like:
156 * | SerSeq | NodeID | U32 (CRC) |
157 * | 1 byte | 1 byte | 4 bytes |
158 * ---------|--------|------------|
159 * | 0x42 | 0x00 | 0xDEADBEEF |
161 * A spontaneous error from the meter (e.g. in response to a bad packet)
162 * can be emitted like:
164 * | SerSeq | NodeID | U16 (len) | String |
165 * | 1 byte | 1 byte | 2 bytes | len (=8) bytes |
166 * ---------|--------|------------|------------------|
167 * | 0xAB | 0x20 | 0x0008 | BAD\x20DATA |
170 * The config tree at the time of writing looks like:
176 * DIAGNOSTIC (STR) = 2
177 * PCB_VERSION (U8) = 3
180 * TIME_UTC_MS (U16) = 6
182 * REBOOT (CHOOSER) = 8
194 * DEPTH (CHOOSER) = 10
199 * TRIGGER (CHOOSER) = 11
205 * INTERVAL (U16) = 13
210 * END_TIME (U32) = 17
217 * MAPPING (CHOOSER) = 22
224 * ANALYSIS (CHOOSER) = 24
232 * BUF_LSB2NATIVE (FLT) = 29
234 * MAPPING (CHOOSER) = 30
242 * ANALYSIS (CHOOSER) = 32
250 * BUF_LSB2NATIVE (FLT) = 37
251 * SHARED (CHOOSER) = 38
264 * REAL_PWR (FLT) = 39
267 static struct config_tree_node *lookup_tree_path(struct dev_context *devc,
270 struct config_tree_node *current = &devc->tree_root;
271 struct config_tree_node *next;
276 end = strchr(path, ':');
278 length = strlen(path);
283 for (size_t i = 0; i < current->count_children; i++) {
284 if (!current->children[i].name)
286 if (strlen(current->children[i].name) != length)
288 if (g_ascii_strncasecmp(path,
289 current->children[i].name,
294 next = ¤t->children[i];
306 static int lookup_chooser_index(struct dev_context *devc, const char *path)
308 struct config_tree_node *node;
310 node = lookup_tree_path(devc, path);
314 return (int)node->index_in_parent;
317 static gboolean update_tree_data(struct config_tree_node *node,
318 GByteArray *contents)
321 switch (node->type) {
322 case TREE_NODE_DATATYPE_PLAIN:
323 case TREE_NODE_DATATYPE_LINK:
324 sr_err("Update for dataless node.");
325 g_byte_array_remove_range(contents, 0, 2);
327 case TREE_NODE_DATATYPE_CHOOSER:
328 case TREE_NODE_DATATYPE_U8:
329 node->value.i = R8(contents->data + 1);
330 g_byte_array_remove_range(contents, 0, 2);
332 case TREE_NODE_DATATYPE_U16:
333 if (contents->len < 3)
335 node->value.i = RL16(contents->data + 1);
336 g_byte_array_remove_range(contents, 0, 3);
338 case TREE_NODE_DATATYPE_U32:
339 if (contents->len < 5)
341 node->value.i = RL32(contents->data + 1);
342 g_byte_array_remove_range(contents, 0, 5);
344 case TREE_NODE_DATATYPE_S8:
345 node->value.i = (int8_t)R8(contents->data + 1);
346 g_byte_array_remove_range(contents, 0, 2);
348 case TREE_NODE_DATATYPE_S16:
349 if (contents->len < 3)
351 node->value.i = RL16S(contents->data + 1);
352 g_byte_array_remove_range(contents, 0, 3);
354 case TREE_NODE_DATATYPE_S32:
355 if (contents->len < 5)
357 node->value.i = RL32S(contents->data + 1);
358 g_byte_array_remove_range(contents, 0, 5);
360 case TREE_NODE_DATATYPE_STRING:
361 case TREE_NODE_DATATYPE_BINARY:
362 if (contents->len < 3)
364 len = RL16(contents->data + 1);
365 if (contents->len < 3 + len)
367 g_byte_array_set_size(node->value.b, len);
368 memcpy(node->value.b->data, contents->data + 3, len);
369 g_byte_array_remove_range(contents, 0, 3 + len);
371 case TREE_NODE_DATATYPE_FLOAT:
372 if (contents->len < 5)
374 node->value.f = RLFL(contents->data + 1);
375 g_byte_array_remove_range(contents, 0, 5);
379 node->update_number++;
382 (*node->on_update)(node, node->on_update_param);
387 static gboolean incoming_frame(struct packet_rx *rx,
388 const void *data, guint count)
390 const guint8 *bytes = data;
393 GSList *target = NULL;
399 if (rx->sequence_number < 0) {
400 rx->sequence_number = (seq + 1) & 0xFF;
401 g_byte_array_append(rx->contents, bytes + 1, count - 1);
403 } else if (rx->sequence_number == seq) {
404 rx->sequence_number = (seq + 1) & 0xFF;
405 g_byte_array_append(rx->contents, data + 1, count - 1);
407 while (rx->reorder_buffer && rx->reorder_buffer->data) {
408 rx->sequence_number = (rx->sequence_number + 1) & 0xFF;
410 ba = rx->reorder_buffer->data;
411 g_byte_array_append(rx->contents, ba->data, ba->len);
412 g_byte_array_free(ba, TRUE);
413 target = rx->reorder_buffer;
414 rx->reorder_buffer = rx->reorder_buffer->next;
415 g_slist_free_1(target);
419 ahead = seq - rx->sequence_number;
422 if (!rx->reorder_buffer)
423 rx->reorder_buffer = g_slist_alloc();
424 target = rx->reorder_buffer;
425 for (--ahead; ahead > 0; --ahead) {
427 target->next = g_slist_alloc();
428 target = target->next;
431 g_byte_array_free(target->data, TRUE);
432 target->data = g_byte_array_sized_new(count);
433 g_byte_array_append(target->data, data + 1, count - 1);
438 static void consume_packets(struct dev_context *devc)
441 struct config_tree_node *target;
443 if (devc->rx.contents->len < 2)
446 id = devc->rx.contents->data[0];
448 target = devc->tree_id_lookup[id];
451 sr_err("Command %hhu code does not map to a known node.", id);
452 g_byte_array_remove_index(devc->rx.contents, 0);
453 return consume_packets(devc);
456 if (!update_tree_data(target, devc->rx.contents))
459 return consume_packets(devc);
462 static int notify_cb(void *cb_data, uint8_t *data, size_t dlen)
464 const struct sr_dev_inst *sdi = cb_data;
465 struct dev_context *devc = sdi->priv;
467 if (!incoming_frame(&devc->rx, data, (guint)dlen))
470 consume_packets(devc);
475 static int write_frame(const struct sr_dev_inst *sdi,
476 const void *frame, size_t length)
478 struct sr_bt_desc *desc = sdi->conn;
480 if (sr_bt_write(desc, frame, length) != (ssize_t)length)
486 static int poll_tree_value(const struct sr_dev_inst *sdi,
487 struct config_tree_node *node)
489 struct dev_context *devc = sdi->priv;
492 W8(&frame[0], devc->tx.sequence_number);
493 W8(&frame[1], node->id);
495 devc->tx.sequence_number = (devc->tx.sequence_number + 1) & 0xFF;
497 return write_frame(sdi, frame, 2);
500 static void set_tree_integer(const struct sr_dev_inst *sdi,
501 struct config_tree_node *node, int32_t value)
503 struct dev_context *devc = sdi->priv;
507 W8(&frame[0], devc->tx.sequence_number);
508 W8(&frame[1], 0x80 | node->id);
512 switch (node->type) {
513 case TREE_NODE_DATATYPE_PLAIN:
514 case TREE_NODE_DATATYPE_LINK:
515 sr_err("Set attempted for dataless node.");
517 case TREE_NODE_DATATYPE_CHOOSER:
518 case TREE_NODE_DATATYPE_U8:
519 node->value.i = value;
520 W8(&frame[length], value);
523 case TREE_NODE_DATATYPE_U16:
524 node->value.i = value;
525 WL16(&frame[length], value);
528 case TREE_NODE_DATATYPE_U32:
529 node->value.i = value;
530 WL32(&frame[length], value);
533 case TREE_NODE_DATATYPE_S8:
534 node->value.i = value;
535 W8(&frame[length], value);
538 case TREE_NODE_DATATYPE_S16:
539 node->value.i = value;
540 WL16(&frame[length], value);
543 case TREE_NODE_DATATYPE_S32:
544 node->value.i = value;
545 WL32(&frame[length], value);
548 case TREE_NODE_DATATYPE_STRING:
549 case TREE_NODE_DATATYPE_BINARY:
550 case TREE_NODE_DATATYPE_FLOAT:
554 devc->tx.sequence_number = (devc->tx.sequence_number + 1) & 0xFF;
555 write_frame(sdi, frame, length);
558 static int32_t get_tree_integer(struct config_tree_node *node)
560 switch (node->type) {
561 case TREE_NODE_DATATYPE_PLAIN:
562 case TREE_NODE_DATATYPE_LINK:
563 sr_err("Read attempted for dataless node.");
565 case TREE_NODE_DATATYPE_CHOOSER:
566 case TREE_NODE_DATATYPE_U8:
567 case TREE_NODE_DATATYPE_U16:
568 case TREE_NODE_DATATYPE_U32:
569 case TREE_NODE_DATATYPE_S8:
570 case TREE_NODE_DATATYPE_S16:
571 case TREE_NODE_DATATYPE_S32:
572 return node->value.i;
573 case TREE_NODE_DATATYPE_FLOAT:
574 return (int)node->value.f;
582 static void tree_diagnostic_updated(struct config_tree_node *node, void *param)
586 if (!node->value.b->len) {
587 sr_warn("Mooshimeter error with no information.");
591 if (node->value.b->data[node->value.b->len]) {
592 g_byte_array_set_size(node->value.b, node->value.b->len + 1);
593 node->value.b->data[node->value.b->len - 1] = 0;
596 sr_warn("Mooshimeter error: %s.", node->value.b->data);
599 static void chX_value_update(struct config_tree_node *node,
600 struct sr_dev_inst *sdi, int channel)
602 struct dev_context *devc = sdi->priv;
604 struct sr_datafeed_packet packet;
605 struct sr_datafeed_analog analog;
606 struct sr_analog_encoding encoding;
607 struct sr_analog_meaning meaning;
608 struct sr_analog_spec spec;
610 if (!devc->enable_value_stream)
613 if (!((struct sr_channel *)devc->channel_meaning[channel].
614 channels->data)->enabled) {
618 if (node->type != TREE_NODE_DATATYPE_FLOAT)
620 value = node->value.f;
622 sr_spew("Received value for channel %d = %g.", channel, value);
625 * Could do significant digit calculations based on the
626 * effective number of effective bits (sample rate, buffer size, etc),
627 * but does it matter?
628 * (see https://github.com/mooshim/Mooshimeter-AndroidApp/blob/94a20a2d42f6af9975ad48591caa6a17130ca53b/app/src/main/java/com/mooshim/mooshimeter/devices/MooshimeterDevice.java#L691 )
630 sr_analog_init(&analog, &encoding, &meaning, &spec, 2);
632 memcpy(analog.meaning, &devc->channel_meaning[channel],
633 sizeof(struct sr_analog_meaning));
634 analog.num_samples = 1;
635 analog.data = &value;
636 packet.type = SR_DF_ANALOG;
637 packet.payload = &analog;
638 sr_session_send(sdi, &packet);
640 if (devc->channel_autorange[channel])
641 (*devc->channel_autorange[channel])(sdi, value);
643 sr_sw_limits_update_samples_read(&devc->limits, 1);
644 if (sr_sw_limits_check(&devc->limits))
645 sr_dev_acquisition_stop(sdi);
648 static void chX_buffer_update(struct config_tree_node *node,
649 struct sr_dev_inst *sdi, int channel)
651 struct dev_context *devc = sdi->priv;
652 uint32_t bits_per_sample = devc->buffer_bps[channel];
653 float output_scalar = devc->buffer_lsb2native[channel];
654 uint32_t bytes_per_sample;
657 size_t number_of_samples;
658 int32_t unscaled = 0;
661 float converted_value = 0;
662 float maximum_value = 0;
665 struct sr_datafeed_packet packet;
666 struct sr_datafeed_analog analog;
667 struct sr_analog_encoding encoding;
668 struct sr_analog_meaning meaning;
669 struct sr_analog_spec spec;
671 if (!devc->enable_value_stream)
674 if (!((struct sr_channel *)devc->channel_meaning[channel].
675 channels->data)->enabled) {
679 if (!bits_per_sample)
681 if (node->type != TREE_NODE_DATATYPE_BINARY)
683 raw = node->value.b->data;
684 size = node->value.b->len;
688 bytes_per_sample = bits_per_sample / 8;
689 if (bits_per_sample % 8 != 0)
691 if (bytes_per_sample > 4)
693 number_of_samples = size / bytes_per_sample;
694 if (!number_of_samples)
697 sr_analog_init(&analog, &encoding, &meaning, &spec, 0);
699 values = g_new0(float, number_of_samples);
700 output_value = values;
702 memcpy(analog.meaning, &devc->channel_meaning[channel],
703 sizeof(struct sr_analog_meaning));
704 analog.num_samples = number_of_samples;
705 analog.data = output_value;
706 packet.type = SR_DF_ANALOG;
707 packet.payload = &analog;
709 sr_spew("Received buffer for channel %d with %u bytes (%u samples).",
710 channel, (unsigned int)size, (unsigned int)number_of_samples);
712 sign_bit = 1 << (bits_per_sample - 1);
713 sign_mask = sign_bit - 1;
714 for (; size >= bytes_per_sample; size -= bytes_per_sample,
715 raw += bytes_per_sample, output_value++) {
716 switch (bytes_per_sample) {
721 unscaled = RL16(raw);
724 unscaled = ((uint32_t)raw[0]) |
725 (((uint32_t)raw[1]) << 8) |
726 (((uint32_t)raw[2]) << 16);
729 unscaled = RL32(raw);
735 unscaled = (unscaled & sign_mask) - (unscaled & sign_bit);
736 converted_value = (float)unscaled * output_scalar;
737 *output_value = converted_value;
738 if (fabsf(converted_value) > maximum_value)
739 maximum_value = fabsf(maximum_value);
742 sr_session_send(sdi, &packet);
746 if (devc->channel_autorange[channel])
747 (*devc->channel_autorange[channel])(sdi, maximum_value);
749 sr_sw_limits_update_samples_read(&devc->limits, number_of_samples);
750 if (sr_sw_limits_check(&devc->limits))
751 sr_dev_acquisition_stop(sdi);
754 static void ch1_value_update(struct config_tree_node *node, void *param)
756 chX_value_update(node, param, 0);
759 static void ch2_value_update(struct config_tree_node *node, void *param)
761 chX_value_update(node, param, 1);
764 static void power_value_update(struct config_tree_node *node, void *param)
766 chX_value_update(node, param, 2);
769 static void ch1_buffer_update(struct config_tree_node *node, void *param)
771 chX_buffer_update(node, param, 0);
774 static void ch2_buffer_update(struct config_tree_node *node, void *param)
776 chX_buffer_update(node, param, 1);
779 static void ch1_buffer_bps_update(struct config_tree_node *node, void *param)
781 const struct sr_dev_inst *sdi = param;
782 struct dev_context *devc = sdi->priv;
783 devc->buffer_bps[0] = (uint32_t)get_tree_integer(node);
786 static void ch2_buffer_bps_update(struct config_tree_node *node, void *param)
788 const struct sr_dev_inst *sdi = param;
789 struct dev_context *devc = sdi->priv;
790 devc->buffer_bps[1] = (uint32_t)get_tree_integer(node);
793 static void ch1_buffer_lsb2native_update(struct config_tree_node *node,
796 const struct sr_dev_inst *sdi = param;
797 struct dev_context *devc = sdi->priv;
798 if (node->type != TREE_NODE_DATATYPE_BINARY)
800 devc->buffer_lsb2native[0] = node->value.f;
803 static void ch2_buffer_lsb2native_update(struct config_tree_node *node,
806 const struct sr_dev_inst *sdi = param;
807 struct dev_context *devc = sdi->priv;
808 if (node->type != TREE_NODE_DATATYPE_BINARY)
810 devc->buffer_lsb2native[1] = node->value.f;
813 static void release_tree_node(struct config_tree_node *node)
817 switch (node->type) {
818 case TREE_NODE_DATATYPE_STRING:
819 case TREE_NODE_DATATYPE_BINARY:
820 g_byte_array_free(node->value.b, TRUE);
826 for (size_t i = 0; i < node->count_children; i++)
827 release_tree_node(node->children + i);
828 g_free(node->children);
831 static void allocate_startup_tree(struct dev_context *devc)
833 struct config_tree_node *node;
835 node = &devc->tree_root;
836 node->name = g_strdup("ADMIN");
837 node->type = TREE_NODE_DATATYPE_PLAIN;
838 node->count_children = 3;
839 node->children = g_new0(struct config_tree_node, node->count_children);
841 node = &devc->tree_root.children[0];
842 node->name = g_strdup("CRC");
843 node->type = TREE_NODE_DATATYPE_U32;
845 devc->tree_id_lookup[node->id] = node;
847 node = &devc->tree_root.children[1];
848 node->name = g_strdup("TREE");
849 node->type = TREE_NODE_DATATYPE_BINARY;
850 node->value.b = g_byte_array_new();
852 devc->tree_id_lookup[node->id] = node;
854 node = &devc->tree_root.children[2];
855 node->name = g_strdup("DIAGNOSTIC");
856 node->type = TREE_NODE_DATATYPE_STRING;
857 node->value.b = g_byte_array_new();
859 devc->tree_id_lookup[node->id] = node;
862 static gboolean tree_node_has_id(struct config_tree_node *node)
864 switch (node->type) {
865 case TREE_NODE_DATATYPE_PLAIN:
866 case TREE_NODE_DATATYPE_LINK:
875 static int deserialize_tree(struct dev_context *devc,
876 struct config_tree_node *node,
877 int *id, const uint8_t **data, size_t *size)
888 if (n > TREE_NODE_DATATYPE_FLOAT)
892 switch (node->type) {
893 case TREE_NODE_DATATYPE_STRING:
894 case TREE_NODE_DATATYPE_BINARY:
895 node->value.b = g_byte_array_new();
906 node->name = g_strndup((const char *)(*data), n);
913 if (tree_node_has_id(node)) {
916 devc->tree_id_lookup[node->id] = node;
924 node->count_children = n;
925 node->children = g_new0(struct config_tree_node, n);
927 for (size_t i = 0; i < n; i++) {
928 if ((res = deserialize_tree(devc,
929 node->children + i, id,
930 data, size)) != SR_OK) {
933 node->children[i].index_in_parent = i;
940 static int wait_for_update(const struct sr_dev_inst *sdi,
941 struct config_tree_node *node,
942 uint32_t original_update_number)
944 struct sr_bt_desc *desc = sdi->conn;
948 start_time = g_get_monotonic_time();
950 ret = sr_bt_check_notify(desc);
954 if (node->update_number != original_update_number)
957 if (g_get_monotonic_time() - start_time > 5 * 1000 * 1000)
963 /* Nothing pollable, so just sleep a bit and try again. */
967 return SR_ERR_TIMEOUT;
970 static void install_update_handlers(struct sr_dev_inst *sdi)
972 struct dev_context *devc = sdi->priv;
973 struct config_tree_node *target;
975 target = lookup_tree_path(devc, "CH1:VALUE");
977 target->on_update = ch1_value_update;
978 target->on_update_param = sdi;
980 sr_warn("No tree path for channel 1 values.");
983 target = lookup_tree_path(devc, "CH1:BUF");
985 target->on_update = ch1_buffer_update;
986 target->on_update_param = sdi;
988 sr_warn("No tree path for channel 1 buffer.");
991 target = lookup_tree_path(devc, "CH1:BUF_BPS");
993 target->on_update = ch1_buffer_bps_update;
994 target->on_update_param = sdi;
996 sr_warn("No tree path for channel 1 buffer BPS.");
999 target = lookup_tree_path(devc, "CH1:BUF_LSB2NATIVE");
1001 target->on_update = ch1_buffer_lsb2native_update;
1002 target->on_update_param = sdi;
1004 sr_warn("No tree path for channel 1 buffer conversion factor.");
1007 target = lookup_tree_path(devc, "CH2:VALUE");
1009 target->on_update = ch2_value_update;
1010 target->on_update_param = sdi;
1012 sr_warn("No tree path for channel 2 values.");
1015 target = lookup_tree_path(devc, "CH2:BUF");
1017 target->on_update = ch2_buffer_update;
1018 target->on_update_param = sdi;
1020 sr_warn("No tree path for channel 2 buffer.");
1023 target = lookup_tree_path(devc, "CH2:BUF_BPS");
1025 target->on_update = ch2_buffer_bps_update;
1026 target->on_update_param = sdi;
1028 sr_warn("No tree path for channel 2 buffer BPS.");
1031 target = lookup_tree_path(devc, "CH2:BUF_LSB2NATIVE");
1033 target->on_update = ch2_buffer_lsb2native_update;
1034 target->on_update_param = sdi;
1036 sr_warn("No tree path for channel 2 buffer conversion factor.");
1039 target = lookup_tree_path(devc, "REAL_PWR");
1041 target->on_update = power_value_update;
1042 target->on_update_param = sdi;
1044 sr_warn("No tree path for real power.");
1048 struct startup_context {
1049 struct sr_dev_inst *sdi;
1055 static void startup_failed(struct startup_context *ctx, int err)
1057 sr_dbg("Startup handshake failed: %s.", sr_strerror(err));
1060 ctx->running = FALSE;
1063 static void startup_complete(struct startup_context *ctx)
1065 sr_dbg("Startup handshake completed.");
1067 install_update_handlers(ctx->sdi);
1069 ctx->running = FALSE;
1072 static int startup_run(struct startup_context *ctx)
1074 struct sr_bt_desc *desc = ctx->sdi->conn;
1078 ctx->result = SR_OK;
1079 ctx->running = TRUE;
1081 start_time = g_get_monotonic_time();
1083 ret = sr_bt_check_notify(desc);
1090 if (g_get_monotonic_time() - start_time > 30 * 1000 * 1000)
1096 /* Nothing pollable, so just sleep a bit and try again. */
1097 g_usleep(50 * 1000);
1100 return SR_ERR_TIMEOUT;
1103 static void startup_tree_crc_updated(struct config_tree_node *node, void *param)
1105 struct startup_context *ctx = param;
1108 node->on_update = NULL;
1110 result = (uint32_t)get_tree_integer(node);
1111 if (result != ctx->crc) {
1112 sr_err("Tree CRC mismatch, expected %08X but received %08X.",
1114 startup_failed(ctx, SR_ERR_DATA);
1118 startup_complete(ctx);
1121 static void startup_send_tree_crc(struct startup_context *ctx)
1123 struct dev_context *devc = ctx->sdi->priv;
1124 struct config_tree_node *target;
1126 if (!(target = lookup_tree_path(devc, "ADMIN:CRC32"))) {
1127 sr_err("ADMIN:CRC32 node not found in received startup tree.");
1128 startup_failed(ctx, SR_ERR_DATA);
1132 target->on_update = startup_tree_crc_updated;
1133 target->on_update_param = ctx;
1135 set_tree_integer(ctx->sdi, target, ctx->crc);
1138 static uint32_t crc32(const uint8_t *ptr, size_t size)
1140 uint32_t result = 0xFFFFFFFF;
1142 for (; size; size--, ptr++) {
1144 for (int i = 0; i < 8; i++) {
1148 result ^= 0xEDB88320;
1155 static void startup_tree_updated(struct config_tree_node *node, void *param)
1157 struct startup_context *ctx = param;
1158 struct dev_context *devc = ctx->sdi->priv;
1160 GConverter *decompressor;
1161 GConverterResult decompress_result;
1162 GByteArray *tree_data;
1168 const uint8_t *data;
1170 struct config_tree_node *target;
1172 ctx->crc = crc32(node->value.b->data, node->value.b->len);
1174 tree_data = g_byte_array_new();
1175 g_byte_array_set_size(tree_data, 4096);
1176 decompressor = (GConverter *)g_zlib_decompressor_new(
1177 G_ZLIB_COMPRESSOR_FORMAT_ZLIB);
1179 g_converter_reset(decompressor);
1180 decompress_result = g_converter_convert(decompressor,
1181 node->value.b->data,
1185 G_CONVERTER_INPUT_AT_END,
1189 if (decompress_result == G_CONVERTER_FINISHED)
1191 if (decompress_result == G_CONVERTER_ERROR) {
1192 if (err->code == G_IO_ERROR_NO_SPACE &&
1193 tree_data->len < 1024 * 1024) {
1194 g_byte_array_set_size(tree_data,
1195 tree_data->len * 2);
1198 sr_err("Tree decompression failed: %s.", err->message);
1200 sr_err("Tree decompression error %d.",
1201 (int)decompress_result);
1203 startup_failed(ctx, SR_ERR_DATA);
1206 g_object_unref(decompressor);
1208 sr_dbg("Config tree received (%d -> %d bytes) with CRC %08X.",
1209 node->value.b->len, (int)output_size,
1212 release_tree_node(&devc->tree_root);
1213 memset(&devc->tree_root, 0, sizeof(struct config_tree_node));
1214 memset(devc->tree_id_lookup, 0, sizeof(devc->tree_id_lookup));
1217 data = tree_data->data;
1219 res = deserialize_tree(devc, &devc->tree_root, &id, &data, &size);
1220 g_byte_array_free(tree_data, TRUE);
1223 sr_err("Tree deserialization failed.");
1224 startup_failed(ctx, res);
1228 if ((target = lookup_tree_path(devc, "ADMIN:DIAGNOSTIC"))) {
1229 target->on_update = tree_diagnostic_updated;
1230 target->on_update_param = ctx->sdi;
1233 startup_send_tree_crc(ctx);
1236 static void release_rx_buffer(void *data)
1238 GByteArray *ba = data;
1241 g_byte_array_free(ba, TRUE);
1244 SR_PRIV int mooshimeter_dmm_open(const struct sr_dev_inst *sdi)
1246 struct dev_context *devc = sdi->priv;
1247 struct sr_bt_desc *desc = sdi->conn;
1248 struct startup_context ctx;
1251 release_tree_node(&devc->tree_root);
1252 memset(&devc->tree_root, 0, sizeof(struct config_tree_node));
1253 memset(devc->tree_id_lookup, 0, sizeof(devc->tree_id_lookup));
1255 g_slist_free_full(devc->rx.reorder_buffer, release_rx_buffer);
1256 devc->rx.reorder_buffer = NULL;
1257 if (devc->rx.contents)
1258 devc->rx.contents->len = 0;
1260 devc->rx.contents = g_byte_array_new();
1261 devc->rx.sequence_number = -1;
1262 devc->tx.sequence_number = 0;
1264 ret = sr_bt_config_cb_data(desc, notify_cb, (void *)sdi);
1268 ret = sr_bt_connect_ble(desc);
1272 ret = sr_bt_start_notify(desc);
1276 memset(&ctx, 0, sizeof(ctx));
1277 ctx.sdi = (struct sr_dev_inst *)sdi;
1279 allocate_startup_tree(devc);
1280 devc->tree_id_lookup[1]->on_update = startup_tree_updated;
1281 devc->tree_id_lookup[1]->on_update_param = &ctx;
1282 devc->tree_id_lookup[2]->on_update = tree_diagnostic_updated;
1283 devc->tree_id_lookup[2]->on_update_param = (struct sr_dev_inst *)sdi;
1285 sr_spew("Initiating startup handshake.");
1287 ret = poll_tree_value(sdi, devc->tree_id_lookup[1]);
1291 return startup_run(&ctx);
1294 SR_PRIV int mooshimeter_dmm_close(const struct sr_dev_inst *sdi)
1296 struct dev_context *devc = sdi->priv;
1297 struct sr_bt_desc *desc = sdi->conn;
1299 sr_bt_disconnect(desc);
1301 release_tree_node(&devc->tree_root);
1302 memset(&devc->tree_root, 0, sizeof(struct config_tree_node));
1303 memset(devc->tree_id_lookup, 0, sizeof(devc->tree_id_lookup));
1305 g_slist_free_full(devc->rx.reorder_buffer, release_rx_buffer);
1306 devc->rx.reorder_buffer = NULL;
1307 if (devc->rx.contents)
1308 g_byte_array_free(devc->rx.contents, TRUE);
1309 devc->rx.contents = NULL;
1314 SR_PRIV int mooshimeter_dmm_set_chooser(const struct sr_dev_inst *sdi,
1315 const char *path, const char *choice)
1317 struct dev_context *devc = sdi->priv;
1318 struct config_tree_node *target;
1320 uint32_t original_update_number;
1322 value = lookup_chooser_index(devc, choice);
1324 sr_err("Value %s not found for chooser %s.", choice, path);
1328 target = lookup_tree_path(devc, path);
1330 sr_err("Tree path %s not found.", path);
1334 sr_spew("Setting chooser %s to %s (%d).", path, choice, value);
1336 original_update_number = target->update_number;
1337 set_tree_integer(sdi, target, value);
1338 return wait_for_update(sdi, target, original_update_number);
1341 SR_PRIV int mooshimeter_dmm_set_integer(const struct sr_dev_inst *sdi,
1342 const char *path, int value)
1344 struct dev_context *devc = sdi->priv;
1345 struct config_tree_node *target;
1346 uint32_t original_update_number;
1348 target = lookup_tree_path(devc, path);
1350 sr_err("Tree path %s not found.", path);
1354 sr_spew("Setting integer %s to %d.", path, value);
1356 original_update_number = target->update_number;
1357 set_tree_integer(sdi, target, value);
1358 return wait_for_update(sdi, target, original_update_number);
1361 static struct config_tree_node *select_next_largest_in_tree(
1362 struct dev_context *devc,
1363 const char *parent, float number)
1367 float best_distance = 0;
1368 struct config_tree_node *choice_parent;
1369 struct config_tree_node *selected_choice = NULL;
1371 choice_parent = lookup_tree_path(devc, parent);
1372 if (!choice_parent) {
1373 sr_err("Tree path %s not found.", parent);
1376 if (!choice_parent->count_children) {
1377 sr_err("Tree path %s has no children.", parent);
1381 for (size_t i = 0; i < choice_parent->count_children; i++) {
1382 node_value = strtof(choice_parent->children[i].name, NULL);
1383 if (node_value <= 0)
1385 distance = node_value - number;
1386 if (!selected_choice) {
1387 selected_choice = &choice_parent->children[i];
1388 best_distance = distance;
1391 /* Select the one that's the least below it, if all
1392 * are below the target */
1394 if (best_distance > 0)
1396 if (distance > best_distance) {
1397 selected_choice = &choice_parent->children[i];
1398 best_distance = distance;
1402 if (best_distance < 0 || distance < best_distance) {
1403 selected_choice = &choice_parent->children[i];
1404 best_distance = distance;
1408 return selected_choice;
1411 SR_PRIV int mooshimeter_dmm_set_larger_number(const struct sr_dev_inst *sdi,
1412 const char *path, const char *parent, float number)
1414 struct dev_context *devc = sdi->priv;
1415 struct config_tree_node *selected_choice;
1416 struct config_tree_node *target;
1417 uint32_t original_update_number;
1419 selected_choice = select_next_largest_in_tree(devc, parent, number);
1420 if (!selected_choice) {
1421 sr_err("No choice available for %f at %s.", number, parent);
1425 target = lookup_tree_path(devc, path);
1427 sr_err("Tree path %s not found.", path);
1431 sr_spew("Setting number choice %s to index %d for requested %g.", path,
1432 (int)selected_choice->index_in_parent, number);
1434 original_update_number = target->update_number;
1435 set_tree_integer(sdi, target, selected_choice->index_in_parent);
1436 return wait_for_update(sdi, target, original_update_number);
1439 SR_PRIV gboolean mooshimeter_dmm_set_autorange(const struct sr_dev_inst *sdi,
1440 const char *path, const char *parent, float latest)
1442 struct dev_context *devc = sdi->priv;
1443 struct config_tree_node *selected_choice;
1444 struct config_tree_node *target;
1446 selected_choice = select_next_largest_in_tree(devc, parent,
1448 if (!selected_choice) {
1449 sr_err("No choice available for %f at %s.", latest, parent);
1453 target = lookup_tree_path(devc, path);
1455 sr_err("Tree path %s not found.", path);
1459 if (get_tree_integer(target) == (int)selected_choice->index_in_parent)
1462 sr_spew("Changing autorange %s to index %d for %g.", path,
1463 (int)selected_choice->index_in_parent, latest);
1465 set_tree_integer(sdi, target, selected_choice->index_in_parent);
1470 SR_PRIV int mooshimeter_dmm_get_chosen_number(const struct sr_dev_inst *sdi,
1471 const char *path, const char *parent, float *number)
1473 struct dev_context *devc = sdi->priv;
1474 struct config_tree_node *value_node;
1475 struct config_tree_node *available;
1478 value_node = lookup_tree_path(devc, path);
1480 sr_err("Tree path %s not found.", path);
1484 available = lookup_tree_path(devc, parent);
1486 sr_err("Tree path %s not found.", path);
1490 selected = get_tree_integer(value_node);
1491 if (selected < 0 || selected >= (int32_t)available->count_children)
1494 *number = g_ascii_strtod(available->children[selected].name, NULL);
1499 SR_PRIV int mooshimeter_dmm_get_available_number_choices(
1500 const struct sr_dev_inst *sdi, const char *path,
1501 float **numbers, size_t *count)
1503 struct dev_context *devc = sdi->priv;
1504 struct config_tree_node *available;
1506 available = lookup_tree_path(devc, path);
1508 sr_err("Tree path %s not found.", path);
1512 *numbers = g_malloc(sizeof(float) * available->count_children);
1513 *count = available->count_children;
1515 for (size_t i = 0; i < available->count_children; i++) {
1516 (*numbers)[i] = g_ascii_strtod(available->children[i].name,
1523 SR_PRIV int mooshimeter_dmm_poll(int fd, int revents, void *cb_data)
1525 struct sr_dev_inst *sdi;
1526 struct sr_bt_desc *desc;
1531 if (!(sdi = cb_data))
1536 while (sr_bt_check_notify(desc) > 0);
1542 * The meter will disconnect if it doesn't receive a host command for 30 (?)
1543 * seconds, so periodically poll a trivial value to keep it alive.
1545 SR_PRIV int mooshimeter_dmm_heartbeat(int fd, int revents, void *cb_data)
1547 struct sr_dev_inst *sdi;
1548 struct dev_context *devc;
1549 struct config_tree_node *target;
1554 if (!(sdi = cb_data))
1557 if (!(devc = sdi->priv))
1560 target = lookup_tree_path(devc, "PCB_VERSION");
1562 sr_err("Tree for PCB_VERSION not found.");
1566 sr_spew("Sending heartbeat request.");
1567 poll_tree_value(sdi, target);