blob: b1e3ebbbe8b1debde4f86a220b96c4e72f91c5da [file] [log] [blame]
Uwe Hermanna1bb33a2010-04-02 20:18:27 +02001/*
2 * This file is part of the sigrok project.
3 *
Bert Vermeulenc73d2ea2012-02-13 14:31:51 +01004 * Copyright (C) 2010-2012 Bert Vermeulen <bert@biot.com>
Uwe Hermanna1bb33a2010-04-02 20:18:27 +02005 *
6 * This program is free software: you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation, either version 3 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program. If not, see <http://www.gnu.org/licenses/>.
18 */
19
20#include <stdio.h>
21#include <stdlib.h>
22#include <unistd.h>
23#include <string.h>
Bert Vermeulen544a4582011-01-30 02:40:55 +010024#include <glib.h>
Bert Vermeulen45c59c82012-07-05 00:55:07 +020025#include "libsigrok.h"
26#include "libsigrok-internal.h"
Bert Vermeulenaa4b1102011-01-24 07:46:16 +010027
Bert Vermeulen544a4582011-01-30 02:40:55 +010028struct source {
Bert Vermeulen544a4582011-01-30 02:40:55 +010029 int timeout;
Uwe Hermannd08490a2012-02-29 21:56:24 +010030 sr_receive_data_callback_t cb;
Uwe Hermann1f9813e2012-02-29 22:32:34 +010031 void *cb_data;
Lars-Peter Clausenaac0ea22012-06-30 20:54:44 +020032
33 /* This is used to keep track of the object (fd, pollfd or channel) which is
34 * being polled and will be used to match the source when removing it again.
35 */
36 gintptr poll_object;
Bert Vermeulen544a4582011-01-30 02:40:55 +010037};
38
Bert Vermeulen7d658872011-01-31 22:34:14 +010039/* There can only be one session at a time. */
Uwe Hermanna0ecd832011-12-28 22:55:21 +010040/* 'session' is not static, it's used elsewhere (via 'extern'). */
Uwe Hermann2872d212011-02-08 17:50:29 +010041struct sr_session *session;
Bert Vermeulen544a4582011-01-30 02:40:55 +010042
Uwe Hermann9f45fb32012-01-02 14:15:25 +010043/**
44 * Create a new session.
45 *
Uwe Hermann9f45fb32012-01-02 14:15:25 +010046 * TODO: Should it use the file-global "session" variable or take an argument?
47 * The same question applies to all the other session functions.
48 *
49 * @return A pointer to the newly allocated session, or NULL upon errors.
50 */
Uwe Hermann1a081ca2012-02-01 23:40:35 +010051SR_API struct sr_session *sr_session_new(void)
Uwe Hermanna1bb33a2010-04-02 20:18:27 +020052{
Uwe Hermann133a37b2012-02-11 20:06:46 +010053 if (!(session = g_try_malloc0(sizeof(struct sr_session)))) {
Uwe Hermann9f45fb32012-01-02 14:15:25 +010054 sr_err("session: %s: session malloc failed", __func__);
55 return NULL; /* TODO: SR_ERR_MALLOC? */
56 }
Uwe Hermanna1bb33a2010-04-02 20:18:27 +020057
Lars-Peter Clausenb7e94112012-07-06 23:23:31 +020058 session->source_timeout = -1;
59
Uwe Hermanna1bb33a2010-04-02 20:18:27 +020060 return session;
61}
62
Uwe Hermann9f45fb32012-01-02 14:15:25 +010063/**
64 * Destroy the current session.
65 *
66 * This frees up all memory used by the session.
67 *
Uwe Hermanne0508e62012-01-07 17:08:54 +010068 * @return SR_OK upon success, SR_ERR_BUG if no session exists.
Uwe Hermann9f45fb32012-01-02 14:15:25 +010069 */
Uwe Hermann1a081ca2012-02-01 23:40:35 +010070SR_API int sr_session_destroy(void)
Uwe Hermanna1bb33a2010-04-02 20:18:27 +020071{
Uwe Hermann9f45fb32012-01-02 14:15:25 +010072 if (!session) {
Uwe Hermann133a37b2012-02-11 20:06:46 +010073 sr_err("session: %s: session was NULL", __func__);
Uwe Hermanne0508e62012-01-07 17:08:54 +010074 return SR_ERR_BUG;
Uwe Hermann9f45fb32012-01-02 14:15:25 +010075 }
76
Lars-Peter Clausened229aa2012-07-05 21:15:07 +020077 sr_session_dev_remove_all();
Uwe Hermanna1bb33a2010-04-02 20:18:27 +020078
Uwe Hermann9f45fb32012-01-02 14:15:25 +010079 /* TODO: Error checks needed? */
80
Bert Vermeulenaa4b1102011-01-24 07:46:16 +010081 /* TODO: Loop over protocol decoders and free them. */
Uwe Hermanna1bb33a2010-04-02 20:18:27 +020082
83 g_free(session);
Uwe Hermann9f45fb32012-01-02 14:15:25 +010084 session = NULL;
Uwe Hermanne0508e62012-01-07 17:08:54 +010085
86 return SR_OK;
Uwe Hermanna1bb33a2010-04-02 20:18:27 +020087}
88
Bert Vermeulende4d3f92012-07-22 15:31:56 +020089static void sr_dev_close(struct sr_dev_inst *sdi)
Lars-Peter Clausened229aa2012-07-05 21:15:07 +020090{
Bert Vermeulene8d3d6c2012-07-29 03:01:57 +020091 if (sdi->driver && sdi->driver->dev_close)
Bert Vermeulende4d3f92012-07-22 15:31:56 +020092 sdi->driver->dev_close(sdi);
Lars-Peter Clausened229aa2012-07-05 21:15:07 +020093}
94
Uwe Hermann9f45fb32012-01-02 14:15:25 +010095/**
96 * Remove all the devices from the current session. TODO?
97 *
98 * The session itself (i.e., the struct sr_session) is not free'd and still
99 * exists after this function returns.
100 *
Uwe Hermanne0508e62012-01-07 17:08:54 +0100101 * @return SR_OK upon success, SR_ERR_BUG if no session exists.
Uwe Hermann9f45fb32012-01-02 14:15:25 +0100102 */
Uwe Hermann01c3e9d2012-03-28 21:55:48 +0200103SR_API int sr_session_dev_remove_all(void)
Uwe Hermanna1bb33a2010-04-02 20:18:27 +0200104{
Uwe Hermann9f45fb32012-01-02 14:15:25 +0100105 if (!session) {
Uwe Hermann133a37b2012-02-11 20:06:46 +0100106 sr_err("session: %s: session was NULL", __func__);
Uwe Hermanne0508e62012-01-07 17:08:54 +0100107 return SR_ERR_BUG;
Uwe Hermann9f45fb32012-01-02 14:15:25 +0100108 }
109
Lars-Peter Clausened229aa2012-07-05 21:15:07 +0200110 g_slist_free_full(session->devs, (GDestroyNotify)sr_dev_close);
Uwe Hermannbb7ef792012-02-17 22:25:01 +0100111 session->devs = NULL;
Uwe Hermanne0508e62012-01-07 17:08:54 +0100112
113 return SR_OK;
Uwe Hermanna1bb33a2010-04-02 20:18:27 +0200114}
115
Uwe Hermann9f45fb32012-01-02 14:15:25 +0100116/**
117 * Add a device to the current session.
118 *
Bert Vermeulende4d3f92012-07-22 15:31:56 +0200119 * @param dev The device instance to add to the current session. Must not
120 * be NULL. Also, sdi->driver and sdi->driver->dev_open must
121 * not be NULL.
Uwe Hermann9f45fb32012-01-02 14:15:25 +0100122 *
123 * @return SR_OK upon success, SR_ERR_ARG upon invalid arguments.
124 */
Bert Vermeulende4d3f92012-07-22 15:31:56 +0200125SR_API int sr_session_dev_add(const struct sr_dev_inst *sdi)
Uwe Hermanna1bb33a2010-04-02 20:18:27 +0200126{
127 int ret;
128
Bert Vermeulende4d3f92012-07-22 15:31:56 +0200129 if (!sdi) {
130 sr_err("session: %s: sdi was NULL", __func__);
Uwe Hermann9f45fb32012-01-02 14:15:25 +0100131 return SR_ERR_ARG;
132 }
133
Uwe Hermannd6eb0c32012-03-18 12:57:34 +0100134 if (!session) {
135 sr_err("session: %s: session was NULL", __func__);
136 return SR_ERR_BUG;
Uwe Hermann9f45fb32012-01-02 14:15:25 +0100137 }
138
Bert Vermeulende4d3f92012-07-22 15:31:56 +0200139 /* If sdi->driver is NULL, this is a virtual device. */
140 if (!sdi->driver) {
141 sr_dbg("session: %s: sdi->driver was NULL, this seems to be "
Uwe Hermannd6eb0c32012-03-18 12:57:34 +0100142 "a virtual device; continuing", __func__);
143 /* Just add the device, don't run dev_open(). */
Bert Vermeulende4d3f92012-07-22 15:31:56 +0200144 session->devs = g_slist_append(session->devs, (gpointer)sdi);
Uwe Hermannd6eb0c32012-03-18 12:57:34 +0100145 return SR_OK;
146 }
147
Bert Vermeulende4d3f92012-07-22 15:31:56 +0200148 /* sdi->driver is non-NULL (i.e. we have a real device). */
149 if (!sdi->driver->dev_open) {
150 sr_err("session: %s: sdi->driver->dev_open was NULL", __func__);
Uwe Hermann8ec95d22012-03-21 19:28:43 +0100151 return SR_ERR_BUG;
Uwe Hermann9f45fb32012-01-02 14:15:25 +0100152 }
153
Bert Vermeulende4d3f92012-07-22 15:31:56 +0200154 if ((ret = sdi->driver->dev_open((struct sr_dev_inst *)sdi)) != SR_OK) {
Uwe Hermanne7eb7032012-02-18 11:57:43 +0100155 sr_err("session: %s: dev_open failed (%d)", __func__, ret);
Uwe Hermann9f45fb32012-01-02 14:15:25 +0100156 return ret;
Bert Vermeulenaa4b1102011-01-24 07:46:16 +0100157 }
Uwe Hermanna1bb33a2010-04-02 20:18:27 +0200158
Bert Vermeulende4d3f92012-07-22 15:31:56 +0200159 session->devs = g_slist_append(session->devs, (gpointer)sdi);
Bert Vermeulenaa4b1102011-01-24 07:46:16 +0100160
Uwe Hermanne46b8fb2011-01-29 16:23:12 +0100161 return SR_OK;
Uwe Hermanna1bb33a2010-04-02 20:18:27 +0200162}
163
Uwe Hermann9f45fb32012-01-02 14:15:25 +0100164/**
Uwe Hermann01c3e9d2012-03-28 21:55:48 +0200165 * Remove all datafeed callbacks in the current session.
Uwe Hermann9f45fb32012-01-02 14:15:25 +0100166 *
Uwe Hermanne0508e62012-01-07 17:08:54 +0100167 * @return SR_OK upon success, SR_ERR_BUG if no session exists.
Uwe Hermann9f45fb32012-01-02 14:15:25 +0100168 */
Uwe Hermann01c3e9d2012-03-28 21:55:48 +0200169SR_API int sr_session_datafeed_callback_remove_all(void)
Uwe Hermanna1bb33a2010-04-02 20:18:27 +0200170{
Uwe Hermann9f45fb32012-01-02 14:15:25 +0100171 if (!session) {
172 sr_err("session: %s: session was NULL", __func__);
Uwe Hermanne0508e62012-01-07 17:08:54 +0100173 return SR_ERR_BUG;
Uwe Hermann9f45fb32012-01-02 14:15:25 +0100174 }
175
Uwe Hermanna1bb33a2010-04-02 20:18:27 +0200176 g_slist_free(session->datafeed_callbacks);
177 session->datafeed_callbacks = NULL;
Uwe Hermanne0508e62012-01-07 17:08:54 +0100178
179 return SR_OK;
Uwe Hermanna1bb33a2010-04-02 20:18:27 +0200180}
181
Uwe Hermann9f45fb32012-01-02 14:15:25 +0100182/**
183 * Add a datafeed callback to the current session.
184 *
Uwe Hermannd08490a2012-02-29 21:56:24 +0100185 * @param cb Function to call when a chunk of data is received.
Uwe Hermann0abee502012-03-04 15:08:11 +0100186 * Must not be NULL.
Bert Vermeulena1645fc2012-02-13 03:36:32 +0100187 *
Uwe Hermanne0508e62012-01-07 17:08:54 +0100188 * @return SR_OK upon success, SR_ERR_BUG if no session exists.
Uwe Hermann9f45fb32012-01-02 14:15:25 +0100189 */
Uwe Hermannd08490a2012-02-29 21:56:24 +0100190SR_API int sr_session_datafeed_callback_add(sr_datafeed_callback_t cb)
Uwe Hermanna1bb33a2010-04-02 20:18:27 +0200191{
Uwe Hermann9f45fb32012-01-02 14:15:25 +0100192 if (!session) {
193 sr_err("session: %s: session was NULL", __func__);
Uwe Hermanne0508e62012-01-07 17:08:54 +0100194 return SR_ERR_BUG;
Uwe Hermann9f45fb32012-01-02 14:15:25 +0100195 }
196
Uwe Hermann0abee502012-03-04 15:08:11 +0100197 if (!cb) {
198 sr_err("session: %s: cb was NULL", __func__);
199 return SR_ERR_ARG;
200 }
Uwe Hermann9f45fb32012-01-02 14:15:25 +0100201
Uwe Hermann62c82022010-04-15 20:16:53 +0200202 session->datafeed_callbacks =
Uwe Hermannd08490a2012-02-29 21:56:24 +0100203 g_slist_append(session->datafeed_callbacks, cb);
Uwe Hermanne0508e62012-01-07 17:08:54 +0100204
205 return SR_OK;
Uwe Hermanna1bb33a2010-04-02 20:18:27 +0200206}
207
Uwe Hermanne0508e62012-01-07 17:08:54 +0100208static int sr_session_run_poll(void)
Bert Vermeulen544a4582011-01-30 02:40:55 +0100209{
Lars-Peter Clausenb7e94112012-07-06 23:23:31 +0200210 unsigned int i;
211 int ret;
Bert Vermeulen544a4582011-01-30 02:40:55 +0100212
Bert Vermeulen2cbeb2b2012-08-03 01:04:05 +0200213 while (session->num_sources > 0) {
214 ret = g_poll(session->pollfds, session->num_sources,
215 session->source_timeout);
Lars-Peter Clausenb7e94112012-07-06 23:23:31 +0200216 for (i = 0; i < session->num_sources; i++) {
217 if (session->pollfds[i].revents > 0 || (ret == 0
218 && session->source_timeout == session->sources[i].timeout)) {
Bert Vermeulen544a4582011-01-30 02:40:55 +0100219 /*
220 * Invoke the source's callback on an event,
Bert Vermeulen2cbeb2b2012-08-03 01:04:05 +0200221 * or if the poll timed out and this source
Bert Vermeulen544a4582011-01-30 02:40:55 +0100222 * asked for that timeout.
223 */
Bert Vermeulen2cbeb2b2012-08-03 01:04:05 +0200224 if (!session->sources[i].cb(session->pollfds[i].fd,
225 session->pollfds[i].revents,
226 session->sources[i].cb_data))
Lars-Peter Clausenb7e94112012-07-06 23:23:31 +0200227 sr_session_source_remove(session->sources[i].poll_object);
Bert Vermeulen544a4582011-01-30 02:40:55 +0100228 }
229 }
230 }
Uwe Hermanne0508e62012-01-07 17:08:54 +0100231
232 return SR_OK;
Bert Vermeulen544a4582011-01-30 02:40:55 +0100233}
234
Uwe Hermann9f45fb32012-01-02 14:15:25 +0100235/**
236 * Start a session.
237 *
Bert Vermeulena1645fc2012-02-13 03:36:32 +0100238 * There can only be one session at a time.
Uwe Hermann9f45fb32012-01-02 14:15:25 +0100239 *
240 * @return SR_OK upon success, SR_ERR upon errors.
241 */
Uwe Hermann1a081ca2012-02-01 23:40:35 +0100242SR_API int sr_session_start(void)
Bert Vermeulen7d658872011-01-31 22:34:14 +0100243{
Bert Vermeulende4d3f92012-07-22 15:31:56 +0200244 struct sr_dev_inst *sdi;
Bert Vermeulen7d658872011-01-31 22:34:14 +0100245 GSList *l;
246 int ret;
247
Uwe Hermann9f45fb32012-01-02 14:15:25 +0100248 if (!session) {
249 sr_err("session: %s: session was NULL; a session must be "
Bert Vermeulende4d3f92012-07-22 15:31:56 +0200250 "created before starting it.", __func__);
Uwe Hermann0abee502012-03-04 15:08:11 +0100251 return SR_ERR_BUG;
Uwe Hermann9f45fb32012-01-02 14:15:25 +0100252 }
253
Uwe Hermannbb7ef792012-02-17 22:25:01 +0100254 if (!session->devs) {
Uwe Hermannbb7ef792012-02-17 22:25:01 +0100255 sr_err("session: %s: session->devs was NULL; a session "
Uwe Hermann9f45fb32012-01-02 14:15:25 +0100256 "cannot be started without devices.", __func__);
Uwe Hermann0abee502012-03-04 15:08:11 +0100257 return SR_ERR_BUG;
Uwe Hermann9f45fb32012-01-02 14:15:25 +0100258 }
259
Uwe Hermannb08024a2011-04-14 09:46:53 +0200260 sr_info("session: starting");
Uwe Hermann9f45fb32012-01-02 14:15:25 +0100261
Uwe Hermannbb7ef792012-02-17 22:25:01 +0100262 for (l = session->devs; l; l = l->next) {
Bert Vermeulende4d3f92012-07-22 15:31:56 +0200263 sdi = l->data;
264 if ((ret = sdi->driver->dev_acquisition_start(sdi, sdi)) != SR_OK) {
Renato Caldas446a0372012-01-06 00:04:29 +0000265 sr_err("session: %s: could not start an acquisition "
Uwe Hermann9f45fb32012-01-02 14:15:25 +0100266 "(%d)", __func__, ret);
Bert Vermeulen7d658872011-01-31 22:34:14 +0100267 break;
Uwe Hermann9f45fb32012-01-02 14:15:25 +0100268 }
Bert Vermeulen7d658872011-01-31 22:34:14 +0100269 }
270
Uwe Hermann9f45fb32012-01-02 14:15:25 +0100271 /* TODO: What if there are multiple devices? Which return code? */
272
Bert Vermeulen7d658872011-01-31 22:34:14 +0100273 return ret;
274}
275
Uwe Hermann9f45fb32012-01-02 14:15:25 +0100276/**
277 * Run the session.
278 *
Uwe Hermann9f45fb32012-01-02 14:15:25 +0100279 * TODO: Various error checks etc.
280 *
Uwe Hermanne0508e62012-01-07 17:08:54 +0100281 * @return SR_OK upon success, SR_ERR_BUG upon errors.
Uwe Hermann9f45fb32012-01-02 14:15:25 +0100282 */
Uwe Hermann1a081ca2012-02-01 23:40:35 +0100283SR_API int sr_session_run(void)
Bert Vermeulen7d658872011-01-31 22:34:14 +0100284{
Uwe Hermann9f45fb32012-01-02 14:15:25 +0100285 if (!session) {
286 sr_err("session: %s: session was NULL; a session must be "
287 "created first, before running it.", __func__);
Uwe Hermanne0508e62012-01-07 17:08:54 +0100288 return SR_ERR_BUG;
Uwe Hermann9f45fb32012-01-02 14:15:25 +0100289 }
290
Uwe Hermannbb7ef792012-02-17 22:25:01 +0100291 if (!session->devs) {
Uwe Hermann9f45fb32012-01-02 14:15:25 +0100292 /* TODO: Actually the case? */
Uwe Hermannbb7ef792012-02-17 22:25:01 +0100293 sr_err("session: %s: session->devs was NULL; a session "
Uwe Hermann9f45fb32012-01-02 14:15:25 +0100294 "cannot be run without devices.", __func__);
Uwe Hermanne0508e62012-01-07 17:08:54 +0100295 return SR_ERR_BUG;
Uwe Hermann9f45fb32012-01-02 14:15:25 +0100296 }
297
Uwe Hermannb08024a2011-04-14 09:46:53 +0200298 sr_info("session: running");
Bert Vermeulen7d658872011-01-31 22:34:14 +0100299
Uwe Hermann9f45fb32012-01-02 14:15:25 +0100300 /* Do we have real sources? */
Lars-Peter Clausenb7e94112012-07-06 23:23:31 +0200301 if (session->num_sources == 1 && session->pollfds[0].fd == -1) {
Uwe Hermann9f45fb32012-01-02 14:15:25 +0100302 /* Dummy source, freewheel over it. */
Bert Vermeulen2cbeb2b2012-08-03 01:04:05 +0200303 while (session->num_sources)
Lars-Peter Clausenb7e94112012-07-06 23:23:31 +0200304 session->sources[0].cb(-1, 0, session->sources[0].cb_data);
Uwe Hermann9f45fb32012-01-02 14:15:25 +0100305 } else {
306 /* Real sources, use g_poll() main loop. */
Uwe Hermann8a2efef2011-02-08 18:00:49 +0100307 sr_session_run_poll();
Uwe Hermann9f45fb32012-01-02 14:15:25 +0100308 }
309
Uwe Hermanne0508e62012-01-07 17:08:54 +0100310 return SR_OK;
Bert Vermeulen7d658872011-01-31 22:34:14 +0100311}
312
Uwe Hermann9f45fb32012-01-02 14:15:25 +0100313/**
314 * Halt the current session.
315 *
Lars-Peter Clausen9ffbde02012-07-05 21:15:09 +0200316 * This function is deprecated and should not be used in new code, use
317 * sr_session_stop() instead. The behaviour of this function is identical to
318 * sr_session_stop().
Uwe Hermanne0508e62012-01-07 17:08:54 +0100319 *
320 * @return SR_OK upon success, SR_ERR_BUG if no session exists.
Uwe Hermann9f45fb32012-01-02 14:15:25 +0100321 */
Uwe Hermann1a081ca2012-02-01 23:40:35 +0100322SR_API int sr_session_halt(void)
Bert Vermeulen544a4582011-01-30 02:40:55 +0100323{
Lars-Peter Clausen9ffbde02012-07-05 21:15:09 +0200324 return sr_session_stop();
Bert Vermeulen544a4582011-01-30 02:40:55 +0100325}
326
Uwe Hermann9f45fb32012-01-02 14:15:25 +0100327/**
328 * Stop the current session.
329 *
Bert Vermeulena1645fc2012-02-13 03:36:32 +0100330 * The current session is stopped immediately, with all acquisition sessions
Uwe Hermannc09f0b52012-02-28 23:52:30 +0100331 * being stopped and hardware drivers cleaned up.
Uwe Hermann9f45fb32012-01-02 14:15:25 +0100332 *
Uwe Hermanne0508e62012-01-07 17:08:54 +0100333 * @return SR_OK upon success, SR_ERR_BUG if no session exists.
Uwe Hermann9f45fb32012-01-02 14:15:25 +0100334 */
Uwe Hermann1a081ca2012-02-01 23:40:35 +0100335SR_API int sr_session_stop(void)
Uwe Hermanna1bb33a2010-04-02 20:18:27 +0200336{
Bert Vermeulende4d3f92012-07-22 15:31:56 +0200337 struct sr_dev_inst *sdi;
Uwe Hermanna1bb33a2010-04-02 20:18:27 +0200338 GSList *l;
339
Uwe Hermann9f45fb32012-01-02 14:15:25 +0100340 if (!session) {
341 sr_err("session: %s: session was NULL", __func__);
Uwe Hermanne0508e62012-01-07 17:08:54 +0100342 return SR_ERR_BUG;
Uwe Hermann9f45fb32012-01-02 14:15:25 +0100343 }
344
Uwe Hermannb08024a2011-04-14 09:46:53 +0200345 sr_info("session: stopping");
Uwe Hermanne0508e62012-01-07 17:08:54 +0100346
Uwe Hermannbb7ef792012-02-17 22:25:01 +0100347 for (l = session->devs; l; l = l->next) {
Bert Vermeulende4d3f92012-07-22 15:31:56 +0200348 sdi = l->data;
349 if (sdi->driver) {
350 if (sdi->driver->dev_acquisition_stop)
351 sdi->driver->dev_acquisition_stop(sdi, sdi);
Bert Vermeulen8c76be52012-01-08 22:05:00 +0100352 }
Uwe Hermanna1bb33a2010-04-02 20:18:27 +0200353 }
Uwe Hermann9f45fb32012-01-02 14:15:25 +0100354
Uwe Hermanne0508e62012-01-07 17:08:54 +0100355 return SR_OK;
Uwe Hermanna1bb33a2010-04-02 20:18:27 +0200356}
357
Uwe Hermann9f45fb32012-01-02 14:15:25 +0100358/**
Bert Vermeulena1645fc2012-02-13 03:36:32 +0100359 * Debug helper.
Uwe Hermann9f45fb32012-01-02 14:15:25 +0100360 *
Bert Vermeulen996b0c72012-02-13 02:13:51 +0100361 * @param packet The packet to show debugging information for.
Uwe Hermann9f45fb32012-01-02 14:15:25 +0100362 */
Bert Vermeulen18beaef2012-02-13 00:08:23 +0100363static void datafeed_dump(struct sr_datafeed_packet *packet)
Bert Vermeulen7d2afd62011-06-20 11:42:43 +0200364{
365 struct sr_datafeed_logic *logic;
Bert Vermeulenee7489d2012-04-22 18:11:31 +0200366 struct sr_datafeed_analog *analog;
Bert Vermeulen7d2afd62011-06-20 11:42:43 +0200367
368 switch (packet->type) {
369 case SR_DF_HEADER:
370 sr_dbg("bus: received SR_DF_HEADER");
371 break;
372 case SR_DF_TRIGGER:
Bert Vermeulen01469702012-02-01 02:59:41 +0100373 sr_dbg("bus: received SR_DF_TRIGGER");
Bert Vermeulen7d2afd62011-06-20 11:42:43 +0200374 break;
Bert Vermeulenee7489d2012-04-22 18:11:31 +0200375 case SR_DF_META_LOGIC:
376 sr_dbg("bus: received SR_DF_META_LOGIC");
377 break;
Bert Vermeulen7d2afd62011-06-20 11:42:43 +0200378 case SR_DF_LOGIC:
379 logic = packet->payload;
Uwe Hermanne0508e62012-01-07 17:08:54 +0100380 /* TODO: Check for logic != NULL. */
Bert Vermeulen01469702012-02-01 02:59:41 +0100381 sr_dbg("bus: received SR_DF_LOGIC %" PRIu64 " bytes", logic->length);
Bert Vermeulen7d2afd62011-06-20 11:42:43 +0200382 break;
Bert Vermeulenee7489d2012-04-22 18:11:31 +0200383 case SR_DF_META_ANALOG:
384 sr_dbg("bus: received SR_DF_META_LOGIC");
385 break;
386 case SR_DF_ANALOG:
387 analog = packet->payload;
388 /* TODO: Check for analog != NULL. */
389 sr_dbg("bus: received SR_DF_ANALOG %d samples", analog->num_samples);
390 break;
Bert Vermeulen7d2afd62011-06-20 11:42:43 +0200391 case SR_DF_END:
392 sr_dbg("bus: received SR_DF_END");
393 break;
Bert Vermeulen6ea76692012-04-30 19:55:06 +0200394 case SR_DF_FRAME_BEGIN:
395 sr_dbg("bus: received SR_DF_FRAME_BEGIN");
396 break;
397 case SR_DF_FRAME_END:
398 sr_dbg("bus: received SR_DF_FRAME_END");
399 break;
Bert Vermeulen7d2afd62011-06-20 11:42:43 +0200400 default:
Bert Vermeulen18beaef2012-02-13 00:08:23 +0100401 sr_dbg("bus: received unknown packet type %d", packet->type);
Uwe Hermann9f45fb32012-01-02 14:15:25 +0100402 break;
Bert Vermeulen7d2afd62011-06-20 11:42:43 +0200403 }
Bert Vermeulen7d2afd62011-06-20 11:42:43 +0200404}
405
Uwe Hermann9f45fb32012-01-02 14:15:25 +0100406/**
Bert Vermeulena1645fc2012-02-13 03:36:32 +0100407 * Send a packet to whatever is listening on the datafeed bus.
408 *
409 * Hardware drivers use this to send a data packet to the frontend.
Uwe Hermann9f45fb32012-01-02 14:15:25 +0100410 *
Uwe Hermannbb7ef792012-02-17 22:25:01 +0100411 * @param dev TODO.
Uwe Hermann31ccebc2012-02-29 22:08:45 +0100412 * @param packet The datafeed packet to send to the session bus.
Uwe Hermann44dae532012-02-17 20:44:19 +0100413 *
Uwe Hermanne0508e62012-01-07 17:08:54 +0100414 * @return SR_OK upon success, SR_ERR_ARG upon invalid arguments.
Uwe Hermann9f45fb32012-01-02 14:15:25 +0100415 */
Bert Vermeulende4d3f92012-07-22 15:31:56 +0200416SR_PRIV int sr_session_send(const struct sr_dev_inst *sdi,
Uwe Hermann31ccebc2012-02-29 22:08:45 +0100417 struct sr_datafeed_packet *packet)
Uwe Hermanna1bb33a2010-04-02 20:18:27 +0200418{
419 GSList *l;
Uwe Hermannd08490a2012-02-29 21:56:24 +0100420 sr_datafeed_callback_t cb;
Uwe Hermanna1bb33a2010-04-02 20:18:27 +0200421
Bert Vermeulende4d3f92012-07-22 15:31:56 +0200422 if (!sdi) {
423 sr_err("session: %s: sdi was NULL", __func__);
Uwe Hermanne0508e62012-01-07 17:08:54 +0100424 return SR_ERR_ARG;
Uwe Hermann9f45fb32012-01-02 14:15:25 +0100425 }
426
Uwe Hermanne0508e62012-01-07 17:08:54 +0100427 if (!packet) {
428 sr_err("session: %s: packet was NULL", __func__);
429 return SR_ERR_ARG;
Uwe Hermann9f45fb32012-01-02 14:15:25 +0100430 }
431
Uwe Hermann62c82022010-04-15 20:16:53 +0200432 for (l = session->datafeed_callbacks; l; l = l->next) {
Bert Vermeulen18beaef2012-02-13 00:08:23 +0100433 if (sr_log_loglevel_get() >= SR_LOG_DBG)
434 datafeed_dump(packet);
Uwe Hermanna1bb33a2010-04-02 20:18:27 +0200435 cb = l->data;
Bert Vermeulende4d3f92012-07-22 15:31:56 +0200436 cb(sdi, packet);
Uwe Hermanna1bb33a2010-04-02 20:18:27 +0200437 }
Uwe Hermann9f45fb32012-01-02 14:15:25 +0100438
Uwe Hermanne0508e62012-01-07 17:08:54 +0100439 return SR_OK;
Uwe Hermanna1bb33a2010-04-02 20:18:27 +0200440}
441
Lars-Peter Clausenaac0ea22012-06-30 20:54:44 +0200442static int _sr_session_source_add(GPollFD *pollfd, int timeout,
Uwe Hermann1a895c62012-07-05 01:47:44 +0200443 sr_receive_data_callback_t cb, void *cb_data, gintptr poll_object)
Bert Vermeulen544a4582011-01-30 02:40:55 +0100444{
445 struct source *new_sources, *s;
Lars-Peter Clausenaac0ea22012-06-30 20:54:44 +0200446 GPollFD *new_pollfds;
Bert Vermeulen544a4582011-01-30 02:40:55 +0100447
Uwe Hermannd08490a2012-02-29 21:56:24 +0100448 if (!cb) {
449 sr_err("session: %s: cb was NULL", __func__);
Uwe Hermanne0508e62012-01-07 17:08:54 +0100450 return SR_ERR_ARG;
Uwe Hermann9f45fb32012-01-02 14:15:25 +0100451 }
452
Uwe Hermann1f9813e2012-02-29 22:32:34 +0100453 /* Note: cb_data can be NULL, that's not a bug. */
Uwe Hermann9f45fb32012-01-02 14:15:25 +0100454
Bert Vermeulen2ac2e622012-07-22 15:32:35 +0200455 new_pollfds = g_try_realloc(session->pollfds,
456 sizeof(GPollFD) * (session->num_sources + 1));
Lars-Peter Clausen0687dfc2012-06-30 20:54:43 +0200457 if (!new_pollfds) {
Uwe Hermann1a895c62012-07-05 01:47:44 +0200458 sr_err("session: %s: new_pollfds malloc failed", __func__);
Lars-Peter Clausen0687dfc2012-06-30 20:54:43 +0200459 return SR_ERR_MALLOC;
460 }
461
Lars-Peter Clausenb7e94112012-07-06 23:23:31 +0200462 new_sources = g_try_realloc(session->sources, sizeof(struct source) *
Bert Vermeulen2ac2e622012-07-22 15:32:35 +0200463 (session->num_sources + 1));
Uwe Hermann9f45fb32012-01-02 14:15:25 +0100464 if (!new_sources) {
465 sr_err("session: %s: new_sources malloc failed", __func__);
Uwe Hermanne0508e62012-01-07 17:08:54 +0100466 return SR_ERR_MALLOC;
Uwe Hermann9f45fb32012-01-02 14:15:25 +0100467 }
Bert Vermeulen544a4582011-01-30 02:40:55 +0100468
Lars-Peter Clausenb7e94112012-07-06 23:23:31 +0200469 new_pollfds[session->num_sources] = *pollfd;
470 s = &new_sources[session->num_sources++];
Bert Vermeulen544a4582011-01-30 02:40:55 +0100471 s->timeout = timeout;
Uwe Hermannd08490a2012-02-29 21:56:24 +0100472 s->cb = cb;
Uwe Hermann1f9813e2012-02-29 22:32:34 +0100473 s->cb_data = cb_data;
Lars-Peter Clausenaac0ea22012-06-30 20:54:44 +0200474 s->poll_object = poll_object;
Lars-Peter Clausenb7e94112012-07-06 23:23:31 +0200475 session->pollfds = new_pollfds;
476 session->sources = new_sources;
Bert Vermeulen544a4582011-01-30 02:40:55 +0100477
Lars-Peter Clausenb7e94112012-07-06 23:23:31 +0200478 if (timeout != session->source_timeout && timeout > 0
479 && (session->source_timeout == -1 || timeout < session->source_timeout))
480 session->source_timeout = timeout;
Uwe Hermann9f45fb32012-01-02 14:15:25 +0100481
Uwe Hermanne0508e62012-01-07 17:08:54 +0100482 return SR_OK;
Bert Vermeulen544a4582011-01-30 02:40:55 +0100483}
484
Uwe Hermann9f45fb32012-01-02 14:15:25 +0100485/**
Lars-Peter Clausenaac0ea22012-06-30 20:54:44 +0200486 * Add a event source for a file descriptor.
Uwe Hermann9f45fb32012-01-02 14:15:25 +0100487 *
Lars-Peter Clausenaac0ea22012-06-30 20:54:44 +0200488 * @param fd The file descriptor.
489 * @param events Events to check for.
490 * @param timeout Max time to wait before the callback is called, ignored if 0.
491 * @param cb Callback function to add. Must not be NULL.
492 * @param cb_data Data for the callback function. Can be NULL.
Uwe Hermann44dae532012-02-17 20:44:19 +0100493 *
Uwe Hermanne0508e62012-01-07 17:08:54 +0100494 * @return SR_OK upon success, SR_ERR_ARG upon invalid arguments, or
Lars-Peter Clausenaac0ea22012-06-30 20:54:44 +0200495 * SR_ERR_MALLOC upon memory allocation errors.
Uwe Hermann9f45fb32012-01-02 14:15:25 +0100496 */
Lars-Peter Clausenaac0ea22012-06-30 20:54:44 +0200497SR_API int sr_session_source_add(int fd, int events, int timeout,
498 sr_receive_data_callback_t cb, void *cb_data)
499{
500 GPollFD p;
501
Lars-Peter Clausenaac0ea22012-06-30 20:54:44 +0200502 p.fd = fd;
503 p.events = events;
Lars-Peter Clausenaac0ea22012-06-30 20:54:44 +0200504
505 return _sr_session_source_add(&p, timeout, cb, cb_data, (gintptr)fd);
506}
507
508/**
Uwe Hermann1a895c62012-07-05 01:47:44 +0200509 * Add an event source for a GPollFD.
Lars-Peter Clausenaac0ea22012-06-30 20:54:44 +0200510 *
511 * TODO: More error checks etc.
512 *
513 * @param pollfd The GPollFD.
514 * @param timeout Max time to wait before the callback is called, ignored if 0.
515 * @param cb Callback function to add. Must not be NULL.
516 * @param cb_data Data for the callback function. Can be NULL.
517 *
518 * @return SR_OK upon success, SR_ERR_ARG upon invalid arguments, or
519 * SR_ERR_MALLOC upon memory allocation errors.
520 */
521SR_API int sr_session_source_add_pollfd(GPollFD *pollfd, int timeout,
522 sr_receive_data_callback_t cb, void *cb_data)
523{
Uwe Hermann1a895c62012-07-05 01:47:44 +0200524 return _sr_session_source_add(pollfd, timeout, cb,
525 cb_data, (gintptr)pollfd);
Lars-Peter Clausenaac0ea22012-06-30 20:54:44 +0200526}
527
528/**
Uwe Hermann1a895c62012-07-05 01:47:44 +0200529 * Add an event source for a GIOChannel.
Lars-Peter Clausenaac0ea22012-06-30 20:54:44 +0200530 *
531 * TODO: More error checks etc.
532 *
533 * @param channel The GIOChannel.
534 * @param events Events to poll on.
535 * @param timeout Max time to wait before the callback is called, ignored if 0.
536 * @param cb Callback function to add. Must not be NULL.
537 * @param cb_data Data for the callback function. Can be NULL.
538 *
539 * @return SR_OK upon success, SR_ERR_ARG upon invalid arguments, or
540 * SR_ERR_MALLOC upon memory allocation errors.
541 */
Uwe Hermann1a895c62012-07-05 01:47:44 +0200542SR_API int sr_session_source_add_channel(GIOChannel *channel, int events,
543 int timeout, sr_receive_data_callback_t cb, void *cb_data)
Lars-Peter Clausenaac0ea22012-06-30 20:54:44 +0200544{
545 GPollFD p;
546
547#ifdef _WIN32
548 g_io_channel_win32_make_pollfd(channel,
549 events, &p);
550#else
551 p.fd = g_io_channel_unix_get_fd(channel);
552 p.events = events;
553#endif
554
555 return _sr_session_source_add(&p, timeout, cb, cb_data, (gintptr)channel);
556}
557
558
559static int _sr_session_source_remove(gintptr poll_object)
Bert Vermeulen544a4582011-01-30 02:40:55 +0100560{
561 struct source *new_sources;
Lars-Peter Clausen0687dfc2012-06-30 20:54:43 +0200562 GPollFD *new_pollfds;
Lars-Peter Clausenb7e94112012-07-06 23:23:31 +0200563 unsigned int old;
Bert Vermeulen544a4582011-01-30 02:40:55 +0100564
Lars-Peter Clausenb7e94112012-07-06 23:23:31 +0200565 if (!session->sources || !session->num_sources) {
Uwe Hermanne0508e62012-01-07 17:08:54 +0100566 sr_err("session: %s: sources was NULL", __func__);
Uwe Hermann0abee502012-03-04 15:08:11 +0100567 return SR_ERR_BUG;
Uwe Hermanne0508e62012-01-07 17:08:54 +0100568 }
569
Lars-Peter Clausenb7e94112012-07-06 23:23:31 +0200570 for (old = 0; old < session->num_sources; old++) {
571 if (session->sources[old].poll_object == poll_object)
Lars-Peter Clausen2bccd322012-06-30 20:54:42 +0200572 break;
573 }
Bert Vermeulen544a4582011-01-30 02:40:55 +0100574
Lars-Peter Clausen2bccd322012-06-30 20:54:42 +0200575 /* fd not found, nothing to do */
Lars-Peter Clausenb7e94112012-07-06 23:23:31 +0200576 if (old == session->num_sources)
Lars-Peter Clausen2bccd322012-06-30 20:54:42 +0200577 return SR_OK;
578
Lars-Peter Clausenb7e94112012-07-06 23:23:31 +0200579 session->num_sources -= 1;
Lars-Peter Clausen2bccd322012-06-30 20:54:42 +0200580
Lars-Peter Clausenb7e94112012-07-06 23:23:31 +0200581 if (old != session->num_sources) {
582 memmove(&session->pollfds[old], &session->pollfds[old+1],
583 (session->num_sources - old) * sizeof(GPollFD));
584 memmove(&session->sources[old], &session->sources[old+1],
585 (session->num_sources - old) * sizeof(struct source));
Lars-Peter Clausen2bccd322012-06-30 20:54:42 +0200586 }
587
Lars-Peter Clausenb7e94112012-07-06 23:23:31 +0200588 new_pollfds = g_try_realloc(session->pollfds, sizeof(GPollFD) * session->num_sources);
589 if (!new_pollfds && session->num_sources > 0) {
Uwe Hermann1a895c62012-07-05 01:47:44 +0200590 sr_err("session: %s: new_pollfds malloc failed", __func__);
Lars-Peter Clausen0687dfc2012-06-30 20:54:43 +0200591 return SR_ERR_MALLOC;
592 }
593
Lars-Peter Clausenb7e94112012-07-06 23:23:31 +0200594 new_sources = g_try_realloc(session->sources, sizeof(struct source) * session->num_sources);
595 if (!new_sources && session->num_sources > 0) {
Uwe Hermann9f45fb32012-01-02 14:15:25 +0100596 sr_err("session: %s: new_sources malloc failed", __func__);
Uwe Hermanne0508e62012-01-07 17:08:54 +0100597 return SR_ERR_MALLOC;
Uwe Hermann9f45fb32012-01-02 14:15:25 +0100598 }
599
Lars-Peter Clausenb7e94112012-07-06 23:23:31 +0200600 session->pollfds = new_pollfds;
601 session->sources = new_sources;
Uwe Hermanne0508e62012-01-07 17:08:54 +0100602
603 return SR_OK;
Bert Vermeulen544a4582011-01-30 02:40:55 +0100604}
Lars-Peter Clausenaac0ea22012-06-30 20:54:44 +0200605
606/*
607 * Remove the source belonging to the specified file descriptor.
608 *
609 * TODO: More error checks.
610 *
Uwe Hermann1a895c62012-07-05 01:47:44 +0200611 * @param fd The file descriptor for which the source should be removed.
Lars-Peter Clausenaac0ea22012-06-30 20:54:44 +0200612 *
613 * @return SR_OK upon success, SR_ERR_ARG upon invalid arguments, or
614 * SR_ERR_MALLOC upon memory allocation errors, SR_ERR_BUG upon
615 * internal errors.
616 */
617SR_API int sr_session_source_remove(int fd)
618{
619 return _sr_session_source_remove((gintptr)fd);
620}
621
622/**
623 * Remove the source belonging to the specified poll descriptor.
624 *
625 * TODO: More error checks.
626 *
627 * @param pollfd The poll descriptor for which the source should be removed.
628 *
629 * @return SR_OK upon success, SR_ERR_ARG upon invalid arguments, or
630 * SR_ERR_MALLOC upon memory allocation errors, SR_ERR_BUG upon
631 * internal errors.
632 */
633SR_API int sr_session_source_remove_pollfd(GPollFD *pollfd)
634{
635 return _sr_session_source_remove((gintptr)pollfd);
636}
637
638/*
639 * Remove the source belonging to the specified channel.
640 *
641 * TODO: More error checks.
642 *
Uwe Hermann1a895c62012-07-05 01:47:44 +0200643 * @param channel The channel for which the source should be removed.
Lars-Peter Clausenaac0ea22012-06-30 20:54:44 +0200644 *
645 * @return SR_OK upon success, SR_ERR_ARG upon invalid arguments, or
646 * SR_ERR_MALLOC upon memory allocation errors, SR_ERR_BUG upon
647 * internal errors.
648 */
649SR_API int sr_session_source_remove_channel(GIOChannel *channel)
650{
651 return _sr_session_source_remove((gintptr)channel);
652}