]> sigrok.org Git - libsigrok.git/blame - hardware/demo/demo.c
sr: code organization cleanup
[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>
6239c175
UH
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
20 */
21
22#include <stdlib.h>
85b5af06 23#include <unistd.h>
6239c175 24#include <string.h>
d35aaf02
UH
25#ifdef _WIN32
26#include <io.h>
27#include <fcntl.h>
28#define pipe(fds) _pipe(fds, 4096, _O_BINARY)
29#endif
45c59c8b
BV
30#include "libsigrok.h"
31#include "libsigrok-internal.h"
6239c175 32
c03ed397 33/* TODO: Number of probes should be configurable. */
e15f48c2 34#define NUM_PROBES 8
c03ed397 35
e15f48c2 36#define DEMONAME "Demo device"
c03ed397
UH
37
38/* The size of chunks to send through the session bus. */
39/* TODO: Should be configurable. */
e15f48c2 40#define BUFSIZE 4096
85b5af06 41
0d31276b 42/* Supported patterns which we can generate */
e15f48c2 43enum {
0d31276b
UH
44 /**
45 * Pattern which spells "sigrok" using '0's (with '1's as "background")
46 * when displayed using the 'bits' output format.
47 */
c8f4624d 48 PATTERN_SIGROK,
0d31276b 49
c03ed397 50 /** Pattern which consists of (pseudo-)random values on all probes. */
c8f4624d 51 PATTERN_RANDOM,
0d31276b
UH
52
53 /**
54 * Pattern which consists of incrementing numbers.
55 * TODO: Better description.
56 */
c8f4624d 57 PATTERN_INC,
c03ed397
UH
58
59 /** Pattern where all probes have a low logic state. */
60 PATTERN_ALL_LOW,
61
62 /** Pattern where all probes have a high logic state. */
63 PATTERN_ALL_HIGH,
e15f48c2 64};
85b5af06 65
29cbfeaf 66/* FIXME: Should not be global. */
d35aaf02 67
455b26ed 68struct context {
e15f48c2 69 int pipe_fds[2];
249ae2be 70 GIOChannel *channels[2];
e15f48c2
BV
71 uint8_t sample_generator;
72 uint8_t thread_running;
73 uint64_t samples_counter;
3cd3a20b 74 void *session_dev_id;
b9cc3629 75 GTimer *timer;
e15f48c2 76};
85b5af06 77
915f7cc8 78static const int hwcaps[] = {
5a2326a7 79 SR_HWCAP_LOGIC_ANALYZER,
bb7ef793 80 SR_HWCAP_DEMO_DEV,
4bfbf9fc 81 SR_HWCAP_SAMPLERATE,
5a2326a7
UH
82 SR_HWCAP_PATTERN_MODE,
83 SR_HWCAP_LIMIT_SAMPLES,
84 SR_HWCAP_LIMIT_MSEC,
85 SR_HWCAP_CONTINUOUS,
6239c175
UH
86};
87
a533743d 88static const struct sr_samplerates samplerates = {
c9140419 89 SR_HZ(1),
59df0c77 90 SR_GHZ(1),
c9140419 91 SR_HZ(1),
4bfbf9fc
BV
92 NULL,
93};
94
c8f4624d 95static const char *pattern_strings[] = {
c03ed397 96 "sigrok",
e15f48c2
BV
97 "random",
98 "incremental",
c03ed397
UH
99 "all-low",
100 "all-high",
02440dd8 101 NULL,
85b5af06
UH
102};
103
d261dbbf 104/* We name the probes 0-7 on our demo driver. */
464d12c7
KS
105static const char *probe_names[NUM_PROBES + 1] = {
106 "0",
107 "1",
108 "2",
109 "3",
110 "4",
111 "5",
112 "6",
113 "7",
114 NULL,
115};
116
c8f4624d 117static uint8_t pattern_sigrok[] = {
917e0e71
BV
118 0x4c, 0x92, 0x92, 0x92, 0x64, 0x00, 0x00, 0x00,
119 0x82, 0xfe, 0xfe, 0x82, 0x00, 0x00, 0x00, 0x00,
120 0x7c, 0x82, 0x82, 0x92, 0x74, 0x00, 0x00, 0x00,
121 0xfe, 0x12, 0x12, 0x32, 0xcc, 0x00, 0x00, 0x00,
122 0x7c, 0x82, 0x82, 0x82, 0x7c, 0x00, 0x00, 0x00,
123 0xfe, 0x10, 0x28, 0x44, 0x82, 0x00, 0x00, 0x00,
124 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
125 0xbe, 0xbe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
126};
127
ea9cfed7
UH
128/* Private, per-device-instance driver context. */
129/* TODO: struct context as with the other drivers. */
130
e7eb703f 131/* List of struct sr_dev_inst, maintained by dev_open()/dev_close(). */
dcf03d6d
BV
132SR_PRIV struct sr_dev_driver demo_driver_info;
133static struct sr_dev_driver *ddi = &demo_driver_info;
59df0c77 134static uint64_t cur_samplerate = SR_KHZ(200);
b9cc3629
BV
135static uint64_t limit_samples = 0;
136static uint64_t limit_msec = 0;
c8f4624d 137static int default_pattern = PATTERN_SIGROK;
b9cc3629
BV
138static GThread *my_thread;
139static int thread_running;
6239c175 140
3ffb6964
BV
141static int hw_dev_acquisition_stop(const struct sr_dev_inst *sdi,
142 void *cb_data);
6239c175 143
40dda2c3 144static int hw_init(void)
61136ea6
BV
145{
146
147 /* Nothing to do. */
148
149 return SR_OK;
150}
151
067d0716 152static GSList *hw_scan(GSList *options)
6239c175 153{
d68e2d1a 154 struct sr_dev_inst *sdi;
87ca93c5 155 struct sr_probe *probe;
067d0716 156 GSList *devices;
87ca93c5 157 int i;
067d0716
BV
158
159 (void)options;
160 devices = NULL;
85b5af06 161
d3683c42 162 sdi = sr_dev_inst_new(0, SR_ST_ACTIVE, DEMONAME, NULL, NULL);
c03ed397 163 if (!sdi) {
d68e2d1a 164 sr_err("demo: %s: sr_dev_inst_new failed", __func__);
85b5af06 165 return 0;
c03ed397 166 }
7dfcf010 167 sdi->driver = ddi;
e15f48c2 168
87ca93c5
BV
169 for (i = 0; probe_names[i]; i++) {
170 if (!(probe = sr_probe_new(i, SR_PROBE_ANALOG, TRUE,
171 probe_names[i])))
172 return NULL;
173 sdi->probes = g_slist_append(sdi->probes, probe);
174 }
175
067d0716 176 devices = g_slist_append(devices, sdi);
dcf03d6d 177 ddi->instances = g_slist_append(ddi->instances, sdi);
85b5af06 178
067d0716 179 return devices;
6239c175
UH
180}
181
25a0f108 182static int hw_dev_open(struct sr_dev_inst *sdi)
6239c175 183{
17e1afcb 184 /* Avoid compiler warnings. */
25a0f108 185 (void)sdi;
6239c175
UH
186
187 /* Nothing needed so far. */
697785d1 188
e46b8fb1 189 return SR_OK;
6239c175
UH
190}
191
25a0f108 192static int hw_dev_close(struct sr_dev_inst *sdi)
6239c175 193{
17e1afcb 194 /* Avoid compiler warnings. */
25a0f108 195 (void)sdi;
6239c175
UH
196
197 /* Nothing needed so far. */
697785d1
UH
198
199 return SR_OK;
6239c175
UH
200}
201
57ab7d9f 202static int hw_cleanup(void)
6239c175
UH
203{
204 /* Nothing needed so far. */
57ab7d9f 205 return SR_OK;
6239c175
UH
206}
207
dfb0fa1a
BV
208static int hw_info_get(int info_id, const void **data,
209 const struct sr_dev_inst *sdi)
6239c175 210{
85b5af06 211
dfb0fa1a 212 switch (info_id) {
1d9a8a5f 213 case SR_DI_INST:
dfb0fa1a 214 *data = sdi;
6239c175 215 break;
46c7a4da
BV
216 case SR_DI_HWCAPS:
217 *data = hwcaps;
218 break;
5a2326a7 219 case SR_DI_NUM_PROBES:
dfb0fa1a 220 *data = GINT_TO_POINTER(NUM_PROBES);
6239c175 221 break;
464d12c7 222 case SR_DI_PROBE_NAMES:
dfb0fa1a 223 *data = probe_names;
464d12c7 224 break;
4bfbf9fc 225 case SR_DI_SAMPLERATES:
dfb0fa1a 226 *data = &samplerates;
4bfbf9fc 227 break;
5a2326a7 228 case SR_DI_CUR_SAMPLERATE:
dfb0fa1a 229 *data = &cur_samplerate;
6239c175 230 break;
eb0a3731 231 case SR_DI_PATTERNS:
dfb0fa1a 232 *data = &pattern_strings;
e15f48c2 233 break;
7dfcf010
BV
234 default:
235 return SR_ERR_ARG;
6239c175
UH
236 }
237
dfb0fa1a 238 return SR_OK;
6239c175
UH
239}
240
6f4b1868
BV
241static int hw_dev_config_set(const struct sr_dev_inst *sdi, int hwcap,
242 const void *value)
6239c175
UH
243{
244 int ret;
1b79df2f 245 const char *stropt;
6239c175 246
6f4b1868 247 (void)sdi;
6239c175 248
ffedd0bf 249 if (hwcap == SR_HWCAP_PROBECONFIG) {
d81d2933
BV
250 /* Nothing to do, but must be supported */
251 ret = SR_OK;
ffedd0bf 252 } else if (hwcap == SR_HWCAP_SAMPLERATE) {
1b79df2f 253 cur_samplerate = *(const uint64_t *)value;
6f422264
UH
254 sr_dbg("demo: %s: setting samplerate to %" PRIu64, __func__,
255 cur_samplerate);
e46b8fb1 256 ret = SR_OK;
ffedd0bf 257 } else if (hwcap == SR_HWCAP_LIMIT_SAMPLES) {
8489264f 258 limit_msec = 0;
1b79df2f 259 limit_samples = *(const uint64_t *)value;
6f422264
UH
260 sr_dbg("demo: %s: setting limit_samples to %" PRIu64, __func__,
261 limit_samples);
e46b8fb1 262 ret = SR_OK;
ffedd0bf 263 } else if (hwcap == SR_HWCAP_LIMIT_MSEC) {
1b79df2f 264 limit_msec = *(const uint64_t *)value;
8489264f 265 limit_samples = 0;
6f422264
UH
266 sr_dbg("demo: %s: setting limit_msec to %" PRIu64, __func__,
267 limit_msec);
e46b8fb1 268 ret = SR_OK;
ffedd0bf 269 } else if (hwcap == SR_HWCAP_PATTERN_MODE) {
e15f48c2 270 stropt = value;
c03ed397
UH
271 ret = SR_OK;
272 if (!strcmp(stropt, "sigrok")) {
273 default_pattern = PATTERN_SIGROK;
274 } else if (!strcmp(stropt, "random")) {
c8f4624d 275 default_pattern = PATTERN_RANDOM;
e15f48c2 276 } else if (!strcmp(stropt, "incremental")) {
c8f4624d 277 default_pattern = PATTERN_INC;
c03ed397
UH
278 } else if (!strcmp(stropt, "all-low")) {
279 default_pattern = PATTERN_ALL_LOW;
280 } else if (!strcmp(stropt, "all-high")) {
281 default_pattern = PATTERN_ALL_HIGH;
e15f48c2 282 } else {
e46b8fb1 283 ret = SR_ERR;
e15f48c2 284 }
c8f4624d
UH
285 sr_dbg("demo: %s: setting pattern to %d", __func__,
286 default_pattern);
6239c175 287 } else {
e46b8fb1 288 ret = SR_ERR;
6239c175
UH
289 }
290
291 return ret;
292}
293
5096c6a6 294static void samples_generator(uint8_t *buf, uint64_t size, void *data)
85b5af06 295{
cddd1c5f 296 static uint64_t p = 0;
455b26ed 297 struct context *ctx = data;
cddd1c5f 298 uint64_t i;
85b5af06 299
c03ed397 300 /* TODO: Needed? */
5096c6a6 301 memset(buf, 0, size);
85b5af06 302
ab331b67 303 switch (ctx->sample_generator) {
c03ed397 304 case PATTERN_SIGROK: /* sigrok pattern */
917e0e71 305 for (i = 0; i < size; i++) {
c8f4624d 306 *(buf + i) = ~(pattern_sigrok[p] >> 1);
917e0e71
BV
307 if (++p == 64)
308 p = 0;
309 }
310 break;
c8f4624d 311 case PATTERN_RANDOM: /* Random */
5096c6a6
UH
312 for (i = 0; i < size; i++)
313 *(buf + i) = (uint8_t)(rand() & 0xff);
85b5af06 314 break;
c8f4624d 315 case PATTERN_INC: /* Simple increment */
5096c6a6 316 for (i = 0; i < size; i++)
85b5af06
UH
317 *(buf + i) = i;
318 break;
c03ed397 319 case PATTERN_ALL_LOW: /* All probes are low */
5a9660dd 320 memset(buf, 0x00, size);
c03ed397
UH
321 break;
322 case PATTERN_ALL_HIGH: /* All probes are high */
5a9660dd 323 memset(buf, 0xff, size);
c03ed397
UH
324 break;
325 default:
0abee507 326 sr_err("demo: %s: unknown pattern %d", __func__,
ab331b67 327 ctx->sample_generator);
c03ed397 328 break;
85b5af06
UH
329 }
330}
331
332/* Thread function */
333static void thread_func(void *data)
334{
455b26ed 335 struct context *ctx = data;
85b5af06
UH
336 uint8_t buf[BUFSIZE];
337 uint64_t nb_to_send = 0;
d35aaf02 338 int bytes_written;
1924f59f
HE
339 double time_cur, time_last, time_diff;
340
ab331b67 341 time_last = g_timer_elapsed(ctx->timer, NULL);
85b5af06
UH
342
343 while (thread_running) {
1924f59f 344 /* Rate control */
ab331b67 345 time_cur = g_timer_elapsed(ctx->timer, NULL);
1924f59f
HE
346
347 time_diff = time_cur - time_last;
348 time_last = time_cur;
349
350 nb_to_send = cur_samplerate * time_diff;
351
c03ed397 352 if (limit_samples) {
1924f59f 353 nb_to_send = MIN(nb_to_send,
ab331b67 354 limit_samples - ctx->samples_counter);
c03ed397 355 }
1924f59f
HE
356
357 /* Make sure we don't overflow. */
358 nb_to_send = MIN(nb_to_send, BUFSIZE);
359
360 if (nb_to_send) {
361 samples_generator(buf, nb_to_send, data);
ab331b67 362 ctx->samples_counter += nb_to_send;
070befcd 363
249ae2be 364 g_io_channel_write_chars(ctx->channels[1], (gchar *)&buf,
c03ed397 365 nb_to_send, (gsize *)&bytes_written, NULL);
b9cc3629
BV
366 }
367
1924f59f
HE
368 /* Check if we're done. */
369 if ((limit_msec && time_cur * 1000 > limit_msec) ||
ab331b67 370 (limit_samples && ctx->samples_counter >= limit_samples))
1924f59f 371 {
ab331b67 372 close(ctx->pipe_fds[1]);
85b5af06 373 thread_running = 0;
85b5af06
UH
374 }
375
1924f59f 376 g_usleep(10);
85b5af06
UH
377 }
378}
379
380/* Callback handling data */
1f9813eb 381static int receive_data(int fd, int revents, void *cb_data)
85b5af06 382{
249ae2be 383 struct context *ctx = cb_data;
b9c735a2 384 struct sr_datafeed_packet packet;
9c939c51
BV
385 struct sr_datafeed_logic logic;
386 static uint64_t samples_received = 0;
387 unsigned char c[BUFSIZE];
108a5bfb 388 gsize z;
1924f59f 389
26ce0bbf 390 /* Avoid compiler warnings. */
cb93f8a9
UH
391 (void)fd;
392 (void)revents;
1924f59f
HE
393
394 do {
249ae2be 395 g_io_channel_read_chars(ctx->channels[0],
070befcd 396 (gchar *)&c, BUFSIZE, &z, NULL);
1924f59f
HE
397
398 if (z > 0) {
5a2326a7 399 packet.type = SR_DF_LOGIC;
9c939c51 400 packet.payload = &logic;
9c939c51
BV
401 logic.length = z;
402 logic.unitsize = 1;
403 logic.data = c;
249ae2be 404 sr_session_send(ctx->session_dev_id, &packet);
9c939c51 405 samples_received += z;
1924f59f
HE
406 }
407 } while (z > 0);
85b5af06 408
c03ed397
UH
409 if (!thread_running && z <= 0) {
410 /* Make sure we don't receive more packets. */
249ae2be 411 g_io_channel_shutdown(ctx->channels[0], FALSE, NULL);
d35aaf02 412
1924f59f 413 /* Send last packet. */
5a2326a7 414 packet.type = SR_DF_END;
249ae2be 415 sr_session_send(ctx->session_dev_id, &packet);
1924f59f
HE
416
417 return FALSE;
85b5af06 418 }
1924f59f 419
85b5af06
UH
420 return TRUE;
421}
422
3ffb6964
BV
423static int hw_dev_acquisition_start(const struct sr_dev_inst *sdi,
424 void *cb_data)
6239c175 425{
b9c735a2
UH
426 struct sr_datafeed_packet *packet;
427 struct sr_datafeed_header *header;
f366e86c 428 struct sr_datafeed_meta_logic meta;
455b26ed 429 struct context *ctx;
6239c175 430
3ffb6964
BV
431 (void)sdi;
432
ab331b67 433 /* TODO: 'ctx' is never g_free()'d? */
455b26ed 434 if (!(ctx = g_try_malloc(sizeof(struct context)))) {
ab331b67 435 sr_err("demo: %s: ctx malloc failed", __func__);
e46b8fb1 436 return SR_ERR_MALLOC;
27a3a6fe 437 }
85b5af06 438
ab331b67
UH
439 ctx->sample_generator = default_pattern;
440 ctx->session_dev_id = cb_data;
ab331b67 441 ctx->samples_counter = 0;
85b5af06 442
ab331b67 443 if (pipe(ctx->pipe_fds)) {
c03ed397
UH
444 /* TODO: Better error message. */
445 sr_err("demo: %s: pipe() failed", __func__);
e46b8fb1 446 return SR_ERR;
c03ed397 447 }
85b5af06 448
249ae2be
LPC
449 ctx->channels[0] = g_io_channel_unix_new(ctx->pipe_fds[0]);
450 ctx->channels[1] = g_io_channel_unix_new(ctx->pipe_fds[1]);
d35aaf02 451
e6e8f8e0
LPC
452 g_io_channel_set_flags(ctx->channels[0], G_IO_FLAG_NONBLOCK, NULL);
453
d35aaf02 454 /* Set channel encoding to binary (default is UTF-8). */
249ae2be
LPC
455 g_io_channel_set_encoding(ctx->channels[0], NULL, NULL);
456 g_io_channel_set_encoding(ctx->channels[1], NULL, NULL);
d35aaf02
UH
457
458 /* Make channels to unbuffered. */
249ae2be
LPC
459 g_io_channel_set_buffered(ctx->channels[0], FALSE);
460 g_io_channel_set_buffered(ctx->channels[1], FALSE);
d35aaf02 461
249ae2be
LPC
462 sr_session_source_add_channel(ctx->channels[0], G_IO_IN | G_IO_ERR,
463 40, receive_data, ctx);
85b5af06
UH
464
465 /* Run the demo thread. */
466 g_thread_init(NULL);
c03ed397 467 /* This must to be done between g_thread_init() & g_thread_create(). */
ab331b67 468 ctx->timer = g_timer_new();
85b5af06
UH
469 thread_running = 1;
470 my_thread =
ab331b67 471 g_thread_create((GThreadFunc)thread_func, ctx, TRUE, NULL);
c03ed397
UH
472 if (!my_thread) {
473 sr_err("demo: %s: g_thread_create failed", __func__);
474 return SR_ERR; /* TODO */
475 }
6239c175 476
27a3a6fe
UH
477 if (!(packet = g_try_malloc(sizeof(struct sr_datafeed_packet)))) {
478 sr_err("demo: %s: packet malloc failed", __func__);
e46b8fb1 479 return SR_ERR_MALLOC;
27a3a6fe
UH
480 }
481
482 if (!(header = g_try_malloc(sizeof(struct sr_datafeed_header)))) {
483 sr_err("demo: %s: header malloc failed", __func__);
484 return SR_ERR_MALLOC;
485 }
6239c175 486
5a2326a7 487 packet->type = SR_DF_HEADER;
9c939c51 488 packet->payload = header;
6239c175
UH
489 header->feed_version = 1;
490 gettimeofday(&header->starttime, NULL);
ab331b67 491 sr_session_send(ctx->session_dev_id, packet);
f366e86c
BV
492
493 /* Send metadata about the SR_DF_LOGIC packets to come. */
494 packet->type = SR_DF_META_LOGIC;
495 packet->payload = &meta;
496 meta.samplerate = cur_samplerate;
497 meta.num_probes = NUM_PROBES;
498 sr_session_send(ctx->session_dev_id, packet);
499
27a3a6fe
UH
500 g_free(header);
501 g_free(packet);
6239c175 502
e46b8fb1 503 return SR_OK;
6239c175
UH
504}
505
3ffb6964
BV
506static int hw_dev_acquisition_stop(const struct sr_dev_inst *sdi,
507 void *cb_data)
6239c175 508{
17e1afcb 509 /* Avoid compiler warnings. */
3ffb6964 510 (void)sdi;
3cd3a20b 511 (void)cb_data;
6239c175 512
1924f59f
HE
513 /* Stop generate thread. */
514 thread_running = 0;
3010f21c
UH
515
516 return SR_OK;
6239c175
UH
517}
518
c09f0b57 519SR_PRIV struct sr_dev_driver demo_driver_info = {
e519ba86
UH
520 .name = "demo",
521 .longname = "Demo driver and pattern generator",
522 .api_version = 1,
523 .init = hw_init,
524 .cleanup = hw_cleanup,
61136ea6 525 .scan = hw_scan,
e7eb703f
UH
526 .dev_open = hw_dev_open,
527 .dev_close = hw_dev_close,
dfb0fa1a 528 .info_get = hw_info_get,
a9a245b4 529 .dev_config_set = hw_dev_config_set,
69040b7c
UH
530 .dev_acquisition_start = hw_dev_acquisition_start,
531 .dev_acquisition_stop = hw_dev_acquisition_stop,
dcf03d6d 532 .instances = NULL,
6239c175 533};