]> sigrok.org Git - libsigrok.git/blob - src/hardware/beaglelogic/beaglelogic_tcp.c
beaglelogic: Update copyright notices in all files
[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         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
86 static 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)) {
112                 sr_dbg("Only sent %d/%lu bytes of command: '%s'.", out,
113                        strlen(buf), buf);
114         }
115
116         sr_spew("Sent command: '%s'.", buf);
117         g_free(buf);
118
119         return SR_OK;
120 }
121
122 static 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
136 SR_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
162 static 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
208 static 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
227 SR_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
241 static int beaglelogic_open(struct dev_context *devc) {
242         return beaglelogic_tcp_open(devc);
243 }
244
245 static int beaglelogic_close(struct dev_context *devc) {
246         if (close(devc->socket) < 0)
247                 return SR_ERR;
248
249         return SR_OK;
250 }
251
252 static int beaglelogic_get_buffersize(struct dev_context *devc) {
253         return beaglelogic_tcp_get_int(devc, "memalloc",
254                 (int *)&devc->buffersize);
255 }
256
257 static 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
272 static 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
279 static 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
295 static int beaglelogic_get_sampleunit(struct dev_context *devc) {
296         return beaglelogic_tcp_get_int(devc, "sampleunit",
297                 (int *)&devc->sampleunit);
298 }
299
300 static 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
315 static int beaglelogic_get_triggerflags(struct dev_context *devc) {
316         return beaglelogic_tcp_get_int(devc, "triggerflags",
317                 (int *)&devc->triggerflags);
318 }
319
320 static 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
335 static int beaglelogic_get_lasterror(struct dev_context *devc) {
336         devc->last_error = 0;
337         return SR_OK;
338 }
339
340 static int beaglelogic_start(struct dev_context *devc) {
341         beaglelogic_tcp_drain(devc);
342         return beaglelogic_tcp_send_cmd(devc, "get");
343 }
344
345 static int beaglelogic_stop(struct dev_context *devc) {
346         return beaglelogic_tcp_send_cmd(devc, "close");
347 }
348
349 static int beaglelogic_get_bufunitsize(struct dev_context *devc) {
350         return beaglelogic_tcp_get_int(devc, "bufunitsize",
351                 (int *)&devc->bufunitsize);
352 }
353
354 static 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
369 static int dummy(struct dev_context *devc) {
370         (void)devc;
371         return SR_ERR_NA;
372 }
373
374 SR_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 };