]> sigrok.org Git - libsigrok.git/blame - src/hardware/demo/demo.c
Publish config key capabilities.
[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
584560f1 131static const uint32_t scanopts[] = {
3f239f08
UH
132 SR_CONF_NUM_LOGIC_CHANNELS,
133 SR_CONF_NUM_ANALOG_CHANNELS,
e15f48c2 134};
85b5af06 135
7a1da331 136static const int devopts[] = {
1953564a 137 SR_CONF_LOGIC_ANALYZER,
b62bb97a 138 SR_CONF_CONTINUOUS,
5827f61b
BV
139 SR_CONF_DEMO_DEV,
140 SR_CONF_SAMPLERATE | SR_CONF_GET | SR_CONF_SET | SR_CONF_LIST,
141 SR_CONF_LIMIT_SAMPLES | SR_CONF_GET | SR_CONF_SET,
142 SR_CONF_LIMIT_MSEC | SR_CONF_GET | SR_CONF_SET,
143 SR_CONF_PATTERN_MODE | SR_CONF_GET | SR_CONF_SET | SR_CONF_LIST,
144 SR_CONF_NUM_LOGIC_CHANNELS | SR_CONF_GET,
145 SR_CONF_NUM_ANALOG_CHANNELS | SR_CONF_GET,
146 SR_CONF_AMPLITUDE | SR_CONF_GET | SR_CONF_SET,
6239c175
UH
147};
148
49224c28
BV
149static const int devopts_cg_logic[] = {
150 SR_CONF_PATTERN_MODE,
151};
152
153static const int devopts_cg_analog[] = {
7a1da331 154 SR_CONF_PATTERN_MODE,
dddabe37 155 SR_CONF_AMPLITUDE,
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)
205 last_end = i - 1;
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;
61c39f54 292 sdi = sr_dev_inst_new(0, SR_ST_ACTIVE, "Demo device", NULL, NULL);
c03ed397 293 if (!sdi) {
e45ad6e2
UH
294 sr_err("Device instance creation failed.");
295 return NULL;
c03ed397 296 }
a873c594 297 sdi->driver = di;
e15f48c2 298
49224c28 299 devc = g_malloc(sizeof(struct dev_context));
8b2d41ed
BV
300 devc->cur_samplerate = SR_KHZ(200);
301 devc->limit_samples = 0;
302 devc->limit_msec = 0;
303 devc->step = 0;
b62bb97a 304 devc->continuous = FALSE;
ba7dd8bb
UH
305 devc->num_logic_channels = num_logic_channels;
306 devc->logic_unitsize = (devc->num_logic_channels + 7) / 8;
8b2d41ed 307 devc->logic_pattern = PATTERN_SIGROK;
ba7dd8bb 308 devc->num_analog_channels = num_analog_channels;
8b2d41ed 309
ba7dd8bb 310 /* Logic channels, all in one channel group. */
49224c28 311 cg = g_malloc0(sizeof(struct sr_channel_group));
40fd0264 312 cg->name = g_strdup("Logic");
ba7dd8bb
UH
313 for (i = 0; i < num_logic_channels; i++) {
314 sprintf(channel_name, "D%d", i);
3f239f08 315 if (!(ch = sr_channel_new(i, SR_CHANNEL_LOGIC, TRUE, channel_name)))
87ca93c5 316 return NULL;
ba7dd8bb
UH
317 sdi->channels = g_slist_append(sdi->channels, ch);
318 cg->channels = g_slist_append(cg->channels, ch);
87ca93c5 319 }
40fd0264 320 sdi->channel_groups = g_slist_append(NULL, cg);
87ca93c5 321
ba7dd8bb 322 /* Analog channels, channel groups and pattern generators. */
2b36d6c6 323 pattern = 0;
49224c28
BV
324 /* An "Analog" channel group with all analog channels in it. */
325 acg = g_malloc0(sizeof(struct sr_channel_group));
326 acg->name = g_strdup("Analog");
327 sdi->channel_groups = g_slist_append(sdi->channel_groups, acg);
328
329 devc->ch_ag = g_hash_table_new(g_direct_hash, g_direct_equal);
ba7dd8bb 330 for (i = 0; i < num_analog_channels; i++) {
49224c28
BV
331 snprintf(channel_name, 16, "A%d", i);
332 ch = sr_channel_new(i + num_logic_channels, SR_CHANNEL_ANALOG,
333 TRUE, channel_name);
ba7dd8bb 334 sdi->channels = g_slist_append(sdi->channels, ch);
49224c28 335 acg->channels = g_slist_append(acg->channels, ch);
c07f60e7 336
49224c28
BV
337 /* Every analog channel gets its own channel group as well. */
338 cg = g_malloc0(sizeof(struct sr_channel_group));
ba7dd8bb
UH
339 cg->name = g_strdup(channel_name);
340 cg->channels = g_slist_append(NULL, ch);
49224c28 341 sdi->channel_groups = g_slist_append(sdi->channel_groups, cg);
85b5af06 342
49224c28
BV
343 /* Every channel gets a generator struct. */
344 ag = g_malloc(sizeof(struct analog_gen));
dddabe37 345 ag->amplitude = DEFAULT_ANALOG_AMPLITUDE;
ba7dd8bb 346 ag->packet.channels = cg->channels;
8b2d41ed
BV
347 ag->packet.mq = 0;
348 ag->packet.mqflags = 0;
349 ag->packet.unit = SR_UNIT_VOLT;
350 ag->packet.data = ag->pattern_data;
2b36d6c6 351 ag->pattern = pattern;
49224c28 352 g_hash_table_insert(devc->ch_ag, ch, ag);
2b36d6c6
BV
353
354 if (++pattern == ARRAY_SIZE(analog_pattern_str))
355 pattern = 0;
33ef7573 356 }
33ef7573
JH
357
358 sdi->priv = devc;
8b2d41ed
BV
359 devices = g_slist_append(devices, sdi);
360 drvc->instances = g_slist_append(drvc->instances, sdi);
33ef7573 361
067d0716 362 return devices;
6239c175
UH
363}
364
6078d2c9 365static GSList *dev_list(void)
811deee4 366{
0e94d524 367 return ((struct drv_context *)(di->priv))->instances;
811deee4
BV
368}
369
6078d2c9 370static int dev_open(struct sr_dev_inst *sdi)
6239c175 371{
e73ffd42 372 sdi->status = SR_ST_ACTIVE;
697785d1 373
e46b8fb1 374 return SR_OK;
6239c175
UH
375}
376
6078d2c9 377static int dev_close(struct sr_dev_inst *sdi)
6239c175 378{
decfe89d 379 sdi->status = SR_ST_INACTIVE;
697785d1
UH
380
381 return SR_OK;
6239c175
UH
382}
383
ed0b7fed
BV
384static void clear_helper(void *priv)
385{
386 struct dev_context *devc;
49224c28
BV
387 GHashTableIter iter;
388 void *value;
ed0b7fed
BV
389
390 devc = priv;
49224c28
BV
391
392 /* Analog generators. */
393 g_hash_table_iter_init(&iter, devc->ch_ag);
394 while (g_hash_table_iter_next(&iter, NULL, &value))
395 g_free(value);
396 g_hash_table_unref(devc->ch_ag);
ed0b7fed
BV
397 g_free(devc);
398}
399
6078d2c9 400static int cleanup(void)
6239c175 401{
ed0b7fed 402 return std_dev_clear(di, clear_helper);
6239c175
UH
403}
404
584560f1 405static int config_get(uint32_t key, GVariant **data, const struct sr_dev_inst *sdi,
53b4680f 406 const struct sr_channel_group *cg)
6239c175 407{
c07f60e7 408 struct dev_context *devc;
ba7dd8bb 409 struct sr_channel *ch;
2388ae86
BV
410 struct analog_gen *ag;
411 int pattern;
6f57fd96 412
2388ae86
BV
413 if (!sdi)
414 return SR_ERR_ARG;
8f996b89 415
c07f60e7 416 devc = sdi->priv;
584560f1 417 switch (key) {
123e1313 418 case SR_CONF_SAMPLERATE:
a7684294 419 *data = g_variant_new_uint64(devc->cur_samplerate);
6239c175 420 break;
2474d87e 421 case SR_CONF_LIMIT_SAMPLES:
a7684294 422 *data = g_variant_new_uint64(devc->limit_samples);
2474d87e
BV
423 break;
424 case SR_CONF_LIMIT_MSEC:
a7684294 425 *data = g_variant_new_uint64(devc->limit_msec);
2474d87e
BV
426 break;
427 case SR_CONF_PATTERN_MODE:
53b4680f 428 if (!cg)
660e398f 429 return SR_ERR_CHANNEL_GROUP;
49224c28 430 /* Any channel in the group will do. */
ba7dd8bb 431 ch = cg->channels->data;
3f239f08 432 if (ch->type == SR_CHANNEL_LOGIC) {
2388ae86
BV
433 pattern = devc->logic_pattern;
434 *data = g_variant_new_string(logic_pattern_str[pattern]);
3f239f08 435 } else if (ch->type == SR_CHANNEL_ANALOG) {
49224c28 436 ag = g_hash_table_lookup(devc->ch_ag, ch);
2388ae86
BV
437 pattern = ag->pattern;
438 *data = g_variant_new_string(analog_pattern_str[pattern]);
439 } else
440 return SR_ERR_BUG;
c07f60e7 441 break;
3f239f08 442 case SR_CONF_NUM_LOGIC_CHANNELS:
ba7dd8bb 443 *data = g_variant_new_int32(devc->num_logic_channels);
c07f60e7 444 break;
3f239f08 445 case SR_CONF_NUM_ANALOG_CHANNELS:
ba7dd8bb 446 *data = g_variant_new_int32(devc->num_analog_channels);
2474d87e 447 break;
dddabe37
BV
448 case SR_CONF_AMPLITUDE:
449 if (!cg)
450 return SR_ERR_CHANNEL_GROUP;
49224c28 451 /* Any channel in the group will do. */
dddabe37
BV
452 ch = cg->channels->data;
453 if (ch->type != SR_CHANNEL_ANALOG)
454 return SR_ERR_ARG;
49224c28 455 ag = g_hash_table_lookup(devc->ch_ag, ch);
dddabe37
BV
456 *data = g_variant_new_double(ag->amplitude);
457 break;
7dfcf010 458 default:
bd6fbf62 459 return SR_ERR_NA;
6239c175
UH
460 }
461
dfb0fa1a 462 return SR_OK;
6239c175
UH
463}
464
584560f1 465static int config_set(uint32_t key, GVariant *data, const struct sr_dev_inst *sdi,
53b4680f 466 const struct sr_channel_group *cg)
6239c175 467{
8b2d41ed 468 struct dev_context *devc;
4374219b 469 struct analog_gen *ag;
ba7dd8bb 470 struct sr_channel *ch;
49224c28
BV
471 GSList *l;
472 int logic_pattern, analog_pattern, ret;
61c39f54 473 unsigned int i;
1b79df2f 474 const char *stropt;
6239c175 475
8b2d41ed 476 devc = sdi->priv;
6239c175 477
e73ffd42
BV
478 if (sdi->status != SR_ST_ACTIVE)
479 return SR_ERR_DEV_CLOSED;
480
2388ae86 481 ret = SR_OK;
584560f1 482 switch (key) {
2388ae86 483 case SR_CONF_SAMPLERATE:
a7684294 484 devc->cur_samplerate = g_variant_get_uint64(data);
61c39f54 485 sr_dbg("Setting samplerate to %" PRIu64, devc->cur_samplerate);
2388ae86
BV
486 break;
487 case SR_CONF_LIMIT_SAMPLES:
a7684294
JH
488 devc->limit_msec = 0;
489 devc->limit_samples = g_variant_get_uint64(data);
8b2d41ed 490 sr_dbg("Setting sample limit to %" PRIu64, devc->limit_samples);
2388ae86
BV
491 break;
492 case SR_CONF_LIMIT_MSEC:
a7684294
JH
493 devc->limit_msec = g_variant_get_uint64(data);
494 devc->limit_samples = 0;
8b2d41ed 495 sr_dbg("Setting time limit to %" PRIu64"ms", devc->limit_msec);
2388ae86
BV
496 break;
497 case SR_CONF_PATTERN_MODE:
53b4680f 498 if (!cg)
660e398f 499 return SR_ERR_CHANNEL_GROUP;
d00088ca 500 stropt = g_variant_get_string(data, NULL);
ba7dd8bb 501 ch = cg->channels->data;
49224c28
BV
502 logic_pattern = analog_pattern = -1;
503 for (i = 0; i < ARRAY_SIZE(logic_pattern_str); i++) {
504 if (!strcmp(stropt, logic_pattern_str[i])) {
505 logic_pattern = i;
506 break;
8b2d41ed 507 }
49224c28
BV
508 }
509 for (i = 0; i < ARRAY_SIZE(analog_pattern_str); i++) {
510 if (!strcmp(stropt, analog_pattern_str[i])) {
511 analog_pattern = i;
512 break;
8b2d41ed 513 }
49224c28
BV
514 }
515 if (logic_pattern == -1 && analog_pattern == -1)
516 return SR_ERR_ARG;
517 for (l = cg->channels; l; l = l->next) {
518 ch = l->data;
519 if (ch->type == SR_CHANNEL_LOGIC) {
520 if (logic_pattern == -1)
521 return SR_ERR_ARG;
522 sr_dbg("Setting logic pattern to %s",
523 logic_pattern_str[logic_pattern]);
524 devc->logic_pattern = logic_pattern;
525 /* Might as well do this now, these are static. */
526 if (logic_pattern == PATTERN_ALL_LOW)
527 memset(devc->logic_data, 0x00, LOGIC_BUFSIZE);
528 else if (logic_pattern == PATTERN_ALL_HIGH)
529 memset(devc->logic_data, 0xff, LOGIC_BUFSIZE);
530 } else if (ch->type == SR_CHANNEL_ANALOG) {
531 if (analog_pattern == -1)
532 return SR_ERR_ARG;
533 sr_dbg("Setting analog pattern for channel %s to %s",
534 ch->name, analog_pattern_str[analog_pattern]);
535 ag = g_hash_table_lookup(devc->ch_ag, ch);
536 ag->pattern = analog_pattern;
537 } else
538 return SR_ERR_BUG;
539 }
2388ae86 540 break;
dddabe37
BV
541 case SR_CONF_AMPLITUDE:
542 if (!cg)
543 return SR_ERR_CHANNEL_GROUP;
49224c28
BV
544 for (l = cg->channels; l; l = l->next) {
545 ch = l->data;
546 if (ch->type != SR_CHANNEL_ANALOG)
547 return SR_ERR_ARG;
548 ag = g_hash_table_lookup(devc->ch_ag, ch);
549 ag->amplitude = g_variant_get_double(data);
550 }
dddabe37 551 break;
2388ae86 552 default:
bd6fbf62 553 ret = SR_ERR_NA;
6239c175
UH
554 }
555
556 return ret;
557}
558
584560f1 559static int config_list(uint32_t key, GVariant **data, const struct sr_dev_inst *sdi,
53b4680f 560 const struct sr_channel_group *cg)
a1c743fc 561{
ba7dd8bb 562 struct sr_channel *ch;
d00088ca
BV
563 GVariant *gvar;
564 GVariantBuilder gvb;
a1c743fc
BV
565
566 (void)sdi;
567
7a1da331 568 if (key == SR_CONF_SCAN_OPTIONS) {
584560f1
BV
569 *data = g_variant_new_fixed_array(G_VARIANT_TYPE_UINT32,
570 scanopts, ARRAY_SIZE(scanopts), sizeof(uint32_t));
7a1da331
BV
571 return SR_OK;
572 }
573
574 if (!sdi)
575 return SR_ERR_ARG;
576
53b4680f 577 if (!cg) {
7a1da331
BV
578 switch (key) {
579 case SR_CONF_DEVICE_OPTIONS:
584560f1
BV
580 *data = g_variant_new_fixed_array(G_VARIANT_TYPE_UINT32,
581 devopts, ARRAY_SIZE(devopts), sizeof(uint32_t));
7a1da331
BV
582 break;
583 case SR_CONF_SAMPLERATE:
584 g_variant_builder_init(&gvb, G_VARIANT_TYPE("a{sv}"));
585 gvar = g_variant_new_fixed_array(G_VARIANT_TYPE("t"), samplerates,
586 ARRAY_SIZE(samplerates), sizeof(uint64_t));
587 g_variant_builder_add(&gvb, "{sv}", "samplerate-steps", gvar);
588 *data = g_variant_builder_end(&gvb);
589 break;
590 default:
591 return SR_ERR_NA;
592 }
593 } else {
49224c28 594 /* Any channel in the group will do. */
ba7dd8bb 595 ch = cg->channels->data;
7a1da331
BV
596 switch (key) {
597 case SR_CONF_DEVICE_OPTIONS:
49224c28
BV
598 if (ch->type == SR_CHANNEL_LOGIC)
599 *data = g_variant_new_fixed_array(G_VARIANT_TYPE_INT32,
600 devopts_cg_logic, ARRAY_SIZE(devopts_cg_logic),
584560f1 601 sizeof(uint32_t));
49224c28
BV
602 else if (ch->type == SR_CHANNEL_ANALOG)
603 *data = g_variant_new_fixed_array(G_VARIANT_TYPE_INT32,
604 devopts_cg_analog, ARRAY_SIZE(devopts_cg_analog),
584560f1 605 sizeof(uint32_t));
49224c28
BV
606 else
607 return SR_ERR_BUG;
7a1da331
BV
608 break;
609 case SR_CONF_PATTERN_MODE:
3f239f08 610 if (ch->type == SR_CHANNEL_LOGIC)
7a1da331
BV
611 *data = g_variant_new_strv(logic_pattern_str,
612 ARRAY_SIZE(logic_pattern_str));
3f239f08 613 else if (ch->type == SR_CHANNEL_ANALOG)
7a1da331
BV
614 *data = g_variant_new_strv(analog_pattern_str,
615 ARRAY_SIZE(analog_pattern_str));
2388ae86
BV
616 else
617 return SR_ERR_BUG;
7a1da331
BV
618 break;
619 default:
620 return SR_ERR_NA;
621 }
a1c743fc
BV
622 }
623
624 return SR_OK;
625}
626
c07f60e7 627static void logic_generator(struct sr_dev_inst *sdi, uint64_t size)
85b5af06 628{
61c39f54 629 struct dev_context *devc;
c07f60e7
BV
630 uint64_t i, j;
631 uint8_t pat;
85b5af06 632
61c39f54 633 devc = sdi->priv;
85b5af06 634
c07f60e7 635 switch (devc->logic_pattern) {
61c39f54 636 case PATTERN_SIGROK:
c07f60e7
BV
637 memset(devc->logic_data, 0x00, size);
638 for (i = 0; i < size; i += devc->logic_unitsize) {
639 for (j = 0; j < devc->logic_unitsize; j++) {
640 pat = pattern_sigrok[(devc->step + j) % sizeof(pattern_sigrok)] >> 1;
641 devc->logic_data[i + j] = ~pat;
642 }
643 devc->step++;
917e0e71
BV
644 }
645 break;
61c39f54 646 case PATTERN_RANDOM:
5096c6a6 647 for (i = 0; i < size; i++)
61c39f54 648 devc->logic_data[i] = (uint8_t)(rand() & 0xff);
85b5af06 649 break;
61c39f54 650 case PATTERN_INC:
c07f60e7
BV
651 for (i = 0; i < size; i++) {
652 for (j = 0; j < devc->logic_unitsize; j++) {
653 devc->logic_data[i + j] = devc->step;
654 }
655 devc->step++;
656 }
c03ed397 657 break;
61c39f54
BV
658 case PATTERN_ALL_LOW:
659 case PATTERN_ALL_HIGH:
660 /* These were set when the pattern mode was selected. */
c03ed397
UH
661 break;
662 default:
c07f60e7 663 sr_err("Unknown pattern: %d.", devc->logic_pattern);
c03ed397 664 break;
85b5af06
UH
665 }
666}
667
85b5af06 668/* Callback handling data */
61c39f54 669static int prepare_data(int fd, int revents, void *cb_data)
85b5af06 670{
61c39f54
BV
671 struct sr_dev_inst *sdi;
672 struct dev_context *devc;
b9c735a2 673 struct sr_datafeed_packet packet;
9c939c51 674 struct sr_datafeed_logic logic;
8b2d41ed 675 struct analog_gen *ag;
49224c28
BV
676 GHashTableIter iter;
677 void *value;
b62bb97a 678 uint64_t logic_todo, analog_todo, expected_samplenum, analog_sent, sending_now;
3b203673 679 int64_t time, elapsed;
1924f59f 680
cb93f8a9
UH
681 (void)fd;
682 (void)revents;
1924f59f 683
61c39f54
BV
684 sdi = cb_data;
685 devc = sdi->priv;
b62bb97a 686 logic_todo = analog_todo = 0;
61c39f54 687
b62bb97a 688 /* How many samples should we have sent by now? */
3b203673
AG
689 time = g_get_monotonic_time();
690 elapsed = time - devc->starttime;
a7684294 691 expected_samplenum = elapsed * devc->cur_samplerate / 1000000;
7f4975b4 692
b62bb97a
BV
693 /* But never more than the limit, if there is one. */
694 if (!devc->continuous)
695 expected_samplenum = MIN(expected_samplenum, devc->limit_samples);
696
3b203673 697 /* Of those, how many do we still have to send? */
b62bb97a
BV
698 if (devc->num_logic_channels)
699 logic_todo = expected_samplenum - devc->logic_counter;
700 if (devc->num_analog_channels)
701 analog_todo = expected_samplenum - devc->analog_counter;
85b5af06 702
7f4975b4 703 while (logic_todo || analog_todo) {
c07f60e7 704 /* Logic */
b62bb97a
BV
705 if (logic_todo > 0) {
706 sending_now = MIN(logic_todo, LOGIC_BUFSIZE / devc->logic_unitsize);
8b2d41ed
BV
707 logic_generator(sdi, sending_now * devc->logic_unitsize);
708 packet.type = SR_DF_LOGIC;
709 packet.payload = &logic;
710 logic.length = sending_now * devc->logic_unitsize;
711 logic.unitsize = devc->logic_unitsize;
712 logic.data = devc->logic_data;
713 sr_session_send(sdi, &packet);
7f4975b4
BV
714 logic_todo -= sending_now;
715 devc->logic_counter += sending_now;
8b2d41ed
BV
716 }
717
ba7dd8bb 718 /* Analog, one channel at a time */
b62bb97a
BV
719 if (analog_todo > 0) {
720 analog_sent = 0;
49224c28
BV
721
722 g_hash_table_iter_init(&iter, devc->ch_ag);
723 while (g_hash_table_iter_next(&iter, NULL, &value)) {
724 ag = value;
8b2d41ed
BV
725 packet.type = SR_DF_ANALOG;
726 packet.payload = &ag->packet;
4374219b
DJ
727
728 /* FIXME we should make sure we output a whole
729 * period of data before we send out again the
730 * beginning of our buffer. A ring buffer would
731 * help here as well */
732
b62bb97a
BV
733 sending_now = MIN(analog_todo, ag->num_samples);
734 ag->packet.num_samples = sending_now;
8b2d41ed 735 sr_session_send(sdi, &packet);
b62bb97a
BV
736
737 /* Whichever channel group gets there first. */
738 analog_sent = MAX(analog_sent, sending_now);
8b2d41ed 739 }
b62bb97a
BV
740 analog_todo -= analog_sent;
741 devc->analog_counter += analog_sent;
8b2d41ed 742 }
3b203673
AG
743 }
744
b62bb97a
BV
745 if (!devc->continuous
746 && (!devc->num_logic_channels || devc->logic_counter >= devc->limit_samples)
747 && (!devc->num_analog_channels || devc->analog_counter >= devc->limit_samples)) {
7f4975b4 748 sr_dbg("Requested number of samples reached.");
61c39f54 749 dev_acquisition_stop(sdi, cb_data);
c216d623 750 return TRUE;
85b5af06 751 }
1924f59f 752
85b5af06
UH
753 return TRUE;
754}
755
6078d2c9 756static int dev_acquisition_start(const struct sr_dev_inst *sdi, void *cb_data)
6239c175 757{
61c39f54 758 struct dev_context *devc;
49224c28
BV
759 GHashTableIter iter;
760 void *value;
85b5af06 761
102f1239
BV
762 (void)cb_data;
763
e73ffd42
BV
764 if (sdi->status != SR_ST_ACTIVE)
765 return SR_ERR_DEV_CLOSED;
766
61c39f54 767 devc = sdi->priv;
b62bb97a 768 devc->continuous = !devc->limit_samples;
7f4975b4 769 devc->logic_counter = devc->analog_counter = 0;
85b5af06 770
3b203673
AG
771 /*
772 * Setting two channels connected by a pipe is a remnant from when the
773 * demo driver generated data in a thread, and collected and sent the
774 * data in the main program loop.
775 * They are kept here because it provides a convenient way of setting
776 * up a timeout-based polling mechanism.
777 */
b4750a3a 778 if (pipe(devc->pipe_fds)) {
92bcedf6 779 sr_err("%s: pipe() failed", __func__);
e46b8fb1 780 return SR_ERR;
c03ed397 781 }
85b5af06 782
49224c28
BV
783 g_hash_table_iter_init(&iter, devc->ch_ag);
784 while (g_hash_table_iter_next(&iter, NULL, &value))
785 generate_analog_pattern(value, devc->cur_samplerate);
4374219b 786
e0532047 787 devc->channel = g_io_channel_unix_new(devc->pipe_fds[0]);
e0532047 788 g_io_channel_set_flags(devc->channel, G_IO_FLAG_NONBLOCK, NULL);
e6e8f8e0 789
d35aaf02 790 /* Set channel encoding to binary (default is UTF-8). */
e0532047 791 g_io_channel_set_encoding(devc->channel, NULL, NULL);
d35aaf02 792
b62bb97a 793 /* Make channels unbuffered. */
e0532047 794 g_io_channel_set_buffered(devc->channel, FALSE);
d35aaf02 795
b62bb97a
BV
796 sr_session_source_add_channel(sdi->session, devc->channel,
797 G_IO_IN | G_IO_ERR, 40, prepare_data, (void *)sdi);
85b5af06 798
4afdfd46 799 /* Send header packet to the session bus. */
102f1239 800 std_session_send_df_header(sdi, LOG_PREFIX);
f366e86c 801
3b203673
AG
802 /* We use this timestamp to decide how many more samples to send. */
803 devc->starttime = g_get_monotonic_time();
804
e46b8fb1 805 return SR_OK;
6239c175
UH
806}
807
6078d2c9 808static int dev_acquisition_stop(struct sr_dev_inst *sdi, void *cb_data)
6239c175 809{
8b2d41ed 810 struct dev_context *devc;
c216d623 811 struct sr_datafeed_packet packet;
7fd3e859 812
33ef7573 813 (void)cb_data;
7fd3e859 814
8b2d41ed 815 devc = sdi->priv;
a84f6ad3 816 sr_dbg("Stopping acquisition.");
49145a63 817
102f1239 818 sr_session_source_remove_channel(sdi->session, devc->channel);
e0532047 819 g_io_channel_shutdown(devc->channel, FALSE, NULL);
2150a69b
JH
820 g_io_channel_unref(devc->channel);
821 devc->channel = NULL;
c216d623
AG
822
823 /* Send last packet. */
824 packet.type = SR_DF_END;
c07f60e7 825 sr_session_send(sdi, &packet);
7fd3e859 826
3010f21c 827 return SR_OK;
6239c175
UH
828}
829
c09f0b57 830SR_PRIV struct sr_dev_driver demo_driver_info = {
e519ba86
UH
831 .name = "demo",
832 .longname = "Demo driver and pattern generator",
833 .api_version = 1,
6078d2c9
UH
834 .init = init,
835 .cleanup = cleanup,
836 .scan = scan,
837 .dev_list = dev_list,
a6630742 838 .dev_clear = NULL,
035a1078
BV
839 .config_get = config_get,
840 .config_set = config_set,
a1c743fc 841 .config_list = config_list,
6078d2c9
UH
842 .dev_open = dev_open,
843 .dev_close = dev_close,
844 .dev_acquisition_start = dev_acquisition_start,
845 .dev_acquisition_stop = dev_acquisition_stop,
b4750a3a 846 .priv = NULL,
6239c175 847};