]> sigrok.org Git - libsigrok.git/blob - hardware/demo/demo.c
demo: scan/info_get fixes
[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 struct context {
69         int pipe_fds[2];
70         GIOChannel *channels[2];
71         uint8_t sample_generator;
72         uint8_t thread_running;
73         uint64_t samples_counter;
74         int dev_index;
75         void *session_dev_id;
76         GTimer *timer;
77 };
78
79 static const int hwcaps[] = {
80         SR_HWCAP_LOGIC_ANALYZER,
81         SR_HWCAP_DEMO_DEV,
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
89 static const struct sr_samplerates samplerates = {
90         SR_HZ(1),
91         SR_GHZ(1),
92         SR_HZ(1),
93         NULL,
94 };
95
96 static const char *pattern_strings[] = {
97         "sigrok",
98         "random",
99         "incremental",
100         "all-low",
101         "all-high",
102         NULL,
103 };
104
105 /* We name the probes 0-7 on our demo driver. */
106 static const char *probe_names[NUM_PROBES + 1] = {
107         "0",
108         "1",
109         "2",
110         "3",
111         "4",
112         "5",
113         "6",
114         "7",
115         NULL,
116 };
117
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,
127 };
128
129 /* Private, per-device-instance driver context. */
130 /* TODO: struct context as with the other drivers. */
131
132 /* List of struct sr_dev_inst, maintained by dev_open()/dev_close(). */
133 SR_PRIV struct sr_dev_driver demo_driver_info;
134 static struct sr_dev_driver *ddi = &demo_driver_info;
135 static uint64_t cur_samplerate = SR_KHZ(200);
136 static uint64_t limit_samples = 0;
137 static uint64_t limit_msec = 0;
138 static int default_pattern = PATTERN_SIGROK;
139 static GThread *my_thread;
140 static int thread_running;
141
142 static int hw_dev_acquisition_stop(int dev_index, void *cb_data);
143
144 static int hw_init(void)
145 {
146
147         /* Nothing to do. */
148
149         return SR_OK;
150 }
151
152 static GSList *hw_scan(GSList *options)
153 {
154         struct sr_dev_inst *sdi;
155         GSList *devices;
156
157         (void)options;
158         devices = NULL;
159
160         sdi = sr_dev_inst_new(0, SR_ST_ACTIVE, DEMONAME, NULL, NULL);
161         if (!sdi) {
162                 sr_err("demo: %s: sr_dev_inst_new failed", __func__);
163                 return 0;
164         }
165         sdi->driver = ddi;
166
167         devices = g_slist_append(devices, sdi);
168         ddi->instances = g_slist_append(ddi->instances, sdi);
169
170         return devices;
171 }
172
173 static int hw_dev_open(int dev_index)
174 {
175         /* Avoid compiler warnings. */
176         (void)dev_index;
177
178         /* Nothing needed so far. */
179
180         return SR_OK;
181 }
182
183 static int hw_dev_close(int dev_index)
184 {
185         /* Avoid compiler warnings. */
186         (void)dev_index;
187
188         /* Nothing needed so far. */
189
190         return SR_OK;
191 }
192
193 static int hw_cleanup(void)
194 {
195         /* Nothing needed so far. */
196         return SR_OK;
197 }
198
199 static int hw_info_get(int info_id, const void **data,
200        const struct sr_dev_inst *sdi)
201 {
202
203         switch (info_id) {
204         case SR_DI_INST:
205                 *data = sdi;
206                 break;
207         case SR_DI_NUM_PROBES:
208                 *data = GINT_TO_POINTER(NUM_PROBES);
209                 break;
210         case SR_DI_PROBE_NAMES:
211                 *data = probe_names;
212                 break;
213         case SR_DI_SAMPLERATES:
214                 *data = &samplerates;
215                 break;
216         case SR_DI_CUR_SAMPLERATE:
217                 *data = &cur_samplerate;
218                 break;
219         case SR_DI_PATTERNS:
220                 *data = &pattern_strings;
221                 break;
222         default:
223                 return SR_ERR_ARG;
224         }
225
226         return SR_OK;
227 }
228
229 static int hw_dev_status_get(int dev_index)
230 {
231         /* Avoid compiler warnings. */
232         (void)dev_index;
233
234         return SR_ST_ACTIVE;
235 }
236
237 static const int *hw_hwcap_get_all(void)
238 {
239         return hwcaps;
240 }
241
242 static int hw_dev_config_set(int dev_index, int hwcap, const void *value)
243 {
244         int ret;
245         const char *stropt;
246
247         /* Avoid compiler warnings. */
248         (void)dev_index;
249
250         if (hwcap == SR_HWCAP_PROBECONFIG) {
251                 /* Nothing to do, but must be supported */
252                 ret = SR_OK;
253         } else if (hwcap == SR_HWCAP_SAMPLERATE) {
254                 cur_samplerate = *(const uint64_t *)value;
255                 sr_dbg("demo: %s: setting samplerate to %" PRIu64, __func__,
256                        cur_samplerate);
257                 ret = SR_OK;
258         } else if (hwcap == SR_HWCAP_LIMIT_SAMPLES) {
259                 limit_msec = 0;
260                 limit_samples = *(const uint64_t *)value;
261                 sr_dbg("demo: %s: setting limit_samples to %" PRIu64, __func__,
262                        limit_samples);
263                 ret = SR_OK;
264         } else if (hwcap == SR_HWCAP_LIMIT_MSEC) {
265                 limit_msec = *(const uint64_t *)value;
266                 limit_samples = 0;
267                 sr_dbg("demo: %s: setting limit_msec to %" PRIu64, __func__,
268                        limit_msec);
269                 ret = SR_OK;
270         } else if (hwcap == SR_HWCAP_PATTERN_MODE) {
271                 stropt = value;
272                 ret = SR_OK;
273                 if (!strcmp(stropt, "sigrok")) {
274                         default_pattern = PATTERN_SIGROK;
275                 } else if (!strcmp(stropt, "random")) {
276                         default_pattern = PATTERN_RANDOM;
277                 } else if (!strcmp(stropt, "incremental")) {
278                         default_pattern = PATTERN_INC;
279                 } else if (!strcmp(stropt, "all-low")) {
280                         default_pattern = PATTERN_ALL_LOW;
281                 } else if (!strcmp(stropt, "all-high")) {
282                         default_pattern = PATTERN_ALL_HIGH;
283                 } else {
284                         ret = SR_ERR;
285                 }
286                 sr_dbg("demo: %s: setting pattern to %d", __func__,
287                        default_pattern);
288         } else {
289                 ret = SR_ERR;
290         }
291
292         return ret;
293 }
294
295 static void samples_generator(uint8_t *buf, uint64_t size, void *data)
296 {
297         static uint64_t p = 0;
298         struct context *ctx = data;
299         uint64_t i;
300
301         /* TODO: Needed? */
302         memset(buf, 0, size);
303
304         switch (ctx->sample_generator) {
305         case PATTERN_SIGROK: /* sigrok pattern */
306                 for (i = 0; i < size; i++) {
307                         *(buf + i) = ~(pattern_sigrok[p] >> 1);
308                         if (++p == 64)
309                                 p = 0;
310                 }
311                 break;
312         case PATTERN_RANDOM: /* Random */
313                 for (i = 0; i < size; i++)
314                         *(buf + i) = (uint8_t)(rand() & 0xff);
315                 break;
316         case PATTERN_INC: /* Simple increment */
317                 for (i = 0; i < size; i++)
318                         *(buf + i) = i;
319                 break;
320         case PATTERN_ALL_LOW: /* All probes are low */
321                 memset(buf, 0x00, size);
322                 break;
323         case PATTERN_ALL_HIGH: /* All probes are high */
324                 memset(buf, 0xff, size);
325                 break;
326         default:
327                 sr_err("demo: %s: unknown pattern %d", __func__,
328                        ctx->sample_generator);
329                 break;
330         }
331 }
332
333 /* Thread function */
334 static void thread_func(void *data)
335 {
336         struct context *ctx = data;
337         uint8_t buf[BUFSIZE];
338         uint64_t nb_to_send = 0;
339         int bytes_written;
340         double time_cur, time_last, time_diff;
341
342         time_last = g_timer_elapsed(ctx->timer, NULL);
343
344         while (thread_running) {
345                 /* Rate control */
346                 time_cur = g_timer_elapsed(ctx->timer, NULL);
347
348                 time_diff = time_cur - time_last;
349                 time_last = time_cur;
350
351                 nb_to_send = cur_samplerate * time_diff;
352
353                 if (limit_samples) {
354                         nb_to_send = MIN(nb_to_send,
355                                       limit_samples - ctx->samples_counter);
356                 }
357
358                 /* Make sure we don't overflow. */
359                 nb_to_send = MIN(nb_to_send, BUFSIZE);
360
361                 if (nb_to_send) {
362                         samples_generator(buf, nb_to_send, data);
363                         ctx->samples_counter += nb_to_send;
364
365                         g_io_channel_write_chars(ctx->channels[1], (gchar *)&buf,
366                                 nb_to_send, (gsize *)&bytes_written, NULL);
367                 }
368
369                 /* Check if we're done. */
370                 if ((limit_msec && time_cur * 1000 > limit_msec) ||
371                     (limit_samples && ctx->samples_counter >= limit_samples))
372                 {
373                         close(ctx->pipe_fds[1]);
374                         thread_running = 0;
375                 }
376
377                 g_usleep(10);
378         }
379 }
380
381 /* Callback handling data */
382 static int receive_data(int fd, int revents, void *cb_data)
383 {
384         struct context *ctx = cb_data;
385         struct sr_datafeed_packet packet;
386         struct sr_datafeed_logic logic;
387         static uint64_t samples_received = 0;
388         unsigned char c[BUFSIZE];
389         gsize z;
390
391         /* Avoid compiler warnings. */
392         (void)fd;
393         (void)revents;
394
395         do {
396                 g_io_channel_read_chars(ctx->channels[0],
397                                         (gchar *)&c, BUFSIZE, &z, NULL);
398
399                 if (z > 0) {
400                         packet.type = SR_DF_LOGIC;
401                         packet.payload = &logic;
402                         logic.length = z;
403                         logic.unitsize = 1;
404                         logic.data = c;
405                         sr_session_send(ctx->session_dev_id, &packet);
406                         samples_received += z;
407                 }
408         } while (z > 0);
409
410         if (!thread_running && z <= 0) {
411                 /* Make sure we don't receive more packets. */
412                 g_io_channel_shutdown(ctx->channels[0], FALSE, NULL);
413
414                 /* Send last packet. */
415                 packet.type = SR_DF_END;
416                 sr_session_send(ctx->session_dev_id, &packet);
417
418                 return FALSE;
419         }
420
421         return TRUE;
422 }
423
424 static int hw_dev_acquisition_start(int dev_index, void *cb_data)
425 {
426         struct sr_datafeed_packet *packet;
427         struct sr_datafeed_header *header;
428         struct sr_datafeed_meta_logic meta;
429         struct context *ctx;
430
431         /* TODO: 'ctx' is never g_free()'d? */
432         if (!(ctx = g_try_malloc(sizeof(struct context)))) {
433                 sr_err("demo: %s: ctx malloc failed", __func__);
434                 return SR_ERR_MALLOC;
435         }
436
437         ctx->sample_generator = default_pattern;
438         ctx->session_dev_id = cb_data;
439         ctx->dev_index = dev_index;
440         ctx->samples_counter = 0;
441
442         if (pipe(ctx->pipe_fds)) {
443                 /* TODO: Better error message. */
444                 sr_err("demo: %s: pipe() failed", __func__);
445                 return SR_ERR;
446         }
447
448         ctx->channels[0] = g_io_channel_unix_new(ctx->pipe_fds[0]);
449         ctx->channels[1] = g_io_channel_unix_new(ctx->pipe_fds[1]);
450
451         g_io_channel_set_flags(ctx->channels[0], G_IO_FLAG_NONBLOCK, NULL);
452
453         /* Set channel encoding to binary (default is UTF-8). */
454         g_io_channel_set_encoding(ctx->channels[0], NULL, NULL);
455         g_io_channel_set_encoding(ctx->channels[1], NULL, NULL);
456
457         /* Make channels to unbuffered. */
458         g_io_channel_set_buffered(ctx->channels[0], FALSE);
459         g_io_channel_set_buffered(ctx->channels[1], FALSE);
460
461         sr_session_source_add_channel(ctx->channels[0], G_IO_IN | G_IO_ERR,
462                     40, receive_data, ctx);
463
464         /* Run the demo thread. */
465         g_thread_init(NULL);
466         /* This must to be done between g_thread_init() & g_thread_create(). */
467         ctx->timer = g_timer_new();
468         thread_running = 1;
469         my_thread =
470             g_thread_create((GThreadFunc)thread_func, ctx, TRUE, NULL);
471         if (!my_thread) {
472                 sr_err("demo: %s: g_thread_create failed", __func__);
473                 return SR_ERR; /* TODO */
474         }
475
476         if (!(packet = g_try_malloc(sizeof(struct sr_datafeed_packet)))) {
477                 sr_err("demo: %s: packet malloc failed", __func__);
478                 return SR_ERR_MALLOC;
479         }
480
481         if (!(header = g_try_malloc(sizeof(struct sr_datafeed_header)))) {
482                 sr_err("demo: %s: header malloc failed", __func__);
483                 return SR_ERR_MALLOC;
484         }
485
486         packet->type = SR_DF_HEADER;
487         packet->payload = header;
488         header->feed_version = 1;
489         gettimeofday(&header->starttime, NULL);
490         sr_session_send(ctx->session_dev_id, packet);
491
492         /* Send metadata about the SR_DF_LOGIC packets to come. */
493         packet->type = SR_DF_META_LOGIC;
494         packet->payload = &meta;
495         meta.samplerate = cur_samplerate;
496         meta.num_probes = NUM_PROBES;
497         sr_session_send(ctx->session_dev_id, packet);
498
499         g_free(header);
500         g_free(packet);
501
502         return SR_OK;
503 }
504
505 /* TODO: This stops acquisition on ALL devices, ignoring dev_index. */
506 static int hw_dev_acquisition_stop(int dev_index, void *cb_data)
507 {
508         /* Avoid compiler warnings. */
509         (void)dev_index;
510         (void)cb_data;
511
512         /* Stop generate thread. */
513         thread_running = 0;
514
515         return SR_OK;
516 }
517
518 SR_PRIV struct sr_dev_driver demo_driver_info = {
519         .name = "demo",
520         .longname = "Demo driver and pattern generator",
521         .api_version = 1,
522         .init = hw_init,
523         .cleanup = hw_cleanup,
524         .scan = hw_scan,
525         .dev_open = hw_dev_open,
526         .dev_close = hw_dev_close,
527         .info_get = hw_info_get,
528         .dev_status_get = hw_dev_status_get,
529 //      .hwcap_get_all = hw_hwcap_get_all,
530         .dev_config_set = hw_dev_config_set,
531         .dev_acquisition_start = hw_dev_acquisition_start,
532         .dev_acquisition_stop = hw_dev_acquisition_stop,
533         .instances = NULL,
534 };