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