2 * This file is part of the libsigrok project.
4 * Copyright (C) 2017 Kumar Abhishek <abhishek@theembeddedkitchen.net>
5 * Portions of the code are adopted from scpi_tcp.c and scpi.c
7 * Copyright (C) 2013 Martin Ling <martin-sigrok@earth.li>
8 * Copyright (C) 2013 poljar (Damir Jelić) <poljarinho@gmail.com>
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.
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.
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/>.
26 #define _WIN32_WINNT 0x0501
34 #include <sys/socket.h>
35 #include <netinet/in.h>
36 #include <arpa/inet.h>
42 #include "beaglelogic.h"
44 static int beaglelogic_tcp_open(struct dev_context *devc) {
45 struct addrinfo hints;
46 struct addrinfo *results, *res;
49 memset(&hints, 0, sizeof(hints));
50 hints.ai_family = AF_UNSPEC;
51 hints.ai_socktype = SOCK_STREAM;
52 hints.ai_protocol = IPPROTO_TCP;
54 err = getaddrinfo(devc->address, devc->port, &hints, &results);
57 sr_err("Address lookup failed: %s:%s: %s", devc->address,
58 devc->port, gai_strerror(err));
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)
66 if (connect(devc->socket, res->ai_addr, res->ai_addrlen) != 0) {
74 freeaddrinfo(results);
76 if (devc->socket < 0) {
77 sr_err("Failed to connect to %s:%s: %s", devc->address,
78 devc->port, g_strerror(errno));
85 static int beaglelogic_tcp_send_cmd(struct dev_context *devc,
86 const char *format, ...) {
88 va_list args, args_copy;
91 va_start(args, format);
92 va_copy(args_copy, args);
93 len = vsnprintf(NULL, 0, format, args_copy);
96 buf = g_malloc0(len + 2);
97 vsprintf(buf, format, args);
100 if (buf[len - 1] != '\n')
103 out = send(devc->socket, buf, strlen(buf), 0);
106 sr_err("Send error: %s", g_strerror(errno));
110 if (out < (int)strlen(buf)) {
111 sr_dbg("Only sent %d/%lu bytes of command: '%s'.", out,
115 sr_spew("Sent command: '%s'.", buf);
121 static int beaglelogic_tcp_read_data(struct dev_context *devc, char *buf,
125 len = recv(devc->socket, buf, maxlen, 0);
128 sr_err("Receive error: %s", g_strerror(errno));
135 SR_PRIV int beaglelogic_tcp_drain(struct dev_context *devc) {
136 char *buf = g_malloc(1024);
142 FD_SET(devc->socket, &rset);
146 tv.tv_usec = 25 * 1000;
149 ret = select(devc->socket + 1, &rset, NULL, NULL, &tv);
151 len += beaglelogic_tcp_read_data(devc, buf, 1024);
155 sr_spew("Drained %d bytes of data.", len);
161 static int beaglelogic_tcp_get_string(struct dev_context *devc, const char *cmd,
163 GString *response = g_string_sized_new(1024);
168 if (beaglelogic_tcp_send_cmd(devc, cmd) != SR_OK) {
173 timeout = g_get_monotonic_time() + devc->read_timeout;
174 len = beaglelogic_tcp_read_data(devc, response->str,
175 response->allocated_len);
178 g_string_free(response, TRUE);
183 g_string_set_size(response, len);
186 if (g_get_monotonic_time() > timeout) {
187 sr_err("Timed out waiting for response.");
188 g_string_free(response, TRUE);
189 return SR_ERR_TIMEOUT;
192 /* Remove trailing newline if present */
193 if (response->len >= 1 && response->str[response->len - 1] == '\n')
194 g_string_truncate(response, response->len - 1);
196 /* Remove trailing carriage return if present */
197 if (response->len >= 1 && response->str[response->len - 1] == '\r')
198 g_string_truncate(response, response->len - 1);
200 sr_spew("Got response: '%.70s', length %" G_GSIZE_FORMAT ".",
201 response->str, response->len);
203 *tcp_resp = g_string_free(response, FALSE);
207 static int beaglelogic_tcp_get_int(struct dev_context *devc,
208 const char *cmd, int *response) {
212 ret = beaglelogic_tcp_get_string(devc, cmd, &resp);
213 if (!resp && ret != SR_OK)
216 if (sr_atoi(resp, response) == SR_OK)
226 SR_PRIV int beaglelogic_tcp_detect(struct dev_context *devc) {
230 ret = beaglelogic_tcp_get_string(devc, "version", &resp);
231 if (ret == SR_OK && !g_ascii_strncasecmp(resp, "BeagleLogic", 11))
240 static int beaglelogic_open(struct dev_context *devc) {
241 return beaglelogic_tcp_open(devc);
244 static int beaglelogic_close(struct dev_context *devc) {
245 if (close(devc->socket) < 0)
251 static int beaglelogic_get_buffersize(struct dev_context *devc) {
252 return beaglelogic_tcp_get_int(devc, "memalloc",
253 (int *)&devc->buffersize);
256 static int beaglelogic_set_buffersize(struct dev_context *devc) {
260 beaglelogic_tcp_send_cmd(devc, "memalloc %lu", devc->buffersize);
261 ret = beaglelogic_tcp_get_string(devc, NULL, &resp);
262 if (ret == SR_OK && !g_ascii_strncasecmp(resp, "ok", 2))
271 static int beaglelogic_get_samplerate(struct dev_context *devc) {
273 err = beaglelogic_tcp_get_int(devc, "samplerate", &arg);
274 devc->cur_samplerate = arg;
278 static int beaglelogic_set_samplerate(struct dev_context *devc) {
282 beaglelogic_tcp_send_cmd(devc, "samplerate %lu",
283 (uint32_t)devc->cur_samplerate);
284 ret = beaglelogic_tcp_get_string(devc, NULL, &resp);
285 if (ret == SR_OK && !g_ascii_strncasecmp(resp, "ok", 2))
294 static int beaglelogic_get_sampleunit(struct dev_context *devc) {
295 return beaglelogic_tcp_get_int(devc, "sampleunit",
296 (int *)&devc->sampleunit);
299 static int beaglelogic_set_sampleunit(struct dev_context *devc) {
303 beaglelogic_tcp_send_cmd(devc, "sampleunit %lu", devc->sampleunit);
304 ret = beaglelogic_tcp_get_string(devc, NULL, &resp);
305 if (ret == SR_OK && !g_ascii_strncasecmp(resp, "ok", 2))
314 static int beaglelogic_get_triggerflags(struct dev_context *devc) {
315 return beaglelogic_tcp_get_int(devc, "triggerflags",
316 (int *)&devc->triggerflags);
319 static int beaglelogic_set_triggerflags(struct dev_context *devc) {
323 beaglelogic_tcp_send_cmd(devc, "triggerflags %lu", devc->triggerflags);
324 ret = beaglelogic_tcp_get_string(devc, NULL, &resp);
325 if (ret == SR_OK && !g_ascii_strncasecmp(resp, "ok", 2))
334 static int beaglelogic_get_lasterror(struct dev_context *devc) {
335 devc->last_error = 0;
339 static int beaglelogic_start(struct dev_context *devc) {
340 beaglelogic_tcp_drain(devc);
341 return beaglelogic_tcp_send_cmd(devc, "get");
344 static int beaglelogic_stop(struct dev_context *devc) {
345 return beaglelogic_tcp_send_cmd(devc, "close");
348 static int beaglelogic_get_bufunitsize(struct dev_context *devc) {
349 return beaglelogic_tcp_get_int(devc, "bufunitsize",
350 (int *)&devc->bufunitsize);
353 static int beaglelogic_set_bufunitsize(struct dev_context *devc) {
357 beaglelogic_tcp_send_cmd(devc, "bufunitsize %ld", devc->bufunitsize);
358 ret = beaglelogic_tcp_get_string(devc, NULL, &resp);
359 if (ret == SR_OK && !g_ascii_strncasecmp(resp, "ok", 2))
368 static int dummy(struct dev_context *devc) {
373 SR_PRIV const struct beaglelogic_ops beaglelogic_tcp_ops = {
374 .open = beaglelogic_open,
375 .close = beaglelogic_close,
376 .get_buffersize = beaglelogic_get_buffersize,
377 .set_buffersize = beaglelogic_set_buffersize,
378 .get_samplerate = beaglelogic_get_samplerate,
379 .set_samplerate = beaglelogic_set_samplerate,
380 .get_sampleunit = beaglelogic_get_sampleunit,
381 .set_sampleunit = beaglelogic_set_sampleunit,
382 .get_triggerflags = beaglelogic_get_triggerflags,
383 .set_triggerflags = beaglelogic_set_triggerflags,
384 .start = beaglelogic_start,
385 .stop = beaglelogic_stop,
386 .get_lasterror = beaglelogic_get_lasterror,
387 .get_bufunitsize = beaglelogic_get_bufunitsize,
388 .set_bufunitsize = beaglelogic_set_bufunitsize,