~indicator-network-developers/ofono/trunk.packaging

« back to all changes in this revision

Viewing changes to src/emulator.c

  • Committer: Kalle Valo
  • Date: 2011-02-21 07:46:07 UTC
  • mfrom: (2738.1.2125)
  • Revision ID: kalle.valo@canonical.com-20110221074607-u4rocuj2p75kpht9
Merge trunk.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 *
 
3
 *  oFono - Open Source Telephony
 
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
 
 
28
#include <glib.h>
 
29
 
 
30
#include "ofono.h"
 
31
#include "gatserver.h"
 
32
#include "gatppp.h"
 
33
 
 
34
#define DUN_SERVER_ADDRESS     "192.168.1.1"
 
35
#define DUN_PEER_ADDRESS       "192.168.1.2"
 
36
#define DUN_DNS_SERVER_1       "10.10.10.10"
 
37
#define DUN_DNS_SERVER_2       "10.10.10.11"
 
38
 
 
39
struct ofono_emulator {
 
40
        struct ofono_atom *atom;
 
41
        enum ofono_emulator_type type;
 
42
        GAtServer *server;
 
43
        GAtPPP *ppp;
 
44
        guint source;
 
45
};
 
46
 
 
47
static void emulator_debug(const char *str, void *data)
 
48
{
 
49
        ofono_info("%s: %s\n", (char *)data, str);
 
50
}
 
51
 
 
52
static void emulator_disconnect(gpointer user_data)
 
53
{
 
54
        struct ofono_emulator *em = user_data;
 
55
 
 
56
        DBG("%p", em);
 
57
 
 
58
        ofono_emulator_remove(em);
 
59
}
 
60
 
 
61
static void ppp_connect(const char *iface, const char *local,
 
62
                       const char *remote,
 
63
                       const char *dns1, const char *dns2,
 
64
                       gpointer user_data)
 
65
{
 
66
       DBG("Network Device: %s\n", iface);
 
67
       DBG("IP Address: %s\n", local);
 
68
       DBG("Remote IP Address: %s\n", remote);
 
69
       DBG("Primary DNS Server: %s\n", dns1);
 
70
       DBG("Secondary DNS Server: %s\n", dns2);
 
71
}
 
72
 
 
73
static void ppp_disconnect(GAtPPPDisconnectReason reason, gpointer user_data)
 
74
{
 
75
       struct ofono_emulator *em = user_data;
 
76
 
 
77
       DBG("");
 
78
 
 
79
       g_at_ppp_unref(em->ppp);
 
80
       em->ppp = NULL;
 
81
 
 
82
       if (em->server == NULL)
 
83
               return;
 
84
 
 
85
       g_at_server_resume(em->server);
 
86
}
 
87
 
 
88
static gboolean setup_ppp(gpointer user_data)
 
89
{
 
90
       struct ofono_emulator *em = user_data;
 
91
       GAtIO *io;
 
92
 
 
93
       DBG("");
 
94
 
 
95
       em->source = 0;
 
96
 
 
97
       io = g_at_server_get_io(em->server);
 
98
 
 
99
       g_at_server_suspend(em->server);
 
100
 
 
101
       em->ppp = g_at_ppp_server_new_from_io(io, DUN_SERVER_ADDRESS);
 
102
       if (em->ppp == NULL) {
 
103
               g_at_server_resume(em->server);
 
104
               return FALSE;
 
105
       }
 
106
 
 
107
       g_at_ppp_set_server_info(em->ppp, DUN_PEER_ADDRESS,
 
108
                                       DUN_DNS_SERVER_1, DUN_DNS_SERVER_2);
 
109
 
 
110
       g_at_ppp_set_credentials(em->ppp, "", "");
 
111
       g_at_ppp_set_debug(em->ppp, emulator_debug, "PPP");
 
112
 
 
113
       g_at_ppp_set_connect_function(em->ppp, ppp_connect, em);
 
114
       g_at_ppp_set_disconnect_function(em->ppp, ppp_disconnect, em);
 
115
 
 
116
       return FALSE;
 
117
}
 
118
 
 
119
static gboolean dial_call(struct ofono_emulator *em, const char *dial_str)
 
120
{
 
121
       char c = *dial_str;
 
122
 
 
123
       DBG("dial call %s", dial_str);
 
124
 
 
125
       if (c == '*' || c == '#' || c == 'T' || c == 't') {
 
126
               g_at_server_send_intermediate(em->server, "CONNECT");
 
127
               em->source = g_idle_add(setup_ppp, em);
 
128
       }
 
129
 
 
130
       return TRUE;
 
131
}
 
132
 
 
133
static void dial_cb(GAtServer *server, GAtServerRequestType type,
 
134
                                GAtResult *result, gpointer user_data)
 
