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