X-Git-Url: https://sigrok.org/gitweb/?p=libsigrok.git;a=blobdiff_plain;f=src%2Fsession.c;h=8d3f66966a4f156c632d185d4f788274b15e58be;hp=f9df6e1f440411e8081d9fbef5498c75ab54a7de;hb=64f26f744bf3185eddb07e8bfe9855e3c7bfac19;hpb=3393f185a5109832db68966a44b46204cc5c53c5 diff --git a/src/session.c b/src/session.c index f9df6e1f..8d3f6696 100644 --- a/src/session.c +++ b/src/session.c @@ -53,7 +53,6 @@ struct datafeed_callback { /** Custom GLib event source for generic descriptor I/O. * @see https://developer.gnome.org/glib/stable/glib-The-Main-Event-Loop.html - * @internal */ struct fd_source { GSource base; @@ -127,7 +126,7 @@ static gboolean fd_source_dispatch(GSource *source, sr_err("Callback not set, cannot dispatch event."); return G_SOURCE_REMOVE; } - keep = (*(sr_receive_data_callback)callback) + keep = (*SR_RECEIVE_DATA_CALLBACK(callback)) (fsource->pollfd.fd, revents, user_data); if (fsource->timeout_us >= 0 && G_LIKELY(keep) @@ -158,7 +157,9 @@ static void fd_source_finalize(GSource *source) * @param session The session the event source belongs to. * @param key The key used to identify this source. * @param fd The file descriptor or HANDLE. + * @param events Events. * @param timeout_ms The timeout interval in ms, or -1 to wait indefinitely. + * * @return A new event source object, or NULL on failure. */ static GSource *fd_source_new(struct sr_session *session, void *key, @@ -256,6 +257,8 @@ SR_API int sr_session_destroy(struct sr_session *session) sr_session_dev_remove_all(session); g_slist_free_full(session->owned_devs, (GDestroyNotify)sr_dev_inst_free); + sr_session_datafeed_callback_remove_all(session); + g_hash_table_unref(session->event_sources); g_mutex_clear(&session->main_mutex); @@ -363,8 +366,7 @@ SR_API int sr_session_dev_add(struct sr_session *session, sr_strerror(ret)); return ret; } - if ((ret = sdi->driver->dev_acquisition_start(sdi, - sdi)) != SR_OK) { + if ((ret = sr_dev_acquisition_start(sdi)) != SR_OK) { sr_err("Failed to start acquisition of device in " "running session (%s)", sr_strerror(ret)); return ret; @@ -403,6 +405,45 @@ SR_API int sr_session_dev_list(struct sr_session *session, GSList **devlist) return SR_OK; } +/** + * Remove a device instance from a session. + * + * @param session The session to remove from. Must not be NULL. + * @param sdi The device instance to remove from a session. Must not + * be NULL. Also, sdi->driver and sdi->driver->dev_open must + * not be NULL. + * + * @retval SR_OK Success. + * @retval SR_ERR_ARG Invalid argument. + * + * @since 0.4.0 + */ +SR_API int sr_session_dev_remove(struct sr_session *session, + struct sr_dev_inst *sdi) +{ + if (!sdi) { + sr_err("%s: sdi was NULL", __func__); + return SR_ERR_ARG; + } + + if (!session) { + sr_err("%s: session was NULL", __func__); + return SR_ERR_ARG; + } + + /* If sdi->session is not session, the device is not in this + * session. */ + if (sdi->session != session) { + sr_err("%s: not assigned to this session", __func__); + return SR_ERR_ARG; + } + + session->devs = g_slist_remove(session->devs, sdi); + sdi->session = NULL; + + return SR_OK; +} + /** * Remove all datafeed callbacks in a session. * @@ -771,8 +812,12 @@ SR_API int sr_session_start(struct sr_session *session) /* Have all devices start acquisition. */ for (l = session->devs; l; l = l->next) { - sdi = l->data; - ret = sdi->driver->dev_acquisition_start(sdi, sdi); + if (!(sdi = l->data)) { + sr_err("Device sdi was NULL, can't start session."); + ret = SR_ERR; + break; + } + ret = sr_dev_acquisition_start(sdi); if (ret != SR_OK) { sr_err("Could not start %s device %s acquisition.", sdi->driver->name, sdi->connection_id); @@ -786,8 +831,7 @@ SR_API int sr_session_start(struct sr_session *session) lend = l->next; for (l = session->devs; l != lend; l = l->next) { sdi = l->data; - if (sdi->driver->dev_acquisition_stop) - sdi->driver->dev_acquisition_stop(sdi, sdi); + sr_dev_acquisition_stop(sdi); } /* TODO: Handle delayed stops. Need to iterate the event * sources... */ @@ -870,8 +914,7 @@ static gboolean session_stop_sync(void *user_data) for (node = session->devs; node; node = node->next) { sdi = node->data; - if (sdi->driver && sdi->driver->dev_acquisition_stop) - sdi->driver->dev_acquisition_stop(sdi, sdi); + sr_dev_acquisition_stop(sdi); } return G_SOURCE_REMOVE; @@ -991,7 +1034,6 @@ SR_API int sr_session_stopped_callback_set(struct sr_session *session, static void datafeed_dump(const struct sr_datafeed_packet *packet) { const struct sr_datafeed_logic *logic; - const struct sr_datafeed_analog_old *analog_old; const struct sr_datafeed_analog *analog; /* Please use the same order as in libsigrok.h. */ @@ -1013,11 +1055,6 @@ static void datafeed_dump(const struct sr_datafeed_packet *packet) sr_dbg("bus: Received SR_DF_LOGIC packet (%" PRIu64 " bytes, " "unitsize = %d).", logic->length, logic->unitsize); break; - case SR_DF_ANALOG_OLD: - analog_old = packet->payload; - sr_dbg("bus: Received SR_DF_ANALOG_OLD packet (%d samples).", - analog_old->num_samples); - break; case SR_DF_FRAME_BEGIN: sr_dbg("bus: Received SR_DF_FRAME_BEGIN packet."); break; @@ -1035,6 +1072,42 @@ static void datafeed_dump(const struct sr_datafeed_packet *packet) } } +/** + * Helper to send a meta datafeed package (SR_DF_META) to the session bus. + * + * @param sdi The device instance to send the package from. Must not be NULL. + * @param key The config key to send to the session bus. + * @param var The value to send to the session bus. + * + * @retval SR_OK Success. + * @retval SR_ERR_ARG Invalid argument. + * + * @private + */ +SR_PRIV int sr_session_send_meta(const struct sr_dev_inst *sdi, + uint32_t key, GVariant *var) +{ + struct sr_config *cfg; + struct sr_datafeed_packet packet; + struct sr_datafeed_meta meta; + int ret; + + cfg = sr_config_new(key, var); + + memset(&meta, 0, sizeof(meta)); + + packet.type = SR_DF_META; + packet.payload = &meta; + + meta.config = g_slist_append(NULL, cfg); + + ret = sr_session_send(sdi, &packet); + g_slist_free(meta.config); + sr_config_free(cfg); + + return ret; +} + /** * Send a packet to whatever is listening on the datafeed bus. * @@ -1072,43 +1145,6 @@ SR_PRIV int sr_session_send(const struct sr_dev_inst *sdi, return SR_ERR_BUG; } - if (packet->type == SR_DF_ANALOG_OLD) { - /* Convert to SR_DF_ANALOG. */ - const struct sr_datafeed_analog_old *analog_old = packet->payload; - struct sr_analog_encoding encoding; - struct sr_analog_meaning meaning; - struct sr_analog_spec spec; - struct sr_datafeed_analog analog; - struct sr_datafeed_packet new_packet; - new_packet.type = SR_DF_ANALOG; - new_packet.payload = &analog; - analog.data = analog_old->data; - analog.num_samples = analog_old->num_samples; - analog.encoding = &encoding; - analog.meaning = &meaning; - analog.spec = &spec; - encoding.unitsize = sizeof(float); - encoding.is_signed = TRUE; - encoding.is_float = TRUE; -#ifdef WORDS_BIGENDIAN - encoding.is_bigendian = TRUE; -#else - encoding.is_bigendian = FALSE; -#endif - encoding.digits = 0; - encoding.is_digits_decimal = FALSE; - encoding.scale.p = 1; - encoding.scale.q = 1; - encoding.offset.p = 0; - encoding.offset.q = 1; - meaning.mq = analog_old->mq; - meaning.unit = analog_old->unit; - meaning.mqflags = analog_old->mqflags; - meaning.channels = analog_old->channels; - spec.spec_digits = 0; - return sr_session_send(sdi, &new_packet); - } - /* * Pass the packet to the first transform module. If that returns * another packet (instead of NULL), pass that packet to the next @@ -1189,6 +1225,7 @@ SR_PRIV int sr_session_source_add_internal(struct sr_session *session, return SR_OK; } +/** @private */ 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) @@ -1200,7 +1237,7 @@ SR_PRIV int sr_session_fd_source_add(struct sr_session *session, if (!source) return SR_ERR; - g_source_set_callback(source, (GSourceFunc)cb, cb_data, NULL); + g_source_set_callback(source, G_SOURCE_FUNC(cb), cb_data, NULL); ret = sr_session_source_add_internal(session, key, source); g_source_unref(source); @@ -1294,7 +1331,7 @@ SR_PRIV int sr_session_source_add_channel(struct sr_session *session, /* We should be using g_io_create_watch(), but can't without * changing the driver API, as the callback signature is different. */ -#ifdef G_OS_WIN32 +#ifdef _WIN32 g_io_channel_win32_make_pollfd(channel, events, &pollfd); #else pollfd.fd = g_io_channel_unix_get_fd(channel); @@ -1445,22 +1482,30 @@ SR_PRIV int sr_session_source_destroyed(struct sr_session *session, static void copy_src(struct sr_config *src, struct sr_datafeed_meta *meta_copy) { + struct sr_config *item; + +#if GLIB_CHECK_VERSION(2, 67, 3) + item = g_memdup2(src, sizeof(*src)); +#else + item = g_memdup(src, sizeof(*src)); +#endif + g_variant_ref(src->data); - meta_copy->config = g_slist_append(meta_copy->config, - g_memdup(src, sizeof(struct sr_config))); + meta_copy->config = g_slist_append(meta_copy->config, item); } -SR_PRIV int sr_packet_copy(const struct sr_datafeed_packet *packet, +SR_API int sr_packet_copy(const struct sr_datafeed_packet *packet, struct sr_datafeed_packet **copy) { const struct sr_datafeed_meta *meta; struct sr_datafeed_meta *meta_copy; const struct sr_datafeed_logic *logic; struct sr_datafeed_logic *logic_copy; - const struct sr_datafeed_analog_old *analog_old; - struct sr_datafeed_analog_old *analog_old_copy; const struct sr_datafeed_analog *analog; struct sr_datafeed_analog *analog_copy; + struct sr_analog_encoding *encoding_copy; + struct sr_analog_meaning *meaning_copy; + struct sr_analog_spec *spec_copy; uint8_t *payload; *copy = g_malloc0(sizeof(struct sr_datafeed_packet)); @@ -1484,41 +1529,41 @@ SR_PRIV int sr_packet_copy(const struct sr_datafeed_packet *packet, break; case SR_DF_LOGIC: logic = packet->payload; - logic_copy = g_malloc(sizeof(logic)); + logic_copy = g_malloc(sizeof(*logic_copy)); + if (!logic_copy) + return SR_ERR; logic_copy->length = logic->length; logic_copy->unitsize = logic->unitsize; + logic_copy->data = g_malloc(logic->length * logic->unitsize); + if (!logic_copy->data) { + g_free(logic_copy); + return SR_ERR; + } memcpy(logic_copy->data, logic->data, logic->length * logic->unitsize); (*copy)->payload = logic_copy; break; - case SR_DF_ANALOG_OLD: - analog_old = packet->payload; - analog_old_copy = g_malloc(sizeof(analog_old)); - analog_old_copy->channels = g_slist_copy(analog_old->channels); - analog_old_copy->num_samples = analog_old->num_samples; - analog_old_copy->mq = analog_old->mq; - analog_old_copy->unit = analog_old->unit; - analog_old_copy->mqflags = analog_old->mqflags; - analog_old_copy->data = g_malloc(analog_old->num_samples * sizeof(float)); - memcpy(analog_old_copy->data, analog_old->data, - analog_old->num_samples * sizeof(float)); - (*copy)->payload = analog_old_copy; - break; case SR_DF_ANALOG: analog = packet->payload; - analog_copy = g_malloc(sizeof(analog)); + analog_copy = g_malloc(sizeof(*analog_copy)); analog_copy->data = g_malloc( analog->encoding->unitsize * analog->num_samples); memcpy(analog_copy->data, analog->data, analog->encoding->unitsize * analog->num_samples); analog_copy->num_samples = analog->num_samples; - analog_copy->encoding = g_memdup(analog->encoding, - sizeof(struct sr_analog_encoding)); - analog_copy->meaning = g_memdup(analog->meaning, - sizeof(struct sr_analog_meaning)); +#if GLIB_CHECK_VERSION(2, 67, 3) + encoding_copy = g_memdup2(analog->encoding, sizeof(*analog->encoding)); + meaning_copy = g_memdup2(analog->meaning, sizeof(*analog->meaning)); + spec_copy = g_memdup2(analog->spec, sizeof(*analog->spec)); +#else + encoding_copy = g_memdup(analog->encoding, sizeof(*analog->encoding)); + meaning_copy = g_memdup(analog->meaning, sizeof(*analog->meaning)); + spec_copy = g_memdup(analog->spec, sizeof(*analog->spec)); +#endif + analog_copy->encoding = encoding_copy; + analog_copy->meaning = meaning_copy; analog_copy->meaning->channels = g_slist_copy( analog->meaning->channels); - analog_copy->spec = g_memdup(analog->spec, - sizeof(struct sr_analog_spec)); + analog_copy->spec = spec_copy; (*copy)->payload = analog_copy; break; default: @@ -1529,11 +1574,10 @@ SR_PRIV int sr_packet_copy(const struct sr_datafeed_packet *packet, return SR_OK; } -void sr_packet_free(struct sr_datafeed_packet *packet) +SR_API void sr_packet_free(struct sr_datafeed_packet *packet) { const struct sr_datafeed_meta *meta; const struct sr_datafeed_logic *logic; - const struct sr_datafeed_analog_old *analog_old; const struct sr_datafeed_analog *analog; struct sr_config *src; GSList *l; @@ -1562,12 +1606,6 @@ void sr_packet_free(struct sr_datafeed_packet *packet) g_free(logic->data); g_free((void *)packet->payload); break; - case SR_DF_ANALOG_OLD: - analog_old = packet->payload; - g_slist_free(analog_old->channels); - g_free(analog_old->data); - g_free((void *)packet->payload); - break; case SR_DF_ANALOG: analog = packet->payload; g_free(analog->data); @@ -1581,7 +1619,6 @@ void sr_packet_free(struct sr_datafeed_packet *packet) sr_err("Unknown packet type %d", packet->type); } g_free(packet); - } /** @} */