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