3 * AT chat library with GLib integration
5 * Copyright (C) 2008-2011 Intel Corporation. All rights reserved.
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License version 2 as
9 * published by the Free Software Foundation.
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.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
35 #include "ringbuffer.h"
40 gint ref_count; /* Ref count */
41 guint read_watch; /* GSource read id, 0 if no */
42 guint write_watch; /* GSource write id, 0 if no */
43 GIOChannel *channel; /* comms channel */
44 GAtDisconnectFunc user_disconnect; /* user disconnect func */
45 gpointer user_disconnect_data; /* user disconnect data */
46 struct ring_buffer *buf; /* Current read buffer */
47 guint max_read_attempts; /* max reads / select */
48 GAtIOReadFunc read_handler; /* Read callback */
49 gpointer read_data; /* Read callback userdata */
50 gboolean use_write_watch; /* Use write select */
51 GAtIOWriteFunc write_handler; /* Write callback */
52 gpointer write_data; /* Write callback userdata */
53 GAtDebugFunc debugf; /* debugging output function */
54 gpointer debug_data; /* Data to pass to debug func */
55 GAtDisconnectFunc write_done_func; /* tx empty notifier */
56 gpointer write_done_data; /* tx empty data */
57 gboolean destroyed; /* Re-entrancy guard */
60 static void read_watcher_destroy_notify(gpointer user_data)
62 GAtIO *io = user_data;
64 ring_buffer_free(io->buf);
68 io->debug_data = NULL;
71 io->read_handler = NULL;
78 else if (io->user_disconnect)
79 io->user_disconnect(io->user_disconnect_data);
82 static gboolean received_data(GIOChannel *channel, GIOCondition cond,
96 /* Regardless of condition, try to read all the data available */
98 toread = ring_buffer_avail_no_wrap(io->buf);
104 buf = ring_buffer_write_ptr(io->buf, 0);
106 status = g_io_channel_read_chars(channel, (char *) buf,
107 toread, &rbytes, NULL);
108 g_at_util_debug_chat(TRUE, (char *)buf, rbytes,
109 io->debugf, io->debug_data);
113 total_read += rbytes;
116 ring_buffer_write_advance(io->buf, rbytes);
118 } while (status == G_IO_STATUS_NORMAL && rbytes > 0 &&
119 read_count < io->max_read_attempts);
121 if (total_read > 0 && io->read_handler)
122 io->read_handler(io->buf, io->read_data);
124 if (cond & (G_IO_HUP | G_IO_ERR))
127 if (read_count > 0 && rbytes == 0 && status != G_IO_STATUS_AGAIN)
130 /* We're overflowing the buffer, shutdown the socket */
131 if (ring_buffer_avail(io->buf) == 0)
137 gsize g_at_io_write(GAtIO *io, const gchar *data, gsize count)
142 status = g_io_channel_write_chars(io->channel, data,
143 count, &bytes_written, NULL);
145 if (status != G_IO_STATUS_NORMAL) {
146 g_source_remove(io->read_watch);
150 g_at_util_debug_chat(FALSE, data, bytes_written,
151 io->debugf, io->debug_data);
153 return bytes_written;
156 static void write_watcher_destroy_notify(gpointer user_data)
158 GAtIO *io = user_data;
161 io->write_handler = NULL;
162 io->write_data = NULL;
164 if (io->write_done_func) {
165 io->write_done_func(io->write_done_data);
166 io->write_done_func = NULL;
167 io->write_done_data = NULL;
171 static gboolean can_write_data(GIOChannel *channel, GIOCondition cond,
176 if (cond & (G_IO_NVAL | G_IO_HUP | G_IO_ERR))
179 if (io->write_handler == NULL)
182 return io->write_handler(io->write_data);
185 static GAtIO *create_io(GIOChannel *channel, GIOFlags flags)
192 io = g_try_new0(GAtIO, 1);
199 if (flags & G_IO_FLAG_NONBLOCK) {
200 io->max_read_attempts = 3;
201 io->use_write_watch = TRUE;
203 io->max_read_attempts = 1;
204 io->use_write_watch = FALSE;
207 io->buf = ring_buffer_new(8192);
212 if (!g_at_util_setup_io(channel, flags))
215 io->channel = channel;
216 io->read_watch = g_io_add_watch_full(channel, G_PRIORITY_DEFAULT,
217 G_IO_IN | G_IO_HUP | G_IO_ERR | G_IO_NVAL,
219 read_watcher_destroy_notify);
225 ring_buffer_free(io->buf);
232 GAtIO *g_at_io_new(GIOChannel *channel)
234 return create_io(channel, G_IO_FLAG_NONBLOCK);
237 GAtIO *g_at_io_new_blocking(GIOChannel *channel)
239 return create_io(channel, 0);
242 GIOChannel *g_at_io_get_channel(GAtIO *io)
250 gboolean g_at_io_set_read_handler(GAtIO *io, GAtIOReadFunc read_handler,
256 io->read_handler = read_handler;
257 io->read_data = user_data;
259 if (read_handler && ring_buffer_len(io->buf) > 0)
260 read_handler(io->buf, user_data);
265 static gboolean call_blocking_read(gpointer user_data)
267 GAtIO *io = user_data;
269 while (can_write_data(io->channel, G_IO_OUT, io) == TRUE);
270 write_watcher_destroy_notify(io);
275 gboolean g_at_io_set_write_handler(GAtIO *io, GAtIOWriteFunc write_handler,
281 if (io->write_watch > 0) {
282 if (write_handler == NULL) {
283 g_source_remove(io->write_watch);
290 if (write_handler == NULL)
293 io->write_handler = write_handler;
294 io->write_data = user_data;
296 if (io->use_write_watch == TRUE)
297 io->write_watch = g_io_add_watch_full(io->channel,
299 G_IO_OUT | G_IO_HUP | G_IO_ERR | G_IO_NVAL,
301 write_watcher_destroy_notify);
303 io->write_watch = g_idle_add(call_blocking_read, io);
308 GAtIO *g_at_io_ref(GAtIO *io)
313 g_atomic_int_inc(&io->ref_count);
318 static gboolean io_shutdown(GAtIO *io)
320 /* Don't trigger user disconnect on shutdown */
321 io->user_disconnect = NULL;
322 io->user_disconnect_data = NULL;
324 if (io->read_watch > 0)
325 g_source_remove(io->read_watch);
327 if (io->write_watch > 0)
328 g_source_remove(io->write_watch);
333 void g_at_io_unref(GAtIO *io)
340 is_zero = g_atomic_int_dec_and_test(&io->ref_count);
342 if (is_zero == FALSE)
347 /* glib delays the destruction of the watcher until it exits, this
348 * means we can't free the data just yet, even though we've been
349 * destroyed already. We have to wait until the read_watcher
350 * destroy function gets called
352 if (io->read_watch > 0)
353 io->destroyed = TRUE;
358 gboolean g_at_io_set_disconnect_function(GAtIO *io,
359 GAtDisconnectFunc disconnect, gpointer user_data)
364 io->user_disconnect = disconnect;
365 io->user_disconnect_data = user_data;
370 gboolean g_at_io_set_debug(GAtIO *io, GAtDebugFunc func, gpointer user_data)
376 io->debug_data = user_data;
381 void g_at_io_set_write_done(GAtIO *io, GAtDisconnectFunc func,
387 io->write_done_func = func;
388 io->write_done_data = user_data;
391 void g_at_io_drain_ring_buffer(GAtIO *io, guint len)
393 ring_buffer_drain(io->buf, len);