]> sigrok.org Git - libsigrok.git/blob - session.c
Make ARRAY_SIZE/ARRAY_AND_SIZE private.
[libsigrok.git] / session.c
1 /*
2  * This file is part of the sigrok project.
3  *
4  * Copyright (C) 2010 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 "config.h"
21 #include <stdio.h>
22 #include <stdlib.h>
23 #include <unistd.h>
24 #include <string.h>
25 #include <glib.h>
26 #include <sigrok.h>
27
28 /* demo.c */
29 extern GIOChannel channels[2];
30
31 struct source {
32         int fd;
33         int events;
34         int timeout;
35         sr_receive_data_callback cb;
36         void *user_data;
37 };
38
39 /* There can only be one session at a time. */
40 struct sr_session *session;
41 int num_sources = 0;
42
43 struct source *sources = NULL;
44 int source_timeout = -1;
45
46
47 struct sr_session *sr_session_new(void)
48 {
49         session = calloc(1, sizeof(struct sr_session));
50
51         return session;
52 }
53
54 void sr_session_destroy(void)
55 {
56         g_slist_free(session->devices);
57
58         /* TODO: Loop over protocol decoders and free them. */
59
60         g_free(session);
61 }
62
63 void sr_session_device_clear(void)
64 {
65         g_slist_free(session->devices);
66         session->devices = NULL;
67 }
68
69 int sr_session_device_add(struct sr_device *device)
70 {
71         int ret;
72
73         if (device->plugin && device->plugin->open) {
74                 ret = device->plugin->open(device->plugin_index);
75                 if (ret != SR_OK)
76                         return ret;
77         }
78
79         session->devices = g_slist_append(session->devices, device);
80
81         return SR_OK;
82 }
83
84 void sr_session_pa_clear(void)
85 {
86         /*
87          * The protocols are pointers to the global set of PA plugins,
88          * so don't free them.
89          */
90         g_slist_free(session->analyzers);
91         session->analyzers = NULL;
92 }
93
94 void sr_session_pa_add(struct sr_analyzer *an)
95 {
96         session->analyzers = g_slist_append(session->analyzers, an);
97 }
98
99 void sr_session_datafeed_callback_clear(void)
100 {
101         g_slist_free(session->datafeed_callbacks);
102         session->datafeed_callbacks = NULL;
103 }
104
105 void sr_session_datafeed_callback_add(sr_datafeed_callback callback)
106 {
107         session->datafeed_callbacks =
108             g_slist_append(session->datafeed_callbacks, callback);
109 }
110
111 static void sr_session_run_poll()
112 {
113         GPollFD *fds, my_gpollfd;
114         int ret, i;
115
116         fds = NULL;
117         while (session->running) {
118                 if (fds)
119                         free(fds);
120
121                 /* Construct g_poll()'s array. */
122                 fds = malloc(sizeof(GPollFD) * num_sources);
123                 for (i = 0; i < num_sources; i++) {
124 #ifdef _WIN32
125                         g_io_channel_win32_make_pollfd(&channels[0],
126                                         sources[i].events, &my_gpollfd);
127 #else
128                         my_gpollfd.fd = sources[i].fd;
129                         my_gpollfd.events = sources[i].events;
130                         fds[i] = my_gpollfd;
131 #endif
132                 }
133
134                 ret = g_poll(fds, num_sources, source_timeout);
135
136                 for (i = 0; i < num_sources; i++) {
137                         if (fds[i].revents > 0 || (ret == 0
138                                 && source_timeout == sources[i].timeout)) {
139                                 /*
140                                  * Invoke the source's callback on an event,
141                                  * or if the poll timeout out and this source
142                                  * asked for that timeout.
143                                  */
144                                 sources[i].cb(fds[i].fd, fds[i].revents,
145                                                   sources[i].user_data);
146                         }
147                 }
148         }
149         free(fds);
150
151 }
152
153 int sr_session_start(void)
154 {
155         struct sr_device *device;
156         GSList *l;
157         int ret;
158
159         g_message("session: starting");
160         for (l = session->devices; l; l = l->next) {
161                 device = l->data;
162                 if ((ret = device->plugin->start_acquisition(
163                                 device->plugin_index, device)) != SR_OK)
164                         break;
165         }
166
167         return ret;
168 }
169
170 void sr_session_run(void)
171 {
172
173         g_message("session: running");
174         session->running = TRUE;
175
176         /* do we have real sources? */
177         if (num_sources == 1 && sources[0].fd == -1)
178                 /* dummy source, freewheel over it */
179                 while (session->running)
180                         sources[0].cb(-1, 0, sources[0].user_data);
181         else
182                 /* real sources, use g_poll() main loop */
183                 sr_session_run_poll();
184
185 }
186
187 void sr_session_halt(void)
188 {
189
190         g_message("session: halting");
191         session->running = FALSE;
192
193 }
194
195 void sr_session_stop(void)
196 {
197         struct sr_device *device;
198         GSList *l;
199
200         g_message("session: stopping");
201         session->running = FALSE;
202         for (l = session->devices; l; l = l->next) {
203                 device = l->data;
204                 if (device->plugin && device->plugin->stop_acquisition)
205                         device->plugin->stop_acquisition(device->plugin_index, device);
206         }
207
208 }
209
210 void sr_session_bus(struct sr_device *device, struct sr_datafeed_packet *packet)
211 {
212         GSList *l;
213         sr_datafeed_callback cb;
214
215         /*
216          * TODO: Send packet through PD pipe, and send the output of that to
217          * the callbacks as well.
218          */
219         for (l = session->datafeed_callbacks; l; l = l->next) {
220                 cb = l->data;
221                 cb(device, packet);
222         }
223 }
224
225 void sr_session_source_add(int fd, int events, int timeout,
226                 sr_receive_data_callback callback, void *user_data)
227 {
228         struct source *new_sources, *s;
229
230         new_sources = calloc(1, sizeof(struct source) * (num_sources + 1));
231
232         if (sources) {
233                 memcpy(new_sources, sources,
234                        sizeof(struct source) * num_sources);
235                 free(sources);
236         }
237
238         s = &new_sources[num_sources++];
239         s->fd = fd;
240         s->events = events;
241         s->timeout = timeout;
242         s->cb = callback;
243         s->user_data = user_data;
244         sources = new_sources;
245
246         if (timeout != source_timeout && timeout > 0
247             && (source_timeout == -1 || timeout < source_timeout))
248                 source_timeout = timeout;
249 }
250
251 void sr_session_source_remove(int fd)
252 {
253         struct source *new_sources;
254         int old, new;
255
256         if (!sources)
257                 return;
258
259         new_sources = calloc(1, sizeof(struct source) * num_sources);
260         for (old = 0; old < num_sources; old++)
261                 if (sources[old].fd != fd)
262                         memcpy(&new_sources[new++], &sources[old],
263                                sizeof(struct source));
264
265         if (old != new) {
266                 free(sources);
267                 sources = new_sources;
268                 num_sources--;
269         } else {
270                 /* Target fd was not found. */
271                 free(new_sources);
272         }
273 }
274