]> sigrok.org Git - libsigrok.git/blame - src/session.c
Fix two more format warnings uncovered by MinGW build
[libsigrok.git] / src / session.c
CommitLineData
a1bb33af 1/*
50985c20 2 * This file is part of the libsigrok project.
a1bb33af 3 *
c73d2ea4 4 * Copyright (C) 2010-2012 Bert Vermeulen <bert@biot.com>
c2bf5506 5 * Copyright (C) 2015 Daniel Elstner <daniel.kitta@gmail.com>
a1bb33af
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 3 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, see <http://www.gnu.org/licenses/>.
19 */
20
32af282c 21#include <errno.h>
a1bb33af
UH
22#include <stdio.h>
23#include <stdlib.h>
24#include <unistd.h>
25#include <string.h>
544a4582 26#include <glib.h>
c1aae900 27#include <libsigrok/libsigrok.h>
45c59c8b 28#include "libsigrok-internal.h"
aa4b1107 29
2ad1deb8 30/** @cond PRIVATE */
3544f848 31#define LOG_PREFIX "session"
2ad1deb8 32/** @endcond */
a421dc1d 33
393fb9cb
UH
34/**
35 * @file
36 *
37 * Creating, using, or destroying libsigrok sessions.
38 */
39
7b870c38
UH
40/**
41 * @defgroup grp_session Session handling
42 *
43 * Creating, using, or destroying libsigrok sessions.
44 *
45 * @{
46 */
47
c2bf5506
DE
48struct datafeed_callback {
49 sr_datafeed_callback cb;
1f9813eb 50 void *cb_data;
c2bf5506 51};
aac0ea25 52
c2bf5506
DE
53/** Custom GLib event source for generic descriptor I/O.
54 * @internal
55 */
56struct fd_source {
57 GSource base;
62d7945f 58
c2bf5506
DE
59 int64_t timeout_us;
60 int64_t due_us;
92248e78 61
c2bf5506
DE
62 /* Meta-data needed to keep track of installed sources */
63 struct sr_session *session;
64 void *key;
544a4582 65
c2bf5506 66 GPollFD pollfd;
2726474a
ML
67};
68
c2bf5506
DE
69/** FD event source prepare() method.
70 */
71static gboolean fd_source_prepare(GSource *source, int *timeout)
72{
73 int64_t now_us;
74 struct fd_source *fsource;
75 int remaining_ms;
76
77 fsource = (struct fd_source *)source;
78
79 if (fsource->timeout_us >= 0) {
80 now_us = g_source_get_time(source);
81
82 if (fsource->due_us == 0) {
83 /* First-time initialization of the expiration time */
84 fsource->due_us = now_us + fsource->timeout_us;
85 }
86 remaining_ms = (MAX(0, fsource->due_us - now_us) + 999) / 1000;
87 } else {
88 remaining_ms = -1;
89 }
90 *timeout = remaining_ms;
91
92 return (remaining_ms == 0);
93}
94
95/** FD event source check() method.
96 */
97static gboolean fd_source_check(GSource *source)
98{
99 struct fd_source *fsource;
100 unsigned int revents;
101
102 fsource = (struct fd_source *)source;
103 revents = fsource->pollfd.revents;
104
105 return (revents != 0 || (fsource->timeout_us >= 0
106 && fsource->due_us <= g_source_get_time(source)));
107}
108
109/** FD event source dispatch() method.
110 */
111static gboolean fd_source_dispatch(GSource *source,
112 GSourceFunc callback, void *user_data)
113{
114 struct fd_source *fsource;
115 const char *name;
116 unsigned int revents;
117 gboolean keep;
118
119 fsource = (struct fd_source *)source;
120 name = g_source_get_name(source);
121 revents = fsource->pollfd.revents;
122
123 if (revents != 0) {
124 sr_spew("%s: %s " G_POLLFD_FORMAT ", revents 0x%.2X",
125 __func__, name, fsource->pollfd.fd, revents);
126 } else {
127 sr_spew("%s: %s " G_POLLFD_FORMAT ", timed out",
128 __func__, name, fsource->pollfd.fd);
129 }
130 if (!callback) {
131 sr_err("Callback not set, cannot dispatch event.");
132 return G_SOURCE_REMOVE;
133 }
134 keep = (*(sr_receive_data_callback)callback)
135 (fsource->pollfd.fd, revents, user_data);
136
137 if (fsource->timeout_us >= 0 && G_LIKELY(keep)
138 && G_LIKELY(!g_source_is_destroyed(source)))
139 fsource->due_us = g_source_get_time(source)
140 + fsource->timeout_us;
141 return keep;
142}
143
144/** FD event source finalize() method.
145 */
146static void fd_source_finalize(GSource *source)
147{
148 struct fd_source *fsource;
149
150 fsource = (struct fd_source *)source;
151
152 sr_dbg("%s: key %p", __func__, fsource->key);
153
154 sr_session_source_destroyed(fsource->session, fsource->key, source);
155}
156
157/** Create an event source for I/O on a file descriptor.
158 *
159 * In order to maintain API compatibility, this event source also doubles
160 * as a timer event source.
161 *
162 * @param session The session the event source belongs to.
163 * @param key The key used to identify this source.
164 * @param fd The file descriptor or HANDLE.
165 * @param timeout_ms The timeout interval in ms, or -1 to wait indefinitely.
166 * @return A new event source object, or NULL on failure.
167 */
168static GSource *fd_source_new(struct sr_session *session, void *key,
169 gintptr fd, int events, int timeout_ms)
170{
171 static GSourceFuncs fd_source_funcs = {
172 .prepare = &fd_source_prepare,
173 .check = &fd_source_check,
174 .dispatch = &fd_source_dispatch,
175 .finalize = &fd_source_finalize
176 };
177 GSource *source;
178 struct fd_source *fsource;
179
180 source = g_source_new(&fd_source_funcs, sizeof(struct fd_source));
181 fsource = (struct fd_source *)source;
182
183 g_source_set_name(source, (fd < 0) ? "timer" : "fd");
184
185 if (timeout_ms >= 0) {
186 fsource->timeout_us = 1000 * (int64_t)timeout_ms;
187 fsource->due_us = 0;
188 } else {
189 fsource->timeout_us = -1;
190 fsource->due_us = INT64_MAX;
191 }
192 fsource->session = session;
193 fsource->key = key;
194
195 fsource->pollfd.fd = fd;
196 fsource->pollfd.events = events;
197 fsource->pollfd.revents = 0;
198
199 if (fd >= 0)
200 g_source_add_poll(source, &fsource->pollfd);
201
202 return source;
203}
204
9f45fb3a
UH
205/**
206 * Create a new session.
7efe889e 207 *
61e6e2da 208 * @param ctx The context in which to create the new session.
7efe889e
UH
209 * @param new_session This will contain a pointer to the newly created
210 * session if the return value is SR_OK, otherwise the value
211 * is undefined and should not be used. Must not be NULL.
9f45fb3a 212 *
0812c40e 213 * @retval SR_OK Success.
41de54ff 214 * @retval SR_ERR_ARG Invalid argument.
47117241 215 *
0812c40e 216 * @since 0.4.0
9f45fb3a 217 */
61e6e2da
ML
218SR_API int sr_session_new(struct sr_context *ctx,
219 struct sr_session **new_session)
a1bb33af 220{
3337e9a1 221 struct sr_session *session;
a1bb33af 222
41de54ff
UH
223 if (!new_session)
224 return SR_ERR_ARG;
225
3337e9a1 226 session = g_malloc0(sizeof(struct sr_session));
b7e94111 227
4ed5d21d 228 session->ctx = ctx;
faa5d7d9 229
c2bf5506 230 g_mutex_init(&session->main_mutex);
faa5d7d9 231
c2bf5506
DE
232 /* To maintain API compatibility, we need a lookup table
233 * which maps poll_object IDs to GSource* pointers.
234 */
235 session->event_sources = g_hash_table_new(NULL, NULL);
0812c40e 236
3337e9a1 237 *new_session = session;
0812c40e
ML
238
239 return SR_OK;
a1bb33af
UH
240}
241
9f45fb3a 242/**
0812c40e 243 * Destroy a session.
9f45fb3a
UH
244 * This frees up all memory used by the session.
245 *
7efe889e
UH
246 * @param session The session to destroy. Must not be NULL.
247 *
04cb9157 248 * @retval SR_OK Success.
0812c40e 249 * @retval SR_ERR_ARG Invalid session passed.
47117241 250 *
0812c40e 251 * @since 0.4.0
9f45fb3a 252 */
0812c40e 253SR_API int sr_session_destroy(struct sr_session *session)
a1bb33af 254{
9f45fb3a 255 if (!session) {
a421dc1d 256 sr_err("%s: session was NULL", __func__);
0812c40e 257 return SR_ERR_ARG;
9f45fb3a
UH
258 }
259
0812c40e 260 sr_session_dev_remove_all(session);
1de3cced
ML
261 g_slist_free_full(session->owned_devs, (GDestroyNotify)sr_dev_inst_free);
262
c2bf5506
DE
263 g_hash_table_unref(session->event_sources);
264
265 g_mutex_clear(&session->main_mutex);
faa5d7d9 266
a1bb33af 267 g_free(session);
0812c40e 268
e0508e67 269 return SR_OK;
a1bb33af
UH
270}
271
9f45fb3a 272/**
0812c40e 273 * Remove all the devices from a session.
9f45fb3a
UH
274 *
275 * The session itself (i.e., the struct sr_session) is not free'd and still
276 * exists after this function returns.
277 *
7efe889e
UH
278 * @param session The session to use. Must not be NULL.
279 *
04cb9157 280 * @retval SR_OK Success.
0812c40e 281 * @retval SR_ERR_BUG Invalid session passed.
47117241 282 *
0812c40e 283 * @since 0.4.0
9f45fb3a 284 */
0812c40e 285SR_API int sr_session_dev_remove_all(struct sr_session *session)
a1bb33af 286{
0812c40e
ML
287 struct sr_dev_inst *sdi;
288 GSList *l;
289
9f45fb3a 290 if (!session) {
a421dc1d 291 sr_err("%s: session was NULL", __func__);
0812c40e
ML
292 return SR_ERR_ARG;
293 }
294
295 for (l = session->devs; l; l = l->next) {
296 sdi = (struct sr_dev_inst *) l->data;
297 sdi->session = NULL;
9f45fb3a
UH
298 }
299
681803df 300 g_slist_free(session->devs);
bb7ef793 301 session->devs = NULL;
e0508e67
UH
302
303 return SR_OK;
a1bb33af
UH
304}
305
9f45fb3a 306/**
0812c40e 307 * Add a device instance to a session.
9f45fb3a 308 *
7efe889e 309 * @param session The session to add to. Must not be NULL.
0812c40e 310 * @param sdi The device instance to add to a session. Must not
de4d3f99
BV
311 * be NULL. Also, sdi->driver and sdi->driver->dev_open must
312 * not be NULL.
9f45fb3a 313 *
04cb9157
MH
314 * @retval SR_OK Success.
315 * @retval SR_ERR_ARG Invalid argument.
47117241 316 *
0812c40e 317 * @since 0.4.0
9f45fb3a 318 */
0812c40e
ML
319SR_API int sr_session_dev_add(struct sr_session *session,
320 struct sr_dev_inst *sdi)
a1bb33af 321{
5451816f 322 int ret;
a1bb33af 323
de4d3f99 324 if (!sdi) {
a421dc1d 325 sr_err("%s: sdi was NULL", __func__);
9f45fb3a
UH
326 return SR_ERR_ARG;
327 }
328
d6eb0c33 329 if (!session) {
a421dc1d 330 sr_err("%s: session was NULL", __func__);
0812c40e
ML
331 return SR_ERR_ARG;
332 }
333
334 /* If sdi->session is not NULL, the device is already in this or
335 * another session. */
336 if (sdi->session) {
337 sr_err("%s: already assigned to session", __func__);
338 return SR_ERR_ARG;
d6eb0c33
UH
339 }
340
de4d3f99
BV
341 /* If sdi->driver is NULL, this is a virtual device. */
342 if (!sdi->driver) {
d6eb0c33 343 /* Just add the device, don't run dev_open(). */
de4d3f99 344 session->devs = g_slist_append(session->devs, (gpointer)sdi);
0812c40e 345 sdi->session = session;
d6eb0c33 346 return SR_OK;
9f45fb3a
UH
347 }
348
de4d3f99
BV
349 /* sdi->driver is non-NULL (i.e. we have a real device). */
350 if (!sdi->driver->dev_open) {
a421dc1d 351 sr_err("%s: sdi->driver->dev_open was NULL", __func__);
8ec95d22 352 return SR_ERR_BUG;
9f45fb3a
UH
353 }
354
de4d3f99 355 session->devs = g_slist_append(session->devs, (gpointer)sdi);
0812c40e 356 sdi->session = session;
aa4b1107 357
5451816f 358 if (session->running) {
32b7cd4f
DE
359 /* Adding a device to a running session. Commit settings
360 * and start acquisition on that device now. */
361 if ((ret = sr_config_commit(sdi)) != SR_OK) {
362 sr_err("Failed to commit device settings before "
363 "starting acquisition in running session (%s)",
364 sr_strerror(ret));
365 return ret;
366 }
5451816f 367 if ((ret = sdi->driver->dev_acquisition_start(sdi,
32b7cd4f 368 (void *)sdi)) != SR_OK) {
5451816f 369 sr_err("Failed to start acquisition of device in "
32b7cd4f
DE
370 "running session (%s)", sr_strerror(ret));
371 return ret;
372 }
5451816f
BV
373 }
374
e46b8fb1 375 return SR_OK;
a1bb33af
UH
376}
377
2bb311b4 378/**
0812c40e 379 * List all device instances attached to a session.
2bb311b4 380 *
7efe889e 381 * @param session The session to use. Must not be NULL.
2bb311b4
BV
382 * @param devlist A pointer where the device instance list will be
383 * stored on return. If no devices are in the session,
384 * this will be NULL. Each element in the list points
385 * to a struct sr_dev_inst *.
386 * The list must be freed by the caller, but not the
387 * elements pointed to.
388 *
04cb9157 389 * @retval SR_OK Success.
0812c40e 390 * @retval SR_ERR_ARG Invalid argument.
47117241 391 *
0812c40e 392 * @since 0.4.0
2bb311b4 393 */
0812c40e 394SR_API int sr_session_dev_list(struct sr_session *session, GSList **devlist)
2bb311b4 395{
2bb311b4 396 if (!session)
0812c40e
ML
397 return SR_ERR_ARG;
398
399 if (!devlist)
400 return SR_ERR_ARG;
2bb311b4
BV
401
402 *devlist = g_slist_copy(session->devs);
403
404 return SR_OK;
405}
406
9f45fb3a 407/**
0812c40e 408 * Remove all datafeed callbacks in a session.
9f45fb3a 409 *
7efe889e
UH
410 * @param session The session to use. Must not be NULL.
411 *
04cb9157 412 * @retval SR_OK Success.
0812c40e 413 * @retval SR_ERR_ARG Invalid session passed.
47117241 414 *
0812c40e 415 * @since 0.4.0
9f45fb3a 416 */
0812c40e 417SR_API int sr_session_datafeed_callback_remove_all(struct sr_session *session)
a1bb33af 418{
9f45fb3a 419 if (!session) {
a421dc1d 420 sr_err("%s: session was NULL", __func__);
0812c40e 421 return SR_ERR_ARG;
9f45fb3a
UH
422 }
423
2726474a 424 g_slist_free_full(session->datafeed_callbacks, g_free);
a1bb33af 425 session->datafeed_callbacks = NULL;
e0508e67
UH
426
427 return SR_OK;
a1bb33af
UH
428}
429
9f45fb3a 430/**
0812c40e 431 * Add a datafeed callback to a session.
9f45fb3a 432 *
7efe889e 433 * @param session The session to use. Must not be NULL.
d08490aa 434 * @param cb Function to call when a chunk of data is received.
0abee507 435 * Must not be NULL.
85222791 436 * @param cb_data Opaque pointer passed in by the caller.
a1645fcd 437 *
04cb9157
MH
438 * @retval SR_OK Success.
439 * @retval SR_ERR_BUG No session exists.
47117241
UH
440 *
441 * @since 0.3.0
9f45fb3a 442 */
0812c40e
ML
443SR_API int sr_session_datafeed_callback_add(struct sr_session *session,
444 sr_datafeed_callback cb, void *cb_data)
a1bb33af 445{
2726474a
ML
446 struct datafeed_callback *cb_struct;
447
9f45fb3a 448 if (!session) {
a421dc1d 449 sr_err("%s: session was NULL", __func__);
e0508e67 450 return SR_ERR_BUG;
9f45fb3a
UH
451 }
452
0abee507 453 if (!cb) {
a421dc1d 454 sr_err("%s: cb was NULL", __func__);
0abee507
UH
455 return SR_ERR_ARG;
456 }
9f45fb3a 457
91219afc 458 cb_struct = g_malloc0(sizeof(struct datafeed_callback));
2726474a
ML
459 cb_struct->cb = cb;
460 cb_struct->cb_data = cb_data;
461
62c82025 462 session->datafeed_callbacks =
2726474a 463 g_slist_append(session->datafeed_callbacks, cb_struct);
e0508e67
UH
464
465 return SR_OK;
a1bb33af
UH
466}
467
9f42e2e6
UH
468/**
469 * Get the trigger assigned to this session.
470 *
471 * @param session The session to use.
472 *
473 * @retval NULL Invalid (NULL) session was passed to the function.
474 * @retval other The trigger assigned to this session (can be NULL).
475 *
476 * @since 0.4.0
477 */
0812c40e 478SR_API struct sr_trigger *sr_session_trigger_get(struct sr_session *session)
7b5e6d29 479{
9f42e2e6
UH
480 if (!session)
481 return NULL;
482
7b5e6d29
BV
483 return session->trigger;
484}
485
9f42e2e6
UH
486/**
487 * Set the trigger of this session.
488 *
489 * @param session The session to use. Must not be NULL.
490 * @param trig The trigger to assign to this session. Can be NULL.
491 *
492 * @retval SR_OK Success.
493 * @retval SR_ERR_ARG Invalid argument.
494 *
495 * @since 0.4.0
496 */
0812c40e 497SR_API int sr_session_trigger_set(struct sr_session *session, struct sr_trigger *trig)
7b5e6d29 498{
9f42e2e6
UH
499 if (!session)
500 return SR_ERR_ARG;
501
7b5e6d29
BV
502 session->trigger = trig;
503
504 return SR_OK;
505}
506
7b5e6d29
BV
507static int verify_trigger(struct sr_trigger *trigger)
508{
509 struct sr_trigger_stage *stage;
510 struct sr_trigger_match *match;
511 GSList *l, *m;
512
513 if (!trigger->stages) {
514 sr_err("No trigger stages defined.");
515 return SR_ERR;
516 }
517
518 sr_spew("Checking trigger:");
519 for (l = trigger->stages; l; l = l->next) {
520 stage = l->data;
521 if (!stage->matches) {
522 sr_err("Stage %d has no matches defined.", stage->stage);
523 return SR_ERR;
524 }
525 for (m = stage->matches; m; m = m->next) {
526 match = m->data;
527 if (!match->channel) {
528 sr_err("Stage %d match has no channel.", stage->stage);
529 return SR_ERR;
530 }
531 if (!match->match) {
532 sr_err("Stage %d match is not defined.", stage->stage);
533 return SR_ERR;
534 }
535 sr_spew("Stage %d match on channel %s, match %d", stage->stage,
536 match->channel->name, match->match);
537 }
538 }
539
540 return SR_OK;
541}
1beccaed 542
c2bf5506
DE
543/** Set up the main context the session will be executing in.
544 *
545 * Must be called just before the session starts, by the thread which
546 * will execute the session main loop. Once acquired, the main context
547 * pointer is immutable for the duration of the session run.
548 */
549static int set_main_context(struct sr_session *session)
550{
551 GMainContext *def_context;
552
553 /* May happen if sr_session_start() is called again after
554 * sr_session_run(), but the session hasn't been stopped yet.
555 */
556 if (session->main_loop) {
557 sr_err("Cannot set main context; main loop already created.");
558 return SR_ERR;
559 }
560
561 g_mutex_lock(&session->main_mutex);
562
563 def_context = g_main_context_get_thread_default();
564
565 if (!def_context)
566 def_context = g_main_context_default();
567 /*
568 * Try to use an existing main context if possible, but only if we
569 * can make it owned by the current thread. Otherwise, create our
570 * own main context so that event source callbacks can execute in
571 * the session thread.
572 */
573 if (g_main_context_acquire(def_context)) {
574 g_main_context_release(def_context);
575
576 sr_dbg("Using thread-default main context.");
577
578 session->main_context = def_context;
579 session->main_context_is_default = TRUE;
580 } else {
581 sr_dbg("Creating our own main context.");
582
583 session->main_context = g_main_context_new();
584 session->main_context_is_default = FALSE;
585 }
586 g_mutex_unlock(&session->main_mutex);
587
588 return SR_OK;
589}
590
591/** Unset the main context used for the current session run.
592 *
593 * Must be called right after stopping the session. Note that if the
594 * session is stopped asynchronously, the main loop may still be running
595 * after the main context has been unset. This is OK as long as no new
596 * event sources are created -- the main loop holds its own reference
597 * to the main context.
598 */
599static int unset_main_context(struct sr_session *session)
600{
601 int ret;
602
603 g_mutex_lock(&session->main_mutex);
604
605 if (session->main_context) {
606 if (!session->main_context_is_default)
607 g_main_context_unref(session->main_context);
608
609 session->main_context = NULL;
610 ret = SR_OK;
611 } else {
612 /* May happen if the set/unset calls are not matched.
613 */
614 sr_err("No main context to unset.");
615 ret = SR_ERR;
616 }
617 g_mutex_unlock(&session->main_mutex);
618
619 return ret;
620}
621
9f45fb3a
UH
622/**
623 * Start a session.
624 *
7efe889e
UH
625 * @param session The session to use. Must not be NULL.
626 *
04cb9157 627 * @retval SR_OK Success.
0812c40e 628 * @retval SR_ERR_ARG Invalid session passed.
47117241 629 *
0812c40e 630 * @since 0.4.0
9f45fb3a 631 */
0812c40e 632SR_API int sr_session_start(struct sr_session *session)
7d658874 633{
de4d3f99 634 struct sr_dev_inst *sdi;
013ec84b
BV
635 struct sr_channel *ch;
636 GSList *l, *c;
637 int enabled_channels, ret;
7d658874 638
9f45fb3a 639 if (!session) {
0812c40e
ML
640 sr_err("%s: session was NULL", __func__);
641 return SR_ERR_ARG;
9f45fb3a
UH
642 }
643
bb7ef793 644 if (!session->devs) {
a421dc1d 645 sr_err("%s: session->devs was NULL; a session "
9f45fb3a 646 "cannot be started without devices.", __func__);
0812c40e 647 return SR_ERR_ARG;
9f45fb3a
UH
648 }
649
7b5e6d29
BV
650 if (session->trigger && verify_trigger(session->trigger) != SR_OK)
651 return SR_ERR;
652
c2bf5506
DE
653 ret = set_main_context(session);
654 if (ret != SR_OK)
655 return ret;
656
657 session->running = TRUE;
658
c7142604 659 sr_info("Starting.");
9f45fb3a 660
bb7ef793 661 for (l = session->devs; l; l = l->next) {
de4d3f99 662 sdi = l->data;
013ec84b
BV
663 enabled_channels = 0;
664 for (c = sdi->channels; c; c = c->next) {
665 ch = c->data;
666 if (ch->enabled) {
667 enabled_channels++;
668 break;
669 }
670 }
671 if (enabled_channels == 0) {
672 ret = SR_ERR;
1b9e567b
SA
673 sr_err("%s using connection %s has no enabled channels!",
674 sdi->driver->name, sdi->connection_id);
013ec84b
BV
675 break;
676 }
677
32b7cd4f
DE
678 if ((ret = sr_config_commit(sdi)) != SR_OK) {
679 sr_err("Failed to commit device settings before "
680 "starting acquisition (%s)", sr_strerror(ret));
681 break;
682 }
de4d3f99 683 if ((ret = sdi->driver->dev_acquisition_start(sdi, sdi)) != SR_OK) {
a421dc1d 684 sr_err("%s: could not start an acquisition "
568dcacc 685 "(%s)", __func__, sr_strerror(ret));
7d658874 686 break;
9f45fb3a 687 }
7d658874
BV
688 }
689
c2bf5506
DE
690 if (ret != SR_OK) {
691 unset_main_context(session);
692 session->running = FALSE;
693 }
9f45fb3a
UH
694 /* TODO: What if there are multiple devices? Which return code? */
695
7d658874
BV
696 return ret;
697}
698
9f45fb3a 699/**
0812c40e 700 * Run a session.
9f45fb3a 701 *
7efe889e
UH
702 * @param session The session to use. Must not be NULL.
703 *
04cb9157 704 * @retval SR_OK Success.
0812c40e 705 * @retval SR_ERR_ARG Invalid session passed.
faa5d7d9 706 * @retval SR_ERR Error during event processing.
47117241 707 *
0812c40e 708 * @since 0.4.0
9f45fb3a 709 */
0812c40e 710SR_API int sr_session_run(struct sr_session *session)
7d658874 711{
9f45fb3a 712 if (!session) {
0812c40e
ML
713 sr_err("%s: session was NULL", __func__);
714 return SR_ERR_ARG;
9f45fb3a 715 }
bb7ef793 716 if (!session->devs) {
9f45fb3a 717 /* TODO: Actually the case? */
a421dc1d 718 sr_err("%s: session->devs was NULL; a session "
9f45fb3a 719 "cannot be run without devices.", __func__);
0812c40e 720 return SR_ERR_ARG;
9f45fb3a 721 }
c2bf5506
DE
722 if (session->main_loop) {
723 sr_err("Main loop already created.");
724 return SR_ERR;
725 }
726 if (g_hash_table_size(session->event_sources) == 0) {
ab0b3458
DE
727 sr_warn("No event sources, returning immediately.");
728 return SR_OK;
c2bf5506 729 }
9f45fb3a 730
c2bf5506
DE
731 g_mutex_lock(&session->main_mutex);
732 if (!session->main_context) {
733 sr_err("Cannot run without main context.");
734 g_mutex_unlock(&session->main_mutex);
735 return SR_ERR;
736 }
a421dc1d 737 sr_info("Running.");
7d658874 738
c2bf5506
DE
739 session->main_loop = g_main_loop_new(session->main_context, FALSE);
740 g_mutex_unlock(&session->main_mutex);
741
742 g_main_loop_run(session->main_loop);
743
744 g_main_loop_unref(session->main_loop);
745 session->main_loop = NULL;
746
e0508e67 747 return SR_OK;
7d658874
BV
748}
749
c2bf5506 750static gboolean session_stop_sync(void *user_data)
a1bb33af 751{
c2bf5506 752 struct sr_session *session;
de4d3f99 753 struct sr_dev_inst *sdi;
c2bf5506 754 GSList *node;
a1bb33af 755
c2bf5506
DE
756 session = user_data;
757
758 if (!session->running)
759 return G_SOURCE_REMOVE;
9f45fb3a 760
a421dc1d 761 sr_info("Stopping.");
e0508e67 762
c2bf5506
DE
763 for (node = session->devs; node; node = node->next) {
764 sdi = node->data;
765 if (sdi->driver && sdi->driver->dev_acquisition_stop)
766 sdi->driver->dev_acquisition_stop(sdi, sdi);
a1bb33af 767 }
5451816f 768 session->running = FALSE;
9f45fb3a 769
c2bf5506 770 return G_SOURCE_REMOVE;
a1bb33af
UH
771}
772
33c6e4c5 773/**
0812c40e 774 * Stop a session.
33c6e4c5 775 *
0812c40e
ML
776 * The session is stopped immediately, with all acquisition sessions being
777 * stopped and hardware drivers cleaned up.
33c6e4c5
AG
778 *
779 * If the session is run in a separate thread, this function will not block
780 * until the session is finished executing. It is the caller's responsibility
781 * to wait for the session thread to return before assuming that the session is
782 * completely decommissioned.
783 *
7efe889e
UH
784 * @param session The session to use. Must not be NULL.
785 *
04cb9157 786 * @retval SR_OK Success.
0812c40e 787 * @retval SR_ERR_ARG Invalid session passed.
c2bf5506 788 * @retval SR_ERR Other error.
47117241 789 *
0812c40e 790 * @since 0.4.0
33c6e4c5 791 */
0812c40e 792SR_API int sr_session_stop(struct sr_session *session)
33c6e4c5
AG
793{
794 if (!session) {
795 sr_err("%s: session was NULL", __func__);
c2bf5506 796 return SR_ERR_ARG;
33c6e4c5 797 }
c2bf5506 798 g_mutex_lock(&session->main_mutex);
33c6e4c5 799
c2bf5506
DE
800 if (session->main_context) {
801 g_main_context_invoke(session->main_context,
802 &session_stop_sync, session);
803 } else {
804 sr_err("No main context set; already stopped?");
805 }
806 g_mutex_unlock(&session->main_mutex);
33c6e4c5 807
c2bf5506 808 return unset_main_context(session);
33c6e4c5
AG
809}
810
9f45fb3a 811/**
a1645fcd 812 * Debug helper.
9f45fb3a 813 *
996b0c72 814 * @param packet The packet to show debugging information for.
9f45fb3a 815 */
bf53457d 816static void datafeed_dump(const struct sr_datafeed_packet *packet)
7d2afd6c 817{
bf53457d
JH
818 const struct sr_datafeed_logic *logic;
819 const struct sr_datafeed_analog *analog;
1954dfa9 820 const struct sr_datafeed_analog2 *analog2;
7d2afd6c 821
ca7dbb56 822 /* Please use the same order as in libsigrok.h. */
7d2afd6c
BV
823 switch (packet->type) {
824 case SR_DF_HEADER:
a421dc1d 825 sr_dbg("bus: Received SR_DF_HEADER packet.");
7d2afd6c 826 break;
55c9f09d
UH
827 case SR_DF_END:
828 sr_dbg("bus: Received SR_DF_END packet.");
7d2afd6c 829 break;
c71bac3b 830 case SR_DF_META:
a421dc1d 831 sr_dbg("bus: Received SR_DF_META packet.");
ee7489d2 832 break;
55c9f09d
UH
833 case SR_DF_TRIGGER:
834 sr_dbg("bus: Received SR_DF_TRIGGER packet.");
835 break;
7d2afd6c
BV
836 case SR_DF_LOGIC:
837 logic = packet->payload;
7ea45862
UH
838 sr_dbg("bus: Received SR_DF_LOGIC packet (%" PRIu64 " bytes, "
839 "unitsize = %d).", logic->length, logic->unitsize);
7d2afd6c 840 break;
ee7489d2
BV
841 case SR_DF_ANALOG:
842 analog = packet->payload;
a421dc1d
UH
843 sr_dbg("bus: Received SR_DF_ANALOG packet (%d samples).",
844 analog->num_samples);
ee7489d2 845 break;
6ea7669c 846 case SR_DF_FRAME_BEGIN:
a421dc1d 847 sr_dbg("bus: Received SR_DF_FRAME_BEGIN packet.");
6ea7669c
BV
848 break;
849 case SR_DF_FRAME_END:
a421dc1d 850 sr_dbg("bus: Received SR_DF_FRAME_END packet.");
6ea7669c 851 break;
55c9f09d
UH
852 case SR_DF_ANALOG2:
853 analog2 = packet->payload;
854 sr_dbg("bus: Received SR_DF_ANALOG2 packet (%d samples).",
855 analog2->num_samples);
856 break;
7d2afd6c 857 default:
a421dc1d 858 sr_dbg("bus: Received unknown packet type: %d.", packet->type);
9f45fb3a 859 break;
7d2afd6c 860 }
7d2afd6c
BV
861}
862
9f45fb3a 863/**
a1645fcd
BV
864 * Send a packet to whatever is listening on the datafeed bus.
865 *
866 * Hardware drivers use this to send a data packet to the frontend.
9f45fb3a 867 *
6b2d8d3e 868 * @param sdi TODO.
31ccebc4 869 * @param packet The datafeed packet to send to the session bus.
44dae539 870 *
04cb9157
MH
871 * @retval SR_OK Success.
872 * @retval SR_ERR_ARG Invalid argument.
b4bd7088
UH
873 *
874 * @private
9f45fb3a 875 */
de4d3f99 876SR_PRIV int sr_session_send(const struct sr_dev_inst *sdi,
8143cfdc 877 const struct sr_datafeed_packet *packet)
a1bb33af
UH
878{
879 GSList *l;
2726474a 880 struct datafeed_callback *cb_struct;
c0a1e532
UH
881 struct sr_datafeed_packet *packet_in, *packet_out;
882 struct sr_transform *t;
883 int ret;
a1bb33af 884
de4d3f99 885 if (!sdi) {
a421dc1d 886 sr_err("%s: sdi was NULL", __func__);
e0508e67 887 return SR_ERR_ARG;
9f45fb3a
UH
888 }
889
e0508e67 890 if (!packet) {
a421dc1d 891 sr_err("%s: packet was NULL", __func__);
e0508e67 892 return SR_ERR_ARG;
9f45fb3a
UH
893 }
894
79f92686
BV
895 if (!sdi->session) {
896 sr_err("%s: session was NULL", __func__);
897 return SR_ERR_BUG;
898 }
899
c0a1e532
UH
900 /*
901 * Pass the packet to the first transform module. If that returns
902 * another packet (instead of NULL), pass that packet to the next
903 * transform module in the list, and so on.
904 */
905 packet_in = (struct sr_datafeed_packet *)packet;
906 for (l = sdi->session->transforms; l; l = l->next) {
907 t = l->data;
908 sr_spew("Running transform module '%s'.", t->module->id);
909 ret = t->module->receive(t, packet_in, &packet_out);
910 if (ret < 0) {
911 sr_err("Error while running transform module: %d.", ret);
912 return SR_ERR;
913 }
914 if (!packet_out) {
915 /*
916 * If any of the transforms don't return an output
917 * packet, abort.
918 */
919 sr_spew("Transform module didn't return a packet, aborting.");
920 return SR_OK;
921 } else {
922 /*
923 * Use this transform module's output packet as input
924 * for the next transform module.
925 */
926 packet_in = packet_out;
927 }
928 }
4ec436c4 929 packet = packet_in;
c0a1e532
UH
930
931 /*
932 * If the last transform did output a packet, pass it to all datafeed
933 * callbacks.
934 */
3337e9a1 935 for (l = sdi->session->datafeed_callbacks; l; l = l->next) {
18beaeff
BV
936 if (sr_log_loglevel_get() >= SR_LOG_DBG)
937 datafeed_dump(packet);
2726474a
ML
938 cb_struct = l->data;
939 cb_struct->cb(sdi, packet, cb_struct->cb_data);
a1bb33af 940 }
9f45fb3a 941
e0508e67 942 return SR_OK;
a1bb33af
UH
943}
944
6b2d8d3e
UH
945/**
946 * Add an event source for a file descriptor.
947 *
7efe889e 948 * @param session The session to use. Must not be NULL.
c2bf5506
DE
949 * @param key The key which identifies the event source.
950 * @param source An event source object. Must not be NULL.
04cb9157
MH
951 * @retval SR_OK Success.
952 * @retval SR_ERR_ARG Invalid argument.
c2bf5506
DE
953 * @retval SR_ERR_BUG Event source with @a key already installed.
954 * @retval SR_ERR Other error.
6b2d8d3e 955 */
62d7945f 956SR_PRIV int sr_session_source_add_internal(struct sr_session *session,
c2bf5506 957 void *key, GSource *source)
544a4582 958{
c2bf5506
DE
959 int ret;
960 /*
961 * This must not ever happen, since the source has already been
962 * created and its finalize() method will remove the key for the
963 * already installed source. (Well it would, if we did not have
964 * another sanity check there.)
92248e78 965 */
c2bf5506
DE
966 if (g_hash_table_contains(session->event_sources, key)) {
967 sr_err("Event source with key %p already exists.", key);
968 return SR_ERR_BUG;
92248e78 969 }
c2bf5506
DE
970 g_hash_table_insert(session->event_sources, key, source);
971
972 g_mutex_lock(&session->main_mutex);
973
974 if (session->main_context) {
975 if (g_source_attach(source, session->main_context) > 0)
976 ret = SR_OK;
977 else
978 ret = SR_ERR;
faa5d7d9 979 } else {
c2bf5506
DE
980 sr_err("Cannot add event source without main context.");
981 ret = SR_ERR;
faa5d7d9 982 }
c2bf5506 983 g_mutex_unlock(&session->main_mutex);
faa5d7d9 984
c2bf5506 985 return ret;
534b634c
DE
986}
987
c2bf5506
DE
988static int attach_fd_source(struct sr_session *session,
989 void *key, int fd, int events, int timeout,
990 sr_receive_data_callback cb, void *cb_data)
534b634c 991{
c2bf5506
DE
992 GSource *source;
993 int ret;
534b634c 994
c2bf5506
DE
995 source = fd_source_new(session, key, fd, events, timeout);
996 if (!source)
534b634c 997 return SR_ERR;
534b634c 998
c2bf5506 999 g_source_set_callback(source, (GSourceFunc)cb, cb_data, NULL);
534b634c 1000
c2bf5506
DE
1001 ret = sr_session_source_add_internal(session, key, source);
1002 g_source_unref(source);
544a4582 1003
c2bf5506 1004 return ret;
544a4582
BV
1005}
1006
9f45fb3a 1007/**
6b2d8d3e 1008 * Add an event source for a file descriptor.
9f45fb3a 1009 *
7efe889e 1010 * @param session The session to use. Must not be NULL.
534b634c 1011 * @param fd The file descriptor, or a negative value to create a timer source.
aac0ea25 1012 * @param events Events to check for.
faa5d7d9
DE
1013 * @param timeout Max time in ms to wait before the callback is called,
1014 * or -1 to wait indefinitely.
aac0ea25
LPC
1015 * @param cb Callback function to add. Must not be NULL.
1016 * @param cb_data Data for the callback function. Can be NULL.
9f45fb3a 1017 *
04cb9157
MH
1018 * @retval SR_OK Success.
1019 * @retval SR_ERR_ARG Invalid argument.
47117241
UH
1020 *
1021 * @since 0.3.0
aac0ea25 1022 */
0812c40e
ML
1023SR_API int sr_session_source_add(struct sr_session *session, int fd,
1024 int events, int timeout, sr_receive_data_callback cb, void *cb_data)
aac0ea25 1025{
faa5d7d9 1026 if (fd < 0 && timeout < 0) {
c2bf5506 1027 sr_err("Cannot create timer source without timeout.");
faa5d7d9
DE
1028 return SR_ERR_ARG;
1029 }
c2bf5506
DE
1030 return attach_fd_source(session, GINT_TO_POINTER(fd),
1031 fd, events, timeout, cb, cb_data);
aac0ea25
LPC
1032}
1033
1034/**
1a895c61 1035 * Add an event source for a GPollFD.
aac0ea25 1036 *
7efe889e 1037 * @param session The session to use. Must not be NULL.
faa5d7d9
DE
1038 * @param pollfd The GPollFD. Must not be NULL.
1039 * @param timeout Max time in ms to wait before the callback is called,
1040 * or -1 to wait indefinitely.
aac0ea25
LPC
1041 * @param cb Callback function to add. Must not be NULL.
1042 * @param cb_data Data for the callback function. Can be NULL.
44dae539 1043 *
04cb9157
MH
1044 * @retval SR_OK Success.
1045 * @retval SR_ERR_ARG Invalid argument.
47117241
UH
1046 *
1047 * @since 0.3.0
9f45fb3a 1048 */
0812c40e
ML
1049SR_API int sr_session_source_add_pollfd(struct sr_session *session,
1050 GPollFD *pollfd, int timeout, sr_receive_data_callback cb,
1051 void *cb_data)
aac0ea25 1052{
faa5d7d9
DE
1053 if (!pollfd) {
1054 sr_err("%s: pollfd was NULL", __func__);
1055 return SR_ERR_ARG;
1056 }
c2bf5506
DE
1057 return attach_fd_source(session, pollfd, pollfd->fd,
1058 pollfd->events, timeout, cb, cb_data);
aac0ea25
LPC
1059}
1060
1061/**
1a895c61 1062 * Add an event source for a GIOChannel.
aac0ea25 1063 *
7efe889e 1064 * @param session The session to use. Must not be NULL.
aac0ea25
LPC
1065 * @param channel The GIOChannel.
1066 * @param events Events to poll on.
faa5d7d9
DE
1067 * @param timeout Max time in ms to wait before the callback is called,
1068 * or -1 to wait indefinitely.
aac0ea25
LPC
1069 * @param cb Callback function to add. Must not be NULL.
1070 * @param cb_data Data for the callback function. Can be NULL.
1071 *
04cb9157
MH
1072 * @retval SR_OK Success.
1073 * @retval SR_ERR_ARG Invalid argument.
47117241
UH
1074 *
1075 * @since 0.3.0
aac0ea25 1076 */
0812c40e
ML
1077SR_API int sr_session_source_add_channel(struct sr_session *session,
1078 GIOChannel *channel, int events, int timeout,
1079 sr_receive_data_callback cb, void *cb_data)
aac0ea25 1080{
c2bf5506 1081 GPollFD pollfd;
aac0ea25 1082
c2bf5506
DE
1083 if (!channel) {
1084 sr_err("%s: channel was NULL", __func__);
1085 return SR_ERR_ARG;
1086 }
1087 /* We should be using g_io_create_watch(), but can't without
1088 * changing the driver API, as the callback signature is different.
1089 */
faa5d7d9 1090#ifdef G_OS_WIN32
c2bf5506 1091 g_io_channel_win32_make_pollfd(channel, events, &pollfd);
aac0ea25 1092#else
c2bf5506
DE
1093 pollfd.fd = g_io_channel_unix_get_fd(channel);
1094 pollfd.events = events;
aac0ea25 1095#endif
c2bf5506
DE
1096 return attach_fd_source(session, channel, pollfd.fd,
1097 pollfd.events, timeout, cb, cb_data);
aac0ea25
LPC
1098}
1099
6b2d8d3e 1100/**
92248e78 1101 * Remove the source identified by the specified poll object.
6b2d8d3e 1102 *
7efe889e 1103 * @param session The session to use. Must not be NULL.
c2bf5506 1104 * @param key The key by which the source is identified.
6b2d8d3e 1105 *
04cb9157 1106 * @retval SR_OK Success
92248e78 1107 * @retval SR_ERR_BUG No event source for poll_object found.
6b2d8d3e 1108 */
92248e78 1109SR_PRIV int sr_session_source_remove_internal(struct sr_session *session,
c2bf5506 1110 void *key)
544a4582 1111{
c2bf5506 1112 GSource *source;
544a4582 1113
c2bf5506
DE
1114 source = g_hash_table_lookup(session->event_sources, key);
1115 /*
1116 * Trying to remove an already removed event source is problematic
92248e78
DE
1117 * since the poll_object handle may have been reused in the meantime.
1118 */
534b634c 1119 if (!source) {
c2bf5506
DE
1120 sr_warn("Cannot remove non-existing event source %p.", key);
1121 return SR_ERR_BUG;
534b634c 1122 }
c2bf5506 1123 g_source_destroy(source);
534b634c 1124
c2bf5506 1125 return SR_OK;
534b634c
DE
1126}
1127
6b2d8d3e 1128/**
aac0ea25
LPC
1129 * Remove the source belonging to the specified file descriptor.
1130 *
7efe889e 1131 * @param session The session to use. Must not be NULL.
1a895c61 1132 * @param fd The file descriptor for which the source should be removed.
aac0ea25 1133 *
04cb9157
MH
1134 * @retval SR_OK Success
1135 * @retval SR_ERR_ARG Invalid argument
04cb9157 1136 * @retval SR_ERR_BUG Internal error.
47117241
UH
1137 *
1138 * @since 0.3.0
aac0ea25 1139 */
0812c40e 1140SR_API int sr_session_source_remove(struct sr_session *session, int fd)
aac0ea25 1141{
c2bf5506 1142 return sr_session_source_remove_internal(session, GINT_TO_POINTER(fd));
aac0ea25
LPC
1143}
1144
1145/**
1146 * Remove the source belonging to the specified poll descriptor.
1147 *
7efe889e 1148 * @param session The session to use. Must not be NULL.
aac0ea25 1149 * @param pollfd The poll descriptor for which the source should be removed.
faa5d7d9 1150 * Must not be NULL.
aac0ea25
LPC
1151 * @return SR_OK upon success, SR_ERR_ARG upon invalid arguments, or
1152 * SR_ERR_MALLOC upon memory allocation errors, SR_ERR_BUG upon
1153 * internal errors.
47117241
UH
1154 *
1155 * @since 0.2.0
aac0ea25 1156 */
0812c40e
ML
1157SR_API int sr_session_source_remove_pollfd(struct sr_session *session,
1158 GPollFD *pollfd)
aac0ea25 1159{
faa5d7d9
DE
1160 if (!pollfd) {
1161 sr_err("%s: pollfd was NULL", __func__);
1162 return SR_ERR_ARG;
1163 }
c2bf5506 1164 return sr_session_source_remove_internal(session, pollfd);
aac0ea25
LPC
1165}
1166
6b2d8d3e 1167/**
aac0ea25
LPC
1168 * Remove the source belonging to the specified channel.
1169 *
7efe889e 1170 * @param session The session to use. Must not be NULL.
1a895c61 1171 * @param channel The channel for which the source should be removed.
faa5d7d9 1172 * Must not be NULL.
04cb9157
MH
1173 * @retval SR_OK Success.
1174 * @retval SR_ERR_ARG Invalid argument.
04cb9157 1175 * @return SR_ERR_BUG Internal error.
47117241
UH
1176 *
1177 * @since 0.2.0
aac0ea25 1178 */
0812c40e
ML
1179SR_API int sr_session_source_remove_channel(struct sr_session *session,
1180 GIOChannel *channel)
aac0ea25 1181{
faa5d7d9
DE
1182 if (!channel) {
1183 sr_err("%s: channel was NULL", __func__);
1184 return SR_ERR_ARG;
1185 }
c2bf5506
DE
1186 return sr_session_source_remove_internal(session, channel);
1187}
1188
1189/** Unregister an event source that has been destroyed.
1190 *
1191 * This is intended to be called from a source's finalize() method.
1192 *
1193 * @param session The session to use. Must not be NULL.
1194 * @param key The key used to identify @a source.
1195 * @param source The source object that was destroyed.
1196 *
1197 * @retval SR_OK Success.
1198 * @retval SR_ERR_BUG Event source for @a key does not match @a source.
1199 */
1200SR_PRIV int sr_session_source_destroyed(struct sr_session *session,
1201 void *key, GSource *source)
1202{
1203 GSource *registered_source;
1204
1205 registered_source = g_hash_table_lookup(session->event_sources, key);
1206 /*
1207 * Trying to remove an already removed event source is problematic
1208 * since the poll_object handle may have been reused in the meantime.
1209 */
1210 if (!registered_source) {
1211 sr_err("No event source for key %p found.", key);
1212 return SR_ERR_BUG;
1213 }
1214 if (registered_source != source) {
1215 sr_err("Event source for key %p does not match"
1216 " destroyed source.", key);
1217 return SR_ERR_BUG;
1218 }
1219 g_hash_table_remove(session->event_sources, key);
1220 /*
1221 * Quit the main loop if we just removed the last event source.
1222 * TODO: This may need an idle callback depending on when event
1223 * sources are finalized. (The issue is remove followed by add
1224 * within the same main loop iteration.)
1225 */
1226 if (session->main_loop
1227 && g_hash_table_size(session->event_sources) == 0) {
1228 sr_dbg("Stopping main loop...");
1229 g_main_loop_quit(session->main_loop);
1230 }
1231 return SR_OK;
aac0ea25 1232}
7b870c38 1233
ee29d92e 1234static void copy_src(struct sr_config *src, struct sr_datafeed_meta *meta_copy)
8143cfdc 1235{
8143cfdc 1236 g_variant_ref(src->data);
ee29d92e
AJ
1237 meta_copy->config = g_slist_append(meta_copy->config,
1238 g_memdup(src, sizeof(struct sr_config)));
8143cfdc
BV
1239}
1240
1241SR_PRIV int sr_packet_copy(const struct sr_datafeed_packet *packet,
1242 struct sr_datafeed_packet **copy)
1243{
1244 const struct sr_datafeed_meta *meta;
1245 struct sr_datafeed_meta *meta_copy;
1246 const struct sr_datafeed_logic *logic;
1247 struct sr_datafeed_logic *logic_copy;
1248 const struct sr_datafeed_analog *analog;
1249 struct sr_datafeed_analog *analog_copy;
1250 uint8_t *payload;
1251
1252 *copy = g_malloc0(sizeof(struct sr_datafeed_packet));
1253 (*copy)->type = packet->type;
1254
1255 switch (packet->type) {
1256 case SR_DF_TRIGGER:
1257 case SR_DF_END:
1258 /* No payload. */
1259 break;
1260 case SR_DF_HEADER:
1261 payload = g_malloc(sizeof(struct sr_datafeed_header));
1262 memcpy(payload, packet->payload, sizeof(struct sr_datafeed_header));
1263 (*copy)->payload = payload;
1264 break;
1265 case SR_DF_META:
1266 meta = packet->payload;
ee29d92e
AJ
1267 meta_copy = g_malloc0(sizeof(struct sr_datafeed_meta));
1268 g_slist_foreach(meta->config, (GFunc)copy_src, meta_copy->config);
8143cfdc
BV
1269 (*copy)->payload = meta_copy;
1270 break;
1271 case SR_DF_LOGIC:
1272 logic = packet->payload;
1273 logic_copy = g_malloc(sizeof(logic));
1274 logic_copy->length = logic->length;
1275 logic_copy->unitsize = logic->unitsize;
1276 memcpy(logic_copy->data, logic->data, logic->length * logic->unitsize);
1277 (*copy)->payload = logic_copy;
1278 break;
1279 case SR_DF_ANALOG:
1280 analog = packet->payload;
1281 analog_copy = g_malloc(sizeof(analog));
1282 analog_copy->channels = g_slist_copy(analog->channels);
1283 analog_copy->num_samples = analog->num_samples;
1284 analog_copy->mq = analog->mq;
1285 analog_copy->unit = analog->unit;
1286 analog_copy->mqflags = analog->mqflags;
1287 memcpy(analog_copy->data, analog->data,
1288 analog->num_samples * sizeof(float));
1289 (*copy)->payload = analog_copy;
1290 break;
1291 default:
1292 sr_err("Unknown packet type %d", packet->type);
1293 return SR_ERR;
1294 }
1295
1296 return SR_OK;
1297}
1298
1299void sr_packet_free(struct sr_datafeed_packet *packet)
1300{
1301 const struct sr_datafeed_meta *meta;
1302 const struct sr_datafeed_logic *logic;
1303 const struct sr_datafeed_analog *analog;
1304 struct sr_config *src;
1305 GSList *l;
1306
1307 switch (packet->type) {
1308 case SR_DF_TRIGGER:
1309 case SR_DF_END:
1310 /* No payload. */
1311 break;
1312 case SR_DF_HEADER:
1313 /* Payload is a simple struct. */
1314 g_free((void *)packet->payload);
1315 break;
1316 case SR_DF_META:
1317 meta = packet->payload;
1318 for (l = meta->config; l; l = l->next) {
1319 src = l->data;
1320 g_variant_unref(src->data);
1321 g_free(src);
1322 }
1323 g_slist_free(meta->config);
1324 g_free((void *)packet->payload);
1325 break;
1326 case SR_DF_LOGIC:
1327 logic = packet->payload;
1328 g_free(logic->data);
1329 g_free((void *)packet->payload);
1330 break;
1331 case SR_DF_ANALOG:
1332 analog = packet->payload;
1333 g_slist_free(analog->channels);
1334 g_free(analog->data);
1335 g_free((void *)packet->payload);
1336 break;
1337 default:
1338 sr_err("Unknown packet type %d", packet->type);
1339 }
1340 g_free(packet);
1341
1342}
1343
7b870c38 1344/** @} */