]> sigrok.org Git - libsigrok.git/blame - hardware/demo/demo.c
probe_groups: API changes required to implement probe groups.
[libsigrok.git] / hardware / demo / demo.c
CommitLineData
6239c175 1/*
50985c20 2 * This file is part of the libsigrok project.
6239c175
UH
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
29a27196
UH
34/* Message logging helpers with subsystem-specific prefix string. */
35#define LOG_PREFIX "demo: "
36#define sr_log(l, s, args...) sr_log(l, LOG_PREFIX s, ## args)
37#define sr_spew(s, args...) sr_spew(LOG_PREFIX s, ## args)
38#define sr_dbg(s, args...) sr_dbg(LOG_PREFIX s, ## args)
39#define sr_info(s, args...) sr_info(LOG_PREFIX s, ## args)
40#define sr_warn(s, args...) sr_warn(LOG_PREFIX s, ## args)
41#define sr_err(s, args...) sr_err(LOG_PREFIX s, ## args)
92bcedf6 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
6078d2c9 144static int dev_acquisition_stop(struct sr_dev_inst *sdi, void *cb_data);
6239c175 145
3b412e3a 146static int dev_clear(void)
eebb6067 147{
1c2d542d 148 return std_dev_clear(di, NULL);
eebb6067
UH
149}
150
6078d2c9 151static int init(struct sr_context *sr_ctx)
61136ea6 152{
f6beaac5 153 return std_init(sr_ctx, di, LOG_PREFIX);
61136ea6
BV
154}
155
6078d2c9 156static GSList *scan(GSList *options)
6239c175 157{
d68e2d1a 158 struct sr_dev_inst *sdi;
87ca93c5 159 struct sr_probe *probe;
b4750a3a 160 struct drv_context *drvc;
33ef7573 161 struct dev_context *devc;
067d0716 162 GSList *devices;
87ca93c5 163 int i;
067d0716
BV
164
165 (void)options;
64d33dc2 166
a873c594 167 drvc = di->priv;
4b97c74e 168
067d0716 169 devices = NULL;
85b5af06 170
d3683c42 171 sdi = sr_dev_inst_new(0, SR_ST_ACTIVE, DEMONAME, NULL, NULL);
c03ed397 172 if (!sdi) {
e45ad6e2
UH
173 sr_err("Device instance creation failed.");
174 return NULL;
c03ed397 175 }
a873c594 176 sdi->driver = di;
e15f48c2 177
87ca93c5 178 for (i = 0; probe_names[i]; i++) {
de6e0eca 179 if (!(probe = sr_probe_new(i, SR_PROBE_LOGIC, TRUE,
87ca93c5
BV
180 probe_names[i])))
181 return NULL;
182 sdi->probes = g_slist_append(sdi->probes, probe);
183 }
184
067d0716 185 devices = g_slist_append(devices, sdi);
b4750a3a 186 drvc->instances = g_slist_append(drvc->instances, sdi);
85b5af06 187
33ef7573 188 if (!(devc = g_try_malloc(sizeof(struct dev_context)))) {
e45ad6e2
UH
189 sr_err("Device context malloc failed.");
190 return NULL;
33ef7573
JH
191 }
192
193 devc->sdi = sdi;
a7684294
JH
194 devc->cur_samplerate = SR_KHZ(200);
195 devc->limit_samples = 0;
196 devc->limit_msec = 0;
197 devc->sample_generator = PATTERN_SIGROK;
33ef7573
JH
198
199 sdi->priv = devc;
200
067d0716 201 return devices;
6239c175
UH
202}
203
6078d2c9 204static GSList *dev_list(void)
811deee4 205{
0e94d524 206 return ((struct drv_context *)(di->priv))->instances;
811deee4
BV
207}
208
6078d2c9 209static int dev_open(struct sr_dev_inst *sdi)
6239c175 210{
e73ffd42 211 sdi->status = SR_ST_ACTIVE;
697785d1 212
e46b8fb1 213 return SR_OK;
6239c175
UH
214}
215
6078d2c9 216static int dev_close(struct sr_dev_inst *sdi)
6239c175 217{
decfe89d 218 sdi->status = SR_ST_INACTIVE;
697785d1
UH
219
220 return SR_OK;
6239c175
UH
221}
222
6078d2c9 223static int cleanup(void)
6239c175 224{
1c2d542d 225 return dev_clear();
6239c175
UH
226}
227
8f996b89
ML
228static int config_get(int id, GVariant **data, const struct sr_dev_inst *sdi,
229 const struct sr_probe_group *probe_group)
6239c175 230{
a7684294 231 struct dev_context *const devc = sdi->priv;
6f57fd96 232
8f996b89
ML
233 (void)probe_group;
234
035a1078 235 switch (id) {
123e1313 236 case SR_CONF_SAMPLERATE:
a7684294 237 *data = g_variant_new_uint64(devc->cur_samplerate);
6239c175 238 break;
2474d87e 239 case SR_CONF_LIMIT_SAMPLES:
a7684294 240 *data = g_variant_new_uint64(devc->limit_samples);
2474d87e
BV
241 break;
242 case SR_CONF_LIMIT_MSEC:
a7684294 243 *data = g_variant_new_uint64(devc->limit_msec);
2474d87e
BV
244 break;
245 case SR_CONF_PATTERN_MODE:
a7684294 246 switch (devc->sample_generator) {
2474d87e 247 case PATTERN_SIGROK:
d00088ca 248 *data = g_variant_new_string(STR_PATTERN_SIGROK);
2474d87e
BV
249 break;
250 case PATTERN_RANDOM:
d00088ca 251 *data = g_variant_new_string(STR_PATTERN_RANDOM);
2474d87e
BV
252 break;
253 case PATTERN_INC:
d00088ca 254 *data = g_variant_new_string(STR_PATTERN_INC);
2474d87e
BV
255 break;
256 case PATTERN_ALL_LOW:
d00088ca 257 *data = g_variant_new_string(STR_PATTERN_ALL_LOW);
2474d87e
BV
258 break;
259 case PATTERN_ALL_HIGH:
d00088ca 260 *data = g_variant_new_string(STR_PATTERN_ALL_HIGH);
2474d87e
BV
261 break;
262 }
263 break;
7dfcf010 264 default:
bd6fbf62 265 return SR_ERR_NA;
6239c175
UH
266 }
267
dfb0fa1a 268 return SR_OK;
6239c175
UH
269}
270
8f996b89
ML
271static int config_set(int id, GVariant *data, const struct sr_dev_inst *sdi,
272 const struct sr_probe_group *probe_group)
6239c175
UH
273{
274 int ret;
1b79df2f 275 const char *stropt;
6239c175 276
8f996b89 277 (void)probe_group;
a7684294 278 struct dev_context *const devc = sdi->priv;
6239c175 279
e73ffd42
BV
280 if (sdi->status != SR_ST_ACTIVE)
281 return SR_ERR_DEV_CLOSED;
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 {
bd6fbf62 319 ret = SR_ERR_NA;
6239c175
UH
320 }
321
322 return ret;
323}
324
8f996b89
ML
325static int config_list(int key, GVariant **data, const struct sr_dev_inst *sdi,
326 const struct sr_probe_group *probe_group)
a1c743fc 327{
d00088ca
BV
328 GVariant *gvar;
329 GVariantBuilder gvb;
a1c743fc
BV
330
331 (void)sdi;
8f996b89 332 (void)probe_group;
a1c743fc
BV
333
334 switch (key) {
9a6517d1 335 case SR_CONF_DEVICE_OPTIONS:
d00088ca
BV
336 *data = g_variant_new_fixed_array(G_VARIANT_TYPE_INT32,
337 hwcaps, ARRAY_SIZE(hwcaps), sizeof(int32_t));
9a6517d1 338 break;
a1c743fc 339 case SR_CONF_SAMPLERATE:
d00088ca
BV
340 g_variant_builder_init(&gvb, G_VARIANT_TYPE("a{sv}"));
341 gvar = g_variant_new_fixed_array(G_VARIANT_TYPE("t"), samplerates,
342 ARRAY_SIZE(samplerates), sizeof(uint64_t));
343 g_variant_builder_add(&gvb, "{sv}", "samplerate-steps", gvar);
344 *data = g_variant_builder_end(&gvb);
a1c743fc 345 break;
dd96ea98 346 case SR_CONF_PATTERN_MODE:
d00088ca 347 *data = g_variant_new_strv(pattern_strings, ARRAY_SIZE(pattern_strings));
dd96ea98 348 break;
a1c743fc 349 default:
bd6fbf62 350 return SR_ERR_NA;
a1c743fc
BV
351 }
352
353 return SR_OK;
354}
355
3b203673
AG
356static void samples_generator(uint8_t *buf, uint64_t size,
357 struct dev_context *devc)
85b5af06 358{
cddd1c5f 359 static uint64_t p = 0;
cddd1c5f 360 uint64_t i;
85b5af06 361
c03ed397 362 /* TODO: Needed? */
5096c6a6 363 memset(buf, 0, size);
85b5af06 364
b4750a3a 365 switch (devc->sample_generator) {
c03ed397 366 case PATTERN_SIGROK: /* sigrok pattern */
917e0e71 367 for (i = 0; i < size; i++) {
bbd7ef0f
JH
368 *(buf + i) = ~(pattern_sigrok[
369 p++ % sizeof(pattern_sigrok)] >> 1);
917e0e71
BV
370 }
371 break;
c8f4624d 372 case PATTERN_RANDOM: /* Random */
5096c6a6
UH
373 for (i = 0; i < size; i++)
374 *(buf + i) = (uint8_t)(rand() & 0xff);
85b5af06 375 break;
c8f4624d 376 case PATTERN_INC: /* Simple increment */
5096c6a6 377 for (i = 0; i < size; i++)
bbd7ef0f 378 *(buf + i) = p++;
85b5af06 379 break;
c03ed397 380 case PATTERN_ALL_LOW: /* All probes are low */
5a9660dd 381 memset(buf, 0x00, size);
c03ed397
UH
382 break;
383 case PATTERN_ALL_HIGH: /* All probes are high */
5a9660dd 384 memset(buf, 0xff, size);
c03ed397
UH
385 break;
386 default:
92bcedf6 387 sr_err("Unknown pattern: %d.", devc->sample_generator);
c03ed397 388 break;
85b5af06
UH
389 }
390}
391
85b5af06 392/* Callback handling data */
1f9813eb 393static int receive_data(int fd, int revents, void *cb_data)
85b5af06 394{
b4750a3a 395 struct dev_context *devc = cb_data;
b9c735a2 396 struct sr_datafeed_packet packet;
9c939c51 397 struct sr_datafeed_logic logic;
3b203673
AG
398 uint8_t buf[BUFSIZE];
399 static uint64_t samples_to_send, expected_samplenum, sending_now;
400 int64_t time, elapsed;
1924f59f 401
cb93f8a9
UH
402 (void)fd;
403 (void)revents;
1924f59f 404
3b203673
AG
405 /* How many "virtual" samples should we have collected by now? */
406 time = g_get_monotonic_time();
407 elapsed = time - devc->starttime;
a7684294 408 expected_samplenum = elapsed * devc->cur_samplerate / 1000000;
3b203673
AG
409 /* Of those, how many do we still have to send? */
410 samples_to_send = expected_samplenum - devc->samples_counter;
411
a7684294 412 if (devc->limit_samples) {
3b203673 413 samples_to_send = MIN(samples_to_send,
a7684294 414 devc->limit_samples - devc->samples_counter);
3b203673 415 }
85b5af06 416
3b203673
AG
417 while (samples_to_send > 0) {
418 sending_now = MIN(samples_to_send, sizeof(buf));
419 samples_to_send -= sending_now;
420 samples_generator(buf, sending_now, devc);
421
422 packet.type = SR_DF_LOGIC;
423 packet.payload = &logic;
424 logic.length = sending_now;
425 logic.unitsize = 1;
426 logic.data = buf;
3e9b7f9c 427 sr_session_send(devc->cb_data, &packet);
3b203673
AG
428 devc->samples_counter += sending_now;
429 }
430
a7684294
JH
431 if (devc->limit_samples &&
432 devc->samples_counter >= devc->limit_samples) {
35e199da 433 sr_info("Requested number of samples reached.");
6078d2c9 434 dev_acquisition_stop(devc->sdi, cb_data);
c216d623 435 return TRUE;
85b5af06 436 }
1924f59f 437
85b5af06
UH
438 return TRUE;
439}
440
6078d2c9 441static int dev_acquisition_start(const struct sr_dev_inst *sdi, void *cb_data)
6239c175 442{
33ef7573 443 struct dev_context *const devc = sdi->priv;
85b5af06 444
e73ffd42
BV
445 if (sdi->status != SR_ST_ACTIVE)
446 return SR_ERR_DEV_CLOSED;
447
3e9b7f9c 448 devc->cb_data = cb_data;
b4750a3a 449 devc->samples_counter = 0;
85b5af06 450
3b203673
AG
451 /*
452 * Setting two channels connected by a pipe is a remnant from when the
453 * demo driver generated data in a thread, and collected and sent the
454 * data in the main program loop.
455 * They are kept here because it provides a convenient way of setting
456 * up a timeout-based polling mechanism.
457 */
b4750a3a 458 if (pipe(devc->pipe_fds)) {
c03ed397 459 /* TODO: Better error message. */
92bcedf6 460 sr_err("%s: pipe() failed", __func__);
e46b8fb1 461 return SR_ERR;
c03ed397 462 }
85b5af06 463
e0532047 464 devc->channel = g_io_channel_unix_new(devc->pipe_fds[0]);
d35aaf02 465
e0532047 466 g_io_channel_set_flags(devc->channel, G_IO_FLAG_NONBLOCK, NULL);
e6e8f8e0 467
d35aaf02 468 /* Set channel encoding to binary (default is UTF-8). */
e0532047 469 g_io_channel_set_encoding(devc->channel, NULL, NULL);
d35aaf02
UH
470
471 /* Make channels to unbuffered. */
e0532047 472 g_io_channel_set_buffered(devc->channel, FALSE);
d35aaf02 473
e0532047 474 sr_session_source_add_channel(devc->channel, G_IO_IN | G_IO_ERR,
b4750a3a 475 40, receive_data, devc);
85b5af06 476
4afdfd46 477 /* Send header packet to the session bus. */
29a27196 478 std_session_send_df_header(cb_data, LOG_PREFIX);
f366e86c 479
3b203673
AG
480 /* We use this timestamp to decide how many more samples to send. */
481 devc->starttime = g_get_monotonic_time();
482
e46b8fb1 483 return SR_OK;
6239c175
UH
484}
485
6078d2c9 486static int dev_acquisition_stop(struct sr_dev_inst *sdi, void *cb_data)
6239c175 487{
33ef7573 488 struct dev_context *const devc = sdi->priv;
c216d623 489 struct sr_datafeed_packet packet;
7fd3e859 490
33ef7573 491 (void)cb_data;
7fd3e859 492
49145a63
AG
493 sr_dbg("Stopping aquisition.");
494
e0532047
JH
495 sr_session_source_remove_channel(devc->channel);
496 g_io_channel_shutdown(devc->channel, FALSE, NULL);
2150a69b
JH
497 g_io_channel_unref(devc->channel);
498 devc->channel = NULL;
c216d623
AG
499
500 /* Send last packet. */
501 packet.type = SR_DF_END;
3e9b7f9c 502 sr_session_send(devc->cb_data, &packet);
7fd3e859 503
3010f21c 504 return SR_OK;
6239c175
UH
505}
506
c09f0b57 507SR_PRIV struct sr_dev_driver demo_driver_info = {
e519ba86
UH
508 .name = "demo",
509 .longname = "Demo driver and pattern generator",
510 .api_version = 1,
6078d2c9
UH
511 .init = init,
512 .cleanup = cleanup,
513 .scan = scan,
514 .dev_list = dev_list,
3b412e3a 515 .dev_clear = dev_clear,
035a1078
BV
516 .config_get = config_get,
517 .config_set = config_set,
a1c743fc 518 .config_list = config_list,
6078d2c9
UH
519 .dev_open = dev_open,
520 .dev_close = dev_close,
521 .dev_acquisition_start = dev_acquisition_start,
522 .dev_acquisition_stop = dev_acquisition_stop,
b4750a3a 523 .priv = NULL,
6239c175 524};