Upgrade ofono to 1.2
[profile/ivi/ofono.git] / gatchat / gatutil.c
1 /*
2  *
3  *  AT chat library with GLib integration
4  *
5  *  Copyright (C) 2008-2011  Intel Corporation. All rights reserved.
6  *
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.
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, write to the Free Software
18  *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
19  *
20  */
21
22 #ifdef HAVE_CONFIG_H
23 #include <config.h>
24 #endif
25
26 #include <stdio.h>
27 #include <ctype.h>
28 #include <string.h>
29
30 #include <glib.h>
31
32 #include "gatutil.h"
33
34 void g_at_util_debug_chat(gboolean in, const char *str, gsize len,
35                                 GAtDebugFunc debugf, gpointer user_data)
36 {
37         char type = in ? '<' : '>';
38         gsize escaped = 2; /* Enough for '<', ' ' */
39         char *escaped_str;
40         const char *esc = "<ESC>";
41         gsize esc_size = strlen(esc);
42         const char *ctrlz = "<CtrlZ>";
43         gsize ctrlz_size = strlen(ctrlz);
44         gsize i;
45
46         if (debugf == NULL || !len)
47                 return;
48
49         for (i = 0; i < len; i++) {
50                 char c = str[i];
51
52                 if (g_ascii_isprint(c))
53                         escaped += 1;
54                 else if (c == '\r' || c == '\t' || c == '\n')
55                         escaped += 2;
56                 else if (c == 26)
57                         escaped += ctrlz_size;
58                 else if (c == 25)
59                         escaped += esc_size;
60                 else
61                         escaped += 4;
62         }
63
64         escaped_str = g_try_malloc(escaped + 1);
65         if (escaped_str == NULL)
66                 return;
67
68         escaped_str[0] = type;
69         escaped_str[1] = ' ';
70         escaped_str[2] = '\0';
71         escaped_str[escaped] = '\0';
72
73         for (escaped = 2, i = 0; i < len; i++) {
74                 unsigned char c = str[i];
75
76                 switch (c) {
77                 case '\r':
78                         escaped_str[escaped++] = '\\';
79                         escaped_str[escaped++] = 'r';
80                         break;
81                 case '\t':
82                         escaped_str[escaped++] = '\\';
83                         escaped_str[escaped++] = 't';
84                         break;
85                 case '\n':
86                         escaped_str[escaped++] = '\\';
87                         escaped_str[escaped++] = 'n';
88                         break;
89                 case 26:
90                         strncpy(&escaped_str[escaped], ctrlz, ctrlz_size);
91                         escaped += ctrlz_size;
92                         break;
93                 case 25:
94                         strncpy(&escaped_str[escaped], esc, esc_size);
95                         escaped += esc_size;
96                         break;
97                 default:
98                         if (g_ascii_isprint(c))
99                                 escaped_str[escaped++] = c;
100                         else {
101                                 escaped_str[escaped++] = '\\';
102                                 escaped_str[escaped++] = '0' + ((c >> 6) & 07);
103                                 escaped_str[escaped++] = '0' + ((c >> 3) & 07);
104                                 escaped_str[escaped++] = '0' + (c & 07);
105                         }
106                 }
107         }
108
109         debugf(escaped_str, user_data);
110         g_free(escaped_str);
111 }
112
113 void g_at_util_debug_dump(gboolean in, const unsigned char *buf, gsize len,
114                                 GAtDebugFunc debugf, gpointer user_data)
115 {
116         char type = in ? '<' : '>';
117         GString *str;
118         gsize i;
119
120         if (debugf == NULL || !len)
121                 return;
122
123         str = g_string_sized_new(1 + (len * 2));
124         if (str == NULL)
125                 return;
126
127         g_string_append_c(str, type);
128
129         for (i = 0; i < len; i++)
130                 g_string_append_printf(str, " %02x", buf[i]);
131
132         debugf(str->str, user_data);
133         g_string_free(str, TRUE);
134 }
135
136 void g_at_util_debug_hexdump(gboolean in, const unsigned char *buf, gsize len,
137                                 GAtDebugFunc debugf, gpointer user_data)
138 {
139         static const char hexdigits[] = "0123456789abcdef";
140         char str[68];
141         gsize i;
142
143         if (debugf == NULL || !len)
144                 return;
145
146         str[0] = in ? '<' : '>';
147
148         for (i = 0; i < len; i++) {
149                 str[((i % 16) * 3) + 1] = ' ';
150                 str[((i % 16) * 3) + 2] = hexdigits[buf[i] >> 4];
151                 str[((i % 16) * 3) + 3] = hexdigits[buf[i] & 0xf];
152                 str[(i % 16) + 51] = g_ascii_isprint(buf[i]) ? buf[i] : '.';
153
154                 if ((i + 1) % 16 == 0) {
155                         str[49] = ' ';
156                         str[50] = ' ';
157                         str[67] = '\0';
158                         debugf(str, user_data);
159                         str[0] = ' ';
160                 }
161         }
162
163         if (i % 16 > 0) {
164                 gsize j;
165                 for (j = (i % 16); j < 16; j++) {
166                         str[(j * 3) + 1] = ' ';
167                         str[(j * 3) + 2] = ' ';
168                         str[(j * 3) + 3] = ' ';
169                         str[j + 51] = ' ';
170                 }
171                 str[49] = ' ';
172                 str[50] = ' ';
173                 str[67] = '\0';
174                 debugf(str, user_data);
175         }
176 }
177
178 gboolean g_at_util_setup_io(GIOChannel *io, GIOFlags flags)
179 {
180         GIOFlags io_flags;
181
182         if (g_io_channel_set_encoding(io, NULL, NULL) != G_IO_STATUS_NORMAL)
183                 return FALSE;
184
185         g_io_channel_set_buffered(io, FALSE);
186
187         if (flags & G_IO_FLAG_SET_MASK) {
188                 io_flags = g_io_channel_get_flags(io);
189
190                 io_flags |= (flags & G_IO_FLAG_SET_MASK);
191
192                 if (g_io_channel_set_flags(io, io_flags, NULL) !=
193                                                         G_IO_STATUS_NORMAL)
194                         return FALSE;
195         }
196
197         g_io_channel_set_close_on_unref(io, TRUE);
198
199         return TRUE;
200 }