libsigrok
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Macros
demo.c
Go to the documentation of this file.
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  *
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>
23 #include <unistd.h>
24 #include <string.h>
25 #ifdef _WIN32
26 #include <io.h>
27 #include <fcntl.h>
28 #define pipe(fds) _pipe(fds, 4096, _O_BINARY)
29 #endif
30 #include "sigrok.h"
31 #include "sigrok-internal.h"
32 
33 /* TODO: Number of probes should be configurable. */
34 #define NUM_PROBES 8
35 
36 #define DEMONAME "Demo device"
37 
38 /* The size of chunks to send through the session bus. */
39 /* TODO: Should be configurable. */
40 #define BUFSIZE 4096
41 
42 /* Supported patterns which we can generate */
43 enum {
44  /**
45  * Pattern which spells "sigrok" using '0's (with '1's as "background")
46  * when displayed using the 'bits' output format.
47  */
49 
50  /** Pattern which consists of (pseudo-)random values on all probes. */
52 
53  /**
54  * Pattern which consists of incrementing numbers.
55  * TODO: Better description.
56  */
58 
59  /** Pattern where all probes have a low logic state. */
61 
62  /** Pattern where all probes have a high logic state. */
64 };
65 
66 /* FIXME: Should not be global. */
67 SR_PRIV GIOChannel *channels[2];
68 
69 struct context {
70  int pipe_fds[2];
72  uint8_t thread_running;
73  uint64_t samples_counter;
74  int dev_index;
75  void *session_dev_id;
76  GTimer *timer;
77 };
78 
79 static int hwcaps[] = {
87 };
88 
89 static struct sr_samplerates samplerates = {
90  SR_HZ(1),
91  SR_GHZ(1),
92  SR_HZ(1),
93  NULL,
94 };
95 
96 static const char *pattern_strings[] = {
97  "sigrok",
98  "random",
99  "incremental",
100  "all-low",
101  "all-high",
102  NULL,
103 };
104 
105 /* We name the probes 0-7 on our demo driver. */
106 static const char *probe_names[NUM_PROBES + 1] = {
107  "0",
108  "1",
109  "2",
110  "3",
111  "4",
112  "5",
113  "6",
114  "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 static GSList *dev_insts = NULL;
134 static uint64_t cur_samplerate = SR_KHZ(200);
135 static uint64_t limit_samples = 0;
136 static uint64_t limit_msec = 0;
137 static int default_pattern = PATTERN_SIGROK;
138 static GThread *my_thread;
139 static int thread_running;
140 
141 static int hw_dev_acquisition_stop(int dev_index, void *cb_data);
142 
143 static int hw_init(const char *devinfo)
144 {
145  struct sr_dev_inst *sdi;
146 
147  /* Avoid compiler warnings. */
148  (void)devinfo;
149 
150  sdi = sr_dev_inst_new(0, SR_ST_ACTIVE, DEMONAME, NULL, NULL);
151  if (!sdi) {
152  sr_err("demo: %s: sr_dev_inst_new failed", __func__);
153  return 0;
154  }
155 
156  dev_insts = g_slist_append(dev_insts, sdi);
157 
158  return 1;
159 }
160 
161 static int hw_dev_open(int dev_index)
162 {
163  /* Avoid compiler warnings. */
164  (void)dev_index;
165 
166  /* Nothing needed so far. */
167 
168  return SR_OK;
169 }
170 
171 static int hw_dev_close(int dev_index)
172 {
173  /* Avoid compiler warnings. */
174  (void)dev_index;
175 
176  /* Nothing needed so far. */
177 
178  return SR_OK;
179 }
180 
181 static int hw_cleanup(void)
182 {
183  /* Nothing needed so far. */
184  return SR_OK;
185 }
186 
187 static void *hw_dev_info_get(int dev_index, int dev_info_id)
188 {
189  struct sr_dev_inst *sdi;
190  void *info = NULL;
191 
192  if (!(sdi = sr_dev_inst_get(dev_insts, dev_index))) {
193  sr_err("demo: %s: sdi was NULL", __func__);
194  return NULL;
195  }
196 
197  switch (dev_info_id) {
198  case SR_DI_INST:
199  info = sdi;
200  break;
201  case SR_DI_NUM_PROBES:
202  info = GINT_TO_POINTER(NUM_PROBES);
203  break;
204  case SR_DI_PROBE_NAMES:
205  info = probe_names;
206  break;
207  case SR_DI_SAMPLERATES:
208  info = &samplerates;
209  break;
211  info = &cur_samplerate;
212  break;
213  case SR_DI_PATTERNS:
214  info = &pattern_strings;
215  break;
216  }
217 
218  return info;
219 }
220 
221 static int hw_dev_status_get(int dev_index)
222 {
223  /* Avoid compiler warnings. */
224  (void)dev_index;
225 
226  return SR_ST_ACTIVE;
227 }
228 
229 static int *hw_hwcap_get_all(void)
230 {
231  return hwcaps;
232 }
233 
234 static int hw_dev_config_set(int dev_index, int hwcap, void *value)
235 {
236  int ret;
237  char *stropt;
238 
239  /* Avoid compiler warnings. */
240  (void)dev_index;
241 
242  if (hwcap == SR_HWCAP_PROBECONFIG) {
243  /* Nothing to do, but must be supported */
244  ret = SR_OK;
245  } else if (hwcap == SR_HWCAP_SAMPLERATE) {
246  cur_samplerate = *(uint64_t *)value;
247  sr_dbg("demo: %s: setting samplerate to %" PRIu64, __func__,
248  cur_samplerate);
249  ret = SR_OK;
250  } else if (hwcap == SR_HWCAP_LIMIT_SAMPLES) {
251  limit_samples = *(uint64_t *)value;
252  sr_dbg("demo: %s: setting limit_samples to %" PRIu64, __func__,
253  limit_samples);
254  ret = SR_OK;
255  } else if (hwcap == SR_HWCAP_LIMIT_MSEC) {
256  limit_msec = *(uint64_t *)value;
257  sr_dbg("demo: %s: setting limit_msec to %" PRIu64, __func__,
258  limit_msec);
259  ret = SR_OK;
260  } else if (hwcap == SR_HWCAP_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("demo: %s: setting pattern to %d", __func__,
277  default_pattern);
278  } else {
279  ret = SR_ERR;
280  }
281 
282  return ret;
283 }
284 
285 static void samples_generator(uint8_t *buf, uint64_t size, void *data)
286 {
287  static uint64_t p = 0;
288  struct context *ctx = data;
289  uint64_t i;
290 
291  /* TODO: Needed? */
292  memset(buf, 0, size);
293 
294  switch (ctx->sample_generator) {
295  case PATTERN_SIGROK: /* sigrok pattern */
296  for (i = 0; i < size; i++) {
297  *(buf + i) = ~(pattern_sigrok[p] >> 1);
298  if (++p == 64)
299  p = 0;
300  }
301  break;
302  case PATTERN_RANDOM: /* Random */
303  for (i = 0; i < size; i++)
304  *(buf + i) = (uint8_t)(rand() & 0xff);
305  break;
306  case PATTERN_INC: /* Simple increment */
307  for (i = 0; i < size; i++)
308  *(buf + i) = i;
309  break;
310  case PATTERN_ALL_LOW: /* All probes are low */
311  memset(buf, 0x00, size);
312  break;
313  case PATTERN_ALL_HIGH: /* All probes are high */
314  memset(buf, 0xff, size);
315  break;
316  default:
317  sr_err("demo: %s: unknown pattern %d", __func__,
318  ctx->sample_generator);
319  break;
320  }
321 }
322 
323 /* Thread function */
324 static void thread_func(void *data)
325 {
326  struct context *ctx = data;
327  uint8_t buf[BUFSIZE];
328  uint64_t nb_to_send = 0;
329  int bytes_written;
330  double time_cur, time_last, time_diff;
331 
332  time_last = g_timer_elapsed(ctx->timer, NULL);
333 
334  while (thread_running) {
335  /* Rate control */
336  time_cur = g_timer_elapsed(ctx->timer, NULL);
337 
338  time_diff = time_cur - time_last;
339  time_last = time_cur;
340 
341  nb_to_send = cur_samplerate * time_diff;
342 
343  if (limit_samples) {
344  nb_to_send = MIN(nb_to_send,
346  }
347 
348  /* Make sure we don't overflow. */
349  nb_to_send = MIN(nb_to_send, BUFSIZE);
350 
351  if (nb_to_send) {
352  samples_generator(buf, nb_to_send, data);
353  ctx->samples_counter += nb_to_send;
354 
355  g_io_channel_write_chars(channels[1], (gchar *)&buf,
356  nb_to_send, (gsize *)&bytes_written, NULL);
357  }
358 
359  /* Check if we're done. */
360  if ((limit_msec && time_cur * 1000 > limit_msec) ||
362  {
363  close(ctx->pipe_fds[1]);
364  thread_running = 0;
365  }
366 
367  g_usleep(10);
368  }
369 }
370 
371 /* Callback handling data */
372 static int receive_data(int fd, int revents, void *cb_data)
373 {
374  struct sr_datafeed_packet packet;
375  struct sr_datafeed_logic logic;
376  static uint64_t samples_received = 0;
377  unsigned char c[BUFSIZE];
378  gsize z;
379 
380  /* Avoid compiler warnings. */
381  (void)fd;
382  (void)revents;
383 
384  do {
385  g_io_channel_read_chars(channels[0],
386  (gchar *)&c, BUFSIZE, &z, NULL);
387 
388  if (z > 0) {
389  packet.type = SR_DF_LOGIC;
390  packet.payload = &logic;
391  logic.length = z;
392  logic.unitsize = 1;
393  logic.data = c;
394  sr_session_send(cb_data, &packet);
395  samples_received += z;
396  }
397  } while (z > 0);
398 
399  if (!thread_running && z <= 0) {
400  /* Make sure we don't receive more packets. */
401  g_io_channel_shutdown(channels[0], FALSE, NULL);
402 
403  /* Send last packet. */
404  packet.type = SR_DF_END;
405  sr_session_send(cb_data, &packet);
406 
407  return FALSE;
408  }
409 
410  return TRUE;
411 }
412 
413 static int hw_dev_acquisition_start(int dev_index, void *cb_data)
414 {
415  struct sr_datafeed_packet *packet;
416  struct sr_datafeed_header *header;
417  struct context *ctx;
418 
419  /* TODO: 'ctx' is never g_free()'d? */
420  if (!(ctx = g_try_malloc(sizeof(struct context)))) {
421  sr_err("demo: %s: ctx malloc failed", __func__);
422  return SR_ERR_MALLOC;
423  }
424 
425  ctx->sample_generator = default_pattern;
426  ctx->session_dev_id = cb_data;
427  ctx->dev_index = dev_index;
428  ctx->samples_counter = 0;
429 
430  if (pipe(ctx->pipe_fds)) {
431  /* TODO: Better error message. */
432  sr_err("demo: %s: pipe() failed", __func__);
433  return SR_ERR;
434  }
435 
436  channels[0] = g_io_channel_unix_new(ctx->pipe_fds[0]);
437  channels[1] = g_io_channel_unix_new(ctx->pipe_fds[1]);
438 
439  /* Set channel encoding to binary (default is UTF-8). */
440  g_io_channel_set_encoding(channels[0], NULL, NULL);
441  g_io_channel_set_encoding(channels[1], NULL, NULL);
442 
443  /* Make channels to unbuffered. */
444  g_io_channel_set_buffered(channels[0], FALSE);
445  g_io_channel_set_buffered(channels[1], FALSE);
446 
447  sr_source_add(ctx->pipe_fds[0], G_IO_IN | G_IO_ERR, 40,
448  receive_data, ctx->session_dev_id);
449 
450  /* Run the demo thread. */
451  g_thread_init(NULL);
452  /* This must to be done between g_thread_init() & g_thread_create(). */
453  ctx->timer = g_timer_new();
454  thread_running = 1;
455  my_thread =
456  g_thread_create((GThreadFunc)thread_func, ctx, TRUE, NULL);
457  if (!my_thread) {
458  sr_err("demo: %s: g_thread_create failed", __func__);
459  return SR_ERR; /* TODO */
460  }
461 
462  if (!(packet = g_try_malloc(sizeof(struct sr_datafeed_packet)))) {
463  sr_err("demo: %s: packet malloc failed", __func__);
464  return SR_ERR_MALLOC;
465  }
466 
467  if (!(header = g_try_malloc(sizeof(struct sr_datafeed_header)))) {
468  sr_err("demo: %s: header malloc failed", __func__);
469  return SR_ERR_MALLOC;
470  }
471 
472  packet->type = SR_DF_HEADER;
473  packet->payload = header;
474  header->feed_version = 1;
475  gettimeofday(&header->starttime, NULL);
476  header->samplerate = cur_samplerate;
477  header->num_logic_probes = NUM_PROBES;
478  sr_session_send(ctx->session_dev_id, packet);
479  g_free(header);
480  g_free(packet);
481 
482  return SR_OK;
483 }
484 
485 /* TODO: This stops acquisition on ALL devices, ignoring dev_index. */
486 static int hw_dev_acquisition_stop(int dev_index, void *cb_data)
487 {
488  /* Avoid compiler warnings. */
489  (void)dev_index;
490  (void)cb_data;
491 
492  /* Stop generate thread. */
493  thread_running = 0;
494 
495  return SR_OK;
496 }
497 
499  .name = "demo",
500  .longname = "Demo driver and pattern generator",
501  .api_version = 1,
502  .init = hw_init,
503  .cleanup = hw_cleanup,
504  .dev_open = hw_dev_open,
505  .dev_close = hw_dev_close,
506  .dev_info_get = hw_dev_info_get,
507  .dev_status_get = hw_dev_status_get,
508  .hwcap_get_all = hw_hwcap_get_all,
509  .dev_config_set = hw_dev_config_set,
510  .dev_acquisition_start = hw_dev_acquisition_start,
511  .dev_acquisition_stop = hw_dev_acquisition_stop,
512 };