]> sigrok.org Git - libsigrok.git/blame - session.c
sr: session/demo: Remove Windows specific hack
[libsigrok.git] / session.c
CommitLineData
a1bb33af
UH
1/*
2 * This file is part of the sigrok project.
3 *
c73d2ea4 4 * Copyright (C) 2010-2012 Bert Vermeulen <bert@biot.com>
a1bb33af
UH
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 <stdio.h>
21#include <stdlib.h>
22#include <unistd.h>
23#include <string.h>
544a4582 24#include <glib.h>
45c59c8b
BV
25#include "libsigrok.h"
26#include "libsigrok-internal.h"
aa4b1107 27
544a4582 28struct source {
544a4582 29 int timeout;
d08490aa 30 sr_receive_data_callback_t cb;
1f9813eb 31 void *cb_data;
aac0ea25
LPC
32
33 /* This is used to keep track of the object (fd, pollfd or channel) which is
34 * being polled and will be used to match the source when removing it again.
35 */
36 gintptr poll_object;
544a4582
BV
37};
38
7d658874 39/* There can only be one session at a time. */
a0ecd83b 40/* 'session' is not static, it's used elsewhere (via 'extern'). */
2872d21e 41struct sr_session *session;
a0ecd83b 42static int num_sources = 0;
544a4582 43
0687dfcd
LPC
44/* Both "sources" and "pollfds" are of the same size and contain pairs of
45 * descriptor and callback function. We can not embed the GPollFD into the
46 * source struct since we want to be able to pass the array of all poll
47 * descriptors to g_poll.
48 */
a0ecd83b 49static struct source *sources = NULL;
0687dfcd 50static GPollFD *pollfds;
a0ecd83b 51static int source_timeout = -1;
544a4582 52
9f45fb3a
UH
53/**
54 * Create a new session.
55 *
9f45fb3a
UH
56 * TODO: Should it use the file-global "session" variable or take an argument?
57 * The same question applies to all the other session functions.
58 *
59 * @return A pointer to the newly allocated session, or NULL upon errors.
60 */
1a081ca6 61SR_API struct sr_session *sr_session_new(void)
a1bb33af 62{
133a37bf 63 if (!(session = g_try_malloc0(sizeof(struct sr_session)))) {
9f45fb3a
UH
64 sr_err("session: %s: session malloc failed", __func__);
65 return NULL; /* TODO: SR_ERR_MALLOC? */
66 }
a1bb33af
UH
67
68 return session;
69}
70
9f45fb3a
UH
71/**
72 * Destroy the current session.
73 *
74 * This frees up all memory used by the session.
75 *
e0508e67 76 * @return SR_OK upon success, SR_ERR_BUG if no session exists.
9f45fb3a 77 */
1a081ca6 78SR_API int sr_session_destroy(void)
a1bb33af 79{
9f45fb3a 80 if (!session) {
133a37bf 81 sr_err("session: %s: session was NULL", __func__);
e0508e67 82 return SR_ERR_BUG;
9f45fb3a
UH
83 }
84
bb7ef793
UH
85 g_slist_free(session->devs);
86 session->devs = NULL;
a1bb33af 87
9f45fb3a
UH
88 /* TODO: Error checks needed? */
89
aa4b1107 90 /* TODO: Loop over protocol decoders and free them. */
a1bb33af
UH
91
92 g_free(session);
9f45fb3a 93 session = NULL;
e0508e67
UH
94
95 return SR_OK;
a1bb33af
UH
96}
97
9f45fb3a
UH
98/**
99 * Remove all the devices from the current session. TODO?
100 *
101 * The session itself (i.e., the struct sr_session) is not free'd and still
102 * exists after this function returns.
103 *
e0508e67 104 * @return SR_OK upon success, SR_ERR_BUG if no session exists.
9f45fb3a 105 */
01c3e9db 106SR_API int sr_session_dev_remove_all(void)
a1bb33af 107{
9f45fb3a 108 if (!session) {
133a37bf 109 sr_err("session: %s: session was NULL", __func__);
e0508e67 110 return SR_ERR_BUG;
9f45fb3a
UH
111 }
112
bb7ef793
UH
113 g_slist_free(session->devs);
114 session->devs = NULL;
e0508e67
UH
115
116 return SR_OK;
a1bb33af
UH
117}
118
9f45fb3a
UH
119/**
120 * Add a device to the current session.
121 *
bb7ef793 122 * @param dev The device to add to the current session. Must not be NULL.
c09f0b57 123 * Also, dev->driver and dev->driver->dev_open must not be NULL.
9f45fb3a
UH
124 *
125 * @return SR_OK upon success, SR_ERR_ARG upon invalid arguments.
126 */
bb7ef793 127SR_API int sr_session_dev_add(struct sr_dev *dev)
a1bb33af
UH
128{
129 int ret;
130
bb7ef793
UH
131 if (!dev) {
132 sr_err("session: %s: dev was NULL", __func__);
9f45fb3a
UH
133 return SR_ERR_ARG;
134 }
135
d6eb0c33
UH
136 if (!session) {
137 sr_err("session: %s: session was NULL", __func__);
138 return SR_ERR_BUG;
139 }
140
141 /* If dev->driver is NULL, this is a virtual device. */
c09f0b57 142 if (!dev->driver) {
d6eb0c33
UH
143 sr_dbg("session: %s: dev->driver was NULL, this seems to be "
144 "a virtual device; continuing", __func__);
145 /* Just add the device, don't run dev_open(). */
146 session->devs = g_slist_append(session->devs, dev);
147 return SR_OK;
9f45fb3a
UH
148 }
149
d6eb0c33 150 /* dev->driver is non-NULL (i.e. we have a real device). */
c09f0b57
UH
151 if (!dev->driver->dev_open) {
152 sr_err("session: %s: dev->driver->dev_open was NULL",
9f45fb3a 153 __func__);
8ec95d22 154 return SR_ERR_BUG;
9f45fb3a
UH
155 }
156
c09f0b57 157 if ((ret = dev->driver->dev_open(dev->driver_index)) != SR_OK) {
e7eb703f 158 sr_err("session: %s: dev_open failed (%d)", __func__, ret);
9f45fb3a 159 return ret;
aa4b1107 160 }
a1bb33af 161
bb7ef793 162 session->devs = g_slist_append(session->devs, dev);
aa4b1107 163
e46b8fb1 164 return SR_OK;
a1bb33af
UH
165}
166
9f45fb3a 167/**
01c3e9db 168 * Remove all datafeed callbacks in the current session.
9f45fb3a 169 *
e0508e67 170 * @return SR_OK upon success, SR_ERR_BUG if no session exists.
9f45fb3a 171 */
01c3e9db 172SR_API int sr_session_datafeed_callback_remove_all(void)
a1bb33af 173{
9f45fb3a
UH
174 if (!session) {
175 sr_err("session: %s: session was NULL", __func__);
e0508e67 176 return SR_ERR_BUG;
9f45fb3a
UH
177 }
178
a1bb33af
UH
179 g_slist_free(session->datafeed_callbacks);
180 session->datafeed_callbacks = NULL;
e0508e67
UH
181
182 return SR_OK;
a1bb33af
UH
183}
184
9f45fb3a
UH
185/**
186 * Add a datafeed callback to the current session.
187 *
d08490aa 188 * @param cb Function to call when a chunk of data is received.
0abee507 189 * Must not be NULL.
a1645fcd 190 *
e0508e67 191 * @return SR_OK upon success, SR_ERR_BUG if no session exists.
9f45fb3a 192 */
d08490aa 193SR_API int sr_session_datafeed_callback_add(sr_datafeed_callback_t cb)
a1bb33af 194{
9f45fb3a
UH
195 if (!session) {
196 sr_err("session: %s: session was NULL", __func__);
e0508e67 197 return SR_ERR_BUG;
9f45fb3a
UH
198 }
199
0abee507
UH
200 if (!cb) {
201 sr_err("session: %s: cb was NULL", __func__);
202 return SR_ERR_ARG;
203 }
9f45fb3a 204
62c82025 205 session->datafeed_callbacks =
d08490aa 206 g_slist_append(session->datafeed_callbacks, cb);
e0508e67
UH
207
208 return SR_OK;
a1bb33af
UH
209}
210
9f45fb3a
UH
211/**
212 * TODO.
213 */
e0508e67 214static int sr_session_run_poll(void)
544a4582 215{
544a4582
BV
216 int ret, i;
217
544a4582 218 while (session->running) {
0687dfcd 219 ret = g_poll(pollfds, num_sources, source_timeout);
544a4582
BV
220
221 for (i = 0; i < num_sources; i++) {
0687dfcd 222 if (pollfds[i].revents > 0 || (ret == 0
544a4582
BV
223 && source_timeout == sources[i].timeout)) {
224 /*
225 * Invoke the source's callback on an event,
226 * or if the poll timeout out and this source
227 * asked for that timeout.
228 */
0687dfcd 229 if (!sources[i].cb(pollfds[i].fd, pollfds[i].revents,
1f9813eb 230 sources[i].cb_data))
0687dfcd 231 sr_session_source_remove(pollfds[i].fd);
544a4582
BV
232 }
233 }
234 }
e0508e67
UH
235
236 return SR_OK;
544a4582
BV
237}
238
9f45fb3a
UH
239/**
240 * Start a session.
241 *
a1645fcd 242 * There can only be one session at a time.
9f45fb3a
UH
243 *
244 * @return SR_OK upon success, SR_ERR upon errors.
245 */
1a081ca6 246SR_API int sr_session_start(void)
7d658874 247{
bb7ef793 248 struct sr_dev *dev;
7d658874
BV
249 GSList *l;
250 int ret;
251
9f45fb3a
UH
252 if (!session) {
253 sr_err("session: %s: session was NULL; a session must be "
254 "created first, before starting it.", __func__);
0abee507 255 return SR_ERR_BUG;
9f45fb3a
UH
256 }
257
bb7ef793 258 if (!session->devs) {
9f45fb3a 259 /* TODO: Actually the case? */
bb7ef793 260 sr_err("session: %s: session->devs was NULL; a session "
9f45fb3a 261 "cannot be started without devices.", __func__);
0abee507 262 return SR_ERR_BUG;
9f45fb3a
UH
263 }
264
c09f0b57 265 /* TODO: Check driver_index validity? */
9f45fb3a 266
b08024a8 267 sr_info("session: starting");
9f45fb3a 268
bb7ef793
UH
269 for (l = session->devs; l; l = l->next) {
270 dev = l->data;
271 /* TODO: Check for dev != NULL. */
c09f0b57
UH
272 if ((ret = dev->driver->dev_acquisition_start(
273 dev->driver_index, dev)) != SR_OK) {
446a0372 274 sr_err("session: %s: could not start an acquisition "
9f45fb3a 275 "(%d)", __func__, ret);
7d658874 276 break;
9f45fb3a 277 }
7d658874
BV
278 }
279
9f45fb3a
UH
280 /* TODO: What if there are multiple devices? Which return code? */
281
7d658874
BV
282 return ret;
283}
284
9f45fb3a
UH
285/**
286 * Run the session.
287 *
9f45fb3a
UH
288 * TODO: Various error checks etc.
289 *
e0508e67 290 * @return SR_OK upon success, SR_ERR_BUG upon errors.
9f45fb3a 291 */
1a081ca6 292SR_API int sr_session_run(void)
7d658874 293{
9f45fb3a
UH
294 if (!session) {
295 sr_err("session: %s: session was NULL; a session must be "
296 "created first, before running it.", __func__);
e0508e67 297 return SR_ERR_BUG;
9f45fb3a
UH
298 }
299
bb7ef793 300 if (!session->devs) {
9f45fb3a 301 /* TODO: Actually the case? */
bb7ef793 302 sr_err("session: %s: session->devs was NULL; a session "
9f45fb3a 303 "cannot be run without devices.", __func__);
e0508e67 304 return SR_ERR_BUG;
9f45fb3a
UH
305 }
306
b08024a8 307 sr_info("session: running");
7d658874
BV
308 session->running = TRUE;
309
9f45fb3a 310 /* Do we have real sources? */
0687dfcd 311 if (num_sources == 1 && pollfds[0].fd == -1) {
9f45fb3a 312 /* Dummy source, freewheel over it. */
7d658874 313 while (session->running)
1f9813eb 314 sources[0].cb(-1, 0, sources[0].cb_data);
9f45fb3a
UH
315 } else {
316 /* Real sources, use g_poll() main loop. */
8a2efef2 317 sr_session_run_poll();
9f45fb3a
UH
318 }
319
e0508e67 320 return SR_OK;
7d658874
BV
321}
322
9f45fb3a
UH
323/**
324 * Halt the current session.
325 *
44dae539
UH
326 * This requests the current session be stopped as soon as possible, for
327 * example on receiving an SR_DF_END packet.
e0508e67
UH
328 *
329 * @return SR_OK upon success, SR_ERR_BUG if no session exists.
9f45fb3a 330 */
1a081ca6 331SR_API int sr_session_halt(void)
544a4582 332{
9f45fb3a
UH
333 if (!session) {
334 sr_err("session: %s: session was NULL", __func__);
e0508e67 335 return SR_ERR_BUG;
9f45fb3a
UH
336 }
337
b08024a8 338 sr_info("session: halting");
544a4582 339 session->running = FALSE;
9f45fb3a 340
e0508e67 341 return SR_OK;
544a4582
BV
342}
343
9f45fb3a
UH
344/**
345 * Stop the current session.
346 *
a1645fcd 347 * The current session is stopped immediately, with all acquisition sessions
c09f0b57 348 * being stopped and hardware drivers cleaned up.
9f45fb3a 349 *
e0508e67 350 * @return SR_OK upon success, SR_ERR_BUG if no session exists.
9f45fb3a 351 */
1a081ca6 352SR_API int sr_session_stop(void)
a1bb33af 353{
bb7ef793 354 struct sr_dev *dev;
a1bb33af
UH
355 GSList *l;
356
9f45fb3a
UH
357 if (!session) {
358 sr_err("session: %s: session was NULL", __func__);
e0508e67 359 return SR_ERR_BUG;
9f45fb3a
UH
360 }
361
b08024a8 362 sr_info("session: stopping");
544a4582 363 session->running = FALSE;
e0508e67 364
bb7ef793
UH
365 for (l = session->devs; l; l = l->next) {
366 dev = l->data;
367 /* Check for dev != NULL. */
c09f0b57
UH
368 if (dev->driver) {
369 if (dev->driver->dev_acquisition_stop)
370 dev->driver->dev_acquisition_stop(dev->driver_index, dev);
371 if (dev->driver->cleanup)
372 dev->driver->cleanup();
8c76be53 373 }
a1bb33af 374 }
9f45fb3a 375
e0508e67 376 return SR_OK;
a1bb33af
UH
377}
378
9f45fb3a 379/**
a1645fcd 380 * Debug helper.
9f45fb3a 381 *
996b0c72 382 * @param packet The packet to show debugging information for.
9f45fb3a 383 */
18beaeff 384static void datafeed_dump(struct sr_datafeed_packet *packet)
7d2afd6c
BV
385{
386 struct sr_datafeed_logic *logic;
ee7489d2 387 struct sr_datafeed_analog *analog;
7d2afd6c
BV
388
389 switch (packet->type) {
390 case SR_DF_HEADER:
391 sr_dbg("bus: received SR_DF_HEADER");
392 break;
393 case SR_DF_TRIGGER:
01469707 394 sr_dbg("bus: received SR_DF_TRIGGER");
7d2afd6c 395 break;
ee7489d2
BV
396 case SR_DF_META_LOGIC:
397 sr_dbg("bus: received SR_DF_META_LOGIC");
398 break;
7d2afd6c
BV
399 case SR_DF_LOGIC:
400 logic = packet->payload;
e0508e67 401 /* TODO: Check for logic != NULL. */
01469707 402 sr_dbg("bus: received SR_DF_LOGIC %" PRIu64 " bytes", logic->length);
7d2afd6c 403 break;
ee7489d2
BV
404 case SR_DF_META_ANALOG:
405 sr_dbg("bus: received SR_DF_META_LOGIC");
406 break;
407 case SR_DF_ANALOG:
408 analog = packet->payload;
409 /* TODO: Check for analog != NULL. */
410 sr_dbg("bus: received SR_DF_ANALOG %d samples", analog->num_samples);
411 break;
7d2afd6c
BV
412 case SR_DF_END:
413 sr_dbg("bus: received SR_DF_END");
414 break;
6ea7669c
BV
415 case SR_DF_FRAME_BEGIN:
416 sr_dbg("bus: received SR_DF_FRAME_BEGIN");
417 break;
418 case SR_DF_FRAME_END:
419 sr_dbg("bus: received SR_DF_FRAME_END");
420 break;
7d2afd6c 421 default:
18beaeff 422 sr_dbg("bus: received unknown packet type %d", packet->type);
9f45fb3a 423 break;
7d2afd6c 424 }
7d2afd6c
BV
425}
426
9f45fb3a 427/**
a1645fcd
BV
428 * Send a packet to whatever is listening on the datafeed bus.
429 *
430 * Hardware drivers use this to send a data packet to the frontend.
9f45fb3a 431 *
bb7ef793 432 * @param dev TODO.
31ccebc4 433 * @param packet The datafeed packet to send to the session bus.
44dae539 434 *
e0508e67 435 * @return SR_OK upon success, SR_ERR_ARG upon invalid arguments.
9f45fb3a 436 */
31ccebc4
UH
437SR_PRIV int sr_session_send(struct sr_dev *dev,
438 struct sr_datafeed_packet *packet)
a1bb33af
UH
439{
440 GSList *l;
d08490aa 441 sr_datafeed_callback_t cb;
a1bb33af 442
bb7ef793
UH
443 if (!dev) {
444 sr_err("session: %s: dev was NULL", __func__);
e0508e67 445 return SR_ERR_ARG;
9f45fb3a
UH
446 }
447
e0508e67
UH
448 if (!packet) {
449 sr_err("session: %s: packet was NULL", __func__);
450 return SR_ERR_ARG;
9f45fb3a
UH
451 }
452
62c82025 453 for (l = session->datafeed_callbacks; l; l = l->next) {
18beaeff
BV
454 if (sr_log_loglevel_get() >= SR_LOG_DBG)
455 datafeed_dump(packet);
a1bb33af 456 cb = l->data;
9f45fb3a 457 /* TODO: Check for cb != NULL. */
bb7ef793 458 cb(dev, packet);
a1bb33af 459 }
9f45fb3a 460
e0508e67 461 return SR_OK;
a1bb33af
UH
462}
463
aac0ea25
LPC
464static int _sr_session_source_add(GPollFD *pollfd, int timeout,
465 sr_receive_data_callback_t cb, void *cb_data, gintptr poll_object)
544a4582
BV
466{
467 struct source *new_sources, *s;
aac0ea25 468 GPollFD *new_pollfds;
544a4582 469
d08490aa
UH
470 if (!cb) {
471 sr_err("session: %s: cb was NULL", __func__);
e0508e67 472 return SR_ERR_ARG;
9f45fb3a
UH
473 }
474
1f9813eb 475 /* Note: cb_data can be NULL, that's not a bug. */
9f45fb3a 476
0687dfcd
LPC
477 new_pollfds = g_try_realloc(pollfds, sizeof(GPollFD) * (num_sources + 1));
478 if (!new_pollfds) {
479 sr_err("session: %s: new_sources malloc failed", __func__);
480 return SR_ERR_MALLOC;
481 }
482
2bccd322 483 new_sources = g_try_realloc(sources, sizeof(struct source) * (num_sources + 1));
9f45fb3a
UH
484 if (!new_sources) {
485 sr_err("session: %s: new_sources malloc failed", __func__);
e0508e67 486 return SR_ERR_MALLOC;
9f45fb3a 487 }
544a4582 488
aac0ea25 489 new_pollfds[num_sources] = *pollfd;
544a4582 490 s = &new_sources[num_sources++];
544a4582 491 s->timeout = timeout;
d08490aa 492 s->cb = cb;
1f9813eb 493 s->cb_data = cb_data;
aac0ea25 494 s->poll_object = poll_object;
0687dfcd 495 pollfds = new_pollfds;
544a4582
BV
496 sources = new_sources;
497
498 if (timeout != source_timeout && timeout > 0
499 && (source_timeout == -1 || timeout < source_timeout))
500 source_timeout = timeout;
9f45fb3a 501
e0508e67 502 return SR_OK;
544a4582
BV
503}
504
9f45fb3a 505/**
aac0ea25 506 * Add a event source for a file descriptor.
9f45fb3a 507 *
aac0ea25
LPC
508 * @param fd The file descriptor.
509 * @param events Events to check for.
510 * @param timeout Max time to wait before the callback is called, ignored if 0.
511 * @param cb Callback function to add. Must not be NULL.
512 * @param cb_data Data for the callback function. Can be NULL.
9f45fb3a 513 *
aac0ea25
LPC
514 * @return SR_OK upon success, SR_ERR_ARG upon invalid arguments, or
515 * SR_ERR_MALLOC upon memory allocation errors.
516 */
517SR_API int sr_session_source_add(int fd, int events, int timeout,
518 sr_receive_data_callback_t cb, void *cb_data)
519{
520 GPollFD p;
521
aac0ea25
LPC
522 p.fd = fd;
523 p.events = events;
aac0ea25
LPC
524
525 return _sr_session_source_add(&p, timeout, cb, cb_data, (gintptr)fd);
526}
527
528/**
529 * Add a event source for a GPollFD
530 *
531 * TODO: More error checks etc.
532 *
533 * @param pollfd The GPollFD.
534 * @param timeout Max time to wait before the callback is called, ignored if 0.
535 * @param cb Callback function to add. Must not be NULL.
536 * @param cb_data Data for the callback function. Can be NULL.
44dae539 537 *
e0508e67 538 * @return SR_OK upon success, SR_ERR_ARG upon invalid arguments, or
aac0ea25 539 * SR_ERR_MALLOC upon memory allocation errors.
9f45fb3a 540 */
aac0ea25
LPC
541SR_API int sr_session_source_add_pollfd(GPollFD *pollfd, int timeout,
542 sr_receive_data_callback_t cb, void *cb_data)
543{
544 return _sr_session_source_add(pollfd, timeout, cb, cb_data, (gintptr)pollfd);
545}
546
547/**
548 * Add a event source for a GIOChannel
549 *
550 * TODO: More error checks etc.
551 *
552 * @param channel The GIOChannel.
553 * @param events Events to poll on.
554 * @param timeout Max time to wait before the callback is called, ignored if 0.
555 * @param cb Callback function to add. Must not be NULL.
556 * @param cb_data Data for the callback function. Can be NULL.
557 *
558 * @return SR_OK upon success, SR_ERR_ARG upon invalid arguments, or
559 * SR_ERR_MALLOC upon memory allocation errors.
560 */
561SR_API int sr_session_source_add_channel(GIOChannel *channel, int events, int timeout,
562 sr_receive_data_callback_t cb, void *cb_data)
563{
564 GPollFD p;
565
566#ifdef _WIN32
567 g_io_channel_win32_make_pollfd(channel,
568 events, &p);
569#else
570 p.fd = g_io_channel_unix_get_fd(channel);
571 p.events = events;
572#endif
573
574 return _sr_session_source_add(&p, timeout, cb, cb_data, (gintptr)channel);
575}
576
577
578static int _sr_session_source_remove(gintptr poll_object)
544a4582
BV
579{
580 struct source *new_sources;
0687dfcd
LPC
581 GPollFD *new_pollfds;
582 int old;
544a4582 583
e0508e67
UH
584 if (!sources) {
585 sr_err("session: %s: sources was NULL", __func__);
0abee507 586 return SR_ERR_BUG;
e0508e67
UH
587 }
588
2bccd322 589 for (old = 0; old < num_sources; old++) {
aac0ea25 590 if (sources[old].poll_object == poll_object)
2bccd322 591 break;
9f45fb3a
UH
592 }
593
2bccd322
LPC
594 /* fd not found, nothing to do */
595 if (old == num_sources)
596 return SR_OK;
597
598 num_sources -= 1;
599
600 if (old != num_sources) {
0687dfcd
LPC
601 memmove(&pollfds[old], &pollfds[old+1],
602 (num_sources - old) * sizeof(GPollFD));
2bccd322
LPC
603 memmove(&sources[old], &sources[old+1],
604 (num_sources - old) * sizeof(struct source));
9f45fb3a 605 }
544a4582 606
0687dfcd
LPC
607 new_pollfds = g_try_realloc(sources, sizeof(GPollFD) * num_sources);
608 if (!new_pollfds && num_sources > 0) {
609 sr_err("session: %s: new_sources malloc failed", __func__);
610 return SR_ERR_MALLOC;
611 }
612
613 new_sources = g_try_realloc(sources, sizeof(struct source) * num_sources);
2bccd322
LPC
614 if (!new_sources && num_sources > 0) {
615 sr_err("session: %s: new_sources malloc failed", __func__);
616 return SR_ERR_MALLOC;
544a4582 617 }
e0508e67 618
0687dfcd 619 pollfds = new_pollfds;
2bccd322
LPC
620 sources = new_sources;
621
e0508e67 622 return SR_OK;
544a4582 623}
aac0ea25
LPC
624
625/*
626 * Remove the source belonging to the specified file descriptor.
627 *
628 * TODO: More error checks.
629 *
630 * @param fd: The file descriptor for which the source should be removed.
631 *
632 * @return SR_OK upon success, SR_ERR_ARG upon invalid arguments, or
633 * SR_ERR_MALLOC upon memory allocation errors, SR_ERR_BUG upon
634 * internal errors.
635 */
636SR_API int sr_session_source_remove(int fd)
637{
638 return _sr_session_source_remove((gintptr)fd);
639}
640
641/**
642 * Remove the source belonging to the specified poll descriptor.
643 *
644 * TODO: More error checks.
645 *
646 * @param pollfd The poll descriptor for which the source should be removed.
647 *
648 * @return SR_OK upon success, SR_ERR_ARG upon invalid arguments, or
649 * SR_ERR_MALLOC upon memory allocation errors, SR_ERR_BUG upon
650 * internal errors.
651 */
652SR_API int sr_session_source_remove_pollfd(GPollFD *pollfd)
653{
654 return _sr_session_source_remove((gintptr)pollfd);
655}
656
657/*
658 * Remove the source belonging to the specified channel.
659 *
660 * TODO: More error checks.
661 *
662 * @parama channel: The channel for which the source should be removed.
663 *
664 * @return SR_OK upon success, SR_ERR_ARG upon invalid arguments, or
665 * SR_ERR_MALLOC upon memory allocation errors, SR_ERR_BUG upon
666 * internal errors.
667 */
668SR_API int sr_session_source_remove_channel(GIOChannel *channel)
669{
670 return _sr_session_source_remove((gintptr)channel);
671}