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. */
68 /* Private driver context. */
73 /* Private, per-device-instance driver context. */
76 GIOChannel *channels[2];
77 uint8_t sample_generator;
78 uint8_t thread_running;
79 uint64_t samples_counter;
84 static const int hwcaps[] = {
85 SR_HWCAP_LOGIC_ANALYZER,
88 SR_HWCAP_PATTERN_MODE,
89 SR_HWCAP_LIMIT_SAMPLES,
94 static const struct sr_samplerates samplerates = {
101 static const char *pattern_strings[] = {
110 /* We name the probes 0-7 on our demo driver. */
111 static const char *probe_names[NUM_PROBES + 1] = {
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 *ddi = &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;
144 static GThread *my_thread;
145 static int thread_running;
147 static int hw_dev_acquisition_stop(const struct sr_dev_inst *sdi,
150 static int hw_init(void)
152 struct drv_context *drvc;
154 if (!(drvc = g_try_malloc0(sizeof(struct drv_context)))) {
155 sr_err("fx2lafw: driver context malloc failed.");
163 static GSList *hw_scan(GSList *options)
165 struct sr_dev_inst *sdi;
166 struct sr_probe *probe;
167 struct drv_context *drvc;
175 sdi = sr_dev_inst_new(0, SR_ST_ACTIVE, DEMONAME, NULL, NULL);
177 sr_err("demo: %s: sr_dev_inst_new failed", __func__);
182 for (i = 0; probe_names[i]; i++) {
183 if (!(probe = sr_probe_new(i, SR_PROBE_ANALOG, TRUE,
186 sdi->probes = g_slist_append(sdi->probes, probe);
189 devices = g_slist_append(devices, sdi);
190 drvc->instances = g_slist_append(drvc->instances, sdi);
195 static GSList *hw_dev_list(void)
197 struct drv_context *drvc;
201 return drvc->instances;
204 static int hw_dev_open(struct sr_dev_inst *sdi)
206 /* Avoid compiler warnings. */
209 /* Nothing needed so far. */
214 static int hw_dev_close(struct sr_dev_inst *sdi)
216 /* Avoid compiler warnings. */
219 /* Nothing needed so far. */
224 static int hw_cleanup(void)
226 /* Nothing needed so far. */
230 static int hw_info_get(int info_id, const void **data,
231 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("demo: %s: setting samplerate to %" PRIu64, __func__,
275 } else if (hwcap == SR_HWCAP_LIMIT_SAMPLES) {
277 limit_samples = *(const uint64_t *)value;
278 sr_dbg("demo: %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("demo: %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("demo: %s: setting pattern to %d", __func__,
312 static void samples_generator(uint8_t *buf, uint64_t size, void *data)
314 static uint64_t p = 0;
315 struct dev_context *devc = data;
319 memset(buf, 0, size);
321 switch (devc->sample_generator) {
322 case PATTERN_SIGROK: /* sigrok pattern */
323 for (i = 0; i < size; i++) {
324 *(buf + i) = ~(pattern_sigrok[p] >> 1);
329 case PATTERN_RANDOM: /* Random */
330 for (i = 0; i < size; i++)
331 *(buf + i) = (uint8_t)(rand() & 0xff);
333 case PATTERN_INC: /* Simple increment */
334 for (i = 0; i < size; i++)
337 case PATTERN_ALL_LOW: /* All probes are low */
338 memset(buf, 0x00, size);
340 case PATTERN_ALL_HIGH: /* All probes are high */
341 memset(buf, 0xff, size);
344 sr_err("demo: %s: unknown pattern %d", __func__,
345 devc->sample_generator);
350 /* Thread function */
351 static void thread_func(void *data)
353 struct dev_context *devc = data;
354 uint8_t buf[BUFSIZE];
355 uint64_t nb_to_send = 0;
357 double time_cur, time_last, time_diff;
359 time_last = g_timer_elapsed(devc->timer, NULL);
361 while (thread_running) {
363 time_cur = g_timer_elapsed(devc->timer, NULL);
365 time_diff = time_cur - time_last;
366 time_last = time_cur;
368 nb_to_send = cur_samplerate * time_diff;
371 nb_to_send = MIN(nb_to_send,
372 limit_samples - devc->samples_counter);
375 /* Make sure we don't overflow. */
376 nb_to_send = MIN(nb_to_send, BUFSIZE);
379 samples_generator(buf, nb_to_send, data);
380 devc->samples_counter += nb_to_send;
382 g_io_channel_write_chars(devc->channels[1], (gchar *)&buf,
383 nb_to_send, (gsize *)&bytes_written, NULL);
386 /* Check if we're done. */
387 if ((limit_msec && time_cur * 1000 > limit_msec) ||
388 (limit_samples && devc->samples_counter >= limit_samples))
390 close(devc->pipe_fds[1]);
398 /* Callback handling data */
399 static int receive_data(int fd, int revents, void *cb_data)
401 struct dev_context *devc = cb_data;
402 struct sr_datafeed_packet packet;
403 struct sr_datafeed_logic logic;
404 static uint64_t samples_received = 0;
405 unsigned char c[BUFSIZE];
408 /* Avoid compiler warnings. */
413 g_io_channel_read_chars(devc->channels[0],
414 (gchar *)&c, BUFSIZE, &z, NULL);
417 packet.type = SR_DF_LOGIC;
418 packet.payload = &logic;
422 sr_session_send(devc->session_dev_id, &packet);
423 samples_received += z;
427 if (!thread_running && z <= 0) {
428 /* Make sure we don't receive more packets. */
429 g_io_channel_shutdown(devc->channels[0], FALSE, NULL);
431 /* Send last packet. */
432 packet.type = SR_DF_END;
433 sr_session_send(devc->session_dev_id, &packet);
441 static int hw_dev_acquisition_start(const struct sr_dev_inst *sdi,
444 struct sr_datafeed_packet *packet;
445 struct sr_datafeed_header *header;
446 struct sr_datafeed_meta_logic meta;
447 struct dev_context *devc;
451 /* TODO: 'devc' is never g_free()'d? */
452 if (!(devc = g_try_malloc(sizeof(struct dev_context)))) {
453 sr_err("demo: %s: devc malloc failed", __func__);
454 return SR_ERR_MALLOC;
457 devc->sample_generator = default_pattern;
458 devc->session_dev_id = cb_data;
459 devc->samples_counter = 0;
461 if (pipe(devc->pipe_fds)) {
462 /* TODO: Better error message. */
463 sr_err("demo: %s: pipe() failed", __func__);
467 devc->channels[0] = g_io_channel_unix_new(devc->pipe_fds[0]);
468 devc->channels[1] = g_io_channel_unix_new(devc->pipe_fds[1]);
470 g_io_channel_set_flags(devc->channels[0], G_IO_FLAG_NONBLOCK, NULL);
472 /* Set channel encoding to binary (default is UTF-8). */
473 g_io_channel_set_encoding(devc->channels[0], NULL, NULL);
474 g_io_channel_set_encoding(devc->channels[1], NULL, NULL);
476 /* Make channels to unbuffered. */
477 g_io_channel_set_buffered(devc->channels[0], FALSE);
478 g_io_channel_set_buffered(devc->channels[1], FALSE);
480 sr_session_source_add_channel(devc->channels[0], G_IO_IN | G_IO_ERR,
481 40, receive_data, devc);
483 /* Run the demo thread. */
485 /* This must to be done between g_thread_init() & g_thread_create(). */
486 devc->timer = g_timer_new();
489 g_thread_create((GThreadFunc)thread_func, devc, TRUE, NULL);
491 sr_err("demo: %s: g_thread_create failed", __func__);
492 return SR_ERR; /* TODO */
495 if (!(packet = g_try_malloc(sizeof(struct sr_datafeed_packet)))) {
496 sr_err("demo: %s: packet malloc failed", __func__);
497 return SR_ERR_MALLOC;
500 if (!(header = g_try_malloc(sizeof(struct sr_datafeed_header)))) {
501 sr_err("demo: %s: header malloc failed", __func__);
502 return SR_ERR_MALLOC;
505 packet->type = SR_DF_HEADER;
506 packet->payload = header;
507 header->feed_version = 1;
508 gettimeofday(&header->starttime, NULL);
509 sr_session_send(devc->session_dev_id, packet);
511 /* Send metadata about the SR_DF_LOGIC packets to come. */
512 packet->type = SR_DF_META_LOGIC;
513 packet->payload = &meta;
514 meta.samplerate = cur_samplerate;
515 meta.num_probes = NUM_PROBES;
516 sr_session_send(devc->session_dev_id, packet);
524 static int hw_dev_acquisition_stop(const struct sr_dev_inst *sdi,
527 struct dev_context *devc;
529 /* Avoid compiler warnings. */
534 /* Stop generate thread. */
537 sr_session_source_remove_channel(devc->channels[0]);
542 SR_PRIV struct sr_dev_driver demo_driver_info = {
544 .longname = "Demo driver and pattern generator",
547 .cleanup = hw_cleanup,
549 .dev_list = hw_dev_list,
550 .dev_open = hw_dev_open,
551 .dev_close = hw_dev_close,
552 .info_get = hw_info_get,
553 .dev_config_set = hw_dev_config_set,
554 .dev_acquisition_start = hw_dev_acquisition_start,
555 .dev_acquisition_stop = hw_dev_acquisition_stop,