2 * This file is part of the sigrok project.
4 * Copyright (C) 2010 Uwe Hermann <uwe@hermann-uwe.de>
5 * Copyright (C) 2011 Olivier Fauchon <olivier@aixmarseille.com>
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.
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.
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
28 #define pipe(fds) _pipe(fds, 4096, _O_BINARY)
30 #include "libsigrok.h"
31 #include "libsigrok-internal.h"
33 /* TODO: Number of probes should be configurable. */
36 #define DEMONAME "Demo device"
38 /* The size of chunks to send through the session bus. */
39 /* TODO: Should be configurable. */
42 /* Supported patterns which we can generate */
45 * Pattern which spells "sigrok" using '0's (with '1's as "background")
46 * when displayed using the 'bits' output format.
50 /** Pattern which consists of (pseudo-)random values on all probes. */
54 * Pattern which consists of incrementing numbers.
55 * TODO: Better description.
59 /** Pattern where all probes have a low logic state. */
62 /** Pattern where all probes have a high logic state. */
66 /* FIXME: Should not be global. */
70 GIOChannel *channels[2];
71 uint8_t sample_generator;
72 uint8_t thread_running;
73 uint64_t samples_counter;
78 static const int hwcaps[] = {
79 SR_HWCAP_LOGIC_ANALYZER,
82 SR_HWCAP_PATTERN_MODE,
83 SR_HWCAP_LIMIT_SAMPLES,
88 static const struct sr_samplerates samplerates = {
95 static const char *pattern_strings[] = {
104 /* We name the probes 0-7 on our demo driver. */
105 static const char *probe_names[NUM_PROBES + 1] = {
117 static uint8_t pattern_sigrok[] = {
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,
128 /* Private, per-device-instance driver context. */
129 /* TODO: struct context as with the other drivers. */
131 /* List of struct sr_dev_inst, maintained by dev_open()/dev_close(). */
132 SR_PRIV struct sr_dev_driver demo_driver_info;
133 static struct sr_dev_driver *ddi = &demo_driver_info;
134 static uint64_t cur_samplerate = SR_KHZ(200);
135 static uint64_t limit_samples = 0;
136 static uint64_t limit_msec = 0;
137 static int default_pattern = PATTERN_SIGROK;
138 static GThread *my_thread;
139 static int thread_running;
141 static int hw_dev_acquisition_stop(const struct sr_dev_inst *sdi,
144 static int hw_init(void)
152 static GSList *hw_scan(GSList *options)
154 struct sr_dev_inst *sdi;
155 struct sr_probe *probe;
162 sdi = sr_dev_inst_new(0, SR_ST_ACTIVE, DEMONAME, NULL, NULL);
164 sr_err("demo: %s: sr_dev_inst_new failed", __func__);
169 for (i = 0; probe_names[i]; i++) {
170 if (!(probe = sr_probe_new(i, SR_PROBE_ANALOG, TRUE,
173 sdi->probes = g_slist_append(sdi->probes, probe);
176 devices = g_slist_append(devices, sdi);
177 ddi->instances = g_slist_append(ddi->instances, sdi);
182 static int hw_dev_open(struct sr_dev_inst *sdi)
184 /* Avoid compiler warnings. */
187 /* Nothing needed so far. */
192 static int hw_dev_close(struct sr_dev_inst *sdi)
194 /* Avoid compiler warnings. */
197 /* Nothing needed so far. */
202 static int hw_cleanup(void)
204 /* Nothing needed so far. */
208 static int hw_info_get(int info_id, const void **data,
209 const struct sr_dev_inst *sdi)
219 case SR_DI_NUM_PROBES:
220 *data = GINT_TO_POINTER(NUM_PROBES);
222 case SR_DI_PROBE_NAMES:
225 case SR_DI_SAMPLERATES:
226 *data = &samplerates;
228 case SR_DI_CUR_SAMPLERATE:
229 *data = &cur_samplerate;
232 *data = &pattern_strings;
241 static int hw_dev_config_set(const struct sr_dev_inst *sdi, int hwcap,
249 if (hwcap == SR_HWCAP_PROBECONFIG) {
250 /* Nothing to do, but must be supported */
252 } else if (hwcap == SR_HWCAP_SAMPLERATE) {
253 cur_samplerate = *(const uint64_t *)value;
254 sr_dbg("demo: %s: setting samplerate to %" PRIu64, __func__,
257 } else if (hwcap == SR_HWCAP_LIMIT_SAMPLES) {
259 limit_samples = *(const uint64_t *)value;
260 sr_dbg("demo: %s: setting limit_samples to %" PRIu64, __func__,
263 } else if (hwcap == SR_HWCAP_LIMIT_MSEC) {
264 limit_msec = *(const uint64_t *)value;
266 sr_dbg("demo: %s: setting limit_msec to %" PRIu64, __func__,
269 } else if (hwcap == SR_HWCAP_PATTERN_MODE) {
272 if (!strcmp(stropt, "sigrok")) {
273 default_pattern = PATTERN_SIGROK;
274 } else if (!strcmp(stropt, "random")) {
275 default_pattern = PATTERN_RANDOM;
276 } else if (!strcmp(stropt, "incremental")) {
277 default_pattern = PATTERN_INC;
278 } else if (!strcmp(stropt, "all-low")) {
279 default_pattern = PATTERN_ALL_LOW;
280 } else if (!strcmp(stropt, "all-high")) {
281 default_pattern = PATTERN_ALL_HIGH;
285 sr_dbg("demo: %s: setting pattern to %d", __func__,
294 static void samples_generator(uint8_t *buf, uint64_t size, void *data)
296 static uint64_t p = 0;
297 struct context *ctx = data;
301 memset(buf, 0, size);
303 switch (ctx->sample_generator) {
304 case PATTERN_SIGROK: /* sigrok pattern */
305 for (i = 0; i < size; i++) {
306 *(buf + i) = ~(pattern_sigrok[p] >> 1);
311 case PATTERN_RANDOM: /* Random */
312 for (i = 0; i < size; i++)
313 *(buf + i) = (uint8_t)(rand() & 0xff);
315 case PATTERN_INC: /* Simple increment */
316 for (i = 0; i < size; i++)
319 case PATTERN_ALL_LOW: /* All probes are low */
320 memset(buf, 0x00, size);
322 case PATTERN_ALL_HIGH: /* All probes are high */
323 memset(buf, 0xff, size);
326 sr_err("demo: %s: unknown pattern %d", __func__,
327 ctx->sample_generator);
332 /* Thread function */
333 static void thread_func(void *data)
335 struct context *ctx = data;
336 uint8_t buf[BUFSIZE];
337 uint64_t nb_to_send = 0;
339 double time_cur, time_last, time_diff;
341 time_last = g_timer_elapsed(ctx->timer, NULL);
343 while (thread_running) {
345 time_cur = g_timer_elapsed(ctx->timer, NULL);
347 time_diff = time_cur - time_last;
348 time_last = time_cur;
350 nb_to_send = cur_samplerate * time_diff;
353 nb_to_send = MIN(nb_to_send,
354 limit_samples - ctx->samples_counter);
357 /* Make sure we don't overflow. */
358 nb_to_send = MIN(nb_to_send, BUFSIZE);
361 samples_generator(buf, nb_to_send, data);
362 ctx->samples_counter += nb_to_send;
364 g_io_channel_write_chars(ctx->channels[1], (gchar *)&buf,
365 nb_to_send, (gsize *)&bytes_written, NULL);
368 /* Check if we're done. */
369 if ((limit_msec && time_cur * 1000 > limit_msec) ||
370 (limit_samples && ctx->samples_counter >= limit_samples))
372 close(ctx->pipe_fds[1]);
380 /* Callback handling data */
381 static int receive_data(int fd, int revents, void *cb_data)
383 struct context *ctx = cb_data;
384 struct sr_datafeed_packet packet;
385 struct sr_datafeed_logic logic;
386 static uint64_t samples_received = 0;
387 unsigned char c[BUFSIZE];
390 /* Avoid compiler warnings. */
395 g_io_channel_read_chars(ctx->channels[0],
396 (gchar *)&c, BUFSIZE, &z, NULL);
399 packet.type = SR_DF_LOGIC;
400 packet.payload = &logic;
404 sr_session_send(ctx->session_dev_id, &packet);
405 samples_received += z;
409 if (!thread_running && z <= 0) {
410 /* Make sure we don't receive more packets. */
411 g_io_channel_shutdown(ctx->channels[0], FALSE, NULL);
413 /* Send last packet. */
414 packet.type = SR_DF_END;
415 sr_session_send(ctx->session_dev_id, &packet);
423 static int hw_dev_acquisition_start(const struct sr_dev_inst *sdi,
426 struct sr_datafeed_packet *packet;
427 struct sr_datafeed_header *header;
428 struct sr_datafeed_meta_logic meta;
433 /* TODO: 'ctx' is never g_free()'d? */
434 if (!(ctx = g_try_malloc(sizeof(struct context)))) {
435 sr_err("demo: %s: ctx malloc failed", __func__);
436 return SR_ERR_MALLOC;
439 ctx->sample_generator = default_pattern;
440 ctx->session_dev_id = cb_data;
441 ctx->samples_counter = 0;
443 if (pipe(ctx->pipe_fds)) {
444 /* TODO: Better error message. */
445 sr_err("demo: %s: pipe() failed", __func__);
449 ctx->channels[0] = g_io_channel_unix_new(ctx->pipe_fds[0]);
450 ctx->channels[1] = g_io_channel_unix_new(ctx->pipe_fds[1]);
452 g_io_channel_set_flags(ctx->channels[0], G_IO_FLAG_NONBLOCK, NULL);
454 /* Set channel encoding to binary (default is UTF-8). */
455 g_io_channel_set_encoding(ctx->channels[0], NULL, NULL);
456 g_io_channel_set_encoding(ctx->channels[1], NULL, NULL);
458 /* Make channels to unbuffered. */
459 g_io_channel_set_buffered(ctx->channels[0], FALSE);
460 g_io_channel_set_buffered(ctx->channels[1], FALSE);
462 sr_session_source_add_channel(ctx->channels[0], G_IO_IN | G_IO_ERR,
463 40, receive_data, ctx);
465 /* Run the demo thread. */
467 /* This must to be done between g_thread_init() & g_thread_create(). */
468 ctx->timer = g_timer_new();
471 g_thread_create((GThreadFunc)thread_func, ctx, TRUE, NULL);
473 sr_err("demo: %s: g_thread_create failed", __func__);
474 return SR_ERR; /* TODO */
477 if (!(packet = g_try_malloc(sizeof(struct sr_datafeed_packet)))) {
478 sr_err("demo: %s: packet malloc failed", __func__);
479 return SR_ERR_MALLOC;
482 if (!(header = g_try_malloc(sizeof(struct sr_datafeed_header)))) {
483 sr_err("demo: %s: header malloc failed", __func__);
484 return SR_ERR_MALLOC;
487 packet->type = SR_DF_HEADER;
488 packet->payload = header;
489 header->feed_version = 1;
490 gettimeofday(&header->starttime, NULL);
491 sr_session_send(ctx->session_dev_id, packet);
493 /* Send metadata about the SR_DF_LOGIC packets to come. */
494 packet->type = SR_DF_META_LOGIC;
495 packet->payload = &meta;
496 meta.samplerate = cur_samplerate;
497 meta.num_probes = NUM_PROBES;
498 sr_session_send(ctx->session_dev_id, packet);
506 static int hw_dev_acquisition_stop(const struct sr_dev_inst *sdi,
509 /* Avoid compiler warnings. */
513 /* Stop generate thread. */
519 SR_PRIV struct sr_dev_driver demo_driver_info = {
521 .longname = "Demo driver and pattern generator",
524 .cleanup = hw_cleanup,
526 .dev_open = hw_dev_open,
527 .dev_close = hw_dev_close,
528 .info_get = hw_info_get,
529 .dev_config_set = hw_dev_config_set,
530 .dev_acquisition_start = hw_dev_acquisition_start,
531 .dev_acquisition_stop = hw_dev_acquisition_stop,