]> sigrok.org Git - libsigrok.git/blame - hardware/openbench-logic-sniffer/api.c
s/DRIVER_LOG_DOMAIN/LOG_PREFIX/.
[libsigrok.git] / hardware / openbench-logic-sniffer / api.c
CommitLineData
0aba65da 1/*
50985c20 2 * This file is part of the libsigrok project.
0aba65da 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{
29a27196 58 return std_hw_init(sr_ctx, di, LOG_PREFIX);
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. */
72cd99b8 151 sr_info("Device does not support metadata.");
0aba65da
UH
152 sdi = sr_dev_inst_new(0, SR_ST_INACTIVE,
153 "Sump", "Logic Analyzer", "v1.0");
154 sdi->driver = di;
0aba65da
UH
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 }
bf256783 161 devc = ols_dev_new();
0aba65da
UH
162 sdi->priv = devc;
163 }
bf256783
BV
164 /* Configure samplerate and divider. */
165 if (ols_set_samplerate(sdi, DEFAULT_SAMPLERATE) != SR_OK)
166 sr_dbg("Failed to set default samplerate (%"PRIu64").",
167 DEFAULT_SAMPLERATE);
168 /* Clear trigger masks, values and stages. */
169 ols_configure_probes(sdi);
459a0f26
BV
170 sdi->inst_type = SR_INST_SERIAL;
171 sdi->conn = serial;
bf256783 172
0aba65da
UH
173 drvc->instances = g_slist_append(drvc->instances, sdi);
174 devices = g_slist_append(devices, sdi);
175
176 serial_close(serial);
177
178 return devices;
179}
180
181static GSList *hw_dev_list(void)
182{
0e94d524 183 return ((struct drv_context *)(di->priv))->instances;
0aba65da
UH
184}
185
186static int hw_dev_open(struct sr_dev_inst *sdi)
187{
459a0f26 188 struct sr_serial_dev_inst *serial;
0aba65da 189
459a0f26
BV
190 serial = sdi->conn;
191 if (serial_open(serial, SERIAL_RDWR) != SR_OK)
0aba65da
UH
192 return SR_ERR;
193
194 sdi->status = SR_ST_ACTIVE;
195
196 return SR_OK;
197}
198
199static int hw_dev_close(struct sr_dev_inst *sdi)
200{
459a0f26 201 struct sr_serial_dev_inst *serial;
0aba65da 202
459a0f26
BV
203 serial = sdi->conn;
204 if (serial && serial->fd != -1) {
205 serial_close(serial);
0aba65da
UH
206 sdi->status = SR_ST_INACTIVE;
207 }
208
209 return SR_OK;
210}
211
212static int hw_cleanup(void)
213{
214 GSList *l;
215 struct sr_dev_inst *sdi;
216 struct drv_context *drvc;
217 struct dev_context *devc;
459a0f26 218 struct sr_serial_dev_inst *serial;
0aba65da
UH
219 int ret = SR_OK;
220
221 if (!(drvc = di->priv))
222 return SR_OK;
223
224 /* Properly close and free all devices. */
225 for (l = drvc->instances; l; l = l->next) {
226 if (!(sdi = l->data)) {
227 /* Log error, but continue cleaning up the rest. */
228 sr_err("%s: sdi was NULL, continuing", __func__);
229 ret = SR_ERR_BUG;
230 continue;
231 }
232 if (!(devc = sdi->priv)) {
233 /* Log error, but continue cleaning up the rest. */
234 sr_err("%s: sdi->priv was NULL, continuing", __func__);
235 ret = SR_ERR_BUG;
236 continue;
237 }
238 hw_dev_close(sdi);
459a0f26
BV
239 serial = sdi->conn;
240 sr_serial_dev_inst_free(serial);
0aba65da
UH
241 sr_dev_inst_free(sdi);
242 }
243 g_slist_free(drvc->instances);
244 drvc->instances = NULL;
245
246 return ret;
247}
248
e46aa4f6 249static int config_get(int id, GVariant **data, const struct sr_dev_inst *sdi)
0aba65da
UH
250{
251 struct dev_context *devc;
252
0c05591a
BV
253 if (!sdi)
254 return SR_ERR_ARG;
255
256 devc = sdi->priv;
035a1078 257 switch (id) {
123e1313 258 case SR_CONF_SAMPLERATE:
0c05591a
BV
259 *data = g_variant_new_uint64(devc->cur_samplerate);
260 break;
261 case SR_CONF_CAPTURE_RATIO:
262 *data = g_variant_new_uint64(devc->capture_ratio);
263 break;
264 case SR_CONF_LIMIT_SAMPLES:
265 *data = g_variant_new_uint64(devc->limit_samples);
266 break;
267 case SR_CONF_RLE:
268 *data = g_variant_new_boolean(devc->flag_reg & FLAG_RLE ? TRUE : FALSE);
0aba65da
UH
269 break;
270 default:
bd6fbf62 271 return SR_ERR_NA;
0aba65da
UH
272 }
273
274 return SR_OK;
275}
276
e46aa4f6 277static int config_set(int id, GVariant *data, const struct sr_dev_inst *sdi)
0aba65da
UH
278{
279 struct dev_context *devc;
280 int ret;
e46aa4f6 281 uint64_t tmp_u64;
0aba65da 282
e73ffd42
BV
283 if (sdi->status != SR_ST_ACTIVE)
284 return SR_ERR_DEV_CLOSED;
285
0aba65da
UH
286 devc = sdi->priv;
287
035a1078 288 switch (id) {
1953564a 289 case SR_CONF_SAMPLERATE:
e46aa4f6
BV
290 tmp_u64 = g_variant_get_uint64(data);
291 if (tmp_u64 < samplerates[0] || tmp_u64 > samplerates[1])
292 return SR_ERR_SAMPLERATE;
293 ret = ols_set_samplerate(sdi, g_variant_get_uint64(data));
0aba65da 294 break;
1953564a 295 case SR_CONF_LIMIT_SAMPLES:
e46aa4f6
BV
296 tmp_u64 = g_variant_get_uint64(data);
297 if (tmp_u64 < MIN_NUM_SAMPLES)
0aba65da 298 return SR_ERR;
e46aa4f6 299 devc->limit_samples = tmp_u64;
0aba65da
UH
300 ret = SR_OK;
301 break;
1953564a 302 case SR_CONF_CAPTURE_RATIO:
e46aa4f6 303 devc->capture_ratio = g_variant_get_uint64(data);
0aba65da
UH
304 if (devc->capture_ratio < 0 || devc->capture_ratio > 100) {
305 devc->capture_ratio = 0;
306 ret = SR_ERR;
307 } else
308 ret = SR_OK;
309 break;
1953564a 310 case SR_CONF_RLE:
e46aa4f6 311 if (g_variant_get_boolean(data)) {
0aba65da
UH
312 sr_info("Enabling RLE.");
313 devc->flag_reg |= FLAG_RLE;
aeea0572
BV
314 } else {
315 sr_info("Disabling RLE.");
316 devc->flag_reg &= ~FLAG_RLE;
0aba65da
UH
317 }
318 ret = SR_OK;
319 break;
320 default:
bd6fbf62 321 ret = SR_ERR_NA;
0aba65da
UH
322 }
323
324 return ret;
325}
326
e46aa4f6 327static int config_list(int key, GVariant **data, const struct sr_dev_inst *sdi)
a1c743fc 328{
e46aa4f6
BV
329 GVariant *gvar;
330 GVariantBuilder gvb;
a1c743fc
BV
331
332 (void)sdi;
333
334 switch (key) {
0d485e30 335 case SR_CONF_SCAN_OPTIONS:
e46aa4f6
BV
336 *data = g_variant_new_fixed_array(G_VARIANT_TYPE_INT32,
337 hwopts, ARRAY_SIZE(hwopts), sizeof(int32_t));
0d485e30 338 break;
9a6517d1 339 case SR_CONF_DEVICE_OPTIONS:
e46aa4f6
BV
340 *data = g_variant_new_fixed_array(G_VARIANT_TYPE_INT32,
341 hwcaps, ARRAY_SIZE(hwcaps), sizeof(int32_t));
9a6517d1 342 break;
a1c743fc 343 case SR_CONF_SAMPLERATE:
e46aa4f6
BV
344 g_variant_builder_init(&gvb, G_VARIANT_TYPE("a{sv}"));
345 gvar = g_variant_new_fixed_array(G_VARIANT_TYPE("t"), samplerates,
346 ARRAY_SIZE(samplerates), sizeof(uint64_t));
347 g_variant_builder_add(&gvb, "{sv}", "samplerate-steps", gvar);
348 *data = g_variant_builder_end(&gvb);
a1c743fc 349 break;
c50277a6 350 case SR_CONF_TRIGGER_TYPE:
e46aa4f6 351 *data = g_variant_new_string(TRIGGER_TYPE);
c50277a6 352 break;
a1c743fc 353 default:
bd6fbf62 354 return SR_ERR_NA;
a1c743fc
BV
355 }
356
357 return SR_OK;
358}
359
0aba65da
UH
360static int hw_dev_acquisition_start(const struct sr_dev_inst *sdi,
361 void *cb_data)
362{
0aba65da 363 struct dev_context *devc;
459a0f26 364 struct sr_serial_dev_inst *serial;
0aba65da
UH
365 uint32_t trigger_config[4];
366 uint32_t data;
367 uint16_t readcount, delaycount;
368 uint8_t changrp_mask;
369 int num_channels;
370 int i;
371
e73ffd42
BV
372 if (sdi->status != SR_ST_ACTIVE)
373 return SR_ERR_DEV_CLOSED;
374
0aba65da 375 devc = sdi->priv;
459a0f26 376 serial = sdi->conn;
0aba65da 377
0aba65da
UH
378 if (ols_configure_probes(sdi) != SR_OK) {
379 sr_err("Failed to configure probes.");
380 return SR_ERR;
381 }
382
383 /*
384 * Enable/disable channel groups in the flag register according to the
385 * probe mask. Calculate this here, because num_channels is needed
386 * to limit readcount.
387 */
388 changrp_mask = 0;
389 num_channels = 0;
390 for (i = 0; i < 4; i++) {
391 if (devc->probe_mask & (0xff << (i * 8))) {
392 changrp_mask |= (1 << i);
393 num_channels++;
394 }
395 }
396
397 /*
398 * Limit readcount to prevent reading past the end of the hardware
399 * buffer.
400 */
401 readcount = MIN(devc->max_samples / num_channels, devc->limit_samples) / 4;
402
403 memset(trigger_config, 0, 16);
2e5b73c0 404 trigger_config[devc->num_stages] |= 0x08;
0aba65da
UH
405 if (devc->trigger_mask[0]) {
406 delaycount = readcount * (1 - devc->capture_ratio / 100.0);
407 devc->trigger_at = (readcount - delaycount) * 4 - devc->num_stages;
408
459a0f26 409 if (send_longcommand(serial, CMD_SET_TRIGGER_MASK_0,
0aba65da
UH
410 reverse32(devc->trigger_mask[0])) != SR_OK)
411 return SR_ERR;
459a0f26 412 if (send_longcommand(serial, CMD_SET_TRIGGER_VALUE_0,
0aba65da
UH
413 reverse32(devc->trigger_value[0])) != SR_OK)
414 return SR_ERR;
459a0f26 415 if (send_longcommand(serial, CMD_SET_TRIGGER_CONFIG_0,
0aba65da
UH
416 trigger_config[0]) != SR_OK)
417 return SR_ERR;
418
459a0f26 419 if (send_longcommand(serial, CMD_SET_TRIGGER_MASK_1,
0aba65da
UH
420 reverse32(devc->trigger_mask[1])) != SR_OK)
421 return SR_ERR;
459a0f26 422 if (send_longcommand(serial, CMD_SET_TRIGGER_VALUE_1,
0aba65da
UH
423 reverse32(devc->trigger_value[1])) != SR_OK)
424 return SR_ERR;
459a0f26 425 if (send_longcommand(serial, CMD_SET_TRIGGER_CONFIG_1,
0aba65da
UH
426 trigger_config[1]) != SR_OK)
427 return SR_ERR;
428
459a0f26 429 if (send_longcommand(serial, CMD_SET_TRIGGER_MASK_2,
0aba65da
UH
430 reverse32(devc->trigger_mask[2])) != SR_OK)
431 return SR_ERR;
459a0f26 432 if (send_longcommand(serial, CMD_SET_TRIGGER_VALUE_2,
0aba65da
UH
433 reverse32(devc->trigger_value[2])) != SR_OK)
434 return SR_ERR;
459a0f26 435 if (send_longcommand(serial, CMD_SET_TRIGGER_CONFIG_2,
0aba65da
UH
436 trigger_config[2]) != SR_OK)
437 return SR_ERR;
438
459a0f26 439 if (send_longcommand(serial, CMD_SET_TRIGGER_MASK_3,
0aba65da
UH
440 reverse32(devc->trigger_mask[3])) != SR_OK)
441 return SR_ERR;
459a0f26 442 if (send_longcommand(serial, CMD_SET_TRIGGER_VALUE_3,
0aba65da
UH
443 reverse32(devc->trigger_value[3])) != SR_OK)
444 return SR_ERR;
459a0f26 445 if (send_longcommand(serial, CMD_SET_TRIGGER_CONFIG_3,
0aba65da
UH
446 trigger_config[3]) != SR_OK)
447 return SR_ERR;
448 } else {
459a0f26 449 if (send_longcommand(serial, CMD_SET_TRIGGER_MASK_0,
0aba65da
UH
450 devc->trigger_mask[0]) != SR_OK)
451 return SR_ERR;
459a0f26 452 if (send_longcommand(serial, CMD_SET_TRIGGER_VALUE_0,
0aba65da
UH
453 devc->trigger_value[0]) != SR_OK)
454 return SR_ERR;
459a0f26 455 if (send_longcommand(serial, CMD_SET_TRIGGER_CONFIG_0,
0aba65da
UH
456 0x00000008) != SR_OK)
457 return SR_ERR;
458 delaycount = readcount;
459 }
460
461 sr_info("Setting samplerate to %" PRIu64 "Hz (divider %u, "
462 "demux %s)", devc->cur_samplerate, devc->cur_samplerate_divider,
463 devc->flag_reg & FLAG_DEMUX ? "on" : "off");
459a0f26 464 if (send_longcommand(serial, CMD_SET_DIVIDER,
0aba65da
UH
465 reverse32(devc->cur_samplerate_divider)) != SR_OK)
466 return SR_ERR;
467
468 /* Send sample limit and pre/post-trigger capture ratio. */
469 data = ((readcount - 1) & 0xffff) << 16;
470 data |= (delaycount - 1) & 0xffff;
459a0f26 471 if (send_longcommand(serial, CMD_CAPTURE_SIZE, reverse16(data)) != SR_OK)
0aba65da
UH
472 return SR_ERR;
473
474 /* The flag register wants them here, and 1 means "disable channel". */
475 devc->flag_reg |= ~(changrp_mask << 2) & 0x3c;
476 devc->flag_reg |= FLAG_FILTER;
477 devc->rle_count = 0;
478 data = (devc->flag_reg << 24) | ((devc->flag_reg << 8) & 0xff0000);
459a0f26 479 if (send_longcommand(serial, CMD_SET_FLAGS, data) != SR_OK)
0aba65da
UH
480 return SR_ERR;
481
482 /* Start acquisition on the device. */
459a0f26 483 if (send_shortcommand(serial, CMD_RUN) != SR_OK)
0aba65da
UH
484 return SR_ERR;
485
bf256783
BV
486 /* Reset all operational states. */
487 devc->num_transfers = devc->num_samples = devc->num_bytes = 0;
488
4afdfd46 489 /* Send header packet to the session bus. */
29a27196 490 std_session_send_df_header(cb_data, LOG_PREFIX);
4afdfd46 491
459a0f26 492 sr_source_add(serial->fd, G_IO_IN, -1, ols_receive_data, cb_data);
0aba65da 493
0aba65da
UH
494 return SR_OK;
495}
496
0aba65da
UH
497static int hw_dev_acquisition_stop(struct sr_dev_inst *sdi, void *cb_data)
498{
499 /* Avoid compiler warnings. */
500 (void)cb_data;
501
502 abort_acquisition(sdi);
503
504 return SR_OK;
505}
506
507SR_PRIV struct sr_dev_driver ols_driver_info = {
508 .name = "ols",
509 .longname = "Openbench Logic Sniffer",
510 .api_version = 1,
511 .init = hw_init,
512 .cleanup = hw_cleanup,
513 .scan = hw_scan,
514 .dev_list = hw_dev_list,
515 .dev_clear = hw_cleanup,
035a1078
BV
516 .config_get = config_get,
517 .config_set = config_set,
a1c743fc 518 .config_list = config_list,
0aba65da
UH
519 .dev_open = hw_dev_open,
520 .dev_close = hw_dev_close,
0aba65da
UH
521 .dev_acquisition_start = hw_dev_acquisition_start,
522 .dev_acquisition_stop = hw_dev_acquisition_stop,
523 .priv = NULL,
524};