]> sigrok.org Git - libsigrok.git/blame - hardware/demo/demo.c
sr_init(): Add driver sanity checks.
[libsigrok.git] / hardware / demo / demo.c
CommitLineData
6239c175
UH
1/*
2 * This file is part of the sigrok project.
3 *
4 * Copyright (C) 2010 Uwe Hermann <uwe@hermann-uwe.de>
fc96e6f8 5 * Copyright (C) 2011 Olivier Fauchon <olivier@aixmarseille.com>
c216d623 6 * Copyright (C) 2012 Alexandru Gagniuc <mr.nuke.me@gmail.com>
6239c175
UH
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>
85b5af06 24#include <unistd.h>
6239c175 25#include <string.h>
d35aaf02
UH
26#ifdef _WIN32
27#include <io.h>
28#include <fcntl.h>
29#define pipe(fds) _pipe(fds, 4096, _O_BINARY)
30#endif
45c59c8b
BV
31#include "libsigrok.h"
32#include "libsigrok-internal.h"
6239c175 33
92bcedf6
UH
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
c03ed397 43/* TODO: Number of probes should be configurable. */
e15f48c2 44#define NUM_PROBES 8
c03ed397 45
e15f48c2 46#define DEMONAME "Demo device"
c03ed397
UH
47
48/* The size of chunks to send through the session bus. */
49/* TODO: Should be configurable. */
e15f48c2 50#define BUFSIZE 4096
85b5af06 51
0d31276b 52/* Supported patterns which we can generate */
e15f48c2 53enum {
0d31276b
UH
54 /**
55 * Pattern which spells "sigrok" using '0's (with '1's as "background")
56 * when displayed using the 'bits' output format.
57 */
c8f4624d 58 PATTERN_SIGROK,
0d31276b 59
c03ed397 60 /** Pattern which consists of (pseudo-)random values on all probes. */
c8f4624d 61 PATTERN_RANDOM,
0d31276b
UH
62
63 /**
64 * Pattern which consists of incrementing numbers.
65 * TODO: Better description.
66 */
c8f4624d 67 PATTERN_INC,
c03ed397
UH
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,
e15f48c2 74};
85b5af06 75
b4750a3a
BV
76/* Private, per-device-instance driver context. */
77struct dev_context {
e15f48c2 78 int pipe_fds[2];
249ae2be 79 GIOChannel *channels[2];
e15f48c2 80 uint8_t sample_generator;
e15f48c2 81 uint64_t samples_counter;
3cd3a20b 82 void *session_dev_id;
3b203673 83 int64_t starttime;
e15f48c2 84};
85b5af06 85
915f7cc8 86static const int hwcaps[] = {
5a2326a7 87 SR_HWCAP_LOGIC_ANALYZER,
bb7ef793 88 SR_HWCAP_DEMO_DEV,
4bfbf9fc 89 SR_HWCAP_SAMPLERATE,
5a2326a7
UH
90 SR_HWCAP_PATTERN_MODE,
91 SR_HWCAP_LIMIT_SAMPLES,
92 SR_HWCAP_LIMIT_MSEC,
93 SR_HWCAP_CONTINUOUS,
6239c175
UH
94};
95
a533743d 96static const struct sr_samplerates samplerates = {
c9140419 97 SR_HZ(1),
59df0c77 98 SR_GHZ(1),
c9140419 99 SR_HZ(1),
4bfbf9fc
BV
100 NULL,
101};
102
c8f4624d 103static const char *pattern_strings[] = {
c03ed397 104 "sigrok",
e15f48c2
BV
105 "random",
106 "incremental",
c03ed397
UH
107 "all-low",
108 "all-high",
02440dd8 109 NULL,
85b5af06
UH
110};
111
d261dbbf 112/* We name the probes 0-7 on our demo driver. */
464d12c7
KS
113static const char *probe_names[NUM_PROBES + 1] = {
114 "0",
115 "1",
116 "2",
117 "3",
118 "4",
119 "5",
120 "6",
121 "7",
122 NULL,
123};
124
c8f4624d 125static uint8_t pattern_sigrok[] = {
917e0e71
BV
126 0x4c, 0x92, 0x92, 0x92, 0x64, 0x00, 0x00, 0x00,
127 0x82, 0xfe, 0xfe, 0x82, 0x00, 0x00, 0x00, 0x00,
128 0x7c, 0x82, 0x82, 0x92, 0x74, 0x00, 0x00, 0x00,
129 0xfe, 0x12, 0x12, 0x32, 0xcc, 0x00, 0x00, 0x00,
130 0x7c, 0x82, 0x82, 0x82, 0x7c, 0x00, 0x00, 0x00,
131 0xfe, 0x10, 0x28, 0x44, 0x82, 0x00, 0x00, 0x00,
132 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
133 0xbe, 0xbe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
134};
135
ea9cfed7
UH
136/* Private, per-device-instance driver context. */
137/* TODO: struct context as with the other drivers. */
138
e7eb703f 139/* List of struct sr_dev_inst, maintained by dev_open()/dev_close(). */
dcf03d6d
BV
140SR_PRIV struct sr_dev_driver demo_driver_info;
141static struct sr_dev_driver *ddi = &demo_driver_info;
59df0c77 142static uint64_t cur_samplerate = SR_KHZ(200);
b9cc3629
BV
143static uint64_t limit_samples = 0;
144static uint64_t limit_msec = 0;
c8f4624d 145static int default_pattern = PATTERN_SIGROK;
6239c175 146
69b07d14 147static int hw_dev_acquisition_stop(struct sr_dev_inst *sdi, void *cb_data);
6239c175 148
40dda2c3 149static int hw_init(void)
61136ea6 150{
b4750a3a 151 struct drv_context *drvc;
61136ea6 152
b4750a3a 153 if (!(drvc = g_try_malloc0(sizeof(struct drv_context)))) {
92bcedf6 154 sr_err("Driver context malloc failed.");
886a52b6 155 return SR_ERR_MALLOC;
b4750a3a
BV
156 }
157 ddi->priv = drvc;
61136ea6
BV
158
159 return SR_OK;
160}
161
067d0716 162static GSList *hw_scan(GSList *options)
6239c175 163{
d68e2d1a 164 struct sr_dev_inst *sdi;
87ca93c5 165 struct sr_probe *probe;
b4750a3a 166 struct drv_context *drvc;
067d0716 167 GSList *devices;
87ca93c5 168 int i;
067d0716
BV
169
170 (void)options;
64d33dc2 171
b4750a3a 172 drvc = ddi->priv;
067d0716 173 devices = NULL;
85b5af06 174
d3683c42 175 sdi = sr_dev_inst_new(0, SR_ST_ACTIVE, DEMONAME, NULL, NULL);
c03ed397 176 if (!sdi) {
92bcedf6 177 sr_err("%s: sr_dev_inst_new failed", __func__);
85b5af06 178 return 0;
c03ed397 179 }
7dfcf010 180 sdi->driver = ddi;
e15f48c2 181
87ca93c5 182 for (i = 0; probe_names[i]; i++) {
de6e0eca 183 if (!(probe = sr_probe_new(i, SR_PROBE_LOGIC, TRUE,
87ca93c5
BV
184 probe_names[i])))
185 return NULL;
186 sdi->probes = g_slist_append(sdi->probes, probe);
187 }
188
067d0716 189 devices = g_slist_append(devices, sdi);
b4750a3a 190 drvc->instances = g_slist_append(drvc->instances, sdi);
85b5af06 191
067d0716 192 return devices;
6239c175
UH
193}
194
811deee4
BV
195static GSList *hw_dev_list(void)
196{
197 struct drv_context *drvc;
198
199 drvc = ddi->priv;
200
201 return drvc->instances;
202}
203
25a0f108 204static int hw_dev_open(struct sr_dev_inst *sdi)
6239c175 205{
25a0f108 206 (void)sdi;
6239c175
UH
207
208 /* Nothing needed so far. */
697785d1 209
e46b8fb1 210 return SR_OK;
6239c175
UH
211}
212
25a0f108 213static int hw_dev_close(struct sr_dev_inst *sdi)
6239c175 214{
25a0f108 215 (void)sdi;
6239c175
UH
216
217 /* Nothing needed so far. */
697785d1
UH
218
219 return SR_OK;
6239c175
UH
220}
221
57ab7d9f 222static int hw_cleanup(void)
6239c175
UH
223{
224 /* Nothing needed so far. */
57ab7d9f 225 return SR_OK;
6239c175
UH
226}
227
dfb0fa1a
BV
228static int hw_info_get(int info_id, const void **data,
229 const struct sr_dev_inst *sdi)
6239c175 230{
6f57fd96
BV
231 (void)sdi;
232
dfb0fa1a 233 switch (info_id) {
46c7a4da
BV
234 case SR_DI_HWCAPS:
235 *data = hwcaps;
236 break;
5a2326a7 237 case SR_DI_NUM_PROBES:
dfb0fa1a 238 *data = GINT_TO_POINTER(NUM_PROBES);
6239c175 239 break;
464d12c7 240 case SR_DI_PROBE_NAMES:
dfb0fa1a 241 *data = probe_names;
464d12c7 242 break;
4bfbf9fc 243 case SR_DI_SAMPLERATES:
dfb0fa1a 244 *data = &samplerates;
4bfbf9fc 245 break;
5a2326a7 246 case SR_DI_CUR_SAMPLERATE:
dfb0fa1a 247 *data = &cur_samplerate;
6239c175 248 break;
eb0a3731 249 case SR_DI_PATTERNS:
dfb0fa1a 250 *data = &pattern_strings;
e15f48c2 251 break;
7dfcf010
BV
252 default:
253 return SR_ERR_ARG;
6239c175
UH
254 }
255
dfb0fa1a 256 return SR_OK;
6239c175
UH
257}
258
6f4b1868
BV
259static int hw_dev_config_set(const struct sr_dev_inst *sdi, int hwcap,
260 const void *value)
6239c175
UH
261{
262 int ret;
1b79df2f 263 const char *stropt;
6239c175 264
6f4b1868 265 (void)sdi;
6239c175 266
014359e3 267 if (hwcap == SR_HWCAP_SAMPLERATE) {
1b79df2f 268 cur_samplerate = *(const uint64_t *)value;
92bcedf6 269 sr_dbg("%s: setting samplerate to %" PRIu64, __func__,
6f422264 270 cur_samplerate);
e46b8fb1 271 ret = SR_OK;
ffedd0bf 272 } else if (hwcap == SR_HWCAP_LIMIT_SAMPLES) {
8489264f 273 limit_msec = 0;
1b79df2f 274 limit_samples = *(const uint64_t *)value;
92bcedf6 275 sr_dbg("%s: setting limit_samples to %" PRIu64, __func__,
6f422264 276 limit_samples);
e46b8fb1 277 ret = SR_OK;
ffedd0bf 278 } else if (hwcap == SR_HWCAP_LIMIT_MSEC) {
1b79df2f 279 limit_msec = *(const uint64_t *)value;
8489264f 280 limit_samples = 0;
92bcedf6 281 sr_dbg("%s: setting limit_msec to %" PRIu64, __func__,
6f422264 282 limit_msec);
e46b8fb1 283 ret = SR_OK;
ffedd0bf 284 } else if (hwcap == SR_HWCAP_PATTERN_MODE) {
e15f48c2 285 stropt = value;
c03ed397
UH
286 ret = SR_OK;
287 if (!strcmp(stropt, "sigrok")) {
288 default_pattern = PATTERN_SIGROK;
289 } else if (!strcmp(stropt, "random")) {
c8f4624d 290 default_pattern = PATTERN_RANDOM;
e15f48c2 291 } else if (!strcmp(stropt, "incremental")) {
c8f4624d 292 default_pattern = PATTERN_INC;
c03ed397
UH
293 } else if (!strcmp(stropt, "all-low")) {
294 default_pattern = PATTERN_ALL_LOW;
295 } else if (!strcmp(stropt, "all-high")) {
296 default_pattern = PATTERN_ALL_HIGH;
e15f48c2 297 } else {
e46b8fb1 298 ret = SR_ERR;
e15f48c2 299 }
92bcedf6 300 sr_dbg("%s: setting pattern to %d", __func__, default_pattern);
6239c175 301 } else {
e46b8fb1 302 ret = SR_ERR;
6239c175
UH
303 }
304
305 return ret;
306}
307
3b203673
AG
308static void samples_generator(uint8_t *buf, uint64_t size,
309 struct dev_context *devc)
85b5af06 310{
cddd1c5f 311 static uint64_t p = 0;
cddd1c5f 312 uint64_t i;
85b5af06 313
c03ed397 314 /* TODO: Needed? */
5096c6a6 315 memset(buf, 0, size);
85b5af06 316
b4750a3a 317 switch (devc->sample_generator) {
c03ed397 318 case PATTERN_SIGROK: /* sigrok pattern */
917e0e71 319 for (i = 0; i < size; i++) {
c8f4624d 320 *(buf + i) = ~(pattern_sigrok[p] >> 1);
917e0e71
BV
321 if (++p == 64)
322 p = 0;
323 }
324 break;
c8f4624d 325 case PATTERN_RANDOM: /* Random */
5096c6a6
UH
326 for (i = 0; i < size; i++)
327 *(buf + i) = (uint8_t)(rand() & 0xff);
85b5af06 328 break;
c8f4624d 329 case PATTERN_INC: /* Simple increment */
5096c6a6 330 for (i = 0; i < size; i++)
85b5af06
UH
331 *(buf + i) = i;
332 break;
c03ed397 333 case PATTERN_ALL_LOW: /* All probes are low */
5a9660dd 334 memset(buf, 0x00, size);
c03ed397
UH
335 break;
336 case PATTERN_ALL_HIGH: /* All probes are high */
5a9660dd 337 memset(buf, 0xff, size);
c03ed397
UH
338 break;
339 default:
92bcedf6 340 sr_err("Unknown pattern: %d.", devc->sample_generator);
c03ed397 341 break;
85b5af06
UH
342 }
343}
344
85b5af06 345/* Callback handling data */
1f9813eb 346static int receive_data(int fd, int revents, void *cb_data)
85b5af06 347{
b4750a3a 348 struct dev_context *devc = cb_data;
b9c735a2 349 struct sr_datafeed_packet packet;
9c939c51 350 struct sr_datafeed_logic logic;
3b203673
AG
351 uint8_t buf[BUFSIZE];
352 static uint64_t samples_to_send, expected_samplenum, sending_now;
353 int64_t time, elapsed;
1924f59f 354
cb93f8a9
UH
355 (void)fd;
356 (void)revents;
1924f59f 357
3b203673
AG
358 /* How many "virtual" samples should we have collected by now? */
359 time = g_get_monotonic_time();
360 elapsed = time - devc->starttime;
361 expected_samplenum = elapsed * cur_samplerate / 1000000;
362 /* Of those, how many do we still have to send? */
363 samples_to_send = expected_samplenum - devc->samples_counter;
364
365 if (limit_samples) {
366 samples_to_send = MIN(samples_to_send,
367 limit_samples - devc->samples_counter);
368 }
85b5af06 369
3b203673
AG
370 while (samples_to_send > 0) {
371 sending_now = MIN(samples_to_send, sizeof(buf));
372 samples_to_send -= sending_now;
373 samples_generator(buf, sending_now, devc);
374
375 packet.type = SR_DF_LOGIC;
376 packet.payload = &logic;
377 logic.length = sending_now;
378 logic.unitsize = 1;
379 logic.data = buf;
380 sr_session_send(devc->session_dev_id, &packet);
381 devc->samples_counter += sending_now;
382 }
383
384
385 if (devc->samples_counter >= limit_samples) {
386 sr_spew("We sent a total of %" PRIu64 " samples.",
387 devc->samples_counter);
c03ed397 388 /* Make sure we don't receive more packets. */
c216d623
AG
389 hw_dev_acquisition_stop(NULL, cb_data);
390 return TRUE;
85b5af06 391 }
1924f59f 392
85b5af06
UH
393 return TRUE;
394}
395
3ffb6964
BV
396static int hw_dev_acquisition_start(const struct sr_dev_inst *sdi,
397 void *cb_data)
6239c175 398{
b9c735a2
UH
399 struct sr_datafeed_packet *packet;
400 struct sr_datafeed_header *header;
f366e86c 401 struct sr_datafeed_meta_logic meta;
b4750a3a 402 struct dev_context *devc;
6239c175 403
3ffb6964
BV
404 (void)sdi;
405
49145a63
AG
406 sr_dbg("Starting acquisition.");
407
b4750a3a
BV
408 /* TODO: 'devc' is never g_free()'d? */
409 if (!(devc = g_try_malloc(sizeof(struct dev_context)))) {
92bcedf6 410 sr_err("%s: devc malloc failed", __func__);
e46b8fb1 411 return SR_ERR_MALLOC;
27a3a6fe 412 }
85b5af06 413
b4750a3a
BV
414 devc->sample_generator = default_pattern;
415 devc->session_dev_id = cb_data;
416 devc->samples_counter = 0;
85b5af06 417
3b203673
AG
418 /*
419 * Setting two channels connected by a pipe is a remnant from when the
420 * demo driver generated data in a thread, and collected and sent the
421 * data in the main program loop.
422 * They are kept here because it provides a convenient way of setting
423 * up a timeout-based polling mechanism.
424 */
b4750a3a 425 if (pipe(devc->pipe_fds)) {
c03ed397 426 /* TODO: Better error message. */
92bcedf6 427 sr_err("%s: pipe() failed", __func__);
e46b8fb1 428 return SR_ERR;
c03ed397 429 }
85b5af06 430
b4750a3a
BV
431 devc->channels[0] = g_io_channel_unix_new(devc->pipe_fds[0]);
432 devc->channels[1] = g_io_channel_unix_new(devc->pipe_fds[1]);
d35aaf02 433
b4750a3a 434 g_io_channel_set_flags(devc->channels[0], G_IO_FLAG_NONBLOCK, NULL);
e6e8f8e0 435
d35aaf02 436 /* Set channel encoding to binary (default is UTF-8). */
b4750a3a
BV
437 g_io_channel_set_encoding(devc->channels[0], NULL, NULL);
438 g_io_channel_set_encoding(devc->channels[1], NULL, NULL);
d35aaf02
UH
439
440 /* Make channels to unbuffered. */
b4750a3a
BV
441 g_io_channel_set_buffered(devc->channels[0], FALSE);
442 g_io_channel_set_buffered(devc->channels[1], FALSE);
d35aaf02 443
b4750a3a
BV
444 sr_session_source_add_channel(devc->channels[0], G_IO_IN | G_IO_ERR,
445 40, receive_data, devc);
85b5af06 446
27a3a6fe 447 if (!(packet = g_try_malloc(sizeof(struct sr_datafeed_packet)))) {
92bcedf6 448 sr_err("%s: packet malloc failed", __func__);
e46b8fb1 449 return SR_ERR_MALLOC;
27a3a6fe
UH
450 }
451
452 if (!(header = g_try_malloc(sizeof(struct sr_datafeed_header)))) {
92bcedf6 453 sr_err("%s: header malloc failed", __func__);
27a3a6fe
UH
454 return SR_ERR_MALLOC;
455 }
6239c175 456
5a2326a7 457 packet->type = SR_DF_HEADER;
9c939c51 458 packet->payload = header;
6239c175
UH
459 header->feed_version = 1;
460 gettimeofday(&header->starttime, NULL);
b4750a3a 461 sr_session_send(devc->session_dev_id, packet);
f366e86c
BV
462
463 /* Send metadata about the SR_DF_LOGIC packets to come. */
464 packet->type = SR_DF_META_LOGIC;
465 packet->payload = &meta;
466 meta.samplerate = cur_samplerate;
467 meta.num_probes = NUM_PROBES;
b4750a3a 468 sr_session_send(devc->session_dev_id, packet);
f366e86c 469
3b203673
AG
470 /* We use this timestamp to decide how many more samples to send. */
471 devc->starttime = g_get_monotonic_time();
472
27a3a6fe
UH
473 g_free(header);
474 g_free(packet);
6239c175 475
e46b8fb1 476 return SR_OK;
6239c175
UH
477}
478
69b07d14 479static int hw_dev_acquisition_stop(struct sr_dev_inst *sdi, void *cb_data)
6239c175 480{
7fd3e859 481 struct dev_context *devc;
c216d623 482 struct sr_datafeed_packet packet;
7fd3e859 483
c216d623 484 (void)sdi;
6239c175 485
c216d623 486 devc = cb_data;
7fd3e859 487
49145a63
AG
488 sr_dbg("Stopping aquisition.");
489
7fd3e859 490 sr_session_source_remove_channel(devc->channels[0]);
c216d623
AG
491 g_io_channel_shutdown(devc->channels[0], FALSE, NULL);
492
493 /* Send last packet. */
494 packet.type = SR_DF_END;
495 sr_session_send(devc->session_dev_id, &packet);
7fd3e859 496
3010f21c 497 return SR_OK;
6239c175
UH
498}
499
c09f0b57 500SR_PRIV struct sr_dev_driver demo_driver_info = {
e519ba86
UH
501 .name = "demo",
502 .longname = "Demo driver and pattern generator",
503 .api_version = 1,
504 .init = hw_init,
505 .cleanup = hw_cleanup,
61136ea6 506 .scan = hw_scan,
811deee4 507 .dev_list = hw_dev_list,
e7eb703f
UH
508 .dev_open = hw_dev_open,
509 .dev_close = hw_dev_close,
dfb0fa1a 510 .info_get = hw_info_get,
a9a245b4 511 .dev_config_set = hw_dev_config_set,
69040b7c
UH
512 .dev_acquisition_start = hw_dev_acquisition_start,
513 .dev_acquisition_stop = hw_dev_acquisition_stop,
b4750a3a 514 .priv = NULL,
6239c175 515};