libsigrok
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Macros
session_file.c
Go to the documentation of this file.
1 /*
2  * This file is part of the sigrok project.
3  *
4  * Copyright (C) 2010-2012 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 <string.h>
21 #include <stdlib.h>
22 #include <unistd.h>
23 #include <zip.h>
24 #include <glib.h>
25 #include <glib/gstdio.h>
26 #include "config.h"
27 #include "sigrok.h"
28 #include "sigrok-internal.h"
29 
30 extern struct sr_session *session;
32 
33 /**
34  * Load the session from the specified filename.
35  *
36  * @param filename The name of the session file to load. Must not be NULL.
37  *
38  * @return SR_OK upon success, SR_ERR_ARG upon invalid arguments,
39  * SR_ERR_MALLOC upon memory allocation errors, or SR_ERR upon
40  * other errors.
41  */
42 SR_API int sr_session_load(const char *filename)
43 {
44  GKeyFile *kf;
45  GPtrArray *capturefiles;
46  struct zip *archive;
47  struct zip_file *zf;
48  struct zip_stat zs;
49  struct sr_dev *dev;
50  struct sr_probe *probe;
51  int ret, probenum, devcnt, i, j;
52  uint64_t tmp_u64, total_probes, enabled_probes, p;
53  char **sections, **keys, *metafile, *val, c;
54  char probename[SR_MAX_PROBENAME_LEN + 1];
55 
56  if (!filename) {
57  sr_err("session file: %s: filename was NULL", __func__);
58  return SR_ERR_ARG;
59  }
60 
61  if (!(archive = zip_open(filename, 0, &ret))) {
62  sr_dbg("session file: Failed to open session file: zip "
63  "error %d", ret);
64  return SR_ERR;
65  }
66 
67  /* check "version" */
68  if (!(zf = zip_fopen(archive, "version", 0))) {
69  sr_dbg("session file: Not a sigrok session file.");
70  return SR_ERR;
71  }
72  ret = zip_fread(zf, &c, 1);
73  if (ret != 1 || c != '1') {
74  sr_dbg("session file: Not a valid sigrok session file.");
75  return SR_ERR;
76  }
77  zip_fclose(zf);
78 
79  /* read "metadata" */
80  if (zip_stat(archive, "metadata", 0, &zs) == -1) {
81  sr_dbg("session file: Not a valid sigrok session file.");
82  return SR_ERR;
83  }
84 
85  if (!(metafile = g_try_malloc(zs.size))) {
86  sr_err("session file: %s: metafile malloc failed", __func__);
87  return SR_ERR_MALLOC;
88  }
89 
90  zf = zip_fopen_index(archive, zs.index, 0);
91  zip_fread(zf, metafile, zs.size);
92  zip_fclose(zf);
93 
94  kf = g_key_file_new();
95  if (!g_key_file_load_from_data(kf, metafile, zs.size, 0, NULL)) {
96  sr_dbg("session file: Failed to parse metadata.");
97  return SR_ERR;
98  }
99 
100  sr_session_new();
101 
102  devcnt = 0;
103  capturefiles = g_ptr_array_new_with_free_func(g_free);
104  sections = g_key_file_get_groups(kf, NULL);
105  for (i = 0; sections[i]; i++) {
106  if (!strcmp(sections[i], "global"))
107  /* nothing really interesting in here yet */
108  continue;
109  if (!strncmp(sections[i], "device ", 7)) {
110  /* device section */
111  dev = NULL;
112  enabled_probes = 0;
113  keys = g_key_file_get_keys(kf, sections[i], NULL, NULL);
114  for (j = 0; keys[j]; j++) {
115  val = g_key_file_get_string(kf, sections[i], keys[j], NULL);
116  if (!strcmp(keys[j], "capturefile")) {
117  dev = sr_dev_new(&session_driver, devcnt);
118  if (devcnt == 0)
119  /* first device, init the driver */
120  dev->driver->init((char *)filename);
121  sr_session_dev_add(dev);
122  dev->driver->dev_config_set(devcnt, SR_HWCAP_CAPTUREFILE, val);
123  g_ptr_array_add(capturefiles, val);
124  } else if (!strcmp(keys[j], "samplerate")) {
125  sr_parse_sizestring(val, &tmp_u64);
126  dev->driver->dev_config_set(devcnt, SR_HWCAP_SAMPLERATE, &tmp_u64);
127  } else if (!strcmp(keys[j], "unitsize")) {
128  tmp_u64 = strtoull(val, NULL, 10);
129  dev->driver->dev_config_set(devcnt, SR_HWCAP_CAPTURE_UNITSIZE, &tmp_u64);
130  } else if (!strcmp(keys[j], "total probes")) {
131  total_probes = strtoull(val, NULL, 10);
132  dev->driver->dev_config_set(devcnt, SR_HWCAP_CAPTURE_NUM_PROBES, &total_probes);
133  for (p = 0; p < total_probes; p++) {
134  snprintf(probename, SR_MAX_PROBENAME_LEN, "%" PRIu64, p);
135  sr_dev_probe_add(dev, probename);
136  }
137  } else if (!strncmp(keys[j], "probe", 5)) {
138  if (!dev)
139  continue;
140  enabled_probes++;
141  tmp_u64 = strtoul(keys[j]+5, NULL, 10);
142  sr_dev_probe_name_set(dev, tmp_u64, val);
143  } else if (!strncmp(keys[j], "trigger", 7)) {
144  probenum = strtoul(keys[j]+7, NULL, 10);
145  sr_dev_trigger_set(dev, probenum, val);
146  }
147  }
148  g_strfreev(keys);
149  for (p = enabled_probes; p < total_probes; p++) {
150  probe = g_slist_nth_data(dev->probes, p);
151  probe->enabled = FALSE;
152  }
153  }
154  }
155  g_strfreev(sections);
156  g_key_file_free(kf);
157 
158  return SR_OK;
159 }
160 
161 /**
162  * Save the current session to the specified file.
163  *
164  * @param filename The name of the file where to save the current session.
165  * Must not be NULL.
166  *
167  * @return SR_OK upon success, SR_ERR_ARG upon invalid arguments, or SR_ERR
168  * upon other errors.
169  */
170 int sr_session_save(const char *filename)
171 {
172  GSList *l, *p, *d;
173  FILE *meta;
174  struct sr_dev *dev;
175  struct sr_probe *probe;
176  struct sr_datastore *ds;
177  struct zip *zipfile;
178  struct zip_source *versrc, *metasrc, *logicsrc;
179  int bufcnt, devcnt, tmpfile, ret, probecnt;
180  uint64_t samplerate;
181  char version[1], rawname[16], metafile[32], *buf, *s;
182 
183  if (!filename) {
184  sr_err("session file: %s: filename was NULL", __func__);
185  return SR_ERR_ARG;
186  }
187 
188  /* Quietly delete it first, libzip wants replace ops otherwise. */
189  unlink(filename);
190  if (!(zipfile = zip_open(filename, ZIP_CREATE, &ret)))
191  return SR_ERR;
192 
193  /* "version" */
194  version[0] = '1';
195  if (!(versrc = zip_source_buffer(zipfile, version, 1, 0)))
196  return SR_ERR;
197  if (zip_add(zipfile, "version", versrc) == -1) {
198  sr_info("session file: error saving version into zipfile: %s",
199  zip_strerror(zipfile));
200  return SR_ERR;
201  }
202 
203  /* init "metadata" */
204  strcpy(metafile, "sigrok-meta-XXXXXX");
205  if ((tmpfile = g_mkstemp(metafile)) == -1)
206  return SR_ERR;
207  close(tmpfile);
208  meta = g_fopen(metafile, "wb");
209  fprintf(meta, "[global]\n");
210  fprintf(meta, "sigrok version = %s\n", PACKAGE_VERSION);
211  /* TODO: save protocol decoders used */
212 
213  /* all datastores in all devices */
214  devcnt = 1;
215  for (l = session->devs; l; l = l->next) {
216  dev = l->data;
217  /* metadata */
218  fprintf(meta, "[device %d]\n", devcnt);
219  if (dev->driver)
220  fprintf(meta, "driver = %s\n", dev->driver->name);
221 
222  ds = dev->datastore;
223  if (ds) {
224  /* metadata */
225  fprintf(meta, "capturefile = logic-%d\n", devcnt);
226  fprintf(meta, "unitsize = %d\n", ds->ds_unitsize);
227  fprintf(meta, "total probes = %d\n", g_slist_length(dev->probes));
229  samplerate = *((uint64_t *) dev->driver->dev_info_get(
231  s = sr_samplerate_string(samplerate);
232  fprintf(meta, "samplerate = %s\n", s);
233  g_free(s);
234  }
235  probecnt = 1;
236  for (p = dev->probes; p; p = p->next) {
237  probe = p->data;
238  if (probe->enabled) {
239  if (probe->name)
240  fprintf(meta, "probe%d = %s\n", probecnt, probe->name);
241  if (probe->trigger)
242  fprintf(meta, " trigger%d = %s\n", probecnt, probe->trigger);
243  probecnt++;
244  }
245  }
246 
247  /* dump datastore into logic-n */
248  buf = g_try_malloc(ds->num_units * ds->ds_unitsize +
249  DATASTORE_CHUNKSIZE);
250  if (!buf) {
251  sr_err("session file: %s: buf malloc failed",
252  __func__);
253  return SR_ERR_MALLOC;
254  }
255 
256  bufcnt = 0;
257  for (d = ds->chunklist; d; d = d->next) {
258  memcpy(buf + bufcnt, d->data,
259  DATASTORE_CHUNKSIZE);
260  bufcnt += DATASTORE_CHUNKSIZE;
261  }
262  if (!(logicsrc = zip_source_buffer(zipfile, buf,
263  ds->num_units * ds->ds_unitsize, TRUE)))
264  return SR_ERR;
265  snprintf(rawname, 15, "logic-%d", devcnt);
266  if (zip_add(zipfile, rawname, logicsrc) == -1)
267  return SR_ERR;
268  }
269  devcnt++;
270  }
271  fclose(meta);
272 
273  if (!(metasrc = zip_source_file(zipfile, metafile, 0, -1)))
274  return SR_ERR;
275  if (zip_add(zipfile, "metadata", metasrc) == -1)
276  return SR_ERR;
277 
278  if ((ret = zip_close(zipfile)) == -1) {
279  sr_info("session file: error saving zipfile: %s",
280  zip_strerror(zipfile));
281  return SR_ERR;
282  }
283 
284  unlink(metafile);
285 
286  return SR_OK;
287 }