]> sigrok.org Git - libsigrok.git/blame - hardware/demo/demo.c
demo: Moved demo configuration variables into dev_context
[libsigrok.git] / hardware / demo / demo.c
CommitLineData
6239c175
UH
1/*
2 * This file is part of the sigrok project.
3 *
4 * Copyright (C) 2010 Uwe Hermann <uwe@hermann-uwe.de>
fc96e6f8 5 * Copyright (C) 2011 Olivier Fauchon <olivier@aixmarseille.com>
c216d623 6 * Copyright (C) 2012 Alexandru Gagniuc <mr.nuke.me@gmail.com>
6239c175
UH
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
21 */
22
23#include <stdlib.h>
85b5af06 24#include <unistd.h>
6239c175 25#include <string.h>
d35aaf02
UH
26#ifdef _WIN32
27#include <io.h>
28#include <fcntl.h>
29#define pipe(fds) _pipe(fds, 4096, _O_BINARY)
30#endif
45c59c8b
BV
31#include "libsigrok.h"
32#include "libsigrok-internal.h"
6239c175 33
92bcedf6
UH
34/* Message logging helpers with driver-specific prefix string. */
35#define DRIVER_LOG_DOMAIN "demo: "
36#define sr_log(l, s, args...) sr_log(l, DRIVER_LOG_DOMAIN s, ## args)
37#define sr_spew(s, args...) sr_spew(DRIVER_LOG_DOMAIN s, ## args)
38#define sr_dbg(s, args...) sr_dbg(DRIVER_LOG_DOMAIN s, ## args)
39#define sr_info(s, args...) sr_info(DRIVER_LOG_DOMAIN s, ## args)
40#define sr_warn(s, args...) sr_warn(DRIVER_LOG_DOMAIN s, ## args)
41#define sr_err(s, args...) sr_err(DRIVER_LOG_DOMAIN s, ## args)
42
c03ed397 43/* TODO: Number of probes should be configurable. */
e15f48c2 44#define NUM_PROBES 8
c03ed397 45
e15f48c2 46#define DEMONAME "Demo device"
c03ed397
UH
47
48/* The size of chunks to send through the session bus. */
49/* TODO: Should be configurable. */
e15f48c2 50#define BUFSIZE 4096
85b5af06 51
2474d87e
BV
52#define STR_PATTERN_SIGROK "sigrok"
53#define STR_PATTERN_RANDOM "random"
54#define STR_PATTERN_INC "incremental"
55#define STR_PATTERN_ALL_LOW "all-low"
56#define STR_PATTERN_ALL_HIGH "all-high"
57
0d31276b 58/* Supported patterns which we can generate */
e15f48c2 59enum {
0d31276b
UH
60 /**
61 * Pattern which spells "sigrok" using '0's (with '1's as "background")
62 * when displayed using the 'bits' output format.
63 */
c8f4624d 64 PATTERN_SIGROK,
0d31276b 65
c03ed397 66 /** Pattern which consists of (pseudo-)random values on all probes. */
c8f4624d 67 PATTERN_RANDOM,
0d31276b
UH
68
69 /**
70 * Pattern which consists of incrementing numbers.
71 * TODO: Better description.
72 */
c8f4624d 73 PATTERN_INC,
c03ed397
UH
74
75 /** Pattern where all probes have a low logic state. */
76 PATTERN_ALL_LOW,
77
78 /** Pattern where all probes have a high logic state. */
79 PATTERN_ALL_HIGH,
e15f48c2 80};
85b5af06 81
b4750a3a
BV
82/* Private, per-device-instance driver context. */
83struct dev_context {
33ef7573 84 struct sr_dev_inst *sdi;
e15f48c2 85 int pipe_fds[2];
e0532047 86 GIOChannel *channel;
a7684294
JH
87 uint64_t cur_samplerate;
88 uint64_t limit_samples;
89 uint64_t limit_msec;
e15f48c2 90 uint8_t sample_generator;
e15f48c2 91 uint64_t samples_counter;
3e9b7f9c 92 void *cb_data;
3b203673 93 int64_t starttime;
e15f48c2 94};
85b5af06 95
915f7cc8 96static const int hwcaps[] = {
1953564a
BV
97 SR_CONF_LOGIC_ANALYZER,
98 SR_CONF_DEMO_DEV,
99 SR_CONF_SAMPLERATE,
100 SR_CONF_PATTERN_MODE,
101 SR_CONF_LIMIT_SAMPLES,
102 SR_CONF_LIMIT_MSEC,
103 SR_CONF_CONTINUOUS,
6239c175
UH
104};
105
d00088ca
BV
106static const uint64_t samplerates[] = {
107 SR_HZ(1),
108 SR_GHZ(1),
109 SR_HZ(1),
4bfbf9fc
BV
110};
111
c8f4624d 112static const char *pattern_strings[] = {
c03ed397 113 "sigrok",
e15f48c2
BV
114 "random",
115 "incremental",
c03ed397
UH
116 "all-low",
117 "all-high",
85b5af06
UH
118};
119
d261dbbf 120/* We name the probes 0-7 on our demo driver. */
464d12c7 121static const char *probe_names[NUM_PROBES + 1] = {
78693401 122 "0", "1", "2", "3", "4", "5", "6", "7",
464d12c7
KS
123 NULL,
124};
125
c8f4624d 126static uint8_t pattern_sigrok[] = {
917e0e71
BV
127 0x4c, 0x92, 0x92, 0x92, 0x64, 0x00, 0x00, 0x00,
128 0x82, 0xfe, 0xfe, 0x82, 0x00, 0x00, 0x00, 0x00,
129 0x7c, 0x82, 0x82, 0x92, 0x74, 0x00, 0x00, 0x00,
130 0xfe, 0x12, 0x12, 0x32, 0xcc, 0x00, 0x00, 0x00,
131 0x7c, 0x82, 0x82, 0x82, 0x7c, 0x00, 0x00, 0x00,
132 0xfe, 0x10, 0x28, 0x44, 0x82, 0x00, 0x00, 0x00,
133 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
134 0xbe, 0xbe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
135};
136
ea9cfed7
UH
137/* Private, per-device-instance driver context. */
138/* TODO: struct context as with the other drivers. */
139
e7eb703f 140/* List of struct sr_dev_inst, maintained by dev_open()/dev_close(). */
dcf03d6d 141SR_PRIV struct sr_dev_driver demo_driver_info;
a873c594 142static struct sr_dev_driver *di = &demo_driver_info;
6239c175 143
69b07d14 144static int hw_dev_acquisition_stop(struct sr_dev_inst *sdi, void *cb_data);
6239c175 145
eebb6067
UH
146static int clear_instances(void)
147{
148 /* Nothing needed so far. */
149
150 return SR_OK;
151}
152
34f06b90 153static int hw_init(struct sr_context *sr_ctx)
61136ea6 154{
063e7aef 155 return std_hw_init(sr_ctx, di, DRIVER_LOG_DOMAIN);
61136ea6
BV
156}
157
067d0716 158static GSList *hw_scan(GSList *options)
6239c175 159{
d68e2d1a 160 struct sr_dev_inst *sdi;
87ca93c5 161 struct sr_probe *probe;
b4750a3a 162 struct drv_context *drvc;
33ef7573 163 struct dev_context *devc;
067d0716 164 GSList *devices;
87ca93c5 165 int i;
067d0716
BV
166
167 (void)options;
64d33dc2 168
a873c594 169 drvc = di->priv;
4b97c74e 170
067d0716 171 devices = NULL;
85b5af06 172
d3683c42 173 sdi = sr_dev_inst_new(0, SR_ST_ACTIVE, DEMONAME, NULL, NULL);
c03ed397 174 if (!sdi) {
92bcedf6 175 sr_err("%s: sr_dev_inst_new failed", __func__);
85b5af06 176 return 0;
c03ed397 177 }
a873c594 178 sdi->driver = di;
e15f48c2 179
87ca93c5 180 for (i = 0; probe_names[i]; i++) {
de6e0eca 181 if (!(probe = sr_probe_new(i, SR_PROBE_LOGIC, TRUE,
87ca93c5
BV
182 probe_names[i])))
183 return NULL;
184 sdi->probes = g_slist_append(sdi->probes, probe);
185 }
186
067d0716 187 devices = g_slist_append(devices, sdi);
b4750a3a 188 drvc->instances = g_slist_append(drvc->instances, sdi);
85b5af06 189
33ef7573
JH
190 /* TODO: 'devc' is never g_free()'d? */
191 if (!(devc = g_try_malloc(sizeof(struct dev_context)))) {
192 sr_err("%s: devc malloc failed", __func__);
193 return SR_ERR_MALLOC;
194 }
195
196 devc->sdi = sdi;
a7684294
JH
197 devc->cur_samplerate = SR_KHZ(200);
198 devc->limit_samples = 0;
199 devc->limit_msec = 0;
200 devc->sample_generator = PATTERN_SIGROK;
33ef7573
JH
201
202 sdi->priv = devc;
203
067d0716 204 return devices;
6239c175
UH
205}
206
811deee4
BV
207static GSList *hw_dev_list(void)
208{
0e94d524 209 return ((struct drv_context *)(di->priv))->instances;
811deee4
BV
210}
211
25a0f108 212static int hw_dev_open(struct sr_dev_inst *sdi)
6239c175 213{
25a0f108 214 (void)sdi;
6239c175
UH
215
216 /* Nothing needed so far. */
697785d1 217
e46b8fb1 218 return SR_OK;
6239c175
UH
219}
220
25a0f108 221static int hw_dev_close(struct sr_dev_inst *sdi)
6239c175 222{
25a0f108 223 (void)sdi;
6239c175
UH
224
225 /* Nothing needed so far. */
697785d1
UH
226
227 return SR_OK;
6239c175
UH
228}
229
57ab7d9f 230static int hw_cleanup(void)
6239c175
UH
231{
232 /* Nothing needed so far. */
57ab7d9f 233 return SR_OK;
6239c175
UH
234}
235
d00088ca 236static int config_get(int id, GVariant **data, const struct sr_dev_inst *sdi)
6239c175 237{
a7684294 238 struct dev_context *const devc = sdi->priv;
6f57fd96 239
035a1078 240 switch (id) {
123e1313 241 case SR_CONF_SAMPLERATE:
a7684294 242 *data = g_variant_new_uint64(devc->cur_samplerate);
6239c175 243 break;
2474d87e 244 case SR_CONF_LIMIT_SAMPLES:
a7684294 245 *data = g_variant_new_uint64(devc->limit_samples);
2474d87e
BV
246 break;
247 case SR_CONF_LIMIT_MSEC:
a7684294 248 *data = g_variant_new_uint64(devc->limit_msec);
2474d87e
BV
249 break;
250 case SR_CONF_PATTERN_MODE:
a7684294 251 switch (devc->sample_generator) {
2474d87e 252 case PATTERN_SIGROK:
d00088ca 253 *data = g_variant_new_string(STR_PATTERN_SIGROK);
2474d87e
BV
254 break;
255 case PATTERN_RANDOM:
d00088ca 256 *data = g_variant_new_string(STR_PATTERN_RANDOM);
2474d87e
BV
257 break;
258 case PATTERN_INC:
d00088ca 259 *data = g_variant_new_string(STR_PATTERN_INC);
2474d87e
BV
260 break;
261 case PATTERN_ALL_LOW:
d00088ca 262 *data = g_variant_new_string(STR_PATTERN_ALL_LOW);
2474d87e
BV
263 break;
264 case PATTERN_ALL_HIGH:
d00088ca 265 *data = g_variant_new_string(STR_PATTERN_ALL_HIGH);
2474d87e
BV
266 break;
267 }
268 break;
7dfcf010
BV
269 default:
270 return SR_ERR_ARG;
6239c175
UH
271 }
272
dfb0fa1a 273 return SR_OK;
6239c175
UH
274}
275
d00088ca 276static int config_set(int id, GVariant *data, const struct sr_dev_inst *sdi)
6239c175
UH
277{
278 int ret;
1b79df2f 279 const char *stropt;
6239c175 280
a7684294 281 struct dev_context *const devc = sdi->priv;
6239c175 282
035a1078 283 if (id == SR_CONF_SAMPLERATE) {
a7684294 284 devc->cur_samplerate = g_variant_get_uint64(data);
92bcedf6 285 sr_dbg("%s: setting samplerate to %" PRIu64, __func__,
a7684294 286 devc->cur_samplerate);
e46b8fb1 287 ret = SR_OK;
035a1078 288 } else if (id == SR_CONF_LIMIT_SAMPLES) {
a7684294
JH
289 devc->limit_msec = 0;
290 devc->limit_samples = g_variant_get_uint64(data);
92bcedf6 291 sr_dbg("%s: setting limit_samples to %" PRIu64, __func__,
a7684294 292 devc->limit_samples);
e46b8fb1 293 ret = SR_OK;
035a1078 294 } else if (id == SR_CONF_LIMIT_MSEC) {
a7684294
JH
295 devc->limit_msec = g_variant_get_uint64(data);
296 devc->limit_samples = 0;
92bcedf6 297 sr_dbg("%s: setting limit_msec to %" PRIu64, __func__,
a7684294 298 devc->limit_msec);
e46b8fb1 299 ret = SR_OK;
035a1078 300 } else if (id == SR_CONF_PATTERN_MODE) {
d00088ca 301 stropt = g_variant_get_string(data, NULL);
c03ed397 302 ret = SR_OK;
2474d87e 303 if (!strcmp(stropt, STR_PATTERN_SIGROK)) {
a7684294 304 devc->sample_generator = PATTERN_SIGROK;
2474d87e 305 } else if (!strcmp(stropt, STR_PATTERN_RANDOM)) {
a7684294 306 devc->sample_generator = PATTERN_RANDOM;
2474d87e 307 } else if (!strcmp(stropt, STR_PATTERN_INC)) {
a7684294 308 devc->sample_generator = PATTERN_INC;
2474d87e 309 } else if (!strcmp(stropt, STR_PATTERN_ALL_LOW)) {
a7684294 310 devc->sample_generator = PATTERN_ALL_LOW;
2474d87e 311 } else if (!strcmp(stropt, STR_PATTERN_ALL_HIGH)) {
a7684294 312 devc->sample_generator = PATTERN_ALL_HIGH;
e15f48c2 313 } else {
e46b8fb1 314 ret = SR_ERR;
e15f48c2 315 }
a7684294
JH
316 sr_dbg("%s: setting pattern to %d",
317 __func__, devc->sample_generator);
6239c175 318 } else {
e46b8fb1 319 ret = SR_ERR;
6239c175
UH
320 }
321
322 return ret;
323}
324
d00088ca 325static int config_list(int key, GVariant **data, const struct sr_dev_inst *sdi)
a1c743fc 326{
d00088ca
BV
327 GVariant *gvar;
328 GVariantBuilder gvb;
a1c743fc
BV
329
330 (void)sdi;
331
332 switch (key) {
9a6517d1 333 case SR_CONF_DEVICE_OPTIONS:
d00088ca
BV
334 *data = g_variant_new_fixed_array(G_VARIANT_TYPE_INT32,
335 hwcaps, ARRAY_SIZE(hwcaps), sizeof(int32_t));
9a6517d1 336 break;
a1c743fc 337 case SR_CONF_SAMPLERATE:
d00088ca
BV
338 g_variant_builder_init(&gvb, G_VARIANT_TYPE("a{sv}"));
339 gvar = g_variant_new_fixed_array(G_VARIANT_TYPE("t"), samplerates,
340 ARRAY_SIZE(samplerates), sizeof(uint64_t));
341 g_variant_builder_add(&gvb, "{sv}", "samplerate-steps", gvar);
342 *data = g_variant_builder_end(&gvb);
a1c743fc 343 break;
dd96ea98 344 case SR_CONF_PATTERN_MODE:
d00088ca 345 *data = g_variant_new_strv(pattern_strings, ARRAY_SIZE(pattern_strings));
dd96ea98 346 break;
a1c743fc
BV
347 default:
348 return SR_ERR_ARG;
349 }
350
351 return SR_OK;
352}
353
3b203673
AG
354static void samples_generator(uint8_t *buf, uint64_t size,
355 struct dev_context *devc)
85b5af06 356{
cddd1c5f 357 static uint64_t p = 0;
cddd1c5f 358 uint64_t i;
85b5af06 359
c03ed397 360 /* TODO: Needed? */
5096c6a6 361 memset(buf, 0, size);
85b5af06 362
b4750a3a 363 switch (devc->sample_generator) {
c03ed397 364 case PATTERN_SIGROK: /* sigrok pattern */
917e0e71 365 for (i = 0; i < size; i++) {
bbd7ef0f
JH
366 *(buf + i) = ~(pattern_sigrok[
367 p++ % sizeof(pattern_sigrok)] >> 1);
917e0e71
BV
368 }
369 break;
c8f4624d 370 case PATTERN_RANDOM: /* Random */
5096c6a6
UH
371 for (i = 0; i < size; i++)
372 *(buf + i) = (uint8_t)(rand() & 0xff);
85b5af06 373 break;
c8f4624d 374 case PATTERN_INC: /* Simple increment */
5096c6a6 375 for (i = 0; i < size; i++)
bbd7ef0f 376 *(buf + i) = p++;
85b5af06 377 break;
c03ed397 378 case PATTERN_ALL_LOW: /* All probes are low */
5a9660dd 379 memset(buf, 0x00, size);
c03ed397
UH
380 break;
381 case PATTERN_ALL_HIGH: /* All probes are high */
5a9660dd 382 memset(buf, 0xff, size);
c03ed397
UH
383 break;
384 default:
92bcedf6 385 sr_err("Unknown pattern: %d.", devc->sample_generator);
c03ed397 386 break;
85b5af06
UH
387 }
388}
389
85b5af06 390/* Callback handling data */
1f9813eb 391static int receive_data(int fd, int revents, void *cb_data)
85b5af06 392{
b4750a3a 393 struct dev_context *devc = cb_data;
b9c735a2 394 struct sr_datafeed_packet packet;
9c939c51 395 struct sr_datafeed_logic logic;
3b203673
AG
396 uint8_t buf[BUFSIZE];
397 static uint64_t samples_to_send, expected_samplenum, sending_now;
398 int64_t time, elapsed;
1924f59f 399
cb93f8a9
UH
400 (void)fd;
401 (void)revents;
1924f59f 402
3b203673
AG
403 /* How many "virtual" samples should we have collected by now? */
404 time = g_get_monotonic_time();
405 elapsed = time - devc->starttime;
a7684294 406 expected_samplenum = elapsed * devc->cur_samplerate / 1000000;
3b203673
AG
407 /* Of those, how many do we still have to send? */
408 samples_to_send = expected_samplenum - devc->samples_counter;
409
a7684294 410 if (devc->limit_samples) {
3b203673 411 samples_to_send = MIN(samples_to_send,
a7684294 412 devc->limit_samples - devc->samples_counter);
3b203673 413 }
85b5af06 414
3b203673
AG
415 while (samples_to_send > 0) {
416 sending_now = MIN(samples_to_send, sizeof(buf));
417 samples_to_send -= sending_now;
418 samples_generator(buf, sending_now, devc);
419
420 packet.type = SR_DF_LOGIC;
421 packet.payload = &logic;
422 logic.length = sending_now;
423 logic.unitsize = 1;
424 logic.data = buf;
3e9b7f9c 425 sr_session_send(devc->cb_data, &packet);
3b203673
AG
426 devc->samples_counter += sending_now;
427 }
428
a7684294
JH
429 if (devc->limit_samples &&
430 devc->samples_counter >= devc->limit_samples) {
35e199da 431 sr_info("Requested number of samples reached.");
33ef7573 432 hw_dev_acquisition_stop(devc->sdi, cb_data);
c216d623 433 return TRUE;
85b5af06 434 }
1924f59f 435
85b5af06
UH
436 return TRUE;
437}
438
3ffb6964
BV
439static int hw_dev_acquisition_start(const struct sr_dev_inst *sdi,
440 void *cb_data)
6239c175 441{
33ef7573 442 struct dev_context *const devc = sdi->priv;
85b5af06 443
3e9b7f9c 444 devc->cb_data = cb_data;
b4750a3a 445 devc->samples_counter = 0;
85b5af06 446
3b203673
AG
447 /*
448 * Setting two channels connected by a pipe is a remnant from when the
449 * demo driver generated data in a thread, and collected and sent the
450 * data in the main program loop.
451 * They are kept here because it provides a convenient way of setting
452 * up a timeout-based polling mechanism.
453 */
b4750a3a 454 if (pipe(devc->pipe_fds)) {
c03ed397 455 /* TODO: Better error message. */
92bcedf6 456 sr_err("%s: pipe() failed", __func__);
e46b8fb1 457 return SR_ERR;
c03ed397 458 }
85b5af06 459
e0532047 460 devc->channel = g_io_channel_unix_new(devc->pipe_fds[0]);
d35aaf02 461
e0532047 462 g_io_channel_set_flags(devc->channel, G_IO_FLAG_NONBLOCK, NULL);
e6e8f8e0 463
d35aaf02 464 /* Set channel encoding to binary (default is UTF-8). */
e0532047 465 g_io_channel_set_encoding(devc->channel, NULL, NULL);
d35aaf02
UH
466
467 /* Make channels to unbuffered. */
e0532047 468 g_io_channel_set_buffered(devc->channel, FALSE);
d35aaf02 469
e0532047 470 sr_session_source_add_channel(devc->channel, G_IO_IN | G_IO_ERR,
b4750a3a 471 40, receive_data, devc);
85b5af06 472
4afdfd46
UH
473 /* Send header packet to the session bus. */
474 std_session_send_df_header(cb_data, DRIVER_LOG_DOMAIN);
f366e86c 475
3b203673
AG
476 /* We use this timestamp to decide how many more samples to send. */
477 devc->starttime = g_get_monotonic_time();
478
e46b8fb1 479 return SR_OK;
6239c175
UH
480}
481
69b07d14 482static int hw_dev_acquisition_stop(struct sr_dev_inst *sdi, void *cb_data)
6239c175 483{
33ef7573 484 struct dev_context *const devc = sdi->priv;
c216d623 485 struct sr_datafeed_packet packet;
7fd3e859 486
33ef7573 487 (void)cb_data;
7fd3e859 488
49145a63
AG
489 sr_dbg("Stopping aquisition.");
490
e0532047
JH
491 sr_session_source_remove_channel(devc->channel);
492 g_io_channel_shutdown(devc->channel, FALSE, NULL);
c216d623
AG
493
494 /* Send last packet. */
495 packet.type = SR_DF_END;
3e9b7f9c 496 sr_session_send(devc->cb_data, &packet);
7fd3e859 497
3010f21c 498 return SR_OK;
6239c175
UH
499}
500
c09f0b57 501SR_PRIV struct sr_dev_driver demo_driver_info = {
e519ba86
UH
502 .name = "demo",
503 .longname = "Demo driver and pattern generator",
504 .api_version = 1,
505 .init = hw_init,
506 .cleanup = hw_cleanup,
61136ea6 507 .scan = hw_scan,
811deee4 508 .dev_list = hw_dev_list,
eebb6067 509 .dev_clear = clear_instances,
035a1078
BV
510 .config_get = config_get,
511 .config_set = config_set,
a1c743fc 512 .config_list = config_list,
e7eb703f
UH
513 .dev_open = hw_dev_open,
514 .dev_close = hw_dev_close,
69040b7c
UH
515 .dev_acquisition_start = hw_dev_acquisition_start,
516 .dev_acquisition_stop = hw_dev_acquisition_stop,
b4750a3a 517 .priv = NULL,
6239c175 518};