~ubuntu-branches/ubuntu/utopic/ofono/utopic-proposed

« back to all changes in this revision

Viewing changes to drivers/atmodem/gnss.c

  • Committer: Package Import Robot
  • Author(s): Mathieu Trudel-Lapierre
  • Date: 2012-08-22 19:59:08 UTC
  • mfrom: (1.4.3)
  • mto: This revision was merged to the branch mainline in revision 21.
  • Revision ID: package-import@ubuntu.com-20120822195908-20ccett2uhgcz7f6
Tags: upstream-1.9
ImportĀ upstreamĀ versionĀ 1.9

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
 *  Copyright (C) 2011  ST-Ericsson AB.
 
7
 *
 
8
 *  This program is free software; you can redistribute it and/or modify
 
9
 *  it under the terms of the GNU General Public License version 2 as
 
10
 *  published by the Free Software Foundation.
 
11
 *
 
12
 *  This program is distributed in the hope that it will be useful,
 
13
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 
14
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
15
 *  GNU General Public License for more details.
 
16
 *
 
17
 *  You should have received a copy of the GNU General Public License
 
18
 *  along with this program; if not, write to the Free Software
 
19
 *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 
20
 *
 
21
 */
 
22
 
 
23
#ifdef HAVE_CONFIG_H
 
24
#include <config.h>
 
25
#endif
 
26
 
 
27
#define _GNU_SOURCE
 
28
#include <string.h>
 
29
#include <stdlib.h>
 
30
#include <stdio.h>
 
31
#include <errno.h>
 
32
 
 
33
#include <glib.h>
 
34
 
 
35
#include <ofono/log.h>
 
36
#include <ofono/modem.h>
 
37
#include <ofono/gnss.h>
 
38
 
 
39
#include "gatchat.h"
 
40
#include "gatresult.h"
 
41
 
 
42
#include "atmodem.h"
 
43
#include "vendor.h"
 
44
 
 
45
struct gnss_data {
 
46
        GAtChat *chat;
 
47
        unsigned int vendor;
 
48
};
 
49
 
 
50
static const char *none_prefix[] = { NULL };
 
51
static const char *cpos_prefix[] = { "+CPOS:", NULL };
 
52
static const char *cposr_prefix[] = { "+CPOSR:", NULL };
 
53
 
 
54
static void gnss_pr_cb(gboolean ok, GAtResult *result, gpointer user_data)
 
55
{
 
56
        struct cb_data *cbd = user_data;
 
57
        ofono_gnss_cb_t cb = cbd->cb;
 
58
        struct ofono_error error;
 
59
 
 
60
        DBG("");
 
61
 
 
62
        decode_at_error(&error, g_at_result_final_response(result));
 
63
 
 
64
        cb(&error, cbd->data);
 
65
}
 
66
 
 
67
static void at_gnss_position_reporting(struct ofono_gnss *gnss,
 
68
                                        ofono_bool_t enable,
 
69
                                        ofono_gnss_cb_t cb,
 
70
                                        void *data)
 
71
{
 
72
        struct gnss_data *ad = ofono_gnss_get_data(gnss);
 
73
        struct cb_data *cbd = cb_data_new(cb, data);
 
74
 
 
75
        DBG("");
 
76
 
 
77
        if (enable) {
 
78
                g_at_chat_send(ad->chat, "AT+CPOSR=1",
 
79
                                cposr_prefix, gnss_pr_cb, cbd, g_free);
 
80
 
 
81
                if (ad->vendor == OFONO_VENDOR_STE)
 
82
                        g_at_chat_send(ad->chat, "AT*EPOSADRR=1",
 
83
                                        NULL, NULL, NULL, NULL);
 
84
        } else {
 
85
                g_at_chat_send(ad->chat, "AT+CPOSR=0",
 
86
                                cposr_prefix, gnss_pr_cb, cbd, g_free);
 
87
 
 
88
                if (ad->vendor == OFONO_VENDOR_STE)
 
89
                        g_at_chat_send(ad->chat, "AT*EPOSADRR=0",
 
90
                                        NULL, NULL, NULL, NULL);
 
91
        }
 
92
}
 
93
 
 
94
static void gnss_se_cb(gboolean ok, GAtResult *result, gpointer user_data)
 
95
{
 
96
        struct cb_data *cbd = user_data;
 
97
        ofono_gnss_cb_t cb = cbd->cb;
 
98
        struct ofono_error error;
 
99
 
 
100
        DBG("");
 
101
 
 
102
        decode_at_error(&error, g_at_result_final_response(result));
 
103
 
 
104
        cb(&error, cbd->data);
 
105
}
 
106
 
 
107
static void at_gnss_send_element(struct ofono_gnss *gnss,
 
108
                                const char *xml,
 
109
                                ofono_gnss_cb_t cb, void *data)
 
110
{
 
111
        struct gnss_data *ad = ofono_gnss_get_data(gnss);
 
112
        struct cb_data *cbd = cb_data_new(cb, data);
 
113
        char *buf = g_try_new(char, strlen(xml) + 10);
 
114
        int len;
 
115
 
 
116
        DBG("");
 
117
 
 
118
        if (buf == NULL)
 
119
                goto error;
 
120
 
 
121
        len = sprintf(buf, "AT+CPOS\r");
 
122
        len += sprintf(buf + len, "%s", xml);
 
123
 
 
124
        if (g_at_chat_send_and_expect_short_prompt(ad->chat, buf, cpos_prefix,
 
125
                                                        gnss_se_cb, cbd,
 
126
                                                        g_free) > 0) {
 
127
                g_free(buf);
 
128
                return;
 
129
        }
 
130
 
 
131
error:
 
132
        g_free(buf);
 
133
        g_free(cbd);
 
134
 
 
135
        CALLBACK_WITH_FAILURE(cb, data);
 
136
}
 
