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