]> sigrok.org Git - libsigrok.git/blame - session_driver.c
gnuplot output: Optimize by only storing changes.
[libsigrok.git] / session_driver.c
CommitLineData
7d658874
BV
1/*
2 * This file is part of the sigrok project.
3 *
4 * Copyright (C) 2011 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 <sys/types.h>
21#include <sys/stat.h>
22#include <fcntl.h>
23#include <unistd.h>
24#include <sys/time.h>
25#include <zip.h>
26#include <sigrok.h>
b08024a8 27#include <sigrok-internal.h>
7d658874
BV
28
29/* size of payloads sent across the session bus */
30#define CHUNKSIZE 4096
31
32struct session_vdevice {
33 char *capturefile;
34 struct zip *archive;
35 struct zip_file *capfile;
36 uint64_t samplerate;
37 int unitsize;
38 int num_probes;
39};
40
41static char *sessionfile = NULL;
42static GSList *device_instances = NULL;
43static int capabilities[] = {
44 SR_HWCAP_CAPTUREFILE,
45 SR_HWCAP_CAPTURE_UNITSIZE,
46 0,
47};
48
49
50static struct session_vdevice *get_vdevice_by_index(int device_index)
51{
52 struct sr_device_instance *sdi;
53 struct session_vdevice *vdevice;
54
55 if (!(sdi = sr_get_device_instance(device_instances, device_index)))
56 return NULL;
57
58 vdevice = sdi->priv;
59
60 return vdevice;
61}
62
63static int feed_chunk(int fd, int revents, void *user_data)
64{
65 struct sr_device_instance *sdi;
66 struct session_vdevice *vdevice;
67 struct sr_datafeed_packet packet;
68 GSList *l;
69 void *buf;
70 int ret, got_data;
71
72 /* avoid compiler warning */
73 fd = fd;
74 revents = revents;
75
b08024a8 76 sr_dbg("session_driver: feed chunk");
7d658874
BV
77
78 got_data = FALSE;
79 for (l = device_instances; l; l = l->next) {
80 sdi = l->data;
81 vdevice = sdi->priv;
82 if (!vdevice)
83 /* already done with this instance */
84 continue;
85
86 buf = g_malloc(CHUNKSIZE);
87 ret = zip_fread(vdevice->capfile, buf, CHUNKSIZE);
88 if (ret > 0) {
89 got_data = TRUE;
90 packet.type = SR_DF_LOGIC;
91 packet.length = ret;
92 packet.unitsize = vdevice->unitsize;
93 packet.payload = buf;
8a2efef2 94 sr_session_bus(user_data, &packet);
7d658874
BV
95 } else {
96 /* done with this capture file */
97 zip_fclose(vdevice->capfile);
98 g_free(vdevice->capturefile);
99 g_free(vdevice);
100 sdi->priv = NULL;
101 }
102 }
103
104 if (!got_data) {
105 packet.type = SR_DF_END;
106 packet.length = 0;
8a2efef2 107 sr_session_bus(user_data, &packet);
7d658874
BV
108 }
109
110 return TRUE;
111}
112
113/* driver callbacks */
114
54ac5277 115static int hw_init(const char *deviceinfo)
7d658874
BV
116{
117
118 sessionfile = g_strdup(deviceinfo);
119
120 return 0;
121}
122
123static void hw_cleanup(void)
124{
125 GSList *l;
126
127 for (l = device_instances; l; l = l->next)
128 sr_device_instance_free(l->data);
129
130 g_free(sessionfile);
131
132}
133
134static int hw_opendev(int device_index)
135{
136 struct sr_device_instance *sdi;
137
138 sdi = sr_device_instance_new(device_index, SR_ST_INITIALIZING,
139 NULL, NULL, NULL);
140 if (!sdi)
141 return SR_ERR;
142 sdi->priv = g_malloc0(sizeof(struct session_vdevice));
143 if (!sdi->priv)
144 return SR_ERR;
145 device_instances = g_slist_append(device_instances, sdi);
146
147 return SR_OK;
148}
149
7d658874
BV
150static void *hw_get_device_info(int device_index, int device_info_id)
151{
152 struct session_vdevice *vdevice;
153 void *info;
154
b8c2f85f
BV
155 if (device_info_id != SR_DI_CUR_SAMPLERATE)
156 return NULL;
157
7d658874
BV
158 if (!(vdevice = get_vdevice_by_index(device_index)))
159 return NULL;
160
161 info = &vdevice->samplerate;
162
163 return info;
164}
165
166static int hw_get_status(int device_index)
167{
168
169 /* avoid compiler warning */
170 device_index = device_index;
171
172 if (devices)
173 return SR_OK;
174 else
175 return SR_ERR;
176}
177
178static int *hw_get_capabilities(void)
179{
180
181 return capabilities;
182}
183
184static int hw_set_configuration(int device_index, int capability, void *value)
185{
186 struct session_vdevice *vdevice;
187 uint64_t *tmp_u64;
188
189 if (!(vdevice = get_vdevice_by_index(device_index)))
190 return SR_ERR;
191
192 switch (capability) {
193 case SR_HWCAP_SAMPLERATE:
194 tmp_u64 = value;
195 vdevice->samplerate = *tmp_u64;
196 break;
197 case SR_HWCAP_CAPTUREFILE:
198 vdevice->capturefile = g_strdup(value);
199 break;
200 case SR_HWCAP_CAPTURE_UNITSIZE:
201 tmp_u64 = value;
202 vdevice->unitsize = *tmp_u64;
203 break;
204 case SR_HWCAP_CAPTURE_NUM_PROBES:
205 tmp_u64 = value;
206 vdevice->num_probes = *tmp_u64;
207 break;
208 default:
209 return SR_ERR;
210 }
211
212 return SR_OK;
213}
214
215static int hw_start_acquisition(int device_index, gpointer session_device_id)
216{
217 struct zip_stat zs;
218 struct session_vdevice *vdevice;
219 struct sr_datafeed_header *header;
220 struct sr_datafeed_packet *packet;
221 int err;
222
223 /* avoid compiler warning */
224 session_device_id = session_device_id;
225
226 if (!(vdevice = get_vdevice_by_index(device_index)))
227 return SR_ERR;
228
b08024a8
UH
229 sr_info("session_driver: opening archive %s file %s", sessionfile,
230 vdevice->capturefile);
7d658874
BV
231
232 if (!(vdevice->archive = zip_open(sessionfile, 0, &err))) {
b08024a8
UH
233 sr_warn("Failed to open session file '%s': zip error %d\n",
234 sessionfile, err);
7d658874
BV
235 return SR_ERR;
236 }
237
238 if (zip_stat(vdevice->archive, vdevice->capturefile, 0, &zs) == -1) {
b08024a8
UH
239 sr_warn("Failed to check capture file '%s' in session file '%s'.",
240 vdevice->capturefile, sessionfile);
7d658874
BV
241 return SR_ERR;
242 }
243
244 if (!(vdevice->capfile = zip_fopen(vdevice->archive, vdevice->capturefile, 0))) {
b08024a8
UH
245 sr_warn("Failed to open capture file '%s' in session file '%s'.",
246 vdevice->capturefile, sessionfile);
7d658874
BV
247 return SR_ERR;
248 }
249
250 /* freewheeling source */
8a2efef2 251 sr_session_source_add(-1, 0, 0, feed_chunk, session_device_id);
7d658874
BV
252
253 /* Send header packet to the session bus. */
254 packet = g_malloc(sizeof(struct sr_datafeed_packet));
255 header = g_malloc(sizeof(struct sr_datafeed_header));
256 if (!packet || !header)
257 return SR_ERR;
258 packet->type = SR_DF_HEADER;
259 packet->length = sizeof(struct sr_datafeed_header);
260 packet->payload = (unsigned char *)header;
261 header->feed_version = 1;
262 gettimeofday(&header->starttime, NULL);
263 header->samplerate = 0;
264 header->protocol_id = SR_PROTO_RAW;
265 header->num_logic_probes = vdevice->num_probes;
266 header->num_analog_probes = 0;
8a2efef2 267 sr_session_bus(session_device_id, packet);
7d658874
BV
268 g_free(header);
269 g_free(packet);
270
271 return SR_OK;
272}
273
7d658874
BV
274
275struct sr_device_plugin session_driver = {
276 "session",
277 "Session-emulating driver",
278 1,
279 hw_init,
280 hw_cleanup,
281 hw_opendev,
b8c2f85f 282 NULL,
7d658874
BV
283 hw_get_device_info,
284 hw_get_status,
285 hw_get_capabilities,
286 hw_set_configuration,
287 hw_start_acquisition,
8a2efef2 288 NULL,
7d658874 289};