]> sigrok.org Git - libsigrok.git/blame - hardware/demo/demo.c
serial-dmm: Add PCE PCE-DM32 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>
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
BV
80 uint8_t sample_generator;
81 uint8_t thread_running;
82 uint64_t samples_counter;
3cd3a20b 83 void *session_dev_id;
b9cc3629 84 GTimer *timer;
e15f48c2 85};
85b5af06 86
915f7cc8 87static const int hwcaps[] = {
5a2326a7 88 SR_HWCAP_LOGIC_ANALYZER,
bb7ef793 89 SR_HWCAP_DEMO_DEV,
4bfbf9fc 90 SR_HWCAP_SAMPLERATE,
5a2326a7
UH
91 SR_HWCAP_PATTERN_MODE,
92 SR_HWCAP_LIMIT_SAMPLES,
93 SR_HWCAP_LIMIT_MSEC,
94 SR_HWCAP_CONTINUOUS,
6239c175
UH
95};
96
a533743d 97static const struct sr_samplerates samplerates = {
c9140419 98 SR_HZ(1),
59df0c77 99 SR_GHZ(1),
c9140419 100 SR_HZ(1),
4bfbf9fc
BV
101 NULL,
102};
103
c8f4624d 104static const char *pattern_strings[] = {
c03ed397 105 "sigrok",
e15f48c2
BV
106 "random",
107 "incremental",
c03ed397
UH
108 "all-low",
109 "all-high",
02440dd8 110 NULL,
85b5af06
UH
111};
112
d261dbbf 113/* We name the probes 0-7 on our demo driver. */
464d12c7
KS
114static const char *probe_names[NUM_PROBES + 1] = {
115 "0",
116 "1",
117 "2",
118 "3",
119 "4",
120 "5",
121 "6",
122 "7",
123 NULL,
124};
125
c8f4624d 126static uint8_t pattern_sigrok[] = {
917e0e71
BV
127 0x4c, 0x92, 0x92, 0x92, 0x64, 0x00, 0x00, 0x00,
128 0x82, 0xfe, 0xfe, 0x82, 0x00, 0x00, 0x00, 0x00,
129 0x7c, 0x82, 0x82, 0x92, 0x74, 0x00, 0x00, 0x00,
130 0xfe, 0x12, 0x12, 0x32, 0xcc, 0x00, 0x00, 0x00,
131 0x7c, 0x82, 0x82, 0x82, 0x7c, 0x00, 0x00, 0x00,
132 0xfe, 0x10, 0x28, 0x44, 0x82, 0x00, 0x00, 0x00,
133 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
134 0xbe, 0xbe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
135};
136
ea9cfed7
UH
137/* Private, per-device-instance driver context. */
138/* TODO: struct context as with the other drivers. */
139
e7eb703f 140/* List of struct sr_dev_inst, maintained by dev_open()/dev_close(). */
dcf03d6d
BV
141SR_PRIV struct sr_dev_driver demo_driver_info;
142static struct sr_dev_driver *ddi = &demo_driver_info;
59df0c77 143static uint64_t cur_samplerate = SR_KHZ(200);
b9cc3629
BV
144static uint64_t limit_samples = 0;
145static uint64_t limit_msec = 0;
c8f4624d 146static int default_pattern = PATTERN_SIGROK;
b9cc3629
BV
147static GThread *my_thread;
148static int thread_running;
6239c175 149
69b07d14 150static int hw_dev_acquisition_stop(struct sr_dev_inst *sdi, void *cb_data);
6239c175 151
40dda2c3 152static int hw_init(void)
61136ea6 153{
b4750a3a 154 struct drv_context *drvc;
61136ea6 155
b4750a3a 156 if (!(drvc = g_try_malloc0(sizeof(struct drv_context)))) {
92bcedf6 157 sr_err("Driver context malloc failed.");
886a52b6 158 return SR_ERR_MALLOC;
b4750a3a
BV
159 }
160 ddi->priv = drvc;
61136ea6
BV
161
162 return SR_OK;
163}
164
067d0716 165static GSList *hw_scan(GSList *options)
6239c175 166{
d68e2d1a 167 struct sr_dev_inst *sdi;
87ca93c5 168 struct sr_probe *probe;
b4750a3a 169 struct drv_context *drvc;
067d0716 170 GSList *devices;
87ca93c5 171 int i;
067d0716
BV
172
173 (void)options;
64d33dc2 174
b4750a3a 175 drvc = ddi->priv;
067d0716 176 devices = NULL;
85b5af06 177
d3683c42 178 sdi = sr_dev_inst_new(0, SR_ST_ACTIVE, DEMONAME, NULL, NULL);
c03ed397 179 if (!sdi) {
92bcedf6 180 sr_err("%s: sr_dev_inst_new failed", __func__);
85b5af06 181 return 0;
c03ed397 182 }
7dfcf010 183 sdi->driver = ddi;
e15f48c2 184
87ca93c5 185 for (i = 0; probe_names[i]; i++) {
de6e0eca 186 if (!(probe = sr_probe_new(i, SR_PROBE_LOGIC, TRUE,
87ca93c5
BV
187 probe_names[i])))
188 return NULL;
189 sdi->probes = g_slist_append(sdi->probes, probe);
190 }
191
067d0716 192 devices = g_slist_append(devices, sdi);
b4750a3a 193 drvc->instances = g_slist_append(drvc->instances, sdi);
85b5af06 194
067d0716 195 return devices;
6239c175
UH
196}
197
811deee4
BV
198static GSList *hw_dev_list(void)
199{
200 struct drv_context *drvc;
201
202 drvc = ddi->priv;
203
204 return drvc->instances;
205}
206
25a0f108 207static int hw_dev_open(struct sr_dev_inst *sdi)
6239c175 208{
25a0f108 209 (void)sdi;
6239c175
UH
210
211 /* Nothing needed so far. */
697785d1 212
e46b8fb1 213 return SR_OK;
6239c175
UH
214}
215
25a0f108 216static int hw_dev_close(struct sr_dev_inst *sdi)
6239c175 217{
25a0f108 218 (void)sdi;
6239c175
UH
219
220 /* Nothing needed so far. */
697785d1
UH
221
222 return SR_OK;
6239c175
UH
223}
224
57ab7d9f 225static int hw_cleanup(void)
6239c175
UH
226{
227 /* Nothing needed so far. */
57ab7d9f 228 return SR_OK;
6239c175
UH
229}
230
dfb0fa1a
BV
231static int hw_info_get(int info_id, const void **data,
232 const struct sr_dev_inst *sdi)
6239c175 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;
92bcedf6 272 sr_dbg("%s: setting samplerate to %" PRIu64, __func__,
6f422264 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;
92bcedf6 278 sr_dbg("%s: setting limit_samples to %" PRIu64, __func__,
6f422264 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;
92bcedf6 284 sr_dbg("%s: setting limit_msec to %" PRIu64, __func__,
6f422264 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 }
92bcedf6 303 sr_dbg("%s: setting pattern to %d", __func__, default_pattern);
6239c175 304 } else {
e46b8fb1 305 ret = SR_ERR;
6239c175
UH
306 }
307
308 return ret;
309}
310
5096c6a6 311static void samples_generator(uint8_t *buf, uint64_t size, void *data)
85b5af06 312{
cddd1c5f 313 static uint64_t p = 0;
b4750a3a 314 struct dev_context *devc = data;
cddd1c5f 315 uint64_t i;
85b5af06 316
c03ed397 317 /* TODO: Needed? */
5096c6a6 318 memset(buf, 0, size);
85b5af06 319
b4750a3a 320 switch (devc->sample_generator) {
c03ed397 321 case PATTERN_SIGROK: /* sigrok pattern */
917e0e71 322 for (i = 0; i < size; i++) {
c8f4624d 323 *(buf + i) = ~(pattern_sigrok[p] >> 1);
917e0e71
BV
324 if (++p == 64)
325 p = 0;
326 }
327 break;
c8f4624d 328 case PATTERN_RANDOM: /* Random */
5096c6a6
UH
329 for (i = 0; i < size; i++)
330 *(buf + i) = (uint8_t)(rand() & 0xff);
85b5af06 331 break;
c8f4624d 332 case PATTERN_INC: /* Simple increment */
5096c6a6 333 for (i = 0; i < size; i++)
85b5af06
UH
334 *(buf + i) = i;
335 break;
c03ed397 336 case PATTERN_ALL_LOW: /* All probes are low */
5a9660dd 337 memset(buf, 0x00, size);
c03ed397
UH
338 break;
339 case PATTERN_ALL_HIGH: /* All probes are high */
5a9660dd 340 memset(buf, 0xff, size);
c03ed397
UH
341 break;
342 default:
92bcedf6 343 sr_err("Unknown pattern: %d.", devc->sample_generator);
c03ed397 344 break;
85b5af06
UH
345 }
346}
347
348/* Thread function */
349static void thread_func(void *data)
350{
b4750a3a 351 struct dev_context *devc = data;
85b5af06
UH
352 uint8_t buf[BUFSIZE];
353 uint64_t nb_to_send = 0;
d35aaf02 354 int bytes_written;
1924f59f
HE
355 double time_cur, time_last, time_diff;
356
b4750a3a 357 time_last = g_timer_elapsed(devc->timer, NULL);
85b5af06
UH
358
359 while (thread_running) {
1924f59f 360 /* Rate control */
b4750a3a 361 time_cur = g_timer_elapsed(devc->timer, NULL);
1924f59f
HE
362
363 time_diff = time_cur - time_last;
364 time_last = time_cur;
365
366 nb_to_send = cur_samplerate * time_diff;
367
c03ed397 368 if (limit_samples) {
1924f59f 369 nb_to_send = MIN(nb_to_send,
b4750a3a 370 limit_samples - devc->samples_counter);
c03ed397 371 }
1924f59f
HE
372
373 /* Make sure we don't overflow. */
374 nb_to_send = MIN(nb_to_send, BUFSIZE);
375
376 if (nb_to_send) {
377 samples_generator(buf, nb_to_send, data);
b4750a3a 378 devc->samples_counter += nb_to_send;
070befcd 379
b4750a3a 380 g_io_channel_write_chars(devc->channels[1], (gchar *)&buf,
c03ed397 381 nb_to_send, (gsize *)&bytes_written, NULL);
b9cc3629
BV
382 }
383
1924f59f
HE
384 /* Check if we're done. */
385 if ((limit_msec && time_cur * 1000 > limit_msec) ||
b4750a3a 386 (limit_samples && devc->samples_counter >= limit_samples))
1924f59f 387 {
b4750a3a 388 close(devc->pipe_fds[1]);
85b5af06 389 thread_running = 0;
85b5af06
UH
390 }
391
1924f59f 392 g_usleep(10);
85b5af06
UH
393 }
394}
395
396/* Callback handling data */
1f9813eb 397static int receive_data(int fd, int revents, void *cb_data)
85b5af06 398{
b4750a3a 399 struct dev_context *devc = cb_data;
b9c735a2 400 struct sr_datafeed_packet packet;
9c939c51
BV
401 struct sr_datafeed_logic logic;
402 static uint64_t samples_received = 0;
403 unsigned char c[BUFSIZE];
108a5bfb 404 gsize z;
1924f59f 405
cb93f8a9
UH
406 (void)fd;
407 (void)revents;
1924f59f
HE
408
409 do {
b4750a3a 410 g_io_channel_read_chars(devc->channels[0],
070befcd 411 (gchar *)&c, BUFSIZE, &z, NULL);
1924f59f
HE
412
413 if (z > 0) {
5a2326a7 414 packet.type = SR_DF_LOGIC;
9c939c51 415 packet.payload = &logic;
9c939c51
BV
416 logic.length = z;
417 logic.unitsize = 1;
418 logic.data = c;
b4750a3a 419 sr_session_send(devc->session_dev_id, &packet);
9c939c51 420 samples_received += z;
1924f59f
HE
421 }
422 } while (z > 0);
85b5af06 423
c03ed397
UH
424 if (!thread_running && z <= 0) {
425 /* Make sure we don't receive more packets. */
c216d623
AG
426 hw_dev_acquisition_stop(NULL, cb_data);
427 return TRUE;
85b5af06 428 }
1924f59f 429
85b5af06
UH
430 return TRUE;
431}
432
3ffb6964
BV
433static int hw_dev_acquisition_start(const struct sr_dev_inst *sdi,
434 void *cb_data)
6239c175 435{
b9c735a2
UH
436 struct sr_datafeed_packet *packet;
437 struct sr_datafeed_header *header;
f366e86c 438 struct sr_datafeed_meta_logic meta;
b4750a3a 439 struct dev_context *devc;
6239c175 440
3ffb6964
BV
441 (void)sdi;
442
49145a63
AG
443 sr_dbg("Starting acquisition.");
444
b4750a3a
BV
445 /* TODO: 'devc' is never g_free()'d? */
446 if (!(devc = g_try_malloc(sizeof(struct dev_context)))) {
92bcedf6 447 sr_err("%s: devc malloc failed", __func__);
e46b8fb1 448 return SR_ERR_MALLOC;
27a3a6fe 449 }
85b5af06 450
b4750a3a
BV
451 devc->sample_generator = default_pattern;
452 devc->session_dev_id = cb_data;
453 devc->samples_counter = 0;
85b5af06 454
b4750a3a 455 if (pipe(devc->pipe_fds)) {
c03ed397 456 /* TODO: Better error message. */
92bcedf6 457 sr_err("%s: pipe() failed", __func__);
e46b8fb1 458 return SR_ERR;
c03ed397 459 }
85b5af06 460
b4750a3a
BV
461 devc->channels[0] = g_io_channel_unix_new(devc->pipe_fds[0]);
462 devc->channels[1] = g_io_channel_unix_new(devc->pipe_fds[1]);
d35aaf02 463
b4750a3a 464 g_io_channel_set_flags(devc->channels[0], G_IO_FLAG_NONBLOCK, NULL);
e6e8f8e0 465
d35aaf02 466 /* Set channel encoding to binary (default is UTF-8). */
b4750a3a
BV
467 g_io_channel_set_encoding(devc->channels[0], NULL, NULL);
468 g_io_channel_set_encoding(devc->channels[1], NULL, NULL);
d35aaf02
UH
469
470 /* Make channels to unbuffered. */
b4750a3a
BV
471 g_io_channel_set_buffered(devc->channels[0], FALSE);
472 g_io_channel_set_buffered(devc->channels[1], FALSE);
d35aaf02 473
b4750a3a
BV
474 sr_session_source_add_channel(devc->channels[0], G_IO_IN | G_IO_ERR,
475 40, receive_data, devc);
85b5af06
UH
476
477 /* Run the demo thread. */
b4750a3a 478 devc->timer = g_timer_new();
85b5af06 479 thread_running = 1;
4ca378df
BV
480 my_thread = g_thread_try_new("sigrok demo generator",
481 (GThreadFunc)thread_func, devc, NULL);
c03ed397 482 if (!my_thread) {
92bcedf6 483 sr_err("%s: g_thread_try_new failed", __func__);
c03ed397
UH
484 return SR_ERR; /* TODO */
485 }
6239c175 486
27a3a6fe 487 if (!(packet = g_try_malloc(sizeof(struct sr_datafeed_packet)))) {
92bcedf6 488 sr_err("%s: packet malloc failed", __func__);
e46b8fb1 489 return SR_ERR_MALLOC;
27a3a6fe
UH
490 }
491
492 if (!(header = g_try_malloc(sizeof(struct sr_datafeed_header)))) {
92bcedf6 493 sr_err("%s: header malloc failed", __func__);
27a3a6fe
UH
494 return SR_ERR_MALLOC;
495 }
6239c175 496
5a2326a7 497 packet->type = SR_DF_HEADER;
9c939c51 498 packet->payload = header;
6239c175
UH
499 header->feed_version = 1;
500 gettimeofday(&header->starttime, NULL);
b4750a3a 501 sr_session_send(devc->session_dev_id, packet);
f366e86c
BV
502
503 /* Send metadata about the SR_DF_LOGIC packets to come. */
504 packet->type = SR_DF_META_LOGIC;
505 packet->payload = &meta;
506 meta.samplerate = cur_samplerate;
507 meta.num_probes = NUM_PROBES;
b4750a3a 508 sr_session_send(devc->session_dev_id, packet);
f366e86c 509
27a3a6fe
UH
510 g_free(header);
511 g_free(packet);
6239c175 512
e46b8fb1 513 return SR_OK;
6239c175
UH
514}
515
69b07d14 516static int hw_dev_acquisition_stop(struct sr_dev_inst *sdi, void *cb_data)
6239c175 517{
7fd3e859 518 struct dev_context *devc;
c216d623 519 struct sr_datafeed_packet packet;
7fd3e859 520
c216d623 521 (void)sdi;
6239c175 522
c216d623 523 devc = cb_data;
7fd3e859 524
49145a63
AG
525 sr_dbg("Stopping aquisition.");
526
1924f59f
HE
527 /* Stop generate thread. */
528 thread_running = 0;
3010f21c 529
7fd3e859 530 sr_session_source_remove_channel(devc->channels[0]);
c216d623
AG
531 g_io_channel_shutdown(devc->channels[0], FALSE, NULL);
532
533 /* Send last packet. */
534 packet.type = SR_DF_END;
535 sr_session_send(devc->session_dev_id, &packet);
7fd3e859 536
3010f21c 537 return SR_OK;
6239c175
UH
538}
539
c09f0b57 540SR_PRIV struct sr_dev_driver demo_driver_info = {
e519ba86
UH
541 .name = "demo",
542 .longname = "Demo driver and pattern generator",
543 .api_version = 1,
544 .init = hw_init,
545 .cleanup = hw_cleanup,
61136ea6 546 .scan = hw_scan,
811deee4 547 .dev_list = hw_dev_list,
e7eb703f
UH
548 .dev_open = hw_dev_open,
549 .dev_close = hw_dev_close,
dfb0fa1a 550 .info_get = hw_info_get,
a9a245b4 551 .dev_config_set = hw_dev_config_set,
69040b7c
UH
552 .dev_acquisition_start = hw_dev_acquisition_start,
553 .dev_acquisition_stop = hw_dev_acquisition_stop,
b4750a3a 554 .priv = NULL,
6239c175 555};