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