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;
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 /* 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 static GSList *dev_insts = NULL;
134 static uint64_t cur_samplerate = SR_KHZ(200);
135 static uint64_t limit_samples = 0;
136 static uint64_t limit_msec = 0;
137 static int default_pattern = PATTERN_SIGROK;
138 static GThread *my_thread;
139 static int thread_running;
141 static int hw_dev_acquisition_stop(int dev_index, void *cb_data);
143 static int hw_init(const char *devinfo)
145 struct sr_dev_inst *sdi;
147 /* Avoid compiler warnings. */
150 sdi = sr_dev_inst_new(0, SR_ST_ACTIVE, DEMONAME, NULL, NULL);
152 sr_err("demo: %s: sr_dev_inst_new failed", __func__);
156 dev_insts = g_slist_append(dev_insts, sdi);
161 static int hw_dev_open(int dev_index)
163 /* Avoid compiler warnings. */
166 /* Nothing needed so far. */
171 static int hw_dev_close(int dev_index)
173 /* Avoid compiler warnings. */
176 /* Nothing needed so far. */
181 static int hw_cleanup(void)
183 /* Nothing needed so far. */
187 static void *hw_dev_info_get(int dev_index, int dev_info_id)
189 struct sr_dev_inst *sdi;
192 if (!(sdi = sr_dev_inst_get(dev_insts, dev_index))) {
193 sr_err("demo: %s: sdi was NULL", __func__);
197 switch (dev_info_id) {
201 case SR_DI_NUM_PROBES:
202 info = GINT_TO_POINTER(NUM_PROBES);
204 case SR_DI_PROBE_NAMES:
207 case SR_DI_SAMPLERATES:
210 case SR_DI_CUR_SAMPLERATE:
211 info = &cur_samplerate;
213 case SR_DI_PATTERNMODES:
214 info = &pattern_strings;
221 static int hw_dev_status_get(int dev_index)
223 /* Avoid compiler warnings. */
229 static int *hw_hwcap_get_all(void)
234 static int hw_dev_config_set(int dev_index, int hwcap, void *value)
239 /* Avoid compiler warnings. */
242 if (hwcap == SR_HWCAP_PROBECONFIG) {
243 /* Nothing to do, but must be supported */
245 } else if (hwcap == SR_HWCAP_SAMPLERATE) {
246 cur_samplerate = *(uint64_t *)value;
247 sr_dbg("demo: %s: setting samplerate to %" PRIu64, __func__,
250 } else if (hwcap == SR_HWCAP_LIMIT_SAMPLES) {
251 limit_samples = *(uint64_t *)value;
252 sr_dbg("demo: %s: setting limit_samples to %" PRIu64, __func__,
255 } else if (hwcap == SR_HWCAP_LIMIT_MSEC) {
256 limit_msec = *(uint64_t *)value;
257 sr_dbg("demo: %s: setting limit_msec to %" PRIu64, __func__,
260 } else if (hwcap == SR_HWCAP_PATTERN_MODE) {
263 if (!strcmp(stropt, "sigrok")) {
264 default_pattern = PATTERN_SIGROK;
265 } else if (!strcmp(stropt, "random")) {
266 default_pattern = PATTERN_RANDOM;
267 } else if (!strcmp(stropt, "incremental")) {
268 default_pattern = PATTERN_INC;
269 } else if (!strcmp(stropt, "all-low")) {
270 default_pattern = PATTERN_ALL_LOW;
271 } else if (!strcmp(stropt, "all-high")) {
272 default_pattern = PATTERN_ALL_HIGH;
276 sr_dbg("demo: %s: setting pattern to %d", __func__,
285 static void samples_generator(uint8_t *buf, uint64_t size, void *data)
287 static uint64_t p = 0;
288 struct databag *mydata = data;
292 memset(buf, 0, size);
294 switch (mydata->sample_generator) {
295 case PATTERN_SIGROK: /* sigrok pattern */
296 for (i = 0; i < size; i++) {
297 *(buf + i) = ~(pattern_sigrok[p] >> 1);
302 case PATTERN_RANDOM: /* Random */
303 for (i = 0; i < size; i++)
304 *(buf + i) = (uint8_t)(rand() & 0xff);
306 case PATTERN_INC: /* Simple increment */
307 for (i = 0; i < size; i++)
310 case PATTERN_ALL_LOW: /* All probes are low */
311 memset(buf, 0x00, size);
313 case PATTERN_ALL_HIGH: /* All probes are high */
314 memset(buf, 0xff, size);
317 /* TODO: Error handling. */
322 /* Thread function */
323 static void thread_func(void *data)
325 struct databag *mydata = data;
326 uint8_t buf[BUFSIZE];
327 uint64_t nb_to_send = 0;
329 double time_cur, time_last, time_diff;
331 time_last = g_timer_elapsed(mydata->timer, NULL);
333 while (thread_running) {
335 time_cur = g_timer_elapsed(mydata->timer, NULL);
337 time_diff = time_cur - time_last;
338 time_last = time_cur;
340 nb_to_send = cur_samplerate * time_diff;
343 nb_to_send = MIN(nb_to_send,
344 limit_samples - mydata->samples_counter);
347 /* Make sure we don't overflow. */
348 nb_to_send = MIN(nb_to_send, BUFSIZE);
351 samples_generator(buf, nb_to_send, data);
352 mydata->samples_counter += nb_to_send;
354 g_io_channel_write_chars(channels[1], (gchar *)&buf,
355 nb_to_send, (gsize *)&bytes_written, NULL);
358 /* Check if we're done. */
359 if ((limit_msec && time_cur * 1000 > limit_msec) ||
360 (limit_samples && mydata->samples_counter >= limit_samples))
362 close(mydata->pipe_fds[1]);
370 /* Callback handling data */
371 static int receive_data(int fd, int revents, void *cb_data)
373 struct sr_datafeed_packet packet;
374 struct sr_datafeed_logic logic;
375 static uint64_t samples_received = 0;
376 unsigned char c[BUFSIZE];
379 /* Avoid compiler warnings. */
384 g_io_channel_read_chars(channels[0],
385 (gchar *)&c, BUFSIZE, &z, NULL);
388 packet.type = SR_DF_LOGIC;
389 packet.payload = &logic;
393 sr_session_send(cb_data, &packet);
394 samples_received += z;
398 if (!thread_running && z <= 0) {
399 /* Make sure we don't receive more packets. */
400 g_io_channel_close(channels[0]);
402 /* Send last packet. */
403 packet.type = SR_DF_END;
404 sr_session_send(cb_data, &packet);
412 static int hw_dev_acquisition_start(int dev_index, void *cb_data)
414 struct sr_datafeed_packet *packet;
415 struct sr_datafeed_header *header;
416 struct databag *mydata;
418 /* TODO: 'mydata' is never g_free()'d? */
419 if (!(mydata = g_try_malloc(sizeof(struct databag)))) {
420 sr_err("demo: %s: mydata malloc failed", __func__);
421 return SR_ERR_MALLOC;
424 mydata->sample_generator = default_pattern;
425 mydata->session_dev_id = cb_data;
426 mydata->dev_index = dev_index;
427 mydata->samples_counter = 0;
429 if (pipe(mydata->pipe_fds)) {
430 /* TODO: Better error message. */
431 sr_err("demo: %s: pipe() failed", __func__);
435 channels[0] = g_io_channel_unix_new(mydata->pipe_fds[0]);
436 channels[1] = g_io_channel_unix_new(mydata->pipe_fds[1]);
438 /* Set channel encoding to binary (default is UTF-8). */
439 g_io_channel_set_encoding(channels[0], NULL, NULL);
440 g_io_channel_set_encoding(channels[1], NULL, NULL);
442 /* Make channels to unbuffered. */
443 g_io_channel_set_buffered(channels[0], FALSE);
444 g_io_channel_set_buffered(channels[1], FALSE);
446 sr_source_add(mydata->pipe_fds[0], G_IO_IN | G_IO_ERR, 40,
447 receive_data, mydata->session_dev_id);
449 /* Run the demo thread. */
451 /* This must to be done between g_thread_init() & g_thread_create(). */
452 mydata->timer = g_timer_new();
455 g_thread_create((GThreadFunc)thread_func, mydata, TRUE, NULL);
457 sr_err("demo: %s: g_thread_create failed", __func__);
458 return SR_ERR; /* TODO */
461 if (!(packet = g_try_malloc(sizeof(struct sr_datafeed_packet)))) {
462 sr_err("demo: %s: packet malloc failed", __func__);
463 return SR_ERR_MALLOC;
466 if (!(header = g_try_malloc(sizeof(struct sr_datafeed_header)))) {
467 sr_err("demo: %s: header malloc failed", __func__);
468 return SR_ERR_MALLOC;
471 packet->type = SR_DF_HEADER;
472 packet->payload = header;
473 header->feed_version = 1;
474 gettimeofday(&header->starttime, NULL);
475 header->samplerate = cur_samplerate;
476 header->num_logic_probes = NUM_PROBES;
477 sr_session_send(mydata->session_dev_id, packet);
484 /* TODO: This stops acquisition on ALL devices, ignoring dev_index. */
485 static int hw_dev_acquisition_stop(int dev_index, void *cb_data)
487 /* Avoid compiler warnings. */
491 /* Stop generate thread. */
497 SR_PRIV struct sr_dev_driver demo_driver_info = {
499 .longname = "Demo driver and pattern generator",
502 .cleanup = hw_cleanup,
503 .dev_open = hw_dev_open,
504 .dev_close = hw_dev_close,
505 .dev_info_get = hw_dev_info_get,
506 .dev_status_get = hw_dev_status_get,
507 .hwcap_get_all = hw_hwcap_get_all,
508 .dev_config_set = hw_dev_config_set,
509 .dev_acquisition_start = hw_dev_acquisition_start,
510 .dev_acquisition_stop = hw_dev_acquisition_stop,