]> sigrok.org Git - libsigrok.git/blob - src/hardware/ipdbg-logic-analyser/api.c
f48caf6ab4e4cf60404fd56a1a51633714628245
[libsigrok.git] / src / hardware / ipdbg-logic-analyser / api.c
1 /*
2  * This file is part of the libsigrok project.
3  *
4  * Copyright (C) 2016 danselmi <da@da>
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
20 #include <config.h>
21 #include "protocol.h"
22
23 static const uint32_t ipdbg_org_la_drvopts[] = {
24         SR_CONF_LOGIC_ANALYZER,
25 };
26
27 static const uint32_t ipdbg_org_la_scanopts[] = {
28         SR_CONF_CONN,
29         SR_CONF_SERIALCOMM,
30 };
31
32 static const uint32_t ipdbg_org_la_devopts[] = {
33         SR_CONF_TRIGGER_MATCH | SR_CONF_LIST | SR_CONF_SET,
34         SR_CONF_CAPTURE_RATIO | SR_CONF_GET | SR_CONF_SET,
35         SR_CONF_LIMIT_SAMPLES | SR_CONF_GET
36 };
37
38 static const int32_t ipdbg_org_la_trigger_matches[] = {
39         SR_TRIGGER_ZERO,
40         SR_TRIGGER_ONE,
41         SR_TRIGGER_RISING,
42         SR_TRIGGER_FALLING,
43         SR_TRIGGER_EDGE,
44 };
45
46 SR_PRIV struct sr_dev_driver ipdbg_la_driver_info;
47
48 static void ipdbg_org_la_split_addr_port(const char *conn, char **addr,
49         char **port)
50 {
51         char **strs = g_strsplit(conn, "/", 3);
52
53         *addr = g_strdup(strs[1]);
54         *port = g_strdup(strs[2]);
55
56         g_strfreev(strs);
57 }
58
59 static GSList *scan(struct sr_dev_driver *di, GSList *options)
60 {
61         struct drv_context *drvc;
62         GSList *devices;
63
64         devices = NULL;
65         drvc = di->context;
66         drvc->instances = NULL;
67         const char *conn;
68         struct sr_config *src;
69         GSList *l;
70
71         conn = NULL;
72         for (l = options; l; l = l->next) {
73                 src = l->data;
74                 switch (src->key) {
75                 case SR_CONF_CONN:
76                         conn = g_variant_get_string(src->data, NULL);
77                         break;
78                 }
79         }
80
81         if (!conn)
82                 return NULL;
83
84         struct ipdbg_org_la_tcp *tcp = ipdbg_org_la_tcp_new();
85
86         ipdbg_org_la_split_addr_port(conn, &tcp->address, &tcp->port);
87
88         if (!tcp->address)
89                 return NULL;
90
91         if (ipdbg_org_la_tcp_open(tcp) != SR_OK)
92                 return NULL;
93
94         ipdbg_org_la_send_reset(tcp);
95         ipdbg_org_la_send_reset(tcp);
96         ipdbg_org_la_request_id(tcp);
97
98         struct sr_dev_inst *sdi = g_malloc0(sizeof(struct sr_dev_inst));
99         if (!sdi) {
100                 sr_err("no possible to allocate sr_dev_inst");
101                 return NULL;
102         }
103
104         sdi->status = SR_ST_INACTIVE;
105         sdi->vendor = g_strdup("ipdbg.org");
106         sdi->model = g_strdup("Logic Analyzer");
107         sdi->version = g_strdup("v1.0");
108         sdi->driver = di;
109
110         struct ipdbg_org_la_dev_context *devc = ipdbg_org_la_dev_new();
111         sdi->priv = devc;
112
113         ipdbg_org_la_get_addrwidth_and_datawidth(tcp, devc);
114
115         sr_dbg("addr_width = %d, data_width = %d\n", devc->ADDR_WIDTH,
116                 devc->DATA_WIDTH);
117         sr_dbg("limit samples = %" PRIu64 "\n", devc->limit_samples_max);
118
119         for (uint32_t i = 0; i < devc->DATA_WIDTH; i++) {
120                 const uint8_t buf_size = 16;
121                 char buf[buf_size];
122                 snprintf(buf, buf_size, "ch%d", i);
123                 sr_channel_new(sdi, i, SR_CHANNEL_LOGIC, TRUE, buf);
124         }
125
126         sdi->inst_type = SR_INST_USER;
127         sdi->conn = tcp;
128
129         ipdbg_org_la_tcp_close(tcp);
130
131         devices = g_slist_append(devices, sdi);
132
133         return std_scan_complete(di, devices);
134 }
135
136 static int dev_clear(const struct sr_dev_driver *di)
137 {
138         struct drv_context *drvc = di->context;
139         struct sr_dev_inst *sdi;
140         GSList *l;
141
142         if (drvc) {
143                 for (l = drvc->instances; l; l = l->next) {
144                         sdi = l->data;
145                         struct ipdbg_org_la_tcp *tcp = sdi->conn;
146                         if (tcp) {
147                                 ipdbg_org_la_tcp_close(tcp);
148                                 ipdbg_org_la_tcp_free(tcp);
149                                 g_free(tcp);
150                         }
151                         sdi->conn = NULL;
152                 }
153         }
154
155         return std_dev_clear(di);
156 }
157
158 static int dev_open(struct sr_dev_inst *sdi)
159 {
160         sdi->status = SR_ST_INACTIVE;
161
162         struct ipdbg_org_la_tcp *tcp = sdi->conn;
163
164         if (!tcp)
165                 return SR_ERR;
166
167         if (ipdbg_org_la_tcp_open(tcp) != SR_OK)
168                 return SR_ERR;
169
170         sdi->status = SR_ST_ACTIVE;
171
172         return SR_OK;
173 }
174
175 static int dev_close(struct sr_dev_inst *sdi)
176 {
177         // Should be called before a new call to scan()
178         struct ipdbg_org_la_tcp *tcp = sdi->conn;
179
180         if (tcp)
181                 ipdbg_org_la_tcp_close(tcp);
182
183         sdi->conn = NULL;
184         sdi->status = SR_ST_INACTIVE;
185
186         return SR_OK;
187 }
188
189 static int config_get(uint32_t key, GVariant **data,
190         const struct sr_dev_inst *sdi, const struct sr_channel_group *cg)
191 {
192         int ret = SR_OK;
193
194         (void)cg;
195
196         struct ipdbg_org_la_dev_context *devc = sdi->priv;
197
198         switch (key) {
199         case SR_CONF_CAPTURE_RATIO:
200                 *data = g_variant_new_uint64(devc->capture_ratio);
201                 break;
202         case SR_CONF_LIMIT_SAMPLES:
203                 *data = g_variant_new_uint64(devc->limit_samples);
204                 break;
205         default:
206                 ret = SR_ERR_NA;
207         }
208
209         return ret;
210 }
211
212 static int config_set(uint32_t key, GVariant *data,
213         const struct sr_dev_inst *sdi, const struct sr_channel_group *cg)
214 {
215         int ret = SR_OK;
216         uint64_t value;
217
218         (void)cg;
219
220         if (sdi->status != SR_ST_ACTIVE)
221                 return SR_ERR_DEV_CLOSED;
222
223         struct ipdbg_org_la_dev_context *devc = sdi->priv;
224
225         switch (key) {
226         case SR_CONF_CAPTURE_RATIO:
227                 value = g_variant_get_uint64(data);
228                 if (value <= 100)
229                         devc->capture_ratio = value;
230                 else
231                         ret = SR_ERR;
232                 break;
233         case SR_CONF_LIMIT_SAMPLES:
234                 value = g_variant_get_uint64(data);
235                 if (value <= devc->limit_samples_max)
236                         devc->limit_samples = value;
237                 else
238                         ret = SR_ERR;
239                 break;
240         default:
241                 ret = SR_ERR_NA;
242         }
243
244         return ret;
245 }
246
247 static int config_list(uint32_t key, GVariant **data,
248         const struct sr_dev_inst *sdi, const struct sr_channel_group *cg)
249 {
250         (void)cg;
251
252         switch (key) {
253         case SR_CONF_SCAN_OPTIONS:
254                 *data = g_variant_new_fixed_array(G_VARIANT_TYPE_UINT32,
255                         ipdbg_org_la_scanopts,
256                         ARRAY_SIZE
257                         (ipdbg_org_la_scanopts),
258                         sizeof(uint32_t));
259                 break;
260         case SR_CONF_DEVICE_OPTIONS:
261                 if (!sdi)
262                         *data = g_variant_new_fixed_array(G_VARIANT_TYPE_UINT32,
263                                 ipdbg_org_la_drvopts,
264                                 ARRAY_SIZE
265                                 (ipdbg_org_la_drvopts),
266                                 sizeof(uint32_t));
267                 else
268                         *data = g_variant_new_fixed_array(G_VARIANT_TYPE_UINT32,
269                                 ipdbg_org_la_devopts,
270                                 ARRAY_SIZE
271                                 (ipdbg_org_la_devopts),
272                                 sizeof(uint32_t));
273                 break;
274         case SR_CONF_TRIGGER_MATCH:
275                 *data = g_variant_new_fixed_array(G_VARIANT_TYPE_INT32,
276                         ipdbg_org_la_trigger_matches,
277                         ARRAY_SIZE
278                         (ipdbg_org_la_trigger_matches),
279                         sizeof(int32_t));
280                 break;
281         default:
282                 return SR_ERR_NA;
283         }
284
285         return SR_OK;
286 }
287
288 static int init(struct sr_dev_driver *di, struct sr_context *sr_ctx)
289 {
290         return std_init(di, sr_ctx);
291 }
292
293 static GSList *dev_list(const struct sr_dev_driver *di)
294 {
295         return ((struct drv_context *)(di->context))->instances;
296 }
297
298 static int dev_acquisition_start(const struct sr_dev_inst *sdi)
299 {
300         if (sdi->status != SR_ST_ACTIVE)
301                 return SR_ERR_DEV_CLOSED;
302
303         struct ipdbg_org_la_tcp *tcp = sdi->conn;
304         struct ipdbg_org_la_dev_context *devc = sdi->priv;
305
306         ipdbg_org_la_convert_trigger(sdi);
307         ipdbg_org_la_send_trigger(devc, tcp);
308         ipdbg_org_la_send_delay(devc, tcp);
309
310         /* If the device stops sending for longer than it takes to send a byte,
311          * that means it's finished. But wait at least 100 ms to be safe.
312          */
313         sr_session_source_add(sdi->session, tcp->socket, G_IO_IN, 100,
314                 ipdbg_org_la_receive_data, (struct sr_dev_inst *)sdi);
315
316         ipdbg_org_la_send_start(tcp);
317
318         return SR_OK;
319 }
320
321 static int dev_acquisition_stop(struct sr_dev_inst *sdi)
322 {
323         struct ipdbg_org_la_tcp *tcp = sdi->conn;
324         struct ipdbg_org_la_dev_context *devc = sdi->priv;
325
326         uint8_t byte;
327
328         if (devc->num_transfers > 0) {
329                 while (devc->num_transfers <
330                         (devc->limit_samples_max * devc->DATA_WIDTH_BYTES)) {
331                         ipdbg_org_la_tcp_receive(tcp, &byte);
332                         devc->num_transfers++;
333                 }
334         }
335
336         ipdbg_org_la_send_reset(tcp);
337         ipdbg_org_la_abort_acquisition(sdi);
338
339         return SR_OK;
340 }
341
342 SR_PRIV struct sr_dev_driver ipdbg_la_driver_info = {
343         .name = "ipdbg-org-la",
344         .longname = "ipdbg.org logic analyzer",
345         .api_version = 1,
346         .init = init,
347         .cleanup = std_cleanup,
348         .scan = scan,
349         .dev_list = dev_list,
350         .dev_clear = dev_clear,
351         .config_get = config_get,
352         .config_set = config_set,
353         .config_list = config_list,
354         .dev_open = dev_open,
355         .dev_close = dev_close,
356         .dev_acquisition_start = dev_acquisition_start,
357         .dev_acquisition_stop = dev_acquisition_stop,
358         .context = NULL,
359 };
360
361 SR_REGISTER_DEV_DRIVER(ipdbg_la_driver_info);