Merge lp:~phablet-team/ofono/update-july-first into lp:~phablet-team/ofono/ubuntu

Proposed by Alfonso Sanchez-Beato
Status: Merged
Approved by: Tony Espy
Approved revision: 6903
Merged at revision: 6898
Proposed branch: lp:~phablet-team/ofono/update-july-first
Merge into: lp:~phablet-team/ofono/ubuntu
Diff against target: 2564 lines (+1823/-149)
27 files modified
Makefile.am (+16/-2)
configure.ac (+11/-0)
debian/changelog (+20/-0)
debian/control (+2/-1)
drivers/mtkmodem/mtkutil.h (+1/-0)
drivers/qcommsimmodem/qcom_msim_constants.h (+2/-0)
drivers/qcommsimmodem/qcom_msim_modem.c (+56/-0)
drivers/qcommsimmodem/qcom_msim_modem.h (+25/-0)
drivers/qcommsimmodem/radio-settings.c (+270/-0)
drivers/rilmodem/gprs-context.c (+86/-6)
drivers/rilmodem/radio-settings.c (+1/-1)
drivers/rilmodem/radio-settings.h (+3/-0)
drivers/rilmodem/rilutil.h (+1/-0)
gril/gril.c (+4/-15)
include/dns-client.h (+120/-0)
include/radio-settings.h (+3/-0)
plugins/c-ares-dns-client.c (+767/-0)
plugins/mtk.c (+12/-2)
plugins/ril.c (+20/-6)
src/dns-client.c (+128/-0)
src/gprs.c (+260/-102)
src/radio-settings.c (+3/-3)
test/list-contexts (+1/-1)
test/list-modems (+5/-4)
test/rilmodem/sim/simtestutil.py (+4/-4)
test/rilmodem/sim/test-no-sims-offline (+1/-1)
test/rilmodem/sim/test-sims-offline (+1/-1)
To merge this branch: bzr merge lp:~phablet-team/ofono/update-july-first
Reviewer Review Type Date Requested Status
Tony Espy Approve
Review via email: mp+263462@code.launchpad.net

Commit message

[Tony Espy]
* test/rilmodem/sim: fix testing scripts for arale
* test: reverse meaning of list-modems -p
[ Alfonso Sanchez-Beato ]
* gril: cleanup traces
* src/gprs.c: set preferred for the used IA APN
* rilmodem, mtkmodem, plugins/ril.c, plugins/mtk.c: retry when a
  context deactivation request has finished with an error
