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