Merge lp:~awe/ofono/midori-switch-4g-update into lp:~phablet-team/ofono/ubuntu

Proposed by Tony Espy on 2016-07-19
Status: Merged
Approved by: Scott Sweeny on 2016-07-19
Approved revision: 6918
Merged at revision: 6918
Proposed branch: lp:~awe/ofono/midori-switch-4g-update
Merge into: lp:~phablet-team/ofono/ubuntu
Diff against target: 1169 lines (+609/-171)
14 files modified
debian/changelog (+18/-0)
drivers/mtk2modem/gprs.c (+0/-1)
drivers/mtkmodem/gprs.c (+0/-1)
drivers/mtkmodem/radio-settings.c (+5/-0)
drivers/qcommsimmodem/gprs.c (+0/-1)
drivers/qcommsimmodem/radio-settings.c (+3/-0)
drivers/rilmodem/gprs.c (+0/-48)
drivers/rilmodem/gprs.h (+0/-4)
drivers/rilmodem/radio-settings.c (+514/-35)
drivers/rilmodem/radio-settings.h (+19/-0)
gril/grilreply.c (+9/-3)
include/gprs.h (+2/-4)
plugins/ril.c (+35/-55)
src/gprs.c (+4/-19)
To merge this branch: bzr merge lp:~awe/ofono/midori-switch-4g-update
Reviewer Review Type Date Requested Status
Scott Sweeny (community) 2016-07-19 Approve on 2016-07-19
Review via email: mp+300483@code.launchpad.net

Commit message

  * Add automatic SIM slot capability switching for midori:
   * include: gprs: remove set ia
   * gprs: remove calls to set_ia_apn
   * gril: fix memory leak, print radio_caps event
   * ril: create radio settings when onlining
   * rilmodem: gprs: remove set_ia_apn
   * rilmodem: radio-settings: enable switch slots caps
   * qcommsimmodem: remote set_ia_apn
   * qcommsimmodem: adapt to radio settings changes
   * mtkmodem: adapt to radio settings changes
   * mtkmodem: remove set_ia_apn
   * mtk2modem: remove set_ia_apn

Description of the change

This change adds support for dynamic switching of radio capabilities for dual-standby modems which use the rilmodem driver ( eg. midori ).

Instead of having to explicitly call a DBus method to switch which SIM slot has the ability use 3g or 4g, now the client just uses the standard method of changing the network technology preference. If this new setting requires the slot capabilities to be swapped, rilmodem will do this automatically on behalf of the client.

This change re-works some of the code necessary for LTE support, and as such, we should ensure that LTE still works properly on the MX4 ( EU / China only ).

To post a comment you must log in.
Scott Sweeny (ssweeny) wrote :

