]> sigrok.org Git - libsigrok.git/blame - hardware/openbench-logic-sniffer/api.c
serial-dmm: Add UNI-T UT61E support (UT-D02 cable).
[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
24static const int hwcaps[] = {
25 SR_HWCAP_LOGIC_ANALYZER,
26 SR_HWCAP_SAMPLERATE,
27 SR_HWCAP_CAPTURE_RATIO,
28 SR_HWCAP_LIMIT_SAMPLES,
29 SR_HWCAP_RLE,
30 0,
31};
32
33/* Probes are numbered 0-31 (on the PCB silkscreen). */
34SR_PRIV const char *ols_probe_names[NUM_PROBES + 1] = {
78693401
UH
35 "0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12",
36 "13", "14", "15", "16", "17", "18", "19", "20", "21", "22", "23",
37 "24", "25", "26", "27", "28", "29", "30", "31",
0aba65da
UH
38 NULL,
39};
40
41/* default supported samplerates, can be overridden by device metadata */
42static const struct sr_samplerates samplerates = {
43 SR_HZ(10),
44 SR_MHZ(200),
45 SR_HZ(1),
46 NULL,
47};
48
49SR_PRIV struct sr_dev_driver ols_driver_info;
50static struct sr_dev_driver *di = &ols_driver_info;
51
52static int hw_init(struct sr_context *sr_ctx)
53{
54 struct drv_context *drvc;
55
56 if (!(drvc = g_try_malloc0(sizeof(struct drv_context)))) {
57 sr_err("Driver context malloc failed.");
58 return SR_ERR_MALLOC;
59 }
60 drvc->sr_ctx = sr_ctx;
61 di->priv = drvc;
62
63 return SR_OK;
64}
65
66static GSList *hw_scan(GSList *options)
67{
68 struct sr_hwopt *opt;
69 struct sr_dev_inst *sdi;
70 struct drv_context *drvc;
71 struct dev_context *devc;
72 struct sr_probe *probe;
73 struct sr_serial_dev_inst *serial;
74 GPollFD probefd;
75 GSList *l, *devices;
76 int ret, i;
77 const char *conn, *serialcomm;
78 char buf[8];
79
80 (void)options;
81 drvc = di->priv;
82 devices = NULL;
83
84 conn = serialcomm = NULL;
85 for (l = options; l; l = l->next) {
86 opt = l->data;
87 switch (opt->hwopt) {
88 case SR_HWOPT_CONN:
89 conn = opt->value;
90 break;
91 case SR_HWOPT_SERIALCOMM:
92 serialcomm = opt->value;
93 break;
94 }
95 }
96 if (!conn)
97 return NULL;
98
99 if (serialcomm == NULL)
100 serialcomm = SERIALCOMM;
101
102 if (!(serial = sr_serial_dev_inst_new(conn, serialcomm)))
103 return NULL;
104
105 /* The discovery procedure is like this: first send the Reset
106 * command (0x00) 5 times, since the device could be anywhere
107 * in a 5-byte command. Then send the ID command (0x02).
108 * If the device responds with 4 bytes ("OLS1" or "SLA1"), we
109 * have a match.
110 */
111 sr_info("Probing %s.", conn);
112 if (serial_open(serial, SERIAL_RDWR | SERIAL_NONBLOCK) != SR_OK)
113 return NULL;
114
115 ret = SR_OK;
116 for (i = 0; i < 5; i++) {
117 if ((ret = send_shortcommand(serial, CMD_RESET)) != SR_OK) {
118 sr_err("Port %s is not writable.", conn);
119 break;
120 }
121 }
122 if (ret != SR_OK) {
123 serial_close(serial);
124 sr_err("Could not use port %s. Quitting.", conn);
125 return NULL;
126 }
127 send_shortcommand(serial, CMD_ID);
128
129 /* Wait 10ms for a response. */
130 g_usleep(10000);
131
132 probefd.fd = serial->fd;
133 probefd.events = G_IO_IN;
134 g_poll(&probefd, 1, 1);
135
136 if (probefd.revents != G_IO_IN)
137 return NULL;
138 if (serial_read(serial, buf, 4) != 4)
139 return NULL;
140 if (strncmp(buf, "1SLO", 4) && strncmp(buf, "1ALS", 4))
141 return NULL;
142
143 /* Definitely using the OLS protocol, check if it supports
144 * the metadata command.
145 */
146 send_shortcommand(serial, CMD_METADATA);
147 if (g_poll(&probefd, 1, 10) > 0) {
148 /* Got metadata. */
149 sdi = get_metadata(serial);
150 sdi->index = 0;
151 devc = sdi->priv;
152 } else {
153 /* Not an OLS -- some other board that uses the sump protocol. */
154 sdi = sr_dev_inst_new(0, SR_ST_INACTIVE,
155 "Sump", "Logic Analyzer", "v1.0");
156 sdi->driver = di;
157 devc = ols_dev_new();
158 for (i = 0; i < 32; i++) {
159 if (!(probe = sr_probe_new(i, SR_PROBE_LOGIC, TRUE,
160 ols_probe_names[i])))
161 return 0;
162 sdi->probes = g_slist_append(sdi->probes, probe);
163 }
164 sdi->priv = devc;
165 }
166 devc->serial = serial;
167 drvc->instances = g_slist_append(drvc->instances, sdi);
168 devices = g_slist_append(devices, sdi);
169
170 serial_close(serial);
171
172 return devices;
173}
174
175static GSList *hw_dev_list(void)
176{
177 struct drv_context *drvc;
178
179 drvc = di->priv;
180
181 return drvc->instances;
182}
183
184static int hw_dev_open(struct sr_dev_inst *sdi)
185{
186 struct dev_context *devc;
187
188 devc = sdi->priv;
189
190 if (serial_open(devc->serial, SERIAL_RDWR) != SR_OK)
191 return SR_ERR;
192
193 sdi->status = SR_ST_ACTIVE;
194
195 return SR_OK;
196}
197
198static int hw_dev_close(struct sr_dev_inst *sdi)
199{
200 struct dev_context *devc;
201
202 devc = sdi->priv;
203
204 if (devc->serial && devc->serial->fd != -1) {
205 serial_close(devc->serial);
206 sdi->status = SR_ST_INACTIVE;
207 }
208
209 return SR_OK;
210}
211
212static int hw_cleanup(void)
213{
214 GSList *l;
215 struct sr_dev_inst *sdi;
216 struct drv_context *drvc;
217 struct dev_context *devc;
218 int ret = SR_OK;
219
220 if (!(drvc = di->priv))
221 return SR_OK;
222
223 /* Properly close and free all devices. */
224 for (l = drvc->instances; l; l = l->next) {
225 if (!(sdi = l->data)) {
226 /* Log error, but continue cleaning up the rest. */
227 sr_err("%s: sdi was NULL, continuing", __func__);
228 ret = SR_ERR_BUG;
229 continue;
230 }
231 if (!(devc = sdi->priv)) {
232 /* Log error, but continue cleaning up the rest. */
233 sr_err("%s: sdi->priv was NULL, continuing", __func__);
234 ret = SR_ERR_BUG;
235 continue;
236 }
237 hw_dev_close(sdi);
238 sr_serial_dev_inst_free(devc->serial);
239 sr_dev_inst_free(sdi);
240 }
241 g_slist_free(drvc->instances);
242 drvc->instances = NULL;
243
244 return ret;
245}
246
247static int hw_info_get(int info_id, const void **data,
248 const struct sr_dev_inst *sdi)
249{
250 struct dev_context *devc;
251
252 switch (info_id) {
253 case SR_DI_HWCAPS:
254 *data = hwcaps;
255 break;
256 case SR_DI_NUM_PROBES:
257 *data = GINT_TO_POINTER(1);
258 break;
259 case SR_DI_PROBE_NAMES:
260 *data = ols_probe_names;
261 break;
262 case SR_DI_SAMPLERATES:
263 *data = &samplerates;
264 break;
265 case SR_DI_TRIGGER_TYPES:
266 *data = (char *)TRIGGER_TYPES;
267 break;
268 case SR_DI_CUR_SAMPLERATE:
269 if (sdi) {
270 devc = sdi->priv;
271 *data = &devc->cur_samplerate;
272 } else
273 return SR_ERR;
274 break;
275 default:
276 return SR_ERR_ARG;
277 }
278
279 return SR_OK;
280}
281
282static int hw_dev_config_set(const struct sr_dev_inst *sdi, int hwcap,
283 const void *value)
284{
285 struct dev_context *devc;
286 int ret;
287 const uint64_t *tmp_u64;
288
289 devc = sdi->priv;
290
291 if (sdi->status != SR_ST_ACTIVE)
292 return SR_ERR;
293
294 switch (hwcap) {
295 case SR_HWCAP_SAMPLERATE:
296 ret = ols_set_samplerate(sdi, *(const uint64_t *)value,
297 &samplerates);
298 break;
299 case SR_HWCAP_LIMIT_SAMPLES:
300 tmp_u64 = value;
301 if (*tmp_u64 < MIN_NUM_SAMPLES)
302 return SR_ERR;
303 if (*tmp_u64 > devc->max_samples)
304 sr_err("Sample limit exceeds hardware maximum.");
305 devc->limit_samples = *tmp_u64;
306 sr_info("Sample limit is %" PRIu64 ".", devc->limit_samples);
307 ret = SR_OK;
308 break;
309 case SR_HWCAP_CAPTURE_RATIO:
310 devc->capture_ratio = *(const uint64_t *)value;
311 if (devc->capture_ratio < 0 || devc->capture_ratio > 100) {
312 devc->capture_ratio = 0;
313 ret = SR_ERR;
314 } else
315 ret = SR_OK;
316 break;
317 case SR_HWCAP_RLE:
318 if (GPOINTER_TO_INT(value)) {
319 sr_info("Enabling RLE.");
320 devc->flag_reg |= FLAG_RLE;
321 }
322 ret = SR_OK;
323 break;
324 default:
325 ret = SR_ERR;
326 }
327
328 return ret;
329}
330
331static int hw_dev_acquisition_start(const struct sr_dev_inst *sdi,
332 void *cb_data)
333{
334 struct sr_datafeed_packet *packet;
335 struct sr_datafeed_header *header;
336 struct sr_datafeed_meta_logic meta;
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
479 /* Send metadata about the SR_DF_LOGIC packets to come. */
480 packet->type = SR_DF_META_LOGIC;
481 packet->payload = &meta;
482 meta.samplerate = devc->cur_samplerate;
483 meta.num_probes = NUM_PROBES;
484 sr_session_send(cb_data, packet);
485
486 g_free(header);
487 g_free(packet);
488
489 return SR_OK;
490}
491
492/* TODO: This stops acquisition on ALL devices, ignoring dev_index. */
493static int hw_dev_acquisition_stop(struct sr_dev_inst *sdi, void *cb_data)
494{
495 /* Avoid compiler warnings. */
496 (void)cb_data;
497
498 abort_acquisition(sdi);
499
500 return SR_OK;
501}
502
503SR_PRIV struct sr_dev_driver ols_driver_info = {
504 .name = "ols",
505 .longname = "Openbench Logic Sniffer",
506 .api_version = 1,
507 .init = hw_init,
508 .cleanup = hw_cleanup,
509 .scan = hw_scan,
510 .dev_list = hw_dev_list,
511 .dev_clear = hw_cleanup,
512 .dev_open = hw_dev_open,
513 .dev_close = hw_dev_close,
514 .info_get = hw_info_get,
515 .dev_config_set = hw_dev_config_set,
516 .dev_acquisition_start = hw_dev_acquisition_start,
517 .dev_acquisition_stop = hw_dev_acquisition_stop,
518 .priv = NULL,
519};