Upgrade ofono to 1.2
[profile/ivi/ofono.git] / gatchat / gattty.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 <fcntl.h>
27 #include <unistd.h>
28 #include <string.h>
29 #include <termios.h>
30
31 #include <glib.h>
32
33 #include "gattty.h"
34
35 static gboolean set_baud(const char *baud, struct termios *ti)
36 {
37         speed_t speed;
38
39         if (g_str_equal(baud, "300"))
40                 speed = B300;
41         else if (g_str_equal(baud, "1200"))
42                 speed = B1200;
43         else if (g_str_equal(baud, "2400"))
44                 speed = B2400;
45         else if (g_str_equal(baud, "4800"))
46                 speed = B4800;
47         else if (g_str_equal(baud, "9600"))
48                 speed = B9600;
49         else if (g_str_equal(baud, "19200"))
50                 speed = B19200;
51         else if (g_str_equal(baud, "38400"))
52                 speed = B38400;
53         else if (g_str_equal(baud, "57600"))
54                 speed = B57600;
55         else if (g_str_equal(baud, "115200"))
56                 speed = B115200;
57         else if (g_str_equal(baud, "230400"))
58                 speed = B230400;
59         else if (g_str_equal(baud, "460800"))
60                 speed = B460800;
61         else if (g_str_equal(baud, "500000"))
62                 speed = B500000;
63         else if (g_str_equal(baud, "576000"))
64                 speed = B576000;
65         else if (g_str_equal(baud, "921600"))
66                 speed = B921600;
67         else if (g_str_equal(baud, "1000000"))
68                 speed = B1000000;
69         else if (g_str_equal(baud, "1152000"))
70                 speed = B1152000;
71         else if (g_str_equal(baud, "1500000"))
72                 speed = B1500000;
73         else if (g_str_equal(baud, "2000000"))
74                 speed = B2000000;
75 #ifdef B2500000
76         else if (g_str_equal(baud, "2500000"))
77                 speed = B2500000;
78 #endif
79 #ifdef B3000000
80         else if (g_str_equal(baud, "3000000"))
81                 speed = B3000000;
82 #endif
83 #ifdef B3500000
84         else if (g_str_equal(baud, "3500000"))
85                 speed = B3500000;
86 #endif
87 #ifdef B4000000
88         else if (g_str_equal(baud, "4000000"))
89                 speed = B4000000;
90 #endif
91         else
92                 return FALSE;
93
94         cfsetospeed(ti, speed);
95         cfsetispeed(ti, speed);
96
97         return TRUE;
98 }
99
100 static gboolean set_read(const char *bits, struct termios *ti)
101 {
102         if (g_str_equal(bits, "off"))
103                 ti->c_cflag &= ~(CREAD);
104         else if (g_str_equal(bits, "on"))
105                 ti->c_cflag |= CREAD;
106         else
107                 return FALSE;
108
109         return TRUE;
110 }
111
112 static gboolean set_stop_bits(const char *bits, struct termios *ti)
113 {
114         if (g_str_equal(bits, "1"))
115                 ti->c_cflag &= ~(CSTOPB);
116         else if (g_str_equal(bits, "2"))
117                 ti->c_cflag |= CSTOPB;
118         else
119                 return FALSE;
120
121         return TRUE;
122 }
123
124 static gboolean set_data_bits(const char *bits, struct termios *ti)
125 {
126         if (g_str_equal(bits, "7")) {
127                 ti->c_cflag &= ~(CSIZE);
128                 ti->c_cflag |= CS7;
129         } else if (g_str_equal(bits, "8")) {
130                 ti->c_cflag &= ~(CSIZE);
131                 ti->c_cflag |= CS8;
132         } else
133                 return FALSE;
134
135         return TRUE;
136 }
137
138 static gboolean set_parity(const char *parity, struct termios *ti)
139 {
140         if (g_str_equal(parity, "none"))
141                 ti->c_cflag &= ~(PARENB);
142         else if (g_str_equal(parity, "even")) {
143                 ti->c_cflag |= PARENB;
144                 ti->c_cflag &= ~(PARODD);
145         } else if (g_str_equal(parity, "odd")) {
146                 ti->c_cflag |= PARENB;
147                 ti->c_cflag |= PARODD;
148         } else
149                 return FALSE;
150
151         return TRUE;
152 }
153
154 static gboolean set_xonxoff(const char *xonxoff, struct termios *ti)
155 {
156         if (g_str_equal(xonxoff, "on")) {
157                 ti->c_iflag |= (IXON | IXOFF | IXANY);
158                 ti->c_cc[VSTART] = 17;
159                 ti->c_cc[VSTOP] = 19;
160         } else if (g_str_equal(xonxoff, "off"))
161                 ti->c_iflag &= ~(IXON | IXOFF | IXANY);
162         else
163                 return FALSE;
164
165         return TRUE;
166 }
167
168 static gboolean set_rtscts(const char *rtscts, struct termios *ti)
169 {
170         if (g_str_equal(rtscts, "on"))
171                 ti->c_cflag |= CRTSCTS;
172         else if (g_str_equal(rtscts, "off"))
173                 ti->c_cflag &= ~(CRTSCTS);
174         else
175                 return FALSE;
176
177         return TRUE;
178 }
179
180 static gboolean set_local(const char *local, struct termios *ti)
181 {
182         if (g_str_equal(local, "on"))
183                 ti->c_cflag |= CLOCAL;
184         else if (g_str_equal(local, "off"))
185                 ti->c_cflag &= ~(CLOCAL);
186         else
187                 return FALSE;
188
189         return TRUE;
190 }
191
192 static int open_device(const char *tty, GHashTable *options)
193 {
194         struct termios ti;
195         int fd;
196
197         /* Switch TTY to raw mode */
198         memset(&ti, 0, sizeof(ti));
199         cfmakeraw(&ti);
200
201         if (options) {
202                 GHashTableIter iter;
203                 const char *key;
204                 const char *value;
205
206                 g_hash_table_iter_init (&iter, options);
207                 while (g_hash_table_iter_next(&iter, (void *) &key,
208                                                         (void *) &value)) {
209                         gboolean ok = FALSE;
210
211                         if (g_str_equal(key, "Baud"))
212                                 ok = set_baud(value, &ti);
213                         else if (g_str_equal(key, "StopBits"))
214                                 ok = set_stop_bits(value, &ti);
215                         else if (g_str_equal(key, "DataBits"))
216                                 ok = set_data_bits(value, &ti);
217                         else if (g_str_equal(key, "Parity"))
218                                 ok = set_parity(value, &ti);
219                         else if (g_str_equal(key, "XonXoff"))
220                                 ok = set_xonxoff(value, &ti);
221                         else if (g_str_equal(key, "RtsCts"))
222                                 ok = set_rtscts(value, &ti);
223                         else if (g_str_equal(key, "Local"))
224                                 ok = set_local(value, &ti);
225                         else if (g_str_equal(key, "Read"))
226                                 ok = set_read(value, &ti);
227
228                         if (ok == FALSE)
229                                 return -1;
230                 }
231         }
232
233         fd = open(tty, O_RDWR | O_NOCTTY | O_NONBLOCK);
234         if (fd < 0)
235                 return -1;
236
237         tcflush(fd, TCIOFLUSH);
238         tcsetattr(fd, TCSANOW, &ti);
239
240         return fd;
241 }
242
243 GIOChannel *g_at_tty_open(const char *tty, GHashTable *options)
244 {
245         GIOChannel *channel;
246         int fd;
247
248         fd = open_device(tty, options);
249         if (fd < 0)
250                 return NULL;
251
252         channel = g_io_channel_unix_new(fd);
253         if (channel == NULL) {
254                 close(fd);
255                 return NULL;
256         }
257
258         g_io_channel_set_close_on_unref(channel, TRUE);
259
260         return channel;
261 }
262
263 GIOChannel *g_at_tty_open_qcdm(const char *tty)
264 {
265         GIOChannel *channel;
266         struct termios ti;
267         int fd;
268
269         fd = open(tty, O_RDWR | O_NOCTTY | O_NONBLOCK);
270         if (fd < 0)
271                 return NULL;
272
273         /* Switch TTY to raw mode */
274         memset(&ti, 0, sizeof(ti));
275         cfmakeraw(&ti);
276
277         /* No parity, 1 stop bit */
278         ti.c_cflag &= ~(CSIZE | CSTOPB | PARENB);
279         ti.c_cflag |= (B115200 | CS8);
280
281         if (tcsetattr(fd, TCSANOW, &ti) < 0) {
282                 close(fd);
283                 return NULL;
284         }
285
286         channel = g_io_channel_unix_new(fd);
287         if (channel == NULL) {
288                 close(fd);
289                 return NULL;
290         }
291
292         g_io_channel_set_close_on_unref(channel, TRUE);
293
294         return channel;
295 }