]> sigrok.org Git - libsigrok.git/blob - hardware/demo/demo.c
Factor out common hw_init() driver code.
[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         return std_hw_init(sr_ctx, di, DRIVER_LOG_DOMAIN);
152 }
153
154 static GSList *hw_scan(GSList *options)
155 {
156         struct sr_dev_inst *sdi;
157         struct sr_probe *probe;
158         struct drv_context *drvc;
159         GSList *devices;
160         int i;
161
162         (void)options;
163
164         drvc = di->priv;
165
166         devices = NULL;
167
168         sdi = sr_dev_inst_new(0, SR_ST_ACTIVE, DEMONAME, NULL, NULL);
169         if (!sdi) {
170                 sr_err("%s: sr_dev_inst_new failed", __func__);
171                 return 0;
172         }
173         sdi->driver = di;
174
175         for (i = 0; probe_names[i]; i++) {
176                 if (!(probe = sr_probe_new(i, SR_PROBE_LOGIC, TRUE,
177                                 probe_names[i])))
178                         return NULL;
179                 sdi->probes = g_slist_append(sdi->probes, probe);
180         }
181
182         devices = g_slist_append(devices, sdi);
183         drvc->instances = g_slist_append(drvc->instances, sdi);
184
185         return devices;
186 }
187
188 static GSList *hw_dev_list(void)
189 {
190         struct drv_context *drvc;
191
192         drvc = di->priv;
193
194         return drvc->instances;
195 }
196
197 static int hw_dev_open(struct sr_dev_inst *sdi)
198 {
199         (void)sdi;
200
201         /* Nothing needed so far. */
202
203         return SR_OK;
204 }
205
206 static int hw_dev_close(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_cleanup(void)
216 {
217         /* Nothing needed so far. */
218         return SR_OK;
219 }
220
221 static int config_get(int id, const void **data, const struct sr_dev_inst *sdi)
222 {
223         (void)sdi;
224
225         switch (id) {
226         case SR_CONF_SAMPLERATE:
227                 *data = &cur_samplerate;
228                 break;
229         default:
230                 return SR_ERR_ARG;
231         }
232
233         return SR_OK;
234 }
235
236 static int config_set(int id, const void *value, const struct sr_dev_inst *sdi)
237 {
238         int ret;
239         const char *stropt;
240
241         (void)sdi;
242
243         if (id == SR_CONF_SAMPLERATE) {
244                 cur_samplerate = *(const uint64_t *)value;
245                 sr_dbg("%s: setting samplerate to %" PRIu64, __func__,
246                        cur_samplerate);
247                 ret = SR_OK;
248         } else if (id == SR_CONF_LIMIT_SAMPLES) {
249                 limit_msec = 0;
250                 limit_samples = *(const uint64_t *)value;
251                 sr_dbg("%s: setting limit_samples to %" PRIu64, __func__,
252                        limit_samples);
253                 ret = SR_OK;
254         } else if (id == SR_CONF_LIMIT_MSEC) {
255                 limit_msec = *(const uint64_t *)value;
256                 limit_samples = 0;
257                 sr_dbg("%s: setting limit_msec to %" PRIu64, __func__,
258                        limit_msec);
259                 ret = SR_OK;
260         } else if (id == SR_CONF_PATTERN_MODE) {
261                 stropt = value;
262                 ret = SR_OK;
263                 if (!strcmp(stropt, "sigrok")) {
264                         default_pattern = PATTERN_SIGROK;
265                 } else if (!strcmp(stropt, "random")) {
266                         default_pattern = PATTERN_RANDOM;
267                 } else if (!strcmp(stropt, "incremental")) {
268                         default_pattern = PATTERN_INC;
269                 } else if (!strcmp(stropt, "all-low")) {
270                         default_pattern = PATTERN_ALL_LOW;
271                 } else if (!strcmp(stropt, "all-high")) {
272                         default_pattern = PATTERN_ALL_HIGH;
273                 } else {
274                         ret = SR_ERR;
275                 }
276                 sr_dbg("%s: setting pattern to %d", __func__, default_pattern);
277         } else {
278                 ret = SR_ERR;
279         }
280
281         return ret;
282 }
283
284 static int config_list(int key, const void **data, const struct sr_dev_inst *sdi)
285 {
286
287         (void)sdi;
288
289         switch (key) {
290         case SR_CONF_DEVICE_OPTIONS:
291                 *data = hwcaps;
292                 break;
293         case SR_CONF_SAMPLERATE:
294                 *data = &samplerates;
295                 break;
296         case SR_CONF_PATTERN_MODE:
297                 *data = &pattern_strings;
298                 break;
299         default:
300                 return SR_ERR_ARG;
301         }
302
303         return SR_OK;
304 }
305
306 static void samples_generator(uint8_t *buf, uint64_t size,
307                               struct dev_context *devc)
308 {
309         static uint64_t p = 0;
310         uint64_t i;
311
312         /* TODO: Needed? */
313         memset(buf, 0, size);
314
315         switch (devc->sample_generator) {
316         case PATTERN_SIGROK: /* sigrok pattern */
317                 for (i = 0; i < size; i++) {
318                         *(buf + i) = ~(pattern_sigrok[p] >> 1);
319                         if (++p == 64)
320                                 p = 0;
321                 }
322                 break;
323         case PATTERN_RANDOM: /* Random */
324                 for (i = 0; i < size; i++)
325                         *(buf + i) = (uint8_t)(rand() & 0xff);
326                 break;
327         case PATTERN_INC: /* Simple increment */
328                 for (i = 0; i < size; i++)
329                         *(buf + i) = i;
330                 break;
331         case PATTERN_ALL_LOW: /* All probes are low */
332                 memset(buf, 0x00, size);
333                 break;
334         case PATTERN_ALL_HIGH: /* All probes are high */
335                 memset(buf, 0xff, size);
336                 break;
337         default:
338                 sr_err("Unknown pattern: %d.", devc->sample_generator);
339                 break;
340         }
341 }
342
343 /* Callback handling data */
344 static int receive_data(int fd, int revents, void *cb_data)
345 {
346         struct dev_context *devc = cb_data;
347         struct sr_datafeed_packet packet;
348         struct sr_datafeed_logic logic;
349         uint8_t buf[BUFSIZE];
350         static uint64_t samples_to_send, expected_samplenum, sending_now;
351         int64_t time, elapsed;
352
353         (void)fd;
354         (void)revents;
355
356         /* How many "virtual" samples should we have collected by now? */
357         time = g_get_monotonic_time();
358         elapsed = time - devc->starttime;
359         expected_samplenum = elapsed * cur_samplerate / 1000000;
360         /* Of those, how many do we still have to send? */
361         samples_to_send = expected_samplenum - devc->samples_counter;
362
363         if (limit_samples) {
364                 samples_to_send = MIN(samples_to_send,
365                                  limit_samples - devc->samples_counter);
366         }
367
368         while (samples_to_send > 0) {
369                 sending_now = MIN(samples_to_send, sizeof(buf));
370                 samples_to_send -= sending_now;
371                 samples_generator(buf, sending_now, devc);
372
373                 packet.type = SR_DF_LOGIC;
374                 packet.payload = &logic;
375                 logic.length = sending_now;
376                 logic.unitsize = 1;
377                 logic.data = buf;
378                 sr_session_send(devc->session_dev_id, &packet);
379                 devc->samples_counter += sending_now;
380         }
381
382         if (limit_samples && devc->samples_counter >= limit_samples) {
383                 sr_info("Requested number of samples reached.");
384                 hw_dev_acquisition_stop(NULL, cb_data);
385                 return TRUE;
386         }
387
388         return TRUE;
389 }
390
391 static int hw_dev_acquisition_start(const struct sr_dev_inst *sdi,
392                 void *cb_data)
393 {
394         struct sr_datafeed_packet *packet;
395         struct sr_datafeed_header *header;
396         struct dev_context *devc;
397
398         (void)sdi;
399
400         sr_dbg("Starting acquisition.");
401
402         /* TODO: 'devc' is never g_free()'d? */
403         if (!(devc = g_try_malloc(sizeof(struct dev_context)))) {
404                 sr_err("%s: devc malloc failed", __func__);
405                 return SR_ERR_MALLOC;
406         }
407
408         devc->sample_generator = default_pattern;
409         devc->session_dev_id = cb_data;
410         devc->samples_counter = 0;
411
412         /*
413          * Setting two channels connected by a pipe is a remnant from when the
414          * demo driver generated data in a thread, and collected and sent the
415          * data in the main program loop.
416          * They are kept here because it provides a convenient way of setting
417          * up a timeout-based polling mechanism.
418          */
419         if (pipe(devc->pipe_fds)) {
420                 /* TODO: Better error message. */
421                 sr_err("%s: pipe() failed", __func__);
422                 return SR_ERR;
423         }
424
425         devc->channels[0] = g_io_channel_unix_new(devc->pipe_fds[0]);
426         devc->channels[1] = g_io_channel_unix_new(devc->pipe_fds[1]);
427
428         g_io_channel_set_flags(devc->channels[0], G_IO_FLAG_NONBLOCK, NULL);
429
430         /* Set channel encoding to binary (default is UTF-8). */
431         g_io_channel_set_encoding(devc->channels[0], NULL, NULL);
432         g_io_channel_set_encoding(devc->channels[1], NULL, NULL);
433
434         /* Make channels to unbuffered. */
435         g_io_channel_set_buffered(devc->channels[0], FALSE);
436         g_io_channel_set_buffered(devc->channels[1], FALSE);
437
438         sr_session_source_add_channel(devc->channels[0], G_IO_IN | G_IO_ERR,
439                     40, receive_data, devc);
440
441         if (!(packet = g_try_malloc(sizeof(struct sr_datafeed_packet)))) {
442                 sr_err("%s: packet malloc failed", __func__);
443                 return SR_ERR_MALLOC;
444         }
445
446         if (!(header = g_try_malloc(sizeof(struct sr_datafeed_header)))) {
447                 sr_err("%s: header malloc failed", __func__);
448                 return SR_ERR_MALLOC;
449         }
450
451         packet->type = SR_DF_HEADER;
452         packet->payload = header;
453         header->feed_version = 1;
454         gettimeofday(&header->starttime, NULL);
455         sr_session_send(devc->session_dev_id, packet);
456
457         /* We use this timestamp to decide how many more samples to send. */
458         devc->starttime = g_get_monotonic_time();
459
460         g_free(header);
461         g_free(packet);
462
463         return SR_OK;
464 }
465
466 static int hw_dev_acquisition_stop(struct sr_dev_inst *sdi, void *cb_data)
467 {
468         struct dev_context *devc;
469         struct sr_datafeed_packet packet;
470
471         (void)sdi;
472
473         devc = cb_data;
474
475         sr_dbg("Stopping aquisition.");
476
477         sr_session_source_remove_channel(devc->channels[0]);
478         g_io_channel_shutdown(devc->channels[0], FALSE, NULL);
479
480         /* Send last packet. */
481         packet.type = SR_DF_END;
482         sr_session_send(devc->session_dev_id, &packet);
483
484         return SR_OK;
485 }
486
487 SR_PRIV struct sr_dev_driver demo_driver_info = {
488         .name = "demo",
489         .longname = "Demo driver and pattern generator",
490         .api_version = 1,
491         .init = hw_init,
492         .cleanup = hw_cleanup,
493         .scan = hw_scan,
494         .dev_list = hw_dev_list,
495         .dev_clear = clear_instances,
496         .config_get = config_get,
497         .config_set = config_set,
498         .config_list = config_list,
499         .dev_open = hw_dev_open,
500         .dev_close = hw_dev_close,
501         .dev_acquisition_start = hw_dev_acquisition_start,
502         .dev_acquisition_stop = hw_dev_acquisition_stop,
503         .priv = NULL,
504 };