]> sigrok.org Git - libsigrok.git/blame - src/hardware/openbench-logic-sniffer/api.c
ols: move device context creation from protocol.c to api.c
[libsigrok.git] / src / hardware / openbench-logic-sniffer / api.c
CommitLineData
0aba65da 1/*
50985c20 2 * This file is part of the libsigrok project.
0aba65da 3 *
13d8e03c 4 * Copyright (C) 2013 Bert Vermeulen <bert@biot.com>
0aba65da
UH
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
6ec6c43b 20#include <config.h>
515ab088 21#include "protocol.h"
0aba65da
UH
22
23#define SERIALCOMM "115200/8n1"
24
a0e0bb41 25static const uint32_t scanopts[] = {
1953564a
BV
26 SR_CONF_CONN,
27 SR_CONF_SERIALCOMM,
aeabd308
UH
28};
29
55fb76b3
UH
30static const uint32_t drvopts[] = {
31 SR_CONF_LOGIC_ANALYZER,
32};
33
f254bc4b 34static const uint32_t devopts[] = {
2f67be51 35 SR_CONF_CONN | SR_CONF_GET,
5827f61b
BV
36 SR_CONF_LIMIT_SAMPLES | SR_CONF_GET | SR_CONF_SET | SR_CONF_LIST,
37 SR_CONF_SAMPLERATE | SR_CONF_GET | SR_CONF_SET | SR_CONF_LIST,
38 SR_CONF_TRIGGER_MATCH | SR_CONF_LIST,
39 SR_CONF_CAPTURE_RATIO | SR_CONF_GET | SR_CONF_SET,
50b15953 40 SR_CONF_EXTERNAL_CLOCK | SR_CONF_GET | SR_CONF_SET,
f20c39d9 41 SR_CONF_CLOCK_EDGE | SR_CONF_GET | SR_CONF_SET | SR_CONF_LIST,
5827f61b
BV
42 SR_CONF_PATTERN_MODE | SR_CONF_GET | SR_CONF_SET | SR_CONF_LIST,
43 SR_CONF_SWAP | SR_CONF_SET,
44 SR_CONF_RLE | SR_CONF_GET | SR_CONF_SET,
0aba65da
UH
45};
46
91fd0f72
BV
47static const int32_t trigger_matches[] = {
48 SR_TRIGGER_ZERO,
49 SR_TRIGGER_ONE,
50};
51
55eca716 52static const char *external_clock_edges[] = {
53 "rising", /* positive edge */
54 "falling" /* negative edge */
f20c39d9 55};
56
6d16fdfb
BV
57#define STR_PATTERN_NONE "None"
58#define STR_PATTERN_EXTERNAL "External"
59#define STR_PATTERN_INTERNAL "Internal"
967760a8
MR
60
61/* Supported methods of test pattern outputs */
62enum {
63 /**
64 * Capture pins 31:16 (unbuffered wing) output a test pattern
65 * that can captured on pins 0:15.
66 */
67 PATTERN_EXTERNAL,
68
69 /** Route test pattern internally to capture buffer. */
70 PATTERN_INTERNAL,
71};
72
7c07a178 73static const char *patterns[] = {
6d16fdfb 74 STR_PATTERN_NONE,
7c07a178
UH
75 STR_PATTERN_EXTERNAL,
76 STR_PATTERN_INTERNAL,
77};
78
ba7dd8bb 79/* Channels are numbered 0-31 (on the PCB silkscreen). */
53cda65a 80SR_PRIV const char *ols_channel_names[] = {
78693401
UH
81 "0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12",
82 "13", "14", "15", "16", "17", "18", "19", "20", "21", "22", "23",
83 "24", "25", "26", "27", "28", "29", "30", "31",
0aba65da
UH
84};
85
d3b38ad3 86/* Default supported samplerates, can be overridden by device metadata. */
e46aa4f6
BV
87static const uint64_t samplerates[] = {
88 SR_HZ(10),
89 SR_MHZ(200),
90 SR_HZ(1),
0aba65da
UH
91};
92
ae4e6999 93#define RESPONSE_DELAY_US (20 * 1000)
1a46cc62 94
4f840ce9 95static GSList *scan(struct sr_dev_driver *di, GSList *options)
0aba65da 96{
1987b8d6 97 struct sr_config *src;
0aba65da 98 struct sr_dev_inst *sdi;
0aba65da 99 struct sr_serial_dev_inst *serial;
43376f33 100 GSList *l;
35be304b 101 int num_read;
07ffa5b3 102 unsigned int i;
0aba65da 103 const char *conn, *serialcomm;
35be304b 104 char buf[4] = { 0, 0, 0, 0 };
838f0122 105 struct dev_context *devc;
0aba65da 106
0aba65da
UH
107 conn = serialcomm = NULL;
108 for (l = options; l; l = l->next) {
1987b8d6
BV
109 src = l->data;
110 switch (src->key) {
1953564a 111 case SR_CONF_CONN:
e46aa4f6 112 conn = g_variant_get_string(src->data, NULL);
0aba65da 113 break;
1953564a 114 case SR_CONF_SERIALCOMM:
e46aa4f6 115 serialcomm = g_variant_get_string(src->data, NULL);
0aba65da
UH
116 break;
117 }
118 }
119 if (!conn)
120 return NULL;
121
98fec29e 122 if (!serialcomm)
0aba65da
UH
123 serialcomm = SERIALCOMM;
124
91219afc 125 serial = sr_serial_dev_inst_new(conn, serialcomm);
0aba65da
UH
126
127 /* The discovery procedure is like this: first send the Reset
128 * command (0x00) 5 times, since the device could be anywhere
129 * in a 5-byte command. Then send the ID command (0x02).
130 * If the device responds with 4 bytes ("OLS1" or "SLA1"), we
131 * have a match.
132 */
133 sr_info("Probing %s.", conn);
4ded59ee 134 if (serial_open(serial, SERIAL_RDWR) != SR_OK)
0aba65da
UH
135 return NULL;
136
244995a2 137 if (ols_send_reset(serial) != SR_OK) {
0aba65da
UH
138 serial_close(serial);
139 sr_err("Could not use port %s. Quitting.", conn);
140 return NULL;
141 }
142 send_shortcommand(serial, CMD_ID);
143
1a46cc62 144 g_usleep(RESPONSE_DELAY_US);
0aba65da 145
f9921513 146 if (serial_has_receive_data(serial) == 0) {
35be304b 147 sr_dbg("Didn't get any ID reply.");
0aba65da 148 return NULL;
ed936ccc
UH
149 }
150
55eca716 151 num_read =
152 serial_read_blocking(serial, buf, 4, serial_timeout(serial, 4));
35be304b
WS
153 if (num_read < 0) {
154 sr_err("Getting ID reply failed (%d).", num_read);
0aba65da 155 return NULL;
ed936ccc
UH
156 }
157
158 if (strncmp(buf, "1SLO", 4) && strncmp(buf, "1ALS", 4)) {
35be304b
WS
159 GString *id = sr_hexdump_new((uint8_t *)buf, num_read);
160
161 sr_err("Invalid ID reply (got %s).", id->str);
162
163 sr_hexdump_free(id);
0aba65da 164 return NULL;
163da55b
GS
165 } else {
166 sr_dbg("Successful detection, got '%c%c%c%c' (0x%02x 0x%02x 0x%02x 0x%02x).",
167 buf[0], buf[1], buf[2], buf[3],
168 buf[0], buf[1], buf[2], buf[3]);
ed936ccc 169 }
0aba65da 170
838f0122
GS
171 /*
172 * Create common data structures (sdi, devc) here in the common
173 * code path. These further get filled in either from metadata
174 * which is gathered from the device, or from open coded generic
175 * fallback data which is kept in the driver source code.
176 */
177 sdi = g_malloc0(sizeof(*sdi));
178 sdi->status = SR_ST_INACTIVE;
179 sdi->inst_type = SR_INST_SERIAL;
180 sdi->conn = serial;
181 sdi->connection_id = g_strdup(serial->port);
182 devc = g_malloc0(sizeof(*devc));
183 sdi->priv = devc;
184 devc->trigger_at_smpl = OLS_NO_TRIGGER;
185
186 /*
187 * Definitely using the OLS protocol, check if it supports
0aba65da
UH
188 * the metadata command.
189 */
190 send_shortcommand(serial, CMD_METADATA);
1a46cc62 191 g_usleep(RESPONSE_DELAY_US);
f9921513 192 if (serial_has_receive_data(serial) != 0) {
0aba65da 193 /* Got metadata. */
838f0122 194 (void)ols_get_metadata(sdi);
0aba65da
UH
195 } else {
196 /* Not an OLS -- some other board that uses the sump protocol. */
72cd99b8 197 sr_info("Device does not support metadata.");
0af636be
UH
198 sdi->vendor = g_strdup("Sump");
199 sdi->model = g_strdup("Logic Analyzer");
200 sdi->version = g_strdup("v1.0");
07ffa5b3 201 for (i = 0; i < ARRAY_SIZE(ols_channel_names); i++)
5e23fcab 202 sr_channel_new(sdi, i, SR_CHANNEL_LOGIC, TRUE,
55eca716 203 ols_channel_names[i]);
0aba65da 204 }
bf256783
BV
205 /* Configure samplerate and divider. */
206 if (ols_set_samplerate(sdi, DEFAULT_SAMPLERATE) != SR_OK)
55eca716 207 sr_dbg("Failed to set default samplerate (%" PRIu64 ").",
208 DEFAULT_SAMPLERATE);
bf256783 209
0aba65da
UH
210 serial_close(serial);
211
43376f33 212 return std_scan_complete(di, g_slist_append(NULL, sdi));
0aba65da
UH
213}
214
dd7a72ea 215static int config_get(uint32_t key, GVariant **data,
55eca716 216 const struct sr_dev_inst *sdi,
217 const struct sr_channel_group *cg)
0aba65da
UH
218{
219 struct dev_context *devc;
220
53b4680f 221 (void)cg;
8f996b89 222
0c05591a
BV
223 if (!sdi)
224 return SR_ERR_ARG;
225
226 devc = sdi->priv;
758906aa 227
584560f1 228 switch (key) {
2f67be51
GS
229 case SR_CONF_CONN:
230 if (!sdi->conn || !sdi->connection_id)
231 return SR_ERR_NA;
232 *data = g_variant_new_string(sdi->connection_id);
233 break;
123e1313 234 case SR_CONF_SAMPLERATE:
0c05591a
BV
235 *data = g_variant_new_uint64(devc->cur_samplerate);
236 break;
237 case SR_CONF_CAPTURE_RATIO:
238 *data = g_variant_new_uint64(devc->capture_ratio);
239 break;
240 case SR_CONF_LIMIT_SAMPLES:
241 *data = g_variant_new_uint64(devc->limit_samples);
242 break;
967760a8 243 case SR_CONF_PATTERN_MODE:
a80bed76 244 if (devc->capture_flags & CAPTURE_FLAG_EXTERNAL_TEST_MODE)
967760a8 245 *data = g_variant_new_string(STR_PATTERN_EXTERNAL);
a80bed76 246 else if (devc->capture_flags & CAPTURE_FLAG_INTERNAL_TEST_MODE)
967760a8 247 *data = g_variant_new_string(STR_PATTERN_INTERNAL);
6d16fdfb
BV
248 else
249 *data = g_variant_new_string(STR_PATTERN_NONE);
967760a8 250 break;
0c05591a 251 case SR_CONF_RLE:
55eca716 252 *data = g_variant_new_boolean(
253 devc->capture_flags & CAPTURE_FLAG_RLE ? TRUE : FALSE);
7730e4f0 254 break;
50b15953 255 case SR_CONF_EXTERNAL_CLOCK:
256 *data = g_variant_new_boolean(
55eca716 257 devc->capture_flags & CAPTURE_FLAG_CLOCK_EXTERNAL
258 ? TRUE : FALSE);
50b15953 259 break;
f20c39d9 260 case SR_CONF_CLOCK_EDGE:
261 *data = g_variant_new_string(external_clock_edges[
55eca716 262 devc->capture_flags & CAPTURE_FLAG_INVERT_EXT_CLOCK
263 ? 1 : 0]);
f20c39d9 264 break;
0aba65da 265 default:
bd6fbf62 266 return SR_ERR_NA;
0aba65da
UH
267 }
268
269 return SR_OK;
270}
271
dd7a72ea 272static int config_set(uint32_t key, GVariant *data,
55eca716 273 const struct sr_dev_inst *sdi,
274 const struct sr_channel_group *cg)
0aba65da
UH
275{
276 struct dev_context *devc;
6d16fdfb 277 uint16_t flag;
e46aa4f6 278 uint64_t tmp_u64;
967760a8 279 const char *stropt;
0aba65da 280
53b4680f 281 (void)cg;
8f996b89 282
0aba65da
UH
283 devc = sdi->priv;
284
584560f1 285 switch (key) {
1953564a 286 case SR_CONF_SAMPLERATE:
e46aa4f6
BV
287 tmp_u64 = g_variant_get_uint64(data);
288 if (tmp_u64 < samplerates[0] || tmp_u64 > samplerates[1])
289 return SR_ERR_SAMPLERATE;
758906aa 290 return ols_set_samplerate(sdi, g_variant_get_uint64(data));
1953564a 291 case SR_CONF_LIMIT_SAMPLES:
e46aa4f6
BV
292 tmp_u64 = g_variant_get_uint64(data);
293 if (tmp_u64 < MIN_NUM_SAMPLES)
0aba65da 294 return SR_ERR;
e46aa4f6 295 devc->limit_samples = tmp_u64;
0aba65da 296 break;
1953564a 297 case SR_CONF_CAPTURE_RATIO:
e46aa4f6 298 devc->capture_ratio = g_variant_get_uint64(data);
0aba65da 299 break;
eb1b610b
MR
300 case SR_CONF_EXTERNAL_CLOCK:
301 if (g_variant_get_boolean(data)) {
302 sr_info("Enabling external clock.");
a80bed76 303 devc->capture_flags |= CAPTURE_FLAG_CLOCK_EXTERNAL;
eb1b610b
MR
304 } else {
305 sr_info("Disabled external clock.");
a80bed76 306 devc->capture_flags &= ~CAPTURE_FLAG_CLOCK_EXTERNAL;
eb1b610b 307 }
eb1b610b 308 break;
f20c39d9 309 case SR_CONF_CLOCK_EDGE:
310 stropt = g_variant_get_string(data, NULL);
311 if (!strcmp(stropt, external_clock_edges[1])) {
312 sr_info("Triggering on falling edge of external clock.");
313 devc->capture_flags |= CAPTURE_FLAG_INVERT_EXT_CLOCK;
314 } else {
315 sr_info("Triggering on rising edge of external clock.");
316 devc->capture_flags &= ~CAPTURE_FLAG_INVERT_EXT_CLOCK;
317 }
318 break;
967760a8
MR
319 case SR_CONF_PATTERN_MODE:
320 stropt = g_variant_get_string(data, NULL);
6d16fdfb
BV
321 if (!strcmp(stropt, STR_PATTERN_NONE)) {
322 sr_info("Disabling test modes.");
323 flag = 0x0000;
758906aa 324 } else if (!strcmp(stropt, STR_PATTERN_INTERNAL)) {
967760a8 325 sr_info("Enabling internal test mode.");
a80bed76 326 flag = CAPTURE_FLAG_INTERNAL_TEST_MODE;
967760a8
MR
327 } else if (!strcmp(stropt, STR_PATTERN_EXTERNAL)) {
328 sr_info("Enabling external test mode.");
a80bed76 329 flag = CAPTURE_FLAG_EXTERNAL_TEST_MODE;
967760a8 330 } else {
758906aa 331 return SR_ERR;
967760a8 332 }
a80bed76 333 devc->capture_flags &= ~CAPTURE_FLAG_INTERNAL_TEST_MODE;
334 devc->capture_flags &= ~CAPTURE_FLAG_EXTERNAL_TEST_MODE;
335 devc->capture_flags |= flag;
967760a8 336 break;
7b0a57fd
MR
337 case SR_CONF_SWAP:
338 if (g_variant_get_boolean(data)) {
339 sr_info("Enabling channel swapping.");
a80bed76 340 devc->capture_flags |= CAPTURE_FLAG_SWAP_CHANNELS;
7b0a57fd
MR
341 } else {
342 sr_info("Disabling channel swapping.");
a80bed76 343 devc->capture_flags &= ~CAPTURE_FLAG_SWAP_CHANNELS;
7b0a57fd 344 }
7b0a57fd 345 break;
1953564a 346 case SR_CONF_RLE:
e46aa4f6 347 if (g_variant_get_boolean(data)) {
0aba65da 348 sr_info("Enabling RLE.");
a80bed76 349 devc->capture_flags |= CAPTURE_FLAG_RLE;
aeea0572
BV
350 } else {
351 sr_info("Disabling RLE.");
a80bed76 352 devc->capture_flags &= ~CAPTURE_FLAG_RLE;
0aba65da 353 }
0aba65da
UH
354 break;
355 default:
758906aa 356 return SR_ERR_NA;
0aba65da
UH
357 }
358
758906aa 359 return SR_OK;
0aba65da
UH
360}
361
dd7a72ea 362static int config_list(uint32_t key, GVariant **data,
55eca716 363 const struct sr_dev_inst *sdi,
364 const struct sr_channel_group *cg)
a1c743fc 365{
f0de2dd0 366 struct dev_context *devc;
91fd0f72 367 int num_ols_changrp, i;
a1c743fc 368
a1c743fc 369 switch (key) {
0d485e30 370 case SR_CONF_SCAN_OPTIONS:
9a6517d1 371 case SR_CONF_DEVICE_OPTIONS:
55eca716 372 return STD_CONFIG_LIST(key, data, sdi, cg, scanopts, drvopts,
373 devopts);
a1c743fc 374 case SR_CONF_SAMPLERATE:
53012da6 375 *data = std_gvar_samplerates_steps(ARRAY_AND_SIZE(samplerates));
a1c743fc 376 break;
91fd0f72 377 case SR_CONF_TRIGGER_MATCH:
53012da6 378 *data = std_gvar_array_i32(ARRAY_AND_SIZE(trigger_matches));
c50277a6 379 break;
f20c39d9 380 case SR_CONF_CLOCK_EDGE:
381 *data = std_gvar_array_str(ARRAY_AND_SIZE(external_clock_edges));
382 break;
7c07a178 383 case SR_CONF_PATTERN_MODE:
53012da6 384 *data = g_variant_new_strv(ARRAY_AND_SIZE(patterns));
7c07a178 385 break;
f0de2dd0
BV
386 case SR_CONF_LIMIT_SAMPLES:
387 if (!sdi)
388 return SR_ERR_ARG;
389 devc = sdi->priv;
f0de2dd0
BV
390 if (devc->max_samples == 0)
391 /* Device didn't specify sample memory size in metadata. */
392 return SR_ERR_NA;
393 /*
ba7dd8bb 394 * Channel groups are turned off if no channels in that group are
f0de2dd0
BV
395 * enabled, making more room for samples for the enabled group.
396 */
f8fd8420 397 uint32_t channel_mask = ols_channel_mask(sdi);
91fd0f72 398 num_ols_changrp = 0;
f0de2dd0 399 for (i = 0; i < 4; i++) {
f8fd8420 400 if (channel_mask & (0xff << (i * 8)))
91fd0f72 401 num_ols_changrp++;
1e1dac0c 402 }
a162eeb2 403
55eca716 404 *data = std_gvar_tuple_u64(MIN_NUM_SAMPLES, (num_ols_changrp)
405 ? devc->max_samples / num_ols_changrp : MIN_NUM_SAMPLES);
f0de2dd0 406 break;
a1c743fc 407 default:
bd6fbf62 408 return SR_ERR_NA;
a1c743fc
BV
409 }
410
411 return SR_OK;
412}
413
695dc859 414static int dev_acquisition_start(const struct sr_dev_inst *sdi)
0aba65da 415{
f8fd8420 416 int ret;
0aba65da 417 struct dev_context *devc;
459a0f26 418 struct sr_serial_dev_inst *serial;
0aba65da
UH
419
420 devc = sdi->priv;
459a0f26 421 serial = sdi->conn;
0aba65da 422
f8fd8420 423 ret = ols_prepare_acquisition(sdi);
424 if (ret != SR_OK)
425 return ret;
0aba65da
UH
426
427 /* Start acquisition on the device. */
6f9234e6 428 if (send_shortcommand(serial, CMD_ARM_BASIC_TRIGGER) != SR_OK)
0aba65da
UH
429 return SR_ERR;
430
bf256783 431 /* Reset all operational states. */
6d16fdfb
BV
432 devc->rle_count = devc->num_transfers = 0;
433 devc->num_samples = devc->num_bytes = 0;
625763e2 434 devc->cnt_bytes = devc->cnt_samples = devc->cnt_samples_rle = 0;
abb39e6b 435 memset(devc->sample, 0, 4);
bf256783 436
bee2b016 437 std_session_send_df_header(sdi);
4afdfd46 438
8105e829
DE
439 /* If the device stops sending for longer than it takes to send a byte,
440 * that means it's finished. But wait at least 100 ms to be safe.
441 */
74e28c06 442 return serial_source_add(sdi->session, serial, G_IO_IN, 100,
443 ols_receive_data, (struct sr_dev_inst *)sdi);
0aba65da
UH
444}
445
695dc859 446static int dev_acquisition_stop(struct sr_dev_inst *sdi)
0aba65da 447{
0aba65da
UH
448 abort_acquisition(sdi);
449
450 return SR_OK;
451}
452
15a5bfe4 453static struct sr_dev_driver ols_driver_info = {
0aba65da 454 .name = "ols",
60143473 455 .longname = "Openbench Logic Sniffer & SUMP compatibles",
0aba65da 456 .api_version = 1,
c2fdcc25 457 .init = std_init,
700d6b64 458 .cleanup = std_cleanup,
03f4de8c 459 .scan = scan,
c01bf34c 460 .dev_list = std_dev_list,
f778bf02 461 .dev_clear = std_dev_clear,
035a1078
BV
462 .config_get = config_get,
463 .config_set = config_set,
a1c743fc 464 .config_list = config_list,
854434de 465 .dev_open = std_serial_dev_open,
bf2c987f 466 .dev_close = std_serial_dev_close,
03f4de8c
BV
467 .dev_acquisition_start = dev_acquisition_start,
468 .dev_acquisition_stop = dev_acquisition_stop,
41812aca 469 .context = NULL,
0aba65da 470};
dd5c48a6 471SR_REGISTER_DEV_DRIVER(ols_driver_info);