]> sigrok.org Git - libsigrok.git/blame - hardware/openbench-logic-sniffer/api.c
probe_groups: API changes required to implement probe groups.
[libsigrok.git] / hardware / openbench-logic-sniffer / api.c
CommitLineData
0aba65da 1/*
50985c20 2 * This file is part of the libsigrok project.
0aba65da 3 *
13d8e03c 4 * Copyright (C) 2013 Bert Vermeulen <bert@biot.com>
0aba65da
UH
5 *
6 * This program is free software: you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation, either version 3 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program. If not, see <http://www.gnu.org/licenses/>.
18 */
19
20#include "protocol.h"
21
22#define SERIALCOMM "115200/8n1"
23
e46aa4f6 24static const int32_t hwopts[] = {
1953564a
BV
25 SR_CONF_CONN,
26 SR_CONF_SERIALCOMM,
aeabd308
UH
27};
28
e46aa4f6 29static const int32_t hwcaps[] = {
1953564a
BV
30 SR_CONF_LOGIC_ANALYZER,
31 SR_CONF_SAMPLERATE,
0c05591a 32 SR_CONF_TRIGGER_TYPE,
1953564a
BV
33 SR_CONF_CAPTURE_RATIO,
34 SR_CONF_LIMIT_SAMPLES,
eb1b610b 35 SR_CONF_EXTERNAL_CLOCK,
967760a8 36 SR_CONF_PATTERN_MODE,
7b0a57fd 37 SR_CONF_SWAP,
1953564a 38 SR_CONF_RLE,
0aba65da
UH
39};
40
967760a8
MR
41#define STR_PATTERN_EXTERNAL "external"
42#define STR_PATTERN_INTERNAL "internal"
43
44/* Supported methods of test pattern outputs */
45enum {
46 /**
47 * Capture pins 31:16 (unbuffered wing) output a test pattern
48 * that can captured on pins 0:15.
49 */
50 PATTERN_EXTERNAL,
51
52 /** Route test pattern internally to capture buffer. */
53 PATTERN_INTERNAL,
54};
55
0aba65da
UH
56/* Probes are numbered 0-31 (on the PCB silkscreen). */
57SR_PRIV const char *ols_probe_names[NUM_PROBES + 1] = {
78693401
UH
58 "0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12",
59 "13", "14", "15", "16", "17", "18", "19", "20", "21", "22", "23",
60 "24", "25", "26", "27", "28", "29", "30", "31",
0aba65da
UH
61 NULL,
62};
63
d3b38ad3 64/* Default supported samplerates, can be overridden by device metadata. */
e46aa4f6
BV
65static const uint64_t samplerates[] = {
66 SR_HZ(10),
67 SR_MHZ(200),
68 SR_HZ(1),
0aba65da
UH
69};
70
71SR_PRIV struct sr_dev_driver ols_driver_info;
72static struct sr_dev_driver *di = &ols_driver_info;
73
eea49cf1
UH
74static int dev_clear(void)
75{
76 return std_dev_clear(di, NULL);
77}
78
03f4de8c 79static int init(struct sr_context *sr_ctx)
0aba65da 80{
f6beaac5 81 return std_init(sr_ctx, di, LOG_PREFIX);
0aba65da
UH
82}
83
03f4de8c 84static GSList *scan(GSList *options)
0aba65da 85{
1987b8d6 86 struct sr_config *src;
0aba65da
UH
87 struct sr_dev_inst *sdi;
88 struct drv_context *drvc;
89 struct dev_context *devc;
90 struct sr_probe *probe;
91 struct sr_serial_dev_inst *serial;
92 GPollFD probefd;
93 GSList *l, *devices;
94 int ret, i;
95 const char *conn, *serialcomm;
96 char buf[8];
97
0aba65da 98 drvc = di->priv;
4b97c74e 99
0aba65da
UH
100 devices = NULL;
101
102 conn = serialcomm = NULL;
103 for (l = options; l; l = l->next) {
1987b8d6
BV
104 src = l->data;
105 switch (src->key) {
1953564a 106 case SR_CONF_CONN:
e46aa4f6 107 conn = g_variant_get_string(src->data, NULL);
0aba65da 108 break;
1953564a 109 case SR_CONF_SERIALCOMM:
e46aa4f6 110 serialcomm = g_variant_get_string(src->data, NULL);
0aba65da
UH
111 break;
112 }
113 }
114 if (!conn)
115 return NULL;
116
117 if (serialcomm == NULL)
118 serialcomm = SERIALCOMM;
119
120 if (!(serial = sr_serial_dev_inst_new(conn, serialcomm)))
121 return NULL;
122
123 /* The discovery procedure is like this: first send the Reset
124 * command (0x00) 5 times, since the device could be anywhere
125 * in a 5-byte command. Then send the ID command (0x02).
126 * If the device responds with 4 bytes ("OLS1" or "SLA1"), we
127 * have a match.
128 */
129 sr_info("Probing %s.", conn);
130 if (serial_open(serial, SERIAL_RDWR | SERIAL_NONBLOCK) != SR_OK)
131 return NULL;
132
133 ret = SR_OK;
134 for (i = 0; i < 5; i++) {
135 if ((ret = send_shortcommand(serial, CMD_RESET)) != SR_OK) {
136 sr_err("Port %s is not writable.", conn);
137 break;
138 }
139 }
140 if (ret != SR_OK) {
141 serial_close(serial);
142 sr_err("Could not use port %s. Quitting.", conn);
143 return NULL;
144 }
145 send_shortcommand(serial, CMD_ID);
146
147 /* Wait 10ms for a response. */
148 g_usleep(10000);
149
150 probefd.fd = serial->fd;
151 probefd.events = G_IO_IN;
152 g_poll(&probefd, 1, 1);
153
154 if (probefd.revents != G_IO_IN)
155 return NULL;
156 if (serial_read(serial, buf, 4) != 4)
157 return NULL;
158 if (strncmp(buf, "1SLO", 4) && strncmp(buf, "1ALS", 4))
159 return NULL;
160
161 /* Definitely using the OLS protocol, check if it supports
162 * the metadata command.
163 */
164 send_shortcommand(serial, CMD_METADATA);
165 if (g_poll(&probefd, 1, 10) > 0) {
166 /* Got metadata. */
167 sdi = get_metadata(serial);
168 sdi->index = 0;
169 devc = sdi->priv;
170 } else {
171 /* Not an OLS -- some other board that uses the sump protocol. */
72cd99b8 172 sr_info("Device does not support metadata.");
0aba65da
UH
173 sdi = sr_dev_inst_new(0, SR_ST_INACTIVE,
174 "Sump", "Logic Analyzer", "v1.0");
175 sdi->driver = di;
0aba65da
UH
176 for (i = 0; i < 32; i++) {
177 if (!(probe = sr_probe_new(i, SR_PROBE_LOGIC, TRUE,
178 ols_probe_names[i])))
179 return 0;
180 sdi->probes = g_slist_append(sdi->probes, probe);
181 }
bf256783 182 devc = ols_dev_new();
0aba65da
UH
183 sdi->priv = devc;
184 }
bf256783
BV
185 /* Configure samplerate and divider. */
186 if (ols_set_samplerate(sdi, DEFAULT_SAMPLERATE) != SR_OK)
187 sr_dbg("Failed to set default samplerate (%"PRIu64").",
188 DEFAULT_SAMPLERATE);
189 /* Clear trigger masks, values and stages. */
190 ols_configure_probes(sdi);
459a0f26
BV
191 sdi->inst_type = SR_INST_SERIAL;
192 sdi->conn = serial;
bf256783 193
0aba65da
UH
194 drvc->instances = g_slist_append(drvc->instances, sdi);
195 devices = g_slist_append(devices, sdi);
196
197 serial_close(serial);
198
199 return devices;
200}
201
03f4de8c 202static GSList *dev_list(void)
0aba65da 203{
0e94d524 204 return ((struct drv_context *)(di->priv))->instances;
0aba65da
UH
205}
206
03f4de8c 207static int dev_open(struct sr_dev_inst *sdi)
0aba65da 208{
459a0f26 209 struct sr_serial_dev_inst *serial;
0aba65da 210
459a0f26
BV
211 serial = sdi->conn;
212 if (serial_open(serial, SERIAL_RDWR) != SR_OK)
0aba65da
UH
213 return SR_ERR;
214
215 sdi->status = SR_ST_ACTIVE;
216
217 return SR_OK;
218}
219
03f4de8c 220static int dev_close(struct sr_dev_inst *sdi)
0aba65da 221{
459a0f26 222 struct sr_serial_dev_inst *serial;
0aba65da 223
459a0f26
BV
224 serial = sdi->conn;
225 if (serial && serial->fd != -1) {
226 serial_close(serial);
0aba65da
UH
227 sdi->status = SR_ST_INACTIVE;
228 }
229
230 return SR_OK;
231}
232
eea49cf1 233static int cleanup(void)
0aba65da 234{
eea49cf1 235 return dev_clear();
0aba65da
UH
236}
237
8f996b89
ML
238static int config_get(int id, GVariant **data, const struct sr_dev_inst *sdi,
239 const struct sr_probe_group *probe_group)
0aba65da
UH
240{
241 struct dev_context *devc;
242
8f996b89
ML
243 (void)probe_group;
244
0c05591a
BV
245 if (!sdi)
246 return SR_ERR_ARG;
247
248 devc = sdi->priv;
035a1078 249 switch (id) {
123e1313 250 case SR_CONF_SAMPLERATE:
0c05591a
BV
251 *data = g_variant_new_uint64(devc->cur_samplerate);
252 break;
253 case SR_CONF_CAPTURE_RATIO:
254 *data = g_variant_new_uint64(devc->capture_ratio);
255 break;
256 case SR_CONF_LIMIT_SAMPLES:
257 *data = g_variant_new_uint64(devc->limit_samples);
258 break;
967760a8
MR
259 case SR_CONF_PATTERN_MODE:
260 if (devc->flag_reg & FLAG_EXTERNAL_TEST_MODE)
261 *data = g_variant_new_string(STR_PATTERN_EXTERNAL);
262 else if (devc->flag_reg & FLAG_INTERNAL_TEST_MODE)
263 *data = g_variant_new_string(STR_PATTERN_INTERNAL);
264 break;
0c05591a
BV
265 case SR_CONF_RLE:
266 *data = g_variant_new_boolean(devc->flag_reg & FLAG_RLE ? TRUE : FALSE);
0aba65da
UH
267 break;
268 default:
bd6fbf62 269 return SR_ERR_NA;
0aba65da
UH
270 }
271
272 return SR_OK;
273}
274
8f996b89
ML
275static int config_set(int id, GVariant *data, const struct sr_dev_inst *sdi,
276 const struct sr_probe_group *probe_group)
0aba65da
UH
277{
278 struct dev_context *devc;
279 int ret;
e46aa4f6 280 uint64_t tmp_u64;
967760a8 281 const char *stropt;
0aba65da 282
8f996b89
ML
283 (void)probe_group;
284
e73ffd42
BV
285 if (sdi->status != SR_ST_ACTIVE)
286 return SR_ERR_DEV_CLOSED;
287
0aba65da
UH
288 devc = sdi->priv;
289
035a1078 290 switch (id) {
1953564a 291 case SR_CONF_SAMPLERATE:
e46aa4f6
BV
292 tmp_u64 = g_variant_get_uint64(data);
293 if (tmp_u64 < samplerates[0] || tmp_u64 > samplerates[1])
294 return SR_ERR_SAMPLERATE;
295 ret = ols_set_samplerate(sdi, g_variant_get_uint64(data));
0aba65da 296 break;
1953564a 297 case SR_CONF_LIMIT_SAMPLES:
e46aa4f6
BV
298 tmp_u64 = g_variant_get_uint64(data);
299 if (tmp_u64 < MIN_NUM_SAMPLES)
0aba65da 300 return SR_ERR;
e46aa4f6 301 devc->limit_samples = tmp_u64;
0aba65da
UH
302 ret = SR_OK;
303 break;
1953564a 304 case SR_CONF_CAPTURE_RATIO:
e46aa4f6 305 devc->capture_ratio = g_variant_get_uint64(data);
0aba65da
UH
306 if (devc->capture_ratio < 0 || devc->capture_ratio > 100) {
307 devc->capture_ratio = 0;
308 ret = SR_ERR;
309 } else
310 ret = SR_OK;
311 break;
eb1b610b
MR
312 case SR_CONF_EXTERNAL_CLOCK:
313 if (g_variant_get_boolean(data)) {
314 sr_info("Enabling external clock.");
315 devc->flag_reg |= FLAG_CLOCK_EXTERNAL;
316 } else {
317 sr_info("Disabled external clock.");
318 devc->flag_reg &= ~FLAG_CLOCK_EXTERNAL;
319 }
320 ret = SR_OK;
321 break;
967760a8
MR
322 case SR_CONF_PATTERN_MODE:
323 stropt = g_variant_get_string(data, NULL);
324 ret = SR_OK;
325 if (!strcmp(stropt, STR_PATTERN_INTERNAL)) {
326 sr_info("Enabling internal test mode.");
327 devc->flag_reg |= FLAG_INTERNAL_TEST_MODE;
328 } else if (!strcmp(stropt, STR_PATTERN_EXTERNAL)) {
329 sr_info("Enabling external test mode.");
330 devc->flag_reg |= FLAG_EXTERNAL_TEST_MODE;
331 } else {
332 ret = SR_ERR;
333 }
334 break;
7b0a57fd
MR
335 case SR_CONF_SWAP:
336 if (g_variant_get_boolean(data)) {
337 sr_info("Enabling channel swapping.");
338 devc->flag_reg |= FLAG_SWAP_PROBES;
339 } else {
340 sr_info("Disabling channel swapping.");
341 devc->flag_reg &= ~FLAG_SWAP_PROBES;
342 }
343 ret = SR_OK;
344 break;
345
1953564a 346 case SR_CONF_RLE:
e46aa4f6 347 if (g_variant_get_boolean(data)) {
0aba65da
UH
348 sr_info("Enabling RLE.");
349 devc->flag_reg |= FLAG_RLE;
aeea0572
BV
350 } else {
351 sr_info("Disabling RLE.");
352 devc->flag_reg &= ~FLAG_RLE;
0aba65da
UH
353 }
354 ret = SR_OK;
355 break;
356 default:
bd6fbf62 357 ret = SR_ERR_NA;
0aba65da
UH
358 }
359
360 return ret;
361}
362
8f996b89
ML
363static int config_list(int key, GVariant **data, const struct sr_dev_inst *sdi,
364 const struct sr_probe_group *probe_group)
a1c743fc 365{
e46aa4f6
BV
366 GVariant *gvar;
367 GVariantBuilder gvb;
a1c743fc
BV
368
369 (void)sdi;
8f996b89 370 (void)probe_group;
a1c743fc
BV
371
372 switch (key) {
0d485e30 373 case SR_CONF_SCAN_OPTIONS:
e46aa4f6
BV
374 *data = g_variant_new_fixed_array(G_VARIANT_TYPE_INT32,
375 hwopts, ARRAY_SIZE(hwopts), sizeof(int32_t));
0d485e30 376 break;
9a6517d1 377 case SR_CONF_DEVICE_OPTIONS:
e46aa4f6
BV
378 *data = g_variant_new_fixed_array(G_VARIANT_TYPE_INT32,
379 hwcaps, ARRAY_SIZE(hwcaps), sizeof(int32_t));
9a6517d1 380 break;
a1c743fc 381 case SR_CONF_SAMPLERATE:
e46aa4f6
BV
382 g_variant_builder_init(&gvb, G_VARIANT_TYPE("a{sv}"));
383 gvar = g_variant_new_fixed_array(G_VARIANT_TYPE("t"), samplerates,
384 ARRAY_SIZE(samplerates), sizeof(uint64_t));
385 g_variant_builder_add(&gvb, "{sv}", "samplerate-steps", gvar);
386 *data = g_variant_builder_end(&gvb);
a1c743fc 387 break;
c50277a6 388 case SR_CONF_TRIGGER_TYPE:
e46aa4f6 389 *data = g_variant_new_string(TRIGGER_TYPE);
c50277a6 390 break;
a1c743fc 391 default:
bd6fbf62 392 return SR_ERR_NA;
a1c743fc
BV
393 }
394
395 return SR_OK;
396}
397
03f4de8c 398static int dev_acquisition_start(const struct sr_dev_inst *sdi,
0aba65da
UH
399 void *cb_data)
400{
0aba65da 401 struct dev_context *devc;
459a0f26 402 struct sr_serial_dev_inst *serial;
0aba65da
UH
403 uint32_t trigger_config[4];
404 uint32_t data;
405 uint16_t readcount, delaycount;
406 uint8_t changrp_mask;
407 int num_channels;
408 int i;
409
e73ffd42
BV
410 if (sdi->status != SR_ST_ACTIVE)
411 return SR_ERR_DEV_CLOSED;
412
0aba65da 413 devc = sdi->priv;
459a0f26 414 serial = sdi->conn;
0aba65da 415
0aba65da
UH
416 if (ols_configure_probes(sdi) != SR_OK) {
417 sr_err("Failed to configure probes.");
418 return SR_ERR;
419 }
420
421 /*
422 * Enable/disable channel groups in the flag register according to the
423 * probe mask. Calculate this here, because num_channels is needed
424 * to limit readcount.
425 */
426 changrp_mask = 0;
427 num_channels = 0;
428 for (i = 0; i < 4; i++) {
429 if (devc->probe_mask & (0xff << (i * 8))) {
430 changrp_mask |= (1 << i);
431 num_channels++;
432 }
433 }
434
435 /*
436 * Limit readcount to prevent reading past the end of the hardware
437 * buffer.
438 */
439 readcount = MIN(devc->max_samples / num_channels, devc->limit_samples) / 4;
440
441 memset(trigger_config, 0, 16);
2e5b73c0 442 trigger_config[devc->num_stages] |= 0x08;
0aba65da
UH
443 if (devc->trigger_mask[0]) {
444 delaycount = readcount * (1 - devc->capture_ratio / 100.0);
445 devc->trigger_at = (readcount - delaycount) * 4 - devc->num_stages;
446
459a0f26 447 if (send_longcommand(serial, CMD_SET_TRIGGER_MASK_0,
0aba65da
UH
448 reverse32(devc->trigger_mask[0])) != SR_OK)
449 return SR_ERR;
459a0f26 450 if (send_longcommand(serial, CMD_SET_TRIGGER_VALUE_0,
0aba65da
UH
451 reverse32(devc->trigger_value[0])) != SR_OK)
452 return SR_ERR;
459a0f26 453 if (send_longcommand(serial, CMD_SET_TRIGGER_CONFIG_0,
0aba65da
UH
454 trigger_config[0]) != SR_OK)
455 return SR_ERR;
456
459a0f26 457 if (send_longcommand(serial, CMD_SET_TRIGGER_MASK_1,
0aba65da
UH
458 reverse32(devc->trigger_mask[1])) != SR_OK)
459 return SR_ERR;
459a0f26 460 if (send_longcommand(serial, CMD_SET_TRIGGER_VALUE_1,
0aba65da
UH
461 reverse32(devc->trigger_value[1])) != SR_OK)
462 return SR_ERR;
459a0f26 463 if (send_longcommand(serial, CMD_SET_TRIGGER_CONFIG_1,
0aba65da
UH
464 trigger_config[1]) != SR_OK)
465 return SR_ERR;
466
459a0f26 467 if (send_longcommand(serial, CMD_SET_TRIGGER_MASK_2,
0aba65da
UH
468 reverse32(devc->trigger_mask[2])) != SR_OK)
469 return SR_ERR;
459a0f26 470 if (send_longcommand(serial, CMD_SET_TRIGGER_VALUE_2,
0aba65da
UH
471 reverse32(devc->trigger_value[2])) != SR_OK)
472 return SR_ERR;
459a0f26 473 if (send_longcommand(serial, CMD_SET_TRIGGER_CONFIG_2,
0aba65da
UH
474 trigger_config[2]) != SR_OK)
475 return SR_ERR;
476
459a0f26 477 if (send_longcommand(serial, CMD_SET_TRIGGER_MASK_3,
0aba65da
UH
478 reverse32(devc->trigger_mask[3])) != SR_OK)
479 return SR_ERR;
459a0f26 480 if (send_longcommand(serial, CMD_SET_TRIGGER_VALUE_3,
0aba65da
UH
481 reverse32(devc->trigger_value[3])) != SR_OK)
482 return SR_ERR;
459a0f26 483 if (send_longcommand(serial, CMD_SET_TRIGGER_CONFIG_3,
0aba65da
UH
484 trigger_config[3]) != SR_OK)
485 return SR_ERR;
486 } else {
459a0f26 487 if (send_longcommand(serial, CMD_SET_TRIGGER_MASK_0,
0aba65da
UH
488 devc->trigger_mask[0]) != SR_OK)
489 return SR_ERR;
459a0f26 490 if (send_longcommand(serial, CMD_SET_TRIGGER_VALUE_0,
0aba65da
UH
491 devc->trigger_value[0]) != SR_OK)
492 return SR_ERR;
459a0f26 493 if (send_longcommand(serial, CMD_SET_TRIGGER_CONFIG_0,
0aba65da
UH
494 0x00000008) != SR_OK)
495 return SR_ERR;
496 delaycount = readcount;
497 }
498
499 sr_info("Setting samplerate to %" PRIu64 "Hz (divider %u, "
de524099
MR
500 "demux %s, noise_filter %s)", devc->cur_samplerate,
501 devc->cur_samplerate_divider,
502 devc->flag_reg & FLAG_DEMUX ? "on" : "off",
503 devc->flag_reg & FLAG_FILTER ? "on": "off");
459a0f26 504 if (send_longcommand(serial, CMD_SET_DIVIDER,
0aba65da
UH
505 reverse32(devc->cur_samplerate_divider)) != SR_OK)
506 return SR_ERR;
507
508 /* Send sample limit and pre/post-trigger capture ratio. */
509 data = ((readcount - 1) & 0xffff) << 16;
510 data |= (delaycount - 1) & 0xffff;
459a0f26 511 if (send_longcommand(serial, CMD_CAPTURE_SIZE, reverse16(data)) != SR_OK)
0aba65da
UH
512 return SR_ERR;
513
514 /* The flag register wants them here, and 1 means "disable channel". */
515 devc->flag_reg |= ~(changrp_mask << 2) & 0x3c;
0aba65da
UH
516 devc->rle_count = 0;
517 data = (devc->flag_reg << 24) | ((devc->flag_reg << 8) & 0xff0000);
459a0f26 518 if (send_longcommand(serial, CMD_SET_FLAGS, data) != SR_OK)
0aba65da
UH
519 return SR_ERR;
520
521 /* Start acquisition on the device. */
459a0f26 522 if (send_shortcommand(serial, CMD_RUN) != SR_OK)
0aba65da
UH
523 return SR_ERR;
524
bf256783
BV
525 /* Reset all operational states. */
526 devc->num_transfers = devc->num_samples = devc->num_bytes = 0;
abb39e6b 527 memset(devc->sample, 0, 4);
bf256783 528
4afdfd46 529 /* Send header packet to the session bus. */
29a27196 530 std_session_send_df_header(cb_data, LOG_PREFIX);
4afdfd46 531
459a0f26 532 sr_source_add(serial->fd, G_IO_IN, -1, ols_receive_data, cb_data);
0aba65da 533
0aba65da
UH
534 return SR_OK;
535}
536
03f4de8c 537static int dev_acquisition_stop(struct sr_dev_inst *sdi, void *cb_data)
0aba65da 538{
0aba65da
UH
539 (void)cb_data;
540
541 abort_acquisition(sdi);
542
543 return SR_OK;
544}
545
546SR_PRIV struct sr_dev_driver ols_driver_info = {
547 .name = "ols",
548 .longname = "Openbench Logic Sniffer",
549 .api_version = 1,
03f4de8c 550 .init = init,
eea49cf1 551 .cleanup = cleanup,
03f4de8c
BV
552 .scan = scan,
553 .dev_list = dev_list,
554 .dev_clear = dev_clear,
035a1078
BV
555 .config_get = config_get,
556 .config_set = config_set,
a1c743fc 557 .config_list = config_list,
03f4de8c
BV
558 .dev_open = dev_open,
559 .dev_close = dev_close,
560 .dev_acquisition_start = dev_acquisition_start,
561 .dev_acquisition_stop = dev_acquisition_stop,
0aba65da
UH
562 .priv = NULL,
563};