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