LGTM

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'debian/changelog'
2--- debian/changelog 2016-07-01 17:31:30 +0000
3+++ debian/changelog 2016-07-19 15:19:28 +0000
4@@ -1,3 +1,21 @@
5+ofono (1.17.bzr6919+16.10.20160719-0ubuntu1) UNRELEASED; urgency=medium
6+
7+ [ Alfonso Sanchez-Beato ]
8+ * Add automatic SIM slot capability switching for midori:
9+ * include: gprs: remove set ia
10+ * gprs: remove calls to set_ia_apn
11+ * gril: fix memory leak, print radio_caps event
12+ * ril: create radio settings when onlining
13+ * rilmodem: gprs: remove set_ia_apn
14+ * rilmodem: radio-settings: enable switch slots caps
15+ * qcommsimmodem: remote set_ia_apn
16+ * qcommsimmodem: adapt to radio settings changes
17+ * mtkmodem: adapt to radio settings changes
18+ * mtkmodem: remove set_ia_apn
19+ * mtk2modem: remove set_ia_apn
20+
21+ -- Tony Espy <espy@canonical.com> Tue, 19 Jul 2016 10:29:20 -0400
22+
23 ofono (1.17.bzr6919+16.10.20160701.2-0ubuntu1) yakkety; urgency=medium
24
25 [ Ratchanan Srirattanamet ]
26
27=== modified file 'drivers/mtk2modem/gprs.c'
28--- drivers/mtk2modem/gprs.c 2016-06-28 06:50:11 +0000
29+++ drivers/mtk2modem/gprs.c 2016-07-19 15:19:28 +0000
30@@ -74,7 +74,6 @@
31 .remove = ril_gprs_remove,
32 .set_attached = ril_gprs_set_attached,
33 .attached_status = ril_gprs_registration_status,
34- .set_ia_apn = ril_gprs_set_ia_apn,
35 };
36
37 void mtk2_gprs_init(void)
38
39=== modified file 'drivers/mtkmodem/gprs.c'
40--- drivers/mtkmodem/gprs.c 2015-09-29 08:46:20 +0000
41+++ drivers/mtkmodem/gprs.c 2016-07-19 15:19:28 +0000
42@@ -175,7 +175,6 @@
43 .remove = mtk_gprs_remove,
44 .set_attached = mtk_gprs_set_attached,
45 .attached_status = ril_gprs_registration_status,
46- .set_ia_apn = ril_gprs_set_ia_apn,
47 };
48
49 void mtk_gprs_init(void)
50
51=== modified file 'drivers/mtkmodem/radio-settings.c'
52--- drivers/mtkmodem/radio-settings.c 2015-09-29 08:46:20 +0000
53+++ drivers/mtkmodem/radio-settings.c 2016-07-19 15:19:28 +0000
54@@ -105,6 +105,8 @@
55 }
56 }
57
58+static struct ofono_radio_settings_driver driver;
59+
60 static int mtk_radio_settings_probe(struct ofono_radio_settings *rs,
61 unsigned int vendor, void *user)
62 {
63@@ -116,6 +118,7 @@
64 return -ENOMEM;
65 }
66
67+ rsd->virt_tbl = &driver;
68 rsd->ril = g_ril_clone(rs_init_data->gril);
69 rsd->modem = rs_init_data->modem;
70
71@@ -159,6 +162,8 @@
72 available_rats |= OFONO_RADIO_ACCESS_MODE_LTE;
73 }
74
75+ rd->available_rats = available_rats;
76+
77 CALLBACK_WITH_SUCCESS(cb, available_rats, cbd->data);
78 }
79
80
81=== modified file 'drivers/qcommsimmodem/gprs.c'
82--- drivers/qcommsimmodem/gprs.c 2016-04-15 14:12:39 +0000
83+++ drivers/qcommsimmodem/gprs.c 2016-07-19 15:19:28 +0000
84@@ -104,7 +104,6 @@
85 .remove = ril_gprs_remove,
86 .set_attached = qcom_msim_gprs_set_attached,
87 .attached_status = ril_gprs_registration_status,
88- .set_ia_apn = ril_gprs_set_ia_apn,
89 };
90
91 void qcom_msim_gprs_init(void)
92
93=== modified file 'drivers/qcommsimmodem/radio-settings.c'
94--- drivers/qcommsimmodem/radio-settings.c 2016-02-25 11:59:14 +0000
95+++ drivers/qcommsimmodem/radio-settings.c 2016-07-19 15:19:28 +0000
96@@ -225,6 +225,8 @@
97 qcom_msim_do_set_rat_mode(rs, pref, cbd);
98 }
99
100+static struct ofono_radio_settings_driver driver;
101+
102 static int qcom_msim_radio_settings_probe(struct ofono_radio_settings *rs,
103 unsigned int vendor, void *user)
104 {
105@@ -237,6 +239,7 @@
106 return -ENOMEM;
107 }
108
109+ rsd->virt_tbl = &driver;
110 rsd->ril = g_ril_clone(rs_init_data->gril);
111 rsd->modem = rs_init_data->modem;
112
113
114=== modified file 'drivers/rilmodem/gprs.c'
115--- drivers/rilmodem/gprs.c 2016-06-30 17:41:18 +0000
116+++ drivers/rilmodem/gprs.c 2016-07-19 15:19:28 +0000
117@@ -106,53 +106,6 @@
118 }
119 }
120
121-static void set_ia_apn_cb(struct ril_msg *message, gpointer user_data)
122-{
123- struct cb_data *cbd = user_data;
124- ofono_gprs_cb_t cb = cbd->cb;
125- struct ofono_gprs *gprs = cbd->user;
126- struct ril_gprs_data *gd = ofono_gprs_get_data(gprs);
127-
128- if (message->error != RIL_E_SUCCESS) {
129- ofono_error("%s: reply failure: %s", __func__,
130- ril_error_to_string(message->error));
131- CALLBACK_WITH_FAILURE(cb, cbd->data);
132- return;
133- }
134-
135- g_ril_print_response_no_args(gd->ril, message);
136-
137- CALLBACK_WITH_SUCCESS(cb, cbd->data);
138-}
139-
140-void ril_gprs_set_ia_apn(struct ofono_gprs *gprs, const char *apn,
141- enum ofono_gprs_proto proto, const char *user,
142- const char *passwd, const char *mccmnc,
143- ofono_gprs_cb_t cb, void *data)
144-{
145- struct ril_gprs_data *gd = ofono_gprs_get_data(gprs);
146- struct cb_data *cbd;
147- struct parcel rilp;
148-
149- if (!ofono_modem_get_boolean(gd->modem, MODEM_PROP_LTE_CAPABLE)) {
150- CALLBACK_WITH_SUCCESS(cb, data);
151- return;
152- }
153-
154- cbd = cb_data_new(cb, data, gprs);
155-
156- g_ril_request_set_initial_attach_apn(gd->ril, apn, proto, user, passwd,
157- mccmnc, &rilp);
158-
159- if (g_ril_send(gd->ril, RIL_REQUEST_SET_INITIAL_ATTACH_APN,
160- &rilp, set_ia_apn_cb, cbd, g_free) == 0) {
161- ofono_error("%s: failure sending request", __func__);
162-
163- g_free(cbd);
164- CALLBACK_WITH_FAILURE(cb, data);
165- }
166-}
167-
168 static void ril_gprs_state_change(struct ril_msg *message, gpointer user_data)
169 {
170 struct ofono_gprs *gprs = user_data;
171@@ -604,7 +557,6 @@
172 .remove = ril_gprs_remove,
173 .set_attached = ril_gprs_set_attached,
174 .attached_status = ril_gprs_registration_status,
175- .set_ia_apn = ril_gprs_set_ia_apn,
176 };
177
178 void ril_gprs_init(void)
179
180=== modified file 'drivers/rilmodem/gprs.h'
181--- drivers/rilmodem/gprs.h 2016-06-16 13:29:18 +0000
182+++ drivers/rilmodem/gprs.h 2016-07-19 15:19:28 +0000
183@@ -42,7 +42,3 @@
184 ofono_gprs_cb_t cb, void *data);
185 void ril_gprs_registration_status(struct ofono_gprs *gprs,
186 ofono_gprs_status_cb_t cb, void *data);
187-void ril_gprs_set_ia_apn(struct ofono_gprs *gprs, const char *apn,
188- enum ofono_gprs_proto proto, const char *user,
189- const char *passwd, const char *mccmnc,
190- ofono_gprs_cb_t cb, void *data);
191
192=== modified file 'drivers/rilmodem/radio-settings.c'
193--- drivers/rilmodem/radio-settings.c 2016-06-30 16:41:34 +0000
194+++ drivers/rilmodem/radio-settings.c 2016-07-19 15:19:28 +0000
195@@ -30,9 +30,11 @@
196 #include <stdlib.h>
197 #include <string.h>
198 #include <errno.h>
199+#include <stdint.h>
200
201 #include <glib.h>
202
203+#include <ofono.h>
204 #include <ofono/log.h>
205 #include <ofono/modem.h>
206 #include <ofono/radio-settings.h>
207@@ -46,6 +48,63 @@
208 #include "grilreply.h"
209 #include "radio-settings.h"
210
211+struct radio_data *radio_data_0;
212+struct radio_data *radio_data_1;
213+
214+static int g_session;
215+
216+static struct radio_data *radio_data_complement(struct radio_data *rd)
217+{
218+ if (rd == radio_data_0)
219+ return radio_data_1;
220+ else
221+ return radio_data_0;
222+}
223+
224+static void set_ia_apn_cb(struct ril_msg *message, gpointer user_data)
225+{
226+ struct ofono_radio_settings *rs = user_data;
227+ struct radio_data *rd = ofono_radio_settings_get_data(rs);
228+
229+ if (message->error != RIL_E_SUCCESS) {
230+ ofono_error("%s: reply failure: %s", __func__,
231+ ril_error_to_string(message->error));
232+ return;
233+ }
234+
235+ g_ril_print_response_no_args(rd->ril, message);
236+}
237+
238+static void set_ia_apn(struct ofono_radio_settings *rs)
239+{
240+ char mccmnc[OFONO_MAX_MCC_LENGTH + OFONO_MAX_MNC_LENGTH + 1];
241+ struct radio_data *rd = ofono_radio_settings_get_data(rs);
242+ struct parcel rilp;
243+ struct ofono_gprs *gprs;
244+ const struct ofono_gprs_primary_context *ia_ctx;
245+
246+ if ((rd->available_rats & OFONO_RADIO_ACCESS_MODE_LTE) == 0)
247+ return;
248+
249+ gprs = __ofono_atom_find(OFONO_ATOM_TYPE_GPRS, rd->modem);
250+ if (gprs == NULL)
251+ return;
252+
253+ /* Ask for APN data */
254+ ia_ctx = ofono_gprs_get_ia_apn(gprs, mccmnc);
255+ if (ia_ctx == NULL)
256+ return;
257+
258+ g_ril_request_set_initial_attach_apn(rd->ril, ia_ctx->apn,
259+ ia_ctx->proto, ia_ctx->username,
260+ ia_ctx->password, mccmnc,
261+ &rilp);
262+
263+ if (g_ril_send(rd->ril, RIL_REQUEST_SET_INITIAL_ATTACH_APN,
264+ &rilp, set_ia_apn_cb, rs, NULL) == 0)
265+ ofono_error("%s: failure sending request", __func__);
266+}
267+
268 static void ril_set_rat_cb(struct ril_msg *message, gpointer user_data)
269 {
270 struct cb_data *cbd = user_data;
271@@ -54,7 +113,13 @@
272 ofono_radio_settings_rat_mode_set_cb_t cb = cbd->cb;
273
274 if (message->error == RIL_E_SUCCESS) {
275+ rd->rat_mode = rd->pending_mode;
276+
277 g_ril_print_response_no_args(rd->ril, message);
278+
279+ if (rd->rat_mode == OFONO_RADIO_ACCESS_MODE_LTE)
280+ set_ia_apn(rs);
281+
282 CALLBACK_WITH_SUCCESS(cb, cbd->data);
283 } else {
284 ofono_error("%s: rat mode setting failed", __func__);
285@@ -62,13 +127,10 @@
286 }
287 }
288
289-void ril_set_rat_mode(struct ofono_radio_settings *rs,
290- enum ofono_radio_access_mode mode,
291- ofono_radio_settings_rat_mode_set_cb_t cb,
292- void *data)
293+static void set_preferred_network(struct radio_data *rd, struct cb_data *cbd,
294+ enum ofono_radio_access_mode mode)
295 {
296- struct radio_data *rd = ofono_radio_settings_get_data(rs);
297- struct cb_data *cbd = cb_data_new(cb, data, rs);
298+ ofono_radio_settings_rat_mode_set_cb_t cb = cbd->cb;
299 struct parcel rilp;
300 int pref = PREF_NET_TYPE_GSM_WCDMA;
301
302@@ -87,14 +149,340 @@
303 break;
304 }
305
306+ rd->pending_mode = mode;
307+
308 g_ril_request_set_preferred_network_type(rd->ril, pref, &rilp);
309
310 if (g_ril_send(rd->ril, RIL_REQUEST_SET_PREFERRED_NETWORK_TYPE,
311 &rilp, ril_set_rat_cb, cbd, g_free) == 0) {
312 ofono_error("%s: unable to set rat mode", __func__);
313 g_free(cbd);
314- CALLBACK_WITH_FAILURE(cb, data);
315- }
316+ CALLBACK_WITH_FAILURE(cb, cbd->data);
317+ }
318+}
319+
320+static gboolean send_set_radio_cap(struct radio_data *rd,
321+ int session, int phase, int ril_rats,
322+ const char *logical_modem, int status,
323+ GRilResponseFunc cb)
324+{
325+ struct parcel rilp;
326+ int version = 1;
327+
328+ parcel_init(&rilp);
329+
330+ parcel_w_int32(&rilp, version);
331+ parcel_w_int32(&rilp, session);
332+ parcel_w_int32(&rilp, phase);
333+ parcel_w_int32(&rilp, ril_rats);
334+ parcel_w_string(&rilp, logical_modem);
335+ parcel_w_int32(&rilp, status);
336+
337+ g_ril_append_print_buf(rd->ril, "(%d,%d,%d,0x%X,%s,%d)", version,
338+ session, phase, ril_rats, logical_modem, status);
339+
340+ if (g_ril_send(rd->ril, RIL_REQUEST_SET_RADIO_CAPABILITY,
341+ &rilp, cb, rd, NULL) == 0)
342+ return FALSE;
343+
344+ return TRUE;
345+}
346+
347+static unsigned set_rat_from_ril_rat(int ril_rat)
348+{
349+ unsigned rat = 0;
350+
351+ if (ril_rat & RIL_RAF_GSM)
352+ rat |= OFONO_RADIO_ACCESS_MODE_GSM;
353+
354+ if (ril_rat & (RIL_RAF_UMTS | RIL_RAF_TD_SCDMA))
355+ rat |= OFONO_RADIO_ACCESS_MODE_UMTS;
356+
357+ if (ril_rat & RIL_RAF_LTE)
358+ rat |= OFONO_RADIO_ACCESS_MODE_LTE;
359+
360+ return rat;
361+}
362+
363+static void set_preferred_cb(const struct ofono_error *error, void *data)
364+{
365+ struct radio_data *rd = data;
366+
367+ if (error->type != OFONO_ERROR_TYPE_NO_ERROR) {
368+ ofono_error("%s: error setting radio access mode", __func__);
369+
370+ return;
371+ }
372+
373+ ofono_radio_settings_set_rat_mode(rd->radio_settings, rd->rat_mode);
374+}
375+
376+static enum ofono_radio_access_mode
377+ get_best_available_tech(unsigned available_rats)
378+{
379+ int i;
380+ uint32_t tech;
381+
382+ for (i = sizeof(uint32_t) * CHAR_BIT; i > 0; i--) {
383+ tech = 1 << (i - 1);
384+
385+ if ((available_rats & tech) != 0)
386+ break;
387+ }
388+
389+ if (i == 0)
390+ tech = OFONO_RADIO_ACCESS_MODE_GSM;
391+
392+ return tech;
393+}
394+
395+static void switch_finish_cb(struct ril_msg *message, gpointer user_data)
396+{
397+ struct radio_data *rd = user_data;
398+ struct switch_data *sd = rd->switch_d;
399+ struct radio_data *rd1 = sd->rd_1;
400+ struct radio_data *rd2 = sd->rd_2;
401+ struct reply_radio_capability *caps;
402+
403+ sd->pending_msgs--;
404+
405+ if (message->error != RIL_E_SUCCESS) {
406+ ofono_error("%s: error %s", __func__,
407+ ril_error_to_string(message->error));
408+ return;
409+ }
410+
411+ caps = g_ril_reply_parse_get_radio_capability(rd->ril, message);
412+ if (caps == NULL) {
413+ ofono_error("%s: parse error", __func__);
414+ return;
415+ }
416+
417+ if (sd->pending_msgs != 0)
418+ return;
419+
420+ ofono_info("Switching radio caps between slots - FINISH");
421+
422+ set_preferred_network(rd1, sd->cbd, sd->mode_to_switch);
423+
424+ /*
425+ * If the complementary slot does not support anymore its current
426+ * technology, we change it to the best possible among available ones.
427+ */
428+ if ((rd2->rat_mode & rd2->available_rats) == 0) {
429+
430+ struct cb_data *cbd =
431+ cb_data_new(set_preferred_cb, rd2, rd2->radio_settings);
432+
433+ set_preferred_network(rd2, cbd,
434+ get_best_available_tech(rd2->available_rats));
435+ }
436+
437+ rd1->switch_d = NULL;
438+ rd2->switch_d = NULL;
439+ g_free(sd);
440+ g_free(caps);
441+}
442+
443+static void radio_caps_event(struct ril_msg *message, gpointer user_data)
444+{
445+ struct radio_data *rd = user_data;
446+ struct switch_data *sd = rd->switch_d;
447+ struct radio_data *rd1;
448+ struct radio_data *rd2;
449+ struct reply_radio_capability *caps;
450+
451+ if (sd == NULL)
452+ return;
453+
454+ rd1 = sd->rd_1;
455+ rd2 = sd->rd_2;
456+
457+ caps = g_ril_reply_parse_get_radio_capability(rd->ril, message);
458+ if (caps == NULL) {
459+ ofono_error("%s: parse error", __func__);
460+ return;
461+ }
462+
463+ /*
464+ * Update rats. They come also in the replies to SET_RADIO_CAPABILITY,
465+ * but those seem to be unreliable, at least for midori.
466+ */
467+ rd->ril_rats = caps->rat;
468+ rd->available_rats = set_rat_from_ril_rat(caps->rat);
469+
470+ strcpy(rd->modem_uuid, caps->modem_uuid);
471+
472+ sd->pending_msgs--;
473+
474+ if (sd->pending_msgs != 0)
475+ return;
476+
477+ DBG("Sending requests for FINISH phase");
478+
479+ send_set_radio_cap(rd1, g_session, RIL_RC_PHASE_FINISH,
480+ rd1->ril_rats, rd1->modem_uuid,
481+ RIL_RC_STATUS_SUCCESS, switch_finish_cb);
482+ send_set_radio_cap(rd2, g_session, RIL_RC_PHASE_FINISH,
483+ rd2->ril_rats, rd2->modem_uuid,
484+ RIL_RC_STATUS_SUCCESS, switch_finish_cb);
485+ sd->pending_msgs = 2;
486+
487+ g_free(caps);
488+}
489+
490+/*
491+ * This function is just for completeness, as we actually need to wait for the
492+ * unsolocited events to continue the capabilities switch.
493+ */
494+static void switch_apply_cb(struct ril_msg *message, gpointer user_data)
495+{
496+ struct radio_data *rd = user_data;
497+ struct reply_radio_capability *caps;
498+
499+ if (message->error != RIL_E_SUCCESS) {
500+ ofono_error("%s: error %s", __func__,
501+ ril_error_to_string(message->error));
502+ return;
503+ }
504+
505+ caps = g_ril_reply_parse_get_radio_capability(rd->ril, message);
506+ if (caps == NULL)
507+ ofono_error("%s: parse error", __func__);
508+
509+ g_free(caps);
510+}
511+
512+static void switch_start_cb(struct ril_msg *message, gpointer user_data)
513+{
514+ struct radio_data *rd = user_data;
515+ struct switch_data *sd = rd->switch_d;
516+ struct radio_data *rd1 = sd->rd_1;
517+ struct radio_data *rd2 = sd->rd_2;
518+ struct reply_radio_capability *caps;
519+
520+ sd->pending_msgs--;
521+
522+ if (message->error != RIL_E_SUCCESS) {
523+ ofono_error("%s: error %s", __func__,
524+ ril_error_to_string(message->error));
525+ return;
526+ }
527+
528+ caps = g_ril_reply_parse_get_radio_capability(rd->ril, message);
529+ if (caps == NULL) {
530+ ofono_error("%s: parse error", __func__);
531+ return;
532+ }
533+
534+ if (sd->pending_msgs != 0)
535+ return;
536+
537+ DBG("Sending requests for APPLY phase");
538+
539+ send_set_radio_cap(rd1, g_session, RIL_RC_PHASE_APPLY,
540+ rd2->ril_rats, rd2->modem_uuid,
541+ RIL_RC_STATUS_NONE, switch_apply_cb);
542+ send_set_radio_cap(rd2, g_session, RIL_RC_PHASE_APPLY,
543+ rd1->ril_rats, rd1->modem_uuid,
544+ RIL_RC_STATUS_NONE, switch_apply_cb);
545+ sd->pending_msgs = 2;
546+
547+ g_free(caps);
548+}
549+
550+static void switch_caps(struct switch_data *sd)
551+{
552+ struct radio_data *rd1 = sd->rd_1;
553+ struct radio_data *rd2 = sd->rd_2;
554+
555+ /* START phase */
556+ g_session++;
557+
558+ send_set_radio_cap(rd1, g_session, RIL_RC_PHASE_START,
559+ rd1->ril_rats, rd1->modem_uuid,
560+ RIL_RC_STATUS_NONE, switch_start_cb);
561+ send_set_radio_cap(rd2, g_session, RIL_RC_PHASE_START,
562+ rd2->ril_rats, rd2->modem_uuid,
563+ RIL_RC_STATUS_NONE, switch_start_cb);
564+ sd->pending_msgs = 2;
565+}
566+
567+static void get_rs_with_mode(struct ofono_modem *modem, void *data)
568+{
569+ struct switch_data *sd = data;
570+ struct radio_data *rd_ref = sd->rd_1;
571+ struct ofono_atom *atom;
572+ struct ofono_radio_settings *rs;
573+ struct radio_data *rd;
574+ const char *standby_group, *modem_group;
575+
576+ atom = __ofono_modem_find_atom(modem, OFONO_ATOM_TYPE_RADIO_SETTINGS);
577+ if (atom == NULL)
578+ return;
579+
580+ rs = __ofono_atom_get_data(atom);
581+ rd = ofono_radio_settings_get_data(rs);
582+ if (rd == rd_ref)
583+ return;
584+
585+ standby_group = ofono_modem_get_string(rd_ref->modem, "StandbyGroup");
586+ if (standby_group == NULL)
587+ return;
588+
589+ modem_group = ofono_modem_get_string(modem, "StandbyGroup");
590+ if (g_strcmp0(standby_group, modem_group) != 0)
591+ return;
592+
593+ if ((rd->available_rats & sd->mode_to_switch) == 0)
594+ return;
595+
596+ sd->rd_2 = rd;
597+}
598+
599+void ril_set_rat_mode(struct ofono_radio_settings *rs,
600+ enum ofono_radio_access_mode mode,
601+ ofono_radio_settings_rat_mode_set_cb_t cb,
602+ void *data)
603+{
604+ struct radio_data *rd = ofono_radio_settings_get_data(rs);
605+ struct cb_data *cbd = cb_data_new(cb, data, rs);
606+ struct switch_data *sd = NULL;
607+
608+ if (rd->switch_d != NULL)
609+ goto error;
610+
611+ if ((rd->available_rats & mode) == 0) {
612+ if (g_ril_get_version(rd->ril) < 11)
613+ goto error;
614+
615+ /* Check if we can switch rats with other slot */
616+ sd = g_malloc0(sizeof (*sd));
617+ sd->rd_1 = rd;
618+ sd->mode_to_switch = mode;
619+ sd->cbd = cbd;
620+
621+ __ofono_modem_foreach(get_rs_with_mode, sd);
622+
623+ if (sd->rd_2 == NULL)
624+ goto error;
625+
626+ ofono_info("Switching radio caps between slots - START");
627+ sd->rd_1->switch_d = sd;
628+ sd->rd_2->switch_d = sd;
629+
630+ switch_caps(sd);
631+ } else {
632+ set_preferred_network(rd, cbd, mode);
633+ }
634+
635+ return;
636+
637+error:
638+ ofono_error("%s: unable to set rat mode", __func__);
639+ g_free(sd);
640+ g_free(cbd);
641+ CALLBACK_WITH_FAILURE(cb, data);
642 }
643
644 static void ril_rat_mode_cb(struct ril_msg *message, gpointer user_data)
645@@ -108,15 +496,13 @@
646 if (message->error != RIL_E_SUCCESS) {
647 ofono_error("%s: error %s", __func__,
648 ril_error_to_string(message->error));
649- CALLBACK_WITH_FAILURE(cb, -1, cbd->data);
650- return;
651+ goto error;
652 }
653
654 pref = g_ril_reply_parse_get_preferred_network_type(rd->ril, message);
655 if (pref < 0) {
656 ofono_error("%s: parse error", __func__);
657- CALLBACK_WITH_FAILURE(cb, -1, cbd->data);
658- return;
659+ goto error;
660 }
661
662 /*
663@@ -144,7 +530,22 @@
664 break;
665 }
666
667+ rd->rat_mode = mode;
668+
669 CALLBACK_WITH_SUCCESS(cb, mode, cbd->data);
670+
671+ return;
672+
673+error:
674+ /*
675+ * If error, we assume GSM. This is preferable to not being able to
676+ * access the radio settings properties. Midori returns error if we
677+ * have not completed successfully a capability switch. This should
678+ * not happen if there are no bugs in our implementation, but it is
679+ * better to leave this here so system settings shows something that
680+ * can be manually changed by the user, just in case.
681+ */
682+ CALLBACK_WITH_SUCCESS(cb, OFONO_RADIO_ACCESS_MODE_GSM, cbd->data);
683 }
684
685 void ril_query_rat_mode(struct ofono_radio_settings *rs,
686@@ -211,19 +612,18 @@
687
688 static ofono_bool_t query_available_rats_cb(gpointer user_data)
689 {
690- unsigned int available_rats;
691 struct cb_data *cbd = user_data;
692 ofono_radio_settings_available_rats_query_cb_t cb = cbd->cb;
693 struct ofono_radio_settings *rs = cbd->user;
694 struct radio_data *rd = ofono_radio_settings_get_data(rs);
695
696- available_rats = OFONO_RADIO_ACCESS_MODE_GSM
697- | OFONO_RADIO_ACCESS_MODE_UMTS;
698-
699- if (ofono_modem_get_boolean(rd->modem, MODEM_PROP_LTE_CAPABLE))
700- available_rats |= OFONO_RADIO_ACCESS_MODE_LTE;
701-
702- CALLBACK_WITH_SUCCESS(cb, available_rats, cbd->data);
703+ rd->available_rats = OFONO_RADIO_ACCESS_MODE_GSM
704+ | OFONO_RADIO_ACCESS_MODE_UMTS;
705+
706+ if (getenv("OFONO_RIL_RAT_LTE") != NULL)
707+ rd->available_rats |= OFONO_RADIO_ACCESS_MODE_LTE;
708+
709+ CALLBACK_WITH_SUCCESS(cb, rd->available_rats, cbd->data);
710
711 g_free(cbd);
712
713@@ -232,12 +632,13 @@
714
715 static void get_radio_caps_cb(struct ril_msg *message, gpointer user_data)
716 {
717- unsigned int available_rats = 0;
718 struct cb_data *cbd = user_data;
719 ofono_radio_settings_available_rats_query_cb_t cb = cbd->cb;
720 struct ofono_radio_settings *rs = cbd->user;
721 struct radio_data *rd = ofono_radio_settings_get_data(rs);
722+ struct radio_data *rd_comp;
723 struct reply_radio_capability *caps;
724+ unsigned all_rats;
725
726 if (message->error != RIL_E_SUCCESS) {
727 ofono_error("%s: error %s", __func__,
728@@ -253,18 +654,21 @@
729 return;
730 }
731
732- if (caps->rat & RIL_RAF_GSM)
733- available_rats |= OFONO_RADIO_ACCESS_MODE_GSM;
734-
735- if (caps->rat & (RIL_RAF_UMTS | RIL_RAF_TD_SCDMA))
736- available_rats |= OFONO_RADIO_ACCESS_MODE_UMTS;
737-
738- if (caps->rat & RIL_RAF_LTE)
739- available_rats |= OFONO_RADIO_ACCESS_MODE_LTE;
740+ rd->ril_rats = caps->rat;
741+ rd->available_rats = set_rat_from_ril_rat(caps->rat);
742+
743+ strcpy(rd->modem_uuid, caps->modem_uuid);
744
745 g_free(caps);
746
747- CALLBACK_WITH_SUCCESS(cb, available_rats, cbd->data);
748+ /* We show all rats, as we can switch the ownership between slots */
749+ all_rats = rd->available_rats;
750+
751+ rd_comp = radio_data_complement(rd);
752+ if (rd_comp != NULL)
753+ all_rats |= rd_comp->available_rats;
754+
755+ CALLBACK_WITH_SUCCESS(cb, all_rats, cbd->data);
756 }
757
758 void ril_query_available_rats(struct ofono_radio_settings *rs,
759@@ -286,20 +690,90 @@
760 }
761 }
762
763+static void gprs_watch_cb(struct ofono_atom *atom,
764+ enum ofono_atom_watch_condition cond,
765+ void *data)
766+{
767+ struct ofono_radio_settings *rs = data;
768+
769+ if (cond != OFONO_ATOM_WATCH_CONDITION_REGISTERED)
770+ return;
771+
772+ set_ia_apn(rs);
773+}
774+
775+static void set_safe_preferred_cb(const struct ofono_error *error, void *data)
776+{
777+ if (error->type != OFONO_ERROR_TYPE_NO_ERROR) {
778+ ofono_error("%s: error setting radio access mode", __func__);
779+
780+ return;
781+ }
782+}
783+
784+static void radio_settings_register(const struct ofono_error *error,
785+ unsigned int available_rats,
786+ void *data)
787+{
788+ struct ofono_radio_settings *rs = data;
789+ struct radio_data *rd = ofono_radio_settings_get_data(rs);
790+
791+ g_ril_register(rd->ril, RIL_UNSOL_RADIO_CAPABILITY,
792+ radio_caps_event, rd);
793+
794+ rd->gprs_atom_watch =
795+ __ofono_modem_add_atom_watch(rd->modem, OFONO_ATOM_TYPE_GPRS,
796+ gprs_watch_cb, rs, NULL);
797+
798+ /*
799+ * If the preferred technology was unknown/unsupported, change to a
800+ * valid one (midori can return PREF_NET_TYPE_CDMA_ONLY, for instance).
801+ */
802+ if (rd->rat_mode == OFONO_RADIO_ACCESS_MODE_ANY) {
803+ struct cb_data *cbd = cb_data_new(set_safe_preferred_cb, rd,
804+ rd->radio_settings);
805+
806+ set_preferred_network(rd, cbd,
807+ get_best_available_tech(rd->available_rats));
808+ }
809+
810+ /*
811+ * We register in all cases, setting FD some times fails until radio is
812+ * available (this happens on turbo and maybe in other devices).
813+ */
814+ ofono_radio_settings_register(rs);
815+}
816+
817+static void ril_after_query_rat_mode(const struct ofono_error *error,
818+ enum ofono_radio_access_mode mode,
819+ void *data)
820+{
821+ struct ofono_radio_settings *rs = data;
822+ struct radio_data *rd = ofono_radio_settings_get_data(rs);
823+
824+ rd->virt_tbl->query_available_rats(rs, radio_settings_register, rs);
825+}
826+
827 void ril_delayed_register(const struct ofono_error *error, void *user_data)
828 {
829 struct ofono_radio_settings *rs = user_data;
830+ struct radio_data *rd = ofono_radio_settings_get_data(rs);
831
832 if (error->type != OFONO_ERROR_TYPE_NO_ERROR)
833 ofono_error("%s: cannot set default fast dormancy", __func__);
834
835- /*
836- * We register in all cases, setting FD some times fails until radio is
837- * available (this happens on turbo and maybe in other devices).
838- */
839- ofono_radio_settings_register(rs);
840+ rd->radio_settings = rs;
841+
842+ if (ofono_modem_get_integer(rd->modem, "Slot") == 0)
843+ radio_data_0 = rd;
844+ else
845+ radio_data_1 = rd;
846+
847+ rd->virt_tbl->query_rat_mode(rs, ril_after_query_rat_mode, rs);
848 }
849
850+static struct ofono_radio_settings_driver driver;
851+
852 static int ril_radio_settings_probe(struct ofono_radio_settings *rs,
853 unsigned int vendor, void *user)
854 {
855@@ -311,6 +785,7 @@
856 return -ENOMEM;
857 }
858
859+ rsd->virt_tbl = &driver;
860 rsd->ril = g_ril_clone(rs_init_data->gril);
861 rsd->modem = rs_init_data->modem;
862
863@@ -324,8 +799,12 @@
864 void ril_radio_settings_remove(struct ofono_radio_settings *rs)
865 {
866 struct radio_data *rd = ofono_radio_settings_get_data(rs);
867+
868 ofono_radio_settings_set_data(rs, NULL);
869
870+ if (rd->gprs_atom_watch)
871+ __ofono_modem_remove_atom_watch(rd->modem, rd->gprs_atom_watch);
872+
873 g_ril_unref(rd->ril);
874 g_free(rd);
875 }
876
877=== modified file 'drivers/rilmodem/radio-settings.h'
878--- drivers/rilmodem/radio-settings.h 2015-07-31 13:44:26 +0000
879+++ drivers/rilmodem/radio-settings.h 2016-07-19 15:19:28 +0000
880@@ -19,11 +19,30 @@
881 *
882 */
883
884+struct switch_data;
885+
886 struct radio_data {
887+ struct ofono_radio_settings_driver *virt_tbl;
888 GRil *ril;
889 struct ofono_modem *modem;
890+ struct ofono_radio_settings *radio_settings;
891 gboolean fast_dormancy;
892 gboolean pending_fd;
893+ int rat_mode;
894+ int pending_mode;
895+ unsigned available_rats;
896+ int ril_rats;
897+ char modem_uuid[RIL_MAX_UUID_LENGTH];
898+ struct switch_data *switch_d;
899+ unsigned gprs_atom_watch;
900+};
901+
902+struct switch_data {
903+ struct radio_data *rd_1;
904+ struct radio_data *rd_2;
905+ enum ofono_radio_access_mode mode_to_switch;
906+ int pending_msgs;
907+ struct cb_data *cbd;
908 };
909
910 void ril_delayed_register(const struct ofono_error *error, void *user_data);
911
912=== modified file 'gril/grilreply.c'
913--- gril/grilreply.c 2016-06-28 15:26:37 +0000
914+++ gril/grilreply.c 2016-07-19 15:19:28 +0000
915@@ -1477,8 +1477,11 @@
916 reply->phase = parcel_r_int32(&rilp);
917 reply->rat = parcel_r_int32(&rilp);
918 modem_uuid = parcel_r_string(&rilp);
919- if (modem_uuid != NULL)
920- strcpy(reply->modem_uuid, modem_uuid);
921+ if (modem_uuid != NULL) {
922+ strncpy(reply->modem_uuid, modem_uuid,
923+ sizeof(reply->modem_uuid) - 1);
924+ g_free(modem_uuid);
925+ }
926
927 reply->status = parcel_r_int32(&rilp);
928
929@@ -1552,7 +1555,10 @@
930 reply->modem_uuid,
931 ril_rc_status_to_string(reply->status));
932
933- g_ril_print_response(gril, message);
934+ if (message->unsolicited)
935+ g_ril_print_unsol(gril, message);
936+ else
937+ g_ril_print_response(gril, message);
938
939 end:
940 return reply;
941
942=== modified file 'include/gprs.h'
943--- include/gprs.h 2015-01-28 13:58:34 +0000
944+++ include/gprs.h 2016-07-19 15:19:28 +0000
945@@ -46,10 +46,6 @@
946 ofono_gprs_cb_t cb, void *data);
947 void (*attached_status)(struct ofono_gprs *gprs,
948 ofono_gprs_status_cb_t cb, void *data);
949- void (*set_ia_apn)(struct ofono_gprs *gprs, const char *apn,
950- enum ofono_gprs_proto proto, const char *user,
951- const char *passwd, const char *mccmnc,
952- ofono_gprs_cb_t cb, void *data);
953 };
954
955 enum gprs_suspend_cause {
956@@ -82,6 +78,8 @@
957 unsigned int min, unsigned int max);
958 void ofono_gprs_add_context(struct ofono_gprs *gprs,
959 struct ofono_gprs_context *gc);
960+const struct ofono_gprs_primary_context *ofono_gprs_get_ia_apn(
961+ struct ofono_gprs *gprs, char *mccmnc);
962
963 #ifdef __cplusplus
964 }
965
966=== modified file 'plugins/ril.c'
967--- plugins/ril.c 2016-06-30 17:41:18 +0000
968+++ plugins/ril.c 2016-07-19 15:19:28 +0000
969@@ -128,6 +128,33 @@
970 return RILMODEM;
971 }
972
973+/*
974+ * oFono moves to "Online" state only when told to online the modem AND there is
975+ * a SIM a card. However, we want to have RadioSettings even when there is no
976+ * SIM, but we also want it *only* when we are online. Normally, ofono atoms are
977+ * created/destroyed when the ofono state changes, but for this atom the ofono
978+ * states do not fit, as we do never move from Offline state if there is no SIM.
979+ * Therefore, we handle this atom on modem onlining/offlining.
980+ */
981+static void manage_radio_settings_atom(struct ofono_modem *modem)
982+{
983+ struct ril_data *rd = ofono_modem_get_data(modem);
984+ struct ofono_radio_settings *rs;
985+
986+ rs = __ofono_atom_find(OFONO_ATOM_TYPE_RADIO_SETTINGS, modem);
987+
988+ if (rd->ofono_online && rs == NULL) {
989+ struct ril_radio_settings_driver_data rs_data =
990+ { rd->ril, modem };
991+
992+ ofono_radio_settings_create(modem, rd->vendor,
993+ get_driver_type(rd, OFONO_ATOM_TYPE_RADIO_SETTINGS),
994+ &rs_data);
995+ } else if(!rd->ofono_online && rs != NULL) {
996+ ofono_radio_settings_remove(rs);
997+ }
998+}
999+
1000 static void ril_send_power(struct ril_data *rd, ofono_bool_t online,
1001 GRilResponseFunc func, gpointer user_data)
1002 {
1003@@ -206,6 +233,8 @@
1004
1005 DBG("%s: set_online OK: rd->ofono_online: %d",
1006 __func__, rd->ofono_online);
1007+ manage_radio_settings_atom(modem);
1008+
1009 CALLBACK_WITH_SUCCESS(cb, rd->set_online_cbd->data);
1010
1011 g_free(rd->set_online_cbd);
1012@@ -286,7 +315,6 @@
1013 struct ril_data *rd = ofono_modem_get_data(modem);
1014 struct ril_voicecall_driver_data vc_data = { rd->ril, modem };
1015 struct ril_sim_data sim_data;
1016- struct ril_radio_settings_driver_data rs_data = { rd->ril, modem };
1017
1018 DBG("");
1019
1020@@ -306,16 +334,6 @@
1021
1022 rd->sim = ofono_sim_create(modem, rd->vendor,
1023 get_driver_type(rd, OFONO_ATOM_TYPE_SIM), &sim_data);
1024-
1025- /*
1026- * We need to create radio settings here so FastDormancy property is
1027- * available even when there is no SIM (no SIM -> post_sim and
1028- * post_online are not called) so we can make the modem enter low power
1029- * state in that case.
1030- */
1031- ofono_radio_settings_create(modem, rd->vendor,
1032- get_driver_type(rd, OFONO_ATOM_TYPE_RADIO_SETTINGS),
1033- &rs_data);
1034 }
1035
1036 void ril_post_sim(struct ofono_modem *modem)
1037@@ -334,7 +352,7 @@
1038 get_driver_type(rd, OFONO_ATOM_TYPE_PHONEBOOK), modem);
1039 }
1040
1041-static void create_post_online_atoms(struct ofono_modem *modem)
1042+void ril_post_online(struct ofono_modem *modem)
1043 {
1044 struct ril_data *rd = ofono_modem_get_data(modem);
1045 struct ofono_gprs *gprs;
1046@@ -382,47 +400,6 @@
1047 }
1048 }
1049
1050-static void get_radio_caps_cb(struct ril_msg *message, gpointer user_data)
1051-{
1052- struct ofono_modem *modem = user_data;
1053- struct ril_data *rd = ofono_modem_get_data(modem);
1054- struct reply_radio_capability *caps;
1055-
1056- if (message->error == RIL_E_SUCCESS) {
1057- caps = g_ril_reply_parse_get_radio_capability(rd->ril, message);
1058- if (caps != NULL && (caps->rat & RIL_RAF_LTE)) {
1059- ofono_modem_set_boolean(modem,
1060- MODEM_PROP_LTE_CAPABLE, TRUE);
1061- g_free(caps);
1062- }
1063- } else {
1064- ofono_error("%s: RIL error %s", __func__,
1065- ril_error_to_string(message->error));
1066- }
1067-
1068- create_post_online_atoms(modem);
1069-}
1070-
1071-void ril_post_online(struct ofono_modem *modem)
1072-{
1073- struct ril_data *rd = ofono_modem_get_data(modem);
1074- ofono_bool_t lte_cap;
1075-
1076- /* Radio ON -> we can ask for capabilities */
1077- if (g_ril_get_version(rd->ril) >= 11) {
1078- if (g_ril_send(rd->ril, RIL_REQUEST_GET_RADIO_CAPABILITY, NULL,
1079- get_radio_caps_cb, modem, NULL))
1080- return;
1081-
1082- ofono_error("%s: error sending GET_RADIO_CAPABILITY", __func__);
1083- }
1084-
1085- lte_cap = getenv("OFONO_RIL_RAT_LTE") ? TRUE : FALSE;
1086- ofono_modem_set_boolean(modem, MODEM_PROP_LTE_CAPABLE, lte_cap);
1087-
1088- create_post_online_atoms(modem);
1089-}
1090-
1091 static void ril_set_online_cb(struct ril_msg *message, gpointer user_data)
1092 {
1093 struct ril_data *rd = user_data;
1094@@ -449,11 +426,14 @@
1095 static gboolean set_online_done_cb(gpointer user_data)
1096 {
1097 struct cb_data *cbd = user_data;
1098- struct ril_data *rd = cbd->user;
1099+ struct ofono_modem *modem = cbd->user;
1100+ struct ril_data *rd = ofono_modem_get_data(modem);
1101 ofono_modem_online_cb_t cb = cbd->cb;
1102
1103 DBG("%s: set_online OK: rd->ofono_online: %d",
1104 __func__, rd->ofono_online);
1105+ manage_radio_settings_atom(modem);
1106+
1107 CALLBACK_WITH_SUCCESS(cb, cbd->data);
1108 g_free(cbd);
1109
1110@@ -464,7 +444,7 @@
1111 ofono_modem_online_cb_t callback, void *data)
1112 {
1113 struct ril_data *rd = ofono_modem_get_data(modem);
1114- struct cb_data *cbd = cb_data_new(callback, data, rd);
1115+ struct cb_data *cbd = cb_data_new(callback, data, modem);
1116
1117 rd->ofono_online = online;
1118
1119
1120=== modified file 'src/gprs.c'
1121--- src/gprs.c 2016-06-28 15:26:37 +0000
1122+++ src/gprs.c 2016-07-19 15:19:28 +0000
1123@@ -3444,32 +3444,20 @@
1124 return gprs->contexts->data;
1125 }
1126
1127-static void set_ia_apn_cb(const struct ofono_error *error, void *data)
1128-{
1129- if (error->type != OFONO_ERROR_TYPE_NO_ERROR)
1130- ofono_error("Could not set IA APN");
1131-}
1132-
1133-static void set_ia_apn(struct ofono_gprs *gprs)
1134+const struct ofono_gprs_primary_context *ofono_gprs_get_ia_apn(
1135+ struct ofono_gprs *gprs, char *mccmnc)
1136 {
1137 struct pri_context *ctx = gprs_context_for_ia(gprs);
1138- struct ofono_gprs_primary_context *ofono_ctx;
1139- char mccmnc[OFONO_MAX_MCC_LENGTH + OFONO_MAX_MNC_LENGTH + 1];
1140 const char *mcc = ofono_sim_get_mcc(gprs->sim);
1141 const char *mnc = ofono_sim_get_mnc(gprs->sim);
1142
1143 if (ctx == NULL)
1144- return;
1145-
1146- ofono_ctx = &ctx->context;
1147+ return NULL;
1148
1149 strcpy(mccmnc, mcc);
1150 strcpy(mccmnc + strlen(mcc), mnc);
1151
1152- gprs->driver->set_ia_apn(gprs, ofono_ctx->apn, ofono_ctx->proto,
1153- ofono_ctx->username,
1154- ofono_ctx->password, mccmnc,
1155- set_ia_apn_cb, gprs);
1156+ return &ctx->context;
1157 }
1158
1159 static void ofono_gprs_finish_register(struct ofono_gprs *gprs)
1160@@ -3481,9 +3469,6 @@
1161 if (gprs->contexts == NULL) /* Automatic provisioning failed */
1162 add_context(gprs, NULL, OFONO_GPRS_CONTEXT_TYPE_INTERNET);
1163
1164- if (gprs->driver->set_ia_apn)
1165- set_ia_apn(gprs);
1166-
1167 if (!g_dbus_register_interface(conn, path,
1168 OFONO_CONNECTION_MANAGER_INTERFACE,
1169 manager_methods, manager_signals, NULL,

Subscribers

People subscribed via source and target branches

to all changes: