libsigrok
|
00001 /* 00002 * This file is part of the sigrok project. 00003 * 00004 * Copyright (C) 2010-2012 Bert Vermeulen <bert@biot.com> 00005 * 00006 * This program is free software: you can redistribute it and/or modify 00007 * it under the terms of the GNU General Public License as published by 00008 * the Free Software Foundation, either version 3 of the License, or 00009 * (at your option) any later version. 00010 * 00011 * This program is distributed in the hope that it will be useful, 00012 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00013 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00014 * GNU General Public License for more details. 00015 * 00016 * You should have received a copy of the GNU General Public License 00017 * along with this program. If not, see <http://www.gnu.org/licenses/>. 00018 */ 00019 00020 #include <string.h> 00021 #include <stdlib.h> 00022 #include <unistd.h> 00023 #include <zip.h> 00024 #include <glib.h> 00025 #include <glib/gstdio.h> 00026 #include "config.h" 00027 #include "sigrok.h" 00028 #include "sigrok-internal.h" 00029 00030 extern struct sr_session *session; 00031 extern SR_PRIV struct sr_dev_driver session_driver; 00032 00033 /** 00034 * Load the session from the specified filename. 00035 * 00036 * @param filename The name of the session file to load. Must not be NULL. 00037 * 00038 * @return SR_OK upon success, SR_ERR_ARG upon invalid arguments, 00039 * SR_ERR_MALLOC upon memory allocation errors, or SR_ERR upon 00040 * other errors. 00041 */ 00042 SR_API int sr_session_load(const char *filename) 00043 { 00044 GKeyFile *kf; 00045 GPtrArray *capturefiles; 00046 struct zip *archive; 00047 struct zip_file *zf; 00048 struct zip_stat zs; 00049 struct sr_dev *dev; 00050 struct sr_probe *probe; 00051 int ret, probenum, devcnt, i, j; 00052 uint64_t tmp_u64, total_probes, enabled_probes, p; 00053 char **sections, **keys, *metafile, *val, c; 00054 char probename[SR_MAX_PROBENAME_LEN + 1]; 00055 00056 if (!filename) { 00057 sr_err("session file: %s: filename was NULL", __func__); 00058 return SR_ERR_ARG; 00059 } 00060 00061 if (!(archive = zip_open(filename, 0, &ret))) { 00062 sr_dbg("session file: Failed to open session file: zip " 00063 "error %d", ret); 00064 return SR_ERR; 00065 } 00066 00067 /* check "version" */ 00068 if (!(zf = zip_fopen(archive, "version", 0))) { 00069 sr_dbg("session file: Not a sigrok session file."); 00070 return SR_ERR; 00071 } 00072 ret = zip_fread(zf, &c, 1); 00073 if (ret != 1 || c != '1') { 00074 sr_dbg("session file: Not a valid sigrok session file."); 00075 return SR_ERR; 00076 } 00077 zip_fclose(zf); 00078 00079 /* read "metadata" */ 00080 if (zip_stat(archive, "metadata", 0, &zs) == -1) { 00081 sr_dbg("session file: Not a valid sigrok session file."); 00082 return SR_ERR; 00083 } 00084 00085 if (!(metafile = g_try_malloc(zs.size))) { 00086 sr_err("session file: %s: metafile malloc failed", __func__); 00087 return SR_ERR_MALLOC; 00088 } 00089 00090 zf = zip_fopen_index(archive, zs.index, 0); 00091 zip_fread(zf, metafile, zs.size); 00092 zip_fclose(zf); 00093 00094 kf = g_key_file_new(); 00095 if (!g_key_file_load_from_data(kf, metafile, zs.size, 0, NULL)) { 00096 sr_dbg("session file: Failed to parse metadata."); 00097 return SR_ERR; 00098 } 00099 00100 sr_session_new(); 00101 00102 devcnt = 0; 00103 capturefiles = g_ptr_array_new_with_free_func(g_free); 00104 sections = g_key_file_get_groups(kf, NULL); 00105 for (i = 0; sections[i]; i++) { 00106 if (!strcmp(sections[i], "global")) 00107 /* nothing really interesting in here yet */ 00108 continue; 00109 if (!strncmp(sections[i], "device ", 7)) { 00110 /* device section */ 00111 dev = NULL; 00112 enabled_probes = 0; 00113 keys = g_key_file_get_keys(kf, sections[i], NULL, NULL); 00114 for (j = 0; keys[j]; j++) { 00115 val = g_key_file_get_string(kf, sections[i], keys[j], NULL); 00116 if (!strcmp(keys[j], "capturefile")) { 00117 dev = sr_dev_new(&session_driver, devcnt); 00118 if (devcnt == 0) 00119 /* first device, init the driver */ 00120 dev->driver->init((char *)filename); 00121 sr_session_dev_add(dev); 00122 dev->driver->dev_config_set(devcnt, SR_HWCAP_CAPTUREFILE, val); 00123 g_ptr_array_add(capturefiles, val); 00124 } else if (!strcmp(keys[j], "samplerate")) { 00125 sr_parse_sizestring(val, &tmp_u64); 00126 dev->driver->dev_config_set(devcnt, SR_HWCAP_SAMPLERATE, &tmp_u64); 00127 } else if (!strcmp(keys[j], "unitsize")) { 00128 tmp_u64 = strtoull(val, NULL, 10); 00129 dev->driver->dev_config_set(devcnt, SR_HWCAP_CAPTURE_UNITSIZE, &tmp_u64); 00130 } else if (!strcmp(keys[j], "total probes")) { 00131 total_probes = strtoull(val, NULL, 10); 00132 dev->driver->dev_config_set(devcnt, SR_HWCAP_CAPTURE_NUM_PROBES, &total_probes); 00133 for (p = 0; p < total_probes; p++) { 00134 snprintf(probename, SR_MAX_PROBENAME_LEN, "%" PRIu64, p); 00135 sr_dev_probe_add(dev, probename); 00136 } 00137 } else if (!strncmp(keys[j], "probe", 5)) { 00138 if (!dev) 00139 continue; 00140 enabled_probes++; 00141 tmp_u64 = strtoul(keys[j]+5, NULL, 10); 00142 sr_dev_probe_name_set(dev, tmp_u64, val); 00143 } else if (!strncmp(keys[j], "trigger", 7)) { 00144 probenum = strtoul(keys[j]+7, NULL, 10); 00145 sr_dev_trigger_set(dev, probenum, val); 00146 } 00147 } 00148 g_strfreev(keys); 00149 for (p = enabled_probes; p < total_probes; p++) { 00150 probe = g_slist_nth_data(dev->probes, p); 00151 probe->enabled = FALSE; 00152 } 00153 } 00154 } 00155 g_strfreev(sections); 00156 g_key_file_free(kf); 00157 00158 return SR_OK; 00159 } 00160 00161 /** 00162 * Save the current session to the specified file. 00163 * 00164 * @param filename The name of the file where to save the current session. 00165 * Must not be NULL. 00166 * 00167 * @return SR_OK upon success, SR_ERR_ARG upon invalid arguments, or SR_ERR 00168 * upon other errors. 00169 */ 00170 int sr_session_save(const char *filename) 00171 { 00172 GSList *l, *p, *d; 00173 FILE *meta; 00174 struct sr_dev *dev; 00175 struct sr_probe *probe; 00176 struct sr_datastore *ds; 00177 struct zip *zipfile; 00178 struct zip_source *versrc, *metasrc, *logicsrc; 00179 int bufcnt, devcnt, tmpfile, ret, probecnt; 00180 uint64_t samplerate; 00181 char version[1], rawname[16], metafile[32], *buf, *s; 00182 00183 if (!filename) { 00184 sr_err("session file: %s: filename was NULL", __func__); 00185 return SR_ERR_ARG; 00186 } 00187 00188 /* Quietly delete it first, libzip wants replace ops otherwise. */ 00189 unlink(filename); 00190 if (!(zipfile = zip_open(filename, ZIP_CREATE, &ret))) 00191 return SR_ERR; 00192 00193 /* "version" */ 00194 version[0] = '1'; 00195 if (!(versrc = zip_source_buffer(zipfile, version, 1, 0))) 00196 return SR_ERR; 00197 if (zip_add(zipfile, "version", versrc) == -1) { 00198 sr_info("session file: error saving version into zipfile: %s", 00199 zip_strerror(zipfile)); 00200 return SR_ERR; 00201 } 00202 00203 /* init "metadata" */ 00204 strcpy(metafile, "sigrok-meta-XXXXXX"); 00205 if ((tmpfile = g_mkstemp(metafile)) == -1) 00206 return SR_ERR; 00207 close(tmpfile); 00208 meta = g_fopen(metafile, "wb"); 00209 fprintf(meta, "[global]\n"); 00210 fprintf(meta, "sigrok version = %s\n", PACKAGE_VERSION); 00211 /* TODO: save protocol decoders used */ 00212 00213 /* all datastores in all devices */ 00214 devcnt = 1; 00215 for (l = session->devs; l; l = l->next) { 00216 dev = l->data; 00217 /* metadata */ 00218 fprintf(meta, "[device %d]\n", devcnt); 00219 if (dev->driver) 00220 fprintf(meta, "driver = %s\n", dev->driver->name); 00221 00222 ds = dev->datastore; 00223 if (ds) { 00224 /* metadata */ 00225 fprintf(meta, "capturefile = logic-%d\n", devcnt); 00226 fprintf(meta, "unitsize = %d\n", ds->ds_unitsize); 00227 fprintf(meta, "total probes = %d\n", g_slist_length(dev->probes)); 00228 if (sr_dev_has_hwcap(dev, SR_HWCAP_SAMPLERATE)) { 00229 samplerate = *((uint64_t *) dev->driver->dev_info_get( 00230 dev->driver_index, SR_DI_CUR_SAMPLERATE)); 00231 s = sr_samplerate_string(samplerate); 00232 fprintf(meta, "samplerate = %s\n", s); 00233 g_free(s); 00234 } 00235 probecnt = 1; 00236 for (p = dev->probes; p; p = p->next) { 00237 probe = p->data; 00238 if (probe->enabled) { 00239 if (probe->name) 00240 fprintf(meta, "probe%d = %s\n", probecnt, probe->name); 00241 if (probe->trigger) 00242 fprintf(meta, " trigger%d = %s\n", probecnt, probe->trigger); 00243 probecnt++; 00244 } 00245 } 00246 00247 /* dump datastore into logic-n */ 00248 buf = g_try_malloc(ds->num_units * ds->ds_unitsize + 00249 DATASTORE_CHUNKSIZE); 00250 if (!buf) { 00251 sr_err("session file: %s: buf malloc failed", 00252 __func__); 00253 return SR_ERR_MALLOC; 00254 } 00255 00256 bufcnt = 0; 00257 for (d = ds->chunklist; d; d = d->next) { 00258 memcpy(buf + bufcnt, d->data, 00259 DATASTORE_CHUNKSIZE); 00260 bufcnt += DATASTORE_CHUNKSIZE; 00261 } 00262 if (!(logicsrc = zip_source_buffer(zipfile, buf, 00263 ds->num_units * ds->ds_unitsize, TRUE))) 00264 return SR_ERR; 00265 snprintf(rawname, 15, "logic-%d", devcnt); 00266 if (zip_add(zipfile, rawname, logicsrc) == -1) 00267 return SR_ERR; 00268 } 00269 devcnt++; 00270 } 00271 fclose(meta); 00272 00273 if (!(metasrc = zip_source_file(zipfile, metafile, 0, -1))) 00274 return SR_ERR; 00275 if (zip_add(zipfile, "metadata", metasrc) == -1) 00276 return SR_ERR; 00277 00278 if ((ret = zip_close(zipfile)) == -1) { 00279 sr_info("session file: error saving zipfile: %s", 00280 zip_strerror(zipfile)); 00281 return SR_ERR; 00282 } 00283 00284 unlink(metafile); 00285 00286 return SR_OK; 00287 }