]> sigrok.org Git - libsigrok.git/blob - hardware/demo/demo.c
sr_driver_init(): Improve checks.
[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  * Copyright (C) 2012 Alexandru Gagniuc <mr.nuke.me@gmail.com>
7  *
8  * This program is free software; you can redistribute it and/or modify
9  * it under the terms of the GNU General Public License as published by
10  * the Free Software Foundation; either version 2 of the License, or
11  * (at your option) any later version.
12  *
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with this program; if not, write to the Free Software
20  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA
21  */
22
23 #include <stdlib.h>
24 #include <unistd.h>
25 #include <string.h>
26 #ifdef _WIN32
27 #include <io.h>
28 #include <fcntl.h>
29 #define pipe(fds) _pipe(fds, 4096, _O_BINARY)
30 #endif
31 #include "libsigrok.h"
32 #include "libsigrok-internal.h"
33
34 /* Message logging helpers with driver-specific prefix string. */
35 #define DRIVER_LOG_DOMAIN "demo: "
36 #define sr_log(l, s, args...) sr_log(l, DRIVER_LOG_DOMAIN s, ## args)
37 #define sr_spew(s, args...) sr_spew(DRIVER_LOG_DOMAIN s, ## args)
38 #define sr_dbg(s, args...) sr_dbg(DRIVER_LOG_DOMAIN s, ## args)
39 #define sr_info(s, args...) sr_info(DRIVER_LOG_DOMAIN s, ## args)
40 #define sr_warn(s, args...) sr_warn(DRIVER_LOG_DOMAIN s, ## args)
41 #define sr_err(s, args...) sr_err(DRIVER_LOG_DOMAIN s, ## args)
42
43 /* TODO: Number of probes should be configurable. */
44 #define NUM_PROBES             8
45
46 #define DEMONAME               "Demo device"
47
48 /* The size of chunks to send through the session bus. */
49 /* TODO: Should be configurable. */
50 #define BUFSIZE                4096
51
52 /* Supported patterns which we can generate */
53 enum {
54         /**
55          * Pattern which spells "sigrok" using '0's (with '1's as "background")
56          * when displayed using the 'bits' output format.
57          */
58         PATTERN_SIGROK,
59
60         /** Pattern which consists of (pseudo-)random values on all probes. */
61         PATTERN_RANDOM,
62
63         /**
64          * Pattern which consists of incrementing numbers.
65          * TODO: Better description.
66          */
67         PATTERN_INC,
68
69         /** Pattern where all probes have a low logic state. */
70         PATTERN_ALL_LOW,
71
72         /** Pattern where all probes have a high logic state. */
73         PATTERN_ALL_HIGH,
74 };
75
76 /* Private, per-device-instance driver context. */
77 struct dev_context {
78         int pipe_fds[2];
79         GIOChannel *channels[2];
80         uint8_t sample_generator;
81         uint64_t samples_counter;
82         void *session_dev_id;
83         int64_t starttime;
84 };
85
86 static const int hwcaps[] = {
87         SR_CONF_LOGIC_ANALYZER,
88         SR_CONF_DEMO_DEV,
89         SR_CONF_SAMPLERATE,
90         SR_CONF_PATTERN_MODE,
91         SR_CONF_LIMIT_SAMPLES,
92         SR_CONF_LIMIT_MSEC,
93         SR_CONF_CONTINUOUS,
94 };
95
96 static const struct sr_samplerates samplerates = {
97         SR_HZ(1),
98         SR_GHZ(1),
99         SR_HZ(1),
100         NULL,
101 };
102
103 static const char *pattern_strings[] = {
104         "sigrok",
105         "random",
106         "incremental",
107         "all-low",
108         "all-high",
109         NULL,
110 };
111
112 /* We name the probes 0-7 on our demo driver. */
113 static const char *probe_names[NUM_PROBES + 1] = {
114         "0", "1", "2", "3", "4", "5", "6", "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 *di = &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
140 static int hw_dev_acquisition_stop(struct sr_dev_inst *sdi, void *cb_data);
141
142 static int clear_instances(void)
143 {
144         /* Nothing needed so far. */
145
146         return SR_OK;
147 }
148
149 static int hw_init(struct sr_context *sr_ctx)
150 {
151         struct drv_context *drvc;
152
153         if (!(drvc = g_try_malloc0(sizeof(struct drv_context)))) {
154                 sr_err("Driver context malloc failed.");
155                 return SR_ERR_MALLOC;
156         }
157
158         drvc->sr_ctx = sr_ctx;
159         di->priv = drvc;
160
161         return SR_OK;
162 }
163
164 static GSList *hw_scan(GSList *options)
165 {
166         struct sr_dev_inst *sdi;
167         struct sr_probe *probe;
168         struct drv_context *drvc;
169         GSList *devices;
170         int i;
171
172         (void)options;
173
174         drvc = di->priv;
175         devices = NULL;
176
177         sdi = sr_dev_inst_new(0, SR_ST_ACTIVE, DEMONAME, NULL, NULL);
178         if (!sdi) {
179                 sr_err("%s: sr_dev_inst_new failed", __func__);
180                 return 0;
181         }
182         sdi->driver = di;
183
184         for (i = 0; probe_names[i]; i++) {
185                 if (!(probe = sr_probe_new(i, SR_PROBE_LOGIC, TRUE,
186                                 probe_names[i])))
187                         return NULL;
188                 sdi->probes = g_slist_append(sdi->probes, probe);
189         }
190
191         devices = g_slist_append(devices, sdi);
192         drvc->instances = g_slist_append(drvc->instances, sdi);
193
194         return devices;
195 }
196
197 static GSList *hw_dev_list(void)
198 {
199         struct drv_context *drvc;
200
201         drvc = di->priv;
202
203         return drvc->instances;
204 }
205
206 static int hw_dev_open(struct sr_dev_inst *sdi)
207 {
208         (void)sdi;
209
210         /* Nothing needed so far. */
211
212         return SR_OK;
213 }
214
215 static int hw_dev_close(struct sr_dev_inst *sdi)
216 {
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 config_get(int id, const void **data, const struct sr_dev_inst *sdi)
231 {
232         (void)sdi;
233
234         switch (id) {
235         case SR_CONF_SAMPLERATE:
236                 *data = &cur_samplerate;
237                 break;
238         default:
239                 return SR_ERR_ARG;
240         }
241
242         return SR_OK;
243 }
244
245 static int config_set(int id, const void *value, const struct sr_dev_inst *sdi)
246 {
247         int ret;
248         const char *stropt;
249
250         (void)sdi;
251
252         if (id == SR_CONF_SAMPLERATE) {
253                 cur_samplerate = *(const uint64_t *)value;
254                 sr_dbg("%s: setting samplerate to %" PRIu64, __func__,
255                        cur_samplerate);
256                 ret = SR_OK;
257         } else if (id == SR_CONF_LIMIT_SAMPLES) {
258                 limit_msec = 0;
259                 limit_samples = *(const uint64_t *)value;
260                 sr_dbg("%s: setting limit_samples to %" PRIu64, __func__,
261                        limit_samples);
262                 ret = SR_OK;
263         } else if (id == SR_CONF_LIMIT_MSEC) {
264                 limit_msec = *(const uint64_t *)value;
265                 limit_samples = 0;
266                 sr_dbg("%s: setting limit_msec to %" PRIu64, __func__,
267                        limit_msec);
268                 ret = SR_OK;
269         } else if (id == SR_CONF_PATTERN_MODE) {
270                 stropt = value;
271                 ret = SR_OK;
272                 if (!strcmp(stropt, "sigrok")) {
273                         default_pattern = PATTERN_SIGROK;
274                 } else if (!strcmp(stropt, "random")) {
275                         default_pattern = PATTERN_RANDOM;
276                 } else if (!strcmp(stropt, "incremental")) {
277                         default_pattern = PATTERN_INC;
278                 } else if (!strcmp(stropt, "all-low")) {
279                         default_pattern = PATTERN_ALL_LOW;
280                 } else if (!strcmp(stropt, "all-high")) {
281                         default_pattern = PATTERN_ALL_HIGH;
282                 } else {
283                         ret = SR_ERR;
284                 }
285                 sr_dbg("%s: setting pattern to %d", __func__, default_pattern);
286         } else {
287                 ret = SR_ERR;
288         }
289
290         return ret;
291 }
292
293 static int config_list(int key, const void **data, const struct sr_dev_inst *sdi)
294 {
295
296         (void)sdi;
297
298         switch (key) {
299         case SR_CONF_DEVICE_OPTIONS:
300                 *data = hwcaps;
301                 break;
302         case SR_CONF_SAMPLERATE:
303                 *data = &samplerates;
304                 break;
305         case SR_CONF_PATTERN_MODE:
306                 *data = &pattern_strings;
307                 break;
308         default:
309                 return SR_ERR_ARG;
310         }
311
312         return SR_OK;
313 }
314
315 static void samples_generator(uint8_t *buf, uint64_t size,
316                               struct dev_context *devc)
317 {
318         static uint64_t p = 0;
319         uint64_t i;
320
321         /* TODO: Needed? */
322         memset(buf, 0, size);
323
324         switch (devc->sample_generator) {
325         case PATTERN_SIGROK: /* sigrok pattern */
326                 for (i = 0; i < size; i++) {
327                         *(buf + i) = ~(pattern_sigrok[p] >> 1);
328                         if (++p == 64)
329                                 p = 0;
330                 }
331                 break;
332         case PATTERN_RANDOM: /* Random */
333                 for (i = 0; i < size; i++)
334                         *(buf + i) = (uint8_t)(rand() & 0xff);
335                 break;
336         case PATTERN_INC: /* Simple increment */
337                 for (i = 0; i < size; i++)
338                         *(buf + i) = i;
339                 break;
340         case PATTERN_ALL_LOW: /* All probes are low */
341                 memset(buf, 0x00, size);
342                 break;
343         case PATTERN_ALL_HIGH: /* All probes are high */
344                 memset(buf, 0xff, size);
345                 break;
346         default:
347                 sr_err("Unknown pattern: %d.", devc->sample_generator);
348                 break;
349         }
350 }
351
352 /* Callback handling data */
353 static int receive_data(int fd, int revents, void *cb_data)
354 {
355         struct dev_context *devc = cb_data;
356         struct sr_datafeed_packet packet;
357         struct sr_datafeed_logic logic;
358         uint8_t buf[BUFSIZE];
359         static uint64_t samples_to_send, expected_samplenum, sending_now;
360         int64_t time, elapsed;
361
362         (void)fd;
363         (void)revents;
364
365         /* How many "virtual" samples should we have collected by now? */
366         time = g_get_monotonic_time();
367         elapsed = time - devc->starttime;
368         expected_samplenum = elapsed * cur_samplerate / 1000000;
369         /* Of those, how many do we still have to send? */
370         samples_to_send = expected_samplenum - devc->samples_counter;
371
372         if (limit_samples) {
373                 samples_to_send = MIN(samples_to_send,
374                                  limit_samples - devc->samples_counter);
375         }
376
377         while (samples_to_send > 0) {
378                 sending_now = MIN(samples_to_send, sizeof(buf));
379                 samples_to_send -= sending_now;
380                 samples_generator(buf, sending_now, devc);
381
382                 packet.type = SR_DF_LOGIC;
383                 packet.payload = &logic;
384                 logic.length = sending_now;
385                 logic.unitsize = 1;
386                 logic.data = buf;
387                 sr_session_send(devc->session_dev_id, &packet);
388                 devc->samples_counter += sending_now;
389         }
390
391         if (limit_samples && devc->samples_counter >= limit_samples) {
392                 sr_info("Requested number of samples reached.");
393                 hw_dev_acquisition_stop(NULL, cb_data);
394                 return TRUE;
395         }
396
397         return TRUE;
398 }
399
400 static int hw_dev_acquisition_start(const struct sr_dev_inst *sdi,
401                 void *cb_data)
402 {
403         struct sr_datafeed_packet *packet;
404         struct sr_datafeed_header *header;
405         struct dev_context *devc;
406
407         (void)sdi;
408
409         sr_dbg("Starting acquisition.");
410
411         /* TODO: 'devc' is never g_free()'d? */
412         if (!(devc = g_try_malloc(sizeof(struct dev_context)))) {
413                 sr_err("%s: devc malloc failed", __func__);
414                 return SR_ERR_MALLOC;
415         }
416
417         devc->sample_generator = default_pattern;
418         devc->session_dev_id = cb_data;
419         devc->samples_counter = 0;
420
421         /*
422          * Setting two channels connected by a pipe is a remnant from when the
423          * demo driver generated data in a thread, and collected and sent the
424          * data in the main program loop.
425          * They are kept here because it provides a convenient way of setting
426          * up a timeout-based polling mechanism.
427          */
428         if (pipe(devc->pipe_fds)) {
429                 /* TODO: Better error message. */
430                 sr_err("%s: pipe() failed", __func__);
431                 return SR_ERR;
432         }
433
434         devc->channels[0] = g_io_channel_unix_new(devc->pipe_fds[0]);
435         devc->channels[1] = g_io_channel_unix_new(devc->pipe_fds[1]);
436
437         g_io_channel_set_flags(devc->channels[0], G_IO_FLAG_NONBLOCK, NULL);
438
439         /* Set channel encoding to binary (default is UTF-8). */
440         g_io_channel_set_encoding(devc->channels[0], NULL, NULL);
441         g_io_channel_set_encoding(devc->channels[1], NULL, NULL);
442
443         /* Make channels to unbuffered. */
444         g_io_channel_set_buffered(devc->channels[0], FALSE);
445         g_io_channel_set_buffered(devc->channels[1], FALSE);
446
447         sr_session_source_add_channel(devc->channels[0], G_IO_IN | G_IO_ERR,
448                     40, receive_data, devc);
449
450         if (!(packet = g_try_malloc(sizeof(struct sr_datafeed_packet)))) {
451                 sr_err("%s: packet malloc failed", __func__);
452                 return SR_ERR_MALLOC;
453         }
454
455         if (!(header = g_try_malloc(sizeof(struct sr_datafeed_header)))) {
456                 sr_err("%s: header malloc failed", __func__);
457                 return SR_ERR_MALLOC;
458         }
459
460         packet->type = SR_DF_HEADER;
461         packet->payload = header;
462         header->feed_version = 1;
463         gettimeofday(&header->starttime, NULL);
464         sr_session_send(devc->session_dev_id, packet);
465
466         /* We use this timestamp to decide how many more samples to send. */
467         devc->starttime = g_get_monotonic_time();
468
469         g_free(header);
470         g_free(packet);
471
472         return SR_OK;
473 }
474
475 static int hw_dev_acquisition_stop(struct sr_dev_inst *sdi, void *cb_data)
476 {
477         struct dev_context *devc;
478         struct sr_datafeed_packet packet;
479
480         (void)sdi;
481
482         devc = cb_data;
483
484         sr_dbg("Stopping aquisition.");
485
486         sr_session_source_remove_channel(devc->channels[0]);
487         g_io_channel_shutdown(devc->channels[0], FALSE, NULL);
488
489         /* Send last packet. */
490         packet.type = SR_DF_END;
491         sr_session_send(devc->session_dev_id, &packet);
492
493         return SR_OK;
494 }
495
496 SR_PRIV struct sr_dev_driver demo_driver_info = {
497         .name = "demo",
498         .longname = "Demo driver and pattern generator",
499         .api_version = 1,
500         .init = hw_init,
501         .cleanup = hw_cleanup,
502         .scan = hw_scan,
503         .dev_list = hw_dev_list,
504         .dev_clear = clear_instances,
505         .config_get = config_get,
506         .config_set = config_set,
507         .config_list = config_list,
508         .dev_open = hw_dev_open,
509         .dev_close = hw_dev_close,
510         .dev_acquisition_start = hw_dev_acquisition_start,
511         .dev_acquisition_stop = hw_dev_acquisition_stop,
512         .priv = NULL,
513 };