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