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;
79 static const int hwcaps[] = {
80 SR_HWCAP_LOGIC_ANALYZER,
83 SR_HWCAP_PATTERN_MODE,
84 SR_HWCAP_LIMIT_SAMPLES,
89 static const struct sr_samplerates samplerates = {
96 static const char *pattern_strings[] = {
105 /* We name the probes 0-7 on our demo driver. */
106 static const char *probe_names[NUM_PROBES + 1] = {
118 static uint8_t pattern_sigrok[] = {
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,
129 /* Private, per-device-instance driver context. */
130 /* TODO: struct context as with the other drivers. */
132 /* List of struct sr_dev_inst, maintained by dev_open()/dev_close(). */
133 SR_PRIV struct sr_dev_driver demo_driver_info;
134 static struct sr_dev_driver *ddi = &demo_driver_info;
135 static uint64_t cur_samplerate = SR_KHZ(200);
136 static uint64_t limit_samples = 0;
137 static uint64_t limit_msec = 0;
138 static int default_pattern = PATTERN_SIGROK;
139 static GThread *my_thread;
140 static int thread_running;
142 static int hw_dev_acquisition_stop(int dev_index, void *cb_data);
144 static int hw_init(void)
152 static GSList *hw_scan(GSList *options)
154 struct sr_dev_inst *sdi;
160 sdi = sr_dev_inst_new(0, SR_ST_ACTIVE, DEMONAME, NULL, NULL);
162 sr_err("demo: %s: sr_dev_inst_new failed", __func__);
167 devices = g_slist_append(devices, sdi);
168 ddi->instances = g_slist_append(ddi->instances, sdi);
173 static int hw_dev_open(int dev_index)
175 /* Avoid compiler warnings. */
178 /* Nothing needed so far. */
183 static int hw_dev_close(int dev_index)
185 /* Avoid compiler warnings. */
188 /* Nothing needed so far. */
193 static int hw_cleanup(void)
195 /* Nothing needed so far. */
199 static int hw_info_get(int info_id, const void **data,
200 const struct sr_dev_inst *sdi)
210 case SR_DI_NUM_PROBES:
211 *data = GINT_TO_POINTER(NUM_PROBES);
213 case SR_DI_PROBE_NAMES:
216 case SR_DI_SAMPLERATES:
217 *data = &samplerates;
219 case SR_DI_CUR_SAMPLERATE:
220 *data = &cur_samplerate;
223 *data = &pattern_strings;
232 static int hw_dev_status_get(int dev_index)
234 /* Avoid compiler warnings. */
240 static int hw_dev_config_set(const struct sr_dev_inst *sdi, int hwcap,
248 if (hwcap == SR_HWCAP_PROBECONFIG) {
249 /* Nothing to do, but must be supported */
251 } else if (hwcap == SR_HWCAP_SAMPLERATE) {
252 cur_samplerate = *(const uint64_t *)value;
253 sr_dbg("demo: %s: setting samplerate to %" PRIu64, __func__,
256 } else if (hwcap == SR_HWCAP_LIMIT_SAMPLES) {
258 limit_samples = *(const uint64_t *)value;
259 sr_dbg("demo: %s: setting limit_samples to %" PRIu64, __func__,
262 } else if (hwcap == SR_HWCAP_LIMIT_MSEC) {
263 limit_msec = *(const uint64_t *)value;
265 sr_dbg("demo: %s: setting limit_msec to %" PRIu64, __func__,
268 } else if (hwcap == SR_HWCAP_PATTERN_MODE) {
271 if (!strcmp(stropt, "sigrok")) {
272 default_pattern = PATTERN_SIGROK;
273 } else if (!strcmp(stropt, "random")) {
274 default_pattern = PATTERN_RANDOM;
275 } else if (!strcmp(stropt, "incremental")) {
276 default_pattern = PATTERN_INC;
277 } else if (!strcmp(stropt, "all-low")) {
278 default_pattern = PATTERN_ALL_LOW;
279 } else if (!strcmp(stropt, "all-high")) {
280 default_pattern = PATTERN_ALL_HIGH;
284 sr_dbg("demo: %s: setting pattern to %d", __func__,
293 static void samples_generator(uint8_t *buf, uint64_t size, void *data)
295 static uint64_t p = 0;
296 struct context *ctx = data;
300 memset(buf, 0, size);
302 switch (ctx->sample_generator) {
303 case PATTERN_SIGROK: /* sigrok pattern */
304 for (i = 0; i < size; i++) {
305 *(buf + i) = ~(pattern_sigrok[p] >> 1);
310 case PATTERN_RANDOM: /* Random */
311 for (i = 0; i < size; i++)
312 *(buf + i) = (uint8_t)(rand() & 0xff);
314 case PATTERN_INC: /* Simple increment */
315 for (i = 0; i < size; i++)
318 case PATTERN_ALL_LOW: /* All probes are low */
319 memset(buf, 0x00, size);
321 case PATTERN_ALL_HIGH: /* All probes are high */
322 memset(buf, 0xff, size);
325 sr_err("demo: %s: unknown pattern %d", __func__,
326 ctx->sample_generator);
331 /* Thread function */
332 static void thread_func(void *data)
334 struct context *ctx = data;
335 uint8_t buf[BUFSIZE];
336 uint64_t nb_to_send = 0;
338 double time_cur, time_last, time_diff;
340 time_last = g_timer_elapsed(ctx->timer, NULL);
342 while (thread_running) {
344 time_cur = g_timer_elapsed(ctx->timer, NULL);
346 time_diff = time_cur - time_last;
347 time_last = time_cur;
349 nb_to_send = cur_samplerate * time_diff;
352 nb_to_send = MIN(nb_to_send,
353 limit_samples - ctx->samples_counter);
356 /* Make sure we don't overflow. */
357 nb_to_send = MIN(nb_to_send, BUFSIZE);
360 samples_generator(buf, nb_to_send, data);
361 ctx->samples_counter += nb_to_send;
363 g_io_channel_write_chars(ctx->channels[1], (gchar *)&buf,
364 nb_to_send, (gsize *)&bytes_written, NULL);
367 /* Check if we're done. */
368 if ((limit_msec && time_cur * 1000 > limit_msec) ||
369 (limit_samples && ctx->samples_counter >= limit_samples))
371 close(ctx->pipe_fds[1]);
379 /* Callback handling data */
380 static int receive_data(int fd, int revents, void *cb_data)
382 struct context *ctx = cb_data;
383 struct sr_datafeed_packet packet;
384 struct sr_datafeed_logic logic;
385 static uint64_t samples_received = 0;
386 unsigned char c[BUFSIZE];
389 /* Avoid compiler warnings. */
394 g_io_channel_read_chars(ctx->channels[0],
395 (gchar *)&c, BUFSIZE, &z, NULL);
398 packet.type = SR_DF_LOGIC;
399 packet.payload = &logic;
403 sr_session_send(ctx->session_dev_id, &packet);
404 samples_received += z;
408 if (!thread_running && z <= 0) {
409 /* Make sure we don't receive more packets. */
410 g_io_channel_shutdown(ctx->channels[0], FALSE, NULL);
412 /* Send last packet. */
413 packet.type = SR_DF_END;
414 sr_session_send(ctx->session_dev_id, &packet);
422 static int hw_dev_acquisition_start(int dev_index, void *cb_data)
424 struct sr_datafeed_packet *packet;
425 struct sr_datafeed_header *header;
426 struct sr_datafeed_meta_logic meta;
429 /* TODO: 'ctx' is never g_free()'d? */
430 if (!(ctx = g_try_malloc(sizeof(struct context)))) {
431 sr_err("demo: %s: ctx malloc failed", __func__);
432 return SR_ERR_MALLOC;
435 ctx->sample_generator = default_pattern;
436 ctx->session_dev_id = cb_data;
437 ctx->dev_index = dev_index;
438 ctx->samples_counter = 0;
440 if (pipe(ctx->pipe_fds)) {
441 /* TODO: Better error message. */
442 sr_err("demo: %s: pipe() failed", __func__);
446 ctx->channels[0] = g_io_channel_unix_new(ctx->pipe_fds[0]);
447 ctx->channels[1] = g_io_channel_unix_new(ctx->pipe_fds[1]);
449 g_io_channel_set_flags(ctx->channels[0], G_IO_FLAG_NONBLOCK, NULL);
451 /* Set channel encoding to binary (default is UTF-8). */
452 g_io_channel_set_encoding(ctx->channels[0], NULL, NULL);
453 g_io_channel_set_encoding(ctx->channels[1], NULL, NULL);
455 /* Make channels to unbuffered. */
456 g_io_channel_set_buffered(ctx->channels[0], FALSE);
457 g_io_channel_set_buffered(ctx->channels[1], FALSE);
459 sr_session_source_add_channel(ctx->channels[0], G_IO_IN | G_IO_ERR,
460 40, receive_data, ctx);
462 /* Run the demo thread. */
464 /* This must to be done between g_thread_init() & g_thread_create(). */
465 ctx->timer = g_timer_new();
468 g_thread_create((GThreadFunc)thread_func, ctx, TRUE, NULL);
470 sr_err("demo: %s: g_thread_create failed", __func__);
471 return SR_ERR; /* TODO */
474 if (!(packet = g_try_malloc(sizeof(struct sr_datafeed_packet)))) {
475 sr_err("demo: %s: packet malloc failed", __func__);
476 return SR_ERR_MALLOC;
479 if (!(header = g_try_malloc(sizeof(struct sr_datafeed_header)))) {
480 sr_err("demo: %s: header malloc failed", __func__);
481 return SR_ERR_MALLOC;
484 packet->type = SR_DF_HEADER;
485 packet->payload = header;
486 header->feed_version = 1;
487 gettimeofday(&header->starttime, NULL);
488 sr_session_send(ctx->session_dev_id, packet);
490 /* Send metadata about the SR_DF_LOGIC packets to come. */
491 packet->type = SR_DF_META_LOGIC;
492 packet->payload = &meta;
493 meta.samplerate = cur_samplerate;
494 meta.num_probes = NUM_PROBES;
495 sr_session_send(ctx->session_dev_id, packet);
503 /* TODO: This stops acquisition on ALL devices, ignoring dev_index. */
504 static int hw_dev_acquisition_stop(int dev_index, void *cb_data)
506 /* Avoid compiler warnings. */
510 /* Stop generate thread. */
516 SR_PRIV struct sr_dev_driver demo_driver_info = {
518 .longname = "Demo driver and pattern generator",
521 .cleanup = hw_cleanup,
523 .dev_open = hw_dev_open,
524 .dev_close = hw_dev_close,
525 .info_get = hw_info_get,
526 .dev_status_get = hw_dev_status_get,
527 .dev_config_set = hw_dev_config_set,
528 .dev_acquisition_start = hw_dev_acquisition_start,
529 .dev_acquisition_stop = hw_dev_acquisition_stop,