29 #include "libsigrok-internal.h"
32 #define LOG_PREFIX "session"
49 struct datafeed_callback {
74 static gboolean fd_source_prepare(GSource *source,
int *timeout)
77 struct fd_source *fsource;
80 fsource = (
struct fd_source *)source;
82 if (fsource->timeout_us >= 0) {
83 now_us = g_source_get_time(source);
85 if (fsource->due_us == 0) {
87 fsource->due_us = now_us + fsource->timeout_us;
89 remaining_ms = (MAX(0, fsource->due_us - now_us) + 999) / 1000;
93 *timeout = remaining_ms;
95 return (remaining_ms == 0);
101 static gboolean fd_source_check(GSource *source)
103 struct fd_source *fsource;
104 unsigned int revents;
106 fsource = (
struct fd_source *)source;
107 revents = fsource->pollfd.revents;
109 return (revents != 0 || (fsource->timeout_us >= 0
110 && fsource->due_us <= g_source_get_time(source)));
116 static gboolean fd_source_dispatch(GSource *source,
117 GSourceFunc callback,
void *user_data)
119 struct fd_source *fsource;
120 unsigned int revents;
123 fsource = (
struct fd_source *)source;
124 revents = fsource->pollfd.revents;
127 sr_err(
"Callback not set, cannot dispatch event.");
128 return G_SOURCE_REMOVE;
131 (fsource->pollfd.fd, revents, user_data);
133 if (fsource->timeout_us >= 0 && G_LIKELY(keep)
134 && G_LIKELY(!g_source_is_destroyed(source)))
135 fsource->due_us = g_source_get_time(source)
136 + fsource->timeout_us;
142 static void fd_source_finalize(GSource *source)
144 struct fd_source *fsource;
146 fsource = (
struct fd_source *)source;
148 sr_dbg(
"%s: key %p", __func__, fsource->key);
150 sr_session_source_destroyed(fsource->session, fsource->key, source);
164 static GSource *fd_source_new(
struct sr_session *session,
void *key,
165 gintptr fd,
int events,
int timeout_ms)
167 static GSourceFuncs fd_source_funcs = {
168 .prepare = &fd_source_prepare,
169 .check = &fd_source_check,
170 .dispatch = &fd_source_dispatch,
171 .finalize = &fd_source_finalize
174 struct fd_source *fsource;
176 source = g_source_new(&fd_source_funcs,
sizeof(
struct fd_source));
177 fsource = (
struct fd_source *)source;
179 g_source_set_name(source, (fd < 0) ?
"timer" :
"fd");
181 if (timeout_ms >= 0) {
182 fsource->timeout_us = 1000 * (int64_t)timeout_ms;
185 fsource->timeout_us = -1;
186 fsource->due_us = INT64_MAX;
188 fsource->session = session;
191 fsource->pollfd.fd = fd;
192 fsource->pollfd.events = events;
193 fsource->pollfd.revents = 0;
196 g_source_add_poll(source, &fsource->pollfd);
222 session = g_malloc0(
sizeof(
struct sr_session));
226 g_mutex_init(&session->main_mutex);
231 session->event_sources = g_hash_table_new(NULL, NULL);
233 *new_session = session;
252 sr_err(
"%s: session was NULL", __func__);
257 g_slist_free_full(session->owned_devs, (GDestroyNotify)sr_dev_inst_free);
261 g_hash_table_unref(session->event_sources);
263 g_mutex_clear(&session->main_mutex);
285 struct sr_dev_inst *sdi;
289 sr_err(
"%s: session was NULL", __func__);
293 for (l = session->devs; l; l = l->next) {
294 sdi = (
struct sr_dev_inst *) l->data;
298 g_slist_free(session->devs);
299 session->devs = NULL;
318 struct sr_dev_inst *sdi)
323 sr_err(
"%s: sdi was NULL", __func__);
328 sr_err(
"%s: session was NULL", __func__);
335 sr_err(
"%s: already assigned to session", __func__);
342 session->devs = g_slist_append(session->devs, sdi);
343 sdi->session = session;
348 if (!sdi->driver->dev_open) {
349 sr_err(
"%s: sdi->driver->dev_open was NULL", __func__);
353 session->devs = g_slist_append(session->devs, sdi);
354 sdi->session = session;
359 if (session->running) {
363 sr_err(
"Failed to commit device settings before "
364 "starting acquisition in running session (%s)",
368 if ((ret = sr_dev_acquisition_start(sdi)) !=
SR_OK) {
369 sr_err(
"Failed to start acquisition of device in "
402 *devlist = g_slist_copy(session->devs);
421 struct sr_dev_inst *sdi)
424 sr_err(
"%s: sdi was NULL", __func__);
429 sr_err(
"%s: session was NULL", __func__);
435 if (sdi->session != session) {
436 sr_err(
"%s: not assigned to this session", __func__);
440 session->devs = g_slist_remove(session->devs, sdi);
459 sr_err(
"%s: session was NULL", __func__);
463 g_slist_free_full(session->datafeed_callbacks, g_free);
464 session->datafeed_callbacks = NULL;
485 struct datafeed_callback *cb_struct;
488 sr_err(
"%s: session was NULL", __func__);
493 sr_err(
"%s: cb was NULL", __func__);
497 cb_struct = g_malloc0(
sizeof(
struct datafeed_callback));
499 cb_struct->cb_data = cb_data;
501 session->datafeed_callbacks =
502 g_slist_append(session->datafeed_callbacks, cb_struct);
522 return session->trigger;
541 session->trigger = trig;
546 static int verify_trigger(
struct sr_trigger *trigger)
553 sr_err(
"No trigger stages defined.");
557 sr_spew(
"Checking trigger:");
558 for (l = trigger->
stages; l; l = l->next) {
561 sr_err(
"Stage %d has no matches defined.", stage->
stage);
564 for (m = stage->
matches; m; m = m->next) {
567 sr_err(
"Stage %d match has no channel.", stage->
stage);
571 sr_err(
"Stage %d match is not defined.", stage->
stage);
574 sr_spew(
"Stage %d match on channel %s, match %d", stage->
stage,
588 static int set_main_context(
struct sr_session *session)
590 GMainContext *main_context;
592 g_mutex_lock(&session->main_mutex);
597 if (session->main_context) {
598 sr_err(
"Main context already set.");
600 g_mutex_unlock(&session->main_mutex);
603 main_context = g_main_context_ref_thread_default();
610 if (g_main_context_acquire(main_context)) {
611 g_main_context_release(main_context);
613 sr_dbg(
"Using thread-default main context.");
615 g_main_context_unref(main_context);
617 sr_dbg(
"Creating our own main context.");
618 main_context = g_main_context_new();
620 session->main_context = main_context;
622 g_mutex_unlock(&session->main_mutex);
635 static int unset_main_context(
struct sr_session *session)
639 g_mutex_lock(&session->main_mutex);
641 if (session->main_context) {
642 g_main_context_unref(session->main_context);
643 session->main_context = NULL;
648 sr_err(
"No main context to unset.");
651 g_mutex_unlock(&session->main_mutex);
656 static unsigned int session_source_attach(
struct sr_session *session,
661 g_mutex_lock(&session->main_mutex);
663 if (session->main_context)
664 id = g_source_attach(source, session->main_context);
666 sr_err(
"Cannot add event source without main context.");
668 g_mutex_unlock(&session->main_mutex);
676 static gboolean delayed_stop_check(
void *data)
681 session->stop_check_id = 0;
684 if (!session->running)
685 return G_SOURCE_REMOVE;
688 if (g_hash_table_size(session->event_sources) != 0)
689 return G_SOURCE_REMOVE;
691 session->running = FALSE;
692 unset_main_context(session);
699 if (!session->main_loop && !session->stopped_callback) {
700 sr_err(
"BUG: Session stop left unhandled.");
701 return G_SOURCE_REMOVE;
703 if (session->main_loop)
704 g_main_loop_quit(session->main_loop);
706 if (session->stopped_callback)
707 (*session->stopped_callback)(session->stopped_cb_data);
709 return G_SOURCE_REMOVE;
712 static int stop_check_later(
struct sr_session *session)
715 unsigned int source_id;
717 if (session->stop_check_id != 0)
720 source = g_idle_source_new();
721 g_source_set_callback(source, &delayed_stop_check, session, NULL);
723 source_id = session_source_attach(session, source);
724 session->stop_check_id = source_id;
726 g_source_unref(source);
754 struct sr_dev_inst *sdi;
756 GSList *l, *c, *lend;
760 sr_err(
"%s: session was NULL", __func__);
764 if (!session->devs) {
765 sr_err(
"%s: session->devs was NULL; a session "
766 "cannot be started without devices.", __func__);
770 if (session->running) {
771 sr_err(
"Cannot (re-)start session while it is still running.");
775 if (session->trigger) {
776 ret = verify_trigger(session->trigger);
782 for (l = session->devs; l; l = l->next) {
784 for (c = sdi->channels; c; c = c->next) {
790 sr_err(
"%s device %s has no enabled channels.",
791 sdi->driver->name, sdi->connection_id);
797 sr_err(
"Failed to commit %s device %s settings "
798 "before starting acquisition.",
799 sdi->driver->name, sdi->connection_id);
804 ret = set_main_context(session);
808 sr_info(
"Starting.");
810 session->running = TRUE;
813 for (l = session->devs; l; l = l->next) {
814 if (!(sdi = l->data)) {
815 sr_err(
"Device sdi was NULL, can't start session.");
819 ret = sr_dev_acquisition_start(sdi);
821 sr_err(
"Could not start %s device %s acquisition.",
822 sdi->driver->name, sdi->connection_id);
831 for (l = session->devs; l != lend; l = l->next) {
833 sr_dev_acquisition_stop(sdi);
837 session->running = FALSE;
839 unset_main_context(session);
843 if (g_hash_table_size(session->event_sources) == 0)
844 stop_check_later(session);
870 sr_err(
"%s: session was NULL", __func__);
873 if (!session->running) {
874 sr_err(
"No session running.");
877 if (session->main_loop) {
878 sr_err(
"Main loop already created.");
882 g_mutex_lock(&session->main_mutex);
884 if (!session->main_context) {
885 sr_err(
"Cannot run without main context.");
886 g_mutex_unlock(&session->main_mutex);
889 session->main_loop = g_main_loop_new(session->main_context, FALSE);
891 g_mutex_unlock(&session->main_mutex);
893 g_main_loop_run(session->main_loop);
895 g_main_loop_unref(session->main_loop);
896 session->main_loop = NULL;
901 static gboolean session_stop_sync(
void *user_data)
904 struct sr_dev_inst *sdi;
909 if (!session->running)
910 return G_SOURCE_REMOVE;
912 sr_info(
"Stopping.");
914 for (node = session->devs; node; node = node->next) {
916 sr_dev_acquisition_stop(sdi);
919 return G_SOURCE_REMOVE;
947 GMainContext *main_context;
950 sr_err(
"%s: session was NULL", __func__);
954 g_mutex_lock(&session->main_mutex);
956 main_context = (session->main_context)
957 ? g_main_context_ref(session->main_context)
960 g_mutex_unlock(&session->main_mutex);
963 sr_dbg(
"No main context set; already stopped?");
967 g_main_context_invoke(main_context, &session_stop_sync, session);
968 g_main_context_unref(main_context);
990 sr_err(
"%s: session was NULL", __func__);
993 return session->running;
1019 sr_err(
"%s: session was NULL", __func__);
1022 session->stopped_callback = cb;
1023 session->stopped_cb_data = cb_data;
1039 switch (packet->
type) {
1041 sr_dbg(
"bus: Received SR_DF_HEADER packet.");
1044 sr_dbg(
"bus: Received SR_DF_END packet.");
1047 sr_dbg(
"bus: Received SR_DF_META packet.");
1050 sr_dbg(
"bus: Received SR_DF_TRIGGER packet.");
1054 sr_dbg(
"bus: Received SR_DF_LOGIC packet (%" PRIu64
" bytes, "
1058 sr_dbg(
"bus: Received SR_DF_FRAME_BEGIN packet.");
1061 sr_dbg(
"bus: Received SR_DF_FRAME_END packet.");
1065 sr_dbg(
"bus: Received SR_DF_ANALOG packet (%d samples).",
1069 sr_dbg(
"bus: Received unknown packet type: %d.", packet->
type);
1086 SR_PRIV int sr_session_send_meta(
const struct sr_dev_inst *sdi,
1087 uint32_t key, GVariant *var)
1094 cfg = sr_config_new(key, var);
1096 memset(&meta, 0,
sizeof(meta));
1101 meta.config = g_slist_append(NULL, cfg);
1103 ret = sr_session_send(sdi, &packet);
1104 g_slist_free(meta.config);
1105 sr_config_free(cfg);
1123 SR_PRIV int sr_session_send(
const struct sr_dev_inst *sdi,
1127 struct datafeed_callback *cb_struct;
1129 struct sr_transform *t;
1133 sr_err(
"%s: sdi was NULL", __func__);
1138 sr_err(
"%s: packet was NULL", __func__);
1142 if (!sdi->session) {
1143 sr_err(
"%s: session was NULL", __func__);
1153 for (l = sdi->session->transforms; l; l = l->next) {
1155 sr_spew(
"Running transform module '%s'.", t->module->id);
1156 ret = t->module->receive(t, packet_in, &packet_out);
1158 sr_err(
"Error while running transform module: %d.", ret);
1166 sr_spew(
"Transform module didn't return a packet, aborting.");
1173 packet_in = packet_out;
1182 for (l = sdi->session->datafeed_callbacks; l; l = l->next) {
1184 datafeed_dump(packet);
1185 cb_struct = l->data;
1186 cb_struct->cb(sdi, packet, cb_struct->cb_data);
1207 void *key, GSource *source)
1215 if (g_hash_table_contains(session->event_sources, key)) {
1216 sr_err(
"Event source with key %p already exists.", key);
1219 g_hash_table_insert(session->event_sources, key, source);
1221 if (session_source_attach(session, source) == 0)
1229 void *key, gintptr fd,
int events,
int timeout,
1235 source = fd_source_new(session, key, fd, events, timeout);
1239 g_source_set_callback(source, (GSourceFunc)cb, cb_data, NULL);
1241 ret = sr_session_source_add_internal(session, key, source);
1242 g_source_unref(source);
1267 if (fd < 0 && timeout < 0) {
1268 sr_err(
"Cannot create timer source without timeout.");
1271 return sr_session_fd_source_add(session, GINT_TO_POINTER(fd),
1272 fd, events, timeout, cb, cb_data);
1296 sr_err(
"%s: pollfd was NULL", __func__);
1299 return sr_session_fd_source_add(session, pollfd, pollfd->fd,
1300 pollfd->events, timeout, cb, cb_data);
1321 GIOChannel *channel,
int events,
int timeout,
1327 sr_err(
"%s: channel was NULL", __func__);
1334 g_io_channel_win32_make_pollfd(channel, events, &pollfd);
1336 pollfd.fd = g_io_channel_unix_get_fd(channel);
1337 pollfd.events = events;
1339 return sr_session_fd_source_add(session, channel, pollfd.fd,
1340 pollfd.events, timeout, cb, cb_data);
1359 source = g_hash_table_lookup(session->event_sources, key);
1365 sr_warn(
"Cannot remove non-existing event source %p.", key);
1368 g_source_destroy(source);
1388 return sr_session_source_remove_internal(session, GINT_TO_POINTER(fd));
1408 sr_err(
"%s: pollfd was NULL", __func__);
1411 return sr_session_source_remove_internal(session, pollfd);
1428 GIOChannel *channel)
1431 sr_err(
"%s: channel was NULL", __func__);
1434 return sr_session_source_remove_internal(session, channel);
1452 void *key, GSource *source)
1454 GSource *registered_source;
1456 registered_source = g_hash_table_lookup(session->event_sources, key);
1461 if (!registered_source) {
1462 sr_err(
"No event source for key %p found.", key);
1465 if (registered_source != source) {
1466 sr_err(
"Event source for key %p does not match"
1467 " destroyed source.", key);
1470 g_hash_table_remove(session->event_sources, key);
1472 if (g_hash_table_size(session->event_sources) > 0)
1479 return stop_check_later(session);
1484 g_variant_ref(src->
data);
1486 g_memdup(src,
sizeof(
struct sr_config)));
1501 (*copy)->type = packet->
type;
1503 switch (packet->
type) {
1511 (*copy)->payload = payload;
1516 g_slist_foreach(meta->
config, (GFunc)copy_src, meta_copy->
config);
1517 (*copy)->payload = meta_copy;
1521 logic_copy = g_malloc(
sizeof(*logic_copy));
1527 if (!logic_copy->
data) {
1532 (*copy)->payload = logic_copy;
1536 analog_copy = g_malloc(
sizeof(*analog_copy));
1537 analog_copy->
data = g_malloc(
1539 memcpy(analog_copy->
data, analog->
data,
1548 analog_copy->
spec = g_memdup(analog->
spec,
1550 (*copy)->payload = analog_copy;
1553 sr_err(
"Unknown packet type %d", packet->
type);
1568 switch (packet->
type) {
1575 g_free((
void *)packet->
payload);
1579 for (l = meta->
config; l; l = l->next) {
1581 g_variant_unref(src->
data);
1584 g_slist_free(meta->
config);
1585 g_free((
void *)packet->
payload);
1589 g_free(logic->
data);
1590 g_free((
void *)packet->
payload);
1594 g_free(analog->
data);
1598 g_free(analog->
spec);
1599 g_free((
void *)packet->
payload);
1602 sr_err(
"Unknown packet type %d", packet->
type);
Generic/unspecified error.
struct sr_channel * channel
The channel to trigger on.
int sr_session_dev_list(struct sr_session *session, GSList **devlist)
List all device instances attached to a session.
Logic datafeed payload for type SR_DF_LOGIC.
GSList * matches
List of pointers to struct sr_trigger_match.
int sr_session_datafeed_callback_remove_all(struct sr_session *session)
Remove all datafeed callbacks in a session.
Payload is struct sr_datafeed_meta.
int sr_packet_copy(const struct sr_datafeed_packet *packet, struct sr_datafeed_packet **copy)
int sr_session_dev_remove_all(struct sr_session *session)
Remove all the devices from a session.
int sr_session_new(struct sr_context *ctx, struct sr_session **new_session)
Create a new session.
Payload is struct sr_datafeed_analog.
gboolean enabled
Is this channel enabled?
Payload is struct sr_datafeed_logic.
int sr_session_trigger_set(struct sr_session *session, struct sr_trigger *trig)
Set the trigger of this session.
int match
The trigger match to use.
int sr_session_stop(struct sr_session *session)
Stop a session.
The public libsigrok header file to be used by frontends.
int sr_session_destroy(struct sr_session *session)
Destroy a session.
A channel to match and what to match it on.
void sr_packet_free(struct sr_datafeed_packet *packet)
int sr_session_dev_remove(struct sr_session *session, struct sr_dev_inst *sdi)
Remove a device instance from a session.
struct sr_analog_encoding * encoding
End of stream (no further data).
Used for setting or getting value of a config item.
int sr_session_is_running(struct sr_session *session)
Return whether the session is currently running.
int sr_session_datafeed_callback_add(struct sr_session *session, sr_datafeed_callback cb, void *cb_data)
Add a datafeed callback to a session.
The trigger matched at this point in the data feed.
Header of a sigrok data feed.
Packet in a sigrok data feed.
GVariant * data
Key-specific data.
int sr_config_commit(const struct sr_dev_inst *sdi)
Apply configuration settings to the device hardware.
GSList * stages
List of pointers to struct sr_trigger_stage.
struct sr_analog_meaning * meaning
int(* sr_receive_data_callback)(int fd, int revents, void *cb_data)
Type definition for callback function for data reception.
The representation of a trigger, consisting of one or more stages containing one or more matches on a...
char * name
Name of channel.
int sr_session_run(struct sr_session *session)
Block until the running session stops.
void(* sr_session_stopped_callback)(void *data)
struct sr_analog_spec * spec
Datafeed payload for type SR_DF_META.
Payload is sr_datafeed_header.
const char * sr_strerror(int error_code)
Return a human-readable error string for the given libsigrok error code.
Analog datafeed payload for type SR_DF_ANALOG.
int sr_log_loglevel_get(void)
Get the libsigrok loglevel.
int sr_session_dev_add(struct sr_session *session, struct sr_dev_inst *sdi)
Add a device instance to a session.
int sr_session_stopped_callback_set(struct sr_session *session, sr_session_stopped_callback cb, void *cb_data)
Set the callback to be invoked after a session stopped running.
Information on single channel.
void(* sr_datafeed_callback)(const struct sr_dev_inst *sdi, const struct sr_datafeed_packet *packet, void *cb_data)
Errors hinting at internal bugs.
struct sr_trigger * sr_session_trigger_get(struct sr_session *session)
Get the trigger assigned to this session.
int sr_session_start(struct sr_session *session)
Start a session.
Opaque structure representing a libsigrok session.
Opaque structure representing a libsigrok context.