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