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 #define STR_PATTERN_SIGROK "sigrok"
53 #define STR_PATTERN_RANDOM "random"
54 #define STR_PATTERN_INC "incremental"
55 #define STR_PATTERN_ALL_LOW "all-low"
56 #define STR_PATTERN_ALL_HIGH "all-high"
58 /* Supported patterns which we can generate */
61 * Pattern which spells "sigrok" using '0's (with '1's as "background")
62 * when displayed using the 'bits' output format.
66 /** Pattern which consists of (pseudo-)random values on all probes. */
70 * Pattern which consists of incrementing numbers.
71 * TODO: Better description.
75 /** Pattern where all probes have a low logic state. */
78 /** Pattern where all probes have a high logic state. */
82 /* Private, per-device-instance driver context. */
84 struct sr_dev_inst *sdi;
87 uint8_t sample_generator;
88 uint64_t samples_counter;
93 static const int hwcaps[] = {
94 SR_CONF_LOGIC_ANALYZER,
98 SR_CONF_LIMIT_SAMPLES,
103 static const uint64_t samplerates[] = {
109 static const char *pattern_strings[] = {
117 /* We name the probes 0-7 on our demo driver. */
118 static const char *probe_names[NUM_PROBES + 1] = {
119 "0", "1", "2", "3", "4", "5", "6", "7",
123 static uint8_t pattern_sigrok[] = {
124 0x4c, 0x92, 0x92, 0x92, 0x64, 0x00, 0x00, 0x00,
125 0x82, 0xfe, 0xfe, 0x82, 0x00, 0x00, 0x00, 0x00,
126 0x7c, 0x82, 0x82, 0x92, 0x74, 0x00, 0x00, 0x00,
127 0xfe, 0x12, 0x12, 0x32, 0xcc, 0x00, 0x00, 0x00,
128 0x7c, 0x82, 0x82, 0x82, 0x7c, 0x00, 0x00, 0x00,
129 0xfe, 0x10, 0x28, 0x44, 0x82, 0x00, 0x00, 0x00,
130 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
131 0xbe, 0xbe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
134 /* Private, per-device-instance driver context. */
135 /* TODO: struct context as with the other drivers. */
137 /* List of struct sr_dev_inst, maintained by dev_open()/dev_close(). */
138 SR_PRIV struct sr_dev_driver demo_driver_info;
139 static struct sr_dev_driver *di = &demo_driver_info;
140 static uint64_t cur_samplerate = SR_KHZ(200);
141 static uint64_t limit_samples = 0;
142 static uint64_t limit_msec = 0;
143 static int default_pattern = PATTERN_SIGROK;
145 static int hw_dev_acquisition_stop(struct sr_dev_inst *sdi, void *cb_data);
147 static int clear_instances(void)
149 /* Nothing needed so far. */
154 static int hw_init(struct sr_context *sr_ctx)
156 return std_hw_init(sr_ctx, di, DRIVER_LOG_DOMAIN);
159 static GSList *hw_scan(GSList *options)
161 struct sr_dev_inst *sdi;
162 struct sr_probe *probe;
163 struct drv_context *drvc;
164 struct dev_context *devc;
174 sdi = sr_dev_inst_new(0, SR_ST_ACTIVE, DEMONAME, NULL, NULL);
176 sr_err("%s: sr_dev_inst_new failed", __func__);
181 for (i = 0; probe_names[i]; i++) {
182 if (!(probe = sr_probe_new(i, SR_PROBE_LOGIC, TRUE,
185 sdi->probes = g_slist_append(sdi->probes, probe);
188 devices = g_slist_append(devices, sdi);
189 drvc->instances = g_slist_append(drvc->instances, sdi);
191 /* TODO: 'devc' is never g_free()'d? */
192 if (!(devc = g_try_malloc(sizeof(struct dev_context)))) {
193 sr_err("%s: devc malloc failed", __func__);
194 return SR_ERR_MALLOC;
204 static GSList *hw_dev_list(void)
206 return ((struct drv_context *)(di->priv))->instances;
209 static int hw_dev_open(struct sr_dev_inst *sdi)
213 /* Nothing needed so far. */
218 static int hw_dev_close(struct sr_dev_inst *sdi)
222 /* Nothing needed so far. */
227 static int hw_cleanup(void)
229 /* Nothing needed so far. */
233 static int config_get(int id, GVariant **data, const struct sr_dev_inst *sdi)
238 case SR_CONF_SAMPLERATE:
239 *data = g_variant_new_uint64(cur_samplerate);
241 case SR_CONF_LIMIT_SAMPLES:
242 *data = g_variant_new_uint64(limit_samples);
244 case SR_CONF_LIMIT_MSEC:
245 *data = g_variant_new_uint64(limit_msec);
247 case SR_CONF_PATTERN_MODE:
248 switch (default_pattern) {
250 *data = g_variant_new_string(STR_PATTERN_SIGROK);
253 *data = g_variant_new_string(STR_PATTERN_RANDOM);
256 *data = g_variant_new_string(STR_PATTERN_INC);
258 case PATTERN_ALL_LOW:
259 *data = g_variant_new_string(STR_PATTERN_ALL_LOW);
261 case PATTERN_ALL_HIGH:
262 *data = g_variant_new_string(STR_PATTERN_ALL_HIGH);
273 static int config_set(int id, GVariant *data, const struct sr_dev_inst *sdi)
280 if (id == SR_CONF_SAMPLERATE) {
281 cur_samplerate = g_variant_get_uint64(data);
282 sr_dbg("%s: setting samplerate to %" PRIu64, __func__,
285 } else if (id == SR_CONF_LIMIT_SAMPLES) {
287 limit_samples = g_variant_get_uint64(data);
288 sr_dbg("%s: setting limit_samples to %" PRIu64, __func__,
291 } else if (id == SR_CONF_LIMIT_MSEC) {
292 limit_msec = g_variant_get_uint64(data);
294 sr_dbg("%s: setting limit_msec to %" PRIu64, __func__,
297 } else if (id == SR_CONF_PATTERN_MODE) {
298 stropt = g_variant_get_string(data, NULL);
300 if (!strcmp(stropt, STR_PATTERN_SIGROK)) {
301 default_pattern = PATTERN_SIGROK;
302 } else if (!strcmp(stropt, STR_PATTERN_RANDOM)) {
303 default_pattern = PATTERN_RANDOM;
304 } else if (!strcmp(stropt, STR_PATTERN_INC)) {
305 default_pattern = PATTERN_INC;
306 } else if (!strcmp(stropt, STR_PATTERN_ALL_LOW)) {
307 default_pattern = PATTERN_ALL_LOW;
308 } else if (!strcmp(stropt, STR_PATTERN_ALL_HIGH)) {
309 default_pattern = PATTERN_ALL_HIGH;
313 sr_dbg("%s: setting pattern to %d", __func__, default_pattern);
321 static int config_list(int key, GVariant **data, const struct sr_dev_inst *sdi)
329 case SR_CONF_DEVICE_OPTIONS:
330 *data = g_variant_new_fixed_array(G_VARIANT_TYPE_INT32,
331 hwcaps, ARRAY_SIZE(hwcaps), sizeof(int32_t));
333 case SR_CONF_SAMPLERATE:
334 g_variant_builder_init(&gvb, G_VARIANT_TYPE("a{sv}"));
335 gvar = g_variant_new_fixed_array(G_VARIANT_TYPE("t"), samplerates,
336 ARRAY_SIZE(samplerates), sizeof(uint64_t));
337 g_variant_builder_add(&gvb, "{sv}", "samplerate-steps", gvar);
338 *data = g_variant_builder_end(&gvb);
340 case SR_CONF_PATTERN_MODE:
341 *data = g_variant_new_strv(pattern_strings, ARRAY_SIZE(pattern_strings));
350 static void samples_generator(uint8_t *buf, uint64_t size,
351 struct dev_context *devc)
353 static uint64_t p = 0;
357 memset(buf, 0, size);
359 switch (devc->sample_generator) {
360 case PATTERN_SIGROK: /* sigrok pattern */
361 for (i = 0; i < size; i++) {
362 *(buf + i) = ~(pattern_sigrok[
363 p++ % sizeof(pattern_sigrok)] >> 1);
366 case PATTERN_RANDOM: /* Random */
367 for (i = 0; i < size; i++)
368 *(buf + i) = (uint8_t)(rand() & 0xff);
370 case PATTERN_INC: /* Simple increment */
371 for (i = 0; i < size; i++)
374 case PATTERN_ALL_LOW: /* All probes are low */
375 memset(buf, 0x00, size);
377 case PATTERN_ALL_HIGH: /* All probes are high */
378 memset(buf, 0xff, size);
381 sr_err("Unknown pattern: %d.", devc->sample_generator);
386 /* Callback handling data */
387 static int receive_data(int fd, int revents, void *cb_data)
389 struct dev_context *devc = cb_data;
390 struct sr_datafeed_packet packet;
391 struct sr_datafeed_logic logic;
392 uint8_t buf[BUFSIZE];
393 static uint64_t samples_to_send, expected_samplenum, sending_now;
394 int64_t time, elapsed;
399 /* How many "virtual" samples should we have collected by now? */
400 time = g_get_monotonic_time();
401 elapsed = time - devc->starttime;
402 expected_samplenum = elapsed * cur_samplerate / 1000000;
403 /* Of those, how many do we still have to send? */
404 samples_to_send = expected_samplenum - devc->samples_counter;
407 samples_to_send = MIN(samples_to_send,
408 limit_samples - devc->samples_counter);
411 while (samples_to_send > 0) {
412 sending_now = MIN(samples_to_send, sizeof(buf));
413 samples_to_send -= sending_now;
414 samples_generator(buf, sending_now, devc);
416 packet.type = SR_DF_LOGIC;
417 packet.payload = &logic;
418 logic.length = sending_now;
421 sr_session_send(devc->cb_data, &packet);
422 devc->samples_counter += sending_now;
425 if (limit_samples && devc->samples_counter >= limit_samples) {
426 sr_info("Requested number of samples reached.");
427 hw_dev_acquisition_stop(devc->sdi, cb_data);
434 static int hw_dev_acquisition_start(const struct sr_dev_inst *sdi,
437 struct dev_context *const devc = sdi->priv;
439 devc->sample_generator = default_pattern;
440 devc->cb_data = cb_data;
441 devc->samples_counter = 0;
444 * Setting two channels connected by a pipe is a remnant from when the
445 * demo driver generated data in a thread, and collected and sent the
446 * data in the main program loop.
447 * They are kept here because it provides a convenient way of setting
448 * up a timeout-based polling mechanism.
450 if (pipe(devc->pipe_fds)) {
451 /* TODO: Better error message. */
452 sr_err("%s: pipe() failed", __func__);
456 devc->channel = g_io_channel_unix_new(devc->pipe_fds[0]);
458 g_io_channel_set_flags(devc->channel, G_IO_FLAG_NONBLOCK, NULL);
460 /* Set channel encoding to binary (default is UTF-8). */
461 g_io_channel_set_encoding(devc->channel, NULL, NULL);
463 /* Make channels to unbuffered. */
464 g_io_channel_set_buffered(devc->channel, FALSE);
466 sr_session_source_add_channel(devc->channel, G_IO_IN | G_IO_ERR,
467 40, receive_data, devc);
469 /* Send header packet to the session bus. */
470 std_session_send_df_header(cb_data, DRIVER_LOG_DOMAIN);
472 /* We use this timestamp to decide how many more samples to send. */
473 devc->starttime = g_get_monotonic_time();
478 static int hw_dev_acquisition_stop(struct sr_dev_inst *sdi, void *cb_data)
480 struct dev_context *const devc = sdi->priv;
481 struct sr_datafeed_packet packet;
485 sr_dbg("Stopping aquisition.");
487 sr_session_source_remove_channel(devc->channel);
488 g_io_channel_shutdown(devc->channel, FALSE, NULL);
490 /* Send last packet. */
491 packet.type = SR_DF_END;
492 sr_session_send(devc->cb_data, &packet);
497 SR_PRIV struct sr_dev_driver demo_driver_info = {
499 .longname = "Demo driver and pattern generator",
502 .cleanup = hw_cleanup,
504 .dev_list = hw_dev_list,
505 .dev_clear = clear_instances,
506 .config_get = config_get,
507 .config_set = config_set,
508 .config_list = config_list,
509 .dev_open = hw_dev_open,
510 .dev_close = hw_dev_close,
511 .dev_acquisition_start = hw_dev_acquisition_start,
512 .dev_acquisition_stop = hw_dev_acquisition_stop,