]> sigrok.org Git - libsigrok.git/blame - hardware/demo/demo.c
genericdmm: finish basic USB support
[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
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{
17e1afcb 206 /* Avoid compiler warnings. */
25a0f108 207 (void)sdi;
6239c175
UH
208
209 /* Nothing needed so far. */
697785d1 210
e46b8fb1 211 return SR_OK;
6239c175
UH
212}
213
25a0f108 214static int hw_dev_close(struct sr_dev_inst *sdi)
6239c175 215{
17e1afcb 216 /* Avoid compiler warnings. */
25a0f108 217 (void)sdi;
6239c175
UH
218
219 /* Nothing needed so far. */
697785d1
UH
220
221 return SR_OK;
6239c175
UH
222}
223
57ab7d9f 224static int hw_cleanup(void)
6239c175
UH
225{
226 /* Nothing needed so far. */
57ab7d9f 227 return SR_OK;
6239c175
UH
228}
229
dfb0fa1a
BV
230static int hw_info_get(int info_id, const void **data,
231 const struct sr_dev_inst *sdi)
6239c175 232{
85b5af06 233
6f57fd96
BV
234 (void)sdi;
235
dfb0fa1a 236 switch (info_id) {
46c7a4da
BV
237 case SR_DI_HWCAPS:
238 *data = hwcaps;
239 break;
5a2326a7 240 case SR_DI_NUM_PROBES:
dfb0fa1a 241 *data = GINT_TO_POINTER(NUM_PROBES);
6239c175 242 break;
464d12c7 243 case SR_DI_PROBE_NAMES:
dfb0fa1a 244 *data = probe_names;
464d12c7 245 break;
4bfbf9fc 246 case SR_DI_SAMPLERATES:
dfb0fa1a 247 *data = &samplerates;
4bfbf9fc 248 break;
5a2326a7 249 case SR_DI_CUR_SAMPLERATE:
dfb0fa1a 250 *data = &cur_samplerate;
6239c175 251 break;
eb0a3731 252 case SR_DI_PATTERNS:
dfb0fa1a 253 *data = &pattern_strings;
e15f48c2 254 break;
7dfcf010
BV
255 default:
256 return SR_ERR_ARG;
6239c175
UH
257 }
258
dfb0fa1a 259 return SR_OK;
6239c175
UH
260}
261
6f4b1868
BV
262static int hw_dev_config_set(const struct sr_dev_inst *sdi, int hwcap,
263 const void *value)
6239c175
UH
264{
265 int ret;
1b79df2f 266 const char *stropt;
6239c175 267
6f4b1868 268 (void)sdi;
6239c175 269
014359e3 270 if (hwcap == SR_HWCAP_SAMPLERATE) {
1b79df2f 271 cur_samplerate = *(const uint64_t *)value;
6f422264
UH
272 sr_dbg("demo: %s: setting samplerate to %" PRIu64, __func__,
273 cur_samplerate);
e46b8fb1 274 ret = SR_OK;
ffedd0bf 275 } else if (hwcap == SR_HWCAP_LIMIT_SAMPLES) {
8489264f 276 limit_msec = 0;
1b79df2f 277 limit_samples = *(const uint64_t *)value;
6f422264
UH
278 sr_dbg("demo: %s: setting limit_samples to %" PRIu64, __func__,
279 limit_samples);
e46b8fb1 280 ret = SR_OK;
ffedd0bf 281 } else if (hwcap == SR_HWCAP_LIMIT_MSEC) {
1b79df2f 282 limit_msec = *(const uint64_t *)value;
8489264f 283 limit_samples = 0;
6f422264
UH
284 sr_dbg("demo: %s: setting limit_msec to %" PRIu64, __func__,
285 limit_msec);
e46b8fb1 286 ret = SR_OK;
ffedd0bf 287 } else if (hwcap == SR_HWCAP_PATTERN_MODE) {
e15f48c2 288 stropt = value;
c03ed397
UH
289 ret = SR_OK;
290 if (!strcmp(stropt, "sigrok")) {
291 default_pattern = PATTERN_SIGROK;
292 } else if (!strcmp(stropt, "random")) {
c8f4624d 293 default_pattern = PATTERN_RANDOM;
e15f48c2 294 } else if (!strcmp(stropt, "incremental")) {
c8f4624d 295 default_pattern = PATTERN_INC;
c03ed397
UH
296 } else if (!strcmp(stropt, "all-low")) {
297 default_pattern = PATTERN_ALL_LOW;
298 } else if (!strcmp(stropt, "all-high")) {
299 default_pattern = PATTERN_ALL_HIGH;
e15f48c2 300 } else {
e46b8fb1 301 ret = SR_ERR;
e15f48c2 302 }
c8f4624d
UH
303 sr_dbg("demo: %s: setting pattern to %d", __func__,
304 default_pattern);
6239c175 305 } else {
e46b8fb1 306 ret = SR_ERR;
6239c175
UH
307 }
308
309 return ret;
310}
311
5096c6a6 312static void samples_generator(uint8_t *buf, uint64_t size, void *data)
85b5af06 313{
cddd1c5f 314 static uint64_t p = 0;
b4750a3a 315 struct dev_context *devc = data;
cddd1c5f 316 uint64_t i;
85b5af06 317
c03ed397 318 /* TODO: Needed? */
5096c6a6 319 memset(buf, 0, size);
85b5af06 320
b4750a3a 321 switch (devc->sample_generator) {
c03ed397 322 case PATTERN_SIGROK: /* sigrok pattern */
917e0e71 323 for (i = 0; i < size; i++) {
c8f4624d 324 *(buf + i) = ~(pattern_sigrok[p] >> 1);
917e0e71
BV
325 if (++p == 64)
326 p = 0;
327 }
328 break;
c8f4624d 329 case PATTERN_RANDOM: /* Random */
5096c6a6
UH
330 for (i = 0; i < size; i++)
331 *(buf + i) = (uint8_t)(rand() & 0xff);
85b5af06 332 break;
c8f4624d 333 case PATTERN_INC: /* Simple increment */
5096c6a6 334 for (i = 0; i < size; i++)
85b5af06
UH
335 *(buf + i) = i;
336 break;
c03ed397 337 case PATTERN_ALL_LOW: /* All probes are low */
5a9660dd 338 memset(buf, 0x00, size);
c03ed397
UH
339 break;
340 case PATTERN_ALL_HIGH: /* All probes are high */
5a9660dd 341 memset(buf, 0xff, size);
c03ed397
UH
342 break;
343 default:
0abee507 344 sr_err("demo: %s: unknown pattern %d", __func__,
b4750a3a 345 devc->sample_generator);
c03ed397 346 break;
85b5af06
UH
347 }
348}
349
350/* Thread function */
351static void thread_func(void *data)
352{
b4750a3a 353 struct dev_context *devc = data;
85b5af06
UH
354 uint8_t buf[BUFSIZE];
355 uint64_t nb_to_send = 0;
d35aaf02 356 int bytes_written;
1924f59f
HE
357 double time_cur, time_last, time_diff;
358
b4750a3a 359 time_last = g_timer_elapsed(devc->timer, NULL);
85b5af06
UH
360
361 while (thread_running) {
1924f59f 362 /* Rate control */
b4750a3a 363 time_cur = g_timer_elapsed(devc->timer, NULL);
1924f59f
HE
364
365 time_diff = time_cur - time_last;
366 time_last = time_cur;
367
368 nb_to_send = cur_samplerate * time_diff;
369
c03ed397 370 if (limit_samples) {
1924f59f 371 nb_to_send = MIN(nb_to_send,
b4750a3a 372 limit_samples - devc->samples_counter);
c03ed397 373 }
1924f59f
HE
374
375 /* Make sure we don't overflow. */
376 nb_to_send = MIN(nb_to_send, BUFSIZE);
377
378 if (nb_to_send) {
379 samples_generator(buf, nb_to_send, data);
b4750a3a 380 devc->samples_counter += nb_to_send;
070befcd 381
b4750a3a 382 g_io_channel_write_chars(devc->channels[1], (gchar *)&buf,
c03ed397 383 nb_to_send, (gsize *)&bytes_written, NULL);
b9cc3629
BV
384 }
385
1924f59f
HE
386 /* Check if we're done. */
387 if ((limit_msec && time_cur * 1000 > limit_msec) ||
b4750a3a 388 (limit_samples && devc->samples_counter >= limit_samples))
1924f59f 389 {
b4750a3a 390 close(devc->pipe_fds[1]);
85b5af06 391 thread_running = 0;
85b5af06
UH
392 }
393
1924f59f 394 g_usleep(10);
85b5af06
UH
395 }
396}
397
398/* Callback handling data */
1f9813eb 399static int receive_data(int fd, int revents, void *cb_data)
85b5af06 400{
b4750a3a 401 struct dev_context *devc = cb_data;
b9c735a2 402 struct sr_datafeed_packet packet;
9c939c51
BV
403 struct sr_datafeed_logic logic;
404 static uint64_t samples_received = 0;
405 unsigned char c[BUFSIZE];
108a5bfb 406 gsize z;
1924f59f 407
26ce0bbf 408 /* Avoid compiler warnings. */
cb93f8a9
UH
409 (void)fd;
410 (void)revents;
1924f59f
HE
411
412 do {
b4750a3a 413 g_io_channel_read_chars(devc->channels[0],
070befcd 414 (gchar *)&c, BUFSIZE, &z, NULL);
1924f59f
HE
415
416 if (z > 0) {
5a2326a7 417 packet.type = SR_DF_LOGIC;
9c939c51 418 packet.payload = &logic;
9c939c51
BV
419 logic.length = z;
420 logic.unitsize = 1;
421 logic.data = c;
b4750a3a 422 sr_session_send(devc->session_dev_id, &packet);
9c939c51 423 samples_received += z;
1924f59f
HE
424 }
425 } while (z > 0);
85b5af06 426
c03ed397
UH
427 if (!thread_running && z <= 0) {
428 /* Make sure we don't receive more packets. */
b4750a3a 429 g_io_channel_shutdown(devc->channels[0], FALSE, NULL);
d35aaf02 430
1924f59f 431 /* Send last packet. */
5a2326a7 432 packet.type = SR_DF_END;
b4750a3a 433 sr_session_send(devc->session_dev_id, &packet);
1924f59f
HE
434
435 return FALSE;
85b5af06 436 }
1924f59f 437
85b5af06
UH
438 return TRUE;
439}
440
3ffb6964
BV
441static int hw_dev_acquisition_start(const struct sr_dev_inst *sdi,
442 void *cb_data)
6239c175 443{
b9c735a2
UH
444 struct sr_datafeed_packet *packet;
445 struct sr_datafeed_header *header;
f366e86c 446 struct sr_datafeed_meta_logic meta;
b4750a3a 447 struct dev_context *devc;
6239c175 448
3ffb6964
BV
449 (void)sdi;
450
b4750a3a
BV
451 /* TODO: 'devc' is never g_free()'d? */
452 if (!(devc = g_try_malloc(sizeof(struct dev_context)))) {
453 sr_err("demo: %s: devc malloc failed", __func__);
e46b8fb1 454 return SR_ERR_MALLOC;
27a3a6fe 455 }
85b5af06 456
b4750a3a
BV
457 devc->sample_generator = default_pattern;
458 devc->session_dev_id = cb_data;
459 devc->samples_counter = 0;
85b5af06 460
b4750a3a 461 if (pipe(devc->pipe_fds)) {
c03ed397
UH
462 /* TODO: Better error message. */
463 sr_err("demo: %s: pipe() failed", __func__);
e46b8fb1 464 return SR_ERR;
c03ed397 465 }
85b5af06 466
b4750a3a
BV
467 devc->channels[0] = g_io_channel_unix_new(devc->pipe_fds[0]);
468 devc->channels[1] = g_io_channel_unix_new(devc->pipe_fds[1]);
d35aaf02 469
b4750a3a 470 g_io_channel_set_flags(devc->channels[0], G_IO_FLAG_NONBLOCK, NULL);
e6e8f8e0 471
d35aaf02 472 /* Set channel encoding to binary (default is UTF-8). */
b4750a3a
BV
473 g_io_channel_set_encoding(devc->channels[0], NULL, NULL);
474 g_io_channel_set_encoding(devc->channels[1], NULL, NULL);
d35aaf02
UH
475
476 /* Make channels to unbuffered. */
b4750a3a
BV
477 g_io_channel_set_buffered(devc->channels[0], FALSE);
478 g_io_channel_set_buffered(devc->channels[1], FALSE);
d35aaf02 479
b4750a3a
BV
480 sr_session_source_add_channel(devc->channels[0], G_IO_IN | G_IO_ERR,
481 40, receive_data, devc);
85b5af06
UH
482
483 /* Run the demo thread. */
484 g_thread_init(NULL);
c03ed397 485 /* This must to be done between g_thread_init() & g_thread_create(). */
b4750a3a 486 devc->timer = g_timer_new();
85b5af06
UH
487 thread_running = 1;
488 my_thread =
b4750a3a 489 g_thread_create((GThreadFunc)thread_func, devc, TRUE, NULL);
c03ed397
UH
490 if (!my_thread) {
491 sr_err("demo: %s: g_thread_create failed", __func__);
492 return SR_ERR; /* TODO */
493 }
6239c175 494
27a3a6fe
UH
495 if (!(packet = g_try_malloc(sizeof(struct sr_datafeed_packet)))) {
496 sr_err("demo: %s: packet malloc failed", __func__);
e46b8fb1 497 return SR_ERR_MALLOC;
27a3a6fe
UH
498 }
499
500 if (!(header = g_try_malloc(sizeof(struct sr_datafeed_header)))) {
501 sr_err("demo: %s: header malloc failed", __func__);
502 return SR_ERR_MALLOC;
503 }
6239c175 504
5a2326a7 505 packet->type = SR_DF_HEADER;
9c939c51 506 packet->payload = header;
6239c175
UH
507 header->feed_version = 1;
508 gettimeofday(&header->starttime, NULL);
b4750a3a 509 sr_session_send(devc->session_dev_id, packet);
f366e86c
BV
510
511 /* Send metadata about the SR_DF_LOGIC packets to come. */
512 packet->type = SR_DF_META_LOGIC;
513 packet->payload = &meta;
514 meta.samplerate = cur_samplerate;
515 meta.num_probes = NUM_PROBES;
b4750a3a 516 sr_session_send(devc->session_dev_id, packet);
f366e86c 517
27a3a6fe
UH
518 g_free(header);
519 g_free(packet);
6239c175 520
e46b8fb1 521 return SR_OK;
6239c175
UH
522}
523
3ffb6964
BV
524static int hw_dev_acquisition_stop(const struct sr_dev_inst *sdi,
525 void *cb_data)
6239c175 526{
7fd3e859
BV
527 struct dev_context *devc;
528
17e1afcb 529 /* Avoid compiler warnings. */
3cd3a20b 530 (void)cb_data;
6239c175 531
7fd3e859
BV
532 devc = sdi->priv;
533
1924f59f
HE
534 /* Stop generate thread. */
535 thread_running = 0;
3010f21c 536
7fd3e859
BV
537 sr_session_source_remove_channel(devc->channels[0]);
538
3010f21c 539 return SR_OK;
6239c175
UH
540}
541
c09f0b57 542SR_PRIV struct sr_dev_driver demo_driver_info = {
e519ba86
UH
543 .name = "demo",
544 .longname = "Demo driver and pattern generator",
545 .api_version = 1,
546 .init = hw_init,
547 .cleanup = hw_cleanup,
61136ea6 548 .scan = hw_scan,
811deee4 549 .dev_list = hw_dev_list,
e7eb703f
UH
550 .dev_open = hw_dev_open,
551 .dev_close = hw_dev_close,
dfb0fa1a 552 .info_get = hw_info_get,
a9a245b4 553 .dev_config_set = hw_dev_config_set,
69040b7c
UH
554 .dev_acquisition_start = hw_dev_acquisition_start,
555 .dev_acquisition_stop = hw_dev_acquisition_stop,
b4750a3a 556 .priv = NULL,
6239c175 557};