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
26 #include <sigrok-internal.h>
30 #define pipe(fds) _pipe(fds, 4096, _O_BINARY)
34 /* TODO: Number of probes should be configurable. */
37 #define DEMONAME "Demo device"
39 /* The size of chunks to send through the session bus. */
40 /* TODO: Should be configurable. */
43 /* Supported patterns which we can generate */
46 * Pattern which spells "sigrok" using '0's (with '1's as "background")
47 * when displayed using the 'bits' output format.
51 /** Pattern which consists of (pseudo-)random values on all probes. */
55 * Pattern which consists of incrementing numbers.
56 * TODO: Better description.
60 /** Pattern where all probes have a low logic state. */
63 /** Pattern where all probes have a high logic state. */
67 /* FIXME: Should not be global. */
68 GIOChannel *channels[2];
72 uint8_t sample_generator;
73 uint8_t thread_running;
74 uint64_t samples_counter;
76 gpointer session_device_id;
80 static int capabilities[] = {
81 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 uint8_t pattern_sigrok[] = {
106 0x4c, 0x92, 0x92, 0x92, 0x64, 0x00, 0x00, 0x00,
107 0x82, 0xfe, 0xfe, 0x82, 0x00, 0x00, 0x00, 0x00,
108 0x7c, 0x82, 0x82, 0x92, 0x74, 0x00, 0x00, 0x00,
109 0xfe, 0x12, 0x12, 0x32, 0xcc, 0x00, 0x00, 0x00,
110 0x7c, 0x82, 0x82, 0x82, 0x7c, 0x00, 0x00, 0x00,
111 0xfe, 0x10, 0x28, 0x44, 0x82, 0x00, 0x00, 0x00,
112 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
113 0xbe, 0xbe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
116 /* List of struct sr_device_instance, maintained by opendev()/closedev(). */
117 static GSList *device_instances = NULL;
118 static uint64_t cur_samplerate = SR_KHZ(200);
119 static uint64_t limit_samples = 0;
120 static uint64_t limit_msec = 0;
121 static int default_pattern = PATTERN_SIGROK;
122 static GThread *my_thread;
123 static int thread_running;
125 static void hw_stop_acquisition(int device_index, gpointer session_device_id);
127 static int hw_init(const char *deviceinfo)
129 struct sr_device_instance *sdi;
131 /* Avoid compiler warnings. */
132 deviceinfo = deviceinfo;
134 sdi = sr_device_instance_new(0, SR_ST_ACTIVE, DEMONAME, NULL, NULL);
136 sr_err("demo: %s: sr_device_instance_new failed", __func__);
140 device_instances = g_slist_append(device_instances, sdi);
145 static int hw_opendev(int device_index)
147 /* Avoid compiler warnings. */
148 device_index = device_index;
150 /* Nothing needed so far. */
155 static int hw_closedev(int device_index)
157 /* Avoid compiler warnings. */
158 device_index = device_index;
160 /* Nothing needed so far. */
165 static void hw_cleanup(void)
167 /* Nothing needed so far. */
170 static void *hw_get_device_info(int device_index, int device_info_id)
172 struct sr_device_instance *sdi;
175 if (!(sdi = sr_get_device_instance(device_instances, device_index))) {
176 sr_err("demo: %s: sdi was NULL", __func__);
180 switch (device_info_id) {
184 case SR_DI_NUM_PROBES:
185 info = GINT_TO_POINTER(NUM_PROBES);
187 case SR_DI_SAMPLERATES:
190 case SR_DI_CUR_SAMPLERATE:
191 info = &cur_samplerate;
193 case SR_DI_PATTERNMODES:
194 info = &pattern_strings;
201 static int hw_get_status(int device_index)
203 /* Avoid compiler warnings. */
204 device_index = device_index;
209 static int *hw_get_capabilities(void)
214 static int hw_set_configuration(int device_index, int capability, void *value)
219 /* Avoid compiler warnings. */
220 device_index = device_index;
222 if (capability == SR_HWCAP_PROBECONFIG) {
223 /* Nothing to do, but must be supported */
225 } else if (capability == SR_HWCAP_SAMPLERATE) {
226 cur_samplerate = *(uint64_t *)value;
227 sr_dbg("demo: %s: setting samplerate to %" PRIu64, __func__,
230 } else if (capability == SR_HWCAP_LIMIT_SAMPLES) {
231 limit_samples = *(uint64_t *)value;
232 sr_dbg("demo: %s: setting limit_samples to %" PRIu64, __func__,
235 } else if (capability == SR_HWCAP_LIMIT_MSEC) {
236 limit_msec = *(uint64_t *)value;
237 sr_dbg("demo: %s: setting limit_msec to %" PRIu64, __func__,
240 } else if (capability == SR_HWCAP_PATTERN_MODE) {
243 if (!strcmp(stropt, "sigrok")) {
244 default_pattern = PATTERN_SIGROK;
245 } else if (!strcmp(stropt, "random")) {
246 default_pattern = PATTERN_RANDOM;
247 } else if (!strcmp(stropt, "incremental")) {
248 default_pattern = PATTERN_INC;
249 } else if (!strcmp(stropt, "all-low")) {
250 default_pattern = PATTERN_ALL_LOW;
251 } else if (!strcmp(stropt, "all-high")) {
252 default_pattern = PATTERN_ALL_HIGH;
256 sr_dbg("demo: %s: setting pattern to %d", __func__,
265 static void samples_generator(uint8_t *buf, uint64_t size, void *data)
267 static uint64_t p = 0;
268 struct databag *mydata = data;
272 memset(buf, 0, size);
274 switch (mydata->sample_generator) {
275 case PATTERN_SIGROK: /* sigrok pattern */
276 for (i = 0; i < size; i++) {
277 *(buf + i) = ~(pattern_sigrok[p] >> 1);
282 case PATTERN_RANDOM: /* Random */
283 for (i = 0; i < size; i++)
284 *(buf + i) = (uint8_t)(rand() & 0xff);
286 case PATTERN_INC: /* Simple increment */
287 for (i = 0; i < size; i++)
290 case PATTERN_ALL_LOW: /* All probes are low */
291 memset(buf, 0x00, size);
293 case PATTERN_ALL_HIGH: /* All probes are high */
294 memset(buf, 0xff, size);
297 /* TODO: Error handling. */
302 /* Thread function */
303 static void thread_func(void *data)
305 struct databag *mydata = data;
306 uint8_t buf[BUFSIZE];
307 uint64_t nb_to_send = 0;
309 double time_cur, time_last, time_diff;
311 time_last = g_timer_elapsed(mydata->timer, NULL);
313 while (thread_running) {
315 time_cur = g_timer_elapsed(mydata->timer, NULL);
317 time_diff = time_cur - time_last;
318 time_last = time_cur;
320 nb_to_send = cur_samplerate * time_diff;
323 nb_to_send = MIN(nb_to_send,
324 limit_samples - mydata->samples_counter);
327 /* Make sure we don't overflow. */
328 nb_to_send = MIN(nb_to_send, BUFSIZE);
331 samples_generator(buf, nb_to_send, data);
332 mydata->samples_counter += nb_to_send;
334 g_io_channel_write_chars(channels[1], (gchar *)&buf,
335 nb_to_send, (gsize *)&bytes_written, NULL);
338 /* Check if we're done. */
339 if ((limit_msec && time_cur * 1000 > limit_msec) ||
340 (limit_samples && mydata->samples_counter >= limit_samples))
342 close(mydata->pipe_fds[1]);
350 /* Callback handling data */
351 static int receive_data(int fd, int revents, void *user_data)
353 struct sr_datafeed_packet packet;
357 /* Avoid compiler warnings. */
362 g_io_channel_read_chars(channels[0],
363 (gchar *)&c, BUFSIZE, &z, NULL);
366 packet.type = SR_DF_LOGIC;
370 sr_session_bus(user_data, &packet);
374 if (!thread_running && z <= 0) {
375 /* Make sure we don't receive more packets. */
376 g_io_channel_close(channels[0]);
378 /* Send last packet. */
379 packet.type = SR_DF_END;
380 sr_session_bus(user_data, &packet);
388 static int hw_start_acquisition(int device_index, gpointer session_device_id)
390 struct sr_datafeed_packet *packet;
391 struct sr_datafeed_header *header;
392 struct databag *mydata;
394 /* TODO: 'mydata' is never g_free()'d? */
395 if (!(mydata = g_try_malloc(sizeof(struct databag)))) {
396 sr_err("demo: %s: mydata malloc failed", __func__);
397 return SR_ERR_MALLOC;
400 mydata->sample_generator = default_pattern;
401 mydata->session_device_id = session_device_id;
402 mydata->device_index = device_index;
403 mydata->samples_counter = 0;
405 if (pipe(mydata->pipe_fds)) {
406 /* TODO: Better error message. */
407 sr_err("demo: %s: pipe() failed", __func__);
411 channels[0] = g_io_channel_unix_new(mydata->pipe_fds[0]);
412 channels[1] = g_io_channel_unix_new(mydata->pipe_fds[1]);
414 /* Set channel encoding to binary (default is UTF-8). */
415 g_io_channel_set_encoding(channels[0], NULL, NULL);
416 g_io_channel_set_encoding(channels[1], NULL, NULL);
418 /* Make channels to unbuffered. */
419 g_io_channel_set_buffered(channels[0], FALSE);
420 g_io_channel_set_buffered(channels[1], FALSE);
422 sr_source_add(mydata->pipe_fds[0], G_IO_IN | G_IO_ERR, 40,
423 receive_data, session_device_id);
425 /* Run the demo thread. */
427 /* This must to be done between g_thread_init() & g_thread_create(). */
428 mydata->timer = g_timer_new();
431 g_thread_create((GThreadFunc)thread_func, mydata, TRUE, NULL);
433 sr_err("demo: %s: g_thread_create failed", __func__);
434 return SR_ERR; /* TODO */
437 if (!(packet = g_try_malloc(sizeof(struct sr_datafeed_packet)))) {
438 sr_err("demo: %s: packet malloc failed", __func__);
439 return SR_ERR_MALLOC;
442 if (!(header = g_try_malloc(sizeof(struct sr_datafeed_header)))) {
443 sr_err("demo: %s: header malloc failed", __func__);
444 return SR_ERR_MALLOC;
447 packet->type = SR_DF_HEADER;
448 packet->length = sizeof(struct sr_datafeed_header);
449 packet->payload = (unsigned char *)header;
450 header->feed_version = 1;
451 gettimeofday(&header->starttime, NULL);
452 header->samplerate = cur_samplerate;
453 header->protocol_id = SR_PROTO_RAW;
454 header->num_logic_probes = NUM_PROBES;
455 header->num_analog_probes = 0;
456 sr_session_bus(session_device_id, packet);
463 static void hw_stop_acquisition(int device_index, gpointer session_device_id)
465 /* Avoid compiler warnings. */
466 device_index = device_index;
467 session_device_id = session_device_id;
469 /* Stop generate thread. */
473 struct sr_device_plugin demo_plugin_info = {
475 .longname = "Demo driver and pattern generator",
478 .cleanup = hw_cleanup,
479 .opendev = hw_opendev,
480 .closedev = hw_closedev,
481 .get_device_info = hw_get_device_info,
482 .get_status = hw_get_status,
483 .get_capabilities = hw_get_capabilities,
484 .set_configuration = hw_set_configuration,
485 .start_acquisition = hw_start_acquisition,
486 .stop_acquisition = hw_stop_acquisition,