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