]> sigrok.org Git - libsigrok.git/blame - src/hardware/beaglelogic/beaglelogic_tcp.c
beaglelogic: Implement TCP protocol
[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>
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
44static 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
85static 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
121static 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
135static int beaglelogic_tcp_get_string(struct dev_context *devc, const char *cmd,
136 char **tcp_resp) {
137 GString *response = g_string_sized_new(1024);
138 int len;
139 gint64 timeout;
140
141 if (cmd) {
142 if (beaglelogic_tcp_send_cmd(devc, cmd) != SR_OK) {
143 return SR_ERR;
144 }
145 }
146
147 timeout = g_get_monotonic_time() + devc->read_timeout;
148 len = beaglelogic_tcp_read_data(devc, response->str,
149 response->allocated_len);
150
151 if (len < 0) {
152 g_string_free(response, TRUE);
153 return SR_ERR;
154 }
155
156 if (len > 0) {
157 g_string_set_size(response, len);
158 }
159
160 if (g_get_monotonic_time() > timeout) {
161 sr_err("Timed out waiting for response.");
162 g_string_free(response, TRUE);
163 return SR_ERR_TIMEOUT;
164 }
165
166 /* Remove trailing newline if present */
167 if (response->len >= 1 && response->str[response->len - 1] == '\n')
168 g_string_truncate(response, response->len - 1);
169
170 /* Remove trailing carriage return if present */
171 if (response->len >= 1 && response->str[response->len - 1] == '\r')
172 g_string_truncate(response, response->len - 1);
173
174 sr_spew("Got response: '%.70s', length %" G_GSIZE_FORMAT ".",
175 response->str, response->len);
176
177 *tcp_resp = g_string_free(response, FALSE);
178 return SR_OK;
179}
180
181static int beaglelogic_tcp_get_int(struct dev_context *devc,
182 const char *cmd, int *response) {
183 int ret;
184 char *resp = NULL;
185
186 ret = beaglelogic_tcp_get_string(devc, cmd, &resp);
187 if (!resp && ret != SR_OK)
188 return ret;
189
190 if (sr_atoi(resp, response) == SR_OK)
191 ret = SR_OK;
192 else
193 ret = SR_ERR_DATA;
194
195 g_free(resp);
196
197 return ret;
198}
199
200SR_PRIV int beaglelogic_tcp_detect(struct dev_context *devc) {
201 char *resp = NULL;
202 int ret;
203
204 ret = beaglelogic_tcp_get_string(devc, "version", &resp);
205 if (ret == SR_OK && !g_ascii_strncasecmp(resp, "BeagleLogic", 11))
206 ret = SR_OK;
207 else
208 ret = SR_ERR;
209
210 g_free(resp);
211 return ret;
212}
213
214static int beaglelogic_open(struct dev_context *devc) {
215 return beaglelogic_tcp_open(devc);
216}
217
218static int beaglelogic_close(struct dev_context *devc) {
219 g_free(devc->address);
220 g_free(devc->port);
221
222 if (close(devc->socket) < 0)
223 return SR_ERR;
224
225 return SR_OK;
226}
227
228static int beaglelogic_get_buffersize(struct dev_context *devc) {
229 return beaglelogic_tcp_get_int(devc, "memalloc",
230 (int *)&devc->buffersize);
231}
232
233static int beaglelogic_set_buffersize(struct dev_context *devc) {
234 int ret;
235 char *resp;
236
237 beaglelogic_tcp_send_cmd(devc, "memalloc %lu", devc->buffersize);
238 ret = beaglelogic_tcp_get_string(devc, NULL, &resp);
239 if (ret == SR_OK && !g_ascii_strncasecmp(resp, "ok", 2))
240 ret = SR_OK;
241 else
242 ret = SR_ERR;
243
244 g_free(resp);
245 return ret;
246}
247
248static int beaglelogic_get_samplerate(struct dev_context *devc) {
249 int arg, err;
250 err = beaglelogic_tcp_get_int(devc, "samplerate", &arg);
251 devc->cur_samplerate = arg;
252 return err;
253}
254
255static int beaglelogic_set_samplerate(struct dev_context *devc) {
256 int ret;
257 char *resp;
258
259 beaglelogic_tcp_send_cmd(devc, "samplerate %lu",
260 (uint32_t)devc->cur_samplerate);
261 ret = beaglelogic_tcp_get_string(devc, NULL, &resp);
262 if (ret == SR_OK && !g_ascii_strncasecmp(resp, "ok", 2))
263 ret = SR_OK;
264 else
265 ret = SR_ERR;
266
267 g_free(resp);
268 return ret;
269}
270
271static int beaglelogic_get_sampleunit(struct dev_context *devc) {
272 return beaglelogic_tcp_get_int(devc, "sampleunit",
273 (int *)&devc->sampleunit);
274}
275
276static int beaglelogic_set_sampleunit(struct dev_context *devc) {
277 int ret;
278 char *resp;
279
280 beaglelogic_tcp_send_cmd(devc, "sampleunit %lu", devc->sampleunit);
281 ret = beaglelogic_tcp_get_string(devc, NULL, &resp);
282 if (ret == SR_OK && !g_ascii_strncasecmp(resp, "ok", 2))
283 ret = SR_OK;
284 else
285 ret = SR_ERR;
286
287 g_free(resp);
288 return ret;
289}
290
291static int beaglelogic_get_triggerflags(struct dev_context *devc) {
292 return beaglelogic_tcp_get_int(devc, "triggerflags",
293 (int *)&devc->triggerflags);
294}
295
296static int beaglelogic_set_triggerflags(struct dev_context *devc) {
297 int ret;
298 char *resp;
299
300 beaglelogic_tcp_send_cmd(devc, "triggerflags %lu", devc->triggerflags);
301 ret = beaglelogic_tcp_get_string(devc, NULL, &resp);
302 if (ret == SR_OK && !g_ascii_strncasecmp(resp, "ok", 2))
303 ret = SR_OK;
304 else
305 ret = SR_ERR;
306
307 g_free(resp);
308 return ret;
309}
310
311static int beaglelogic_get_lasterror(struct dev_context *devc) {
312 devc->last_error = 0;
313 return SR_OK;
314}
315
316static int beaglelogic_start(struct dev_context *devc) {
317 return beaglelogic_tcp_send_cmd(devc, "get");
318}
319
320static int beaglelogic_stop(struct dev_context *devc) {
321 return beaglelogic_tcp_send_cmd(devc, "close");
322}
323
324static int beaglelogic_get_bufunitsize(struct dev_context *devc) {
325 return beaglelogic_tcp_get_int(devc, "bufunitsize",
326 (int *)&devc->bufunitsize);
327}
328
329static int beaglelogic_set_bufunitsize(struct dev_context *devc) {
330 int ret;
331 char *resp;
332
333 beaglelogic_tcp_send_cmd(devc, "bufunitsize %ld", devc->bufunitsize);
334 ret = beaglelogic_tcp_get_string(devc, NULL, &resp);
335 if (ret == SR_OK && !g_ascii_strncasecmp(resp, "ok", 2))
336 ret = SR_OK;
337 else
338 ret = SR_ERR;
339
340 g_free(resp);
341 return ret;
342}
343
344static int dummy(struct dev_context *devc) {
345 (devc);
346 return SR_ERR_NA;
347}
348
349SR_PRIV const struct beaglelogic_ops beaglelogic_tcp_ops = {
350 .open = beaglelogic_open,
351 .close = beaglelogic_close,
352 .get_buffersize = beaglelogic_get_buffersize,
353 .set_buffersize = beaglelogic_set_buffersize,
354 .get_samplerate = beaglelogic_get_samplerate,
355 .set_samplerate = beaglelogic_set_samplerate,
356 .get_sampleunit = beaglelogic_get_sampleunit,
357 .set_sampleunit = beaglelogic_set_sampleunit,
358 .get_triggerflags = beaglelogic_get_triggerflags,
359 .set_triggerflags = beaglelogic_set_triggerflags,
360 .start = beaglelogic_start,
361 .stop = beaglelogic_stop,
362 .get_lasterror = beaglelogic_get_lasterror,
363 .get_bufunitsize = beaglelogic_get_bufunitsize,
364 .set_bufunitsize = beaglelogic_set_bufunitsize,
365 .mmap = dummy,
366 .munmap = dummy,
367};