]> sigrok.org Git - libsigrok.git/blob - src/hardware/beaglelogic/beaglelogic_tcp.c
beaglelogic: Fix mismatched printf specifiers.
[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 adapted from scpi_tcp.c and scpi.c, their
6  * copyright notices are listed below:
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
45 static int beaglelogic_tcp_open(struct dev_context *devc)
46 {
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
87 static int beaglelogic_tcp_send_cmd(struct dev_context *devc,
88                                     const char *format, ...)
89 {
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                 g_free(buf);
111                 return SR_ERR;
112         }
113
114         if (out < (int)strlen(buf)) {
115                 sr_dbg("Only sent %d/%zu bytes of command: '%s'.", out,
116                        strlen(buf), buf);
117         }
118
119         sr_spew("Sent command: '%s'.", buf);
120
121         g_free(buf);
122
123         return SR_OK;
124 }
125
126 static int beaglelogic_tcp_read_data(struct dev_context *devc, char *buf,
127                                      int maxlen)
128 {
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
141 SR_PRIV int beaglelogic_tcp_drain(struct dev_context *devc)
142 {
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);
157                 if (ret > 0)
158                         len += beaglelogic_tcp_read_data(devc, buf, 1024);
159         } while (ret > 0);
160
161         sr_spew("Drained %d bytes of data.", len);
162
163         g_free(buf);
164
165         return SR_OK;
166 }
167
168 static int beaglelogic_tcp_get_string(struct dev_context *devc, const char *cmd,
169                                       char **tcp_resp)
170 {
171         GString *response = g_string_sized_new(1024);
172         int len;
173         gint64 timeout;
174
175         *tcp_resp = NULL;
176         if (cmd) {
177                 if (beaglelogic_tcp_send_cmd(devc, cmd) != SR_OK)
178                         return SR_ERR;
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
190         if (len > 0)
191                 g_string_set_size(response, len);
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);
211
212         return SR_OK;
213 }
214
215 static int beaglelogic_tcp_get_int(struct dev_context *devc,
216                                    const char *cmd, int *response)
217 {
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
235 SR_PRIV int beaglelogic_tcp_detect(struct dev_context *devc)
236 {
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);
247
248         return ret;
249 }
250
251 static int beaglelogic_open(struct dev_context *devc)
252 {
253         return beaglelogic_tcp_open(devc);
254 }
255
256 static int beaglelogic_close(struct dev_context *devc)
257 {
258         if (close(devc->socket) < 0)
259                 return SR_ERR;
260
261         return SR_OK;
262 }
263
264 static int beaglelogic_get_buffersize(struct dev_context *devc)
265 {
266         return beaglelogic_tcp_get_int(devc, "memalloc",
267                 (int *)&devc->buffersize);
268 }
269
270 static int beaglelogic_set_buffersize(struct dev_context *devc)
271 {
272         int ret;
273         char *resp;
274
275         beaglelogic_tcp_send_cmd(devc, "memalloc %" PRIu32, devc->buffersize);
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);
283
284         return ret;
285 }
286
287 static int beaglelogic_get_samplerate(struct dev_context *devc)
288 {
289         int arg, err;
290
291         err = beaglelogic_tcp_get_int(devc, "samplerate", &arg);
292         if (err)
293                 return err;
294
295         devc->cur_samplerate = arg;
296         return SR_OK;
297 }
298
299 static int beaglelogic_set_samplerate(struct dev_context *devc)
300 {
301         int ret;
302         char *resp;
303
304         beaglelogic_tcp_send_cmd(devc, "samplerate %" PRIu32,
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);
313
314         return ret;
315 }
316
317 static int beaglelogic_get_sampleunit(struct dev_context *devc)
318 {
319         return beaglelogic_tcp_get_int(devc, "sampleunit",
320                 (int *)&devc->sampleunit);
321 }
322
323 static int beaglelogic_set_sampleunit(struct dev_context *devc)
324 {
325         int ret;
326         char *resp;
327
328         beaglelogic_tcp_send_cmd(devc, "sampleunit %" PRIu32, devc->sampleunit);
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);
336
337         return ret;
338 }
339
340 static int beaglelogic_get_triggerflags(struct dev_context *devc)
341 {
342         return beaglelogic_tcp_get_int(devc, "triggerflags",
343                 (int *)&devc->triggerflags);
344 }
345
346 static int beaglelogic_set_triggerflags(struct dev_context *devc)
347 {
348         int ret;
349         char *resp;
350
351         beaglelogic_tcp_send_cmd(devc, "triggerflags %" PRIu32, devc->triggerflags);
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);
359
360         return ret;
361 }
362
363 static int beaglelogic_get_lasterror(struct dev_context *devc)
364 {
365         devc->last_error = 0;
366
367         return SR_OK;
368 }
369
370 static int beaglelogic_start(struct dev_context *devc)
371 {
372         beaglelogic_tcp_drain(devc);
373
374         return beaglelogic_tcp_send_cmd(devc, "get");
375 }
376
377 static int beaglelogic_stop(struct dev_context *devc)
378 {
379         return beaglelogic_tcp_send_cmd(devc, "close");
380 }
381
382 static int beaglelogic_get_bufunitsize(struct dev_context *devc)
383 {
384         return beaglelogic_tcp_get_int(devc, "bufunitsize",
385                 (int *)&devc->bufunitsize);
386 }
387
388 static int beaglelogic_set_bufunitsize(struct dev_context *devc)
389 {
390         int ret;
391         char *resp;
392
393         beaglelogic_tcp_send_cmd(devc, "bufunitsize %" PRIu32, devc->bufunitsize);
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);
401
402         return ret;
403 }
404
405 static int dummy(struct dev_context *devc)
406 {
407         (void)devc;
408
409         return SR_ERR_NA;
410 }
411
412 SR_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 };