]> sigrok.org Git - libsigrok.git/blame - src/hardware/brymen-dmm/protocol.c
Document if or why sometimes digits/spec_digits is 0.
[libsigrok.git] / src / hardware / brymen-dmm / protocol.c
CommitLineData
20cbc785
AG
1/*
2 * This file is part of the libsigrok project.
3 *
4 * Copyright (C) 2012 Alexandru Gagniuc <mr.nuke.me@gmail.com>
5 *
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.
10 *
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.
15 *
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/>.
18 */
19
6ec6c43b 20#include <config.h>
20cbc785
AG
21#include "protocol.h"
22
601fb67c
AG
23static void handle_packet(const uint8_t *buf, struct sr_dev_inst *sdi)
24{
25 float floatval;
26 struct dev_context *devc;
27 struct sr_datafeed_packet packet;
1653c430
UH
28 struct sr_datafeed_analog analog;
29 struct sr_analog_encoding encoding;
30 struct sr_analog_meaning meaning;
31 struct sr_analog_spec spec;
601fb67c
AG
32
33 devc = sdi->priv;
c5d6f5cc 34
1653c430
UH
35 sr_analog_init(&analog, &encoding, &meaning, &spec, 0);
36
601fb67c 37 analog.num_samples = 1;
1653c430 38 analog.meaning->mq = 0;
601fb67c 39
933e63a1
BV
40 if (brymen_parse(buf, &floatval, &analog, NULL) != SR_OK)
41 return;
601fb67c
AG
42 analog.data = &floatval;
43
1653c430 44 analog.meaning->channels = sdi->channels;
601fb67c 45
1653c430 46 if (analog.meaning->mq != 0) {
601fb67c 47 /* Got a measurement. */
1653c430 48 packet.type = SR_DF_ANALOG;
601fb67c 49 packet.payload = &analog;
695dc859 50 sr_session_send(sdi, &packet);
dcba0c41 51 sr_sw_limits_update_samples_read(&devc->sw_limits, 1);
601fb67c
AG
52 }
53}
54
55static void handle_new_data(struct sr_dev_inst *sdi)
56{
57 struct dev_context *devc;
58 int len, status, offset = 0;
d9a7c349 59 struct sr_serial_dev_inst *serial;
601fb67c
AG
60
61 devc = sdi->priv;
d9a7c349 62 serial = sdi->conn;
601fb67c
AG
63
64 /* Try to get as much data as the buffer can hold. */
65 len = DMM_BUFSIZE - devc->buflen;
44be13b1 66 len = serial_read_nonblocking(serial, devc->buf + devc->buflen, len);
601fb67c
AG
67 if (len < 1) {
68 sr_err("Serial port read error: %d.", len);
69 return;
70 }
71 devc->buflen += len;
72 status = PACKET_INVALID_HEADER;
73
74 /* Now look for packets in that data. */
75 while (status != PACKET_NEED_MORE_DATA) {
c5d6f5cc 76 /* We don't have a header, look for one. */
601fb67c
AG
77 if (devc->next_packet_len == 0) {
78 len = devc->buflen - offset;
79 status = brymen_packet_length(devc->buf + offset, &len);
80 if (status == PACKET_HEADER_OK) {
c5d6f5cc 81 /* We know how large the packet will be. */
601fb67c
AG
82 devc->next_packet_len = len;
83 } else if (status == PACKET_NEED_MORE_DATA) {
c5d6f5cc 84 /* We didn't yet receive the full header. */
601fb67c
AG
85 devc->next_packet_len = 0;
86 break;
87 } else {
c5d6f5cc 88 /* Invalid header. Move on. */
601fb67c
AG
89 devc->next_packet_len = 0;
90 offset++;
91 continue;
92 }
93 }
94
95 /* We know how the packet size, but did we receive all of it? */
96 if (devc->buflen - offset < devc->next_packet_len)
97 break;
98
c5d6f5cc 99 /* We should have a full packet here, so we can check it. */
601fb67c
AG
100 if (brymen_packet_is_valid(devc->buf + offset)) {
101 handle_packet(devc->buf + offset, sdi);
102 offset += devc->next_packet_len;
103 } else {
104 offset++;
105 }
c5d6f5cc 106
601fb67c
AG
107 /* We are done with this packet. Look for a new one. */
108 devc->next_packet_len = 0;
109 }
110
111 /* If we have any data left, move it to the beginning of our buffer. */
112 memmove(devc->buf, devc->buf + offset, devc->buflen - offset);
113 devc->buflen -= offset;
114}
115
20cbc785
AG
116SR_PRIV int brymen_dmm_receive_data(int fd, int revents, void *cb_data)
117{
601fb67c 118 struct sr_dev_inst *sdi;
20cbc785 119 struct dev_context *devc;
d9a7c349 120 struct sr_serial_dev_inst *serial;
601fb67c 121 int ret;
601fb67c
AG
122
123 (void)fd;
20cbc785
AG
124
125 if (!(sdi = cb_data))
126 return TRUE;
127
128 if (!(devc = sdi->priv))
129 return TRUE;
130
d9a7c349
UH
131 serial = sdi->conn;
132
20cbc785 133 if (revents == G_IO_IN) {
601fb67c
AG
134 /* Serial data arrived. */
135 handle_new_data(sdi);
136 } else {
137 /* Timeout, send another packet request. */
d9a7c349 138 if ((ret = brymen_packet_request(serial)) < 0) {
601fb67c
AG
139 sr_err("Failed to request packet: %d.", ret);
140 return FALSE;
141 }
142 }
143
dcba0c41 144 if (sr_sw_limits_check(&devc->sw_limits))
695dc859 145 sdi->driver->dev_acquisition_stop(sdi);
20cbc785
AG
146
147 return TRUE;
148}
601fb67c
AG
149
150/**
151 * Try to find a valid packet in a serial data stream.
152 *
153 * @param serial Previously initialized serial port structure.
154 * @param buf Buffer containing the bytes to write.
155 * @param buflen Size of the buffer.
c5d6f5cc 156 * @param get_packet_size Callback that assesses the size of incoming packets.
601fb67c
AG
157 * @param is_valid Callback that assesses whether the packet is valid or not.
158 * @param timeout_ms The timeout after which, if no packet is detected, to
159 * abort scanning.
160 * @param baudrate The baudrate of the serial port. This parameter is not
161 * critical, but it helps fine tune the serial port polling
162 * delay.
163 *
164 * @return SR_OK if a valid packet is found within the given timeout,
165 * SR_ERR upon failure.
166 */
167SR_PRIV int brymen_stream_detect(struct sr_serial_dev_inst *serial,
168 uint8_t *buf, size_t *buflen,
169 packet_length_t get_packet_size,
144f6660 170 packet_valid_callback is_valid,
601fb67c
AG
171 uint64_t timeout_ms, int baudrate)
172{
173 int64_t start, time, byte_delay_us;
174 size_t ibuf, i, maxlen;
6433156c
DE
175 ssize_t len, stream_len;
176 int packet_len;
177 int status;
601fb67c
AG
178
179 maxlen = *buflen;
180
af473e0e
ML
181 sr_dbg("Detecting packets on %s (timeout = %" PRIu64
182 "ms, baudrate = %d).", serial->port, timeout_ms, baudrate);
601fb67c
AG
183
184 /* Assume 8n1 transmission. That is 10 bits for every byte. */
1a46cc62 185 byte_delay_us = 10 * ((1000 * 1000) / baudrate);
601fb67c
AG
186 start = g_get_monotonic_time();
187
188 packet_len = i = ibuf = len = 0;
189 while (ibuf < maxlen) {
44be13b1 190 len = serial_read_nonblocking(serial, &buf[ibuf], maxlen - ibuf);
601fb67c
AG
191 if (len > 0) {
192 ibuf += len;
6433156c 193 sr_spew("Read %zd bytes.", len);
601fb67c
AG
194 }
195
196 time = g_get_monotonic_time() - start;
197 time /= 1000;
198
199 stream_len = ibuf - i;
200 if (stream_len > 0 && packet_len == 0) {
201 /* How large of a packet are we expecting? */
202 packet_len = stream_len;
203 status = get_packet_size(&buf[i], &packet_len);
0c5f2abc 204 switch (status) {
601fb67c 205 case PACKET_HEADER_OK:
c5d6f5cc 206 /* We know how much data we need to wait for. */
601fb67c
AG
207 break;
208 case PACKET_NEED_MORE_DATA:
c5d6f5cc 209 /* We did not receive the full header. */
601fb67c
AG
210 packet_len = 0;
211 break;
212 case PACKET_INVALID_HEADER:
213 default:
214 /*
215 * We had enough data, but here was an error in
216 * parsing the header. Restart parsing from the
c5d6f5cc 217 * next byte.
601fb67c
AG
218 */
219 packet_len = 0;
220 i++;
221 break;
222 }
223 }
224
c5d6f5cc 225 if ((stream_len >= packet_len) && (packet_len != 0)) {
601fb67c
AG
226 /* We have at least a packet's worth of data. */
227 if (is_valid(&buf[i])) {
228 sr_spew("Found valid %d-byte packet after "
c5d6f5cc 229 "%" PRIu64 "ms.", packet_len, time);
601fb67c
AG
230 *buflen = ibuf;
231 return SR_OK;
232 } else {
233 sr_spew("Got %d bytes, but not a valid "
c5d6f5cc 234 "packet.", packet_len);
601fb67c
AG
235
236 }
c5d6f5cc 237
601fb67c
AG
238 /* Not a valid packet. Continue searching. */
239 i++;
240 packet_len = 0;
241 }
c5d6f5cc 242
601fb67c
AG
243 if (time >= (int64_t)timeout_ms) {
244 /* Timeout */
6433156c 245 sr_dbg("Detection timed out after %" PRIi64 "ms.", time);
601fb67c
AG
246 break;
247 }
248 g_usleep(byte_delay_us);
249 }
250
251 *buflen = ibuf;
6433156c 252 sr_err("Didn't find a valid packet (read %zu bytes).", ibuf);
601fb67c
AG
253
254 return SR_ERR;
255}