]> sigrok.org Git - libsigrok.git/blob - hardware/demo/demo.c
sr/drivers: add API calls sr_dev_inst_list() and sr_dev_inst_clear()
[libsigrok.git] / hardware / demo / demo.c
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 "libsigrok.h"
31 #include "libsigrok-internal.h"
32
33 /* TODO: Number of probes should be configurable. */
34 #define NUM_PROBES             8
35
36 #define DEMONAME               "Demo device"
37
38 /* The size of chunks to send through the session bus. */
39 /* TODO: Should be configurable. */
40 #define BUFSIZE                4096
41
42 /* Supported patterns which we can generate */
43 enum {
44         /**
45          * Pattern which spells "sigrok" using '0's (with '1's as "background")
46          * when displayed using the 'bits' output format.
47          */
48         PATTERN_SIGROK,
49
50         /** Pattern which consists of (pseudo-)random values on all probes. */
51         PATTERN_RANDOM,
52
53         /**
54          * Pattern which consists of incrementing numbers.
55          * TODO: Better description.
56          */
57         PATTERN_INC,
58
59         /** Pattern where all probes have a low logic state. */
60         PATTERN_ALL_LOW,
61
62         /** Pattern where all probes have a high logic state. */
63         PATTERN_ALL_HIGH,
64 };
65
66 /* FIXME: Should not be global. */
67
68 /* Private driver context. */
69 struct drv_context {
70         GSList *instances;
71 };
72
73 /* Private, per-device-instance driver context. */
74 struct dev_context {
75         int pipe_fds[2];
76         GIOChannel *channels[2];
77         uint8_t sample_generator;
78         uint8_t thread_running;
79         uint64_t samples_counter;
80         void *session_dev_id;
81         GTimer *timer;
82 };
83
84 static const int hwcaps[] = {
85         SR_HWCAP_LOGIC_ANALYZER,
86         SR_HWCAP_DEMO_DEV,
87         SR_HWCAP_SAMPLERATE,
88         SR_HWCAP_PATTERN_MODE,
89         SR_HWCAP_LIMIT_SAMPLES,
90         SR_HWCAP_LIMIT_MSEC,
91         SR_HWCAP_CONTINUOUS,
92 };
93
94 static const struct sr_samplerates samplerates = {
95         SR_HZ(1),
96         SR_GHZ(1),
97         SR_HZ(1),
98         NULL,
99 };
100
101 static const char *pattern_strings[] = {
102         "sigrok",
103         "random",
104         "incremental",
105         "all-low",
106         "all-high",
107         NULL,
108 };
109
110 /* We name the probes 0-7 on our demo driver. */
111 static const char *probe_names[NUM_PROBES + 1] = {
112         "0",
113         "1",
114         "2",
115         "3",
116         "4",
117         "5",
118         "6",
119         "7",
120         NULL,
121 };
122
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,
132 };
133
134 /* Private, per-device-instance driver context. */
135 /* TODO: struct context as with the other drivers. */
136
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;
146
147 static int hw_dev_acquisition_stop(const struct sr_dev_inst *sdi,
148                 void *cb_data);
149
150 static int hw_init(void)
151 {
152         struct drv_context *drvc;
153
154         if (!(drvc = g_try_malloc0(sizeof(struct drv_context)))) {
155                 sr_err("fx2lafw: driver context malloc failed.");
156                 return SR_ERR;
157         }
158         ddi->priv = drvc;
159
160         return SR_OK;
161 }
162
163 static GSList *hw_scan(GSList *options)
164 {
165         struct sr_dev_inst *sdi;
166         struct sr_probe *probe;
167         struct drv_context *drvc;
168         GSList *devices;
169         int i;
170
171         (void)options;
172         drvc = ddi->priv;
173         devices = NULL;
174
175         sdi = sr_dev_inst_new(0, SR_ST_ACTIVE, DEMONAME, NULL, NULL);
176         if (!sdi) {
177                 sr_err("demo: %s: sr_dev_inst_new failed", __func__);
178                 return 0;
179         }
180         sdi->driver = ddi;
181
182         for (i = 0; probe_names[i]; i++) {
183                 if (!(probe = sr_probe_new(i, SR_PROBE_ANALOG, TRUE,
184                                 probe_names[i])))
185                         return NULL;
186                 sdi->probes = g_slist_append(sdi->probes, probe);
187         }
188
189         devices = g_slist_append(devices, sdi);
190         drvc->instances = g_slist_append(drvc->instances, sdi);
191
192         return devices;
193 }
194
195 static GSList *hw_dev_list(void)
196 {
197         struct drv_context *drvc;
198
199         drvc = ddi->priv;
200
201         return drvc->instances;
202 }
203
204 static int hw_dev_open(struct sr_dev_inst *sdi)
205 {
206         /* Avoid compiler warnings. */
207         (void)sdi;
208
209         /* Nothing needed so far. */
210
211         return SR_OK;
212 }
213
214 static int hw_dev_close(struct sr_dev_inst *sdi)
215 {
216         /* Avoid compiler warnings. */
217         (void)sdi;
218
219         /* Nothing needed so far. */
220
221         return SR_OK;
222 }
223
224 static int hw_cleanup(void)
225 {
226         /* Nothing needed so far. */
227         return SR_OK;
228 }
229
230 static int hw_info_get(int info_id, const void **data,
231        const struct sr_dev_inst *sdi)
232 {
233
234         (void)sdi;
235
236         switch (info_id) {
237         case SR_DI_HWCAPS:
238                 *data = hwcaps;
239                 break;
240         case SR_DI_NUM_PROBES:
241                 *data = GINT_TO_POINTER(NUM_PROBES);
242                 break;
243         case SR_DI_PROBE_NAMES:
244                 *data = probe_names;
245                 break;
246         case SR_DI_SAMPLERATES:
247                 *data = &samplerates;
248                 break;
249         case SR_DI_CUR_SAMPLERATE:
250                 *data = &cur_samplerate;
251                 break;
252         case SR_DI_PATTERNS:
253                 *data = &pattern_strings;
254                 break;
255         default:
256                 return SR_ERR_ARG;
257         }
258
259         return SR_OK;
260 }
261
262 static int hw_dev_config_set(const struct sr_dev_inst *sdi, int hwcap,
263                 const void *value)
264 {
265         int ret;
266         const char *stropt;
267
268         (void)sdi;
269
270         if (hwcap == SR_HWCAP_SAMPLERATE) {
271                 cur_samplerate = *(const uint64_t *)value;
272                 sr_dbg("demo: %s: setting samplerate to %" PRIu64, __func__,
273                        cur_samplerate);
274                 ret = SR_OK;
275         } else if (hwcap == SR_HWCAP_LIMIT_SAMPLES) {
276                 limit_msec = 0;
277                 limit_samples = *(const uint64_t *)value;
278                 sr_dbg("demo: %s: setting limit_samples to %" PRIu64, __func__,
279                        limit_samples);
280                 ret = SR_OK;
281         } else if (hwcap == SR_HWCAP_LIMIT_MSEC) {
282                 limit_msec = *(const uint64_t *)value;
283                 limit_samples = 0;
284                 sr_dbg("demo: %s: setting limit_msec to %" PRIu64, __func__,
285                        limit_msec);
286                 ret = SR_OK;
287         } else if (hwcap == SR_HWCAP_PATTERN_MODE) {
288                 stropt = value;
289                 ret = SR_OK;
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;
300                 } else {
301                         ret = SR_ERR;
302                 }
303                 sr_dbg("demo: %s: setting pattern to %d", __func__,
304                        default_pattern);
305         } else {
306                 ret = SR_ERR;
307         }
308
309         return ret;
310 }
311
312 static void samples_generator(uint8_t *buf, uint64_t size, void *data)
313 {
314         static uint64_t p = 0;
315         struct dev_context *devc = data;
316         uint64_t i;
317
318         /* TODO: Needed? */
319         memset(buf, 0, size);
320
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);
325                         if (++p == 64)
326                                 p = 0;
327                 }
328                 break;
329         case PATTERN_RANDOM: /* Random */
330                 for (i = 0; i < size; i++)
331                         *(buf + i) = (uint8_t)(rand() & 0xff);
332                 break;
333         case PATTERN_INC: /* Simple increment */
334                 for (i = 0; i < size; i++)
335                         *(buf + i) = i;
336                 break;
337         case PATTERN_ALL_LOW: /* All probes are low */
338                 memset(buf, 0x00, size);
339                 break;
340         case PATTERN_ALL_HIGH: /* All probes are high */
341                 memset(buf, 0xff, size);
342                 break;
343         default:
344                 sr_err("demo: %s: unknown pattern %d", __func__,
345                        devc->sample_generator);
346                 break;
347         }
348 }
349
350 /* Thread function */
351 static void thread_func(void *data)
352 {
353         struct dev_context *devc = data;
354         uint8_t buf[BUFSIZE];
355         uint64_t nb_to_send = 0;
356         int bytes_written;
357         double time_cur, time_last, time_diff;
358
359         time_last = g_timer_elapsed(devc->timer, NULL);
360
361         while (thread_running) {
362                 /* Rate control */
363                 time_cur = g_timer_elapsed(devc->timer, NULL);
364
365                 time_diff = time_cur - time_last;
366                 time_last = time_cur;
367
368                 nb_to_send = cur_samplerate * time_diff;
369
370                 if (limit_samples) {
371                         nb_to_send = MIN(nb_to_send,
372                                       limit_samples - devc->samples_counter);
373                 }
374
375                 /* Make sure we don't overflow. */
376                 nb_to_send = MIN(nb_to_send, BUFSIZE);
377
378                 if (nb_to_send) {
379                         samples_generator(buf, nb_to_send, data);
380                         devc->samples_counter += nb_to_send;
381
382                         g_io_channel_write_chars(devc->channels[1], (gchar *)&buf,
383                                 nb_to_send, (gsize *)&bytes_written, NULL);
384                 }
385
386                 /* Check if we're done. */
387                 if ((limit_msec && time_cur * 1000 > limit_msec) ||
388                     (limit_samples && devc->samples_counter >= limit_samples))
389                 {
390                         close(devc->pipe_fds[1]);
391                         thread_running = 0;
392                 }
393
394                 g_usleep(10);
395         }
396 }
397
398 /* Callback handling data */
399 static int receive_data(int fd, int revents, void *cb_data)
400 {
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];
406         gsize z;
407
408         /* Avoid compiler warnings. */
409         (void)fd;
410         (void)revents;
411
412         do {
413                 g_io_channel_read_chars(devc->channels[0],
414                                         (gchar *)&c, BUFSIZE, &z, NULL);
415
416                 if (z > 0) {
417                         packet.type = SR_DF_LOGIC;
418                         packet.payload = &logic;
419                         logic.length = z;
420                         logic.unitsize = 1;
421                         logic.data = c;
422                         sr_session_send(devc->session_dev_id, &packet);
423                         samples_received += z;
424                 }
425         } while (z > 0);
426
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);
430
431                 /* Send last packet. */
432                 packet.type = SR_DF_END;
433                 sr_session_send(devc->session_dev_id, &packet);
434
435                 return FALSE;
436         }
437
438         return TRUE;
439 }
440
441 static int hw_dev_acquisition_start(const struct sr_dev_inst *sdi,
442                 void *cb_data)
443 {
444         struct sr_datafeed_packet *packet;
445         struct sr_datafeed_header *header;
446         struct sr_datafeed_meta_logic meta;
447         struct dev_context *devc;
448
449         (void)sdi;
450
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;
455         }
456
457         devc->sample_generator = default_pattern;
458         devc->session_dev_id = cb_data;
459         devc->samples_counter = 0;
460
461         if (pipe(devc->pipe_fds)) {
462                 /* TODO: Better error message. */
463                 sr_err("demo: %s: pipe() failed", __func__);
464                 return SR_ERR;
465         }
466
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]);
469
470         g_io_channel_set_flags(devc->channels[0], G_IO_FLAG_NONBLOCK, NULL);
471
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);
475
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);
479
480         sr_session_source_add_channel(devc->channels[0], G_IO_IN | G_IO_ERR,
481                     40, receive_data, devc);
482
483         /* Run the demo thread. */
484         g_thread_init(NULL);
485         /* This must to be done between g_thread_init() & g_thread_create(). */
486         devc->timer = g_timer_new();
487         thread_running = 1;
488         my_thread =
489             g_thread_create((GThreadFunc)thread_func, devc, TRUE, NULL);
490         if (!my_thread) {
491                 sr_err("demo: %s: g_thread_create failed", __func__);
492                 return SR_ERR; /* TODO */
493         }
494
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;
498         }
499
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;
503         }
504
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);
510
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);
517
518         g_free(header);
519         g_free(packet);
520
521         return SR_OK;
522 }
523
524 static int hw_dev_acquisition_stop(const struct sr_dev_inst *sdi,
525                 void *cb_data)
526 {
527         struct dev_context *devc;
528
529         /* Avoid compiler warnings. */
530         (void)cb_data;
531
532         devc = sdi->priv;
533
534         /* Stop generate thread. */
535         thread_running = 0;
536
537         sr_session_source_remove_channel(devc->channels[0]);
538
539         return SR_OK;
540 }
541
542 SR_PRIV struct sr_dev_driver demo_driver_info = {
543         .name = "demo",
544         .longname = "Demo driver and pattern generator",
545         .api_version = 1,
546         .init = hw_init,
547         .cleanup = hw_cleanup,
548         .scan = hw_scan,
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,
556         .priv = NULL,
557 };