]> sigrok.org Git - libsigrok.git/blame - hardware/openbench-logic-sniffer/api.c
GPL headers: Use correct project name.
[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{
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. */
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
UH
282
283 devc = sdi->priv;
284
035a1078 285 switch (id) {
1953564a 286 case SR_CONF_SAMPLERATE:
e46aa4f6
BV
287 tmp_u64 = g_variant_get_uint64(data);
288 if (tmp_u64 < samplerates[0] || tmp_u64 > samplerates[1])
289 return SR_ERR_SAMPLERATE;
290 ret = ols_set_samplerate(sdi, g_variant_get_uint64(data));
0aba65da 291 break;
1953564a 292 case SR_CONF_LIMIT_SAMPLES:
e46aa4f6
BV
293 tmp_u64 = g_variant_get_uint64(data);
294 if (tmp_u64 < MIN_NUM_SAMPLES)
0aba65da 295 return SR_ERR;
e46aa4f6 296 devc->limit_samples = tmp_u64;
0aba65da
UH
297 ret = SR_OK;
298 break;
1953564a 299 case SR_CONF_CAPTURE_RATIO:
e46aa4f6 300 devc->capture_ratio = g_variant_get_uint64(data);
0aba65da
UH
301 if (devc->capture_ratio < 0 || devc->capture_ratio > 100) {
302 devc->capture_ratio = 0;
303 ret = SR_ERR;
304 } else
305 ret = SR_OK;
306 break;
1953564a 307 case SR_CONF_RLE:
e46aa4f6 308 if (g_variant_get_boolean(data)) {
0aba65da
UH
309 sr_info("Enabling RLE.");
310 devc->flag_reg |= FLAG_RLE;
aeea0572
BV
311 } else {
312 sr_info("Disabling RLE.");
313 devc->flag_reg &= ~FLAG_RLE;
0aba65da
UH
314 }
315 ret = SR_OK;
316 break;
317 default:
bd6fbf62 318 ret = SR_ERR_NA;
0aba65da
UH
319 }
320
321 return ret;
322}
323
e46aa4f6 324static int config_list(int key, GVariant **data, const struct sr_dev_inst *sdi)
a1c743fc 325{
e46aa4f6
BV
326 GVariant *gvar;
327 GVariantBuilder gvb;
a1c743fc
BV
328
329 (void)sdi;
330
331 switch (key) {
0d485e30 332 case SR_CONF_SCAN_OPTIONS:
e46aa4f6
BV
333 *data = g_variant_new_fixed_array(G_VARIANT_TYPE_INT32,
334 hwopts, ARRAY_SIZE(hwopts), sizeof(int32_t));
0d485e30 335 break;
9a6517d1 336 case SR_CONF_DEVICE_OPTIONS:
e46aa4f6
BV
337 *data = g_variant_new_fixed_array(G_VARIANT_TYPE_INT32,
338 hwcaps, ARRAY_SIZE(hwcaps), sizeof(int32_t));
9a6517d1 339 break;
a1c743fc 340 case SR_CONF_SAMPLERATE:
e46aa4f6
BV
341 g_variant_builder_init(&gvb, G_VARIANT_TYPE("a{sv}"));
342 gvar = g_variant_new_fixed_array(G_VARIANT_TYPE("t"), samplerates,
343 ARRAY_SIZE(samplerates), sizeof(uint64_t));
344 g_variant_builder_add(&gvb, "{sv}", "samplerate-steps", gvar);
345 *data = g_variant_builder_end(&gvb);
a1c743fc 346 break;
c50277a6 347 case SR_CONF_TRIGGER_TYPE:
e46aa4f6 348 *data = g_variant_new_string(TRIGGER_TYPE);
c50277a6 349 break;
a1c743fc 350 default:
bd6fbf62 351 return SR_ERR_NA;
a1c743fc
BV
352 }
353
354 return SR_OK;
355}
356
0aba65da
UH
357static int hw_dev_acquisition_start(const struct sr_dev_inst *sdi,
358 void *cb_data)
359{
0aba65da 360 struct dev_context *devc;
459a0f26 361 struct sr_serial_dev_inst *serial;
0aba65da
UH
362 uint32_t trigger_config[4];
363 uint32_t data;
364 uint16_t readcount, delaycount;
365 uint8_t changrp_mask;
366 int num_channels;
367 int i;
368
369 devc = sdi->priv;
459a0f26 370 serial = sdi->conn;
0aba65da
UH
371
372 if (sdi->status != SR_ST_ACTIVE)
373 return SR_ERR;
374
375 if (ols_configure_probes(sdi) != SR_OK) {
376 sr_err("Failed to configure probes.");
377 return SR_ERR;
378 }
379
380 /*
381 * Enable/disable channel groups in the flag register according to the
382 * probe mask. Calculate this here, because num_channels is needed
383 * to limit readcount.
384 */
385 changrp_mask = 0;
386 num_channels = 0;
387 for (i = 0; i < 4; i++) {
388 if (devc->probe_mask & (0xff << (i * 8))) {
389 changrp_mask |= (1 << i);
390 num_channels++;
391 }
392 }
393
394 /*
395 * Limit readcount to prevent reading past the end of the hardware
396 * buffer.
397 */
398 readcount = MIN(devc->max_samples / num_channels, devc->limit_samples) / 4;
399
400 memset(trigger_config, 0, 16);
2e5b73c0 401 trigger_config[devc->num_stages] |= 0x08;
0aba65da
UH
402 if (devc->trigger_mask[0]) {
403 delaycount = readcount * (1 - devc->capture_ratio / 100.0);
404 devc->trigger_at = (readcount - delaycount) * 4 - devc->num_stages;
405
459a0f26 406 if (send_longcommand(serial, CMD_SET_TRIGGER_MASK_0,
0aba65da
UH
407 reverse32(devc->trigger_mask[0])) != SR_OK)
408 return SR_ERR;
459a0f26 409 if (send_longcommand(serial, CMD_SET_TRIGGER_VALUE_0,
0aba65da
UH
410 reverse32(devc->trigger_value[0])) != SR_OK)
411 return SR_ERR;
459a0f26 412 if (send_longcommand(serial, CMD_SET_TRIGGER_CONFIG_0,
0aba65da
UH
413 trigger_config[0]) != SR_OK)
414 return SR_ERR;
415
459a0f26 416 if (send_longcommand(serial, CMD_SET_TRIGGER_MASK_1,
0aba65da
UH
417 reverse32(devc->trigger_mask[1])) != SR_OK)
418 return SR_ERR;
459a0f26 419 if (send_longcommand(serial, CMD_SET_TRIGGER_VALUE_1,
0aba65da
UH
420 reverse32(devc->trigger_value[1])) != SR_OK)
421 return SR_ERR;
459a0f26 422 if (send_longcommand(serial, CMD_SET_TRIGGER_CONFIG_1,
0aba65da
UH
423 trigger_config[1]) != SR_OK)
424 return SR_ERR;
425
459a0f26 426 if (send_longcommand(serial, CMD_SET_TRIGGER_MASK_2,
0aba65da
UH
427 reverse32(devc->trigger_mask[2])) != SR_OK)
428 return SR_ERR;
459a0f26 429 if (send_longcommand(serial, CMD_SET_TRIGGER_VALUE_2,
0aba65da
UH
430 reverse32(devc->trigger_value[2])) != SR_OK)
431 return SR_ERR;
459a0f26 432 if (send_longcommand(serial, CMD_SET_TRIGGER_CONFIG_2,
0aba65da
UH
433 trigger_config[2]) != SR_OK)
434 return SR_ERR;
435
459a0f26 436 if (send_longcommand(serial, CMD_SET_TRIGGER_MASK_3,
0aba65da
UH
437 reverse32(devc->trigger_mask[3])) != SR_OK)
438 return SR_ERR;
459a0f26 439 if (send_longcommand(serial, CMD_SET_TRIGGER_VALUE_3,
0aba65da
UH
440 reverse32(devc->trigger_value[3])) != SR_OK)
441 return SR_ERR;
459a0f26 442 if (send_longcommand(serial, CMD_SET_TRIGGER_CONFIG_3,
0aba65da
UH
443 trigger_config[3]) != SR_OK)
444 return SR_ERR;
445 } else {
459a0f26 446 if (send_longcommand(serial, CMD_SET_TRIGGER_MASK_0,
0aba65da
UH
447 devc->trigger_mask[0]) != SR_OK)
448 return SR_ERR;
459a0f26 449 if (send_longcommand(serial, CMD_SET_TRIGGER_VALUE_0,
0aba65da
UH
450 devc->trigger_value[0]) != SR_OK)
451 return SR_ERR;
459a0f26 452 if (send_longcommand(serial, CMD_SET_TRIGGER_CONFIG_0,
0aba65da
UH
453 0x00000008) != SR_OK)
454 return SR_ERR;
455 delaycount = readcount;
456 }
457
458 sr_info("Setting samplerate to %" PRIu64 "Hz (divider %u, "
459 "demux %s)", devc->cur_samplerate, devc->cur_samplerate_divider,
460 devc->flag_reg & FLAG_DEMUX ? "on" : "off");
459a0f26 461 if (send_longcommand(serial, CMD_SET_DIVIDER,
0aba65da
UH
462 reverse32(devc->cur_samplerate_divider)) != SR_OK)
463 return SR_ERR;
464
465 /* Send sample limit and pre/post-trigger capture ratio. */
466 data = ((readcount - 1) & 0xffff) << 16;
467 data |= (delaycount - 1) & 0xffff;
459a0f26 468 if (send_longcommand(serial, CMD_CAPTURE_SIZE, reverse16(data)) != SR_OK)
0aba65da
UH
469 return SR_ERR;
470
471 /* The flag register wants them here, and 1 means "disable channel". */
472 devc->flag_reg |= ~(changrp_mask << 2) & 0x3c;
473 devc->flag_reg |= FLAG_FILTER;
474 devc->rle_count = 0;
475 data = (devc->flag_reg << 24) | ((devc->flag_reg << 8) & 0xff0000);
459a0f26 476 if (send_longcommand(serial, CMD_SET_FLAGS, data) != SR_OK)
0aba65da
UH
477 return SR_ERR;
478
479 /* Start acquisition on the device. */
459a0f26 480 if (send_shortcommand(serial, CMD_RUN) != SR_OK)
0aba65da
UH
481 return SR_ERR;
482
bf256783
BV
483 /* Reset all operational states. */
484 devc->num_transfers = devc->num_samples = devc->num_bytes = 0;
485
4afdfd46
UH
486 /* Send header packet to the session bus. */
487 std_session_send_df_header(cb_data, DRIVER_LOG_DOMAIN);
488
459a0f26 489 sr_source_add(serial->fd, G_IO_IN, -1, ols_receive_data, cb_data);
0aba65da 490
0aba65da
UH
491 return SR_OK;
492}
493
0aba65da
UH
494static int hw_dev_acquisition_stop(struct sr_dev_inst *sdi, void *cb_data)
495{
496 /* Avoid compiler warnings. */
497 (void)cb_data;
498
499 abort_acquisition(sdi);
500
501 return SR_OK;
502}
503
504SR_PRIV struct sr_dev_driver ols_driver_info = {
505 .name = "ols",
506 .longname = "Openbench Logic Sniffer",
507 .api_version = 1,
508 .init = hw_init,
509 .cleanup = hw_cleanup,
510 .scan = hw_scan,
511 .dev_list = hw_dev_list,
512 .dev_clear = hw_cleanup,
035a1078
BV
513 .config_get = config_get,
514 .config_set = config_set,
a1c743fc 515 .config_list = config_list,
0aba65da
UH
516 .dev_open = hw_dev_open,
517 .dev_close = hw_dev_close,
0aba65da
UH
518 .dev_acquisition_start = hw_dev_acquisition_start,
519 .dev_acquisition_stop = hw_dev_acquisition_stop,
520 .priv = NULL,
521};