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