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 = sdi->driver->dev_acquisition_start(sdi,
370 sr_err(
"Failed to start acquisition of device in "
403 *devlist = g_slist_copy(session->devs);
422 struct sr_dev_inst *sdi)
425 sr_err(
"%s: sdi was NULL", __func__);
430 sr_err(
"%s: session was NULL", __func__);
436 if (sdi->session != session) {
437 sr_err(
"%s: not assigned to this session", __func__);
441 session->devs = g_slist_remove(session->devs, sdi);
460 sr_err(
"%s: session was NULL", __func__);
464 g_slist_free_full(session->datafeed_callbacks, g_free);
465 session->datafeed_callbacks = NULL;
486 struct datafeed_callback *cb_struct;
489 sr_err(
"%s: session was NULL", __func__);
494 sr_err(
"%s: cb was NULL", __func__);
498 cb_struct = g_malloc0(
sizeof(
struct datafeed_callback));
500 cb_struct->cb_data = cb_data;
502 session->datafeed_callbacks =
503 g_slist_append(session->datafeed_callbacks, cb_struct);
523 return session->trigger;
542 session->trigger = trig;
547 static int verify_trigger(
struct sr_trigger *trigger)
554 sr_err(
"No trigger stages defined.");
558 sr_spew(
"Checking trigger:");
559 for (l = trigger->
stages; l; l = l->next) {
562 sr_err(
"Stage %d has no matches defined.", stage->
stage);
565 for (m = stage->
matches; m; m = m->next) {
568 sr_err(
"Stage %d match has no channel.", stage->
stage);
572 sr_err(
"Stage %d match is not defined.", stage->
stage);
575 sr_spew(
"Stage %d match on channel %s, match %d", stage->
stage,
589 static int set_main_context(
struct sr_session *session)
591 GMainContext *main_context;
593 g_mutex_lock(&session->main_mutex);
598 if (session->main_context) {
599 sr_err(
"Main context already set.");
601 g_mutex_unlock(&session->main_mutex);
604 main_context = g_main_context_ref_thread_default();
611 if (g_main_context_acquire(main_context)) {
612 g_main_context_release(main_context);
614 sr_dbg(
"Using thread-default main context.");
616 g_main_context_unref(main_context);
618 sr_dbg(
"Creating our own main context.");
619 main_context = g_main_context_new();
621 session->main_context = main_context;
623 g_mutex_unlock(&session->main_mutex);
636 static int unset_main_context(
struct sr_session *session)
640 g_mutex_lock(&session->main_mutex);
642 if (session->main_context) {
643 g_main_context_unref(session->main_context);
644 session->main_context = NULL;
649 sr_err(
"No main context to unset.");
652 g_mutex_unlock(&session->main_mutex);
657 static unsigned int session_source_attach(
struct sr_session *session,
662 g_mutex_lock(&session->main_mutex);
664 if (session->main_context)
665 id = g_source_attach(source, session->main_context);
667 sr_err(
"Cannot add event source without main context.");
669 g_mutex_unlock(&session->main_mutex);
677 static gboolean delayed_stop_check(
void *data)
682 session->stop_check_id = 0;
685 if (!session->running)
686 return G_SOURCE_REMOVE;
689 if (g_hash_table_size(session->event_sources) != 0)
690 return G_SOURCE_REMOVE;
692 session->running = FALSE;
693 unset_main_context(session);
700 if (!session->main_loop && !session->stopped_callback) {
701 sr_err(
"BUG: Session stop left unhandled.");
702 return G_SOURCE_REMOVE;
704 if (session->main_loop)
705 g_main_loop_quit(session->main_loop);
707 if (session->stopped_callback)
708 (*session->stopped_callback)(session->stopped_cb_data);
710 return G_SOURCE_REMOVE;
713 static int stop_check_later(
struct sr_session *session)
716 unsigned int source_id;
718 if (session->stop_check_id != 0)
721 source = g_idle_source_new();
722 g_source_set_callback(source, &delayed_stop_check, session, NULL);
724 source_id = session_source_attach(session, source);
725 session->stop_check_id = source_id;
727 g_source_unref(source);
755 struct sr_dev_inst *sdi;
757 GSList *l, *c, *lend;
761 sr_err(
"%s: session was NULL", __func__);
765 if (!session->devs) {
766 sr_err(
"%s: session->devs was NULL; a session "
767 "cannot be started without devices.", __func__);
771 if (session->running) {
772 sr_err(
"Cannot (re-)start session while it is still running.");
776 if (session->trigger) {
777 ret = verify_trigger(session->trigger);
783 for (l = session->devs; l; l = l->next) {
785 for (c = sdi->channels; c; c = c->next) {
791 sr_err(
"%s device %s has no enabled channels.",
792 sdi->driver->name, sdi->connection_id);
798 sr_err(
"Failed to commit %s device %s settings "
799 "before starting acquisition.",
800 sdi->driver->name, sdi->connection_id);
805 ret = set_main_context(session);
809 sr_info(
"Starting.");
811 session->running = TRUE;
814 for (l = session->devs; l; l = l->next) {
816 ret = sdi->driver->dev_acquisition_start(sdi, sdi);
818 sr_err(
"Could not start %s device %s acquisition.",
819 sdi->driver->name, sdi->connection_id);
828 for (l = session->devs; l != lend; l = l->next) {
830 if (sdi->driver->dev_acquisition_stop)
831 sdi->driver->dev_acquisition_stop(sdi, sdi);
835 session->running = FALSE;
837 unset_main_context(session);
841 if (g_hash_table_size(session->event_sources) == 0)
842 stop_check_later(session);
868 sr_err(
"%s: session was NULL", __func__);
871 if (!session->running) {
872 sr_err(
"No session running.");
875 if (session->main_loop) {
876 sr_err(
"Main loop already created.");
880 g_mutex_lock(&session->main_mutex);
882 if (!session->main_context) {
883 sr_err(
"Cannot run without main context.");
884 g_mutex_unlock(&session->main_mutex);
887 session->main_loop = g_main_loop_new(session->main_context, FALSE);
889 g_mutex_unlock(&session->main_mutex);
891 g_main_loop_run(session->main_loop);
893 g_main_loop_unref(session->main_loop);
894 session->main_loop = NULL;
899 static gboolean session_stop_sync(
void *user_data)
902 struct sr_dev_inst *sdi;
907 if (!session->running)
908 return G_SOURCE_REMOVE;
910 sr_info(
"Stopping.");
912 for (node = session->devs; node; node = node->next) {
914 if (sdi->driver && sdi->driver->dev_acquisition_stop)
915 sdi->driver->dev_acquisition_stop(sdi, sdi);
918 return G_SOURCE_REMOVE;
946 GMainContext *main_context;
949 sr_err(
"%s: session was NULL", __func__);
953 g_mutex_lock(&session->main_mutex);
955 main_context = (session->main_context)
956 ? g_main_context_ref(session->main_context)
959 g_mutex_unlock(&session->main_mutex);
962 sr_dbg(
"No main context set; already stopped?");
966 g_main_context_invoke(main_context, &session_stop_sync, session);
967 g_main_context_unref(main_context);
989 sr_err(
"%s: session was NULL", __func__);
992 return session->running;
1018 sr_err(
"%s: session was NULL", __func__);
1021 session->stopped_callback = cb;
1022 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, "
1059 sr_dbg(
"bus: Received SR_DF_ANALOG_OLD packet (%d samples).",
1063 sr_dbg(
"bus: Received SR_DF_FRAME_BEGIN packet.");
1066 sr_dbg(
"bus: Received SR_DF_FRAME_END packet.");
1070 sr_dbg(
"bus: Received SR_DF_ANALOG packet (%d samples).",
1074 sr_dbg(
"bus: Received unknown packet type: %d.", packet->
type);
1092 SR_PRIV int sr_session_send(
const struct sr_dev_inst *sdi,
1096 struct datafeed_callback *cb_struct;
1098 struct sr_transform *t;
1102 sr_err(
"%s: sdi was NULL", __func__);
1107 sr_err(
"%s: packet was NULL", __func__);
1111 if (!sdi->session) {
1112 sr_err(
"%s: session was NULL", __func__);
1125 new_packet.payload = &analog;
1130 analog.
spec = &spec;
1131 encoding.unitsize =
sizeof(float);
1132 encoding.is_signed = TRUE;
1133 encoding.is_float = TRUE;
1134 #ifdef WORDS_BIGENDIAN
1135 encoding.is_bigendian = TRUE;
1137 encoding.is_bigendian = FALSE;
1139 encoding.digits = 0;
1140 encoding.is_digits_decimal = FALSE;
1141 encoding.scale.p = 1;
1142 encoding.scale.q = 1;
1143 encoding.offset.p = 0;
1144 encoding.offset.q = 1;
1145 meaning.mq = analog_old->
mq;
1146 meaning.unit = analog_old->
unit;
1147 meaning.mqflags = analog_old->
mqflags;
1148 meaning.channels = analog_old->
channels;
1149 spec.spec_digits = 0;
1150 return sr_session_send(sdi, &new_packet);
1159 for (l = sdi->session->transforms; l; l = l->next) {
1161 sr_spew(
"Running transform module '%s'.", t->module->id);
1162 ret = t->module->receive(t, packet_in, &packet_out);
1164 sr_err(
"Error while running transform module: %d.", ret);
1172 sr_spew(
"Transform module didn't return a packet, aborting.");
1179 packet_in = packet_out;
1188 for (l = sdi->session->datafeed_callbacks; l; l = l->next) {
1190 datafeed_dump(packet);
1191 cb_struct = l->data;
1192 cb_struct->cb(sdi, packet, cb_struct->cb_data);
1213 void *key, GSource *source)
1221 if (g_hash_table_contains(session->event_sources, key)) {
1222 sr_err(
"Event source with key %p already exists.", key);
1225 g_hash_table_insert(session->event_sources, key, source);
1227 if (session_source_attach(session, source) == 0)
1234 void *key, gintptr fd,
int events,
int timeout,
1240 source = fd_source_new(session, key, fd, events, timeout);
1244 g_source_set_callback(source, (GSourceFunc)cb, cb_data, NULL);
1246 ret = sr_session_source_add_internal(session, key, source);
1247 g_source_unref(source);
1272 if (fd < 0 && timeout < 0) {
1273 sr_err(
"Cannot create timer source without timeout.");
1277 fd, events, timeout, cb, cb_data);
1301 sr_err(
"%s: pollfd was NULL", __func__);
1305 pollfd->events, timeout, cb, cb_data);
1326 GIOChannel *channel,
int events,
int timeout,
1332 sr_err(
"%s: channel was NULL", __func__);
1339 g_io_channel_win32_make_pollfd(channel, events, &pollfd);
1341 pollfd.fd = g_io_channel_unix_get_fd(channel);
1342 pollfd.events = events;
1345 pollfd.events, timeout, cb, cb_data);
1364 source = g_hash_table_lookup(session->event_sources, key);
1370 sr_warn(
"Cannot remove non-existing event source %p.", key);
1373 g_source_destroy(source);
1393 return sr_session_source_remove_internal(session, GINT_TO_POINTER(fd));
1413 sr_err(
"%s: pollfd was NULL", __func__);
1416 return sr_session_source_remove_internal(session, pollfd);
1433 GIOChannel *channel)
1436 sr_err(
"%s: channel was NULL", __func__);
1439 return sr_session_source_remove_internal(session, channel);
1457 void *key, GSource *source)
1459 GSource *registered_source;
1461 registered_source = g_hash_table_lookup(session->event_sources, key);
1466 if (!registered_source) {
1467 sr_err(
"No event source for key %p found.", key);
1470 if (registered_source != source) {
1471 sr_err(
"Event source for key %p does not match"
1472 " destroyed source.", key);
1475 g_hash_table_remove(session->event_sources, key);
1477 if (g_hash_table_size(session->event_sources) > 0)
1484 return stop_check_later(session);
1489 g_variant_ref(src->
data);
1491 g_memdup(src,
sizeof(
struct sr_config)));
1508 (*copy)->type = packet->
type;
1510 switch (packet->
type) {
1518 (*copy)->payload = payload;
1523 g_slist_foreach(meta->
config, (GFunc)copy_src, meta_copy->
config);
1524 (*copy)->payload = meta_copy;
1528 logic_copy = g_malloc(
sizeof(logic));
1532 (*copy)->payload = logic_copy;
1536 analog_old_copy = g_malloc(
sizeof(analog_old));
1539 analog_old_copy->
mq = analog_old->
mq;
1540 analog_old_copy->
unit = analog_old->
unit;
1542 analog_old_copy->
data = g_malloc(analog_old->
num_samples *
sizeof(
float));
1543 memcpy(analog_old_copy->
data, analog_old->
data,
1545 (*copy)->payload = analog_old_copy;
1549 analog_copy = g_malloc(
sizeof(analog));
1550 analog_copy->
data = g_malloc(
1552 memcpy(analog_copy->
data, analog->
data,
1561 analog_copy->
spec = g_memdup(analog->
spec,
1563 (*copy)->payload = analog_copy;
1566 sr_err(
"Unknown packet type %d", packet->
type);
1582 switch (packet->
type) {
1589 g_free((
void *)packet->
payload);
1593 for (l = meta->
config; l; l = l->next) {
1595 g_variant_unref(src->
data);
1598 g_slist_free(meta->
config);
1599 g_free((
void *)packet->
payload);
1603 g_free(logic->
data);
1604 g_free((
void *)packet->
payload);
1608 g_slist_free(analog_old->
channels);
1609 g_free(analog_old->
data);
1610 g_free((
void *)packet->
payload);
1614 g_free(analog->
data);
1618 g_free(analog->
spec);
1619 g_free((
void *)packet->
payload);
1622 sr_err(
"Unknown packet type %d", packet->
type);
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 representation of a trigger, consisting of one or more stages containing one or more matches on a...
int sr_session_start(struct sr_session *session)
Start a session.
int sr_session_dev_add(struct sr_session *session, struct sr_dev_inst *sdi)
Add a device instance to a session.
Analog datafeed payload for type SR_DF_ANALOG_OLD.
struct sr_analog_encoding * encoding
The public libsigrok header file to be used by frontends.
void(* sr_datafeed_callback)(const struct sr_dev_inst *sdi, const struct sr_datafeed_packet *packet, void *cb_data)
End of stream (no further data).
void(* sr_session_stopped_callback)(void *data)
Errors hinting at internal bugs.
uint64_t mqflags
Bitmap with extra information about the MQ.
Generic/unspecified error.
Opaque structure representing a libsigrok 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.
gboolean enabled
Is this channel enabled?
int match
The trigger match to use.
int sr_session_destroy(struct sr_session *session)
Destroy a session.
SR_PRIV int sr_packet_copy(const struct sr_datafeed_packet *packet, struct sr_datafeed_packet **copy)
int mq
Measured quantity (voltage, current, temperature, and so on).
float * data
The analog value(s).
SR_PRIV int sr_session_fd_source_add(struct sr_session *session, void *key, gintptr fd, int events, int timeout, sr_receive_data_callback cb, void *cb_data)
void sr_packet_free(struct sr_datafeed_packet *packet)
Analog datafeed payload for type SR_DF_ANALOG.
char * name
Name of channel.
int sr_session_datafeed_callback_remove_all(struct sr_session *session)
Remove all datafeed callbacks in a session.
GSList * channels
The channels for which data is included in this packet.
GVariant * data
Key-specific data.
int sr_session_trigger_set(struct sr_session *session, struct sr_trigger *trig)
Set the trigger of this session.
struct sr_trigger * sr_session_trigger_get(struct sr_session *session)
Get the trigger assigned to this session.
Packet in a sigrok data feed.
struct sr_analog_meaning * meaning
Logic datafeed payload for type SR_DF_LOGIC.
Payload is sr_datafeed_header.
The trigger matched at this point in the data feed.
Information on single channel.
int sr_session_dev_remove_all(struct sr_session *session)
Remove all the devices from a session.
int sr_log_loglevel_get(void)
Get the libsigrok loglevel.
int sr_session_is_running(struct sr_session *session)
Return whether the session is currently running.
struct sr_analog_spec * spec
int unit
Unit in which the MQ is measured.
A channel to match and what to match it on.
int(* sr_receive_data_callback)(int fd, int revents, void *cb_data)
Type definition for callback function for data reception.
Datafeed payload for type SR_DF_META.
Header of a sigrok data feed.
int sr_session_stop(struct sr_session *session)
Stop a session.
int sr_config_commit(const struct sr_dev_inst *sdi)
Apply configuration settings to the device hardware.
int sr_session_dev_list(struct sr_session *session, GSList **devlist)
List all device instances attached to a session.
Opaque structure representing a libsigrok context.
int sr_session_dev_remove(struct sr_session *session, struct sr_dev_inst *sdi)
Remove a device instance from a session.
GSList * stages
List of pointers to struct sr_trigger_stage.
int sr_session_new(struct sr_context *ctx, struct sr_session **new_session)
Create a new session.
Payload is struct sr_datafeed_meta.
int sr_session_run(struct sr_session *session)
Block until the running session stops.
const char * sr_strerror(int error_code)
Return a human-readable error string for the given libsigrok error code.
struct sr_channel * channel
The channel to trigger on.
DEPRECATED! Use SR_DF_ANALOG instead.
Payload is struct sr_datafeed_analog.
Payload is struct sr_datafeed_logic.
int num_samples
Number of samples in data.
GSList * matches
List of pointers to struct sr_trigger_match.
Used for setting or getting value of a config item.