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)
31 #include "sigrok-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. */
67 SR_PRIV GIOChannel *channels[2];
71 uint8_t sample_generator;
72 uint8_t thread_running;
73 uint64_t samples_counter;
75 gpointer session_data;
79 static int hwcaps[] = {
80 SR_HWCAP_LOGIC_ANALYZER,
83 SR_HWCAP_PATTERN_MODE,
84 SR_HWCAP_LIMIT_SAMPLES,
89 static struct sr_samplerates samplerates = {
96 static const char *pattern_strings[] = {
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 /* List of struct sr_dev_inst, maintained by opendev()/closedev(). */
129 static GSList *dev_insts = NULL;
130 static uint64_t cur_samplerate = SR_KHZ(200);
131 static uint64_t limit_samples = 0;
132 static uint64_t limit_msec = 0;
133 static int default_pattern = PATTERN_SIGROK;
134 static GThread *my_thread;
135 static int thread_running;
137 static int hw_stop_acquisition(int dev_index, gpointer session_data);
139 static int hw_init(const char *devinfo)
141 struct sr_dev_inst *sdi;
143 /* Avoid compiler warnings. */
146 sdi = sr_dev_inst_new(0, SR_ST_ACTIVE, DEMONAME, NULL, NULL);
148 sr_err("demo: %s: sr_dev_inst_new failed", __func__);
152 dev_insts = g_slist_append(dev_insts, sdi);
157 static int hw_opendev(int dev_index)
159 /* Avoid compiler warnings. */
162 /* Nothing needed so far. */
167 static int hw_closedev(int dev_index)
169 /* Avoid compiler warnings. */
172 /* Nothing needed so far. */
177 static int hw_cleanup(void)
179 /* Nothing needed so far. */
183 static void *hw_get_dev_info(int dev_index, int dev_info_id)
185 struct sr_dev_inst *sdi;
188 if (!(sdi = sr_dev_inst_get(dev_insts, dev_index))) {
189 sr_err("demo: %s: sdi was NULL", __func__);
193 switch (dev_info_id) {
197 case SR_DI_NUM_PROBES:
198 info = GINT_TO_POINTER(NUM_PROBES);
200 case SR_DI_PROBE_NAMES:
203 case SR_DI_SAMPLERATES:
206 case SR_DI_CUR_SAMPLERATE:
207 info = &cur_samplerate;
209 case SR_DI_PATTERNMODES:
210 info = &pattern_strings;
217 static int hw_get_status(int dev_index)
219 /* Avoid compiler warnings. */
225 static int *hw_hwcap_get_all(void)
230 static int hw_set_configuration(int dev_index, int hwcap, void *value)
235 /* Avoid compiler warnings. */
238 if (hwcap == SR_HWCAP_PROBECONFIG) {
239 /* Nothing to do, but must be supported */
241 } else if (hwcap == SR_HWCAP_SAMPLERATE) {
242 cur_samplerate = *(uint64_t *)value;
243 sr_dbg("demo: %s: setting samplerate to %" PRIu64, __func__,
246 } else if (hwcap == SR_HWCAP_LIMIT_SAMPLES) {
247 limit_samples = *(uint64_t *)value;
248 sr_dbg("demo: %s: setting limit_samples to %" PRIu64, __func__,
251 } else if (hwcap == SR_HWCAP_LIMIT_MSEC) {
252 limit_msec = *(uint64_t *)value;
253 sr_dbg("demo: %s: setting limit_msec to %" PRIu64, __func__,
256 } else if (hwcap == SR_HWCAP_PATTERN_MODE) {
259 if (!strcmp(stropt, "sigrok")) {
260 default_pattern = PATTERN_SIGROK;
261 } else if (!strcmp(stropt, "random")) {
262 default_pattern = PATTERN_RANDOM;
263 } else if (!strcmp(stropt, "incremental")) {
264 default_pattern = PATTERN_INC;
265 } else if (!strcmp(stropt, "all-low")) {
266 default_pattern = PATTERN_ALL_LOW;
267 } else if (!strcmp(stropt, "all-high")) {
268 default_pattern = PATTERN_ALL_HIGH;
272 sr_dbg("demo: %s: setting pattern to %d", __func__,
281 static void samples_generator(uint8_t *buf, uint64_t size, void *data)
283 static uint64_t p = 0;
284 struct databag *mydata = data;
288 memset(buf, 0, size);
290 switch (mydata->sample_generator) {
291 case PATTERN_SIGROK: /* sigrok pattern */
292 for (i = 0; i < size; i++) {
293 *(buf + i) = ~(pattern_sigrok[p] >> 1);
298 case PATTERN_RANDOM: /* Random */
299 for (i = 0; i < size; i++)
300 *(buf + i) = (uint8_t)(rand() & 0xff);
302 case PATTERN_INC: /* Simple increment */
303 for (i = 0; i < size; i++)
306 case PATTERN_ALL_LOW: /* All probes are low */
307 memset(buf, 0x00, size);
309 case PATTERN_ALL_HIGH: /* All probes are high */
310 memset(buf, 0xff, size);
313 /* TODO: Error handling. */
318 /* Thread function */
319 static void thread_func(void *data)
321 struct databag *mydata = data;
322 uint8_t buf[BUFSIZE];
323 uint64_t nb_to_send = 0;
325 double time_cur, time_last, time_diff;
327 time_last = g_timer_elapsed(mydata->timer, NULL);
329 while (thread_running) {
331 time_cur = g_timer_elapsed(mydata->timer, NULL);
333 time_diff = time_cur - time_last;
334 time_last = time_cur;
336 nb_to_send = cur_samplerate * time_diff;
339 nb_to_send = MIN(nb_to_send,
340 limit_samples - mydata->samples_counter);
343 /* Make sure we don't overflow. */
344 nb_to_send = MIN(nb_to_send, BUFSIZE);
347 samples_generator(buf, nb_to_send, data);
348 mydata->samples_counter += nb_to_send;
350 g_io_channel_write_chars(channels[1], (gchar *)&buf,
351 nb_to_send, (gsize *)&bytes_written, NULL);
354 /* Check if we're done. */
355 if ((limit_msec && time_cur * 1000 > limit_msec) ||
356 (limit_samples && mydata->samples_counter >= limit_samples))
358 close(mydata->pipe_fds[1]);
366 /* Callback handling data */
367 static int receive_data(int fd, int revents, void *session_data)
369 struct sr_datafeed_packet packet;
370 struct sr_datafeed_logic logic;
371 static uint64_t samples_received = 0;
372 unsigned char c[BUFSIZE];
375 /* Avoid compiler warnings. */
380 g_io_channel_read_chars(channels[0],
381 (gchar *)&c, BUFSIZE, &z, NULL);
384 packet.type = SR_DF_LOGIC;
385 packet.payload = &logic;
389 sr_session_bus(session_data, &packet);
390 samples_received += z;
394 if (!thread_running && z <= 0) {
395 /* Make sure we don't receive more packets. */
396 g_io_channel_close(channels[0]);
398 /* Send last packet. */
399 packet.type = SR_DF_END;
400 sr_session_bus(session_data, &packet);
408 static int hw_start_acquisition(int dev_index, gpointer session_data)
410 struct sr_datafeed_packet *packet;
411 struct sr_datafeed_header *header;
412 struct databag *mydata;
414 /* TODO: 'mydata' is never g_free()'d? */
415 if (!(mydata = g_try_malloc(sizeof(struct databag)))) {
416 sr_err("demo: %s: mydata malloc failed", __func__);
417 return SR_ERR_MALLOC;
420 mydata->sample_generator = default_pattern;
421 mydata->session_data = session_data;
422 mydata->dev_index = dev_index;
423 mydata->samples_counter = 0;
425 if (pipe(mydata->pipe_fds)) {
426 /* TODO: Better error message. */
427 sr_err("demo: %s: pipe() failed", __func__);
431 channels[0] = g_io_channel_unix_new(mydata->pipe_fds[0]);
432 channels[1] = g_io_channel_unix_new(mydata->pipe_fds[1]);
434 /* Set channel encoding to binary (default is UTF-8). */
435 g_io_channel_set_encoding(channels[0], NULL, NULL);
436 g_io_channel_set_encoding(channels[1], NULL, NULL);
438 /* Make channels to unbuffered. */
439 g_io_channel_set_buffered(channels[0], FALSE);
440 g_io_channel_set_buffered(channels[1], FALSE);
442 sr_source_add(mydata->pipe_fds[0], G_IO_IN | G_IO_ERR, 40,
443 receive_data, session_data);
445 /* Run the demo thread. */
447 /* This must to be done between g_thread_init() & g_thread_create(). */
448 mydata->timer = g_timer_new();
451 g_thread_create((GThreadFunc)thread_func, mydata, TRUE, NULL);
453 sr_err("demo: %s: g_thread_create failed", __func__);
454 return SR_ERR; /* TODO */
457 if (!(packet = g_try_malloc(sizeof(struct sr_datafeed_packet)))) {
458 sr_err("demo: %s: packet malloc failed", __func__);
459 return SR_ERR_MALLOC;
462 if (!(header = g_try_malloc(sizeof(struct sr_datafeed_header)))) {
463 sr_err("demo: %s: header malloc failed", __func__);
464 return SR_ERR_MALLOC;
467 packet->type = SR_DF_HEADER;
468 packet->payload = header;
469 header->feed_version = 1;
470 gettimeofday(&header->starttime, NULL);
471 header->samplerate = cur_samplerate;
472 header->num_logic_probes = NUM_PROBES;
473 sr_session_bus(session_data, packet);
480 static int hw_stop_acquisition(int dev_index, gpointer session_data)
482 /* Avoid compiler warnings. */
486 /* Stop generate thread. */
492 SR_PRIV struct sr_dev_plugin demo_plugin_info = {
494 .longname = "Demo driver and pattern generator",
497 .cleanup = hw_cleanup,
498 .opendev = hw_opendev,
499 .closedev = hw_closedev,
500 .get_dev_info = hw_get_dev_info,
501 .get_status = hw_get_status,
502 .hwcap_get_all = hw_hwcap_get_all,
503 .set_configuration = hw_set_configuration,
504 .start_acquisition = hw_start_acquisition,
505 .stop_acquisition = hw_stop_acquisition,