]> sigrok.org Git - libsigrok.git/blob - src/hardware/beaglelogic/beaglelogic_tcp.c
beaglelogic: Add beaglelogic_tcp_drain function
[libsigrok.git] / src / hardware / beaglelogic / beaglelogic_tcp.c
1 /*
2  * This file is part of the libsigrok project.
3  *
4  * Copyright (C) 2017 Kumar Abhishek <abhishek@theembeddedkitchen.net>
5  * Portions of the code are adopted from scpi_tcp.c and scpi.c
6  *
7  * Copyright (C) 2013 Martin Ling <martin-sigrok@earth.li>
8  * Copyright (C) 2013 poljar (Damir Jelić) <poljarinho@gmail.com>
9  *
10  * This program is free software: you can redistribute it and/or modify
11  * it under the terms of the GNU General Public License as published by
12  * the Free Software Foundation, either version 3 of the License, or
13  * (at your option) any later version.
14  *
15  * This program is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU General Public License for more details.
19  *
20  * You should have received a copy of the GNU General Public License
21  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
22  */
23
24 #include <config.h>
25 #ifdef _WIN32
26 #define _WIN32_WINNT 0x0501
27 #include <winsock2.h>
28 #include <ws2tcpip.h>
29 #endif
30 #include <glib.h>
31 #include <string.h>
32 #include <unistd.h>
33 #ifndef _WIN32
34 #include <sys/socket.h>
35 #include <netinet/in.h>
36 #include <arpa/inet.h>
37 #include <netdb.h>
38 #endif
39 #include <errno.h>
40
41 #include "protocol.h"
42 #include "beaglelogic.h"
43
44 static int beaglelogic_tcp_open(struct dev_context *devc) {
45         struct addrinfo hints;
46         struct addrinfo *results, *res;
47         int err;
48
49         memset(&hints, 0, sizeof(hints));
50         hints.ai_family = AF_UNSPEC;
51         hints.ai_socktype = SOCK_STREAM;
52         hints.ai_protocol = IPPROTO_TCP;
53
54         err = getaddrinfo(devc->address, devc->port, &hints, &results);
55
56         if (err) {
57                 sr_err("Address lookup failed: %s:%s: %s", devc->address,
58                         devc->port, gai_strerror(err));
59                 return SR_ERR;
60         }
61
62         for (res = results; res; res = res->ai_next) {
63                 if ((devc->socket = socket(res->ai_family, res->ai_socktype,
64                                                 res->ai_protocol)) < 0)
65                         continue;
66                 if (connect(devc->socket, res->ai_addr, res->ai_addrlen) != 0) {
67                         close(devc->socket);
68                         devc->socket = -1;
69                         continue;
70                 }
71                 break;
72         }
73
74         freeaddrinfo(results);
75
76         if (devc->socket < 0) {
77                 sr_err("Failed to connect to %s:%s: %s", devc->address,
78                         devc->port, g_strerror(errno));
79                 return SR_ERR;
80         }
81
82         return SR_OK;
83 }
84
85 static int beaglelogic_tcp_send_cmd(struct dev_context *devc,
86                                     const char *format, ...) {
87         int len, out;
88         va_list args, args_copy;
89         char *buf;
90
91         va_start(args, format);
92         va_copy(args_copy, args);
93         len = vsnprintf(NULL, 0, format, args_copy);
94         va_end(args_copy);
95
96         buf = g_malloc0(len + 2);
97         vsprintf(buf, format, args);
98         va_end(args);
99
100         if (buf[len - 1] != '\n')
101                 buf[len] = '\n';
102
103         out = send(devc->socket, buf, strlen(buf), 0);
104
105         if (out < 0) {
106                 sr_err("Send error: %s", g_strerror(errno));
107                 return SR_ERR;
108         }
109
110         if (out < (int)strlen(buf)) {
111                 sr_dbg("Only sent %d/%d bytes of command: '%s'.", out,
112                        strlen(buf), buf);
113         }
114
115         sr_spew("Sent command: '%s'.", buf);
116         g_free(buf);
117
118         return SR_OK;
119 }
120
121 static int beaglelogic_tcp_read_data(struct dev_context *devc, char *buf,
122                 int maxlen) {
123         int len;
124
125         len = recv(devc->socket, buf, maxlen, 0);
126
127         if (len < 0) {
128                 sr_err("Receive error: %s", g_strerror(errno));
129                 return SR_ERR;
130         }
131
132         return len;
133 }
134
135 SR_PRIV int beaglelogic_tcp_drain(struct dev_context *devc) {
136         char *buf = g_malloc(1024);
137         fd_set rset;
138         int ret, len = 0;
139         struct timeval tv;
140
141         FD_ZERO(&rset);
142         FD_SET(devc->socket, &rset);
143
144         /* 25ms timeout */
145         tv.tv_sec = 0;
146         tv.tv_usec = 25 * 1000;
147
148         do {
149                 ret = select(devc->socket + 1, &rset, NULL, NULL, &tv);
150                 if (ret > 0) {
151                         len += beaglelogic_tcp_read_data(devc, buf, 1024);
152                 }
153         } while (ret > 0);
154
155         sr_spew("Drained %d bytes of data.", len);
156
157         g_free(buf);
158         return SR_OK;
159 }
160
161 static int beaglelogic_tcp_get_string(struct dev_context *devc, const char *cmd,
162                 char **tcp_resp) {
163         GString *response = g_string_sized_new(1024);
164         int len;
165         gint64 timeout;
166
167         if (cmd) {
168                 if (beaglelogic_tcp_send_cmd(devc, cmd) != SR_OK) {
169                         return SR_ERR;
170                 }
171         }
172
173         timeout = g_get_monotonic_time() + devc->read_timeout;
174         len = beaglelogic_tcp_read_data(devc, response->str,
175                                         response->allocated_len);
176
177         if (len < 0) {
178                 g_string_free(response, TRUE);
179                 return SR_ERR;
180         }
181
182         if (len > 0) {
183                 g_string_set_size(response, len);
184         }
185
186         if (g_get_monotonic_time() > timeout) {
187                 sr_err("Timed out waiting for response.");
188                 g_string_free(response, TRUE);
189                 return SR_ERR_TIMEOUT;
190         }
191
192         /* Remove trailing newline if present */
193         if (response->len >= 1 && response->str[response->len - 1] == '\n')
194                 g_string_truncate(response, response->len - 1);
195
196         /* Remove trailing carriage return if present */
197         if (response->len >= 1 && response->str[response->len - 1] == '\r')
198                 g_string_truncate(response, response->len - 1);
199
200         sr_spew("Got response: '%.70s', length %" G_GSIZE_FORMAT ".",
201                 response->str, response->len);
202
203         *tcp_resp = g_string_free(response, FALSE);
204         return SR_OK;
205 }
206
207 static int beaglelogic_tcp_get_int(struct dev_context *devc,
208                                    const char *cmd, int *response) {
209         int ret;
210         char *resp = NULL;
211
212         ret = beaglelogic_tcp_get_string(devc, cmd, &resp);
213         if (!resp && ret != SR_OK)
214                 return ret;
215
216         if (sr_atoi(resp, response) == SR_OK)
217                 ret = SR_OK;
218         else
219                 ret = SR_ERR_DATA;
220
221         g_free(resp);
222
223         return ret;
224 }
225
226 SR_PRIV int beaglelogic_tcp_detect(struct dev_context *devc) {
227         char *resp = NULL;
228         int ret;
229
230         ret = beaglelogic_tcp_get_string(devc, "version", &resp);
231         if (ret == SR_OK && !g_ascii_strncasecmp(resp, "BeagleLogic", 11))
232                 ret = SR_OK;
233         else
234                 ret = SR_ERR;
235
236         g_free(resp);
237         return ret;
238 }
239
240 static int beaglelogic_open(struct dev_context *devc) {
241         return beaglelogic_tcp_open(devc);
242 }
243
244 static int beaglelogic_close(struct dev_context *devc) {
245         g_free(devc->address);
246         g_free(devc->port);
247
248         if (close(devc->socket) < 0)
249                 return SR_ERR;
250
251         return SR_OK;
252 }
253
254 static int beaglelogic_get_buffersize(struct dev_context *devc) {
255         return beaglelogic_tcp_get_int(devc, "memalloc",
256                 (int *)&devc->buffersize);
257 }
258
259 static int beaglelogic_set_buffersize(struct dev_context *devc) {
260         int ret;
261         char *resp;
262
263         beaglelogic_tcp_send_cmd(devc, "memalloc %lu", devc->buffersize);
264         ret = beaglelogic_tcp_get_string(devc, NULL, &resp);
265         if (ret == SR_OK && !g_ascii_strncasecmp(resp, "ok", 2))
266                 ret = SR_OK;
267         else
268                 ret = SR_ERR;
269
270         g_free(resp);
271         return ret;
272 }
273
274 static int beaglelogic_get_samplerate(struct dev_context *devc) {
275         int arg, err;
276         err = beaglelogic_tcp_get_int(devc, "samplerate", &arg);
277         devc->cur_samplerate = arg;
278         return err;
279 }
280
281 static int beaglelogic_set_samplerate(struct dev_context *devc) {
282         int ret;
283         char *resp;
284
285         beaglelogic_tcp_send_cmd(devc, "samplerate %lu",
286                 (uint32_t)devc->cur_samplerate);
287         ret = beaglelogic_tcp_get_string(devc, NULL, &resp);
288         if (ret == SR_OK && !g_ascii_strncasecmp(resp, "ok", 2))
289                 ret = SR_OK;
290         else
291                 ret = SR_ERR;
292
293         g_free(resp);
294         return ret;
295 }
296
297 static int beaglelogic_get_sampleunit(struct dev_context *devc) {
298         return beaglelogic_tcp_get_int(devc, "sampleunit",
299                 (int *)&devc->sampleunit);
300 }
301
302 static int beaglelogic_set_sampleunit(struct dev_context *devc) {
303         int ret;
304         char *resp;
305
306         beaglelogic_tcp_send_cmd(devc, "sampleunit %lu", devc->sampleunit);
307         ret = beaglelogic_tcp_get_string(devc, NULL, &resp);
308         if (ret == SR_OK && !g_ascii_strncasecmp(resp, "ok", 2))
309                 ret = SR_OK;
310         else
311                 ret = SR_ERR;
312
313         g_free(resp);
314         return ret;
315 }
316
317 static int beaglelogic_get_triggerflags(struct dev_context *devc) {
318         return beaglelogic_tcp_get_int(devc, "triggerflags",
319                 (int *)&devc->triggerflags);
320 }
321
322 static int beaglelogic_set_triggerflags(struct dev_context *devc) {
323         int ret;
324         char *resp;
325
326         beaglelogic_tcp_send_cmd(devc, "triggerflags %lu", devc->triggerflags);
327         ret = beaglelogic_tcp_get_string(devc, NULL, &resp);
328         if (ret == SR_OK && !g_ascii_strncasecmp(resp, "ok", 2))
329                 ret = SR_OK;
330         else
331                 ret = SR_ERR;
332
333         g_free(resp);
334         return ret;
335 }
336
337 static int beaglelogic_get_lasterror(struct dev_context *devc) {
338         devc->last_error = 0;
339         return SR_OK;
340 }
341
342 static int beaglelogic_start(struct dev_context *devc) {
343         beaglelogic_tcp_drain(devc);
344         return beaglelogic_tcp_send_cmd(devc, "get");
345 }
346
347 static int beaglelogic_stop(struct dev_context *devc) {
348         return beaglelogic_tcp_send_cmd(devc, "close");
349 }
350
351 static int beaglelogic_get_bufunitsize(struct dev_context *devc) {
352         return beaglelogic_tcp_get_int(devc, "bufunitsize",
353                 (int *)&devc->bufunitsize);
354 }
355
356 static int beaglelogic_set_bufunitsize(struct dev_context *devc) {
357         int ret;
358         char *resp;
359
360         beaglelogic_tcp_send_cmd(devc, "bufunitsize %ld", devc->bufunitsize);
361         ret = beaglelogic_tcp_get_string(devc, NULL, &resp);
362         if (ret == SR_OK && !g_ascii_strncasecmp(resp, "ok", 2))
363                 ret = SR_OK;
364         else
365                 ret = SR_ERR;
366
367         g_free(resp);
368         return ret;
369 }
370
371 static int dummy(struct dev_context *devc) {
372         (devc);
373         return SR_ERR_NA;
374 }
375
376 SR_PRIV const struct beaglelogic_ops beaglelogic_tcp_ops = {
377         .open = beaglelogic_open,
378         .close = beaglelogic_close,
379         .get_buffersize = beaglelogic_get_buffersize,
380         .set_buffersize = beaglelogic_set_buffersize,
381         .get_samplerate = beaglelogic_get_samplerate,
382         .set_samplerate = beaglelogic_set_samplerate,
383         .get_sampleunit = beaglelogic_get_sampleunit,
384         .set_sampleunit = beaglelogic_set_sampleunit,
385         .get_triggerflags = beaglelogic_get_triggerflags,
386         .set_triggerflags = beaglelogic_set_triggerflags,
387         .start = beaglelogic_start,
388         .stop = beaglelogic_stop,
389         .get_lasterror = beaglelogic_get_lasterror,
390         .get_bufunitsize = beaglelogic_get_bufunitsize,
391         .set_bufunitsize = beaglelogic_set_bufunitsize,
392         .mmap = dummy,
393         .munmap = dummy,
394 };