]> sigrok.org Git - libsigrok.git/blame - hardware/demo/demo.c
demo: scan/info_get fixes
[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;
bb7ef793 74 int dev_index;
3cd3a20b 75 void *session_dev_id;
b9cc3629 76 GTimer *timer;
e15f48c2 77};
85b5af06 78
915f7cc8 79static const int hwcaps[] = {
5a2326a7 80 SR_HWCAP_LOGIC_ANALYZER,
bb7ef793 81 SR_HWCAP_DEMO_DEV,
4bfbf9fc 82 SR_HWCAP_SAMPLERATE,
5a2326a7
UH
83 SR_HWCAP_PATTERN_MODE,
84 SR_HWCAP_LIMIT_SAMPLES,
85 SR_HWCAP_LIMIT_MSEC,
86 SR_HWCAP_CONTINUOUS,
6239c175
UH
87};
88
a533743d 89static const struct sr_samplerates samplerates = {
c9140419 90 SR_HZ(1),
59df0c77 91 SR_GHZ(1),
c9140419 92 SR_HZ(1),
4bfbf9fc
BV
93 NULL,
94};
95
c8f4624d 96static const char *pattern_strings[] = {
c03ed397 97 "sigrok",
e15f48c2
BV
98 "random",
99 "incremental",
c03ed397
UH
100 "all-low",
101 "all-high",
02440dd8 102 NULL,
85b5af06
UH
103};
104
d261dbbf 105/* We name the probes 0-7 on our demo driver. */
464d12c7
KS
106static const char *probe_names[NUM_PROBES + 1] = {
107 "0",
108 "1",
109 "2",
110 "3",
111 "4",
112 "5",
113 "6",
114 "7",
115 NULL,
116};
117
c8f4624d 118static uint8_t pattern_sigrok[] = {
917e0e71
BV
119 0x4c, 0x92, 0x92, 0x92, 0x64, 0x00, 0x00, 0x00,
120 0x82, 0xfe, 0xfe, 0x82, 0x00, 0x00, 0x00, 0x00,
121 0x7c, 0x82, 0x82, 0x92, 0x74, 0x00, 0x00, 0x00,
122 0xfe, 0x12, 0x12, 0x32, 0xcc, 0x00, 0x00, 0x00,
123 0x7c, 0x82, 0x82, 0x82, 0x7c, 0x00, 0x00, 0x00,
124 0xfe, 0x10, 0x28, 0x44, 0x82, 0x00, 0x00, 0x00,
125 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
126 0xbe, 0xbe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
127};
128
ea9cfed7
UH
129/* Private, per-device-instance driver context. */
130/* TODO: struct context as with the other drivers. */
131
e7eb703f 132/* List of struct sr_dev_inst, maintained by dev_open()/dev_close(). */
dcf03d6d
BV
133SR_PRIV struct sr_dev_driver demo_driver_info;
134static struct sr_dev_driver *ddi = &demo_driver_info;
59df0c77 135static uint64_t cur_samplerate = SR_KHZ(200);
b9cc3629
BV
136static uint64_t limit_samples = 0;
137static uint64_t limit_msec = 0;
c8f4624d 138static int default_pattern = PATTERN_SIGROK;
b9cc3629
BV
139static GThread *my_thread;
140static int thread_running;
6239c175 141
3cd3a20b 142static int hw_dev_acquisition_stop(int dev_index, 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;
067d0716
BV
155 GSList *devices;
156
157 (void)options;
158 devices = NULL;
85b5af06 159
d3683c42 160 sdi = sr_dev_inst_new(0, SR_ST_ACTIVE, DEMONAME, NULL, NULL);
c03ed397 161 if (!sdi) {
d68e2d1a 162 sr_err("demo: %s: sr_dev_inst_new failed", __func__);
85b5af06 163 return 0;
c03ed397 164 }
7dfcf010 165 sdi->driver = ddi;
e15f48c2 166
067d0716 167 devices = g_slist_append(devices, sdi);
dcf03d6d 168 ddi->instances = g_slist_append(ddi->instances, sdi);
85b5af06 169
067d0716 170 return devices;
6239c175
UH
171}
172
e7eb703f 173static int hw_dev_open(int dev_index)
6239c175 174{
17e1afcb 175 /* Avoid compiler warnings. */
bb7ef793 176 (void)dev_index;
6239c175
UH
177
178 /* Nothing needed so far. */
697785d1 179
e46b8fb1 180 return SR_OK;
6239c175
UH
181}
182
e7eb703f 183static int hw_dev_close(int dev_index)
6239c175 184{
17e1afcb 185 /* Avoid compiler warnings. */
bb7ef793 186 (void)dev_index;
6239c175
UH
187
188 /* Nothing needed so far. */
697785d1
UH
189
190 return SR_OK;
6239c175
UH
191}
192
57ab7d9f 193static int hw_cleanup(void)
6239c175
UH
194{
195 /* Nothing needed so far. */
57ab7d9f 196 return SR_OK;
6239c175
UH
197}
198
dfb0fa1a
BV
199static int hw_info_get(int info_id, const void **data,
200 const struct sr_dev_inst *sdi)
6239c175 201{
85b5af06 202
dfb0fa1a 203 switch (info_id) {
1d9a8a5f 204 case SR_DI_INST:
dfb0fa1a 205 *data = sdi;
6239c175 206 break;
5a2326a7 207 case SR_DI_NUM_PROBES:
dfb0fa1a 208 *data = GINT_TO_POINTER(NUM_PROBES);
6239c175 209 break;
464d12c7 210 case SR_DI_PROBE_NAMES:
dfb0fa1a 211 *data = probe_names;
464d12c7 212 break;
4bfbf9fc 213 case SR_DI_SAMPLERATES:
dfb0fa1a 214 *data = &samplerates;
4bfbf9fc 215 break;
5a2326a7 216 case SR_DI_CUR_SAMPLERATE:
dfb0fa1a 217 *data = &cur_samplerate;
6239c175 218 break;
eb0a3731 219 case SR_DI_PATTERNS:
dfb0fa1a 220 *data = &pattern_strings;
e15f48c2 221 break;
7dfcf010
BV
222 default:
223 return SR_ERR_ARG;
6239c175
UH
224 }
225
dfb0fa1a 226 return SR_OK;
6239c175
UH
227}
228
e7eb703f 229static int hw_dev_status_get(int dev_index)
6239c175 230{
17e1afcb 231 /* Avoid compiler warnings. */
bb7ef793 232 (void)dev_index;
5096c6a6 233
5a2326a7 234 return SR_ST_ACTIVE;
6239c175
UH
235}
236
915f7cc8 237static const int *hw_hwcap_get_all(void)
6239c175 238{
ffedd0bf 239 return hwcaps;
6239c175
UH
240}
241
1b79df2f 242static int hw_dev_config_set(int dev_index, int hwcap, const void *value)
6239c175
UH
243{
244 int ret;
1b79df2f 245 const char *stropt;
6239c175 246
17e1afcb 247 /* Avoid compiler warnings. */
bb7ef793 248 (void)dev_index;
6239c175 249
ffedd0bf 250 if (hwcap == SR_HWCAP_PROBECONFIG) {
d81d2933
BV
251 /* Nothing to do, but must be supported */
252 ret = SR_OK;
ffedd0bf 253 } else if (hwcap == SR_HWCAP_SAMPLERATE) {
1b79df2f 254 cur_samplerate = *(const uint64_t *)value;
6f422264
UH
255 sr_dbg("demo: %s: setting samplerate to %" PRIu64, __func__,
256 cur_samplerate);
e46b8fb1 257 ret = SR_OK;
ffedd0bf 258 } else if (hwcap == SR_HWCAP_LIMIT_SAMPLES) {
8489264f 259 limit_msec = 0;
1b79df2f 260 limit_samples = *(const uint64_t *)value;
6f422264
UH
261 sr_dbg("demo: %s: setting limit_samples to %" PRIu64, __func__,
262 limit_samples);
e46b8fb1 263 ret = SR_OK;
ffedd0bf 264 } else if (hwcap == SR_HWCAP_LIMIT_MSEC) {
1b79df2f 265 limit_msec = *(const uint64_t *)value;
8489264f 266 limit_samples = 0;
6f422264
UH
267 sr_dbg("demo: %s: setting limit_msec to %" PRIu64, __func__,
268 limit_msec);
e46b8fb1 269 ret = SR_OK;
ffedd0bf 270 } else if (hwcap == SR_HWCAP_PATTERN_MODE) {
e15f48c2 271 stropt = value;
c03ed397
UH
272 ret = SR_OK;
273 if (!strcmp(stropt, "sigrok")) {
274 default_pattern = PATTERN_SIGROK;
275 } else if (!strcmp(stropt, "random")) {
c8f4624d 276 default_pattern = PATTERN_RANDOM;
e15f48c2 277 } else if (!strcmp(stropt, "incremental")) {
c8f4624d 278 default_pattern = PATTERN_INC;
c03ed397
UH
279 } else if (!strcmp(stropt, "all-low")) {
280 default_pattern = PATTERN_ALL_LOW;
281 } else if (!strcmp(stropt, "all-high")) {
282 default_pattern = PATTERN_ALL_HIGH;
e15f48c2 283 } else {
e46b8fb1 284 ret = SR_ERR;
e15f48c2 285 }
c8f4624d
UH
286 sr_dbg("demo: %s: setting pattern to %d", __func__,
287 default_pattern);
6239c175 288 } else {
e46b8fb1 289 ret = SR_ERR;
6239c175
UH
290 }
291
292 return ret;
293}
294
5096c6a6 295static void samples_generator(uint8_t *buf, uint64_t size, void *data)
85b5af06 296{
cddd1c5f 297 static uint64_t p = 0;
455b26ed 298 struct context *ctx = data;
cddd1c5f 299 uint64_t i;
85b5af06 300
c03ed397 301 /* TODO: Needed? */
5096c6a6 302 memset(buf, 0, size);
85b5af06 303
ab331b67 304 switch (ctx->sample_generator) {
c03ed397 305 case PATTERN_SIGROK: /* sigrok pattern */
917e0e71 306 for (i = 0; i < size; i++) {
c8f4624d 307 *(buf + i) = ~(pattern_sigrok[p] >> 1);
917e0e71
BV
308 if (++p == 64)
309 p = 0;
310 }
311 break;
c8f4624d 312 case PATTERN_RANDOM: /* Random */
5096c6a6
UH
313 for (i = 0; i < size; i++)
314 *(buf + i) = (uint8_t)(rand() & 0xff);
85b5af06 315 break;
c8f4624d 316 case PATTERN_INC: /* Simple increment */
5096c6a6 317 for (i = 0; i < size; i++)
85b5af06
UH
318 *(buf + i) = i;
319 break;
c03ed397 320 case PATTERN_ALL_LOW: /* All probes are low */
5a9660dd 321 memset(buf, 0x00, size);
c03ed397
UH
322 break;
323 case PATTERN_ALL_HIGH: /* All probes are high */
5a9660dd 324 memset(buf, 0xff, size);
c03ed397
UH
325 break;
326 default:
0abee507 327 sr_err("demo: %s: unknown pattern %d", __func__,
ab331b67 328 ctx->sample_generator);
c03ed397 329 break;
85b5af06
UH
330 }
331}
332
333/* Thread function */
334static void thread_func(void *data)
335{
455b26ed 336 struct context *ctx = data;
85b5af06
UH
337 uint8_t buf[BUFSIZE];
338 uint64_t nb_to_send = 0;
d35aaf02 339 int bytes_written;
1924f59f
HE
340 double time_cur, time_last, time_diff;
341
ab331b67 342 time_last = g_timer_elapsed(ctx->timer, NULL);
85b5af06
UH
343
344 while (thread_running) {
1924f59f 345 /* Rate control */
ab331b67 346 time_cur = g_timer_elapsed(ctx->timer, NULL);
1924f59f
HE
347
348 time_diff = time_cur - time_last;
349 time_last = time_cur;
350
351 nb_to_send = cur_samplerate * time_diff;
352
c03ed397 353 if (limit_samples) {
1924f59f 354 nb_to_send = MIN(nb_to_send,
ab331b67 355 limit_samples - ctx->samples_counter);
c03ed397 356 }
1924f59f
HE
357
358 /* Make sure we don't overflow. */
359 nb_to_send = MIN(nb_to_send, BUFSIZE);
360
361 if (nb_to_send) {
362 samples_generator(buf, nb_to_send, data);
ab331b67 363 ctx->samples_counter += nb_to_send;
070befcd 364
249ae2be 365 g_io_channel_write_chars(ctx->channels[1], (gchar *)&buf,
c03ed397 366 nb_to_send, (gsize *)&bytes_written, NULL);
b9cc3629
BV
367 }
368
1924f59f
HE
369 /* Check if we're done. */
370 if ((limit_msec && time_cur * 1000 > limit_msec) ||
ab331b67 371 (limit_samples && ctx->samples_counter >= limit_samples))
1924f59f 372 {
ab331b67 373 close(ctx->pipe_fds[1]);
85b5af06 374 thread_running = 0;
85b5af06
UH
375 }
376
1924f59f 377 g_usleep(10);
85b5af06
UH
378 }
379}
380
381/* Callback handling data */
1f9813eb 382static int receive_data(int fd, int revents, void *cb_data)
85b5af06 383{
249ae2be 384 struct context *ctx = cb_data;
b9c735a2 385 struct sr_datafeed_packet packet;
9c939c51
BV
386 struct sr_datafeed_logic logic;
387 static uint64_t samples_received = 0;
388 unsigned char c[BUFSIZE];
108a5bfb 389 gsize z;
1924f59f 390
26ce0bbf 391 /* Avoid compiler warnings. */
cb93f8a9
UH
392 (void)fd;
393 (void)revents;
1924f59f
HE
394
395 do {
249ae2be 396 g_io_channel_read_chars(ctx->channels[0],
070befcd 397 (gchar *)&c, BUFSIZE, &z, NULL);
1924f59f
HE
398
399 if (z > 0) {
5a2326a7 400 packet.type = SR_DF_LOGIC;
9c939c51 401 packet.payload = &logic;
9c939c51
BV
402 logic.length = z;
403 logic.unitsize = 1;
404 logic.data = c;
249ae2be 405 sr_session_send(ctx->session_dev_id, &packet);
9c939c51 406 samples_received += z;
1924f59f
HE
407 }
408 } while (z > 0);
85b5af06 409
c03ed397
UH
410 if (!thread_running && z <= 0) {
411 /* Make sure we don't receive more packets. */
249ae2be 412 g_io_channel_shutdown(ctx->channels[0], FALSE, NULL);
d35aaf02 413
1924f59f 414 /* Send last packet. */
5a2326a7 415 packet.type = SR_DF_END;
249ae2be 416 sr_session_send(ctx->session_dev_id, &packet);
1924f59f
HE
417
418 return FALSE;
85b5af06 419 }
1924f59f 420
85b5af06
UH
421 return TRUE;
422}
423
3cd3a20b 424static int hw_dev_acquisition_start(int dev_index, 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
ab331b67 431 /* TODO: 'ctx' is never g_free()'d? */
455b26ed 432 if (!(ctx = g_try_malloc(sizeof(struct context)))) {
ab331b67 433 sr_err("demo: %s: ctx malloc failed", __func__);
e46b8fb1 434 return SR_ERR_MALLOC;
27a3a6fe 435 }
85b5af06 436
ab331b67
UH
437 ctx->sample_generator = default_pattern;
438 ctx->session_dev_id = cb_data;
439 ctx->dev_index = dev_index;
440 ctx->samples_counter = 0;
85b5af06 441
ab331b67 442 if (pipe(ctx->pipe_fds)) {
c03ed397
UH
443 /* TODO: Better error message. */
444 sr_err("demo: %s: pipe() failed", __func__);
e46b8fb1 445 return SR_ERR;
c03ed397 446 }
85b5af06 447
249ae2be
LPC
448 ctx->channels[0] = g_io_channel_unix_new(ctx->pipe_fds[0]);
449 ctx->channels[1] = g_io_channel_unix_new(ctx->pipe_fds[1]);
d35aaf02 450
e6e8f8e0
LPC
451 g_io_channel_set_flags(ctx->channels[0], G_IO_FLAG_NONBLOCK, NULL);
452
d35aaf02 453 /* Set channel encoding to binary (default is UTF-8). */
249ae2be
LPC
454 g_io_channel_set_encoding(ctx->channels[0], NULL, NULL);
455 g_io_channel_set_encoding(ctx->channels[1], NULL, NULL);
d35aaf02
UH
456
457 /* Make channels to unbuffered. */
249ae2be
LPC
458 g_io_channel_set_buffered(ctx->channels[0], FALSE);
459 g_io_channel_set_buffered(ctx->channels[1], FALSE);
d35aaf02 460
249ae2be
LPC
461 sr_session_source_add_channel(ctx->channels[0], G_IO_IN | G_IO_ERR,
462 40, receive_data, ctx);
85b5af06
UH
463
464 /* Run the demo thread. */
465 g_thread_init(NULL);
c03ed397 466 /* This must to be done between g_thread_init() & g_thread_create(). */
ab331b67 467 ctx->timer = g_timer_new();
85b5af06
UH
468 thread_running = 1;
469 my_thread =
ab331b67 470 g_thread_create((GThreadFunc)thread_func, ctx, TRUE, NULL);
c03ed397
UH
471 if (!my_thread) {
472 sr_err("demo: %s: g_thread_create failed", __func__);
473 return SR_ERR; /* TODO */
474 }
6239c175 475
27a3a6fe
UH
476 if (!(packet = g_try_malloc(sizeof(struct sr_datafeed_packet)))) {
477 sr_err("demo: %s: packet malloc failed", __func__);
e46b8fb1 478 return SR_ERR_MALLOC;
27a3a6fe
UH
479 }
480
481 if (!(header = g_try_malloc(sizeof(struct sr_datafeed_header)))) {
482 sr_err("demo: %s: header malloc failed", __func__);
483 return SR_ERR_MALLOC;
484 }
6239c175 485
5a2326a7 486 packet->type = SR_DF_HEADER;
9c939c51 487 packet->payload = header;
6239c175
UH
488 header->feed_version = 1;
489 gettimeofday(&header->starttime, NULL);
ab331b67 490 sr_session_send(ctx->session_dev_id, packet);
f366e86c
BV
491
492 /* Send metadata about the SR_DF_LOGIC packets to come. */
493 packet->type = SR_DF_META_LOGIC;
494 packet->payload = &meta;
495 meta.samplerate = cur_samplerate;
496 meta.num_probes = NUM_PROBES;
497 sr_session_send(ctx->session_dev_id, packet);
498
27a3a6fe
UH
499 g_free(header);
500 g_free(packet);
6239c175 501
e46b8fb1 502 return SR_OK;
6239c175
UH
503}
504
3cd3a20b
UH
505/* TODO: This stops acquisition on ALL devices, ignoring dev_index. */
506static int hw_dev_acquisition_stop(int dev_index, void *cb_data)
6239c175 507{
17e1afcb 508 /* Avoid compiler warnings. */
bb7ef793 509 (void)dev_index;
3cd3a20b 510 (void)cb_data;
6239c175 511
1924f59f
HE
512 /* Stop generate thread. */
513 thread_running = 0;
3010f21c
UH
514
515 return SR_OK;
6239c175
UH
516}
517
c09f0b57 518SR_PRIV struct sr_dev_driver demo_driver_info = {
e519ba86
UH
519 .name = "demo",
520 .longname = "Demo driver and pattern generator",
521 .api_version = 1,
522 .init = hw_init,
523 .cleanup = hw_cleanup,
61136ea6 524 .scan = hw_scan,
e7eb703f
UH
525 .dev_open = hw_dev_open,
526 .dev_close = hw_dev_close,
dfb0fa1a 527 .info_get = hw_info_get,
e7eb703f 528 .dev_status_get = hw_dev_status_get,
dfb0fa1a 529// .hwcap_get_all = hw_hwcap_get_all,
a9a245b4 530 .dev_config_set = hw_dev_config_set,
69040b7c
UH
531 .dev_acquisition_start = hw_dev_acquisition_start,
532 .dev_acquisition_stop = hw_dev_acquisition_stop,
dcf03d6d 533 .instances = NULL,
6239c175 534};