135
{
 
136
       struct ofono_emulator *em = user_data;
 
137
       GAtResultIter iter;
 
138
       const char *dial_str;
 
139
 
 
140
       DBG("");
 
141
 
 
142
       if (type != G_AT_SERVER_REQUEST_TYPE_SET)
 
143
               goto error;
 
144
 
 
145
       g_at_result_iter_init(&iter, result);
 
146
 
 
147
       if (!g_at_result_iter_next(&iter, ""))
 
148
               goto error;
 
149
 
 
150
       dial_str = g_at_result_iter_raw_line(&iter);
 
151
       if (!dial_str)
 
152
               goto error;
 
153
 
 
154
       if (em->ppp)
 
155
               goto error;
 
156
 
 
157
       if (!dial_call(em, dial_str))
 
158
               goto error;
 
159
 
 
160
       return;
 
161
 
 
162
error:
 
163
       g_at_server_send_final(em->server, G_AT_SERVER_RESULT_ERROR);
 
164
}
 
165
 
 
166
static void emulator_unregister(struct ofono_atom *atom)
 
167
{
 
168
        struct ofono_emulator *em = __ofono_atom_get_data(atom);
 
169
 
 
170
        DBG("%p", em);
 
171
 
 
172
        if (em->source) {
 
173
                g_source_remove(em->source);
 
174
                em->source = 0;
 
175
        }
 
176
 
 
177
        g_at_server_unref(em->server);
 
178
        em->server = NULL;
 
179
}
 
180
 
 
181
void ofono_emulator_register(struct ofono_emulator *em, int fd)
 
182
{
 
183
        GIOChannel *io;
 
184
 
 
185
        DBG("%p, %d", em, fd);
 
186
 
 
187
        if (fd < 0)
 
188
                return;
 
189
 
 
190
        io = g_io_channel_unix_new(fd);
 
191
 
 
192
        em->server = g_at_server_new(io);
 
193
        if (em->server == NULL)
 
194
                return;
 
195
 
 
196
        g_io_channel_unref(io);
 
197
 
 
198
        g_at_server_set_debug(em->server, emulator_debug, "Server");
 
199
        g_at_server_set_disconnect_function(em->server,
 
200
                                                emulator_disconnect, em);
 
201
 
 
202
        __ofono_atom_register(em->atom, emulator_unregister);
 
203
 
 
204
        if (em->type == OFONO_EMULATOR_TYPE_DUN)
 
205
                g_at_server_register(em->server, "D", dial_cb, em, NULL);
 
206
}
 
207
 
 
208
static void emulator_remove(struct ofono_atom *atom)
 
209
{
 
210
        struct ofono_emulator *em = __ofono_atom_get_data(atom);
 
211
 
 
212
        DBG("atom: %p", atom);
 
213
 
 
214
        g_free(em);
 
215
}
 
216
 
 
217
struct ofono_emulator *ofono_emulator_create(struct ofono_modem *modem,
 
218
                                                enum ofono_emulator_type type)
 
219
{
 
220
        struct ofono_emulator *em;
 
221
        enum ofono_atom_type atom_t;
 
222
 
 
223
        DBG("modem: %p, type: %d", modem, type);
 
224
 
 
225
        if (type == OFONO_EMULATOR_TYPE_DUN)
 
226
                atom_t = OFONO_ATOM_TYPE_EMULATOR_DUN;
 
227
        else if (type == OFONO_EMULATOR_TYPE_HFP)
 
228
                atom_t = OFONO_ATOM_TYPE_EMULATOR_HFP;
 
229
        else
 
230
                return NULL;
 
231
 
 
232
        em = g_try_new0(struct ofono_emulator, 1);
 
233
 
 
234
        if (em == NULL)
 
235
                return NULL;
 
236
 
 
237
        em->type = type;
 
238
 
 
239
        em->atom = __ofono_modem_add_atom_offline(modem, atom_t,
 
240
                                                        emulator_remove, em);
 
241
 
 
242
        return em;
 
243
}
 
244
 
 
245
void ofono_emulator_remove(struct ofono_emulator *em)
 
246
{
 
247
        __ofono_atom_free(em->atom);
 
248
}
 
249
 
 
250
void ofono_emulator_send_final(struct ofono_emulator *em,
 
251
                                const struct ofono_error *final)
 
252
{
 
253
        char buf[256];
 
254
 
 
255
        /*
 
256
         * TODO: Handle various CMEE modes and report error strings from
 
257
         * common.c
 
258
         */
 
259
        switch (final->type) {
 
260
        case OFONO_ERROR_TYPE_CMS:
 
261
                sprintf(buf, "+CMS ERROR: %d", final->error);
 
262
                g_at_server_send_ext_final(em->server, buf);
 
263
                break;
 
264
 
 
265
        case OFONO_ERROR_TYPE_CME:
 
266
                sprintf(buf, "+CME ERROR: %d", final->error);
 
267
                g_at_server_send_ext_final(em->server, buf);
 
268
                break;
 
269
 
 
270
        case OFONO_ERROR_TYPE_NO_ERROR:
 
271
                g_at_server_send_final(em->server, G_AT_SERVER_RESULT_OK);
 
272
                break;
 
273
 
 
274
        case OFONO_ERROR_TYPE_CEER:
 
275
        case OFONO_ERROR_TYPE_SIM:
 
276
        case OFONO_ERROR_TYPE_FAILURE:
 
277
                g_at_server_send_final(em->server, G_AT_SERVER_RESULT_ERROR);
 
278
                break;
 
279
        };
 
280
}
 
