]> sigrok.org Git - libsigrok.git/blame - hardware/openbench-logic-sniffer/api.c
drivers: rename and reorganize config get/set
[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{
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{
1987b8d6 74 struct sr_config *src;
0aba65da
UH
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) {
1987b8d6
BV
92 src = l->data;
93 switch (src->key) {
1953564a 94 case SR_CONF_CONN:
1987b8d6 95 conn = src->value;
0aba65da 96 break;
1953564a 97 case SR_CONF_SERIALCOMM:
1987b8d6 98 serialcomm = src->value;
0aba65da
UH
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
035a1078 253static int config_get(int id, const void **data, const struct sr_dev_inst *sdi)
0aba65da
UH
254{
255 struct dev_context *devc;
256
035a1078 257 switch (id) {
aeabd308
UH
258 case SR_DI_HWOPTS:
259 *data = hwopts;
260 break;
0aba65da
UH
261 case SR_DI_HWCAPS:
262 *data = hwcaps;
263 break;
0aba65da
UH
264 case SR_DI_SAMPLERATES:
265 *data = &samplerates;
266 break;
267 case SR_DI_TRIGGER_TYPES:
268 *data = (char *)TRIGGER_TYPES;
269 break;
270 case SR_DI_CUR_SAMPLERATE:
271 if (sdi) {
272 devc = sdi->priv;
273 *data = &devc->cur_samplerate;
274 } else
275 return SR_ERR;
276 break;
277 default:
278 return SR_ERR_ARG;
279 }
280
281 return SR_OK;
282}
283
035a1078 284static int config_set(int id, const void *value, const struct sr_dev_inst *sdi)
0aba65da
UH
285{
286 struct dev_context *devc;
287 int ret;
288 const uint64_t *tmp_u64;
289
290 devc = sdi->priv;
291
292 if (sdi->status != SR_ST_ACTIVE)
293 return SR_ERR;
294
035a1078 295 switch (id) {
1953564a 296 case SR_CONF_SAMPLERATE:
0aba65da
UH
297 ret = ols_set_samplerate(sdi, *(const uint64_t *)value,
298 &samplerates);
299 break;
1953564a 300 case SR_CONF_LIMIT_SAMPLES:
0aba65da
UH
301 tmp_u64 = value;
302 if (*tmp_u64 < MIN_NUM_SAMPLES)
303 return SR_ERR;
304 if (*tmp_u64 > devc->max_samples)
305 sr_err("Sample limit exceeds hardware maximum.");
306 devc->limit_samples = *tmp_u64;
307 sr_info("Sample limit is %" PRIu64 ".", devc->limit_samples);
308 ret = SR_OK;
309 break;
1953564a 310 case SR_CONF_CAPTURE_RATIO:
0aba65da
UH
311 devc->capture_ratio = *(const uint64_t *)value;
312 if (devc->capture_ratio < 0 || devc->capture_ratio > 100) {
313 devc->capture_ratio = 0;
314 ret = SR_ERR;
315 } else
316 ret = SR_OK;
317 break;
1953564a 318 case SR_CONF_RLE:
0aba65da
UH
319 if (GPOINTER_TO_INT(value)) {
320 sr_info("Enabling RLE.");
321 devc->flag_reg |= FLAG_RLE;
322 }
323 ret = SR_OK;
324 break;
325 default:
326 ret = SR_ERR;
327 }
328
329 return ret;
330}
331
332static int hw_dev_acquisition_start(const struct sr_dev_inst *sdi,
333 void *cb_data)
334{
335 struct sr_datafeed_packet *packet;
336 struct sr_datafeed_header *header;
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
458 sr_source_add(devc->serial->fd, G_IO_IN, -1, ols_receive_data,
459 cb_data);
460
461 if (!(packet = g_try_malloc(sizeof(struct sr_datafeed_packet)))) {
462 sr_err("Datafeed packet malloc failed.");
463 return SR_ERR_MALLOC;
464 }
465
466 if (!(header = g_try_malloc(sizeof(struct sr_datafeed_header)))) {
467 sr_err("Datafeed header malloc failed.");
468 g_free(packet);
469 return SR_ERR_MALLOC;
470 }
471
472 /* Send header packet to the session bus. */
473 packet->type = SR_DF_HEADER;
474 packet->payload = (unsigned char *)header;
475 header->feed_version = 1;
476 gettimeofday(&header->starttime, NULL);
477 sr_session_send(cb_data, packet);
478
0aba65da
UH
479 g_free(header);
480 g_free(packet);
481
482 return SR_OK;
483}
484
485/* TODO: This stops acquisition on ALL devices, ignoring dev_index. */
486static int hw_dev_acquisition_stop(struct sr_dev_inst *sdi, void *cb_data)
487{
488 /* Avoid compiler warnings. */
489 (void)cb_data;
490
491 abort_acquisition(sdi);
492
493 return SR_OK;
494}
495
496SR_PRIV struct sr_dev_driver ols_driver_info = {
497 .name = "ols",
498 .longname = "Openbench Logic Sniffer",
499 .api_version = 1,
500 .init = hw_init,
501 .cleanup = hw_cleanup,
502 .scan = hw_scan,
503 .dev_list = hw_dev_list,
504 .dev_clear = hw_cleanup,
035a1078
BV
505 .config_get = config_get,
506 .config_set = config_set,
0aba65da
UH
507 .dev_open = hw_dev_open,
508 .dev_close = hw_dev_close,
0aba65da
UH
509 .dev_acquisition_start = hw_dev_acquisition_start,
510 .dev_acquisition_stop = hw_dev_acquisition_stop,
511 .priv = NULL,
512};