]> sigrok.org Git - libsigrok.git/blame - session.c
Prefix datafeed structs with sr_.
[libsigrok.git] / session.c
CommitLineData
a1bb33af
UH
1/*
2 * This file is part of the sigrok project.
3 *
4 * Copyright (C) 2010 Bert Vermeulen <bert@biot.com>
5 *
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>
24#include <zip.h>
544a4582 25#include <glib.h>
62c82025 26#include <sigrok.h>
aa4b1107
BV
27#include <config.h>
28
a1bb33af 29
62c82025 30/* There can only be one session at a time. */
a1bb33af 31struct session *session;
544a4582
BV
32int num_sources = 0;
33/* These live in hwplugin.c, for the frontend to override. */
34extern source_callback_add source_cb_add;
35extern source_callback_remove source_cb_remove;
36
37struct source {
38 int fd;
39 int events;
40 int timeout;
41 receive_data_callback cb;
42 void *user_data;
43};
44
45struct source *sources = NULL;
46int source_timeout = -1;
47
48
49
a1bb33af 50
afc8e4de 51struct session *session_load(const char *filename)
a1bb33af
UH
52{
53 struct session *session;
54
17e1afcb
UH
55 /* Avoid compiler warnings. */
56 filename = filename;
57
62c82025 58 /* TODO: Implement. */
a1bb33af
UH
59 session = NULL;
60
61 return session;
62}
63
a1bb33af
UH
64struct session *session_new(void)
65{
a1bb33af
UH
66 session = calloc(1, sizeof(struct session));
67
68 return session;
69}
70
a1bb33af
UH
71void session_destroy(void)
72{
a1bb33af
UH
73 g_slist_free(session->devices);
74
aa4b1107 75 /* TODO: Loop over protocol decoders and free them. */
a1bb33af
UH
76
77 g_free(session);
a1bb33af
UH
78}
79
a1bb33af
UH
80void session_device_clear(void)
81{
a1bb33af
UH
82 g_slist_free(session->devices);
83 session->devices = NULL;
a1bb33af
UH
84}
85
a1bb33af
UH
86int session_device_add(struct device *device)
87{
88 int ret;
89
aa4b1107
BV
90 if (device->plugin && device->plugin->open) {
91 ret = device->plugin->open(device->plugin_index);
e46b8fb1 92 if (ret != SR_OK)
aa4b1107
BV
93 return ret;
94 }
a1bb33af 95
aa4b1107
BV
96 session->devices = g_slist_append(session->devices, device);
97
e46b8fb1 98 return SR_OK;
a1bb33af
UH
99}
100
a1bb33af
UH
101void session_pa_clear(void)
102{
62c82025
UH
103 /*
104 * The protocols are pointers to the global set of PA plugins,
105 * so don't free them.
106 */
a1bb33af
UH
107 g_slist_free(session->analyzers);
108 session->analyzers = NULL;
a1bb33af
UH
109}
110
a1bb33af
UH
111void session_pa_add(struct analyzer *an)
112{
a1bb33af 113 session->analyzers = g_slist_append(session->analyzers, an);
a1bb33af
UH
114}
115
a1bb33af
UH
116void session_datafeed_callback_clear(void)
117{
a1bb33af
UH
118 g_slist_free(session->datafeed_callbacks);
119 session->datafeed_callbacks = NULL;
a1bb33af
UH
120}
121
a1bb33af
UH
122void session_datafeed_callback_add(datafeed_callback callback)
123{
62c82025
UH
124 session->datafeed_callbacks =
125 g_slist_append(session->datafeed_callbacks, callback);
a1bb33af
UH
126}
127
a1bb33af
UH
128int session_start(void)
129{
130 struct device *device;
131 GSList *l;
132 int ret;
133
544a4582 134 g_message("starting session");
62c82025 135 for (l = session->devices; l; l = l->next) {
a1bb33af 136 device = l->data;
62c82025 137 if ((ret = device->plugin->start_acquisition(
e46b8fb1 138 device->plugin_index, device)) != SR_OK)
a1bb33af
UH
139 break;
140 }
141
142 return ret;
143}
144
544a4582
BV
145void session_run(void)
146{
147 GPollFD *fds, my_gpollfd;
148 int ret, i;
149
150 g_message("running session");
151 session->running = TRUE;
152 fds = NULL;
153 while (session->running) {
154 if (fds)
155 free(fds);
156
157 /* Construct g_poll()'s array. */
158 fds = malloc(sizeof(GPollFD) * num_sources);
159 for (i = 0; i < num_sources; i++) {
160#ifdef _WIN32
161 g_io_channel_win32_make_pollfd(&channels[0],
162 sources[i].events, &my_gpollfd);
163#else
164 my_gpollfd.fd = sources[i].fd;
165 my_gpollfd.events = sources[i].events;
166 fds[i] = my_gpollfd;
167#endif
168 }
169
170 ret = g_poll(fds, num_sources, source_timeout);
171
172 for (i = 0; i < num_sources; i++) {
173 if (fds[i].revents > 0 || (ret == 0
174 && source_timeout == sources[i].timeout)) {
175 /*
176 * Invoke the source's callback on an event,
177 * or if the poll timeout out and this source
178 * asked for that timeout.
179 */
180 sources[i].cb(fds[i].fd, fds[i].revents,
181 sources[i].user_data);
182 }
183 }
184 }
185 free(fds);
186
187}
188
189void session_halt(void)
190{
191
192 g_message("halting session");
193 session->running = FALSE;
194
195}
196
a1bb33af
UH
197void session_stop(void)
198{
199 struct device *device;
200 GSList *l;
201
544a4582
BV
202 g_message("stopping session");
203 session->running = FALSE;
62c82025 204 for (l = session->devices; l; l = l->next) {
a1bb33af 205 device = l->data;
aa4b1107
BV
206 if (device->plugin)
207 device->plugin->stop_acquisition(device->plugin_index, device);
a1bb33af 208 }
544a4582 209
a1bb33af
UH
210}
211
b9c735a2 212void session_bus(struct device *device, struct sr_datafeed_packet *packet)
a1bb33af
UH
213{
214 GSList *l;
215 datafeed_callback cb;
216
62c82025 217 /*
aa4b1107 218 * TODO: Send packet through PD pipe, and send the output of that to
62c82025 219 * the callbacks as well.
a1bb33af 220 */
62c82025 221 for (l = session->datafeed_callbacks; l; l = l->next) {
a1bb33af
UH
222 cb = l->data;
223 cb(device, packet);
224 }
a1bb33af
UH
225}
226
a1bb33af
UH
227int session_save(char *filename)
228{
aa4b1107
BV
229 GSList *l, *p, *d;
230 FILE *meta;
a1bb33af 231 struct device *device;
aa4b1107 232 struct probe *probe;
a1bb33af
UH
233 struct datastore *ds;
234 struct zip *zipfile;
aa4b1107 235 struct zip_source *versrc, *metasrc, *logicsrc;
a1bb33af 236 int bufcnt, devcnt, tmpfile, ret, error;
aa4b1107 237 char version[1], rawname[16], metafile[32], *newfn, *buf;
a1bb33af 238
aa4b1107
BV
239 newfn = g_malloc(strlen(filename) + 10);
240 strcpy(newfn, filename);
241 if (strstr(filename, ".sigrok") != filename+strlen(filename)-7)
242 strcat(newfn, ".sigrok");
a1bb33af 243
aa4b1107
BV
244 /* Quietly delete it first, libzip wants replace ops otherwise. */
245 unlink(newfn);
246 if (!(zipfile = zip_open(newfn, ZIP_CREATE, &error)))
e46b8fb1 247 return SR_ERR;
aa4b1107 248 g_free(newfn);
a1bb33af 249
aa4b1107 250 /* "version" */
a1bb33af 251 version[0] = '1';
aa4b1107 252 if (!(versrc = zip_source_buffer(zipfile, version, 1, 0)))
e46b8fb1 253 return SR_ERR;
aa4b1107 254 if (zip_add(zipfile, "version", versrc) == -1) {
62c82025
UH
255 g_message("error saving version into zipfile: %s",
256 zip_strerror(zipfile));
e46b8fb1 257 return SR_ERR;
a1bb33af
UH
258 }
259
aa4b1107 260 /* init "metadata" */
a1bb33af 261 strcpy(metafile, "sigrok-meta-XXXXXX");
62c82025 262 if ((tmpfile = g_mkstemp(metafile)) == -1)
e46b8fb1 263 return SR_ERR;
a1bb33af 264 close(tmpfile);
aa4b1107
BV
265 meta = fopen(metafile, "wb");
266 fprintf(meta, "sigrok version = %s\n", PACKAGE_VERSION);
267 /* TODO: save protocol decoders used */
a1bb33af 268
aa4b1107 269 /* all datastores in all devices */
a1bb33af 270 devcnt = 1;
62c82025 271 for (l = session->devices; l; l = l->next) {
a1bb33af 272 device = l->data;
aa4b1107
BV
273 /* metadata */
274 fprintf(meta, "[device]\n");
275 if (device->plugin)
276 fprintf(meta, "driver = %s\n", device->plugin->name);
277
a1bb33af 278 ds = device->datastore;
62c82025 279 if (ds) {
aa4b1107
BV
280 /* metadata */
281 fprintf(meta, "capturefile = logic-%d\n", devcnt);
282 for (p = device->probes; p; p = p->next) {
283 probe = p->data;
284 if (probe->enabled) {
285 fprintf(meta, "probe %d", probe->index);
286 if (probe->name)
287 fprintf(meta, " name \"%s\"", probe->name);
288 if (probe->trigger)
289 fprintf(meta, " trigger \"%s\"",
290 probe->trigger);
291 fprintf(meta, "\n");
292 }
293 }
294
295 /* dump datastore into logic-n */
62c82025
UH
296 buf = malloc(ds->num_units * ds->ds_unitsize +
297 DATASTORE_CHUNKSIZE);
a1bb33af 298 bufcnt = 0;
62c82025
UH
299 for (d = ds->chunklist; d; d = d->next) {
300 memcpy(buf + bufcnt, d->data,
301 DATASTORE_CHUNKSIZE);
a1bb33af
UH
302 bufcnt += DATASTORE_CHUNKSIZE;
303 }
aa4b1107 304 if (!(logicsrc = zip_source_buffer(zipfile, buf,
62c82025 305 ds->num_units * ds->ds_unitsize, TRUE)))
e46b8fb1 306 return SR_ERR;
aa4b1107
BV
307 snprintf(rawname, 15, "logic-%d", devcnt);
308 if (zip_add(zipfile, rawname, logicsrc) == -1)
e46b8fb1 309 return SR_ERR;
a1bb33af
UH
310 }
311 devcnt++;
312 }
aa4b1107
BV
313 fclose(meta);
314
315 if (!(metasrc = zip_source_file(zipfile, metafile, 0, -1)))
e46b8fb1 316 return SR_ERR;
aa4b1107 317 if (zip_add(zipfile, "metadata", metasrc) == -1)
e46b8fb1 318 return SR_ERR;
a1bb33af 319
62c82025 320 if ((ret = zip_close(zipfile)) == -1) {
a1bb33af 321 g_message("error saving zipfile: %s", zip_strerror(zipfile));
e46b8fb1 322 return SR_ERR;
a1bb33af
UH
323 }
324
aa4b1107
BV
325 unlink(metafile);
326
e46b8fb1 327 return SR_OK;
a1bb33af 328}
544a4582
BV
329
330void session_source_add(int fd, int events, int timeout,
331 receive_data_callback callback, void *user_data)
332{
333 struct source *new_sources, *s;
334
335 new_sources = calloc(1, sizeof(struct source) * (num_sources + 1));
336
337 if (sources) {
338 memcpy(new_sources, sources,
339 sizeof(struct source) * num_sources);
340 free(sources);
341 }
342
343 s = &new_sources[num_sources++];
344 s->fd = fd;
345 s->events = events;
346 s->timeout = timeout;
347 s->cb = callback;
348 s->user_data = user_data;
349 sources = new_sources;
350
351 if (timeout != source_timeout && timeout > 0
352 && (source_timeout == -1 || timeout < source_timeout))
353 source_timeout = timeout;
354}
355
356void session_source_remove(int fd)
357{
358 struct source *new_sources;
359 int old, new;
360
361 if (!sources)
362 return;
363
364 new_sources = calloc(1, sizeof(struct source) * num_sources);
365 for (old = 0; old < num_sources; old++)
366 if (sources[old].fd != fd)
367 memcpy(&new_sources[new++], &sources[old],
368 sizeof(struct source));
369
370 if (old != new) {
371 free(sources);
372 sources = new_sources;
373 num_sources--;
374 } else {
375 /* Target fd was not found. */
376 free(new_sources);
377 }
378}
379