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