]> sigrok.org Git - libsigrok.git/blame - hardware/demo/demo.c
sr/drivers: remove driver API call dev_status_get()
[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;
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
25a0f108 173static int hw_dev_open(struct sr_dev_inst *sdi)
6239c175 174{
17e1afcb 175 /* Avoid compiler warnings. */
25a0f108 176 (void)sdi;
6239c175
UH
177
178 /* Nothing needed so far. */
697785d1 179
e46b8fb1 180 return SR_OK;
6239c175
UH
181}
182
25a0f108 183static int hw_dev_close(struct sr_dev_inst *sdi)
6239c175 184{
17e1afcb 185 /* Avoid compiler warnings. */
25a0f108 186 (void)sdi;
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;
46c7a4da
BV
207 case SR_DI_HWCAPS:
208 *data = hwcaps;
209 break;
5a2326a7 210 case SR_DI_NUM_PROBES:
dfb0fa1a 211 *data = GINT_TO_POINTER(NUM_PROBES);
6239c175 212 break;
464d12c7 213 case SR_DI_PROBE_NAMES:
dfb0fa1a 214 *data = probe_names;
464d12c7 215 break;
4bfbf9fc 216 case SR_DI_SAMPLERATES:
dfb0fa1a 217 *data = &samplerates;
4bfbf9fc 218 break;
5a2326a7 219 case SR_DI_CUR_SAMPLERATE:
dfb0fa1a 220 *data = &cur_samplerate;
6239c175 221 break;
eb0a3731 222 case SR_DI_PATTERNS:
dfb0fa1a 223 *data = &pattern_strings;
e15f48c2 224 break;
7dfcf010
BV
225 default:
226 return SR_ERR_ARG;
6239c175
UH
227 }
228
dfb0fa1a 229 return SR_OK;
6239c175
UH
230}
231
6f4b1868
BV
232static int hw_dev_config_set(const struct sr_dev_inst *sdi, int hwcap,
233 const void *value)
6239c175
UH
234{
235 int ret;
1b79df2f 236 const char *stropt;
6239c175 237
6f4b1868 238 (void)sdi;
6239c175 239
ffedd0bf 240 if (hwcap == SR_HWCAP_PROBECONFIG) {
d81d2933
BV
241 /* Nothing to do, but must be supported */
242 ret = SR_OK;
ffedd0bf 243 } else if (hwcap == SR_HWCAP_SAMPLERATE) {
1b79df2f 244 cur_samplerate = *(const uint64_t *)value;
6f422264
UH
245 sr_dbg("demo: %s: setting samplerate to %" PRIu64, __func__,
246 cur_samplerate);
e46b8fb1 247 ret = SR_OK;
ffedd0bf 248 } else if (hwcap == SR_HWCAP_LIMIT_SAMPLES) {
8489264f 249 limit_msec = 0;
1b79df2f 250 limit_samples = *(const uint64_t *)value;
6f422264
UH
251 sr_dbg("demo: %s: setting limit_samples to %" PRIu64, __func__,
252 limit_samples);
e46b8fb1 253 ret = SR_OK;
ffedd0bf 254 } else if (hwcap == SR_HWCAP_LIMIT_MSEC) {
1b79df2f 255 limit_msec = *(const uint64_t *)value;
8489264f 256 limit_samples = 0;
6f422264
UH
257 sr_dbg("demo: %s: setting limit_msec to %" PRIu64, __func__,
258 limit_msec);
e46b8fb1 259 ret = SR_OK;
ffedd0bf 260 } else if (hwcap == SR_HWCAP_PATTERN_MODE) {
e15f48c2 261 stropt = value;
c03ed397
UH
262 ret = SR_OK;
263 if (!strcmp(stropt, "sigrok")) {
264 default_pattern = PATTERN_SIGROK;
265 } else if (!strcmp(stropt, "random")) {
c8f4624d 266 default_pattern = PATTERN_RANDOM;
e15f48c2 267 } else if (!strcmp(stropt, "incremental")) {
c8f4624d 268 default_pattern = PATTERN_INC;
c03ed397
UH
269 } else if (!strcmp(stropt, "all-low")) {
270 default_pattern = PATTERN_ALL_LOW;
271 } else if (!strcmp(stropt, "all-high")) {
272 default_pattern = PATTERN_ALL_HIGH;
e15f48c2 273 } else {
e46b8fb1 274 ret = SR_ERR;
e15f48c2 275 }
c8f4624d
UH
276 sr_dbg("demo: %s: setting pattern to %d", __func__,
277 default_pattern);
6239c175 278 } else {
e46b8fb1 279 ret = SR_ERR;
6239c175
UH
280 }
281
282 return ret;
283}
284
5096c6a6 285static void samples_generator(uint8_t *buf, uint64_t size, void *data)
85b5af06 286{
cddd1c5f 287 static uint64_t p = 0;
455b26ed 288 struct context *ctx = data;
cddd1c5f 289 uint64_t i;
85b5af06 290
c03ed397 291 /* TODO: Needed? */
5096c6a6 292 memset(buf, 0, size);
85b5af06 293
ab331b67 294 switch (ctx->sample_generator) {
c03ed397 295 case PATTERN_SIGROK: /* sigrok pattern */
917e0e71 296 for (i = 0; i < size; i++) {
c8f4624d 297 *(buf + i) = ~(pattern_sigrok[p] >> 1);
917e0e71
BV
298 if (++p == 64)
299 p = 0;
300 }
301 break;
c8f4624d 302 case PATTERN_RANDOM: /* Random */
5096c6a6
UH
303 for (i = 0; i < size; i++)
304 *(buf + i) = (uint8_t)(rand() & 0xff);
85b5af06 305 break;
c8f4624d 306 case PATTERN_INC: /* Simple increment */
5096c6a6 307 for (i = 0; i < size; i++)
85b5af06
UH
308 *(buf + i) = i;
309 break;
c03ed397 310 case PATTERN_ALL_LOW: /* All probes are low */
5a9660dd 311 memset(buf, 0x00, size);
c03ed397
UH
312 break;
313 case PATTERN_ALL_HIGH: /* All probes are high */
5a9660dd 314 memset(buf, 0xff, size);
c03ed397
UH
315 break;
316 default:
0abee507 317 sr_err("demo: %s: unknown pattern %d", __func__,
ab331b67 318 ctx->sample_generator);
c03ed397 319 break;
85b5af06
UH
320 }
321}
322
323/* Thread function */
324static void thread_func(void *data)
325{
455b26ed 326 struct context *ctx = data;
85b5af06
UH
327 uint8_t buf[BUFSIZE];
328 uint64_t nb_to_send = 0;
d35aaf02 329 int bytes_written;
1924f59f
HE
330 double time_cur, time_last, time_diff;
331
ab331b67 332 time_last = g_timer_elapsed(ctx->timer, NULL);
85b5af06
UH
333
334 while (thread_running) {
1924f59f 335 /* Rate control */
ab331b67 336 time_cur = g_timer_elapsed(ctx->timer, NULL);
1924f59f
HE
337
338 time_diff = time_cur - time_last;
339 time_last = time_cur;
340
341 nb_to_send = cur_samplerate * time_diff;
342
c03ed397 343 if (limit_samples) {
1924f59f 344 nb_to_send = MIN(nb_to_send,
ab331b67 345 limit_samples - ctx->samples_counter);
c03ed397 346 }
1924f59f
HE
347
348 /* Make sure we don't overflow. */
349 nb_to_send = MIN(nb_to_send, BUFSIZE);
350
351 if (nb_to_send) {
352 samples_generator(buf, nb_to_send, data);
ab331b67 353 ctx->samples_counter += nb_to_send;
070befcd 354
249ae2be 355 g_io_channel_write_chars(ctx->channels[1], (gchar *)&buf,
c03ed397 356 nb_to_send, (gsize *)&bytes_written, NULL);
b9cc3629
BV
357 }
358
1924f59f
HE
359 /* Check if we're done. */
360 if ((limit_msec && time_cur * 1000 > limit_msec) ||
ab331b67 361 (limit_samples && ctx->samples_counter >= limit_samples))
1924f59f 362 {
ab331b67 363 close(ctx->pipe_fds[1]);
85b5af06 364 thread_running = 0;
85b5af06
UH
365 }
366
1924f59f 367 g_usleep(10);
85b5af06
UH
368 }
369}
370
371/* Callback handling data */
1f9813eb 372static int receive_data(int fd, int revents, void *cb_data)
85b5af06 373{
249ae2be 374 struct context *ctx = cb_data;
b9c735a2 375 struct sr_datafeed_packet packet;
9c939c51
BV
376 struct sr_datafeed_logic logic;
377 static uint64_t samples_received = 0;
378 unsigned char c[BUFSIZE];
108a5bfb 379 gsize z;
1924f59f 380
26ce0bbf 381 /* Avoid compiler warnings. */
cb93f8a9
UH
382 (void)fd;
383 (void)revents;
1924f59f
HE
384
385 do {
249ae2be 386 g_io_channel_read_chars(ctx->channels[0],
070befcd 387 (gchar *)&c, BUFSIZE, &z, NULL);
1924f59f
HE
388
389 if (z > 0) {
5a2326a7 390 packet.type = SR_DF_LOGIC;
9c939c51 391 packet.payload = &logic;
9c939c51
BV
392 logic.length = z;
393 logic.unitsize = 1;
394 logic.data = c;
249ae2be 395 sr_session_send(ctx->session_dev_id, &packet);
9c939c51 396 samples_received += z;
1924f59f
HE
397 }
398 } while (z > 0);
85b5af06 399
c03ed397
UH
400 if (!thread_running && z <= 0) {
401 /* Make sure we don't receive more packets. */
249ae2be 402 g_io_channel_shutdown(ctx->channels[0], FALSE, NULL);
d35aaf02 403
1924f59f 404 /* Send last packet. */
5a2326a7 405 packet.type = SR_DF_END;
249ae2be 406 sr_session_send(ctx->session_dev_id, &packet);
1924f59f
HE
407
408 return FALSE;
85b5af06 409 }
1924f59f 410
85b5af06
UH
411 return TRUE;
412}
413
3ffb6964
BV
414static int hw_dev_acquisition_start(const struct sr_dev_inst *sdi,
415 void *cb_data)
6239c175 416{
b9c735a2
UH
417 struct sr_datafeed_packet *packet;
418 struct sr_datafeed_header *header;
f366e86c 419 struct sr_datafeed_meta_logic meta;
455b26ed 420 struct context *ctx;
6239c175 421
3ffb6964
BV
422 (void)sdi;
423
ab331b67 424 /* TODO: 'ctx' is never g_free()'d? */
455b26ed 425 if (!(ctx = g_try_malloc(sizeof(struct context)))) {
ab331b67 426 sr_err("demo: %s: ctx malloc failed", __func__);
e46b8fb1 427 return SR_ERR_MALLOC;
27a3a6fe 428 }
85b5af06 429
ab331b67
UH
430 ctx->sample_generator = default_pattern;
431 ctx->session_dev_id = cb_data;
ab331b67 432 ctx->samples_counter = 0;
85b5af06 433
ab331b67 434 if (pipe(ctx->pipe_fds)) {
c03ed397
UH
435 /* TODO: Better error message. */
436 sr_err("demo: %s: pipe() failed", __func__);
e46b8fb1 437 return SR_ERR;
c03ed397 438 }
85b5af06 439
249ae2be
LPC
440 ctx->channels[0] = g_io_channel_unix_new(ctx->pipe_fds[0]);
441 ctx->channels[1] = g_io_channel_unix_new(ctx->pipe_fds[1]);
d35aaf02 442
e6e8f8e0
LPC
443 g_io_channel_set_flags(ctx->channels[0], G_IO_FLAG_NONBLOCK, NULL);
444
d35aaf02 445 /* Set channel encoding to binary (default is UTF-8). */
249ae2be
LPC
446 g_io_channel_set_encoding(ctx->channels[0], NULL, NULL);
447 g_io_channel_set_encoding(ctx->channels[1], NULL, NULL);
d35aaf02
UH
448
449 /* Make channels to unbuffered. */
249ae2be
LPC
450 g_io_channel_set_buffered(ctx->channels[0], FALSE);
451 g_io_channel_set_buffered(ctx->channels[1], FALSE);
d35aaf02 452
249ae2be
LPC
453 sr_session_source_add_channel(ctx->channels[0], G_IO_IN | G_IO_ERR,
454 40, receive_data, ctx);
85b5af06
UH
455
456 /* Run the demo thread. */
457 g_thread_init(NULL);
c03ed397 458 /* This must to be done between g_thread_init() & g_thread_create(). */
ab331b67 459 ctx->timer = g_timer_new();
85b5af06
UH
460 thread_running = 1;
461 my_thread =
ab331b67 462 g_thread_create((GThreadFunc)thread_func, ctx, TRUE, NULL);
c03ed397
UH
463 if (!my_thread) {
464 sr_err("demo: %s: g_thread_create failed", __func__);
465 return SR_ERR; /* TODO */
466 }
6239c175 467
27a3a6fe
UH
468 if (!(packet = g_try_malloc(sizeof(struct sr_datafeed_packet)))) {
469 sr_err("demo: %s: packet malloc failed", __func__);
e46b8fb1 470 return SR_ERR_MALLOC;
27a3a6fe
UH
471 }
472
473 if (!(header = g_try_malloc(sizeof(struct sr_datafeed_header)))) {
474 sr_err("demo: %s: header malloc failed", __func__);
475 return SR_ERR_MALLOC;
476 }
6239c175 477
5a2326a7 478 packet->type = SR_DF_HEADER;
9c939c51 479 packet->payload = header;
6239c175
UH
480 header->feed_version = 1;
481 gettimeofday(&header->starttime, NULL);
ab331b67 482 sr_session_send(ctx->session_dev_id, packet);
f366e86c
BV
483
484 /* Send metadata about the SR_DF_LOGIC packets to come. */
485 packet->type = SR_DF_META_LOGIC;
486 packet->payload = &meta;
487 meta.samplerate = cur_samplerate;
488 meta.num_probes = NUM_PROBES;
489 sr_session_send(ctx->session_dev_id, packet);
490
27a3a6fe
UH
491 g_free(header);
492 g_free(packet);
6239c175 493
e46b8fb1 494 return SR_OK;
6239c175
UH
495}
496
3ffb6964
BV
497static int hw_dev_acquisition_stop(const struct sr_dev_inst *sdi,
498 void *cb_data)
6239c175 499{
17e1afcb 500 /* Avoid compiler warnings. */
3ffb6964 501 (void)sdi;
3cd3a20b 502 (void)cb_data;
6239c175 503
1924f59f
HE
504 /* Stop generate thread. */
505 thread_running = 0;
3010f21c
UH
506
507 return SR_OK;
6239c175
UH
508}
509
c09f0b57 510SR_PRIV struct sr_dev_driver demo_driver_info = {
e519ba86
UH
511 .name = "demo",
512 .longname = "Demo driver and pattern generator",
513 .api_version = 1,
514 .init = hw_init,
515 .cleanup = hw_cleanup,
61136ea6 516 .scan = hw_scan,
e7eb703f
UH
517 .dev_open = hw_dev_open,
518 .dev_close = hw_dev_close,
dfb0fa1a 519 .info_get = hw_info_get,
a9a245b4 520 .dev_config_set = hw_dev_config_set,
69040b7c
UH
521 .dev_acquisition_start = hw_dev_acquisition_start,
522 .dev_acquisition_stop = hw_dev_acquisition_stop,
dcf03d6d 523 .instances = NULL,
6239c175 524};