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
26 #include <arpa/inet.h>
28 #include <sys/types.h>
35 #include "crc-ccitt.h"
36 #include "ringbuffer.h"
41 #define BUFFER_SIZE (2 * 2048)
42 #define MAX_BUFFERS 64 /* Maximum number of in-flight write buffers */
43 #define HDLC_OVERHEAD 256 /* Rough estimate of HDLC protocol overhead */
45 #define HDLC_FLAG 0x7e /* Flag sequence */
46 #define HDLC_ESCAPE 0x7d /* Asynchronous control escape */
47 #define HDLC_TRANS 0x20 /* Asynchronous transparency modifier */
49 #define HDLC_INITFCS 0xffff /* Initial FCS value */
50 #define HDLC_GOODFCS 0xf0b8 /* Good final FCS value */
52 #define HDLC_FCS(fcs, c) crc_ccitt_byte(fcs, c)
54 #define GUARD_TIMEOUT 1000 /* Pause time before and after '+++' sequence */
59 GQueue *write_queue; /* Write buffer queue */
60 unsigned char *decode_buffer;
63 gboolean decode_escape;
66 GAtReceiveFunc receive_func;
67 gpointer receive_data;
71 gboolean in_read_handler;
74 gboolean start_frame_marker;
75 gboolean no_carrier_detect;
76 GAtSuspendFunc suspend_func;
77 gpointer suspend_data;
83 static inline void hdlc_record(GAtHDLC *hdlc, gboolean in,
84 guint8 *data, guint16 length)
86 guint16 len = htons(length);
92 g_at_util_debug_hexdump(in, data, length,
93 hdlc->debugf, hdlc->debug_data);
95 if (hdlc->record_fd < 0)
101 gettimeofday(&now, NULL);
102 ts = htonl(now.tv_sec & 0xffffffff);
106 err = write(hdlc->record_fd, &id, 1);
110 err = write(hdlc->record_fd, &ts, 4);
114 id = in ? 0x02 : 0x01;
116 err = write(hdlc->record_fd, &id, 1);
120 err = write(hdlc->record_fd, &len, 2);
124 err = write(hdlc->record_fd, data, length);
129 void g_at_hdlc_set_recording(GAtHDLC *hdlc, const char *filename)
134 if (hdlc->record_fd > fileno(stderr)) {
135 close(hdlc->record_fd);
136 hdlc->record_fd = -1;
139 if (filename == NULL)
142 hdlc->record_fd = open(filename, O_WRONLY | O_CREAT | O_APPEND,
143 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
146 void g_at_hdlc_set_recv_accm(GAtHDLC *hdlc, guint32 accm)
151 hdlc->recv_accm = accm;
154 guint32 g_at_hdlc_get_recv_accm(GAtHDLC *hdlc)
159 return hdlc->recv_accm;
162 void g_at_hdlc_set_suspend_function(GAtHDLC *hdlc, GAtSuspendFunc func,
170 g_timer_destroy(hdlc->timer);
174 if (hdlc->suspend_source > 0) {
175 g_source_remove(hdlc->suspend_source);
176 hdlc->suspend_source = 0;
179 hdlc->timer = g_timer_new();
181 hdlc->suspend_func = func;
182 hdlc->suspend_data = user_data;
185 static gboolean hdlc_suspend(gpointer user_data)
187 GAtHDLC *hdlc = user_data;
189 g_at_io_drain_ring_buffer(hdlc->io, 3);
191 g_at_io_set_write_handler(hdlc->io, NULL, NULL);
192 g_at_io_set_read_handler(hdlc->io, NULL, NULL);
194 if (hdlc->suspend_func)
195 hdlc->suspend_func(hdlc->suspend_data);
197 hdlc->suspend_source = 0;
202 static gboolean check_escape(GAtHDLC *hdlc, struct ring_buffer *rbuf)
204 unsigned int len = ring_buffer_len(rbuf);
205 unsigned int wrap = ring_buffer_len_no_wrap(rbuf);
206 unsigned char *buf = ring_buffer_read_ptr(rbuf, 0);
207 unsigned int pos = 0;
208 unsigned int elapsed = g_timer_elapsed(hdlc->timer, NULL) * 1000;
209 unsigned int num_plus = 0;
210 gboolean guard_timeout = FALSE;
212 if (elapsed >= GUARD_TIMEOUT)
213 guard_timeout = TRUE;
215 while (pos < len && pos < 3) {
224 buf = ring_buffer_read_ptr(rbuf, pos);
230 /* We got some escape chars, but no guard timeout first */
231 if (guard_timeout == FALSE && hdlc->num_plus == 0)
235 hdlc->num_plus = num_plus;
240 hdlc->suspend_source = g_timeout_add(GUARD_TIMEOUT, hdlc_suspend, hdlc);
245 static void new_bytes(struct ring_buffer *rbuf, gpointer user_data)
247 GAtHDLC *hdlc = user_data;
248 unsigned int len = ring_buffer_len(rbuf);
249 unsigned int wrap = ring_buffer_len_no_wrap(rbuf);
250 unsigned char *buf = ring_buffer_read_ptr(rbuf, 0);
251 unsigned int pos = 0;
254 * We delete the the paused_timeout_cb or hdlc_suspend as soons as
257 if (hdlc->suspend_source > 0) {
258 g_source_remove(hdlc->suspend_source);
259 hdlc->suspend_source = 0;
260 g_timer_start(hdlc->timer);
261 } else if (hdlc->timer) {
262 gboolean escaping = check_escape(hdlc, rbuf);
264 g_timer_start(hdlc->timer);
270 hdlc_record(hdlc, TRUE, buf, wrap);
272 hdlc->in_read_handler = TRUE;
276 * We try to detect NO CARRIER conditions here. We
277 * (ab) use the fact that a HDLC_FLAG must be followed
278 * by the Address or Protocol fields, depending on whether
281 if (hdlc->no_carrier_detect &&
282 hdlc->decode_offset == 0 && *buf == '\r')
285 if (hdlc->decode_escape == TRUE) {
286 unsigned char val = *buf ^ HDLC_TRANS;
288 hdlc->decode_buffer[hdlc->decode_offset++] = val;
289 hdlc->decode_fcs = HDLC_FCS(hdlc->decode_fcs, val);
291 hdlc->decode_escape = FALSE;
292 } else if (*buf == HDLC_ESCAPE) {
293 hdlc->decode_escape = TRUE;
294 } else if (*buf == HDLC_FLAG) {
295 if (hdlc->receive_func && hdlc->decode_offset > 2 &&
296 hdlc->decode_fcs == HDLC_GOODFCS) {
297 hdlc->receive_func(hdlc->decode_buffer,
298 hdlc->decode_offset - 2,
305 hdlc->decode_fcs = HDLC_INITFCS;
306 hdlc->decode_offset = 0;
307 } else if (*buf >= 0x20 ||
308 (hdlc->recv_accm & (1 << *buf)) == 0) {
309 hdlc->decode_buffer[hdlc->decode_offset++] = *buf;
310 hdlc->decode_fcs = HDLC_FCS(hdlc->decode_fcs, *buf);
317 buf = ring_buffer_read_ptr(rbuf, pos);
318 hdlc_record(hdlc, TRUE, buf, len - wrap);
323 ring_buffer_drain(rbuf, pos);
325 hdlc->in_read_handler = FALSE;
331 GAtHDLC *g_at_hdlc_new_from_io(GAtIO *io)
334 struct ring_buffer* write_buffer;
339 hdlc = g_try_new0(GAtHDLC, 1);
344 hdlc->decode_fcs = HDLC_INITFCS;
345 hdlc->decode_offset = 0;
346 hdlc->decode_escape = FALSE;
348 hdlc->xmit_accm[0] = ~0U;
349 hdlc->xmit_accm[3] = 0x60000000; /* 0x7d, 0x7e */
350 hdlc->recv_accm = ~0U;
352 write_buffer = ring_buffer_new(BUFFER_SIZE);
356 hdlc->write_queue = g_queue_new();
357 if (!hdlc->write_queue)
360 g_queue_push_tail(hdlc->write_queue, write_buffer);
362 hdlc->decode_buffer = g_try_malloc(BUFFER_SIZE);
363 if (!hdlc->decode_buffer)
366 hdlc->record_fd = -1;
368 hdlc->io = g_at_io_ref(io);
369 g_at_io_set_read_handler(hdlc->io, new_bytes, hdlc);
374 if (hdlc->write_queue)
375 g_queue_free(hdlc->write_queue);
378 ring_buffer_free(write_buffer);
380 g_free(hdlc->decode_buffer);
387 GAtHDLC *g_at_hdlc_new(GIOChannel *channel)
392 io = g_at_io_new(channel);
396 hdlc = g_at_hdlc_new_from_io(io);
402 GAtHDLC *g_at_hdlc_ref(GAtHDLC *hdlc)
407 g_atomic_int_inc(&hdlc->ref_count);
412 void g_at_hdlc_unref(GAtHDLC *hdlc)
414 struct ring_buffer *write_buffer;
419 if (g_atomic_int_dec_and_test(&hdlc->ref_count) == FALSE)
422 if (hdlc->record_fd > fileno(stderr)) {
423 close(hdlc->record_fd);
424 hdlc->record_fd = -1;
427 g_at_io_set_write_handler(hdlc->io, NULL, NULL);
428 g_at_io_set_read_handler(hdlc->io, NULL, NULL);
430 if (hdlc->suspend_source > 0)
431 g_source_remove(hdlc->suspend_source);
433 g_at_io_unref(hdlc->io);
436 while ((write_buffer = g_queue_pop_head(hdlc->write_queue)))
437 ring_buffer_free(write_buffer);
439 g_queue_free(hdlc->write_queue);
441 g_free(hdlc->decode_buffer);
443 g_timer_destroy(hdlc->timer);
445 if (hdlc->in_read_handler)
446 hdlc->destroyed = TRUE;
451 void g_at_hdlc_set_debug(GAtHDLC *hdlc, GAtDebugFunc func, gpointer user_data)
457 hdlc->debug_data = user_data;
460 void g_at_hdlc_set_receive(GAtHDLC *hdlc, GAtReceiveFunc func,
466 hdlc->receive_func = func;
467 hdlc->receive_data = user_data;
470 static gboolean can_write_data(gpointer data)
472 GAtHDLC *hdlc = data;
476 struct ring_buffer* write_buffer;
478 /* Write data out from the head of the queue */
479 write_buffer = g_queue_peek_head(hdlc->write_queue);
481 len = ring_buffer_len_no_wrap(write_buffer);
482 buf = ring_buffer_read_ptr(write_buffer, 0);
484 bytes_written = g_at_io_write(hdlc->io, (gchar *) buf, len);
485 hdlc_record(hdlc, FALSE, buf, bytes_written);
486 ring_buffer_drain(write_buffer, bytes_written);
488 if (ring_buffer_len(write_buffer) > 0)
491 /* All data in current buffer is written, free it
492 * unless it's the last buffer in the queue.
494 if ((ring_buffer_len(write_buffer) == 0) &&
495 (g_queue_get_length(hdlc->write_queue) > 1)) {
496 write_buffer = g_queue_pop_head(hdlc->write_queue);
497 ring_buffer_free(write_buffer);
498 write_buffer = g_queue_peek_head(hdlc->write_queue);
501 if (ring_buffer_len(write_buffer) > 0)
507 void g_at_hdlc_set_xmit_accm(GAtHDLC *hdlc, guint32 accm)
512 hdlc->xmit_accm[0] = accm;
515 guint32 g_at_hdlc_get_xmit_accm(GAtHDLC *hdlc)
520 return hdlc->xmit_accm[0];
523 GAtIO *g_at_hdlc_get_io(GAtHDLC *hdlc)
531 #define NEED_ESCAPE(xmit_accm, c) xmit_accm[c >> 5] & (1 << (c & 0x1f))
533 gboolean g_at_hdlc_send(GAtHDLC *hdlc, const unsigned char *data, gsize size)
535 struct ring_buffer* write_buffer = g_queue_peek_tail(hdlc->write_queue);
537 unsigned int avail = ring_buffer_avail(write_buffer);
538 unsigned int wrap = ring_buffer_avail_no_wrap(write_buffer);
540 unsigned char tail[2];
542 guint16 fcs = HDLC_INITFCS;
543 gboolean escape = FALSE;
546 if (avail < size + HDLC_OVERHEAD) {
547 if (g_queue_get_length(hdlc->write_queue) > MAX_BUFFERS)
548 return FALSE; /* Too many pending buffers */
550 write_buffer = ring_buffer_new(BUFFER_SIZE);
551 if (write_buffer == NULL)
554 g_queue_push_tail(hdlc->write_queue, write_buffer);
556 avail = ring_buffer_avail(write_buffer);
557 wrap = ring_buffer_avail_no_wrap(write_buffer);
561 buf = ring_buffer_write_ptr(write_buffer, 0);
563 if (hdlc->start_frame_marker == TRUE) {
564 /* Protocol requires 0x7e as start marker */
572 buf = ring_buffer_write_ptr(write_buffer, pos);
573 } else if (hdlc->wakeup_sent == FALSE) {
574 /* Write an initial 0x7e as wakeup character */
578 hdlc->wakeup_sent = TRUE;
581 while (pos < avail && i < size) {
582 if (escape == TRUE) {
583 fcs = HDLC_FCS(fcs, data[i]);
584 *buf = data[i++] ^ HDLC_TRANS;
586 } else if (NEED_ESCAPE(hdlc->xmit_accm, data[i])) {
590 fcs = HDLC_FCS(fcs, data[i]);
598 buf = ring_buffer_write_ptr(write_buffer, pos);
605 tail[0] = fcs & 0xff;
610 while (pos < avail && i < sizeof(tail)) {
611 if (escape == TRUE) {
612 *buf = tail[i++] ^ HDLC_TRANS;
614 } else if (NEED_ESCAPE(hdlc->xmit_accm, tail[i])) {
625 buf = ring_buffer_write_ptr(write_buffer, pos);
628 if (i < sizeof(tail))
634 /* Add 0x7e as end marker */
638 ring_buffer_write_advance(write_buffer, pos);
640 g_at_io_set_write_handler(hdlc->io, can_write_data, hdlc);
645 void g_at_hdlc_set_start_frame_marker(GAtHDLC *hdlc, gboolean marker)
650 hdlc->start_frame_marker = marker;
653 void g_at_hdlc_set_no_carrier_detect(GAtHDLC *hdlc, gboolean detect)
658 hdlc->no_carrier_detect = detect;
661 void g_at_hdlc_suspend(GAtHDLC *hdlc)
666 g_at_io_set_write_handler(hdlc->io, NULL, NULL);
667 g_at_io_set_read_handler(hdlc->io, NULL, NULL);
670 void g_at_hdlc_resume(GAtHDLC *hdlc)
675 g_at_io_set_read_handler(hdlc->io, new_bytes, hdlc);
677 if (g_queue_get_length(hdlc->write_queue) > 0)
678 g_at_io_set_write_handler(hdlc->io, can_write_data, hdlc);