* build, include, plugins/c-ares-dns-client.c, src/dns-client.c,
  src/gprs.c: resolve MMS proxy/MMSC host name (LP: #1417976)
[ Ratchanan Srirattanamet ]
* build, rilmodem, qcommsimmodem, plugins/ril.c,
  src/radio-settings.c: add multi-sim support for qcommsimmodem

Description of the change

[Tony Espy]
* test/rilmodem/sim: fix testing scripts for arale
* test: reverse meaning of list-modems -p
[ Alfonso Sanchez-Beato ]
* gril: cleanup traces
* src/gprs.c: set preferred for the used IA APN
* rilmodem, mtkmodem, plugins/ril.c, plugins/mtk.c: retry when a
  context deactivation request has finished with an error
* build, include, plugins/c-ares-dns-client.c, src/dns-client.c,
  src/gprs.c: resolve MMS proxy/MMSC host name (LP: #1417976)
[ Ratchanan Srirattanamet ]
* build, rilmodem, qcommsimmodem, plugins/ril.c,
  src/radio-settings.c: add multi-sim support for qcommsimmodem

To post a comment you must log in.
6899. By Alfonso Sanchez-Beato

Add c-ares-dev to debian build dependencies

6900. By Alfonso Sanchez-Beato

Fix printing context properties

Revision history for this message
Tony Espy (awe) wrote :

The code all looks good. That said, the changelog needs some fixing ( see inline comments ).

review: Needs Fixing
6901. By Alfonso Sanchez-Beato

Fix changelog

6902. By Alfonso Sanchez-Beato

Fix debian package version

Revision history for this message
Alfonso Sanchez-Beato (alfonsosanchezbeato) wrote :

Changelog changed adding bug numbers, but I have not reverted the package version number because the actual version produced in the silo is 6900. I think that at some moment there has been a mismatch between changelog version and the version in the package name, and using 6900 we get both things synced again.

Revision history for this message
Tony Espy (awe) wrote :

The version in the silo is 6900 because that's what you told it to build.

Again, the latest version in trunk is 6897, so the merge will be 6898 in trunk, which != 6900, so the versions will actually not be in sync... Let's discuss at our net/telephony meeting.

Revision history for this message
Tony Espy (awe) :
Revision history for this message
Alfonso Sanchez-Beato (alfonsosanchezbeato) wrote :

No, I did change the version to 6898 in the changelog, and the package version was still 6900. It takes the bzr branch version, not the version from the changelog.

6903. By Alfonso Sanchez-Beato

Fix changelog

Revision history for this message
Tony Espy (awe) :
review: Approve
6904. By Alfonso Sanchez-Beato

Fix package version

6905. By Alfonso Sanchez-Beato

Fix version to 6900

Revision history for this message
Tony Espy (awe) wrote :

Tested mako ( rc/ubuntu #1 ); Note, the latest version of network-manager (4ubuntu15.1.4) from the overlay PPA was also installed.

Ran the Basic Tests from:

https://wiki.ubuntu.com/Process/Merges/TestPlans/ofono

Also verified that MMS can be sent & received using AT&T, which provision an APN that specifies a non-dotted-IP-address MessageProxy ( proxy.mobile.att:80 ). Both sending and receiving worked as expected.

Verified that the list-modems privacy flag has indeed been reversed, and also checked that the rilmodem test scripts didn't break due to an arale fix contained in this merge. Did find one bug in one of the test scripts though ( not a regression ):

https://bugs.launchpad.net/ubuntu/+source/ofono/+bug/1471019

Revision history for this message
Alfonso Sanchez-Beato (alfonsosanchezbeato) wrote :

Tested on arale (devel-proposed, #41)

Ran the Basic Tests from:

https://wiki.ubuntu.com/Process/Merges/TestPlans/ofono

Restoring cellular mode after unsetting flight mode failed, which was expected as the NM version that fixes this has not landed in wily.

Verified bugs #1438715, #1457775, #1361864 are fixed.

MMS tx/rx working for pepephone operator.

Revision history for this message
Alfonso Sanchez-Beato (alfonsosanchezbeato) wrote :

Tested on krillin (rc-proposed, #56)

Ran the Basic Tests from:

https://wiki.ubuntu.com/Process/Merges/TestPlans/ofono

Verified bugs #1438715, #1361864 are fixed.

MMS tx/rx working for pepephone operator.

Revision history for this message
Alfonso Sanchez-Beato (alfonsosanchezbeato) wrote :

Vivid silo tested on krillin (rc-proposed, #56)

Ran the Basic Tests from:

https://wiki.ubuntu.com/Process/Merges/TestPlans/ofono

MMS tx/rx working for pepephone operator.

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'Makefile.am'
2--- Makefile.am 2015-05-20 16:32:09 +0000
3+++ Makefile.am 2015-07-02 17:01:42 +0000
4@@ -19,7 +19,8 @@
5 include/cdma-connman.h include/gnss.h \
6 include/private-network.h include/cdma-netreg.h \
7 include/cdma-provision.h include/handsfree.h \
8- include/sim-mnclength.h include/spn-table.h
9+ include/sim-mnclength.h include/spn-table.h \
10+ include/dns-client.h
11
12 nodist_pkginclude_HEADERS = include/version.h
13
14@@ -172,6 +173,10 @@
15 drivers/rilmodem/radio-settings.c \
16 drivers/rilmodem/call-barring.c \
17 drivers/rilmodem/phonebook.c
18+
19+builtin_modules += qcommsimmodem
20+builtin_sources += drivers/qcommsimmodem/qcom_msim_modem.c \
21+ drivers/qcommsimmodem/radio-settings.c
22 endif
23
24 if ISIMODEM
25@@ -530,6 +535,14 @@
26 builtin_sources += plugins/mnclength.c
27 endif
28
29+if CARES
30+builtin_modules += c_ares_dns_client
31+builtin_sources += plugins/c-ares-dns-client.c
32+
33+builtin_cflags += @CARES_CFLAGS@
34+builtin_libadd += @CARES_LIBS@
35+endif
36+
37 if MAINTAINER_MODE
38 builtin_modules += example_history
39 builtin_sources += examples/history.c
40@@ -585,7 +598,8 @@
41 src/cdma-smsutil.h src/cdma-smsutil.c \
42 src/cdma-sms.c src/private-network.c src/cdma-netreg.c \
43 src/cdma-provision.c src/handsfree.c \
44- src/sim-mnclength.c src/spn-table.c
45+ src/sim-mnclength.c src/spn-table.c \
46+ src/dns-client.c
47
48 src_ofonod_LDADD = $(builtin_libadd) @GLIB_LIBS@ @DBUS_LIBS@ -ldl
49
50
51=== modified file 'configure.ac'
52--- configure.ac 2014-06-24 18:59:26 +0000
53+++ configure.ac 2015-07-02 17:01:42 +0000
54@@ -188,6 +188,17 @@
55 AC_SUBST(BLUEZ_LIBS)
56 AM_CONDITIONAL(BLUETOOTH, test "${enable_bluetooth}" != "no")
57
58+AC_ARG_ENABLE(cares, AC_HELP_STRING([--disable-cares],
59+ [disable DNS client using c-ares library]),
60+ [enable_cares=${enableval}])
61+if (test "${enable_cares}" != "no"); then
62+ PKG_CHECK_MODULES(CARES, libcares, dummy=yes,
63+ AC_MSG_ERROR(libcares is required))
64+fi
65+AC_SUBST(CARES_CFLAGS)
66+AC_SUBST(CARES_LIBS)
67+AM_CONDITIONAL(CARES, test "${enable_cares}" != "no")
68+
69 AC_ARG_ENABLE(nettime, AC_HELP_STRING([--disable-nettime],
70 [disable Nettime plugin]),
71 [enable_nettime=${enableval}])
72
73=== modified file 'debian/changelog'
74--- debian/changelog 2015-05-21 08:44:39 +0000
75+++ debian/changelog 2015-07-02 17:01:42 +0000
76@@ -1,3 +1,23 @@
77+ofono (1.12.bzr6900+15.04.20150701-0ubuntu1) UNRELEASED; urgency=medium
78+
79+ [Tony Espy]
80+ * test/rilmodem/sim: fix testing scripts for arale (LP: #1457775)
81+ * test: reverse meaning of list-modems -p (LP: #1438715)
82+
83+ [ Alfonso Sanchez-Beato ]
84+ * gril: cleanup traces
85+ * src/gprs.c: set preferred for the used IA APN (LP: #1361864)
86+ * rilmodem, mtkmodem, plugins/ril.c, plugins/mtk.c: retry when a
87+ context deactivation request has finished with an error
88+ * build, include, plugins/c-ares-dns-client.c, src/dns-client.c,
89+ src/gprs.c: resolve MMS proxy/MMSC host name (LP: #1417976)
90+
91+ [ Ratchanan Srirattanamet ]
92+ * build, rilmodem, qcommsimmodem, plugins/ril.c,
93+ src/radio-settings.c: add multi-sim support for qcommsimmodem
94+
95+ -- Alfonso Sanchez-Beato (email Canonical) <alfonso.sanchez-beato@canonical.com> Wed, 01 Jul 2015 08:40:36 +0200
96+
97 ofono (1.12.bzr6896+15.04.20150521-0ubuntu1) vivid; urgency=medium
98
99 [ Ratchanan Srirattanamet ]
100
101=== modified file 'debian/control'
102--- debian/control 2015-01-12 10:01:50 +0000
103+++ debian/control 2015-07-02 17:01:42 +0000
104@@ -13,7 +13,8 @@
105 libudev-dev,
106 udev,
107 libbluetooth-dev (>= 4.30),
108- mobile-broadband-provider-info
109+ mobile-broadband-provider-info,
110+ libc-ares-dev
111 Standards-Version: 3.9.4
112 Homepage: http://www.ofono.org/
113 # If you aren't a member of ~phablet-team but need to upload
114
115=== modified file 'drivers/mtkmodem/mtkutil.h'
116--- drivers/mtkmodem/mtkutil.h 2015-01-29 14:50:30 +0000
117+++ drivers/mtkmodem/mtkutil.h 2015-07-02 17:01:42 +0000
118@@ -35,6 +35,7 @@
119 void mtk_detach_received(struct ofono_modem *modem);
120
121 void mtk_reset_all_modems(void);
122+void mtk_reset_modem(struct ofono_modem *modem);
123
124 const char *mtk_request_id_to_string(int req);
125 const char *mtk_unsol_request_to_string(int req);
126
127=== modified file 'drivers/qcommsimmodem/qcom_msim_constants.h'
128--- drivers/qcommsimmodem/qcom_msim_constants.h 2015-04-23 13:08:30 +0000
129+++ drivers/qcommsimmodem/qcom_msim_constants.h 2015-07-02 17:01:42 +0000
130@@ -22,6 +22,8 @@
131 #ifndef QCOM_MSIM_CONSTANTS_H
132 #define QCOM_MSIM_CONSTANTS_H
133
134+#define QCOMMSIM_NUM_SLOTS_MAX 2
135+
136 #define QCOM_MSIM_RIL_REQUEST_SET_UICC_SUBSCRIPTION 115
137
138 #endif /* QCOM_MSIM_CONSTANTS_H */
139
140=== added file 'drivers/qcommsimmodem/qcom_msim_modem.c'
141--- drivers/qcommsimmodem/qcom_msim_modem.c 1970-01-01 00:00:00 +0000
142+++ drivers/qcommsimmodem/qcom_msim_modem.c 2015-07-02 17:01:42 +0000
143@@ -0,0 +1,56 @@
144+/*
145+ *
146+ * oFono - Open Source Telephony - RIL Modem Support
147+ *
148+ * Copyright (C) 2008-2011 Intel Corporation. All rights reserved.
149+ * Copyright (C) 2012 Canonical, Ltd. All rights reserved.
150+ * Copyright (C) 2015 Ratchanan Srirattanamet.
151+ *
152+ * This program is free software; you can redistribute it and/or modify
153+ * it under the terms of the GNU General Public License version 2 as
154+ * published by the Free Software Foundation.
155+ *
156+ * This program is distributed in the hope that it will be useful,
157+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
158+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
159+ * GNU General Public License for more details.
160+ *
161+ * You should have received a copy of the GNU General Public License
162+ * along with this program; if not, write to the Free Software
163+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
164+ *
165+ */
166+
167+#ifdef HAVE_CONFIG_H
168+#include <config.h>
169+#endif
170+
171+#include <glib.h>
172+#include <gril.h>
173+
174+#define OFONO_API_SUBJECT_TO_CHANGE
175+#include <ofono/plugin.h>
176+#include <ofono/log.h>
177+#include <ofono/types.h>
178+
179+#include "qcom_msim_modem.h"
180+
181+static int qcom_msim_modem_init(void)
182+{
183+ DBG("");
184+
185+ qcom_msim_radio_settings_init();
186+
187+ return 0;
188+}
189+
190+static void qcom_msim_modem_exit(void)
191+{
192+ DBG("");
193+
194+ qcom_msim_radio_settings_exit();
195+}
196+
197+OFONO_PLUGIN_DEFINE(qcommsimmodem, "Qualcomm multi-sim modem driver", VERSION,
198+ OFONO_PLUGIN_PRIORITY_DEFAULT,
199+ qcom_msim_modem_init, qcom_msim_modem_exit)
200
201=== added file 'drivers/qcommsimmodem/qcom_msim_modem.h'
202--- drivers/qcommsimmodem/qcom_msim_modem.h 1970-01-01 00:00:00 +0000
203+++ drivers/qcommsimmodem/qcom_msim_modem.h 2015-07-02 17:01:42 +0000
204@@ -0,0 +1,25 @@
205+/*
206+ *
207+ * oFono - Open Source Telephony - RIL Modem Support
208+ *
209+ * Copyright (C) 2015 Ratchanan Srirattanamet
210+ *
211+ * This program is free software; you can redistribute it and/or modify
212+ * it under the terms of the GNU General Public License version 2 as
213+ * published by the Free Software Foundation.
214+ *
215+ * This program is distributed in the hope that it will be useful,
216+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
217+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
218+ * GNU General Public License for more details.
219+ *
220+ * You should have received a copy of the GNU General Public License
221+ * along with this program; if not, write to the Free Software
222+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
223+ *
224+ */
225+
226+#define QCOMMSIMMODEM "qcommsimmodem"
227+
228+extern void qcom_msim_radio_settings_init(void);
229+extern void qcom_msim_radio_settings_exit(void);
230
231=== added file 'drivers/qcommsimmodem/radio-settings.c'
232--- drivers/qcommsimmodem/radio-settings.c 1970-01-01 00:00:00 +0000
233+++ drivers/qcommsimmodem/radio-settings.c 2015-07-02 17:01:42 +0000
234@@ -0,0 +1,270 @@
235+/*
236+ *
237+ * oFono - Open Source Telephony
238+ *
239+ * Copyright (C) 2014 Canonical Ltd.
240+ * Copyright (C) 2015 Ratchanan Srirattanamet
241+ *
242+ * This program is free software; you can redistribute it and/or modify
243+ * it under the terms of the GNU General Public License version 2 as
244+ * published by the Free Software Foundation.
245+ *
246+ * This program is distributed in the hope that it will be useful,
247+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
248+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
249+ * GNU General Public License for more details.
250+ *
251+ * You should have received a copy of the GNU General Public License
252+ * along with this program; if not, write to the Free Software
253+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
254+ *
255+ */
256+
257+#ifdef HAVE_CONFIG_H
258+#include <config.h>
259+#endif
260+
261+#define _GNU_SOURCE
262+#include <stdio.h>
263+#include <stdlib.h>
264+#include <string.h>
265+#include <errno.h>
266+
267+#include <glib.h>
268+
269+#include <ofono/log.h>
270+#include <ofono/modem.h>
271+#include <ofono/radio-settings.h>
272+
273+#include "gril.h"
274+#include "grilrequest.h"
275+#include "grilreply.h"
276+
277+#include "drivers/rilmodem/radio-settings.h"
278+#include "drivers/rilmodem/rilutil.h"
279+#include "qcom_msim_modem.h"
280+#include "qcom_msim_constants.h"
281+
282+struct qcom_msim_pending_pref_setting {
283+ struct ofono_radio_settings *rs;
284+ int pref;
285+ int pending_gsm_pref_remaining;
286+ struct cb_data *cbd;
287+};
288+
289+struct qcom_msim_set_2g_rat {
290+ struct ofono_radio_settings *rs;
291+ struct qcom_msim_pending_pref_setting *pps;
292+};
293+
294+static struct ofono_radio_settings *multisim_rs[QCOMMSIM_NUM_SLOTS_MAX];
295+static int multisim_num_slots;
296+
297+static void qcom_msim_set_rat_cb(struct ril_msg *message, gpointer user_data)
298+{
299+ struct cb_data *cbd = user_data;
300+ struct ofono_radio_settings *rs = cbd->user;
301+ struct radio_data *rd = ofono_radio_settings_get_data(rs);
302+ ofono_radio_settings_rat_mode_set_cb_t cb = cbd->cb;
303+
304+ if (message->error == RIL_E_SUCCESS) {
305+ g_ril_print_response_no_args(rd->ril, message);
306+ CALLBACK_WITH_SUCCESS(cb, cbd->data);
307+ } else {
308+ ofono_error("%s: rat mode setting failed", __func__);
309+ CALLBACK_WITH_FAILURE(cb, cbd->data);
310+ }
311+}
312+
313+static void qcom_msim_set_2g_rat_cb(struct ril_msg *message,
314+ gpointer user_data)
315+{
316+ struct qcom_msim_set_2g_rat *set_2g_rat_data = user_data;
317+ struct ofono_radio_settings *rs = set_2g_rat_data->rs;
318+ struct qcom_msim_pending_pref_setting *pps = set_2g_rat_data->pps;
319+ struct radio_data *rd = ofono_radio_settings_get_data(rs);
320+ ofono_radio_settings_rat_mode_set_cb_t cb;
321+ struct parcel rilp;
322+
323+ pps->pending_gsm_pref_remaining -= 1;
324+
325+ if (message->error == RIL_E_SUCCESS) {
326+ g_ril_print_response_no_args(rd->ril, message);
327+ ofono_radio_settings_set_rat_mode(rs,
328+ OFONO_RADIO_ACCESS_MODE_GSM);
329+ } else {
330+ ofono_error("%s: rat mode setting failed", __func__);
331+ if (pps->cbd != NULL) {
332+ cb = pps->cbd->cb;
333+ CALLBACK_WITH_FAILURE(cb, pps->cbd->data);
334+
335+ g_free(pps->cbd);
336+ pps->cbd = NULL;
337+ }
338+ }
339+
340+ if (pps->pending_gsm_pref_remaining == 0) {
341+ if (pps->cbd != NULL) {
342+ struct radio_data *pps_rd =
343+ ofono_radio_settings_get_data(pps->rs);
344+ g_ril_request_set_preferred_network_type(pps_rd->ril,
345+ pps->pref, &rilp);
346+
347+ if (g_ril_send(pps_rd->ril,
348+ RIL_REQUEST_SET_PREFERRED_NETWORK_TYPE,
349+ &rilp, qcom_msim_set_rat_cb, pps->cbd,
350+ g_free) == 0) {
351+ ofono_error("%s: unable to set rat mode",
352+ __func__);
353+ cb = pps->cbd->cb;
354+ CALLBACK_WITH_FAILURE(cb, pps->cbd->data);
355+ g_free(pps->cbd);
356+ }
357+ }
358+
359+ g_free(pps);
360+ }
361+}
362+
363+static void qcom_msim_set_rat_mode(struct ofono_radio_settings *rs,
364+ enum ofono_radio_access_mode mode,
365+ ofono_radio_settings_rat_mode_set_cb_t cb,
366+ void *data)
367+{
368+ struct radio_data *rd = ofono_radio_settings_get_data(rs);
369+ struct cb_data *cbd = cb_data_new(cb, data, rs);
370+ struct parcel rilp;
371+ int pref = PREF_NET_TYPE_GSM_WCDMA;
372+
373+ switch (mode) {
374+ case OFONO_RADIO_ACCESS_MODE_ANY:
375+ pref = PREF_NET_TYPE_LTE_GSM_WCDMA;
376+ break;
377+ case OFONO_RADIO_ACCESS_MODE_GSM:
378+ pref = PREF_NET_TYPE_GSM_ONLY;
379+ break;
380+ case OFONO_RADIO_ACCESS_MODE_UMTS:
381+ pref = PREF_NET_TYPE_GSM_WCDMA;
382+ break;
383+ case OFONO_RADIO_ACCESS_MODE_LTE:
384+ pref = PREF_NET_TYPE_LTE_GSM_WCDMA;
385+ break;
386+ }
387+
388+ if (pref != PREF_NET_TYPE_GSM_ONLY && multisim_num_slots > 1) {
389+ struct qcom_msim_pending_pref_setting *pps =
390+ g_try_new0(struct qcom_msim_pending_pref_setting, 1);
391+ int i;
392+
393+ pps->rs = rs;
394+ pps->pref = pref;
395+ pps->cbd = cbd;
396+ pps->pending_gsm_pref_remaining = 0;
397+
398+ for (i = 0; i < QCOMMSIM_NUM_SLOTS_MAX; i++) {
399+ struct radio_data *temp_rd;
400+ struct qcom_msim_set_2g_rat *set_2g_rat_data;
401+
402+ if (multisim_rs[i] == rs || multisim_rs[i] == NULL)
403+ continue;
404+
405+ temp_rd = ofono_radio_settings_get_data(multisim_rs[i]);
406+ set_2g_rat_data =
407+ g_try_new0(struct qcom_msim_set_2g_rat, 1);
408+ set_2g_rat_data->pps = pps;
409+ set_2g_rat_data->rs = multisim_rs[i];
410+
411+ g_ril_request_set_preferred_network_type(temp_rd->ril,
412+ PREF_NET_TYPE_GSM_ONLY, &rilp);
413+
414+ if (g_ril_send(temp_rd->ril,
415+ RIL_REQUEST_SET_PREFERRED_NETWORK_TYPE,
416+ &rilp, qcom_msim_set_2g_rat_cb,
417+ set_2g_rat_data, g_free) == 0) {
418+ ofono_error("%s: unable to set rat mode",
419+ __func__);
420+ pps->cbd = NULL;
421+ g_free(cbd);
422+ g_free(set_2g_rat_data);
423+ CALLBACK_WITH_FAILURE(cb, data);
424+ break;
425+ } else {
426+ pps->pending_gsm_pref_remaining += 1;
427+ }
428+ }
429+
430+ if (pps->pending_gsm_pref_remaining == 0)
431+ g_free(pps);
432+ } else {
433+ g_ril_request_set_preferred_network_type(rd->ril, pref, &rilp);
434+
435+ if (g_ril_send(rd->ril, RIL_REQUEST_SET_PREFERRED_NETWORK_TYPE,
436+ &rilp, qcom_msim_set_rat_cb, cbd,
437+ g_free) == 0) {
438+ ofono_error("%s: unable to set rat mode", __func__);
439+ g_free(cbd);
440+ CALLBACK_WITH_FAILURE(cb, data);
441+ }
442+ }
443+}
444+
445+static int qcom_msim_radio_settings_probe(struct ofono_radio_settings *rs,
446+ unsigned int vendor, void *user)
447+{
448+ struct ril_radio_settings_driver_data *rs_init_data = user;
449+ struct radio_data *rsd = g_try_new0(struct radio_data, 1);
450+ int slot_id;
451+
452+ if (rsd == NULL) {
453+ ofono_error("%s: cannot allocate memory", __func__);
454+ return -ENOMEM;
455+ }
456+
457+ rsd->ril = g_ril_clone(rs_init_data->gril);
458+ rsd->modem = rs_init_data->modem;
459+
460+ ofono_radio_settings_set_data(rs, rsd);
461+
462+ ril_set_fast_dormancy(rs, FALSE, ril_delayed_register, rs);
463+
464+ slot_id = ofono_modem_get_integer(rsd->modem, "Slot");
465+ multisim_rs[slot_id] = rs;
466+ multisim_num_slots += 1;
467+
468+ return 0;
469+}
470+
471+static void qcom_msim_radio_settings_remove(struct ofono_radio_settings *rs)
472+{
473+ struct radio_data *rd = ofono_radio_settings_get_data(rs);
474+ int slot_id = ofono_modem_get_integer(rd->modem, "Slot");
475+
476+ multisim_rs[slot_id] = NULL;
477+ multisim_num_slots -= 1;
478+
479+ ofono_radio_settings_set_data(rs, NULL);
480+
481+ g_ril_unref(rd->ril);
482+ g_free(rd);
483+}
484+
485+static struct ofono_radio_settings_driver driver = {
486+ .name = QCOMMSIMMODEM,
487+ .probe = qcom_msim_radio_settings_probe,
488+ .remove = qcom_msim_radio_settings_remove,
489+ .query_rat_mode = ril_query_rat_mode,
490+ .set_rat_mode = qcom_msim_set_rat_mode,
491+ .query_fast_dormancy = ril_query_fast_dormancy,
492+ .set_fast_dormancy = ril_set_fast_dormancy,
493+ .query_modem_rats = ril_query_modem_rats
494+};
495+
496+void qcom_msim_radio_settings_init(void)
497+{
498+ ofono_radio_settings_driver_register(&driver);
499+}
500+
501+void qcom_msim_radio_settings_exit(void)
502+{
503+ ofono_radio_settings_driver_unregister(&driver);
504+}
505
506=== modified file 'drivers/rilmodem/gprs-context.c'
507--- drivers/rilmodem/gprs-context.c 2015-05-20 16:32:09 +0000
508+++ drivers/rilmodem/gprs-context.c 2015-07-02 17:01:42 +0000
509@@ -46,6 +46,10 @@
510
511 #include "gprs.h"
512 #include "rilmodem.h"
513+#include "drivers/mtkmodem/mtkutil.h"
514+
515+#define NUM_DEACTIVATION_RETRIES 4
516+#define TIME_BETWEEN_DEACT_RETRIES_S 2
517
518 enum state {
519 STATE_IDLE,
520@@ -56,18 +60,23 @@
521
522 struct gprs_context_data {
523 GRil *ril;
524+ struct ofono_modem *modem;
525+ unsigned vendor;
526 gint active_ctx_cid;
527 gint active_rild_cid;
528 enum state state;
529 guint call_list_id;
530 char *apn;
531 enum ofono_gprs_context_type type;
532+ int deact_retries;
533 };
534
535 static void ril_gprs_context_deactivate_primary(struct ofono_gprs_context *gc,
536 unsigned int id,
537 ofono_gprs_context_cb_t cb,
538 void *data);
539+static void ril_deactivate_data_call_cb(struct ril_msg *message,
540+ gpointer user_data);
541
542 static void set_context_disconnected(struct gprs_context_data *gcd)
543 {
544@@ -318,6 +327,52 @@
545 }
546 }
547
548+static gboolean reset_modem(gpointer data)
549+{
550+ mtk_reset_modem(data);
551+
552+ return FALSE;
553+}
554+
555+static gboolean retry_deactivate(gpointer user_data)
556+{
557+ struct cb_data *cbd = user_data;
558+ ofono_gprs_context_cb_t cb = cbd->cb;
559+ struct ofono_gprs_context *gc = cbd->user;
560+ struct gprs_context_data *gcd = ofono_gprs_context_get_data(gc);
561+ struct req_deactivate_data_call request;
562+ struct parcel rilp;
563+ struct ofono_error error;
564+
565+ /* We might have received a call list update while waiting */
566+ if (gcd->state == STATE_IDLE) {
567+ if (cb)
568+ CALLBACK_WITH_SUCCESS(cb, cbd->data);
569+
570+ g_free(cbd);
571+
572+ return FALSE;
573+ }
574+
575+ request.cid = gcd->active_rild_cid;
576+ request.reason = RIL_DEACTIVATE_DATA_CALL_NO_REASON;
577+
578+ g_ril_request_deactivate_data_call(gcd->ril, &request, &rilp, &error);
579+
580+ if (g_ril_send(gcd->ril, RIL_REQUEST_DEACTIVATE_DATA_CALL, &rilp,
581+ ril_deactivate_data_call_cb, cbd, g_free) == 0) {
582+
583+ ofono_error("%s: send DEACTIVATE_DATA_CALL failed for apn: %s",
584+ __func__, gcd->apn);
585+ if (cb)
586+ CALLBACK_WITH_FAILURE(cb, cbd->data);
587+
588+ g_free(cbd);
589+ }
590+
591+ return FALSE;
592+}
593+
594 static void ril_deactivate_data_call_cb(struct ril_msg *message,
595 gpointer user_data)
596 {
597@@ -329,7 +384,6 @@
598
599 DBG("*gc: %p", gc);
600
601- /* Reply has no data... */
602 if (message->error == RIL_E_SUCCESS) {
603
604 g_ril_print_response_no_args(gcd->ril, message);
605@@ -337,9 +391,9 @@
606 active_ctx_cid = gcd->active_ctx_cid;
607 set_context_disconnected(gcd);
608
609- /* If the deactivate was a result of a shutdown,
610- * there won't be call back, so _deactivated()
611- * needs to be called directly.
612+ /*
613+ * If the deactivate was a result of a shutdown, there won't be
614+ * call back, so _deactivated() needs to be called directly.
615 */
616 if (cb)
617 CALLBACK_WITH_SUCCESS(cb, cbd->data);
618@@ -351,8 +405,31 @@
619 __func__, gcd->apn,
620 ril_error_to_string(message->error));
621
622- if (cb)
623- CALLBACK_WITH_FAILURE(cb, cbd->data);
624+ /*
625+ * It has been detected that some modems fail the deactivation
626+ * temporarily. We do retries to handle that case.
627+ */
628+ if (--(gcd->deact_retries) > 0) {
629+ struct cb_data *cbd2;
630+
631+ cbd2 = cb_data_new(cb, cbd->data, gc);
632+ g_timeout_add_seconds(TIME_BETWEEN_DEACT_RETRIES_S,
633+ retry_deactivate, cbd2);
634+ } else {
635+ ofono_error("%s: retry limit hit", __func__);
636+
637+ if (cb)
638+ CALLBACK_WITH_FAILURE(cb, cbd->data);
639+
640+ /*
641+ * Reset modem if MTK. TODO Failures deactivating a
642+ * context have not been reported for other modems, but
643+ * it would be good to have a generic method to force an
644+ * internal reset nonetheless.
645+ */
646+ if (gcd->vendor == OFONO_RIL_VENDOR_MTK)
647+ g_idle_add(reset_modem, gcd->modem);
648+ }
649 }
650 }
651
652@@ -402,6 +479,7 @@
653 goto error;
654 }
655
656+ gcd->deact_retries = NUM_DEACTIVATION_RETRIES;
657 ret = g_ril_send(gcd->ril, RIL_REQUEST_DEACTIVATE_DATA_CALL, &rilp,
658 ril_deactivate_data_call_cb, cbd, g_free);
659
660@@ -438,6 +516,8 @@
661 return -ENOMEM;
662
663 gcd->ril = g_ril_clone(ril_data->gril);
664+ gcd->modem = ril_data->modem;
665+ gcd->vendor = vendor;
666 set_context_disconnected(gcd);
667 gcd->call_list_id = -1;
668 gcd->type = ril_data->type;
669
670=== modified file 'drivers/rilmodem/radio-settings.c'
671--- drivers/rilmodem/radio-settings.c 2015-01-29 14:50:30 +0000
672+++ drivers/rilmodem/radio-settings.c 2015-07-02 17:01:42 +0000
673@@ -229,7 +229,7 @@
674 return FALSE;
675 }
676
677-static void ril_query_modem_rats(struct ofono_radio_settings *rs,
678+void ril_query_modem_rats(struct ofono_radio_settings *rs,
679 ofono_radio_settings_modem_rats_query_cb_t cb,
680 void *data)
681 {
682
683=== modified file 'drivers/rilmodem/radio-settings.h'
684--- drivers/rilmodem/radio-settings.h 2015-01-29 14:50:30 +0000
685+++ drivers/rilmodem/radio-settings.h 2015-07-02 17:01:42 +0000
686@@ -42,3 +42,6 @@
687 ofono_bool_t enable,
688 ofono_radio_settings_fast_dormancy_set_cb_t cb,
689 void *data);
690+void ril_query_modem_rats(struct ofono_radio_settings *rs,
691+ ofono_radio_settings_modem_rats_query_cb_t cb,
692+ void *data);
693
694=== modified file 'drivers/rilmodem/rilutil.h'
695--- drivers/rilmodem/rilutil.h 2015-01-29 14:50:30 +0000
696+++ drivers/rilmodem/rilutil.h 2015-07-02 17:01:42 +0000
697@@ -75,6 +75,7 @@
698
699 struct ril_gprs_context_data {
700 GRil *gril;
701+ struct ofono_modem *modem;
702 enum ofono_gprs_context_type type;
703 };
704
705
706=== modified file 'gril/gril.c'
707--- gril/gril.c 2014-09-22 16:06:53 +0000
708+++ gril/gril.c 2015-07-02 17:01:42 +0000
709@@ -272,9 +272,6 @@
710 return NULL;
711 }
712
713- DBG("req: %s, id: %d, data_len: %u",
714- request_id_to_string(ril, req), id, data_len);
715-
716 /* Full request size: header size plus buffer length */
717 r->data_len = data_len + sizeof(header);
718
719@@ -375,9 +372,6 @@
720 for (i = 0; i < count; i++) {
721 req = g_queue_peek_nth(p->command_queue, i);
722
723- DBG("comparing req->id: %d to message->serial_no: %d",
724- req->id, message->serial_no);
725-
726 if (req->id == message->serial_no) {
727 found = TRUE;
728 message->req = req->req;
729@@ -393,7 +387,7 @@
730 req->callback(message, req->user_data);
731
732 len = g_queue_get_length(p->out_queue);
733- DBG("requests in out_queue before removing: %d", len);
734+
735 for (i = 0; i < len; i++) {
736 id = GPOINTER_TO_INT(g_queue_peek_nth(
737 p->out_queue, i));
738@@ -413,7 +407,7 @@
739 }
740
741 if (found == FALSE)
742- DBG("Reply: %s serial_no: %d without a matching request!",
743+ ofono_error("No matching request for reply: %s serial_no: %d!",
744 request_id_to_string(p, message->req),
745 message->serial_no);
746
747@@ -584,11 +578,8 @@
748 */
749
750 message_len = *len - 4;
751- if (message_len < plen) {
752- DBG("Not enough bytes for fixed record; len: %d avail: %d",
753- plen, message_len);
754+ if (message_len < plen)
755 return NULL;
756- }
757
758 /* FIXME: add check for message_len = 0? */
759
760@@ -738,7 +729,7 @@
761 len = req->data_len;
762
763 towrite = len - ril->req_bytes_written;
764- DBG("req:%d,len:%zu,towrite:%zu", req->id, len, towrite);
765+
766 #ifdef WRITE_SCHEDULER_DEBUG
767 if (towrite > 5)
768 towrite = 5;
769@@ -1168,8 +1159,6 @@
770
771 g_queue_push_tail(p->command_queue, r);
772
773- DBG("calling wakeup_writer: command_queue len: %d",
774- g_queue_get_length(p->command_queue));
775 ril_wakeup_writer(p);
776
777 if (rilp == NULL)
778
779=== added file 'include/dns-client.h'
780--- include/dns-client.h 1970-01-01 00:00:00 +0000
781+++ include/dns-client.h 2015-07-02 17:01:42 +0000
782@@ -0,0 +1,120 @@
783+/*
784+ *
785+ * DNS Client - provides an asynchronous DNS resolution client.
786+ *
787+ * This file originally created by Google, Inc.
788+ * Copyright (c) 2011 The Chromium OS Authors. All rights reserved.
789+ * Copyright (c) 2015 Canonical Ltd.
790+ *
791+ * This program is free software; you can redistribute it and/or modify
792+ * it under the terms of the GNU General Public License version 2 as
793+ * published by the Free Software Foundation.
794+ *
795+ * This program is distributed in the hope that it will be useful,
796+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
797+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
798+ * GNU General Public License for more details.
799+ *
800+ * You should have received a copy of the GNU General Public License
801+ * along with this program; if not, write to the Free Software
802+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
803+ *
804+ */
805+
806+#ifndef OFONO_DNS_CLIENT_H
807+#define OFONO_DNS_CLIENT_H
808+
809+struct sockaddr;
810+
811+/**
812+ * SECTION:dns_client
813+ * @title: DNS client interface
814+ * @short_description: Functions for interacting with asynchronous DNS client
815+ */
816+
817+/*
818+ * Enumeration of possible DNS request completion status codes.
819+ * These are intentionally consistent with shill error codes.
820+ */
821+typedef enum {
822+ OFONO_DNS_CLIENT_SUCCESS = 0,
823+ OFONO_DNS_CLIENT_ERROR_NO_DATA,
824+ OFONO_DNS_CLIENT_ERROR_FORM_ERR,
825+ OFONO_DNS_CLIENT_ERROR_SERVER_FAIL,
826+ OFONO_DNS_CLIENT_ERROR_NOT_FOUND,
827+ OFONO_DNS_CLIENT_ERROR_NOT_IMP,
828+ OFONO_DNS_CLIENT_ERROR_REFUSED,
829+ OFONO_DNS_CLIENT_ERROR_BAD_QUERY,
830+ OFONO_DNS_CLIENT_ERROR_NET_REFUSED,
831+ OFONO_DNS_CLIENT_ERROR_TIMED_OUT,
832+ OFONO_DNS_CLIENT_ERROR_UNKNOWN,
833+} ofono_dns_client_status_t;
834+
835+/*
836+ * Callbacks of this type are provided by a client when initiating a DNS request
837+ * and invoked by the dns_client module when a request has completed.
838+ * |data| is user data supplied by the client.
839+ * |status| is the completion status of the request.
840+ * |ip_addr| is a struct sockaddr containing an IPv4 or IPv6 address if the
841+ * request succeeded and NULL otherwise. The callee should copy |ip_addr| if it
842+ * wishes to retain it beyond the lifetime of this callback.
843+ */
844+typedef void (*ofono_dns_client_callback_t)(void *data,
845+ ofono_dns_client_status_t status,
846+ struct sockaddr *ip_addr);
847+
848+/*
849+ * Opaque handle uniquely indentifying an in-progress request.
850+ */
851+typedef void *ofono_dns_client_request_t;
852+
853+struct ofono_dns_client_driver {
854+ const char *name;
855+ ofono_dns_client_request_t (*submit_request)(const char *hostname,
856+ const char *device,
857+ const char **servers,
858+ int timeout_ms,
859+ ofono_dns_client_callback_t cb,
860+ void *data);
861+ gboolean (*cancel_request)(ofono_dns_client_request_t request);
862+};
863+
864+
865+/*
866+ * Initiate an asynchronous name resolution request for |hostname|.
867+ * |device| specifies the interface out which the request should be sent, or
868+ * NULL to use the default interface.
869+ * |servers| string array with name servers to query or NULL to use system
870+ * defaults
871+ * |timeout_ms| specifies a max timeout in milliseconds, or 0 to use the default
872+ * timeout (which depends on the plugin).
873+ * Returns an opaque handle identifying the request on success and NULL on
874+ * failure. Success indicates only that the request was initiated, not that the
875+ * request itself was successful.
876+ * When the request is complete, the callback |cb| will be invoked with |data|
877+ * passed as an arg.
878+ */
879+ofono_dns_client_request_t __ofono_dns_client_submit_request(
880+ const char *hostname,
881+ const char *device,
882+ const char **servers,
883+ int timeout_ms,
884+ ofono_dns_client_callback_t cb,
885+ void *data);
886+
887+/*
888+ * Cancel the request identified by |request|. Does not invoke the callback for
889+ * the cancelled request.
890+ */
891+void __ofono_dns_client_cancel_request(ofono_dns_client_request_t request);
892+
893+/*
894+ * Returns a human-friendly error string corresponding to |status|.
895+ */
896+const char *__ofono_dns_client_strerror(ofono_dns_client_status_t status);
897+
898+int ofono_dns_client_driver_register(struct ofono_dns_client_driver *driver);
899+void ofono_dns_client_driver_unregister(
900+ const struct ofono_dns_client_driver *driver);
901+
902+#endif /* OFONO_DNS_CLIENT_H */
903
904=== modified file 'include/radio-settings.h'
905--- include/radio-settings.h 2014-07-24 08:31:17 +0000
906+++ include/radio-settings.h 2015-07-02 17:01:42 +0000
907@@ -136,6 +136,9 @@
908 void ofono_radio_settings_set_data(struct ofono_radio_settings *rs, void *data);
909 void *ofono_radio_settings_get_data(struct ofono_radio_settings *rs);
910
911+void ofono_radio_settings_set_rat_mode(struct ofono_radio_settings *rs,
912+ enum ofono_radio_access_mode mode);
913+
914 #ifdef __cplusplus
915 }
916 #endif
917
918=== added file 'plugins/c-ares-dns-client.c'
919--- plugins/c-ares-dns-client.c 1970-01-01 00:00:00 +0000
920+++ plugins/c-ares-dns-client.c 2015-07-02 17:01:42 +0000
921@@ -0,0 +1,767 @@
922+/*
923+ *
924+ * DNS Client - provides an asynchronous DNS resolution client.
925+ *
926+ * The client is implemented using the c-ares library, and integrates with
927+ * glib's main event loop. It was originally written to be used by flimflam,
928+ * and it has been modified to integrate with ofono. See http://c-ares.haxx.se
929+ * and http://developer.gnome.org/glib for c-ares and glib documentation.
930+ *
931+ * This file originally created by Google, Inc.
932+ * Copyright (c) 2011 The Chromium OS Authors. All rights reserved.
933+ * Copyright (c) 2015 Canonical Ltd.
934+ *
935+ * This program is free software; you can redistribute it and/or modify
936+ * it under the terms of the GNU General Public License version 2 as
937+ * published by the Free Software Foundation.
938+ *
939+ * This program is distributed in the hope that it will be useful,
940+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
941+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
942+ * GNU General Public License for more details.
943+ *
944+ * You should have received a copy of the GNU General Public License
945+ * along with this program; if not, write to the Free Software
946+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
947+ *
948+ */
949+
950+#ifdef HAVE_CONFIG_H
951+#include <config.h>
952+#endif
953+
954+#include <stdio.h>
955+#include <string.h>
956+#include <errno.h>
957+
958+#include <unistd.h>
959+#include <fcntl.h>
960+#include <sys/socket.h>
961+#include <netinet/in.h>
962+#include <arpa/inet.h>
963+#include <netdb.h>
964+#include <sys/time.h>
965+
966+#include <ares.h>
967+#include <glib.h>
968+
969+#define OFONO_API_SUBJECT_TO_CHANGE
970+#include <ofono/types.h>
971+#include <ofono/log.h>
972+#include <ofono/plugin.h>
973+#include <ofono/modem.h>
974+#include <ofono/dns-client.h>
975+
976+/* Structure representing a pending asynchronous name resolution request. */
977+struct ares_request {
978+ char *hostname; /* hostname that we're resolving */
979+ char *interface; /* interface to use for queries */
980+ struct ares_addr_node *servers;
981+ struct timeval timeout; /* caller-specified timeout */
982+ struct timeval start_time; /* time at which request was started */
983+ ofono_dns_client_callback_t cb; /* client-provided callback */
984+ void *data; /* user data */
985+ ares_channel channel; /* opaque, used by c-ares library */
986+ GHashTable *ares_watches; /* fds that we're monitoring for c-ares */
987+ guint timeout_source_id; /* glib source id for our ares timeout */
988+ gboolean running; /* stopped requests are eligible for deletion */
989+};
990+
991+/*
992+ * Structure representing a file descriptor that we're monitoring within our
993+ * glib event loop for c-ares.
994+ */
995+struct ares_watch {
996+ struct ares_request *request; /* backpointer to our owner */
997+ int fd; /* file descriptor that we're watching */
998+ GIOChannel *gio_channel; /* glib IO channel */
999+ GIOCondition gio_condition; /* events in which we're interested */
1000+ guint g_source_id; /* glib source id */
1001+};
1002+
1003+/*
1004+ * List of pending asynchronous name resolution requests. We expect the number
1005+ * of pending requests to be small, hence the use of a linked list.
1006+ */
1007+static GList *pending_requests = NULL;
1008+
1009+/*
1010+ * ares requests are often stopped from within ares callbacks. In these cases,
1011+ * we defer deletion of the ares_request struct to the idle loop. This is the
1012+ * glib source id associated with the deferred deletion task.
1013+ */
1014+static guint deferred_deletion_g_source_id = 0;
1015+
1016+static void reset_ares_timeout(struct ares_request *request,
1017+ gboolean destroy_old_source);
1018+static void stop_ares_request(struct ares_request *request);
1019+
1020+/*#define USE_RP_FILTER*/
1021+
1022+/*
1023+ * Set/unset reverse path filtering (from connman). Using this should make
1024+ * setting routes for the DNS servers unnecessary, but unfortunately that is not
1025+ * happening.
1026+ * TODO Investigate why this is not working.
1027+ */
1028+#ifdef USE_RP_FILTER
1029+static void rp_filter_set(const char *interface, gboolean enabled)
1030+{
1031+ int fd;
1032+ ssize_t cnt;
1033+ char filename[PATH_MAX];
1034+ const char *str_value = (enabled == TRUE) ? "1" : "0";
1035+
1036+ snprintf(filename, sizeof(filename),
1037+ "/proc/sys/net/ipv4/conf/%s/rp_filter", interface);
1038+ fd = open(filename, O_WRONLY);
1039+ if (fd == -1)
1040+ return;
1041+ cnt = write(fd, str_value, strlen(str_value));
1042+ if (cnt == -1)
1043+ ofono_error("%s: cannot write (%s)", __func__, strerror(errno));
1044+ close(fd);
1045+}
1046+#else
1047+static void rp_filter_set(const char *interface, gboolean enabled)
1048+{
1049+}
1050+#endif
1051+
1052+/*
1053+ * Callback invoked when it's time to give control back to c-ares. Controlled by
1054+ * the glib source referred to by |timeout_source_id| in struct ares_request.
1055+ */
1056+static gboolean ares_timeout_cb(gpointer data)
1057+{
1058+ struct ares_request *request = data;
1059+ const gboolean destroy_old_source = FALSE;
1060+
1061+ DBG("request %p: running = %d", request, request->running);
1062+
1063+ if (!request->running) {
1064+ request->timeout_source_id = 0;
1065+ return FALSE;
1066+ }
1067+
1068+ ares_process_fd(request->channel, ARES_SOCKET_BAD, ARES_SOCKET_BAD);
1069+
1070+ /*
1071+ * NOTE: We tell reset_ares_timeout not to destroy its old timer source
1072+ * because we're calling it from within that source and it will be
1073+ * destroyed by glib when we return FALSE below.
1074+ */
1075+ reset_ares_timeout(request, destroy_old_source);
1076+
1077+ /*
1078+ * Return FALSE to get rid of our old glib source. We created a new
1079+ * one during our call to reset_ares_timeout above.
1080+ */
1081+ return FALSE;
1082+}
1083+
1084+/*
1085+ * Determine how long c-ares is willing to wait until being given control and
1086+ * schedule ares_timeout_cb to be invoked at that time. Any existing
1087+ * timer is replaced. If |destroy_old_source| is TRUE, the old timer's glib
1088+ * source will be destroyed.
1089+ */
1090+static void reset_ares_timeout(struct ares_request *request,
1091+ gboolean destroy_old_source)
1092+{
1093+ struct timeval ret_tv, now, elapsed, max_tv;
1094+ struct timeval *tv;
1095+ struct timeval *max = NULL;
1096+ guint timeout_interval_msecs = 0;
1097+ gboolean timeout_provided = FALSE;
1098+
1099+ DBG("request %p: running = %d", request, request->running);
1100+
1101+ if (!request->running)
1102+ return;
1103+
1104+ /*
1105+ * Compute how much time has elapsed since the request started.
1106+ * If the client provided a non-default timeout and we've timed out,
1107+ * notify the client and stop the request.
1108+ */
1109+ gettimeofday(&now, NULL);
1110+ timersub(&now, &request->start_time, &elapsed);
1111+ timeout_provided = request->timeout.tv_sec != 0 ||
1112+ request->timeout.tv_usec != 0;
1113+ if (timeout_provided && timercmp(&elapsed, &request->timeout, >=)) {
1114+ request->cb(request->data, OFONO_DNS_CLIENT_ERROR_TIMED_OUT,
1115+ NULL);
1116+ stop_ares_request(request);
1117+ return;
1118+ }
1119+
1120+ /*
1121+ * Tell c-ares how long we're willing to wait (max) and see if it wants
1122+ * to regain control sooner than that.
1123+ */
1124+ if (timeout_provided) {
1125+ timersub(&request->timeout, &elapsed, &max_tv);
1126+ max = &max_tv;
1127+ }
1128+ if ((tv = ares_timeout(request->channel, max, &ret_tv)) == NULL) {
1129+ ofono_error("%s: ares_timeout failed", __func__);
1130+ return;
1131+ }
1132+
1133+ /*
1134+ * Reschedule our timeout to be the sooner of the ares-specified tiemout
1135+ * and the client-specified timeout.
1136+ */
1137+ if (request->timeout_source_id != 0 && destroy_old_source) {
1138+ if (!g_source_remove(request->timeout_source_id))
1139+ ofono_error("%s: g_source_remove failed", __func__);
1140+ }
1141+
1142+ timeout_interval_msecs = tv->tv_sec * 1000 + tv->tv_usec / 1000;
1143+ DBG("timeout interval = %u", timeout_interval_msecs);
1144+
1145+ request->timeout_source_id = g_timeout_add(timeout_interval_msecs,
1146+ ares_timeout_cb,
1147+ request);
1148+}
1149+
1150+/*
1151+ * Callback invoked by glib when there is activity on a file descriptor that
1152+ * we're monitoring for c-ares.
1153+ */
1154+static gboolean ares_watch_io_cb(GIOChannel *source,
1155+ GIOCondition condition,
1156+ gpointer data)
1157+{
1158+ struct ares_watch *watch = data;
1159+ ares_socket_t read_fd = ARES_SOCKET_BAD;
1160+ ares_socket_t write_fd = ARES_SOCKET_BAD;
1161+ const gboolean destroy_old_source = TRUE;
1162+
1163+ DBG("watch %p (fd %d): condition = 0x%x", watch, watch->fd,
1164+ condition);
1165+
1166+ if (!watch->request->running) {
1167+ /* Destroy this source by returning FALSE. */
1168+ watch->g_source_id = 0;
1169+ return FALSE;
1170+ }
1171+
1172+ if (condition & (G_IO_NVAL | G_IO_HUP | G_IO_ERR)) {
1173+ ofono_error("%s: error condition on fd %d", __func__,
1174+ watch->fd);
1175+ watch->g_source_id = 0;
1176+ return FALSE;
1177+ }
1178+
1179+ if (condition & G_IO_IN)
1180+ read_fd = watch->fd;
1181+ if (condition & G_IO_OUT)
1182+ write_fd = watch->fd;
1183+
1184+ /* Give control to c-ares. */
1185+ ares_process_fd(watch->request->channel, read_fd, write_fd);
1186+
1187+ reset_ares_timeout(watch->request, destroy_old_source);
1188+
1189+ return TRUE;
1190+}
1191+
1192+/*
1193+ * Destroy an ares_watch structure. We register this as our value destroy
1194+ * function when creating the ares_watches table, and it is called by glib
1195+ * whenever we remove a value from the table or destroy the table.
1196+ */
1197+static void destroy_ares_watch(gpointer data)
1198+{
1199+ struct ares_watch *watch = data;
1200+
1201+ DBG("watch %p (fd %d)", watch, watch->fd);
1202+
1203+ if (watch->g_source_id != 0) {
1204+ if (!g_source_remove(watch->g_source_id)) {
1205+ ofono_error("%s: g_source_remove failed for id %d",
1206+ __func__, watch->g_source_id);
1207+ }
1208+ watch->g_source_id = 0;
1209+ }
1210+
1211+ g_io_channel_unref(watch->gio_channel);
1212+ g_free(watch);
1213+}
1214+
1215+/*
1216+ * Create an ares_watch for |fd| and store it in the ares_watches table for
1217+ * |request|. Monitor for readability if |read| is TRUE. Monitor for writability
1218+ * if |write| is TRUE. If there is already an entry for |fd| in the table,
1219+ * update it according to the values of |read| and |write|.
1220+ */
1221+static gboolean init_ares_watch(struct ares_request *request, int fd,
1222+ gboolean read, gboolean write)
1223+{
1224+ struct ares_watch *watch;
1225+
1226+ DBG("fd = %d, read = %d, write = %d", fd, read, write);
1227+
1228+ /*
1229+ * If there's an old watch in the table, destroy it. We'll replace it
1230+ * with a new one below if c-ares is still interested in this fd.
1231+ */
1232+ if (g_hash_table_lookup(request->ares_watches, &fd) != NULL) {
1233+ /* This removal calls destroy_ares_watch on the old watch. */
1234+ g_hash_table_remove(request->ares_watches, &fd);
1235+ }
1236+
1237+ if (!read && !write)
1238+ return TRUE;
1239+
1240+ watch = g_malloc0(sizeof(struct ares_watch));
1241+
1242+ watch->request = request;
1243+ watch->fd = fd;
1244+ watch->g_source_id = 0;
1245+
1246+ watch->gio_condition = G_IO_NVAL | G_IO_HUP | G_IO_ERR;
1247+ if (read)
1248+ watch->gio_condition |= G_IO_IN;
1249+ if (write)
1250+ watch->gio_condition |= G_IO_OUT;
1251+
1252+ watch->gio_channel = g_io_channel_unix_new(fd);
1253+ if (watch->gio_channel == NULL) {
1254+ ofono_error("%s: could not create g_io_channel for fd %d",
1255+ __func__, fd);
1256+ g_free(watch);
1257+ return FALSE;
1258+ }
1259+ g_io_channel_set_close_on_unref(watch->gio_channel, FALSE);
1260+
1261+ g_hash_table_insert(request->ares_watches, &fd, watch);
1262+
1263+ watch->g_source_id = g_io_add_watch(watch->gio_channel,
1264+ watch->gio_condition,
1265+ ares_watch_io_cb,
1266+ watch);
1267+
1268+ return TRUE;
1269+}
1270+
1271+/*
1272+ * Destroy an ares_request struct, freeing the resources allocated in
1273+ * init_ares_request. |request| must already have been removed from the
1274+ * |pending_requests| list and must have been marked not running.
1275+ */
1276+static void destroy_ares_request(struct ares_request *request)
1277+{
1278+ struct ares_addr_node *node, *next;
1279+
1280+ DBG("request %p", request);
1281+
1282+ ares_destroy(request->channel);
1283+ g_free(request->hostname);
1284+ if (request->interface) {
1285+ rp_filter_set(request->interface, TRUE);
1286+ g_free(request->interface);
1287+ }
1288+ for (node = request->servers; node != NULL; node = next) {
1289+ next = node->next;
1290+ g_free(node);
1291+ }
1292+ if (request->timeout_source_id != 0)
1293+ g_source_remove(request->timeout_source_id);
1294+ /* Hash table destruction calls destroy_ares_watch on all watches. */
1295+ g_hash_table_destroy(request->ares_watches);
1296+ g_free(request);
1297+}
1298+
1299+/*
1300+ * Callback invoked from the main loop to perform deferred deletion of stopped
1301+ * ares_request objects. We do deferred deletion to avoid problems when we're in
1302+ * an ares callback and want to delete an object that contains context
1303+ * associated with that callback.
1304+ */
1305+static gboolean delete_stopped_ares_requests_cb(gpointer data)
1306+{
1307+ GList *node, *next;
1308+ struct ares_request *request;
1309+ guint num_requests_deleted = 0;
1310+
1311+ DBG("pending_requests list has length %u",
1312+ g_list_length(pending_requests));
1313+
1314+ /*
1315+ * Inspect each request in |pending_requests| and destroy it if it's
1316+ * not running.
1317+ */
1318+ for (node = pending_requests; node != NULL; node = next) {
1319+ next = g_list_next(node);
1320+ request = node->data;
1321+ if (!request->running) {
1322+ pending_requests = g_list_delete_link(pending_requests,
1323+ node);
1324+ destroy_ares_request(request);
1325+ ++num_requests_deleted;
1326+ }
1327+ }
1328+ DBG("deleted %u stopped requests", num_requests_deleted);
1329+
1330+ deferred_deletion_g_source_id = 0;
1331+ return FALSE;
1332+}
1333+
1334+/*
1335+ * Stop an ares_request and schedule the deferred deletion task if it's
1336+ * not already running.
1337+ */
1338+static void stop_ares_request(struct ares_request *request)
1339+{
1340+ DBG("");
1341+
1342+ request->running = FALSE;
1343+
1344+ if (deferred_deletion_g_source_id != 0)
1345+ return;
1346+
1347+ deferred_deletion_g_source_id =
1348+ g_idle_add(delete_stopped_ares_requests_cb, NULL);
1349+ if (deferred_deletion_g_source_id == 0)
1350+ ofono_error("%s: g_idle_add failed", __func__);
1351+}
1352+
1353+/*
1354+ * Callback that is invoked by c-ares to tell us which sockets it wants us to
1355+ * monitor for readability and writability.
1356+ */
1357+static void ares_socket_state_cb(void *data, int s, int read, int write)
1358+{
1359+ struct ares_request *request = (struct ares_request *) data;
1360+
1361+ DBG("");
1362+
1363+ if (!request->running)
1364+ return;
1365+
1366+ DBG("socket %d: read = %d, write = %d", s, read, write);
1367+
1368+ if (!init_ares_watch(request, s, read, write))
1369+ ofono_error("%s: couldn't create ares_watch for socket %d",
1370+ __func__, s);
1371+}
1372+
1373+/*
1374+ * Converts a c-ares status code to the corresponding dns_client status code.
1375+ * We do this to completely encapsulate c-ares. In theory, we should be able to
1376+ * replace it with a different asynchronous DNS library without changing our
1377+ * clients.
1378+ */
1379+static ofono_dns_client_status_t status_from_ares_status(int ares_status)
1380+{
1381+ switch(ares_status) {
1382+ case ARES_SUCCESS:
1383+ return OFONO_DNS_CLIENT_SUCCESS;
1384+ case ARES_ENODATA:
1385+ return OFONO_DNS_CLIENT_ERROR_NO_DATA;
1386+ case ARES_EFORMERR:
1387+ return OFONO_DNS_CLIENT_ERROR_FORM_ERR;
1388+ case ARES_ESERVFAIL:
1389+ return OFONO_DNS_CLIENT_ERROR_SERVER_FAIL;
1390+ case ARES_ENOTFOUND:
1391+ return OFONO_DNS_CLIENT_ERROR_NOT_FOUND;
1392+ case ARES_ENOTIMP:
1393+ return OFONO_DNS_CLIENT_ERROR_NOT_IMP;
1394+ case ARES_EREFUSED:
1395+ return OFONO_DNS_CLIENT_ERROR_REFUSED;
1396+ case ARES_EBADQUERY:
1397+ case ARES_EBADNAME:
1398+ case ARES_EBADFAMILY:
1399+ case ARES_EBADRESP:
1400+ return OFONO_DNS_CLIENT_ERROR_BAD_QUERY;
1401+ case ARES_ECONNREFUSED:
1402+ return OFONO_DNS_CLIENT_ERROR_NET_REFUSED;
1403+ case ARES_ETIMEOUT:
1404+ return OFONO_DNS_CLIENT_ERROR_TIMED_OUT;
1405+ default:
1406+ return OFONO_DNS_CLIENT_ERROR_UNKNOWN;
1407+ }
1408+}
1409+
1410+/*
1411+ * Callback that is invoked by c-ares when an asynchronous name resolution
1412+ * request that we have previously initiated is complete.
1413+ */
1414+static void ares_request_cb(void *arg, int ares_status, int timeouts,
1415+ struct hostent *hostent)
1416+{
1417+ struct sockaddr_in sin;
1418+ struct sockaddr_in6 sin6;
1419+ int addr_length;
1420+ void *addr_buffer;
1421+ char ip_addr_string[INET6_ADDRSTRLEN];
1422+ struct sockaddr *ip_addr;
1423+ struct ares_request *request = (struct ares_request *)arg;
1424+
1425+ DBG("");
1426+
1427+ if (!request->running)
1428+ return;
1429+
1430+ /* Stop the request. It will be deleted later from the idle loop. */
1431+ stop_ares_request(request);
1432+
1433+ if (ares_status != ARES_SUCCESS) {
1434+ DBG("ares request for '%s' failed: %s",
1435+ request->hostname, ares_strerror(ares_status));
1436+ /* Notify client. */
1437+ request->cb(request->data, status_from_ares_status(ares_status),
1438+ NULL);
1439+ return;
1440+ }
1441+
1442+ if (hostent->h_addrtype != AF_INET && hostent->h_addrtype != AF_INET6) {
1443+ ofono_error("%s: unsupported addrtype: %d",
1444+ __func__, hostent->h_addrtype);
1445+ request->cb(request->data, OFONO_DNS_CLIENT_ERROR_NO_DATA,
1446+ NULL);
1447+ return;
1448+ }
1449+
1450+ if (hostent->h_addrtype == AF_INET) {
1451+ memset(&sin, 0, sizeof(sin));
1452+ sin.sin_family = AF_INET;
1453+ addr_length = sizeof(sin.sin_addr.s_addr);
1454+ addr_buffer = &sin.sin_addr.s_addr;
1455+ ip_addr = (struct sockaddr *) &sin;
1456+ } else { /* AF_INET6 */
1457+ memset(&sin6, 0, sizeof(sin6));
1458+ sin6.sin6_family = AF_INET6;
1459+ addr_length = sizeof(sin6.sin6_addr.s6_addr);
1460+ addr_buffer = &sin6.sin6_addr.s6_addr;
1461+ ip_addr = (struct sockaddr *) &sin6;
1462+ }
1463+
1464+ if (hostent->h_length > addr_length) {
1465+ ofono_error("%s: address too large: %u bytes",
1466+ __func__, hostent->h_length);
1467+ request->cb(request->data, OFONO_DNS_CLIENT_ERROR_NO_DATA,
1468+ NULL);
1469+ return;
1470+ }
1471+
1472+ memcpy(addr_buffer, hostent->h_addr, hostent->h_length);
1473+
1474+ if (inet_ntop(hostent->h_addrtype, addr_buffer, ip_addr_string,
1475+ sizeof(ip_addr_string)) == NULL) {
1476+ ofono_error("%s: could not convert address to string: %s",
1477+ __func__, strerror(errno));
1478+ request->cb(request->data, OFONO_DNS_CLIENT_ERROR_NO_DATA,
1479+ NULL);
1480+ return;
1481+ }
1482+
1483+ DBG("ares request for '%s' succeeded with %d timeouts: %s",
1484+ request->hostname, timeouts, ip_addr_string);
1485+ request->cb(request->data, status_from_ares_status(ares_status),
1486+ ip_addr);
1487+}
1488+
1489+/* Cancel all in-progress asynchronous name resolution requests. */
1490+static void cancel_all_ares_requests()
1491+{
1492+ GList *node;
1493+ struct ares_request *request;
1494+
1495+ DBG("");
1496+
1497+ while ((node = g_list_first(pending_requests)) != NULL) {
1498+ request = node->data;
1499+ pending_requests = g_list_delete_link(pending_requests, node);
1500+ request->running = FALSE; /* don't trip assertion */
1501+ destroy_ares_request(request);
1502+ }
1503+}
1504+
1505+static void set_request_servers(const char **servers,
1506+ struct ares_request *request)
1507+{
1508+ struct ares_addr_node *current;
1509+ struct ares_addr_node **prev = &request->servers;
1510+ const char **dns;
1511+ int rc;
1512+
1513+ for (dns = servers; *dns != NULL; ++dns) {
1514+ current = g_malloc0(sizeof(*current));
1515+ rc = inet_pton(AF_INET, *dns, &current->addr.addr4);
1516+ if (rc == 1) {
1517+ current->family = AF_INET;
1518+ } else {
1519+ rc = inet_pton(AF_INET6, *dns, &current->addr.addr6);
1520+ if (rc != 1) {
1521+ ofono_error("%s: wrong dns address %s",
1522+ __func__, *dns);
1523+ g_free(current);
1524+ continue;
1525+ }
1526+ current->family = AF_INET6;
1527+ }
1528+
1529+ *prev = current;
1530+ prev = &current->next;
1531+ }
1532+}
1533+
1534+/* Initiate an asynchronous name resolution request. */
1535+static ofono_dns_client_request_t
1536+ofono_dns_client_submit_request(const char *hostname,
1537+ const char *interface,
1538+ const char **servers,
1539+ int timeout_ms,
1540+ ofono_dns_client_callback_t cb,
1541+ void *data)
1542+{
1543+ int ares_status;
1544+ struct ares_request *request;
1545+ struct ares_options options;
1546+ int optmask;
1547+ const gboolean destroy_old_source = TRUE;
1548+
1549+ DBG("");
1550+
1551+ if (timeout_ms < 0) {
1552+ DBG("invalid timeout value of %d ms", timeout_ms);
1553+ return NULL;
1554+ }
1555+
1556+ request = g_malloc0(sizeof(struct ares_request));
1557+ request->running = TRUE;
1558+
1559+ request->ares_watches = g_hash_table_new_full(g_int_hash, g_int_equal,
1560+ NULL, destroy_ares_watch);
1561+ if (request->ares_watches == NULL) {
1562+ ofono_error("%s: could not create ares_watches table",
1563+ __func__);
1564+ g_free(request);
1565+ return NULL;
1566+ }
1567+
1568+ /*
1569+ * Init a c-ares channel for this request. We set an option asking
1570+ * c-ares to notify us via callback about which sockets it wants to
1571+ * monitor for readability and writability. This allows us to
1572+ * integrate c-ares activity into our glib main event loop.
1573+ */
1574+ memset(&options, 0, sizeof(options));
1575+ options.sock_state_cb = ares_socket_state_cb;
1576+ options.sock_state_cb_data = request;
1577+ optmask = ARES_OPT_SOCK_STATE_CB;
1578+ if (timeout_ms > 0) {
1579+ options.timeout = timeout_ms;
1580+ optmask |= ARES_OPT_TIMEOUTMS;
1581+ }
1582+ ares_status = ares_init_options(&request->channel, &options, optmask);
1583+ if (ares_status != ARES_SUCCESS) {
1584+ ofono_error("%s: failed to init c-ares channel: %s", __func__,
1585+ ares_strerror(ares_status));
1586+ request->running = FALSE; /* don't trip assertion */
1587+ g_hash_table_destroy(request->ares_watches);
1588+ g_free(request);
1589+ return NULL;
1590+ }
1591+
1592+ if (servers != NULL) {
1593+ set_request_servers(servers, request);
1594+ ares_status =
1595+ ares_set_servers(request->channel, request->servers);
1596+ /* Log an error, but continue anyway */
1597+ if (ares_status != ARES_SUCCESS)
1598+ ofono_error("%s: failed to set name servers: %s",
1599+ __func__, ares_strerror(ares_status));
1600+ }
1601+
1602+ /*
1603+ * If the caller has provided a preferred interface, tell c-ares to
1604+ * send requests out that interface, and unset rf filter.
1605+ */
1606+ if (interface != NULL) {
1607+ DBG("caller has specified device %s", interface);
1608+
1609+ request->interface = g_strdup(interface);
1610+ ares_set_local_dev(request->channel, request->interface);
1611+ rp_filter_set(request->interface, FALSE);
1612+ }
1613+
1614+ request->cb = cb;
1615+ request->data = data;
1616+ request->hostname = g_strdup(hostname);
1617+ request->timeout.tv_sec = timeout_ms / 1000;
1618+ request->timeout.tv_usec = (timeout_ms % 1000) * 1000;
1619+ gettimeofday(&request->start_time, NULL);
1620+
1621+ pending_requests = g_list_append(pending_requests, request);
1622+
1623+ ares_gethostbyname(request->channel, hostname, AF_INET,
1624+ ares_request_cb, request);
1625+
1626+ reset_ares_timeout(request, destroy_old_source);
1627+
1628+ return request;
1629+}
1630+
1631+/* Cancel an in-progress name resolution request. */
1632+static gboolean ofono_dns_client_cancel_request(ofono_dns_client_request_t req)
1633+{
1634+ struct ares_request *request = req;
1635+
1636+ if (request == NULL || g_list_find (pending_requests, request) == NULL)
1637+ return FALSE;
1638+
1639+ DBG("request %p", request);
1640+
1641+ if (!request->running)
1642+ return TRUE;
1643+
1644+ pending_requests = g_list_remove(pending_requests, request);
1645+ request->running = FALSE; /* don't trip assertion */
1646+ destroy_ares_request(request);
1647+
1648+ return TRUE;
1649+}
1650+
1651+static struct ofono_dns_client_driver dns_driver = {
1652+ .name = "c-ares DNS client",
1653+ .submit_request = ofono_dns_client_submit_request,
1654+ .cancel_request = ofono_dns_client_cancel_request
1655+};
1656+
1657+/* Intitialize this module. */
1658+static int c_ares_init(void)
1659+{
1660+ int ares_status = 0;
1661+ DBG("");
1662+ ares_status = ares_library_init(ARES_LIB_INIT_ALL);
1663+ if (ares_status != ARES_SUCCESS) {
1664+ ofono_error("%s: Failed to init c-ares: %s", __func__,
1665+ ares_strerror(ares_status));
1666+ return -1;
1667+ }
1668+ return ofono_dns_client_driver_register(&dns_driver);
1669+}
1670+
1671+/* Clean up. */
1672+static void c_ares_exit(void)
1673+{
1674+ DBG("");
1675+
1676+ ofono_dns_client_driver_unregister(&dns_driver);
1677+
1678+ if (deferred_deletion_g_source_id != 0) {
1679+ g_source_remove(deferred_deletion_g_source_id);
1680+ deferred_deletion_g_source_id = 0;
1681+ }
1682+ cancel_all_ares_requests();
1683+ ares_library_cleanup();
1684+}
1685+
1686+OFONO_PLUGIN_DEFINE(c_ares_dns_client, "c-ares DNS client", VERSION,
1687+ OFONO_PLUGIN_PRIORITY_DEFAULT,
1688+ c_ares_init, c_ares_exit)
1689
1690=== modified file 'plugins/mtk.c'
1691--- plugins/mtk.c 2015-04-01 07:04:18 +0000
1692+++ plugins/mtk.c 2015-07-02 17:01:42 +0000
1693@@ -830,9 +830,9 @@
1694 struct ofono_gprs_context *gc;
1695 struct ril_gprs_driver_data gprs_data = { md->ril, modem };
1696 struct ril_gprs_context_data inet_ctx =
1697- { md->ril, OFONO_GPRS_CONTEXT_TYPE_INTERNET };
1698+ { md->ril, modem, OFONO_GPRS_CONTEXT_TYPE_INTERNET };
1699 struct ril_gprs_context_data mms_ctx =
1700- { md->ril, OFONO_GPRS_CONTEXT_TYPE_MMS };
1701+ { md->ril, modem, OFONO_GPRS_CONTEXT_TYPE_MMS };
1702
1703 DBG("SIM ready, creating more atoms");
1704
1705@@ -1347,6 +1347,16 @@
1706 mtk_set_online(mtk_data_1->modem, FALSE, set_offline_cb, NULL);
1707 }
1708
1709+void mtk_reset_modem(struct ofono_modem *modem)
1710+{
1711+
1712+ if (ofono_modem_get_powered(modem) == FALSE)
1713+ return;
1714+
1715+ ofono_modem_set_powered(modem, FALSE);
1716+ g_idle_add(mtk_connected, modem);
1717+}
1718+
1719 static void create_atoms_on_connection(struct ofono_modem *modem)
1720 {
1721 struct mtk_data *md = ofono_modem_get_data(modem);
1722
1723=== modified file 'plugins/ril.c'
1724--- plugins/ril.c 2015-02-04 00:09:22 +0000
1725+++ plugins/ril.c 2015-07-02 17:01:42 +0000
1726@@ -63,6 +63,7 @@
1727 #include "ril.h"
1728 #include "drivers/rilmodem/rilmodem.h"
1729 #include "drivers/rilmodem/vendor.h"
1730+#include "drivers/qcommsimmodem/qcom_msim_modem.h"
1731
1732 #define MAX_SIM_STATUS_RETRIES 15
1733
1734@@ -70,7 +71,8 @@
1735 #define RILD_MAX_CONNECT_RETRIES 5
1736 #define RILD_CONNECT_RETRY_TIME_S 5
1737
1738-#define RILD_CMD_SOCKET "/dev/socket/rild"
1739+char *RILD_CMD_SOCKET[] = {"/dev/socket/rild", "/dev/socket/rild1"};
1740+char *GRIL_HEX_PREFIX[] = {"Device 0: ", "Device 1: "};
1741
1742 struct ril_data {
1743 GRil *ril;
1744@@ -111,11 +113,19 @@
1745 case RADIO_STATE_ON:
1746
1747 if (rd->radio_settings == NULL) {
1748+ char *rs_driver;
1749 struct ril_radio_settings_driver_data rs_data =
1750 { rd->ril, modem };
1751+
1752+ if (rd->vendor == OFONO_RIL_VENDOR_QCOM_MSIM)
1753+ rs_driver = QCOMMSIMMODEM;
1754+ else
1755+ rs_driver = RILMODEM;
1756+
1757 rd->radio_settings =
1758 ofono_radio_settings_create(modem,
1759- rd->vendor, RILMODEM, &rs_data);
1760+ rd->vendor, rs_driver,
1761+ &rs_data);
1762 }
1763
1764 break;
1765@@ -215,9 +225,9 @@
1766 struct ofono_message_waiting *mw;
1767 struct ril_gprs_driver_data gprs_data = { rd->ril, modem };
1768 struct ril_gprs_context_data inet_ctx =
1769- { rd->ril, OFONO_GPRS_CONTEXT_TYPE_INTERNET };
1770+ { rd->ril, modem, OFONO_GPRS_CONTEXT_TYPE_INTERNET };
1771 struct ril_gprs_context_data mms_ctx =
1772- { rd->ril, OFONO_GPRS_CONTEXT_TYPE_MMS };
1773+ { rd->ril, modem, OFONO_GPRS_CONTEXT_TYPE_MMS };
1774
1775 /* TODO: this function should setup:
1776 * - phonebook
1777@@ -337,8 +347,11 @@
1778 static int create_gril(struct ofono_modem *modem)
1779 {
1780 struct ril_data *rd = ofono_modem_get_data(modem);
1781+ int slot_id = ofono_modem_get_integer(modem, "Slot");
1782
1783- rd->ril = g_ril_new(RILD_CMD_SOCKET, OFONO_RIL_VENDOR_AOSP);
1784+ ofono_info("Using %s as socket for slot %d.",
1785+ RILD_CMD_SOCKET[slot_id], slot_id);
1786+ rd->ril = g_ril_new(RILD_CMD_SOCKET[slot_id], OFONO_RIL_VENDOR_AOSP);
1787
1788 /* NOTE: Since AT modems open a tty, and then call
1789 * g_at_chat_new(), they're able to return -EIO if
1790@@ -352,12 +365,13 @@
1791 ofono_error("g_ril_new() failed to create modem!");
1792 return -EIO;
1793 }
1794+ g_ril_set_slot(rd->ril, slot_id);
1795
1796 if (getenv("OFONO_RIL_TRACE"))
1797 g_ril_set_trace(rd->ril, TRUE);
1798
1799 if (getenv("OFONO_RIL_HEX_TRACE"))
1800- g_ril_set_debugf(rd->ril, ril_debug, "Device: ");
1801+ g_ril_set_debugf(rd->ril, ril_debug, GRIL_HEX_PREFIX[slot_id]);
1802
1803 g_ril_register(rd->ril, RIL_UNSOL_RIL_CONNECTED,
1804 ril_connected, modem);
1805
1806=== added file 'src/dns-client.c'
1807--- src/dns-client.c 1970-01-01 00:00:00 +0000
1808+++ src/dns-client.c 2015-07-02 17:01:42 +0000
1809@@ -0,0 +1,128 @@
1810+/*
1811+ *
1812+ * oFono - Open Source Telephony
1813+ *
1814+ * Copyright (c) 2011 The Chromium OS Authors. All rights reserved.
1815+ * Copyright (C) 2015 Canonical Ltd.
1816+ *
1817+ * This program is free software; you can redistribute it and/or modify
1818+ * it under the terms of the GNU General Public License version 2 as
1819+ * published by the Free Software Foundation.
1820+ *
1821+ * This program is distributed in the hope that it will be useful,
1822+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
1823+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1824+ * GNU General Public License for more details.
1825+ *
1826+ * You should have received a copy of the GNU General Public License
1827+ * along with this program; if not, write to the Free Software
1828+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1829+ *
1830+ */
1831+
1832+#ifdef HAVE_CONFIG_H
1833+#include <config.h>
1834+#endif
1835+
1836+#include <errno.h>
1837+#include <string.h>
1838+#include <glib.h>
1839+#include "ofono.h"
1840+#include "dns-client.h"
1841+
1842+static GSList *g_drivers = NULL;
1843+
1844+ofono_dns_client_request_t __ofono_dns_client_submit_request(
1845+ const char *hostname,
1846+ const char *device,
1847+ const char **servers,
1848+ int timeout_ms,
1849+ ofono_dns_client_callback_t cb,
1850+ void *data)
1851+{
1852+ GSList *d;
1853+ ofono_dns_client_request_t token = NULL;
1854+
1855+ for (d = g_drivers; d != NULL; d = d->next) {
1856+ const struct ofono_dns_client_driver *driver = d->data;
1857+
1858+ if (driver->submit_request == NULL)
1859+ continue;
1860+
1861+ DBG("Calling dns client plugin '%s'", driver->name);
1862+
1863+ if ((token = driver->submit_request(hostname, device, servers,
1864+ timeout_ms, cb, data)) == NULL)
1865+ continue;
1866+
1867+ return token;
1868+ }
1869+
1870+ return token;
1871+}
1872+
1873+void __ofono_dns_client_cancel_request(ofono_dns_client_request_t request)
1874+{
1875+ GSList *d;
1876+
1877+ for (d = g_drivers; d != NULL; d = d->next) {
1878+ const struct ofono_dns_client_driver *driver = d->data;
1879+
1880+ if (driver->cancel_request == NULL)
1881+ continue;
1882+
1883+ /* Returns TRUE if this driver is the request owner */
1884+ if (driver->cancel_request(request))
1885+ break;
1886+ }
1887+}
1888+
1889+/*
1890+ * Returns a human-friendly error string corresponding to |status|.
1891+ * The strings that we return are intentionally consistent with shill error
1892+ * messages.
1893+ */
1894+const char *__ofono_dns_client_strerror(ofono_dns_client_status_t status)
1895+{
1896+ switch(status) {
1897+ case OFONO_DNS_CLIENT_SUCCESS:
1898+ return "The query was successful.";
1899+ case OFONO_DNS_CLIENT_ERROR_NO_DATA:
1900+ return "The query response contains no answers.";
1901+ case OFONO_DNS_CLIENT_ERROR_FORM_ERR:
1902+ return "The server says the query is bad.";
1903+ case OFONO_DNS_CLIENT_ERROR_SERVER_FAIL:
1904+ return "The server says it had a failure.";
1905+ case OFONO_DNS_CLIENT_ERROR_NOT_FOUND:
1906+ return "The queried-for domain was not found.";
1907+ case OFONO_DNS_CLIENT_ERROR_NOT_IMP:
1908+ return "The server doesn't implement operation.";
1909+ case OFONO_DNS_CLIENT_ERROR_REFUSED:
1910+ return "The server replied, refused the query.";
1911+ case OFONO_DNS_CLIENT_ERROR_BAD_QUERY:
1912+ return "Locally we could not format a query.";
1913+ case OFONO_DNS_CLIENT_ERROR_NET_REFUSED:
1914+ return "The network connection was refused.";
1915+ case OFONO_DNS_CLIENT_ERROR_TIMED_OUT:
1916+ return "The network connection was timed out.";
1917+ case OFONO_DNS_CLIENT_ERROR_UNKNOWN:
1918+ default:
1919+ return "DNS Resolver unknown internal error.";
1920+ }
1921+}
1922+
1923+int ofono_dns_client_driver_register(struct ofono_dns_client_driver *driver)
1924+{
1925+ DBG("driver: %p name: %s", driver, driver->name);
1926+
1927+ g_drivers = g_slist_prepend(g_drivers, driver);
1928+ return 0;
1929+}
1930+
1931+void ofono_dns_client_driver_unregister(
1932+ const struct ofono_dns_client_driver *driver)
1933+{
1934+ DBG("driver: %p name: %s", driver, driver->name);
1935+
1936+ g_drivers = g_slist_remove(g_drivers, driver);
1937+}
1938
1939=== modified file 'src/gprs.c'
1940--- src/gprs.c 2015-05-20 16:32:09 +0000
1941+++ src/gprs.c 2015-07-02 17:01:42 +0000
1942@@ -35,6 +35,8 @@
1943 #include <net/route.h>
1944 #include <netinet/in.h>
1945 #include <arpa/inet.h>
1946+#include <resolv.h>
1947+#include <netdb.h>
1948
1949 #include <glib.h>
1950 #include <gdbus.h>
1951@@ -46,6 +48,7 @@
1952 #include "idmap.h"
1953 #include "simutil.h"
1954 #include "util.h"
1955+#include "dns-client.h"
1956
1957 #define GPRS_FLAG_ATTACHING 0x1
1958 #define GPRS_FLAG_RECHECK 0x2
1959@@ -58,6 +61,7 @@
1960 #define MAX_MESSAGE_CENTER_LENGTH 255
1961 #define MAX_CONTEXTS 256
1962 #define SUSPEND_TIMEOUT 8
1963+#define DNS_LOOKUP_TOUT_MS 15000
1964
1965 struct ofono_gprs {
1966 GSList *contexts;
1967@@ -97,6 +101,7 @@
1968 char *gateway;
1969 char **dns;
1970 char *proxy;
1971+ uint16_t proxy_port;
1972 };
1973
1974 struct ipv6_settings {
1975@@ -138,6 +143,7 @@
1976 struct ofono_gprs_primary_context context;
1977 struct ofono_gprs_context *context_driver;
1978 struct ofono_gprs *gprs;
1979+ ofono_dns_client_request_t lookup_req;
1980 };
1981
1982 static void gprs_netreg_update(struct ofono_gprs *gprs);
1983@@ -377,11 +383,11 @@
1984 ofono_dbus_dict_append(&array, "Interface",
1985 DBUS_TYPE_STRING, &settings->interface);
1986
1987- /* If we have a Proxy, no other settings are relevant */
1988 if (settings->ipv4->proxy) {
1989 ofono_dbus_dict_append(&array, "Proxy", DBUS_TYPE_STRING,
1990 &settings->ipv4->proxy);
1991- goto done;
1992+ ofono_dbus_dict_append(&array, "ProxyPort", DBUS_TYPE_UINT16,
1993+ &settings->ipv4->proxy_port);
1994 }
1995
1996 if (settings->ipv4->static_ip == TRUE)
1997@@ -536,9 +542,183 @@
1998 context_settings_append_ipv6);
1999 }
2000
2001-static void pri_parse_proxy(struct pri_context *ctx, const char *proxy)
2002-{
2003- char *scheme, *host, *port, *path;
2004+static void set_route(const struct context_settings *settings,
2005+ const char *ipstr, gboolean create)
2006+{
2007+ struct rtentry rt;
2008+ struct sockaddr_in addr;
2009+ int sk;
2010+ const char *debug_str = create ? "create" : "remove";
2011+
2012+ /* TODO Handle IPv6 case */
2013+
2014+ DBG("%s for %s", ipstr, debug_str);
2015+
2016+ if (settings->interface == NULL)
2017+ return;
2018+
2019+ sk = socket(PF_INET, SOCK_DGRAM, 0);
2020+ if (sk < 0)
2021+ return;
2022+
2023+ memset(&rt, 0, sizeof(rt));
2024+ rt.rt_dev = (char *) settings->interface;
2025+ rt.rt_flags = RTF_HOST;
2026+
2027+ if (create)
2028+ rt.rt_flags |= RTF_UP;
2029+
2030+ memset(&addr, 0, sizeof(addr));
2031+ addr.sin_family = AF_INET;
2032+ addr.sin_addr.s_addr = inet_addr(ipstr);
2033+ if (addr.sin_addr.s_addr == INADDR_NONE) {
2034+ ofono_error("Cannot %s route for invalid IP %s",
2035+ debug_str, ipstr);
2036+ return;
2037+ }
2038+ memcpy(&rt.rt_dst, &addr, sizeof(rt.rt_dst));
2039+
2040+ memset(&addr, 0, sizeof(addr));
2041+ addr.sin_family = AF_INET;
2042+ addr.sin_addr.s_addr = INADDR_ANY;
2043+ memcpy(&rt.rt_gateway, &addr, sizeof(rt.rt_gateway));
2044+ memcpy(&rt.rt_genmask, &addr, sizeof(rt.rt_genmask));
2045+
2046+ if (ioctl(sk, create ? SIOCADDRT : SIOCDELRT, &rt) < 0)
2047+ ofono_error("Failed to %s proxy host route: %s (%d)",
2048+ debug_str, strerror(errno), errno);
2049+
2050+ close(sk);
2051+}
2052+
2053+static void pri_activate_finish(struct pri_context *ctx)
2054+{
2055+ struct ofono_gprs_context *gc = ctx->context_driver;
2056+ struct context_settings *settings = gc->settings;
2057+ DBusConnection *conn = ofono_dbus_get_connection();
2058+ dbus_bool_t value;
2059+
2060+ DBG("proxy %s port %u", ctx->proxy_host ? ctx->proxy_host : "NULL",
2061+ ctx->proxy_port);
2062+
2063+ if (ctx->proxy_host) {
2064+ settings->ipv4->proxy = g_strdup(ctx->proxy_host);
2065+ settings->ipv4->proxy_port = ctx->proxy_port;
2066+
2067+ if (ctx->type == OFONO_GPRS_CONTEXT_TYPE_MMS)
2068+ set_route(settings, ctx->proxy_host, TRUE);
2069+ }
2070+
2071+ ctx->active = TRUE;
2072+ __ofono_dbus_pending_reply(&ctx->pending,
2073+ dbus_message_new_method_return(ctx->pending));
2074+
2075+ if (gc->settings->interface != NULL)
2076+ pri_context_signal_settings(ctx, settings->ipv4 != NULL,
2077+ settings->ipv6 != NULL);
2078+
2079+ value = ctx->active;
2080+ ofono_dbus_signal_property_changed(conn, ctx->path,
2081+ OFONO_CONNECTION_CONTEXT_INTERFACE,
2082+ "Active", DBUS_TYPE_BOOLEAN, &value);
2083+}
2084+
2085+static void clean_dns_routes(struct pri_context *ctx)
2086+{
2087+ struct context_settings *settings = ctx->context_driver->settings;
2088+ int i;
2089+
2090+ for (i = 0; settings->ipv4->dns[i] != NULL; ++i)
2091+ set_route(settings, settings->ipv4->dns[i], FALSE);
2092+}
2093+
2094+static void lookup_address_cb(void *data, ofono_dns_client_status_t status,
2095+ struct sockaddr *ip_addr)
2096+{
2097+ struct pri_context *ctx = data;
2098+ char str[INET_ADDRSTRLEN];
2099+
2100+ if (status == OFONO_DNS_CLIENT_SUCCESS) {
2101+ void *addr;
2102+
2103+ if (ip_addr->sa_family == AF_INET) {
2104+ struct sockaddr_in *ip4 = (void *) ip_addr;
2105+ addr = &ip4->sin_addr;
2106+ } else {
2107+ /* Assume ipv6 */
2108+ struct sockaddr_in6 *ip6 = (void *) ip_addr;
2109+ addr = &ip6->sin6_addr;
2110+ }
2111+
2112+ if (inet_ntop(ip_addr->sa_family, addr, str, sizeof(str)))
2113+ ctx->proxy_host = g_strdup(str);
2114+ else
2115+ ofono_error("%s: Cannot convert type %d to address",
2116+ __func__, ip_addr->sa_family);
2117+ } else {
2118+ ofono_error("DNS error %s",
2119+ __ofono_dns_client_strerror(status));
2120+ }
2121+
2122+ ctx->lookup_req = NULL;
2123+
2124+ clean_dns_routes(ctx);
2125+ pri_activate_finish(ctx);
2126+}
2127+
2128+static void lookup_address(struct pri_context *ctx, const char *proxy)
2129+{
2130+ struct context_settings *settings = ctx->context_driver->settings;
2131+
2132+ DBG("hostname is %s", proxy);
2133+
2134+ ctx->lookup_req = __ofono_dns_client_submit_request(
2135+ proxy, settings->interface,
2136+ (const char **) settings->ipv4->dns,
2137+ DNS_LOOKUP_TOUT_MS,
2138+ lookup_address_cb, ctx);
2139+ if (ctx->lookup_req == NULL)
2140+ clean_dns_routes(ctx);
2141+}
2142+
2143+static void get_proxy_ip(struct pri_context *ctx, const char *host)
2144+{
2145+ struct context_settings *settings = ctx->context_driver->settings;
2146+ struct in_addr addr;
2147+ int i;
2148+
2149+ if (inet_pton(AF_INET, host, &addr) == 1) {
2150+ ctx->proxy_host = g_strdup(host);
2151+ return;
2152+ }
2153+
2154+ /* Not an IP -> use DNS if possible */
2155+
2156+ if (settings->ipv4 == NULL || settings->ipv4->dns == NULL ||
2157+ settings->ipv4->dns[0] == NULL) {
2158+ ofono_error("No DNS to find IP for MMS proxy/MMSC %s", host);
2159+ return;
2160+ }
2161+
2162+ for (i = 0; settings->ipv4->dns[i] != NULL; ++i)
2163+ set_route(settings, settings->ipv4->dns[i], TRUE);
2164+
2165+ lookup_address(ctx, host);
2166+}
2167+
2168+static void pri_parse_proxy(struct pri_context *ctx)
2169+{
2170+ char *proxy, *scheme, *host, *port, *path;
2171+
2172+ g_free(ctx->proxy_host);
2173+ ctx->proxy_host = NULL;
2174+
2175+ if (ctx->message_proxy[0] != '\0')
2176+ proxy = ctx->message_proxy;
2177+ else if (ctx->message_center[0] != '\0')
2178+ proxy = ctx->message_center;
2179+ else
2180+ return;
2181
2182 scheme = g_strdup(proxy);
2183 if (scheme == NULL)
2184@@ -577,8 +757,7 @@
2185 }
2186 }
2187
2188- g_free(ctx->proxy_host);
2189- ctx->proxy_host = g_strdup(host);
2190+ get_proxy_ip(ctx, host);
2191
2192 g_free(scheme);
2193 }
2194@@ -662,44 +841,6 @@
2195 close(sk);
2196 }
2197
2198-static void pri_setproxy(const char *interface, const char *proxy)
2199-{
2200- struct rtentry rt;
2201- struct sockaddr_in addr;
2202- int sk;
2203-
2204- if (interface == NULL)
2205- return;
2206-
2207- sk = socket(PF_INET, SOCK_DGRAM, 0);
2208- if (sk < 0)
2209- return;
2210-
2211- memset(&rt, 0, sizeof(rt));
2212- rt.rt_flags = RTF_UP | RTF_HOST;
2213- rt.rt_dev = (char *) interface;
2214-
2215- memset(&addr, 0, sizeof(addr));
2216- addr.sin_family = AF_INET;
2217- addr.sin_addr.s_addr = inet_addr(proxy);
2218- memcpy(&rt.rt_dst, &addr, sizeof(rt.rt_dst));
2219-
2220- memset(&addr, 0, sizeof(addr));
2221- addr.sin_family = AF_INET;
2222- addr.sin_addr.s_addr = INADDR_ANY;
2223- memcpy(&rt.rt_gateway, &addr, sizeof(rt.rt_gateway));
2224-
2225- memset(&addr, 0, sizeof(addr));
2226- addr.sin_family = AF_INET;
2227- addr.sin_addr.s_addr = INADDR_ANY;
2228- memcpy(&rt.rt_genmask, &addr, sizeof(rt.rt_genmask));
2229-
2230- if (ioctl(sk, SIOCADDRT, &rt) < 0)
2231- ofono_error("Failed to add proxy host route");
2232-
2233- close(sk);
2234-}
2235-
2236 static void pri_reset_context_settings(struct pri_context *ctx)
2237 {
2238 struct context_settings *settings;
2239@@ -736,24 +877,6 @@
2240 g_free(interface);
2241 }
2242
2243-static void pri_update_mms_context_settings(struct pri_context *ctx)
2244-{
2245- struct ofono_gprs_context *gc = ctx->context_driver;
2246- struct context_settings *settings = gc->settings;
2247-
2248- if (ctx->message_proxy)
2249- settings->ipv4->proxy = g_strdup(ctx->message_proxy);
2250-
2251- pri_parse_proxy(ctx, ctx->message_proxy);
2252-
2253- DBG("proxy %s port %u", ctx->proxy_host, ctx->proxy_port);
2254-
2255- pri_set_ipv4_addr(settings->interface, settings->ipv4->ip);
2256-
2257- if (ctx->proxy_host)
2258- pri_setproxy(settings->interface, ctx->proxy_host);
2259-}
2260-
2261 static void append_context_properties(struct pri_context *ctx,
2262 DBusMessageIter *dict)
2263 {
2264@@ -835,8 +958,6 @@
2265 {
2266 struct pri_context *ctx = data;
2267 struct ofono_gprs_context *gc = ctx->context_driver;
2268- DBusConnection *conn = ofono_dbus_get_connection();
2269- dbus_bool_t value;
2270
2271 DBG("%p", ctx);
2272
2273@@ -850,25 +971,23 @@
2274 return;
2275 }
2276
2277- ctx->active = TRUE;
2278- __ofono_dbus_pending_reply(&ctx->pending,
2279- dbus_message_new_method_return(ctx->pending));
2280-
2281 if (gc->settings->interface != NULL) {
2282 pri_ifupdown(gc->settings->interface, TRUE);
2283
2284- if (ctx->type == OFONO_GPRS_CONTEXT_TYPE_MMS &&
2285- gc->settings->ipv4)
2286- pri_update_mms_context_settings(ctx);
2287-
2288- pri_context_signal_settings(ctx, gc->settings->ipv4 != NULL,
2289- gc->settings->ipv6 != NULL);
2290+ if (gc->settings->ipv4) {
2291+ if (ctx->type == OFONO_GPRS_CONTEXT_TYPE_MMS)
2292+ pri_set_ipv4_addr(gc->settings->interface,
2293+ gc->settings->ipv4->ip);
2294+
2295+ pri_parse_proxy(ctx);
2296+
2297+ /* Not answer yet if waiting for DNS lookup */
2298+ if (ctx->lookup_req != NULL)
2299+ return;
2300+ }
2301 }
2302
2303- value = ctx->active;
2304- ofono_dbus_signal_property_changed(conn, ctx->path,
2305- OFONO_CONNECTION_CONTEXT_INTERFACE,
2306- "Active", DBUS_TYPE_BOOLEAN, &value);
2307+ pri_activate_finish(ctx);
2308 }
2309
2310 static void pri_deactivate_callback(const struct ofono_error *error, void *data)
2311@@ -897,15 +1016,11 @@
2312 "Active", DBUS_TYPE_BOOLEAN, &value);
2313 }
2314
2315-static DBusMessage *pri_set_preferred(struct pri_context *ctx,
2316- DBusConnection *conn,
2317- DBusMessage *msg, gboolean preferred)
2318+static void set_preferred(struct pri_context *ctx, DBusConnection *conn,
2319+ gboolean preferred)
2320 {
2321 GKeyFile *settings = ctx->gprs->settings;
2322
2323- if (ctx->preferred == preferred)
2324- return dbus_message_new_method_return(msg);
2325-
2326 ctx->preferred = preferred;
2327
2328 if (settings) {
2329@@ -914,12 +1029,22 @@
2330 storage_sync(ctx->gprs->imsi, SETTINGS_STORE, settings);
2331 }
2332
2333- g_dbus_send_reply(conn, msg, DBUS_TYPE_INVALID);
2334-
2335 ofono_dbus_signal_property_changed(conn, ctx->path,
2336 OFONO_CONNECTION_CONTEXT_INTERFACE,
2337 "Preferred", DBUS_TYPE_BOOLEAN,
2338 &preferred);
2339+}
2340+
2341+static DBusMessage *pri_set_preferred(struct pri_context *ctx,
2342+ DBusConnection *conn,
2343+ DBusMessage *msg, gboolean preferred)
2344+{
2345+ if (ctx->preferred == preferred)
2346+ return dbus_message_new_method_return(msg);
2347+
2348+ g_dbus_send_reply(conn, msg, DBUS_TYPE_INVALID);
2349+
2350+ set_preferred(ctx, conn, preferred);
2351
2352 return NULL;
2353 }
2354@@ -3186,20 +3311,48 @@
2355 static struct pri_context *gprs_context_for_ia(struct ofono_gprs *gprs)
2356 {
2357 GSList *l;
2358-
2359- for (l = gprs->contexts; l; l = l->next) {
2360- struct pri_context *ctx = l->data;
2361-
2362- if (ctx->type == OFONO_GPRS_CONTEXT_TYPE_IA)
2363- return ctx;
2364- }
2365-
2366- for (l = gprs->contexts; l; l = l->next) {
2367- struct pri_context *ctx = l->data;
2368-
2369- if (ctx->type == OFONO_GPRS_CONTEXT_TYPE_INTERNET)
2370- return ctx;
2371- }
2372+ struct pri_context *ctx_ia = NULL;
2373+ struct pri_context *ctx_inet_pref = NULL;
2374+ struct pri_context *ctx_inet = NULL;
2375+ struct pri_context *ctx_other_pref = NULL;
2376+
2377+ for (l = gprs->contexts; l; l = l->next) {
2378+ struct pri_context *ctx = l->data;
2379+
2380+ if (ctx->type == OFONO_GPRS_CONTEXT_TYPE_IA) {
2381+ if (ctx->preferred)
2382+ return ctx;
2383+
2384+ if (ctx_ia == NULL)
2385+ ctx_ia = ctx;
2386+ } else if (ctx->type == OFONO_GPRS_CONTEXT_TYPE_INTERNET) {
2387+
2388+ if (ctx->preferred && ctx_inet_pref == NULL)
2389+ ctx_inet_pref = ctx;
2390+ else if (ctx_inet == NULL)
2391+ ctx_inet = ctx;
2392+
2393+ } else if (ctx->preferred && ctx_other_pref == NULL) {
2394+ ctx_other_pref = ctx;
2395+ }
2396+ }
2397+
2398+ if (ctx_ia != NULL) {
2399+ set_preferred(ctx_ia, ofono_dbus_get_connection(), TRUE);
2400+ return ctx_ia;
2401+ }
2402+
2403+ if (ctx_inet_pref != NULL)
2404+ return ctx_inet_pref;
2405+
2406+ if (ctx_inet != NULL)
2407+ return ctx_inet;
2408+
2409+ if (ctx_other_pref != NULL)
2410+ return ctx_other_pref;
2411+
2412+ if (gprs->contexts == NULL)
2413+ return NULL;
2414
2415 return gprs->contexts->data;
2416 }
2417@@ -3213,11 +3366,16 @@
2418 static void set_ia_apn(struct ofono_gprs *gprs)
2419 {
2420 struct pri_context *ctx = gprs_context_for_ia(gprs);
2421- struct ofono_gprs_primary_context *ofono_ctx = &ctx->context;
2422+ struct ofono_gprs_primary_context *ofono_ctx;
2423 char mccmnc[OFONO_MAX_MCC_LENGTH + OFONO_MAX_MNC_LENGTH + 1];
2424 const char *mcc = ofono_sim_get_mcc(gprs->sim);
2425 const char *mnc = ofono_sim_get_mnc(gprs->sim);
2426
2427+ if (ctx == NULL)
2428+ return;
2429+
2430+ ofono_ctx = &ctx->context;
2431+
2432 strcpy(mccmnc, mcc);
2433 strcpy(mccmnc + strlen(mcc), mnc);
2434
2435
2436=== modified file 'src/radio-settings.c'
2437--- src/radio-settings.c 2014-07-24 08:31:18 +0000
2438+++ src/radio-settings.c 2015-07-02 17:01:42 +0000
2439@@ -338,7 +338,7 @@
2440 radio_set_band(rs);
2441 }
2442
2443-static void radio_set_rat_mode(struct ofono_radio_settings *rs,
2444+void ofono_radio_settings_set_rat_mode(struct ofono_radio_settings *rs,
2445 enum ofono_radio_access_mode mode)
2446 {
2447 DBusConnection *conn = ofono_dbus_get_connection();
2448@@ -378,7 +378,7 @@
2449 reply = dbus_message_new_method_return(rs->pending);
2450 __ofono_dbus_pending_reply(&rs->pending, reply);
2451
2452- radio_set_rat_mode(rs, rs->pending_mode);
2453+ ofono_radio_settings_set_rat_mode(rs, rs->pending_mode);
2454 }
2455
2456 static void radio_send_properties_reply(struct ofono_radio_settings *rs)
2457@@ -513,7 +513,7 @@
2458 return;
2459 }
2460
2461- radio_set_rat_mode(rs, mode);
2462+ ofono_radio_settings_set_rat_mode(rs, mode);
2463 radio_query_band(rs);
2464 }
2465
2466
2467=== modified file 'test/list-contexts'
2468--- test/list-contexts 2014-02-26 09:12:18 +0000
2469+++ test/list-contexts 2015-07-02 17:01:42 +0000
2470@@ -31,7 +31,7 @@
2471 if i in ["DomainNameServers"]:
2472 for n in properties[key][i]:
2473 val += n + ","
2474- elif i in ["PrefixLength"]:
2475+ elif i in ["PrefixLength", "ProxyPort"]:
2476 p = int(properties[key][i])
2477 val += str(p)
2478 else:
2479
2480=== modified file 'test/list-modems'
2481--- test/list-modems 2015-05-20 16:32:09 +0000
2482+++ test/list-modems 2015-07-02 17:01:42 +0000
2483@@ -13,10 +13,11 @@
2484 parser.add_argument("-p",
2485 "--private",
2486 dest="priv",
2487- help="""Specifies that properties considered private
2488- should be output as clear-text vs. obfuscated""",
2489- action="store_false",
2490- default="true"
2491+ help="""Specifies that properties considered
2492+ private should be output obfuscated vs.
2493+ cleartext (default).""",
2494+ action="store_true",
2495+ default=False
2496 )
2497
2498 return parser.parse_args()
2499
2500=== modified file 'test/rilmodem/sim/simtestutil.py'
2501--- test/rilmodem/sim/simtestutil.py 2014-12-15 19:11:43 +0000
2502+++ test/rilmodem/sim/simtestutil.py 2015-07-02 17:01:42 +0000
2503@@ -176,7 +176,7 @@
2504 path),
2505 'org.ofono.SimManager')
2506 def if_supports_sim_offline(self):
2507- if self.product != "krillin":
2508+ if self.product != "krillin" and self.product != "arale":
2509 return True
2510 else:
2511 return False
2512@@ -225,7 +225,7 @@
2513 else:
2514 check_features = no_sim_online_features[:]
2515 else:
2516- if self.product == "krillin":
2517+ if self.product == "krillin" or self.product == "arale":
2518 check_features = []
2519 else:
2520 if test_sims:
2521@@ -264,7 +264,7 @@
2522 else:
2523
2524 # krillin no diff between sim/no-SIM when offline
2525- if self.product == "krillin":
2526+ if self.product == "krillin" or self.product == "arale":
2527 check_ifaces = no_sim_offline_ifaces[:]
2528 check_ifaces.append("org.ofono.NetworkTime")
2529 else:
2530@@ -298,7 +298,7 @@
2531 #
2532 # https://bugs.launchpad.net/ubuntu/+source/ofono/+bug/1396317
2533
2534- if self.product == "krillin":
2535+ if self.product == "krillin" or self.product == "arale":
2536 self.assertTrue(properties["Muted"] == 0)
2537 else:
2538 self.assertTrue(properties["Muted"] == 1)
2539
2540=== modified file 'test/rilmodem/sim/test-no-sims-offline'
2541--- test/rilmodem/sim/test-no-sims-offline 2014-12-15 19:11:43 +0000
2542+++ test/rilmodem/sim/test-no-sims-offline 2015-07-02 17:01:42 +0000
2543@@ -67,7 +67,7 @@
2544 self.validate_modem_properties(path, False, False)
2545
2546 # krillin doesn't expose SimManager when offline
2547- if (self.product != "krillin"):
2548+ if (self.product != "krillin" and self.product != "arale"):
2549 self.assertTrue(self.check_no_sim_present(path))
2550
2551 self.validate_emergency_numbers(path)
2552
2553=== modified file 'test/rilmodem/sim/test-sims-offline'
2554--- test/rilmodem/sim/test-sims-offline 2014-12-12 15:51:15 +0000
2555+++ test/rilmodem/sim/test-sims-offline 2015-07-02 17:01:42 +0000
2556@@ -89,7 +89,7 @@
2557 self.validate_modem_properties(path, False, True)
2558
2559 # krillin: no SIM access when modem offline
2560- if (self.product != "krillin"):
2561+ if (self.product != "krillin" and self.product != "arale"):
2562 self.validate_sim_properties(path, self.args.mcc,
2563 self.args.mnc,
2564 self.args.subscriber)

Subscribers

People subscribed via source and target branches

to all changes: