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>
6 * Copyright (C) 2012 Alexandru Gagniuc <mr.nuke.me@gmail.com>
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
29 #define pipe(fds) _pipe(fds, 4096, _O_BINARY)
31 #include "libsigrok.h"
32 #include "libsigrok-internal.h"
34 /* Message logging helpers with driver-specific prefix string. */
35 #define DRIVER_LOG_DOMAIN "demo: "
36 #define sr_log(l, s, args...) sr_log(l, DRIVER_LOG_DOMAIN s, ## args)
37 #define sr_spew(s, args...) sr_spew(DRIVER_LOG_DOMAIN s, ## args)
38 #define sr_dbg(s, args...) sr_dbg(DRIVER_LOG_DOMAIN s, ## args)
39 #define sr_info(s, args...) sr_info(DRIVER_LOG_DOMAIN s, ## args)
40 #define sr_warn(s, args...) sr_warn(DRIVER_LOG_DOMAIN s, ## args)
41 #define sr_err(s, args...) sr_err(DRIVER_LOG_DOMAIN s, ## args)
43 /* TODO: Number of probes should be configurable. */
46 #define DEMONAME "Demo device"
48 /* The size of chunks to send through the session bus. */
49 /* TODO: Should be configurable. */
52 /* Supported patterns which we can generate */
55 * Pattern which spells "sigrok" using '0's (with '1's as "background")
56 * when displayed using the 'bits' output format.
60 /** Pattern which consists of (pseudo-)random values on all probes. */
64 * Pattern which consists of incrementing numbers.
65 * TODO: Better description.
69 /** Pattern where all probes have a low logic state. */
72 /** Pattern where all probes have a high logic state. */
76 /* Private, per-device-instance driver context. */
79 GIOChannel *channels[2];
80 uint8_t sample_generator;
81 uint8_t thread_running;
82 uint64_t samples_counter;
87 static const int hwcaps[] = {
88 SR_HWCAP_LOGIC_ANALYZER,
91 SR_HWCAP_PATTERN_MODE,
92 SR_HWCAP_LIMIT_SAMPLES,
97 static const struct sr_samplerates samplerates = {
104 static const char *pattern_strings[] = {
113 /* We name the probes 0-7 on our demo driver. */
114 static const char *probe_names[NUM_PROBES + 1] = {
126 static uint8_t pattern_sigrok[] = {
127 0x4c, 0x92, 0x92, 0x92, 0x64, 0x00, 0x00, 0x00,
128 0x82, 0xfe, 0xfe, 0x82, 0x00, 0x00, 0x00, 0x00,
129 0x7c, 0x82, 0x82, 0x92, 0x74, 0x00, 0x00, 0x00,
130 0xfe, 0x12, 0x12, 0x32, 0xcc, 0x00, 0x00, 0x00,
131 0x7c, 0x82, 0x82, 0x82, 0x7c, 0x00, 0x00, 0x00,
132 0xfe, 0x10, 0x28, 0x44, 0x82, 0x00, 0x00, 0x00,
133 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
134 0xbe, 0xbe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
137 /* Private, per-device-instance driver context. */
138 /* TODO: struct context as with the other drivers. */
140 /* List of struct sr_dev_inst, maintained by dev_open()/dev_close(). */
141 SR_PRIV struct sr_dev_driver demo_driver_info;
142 static struct sr_dev_driver *ddi = &demo_driver_info;
143 static uint64_t cur_samplerate = SR_KHZ(200);
144 static uint64_t limit_samples = 0;
145 static uint64_t limit_msec = 0;
146 static int default_pattern = PATTERN_SIGROK;
147 static GThread *my_thread;
148 static int thread_running;
150 static int hw_dev_acquisition_stop(struct sr_dev_inst *sdi, void *cb_data);
152 static int hw_init(void)
154 struct drv_context *drvc;
156 if (!(drvc = g_try_malloc0(sizeof(struct drv_context)))) {
157 sr_err("Driver context malloc failed.");
158 return SR_ERR_MALLOC;
165 static GSList *hw_scan(GSList *options)
167 struct sr_dev_inst *sdi;
168 struct sr_probe *probe;
169 struct drv_context *drvc;
178 sdi = sr_dev_inst_new(0, SR_ST_ACTIVE, DEMONAME, NULL, NULL);
180 sr_err("%s: sr_dev_inst_new failed", __func__);
185 for (i = 0; probe_names[i]; i++) {
186 if (!(probe = sr_probe_new(i, SR_PROBE_LOGIC, TRUE,
189 sdi->probes = g_slist_append(sdi->probes, probe);
192 devices = g_slist_append(devices, sdi);
193 drvc->instances = g_slist_append(drvc->instances, sdi);
198 static GSList *hw_dev_list(void)
200 struct drv_context *drvc;
204 return drvc->instances;
207 static int hw_dev_open(struct sr_dev_inst *sdi)
211 /* Nothing needed so far. */
216 static int hw_dev_close(struct sr_dev_inst *sdi)
220 /* Nothing needed so far. */
225 static int hw_cleanup(void)
227 /* Nothing needed so far. */
231 static int hw_info_get(int info_id, const void **data,
232 const struct sr_dev_inst *sdi)
240 case SR_DI_NUM_PROBES:
241 *data = GINT_TO_POINTER(NUM_PROBES);
243 case SR_DI_PROBE_NAMES:
246 case SR_DI_SAMPLERATES:
247 *data = &samplerates;
249 case SR_DI_CUR_SAMPLERATE:
250 *data = &cur_samplerate;
253 *data = &pattern_strings;
262 static int hw_dev_config_set(const struct sr_dev_inst *sdi, int hwcap,
270 if (hwcap == SR_HWCAP_SAMPLERATE) {
271 cur_samplerate = *(const uint64_t *)value;
272 sr_dbg("%s: setting samplerate to %" PRIu64, __func__,
275 } else if (hwcap == SR_HWCAP_LIMIT_SAMPLES) {
277 limit_samples = *(const uint64_t *)value;
278 sr_dbg("%s: setting limit_samples to %" PRIu64, __func__,
281 } else if (hwcap == SR_HWCAP_LIMIT_MSEC) {
282 limit_msec = *(const uint64_t *)value;
284 sr_dbg("%s: setting limit_msec to %" PRIu64, __func__,
287 } else if (hwcap == SR_HWCAP_PATTERN_MODE) {
290 if (!strcmp(stropt, "sigrok")) {
291 default_pattern = PATTERN_SIGROK;
292 } else if (!strcmp(stropt, "random")) {
293 default_pattern = PATTERN_RANDOM;
294 } else if (!strcmp(stropt, "incremental")) {
295 default_pattern = PATTERN_INC;
296 } else if (!strcmp(stropt, "all-low")) {
297 default_pattern = PATTERN_ALL_LOW;
298 } else if (!strcmp(stropt, "all-high")) {
299 default_pattern = PATTERN_ALL_HIGH;
303 sr_dbg("%s: setting pattern to %d", __func__, default_pattern);
311 static void samples_generator(uint8_t *buf, uint64_t size, void *data)
313 static uint64_t p = 0;
314 struct dev_context *devc = data;
318 memset(buf, 0, size);
320 switch (devc->sample_generator) {
321 case PATTERN_SIGROK: /* sigrok pattern */
322 for (i = 0; i < size; i++) {
323 *(buf + i) = ~(pattern_sigrok[p] >> 1);
328 case PATTERN_RANDOM: /* Random */
329 for (i = 0; i < size; i++)
330 *(buf + i) = (uint8_t)(rand() & 0xff);
332 case PATTERN_INC: /* Simple increment */
333 for (i = 0; i < size; i++)
336 case PATTERN_ALL_LOW: /* All probes are low */
337 memset(buf, 0x00, size);
339 case PATTERN_ALL_HIGH: /* All probes are high */
340 memset(buf, 0xff, size);
343 sr_err("Unknown pattern: %d.", devc->sample_generator);
348 /* Thread function */
349 static void thread_func(void *data)
351 struct dev_context *devc = data;
352 uint8_t buf[BUFSIZE];
353 uint64_t nb_to_send = 0;
355 double time_cur, time_last, time_diff;
357 time_last = g_timer_elapsed(devc->timer, NULL);
359 while (thread_running) {
361 time_cur = g_timer_elapsed(devc->timer, NULL);
363 time_diff = time_cur - time_last;
364 time_last = time_cur;
366 nb_to_send = cur_samplerate * time_diff;
369 nb_to_send = MIN(nb_to_send,
370 limit_samples - devc->samples_counter);
373 /* Make sure we don't overflow. */
374 nb_to_send = MIN(nb_to_send, BUFSIZE);
377 samples_generator(buf, nb_to_send, data);
378 devc->samples_counter += nb_to_send;
380 g_io_channel_write_chars(devc->channels[1], (gchar *)&buf,
381 nb_to_send, (gsize *)&bytes_written, NULL);
384 /* Check if we're done. */
385 if ((limit_msec && time_cur * 1000 > limit_msec) ||
386 (limit_samples && devc->samples_counter >= limit_samples))
388 close(devc->pipe_fds[1]);
396 /* Callback handling data */
397 static int receive_data(int fd, int revents, void *cb_data)
399 struct dev_context *devc = cb_data;
400 struct sr_datafeed_packet packet;
401 struct sr_datafeed_logic logic;
402 static uint64_t samples_received = 0;
403 unsigned char c[BUFSIZE];
410 g_io_channel_read_chars(devc->channels[0],
411 (gchar *)&c, BUFSIZE, &z, NULL);
414 packet.type = SR_DF_LOGIC;
415 packet.payload = &logic;
419 sr_session_send(devc->session_dev_id, &packet);
420 samples_received += z;
424 if (!thread_running && z <= 0) {
425 /* Make sure we don't receive more packets. */
426 hw_dev_acquisition_stop(NULL, cb_data);
433 static int hw_dev_acquisition_start(const struct sr_dev_inst *sdi,
436 struct sr_datafeed_packet *packet;
437 struct sr_datafeed_header *header;
438 struct sr_datafeed_meta_logic meta;
439 struct dev_context *devc;
443 sr_dbg("Starting acquisition.");
445 /* TODO: 'devc' is never g_free()'d? */
446 if (!(devc = g_try_malloc(sizeof(struct dev_context)))) {
447 sr_err("%s: devc malloc failed", __func__);
448 return SR_ERR_MALLOC;
451 devc->sample_generator = default_pattern;
452 devc->session_dev_id = cb_data;
453 devc->samples_counter = 0;
455 if (pipe(devc->pipe_fds)) {
456 /* TODO: Better error message. */
457 sr_err("%s: pipe() failed", __func__);
461 devc->channels[0] = g_io_channel_unix_new(devc->pipe_fds[0]);
462 devc->channels[1] = g_io_channel_unix_new(devc->pipe_fds[1]);
464 g_io_channel_set_flags(devc->channels[0], G_IO_FLAG_NONBLOCK, NULL);
466 /* Set channel encoding to binary (default is UTF-8). */
467 g_io_channel_set_encoding(devc->channels[0], NULL, NULL);
468 g_io_channel_set_encoding(devc->channels[1], NULL, NULL);
470 /* Make channels to unbuffered. */
471 g_io_channel_set_buffered(devc->channels[0], FALSE);
472 g_io_channel_set_buffered(devc->channels[1], FALSE);
474 sr_session_source_add_channel(devc->channels[0], G_IO_IN | G_IO_ERR,
475 40, receive_data, devc);
477 /* Run the demo thread. */
478 devc->timer = g_timer_new();
480 my_thread = g_thread_try_new("sigrok demo generator",
481 (GThreadFunc)thread_func, devc, NULL);
483 sr_err("%s: g_thread_try_new failed", __func__);
484 return SR_ERR; /* TODO */
487 if (!(packet = g_try_malloc(sizeof(struct sr_datafeed_packet)))) {
488 sr_err("%s: packet malloc failed", __func__);
489 return SR_ERR_MALLOC;
492 if (!(header = g_try_malloc(sizeof(struct sr_datafeed_header)))) {
493 sr_err("%s: header malloc failed", __func__);
494 return SR_ERR_MALLOC;
497 packet->type = SR_DF_HEADER;
498 packet->payload = header;
499 header->feed_version = 1;
500 gettimeofday(&header->starttime, NULL);
501 sr_session_send(devc->session_dev_id, packet);
503 /* Send metadata about the SR_DF_LOGIC packets to come. */
504 packet->type = SR_DF_META_LOGIC;
505 packet->payload = &meta;
506 meta.samplerate = cur_samplerate;
507 meta.num_probes = NUM_PROBES;
508 sr_session_send(devc->session_dev_id, packet);
516 static int hw_dev_acquisition_stop(struct sr_dev_inst *sdi, void *cb_data)
518 struct dev_context *devc;
519 struct sr_datafeed_packet packet;
525 sr_dbg("Stopping aquisition.");
527 /* Stop generate thread. */
530 sr_session_source_remove_channel(devc->channels[0]);
531 g_io_channel_shutdown(devc->channels[0], FALSE, NULL);
533 /* Send last packet. */
534 packet.type = SR_DF_END;
535 sr_session_send(devc->session_dev_id, &packet);
540 SR_PRIV struct sr_dev_driver demo_driver_info = {
542 .longname = "Demo driver and pattern generator",
545 .cleanup = hw_cleanup,
547 .dev_list = hw_dev_list,
548 .dev_open = hw_dev_open,
549 .dev_close = hw_dev_close,
550 .info_get = hw_info_get,
551 .dev_config_set = hw_dev_config_set,
552 .dev_acquisition_start = hw_dev_acquisition_start,
553 .dev_acquisition_stop = hw_dev_acquisition_stop,