]> sigrok.org Git - libsigrok.git/blame - src/hardware/demo/demo.c
Fix invalid pointer dereference.
[libsigrok.git] / src / 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>
4374219b 26#include <math.h>
d35aaf02
UH
27#ifdef _WIN32
28#include <io.h>
29#include <fcntl.h>
30#define pipe(fds) _pipe(fds, 4096, _O_BINARY)
31#endif
45c59c8b
BV
32#include "libsigrok.h"
33#include "libsigrok-internal.h"
6239c175 34
3544f848 35#define LOG_PREFIX "demo"
92bcedf6 36
3f239f08
UH
37#define DEFAULT_NUM_LOGIC_CHANNELS 8
38#define DEFAULT_NUM_ANALOG_CHANNELS 4
c03ed397 39
8b2d41ed 40/* The size in bytes of chunks to send through the session bus. */
61c39f54 41#define LOGIC_BUFSIZE 4096
8b2d41ed
BV
42/* Size of the analog pattern space per channel. */
43#define ANALOG_BUFSIZE 4096
2474d87e 44
dddabe37 45#define DEFAULT_ANALOG_AMPLITUDE 25
4374219b
DJ
46#define ANALOG_SAMPLES_PER_PERIOD 20
47
2388ae86 48/* Logic patterns we can generate. */
e15f48c2 49enum {
0d31276b 50 /**
ba7dd8bb 51 * Spells "sigrok" across 8 channels using '0's (with '1's as
61c39f54 52 * "background") when displayed using the 'bits' output format.
95035832 53 * The pattern is repeated every 8 channels, shifted to the right
c07f60e7 54 * in time by one bit.
0d31276b 55 */
c8f4624d 56 PATTERN_SIGROK,
0d31276b 57
ba7dd8bb 58 /** Pseudo-random values on all channels. */
c8f4624d 59 PATTERN_RANDOM,
0d31276b
UH
60
61 /**
95035832 62 * Incrementing number across 8 channels. The pattern is repeated
ba7dd8bb 63 * every 8 channels, shifted to the right in time by one bit.
0d31276b 64 */
c8f4624d 65 PATTERN_INC,
c03ed397 66
ba7dd8bb 67 /** All channels have a low logic state. */
c03ed397
UH
68 PATTERN_ALL_LOW,
69
ba7dd8bb 70 /** All channels have a high logic state. */
c03ed397 71 PATTERN_ALL_HIGH,
2388ae86 72};
8b2d41ed 73
2388ae86
BV
74/* Analog patterns we can generate. */
75enum {
8b2d41ed
BV
76 /**
77 * Square wave.
78 */
79 PATTERN_SQUARE,
4374219b 80 PATTERN_SINE,
091c9621 81 PATTERN_TRIANGLE,
9f54e0e8 82 PATTERN_SAWTOOTH,
e15f48c2 83};
85b5af06 84
8b2d41ed 85static const char *logic_pattern_str[] = {
61c39f54
BV
86 "sigrok",
87 "random",
88 "incremental",
89 "all-low",
90 "all-high",
91};
92
8b2d41ed
BV
93static const char *analog_pattern_str[] = {
94 "square",
4374219b 95 "sine",
091c9621 96 "triangle",
9f54e0e8 97 "sawtooth",
8b2d41ed
BV
98};
99
100struct analog_gen {
101 int pattern;
dddabe37 102 float amplitude;
8b2d41ed
BV
103 float pattern_data[ANALOG_BUFSIZE];
104 unsigned int num_samples;
105 struct sr_datafeed_analog packet;
106};
107
b4750a3a
BV
108/* Private, per-device-instance driver context. */
109struct dev_context {
e15f48c2 110 int pipe_fds[2];
e0532047 111 GIOChannel *channel;
a7684294 112 uint64_t cur_samplerate;
b62bb97a 113 gboolean continuous;
a7684294
JH
114 uint64_t limit_samples;
115 uint64_t limit_msec;
7f4975b4
BV
116 uint64_t logic_counter;
117 uint64_t analog_counter;
3b203673 118 int64_t starttime;
61c39f54 119 uint64_t step;
8b2d41ed 120 /* Logic */
ba7dd8bb 121 int32_t num_logic_channels;
c07f60e7 122 unsigned int logic_unitsize;
660e398f 123 /* There is only ever one logic channel group, so its pattern goes here. */
c07f60e7
BV
124 uint8_t logic_pattern;
125 unsigned char logic_data[LOGIC_BUFSIZE];
8b2d41ed 126 /* Analog */
ba7dd8bb 127 int32_t num_analog_channels;
49224c28 128 GHashTable *ch_ag;
c07f60e7
BV
129};
130
1e4a7cac
BV
131static const uint32_t drvopts[] = {
132 SR_CONF_DEMO_DEV,
133 SR_CONF_LOGIC_ANALYZER,
134 SR_CONF_OSCILLOSCOPE,
135};
136
584560f1 137static const uint32_t scanopts[] = {
3f239f08
UH
138 SR_CONF_NUM_LOGIC_CHANNELS,
139 SR_CONF_NUM_ANALOG_CHANNELS,
e15f48c2 140};
85b5af06 141
390795c0 142static const uint32_t devopts[] = {
1e4a7cac 143 SR_CONF_CONTINUOUS | SR_CONF_SET,
5827f61b
BV
144 SR_CONF_LIMIT_SAMPLES | SR_CONF_GET | SR_CONF_SET,
145 SR_CONF_LIMIT_MSEC | SR_CONF_GET | SR_CONF_SET,
390795c0
BV
146 SR_CONF_SAMPLERATE | SR_CONF_GET | SR_CONF_SET | SR_CONF_LIST,
147};
148
149static const uint32_t devopts_cg_logic[] = {
f12d9979 150 SR_CONF_PATTERN_MODE | SR_CONF_GET | SR_CONF_SET | SR_CONF_LIST,
49224c28
BV
151};
152
390795c0 153static const uint32_t devopts_cg_analog[] = {
f12d9979
BV
154 SR_CONF_PATTERN_MODE | SR_CONF_GET | SR_CONF_SET | SR_CONF_LIST,
155 SR_CONF_AMPLITUDE | SR_CONF_GET | SR_CONF_SET,
7a1da331
BV
156};
157
d00088ca
BV
158static const uint64_t samplerates[] = {
159 SR_HZ(1),
160 SR_GHZ(1),
161 SR_HZ(1),
4bfbf9fc
BV
162};
163
c8f4624d 164static uint8_t pattern_sigrok[] = {
917e0e71
BV
165 0x4c, 0x92, 0x92, 0x92, 0x64, 0x00, 0x00, 0x00,
166 0x82, 0xfe, 0xfe, 0x82, 0x00, 0x00, 0x00, 0x00,
167 0x7c, 0x82, 0x82, 0x92, 0x74, 0x00, 0x00, 0x00,
168 0xfe, 0x12, 0x12, 0x32, 0xcc, 0x00, 0x00, 0x00,
169 0x7c, 0x82, 0x82, 0x82, 0x7c, 0x00, 0x00, 0x00,
170 0xfe, 0x10, 0x28, 0x44, 0x82, 0x00, 0x00, 0x00,
171 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
172 0xbe, 0xbe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
173};
174
dcf03d6d 175SR_PRIV struct sr_dev_driver demo_driver_info;
a873c594 176static struct sr_dev_driver *di = &demo_driver_info;
6239c175 177
6078d2c9 178static int dev_acquisition_stop(struct sr_dev_inst *sdi, void *cb_data);
6239c175 179
c07f60e7 180
6078d2c9 181static int init(struct sr_context *sr_ctx)
61136ea6 182{
f6beaac5 183 return std_init(sr_ctx, di, LOG_PREFIX);
61136ea6
BV
184}
185
49224c28 186static void generate_analog_pattern(struct analog_gen *ag, uint64_t sample_rate)
8b2d41ed 187{
4374219b 188 double t, frequency;
8b2d41ed
BV
189 float value;
190 unsigned int num_samples, i;
191 int last_end;
192
49224c28 193 sr_dbg("Generating %s pattern.", analog_pattern_str[ag->pattern]);
4374219b 194
49224c28 195 num_samples = ANALOG_BUFSIZE / sizeof(float);
8b2d41ed 196
4374219b 197 switch (ag->pattern) {
8b2d41ed 198 case PATTERN_SQUARE:
dddabe37 199 value = ag->amplitude;
8b2d41ed
BV
200 last_end = 0;
201 for (i = 0; i < num_samples; i++) {
202 if (i % 5 == 0)
203 value = -value;
204 if (i % 10 == 0)
3772c049 205 last_end = i;
8b2d41ed
BV
206 ag->pattern_data[i] = value;
207 }
208 ag->num_samples = last_end;
209 break;
4374219b
DJ
210
211 case PATTERN_SINE:
9d156555 212 frequency = (double) sample_rate / ANALOG_SAMPLES_PER_PERIOD;
4374219b
DJ
213
214 /* Make sure the number of samples we put out is an integer
215 * multiple of our period size */
216 /* FIXME we actually need only one period. A ringbuffer would be
217 * usefull here.*/
218 while (num_samples % ANALOG_SAMPLES_PER_PERIOD != 0)
219 num_samples--;
220
221 for (i = 0; i < num_samples; i++) {
222 t = (double) i / (double) sample_rate;
dddabe37 223 ag->pattern_data[i] = ag->amplitude *
4374219b
DJ
224 sin(2 * M_PI * frequency * t);
225 }
226
091c9621
DJ
227 ag->num_samples = num_samples;
228 break;
229
230 case PATTERN_TRIANGLE:
9d156555 231 frequency = (double) sample_rate / ANALOG_SAMPLES_PER_PERIOD;
091c9621
DJ
232
233 while (num_samples % ANALOG_SAMPLES_PER_PERIOD != 0)
234 num_samples--;
235
236 for (i = 0; i < num_samples; i++) {
237 t = (double) i / (double) sample_rate;
dddabe37 238 ag->pattern_data[i] = (2 * ag->amplitude / M_PI) *
091c9621
DJ
239 asin(sin(2 * M_PI * frequency * t));
240 }
241
9f54e0e8
DJ
242 ag->num_samples = num_samples;
243 break;
244
245 case PATTERN_SAWTOOTH:
9d156555 246 frequency = (double) sample_rate / ANALOG_SAMPLES_PER_PERIOD;
9f54e0e8
DJ
247
248 while (num_samples % ANALOG_SAMPLES_PER_PERIOD != 0)
249 num_samples--;
250
251 for (i = 0; i < num_samples; i++) {
252 t = (double) i / (double) sample_rate;
dddabe37 253 ag->pattern_data[i] = 2 * ag->amplitude *
9f54e0e8
DJ
254 ((t * frequency) - floor(0.5f + t * frequency));
255 }
256
4374219b
DJ
257 ag->num_samples = num_samples;
258 break;
8b2d41ed
BV
259 }
260}
261
6078d2c9 262static GSList *scan(GSList *options)
6239c175 263{
b4750a3a 264 struct drv_context *drvc;
33ef7573 265 struct dev_context *devc;
c07f60e7 266 struct sr_dev_inst *sdi;
ba7dd8bb 267 struct sr_channel *ch;
49224c28 268 struct sr_channel_group *cg, *acg;
c07f60e7 269 struct sr_config *src;
8b2d41ed 270 struct analog_gen *ag;
c07f60e7 271 GSList *devices, *l;
ba7dd8bb
UH
272 int num_logic_channels, num_analog_channels, pattern, i;
273 char channel_name[16];
067d0716 274
a873c594 275 drvc = di->priv;
4b97c74e 276
3f239f08
UH
277 num_logic_channels = DEFAULT_NUM_LOGIC_CHANNELS;
278 num_analog_channels = DEFAULT_NUM_ANALOG_CHANNELS;
c07f60e7
BV
279 for (l = options; l; l = l->next) {
280 src = l->data;
281 switch (src->key) {
3f239f08 282 case SR_CONF_NUM_LOGIC_CHANNELS:
ba7dd8bb 283 num_logic_channels = g_variant_get_int32(src->data);
c07f60e7 284 break;
3f239f08 285 case SR_CONF_NUM_ANALOG_CHANNELS:
ba7dd8bb 286 num_analog_channels = g_variant_get_int32(src->data);
c07f60e7
BV
287 break;
288 }
289 }
85b5af06 290
c07f60e7 291 devices = NULL;
0af636be
UH
292
293 sdi = sr_dev_inst_new();
294 sdi->status = SR_ST_ACTIVE;
4b664cd6 295 sdi->model = g_strdup("Demo device");
a873c594 296 sdi->driver = di;
e15f48c2 297
49224c28 298 devc = g_malloc(sizeof(struct dev_context));
8b2d41ed
BV
299 devc->cur_samplerate = SR_KHZ(200);
300 devc->limit_samples = 0;
301 devc->limit_msec = 0;
302 devc->step = 0;
b62bb97a 303 devc->continuous = FALSE;
ba7dd8bb
UH
304 devc->num_logic_channels = num_logic_channels;
305 devc->logic_unitsize = (devc->num_logic_channels + 7) / 8;
8b2d41ed 306 devc->logic_pattern = PATTERN_SIGROK;
ba7dd8bb 307 devc->num_analog_channels = num_analog_channels;
8b2d41ed 308
ba7dd8bb 309 /* Logic channels, all in one channel group. */
49224c28 310 cg = g_malloc0(sizeof(struct sr_channel_group));
40fd0264 311 cg->name = g_strdup("Logic");
ba7dd8bb
UH
312 for (i = 0; i < num_logic_channels; i++) {
313 sprintf(channel_name, "D%d", i);
3f239f08 314 if (!(ch = sr_channel_new(i, SR_CHANNEL_LOGIC, TRUE, channel_name)))
87ca93c5 315 return NULL;
ba7dd8bb
UH
316 sdi->channels = g_slist_append(sdi->channels, ch);
317 cg->channels = g_slist_append(cg->channels, ch);
87ca93c5 318 }
40fd0264 319 sdi->channel_groups = g_slist_append(NULL, cg);
87ca93c5 320
ba7dd8bb 321 /* Analog channels, channel groups and pattern generators. */
2b36d6c6 322 pattern = 0;
49224c28
BV
323 /* An "Analog" channel group with all analog channels in it. */
324 acg = g_malloc0(sizeof(struct sr_channel_group));
325 acg->name = g_strdup("Analog");
326 sdi->channel_groups = g_slist_append(sdi->channel_groups, acg);
327
328 devc->ch_ag = g_hash_table_new(g_direct_hash, g_direct_equal);
ba7dd8bb 329 for (i = 0; i < num_analog_channels; i++) {
49224c28
BV
330 snprintf(channel_name, 16, "A%d", i);
331 ch = sr_channel_new(i + num_logic_channels, SR_CHANNEL_ANALOG,
332 TRUE, channel_name);
ba7dd8bb 333 sdi->channels = g_slist_append(sdi->channels, ch);
49224c28 334 acg->channels = g_slist_append(acg->channels, ch);
c07f60e7 335
49224c28
BV
336 /* Every analog channel gets its own channel group as well. */
337 cg = g_malloc0(sizeof(struct sr_channel_group));
ba7dd8bb
UH
338 cg->name = g_strdup(channel_name);
339 cg->channels = g_slist_append(NULL, ch);
49224c28 340 sdi->channel_groups = g_slist_append(sdi->channel_groups, cg);
85b5af06 341
49224c28
BV
342 /* Every channel gets a generator struct. */
343 ag = g_malloc(sizeof(struct analog_gen));
dddabe37 344 ag->amplitude = DEFAULT_ANALOG_AMPLITUDE;
ba7dd8bb 345 ag->packet.channels = cg->channels;
8b2d41ed
BV
346 ag->packet.mq = 0;
347 ag->packet.mqflags = 0;
348 ag->packet.unit = SR_UNIT_VOLT;
349 ag->packet.data = ag->pattern_data;
2b36d6c6 350 ag->pattern = pattern;
49224c28 351 g_hash_table_insert(devc->ch_ag, ch, ag);
2b36d6c6
BV
352
353 if (++pattern == ARRAY_SIZE(analog_pattern_str))
354 pattern = 0;
33ef7573 355 }
33ef7573
JH
356
357 sdi->priv = devc;
8b2d41ed
BV
358 devices = g_slist_append(devices, sdi);
359 drvc->instances = g_slist_append(drvc->instances, sdi);
33ef7573 360
067d0716 361 return devices;
6239c175
UH
362}
363
6078d2c9 364static GSList *dev_list(void)
811deee4 365{
0e94d524 366 return ((struct drv_context *)(di->priv))->instances;
811deee4
BV
367}
368
6078d2c9 369static int dev_open(struct sr_dev_inst *sdi)
6239c175 370{
e73ffd42 371 sdi->status = SR_ST_ACTIVE;
697785d1 372
e46b8fb1 373 return SR_OK;
6239c175
UH
374}
375
6078d2c9 376static int dev_close(struct sr_dev_inst *sdi)
6239c175 377{
decfe89d 378 sdi->status = SR_ST_INACTIVE;
697785d1
UH
379
380 return SR_OK;
6239c175
UH
381}
382
ed0b7fed
BV
383static void clear_helper(void *priv)
384{
385 struct dev_context *devc;
49224c28
BV
386 GHashTableIter iter;
387 void *value;
ed0b7fed
BV
388
389 devc = priv;
49224c28
BV
390
391 /* Analog generators. */
392 g_hash_table_iter_init(&iter, devc->ch_ag);
393 while (g_hash_table_iter_next(&iter, NULL, &value))
394 g_free(value);
395 g_hash_table_unref(devc->ch_ag);
ed0b7fed
BV
396 g_free(devc);
397}
398
6078d2c9 399static int cleanup(void)
6239c175 400{
ed0b7fed 401 return std_dev_clear(di, clear_helper);
6239c175
UH
402}
403
584560f1 404static int config_get(uint32_t key, GVariant **data, const struct sr_dev_inst *sdi,
53b4680f 405 const struct sr_channel_group *cg)
6239c175 406{
c07f60e7 407 struct dev_context *devc;
ba7dd8bb 408 struct sr_channel *ch;
2388ae86
BV
409 struct analog_gen *ag;
410 int pattern;
6f57fd96 411
2388ae86
BV
412 if (!sdi)
413 return SR_ERR_ARG;
8f996b89 414
c07f60e7 415 devc = sdi->priv;
584560f1 416 switch (key) {
123e1313 417 case SR_CONF_SAMPLERATE:
a7684294 418 *data = g_variant_new_uint64(devc->cur_samplerate);
6239c175 419 break;
2474d87e 420 case SR_CONF_LIMIT_SAMPLES:
a7684294 421 *data = g_variant_new_uint64(devc->limit_samples);
2474d87e
BV
422 break;
423 case SR_CONF_LIMIT_MSEC:
a7684294 424 *data = g_variant_new_uint64(devc->limit_msec);
2474d87e
BV
425 break;
426 case SR_CONF_PATTERN_MODE:
53b4680f 427 if (!cg)
660e398f 428 return SR_ERR_CHANNEL_GROUP;
49224c28 429 /* Any channel in the group will do. */
ba7dd8bb 430 ch = cg->channels->data;
3f239f08 431 if (ch->type == SR_CHANNEL_LOGIC) {
2388ae86
BV
432 pattern = devc->logic_pattern;
433 *data = g_variant_new_string(logic_pattern_str[pattern]);
3f239f08 434 } else if (ch->type == SR_CHANNEL_ANALOG) {
49224c28 435 ag = g_hash_table_lookup(devc->ch_ag, ch);
2388ae86
BV
436 pattern = ag->pattern;
437 *data = g_variant_new_string(analog_pattern_str[pattern]);
438 } else
439 return SR_ERR_BUG;
c07f60e7 440 break;
dddabe37
BV
441 case SR_CONF_AMPLITUDE:
442 if (!cg)
443 return SR_ERR_CHANNEL_GROUP;
49224c28 444 /* Any channel in the group will do. */
dddabe37
BV
445 ch = cg->channels->data;
446 if (ch->type != SR_CHANNEL_ANALOG)
447 return SR_ERR_ARG;
49224c28 448 ag = g_hash_table_lookup(devc->ch_ag, ch);
dddabe37
BV
449 *data = g_variant_new_double(ag->amplitude);
450 break;
7dfcf010 451 default:
bd6fbf62 452 return SR_ERR_NA;
6239c175
UH
453 }
454
dfb0fa1a 455 return SR_OK;
6239c175
UH
456}
457
584560f1 458static int config_set(uint32_t key, GVariant *data, const struct sr_dev_inst *sdi,
53b4680f 459 const struct sr_channel_group *cg)
6239c175 460{
8b2d41ed 461 struct dev_context *devc;
4374219b 462 struct analog_gen *ag;
ba7dd8bb 463 struct sr_channel *ch;
49224c28
BV
464 GSList *l;
465 int logic_pattern, analog_pattern, ret;
61c39f54 466 unsigned int i;
1b79df2f 467 const char *stropt;
6239c175 468
8b2d41ed 469 devc = sdi->priv;
6239c175 470
e73ffd42
BV
471 if (sdi->status != SR_ST_ACTIVE)
472 return SR_ERR_DEV_CLOSED;
473
2388ae86 474 ret = SR_OK;
584560f1 475 switch (key) {
2388ae86 476 case SR_CONF_SAMPLERATE:
a7684294 477 devc->cur_samplerate = g_variant_get_uint64(data);
61c39f54 478 sr_dbg("Setting samplerate to %" PRIu64, devc->cur_samplerate);
2388ae86
BV
479 break;
480 case SR_CONF_LIMIT_SAMPLES:
a7684294
JH
481 devc->limit_msec = 0;
482 devc->limit_samples = g_variant_get_uint64(data);
8b2d41ed 483 sr_dbg("Setting sample limit to %" PRIu64, devc->limit_samples);
2388ae86
BV
484 break;
485 case SR_CONF_LIMIT_MSEC:
a7684294
JH
486 devc->limit_msec = g_variant_get_uint64(data);
487 devc->limit_samples = 0;
8b2d41ed 488 sr_dbg("Setting time limit to %" PRIu64"ms", devc->limit_msec);
2388ae86
BV
489 break;
490 case SR_CONF_PATTERN_MODE:
53b4680f 491 if (!cg)
660e398f 492 return SR_ERR_CHANNEL_GROUP;
d00088ca 493 stropt = g_variant_get_string(data, NULL);
49224c28
BV
494 logic_pattern = analog_pattern = -1;
495 for (i = 0; i < ARRAY_SIZE(logic_pattern_str); i++) {
496 if (!strcmp(stropt, logic_pattern_str[i])) {
497 logic_pattern = i;
498 break;
8b2d41ed 499 }
49224c28
BV
500 }
501 for (i = 0; i < ARRAY_SIZE(analog_pattern_str); i++) {
502 if (!strcmp(stropt, analog_pattern_str[i])) {
503 analog_pattern = i;
504 break;
8b2d41ed 505 }
49224c28
BV
506 }
507 if (logic_pattern == -1 && analog_pattern == -1)
508 return SR_ERR_ARG;
509 for (l = cg->channels; l; l = l->next) {
510 ch = l->data;
511 if (ch->type == SR_CHANNEL_LOGIC) {
512 if (logic_pattern == -1)
513 return SR_ERR_ARG;
514 sr_dbg("Setting logic pattern to %s",
515 logic_pattern_str[logic_pattern]);
516 devc->logic_pattern = logic_pattern;
517 /* Might as well do this now, these are static. */
518 if (logic_pattern == PATTERN_ALL_LOW)
519 memset(devc->logic_data, 0x00, LOGIC_BUFSIZE);
520 else if (logic_pattern == PATTERN_ALL_HIGH)
521 memset(devc->logic_data, 0xff, LOGIC_BUFSIZE);
522 } else if (ch->type == SR_CHANNEL_ANALOG) {
523 if (analog_pattern == -1)
524 return SR_ERR_ARG;
525 sr_dbg("Setting analog pattern for channel %s to %s",
526 ch->name, analog_pattern_str[analog_pattern]);
527 ag = g_hash_table_lookup(devc->ch_ag, ch);
528 ag->pattern = analog_pattern;
529 } else
530 return SR_ERR_BUG;
531 }
2388ae86 532 break;
dddabe37
BV
533 case SR_CONF_AMPLITUDE:
534 if (!cg)
535 return SR_ERR_CHANNEL_GROUP;
49224c28
BV
536 for (l = cg->channels; l; l = l->next) {
537 ch = l->data;
538 if (ch->type != SR_CHANNEL_ANALOG)
539 return SR_ERR_ARG;
540 ag = g_hash_table_lookup(devc->ch_ag, ch);
541 ag->amplitude = g_variant_get_double(data);
542 }
dddabe37 543 break;
2388ae86 544 default:
bd6fbf62 545 ret = SR_ERR_NA;
6239c175
UH
546 }
547
548 return ret;
549}
550
584560f1 551static int config_list(uint32_t key, GVariant **data, const struct sr_dev_inst *sdi,
53b4680f 552 const struct sr_channel_group *cg)
a1c743fc 553{
ba7dd8bb 554 struct sr_channel *ch;
d00088ca
BV
555 GVariant *gvar;
556 GVariantBuilder gvb;
a1c743fc
BV
557
558 (void)sdi;
559
7a1da331 560 if (key == SR_CONF_SCAN_OPTIONS) {
584560f1
BV
561 *data = g_variant_new_fixed_array(G_VARIANT_TYPE_UINT32,
562 scanopts, ARRAY_SIZE(scanopts), sizeof(uint32_t));
7a1da331
BV
563 return SR_OK;
564 }
565
390795c0
BV
566 if (key == SR_CONF_DEVICE_OPTIONS && !sdi) {
567 *data = g_variant_new_fixed_array(G_VARIANT_TYPE_UINT32,
1e4a7cac 568 drvopts, ARRAY_SIZE(drvopts), sizeof(uint32_t));
390795c0
BV
569 return SR_OK;
570 }
571
7a1da331
BV
572 if (!sdi)
573 return SR_ERR_ARG;
574
53b4680f 575 if (!cg) {
7a1da331
BV
576 switch (key) {
577 case SR_CONF_DEVICE_OPTIONS:
584560f1 578 *data = g_variant_new_fixed_array(G_VARIANT_TYPE_UINT32,
1e4a7cac 579 devopts, ARRAY_SIZE(devopts), sizeof(uint32_t));
7a1da331
BV
580 break;
581 case SR_CONF_SAMPLERATE:
582 g_variant_builder_init(&gvb, G_VARIANT_TYPE("a{sv}"));
583 gvar = g_variant_new_fixed_array(G_VARIANT_TYPE("t"), samplerates,
584 ARRAY_SIZE(samplerates), sizeof(uint64_t));
585 g_variant_builder_add(&gvb, "{sv}", "samplerate-steps", gvar);
586 *data = g_variant_builder_end(&gvb);
587 break;
588 default:
589 return SR_ERR_NA;
590 }
591 } else {
49224c28 592 /* Any channel in the group will do. */
ba7dd8bb 593 ch = cg->channels->data;
7a1da331
BV
594 switch (key) {
595 case SR_CONF_DEVICE_OPTIONS:
49224c28
BV
596 if (ch->type == SR_CHANNEL_LOGIC)
597 *data = g_variant_new_fixed_array(G_VARIANT_TYPE_INT32,
598 devopts_cg_logic, ARRAY_SIZE(devopts_cg_logic),
584560f1 599 sizeof(uint32_t));
49224c28
BV
600 else if (ch->type == SR_CHANNEL_ANALOG)
601 *data = g_variant_new_fixed_array(G_VARIANT_TYPE_INT32,
602 devopts_cg_analog, ARRAY_SIZE(devopts_cg_analog),
584560f1 603 sizeof(uint32_t));
49224c28
BV
604 else
605 return SR_ERR_BUG;
7a1da331
BV
606 break;
607 case SR_CONF_PATTERN_MODE:
3f239f08 608 if (ch->type == SR_CHANNEL_LOGIC)
7a1da331
BV
609 *data = g_variant_new_strv(logic_pattern_str,
610 ARRAY_SIZE(logic_pattern_str));
3f239f08 611 else if (ch->type == SR_CHANNEL_ANALOG)
7a1da331
BV
612 *data = g_variant_new_strv(analog_pattern_str,
613 ARRAY_SIZE(analog_pattern_str));
2388ae86
BV
614 else
615 return SR_ERR_BUG;
7a1da331
BV
616 break;
617 default:
618 return SR_ERR_NA;
619 }
a1c743fc
BV
620 }
621
622 return SR_OK;
623}
624
c07f60e7 625static void logic_generator(struct sr_dev_inst *sdi, uint64_t size)
85b5af06 626{
61c39f54 627 struct dev_context *devc;
c07f60e7
BV
628 uint64_t i, j;
629 uint8_t pat;
85b5af06 630
61c39f54 631 devc = sdi->priv;
85b5af06 632
c07f60e7 633 switch (devc->logic_pattern) {
61c39f54 634 case PATTERN_SIGROK:
c07f60e7
BV
635 memset(devc->logic_data, 0x00, size);
636 for (i = 0; i < size; i += devc->logic_unitsize) {
637 for (j = 0; j < devc->logic_unitsize; j++) {
638 pat = pattern_sigrok[(devc->step + j) % sizeof(pattern_sigrok)] >> 1;
639 devc->logic_data[i + j] = ~pat;
640 }
641 devc->step++;
917e0e71
BV
642 }
643 break;
61c39f54 644 case PATTERN_RANDOM:
5096c6a6 645 for (i = 0; i < size; i++)
61c39f54 646 devc->logic_data[i] = (uint8_t)(rand() & 0xff);
85b5af06 647 break;
61c39f54 648 case PATTERN_INC:
c07f60e7
BV
649 for (i = 0; i < size; i++) {
650 for (j = 0; j < devc->logic_unitsize; j++) {
651 devc->logic_data[i + j] = devc->step;
652 }
653 devc->step++;
654 }
c03ed397 655 break;
61c39f54
BV
656 case PATTERN_ALL_LOW:
657 case PATTERN_ALL_HIGH:
658 /* These were set when the pattern mode was selected. */
c03ed397
UH
659 break;
660 default:
c07f60e7 661 sr_err("Unknown pattern: %d.", devc->logic_pattern);
c03ed397 662 break;
85b5af06
UH
663 }
664}
665
85b5af06 666/* Callback handling data */
61c39f54 667static int prepare_data(int fd, int revents, void *cb_data)
85b5af06 668{
61c39f54
BV
669 struct sr_dev_inst *sdi;
670 struct dev_context *devc;
b9c735a2 671 struct sr_datafeed_packet packet;
9c939c51 672 struct sr_datafeed_logic logic;
8b2d41ed 673 struct analog_gen *ag;
62f155f0 674 int ag_pattern_pos;
49224c28
BV
675 GHashTableIter iter;
676 void *value;
b62bb97a 677 uint64_t logic_todo, analog_todo, expected_samplenum, analog_sent, sending_now;
3b203673 678 int64_t time, elapsed;
1924f59f 679
cb93f8a9
UH
680 (void)fd;
681 (void)revents;
1924f59f 682
61c39f54
BV
683 sdi = cb_data;
684 devc = sdi->priv;
b62bb97a 685 logic_todo = analog_todo = 0;
61c39f54 686
b62bb97a 687 /* How many samples should we have sent by now? */
3b203673
AG
688 time = g_get_monotonic_time();
689 elapsed = time - devc->starttime;
a7684294 690 expected_samplenum = elapsed * devc->cur_samplerate / 1000000;
7f4975b4 691
b62bb97a
BV
692 /* But never more than the limit, if there is one. */
693 if (!devc->continuous)
694 expected_samplenum = MIN(expected_samplenum, devc->limit_samples);
695
3b203673 696 /* Of those, how many do we still have to send? */
b62bb97a
BV
697 if (devc->num_logic_channels)
698 logic_todo = expected_samplenum - devc->logic_counter;
699 if (devc->num_analog_channels)
700 analog_todo = expected_samplenum - devc->analog_counter;
85b5af06 701
7f4975b4 702 while (logic_todo || analog_todo) {
c07f60e7 703 /* Logic */
b62bb97a
BV
704 if (logic_todo > 0) {
705 sending_now = MIN(logic_todo, LOGIC_BUFSIZE / devc->logic_unitsize);
8b2d41ed
BV
706 logic_generator(sdi, sending_now * devc->logic_unitsize);
707 packet.type = SR_DF_LOGIC;
708 packet.payload = &logic;
709 logic.length = sending_now * devc->logic_unitsize;
710 logic.unitsize = devc->logic_unitsize;
711 logic.data = devc->logic_data;
712 sr_session_send(sdi, &packet);
7f4975b4
BV
713 logic_todo -= sending_now;
714 devc->logic_counter += sending_now;
8b2d41ed
BV
715 }
716
ba7dd8bb 717 /* Analog, one channel at a time */
b62bb97a
BV
718 if (analog_todo > 0) {
719 analog_sent = 0;
49224c28
BV
720
721 g_hash_table_iter_init(&iter, devc->ch_ag);
722 while (g_hash_table_iter_next(&iter, NULL, &value)) {
723 ag = value;
8b2d41ed
BV
724 packet.type = SR_DF_ANALOG;
725 packet.payload = &ag->packet;
62f155f0
AJ
726 ag_pattern_pos = devc->analog_counter % ag->num_samples;
727 sending_now = MIN(analog_todo, ag->num_samples-ag_pattern_pos);
728 ag->packet.data = ag->pattern_data + ag_pattern_pos;
b62bb97a 729 ag->packet.num_samples = sending_now;
8b2d41ed 730 sr_session_send(sdi, &packet);
b62bb97a
BV
731
732 /* Whichever channel group gets there first. */
733 analog_sent = MAX(analog_sent, sending_now);
8b2d41ed 734 }
b62bb97a
BV
735 analog_todo -= analog_sent;
736 devc->analog_counter += analog_sent;
8b2d41ed 737 }
3b203673
AG
738 }
739
b62bb97a
BV
740 if (!devc->continuous
741 && (!devc->num_logic_channels || devc->logic_counter >= devc->limit_samples)
742 && (!devc->num_analog_channels || devc->analog_counter >= devc->limit_samples)) {
7f4975b4 743 sr_dbg("Requested number of samples reached.");
61c39f54 744 dev_acquisition_stop(sdi, cb_data);
c216d623 745 return TRUE;
85b5af06 746 }
1924f59f 747
85b5af06
UH
748 return TRUE;
749}
750
6078d2c9 751static int dev_acquisition_start(const struct sr_dev_inst *sdi, void *cb_data)
6239c175 752{
61c39f54 753 struct dev_context *devc;
49224c28
BV
754 GHashTableIter iter;
755 void *value;
85b5af06 756
102f1239
BV
757 (void)cb_data;
758
e73ffd42
BV
759 if (sdi->status != SR_ST_ACTIVE)
760 return SR_ERR_DEV_CLOSED;
761
61c39f54 762 devc = sdi->priv;
b62bb97a 763 devc->continuous = !devc->limit_samples;
7f4975b4 764 devc->logic_counter = devc->analog_counter = 0;
85b5af06 765
3b203673
AG
766 /*
767 * Setting two channels connected by a pipe is a remnant from when the
768 * demo driver generated data in a thread, and collected and sent the
769 * data in the main program loop.
770 * They are kept here because it provides a convenient way of setting
771 * up a timeout-based polling mechanism.
772 */
b4750a3a 773 if (pipe(devc->pipe_fds)) {
92bcedf6 774 sr_err("%s: pipe() failed", __func__);
e46b8fb1 775 return SR_ERR;
c03ed397 776 }
85b5af06 777
49224c28
BV
778 g_hash_table_iter_init(&iter, devc->ch_ag);
779 while (g_hash_table_iter_next(&iter, NULL, &value))
780 generate_analog_pattern(value, devc->cur_samplerate);
4374219b 781
e0532047 782 devc->channel = g_io_channel_unix_new(devc->pipe_fds[0]);
e0532047 783 g_io_channel_set_flags(devc->channel, G_IO_FLAG_NONBLOCK, NULL);
e6e8f8e0 784
d35aaf02 785 /* Set channel encoding to binary (default is UTF-8). */
e0532047 786 g_io_channel_set_encoding(devc->channel, NULL, NULL);
d35aaf02 787
b62bb97a 788 /* Make channels unbuffered. */
e0532047 789 g_io_channel_set_buffered(devc->channel, FALSE);
d35aaf02 790
b62bb97a
BV
791 sr_session_source_add_channel(sdi->session, devc->channel,
792 G_IO_IN | G_IO_ERR, 40, prepare_data, (void *)sdi);
85b5af06 793
4afdfd46 794 /* Send header packet to the session bus. */
102f1239 795 std_session_send_df_header(sdi, LOG_PREFIX);
f366e86c 796
3b203673
AG
797 /* We use this timestamp to decide how many more samples to send. */
798 devc->starttime = g_get_monotonic_time();
799
e46b8fb1 800 return SR_OK;
6239c175
UH
801}
802
6078d2c9 803static int dev_acquisition_stop(struct sr_dev_inst *sdi, void *cb_data)
6239c175 804{
8b2d41ed 805 struct dev_context *devc;
c216d623 806 struct sr_datafeed_packet packet;
7fd3e859 807
33ef7573 808 (void)cb_data;
7fd3e859 809
8b2d41ed 810 devc = sdi->priv;
a84f6ad3 811 sr_dbg("Stopping acquisition.");
49145a63 812
102f1239 813 sr_session_source_remove_channel(sdi->session, devc->channel);
e0532047 814 g_io_channel_shutdown(devc->channel, FALSE, NULL);
2150a69b
JH
815 g_io_channel_unref(devc->channel);
816 devc->channel = NULL;
c216d623
AG
817
818 /* Send last packet. */
819 packet.type = SR_DF_END;
c07f60e7 820 sr_session_send(sdi, &packet);
7fd3e859 821
3010f21c 822 return SR_OK;
6239c175
UH
823}
824
c09f0b57 825SR_PRIV struct sr_dev_driver demo_driver_info = {
e519ba86
UH
826 .name = "demo",
827 .longname = "Demo driver and pattern generator",
828 .api_version = 1,
6078d2c9
UH
829 .init = init,
830 .cleanup = cleanup,
831 .scan = scan,
832 .dev_list = dev_list,
a6630742 833 .dev_clear = NULL,
035a1078
BV
834 .config_get = config_get,
835 .config_set = config_set,
a1c743fc 836 .config_list = config_list,
6078d2c9
UH
837 .dev_open = dev_open,
838 .dev_close = dev_close,
839 .dev_acquisition_start = dev_acquisition_start,
840 .dev_acquisition_stop = dev_acquisition_stop,
b4750a3a 841 .priv = NULL,
6239c175 842};