29 #include "libsigrok-internal.h" 32 #define LOG_PREFIX "session" 49 struct datafeed_callback {
73 static gboolean fd_source_prepare(GSource *source,
int *timeout)
76 struct fd_source *fsource;
79 fsource = (
struct fd_source *)source;
81 if (fsource->timeout_us >= 0) {
82 now_us = g_source_get_time(source);
84 if (fsource->due_us == 0) {
86 fsource->due_us = now_us + fsource->timeout_us;
88 remaining_ms = (MAX(0, fsource->due_us - now_us) + 999) / 1000;
92 *timeout = remaining_ms;
94 return (remaining_ms == 0);
100 static gboolean fd_source_check(GSource *source)
102 struct fd_source *fsource;
103 unsigned int revents;
105 fsource = (
struct fd_source *)source;
106 revents = fsource->pollfd.revents;
108 return (revents != 0 || (fsource->timeout_us >= 0
109 && fsource->due_us <= g_source_get_time(source)));
115 static gboolean fd_source_dispatch(GSource *source,
116 GSourceFunc callback,
void *user_data)
118 struct fd_source *fsource;
119 unsigned int revents;
122 fsource = (
struct fd_source *)source;
123 revents = fsource->pollfd.revents;
126 sr_err(
"Callback not set, cannot dispatch event.");
127 return G_SOURCE_REMOVE;
129 keep = (*SR_RECEIVE_DATA_CALLBACK(callback))
130 (fsource->pollfd.fd, revents, user_data);
132 if (fsource->timeout_us >= 0 && G_LIKELY(keep)
133 && G_LIKELY(!g_source_is_destroyed(source)))
134 fsource->due_us = g_source_get_time(source)
135 + fsource->timeout_us;
141 static void fd_source_finalize(GSource *source)
143 struct fd_source *fsource;
145 fsource = (
struct fd_source *)source;
147 sr_dbg(
"%s: key %p", __func__, fsource->key);
149 sr_session_source_destroyed(fsource->session, fsource->key, source);
165 static GSource *fd_source_new(
struct sr_session *session,
void *key,
166 gintptr fd,
int events,
int timeout_ms)
168 static GSourceFuncs fd_source_funcs = {
169 .prepare = &fd_source_prepare,
170 .check = &fd_source_check,
171 .dispatch = &fd_source_dispatch,
172 .finalize = &fd_source_finalize
175 struct fd_source *fsource;
177 source = g_source_new(&fd_source_funcs,
sizeof(
struct fd_source));
178 fsource = (
struct fd_source *)source;
180 g_source_set_name(source, (fd < 0) ?
"timer" :
"fd");
182 if (timeout_ms >= 0) {
183 fsource->timeout_us = 1000 * (int64_t)timeout_ms;
186 fsource->timeout_us = -1;
187 fsource->due_us = INT64_MAX;
189 fsource->session = session;
192 fsource->pollfd.fd = fd;
193 fsource->pollfd.events = events;
194 fsource->pollfd.revents = 0;
197 g_source_add_poll(source, &fsource->pollfd);
223 session = g_malloc0(
sizeof(
struct sr_session));
227 g_mutex_init(&session->main_mutex);
232 session->event_sources = g_hash_table_new(NULL, NULL);
234 *new_session = session;
253 sr_err(
"%s: session was NULL", __func__);
258 g_slist_free_full(session->owned_devs, (GDestroyNotify)sr_dev_inst_free);
262 g_hash_table_unref(session->event_sources);
264 g_mutex_clear(&session->main_mutex);
286 struct sr_dev_inst *sdi;
290 sr_err(
"%s: session was NULL", __func__);
294 for (l = session->devs; l; l = l->next) {
295 sdi = (
struct sr_dev_inst *) l->data;
299 g_slist_free(session->devs);
300 session->devs = NULL;
319 struct sr_dev_inst *sdi)
324 sr_err(
"%s: sdi was NULL", __func__);
329 sr_err(
"%s: session was NULL", __func__);
336 sr_err(
"%s: already assigned to session", __func__);
343 session->devs = g_slist_append(session->devs, sdi);
344 sdi->session = session;
349 if (!sdi->driver->dev_open) {
350 sr_err(
"%s: sdi->driver->dev_open was NULL", __func__);
354 session->devs = g_slist_append(session->devs, sdi);
355 sdi->session = session;
360 if (session->running) {
364 sr_err(
"Failed to commit device settings before " 365 "starting acquisition in running session (%s)",
369 if ((ret = sr_dev_acquisition_start(sdi)) !=
SR_OK) {
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) {
815 if (!(sdi = l->data)) {
816 sr_err(
"Device sdi was NULL, can't start session.");
820 ret = sr_dev_acquisition_start(sdi);
822 sr_err(
"Could not start %s device %s acquisition.",
823 sdi->driver->name, sdi->connection_id);
832 for (l = session->devs; l != lend; l = l->next) {
834 sr_dev_acquisition_stop(sdi);
838 session->running = FALSE;
840 unset_main_context(session);
844 if (g_hash_table_size(session->event_sources) == 0)
845 stop_check_later(session);
871 sr_err(
"%s: session was NULL", __func__);
874 if (!session->running) {
875 sr_err(
"No session running.");
878 if (session->main_loop) {
879 sr_err(
"Main loop already created.");
883 g_mutex_lock(&session->main_mutex);
885 if (!session->main_context) {
886 sr_err(
"Cannot run without main context.");
887 g_mutex_unlock(&session->main_mutex);
890 session->main_loop = g_main_loop_new(session->main_context, FALSE);
892 g_mutex_unlock(&session->main_mutex);
894 g_main_loop_run(session->main_loop);
896 g_main_loop_unref(session->main_loop);
897 session->main_loop = NULL;
902 static gboolean session_stop_sync(
void *user_data)
905 struct sr_dev_inst *sdi;
910 if (!session->running)
911 return G_SOURCE_REMOVE;
913 sr_info(
"Stopping.");
915 for (node = session->devs; node; node = node->next) {
917 sr_dev_acquisition_stop(sdi);
920 return G_SOURCE_REMOVE;
948 GMainContext *main_context;
951 sr_err(
"%s: session was NULL", __func__);
955 g_mutex_lock(&session->main_mutex);
957 main_context = (session->main_context)
958 ? g_main_context_ref(session->main_context)
961 g_mutex_unlock(&session->main_mutex);
964 sr_dbg(
"No main context set; already stopped?");
968 g_main_context_invoke(main_context, &session_stop_sync, session);
969 g_main_context_unref(main_context);
991 sr_err(
"%s: session was NULL", __func__);
994 return session->running;
1020 sr_err(
"%s: session was NULL", __func__);
1023 session->stopped_callback = cb;
1024 session->stopped_cb_data = cb_data;
1040 switch (packet->
type) {
1042 sr_dbg(
"bus: Received SR_DF_HEADER packet.");
1045 sr_dbg(
"bus: Received SR_DF_END packet.");
1048 sr_dbg(
"bus: Received SR_DF_META packet.");
1051 sr_dbg(
"bus: Received SR_DF_TRIGGER packet.");
1055 sr_dbg(
"bus: Received SR_DF_LOGIC packet (%" PRIu64
" bytes, " 1059 sr_dbg(
"bus: Received SR_DF_FRAME_BEGIN packet.");
1062 sr_dbg(
"bus: Received SR_DF_FRAME_END packet.");
1066 sr_dbg(
"bus: Received SR_DF_ANALOG packet (%d samples).",
1070 sr_dbg(
"bus: Received unknown packet type: %d.", packet->
type);
1087 SR_PRIV int sr_session_send_meta(
const struct sr_dev_inst *sdi,
1088 uint32_t key, GVariant *var)
1095 cfg = sr_config_new(key, var);
1097 memset(&meta, 0,
sizeof(meta));
1102 meta.
config = g_slist_append(NULL, cfg);
1104 ret = sr_session_send(sdi, &packet);
1105 g_slist_free(meta.
config);
1106 sr_config_free(cfg);
1124 SR_PRIV int sr_session_send(
const struct sr_dev_inst *sdi,
1128 struct datafeed_callback *cb_struct;
1130 struct sr_transform *t;
1134 sr_err(
"%s: sdi was NULL", __func__);
1139 sr_err(
"%s: packet was NULL", __func__);
1143 if (!sdi->session) {
1144 sr_err(
"%s: session was NULL", __func__);
1154 for (l = sdi->session->transforms; l; l = l->next) {
1156 sr_spew(
"Running transform module '%s'.", t->module->id);
1157 ret = t->module->receive(t, packet_in, &packet_out);
1159 sr_err(
"Error while running transform module: %d.", ret);
1167 sr_spew(
"Transform module didn't return a packet, aborting.");
1174 packet_in = packet_out;
1183 for (l = sdi->session->datafeed_callbacks; l; l = l->next) {
1185 datafeed_dump(packet);
1186 cb_struct = l->data;
1187 cb_struct->cb(sdi, packet, cb_struct->cb_data);
1208 void *key, GSource *source)
1216 if (g_hash_table_contains(session->event_sources, key)) {
1217 sr_err(
"Event source with key %p already exists.", key);
1220 g_hash_table_insert(session->event_sources, key, source);
1222 if (session_source_attach(session, source) == 0)
1230 void *key, gintptr fd,
int events,
int timeout,
1236 source = fd_source_new(session, key, fd, events, timeout);
1240 g_source_set_callback(source, G_SOURCE_FUNC(cb), cb_data, NULL);
1242 ret = sr_session_source_add_internal(session, key, source);
1243 g_source_unref(source);
1268 if (fd < 0 && timeout < 0) {
1269 sr_err(
"Cannot create timer source without timeout.");
1272 return sr_session_fd_source_add(session, GINT_TO_POINTER(fd),
1273 fd, events, timeout, cb, cb_data);
1297 sr_err(
"%s: pollfd was NULL", __func__);
1300 return sr_session_fd_source_add(session, pollfd, pollfd->fd,
1301 pollfd->events, timeout, cb, cb_data);
1322 GIOChannel *channel,
int events,
int timeout,
1328 sr_err(
"%s: channel was NULL", __func__);
1335 g_io_channel_win32_make_pollfd(channel, events, &pollfd);
1337 pollfd.fd = g_io_channel_unix_get_fd(channel);
1338 pollfd.events = events;
1340 return sr_session_fd_source_add(session, channel, pollfd.fd,
1341 pollfd.events, timeout, cb, cb_data);
1360 source = g_hash_table_lookup(session->event_sources, key);
1366 sr_warn(
"Cannot remove non-existing event source %p.", key);
1369 g_source_destroy(source);
1389 return sr_session_source_remove_internal(session, GINT_TO_POINTER(fd));
1409 sr_err(
"%s: pollfd was NULL", __func__);
1412 return sr_session_source_remove_internal(session, pollfd);
1429 GIOChannel *channel)
1432 sr_err(
"%s: channel was NULL", __func__);
1435 return sr_session_source_remove_internal(session, channel);
1453 void *key, GSource *source)
1455 GSource *registered_source;
1457 registered_source = g_hash_table_lookup(session->event_sources, key);
1462 if (!registered_source) {
1463 sr_err(
"No event source for key %p found.", key);
1466 if (registered_source != source) {
1467 sr_err(
"Event source for key %p does not match" 1468 " destroyed source.", key);
1471 g_hash_table_remove(session->event_sources, key);
1473 if (g_hash_table_size(session->event_sources) > 0)
1480 return stop_check_later(session);
1487 #if GLIB_CHECK_VERSION(2, 67, 3) 1488 item = g_memdup2(src,
sizeof(*src));
1490 item = g_memdup(src,
sizeof(*src));
1493 g_variant_ref(src->
data);
1494 meta_copy->
config = g_slist_append(meta_copy->
config, item);
1512 (*copy)->type = packet->
type;
1514 switch (packet->
type) {
1522 (*copy)->payload = payload;
1527 g_slist_foreach(meta->
config, (GFunc)copy_src, meta_copy->
config);
1528 (*copy)->payload = meta_copy;
1532 logic_copy = g_malloc(
sizeof(*logic_copy));
1538 if (!logic_copy->
data) {
1543 (*copy)->payload = logic_copy;
1547 analog_copy = g_malloc(
sizeof(*analog_copy));
1548 analog_copy->
data = g_malloc(
1550 memcpy(analog_copy->
data, analog->
data,
1553 #if GLIB_CHECK_VERSION(2, 67, 3) 1555 meaning_copy = g_memdup2(analog->
meaning,
sizeof(*analog->
meaning));
1556 spec_copy = g_memdup2(analog->
spec,
sizeof(*analog->
spec));
1559 meaning_copy = g_memdup(analog->
meaning,
sizeof(*analog->
meaning));
1560 spec_copy = g_memdup(analog->
spec,
sizeof(*analog->
spec));
1562 analog_copy->
encoding = encoding_copy;
1563 analog_copy->
meaning = meaning_copy;
1566 analog_copy->
spec = spec_copy;
1567 (*copy)->payload = analog_copy;
1570 sr_err(
"Unknown packet type %d", packet->
type);
1585 switch (packet->
type) {
1592 g_free((
void *)packet->
payload);
1596 for (l = meta->
config; l; l = l->next) {
1598 g_variant_unref(src->
data);
1601 g_slist_free(meta->
config);
1602 g_free((
void *)packet->
payload);
1606 g_free(logic->
data);
1607 g_free((
void *)packet->
payload);
1611 g_free(analog->
data);
1615 g_free(analog->
spec);
1616 g_free((
void *)packet->
payload);
1619 sr_err(
"Unknown packet type %d", packet->
type);
struct sr_analog_encoding * encoding
Information on single channel.
void sr_packet_free(struct sr_datafeed_packet *packet)
GSList * stages
List of pointers to struct sr_trigger_stage.
A channel to match and what to match it on.
struct sr_channel * channel
The channel to trigger on.
Header of a sigrok data feed.
GSList * matches
List of pointers to struct sr_trigger_match.
Payload is struct sr_datafeed_meta.
Payload is sr_datafeed_header.
int sr_log_loglevel_get(void)
Get the libsigrok loglevel.
int sr_packet_copy(const struct sr_datafeed_packet *packet, struct sr_datafeed_packet **copy)
Packet in a sigrok data feed.
GVariant * data
Key-specific data.
int sr_session_stop(struct sr_session *session)
Stop a session.
Payload is struct sr_datafeed_logic.
int sr_session_dev_list(struct sr_session *session, GSList **devlist)
List all device instances attached to a session.
The representation of a trigger, consisting of one or more stages containing one or more matches on a...
Analog datafeed payload for type SR_DF_ANALOG.
Used for setting or getting value of a config item.
Generic/unspecified error.
int sr_session_datafeed_callback_remove_all(struct sr_session *session)
Remove all datafeed callbacks in a session.
gboolean enabled
Is this channel enabled?
struct sr_analog_meaning * meaning
int sr_session_dev_remove_all(struct sr_session *session)
Remove all the devices from a session.
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.
Datafeed payload for type SR_DF_META.
struct sr_analog_spec * spec
Errors hinting at internal bugs.
Payload is struct sr_datafeed_analog.
int sr_config_commit(const struct sr_dev_inst *sdi)
Apply configuration settings to the device hardware.
int sr_session_destroy(struct sr_session *session)
Destroy a session.
Opaque structure representing a libsigrok session.
void(* sr_datafeed_callback)(const struct sr_dev_inst *sdi, const struct sr_datafeed_packet *packet, void *cb_data)
Opaque structure representing a libsigrok context.
int sr_session_dev_add(struct sr_session *session, struct sr_dev_inst *sdi)
Add a device instance to a session.
int sr_session_new(struct sr_context *ctx, struct sr_session **new_session)
Create a new 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.
int match
The trigger match to use.
int sr_session_trigger_set(struct sr_session *session, struct sr_trigger *trig)
Set the trigger of this session.
The public libsigrok header file to be used by frontends.
End of stream (no further data).
int sr_session_run(struct sr_session *session)
Block until the running session stops.
int sr_session_dev_remove(struct sr_session *session, struct sr_dev_inst *sdi)
Remove a device instance from a session.
The trigger matched at this point in the data feed.
const char * sr_strerror(int error_code)
Return a human-readable error string for the given libsigrok error code.
Logic datafeed payload for type SR_DF_LOGIC.
int(* sr_receive_data_callback)(int fd, int revents, void *cb_data)
Type definition for callback function for data reception.
void(* sr_session_stopped_callback)(void *data)
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.
char * name
Name of channel.