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