281
 
 
282
void ofono_emulator_send_unsolicited(struct ofono_emulator *em,
 
283
                                        const char *result)
 
284
{
 
285
        g_at_server_send_unsolicited(em->server, result);
 
286
}
 
287
 
 
288
void ofono_emulator_send_intermediate(struct ofono_emulator *em,
 
289
                                        const char *result)
 
290
{
 
291
        g_at_server_send_intermediate(em->server, result);
 
292
}
 
293
 
 
294
void ofono_emulator_send_info(struct ofono_emulator *em, const char *line,
 
295
                                ofono_bool_t last)
 
296
{
 
297
        g_at_server_send_info(em->server, line, last);
 
298
}
 
299
 
 
300
struct handler {
 
301
        ofono_emulator_request_cb_t cb;
 
302
        void *data;
 
303
        ofono_destroy_func destroy;
 
304
        struct ofono_emulator *em;
 
305
};
 
306
 
 
307
struct ofono_emulator_request {
 
308
        GAtResultIter iter;
 
309
        enum ofono_emulator_request_type type;
 
310
};
 
311
 
 
312
static void handler_proxy(GAtServer *server, GAtServerRequestType type,
 
313
                                GAtResult *result, gpointer userdata)
 
314
{
 
315
        struct handler *h = userdata;
 
316
        struct ofono_emulator_request req;
 
317
 
 
318
        switch (type) {
 
319
        case G_AT_SERVER_REQUEST_TYPE_COMMAND_ONLY:
 
320
                req.type = OFONO_EMULATOR_REQUEST_TYPE_COMMAND_ONLY;
 
321
                break;
 
322
        case G_AT_SERVER_REQUEST_TYPE_SET:
 
323
                req.type = OFONO_EMULATOR_REQUEST_TYPE_SET;
 
324
                break;
 
325
        case G_AT_SERVER_REQUEST_TYPE_QUERY:
 
326
                req.type = OFONO_EMULATOR_REQUEST_TYPE_QUERY;
 
327
                break;
 
328
        case G_AT_SERVER_REQUEST_TYPE_SUPPORT:
 
329
                req.type = OFONO_EMULATOR_REQUEST_TYPE_SUPPORT;
 
330
        }
 
331
 
 
332
        g_at_result_iter_init(&req.iter, result);
 
333
        g_at_result_iter_next(&req.iter, "");
 
334
 
 
335
        h->cb(h->em, &req, h->data);
 
336
}
 
337
 
 
338
static void handler_destroy(gpointer userdata)
 
339
{
 
340
        struct handler *h = userdata;
 
341
 
 
342
        if (h->destroy)
 
343
                h->destroy(h->data);
 
344
 
 
345
        g_free(h);
 
346
}
 
347
 
 
348
ofono_bool_t ofono_emulator_add_handler(struct ofono_emulator *em,
 
349
                                        const char *prefix,
 
350
                                        ofono_emulator_request_cb_t cb,
 
351
                                        void *data, ofono_destroy_func destroy)
 
352
{
 
353
        struct handler *h;
 
354
 
 
355
        h = g_new0(struct handler, 1);
 
356
        h->cb = cb;
 
357
        h->data = data;
 
358
        h->destroy = destroy;
 
359
        h->em = em;
 
360
 
 
361
        if (g_at_server_register(em->server, prefix, handler_proxy, h,
 
362
                                        handler_destroy) == TRUE)
 
363
                return TRUE;
 
364
 
 
365
        g_free(h);
 
366
 
 
367
        return FALSE;
 
368
}
 
369
 
 
370
ofono_bool_t ofono_emulator_remove_handler(struct ofono_emulator *em,
 
371
                                                const char *prefix)
 
372
{
 
373
        return g_at_server_unregister(em->server, prefix);
 
374
}
 
375
 
 
376
ofono_bool_t ofono_emulator_request_next_string(
 
377
                                        struct ofono_emulator_request *req,
 
378
                                        const char **str)
 
379
{
 
380
        return g_at_result_iter_next_string(&req->iter, str);
 
381
}
 
382
 
 
383
ofono_bool_t ofono_emulator_request_next_number(
 
384
                                        struct ofono_emulator_request *req,
 
385
                                        int *number)
 
386
{
 
387
        return g_at_result_iter_next_number(&req->iter, number);
 
388
}
 
389
 
 
390
const char *ofono_emulator_request_get_raw(struct ofono_emulator_request *req)
 
391
{
 
392
        return g_at_result_iter_raw_line(&req->iter);
 
393
}
 
394
 
 
395
enum ofono_emulator_request_type ofono_emulator_request_get_type(
 
396
                                        struct ofono_emulator_request *req)
 
397
{
 
398
        return req->type;
 
399
}