]> sigrok.org Git - libsigrok.git/blame - src/hardware/beaglelogic/beaglelogic_tcp.c
beaglelogic: Coding style fixes
[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));
110 return SR_ERR;
111 }
112
113 if (out < (int)strlen(buf)) {
f154b40d 114 sr_dbg("Only sent %d/%lu bytes of command: '%s'.", out,
9b2b3ef9
KA
115 strlen(buf), buf);
116 }
117
118 sr_spew("Sent command: '%s'.", buf);
119 g_free(buf);
120
121 return SR_OK;
122}
123
124static int beaglelogic_tcp_read_data(struct dev_context *devc, char *buf,
a31010b3
KA
125 int maxlen)
126{
9b2b3ef9
KA
127 int len;
128
129 len = recv(devc->socket, buf, maxlen, 0);
130
131 if (len < 0) {
132 sr_err("Receive error: %s", g_strerror(errno));
133 return SR_ERR;
134 }
135
136 return len;
137}
138
a31010b3
KA
139SR_PRIV int beaglelogic_tcp_drain(struct dev_context *devc)
140{
f7d7ee82
KA
141 char *buf = g_malloc(1024);
142 fd_set rset;
143 int ret, len = 0;
144 struct timeval tv;
145
146 FD_ZERO(&rset);
147 FD_SET(devc->socket, &rset);
148
149 /* 25ms timeout */
150 tv.tv_sec = 0;
151 tv.tv_usec = 25 * 1000;
152
153 do {
154 ret = select(devc->socket + 1, &rset, NULL, NULL, &tv);
155 if (ret > 0) {
156 len += beaglelogic_tcp_read_data(devc, buf, 1024);
157 }
158 } while (ret > 0);
159
160 sr_spew("Drained %d bytes of data.", len);
161
162 g_free(buf);
163 return SR_OK;
164}
165
9b2b3ef9 166static int beaglelogic_tcp_get_string(struct dev_context *devc, const char *cmd,
a31010b3
KA
167 char **tcp_resp)
168{
9b2b3ef9
KA
169 GString *response = g_string_sized_new(1024);
170 int len;
171 gint64 timeout;
172
173 if (cmd) {
174 if (beaglelogic_tcp_send_cmd(devc, cmd) != SR_OK) {
175 return SR_ERR;
176 }
177 }
178
179 timeout = g_get_monotonic_time() + devc->read_timeout;
180 len = beaglelogic_tcp_read_data(devc, response->str,
181 response->allocated_len);
182
183 if (len < 0) {
184 g_string_free(response, TRUE);
185 return SR_ERR;
186 }
187
188 if (len > 0) {
189 g_string_set_size(response, len);
190 }
191
192 if (g_get_monotonic_time() > timeout) {
193 sr_err("Timed out waiting for response.");
194 g_string_free(response, TRUE);
195 return SR_ERR_TIMEOUT;
196 }
197
198 /* Remove trailing newline if present */
199 if (response->len >= 1 && response->str[response->len - 1] == '\n')
200 g_string_truncate(response, response->len - 1);
201
202 /* Remove trailing carriage return if present */
203 if (response->len >= 1 && response->str[response->len - 1] == '\r')
204 g_string_truncate(response, response->len - 1);
205
206 sr_spew("Got response: '%.70s', length %" G_GSIZE_FORMAT ".",
207 response->str, response->len);
208
209 *tcp_resp = g_string_free(response, FALSE);
210 return SR_OK;
211}
212
213static int beaglelogic_tcp_get_int(struct dev_context *devc,
a31010b3
KA
214 const char *cmd, int *response)
215{
9b2b3ef9
KA
216 int ret;
217 char *resp = NULL;
218
219 ret = beaglelogic_tcp_get_string(devc, cmd, &resp);
220 if (!resp && ret != SR_OK)
221 return ret;
222
223 if (sr_atoi(resp, response) == SR_OK)
224 ret = SR_OK;
225 else
226 ret = SR_ERR_DATA;
227
228 g_free(resp);
229
230 return ret;
231}
232
a31010b3
KA
233SR_PRIV int beaglelogic_tcp_detect(struct dev_context *devc)
234{
9b2b3ef9
KA
235 char *resp = NULL;
236 int ret;
237
238 ret = beaglelogic_tcp_get_string(devc, "version", &resp);
239 if (ret == SR_OK && !g_ascii_strncasecmp(resp, "BeagleLogic", 11))
240 ret = SR_OK;
241 else
242 ret = SR_ERR;
243
244 g_free(resp);
245 return ret;
246}
247
a31010b3
KA
248static int beaglelogic_open(struct dev_context *devc)
249{
9b2b3ef9
KA
250 return beaglelogic_tcp_open(devc);
251}
252
a31010b3
KA
253static int beaglelogic_close(struct dev_context *devc)
254{
9b2b3ef9
KA
255 if (close(devc->socket) < 0)
256 return SR_ERR;
257
258 return SR_OK;
259}
260
a31010b3
KA
261static int beaglelogic_get_buffersize(struct dev_context *devc)
262{
9b2b3ef9
KA
263 return beaglelogic_tcp_get_int(devc, "memalloc",
264 (int *)&devc->buffersize);
265}
266
a31010b3
KA
267static int beaglelogic_set_buffersize(struct dev_context *devc)
268{
9b2b3ef9
KA
269 int ret;
270 char *resp;
271
272 beaglelogic_tcp_send_cmd(devc, "memalloc %lu", devc->buffersize);
273 ret = beaglelogic_tcp_get_string(devc, NULL, &resp);
274 if (ret == SR_OK && !g_ascii_strncasecmp(resp, "ok", 2))
275 ret = SR_OK;
276 else
277 ret = SR_ERR;
278
279 g_free(resp);
280 return ret;
281}
282
a31010b3
KA
283static int beaglelogic_get_samplerate(struct dev_context *devc)
284{
9b2b3ef9
KA
285 int arg, err;
286 err = beaglelogic_tcp_get_int(devc, "samplerate", &arg);
287 devc->cur_samplerate = arg;
288 return err;
289}
290
a31010b3
KA
291static int beaglelogic_set_samplerate(struct dev_context *devc)
292{
9b2b3ef9
KA
293 int ret;
294 char *resp;
295
296 beaglelogic_tcp_send_cmd(devc, "samplerate %lu",
297 (uint32_t)devc->cur_samplerate);
298 ret = beaglelogic_tcp_get_string(devc, NULL, &resp);
299 if (ret == SR_OK && !g_ascii_strncasecmp(resp, "ok", 2))
300 ret = SR_OK;
301 else
302 ret = SR_ERR;
303
304 g_free(resp);
305 return ret;
306}
307
a31010b3
KA
308static int beaglelogic_get_sampleunit(struct dev_context *devc)
309{
9b2b3ef9
KA
310 return beaglelogic_tcp_get_int(devc, "sampleunit",
311 (int *)&devc->sampleunit);
312}
313
a31010b3
KA
314static int beaglelogic_set_sampleunit(struct dev_context *devc)
315{
9b2b3ef9
KA
316 int ret;
317 char *resp;
318
319 beaglelogic_tcp_send_cmd(devc, "sampleunit %lu", devc->sampleunit);
320 ret = beaglelogic_tcp_get_string(devc, NULL, &resp);
321 if (ret == SR_OK && !g_ascii_strncasecmp(resp, "ok", 2))
322 ret = SR_OK;
323 else
324 ret = SR_ERR;
325
326 g_free(resp);
327 return ret;
328}
329
a31010b3
KA
330static int beaglelogic_get_triggerflags(struct dev_context *devc)
331{
9b2b3ef9
KA
332 return beaglelogic_tcp_get_int(devc, "triggerflags",
333 (int *)&devc->triggerflags);
334}
335
a31010b3
KA
336static int beaglelogic_set_triggerflags(struct dev_context *devc)
337{
9b2b3ef9
KA
338 int ret;
339 char *resp;
340
341 beaglelogic_tcp_send_cmd(devc, "triggerflags %lu", devc->triggerflags);
342 ret = beaglelogic_tcp_get_string(devc, NULL, &resp);
343 if (ret == SR_OK && !g_ascii_strncasecmp(resp, "ok", 2))
344 ret = SR_OK;
345 else
346 ret = SR_ERR;
347
348 g_free(resp);
349 return ret;
350}
351
a31010b3
KA
352static int beaglelogic_get_lasterror(struct dev_context *devc)
353{
9b2b3ef9
KA
354 devc->last_error = 0;
355 return SR_OK;
356}
357
a31010b3
KA
358static int beaglelogic_start(struct dev_context *devc)
359{
f7d7ee82 360 beaglelogic_tcp_drain(devc);
9b2b3ef9
KA
361 return beaglelogic_tcp_send_cmd(devc, "get");
362}
363
a31010b3
KA
364static int beaglelogic_stop(struct dev_context *devc)
365{
9b2b3ef9
KA
366 return beaglelogic_tcp_send_cmd(devc, "close");
367}
368
a31010b3
KA
369static int beaglelogic_get_bufunitsize(struct dev_context *devc)
370{
9b2b3ef9
KA
371 return beaglelogic_tcp_get_int(devc, "bufunitsize",
372 (int *)&devc->bufunitsize);
373}
374
a31010b3
KA
375static int beaglelogic_set_bufunitsize(struct dev_context *devc)
376{
9b2b3ef9
KA
377 int ret;
378 char *resp;
379
380 beaglelogic_tcp_send_cmd(devc, "bufunitsize %ld", devc->bufunitsize);
381 ret = beaglelogic_tcp_get_string(devc, NULL, &resp);
382 if (ret == SR_OK && !g_ascii_strncasecmp(resp, "ok", 2))
383 ret = SR_OK;
384 else
385 ret = SR_ERR;
386
387 g_free(resp);
388 return ret;
389}
390
a31010b3
KA
391static int dummy(struct dev_context *devc)
392{
f154b40d 393 (void)devc;
9b2b3ef9
KA
394 return SR_ERR_NA;
395}
396
397SR_PRIV const struct beaglelogic_ops beaglelogic_tcp_ops = {
398 .open = beaglelogic_open,
399 .close = beaglelogic_close,
400 .get_buffersize = beaglelogic_get_buffersize,
401 .set_buffersize = beaglelogic_set_buffersize,
402 .get_samplerate = beaglelogic_get_samplerate,
403 .set_samplerate = beaglelogic_set_samplerate,
404 .get_sampleunit = beaglelogic_get_sampleunit,
405 .set_sampleunit = beaglelogic_set_sampleunit,
406 .get_triggerflags = beaglelogic_get_triggerflags,
407 .set_triggerflags = beaglelogic_set_triggerflags,
408 .start = beaglelogic_start,
409 .stop = beaglelogic_stop,
410 .get_lasterror = beaglelogic_get_lasterror,
411 .get_bufunitsize = beaglelogic_get_bufunitsize,
412 .set_bufunitsize = beaglelogic_set_bufunitsize,
413 .mmap = dummy,
414 .munmap = dummy,
415};