]> sigrok.org Git - libsigrok.git/blame - src/scpi/scpi_tcp.c
SCPI: add sr_scpi_write_data()
[libsigrok.git] / src / scpi / scpi_tcp.c
CommitLineData
08a35913
ML
1/*
2 * This file is part of the libsigrok project.
3 *
4 * Copyright (C) 2013 Martin Ling <martin-sigrok@earth.li>
5 *
6 * This program is free software: you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation, either version 3 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program. If not, see <http://www.gnu.org/licenses/>.
18 */
19
6ec6c43b 20#include <config.h>
589edd9b 21#ifdef _WIN32
0f4a4350 22#define _WIN32_WINNT 0x0501
589edd9b
ML
23#include <winsock2.h>
24#include <ws2tcpip.h>
25#endif
08a35913
ML
26#include <glib.h>
27#include <string.h>
28#include <unistd.h>
589edd9b 29#ifndef _WIN32
08a35913
ML
30#include <sys/socket.h>
31#include <netinet/in.h>
32#include <arpa/inet.h>
33#include <netdb.h>
987a0530 34#endif
08a35913 35#include <errno.h>
c1aae900 36#include <libsigrok/libsigrok.h>
515ab088 37#include "libsigrok-internal.h"
5a1afc09 38#include "scpi.h"
08a35913 39
3544f848 40#define LOG_PREFIX "scpi_tcp"
08a35913 41
05c644ea
ML
42#define LENGTH_BYTES 4
43
08a35913
ML
44struct scpi_tcp {
45 char *address;
46 char *port;
47 int socket;
05c644ea
ML
48 char length_buf[LENGTH_BYTES];
49 int length_bytes_read;
50 int response_length;
51 int response_bytes_read;
08a35913
ML
52};
53
17bdda58
AJ
54static int scpi_tcp_dev_inst_new(void *priv, struct drv_context *drvc,
55 const char *resource, char **params, const char *serialcomm)
f754c146
AJ
56{
57 struct scpi_tcp *tcp = priv;
58
17bdda58 59 (void)drvc;
f754c146
AJ
60 (void)resource;
61 (void)serialcomm;
62
63 if (!params || !params[1] || !params[2]) {
64 sr_err("Invalid parameters.");
65 return SR_ERR;
66 }
67
68 tcp->address = g_strdup(params[1]);
d9251a2c
UH
69 tcp->port = g_strdup(params[2]);
70 tcp->socket = -1;
f754c146
AJ
71
72 return SR_OK;
73}
74
04229f7b 75static int scpi_tcp_open(struct sr_scpi_dev_inst *scpi)
08a35913 76{
04229f7b 77 struct scpi_tcp *tcp = scpi->priv;
08a35913
ML
78 struct addrinfo hints;
79 struct addrinfo *results, *res;
80 int err;
81
82 memset(&hints, 0, sizeof(hints));
83 hints.ai_family = AF_UNSPEC;
84 hints.ai_socktype = SOCK_STREAM;
85 hints.ai_protocol = IPPROTO_TCP;
86
87 err = getaddrinfo(tcp->address, tcp->port, &hints, &results);
88
89 if (err) {
6433156c 90 sr_err("Address lookup failed: %s:%s: %s", tcp->address, tcp->port,
08a35913
ML
91 gai_strerror(err));
92 return SR_ERR;
93 }
94
95 for (res = results; res; res = res->ai_next) {
96 if ((tcp->socket = socket(res->ai_family, res->ai_socktype,
97 res->ai_protocol)) < 0)
98 continue;
99 if (connect(tcp->socket, res->ai_addr, res->ai_addrlen) != 0) {
100 close(tcp->socket);
101 tcp->socket = -1;
102 continue;
103 }
104 break;
105 }
106
107 freeaddrinfo(results);
108
109 if (tcp->socket < 0) {
110 sr_err("Failed to connect to %s:%s: %s", tcp->address, tcp->port,
7237e912 111 g_strerror(errno));
08a35913
ML
112 return SR_ERR;
113 }
114
115 return SR_OK;
116}
117
102f1239
BV
118static int scpi_tcp_source_add(struct sr_session *session, void *priv,
119 int events, int timeout, sr_receive_data_callback cb, void *cb_data)
08a35913
ML
120{
121 struct scpi_tcp *tcp = priv;
122
102f1239
BV
123 return sr_session_source_add(session, tcp->socket, events, timeout,
124 cb, cb_data);
08a35913
ML
125}
126
102f1239 127static int scpi_tcp_source_remove(struct sr_session *session, void *priv)
08a35913
ML
128{
129 struct scpi_tcp *tcp = priv;
130
102f1239 131 return sr_session_source_remove(session, tcp->socket);
08a35913
ML
132}
133
d87c1766 134static int scpi_tcp_send(void *priv, const char *command)
08a35913
ML
135{
136 struct scpi_tcp *tcp = priv;
137 int len, out;
138
055804e8
SB
139 len = strlen(command);
140 out = send(tcp->socket, command, len, 0);
08a35913
ML
141
142 if (out < 0) {
7237e912 143 sr_err("Send error: %s", g_strerror(errno));
08a35913
ML
144 return SR_ERR;
145 }
146
147 if (out < len) {
148 sr_dbg("Only sent %d/%d bytes of SCPI command: '%s'.", out,
149 len, command);
150 }
151
152 sr_spew("Successfully sent SCPI command: '%s'.", command);
153
154 return SR_OK;
155}
156
d87c1766 157static int scpi_tcp_read_begin(void *priv)
08a35913
ML
158{
159 struct scpi_tcp *tcp = priv;
08a35913 160
05c644ea
ML
161 tcp->response_bytes_read = 0;
162 tcp->length_bytes_read = 0;
08a35913
ML
163
164 return SR_OK;
165}
166
d87c1766 167static int scpi_tcp_raw_read_data(void *priv, char *buf, int maxlen)
104ed125
AJ
168{
169 struct scpi_tcp *tcp = priv;
170 int len;
171
172 len = recv(tcp->socket, buf, maxlen, 0);
173
174 if (len < 0) {
7237e912 175 sr_err("Receive error: %s", g_strerror(errno));
104ed125
AJ
176 return SR_ERR;
177 }
178
179 tcp->length_bytes_read = LENGTH_BYTES;
180 tcp->response_length = len < maxlen ? len : maxlen + 1;
181 tcp->response_bytes_read = len;
182
183 return len;
184}
185
b6be55ce
SS
186static int scpi_tcp_raw_write_data(void *priv, char *buf, int len)
187{
188 struct scpi_tcp *tcp = priv;
189 int sentlen;
190
191 sentlen = send(tcp->socket, buf, len, 0);
192
193 if (sentlen < 0) {
194 sr_err("Send error: %s.", g_strerror(errno));
195 return SR_ERR;
196 }
197
198 return sentlen;
199}
200
d87c1766 201static int scpi_tcp_rigol_read_data(void *priv, char *buf, int maxlen)
08a35913
ML
202{
203 struct scpi_tcp *tcp = priv;
204 int len;
205
05c644ea
ML
206 if (tcp->length_bytes_read < LENGTH_BYTES) {
207 len = recv(tcp->socket, tcp->length_buf + tcp->length_bytes_read,
208 LENGTH_BYTES - tcp->length_bytes_read, 0);
209 if (len < 0) {
7237e912 210 sr_err("Receive error: %s", g_strerror(errno));
05c644ea
ML
211 return SR_ERR;
212 }
213
214 tcp->length_bytes_read += len;
215
216 if (tcp->length_bytes_read < LENGTH_BYTES)
217 return 0;
218 else
219 tcp->response_length = RL32(tcp->length_buf);
220 }
221
222 if (tcp->response_bytes_read >= tcp->response_length)
223 return SR_ERR;
224
08a35913
ML
225 len = recv(tcp->socket, buf, maxlen, 0);
226
227 if (len < 0) {
7237e912 228 sr_err("Receive error: %s", g_strerror(errno));
08a35913
ML
229 return SR_ERR;
230 }
231
05c644ea
ML
232 tcp->response_bytes_read += len;
233
08a35913
ML
234 return len;
235}
236
d87c1766 237static int scpi_tcp_read_complete(void *priv)
05c644ea
ML
238{
239 struct scpi_tcp *tcp = priv;
240
241 return (tcp->length_bytes_read == LENGTH_BYTES &&
242 tcp->response_bytes_read >= tcp->response_length);
243}
244
04229f7b 245static int scpi_tcp_close(struct sr_scpi_dev_inst *scpi)
08a35913 246{
04229f7b 247 struct scpi_tcp *tcp = scpi->priv;
08a35913
ML
248
249 if (close(tcp->socket) < 0)
250 return SR_ERR;
251
252 return SR_OK;
253}
254
d87c1766 255static void scpi_tcp_free(void *priv)
08a35913
ML
256{
257 struct scpi_tcp *tcp = priv;
258
259 g_free(tcp->address);
260 g_free(tcp->port);
08a35913
ML
261}
262
104ed125
AJ
263SR_PRIV const struct sr_scpi_dev_inst scpi_tcp_raw_dev = {
264 .name = "RAW TCP",
265 .prefix = "tcp-raw",
266 .priv_size = sizeof(struct scpi_tcp),
267 .dev_inst_new = scpi_tcp_dev_inst_new,
268 .open = scpi_tcp_open,
269 .source_add = scpi_tcp_source_add,
270 .source_remove = scpi_tcp_source_remove,
271 .send = scpi_tcp_send,
272 .read_begin = scpi_tcp_read_begin,
273 .read_data = scpi_tcp_raw_read_data,
b6be55ce 274 .write_data = scpi_tcp_raw_write_data,
104ed125
AJ
275 .read_complete = scpi_tcp_read_complete,
276 .close = scpi_tcp_close,
277 .free = scpi_tcp_free,
278};
279
280SR_PRIV const struct sr_scpi_dev_inst scpi_tcp_rigol_dev = {
281 .name = "RIGOL TCP",
282 .prefix = "tcp-rigol",
f754c146
AJ
283 .priv_size = sizeof(struct scpi_tcp),
284 .dev_inst_new = scpi_tcp_dev_inst_new,
285 .open = scpi_tcp_open,
286 .source_add = scpi_tcp_source_add,
287 .source_remove = scpi_tcp_source_remove,
288 .send = scpi_tcp_send,
289 .read_begin = scpi_tcp_read_begin,
104ed125 290 .read_data = scpi_tcp_rigol_read_data,
f754c146
AJ
291 .read_complete = scpi_tcp_read_complete,
292 .close = scpi_tcp_close,
293 .free = scpi_tcp_free,
294};