]> sigrok.org Git - libsigrok.git/blame - src/hardware/beaglelogic/beaglelogic_tcp.c
beaglelogic: Update copyright notices in all files
[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
45static int beaglelogic_tcp_open(struct dev_context *devc) {
46 struct addrinfo hints;
47 struct addrinfo *results, *res;
48 int err;
49
50 memset(&hints, 0, sizeof(hints));
51 hints.ai_family = AF_UNSPEC;
52 hints.ai_socktype = SOCK_STREAM;
53 hints.ai_protocol = IPPROTO_TCP;
54
55 err = getaddrinfo(devc->address, devc->port, &hints, &results);
56
57 if (err) {
58 sr_err("Address lookup failed: %s:%s: %s", devc->address,
59 devc->port, gai_strerror(err));
60 return SR_ERR;
61 }
62
63 for (res = results; res; res = res->ai_next) {
64 if ((devc->socket = socket(res->ai_family, res->ai_socktype,
65 res->ai_protocol)) < 0)
66 continue;
67 if (connect(devc->socket, res->ai_addr, res->ai_addrlen) != 0) {
68 close(devc->socket);
69 devc->socket = -1;
70 continue;
71 }
72 break;
73 }
74
75 freeaddrinfo(results);
76
77 if (devc->socket < 0) {
78 sr_err("Failed to connect to %s:%s: %s", devc->address,
79 devc->port, g_strerror(errno));
80 return SR_ERR;
81 }
82
83 return SR_OK;
84}
85
86static int beaglelogic_tcp_send_cmd(struct dev_context *devc,
87 const char *format, ...) {
88 int len, out;
89 va_list args, args_copy;
90 char *buf;
91
92 va_start(args, format);
93 va_copy(args_copy, args);
94 len = vsnprintf(NULL, 0, format, args_copy);
95 va_end(args_copy);
96
97 buf = g_malloc0(len + 2);
98 vsprintf(buf, format, args);
99 va_end(args);
100
101 if (buf[len - 1] != '\n')
102 buf[len] = '\n';
103
104 out = send(devc->socket, buf, strlen(buf), 0);
105
106 if (out < 0) {
107 sr_err("Send error: %s", g_strerror(errno));
108 return SR_ERR;
109 }
110
111 if (out < (int)strlen(buf)) {
f154b40d 112 sr_dbg("Only sent %d/%lu bytes of command: '%s'.", out,
9b2b3ef9
KA
113 strlen(buf), buf);
114 }
115
116 sr_spew("Sent command: '%s'.", buf);
117 g_free(buf);
118
119 return SR_OK;
120}
121
122static int beaglelogic_tcp_read_data(struct dev_context *devc, char *buf,
123 int maxlen) {
124 int len;
125
126 len = recv(devc->socket, buf, maxlen, 0);
127
128 if (len < 0) {
129 sr_err("Receive error: %s", g_strerror(errno));
130 return SR_ERR;
131 }
132
133 return len;
134}
135
f7d7ee82
KA
136SR_PRIV int beaglelogic_tcp_drain(struct dev_context *devc) {
137 char *buf = g_malloc(1024);
138 fd_set rset;
139 int ret, len = 0;
140 struct timeval tv;
141
142 FD_ZERO(&rset);
143 FD_SET(devc->socket, &rset);
144
145 /* 25ms timeout */
146 tv.tv_sec = 0;
147 tv.tv_usec = 25 * 1000;
148
149 do {
150 ret = select(devc->socket + 1, &rset, NULL, NULL, &tv);
151 if (ret > 0) {
152 len += beaglelogic_tcp_read_data(devc, buf, 1024);
153 }
154 } while (ret > 0);
155
156 sr_spew("Drained %d bytes of data.", len);
157
158 g_free(buf);
159 return SR_OK;
160}
161
9b2b3ef9
KA
162static int beaglelogic_tcp_get_string(struct dev_context *devc, const char *cmd,
163 char **tcp_resp) {
164 GString *response = g_string_sized_new(1024);
165 int len;
166 gint64 timeout;
167
168 if (cmd) {
169 if (beaglelogic_tcp_send_cmd(devc, cmd) != SR_OK) {
170 return SR_ERR;
171 }
172 }
173
174 timeout = g_get_monotonic_time() + devc->read_timeout;
175 len = beaglelogic_tcp_read_data(devc, response->str,
176 response->allocated_len);
177
178 if (len < 0) {
179 g_string_free(response, TRUE);
180 return SR_ERR;
181 }
182
183 if (len > 0) {
184 g_string_set_size(response, len);
185 }
186
187 if (g_get_monotonic_time() > timeout) {
188 sr_err("Timed out waiting for response.");
189 g_string_free(response, TRUE);
190 return SR_ERR_TIMEOUT;
191 }
192
193 /* Remove trailing newline if present */
194 if (response->len >= 1 && response->str[response->len - 1] == '\n')
195 g_string_truncate(response, response->len - 1);
196
197 /* Remove trailing carriage return if present */
198 if (response->len >= 1 && response->str[response->len - 1] == '\r')
199 g_string_truncate(response, response->len - 1);
200
201 sr_spew("Got response: '%.70s', length %" G_GSIZE_FORMAT ".",
202 response->str, response->len);
203
204 *tcp_resp = g_string_free(response, FALSE);
205 return SR_OK;
206}
207
208static int beaglelogic_tcp_get_int(struct dev_context *devc,
209 const char *cmd, int *response) {
210 int ret;
211 char *resp = NULL;
212
213 ret = beaglelogic_tcp_get_string(devc, cmd, &resp);
214 if (!resp && ret != SR_OK)
215 return ret;
216
217 if (sr_atoi(resp, response) == SR_OK)
218 ret = SR_OK;
219 else
220 ret = SR_ERR_DATA;
221
222 g_free(resp);
223
224 return ret;
225}
226
227SR_PRIV int beaglelogic_tcp_detect(struct dev_context *devc) {
228 char *resp = NULL;
229 int ret;
230
231 ret = beaglelogic_tcp_get_string(devc, "version", &resp);
232 if (ret == SR_OK && !g_ascii_strncasecmp(resp, "BeagleLogic", 11))
233 ret = SR_OK;
234 else
235 ret = SR_ERR;
236
237 g_free(resp);
238 return ret;
239}
240
241static int beaglelogic_open(struct dev_context *devc) {
242 return beaglelogic_tcp_open(devc);
243}
244
245static int beaglelogic_close(struct dev_context *devc) {
9b2b3ef9
KA
246 if (close(devc->socket) < 0)
247 return SR_ERR;
248
249 return SR_OK;
250}
251
252static int beaglelogic_get_buffersize(struct dev_context *devc) {
253 return beaglelogic_tcp_get_int(devc, "memalloc",
254 (int *)&devc->buffersize);
255}
256
257static int beaglelogic_set_buffersize(struct dev_context *devc) {
258 int ret;
259 char *resp;
260
261 beaglelogic_tcp_send_cmd(devc, "memalloc %lu", devc->buffersize);
262 ret = beaglelogic_tcp_get_string(devc, NULL, &resp);
263 if (ret == SR_OK && !g_ascii_strncasecmp(resp, "ok", 2))
264 ret = SR_OK;
265 else
266 ret = SR_ERR;
267
268 g_free(resp);
269 return ret;
270}
271
272static int beaglelogic_get_samplerate(struct dev_context *devc) {
273 int arg, err;
274 err = beaglelogic_tcp_get_int(devc, "samplerate", &arg);
275 devc->cur_samplerate = arg;
276 return err;
277}
278
279static int beaglelogic_set_samplerate(struct dev_context *devc) {
280 int ret;
281 char *resp;
282
283 beaglelogic_tcp_send_cmd(devc, "samplerate %lu",
284 (uint32_t)devc->cur_samplerate);
285 ret = beaglelogic_tcp_get_string(devc, NULL, &resp);
286 if (ret == SR_OK && !g_ascii_strncasecmp(resp, "ok", 2))
287 ret = SR_OK;
288 else
289 ret = SR_ERR;
290
291 g_free(resp);
292 return ret;
293}
294
295static int beaglelogic_get_sampleunit(struct dev_context *devc) {
296 return beaglelogic_tcp_get_int(devc, "sampleunit",
297 (int *)&devc->sampleunit);
298}
299
300static int beaglelogic_set_sampleunit(struct dev_context *devc) {
301 int ret;
302 char *resp;
303
304 beaglelogic_tcp_send_cmd(devc, "sampleunit %lu", devc->sampleunit);
305 ret = beaglelogic_tcp_get_string(devc, NULL, &resp);
306 if (ret == SR_OK && !g_ascii_strncasecmp(resp, "ok", 2))
307 ret = SR_OK;
308 else
309 ret = SR_ERR;
310
311 g_free(resp);
312 return ret;
313}
314
315static int beaglelogic_get_triggerflags(struct dev_context *devc) {
316 return beaglelogic_tcp_get_int(devc, "triggerflags",
317 (int *)&devc->triggerflags);
318}
319
320static int beaglelogic_set_triggerflags(struct dev_context *devc) {
321 int ret;
322 char *resp;
323
324 beaglelogic_tcp_send_cmd(devc, "triggerflags %lu", devc->triggerflags);
325 ret = beaglelogic_tcp_get_string(devc, NULL, &resp);
326 if (ret == SR_OK && !g_ascii_strncasecmp(resp, "ok", 2))
327 ret = SR_OK;
328 else
329 ret = SR_ERR;
330
331 g_free(resp);
332 return ret;
333}
334
335static int beaglelogic_get_lasterror(struct dev_context *devc) {
336 devc->last_error = 0;
337 return SR_OK;
338}
339
340static int beaglelogic_start(struct dev_context *devc) {
f7d7ee82 341 beaglelogic_tcp_drain(devc);
9b2b3ef9
KA
342 return beaglelogic_tcp_send_cmd(devc, "get");
343}
344
345static int beaglelogic_stop(struct dev_context *devc) {
346 return beaglelogic_tcp_send_cmd(devc, "close");
347}
348
349static int beaglelogic_get_bufunitsize(struct dev_context *devc) {
350 return beaglelogic_tcp_get_int(devc, "bufunitsize",
351 (int *)&devc->bufunitsize);
352}
353
354static int beaglelogic_set_bufunitsize(struct dev_context *devc) {
355 int ret;
356 char *resp;
357
358 beaglelogic_tcp_send_cmd(devc, "bufunitsize %ld", devc->bufunitsize);
359 ret = beaglelogic_tcp_get_string(devc, NULL, &resp);
360 if (ret == SR_OK && !g_ascii_strncasecmp(resp, "ok", 2))
361 ret = SR_OK;
362 else
363 ret = SR_ERR;
364
365 g_free(resp);
366 return ret;
367}
368
369static int dummy(struct dev_context *devc) {
f154b40d 370 (void)devc;
9b2b3ef9
KA
371 return SR_ERR_NA;
372}
373
374SR_PRIV const struct beaglelogic_ops beaglelogic_tcp_ops = {
375 .open = beaglelogic_open,
376 .close = beaglelogic_close,
377 .get_buffersize = beaglelogic_get_buffersize,
378 .set_buffersize = beaglelogic_set_buffersize,
379 .get_samplerate = beaglelogic_get_samplerate,
380 .set_samplerate = beaglelogic_set_samplerate,
381 .get_sampleunit = beaglelogic_get_sampleunit,
382 .set_sampleunit = beaglelogic_set_sampleunit,
383 .get_triggerflags = beaglelogic_get_triggerflags,
384 .set_triggerflags = beaglelogic_set_triggerflags,
385 .start = beaglelogic_start,
386 .stop = beaglelogic_stop,
387 .get_lasterror = beaglelogic_get_lasterror,
388 .get_bufunitsize = beaglelogic_get_bufunitsize,
389 .set_bufunitsize = beaglelogic_set_bufunitsize,
390 .mmap = dummy,
391 .munmap = dummy,
392};