]> sigrok.org Git - libsigrok.git/blob - hardware/common/scpi_serial.c
scpi_serial: Reimplement to allow scpi_read_complete() to work correctly.
[libsigrok.git] / hardware / common / scpi_serial.c
1 /*
2  * This file is part of the libsigrok project.
3  *
4  * Copyright (C) 2013 poljar (Damir Jelić) <poljarinho@gmail.com>
5  * Copyright (C) 2013 Martin Ling <martin-sigrok@earth.li>
6  *
7  * This program is free software: you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License as published by
9  * the Free Software Foundation, either version 3 of the License, or
10  * (at your option) any later version.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
19  */
20
21 #include "libsigrok.h"
22 #include "libsigrok-internal.h"
23
24 #include <glib.h>
25 #include <string.h>
26
27 #define LOG_PREFIX "scpi_serial"
28
29 #define BUFFER_SIZE 1024
30
31 struct scpi_serial {
32         struct sr_serial_dev_inst *serial;
33         char buffer[BUFFER_SIZE];
34         size_t count;
35         size_t read;
36 };
37
38 static int scpi_serial_dev_inst_new(void *priv, const char *resource,
39                 char **params, const char *serialcomm)
40 {
41         struct scpi_serial *sscpi = priv;
42
43         (void)params;
44
45         if (!(sscpi->serial = sr_serial_dev_inst_new(resource, serialcomm)))
46                 return SR_ERR;
47
48         return SR_OK;
49 }
50
51 static int scpi_serial_open(void *priv)
52 {
53         struct scpi_serial *sscpi = priv;
54         struct sr_serial_dev_inst *serial = sscpi->serial;
55
56         if (serial_open(serial, SERIAL_RDWR | SERIAL_NONBLOCK) != SR_OK)
57                 return SR_ERR;
58
59         if (serial_flush(serial) != SR_OK)
60                 return SR_ERR;
61
62         sscpi->count = 0;
63         sscpi->read = 0;
64
65         return SR_OK;
66 }
67
68 static int scpi_serial_source_add(void *priv, int events, int timeout,
69                         sr_receive_data_callback_t cb, void *cb_data)
70 {
71         struct scpi_serial *sscpi = priv;
72         struct sr_serial_dev_inst *serial = sscpi->serial;
73
74         return serial_source_add(serial, events, timeout, cb, cb_data);
75 }
76
77 static int scpi_serial_source_remove(void *priv)
78 {
79         struct scpi_serial *sscpi = priv;
80         struct sr_serial_dev_inst *serial = sscpi->serial;
81
82         return serial_source_remove(serial);
83 }
84
85 static int scpi_serial_send(void *priv, const char *command)
86 {
87         int len, result, written;
88         gchar *terminated_command;
89         struct scpi_serial *sscpi = priv;
90         struct sr_serial_dev_inst *serial = sscpi->serial;
91
92         terminated_command = g_strconcat(command, "\n", NULL);
93         len = strlen(terminated_command);
94         written = 0;
95         while (written < len) {
96                 result = serial_write(serial, terminated_command + written, len - written);
97                 if (result < 0) {
98                         sr_err("Error while sending SCPI command: '%s'.", command);
99                         g_free(terminated_command);
100                         return SR_ERR;
101                 }
102                 written += result;
103         }
104
105         g_free(terminated_command);
106
107         sr_spew("Successfully sent SCPI command: '%s'.", command);
108
109         return SR_OK;
110 }
111
112 static int scpi_serial_read_begin(void *priv)
113 {
114         (void) priv;
115
116         return SR_OK;
117 }
118
119 static int scpi_serial_read_data(void *priv, char *buf, int maxlen)
120 {
121         struct scpi_serial *sscpi = priv;
122         int len, ret;
123
124         len = BUFFER_SIZE - sscpi->count;
125
126         /* Try to read new data into the buffer if there is space. */
127         if (len > 0) {
128                 ret = serial_read(sscpi->serial, sscpi->buffer + sscpi->read,
129                                 BUFFER_SIZE - sscpi->count);
130
131                 if (ret < 0)
132                         return ret;
133
134                 sscpi->count += ret;
135
136                 if (ret > 0)
137                         sr_spew("Read %d bytes into buffer.", ret);
138         }
139
140         /* Return as many bytes as possible from buffer, excluding any trailing newline. */
141         if (sscpi->read < sscpi->count) {
142                 len = sscpi->count - sscpi->read;
143                 if (len > maxlen)
144                         len = maxlen;
145                 if (sscpi->buffer[sscpi->read + len - 1] == '\n')
146                         len--;
147                 sr_spew("Returning %d bytes from buffer.", len);
148                 memcpy(buf, sscpi->buffer + sscpi->read, len);
149                 sscpi->read += len;
150                 if (sscpi->read == BUFFER_SIZE) {
151                         sr_spew("Resetting buffer.");
152                         sscpi->count = 0;
153                         sscpi->read = 0;
154                 }
155                 return len;
156         }
157
158         return 0;
159 }
160
161 static int scpi_serial_read_complete(void *priv)
162 {
163         struct scpi_serial *sscpi = priv;
164
165         /* If the next character is a newline, discard it and report complete. */
166         if (sscpi->read < sscpi->count && sscpi->buffer[sscpi->read] == '\n') {
167                 sscpi->read++;
168                 return 1;
169         } else {
170                 return 0;
171         }
172 }
173
174 static int scpi_serial_close(void *priv)
175 {
176         struct scpi_serial *sscpi = priv;
177
178         return serial_close(sscpi->serial);
179 }
180
181 static void scpi_serial_free(void *priv)
182 {
183         struct scpi_serial *sscpi = priv;
184
185         sr_serial_dev_inst_free(sscpi->serial);
186 }
187
188 SR_PRIV const struct sr_scpi_dev_inst scpi_serial_dev = {
189         .name          = "serial",
190         .prefix        = "",
191         .priv_size     = sizeof(struct scpi_serial),
192         .dev_inst_new  = scpi_serial_dev_inst_new,
193         .open          = scpi_serial_open,
194         .source_add    = scpi_serial_source_add,
195         .source_remove = scpi_serial_source_remove,
196         .send          = scpi_serial_send,
197         .read_begin    = scpi_serial_read_begin,
198         .read_data     = scpi_serial_read_data,
199         .read_complete = scpi_serial_read_complete,
200         .close         = scpi_serial_close,
201         .free          = scpi_serial_free,
202 };