]> sigrok.org Git - libsigrok.git/blame_incremental - hardware/demo/demo.c
Fix outdated ezusb_install_firmware() prototype.
[libsigrok.git] / hardware / demo / demo.c
... / ...
CommitLineData
1/*
2 * This file is part of the sigrok project.
3 *
4 * Copyright (C) 2010 Uwe Hermann <uwe@hermann-uwe.de>
5 * Copyright (C) 2011 Olivier Fauchon <olivier@aixmarseille.com>
6 *
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.
11 *
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.
16 *
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
20 */
21
22#include <stdlib.h>
23#include <unistd.h>
24#include <string.h>
25#ifdef _WIN32
26#include <io.h>
27#include <fcntl.h>
28#define pipe(fds) _pipe(fds, 4096, _O_BINARY)
29#endif
30#include "config.h"
31#include "sigrok.h"
32#include "sigrok-internal.h"
33
34/* TODO: Number of probes should be configurable. */
35#define NUM_PROBES 8
36
37#define DEMONAME "Demo device"
38
39/* The size of chunks to send through the session bus. */
40/* TODO: Should be configurable. */
41#define BUFSIZE 4096
42
43/* Supported patterns which we can generate */
44enum {
45 /**
46 * Pattern which spells "sigrok" using '0's (with '1's as "background")
47 * when displayed using the 'bits' output format.
48 */
49 PATTERN_SIGROK,
50
51 /** Pattern which consists of (pseudo-)random values on all probes. */
52 PATTERN_RANDOM,
53
54 /**
55 * Pattern which consists of incrementing numbers.
56 * TODO: Better description.
57 */
58 PATTERN_INC,
59
60 /** Pattern where all probes have a low logic state. */
61 PATTERN_ALL_LOW,
62
63 /** Pattern where all probes have a high logic state. */
64 PATTERN_ALL_HIGH,
65};
66
67/* FIXME: Should not be global. */
68GIOChannel *channels[2];
69
70struct databag {
71 int pipe_fds[2];
72 uint8_t sample_generator;
73 uint8_t thread_running;
74 uint64_t samples_counter;
75 int device_index;
76 gpointer session_data;
77 GTimer *timer;
78};
79
80static int capabilities[] = {
81 SR_HWCAP_LOGIC_ANALYZER,
82 SR_HWCAP_SAMPLERATE,
83 SR_HWCAP_PATTERN_MODE,
84 SR_HWCAP_LIMIT_SAMPLES,
85 SR_HWCAP_LIMIT_MSEC,
86 SR_HWCAP_CONTINUOUS,
87};
88
89static struct sr_samplerates samplerates = {
90 SR_HZ(1),
91 SR_GHZ(1),
92 SR_HZ(1),
93 NULL,
94};
95
96static const char *pattern_strings[] = {
97 "sigrok",
98 "random",
99 "incremental",
100 "all-low",
101 "all-high",
102 NULL,
103};
104
105static 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,
114};
115
116/* List of struct sr_device_instance, maintained by opendev()/closedev(). */
117static GSList *device_instances = NULL;
118static uint64_t cur_samplerate = SR_KHZ(200);
119static uint64_t period_ps = 5000000;
120static uint64_t limit_samples = 0;
121static uint64_t limit_msec = 0;
122static int default_pattern = PATTERN_SIGROK;
123static GThread *my_thread;
124static int thread_running;
125
126static void hw_stop_acquisition(int device_index, gpointer session_data);
127
128static int hw_init(const char *deviceinfo)
129{
130 struct sr_device_instance *sdi;
131
132 /* Avoid compiler warnings. */
133 (void)deviceinfo;
134
135 sdi = sr_device_instance_new(0, SR_ST_ACTIVE, DEMONAME, NULL, NULL);
136 if (!sdi) {
137 sr_err("demo: %s: sr_device_instance_new failed", __func__);
138 return 0;
139 }
140
141 device_instances = g_slist_append(device_instances, sdi);
142
143 return 1;
144}
145
146static int hw_opendev(int device_index)
147{
148 /* Avoid compiler warnings. */
149 (void)device_index;
150
151 /* Nothing needed so far. */
152
153 return SR_OK;
154}
155
156static int hw_closedev(int device_index)
157{
158 /* Avoid compiler warnings. */
159 (void)device_index;
160
161 /* Nothing needed so far. */
162
163 return SR_OK;
164}
165
166static void hw_cleanup(void)
167{
168 /* Nothing needed so far. */
169}
170
171static void *hw_get_device_info(int device_index, int device_info_id)
172{
173 struct sr_device_instance *sdi;
174 void *info = NULL;
175
176 if (!(sdi = sr_get_device_instance(device_instances, device_index))) {
177 sr_err("demo: %s: sdi was NULL", __func__);
178 return NULL;
179 }
180
181 switch (device_info_id) {
182 case SR_DI_INSTANCE:
183 info = sdi;
184 break;
185 case SR_DI_NUM_PROBES:
186 info = GINT_TO_POINTER(NUM_PROBES);
187 break;
188 case SR_DI_SAMPLERATES:
189 info = &samplerates;
190 break;
191 case SR_DI_CUR_SAMPLERATE:
192 info = &cur_samplerate;
193 break;
194 case SR_DI_PATTERNMODES:
195 info = &pattern_strings;
196 break;
197 }
198
199 return info;
200}
201
202static int hw_get_status(int device_index)
203{
204 /* Avoid compiler warnings. */
205 (void)device_index;
206
207 return SR_ST_ACTIVE;
208}
209
210static int *hw_get_capabilities(void)
211{
212 return capabilities;
213}
214
215static int hw_set_configuration(int device_index, int capability, void *value)
216{
217 int ret;
218 char *stropt;
219
220 /* Avoid compiler warnings. */
221 (void)device_index;
222
223 if (capability == SR_HWCAP_PROBECONFIG) {
224 /* Nothing to do, but must be supported */
225 ret = SR_OK;
226 } else if (capability == SR_HWCAP_SAMPLERATE) {
227 cur_samplerate = *(uint64_t *)value;
228 period_ps = 1000000000000 / cur_samplerate;
229 sr_dbg("demo: %s: setting samplerate to %" PRIu64, __func__,
230 cur_samplerate);
231 ret = SR_OK;
232 } else if (capability == SR_HWCAP_LIMIT_SAMPLES) {
233 limit_samples = *(uint64_t *)value;
234 sr_dbg("demo: %s: setting limit_samples to %" PRIu64, __func__,
235 limit_samples);
236 ret = SR_OK;
237 } else if (capability == SR_HWCAP_LIMIT_MSEC) {
238 limit_msec = *(uint64_t *)value;
239 sr_dbg("demo: %s: setting limit_msec to %" PRIu64, __func__,
240 limit_msec);
241 ret = SR_OK;
242 } else if (capability == SR_HWCAP_PATTERN_MODE) {
243 stropt = value;
244 ret = SR_OK;
245 if (!strcmp(stropt, "sigrok")) {
246 default_pattern = PATTERN_SIGROK;
247 } else if (!strcmp(stropt, "random")) {
248 default_pattern = PATTERN_RANDOM;
249 } else if (!strcmp(stropt, "incremental")) {
250 default_pattern = PATTERN_INC;
251 } else if (!strcmp(stropt, "all-low")) {
252 default_pattern = PATTERN_ALL_LOW;
253 } else if (!strcmp(stropt, "all-high")) {
254 default_pattern = PATTERN_ALL_HIGH;
255 } else {
256 ret = SR_ERR;
257 }
258 sr_dbg("demo: %s: setting pattern to %d", __func__,
259 default_pattern);
260 } else {
261 ret = SR_ERR;
262 }
263
264 return ret;
265}
266
267static void samples_generator(uint8_t *buf, uint64_t size, void *data)
268{
269 static uint64_t p = 0;
270 struct databag *mydata = data;
271 uint64_t i;
272
273 /* TODO: Needed? */
274 memset(buf, 0, size);
275
276 switch (mydata->sample_generator) {
277 case PATTERN_SIGROK: /* sigrok pattern */
278 for (i = 0; i < size; i++) {
279 *(buf + i) = ~(pattern_sigrok[p] >> 1);
280 if (++p == 64)
281 p = 0;
282 }
283 break;
284 case PATTERN_RANDOM: /* Random */
285 for (i = 0; i < size; i++)
286 *(buf + i) = (uint8_t)(rand() & 0xff);
287 break;
288 case PATTERN_INC: /* Simple increment */
289 for (i = 0; i < size; i++)
290 *(buf + i) = i;
291 break;
292 case PATTERN_ALL_LOW: /* All probes are low */
293 memset(buf, 0x00, size);
294 break;
295 case PATTERN_ALL_HIGH: /* All probes are high */
296 memset(buf, 0xff, size);
297 break;
298 default:
299 /* TODO: Error handling. */
300 break;
301 }
302}
303
304/* Thread function */
305static void thread_func(void *data)
306{
307 struct databag *mydata = data;
308 uint8_t buf[BUFSIZE];
309 uint64_t nb_to_send = 0;
310 int bytes_written;
311 double time_cur, time_last, time_diff;
312
313 time_last = g_timer_elapsed(mydata->timer, NULL);
314
315 while (thread_running) {
316 /* Rate control */
317 time_cur = g_timer_elapsed(mydata->timer, NULL);
318
319 time_diff = time_cur - time_last;
320 time_last = time_cur;
321
322 nb_to_send = cur_samplerate * time_diff;
323
324 if (limit_samples) {
325 nb_to_send = MIN(nb_to_send,
326 limit_samples - mydata->samples_counter);
327 }
328
329 /* Make sure we don't overflow. */
330 nb_to_send = MIN(nb_to_send, BUFSIZE);
331
332 if (nb_to_send) {
333 samples_generator(buf, nb_to_send, data);
334 mydata->samples_counter += nb_to_send;
335
336 g_io_channel_write_chars(channels[1], (gchar *)&buf,
337 nb_to_send, (gsize *)&bytes_written, NULL);
338 }
339
340 /* Check if we're done. */
341 if ((limit_msec && time_cur * 1000 > limit_msec) ||
342 (limit_samples && mydata->samples_counter >= limit_samples))
343 {
344 close(mydata->pipe_fds[1]);
345 thread_running = 0;
346 }
347
348 g_usleep(10);
349 }
350}
351
352/* Callback handling data */
353static int receive_data(int fd, int revents, void *session_data)
354{
355 struct sr_datafeed_packet packet;
356 struct sr_datafeed_logic logic;
357 static uint64_t samples_received = 0;
358 unsigned char c[BUFSIZE];
359 gsize z;
360
361 /* Avoid compiler warnings. */
362 (void)fd;
363 (void)revents;
364
365 do {
366 g_io_channel_read_chars(channels[0],
367 (gchar *)&c, BUFSIZE, &z, NULL);
368
369 if (z > 0) {
370 packet.type = SR_DF_LOGIC;
371 packet.payload = &logic;
372 packet.timeoffset = samples_received * period_ps;
373 packet.duration = z * period_ps;
374 logic.length = z;
375 logic.unitsize = 1;
376 logic.data = c;
377 sr_session_bus(session_data, &packet);
378 samples_received += z;
379 }
380 } while (z > 0);
381
382 if (!thread_running && z <= 0) {
383 /* Make sure we don't receive more packets. */
384 g_io_channel_close(channels[0]);
385
386 /* Send last packet. */
387 packet.type = SR_DF_END;
388 sr_session_bus(session_data, &packet);
389
390 return FALSE;
391 }
392
393 return TRUE;
394}
395
396static int hw_start_acquisition(int device_index, gpointer session_data)
397{
398 struct sr_datafeed_packet *packet;
399 struct sr_datafeed_header *header;
400 struct databag *mydata;
401
402 /* TODO: 'mydata' is never g_free()'d? */
403 if (!(mydata = g_try_malloc(sizeof(struct databag)))) {
404 sr_err("demo: %s: mydata malloc failed", __func__);
405 return SR_ERR_MALLOC;
406 }
407
408 mydata->sample_generator = default_pattern;
409 mydata->session_data = session_data;
410 mydata->device_index = device_index;
411 mydata->samples_counter = 0;
412
413 if (pipe(mydata->pipe_fds)) {
414 /* TODO: Better error message. */
415 sr_err("demo: %s: pipe() failed", __func__);
416 return SR_ERR;
417 }
418
419 channels[0] = g_io_channel_unix_new(mydata->pipe_fds[0]);
420 channels[1] = g_io_channel_unix_new(mydata->pipe_fds[1]);
421
422 /* Set channel encoding to binary (default is UTF-8). */
423 g_io_channel_set_encoding(channels[0], NULL, NULL);
424 g_io_channel_set_encoding(channels[1], NULL, NULL);
425
426 /* Make channels to unbuffered. */
427 g_io_channel_set_buffered(channels[0], FALSE);
428 g_io_channel_set_buffered(channels[1], FALSE);
429
430 sr_source_add(mydata->pipe_fds[0], G_IO_IN | G_IO_ERR, 40,
431 receive_data, session_data);
432
433 /* Run the demo thread. */
434 g_thread_init(NULL);
435 /* This must to be done between g_thread_init() & g_thread_create(). */
436 mydata->timer = g_timer_new();
437 thread_running = 1;
438 my_thread =
439 g_thread_create((GThreadFunc)thread_func, mydata, TRUE, NULL);
440 if (!my_thread) {
441 sr_err("demo: %s: g_thread_create failed", __func__);
442 return SR_ERR; /* TODO */
443 }
444
445 if (!(packet = g_try_malloc(sizeof(struct sr_datafeed_packet)))) {
446 sr_err("demo: %s: packet malloc failed", __func__);
447 return SR_ERR_MALLOC;
448 }
449
450 if (!(header = g_try_malloc(sizeof(struct sr_datafeed_header)))) {
451 sr_err("demo: %s: header malloc failed", __func__);
452 return SR_ERR_MALLOC;
453 }
454
455 packet->type = SR_DF_HEADER;
456 packet->payload = header;
457 packet->timeoffset = 0;
458 packet->duration = 0;
459 header->feed_version = 1;
460 gettimeofday(&header->starttime, NULL);
461 header->samplerate = cur_samplerate;
462 header->num_logic_probes = NUM_PROBES;
463 header->num_analog_probes = 0;
464 sr_session_bus(session_data, packet);
465 g_free(header);
466 g_free(packet);
467
468 return SR_OK;
469}
470
471static void hw_stop_acquisition(int device_index, gpointer session_data)
472{
473 /* Avoid compiler warnings. */
474 (void)device_index;
475 (void)session_data;
476
477 /* Stop generate thread. */
478 thread_running = 0;
479}
480
481struct sr_device_plugin demo_plugin_info = {
482 .name = "demo",
483 .longname = "Demo driver and pattern generator",
484 .api_version = 1,
485 .init = hw_init,
486 .cleanup = hw_cleanup,
487 .opendev = hw_opendev,
488 .closedev = hw_closedev,
489 .get_device_info = hw_get_device_info,
490 .get_status = hw_get_status,
491 .get_capabilities = hw_get_capabilities,
492 .set_configuration = hw_set_configuration,
493 .start_acquisition = hw_start_acquisition,
494 .stop_acquisition = hw_stop_acquisition,
495};