]> sigrok.org Git - libsigrok.git/blame - hardware/openbench-logic-sniffer/api.c
ols: Support get/set/list on all device options
[libsigrok.git] / hardware / openbench-logic-sniffer / api.c
CommitLineData
0aba65da
UH
1/*
2 * This file is part of the sigrok project.
3 *
13d8e03c 4 * Copyright (C) 2013 Bert Vermeulen <bert@biot.com>
0aba65da
UH
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 "protocol.h"
21
22#define SERIALCOMM "115200/8n1"
23
e46aa4f6 24static const int32_t hwopts[] = {
1953564a
BV
25 SR_CONF_CONN,
26 SR_CONF_SERIALCOMM,
aeabd308
UH
27};
28
e46aa4f6 29static const int32_t hwcaps[] = {
1953564a
BV
30 SR_CONF_LOGIC_ANALYZER,
31 SR_CONF_SAMPLERATE,
0c05591a 32 SR_CONF_TRIGGER_TYPE,
1953564a
BV
33 SR_CONF_CAPTURE_RATIO,
34 SR_CONF_LIMIT_SAMPLES,
35 SR_CONF_RLE,
0aba65da
UH
36};
37
38/* Probes are numbered 0-31 (on the PCB silkscreen). */
39SR_PRIV const char *ols_probe_names[NUM_PROBES + 1] = {
78693401
UH
40 "0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12",
41 "13", "14", "15", "16", "17", "18", "19", "20", "21", "22", "23",
42 "24", "25", "26", "27", "28", "29", "30", "31",
0aba65da
UH
43 NULL,
44};
45
d3b38ad3 46/* Default supported samplerates, can be overridden by device metadata. */
e46aa4f6
BV
47static const uint64_t samplerates[] = {
48 SR_HZ(10),
49 SR_MHZ(200),
50 SR_HZ(1),
0aba65da
UH
51};
52
53SR_PRIV struct sr_dev_driver ols_driver_info;
54static struct sr_dev_driver *di = &ols_driver_info;
55
56static int hw_init(struct sr_context *sr_ctx)
57{
063e7aef 58 return std_hw_init(sr_ctx, di, DRIVER_LOG_DOMAIN);
0aba65da
UH
59}
60
61static GSList *hw_scan(GSList *options)
62{
1987b8d6 63 struct sr_config *src;
0aba65da
UH
64 struct sr_dev_inst *sdi;
65 struct drv_context *drvc;
66 struct dev_context *devc;
67 struct sr_probe *probe;
68 struct sr_serial_dev_inst *serial;
69 GPollFD probefd;
70 GSList *l, *devices;
71 int ret, i;
72 const char *conn, *serialcomm;
73 char buf[8];
74
75 (void)options;
4b97c74e 76
0aba65da 77 drvc = di->priv;
4b97c74e 78
0aba65da
UH
79 devices = NULL;
80
81 conn = serialcomm = NULL;
82 for (l = options; l; l = l->next) {
1987b8d6
BV
83 src = l->data;
84 switch (src->key) {
1953564a 85 case SR_CONF_CONN:
e46aa4f6 86 conn = g_variant_get_string(src->data, NULL);
0aba65da 87 break;
1953564a 88 case SR_CONF_SERIALCOMM:
e46aa4f6 89 serialcomm = g_variant_get_string(src->data, NULL);
0aba65da
UH
90 break;
91 }
92 }
93 if (!conn)
94 return NULL;
95
96 if (serialcomm == NULL)
97 serialcomm = SERIALCOMM;
98
99 if (!(serial = sr_serial_dev_inst_new(conn, serialcomm)))
100 return NULL;
101
102 /* The discovery procedure is like this: first send the Reset
103 * command (0x00) 5 times, since the device could be anywhere
104 * in a 5-byte command. Then send the ID command (0x02).
105 * If the device responds with 4 bytes ("OLS1" or "SLA1"), we
106 * have a match.
107 */
108 sr_info("Probing %s.", conn);
109 if (serial_open(serial, SERIAL_RDWR | SERIAL_NONBLOCK) != SR_OK)
110 return NULL;
111
112 ret = SR_OK;
113 for (i = 0; i < 5; i++) {
114 if ((ret = send_shortcommand(serial, CMD_RESET)) != SR_OK) {
115 sr_err("Port %s is not writable.", conn);
116 break;
117 }
118 }
119 if (ret != SR_OK) {
120 serial_close(serial);
121 sr_err("Could not use port %s. Quitting.", conn);
122 return NULL;
123 }
124 send_shortcommand(serial, CMD_ID);
125
126 /* Wait 10ms for a response. */
127 g_usleep(10000);
128
129 probefd.fd = serial->fd;
130 probefd.events = G_IO_IN;
131 g_poll(&probefd, 1, 1);
132
133 if (probefd.revents != G_IO_IN)
134 return NULL;
135 if (serial_read(serial, buf, 4) != 4)
136 return NULL;
137 if (strncmp(buf, "1SLO", 4) && strncmp(buf, "1ALS", 4))
138 return NULL;
139
140 /* Definitely using the OLS protocol, check if it supports
141 * the metadata command.
142 */
143 send_shortcommand(serial, CMD_METADATA);
144 if (g_poll(&probefd, 1, 10) > 0) {
145 /* Got metadata. */
146 sdi = get_metadata(serial);
147 sdi->index = 0;
148 devc = sdi->priv;
149 } else {
150 /* Not an OLS -- some other board that uses the sump protocol. */
151 sdi = sr_dev_inst_new(0, SR_ST_INACTIVE,
152 "Sump", "Logic Analyzer", "v1.0");
153 sdi->driver = di;
154 devc = ols_dev_new();
155 for (i = 0; i < 32; i++) {
156 if (!(probe = sr_probe_new(i, SR_PROBE_LOGIC, TRUE,
157 ols_probe_names[i])))
158 return 0;
159 sdi->probes = g_slist_append(sdi->probes, probe);
160 }
161 sdi->priv = devc;
162 }
163 devc->serial = serial;
164 drvc->instances = g_slist_append(drvc->instances, sdi);
165 devices = g_slist_append(devices, sdi);
166
167 serial_close(serial);
168
169 return devices;
170}
171
172static GSList *hw_dev_list(void)
173{
0e94d524 174 return ((struct drv_context *)(di->priv))->instances;
0aba65da
UH
175}
176
177static int hw_dev_open(struct sr_dev_inst *sdi)
178{
179 struct dev_context *devc;
180
181 devc = sdi->priv;
182
183 if (serial_open(devc->serial, SERIAL_RDWR) != SR_OK)
184 return SR_ERR;
185
186 sdi->status = SR_ST_ACTIVE;
187
188 return SR_OK;
189}
190
191static int hw_dev_close(struct sr_dev_inst *sdi)
192{
193 struct dev_context *devc;
194
195 devc = sdi->priv;
196
197 if (devc->serial && devc->serial->fd != -1) {
198 serial_close(devc->serial);
199 sdi->status = SR_ST_INACTIVE;
200 }
201
202 return SR_OK;
203}
204
205static int hw_cleanup(void)
206{
207 GSList *l;
208 struct sr_dev_inst *sdi;
209 struct drv_context *drvc;
210 struct dev_context *devc;
211 int ret = SR_OK;
212
213 if (!(drvc = di->priv))
214 return SR_OK;
215
216 /* Properly close and free all devices. */
217 for (l = drvc->instances; l; l = l->next) {
218 if (!(sdi = l->data)) {
219 /* Log error, but continue cleaning up the rest. */
220 sr_err("%s: sdi was NULL, continuing", __func__);
221 ret = SR_ERR_BUG;
222 continue;
223 }
224 if (!(devc = sdi->priv)) {
225 /* Log error, but continue cleaning up the rest. */
226 sr_err("%s: sdi->priv was NULL, continuing", __func__);
227 ret = SR_ERR_BUG;
228 continue;
229 }
230 hw_dev_close(sdi);
231 sr_serial_dev_inst_free(devc->serial);
232 sr_dev_inst_free(sdi);
233 }
234 g_slist_free(drvc->instances);
235 drvc->instances = NULL;
236
237 return ret;
238}
239
e46aa4f6 240static int config_get(int id, GVariant **data, const struct sr_dev_inst *sdi)
0aba65da
UH
241{
242 struct dev_context *devc;
243
0c05591a
BV
244 if (!sdi)
245 return SR_ERR_ARG;
246
247 devc = sdi->priv;
035a1078 248 switch (id) {
123e1313 249 case SR_CONF_SAMPLERATE:
0c05591a
BV
250 *data = g_variant_new_uint64(devc->cur_samplerate);
251 break;
252 case SR_CONF_CAPTURE_RATIO:
253 *data = g_variant_new_uint64(devc->capture_ratio);
254 break;
255 case SR_CONF_LIMIT_SAMPLES:
256 *data = g_variant_new_uint64(devc->limit_samples);
257 break;
258 case SR_CONF_RLE:
259 *data = g_variant_new_boolean(devc->flag_reg & FLAG_RLE ? TRUE : FALSE);
0aba65da
UH
260 break;
261 default:
262 return SR_ERR_ARG;
263 }
264
265 return SR_OK;
266}
267
e46aa4f6 268static int config_set(int id, GVariant *data, const struct sr_dev_inst *sdi)
0aba65da
UH
269{
270 struct dev_context *devc;
271 int ret;
e46aa4f6 272 uint64_t tmp_u64;
0aba65da
UH
273
274 devc = sdi->priv;
275
276 if (sdi->status != SR_ST_ACTIVE)
277 return SR_ERR;
278
035a1078 279 switch (id) {
1953564a 280 case SR_CONF_SAMPLERATE:
e46aa4f6
BV
281 tmp_u64 = g_variant_get_uint64(data);
282 if (tmp_u64 < samplerates[0] || tmp_u64 > samplerates[1])
283 return SR_ERR_SAMPLERATE;
284 ret = ols_set_samplerate(sdi, g_variant_get_uint64(data));
0aba65da 285 break;
1953564a 286 case SR_CONF_LIMIT_SAMPLES:
e46aa4f6
BV
287 tmp_u64 = g_variant_get_uint64(data);
288 if (tmp_u64 < MIN_NUM_SAMPLES)
0aba65da 289 return SR_ERR;
e46aa4f6 290 devc->limit_samples = tmp_u64;
0aba65da
UH
291 ret = SR_OK;
292 break;
1953564a 293 case SR_CONF_CAPTURE_RATIO:
e46aa4f6 294 devc->capture_ratio = g_variant_get_uint64(data);
0aba65da
UH
295 if (devc->capture_ratio < 0 || devc->capture_ratio > 100) {
296 devc->capture_ratio = 0;
297 ret = SR_ERR;
298 } else
299 ret = SR_OK;
300 break;
1953564a 301 case SR_CONF_RLE:
e46aa4f6 302 if (g_variant_get_boolean(data)) {
0aba65da
UH
303 sr_info("Enabling RLE.");
304 devc->flag_reg |= FLAG_RLE;
aeea0572
BV
305 } else {
306 sr_info("Disabling RLE.");
307 devc->flag_reg &= ~FLAG_RLE;
0aba65da
UH
308 }
309 ret = SR_OK;
310 break;
311 default:
312 ret = SR_ERR;
313 }
314
315 return ret;
316}
317
e46aa4f6 318static int config_list(int key, GVariant **data, const struct sr_dev_inst *sdi)
a1c743fc 319{
e46aa4f6
BV
320 GVariant *gvar;
321 GVariantBuilder gvb;
a1c743fc
BV
322
323 (void)sdi;
324
325 switch (key) {
0d485e30 326 case SR_CONF_SCAN_OPTIONS:
e46aa4f6
BV
327 *data = g_variant_new_fixed_array(G_VARIANT_TYPE_INT32,
328 hwopts, ARRAY_SIZE(hwopts), sizeof(int32_t));
0d485e30 329 break;
9a6517d1 330 case SR_CONF_DEVICE_OPTIONS:
e46aa4f6
BV
331 *data = g_variant_new_fixed_array(G_VARIANT_TYPE_INT32,
332 hwcaps, ARRAY_SIZE(hwcaps), sizeof(int32_t));
9a6517d1 333 break;
a1c743fc 334 case SR_CONF_SAMPLERATE:
e46aa4f6
BV
335 g_variant_builder_init(&gvb, G_VARIANT_TYPE("a{sv}"));
336 gvar = g_variant_new_fixed_array(G_VARIANT_TYPE("t"), samplerates,
337 ARRAY_SIZE(samplerates), sizeof(uint64_t));
338 g_variant_builder_add(&gvb, "{sv}", "samplerate-steps", gvar);
339 *data = g_variant_builder_end(&gvb);
a1c743fc 340 break;
c50277a6 341 case SR_CONF_TRIGGER_TYPE:
e46aa4f6 342 *data = g_variant_new_string(TRIGGER_TYPE);
c50277a6 343 break;
a1c743fc
BV
344 default:
345 return SR_ERR_ARG;
346 }
347
348 return SR_OK;
349}
350
0aba65da
UH
351static int hw_dev_acquisition_start(const struct sr_dev_inst *sdi,
352 void *cb_data)
353{
0aba65da
UH
354 struct dev_context *devc;
355 uint32_t trigger_config[4];
356 uint32_t data;
357 uint16_t readcount, delaycount;
358 uint8_t changrp_mask;
359 int num_channels;
360 int i;
361
362 devc = sdi->priv;
363
364 if (sdi->status != SR_ST_ACTIVE)
365 return SR_ERR;
366
367 if (ols_configure_probes(sdi) != SR_OK) {
368 sr_err("Failed to configure probes.");
369 return SR_ERR;
370 }
371
372 /*
373 * Enable/disable channel groups in the flag register according to the
374 * probe mask. Calculate this here, because num_channels is needed
375 * to limit readcount.
376 */
377 changrp_mask = 0;
378 num_channels = 0;
379 for (i = 0; i < 4; i++) {
380 if (devc->probe_mask & (0xff << (i * 8))) {
381 changrp_mask |= (1 << i);
382 num_channels++;
383 }
384 }
385
386 /*
387 * Limit readcount to prevent reading past the end of the hardware
388 * buffer.
389 */
390 readcount = MIN(devc->max_samples / num_channels, devc->limit_samples) / 4;
391
392 memset(trigger_config, 0, 16);
393 trigger_config[devc->num_stages - 1] |= 0x08;
394 if (devc->trigger_mask[0]) {
395 delaycount = readcount * (1 - devc->capture_ratio / 100.0);
396 devc->trigger_at = (readcount - delaycount) * 4 - devc->num_stages;
397
398 if (send_longcommand(devc->serial, CMD_SET_TRIGGER_MASK_0,
399 reverse32(devc->trigger_mask[0])) != SR_OK)
400 return SR_ERR;
401 if (send_longcommand(devc->serial, CMD_SET_TRIGGER_VALUE_0,
402 reverse32(devc->trigger_value[0])) != SR_OK)
403 return SR_ERR;
404 if (send_longcommand(devc->serial, CMD_SET_TRIGGER_CONFIG_0,
405 trigger_config[0]) != SR_OK)
406 return SR_ERR;
407
408 if (send_longcommand(devc->serial, CMD_SET_TRIGGER_MASK_1,
409 reverse32(devc->trigger_mask[1])) != SR_OK)
410 return SR_ERR;
411 if (send_longcommand(devc->serial, CMD_SET_TRIGGER_VALUE_1,
412 reverse32(devc->trigger_value[1])) != SR_OK)
413 return SR_ERR;
414 if (send_longcommand(devc->serial, CMD_SET_TRIGGER_CONFIG_1,
415 trigger_config[1]) != SR_OK)
416 return SR_ERR;
417
418 if (send_longcommand(devc->serial, CMD_SET_TRIGGER_MASK_2,
419 reverse32(devc->trigger_mask[2])) != SR_OK)
420 return SR_ERR;
421 if (send_longcommand(devc->serial, CMD_SET_TRIGGER_VALUE_2,
422 reverse32(devc->trigger_value[2])) != SR_OK)
423 return SR_ERR;
424 if (send_longcommand(devc->serial, CMD_SET_TRIGGER_CONFIG_2,
425 trigger_config[2]) != SR_OK)
426 return SR_ERR;
427
428 if (send_longcommand(devc->serial, CMD_SET_TRIGGER_MASK_3,
429 reverse32(devc->trigger_mask[3])) != SR_OK)
430 return SR_ERR;
431 if (send_longcommand(devc->serial, CMD_SET_TRIGGER_VALUE_3,
432 reverse32(devc->trigger_value[3])) != SR_OK)
433 return SR_ERR;
434 if (send_longcommand(devc->serial, CMD_SET_TRIGGER_CONFIG_3,
435 trigger_config[3]) != SR_OK)
436 return SR_ERR;
437 } else {
438 if (send_longcommand(devc->serial, CMD_SET_TRIGGER_MASK_0,
439 devc->trigger_mask[0]) != SR_OK)
440 return SR_ERR;
441 if (send_longcommand(devc->serial, CMD_SET_TRIGGER_VALUE_0,
442 devc->trigger_value[0]) != SR_OK)
443 return SR_ERR;
444 if (send_longcommand(devc->serial, CMD_SET_TRIGGER_CONFIG_0,
445 0x00000008) != SR_OK)
446 return SR_ERR;
447 delaycount = readcount;
448 }
449
450 sr_info("Setting samplerate to %" PRIu64 "Hz (divider %u, "
451 "demux %s)", devc->cur_samplerate, devc->cur_samplerate_divider,
452 devc->flag_reg & FLAG_DEMUX ? "on" : "off");
453 if (send_longcommand(devc->serial, CMD_SET_DIVIDER,
454 reverse32(devc->cur_samplerate_divider)) != SR_OK)
455 return SR_ERR;
456
457 /* Send sample limit and pre/post-trigger capture ratio. */
458 data = ((readcount - 1) & 0xffff) << 16;
459 data |= (delaycount - 1) & 0xffff;
460 if (send_longcommand(devc->serial, CMD_CAPTURE_SIZE, reverse16(data)) != SR_OK)
461 return SR_ERR;
462
463 /* The flag register wants them here, and 1 means "disable channel". */
464 devc->flag_reg |= ~(changrp_mask << 2) & 0x3c;
465 devc->flag_reg |= FLAG_FILTER;
466 devc->rle_count = 0;
467 data = (devc->flag_reg << 24) | ((devc->flag_reg << 8) & 0xff0000);
468 if (send_longcommand(devc->serial, CMD_SET_FLAGS, data) != SR_OK)
469 return SR_ERR;
470
471 /* Start acquisition on the device. */
472 if (send_shortcommand(devc->serial, CMD_RUN) != SR_OK)
473 return SR_ERR;
474
4afdfd46
UH
475 /* Send header packet to the session bus. */
476 std_session_send_df_header(cb_data, DRIVER_LOG_DOMAIN);
477
0aba65da
UH
478 sr_source_add(devc->serial->fd, G_IO_IN, -1, ols_receive_data,
479 cb_data);
480
0aba65da
UH
481 return SR_OK;
482}
483
484/* TODO: This stops acquisition on ALL devices, ignoring dev_index. */
485static int hw_dev_acquisition_stop(struct sr_dev_inst *sdi, void *cb_data)
486{
487 /* Avoid compiler warnings. */
488 (void)cb_data;
489
490 abort_acquisition(sdi);
491
492 return SR_OK;
493}
494
495SR_PRIV struct sr_dev_driver ols_driver_info = {
496 .name = "ols",
497 .longname = "Openbench Logic Sniffer",
498 .api_version = 1,
499 .init = hw_init,
500 .cleanup = hw_cleanup,
501 .scan = hw_scan,
502 .dev_list = hw_dev_list,
503 .dev_clear = hw_cleanup,
035a1078
BV
504 .config_get = config_get,
505 .config_set = config_set,
a1c743fc 506 .config_list = config_list,
0aba65da
UH
507 .dev_open = hw_dev_open,
508 .dev_close = hw_dev_close,
0aba65da
UH
509 .dev_acquisition_start = hw_dev_acquisition_start,
510 .dev_acquisition_stop = hw_dev_acquisition_stop,
511 .priv = NULL,
512};