]> sigrok.org Git - libsigrok.git/blame - hardware/openbench-logic-sniffer/api.c
Get rid of obsolete SR_DI_NUM_PROBES and SR_DI_PROBE_NAMES.
[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;
0aba65da
UH
265 case SR_DI_SAMPLERATES:
266 *data = &samplerates;
267 break;
268 case SR_DI_TRIGGER_TYPES:
269 *data = (char *)TRIGGER_TYPES;
270 break;
271 case SR_DI_CUR_SAMPLERATE:
272 if (sdi) {
273 devc = sdi->priv;
274 *data = &devc->cur_samplerate;
275 } else
276 return SR_ERR;
277 break;
278 default:
279 return SR_ERR_ARG;
280 }
281
282 return SR_OK;
283}
284
285static int hw_dev_config_set(const struct sr_dev_inst *sdi, int hwcap,
286 const void *value)
287{
288 struct dev_context *devc;
289 int ret;
290 const uint64_t *tmp_u64;
291
292 devc = sdi->priv;
293
294 if (sdi->status != SR_ST_ACTIVE)
295 return SR_ERR;
296
297 switch (hwcap) {
298 case SR_HWCAP_SAMPLERATE:
299 ret = ols_set_samplerate(sdi, *(const uint64_t *)value,
300 &samplerates);
301 break;
302 case SR_HWCAP_LIMIT_SAMPLES:
303 tmp_u64 = value;
304 if (*tmp_u64 < MIN_NUM_SAMPLES)
305 return SR_ERR;
306 if (*tmp_u64 > devc->max_samples)
307 sr_err("Sample limit exceeds hardware maximum.");
308 devc->limit_samples = *tmp_u64;
309 sr_info("Sample limit is %" PRIu64 ".", devc->limit_samples);
310 ret = SR_OK;
311 break;
312 case SR_HWCAP_CAPTURE_RATIO:
313 devc->capture_ratio = *(const uint64_t *)value;
314 if (devc->capture_ratio < 0 || devc->capture_ratio > 100) {
315 devc->capture_ratio = 0;
316 ret = SR_ERR;
317 } else
318 ret = SR_OK;
319 break;
320 case SR_HWCAP_RLE:
321 if (GPOINTER_TO_INT(value)) {
322 sr_info("Enabling RLE.");
323 devc->flag_reg |= FLAG_RLE;
324 }
325 ret = SR_OK;
326 break;
327 default:
328 ret = SR_ERR;
329 }
330
331 return ret;
332}
333
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;
339 struct sr_datafeed_meta_logic meta;
340 struct dev_context *devc;
341 uint32_t trigger_config[4];
342 uint32_t data;
343 uint16_t readcount, delaycount;
344 uint8_t changrp_mask;
345 int num_channels;
346 int i;
347
348 devc = sdi->priv;
349
350 if (sdi->status != SR_ST_ACTIVE)
351 return SR_ERR;
352
353 if (ols_configure_probes(sdi) != SR_OK) {
354 sr_err("Failed to configure probes.");
355 return SR_ERR;
356 }
357
358 /*
359 * Enable/disable channel groups in the flag register according to the
360 * probe mask. Calculate this here, because num_channels is needed
361 * to limit readcount.
362 */
363 changrp_mask = 0;
364 num_channels = 0;
365 for (i = 0; i < 4; i++) {
366 if (devc->probe_mask & (0xff << (i * 8))) {
367 changrp_mask |= (1 << i);
368 num_channels++;
369 }
370 }
371
372 /*
373 * Limit readcount to prevent reading past the end of the hardware
374 * buffer.
375 */
376 readcount = MIN(devc->max_samples / num_channels, devc->limit_samples) / 4;
377
378 memset(trigger_config, 0, 16);
379 trigger_config[devc->num_stages - 1] |= 0x08;
380 if (devc->trigger_mask[0]) {
381 delaycount = readcount * (1 - devc->capture_ratio / 100.0);
382 devc->trigger_at = (readcount - delaycount) * 4 - devc->num_stages;
383
384 if (send_longcommand(devc->serial, CMD_SET_TRIGGER_MASK_0,
385 reverse32(devc->trigger_mask[0])) != SR_OK)
386 return SR_ERR;
387 if (send_longcommand(devc->serial, CMD_SET_TRIGGER_VALUE_0,
388 reverse32(devc->trigger_value[0])) != SR_OK)
389 return SR_ERR;
390 if (send_longcommand(devc->serial, CMD_SET_TRIGGER_CONFIG_0,
391 trigger_config[0]) != SR_OK)
392 return SR_ERR;
393
394 if (send_longcommand(devc->serial, CMD_SET_TRIGGER_MASK_1,
395 reverse32(devc->trigger_mask[1])) != SR_OK)
396 return SR_ERR;
397 if (send_longcommand(devc->serial, CMD_SET_TRIGGER_VALUE_1,
398 reverse32(devc->trigger_value[1])) != SR_OK)
399 return SR_ERR;
400 if (send_longcommand(devc->serial, CMD_SET_TRIGGER_CONFIG_1,
401 trigger_config[1]) != SR_OK)
402 return SR_ERR;
403
404 if (send_longcommand(devc->serial, CMD_SET_TRIGGER_MASK_2,
405 reverse32(devc->trigger_mask[2])) != SR_OK)
406 return SR_ERR;
407 if (send_longcommand(devc->serial, CMD_SET_TRIGGER_VALUE_2,
408 reverse32(devc->trigger_value[2])) != SR_OK)
409 return SR_ERR;
410 if (send_longcommand(devc->serial, CMD_SET_TRIGGER_CONFIG_2,
411 trigger_config[2]) != SR_OK)
412 return SR_ERR;
413
414 if (send_longcommand(devc->serial, CMD_SET_TRIGGER_MASK_3,
415 reverse32(devc->trigger_mask[3])) != SR_OK)
416 return SR_ERR;
417 if (send_longcommand(devc->serial, CMD_SET_TRIGGER_VALUE_3,
418 reverse32(devc->trigger_value[3])) != SR_OK)
419 return SR_ERR;
420 if (send_longcommand(devc->serial, CMD_SET_TRIGGER_CONFIG_3,
421 trigger_config[3]) != SR_OK)
422 return SR_ERR;
423 } else {
424 if (send_longcommand(devc->serial, CMD_SET_TRIGGER_MASK_0,
425 devc->trigger_mask[0]) != SR_OK)
426 return SR_ERR;
427 if (send_longcommand(devc->serial, CMD_SET_TRIGGER_VALUE_0,
428 devc->trigger_value[0]) != SR_OK)
429 return SR_ERR;
430 if (send_longcommand(devc->serial, CMD_SET_TRIGGER_CONFIG_0,
431 0x00000008) != SR_OK)
432 return SR_ERR;
433 delaycount = readcount;
434 }
435
436 sr_info("Setting samplerate to %" PRIu64 "Hz (divider %u, "
437 "demux %s)", devc->cur_samplerate, devc->cur_samplerate_divider,
438 devc->flag_reg & FLAG_DEMUX ? "on" : "off");
439 if (send_longcommand(devc->serial, CMD_SET_DIVIDER,
440 reverse32(devc->cur_samplerate_divider)) != SR_OK)
441 return SR_ERR;
442
443 /* Send sample limit and pre/post-trigger capture ratio. */
444 data = ((readcount - 1) & 0xffff) << 16;
445 data |= (delaycount - 1) & 0xffff;
446 if (send_longcommand(devc->serial, CMD_CAPTURE_SIZE, reverse16(data)) != SR_OK)
447 return SR_ERR;
448
449 /* The flag register wants them here, and 1 means "disable channel". */
450 devc->flag_reg |= ~(changrp_mask << 2) & 0x3c;
451 devc->flag_reg |= FLAG_FILTER;
452 devc->rle_count = 0;
453 data = (devc->flag_reg << 24) | ((devc->flag_reg << 8) & 0xff0000);
454 if (send_longcommand(devc->serial, CMD_SET_FLAGS, data) != SR_OK)
455 return SR_ERR;
456
457 /* Start acquisition on the device. */
458 if (send_shortcommand(devc->serial, CMD_RUN) != SR_OK)
459 return SR_ERR;
460
461 sr_source_add(devc->serial->fd, G_IO_IN, -1, ols_receive_data,
462 cb_data);
463
464 if (!(packet = g_try_malloc(sizeof(struct sr_datafeed_packet)))) {
465 sr_err("Datafeed packet malloc failed.");
466 return SR_ERR_MALLOC;
467 }
468
469 if (!(header = g_try_malloc(sizeof(struct sr_datafeed_header)))) {
470 sr_err("Datafeed header malloc failed.");
471 g_free(packet);
472 return SR_ERR_MALLOC;
473 }
474
475 /* Send header packet to the session bus. */
476 packet->type = SR_DF_HEADER;
477 packet->payload = (unsigned char *)header;
478 header->feed_version = 1;
479 gettimeofday(&header->starttime, NULL);
480 sr_session_send(cb_data, packet);
481
482 /* Send metadata about the SR_DF_LOGIC packets to come. */
483 packet->type = SR_DF_META_LOGIC;
484 packet->payload = &meta;
485 meta.samplerate = devc->cur_samplerate;
486 meta.num_probes = NUM_PROBES;
487 sr_session_send(cb_data, packet);
488
489 g_free(header);
490 g_free(packet);
491
492 return SR_OK;
493}
494
495/* TODO: This stops acquisition on ALL devices, ignoring dev_index. */
496static int hw_dev_acquisition_stop(struct sr_dev_inst *sdi, void *cb_data)
497{
498 /* Avoid compiler warnings. */
499 (void)cb_data;
500
501 abort_acquisition(sdi);
502
503 return SR_OK;
504}
505
506SR_PRIV struct sr_dev_driver ols_driver_info = {
507 .name = "ols",
508 .longname = "Openbench Logic Sniffer",
509 .api_version = 1,
510 .init = hw_init,
511 .cleanup = hw_cleanup,
512 .scan = hw_scan,
513 .dev_list = hw_dev_list,
514 .dev_clear = hw_cleanup,
515 .dev_open = hw_dev_open,
516 .dev_close = hw_dev_close,
517 .info_get = hw_info_get,
518 .dev_config_set = hw_dev_config_set,
519 .dev_acquisition_start = hw_dev_acquisition_start,
520 .dev_acquisition_stop = hw_dev_acquisition_stop,
521 .priv = NULL,
522};