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