]> sigrok.org Git - libsigrok.git/blame - hardware/openbench-logic-sniffer/api.c
Shorten/simplify hw_dev_list() implementations.
[libsigrok.git] / hardware / openbench-logic-sniffer / api.c
CommitLineData
0aba65da
UH
1/*
2 * This file is part of the sigrok project.
3 *
4 * Copyright (C) 2010-2012 Bert Vermeulen <bert@biot.com>
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:
0aba65da
UH
296 if (GPOINTER_TO_INT(value)) {
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{
337 struct sr_datafeed_packet *packet;
338 struct sr_datafeed_header *header;
0aba65da
UH
339 struct dev_context *devc;
340 uint32_t trigger_config[4];
341 uint32_t data;
342 uint16_t readcount, delaycount;
343 uint8_t changrp_mask;
344 int num_channels;
345 int i;
346
347 devc = sdi->priv;
348
349 if (sdi->status != SR_ST_ACTIVE)
350 return SR_ERR;
351
352 if (ols_configure_probes(sdi) != SR_OK) {
353 sr_err("Failed to configure probes.");
354 return SR_ERR;
355 }
356
357 /*
358 * Enable/disable channel groups in the flag register according to the
359 * probe mask. Calculate this here, because num_channels is needed
360 * to limit readcount.
361 */
362 changrp_mask = 0;
363 num_channels = 0;
364 for (i = 0; i < 4; i++) {
365 if (devc->probe_mask & (0xff << (i * 8))) {
366 changrp_mask |= (1 << i);
367 num_channels++;
368 }
369 }
370
371 /*
372 * Limit readcount to prevent reading past the end of the hardware
373 * buffer.
374 */
375 readcount = MIN(devc->max_samples / num_channels, devc->limit_samples) / 4;
376
377 memset(trigger_config, 0, 16);
378 trigger_config[devc->num_stages - 1] |= 0x08;
379 if (devc->trigger_mask[0]) {
380 delaycount = readcount * (1 - devc->capture_ratio / 100.0);
381 devc->trigger_at = (readcount - delaycount) * 4 - devc->num_stages;
382
383 if (send_longcommand(devc->serial, CMD_SET_TRIGGER_MASK_0,
384 reverse32(devc->trigger_mask[0])) != SR_OK)
385 return SR_ERR;
386 if (send_longcommand(devc->serial, CMD_SET_TRIGGER_VALUE_0,
387 reverse32(devc->trigger_value[0])) != SR_OK)
388 return SR_ERR;
389 if (send_longcommand(devc->serial, CMD_SET_TRIGGER_CONFIG_0,
390 trigger_config[0]) != SR_OK)
391 return SR_ERR;
392
393 if (send_longcommand(devc->serial, CMD_SET_TRIGGER_MASK_1,
394 reverse32(devc->trigger_mask[1])) != SR_OK)
395 return SR_ERR;
396 if (send_longcommand(devc->serial, CMD_SET_TRIGGER_VALUE_1,
397 reverse32(devc->trigger_value[1])) != SR_OK)
398 return SR_ERR;
399 if (send_longcommand(devc->serial, CMD_SET_TRIGGER_CONFIG_1,
400 trigger_config[1]) != SR_OK)
401 return SR_ERR;
402
403 if (send_longcommand(devc->serial, CMD_SET_TRIGGER_MASK_2,
404 reverse32(devc->trigger_mask[2])) != SR_OK)
405 return SR_ERR;
406 if (send_longcommand(devc->serial, CMD_SET_TRIGGER_VALUE_2,
407 reverse32(devc->trigger_value[2])) != SR_OK)
408 return SR_ERR;
409 if (send_longcommand(devc->serial, CMD_SET_TRIGGER_CONFIG_2,
410 trigger_config[2]) != SR_OK)
411 return SR_ERR;
412
413 if (send_longcommand(devc->serial, CMD_SET_TRIGGER_MASK_3,
414 reverse32(devc->trigger_mask[3])) != SR_OK)
415 return SR_ERR;
416 if (send_longcommand(devc->serial, CMD_SET_TRIGGER_VALUE_3,
417 reverse32(devc->trigger_value[3])) != SR_OK)
418 return SR_ERR;
419 if (send_longcommand(devc->serial, CMD_SET_TRIGGER_CONFIG_3,
420 trigger_config[3]) != SR_OK)
421 return SR_ERR;
422 } else {
423 if (send_longcommand(devc->serial, CMD_SET_TRIGGER_MASK_0,
424 devc->trigger_mask[0]) != SR_OK)
425 return SR_ERR;
426 if (send_longcommand(devc->serial, CMD_SET_TRIGGER_VALUE_0,
427 devc->trigger_value[0]) != SR_OK)
428 return SR_ERR;
429 if (send_longcommand(devc->serial, CMD_SET_TRIGGER_CONFIG_0,
430 0x00000008) != SR_OK)
431 return SR_ERR;
432 delaycount = readcount;
433 }
434
435 sr_info("Setting samplerate to %" PRIu64 "Hz (divider %u, "
436 "demux %s)", devc->cur_samplerate, devc->cur_samplerate_divider,
437 devc->flag_reg & FLAG_DEMUX ? "on" : "off");
438 if (send_longcommand(devc->serial, CMD_SET_DIVIDER,
439 reverse32(devc->cur_samplerate_divider)) != SR_OK)
440 return SR_ERR;
441
442 /* Send sample limit and pre/post-trigger capture ratio. */
443 data = ((readcount - 1) & 0xffff) << 16;
444 data |= (delaycount - 1) & 0xffff;
445 if (send_longcommand(devc->serial, CMD_CAPTURE_SIZE, reverse16(data)) != SR_OK)
446 return SR_ERR;
447
448 /* The flag register wants them here, and 1 means "disable channel". */
449 devc->flag_reg |= ~(changrp_mask << 2) & 0x3c;
450 devc->flag_reg |= FLAG_FILTER;
451 devc->rle_count = 0;
452 data = (devc->flag_reg << 24) | ((devc->flag_reg << 8) & 0xff0000);
453 if (send_longcommand(devc->serial, CMD_SET_FLAGS, data) != SR_OK)
454 return SR_ERR;
455
456 /* Start acquisition on the device. */
457 if (send_shortcommand(devc->serial, CMD_RUN) != SR_OK)
458 return SR_ERR;
459
460 sr_source_add(devc->serial->fd, G_IO_IN, -1, ols_receive_data,
461 cb_data);
462
463 if (!(packet = g_try_malloc(sizeof(struct sr_datafeed_packet)))) {
464 sr_err("Datafeed packet malloc failed.");
465 return SR_ERR_MALLOC;
466 }
467
468 if (!(header = g_try_malloc(sizeof(struct sr_datafeed_header)))) {
469 sr_err("Datafeed header malloc failed.");
470 g_free(packet);
471 return SR_ERR_MALLOC;
472 }
473
474 /* Send header packet to the session bus. */
475 packet->type = SR_DF_HEADER;
476 packet->payload = (unsigned char *)header;
477 header->feed_version = 1;
478 gettimeofday(&header->starttime, NULL);
479 sr_session_send(cb_data, packet);
480
0aba65da
UH
481 g_free(header);
482 g_free(packet);
483
484 return SR_OK;
485}
486
487/* TODO: This stops acquisition on ALL devices, ignoring dev_index. */
488static int hw_dev_acquisition_stop(struct sr_dev_inst *sdi, void *cb_data)
489{
490 /* Avoid compiler warnings. */
491 (void)cb_data;
492
493 abort_acquisition(sdi);
494
495 return SR_OK;
496}
497
498SR_PRIV struct sr_dev_driver ols_driver_info = {
499 .name = "ols",
500 .longname = "Openbench Logic Sniffer",
501 .api_version = 1,
502 .init = hw_init,
503 .cleanup = hw_cleanup,
504 .scan = hw_scan,
505 .dev_list = hw_dev_list,
506 .dev_clear = hw_cleanup,
035a1078
BV
507 .config_get = config_get,
508 .config_set = config_set,
a1c743fc 509 .config_list = config_list,
0aba65da
UH
510 .dev_open = hw_dev_open,
511 .dev_close = hw_dev_close,
0aba65da
UH
512 .dev_acquisition_start = hw_dev_acquisition_start,
513 .dev_acquisition_stop = hw_dev_acquisition_stop,
514 .priv = NULL,
515};