137
 
 
138
static gboolean gnss_parse_report(GAtResult *result, const char *prefix,
 
139
                                        const char **xml)
 
140
{
 
141
        GAtResultIter iter;
 
142
 
 
143
        g_at_result_iter_init(&iter, result);
 
144
 
 
145
        if (!g_at_result_iter_next(&iter, prefix))
 
146
                return FALSE;
 
147
 
 
148
        if (!g_at_result_iter_next_unquoted_string(&iter, xml))
 
149
                return FALSE;
 
150
 
 
151
        return TRUE;
 
152
}
 
153
 
 
154
static void gnss_report(GAtResult *result, gpointer user_data)
 
155
{
 
156
        const char *xml;
 
157
 
 
158
        DBG("");
 
159
 
 
160
        xml = NULL;
 
161
 
 
162
        if (!gnss_parse_report(result, "+CPOSR:", &xml)) {
 
163
                ofono_error("Unable to parse CPOSR notification");
 
164
                return;
 
165
        }
 
166
 
 
167
        if (xml == NULL) {
 
168
                ofono_error("Unable to parse CPOSR notification");
 
169
                return;
 
170
        }
 
171
 
 
172
        DBG("%s", xml);
 
173
}
 
174
 
 
175
static void at_gnss_reset_notify(GAtResult *result, gpointer user_data)
 
176
{
 
177
        struct ofono_gnss *gnss = user_data;
 
178
 
 
179
        DBG("");
 
180
 
 
181
        ofono_gnss_notify_posr_reset(gnss);
 
182
}
 
183
 
 
184
static void at_gnss_not_supported(struct ofono_gnss *gnss)
 
185
{
 
186
        ofono_error("gnss not supported by this modem.");
 
187
 
 
188
        ofono_gnss_remove(gnss);
 
189
}
 
190
 
 
191
static void at_gnss_cposr_support_cb(gboolean ok, GAtResult *result,
 
192
                                        gpointer user_data)
 
193
{
 
194
        struct ofono_gnss *gnss = user_data;
 
195
        struct gnss_data *ad = ofono_gnss_get_data(gnss);
 
196
 
 
197
        DBG("");
 
198
 
 
199
        if (!ok) {
 
200
                at_gnss_not_supported(gnss);
 
201
                return;
 
202
        }
 
203
 
 
204
        g_at_chat_register(ad->chat, "+CPOSR:", gnss_report,
 
205
                                FALSE, gnss, NULL);
 
206
 
 
207
        if (ad->vendor == OFONO_VENDOR_STE)
 
208
                g_at_chat_register(ad->chat, "*EPOSADRR:", at_gnss_reset_notify,
 
209
                                        FALSE, gnss, NULL);
 
210
 
 
211
        ofono_gnss_register(gnss);
 
212
}
 
213
 
 
214
static void at_gnss_cpos_support_cb(gboolean ok, GAtResult *result,
 
215
                                        gpointer user_data)
 
216
{
 
217
        struct ofono_gnss *gnss = user_data;
 
218
        struct gnss_data *ad = ofono_gnss_get_data(gnss);
 
219
 
 
220
        DBG("");
 
221
 
 
222
        if (!ok) {
 
223
                at_gnss_not_supported(gnss);
 
224
                return;
 
225
        }
 
226
 
 
227
        g_at_chat_send(ad->chat, "AT+CPOSR=?",
 
228
                        none_prefix, at_gnss_cposr_support_cb, gnss, NULL);
 
229
}
 
230
 
 
231
static int at_gnss_probe(struct ofono_gnss *gnss, unsigned int vendor,
 
232
                                void *user)
 
233
{
 
234
        GAtChat *chat = user;
 
235
        struct gnss_data *gd;
 
236
 
 
237
        DBG("");
 
238
 
 
239
        gd = g_try_new0(struct gnss_data, 1);
 
240
        if (gd == NULL)
 
241
                return -ENOMEM;
 
242
 
 
243
        gd->chat = g_at_chat_clone(chat);
 
244
        gd->vendor = vendor;
 
245
 
 
246
        ofono_gnss_set_data(gnss, gd);
 
247
 
 
248
        g_at_chat_send(gd->chat, "AT+CPOS=?",
 
249
                        none_prefix, at_gnss_cpos_support_cb, gnss, NULL);
 
250
 
 
251
        return 0;
 
252
}
 
253
 
 
254
static void at_gnss_remove(struct ofono_gnss *gnss)
 
255
{
 
256
        struct gnss_data *gd = ofono_gnss_get_data(gnss);
 
257
 
 
258
        DBG("");
 
259
 
 
260
        ofono_gnss_set_data(gnss, NULL);
 
261
 
 
262
        g_at_chat_unref(gd->chat);
 
263
        g_free(gd);
 
264
}
 
265
 
 
266
static struct ofono_gnss_driver driver = {
 
267
        .name                   = "atmodem",
 
268
        .probe                  = at_gnss_probe,
 
269
        .remove                 = at_gnss_remove,
 
270
        .send_element           = at_gnss_send_element,
 
271
        .set_position_reporting = at_gnss_position_reporting,
 
272
};
 
273
 
 
274
void at_gnss_init(void)
 
275
{
 
276
        ofono_gnss_driver_register(&driver);
 
277
}
 
278
 
 
279
void at_gnss_exit(void)
 
280
{
 
281
        ofono_gnss_driver_unregister(&driver);
 
282
}