Merge lp:~phablet-team/ofono/vivid-update-1 into lp:~phablet-team/ofono/ubuntu

Proposed by Tony Espy
Status: Merged
Approved by: Alfonso Sanchez-Beato
Approved revision: 6882
Merged at revision: 6882
Proposed branch: lp:~phablet-team/ofono/vivid-update-1
Merge into: lp:~phablet-team/ofono/ubuntu
Diff against target: 3916 lines (+2429/-479)
35 files modified
Makefile.am (+4/-3)
debian/changelog (+16/-0)
doc/mtk-settings-api.txt (+49/-0)
drivers/mtkmodem/mtk_constants.h (+1/-0)
drivers/mtkmodem/mtkreply.c (+5/-6)
drivers/mtkmodem/mtkrequest.c (+11/-0)
drivers/mtkmodem/mtkrequest.h (+6/-0)
drivers/mtkmodem/mtksettings.c (+261/-0)
drivers/mtkmodem/mtksettings.h (+43/-0)
drivers/mtkmodem/mtkutil.c (+2/-0)
drivers/mtkmodem/mtkutil.h (+2/-0)
drivers/mtkmodem/radio-settings.c (+5/-3)
drivers/rilmodem/gprs.c (+18/-14)
drivers/rilmodem/network-registration.c (+2/-1)
drivers/rilmodem/phonebook.c (+1054/-0)
drivers/rilmodem/radio-settings.c (+8/-0)
drivers/rilmodem/rilmodem.c (+2/-0)
drivers/rilmodem/rilmodem.h (+3/-0)
drivers/rilmodem/sim.c (+73/-53)
gril/grilreply.c (+233/-173)
gril/grilreply.h (+7/-2)
gril/parcel.c (+35/-0)
gril/parcel.h (+7/-0)
include/sim.h (+23/-1)
plugins/mtk.c (+307/-109)
plugins/ril.c (+2/-62)
src/sim.c (+30/-2)
src/simfs.c (+107/-7)
src/simfs.h (+8/-5)
src/simutil.c (+2/-0)
src/simutil.h (+1/-0)
test/set-3g-slot (+20/-0)
unit/test-grilreply.c (+48/-34)
unit/test-mtkreply.c (+4/-4)
unit/test-mtkrequest.c (+30/-0)
To merge this branch: bzr merge lp:~phablet-team/ofono/vivid-update-1
Reviewer Review Type Date Requested Status
Alfonso Sanchez-Beato Approve
PS Jenkins bot continuous-integration Approve
Review via email: mp+242287@code.launchpad.net

Commit message

  * grilreply.c, parcel.c, rilmodem: merge data and voice reg parsing
    This change splits the orginal parsing code for data and voice
    registration replies, cleaning up some of original parsing code
    which wasn't very elegant.
  * Makefile.am, rilmodem, src/sim*.*, include/sim.h,
    plugins/mtk.c, ril.c: enable SIM phonebook import support
  * rilmodem/sim.c, plugins/mtk.c, ril.c: fix SIM interface signals (LP: #1376250)
  * plugins/mtk.c: fix krillin slow socket disconnection (LP: #1388030)
  * Makefile.am, doc/mtk-settings-api.txt, mtkmodem,
    plugins/mtk.c, test, unit: support krillin 3g slot switch (LP: #1373388)

Description of the change

This change brings vivid up to the latest HEAD of the rilmodem git tree. Changes include:

 * Merge of RIL data and voice reg parsing code. This change splits the orginal parsing code for data and voice registration replies, cleaning up some of original parsing code which wasn't very elegant.

 * enable SIM phonebook import support

 * fix SIM interface signals (LP: #1376250)

 * fix krillin slow socket disconnection (LP: #1388030)

 * support krillin 3g slot switch (LP: #1373388)

To post a comment you must log in.
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Approve (continuous-integration)
Revision history for this message
Alfonso Sanchez-Beato (alfonsosanchezbeato) wrote :

Diff seems good, approving.

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

Tested on krillin, image #169, following https://wiki.ubuntu.com/Process/Merges/TestPlans/ofono

All test cases but the supplementary services ones executed and passed, plus tests for targeted bugs and new features.

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 2014-07-29 21:21:56 +0000
3+++ Makefile.am 2014-11-20 00:09:27 +0000
4@@ -146,7 +146,8 @@
5 drivers/mtkmodem/mtkreply.c \
6 drivers/mtkmodem/voicecall.c \
7 drivers/mtkmodem/gprs.c \
8- drivers/mtkmodem/radio-settings.c
9+ drivers/mtkmodem/radio-settings.c \
10+ drivers/mtkmodem/mtksettings.c
11
12 builtin_modules += rilmodem
13 builtin_sources += drivers/rilmodem/rilmodem.h \
14@@ -166,8 +167,8 @@
15 drivers/rilmodem/call-settings.c \
16 drivers/rilmodem/call-forwarding.c \
17 drivers/rilmodem/radio-settings.c \
18- drivers/rilmodem/call-barring.c
19-
20+ drivers/rilmodem/call-barring.c \
21+ drivers/rilmodem/phonebook.c
22 endif
23
24 if ISIMODEM
25
26=== modified file 'debian/changelog'
27--- debian/changelog 2014-10-10 08:53:32 +0000
28+++ debian/changelog 2014-11-20 00:09:27 +0000
29@@ -1,3 +1,19 @@
30+ofono (1.12.bzr6882+14.10.20141120-0ubuntu1) UNRELEASED; urgency=medium
31+
32+ [ Alfonso Sanchez-Beato ]
33+ * grilreply.c, parcel.c, rilmodem: merge data and voice reg parsing
34+ This change splits the orginal parsing code for data and voice
35+ registration replies, cleaning up some of original parsing code
36+ which wasn't very elegant.
37+ * Makefile.am, rilmodem, src/sim*.*, include/sim.h,
38+ plugins/mtk.c, ril.c: enable SIM phonebook import support
39+ * rilmodem/sim.c, plugins/mtk.c, ril.c: fix SIM interface signals (LP: #1376250)
40+ * plugins/mtk.c: fix krillin slow socket disconnection (LP: #1388030)
41+ * Makefile.am, doc/mtk-settings-api.txt, mtkmodem,
42+ plugins/mtk.c, test, unit: support krillin 3g slot switch (LP: #1373388)
43+
44+ -- Ubuntu daily release <ps-jenkins@lists.canonical.com> Wed, 19 Nov 2014 18:28:00 -0500
45+
46 ofono (1.12.bzr6880+14.10.20141010-0ubuntu1) utopic; urgency=medium
47
48 [ Alfonso Sanchez-Beato ]
49
50=== added file 'doc/mtk-settings-api.txt'
51--- doc/mtk-settings-api.txt 1970-01-01 00:00:00 +0000
52+++ doc/mtk-settings-api.txt 2014-11-20 00:09:27 +0000
53@@ -0,0 +1,49 @@
54+MediaTek settings hierarchy
55+===========================
56+
57+Service org.ofono
58+Interface org.ofono.MtkSettings
59+Object path [variable prefix]/{modem0,modem1,...}
60+
61+Methods dict GetProperties()
62+
63+ Returns all MtkSettings properties. See the
64+ properties section for available properties.
65+
66+ Possible Errors: [service].Error.InProgress
67+ [service].Error.NotImplemented
68+ [service].Error.Failed
69+
70+ void SetProperty(string name, variant value)
71+
72+ Changes the value of the specified property. Only
73+ properties that are listed as readwrite are
74+ changeable. On success a PropertyChanged signal
75+ will be emitted.
76+
77+ Possible Errors: [service].Error.InProgress
78+ [service].Error.NotImplemented
79+ [service].Error.InvalidArguments
80+ [service].Error.Failed
81+
82+Signals PropertyChanged(string property, variant value)
83+
84+ This signal indicates a changed value of the given
85+ property.
86+
87+Properties boolean Has3G [readwrite]
88+
89+ If true, the modem has 3G capabilities, otherwise it is
90+ just 2G. Only one of the modems can have this set at a
91+ time (note that in fact the modem hardware is shared
92+ among all ofono MTK modems, and that each ofono MTK
93+ modem represents one physical slot in the phone).
94+
95+ When we set the property to TRUE, all MTK modems are
96+ reset, and after that this property will be false for
97+ all modems except for the one for which we set the
98+ property. Note that setting this property to FALSE is
99+ not allowed to avoid confusion, as one and only one of
100+ the modems must have it set to true and we can have
101+ the case of more than two modems.
102+
103
104=== modified file 'drivers/mtkmodem/mtk_constants.h'
105--- drivers/mtkmodem/mtk_constants.h 2014-07-28 07:12:26 +0000
106+++ drivers/mtkmodem/mtk_constants.h 2014-11-20 00:09:27 +0000
107@@ -30,6 +30,7 @@
108 #define MTK_RIL_REQUEST_RADIO_POWERON 2033
109 #define MTK_RIL_REQUEST_SET_CALL_INDICATION 2036
110 #define MTK_RIL_REQUEST_GET_3G_CAPABILITY 2038
111+#define MTK_RIL_REQUEST_SET_3G_CAPABILITY 2039
112 #define MTK_RIL_REQUEST_SET_FD_MODE 2073
113
114 /* RIL Unsolicited Messages */
115
116=== modified file 'drivers/mtkmodem/mtkreply.c'
117--- drivers/mtkmodem/mtkreply.c 2014-07-24 08:31:18 +0000
118+++ drivers/mtkmodem/mtkreply.c 2014-11-20 00:09:27 +0000
119@@ -35,7 +35,7 @@
120 const struct ril_msg *message)
121 {
122 struct parcel rilp;
123- int sim_3g, numint, slot;
124+ int slot_3g, numint;
125
126 g_ril_init_parcel(message, &rilp);
127
128@@ -49,19 +49,18 @@
129 * Bitmap with 3g capability per slot. Reply is the same regardless of
130 * the socket used to sent the request.
131 */
132- sim_3g = parcel_r_int32(&rilp);
133+ slot_3g = parcel_r_int32(&rilp);
134
135 if (rilp.malformed) {
136 ofono_error("%s: malformed parcel", __func__);
137 goto error;
138 }
139
140- g_ril_append_print_buf(gril, "{%d}", sim_3g);
141+ g_ril_append_print_buf(gril, "{%d}", slot_3g);
142 g_ril_print_response(gril, message);
143
144- slot = g_ril_get_slot(gril);
145-
146- return (sim_3g >> slot) & 0x01;
147+ /* Do it zero-based */
148+ return slot_3g - 1;
149
150 error:
151 return -1;
152
153=== modified file 'drivers/mtkmodem/mtkrequest.c'
154--- drivers/mtkmodem/mtkrequest.c 2014-06-12 10:49:29 +0000
155+++ drivers/mtkmodem/mtkrequest.c 2014-11-20 00:09:27 +0000
156@@ -122,3 +122,14 @@
157 g_ril_append_print_buf(gril, "%s)", print_buf);
158 }
159 }
160+
161+void g_mtk_request_set_3g_capability(GRil *gril, struct parcel *rilp)
162+{
163+ int mode = g_ril_get_slot(gril) + 1;
164+
165+ parcel_init(rilp);
166+ parcel_w_int32(rilp, 1);
167+ parcel_w_int32(rilp, mode);
168+
169+ g_ril_append_print_buf(gril, "(%d)", mode);
170+}
171
172=== modified file 'drivers/mtkmodem/mtkrequest.h'
173--- drivers/mtkmodem/mtkrequest.h 2014-06-12 10:49:29 +0000
174+++ drivers/mtkmodem/mtkrequest.h 2014-11-20 00:09:27 +0000
175@@ -102,6 +102,12 @@
176 void g_mtk_request_set_fd_mode(GRil *gril, int mode, int param1,
177 int param2, struct parcel *rilp);
178
179+/*
180+ * Sets the slot to which the GRil object is connected as the one with 3G
181+ * capabilities. This makes the other slot just 2G.
182+ */
183+void g_mtk_request_set_3g_capability(GRil *gril, struct parcel *rilp);
184+
185 #ifdef __cplusplus
186 }
187 #endif
188
189=== added file 'drivers/mtkmodem/mtksettings.c'
190--- drivers/mtkmodem/mtksettings.c 1970-01-01 00:00:00 +0000
191+++ drivers/mtkmodem/mtksettings.c 2014-11-20 00:09:27 +0000
192@@ -0,0 +1,261 @@
193+/*
194+ *
195+ * oFono - Open Source Telephony
196+ *
197+ * Copyright (C) 2014 Canonical Ltd.
198+ *
199+ * This program is free software; you can redistribute it and/or modify
200+ * it under the terms of the GNU General Public License version 2 as
201+ * published by the Free Software Foundation.
202+ *
203+ * This program is distributed in the hope that it will be useful,
204+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
205+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
206+ * GNU General Public License for more details.
207+ *
208+ * You should have received a copy of the GNU General Public License
209+ * along with this program; if not, write to the Free Software
210+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
211+ *
212+ */
213+
214+#ifdef HAVE_CONFIG_H
215+#include <config.h>
216+#endif
217+#include <string.h>
218+#include <stdlib.h>
219+#include <stdio.h>
220+#include <errno.h>
221+#include <glib.h>
222+#include <gdbus.h>
223+#include <ofono.h>
224+
225+#define OFONO_API_SUBJECT_TO_CHANGE
226+#include <ofono/plugin.h>
227+#include <ofono/log.h>
228+#include <ofono/modem.h>
229+#include <ofono/dbus.h>
230+
231+#include "drivers/mtkmodem/mtk_constants.h"
232+#include "drivers/mtkmodem/mtkrequest.h"
233+#include "drivers/mtkmodem/mtkutil.h"
234+#include "mtksettings.h"
235+
236+#define MTK_SETTINGS_INTERFACE "org.ofono.MtkSettings"
237+
238+struct mtk_settings_data {
239+ struct ofono_modem *modem;
240+ GRil *ril;
241+ ofono_bool_t has_3g;
242+ ofono_bool_t has_3g_pending;
243+ DBusMessage *pending;
244+};
245+
246+static void set_3g(struct mtk_settings_data *msd, ofono_bool_t has_3g)
247+{
248+ DBusConnection *conn = ofono_dbus_get_connection();
249+ const char *path = ofono_modem_get_path(msd->modem);
250+ dbus_bool_t value = has_3g;
251+
252+ if (msd->has_3g == has_3g)
253+ return;
254+
255+ ofono_dbus_signal_property_changed(conn, path, MTK_SETTINGS_INTERFACE,
256+ "Has3G", DBUS_TYPE_BOOLEAN,
257+ &value);
258+ msd->has_3g = has_3g;
259+}
260+
261+static void set_3g_cb(struct ril_msg *message, gpointer user_data)
262+{
263+ struct mtk_settings_data *msd = user_data;
264+ DBusMessage *reply;
265+
266+ if (message->error != RIL_E_SUCCESS) {
267+ ofono_error("%s: Error setting 3G", __func__);
268+
269+ msd->has_3g_pending = msd->has_3g;
270+
271+ reply = __ofono_error_failed(msd->pending);
272+ __ofono_dbus_pending_reply(&msd->pending, reply);
273+
274+ return;
275+ }
276+
277+ g_ril_print_response_no_args(msd->ril, message);
278+
279+ reply = dbus_message_new_method_return(msd->pending);
280+ __ofono_dbus_pending_reply(&msd->pending, reply);
281+
282+ set_3g(msd, msd->has_3g_pending);
283+
284+ mtk_reset_all_modems();
285+}
286+
287+static DBusMessage *set_property(DBusConnection *conn, DBusMessage *msg,
288+ void *data)
289+{
290+ struct mtk_settings_data *msd = data;
291+ DBusMessageIter iter;
292+ DBusMessageIter var;
293+ const char *property;
294+
295+ if (msd->pending)
296+ return __ofono_error_busy(msg);
297+
298+ if (!dbus_message_iter_init(msg, &iter))
299+ return __ofono_error_invalid_args(msg);
300+
301+ if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_STRING)
302+ return __ofono_error_invalid_args(msg);
303+
304+ dbus_message_iter_get_basic(&iter, &property);
305+ dbus_message_iter_next(&iter);
306+
307+ if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT)
308+ return __ofono_error_invalid_args(msg);
309+
310+ dbus_message_iter_recurse(&iter, &var);
311+
312+ if (g_strcmp0(property, "Has3G") == 0) {
313+ dbus_bool_t value;
314+ struct parcel rilp;
315+
316+ if (dbus_message_iter_get_arg_type(&var) != DBUS_TYPE_BOOLEAN)
317+ return __ofono_error_invalid_args(msg);
318+
319+ dbus_message_iter_get_basic(&var, &value);
320+
321+ if (msd->has_3g_pending == (ofono_bool_t) value)
322+ return dbus_message_new_method_return(msg);
323+
324+ /*
325+ * We can only set to true, as setting to false could be
326+ * confusing in a multi-sim environment (>2 SIM)
327+ */
328+ if (value == FALSE)
329+ return __ofono_error_invalid_args(msg);
330+
331+ g_mtk_request_set_3g_capability(msd->ril, &rilp);
332+
333+ if (g_ril_send(msd->ril, MTK_RIL_REQUEST_SET_3G_CAPABILITY,
334+ &rilp, set_3g_cb, msd, NULL) == 0) {
335+ ofono_error("%s: unable to set 3G for slot", __func__);
336+ return __ofono_error_failed(msg);
337+ }
338+
339+ msd->pending = dbus_message_ref(msg);
340+ msd->has_3g_pending = value;
341+
342+ return NULL;
343+ }
344+
345+ return __ofono_error_invalid_args(msg);
346+}
347+
348+static DBusMessage *get_properties(DBusConnection *conn,
349+ DBusMessage *msg, void *data)
350+{
351+ struct mtk_settings_data *msd = data;
352+ DBusMessage *reply;
353+ DBusMessageIter iter;
354+ DBusMessageIter dict;
355+
356+ reply = dbus_message_new_method_return(msg);
357+ if (reply == NULL)
358+ return NULL;
359+
360+ dbus_message_iter_init_append(reply, &iter);
361+
362+ dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY,
363+ OFONO_PROPERTIES_ARRAY_SIGNATURE,
364+ &dict);
365+
366+ ofono_dbus_dict_append(&dict, "Has3G",
367+ DBUS_TYPE_BOOLEAN, &msd->has_3g);
368+
369+ dbus_message_iter_close_container(&iter, &dict);
370+
371+ return reply;
372+}
373+
374+static const GDBusMethodTable mtk_settings_methods[] = {
375+ { GDBUS_ASYNC_METHOD("GetProperties",
376+ NULL, GDBUS_ARGS({ "properties", "a{sv}" }),
377+ get_properties) },
378+ { GDBUS_ASYNC_METHOD("SetProperty",
379+ GDBUS_ARGS({ "property", "s" }, { "value", "v" }),
380+ NULL, set_property) },
381+ { }
382+};
383+
384+static const GDBusSignalTable mtk_settings_signals[] = {
385+ { GDBUS_SIGNAL("PropertyChanged",
386+ GDBUS_ARGS({ "name", "s" }, { "value", "v" })) },
387+ { }
388+};
389+
390+
391+static void register_interface(struct mtk_settings_data *msd)
392+{
393+ DBusConnection *conn = ofono_dbus_get_connection();
394+
395+ if (!g_dbus_register_interface(conn, ofono_modem_get_path(msd->modem),
396+ MTK_SETTINGS_INTERFACE,
397+ mtk_settings_methods,
398+ mtk_settings_signals,
399+ NULL, msd, NULL)) {
400+ ofono_error("Could not create %s interface",
401+ MTK_SETTINGS_INTERFACE);
402+ return;
403+ }
404+
405+ ofono_modem_add_interface(msd->modem, MTK_SETTINGS_INTERFACE);
406+}
407+
408+static void unregister_interface(struct mtk_settings_data *msd)
409+{
410+ DBusConnection *conn = ofono_dbus_get_connection();
411+
412+ ofono_modem_remove_interface(msd->modem, MTK_SETTINGS_INTERFACE);
413+
414+ g_dbus_unregister_interface(conn,
415+ ofono_modem_get_path(msd->modem),
416+ MTK_SETTINGS_INTERFACE);
417+}
418+
419+struct mtk_settings_data *mtk_settings_create(struct ofono_modem *modem,
420+ GRil *ril, ofono_bool_t has_3g)
421+{
422+ struct mtk_settings_data *msd = g_try_malloc0(sizeof(*msd));
423+
424+ DBG("");
425+
426+ if (msd == NULL) {
427+ ofono_error("%s: Cannot allocate mtk_settings_data", __func__);
428+ return NULL;
429+ }
430+
431+ msd->modem = modem;
432+ msd->ril = g_ril_clone(ril);
433+
434+ msd->has_3g = has_3g;
435+ msd->has_3g_pending = has_3g;
436+
437+ register_interface(msd);
438+
439+ return msd;
440+}
441+
442+void mtk_settings_remove(struct mtk_settings_data *msd)
443+{
444+ DBG("");
445+
446+ if (msd == NULL)
447+ return;
448+
449+ unregister_interface(msd);
450+
451+ g_ril_unref(msd->ril);
452+ g_free(msd);
453+}
454
455=== added file 'drivers/mtkmodem/mtksettings.h'
456--- drivers/mtkmodem/mtksettings.h 1970-01-01 00:00:00 +0000
457+++ drivers/mtkmodem/mtksettings.h 2014-11-20 00:09:27 +0000
458@@ -0,0 +1,43 @@
459+/*
460+ *
461+ * MTK driver for ofono/rilmodem
462+ *
463+ * Copyright (C) 2014 Canonical Ltd.
464+ *
465+ * This program is free software; you can redistribute it and/or modify
466+ * it under the terms of the GNU General Public License version 2 as
467+ * published by the Free Software Foundation.
468+ *
469+ * This program is distributed in the hope that it will be useful,
470+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
471+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
472+ * GNU General Public License for more details.
473+ *
474+ * You should have received a copy of the GNU General Public License
475+ * along with this program; if not, write to the Free Software
476+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
477+ *
478+ */
479+
480+#ifndef MTKSETTINGS_H
481+#define MTKSETTINGS_H
482+
483+#include <ofono/types.h>
484+
485+#include "gril.h"
486+
487+#ifdef __cplusplus
488+extern "C" {
489+#endif
490+
491+struct mtk_settings_data;
492+
493+struct mtk_settings_data *mtk_settings_create(struct ofono_modem *modem,
494+ GRil *ril, ofono_bool_t has_3g);
495+void mtk_settings_remove(struct mtk_settings_data *msd);
496+
497+#ifdef __cplusplus
498+}
499+#endif
500+
501+#endif /* MTKSETTINGS_H */
502
503=== modified file 'drivers/mtkmodem/mtkutil.c'
504--- drivers/mtkmodem/mtkutil.c 2014-07-28 07:12:26 +0000
505+++ drivers/mtkmodem/mtkutil.c 2014-11-20 00:09:27 +0000
506@@ -41,6 +41,8 @@
507 return "MTK_RIL_REQUEST_SET_CALL_INDICATION";
508 case MTK_RIL_REQUEST_GET_3G_CAPABILITY:
509 return "MTK_RIL_REQUEST_GET_3G_CAPABILITY";
510+ case MTK_RIL_REQUEST_SET_3G_CAPABILITY:
511+ return "MTK_RIL_REQUEST_SET_3G_CAPABILITY";
512 case MTK_RIL_REQUEST_SET_FD_MODE:
513 return "MTK_RIL_REQUEST_SET_FD_MODE";
514 default:
515
516=== modified file 'drivers/mtkmodem/mtkutil.h'
517--- drivers/mtkmodem/mtkutil.h 2014-07-31 06:45:32 +0000
518+++ drivers/mtkmodem/mtkutil.h 2014-11-20 00:09:27 +0000
519@@ -34,6 +34,8 @@
520 void mtk_set_attach_state(struct ofono_modem *modem, ofono_bool_t attached);
521 void mtk_detach_received(struct ofono_modem *modem);
522
523+void mtk_reset_all_modems(void);
524+
525 struct mtk_gprs_data {
526 GRil *gril;
527 struct ofono_modem *modem;
528
529=== modified file 'drivers/mtkmodem/radio-settings.c'
530--- drivers/mtkmodem/radio-settings.c 2014-09-25 12:16:25 +0000
531+++ drivers/mtkmodem/radio-settings.c 2014-11-20 00:09:27 +0000
532@@ -132,7 +132,7 @@
533 struct radio_data *rd = ofono_radio_settings_get_data(rs);
534 ofono_radio_settings_modem_rats_query_cb_t cb = cbd->cb;
535 ofono_bool_t modem_rats[OFONO_RADIO_ACCESS_MODE_LAST] = { FALSE };
536- int is_3g;
537+ int slot_3g, is_3g;
538
539 if (message->error != RIL_E_SUCCESS) {
540 ofono_error("%s: error %s", __func__,
541@@ -141,13 +141,15 @@
542 return;
543 }
544
545- is_3g = g_mtk_reply_parse_get_3g_capability(rd->ril, message);
546- if (is_3g < 0) {
547+ slot_3g = g_mtk_reply_parse_get_3g_capability(rd->ril, message);
548+ if (slot_3g < 0) {
549 ofono_error("%s: parse error", __func__);
550 CALLBACK_WITH_FAILURE(cb, NULL, cbd->data);
551 return;
552 }
553
554+ is_3g = (g_ril_get_slot(rd->ril) == slot_3g);
555+
556 modem_rats[OFONO_RADIO_ACCESS_MODE_GSM] = TRUE;
557
558 if (is_3g) {
559
560=== modified file 'drivers/rilmodem/gprs.c'
561--- drivers/rilmodem/gprs.c 2014-09-26 14:34:59 +0000
562+++ drivers/rilmodem/gprs.c 2014-11-20 00:09:27 +0000
563@@ -175,7 +175,7 @@
564 ofono_gprs_status_cb_t cb = cbd->cb;
565 struct ofono_gprs *gprs = cbd->user;
566 struct ril_gprs_data *gd = ofono_gprs_get_data(gprs);
567- struct reply_reg_state *reply;
568+ struct reply_data_reg_state *reply;
569 gboolean attached = FALSE;
570 gboolean notify_status = FALSE;
571 int old_status;
572@@ -189,7 +189,8 @@
573 goto error;
574 }
575
576- if ((reply = g_ril_reply_parse_reg_state(gd->ril, message)) == NULL)
577+ if ((reply = g_ril_reply_parse_data_reg_state(gd->ril, message))
578+ == NULL)
579 goto error;
580
581 /*
582@@ -207,8 +208,8 @@
583 * function. A valid ofono cb exists.
584 */
585
586- if (gd->rild_status != reply->status) {
587- gd->rild_status = reply->status;
588+ if (gd->rild_status != reply->reg_state.status) {
589+ gd->rild_status = reply->reg_state.status;
590
591 if (cb == NULL)
592 notify_status = TRUE;
593@@ -219,12 +220,15 @@
594 * attached status set by the core GPRS code ( controlled
595 * by the ConnnectionManager's 'Powered' property ).
596 */
597- attached = (reply->status == NETWORK_REGISTRATION_STATUS_REGISTERED ||
598- reply->status == NETWORK_REGISTRATION_STATUS_ROAMING);
599+ attached = (reply->reg_state.status ==
600+ NETWORK_REGISTRATION_STATUS_REGISTERED ||
601+ reply->reg_state.status ==
602+ NETWORK_REGISTRATION_STATUS_ROAMING);
603
604 if (attached && gd->ofono_attached == FALSE) {
605 DBG("attached=true; ofono_attached=false; return !REGISTERED");
606- reply->status = NETWORK_REGISTRATION_STATUS_NOT_REGISTERED;
607+ reply->reg_state.status =
608+ NETWORK_REGISTRATION_STATUS_NOT_REGISTERED;
609
610 /*
611 * Further optimization so that if ril_status ==
612@@ -234,7 +238,7 @@
613 * As is, this results in unecessary status notify calls
614 * when nothing has changed.
615 */
616- if (notify_status && reply->status == old_status)
617+ if (notify_status && reply->reg_state.status == old_status)
618 notify_status = FALSE;
619 }
620
621@@ -278,22 +282,22 @@
622 NETWORK_REGISTRATION_STATUS_ROAMING)) {
623 DBG("calling ofono_gprs_detached_notify()");
624 ofono_gprs_detached_notify(gprs);
625- reply->tech = RADIO_TECH_UNKNOWN;
626+ reply->reg_state.tech = RADIO_TECH_UNKNOWN;
627 } else {
628 DBG("calling ofono_gprs_status_notify()");
629- ofono_gprs_status_notify(gprs, reply->status);
630+ ofono_gprs_status_notify(gprs, reply->reg_state.status);
631 }
632 }
633
634- if (gd->tech != reply->tech) {
635- gd->tech = reply->tech;
636+ if (gd->tech != reply->reg_state.tech) {
637+ gd->tech = reply->reg_state.tech;
638
639 ofono_gprs_bearer_notify(gprs,
640- ril_tech_to_bearer_tech(reply->tech));
641+ ril_tech_to_bearer_tech(reply->reg_state.tech));
642 }
643
644 if (cb)
645- CALLBACK_WITH_SUCCESS(cb, reply->status, cbd->data);
646+ CALLBACK_WITH_SUCCESS(cb, reply->reg_state.status, cbd->data);
647
648 g_free(reply);
649
650
651=== modified file 'drivers/rilmodem/network-registration.c'
652--- drivers/rilmodem/network-registration.c 2014-08-11 12:41:12 +0000
653+++ drivers/rilmodem/network-registration.c 2014-11-20 00:09:27 +0000
654@@ -129,7 +129,8 @@
655 goto error;
656 }
657
658- if ((reply = g_ril_reply_parse_reg_state(nd->ril, message)) == NULL)
659+ if ((reply = g_ril_reply_parse_voice_reg_state(nd->ril, message))
660+ == NULL)
661 goto error;
662
663 nd->tech = reply->tech;
664
665=== added file 'drivers/rilmodem/phonebook.c'
666--- drivers/rilmodem/phonebook.c 1970-01-01 00:00:00 +0000
667+++ drivers/rilmodem/phonebook.c 2014-11-20 00:09:27 +0000
668@@ -0,0 +1,1054 @@
669+/*
670+ *
671+ * oFono - Open Source Telephony - RIL Modem Support
672+ *
673+ * Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
674+ * Copyright (C) ST-Ericsson SA 2010.
675+ * Copyright (C) 2008-2011 Intel Corporation. All rights reserved.
676+ * Copyright (C) 2013 Jolla Ltd
677+ * Contact: Jussi Kangas <jussi.kangas@tieto.com>
678+ * Copyright (C) 2014 Canonical Ltd
679+ *
680+ * This program is free software; you can redistribute it and/or modify
681+ * it under the terms of the GNU General Public License version 2 as
682+ * published by the Free Software Foundation.
683+ *
684+ * This program is distributed in the hope that it will be useful,
685+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
686+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
687+ * GNU General Public License for more details.
688+ *
689+ * You should have received a copy of the GNU General Public License
690+ * along with this program; if not, write to the Free Software
691+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
692+ *
693+ */
694+#ifdef HAVE_CONFIG_H
695+#include <config.h>
696+#endif
697+
698+#define _GNU_SOURCE
699+#include <stdio.h>
700+#include <stdlib.h>
701+#include <string.h>
702+#include <errno.h>
703+#include <stdint.h>
704+
705+#include <glib.h>
706+
707+#include <ofono.h>
708+#include <ofono/log.h>
709+#include <ofono/modem.h>
710+#include <ofono/phonebook.h>
711+#include <sim.h>
712+#include <simfs.h>
713+#include <util.h>
714+
715+#include "gril.h"
716+#include "simutil.h"
717+#include "common.h"
718+
719+#include "rilmodem.h"
720+
721+#define UNUSED 0xFF
722+
723+#define EXT1_CP_SUBADDRESS 1
724+#define EXT1_ADDITIONAL_DATA 2
725+
726+/* TON (Type Of Number) See TS 24.008 */
727+#define TON_MASK 0x70
728+#define TON_INTERNATIONAL 0x10
729+
730+enum constructed_tag {
731+ TYPE_1_TAG = 0xA8,
732+ TYPE_2_TAG = 0xA9,
733+ TYPE_3_TAG = 0xAA
734+};
735+
736+enum file_type_tag {
737+ TYPE_ADN = 0xC0,
738+ TYPE_IAP = 0xC1,
739+ TYPE_EXT1 = 0xC2,
740+ TYPE_SNE = 0xC3,
741+ TYPE_ANR = 0xC4,
742+ TYPE_PBC = 0xC5,
743+ TYPE_GPR = 0xC6,
744+ TYPE_AAS = 0xC7,
745+ TYPE_GAS = 0xC8,
746+ TYPE_UID = 0xC9,
747+ TYPE_EMAIL = 0xCA,
748+ TYPE_CCP1 = 0xCB
749+};
750+
751+struct pb_file_info {
752+ enum constructed_tag pbr_type;
753+ int file_id;
754+ enum file_type_tag file_type;
755+ int file_length;
756+ int record_length;
757+};
758+
759+struct record_to_read {
760+ int file_id;
761+ enum file_type_tag type_tag;
762+ int record_length;
763+ int record;
764+ int adn_idx;
765+ gboolean anr_ext; /* Is it an EXT1 record for ANR? */
766+ gboolean set_by_iap; /* Type 2 file? */
767+};
768+
769+struct phonebook_entry {
770+ int entry;
771+ char *name;
772+ char *number;
773+ char *email;
774+ char *anr;
775+ char *sne;
776+};
777+
778+unsigned char sim_path[] = { 0x3F, 0x00, 0x7F, 0x10 };
779+unsigned char usim_path[] = { 0x3F, 0x00, 0x7F, 0x10, 0x5F, 0x3A };
780+
781+/*
782+ * Table for BCD to utf8 conversion. See table 4.4 in TS 31.102.
783+ * BCD 0x0C indicates pause before sending following digits as DTMF tones.
784+ * BCD 0x0D is a wildcard that means "any digit". These values are mapped to
785+ * ',' and '?', following the Android/iPhone convention for the first and Nokia
786+ * convention for the second (only OEM that I have seen that supports this
787+ * feature). BCD 0x0E is reserved, we convert it to 'r'.
788+ */
789+static const char digit_to_utf8[] = "0123456789*#,?r\0";
790+
791+/* One of these for each record in EF_PBR */
792+struct pb_ref_rec {
793+ GSList *pb_files; /* File ids to read (pb_file_info nodes) */
794+ GSList *pb_next; /* Next file info to read */
795+ GSList *pending_records; /* List of record_to_read */
796+ GSList *next_record; /* Next record_to_read to process */
797+ GTree *phonebook; /* Container of phonebook_entry structures */
798+};
799+
800+struct pb_data {
801+ GSList *pb_refs;
802+ GSList *pb_ref_next;
803+ struct ofono_sim *sim;
804+ struct ofono_sim_context *sim_context;
805+ const unsigned char *df_path;
806+ size_t df_size;
807+};
808+
809+static void read_info_cb(int ok, unsigned char file_status,
810+ int total_length, int record_length,
811+ void *userdata);
812+
813+static gint comp_int(gconstpointer a, gconstpointer b)
814+{
815+ int a_val = GPOINTER_TO_INT(a);
816+ int b_val = GPOINTER_TO_INT(b);
817+
818+ return a_val - b_val;
819+}
820+
821+static const struct pb_file_info *
822+ext1_info(const GSList *pb_files)
823+{
824+ const GSList *l;
825+ for (l = pb_files; l; l = l->next) {
826+ const struct pb_file_info *f_info = l->data;
827+ if (f_info->file_type == TYPE_EXT1)
828+ return f_info;
829+ }
830+
831+ return NULL;
832+}
833+
834+static struct phonebook_entry *handle_adn(size_t len, const unsigned char *msg,
835+ struct pb_ref_rec *ref, int adn_idx)
836+{
837+ unsigned name_length = len - 14;
838+ unsigned number_start = name_length;
839+ unsigned number_length;
840+ unsigned extension_record = UNUSED;
841+ unsigned i, prefix;
842+ char *number = NULL;
843+ char *name = sim_string_to_utf8(msg, name_length);
844+ struct phonebook_entry *new_entry;
845+
846+ /* Length contains also TON & NPI */
847+ number_length = msg[number_start];
848+
849+ if (number_length != UNUSED && number_length != 0) {
850+ number_length--;
851+ /* '+' + number + terminator */
852+ number = g_try_malloc0(2 * number_length + 2);
853+
854+ if (number) {
855+ prefix = 0;
856+
857+ if ((msg[number_start + 1] & TON_MASK)
858+ == TON_INTERNATIONAL) {
859+ number[0] = '+';
860+ prefix = 1;
861+ }
862+
863+ for (i = 0; i < number_length; i++) {
864+
865+ number[2 * i + prefix] =
866+ digit_to_utf8[msg[number_start + 2 + i]
867+ & 0x0f];
868+ number[2 * i + 1 + prefix] =
869+ digit_to_utf8[msg[number_start + 2 + i]
870+ >> 4];
871+ }
872+
873+ extension_record = msg[len - 1];
874+ }
875+ }
876+
877+ DBG("ADN name %s, number %s ", name, number);
878+ DBG("number length %d extension_record %d",
879+ 2 * number_length, extension_record);
880+
881+ if ((name == NULL || *name == '\0') && number == NULL)
882+ goto end;
883+
884+ new_entry = g_try_malloc0(sizeof(*new_entry));
885+ if (new_entry == NULL) {
886+ ofono_error("%s: out of memory", __func__);
887+ goto end;
888+ }
889+
890+ new_entry->name = name;
891+ new_entry->number = number;
892+
893+ DBG("Creating PB entry %d with", adn_idx);
894+ DBG("name %s and number %s", new_entry->name, new_entry->number);
895+
896+ g_tree_insert(ref->phonebook, GINT_TO_POINTER(adn_idx), new_entry);
897+
898+ if (extension_record != UNUSED) {
899+ struct record_to_read *ext_rec =
900+ g_try_malloc0(sizeof(*ext_rec));
901+ const struct pb_file_info *f_info = ext1_info(ref->pb_files);
902+
903+ if (ext_rec && f_info) {
904+ ext_rec->file_id = f_info->file_id;
905+ ext_rec->type_tag = TYPE_EXT1;
906+ ext_rec->record_length = f_info->record_length;
907+ ext_rec->record = extension_record;
908+ ext_rec->adn_idx = adn_idx;
909+
910+ ref->pending_records =
911+ g_slist_prepend(ref->pending_records, ext_rec);
912+ }
913+ }
914+
915+ return new_entry;
916+
917+end:
918+ g_free(name);
919+ g_free(number);
920+
921+ return NULL;
922+}
923+
924+static void handle_iap(size_t len, const unsigned char *msg,
925+ struct pb_ref_rec *ref,
926+ const struct record_to_read *rec_data)
927+{
928+ GSList *l;
929+ size_t i = 0;
930+
931+ for (l = ref->pb_files; l; l = l->next) {
932+ struct pb_file_info *f_info = l->data;
933+ if (f_info->pbr_type == TYPE_2_TAG) {
934+ if (i >= len) {
935+ ofono_error("%s: EF_IAP record too small",
936+ __func__);
937+ return;
938+ }
939+ if (msg[i] != UNUSED) {
940+ struct record_to_read *new_rec =
941+ g_try_malloc0(sizeof(*new_rec));
942+ if (new_rec == NULL) {
943+ ofono_error("%s: OOM", __func__);
944+ return;
945+ }
946+ DBG("type 0x%X record %d",
947+ f_info->file_type, msg[i]);
948+
949+ new_rec->file_id = f_info->file_id;
950+ new_rec->type_tag = f_info->file_type;
951+ new_rec->record_length = f_info->record_length;
952+ new_rec->record = msg[i];
953+ new_rec->adn_idx = rec_data->adn_idx;
954+ new_rec->anr_ext = FALSE;
955+ new_rec->set_by_iap = TRUE;
956+
957+ ref->pending_records =
958+ g_slist_prepend(ref->pending_records,
959+ new_rec);
960+ }
961+ ++i;
962+ }
963+ }
964+}
965+
966+static void handle_sne(size_t len, const unsigned char *msg,
967+ struct pb_ref_rec *ref,
968+ const struct record_to_read *rec_data)
969+{
970+ char *sne;
971+
972+ /* There are additional fields for type 2 files */
973+ if (rec_data->set_by_iap)
974+ len -= 2;
975+
976+ sne = sim_string_to_utf8(msg, len);
977+
978+ if (sne && *sne != '\0') {
979+ struct phonebook_entry *entry;
980+
981+ entry = g_tree_lookup(ref->phonebook,
982+ GINT_TO_POINTER(rec_data->adn_idx));
983+ if (entry) {
984+ /* If one already exists, delete it */
985+ if (entry->sne)
986+ g_free(entry->sne);
987+
988+ DBG("Adding SNE %s to %d", sne, rec_data->adn_idx);
989+ DBG("name %s", entry->name);
990+
991+ entry->sne = sne;
992+ } else {
993+ g_free(sne);
994+ }
995+ } else {
996+ g_free(sne);
997+ }
998+}
999+
1000+static void handle_anr(size_t len,
1001+ const unsigned char *msg,
1002+ struct pb_ref_rec *ref,
1003+ const struct record_to_read *rec_data)
1004+{
1005+ unsigned number_length;
1006+ unsigned extension_record;
1007+ unsigned aas_record;
1008+ unsigned i, prefix;
1009+ char *anr;
1010+ struct phonebook_entry *entry;
1011+
1012+ if (len < 15) {
1013+ ofono_error("%s: bad EF_ANR record size", __func__);
1014+ return;
1015+ }
1016+
1017+ aas_record = msg[0];
1018+ if (aas_record == UNUSED)
1019+ return;
1020+
1021+ DBG("ANR %d", aas_record);
1022+
1023+ /* Length contains also TON & NPI */
1024+ number_length = msg[1];
1025+ if (number_length < 2)
1026+ return;
1027+
1028+ number_length--;
1029+ /* '+' + number + terminator */
1030+ anr = g_try_malloc0(2 * number_length + 2);
1031+ if (anr == NULL)
1032+ return;
1033+
1034+ prefix = 0;
1035+ if ((msg[2] & TON_MASK) == TON_INTERNATIONAL) {
1036+ anr[0] = '+';
1037+ prefix = 1;
1038+ }
1039+
1040+ for (i = 0; i < number_length; i++) {
1041+ anr[2 * i + prefix] = digit_to_utf8[msg[3 + i] & 0x0f];
1042+ anr[2 * i + 1 + prefix] = digit_to_utf8[msg[3 + i] >> 4];
1043+ }
1044+
1045+ entry = g_tree_lookup(ref->phonebook,
1046+ GINT_TO_POINTER(rec_data->adn_idx));
1047+ if (entry == NULL) {
1048+ g_free(anr);
1049+ return;
1050+ }
1051+
1052+ /* If one already exists, delete it */
1053+ if (entry->anr)
1054+ g_free(entry->anr);
1055+
1056+ DBG("Adding ANR %s to %d", anr, rec_data->adn_idx);
1057+ DBG("name %s", entry->name);
1058+
1059+ entry->anr = anr;
1060+
1061+ extension_record = msg[14];
1062+
1063+ DBG("ANR to entry %d number %s number length %d",
1064+ rec_data->adn_idx, anr, number_length);
1065+ DBG("extension_record %d aas %d", extension_record, aas_record);
1066+
1067+ if (extension_record != UNUSED) {
1068+ struct record_to_read *ext_rec =
1069+ g_try_malloc0(sizeof(*ext_rec));
1070+ const struct pb_file_info *f_info = ext1_info(ref->pb_files);
1071+
1072+ if (ext_rec && f_info) {
1073+ ext_rec->file_id = f_info->file_id;
1074+ ext_rec->type_tag = TYPE_EXT1;
1075+ ext_rec->record_length = f_info->record_length;
1076+ ext_rec->record = extension_record;
1077+ ext_rec->adn_idx = rec_data->adn_idx;
1078+ ext_rec->anr_ext = TRUE;
1079+
1080+ ref->pending_records =
1081+ g_slist_prepend(ref->pending_records, ext_rec);
1082+ }
1083+ }
1084+}
1085+
1086+static void handle_email(size_t len, const unsigned char *msg,
1087+ struct pb_ref_rec *ref,
1088+ const struct record_to_read *rec_data)
1089+{
1090+ char *email;
1091+ struct phonebook_entry *entry;
1092+
1093+ /* There are additional fields for type 2 files */
1094+ if (rec_data->set_by_iap)
1095+ len -= 2;
1096+
1097+ email = sim_string_to_utf8(msg, len);
1098+ if (email == NULL || *email == '\0') {
1099+ g_free(email);
1100+ return;
1101+ }
1102+
1103+ entry = g_tree_lookup(ref->phonebook,
1104+ GINT_TO_POINTER(rec_data->adn_idx));
1105+ if (entry == NULL) {
1106+ g_free(email);
1107+ return;
1108+ }
1109+
1110+ /* if one already exists, delete it */
1111+ if (entry->email)
1112+ g_free(entry->email);
1113+
1114+ DBG("Adding email to entry %d", rec_data->adn_idx);
1115+ DBG("name %s", entry->name);
1116+
1117+ entry->email = email;
1118+}
1119+
1120+static void handle_ext1(size_t len, const unsigned char *msg,
1121+ struct pb_ref_rec *ref,
1122+ const struct record_to_read *rec_data)
1123+{
1124+ unsigned number_length, i, next_extension_record;
1125+ struct phonebook_entry *entry;
1126+ char *ext_number;
1127+
1128+ if (len < 13) {
1129+ ofono_error("%s: bad EF_EXT1 record size", __func__);
1130+ return;
1131+ }
1132+
1133+ /* Check if there is more extension data */
1134+ next_extension_record = msg[12];
1135+ if (next_extension_record != UNUSED) {
1136+ struct record_to_read *ext_rec =
1137+ g_try_malloc0(sizeof(*ext_rec));
1138+ const struct pb_file_info *f_info = ext1_info(ref->pb_files);
1139+
1140+ if (ext_rec && f_info) {
1141+ DBG("next_extension_record %d", next_extension_record);
1142+
1143+ ext_rec->file_id = f_info->file_id;
1144+ ext_rec->record_length = f_info->record_length;
1145+ ext_rec->type_tag = TYPE_EXT1;
1146+ ext_rec->record = next_extension_record;
1147+ ext_rec->adn_idx = rec_data->adn_idx;
1148+ ext_rec->anr_ext = rec_data->anr_ext;
1149+
1150+ ref->pending_records =
1151+ g_slist_prepend(ref->pending_records, ext_rec);
1152+ }
1153+ }
1154+
1155+ if (msg[0] != EXT1_ADDITIONAL_DATA) {
1156+ DBG("EXT1 record with subaddress ignored");
1157+ return;
1158+ }
1159+
1160+ number_length = msg[1];
1161+ ext_number = g_try_malloc0(2 * number_length + 1);
1162+ if (ext_number == NULL)
1163+ return;
1164+
1165+ for (i = 0; i < number_length; i++) {
1166+ ext_number[2 * i] = digit_to_utf8[msg[2 + i] & 0x0f];
1167+ ext_number[2 * i + 1] = digit_to_utf8[msg[2 + i] >> 4];
1168+ }
1169+
1170+ DBG("Number extension %s", ext_number);
1171+ DBG("number length %d", number_length);
1172+
1173+ DBG("Looking for ADN entry %d", rec_data->adn_idx);
1174+ entry = g_tree_lookup(ref->phonebook,
1175+ GINT_TO_POINTER(rec_data->adn_idx));
1176+ if (entry == NULL) {
1177+ g_free(ext_number);
1178+ return;
1179+ }
1180+
1181+ if (rec_data->anr_ext) {
1182+ char *anr = entry->anr;
1183+ entry->anr = g_strconcat(anr, ext_number, NULL);
1184+ g_free(anr);
1185+ } else {
1186+ char *number = entry->number;
1187+ entry->number = g_strconcat(number, ext_number, NULL);
1188+ g_free(number);
1189+ }
1190+
1191+ g_free(ext_number);
1192+}
1193+
1194+static const char *file_tag_to_string(enum file_type_tag tag)
1195+{
1196+ switch (tag) {
1197+ case TYPE_ADN: return "ADN";
1198+ case TYPE_IAP: return "IAP";
1199+ case TYPE_EXT1: return "EXT1";
1200+ case TYPE_SNE: return "SNE";
1201+ case TYPE_ANR: return "ANR";
1202+ case TYPE_PBC: return "PBC";
1203+ case TYPE_GPR: return "GPR";
1204+ case TYPE_AAS: return "AAS";
1205+ case TYPE_GAS: return "GAS";
1206+ case TYPE_UID: return "UID";
1207+ case TYPE_EMAIL: return "EMAIL";
1208+ case TYPE_CCP1: return "CCP1";
1209+ default: return "<UNKNOWN>";
1210+ }
1211+}
1212+
1213+static void decode_read_response(const struct record_to_read *rec_data,
1214+ const unsigned char *msg, size_t len,
1215+ struct pb_ref_rec *ref)
1216+{
1217+ DBG("Decoding %s type record", file_tag_to_string(rec_data->type_tag));
1218+ switch (rec_data->type_tag) {
1219+ case TYPE_IAP:
1220+ handle_iap(len, msg, ref, rec_data);
1221+ break;
1222+ case TYPE_SNE:
1223+ handle_sne(len, msg, ref, rec_data);
1224+ break;
1225+ case TYPE_ANR:
1226+ handle_anr(len, msg, ref, rec_data);
1227+ break;
1228+ case TYPE_EMAIL:
1229+ handle_email(len, msg, ref, rec_data);
1230+ break;
1231+ case TYPE_EXT1:
1232+ handle_ext1(len, msg, ref, rec_data);
1233+ break;
1234+ default:
1235+ DBG("Skipping type");
1236+ break;
1237+ }
1238+}
1239+
1240+static gboolean export_entry(gpointer key, gpointer value, gpointer data)
1241+{
1242+ struct ofono_phonebook *pb = data;
1243+ struct phonebook_entry *entry = value;
1244+
1245+ ofono_phonebook_entry(pb, -1,
1246+ entry->number, -1,
1247+ entry->name, -1,
1248+ NULL,
1249+ entry->anr, -1,
1250+ entry->sne,
1251+ entry->email,
1252+ NULL, NULL);
1253+
1254+ g_free(entry->name);
1255+ g_free(entry->number);
1256+ g_free(entry->email);
1257+ g_free(entry->anr);
1258+ g_free(entry->sne);
1259+ g_free(entry);
1260+
1261+ return FALSE;
1262+}
1263+
1264+static void export_and_return(gboolean ok, struct cb_data *cbd)
1265+{
1266+ struct ofono_phonebook *pb = cbd->user;
1267+ ofono_phonebook_cb_t cb = cbd->cb;
1268+ struct pb_data *pbd = ofono_phonebook_get_data(pb);
1269+ GSList *l;
1270+
1271+ DBG("phonebook fully read");
1272+
1273+ for (l = pbd->pb_refs; l != NULL; l = l->next) {
1274+ struct pb_ref_rec *ref = l->data;
1275+
1276+ g_tree_foreach(ref->phonebook, export_entry, pb);
1277+ g_tree_destroy(ref->phonebook);
1278+ g_slist_free_full(ref->pending_records, g_free);
1279+ g_slist_free_full(ref->pb_files, g_free);
1280+ }
1281+
1282+ g_slist_free_full(pbd->pb_refs, g_free);
1283+ pbd->pb_refs = NULL;
1284+
1285+ if (ok)
1286+ CALLBACK_WITH_SUCCESS(cb, cbd->data);
1287+ else
1288+ CALLBACK_WITH_FAILURE(cb, cbd->data);
1289+
1290+ g_free(cbd);
1291+}
1292+
1293+static void read_record_cb(int ok, int total_length, int record,
1294+ const unsigned char *data,
1295+ int record_length, void *userdata)
1296+{
1297+ struct cb_data *cbd = userdata;
1298+ struct ofono_phonebook *pb = cbd->user;
1299+ struct pb_data *pbd = ofono_phonebook_get_data(pb);
1300+ struct pb_ref_rec *ref = pbd->pb_ref_next->data;
1301+ struct record_to_read *rec;
1302+
1303+ if (!ok) {
1304+ ofono_error("%s: error %d", __func__, ok);
1305+ export_and_return(FALSE, cbd);
1306+ return;
1307+ }
1308+
1309+ DBG("ok %d; total_length %d; record %d; record_length %d",
1310+ ok, total_length, record, record_length);
1311+
1312+ rec = ref->next_record->data;
1313+
1314+ /* This call might add elements to pending_records */
1315+ decode_read_response(rec, data, record_length, ref);
1316+
1317+ ref->pending_records = g_slist_remove(ref->pending_records, rec);
1318+ g_free(rec);
1319+
1320+ if (ref->pending_records) {
1321+ struct record_to_read *rec;
1322+
1323+ ref->next_record = ref->pending_records;
1324+ rec = ref->next_record->data;
1325+
1326+ ofono_sim_read_record(pbd->sim_context, rec->file_id,
1327+ OFONO_SIM_FILE_STRUCTURE_FIXED,
1328+ rec->record,
1329+ rec->record_length,
1330+ pbd->df_path, pbd->df_size,
1331+ read_record_cb, cbd);
1332+ } else {
1333+ /* Read files from next EF_PBR record, if any */
1334+
1335+ pbd->pb_ref_next = pbd->pb_ref_next->next;
1336+ if (pbd->pb_ref_next == NULL) {
1337+ export_and_return(TRUE, cbd);
1338+ } else {
1339+ struct pb_ref_rec *ref;
1340+ struct pb_file_info *file_info;
1341+
1342+ DBG("Next EFpbr record");
1343+
1344+ ref = pbd->pb_ref_next->data;
1345+
1346+ ref->pb_next = ref->pb_files;
1347+ file_info = ref->pb_files->data;
1348+
1349+ if (!file_info) {
1350+ export_and_return(TRUE, cbd);
1351+ } else {
1352+ ofono_sim_read_info(pbd->sim_context,
1353+ file_info->file_id,
1354+ OFONO_SIM_FILE_STRUCTURE_FIXED,
1355+ pbd->df_path, pbd->df_size,
1356+ read_info_cb, cbd);
1357+ }
1358+ }
1359+ }
1360+}
1361+
1362+static void pb_adn_cb(int ok, int total_length, int record,
1363+ const unsigned char *data,
1364+ int record_length, void *userdata)
1365+{
1366+ struct cb_data *cbd = userdata;
1367+ struct ofono_phonebook *pb = cbd->user;
1368+ struct pb_data *pbd = ofono_phonebook_get_data(pb);
1369+ struct pb_ref_rec *ref = pbd->pb_ref_next->data;
1370+ GSList *l;
1371+
1372+ if (!ok) {
1373+ ofono_error("%s: error %d", __func__, ok);
1374+ export_and_return(FALSE, cbd);
1375+ return;
1376+ }
1377+
1378+ DBG("ok %d; total_length %d; record %d; record_length %d",
1379+ ok, total_length, record, record_length);
1380+
1381+ if (handle_adn(record_length, data, ref, record) != NULL) {
1382+ /* Add type 1 records */
1383+ for (l = ref->pb_files; l; l = l->next) {
1384+ const struct pb_file_info *f_info = l->data;
1385+ struct record_to_read *ext_rec;
1386+
1387+ if (f_info->pbr_type == TYPE_1_TAG &&
1388+ f_info->file_type != TYPE_ADN) {
1389+ ext_rec = g_try_malloc0(sizeof(*ext_rec));
1390+ if (ext_rec == NULL)
1391+ break;
1392+
1393+ ext_rec->file_id = f_info->file_id;
1394+ ext_rec->type_tag = f_info->file_type;
1395+ ext_rec->record_length = f_info->record_length;
1396+ ext_rec->record = record;
1397+ ext_rec->adn_idx = record;
1398+
1399+ ref->pending_records =
1400+ g_slist_prepend(ref->pending_records,
1401+ ext_rec);
1402+ }
1403+ }
1404+ }
1405+
1406+ if (record*record_length >= total_length) {
1407+ DBG("All ADN records read: reading additional files");
1408+
1409+ if (ref->pending_records) {
1410+ struct record_to_read *rec;
1411+
1412+ ref->next_record = ref->pending_records;
1413+ rec = ref->next_record->data;
1414+
1415+ ofono_sim_read_record(pbd->sim_context, rec->file_id,
1416+ OFONO_SIM_FILE_STRUCTURE_FIXED,
1417+ rec->record,
1418+ rec->record_length,
1419+ pbd->df_path, pbd->df_size,
1420+ read_record_cb, cbd);
1421+ } else {
1422+ export_and_return(TRUE, cbd);
1423+ }
1424+ }
1425+}
1426+
1427+static void read_info_cb(int ok, unsigned char file_status,
1428+ int total_length, int record_length,
1429+ void *userdata)
1430+{
1431+ struct cb_data *cbd = userdata;
1432+ struct ofono_phonebook *pb = cbd->user;
1433+ struct pb_data *pbd = ofono_phonebook_get_data(pb);
1434+ struct pb_file_info *file_info;
1435+ struct pb_ref_rec *ref = pbd->pb_ref_next->data;
1436+
1437+ file_info = ref->pb_next->data;
1438+ ref->pb_next = ref->pb_next->next;
1439+
1440+ if (ok) {
1441+ file_info->record_length = record_length;
1442+ file_info->file_length = total_length;
1443+
1444+ DBG("file id %x record length %d total_length %d",
1445+ file_info->file_id, record_length, total_length);
1446+ } else {
1447+ ofono_warn("%s: %x not found", __func__, file_info->file_id);
1448+ ref->pb_files = g_slist_remove(ref->pb_files, file_info);
1449+ g_free(file_info);
1450+ }
1451+
1452+ if (ref->pb_next == NULL) {
1453+ if (ref->pb_files == NULL) {
1454+ ofono_warn("%s: no phonebook on SIM", __func__);
1455+ export_and_return(FALSE, cbd);
1456+ return;
1457+ }
1458+
1459+ /* Read full contents of the master file */
1460+ file_info = ref->pb_files->data;
1461+
1462+ ofono_sim_read_path(pbd->sim_context, file_info->file_id,
1463+ OFONO_SIM_FILE_STRUCTURE_FIXED,
1464+ pbd->df_path, pbd->df_size,
1465+ pb_adn_cb, cbd);
1466+ } else {
1467+ file_info = ref->pb_next->data;
1468+
1469+ ofono_sim_read_info(pbd->sim_context, file_info->file_id,
1470+ OFONO_SIM_FILE_STRUCTURE_FIXED,
1471+ pbd->df_path, pbd->df_size,
1472+ read_info_cb, cbd);
1473+ }
1474+}
1475+
1476+static void start_sim_app_read(struct cb_data *cbd)
1477+{
1478+ struct ofono_phonebook *pb = cbd->user;
1479+ struct pb_data *pbd = ofono_phonebook_get_data(pb);
1480+ struct pb_ref_rec *ref_rec;
1481+ struct pb_file_info *f_info;
1482+ struct pb_file_info *f_ext1;
1483+
1484+ pbd->df_path = sim_path;
1485+ pbd->df_size = sizeof(sim_path);
1486+
1487+ ref_rec = g_try_malloc0(sizeof(*ref_rec));
1488+ if (ref_rec == NULL) {
1489+ ofono_error("%s: OOM", __func__);
1490+ export_and_return(FALSE, cbd);
1491+ return;
1492+ }
1493+
1494+ ref_rec->phonebook = g_tree_new(comp_int);
1495+
1496+ /* Only EF_ADN and EF_EXT1 read for SIM */
1497+
1498+ f_info = g_try_malloc0(sizeof(*f_info));
1499+ if (f_info == NULL) {
1500+ ofono_error("%s: OOM", __func__);
1501+ export_and_return(FALSE, cbd);
1502+ return;
1503+ }
1504+
1505+ f_info->file_id = SIM_EFADN_FILEID;
1506+ f_info->pbr_type = TYPE_1_TAG;
1507+ f_info->file_type = TYPE_ADN;
1508+ ref_rec->pb_files = g_slist_append(ref_rec->pb_files, f_info);
1509+
1510+ f_ext1 = g_try_malloc0(sizeof(*f_ext1));
1511+ if (f_ext1 == NULL) {
1512+ ofono_error("%s: OOM", __func__);
1513+ export_and_return(FALSE, cbd);
1514+ return;
1515+ }
1516+
1517+ f_ext1->file_id = SIM_EFEXT1_FILEID;
1518+ f_ext1->pbr_type = TYPE_3_TAG;
1519+ f_ext1->file_type = TYPE_EXT1;
1520+ ref_rec->pb_files = g_slist_append(ref_rec->pb_files, f_ext1);
1521+
1522+ pbd->pb_refs = g_slist_append(pbd->pb_refs, ref_rec);
1523+ pbd->pb_ref_next = pbd->pb_refs;
1524+
1525+ ref_rec->pb_next = ref_rec->pb_files;
1526+
1527+ /* Start reading process for MF */
1528+ ofono_sim_read_info(pbd->sim_context, f_info->file_id,
1529+ OFONO_SIM_FILE_STRUCTURE_FIXED,
1530+ pbd->df_path, pbd->df_size,
1531+ read_info_cb, cbd);
1532+}
1533+
1534+static void pb_reference_data_cb(int ok, int total_length, int record,
1535+ const unsigned char *sdata,
1536+ int record_length, void *userdata)
1537+{
1538+ struct cb_data *cbd = userdata;
1539+ struct ofono_phonebook *pb = cbd->user;
1540+ struct pb_data *pbd = ofono_phonebook_get_data(pb);
1541+ const unsigned char *ptr = sdata;
1542+ gboolean finished = FALSE;
1543+ struct pb_ref_rec *ref_rec;
1544+
1545+ DBG("total_length %d record %d record_length %d",
1546+ total_length, record, record_length);
1547+
1548+ if (!ok) {
1549+ /* We migh have a SIM instead of USIM application: try that */
1550+ DBG("%s: error %d, trying SIM files", __func__, ok);
1551+ start_sim_app_read(cbd);
1552+ return;
1553+ }
1554+
1555+ ref_rec = g_try_malloc0(sizeof(*ref_rec));
1556+ if (ref_rec == NULL) {
1557+ ofono_error("%s: OOM", __func__);
1558+ export_and_return(FALSE, cbd);
1559+ return;
1560+ }
1561+
1562+ ref_rec->phonebook = g_tree_new(comp_int);
1563+
1564+ while (ptr < sdata + record_length && finished == FALSE) {
1565+ int typelen, file_id, i;
1566+ enum constructed_tag pbr_type = *ptr;
1567+
1568+ switch (pbr_type) {
1569+ case TYPE_1_TAG:
1570+ case TYPE_2_TAG:
1571+ case TYPE_3_TAG:
1572+ typelen = *(ptr + 1);
1573+ DBG("File type=%02X, len=%d", *ptr, typelen);
1574+ ptr += 2;
1575+ i = 0;
1576+
1577+ while (i < typelen) {
1578+ struct pb_file_info *file_info =
1579+ g_try_new0(struct pb_file_info, 1);
1580+ if (!file_info) {
1581+ ofono_error("%s: OOM", __func__);
1582+ export_and_return(FALSE, cbd);
1583+ return;
1584+ }
1585+
1586+ file_id = (ptr[i + 2] << 8) + ptr[i + 3];
1587+
1588+ DBG("creating file info for File type=%02X",
1589+ ptr[i]);
1590+ DBG("File ID=%04X", file_id);
1591+
1592+
1593+ file_info->pbr_type = pbr_type;
1594+ file_info->file_type = ptr[i];
1595+ file_info->file_id = file_id;
1596+ /* Keep order, important for type 2 files */
1597+ ref_rec->pb_files =
1598+ g_slist_append(ref_rec->pb_files,
1599+ file_info);
1600+ i += ptr[i + 1] + 2;
1601+ }
1602+
1603+ ptr += typelen;
1604+ break;
1605+ default:
1606+ DBG("All handled %02x", *ptr);
1607+ finished = TRUE;
1608+ break;
1609+ }
1610+ }
1611+
1612+ pbd->pb_refs = g_slist_append(pbd->pb_refs, ref_rec);
1613+
1614+ if (record*record_length >= total_length) {
1615+ struct pb_ref_rec *ref;
1616+ struct pb_file_info *file_info;
1617+
1618+ DBG("All EFpbr records read");
1619+
1620+ pbd->pb_ref_next = pbd->pb_refs;
1621+ ref = pbd->pb_ref_next->data;
1622+
1623+ ref->pb_next = ref->pb_files;
1624+ file_info = ref->pb_files->data;
1625+ if (file_info == NULL) {
1626+ ofono_error("%s: no files to read", __func__);
1627+ export_and_return(FALSE, cbd);
1628+ return;
1629+ }
1630+
1631+ /* Start reading process for first EF_PBR entry */
1632+
1633+ ofono_sim_read_info(pbd->sim_context, file_info->file_id,
1634+ OFONO_SIM_FILE_STRUCTURE_FIXED,
1635+ pbd->df_path, pbd->df_size,
1636+ read_info_cb, cbd);
1637+ }
1638+}
1639+
1640+static void ril_export_entries(struct ofono_phonebook *pb,
1641+ const char *storage,
1642+ ofono_phonebook_cb_t cb, void *data)
1643+{
1644+ struct pb_data *pbd = ofono_phonebook_get_data(pb);
1645+ struct cb_data *cbd;
1646+
1647+ DBG("Storage %s", storage);
1648+
1649+ /* Only for SIM memory */
1650+ if (strcmp(storage, "SM") != 0) {
1651+ CALLBACK_WITH_FAILURE(cb, data);
1652+ return;
1653+ }
1654+
1655+ cbd = cb_data_new(cb, data, pb);
1656+
1657+ /* Assume USIM, change in case EF_PBR is not present */
1658+ pbd->df_path = usim_path;
1659+ pbd->df_size = sizeof(usim_path);
1660+
1661+ ofono_sim_read(pbd->sim_context, SIM_EFPBR_FILEID,
1662+ OFONO_SIM_FILE_STRUCTURE_FIXED,
1663+ pb_reference_data_cb, cbd);
1664+}
1665+
1666+static gboolean ril_delayed_register(gpointer user_data)
1667+{
1668+ struct ofono_phonebook *pb = user_data;
1669+
1670+ ofono_phonebook_register(pb);
1671+ return FALSE;
1672+}
1673+
1674+static int ril_phonebook_probe(struct ofono_phonebook *pb,
1675+ unsigned int vendor, void *user)
1676+{
1677+ struct ofono_modem *modem = user;
1678+ struct pb_data *pd = g_try_new0(struct pb_data, 1);
1679+ if (pd == NULL)
1680+ return -ENOMEM;
1681+
1682+ pd->sim = __ofono_atom_find(OFONO_ATOM_TYPE_SIM, modem);
1683+ if (pd->sim == NULL)
1684+ return -ENOENT;
1685+
1686+ pd->sim_context = ofono_sim_context_create(pd->sim);
1687+ if (pd->sim_context == NULL)
1688+ return -ENOENT;
1689+
1690+ ofono_phonebook_set_data(pb, pd);
1691+
1692+ g_idle_add(ril_delayed_register, pb);
1693+
1694+ return 0;
1695+}
1696+
1697+static void ril_phonebook_remove(struct ofono_phonebook *pb)
1698+{
1699+ struct pb_data *pbd = ofono_phonebook_get_data(pb);
1700+
1701+ ofono_phonebook_set_data(pb, NULL);
1702+ ofono_sim_context_free(pbd->sim_context);
1703+
1704+ g_free(pbd);
1705+}
1706+
1707+static struct ofono_phonebook_driver driver = {
1708+ .name = RILMODEM,
1709+ .probe = ril_phonebook_probe,
1710+ .remove = ril_phonebook_remove,
1711+ .export_entries = ril_export_entries
1712+};
1713+
1714+void ril_phonebook_init(void)
1715+{
1716+ ofono_phonebook_driver_register(&driver);
1717+}
1718+
1719+void ril_phonebook_exit(void)
1720+{
1721+ ofono_phonebook_driver_unregister(&driver);
1722+}
1723
1724=== modified file 'drivers/rilmodem/radio-settings.c'
1725--- drivers/rilmodem/radio-settings.c 2014-07-24 08:31:18 +0000
1726+++ drivers/rilmodem/radio-settings.c 2014-11-20 00:09:27 +0000
1727@@ -118,8 +118,16 @@
1728 return;
1729 }
1730
1731+ /*
1732+ * GSM_WCDMA_AUTO -> ril.h: GSM/WCDMA (auto mode, according to PRL)
1733+ * PRL: preferred roaming list.
1734+ * This value is returned when selecting the slot as having 3G
1735+ * capabilities, so it is sort of the default for MTK modems.
1736+ */
1737+
1738 switch (pref) {
1739 case PREF_NET_TYPE_GSM_WCDMA:
1740+ case PREF_NET_TYPE_GSM_WCDMA_AUTO:
1741 mode = OFONO_RADIO_ACCESS_MODE_UMTS;
1742 break;
1743 case PREF_NET_TYPE_GSM_ONLY:
1744
1745=== modified file 'drivers/rilmodem/rilmodem.c'
1746--- drivers/rilmodem/rilmodem.c 2014-04-21 07:56:17 +0000
1747+++ drivers/rilmodem/rilmodem.c 2014-11-20 00:09:27 +0000
1748@@ -51,6 +51,7 @@
1749 ril_call_forwarding_init();
1750 ril_radio_settings_init();
1751 ril_call_barring_init();
1752+ ril_phonebook_init();
1753
1754 return 0;
1755 }
1756@@ -72,6 +73,7 @@
1757 ril_call_forwarding_exit();
1758 ril_radio_settings_exit();
1759 ril_call_barring_exit();
1760+ ril_phonebook_exit();
1761 }
1762
1763 OFONO_PLUGIN_DEFINE(rilmodem, "RIL modem driver", VERSION,
1764
1765=== modified file 'drivers/rilmodem/rilmodem.h'
1766--- drivers/rilmodem/rilmodem.h 2014-04-21 07:56:17 +0000
1767+++ drivers/rilmodem/rilmodem.h 2014-11-20 00:09:27 +0000
1768@@ -66,3 +66,6 @@
1769
1770 extern void ril_call_barring_init(void);
1771 extern void ril_call_barring_exit(void);
1772+
1773+extern void ril_phonebook_init(void);
1774+extern void ril_phonebook_exit(void);
1775
1776=== modified file 'drivers/rilmodem/sim.c'
1777--- drivers/rilmodem/sim.c 2014-10-10 02:10:48 +0000
1778+++ drivers/rilmodem/sim.c 2014-11-20 00:09:27 +0000
1779@@ -85,7 +85,6 @@
1780 guint app_type;
1781 gchar *app_str;
1782 guint app_index;
1783- gboolean sim_registered;
1784 enum ofono_sim_password_type passwd_type;
1785 int retries[OFONO_SIM_PASSWORD_INVALID];
1786 enum ofono_sim_password_type passwd_state;
1787@@ -646,55 +645,56 @@
1788 struct ofono_sim *sim = user_data;
1789 struct sim_data *sd = ofono_sim_get_data(sim);
1790 struct reply_sim_status *status;
1791- guint i = 0;
1792- guint search_index = -1;
1793-
1794- if (sd->sim_registered == FALSE) {
1795- /* First status request, after sim_probe() */
1796- ofono_sim_register(sim);
1797- sd->sim_registered = TRUE;
1798-
1799- if (sd->ril_state_watch != NULL &&
1800- !ofono_sim_add_state_watch(sim,
1801- sd->ril_state_watch,
1802- sd->modem, NULL))
1803- ofono_error("Error registering ril sim watch");
1804+ guint search_index;
1805+
1806+ status = g_ril_reply_parse_sim_status(sd->ril, message);
1807+ if (status == NULL) {
1808+ ofono_error("%s: Cannot parse SIM status reply", __func__);
1809+ return;
1810 }
1811
1812- if ((status = g_ril_reply_parse_sim_status(sd->ril, message))
1813- != NULL
1814- && status->card_state == RIL_CARDSTATE_PRESENT
1815- && status->num_apps) {
1816-
1817- DBG("num_apps: %d gsm_umts_index: %d", status->num_apps,
1818- status->gsm_umts_index);
1819-
1820- /*
1821- * TODO(CDMA): need some kind of logic to
1822- * set the correct app_index,
1823- */
1824- search_index = status->gsm_umts_index;
1825-
1826- for (i = 0; i < status->num_apps; i++) {
1827- struct reply_sim_app *app = status->apps[i];
1828- if (i == search_index &&
1829- app->app_type != RIL_APPTYPE_UNKNOWN) {
1830- configure_active_app(sd, app, i);
1831- break;
1832- }
1833- }
1834-
1835- /*
1836- * Note: There doesn't seem to be any other way to
1837- * force the core SIM code to recheck the PIN. This
1838- * call causes the core to call the this atom's
1839- * query_passwd() function.
1840- */
1841- __ofono_sim_recheck_pin(sim);
1842-
1843- } else if (status && status->card_state == RIL_CARDSTATE_ABSENT) {
1844- ofono_info("SIM card absent");
1845+ DBG("SIM status is %u", status->card_state);
1846+
1847+ if (status->card_state == RIL_CARDSTATE_PRESENT)
1848+ ofono_sim_inserted_notify(sim, TRUE);
1849+ else if (status && status->card_state == RIL_CARDSTATE_ABSENT)
1850 ofono_sim_inserted_notify(sim, FALSE);
1851+ else
1852+ ofono_error("%s: bad SIM state (%u)",
1853+ __func__, status->card_state);
1854+
1855+ /* TODO(CDMA): need some kind of logic to set the correct app_index */
1856+ search_index = status->gsm_umts_index;
1857+
1858+ /*
1859+ * We cache the current password state. Ideally this should be done by
1860+ * issuing a GET_SIM_STATUS request from ril_query_passwd_state, which
1861+ * is called by the core after sending a password, but unfortunately the
1862+ * response to GET_SIM_STATUS is not reliable in mako when sent just
1863+ * after sending the password. Some time is needed before the modem
1864+ * refreshes its internal state, and when it does it sends a
1865+ * SIM_STATUS_CHANGED event. In that moment we retrieve the status and
1866+ * this function is executed. We call __ofono_sim_recheck_pin as it is
1867+ * the only way to indicate the core to call query_passwd_state again.
1868+ * An option that can be explored in the future is wait before invoking
1869+ * core callback for send_passwd until we know the real password state.
1870+ */
1871+ if (status->card_state == RIL_CARDSTATE_PRESENT
1872+ && search_index < status->num_apps) {
1873+ struct reply_sim_app *app = status->apps[search_index];
1874+
1875+ if (app->app_type != RIL_APPTYPE_UNKNOWN) {
1876+ configure_active_app(sd, app, search_index);
1877+ DBG("passwd_state: %d", sd->passwd_state);
1878+
1879+ /*
1880+ * Note: There doesn't seem to be any other way to force
1881+ * the core SIM code to recheck the PIN. This call
1882+ * causes the core to call the this atom's
1883+ * query_passwd() function.
1884+ */
1885+ __ofono_sim_recheck_pin(sim);
1886+ }
1887 }
1888
1889 g_ril_reply_free_sim_status(status);
1890@@ -823,7 +823,7 @@
1891 g_free(retries);
1892 }
1893
1894- /* TODO: re-bfactor to not use macro for FAILURE;
1895+ /* TODO: re-factor to not use macro for FAILURE;
1896 doesn't return error! */
1897 if (message->error == RIL_E_SUCCESS) {
1898 CALLBACK_WITH_SUCCESS(cb, cbd->data);
1899@@ -992,19 +992,40 @@
1900 }
1901 }
1902
1903-static gboolean ril_sim_register(gpointer user)
1904+static gboolean listen_and_get_sim_status(gpointer user)
1905 {
1906 struct ofono_sim *sim = user;
1907 struct sim_data *sd = ofono_sim_get_data(sim);
1908
1909- DBG("");
1910-
1911- send_get_sim_status(sim);
1912+ send_get_sim_status(sim);
1913
1914 g_ril_register(sd->ril, RIL_UNSOL_RESPONSE_SIM_STATUS_CHANGED,
1915 (GRilNotifyFunc) ril_sim_status_changed, sim);
1916
1917 /* TODO: should we also register for RIL_UNSOL_SIM_REFRESH? */
1918+ return FALSE;
1919+}
1920+
1921+static gboolean ril_sim_register(gpointer user)
1922+{
1923+ struct ofono_sim *sim = user;
1924+ struct sim_data *sd = ofono_sim_get_data(sim);
1925+
1926+ DBG("");
1927+
1928+ ofono_sim_register(sim);
1929+
1930+ if (sd->ril_state_watch != NULL &&
1931+ !ofono_sim_add_state_watch(sim, sd->ril_state_watch,
1932+ sd->modem, NULL))
1933+ ofono_error("Error registering ril sim watch");
1934+
1935+ /*
1936+ * We use g_idle_add here to make sure that the presence of the SIM
1937+ * interface is signalled before signalling anything else from the said
1938+ * interface, as ofono_sim_register also uses g_idle_add.
1939+ */
1940+ g_idle_add(listen_and_get_sim_status, sim);
1941
1942 return FALSE;
1943 }
1944@@ -1025,7 +1046,6 @@
1945 sd->app_type = RIL_APPTYPE_UNKNOWN;
1946 sd->passwd_state = OFONO_SIM_PASSWORD_NONE;
1947 sd->passwd_type = OFONO_SIM_PASSWORD_NONE;
1948- sd->sim_registered = FALSE;
1949 sd->modem = ril_data->modem;
1950 sd->ril_state_watch = ril_data->ril_state_watch;
1951
1952
1953=== modified file 'gril/grilreply.c'
1954--- gril/grilreply.c 2014-09-22 17:39:35 +0000
1955+++ gril/grilreply.c 2014-11-20 00:09:27 +0000
1956@@ -45,6 +45,13 @@
1957
1958 #define OPERATOR_NUM_PARAMS 3
1959
1960+/* Indexes for registration state replies */
1961+#define RST_IX_STATE 0
1962+#define RST_IX_LAC 1
1963+#define RST_IX_CID 2
1964+#define RST_IX_RAT 3
1965+#define RDST_IX_MAXDC 5
1966+
1967 #define MTK_MODEM_MAX_CIDS 3
1968
1969 static void ril_reply_free_operator(gpointer data)
1970@@ -269,183 +276,236 @@
1971 return NULL;
1972 }
1973
1974-struct reply_reg_state *g_ril_reply_parse_reg_state(GRil *gril,
1975- const struct ril_msg *message)
1976-
1977+static void set_reg_state(GRil *gril, struct reply_reg_state *reply,
1978+ int i, const char *str)
1979 {
1980- struct parcel rilp;
1981- int tmp, status;
1982- char *sstatus = NULL, *slac = NULL, *sci = NULL;
1983- char *stech = NULL, *sreason = NULL, *smax = NULL;
1984- struct reply_reg_state *reply;
1985+ int val;
1986 char *endp;
1987+ int base;
1988 const char *strstate;
1989
1990- DBG("");
1991-
1992- /*
1993- * If no array length is present, reply is invalid.
1994- */
1995- if (message->buf_len < 4) {
1996- ofono_error("%s: invalid %s reply: "
1997- "size too small (< 4): %d ",
1998- __func__,
1999- ril_request_id_to_string(message->req),
2000- (int) message->buf_len);
2001- return NULL;
2002- }
2003-
2004- g_ril_init_parcel(message, &rilp);
2005-
2006- reply = g_new0(struct reply_reg_state, 1);
2007-
2008- /*
2009- * Size of response string array
2010- * Should be:
2011- * >= 4 for VOICE_REG reply
2012- * >= 5 for DATA_REG reply
2013- * But we allow a minimum of 1 (infineon, not registered case)
2014- */
2015- if ((tmp = parcel_r_int32(&rilp)) < 1) {
2016- ofono_error("%s: invalid %s; response array is too small: %d",
2017- __func__,
2018- ril_request_id_to_string(message->req),
2019- tmp);
2020- goto error;
2021- }
2022-
2023- sstatus = parcel_r_string(&rilp);
2024- --tmp;
2025- if (tmp > 0) {
2026- slac = parcel_r_string(&rilp);
2027- --tmp;
2028- }
2029- if (tmp > 0) {
2030- sci = parcel_r_string(&rilp);
2031- --tmp;
2032- }
2033- if (tmp > 0) {
2034- stech = parcel_r_string(&rilp);
2035- --tmp;
2036- }
2037-
2038- /*
2039- * FIXME: need to review VOICE_REGISTRATION response
2040- * as it returns ~15 parameters ( vs. 6 for DATA ).
2041- *
2042- * The first four parameters are the same for both
2043- * responses ( although status includes values for
2044- * emergency calls for VOICE response ).
2045- *
2046- * Parameters 5 & 6 have different meanings for
2047- * voice & data response.
2048- */
2049- if (tmp--) {
2050- /* TODO: different use for CDMA */
2051- sreason = parcel_r_string(&rilp);
2052-
2053- if (tmp--) {
2054- /* TODO: different use for CDMA */
2055- smax = parcel_r_string(&rilp);
2056-
2057- /*
2058- * MTK modem does not return max_cids, string for this
2059- * index actually contains the maximum data bearer
2060- * capability.
2061- */
2062- if (g_ril_vendor(gril) == OFONO_RIL_VENDOR_MTK)
2063- reply->max_cids = MTK_MODEM_MAX_CIDS;
2064- else if (smax)
2065- reply->max_cids = atoi(smax);
2066- }
2067- }
2068-
2069-
2070- if (sstatus == NULL) {
2071- ofono_error("%s: no status included in %s reply",
2072- __func__,
2073- ril_request_id_to_string(message->req));
2074- goto error;
2075- }
2076-
2077- status = atoi(sstatus);
2078-
2079- switch (status) {
2080- case RIL_REG_STATE_NOT_REGISTERED:
2081- case RIL_REG_STATE_REGISTERED:
2082- case RIL_REG_STATE_SEARCHING:
2083- case RIL_REG_STATE_DENIED:
2084- case RIL_REG_STATE_UNKNOWN:
2085- case RIL_REG_STATE_ROAMING:
2086- /* Only valid values for ofono */
2087- reply->status = status;
2088- strstate = registration_status_to_string(status);
2089- break;
2090- case RIL_REG_STATE_EMERGENCY_NOT_REGISTERED:
2091- case RIL_REG_STATE_EMERGENCY_SEARCHING:
2092- case RIL_REG_STATE_EMERGENCY_DENIED:
2093- case RIL_REG_STATE_EMERGENCY_UNKNOWN:
2094- /* Map to states valid for ofono core */
2095- reply->status = status - RIL_REG_STATE_EMERGENCY_NOT_REGISTERED;
2096- strstate = sstatus;
2097- break;
2098- default:
2099- reply->status = NETWORK_REGISTRATION_STATUS_UNKNOWN;
2100- strstate = sstatus;
2101- ofono_error("%s: Error unknown status code (%s)",
2102- __func__, sstatus);
2103- }
2104-
2105-
2106- if (slac)
2107- reply->lac = strtol(slac, NULL, 16);
2108- else
2109- reply->lac = -1;
2110-
2111- if (sci)
2112- reply->ci = strtol(sci, NULL, 16);
2113- else
2114- reply->ci = -1;
2115-
2116- if (stech && *stech != '\0') {
2117- reply->tech = (int) strtol(stech, &endp, 10);
2118- if (*endp != '\0') {
2119- ofono_error("%s: cannot parse tech: %s in %s reply",
2120- __func__, stech,
2121- ril_request_id_to_string(message->req));
2122- reply->tech = RADIO_TECH_UNKNOWN;
2123- }
2124- } else {
2125- ofono_error("%s: no tech included in %s reply",
2126- __func__,
2127- ril_request_id_to_string(message->req));
2128- reply->tech = RADIO_TECH_UNKNOWN;
2129- }
2130-
2131- g_ril_append_print_buf(gril,
2132- "{%s,%s,%s,%s,%s,%s}",
2133- strstate,
2134- slac,
2135- sci,
2136- ril_radio_tech_to_string(reply->tech),
2137- sreason,
2138- smax ? smax : "NULL");
2139-
2140- g_ril_print_response(gril, message);
2141-
2142- /* Free our parcel handlers */
2143- g_free(sstatus);
2144- g_free(slac);
2145- g_free(sci);
2146- g_free(stech);
2147- g_free(sreason);
2148- g_free(smax);
2149-
2150- return reply;
2151-
2152-error:
2153- g_free(reply);
2154- return NULL;
2155+ if (str == NULL || *str == '\0')
2156+ goto no_val;
2157+
2158+ if (i == RST_IX_LAC || i == RST_IX_CID)
2159+ base = 16;
2160+ else
2161+ base = 10;
2162+
2163+ val = (int) strtol(str, &endp, base);
2164+ if (*endp != '\0')
2165+ goto no_val;
2166+
2167+ switch (i) {
2168+ case RST_IX_STATE:
2169+ switch (val) {
2170+ case RIL_REG_STATE_NOT_REGISTERED:
2171+ case RIL_REG_STATE_REGISTERED:
2172+ case RIL_REG_STATE_SEARCHING:
2173+ case RIL_REG_STATE_DENIED:
2174+ case RIL_REG_STATE_UNKNOWN:
2175+ case RIL_REG_STATE_ROAMING:
2176+ /* Only valid values for ofono */
2177+ strstate = registration_status_to_string(val);
2178+ break;
2179+ case RIL_REG_STATE_EMERGENCY_NOT_REGISTERED:
2180+ case RIL_REG_STATE_EMERGENCY_SEARCHING:
2181+ case RIL_REG_STATE_EMERGENCY_DENIED:
2182+ case RIL_REG_STATE_EMERGENCY_UNKNOWN:
2183+ /* Map to states valid for ofono core */
2184+ val -= RIL_REG_STATE_EMERGENCY_NOT_REGISTERED;
2185+ strstate = str;
2186+ break;
2187+ default:
2188+ val = NETWORK_REGISTRATION_STATUS_UNKNOWN;
2189+ strstate = str;
2190+ }
2191+ reply->status = val;
2192+ g_ril_append_print_buf(gril, "%s%s", print_buf, strstate);
2193+ break;
2194+ case RST_IX_LAC:
2195+ reply->lac = val;
2196+ g_ril_append_print_buf(gril, "%s0x%x", print_buf, val);
2197+ break;
2198+ case RST_IX_CID:
2199+ reply->ci = val;
2200+ g_ril_append_print_buf(gril, "%s0x%x", print_buf, val);
2201+ break;
2202+ case RST_IX_RAT:
2203+ reply->tech = val;
2204+ g_ril_append_print_buf(gril, "%s%s", print_buf,
2205+ ril_radio_tech_to_string(val));
2206+ break;
2207+ default:
2208+ goto no_val;
2209+ }
2210+
2211+ return;
2212+
2213+no_val:
2214+ g_ril_append_print_buf(gril, "%s%s", print_buf, str ? str : "(null)");
2215+}
2216+
2217+struct reply_reg_state *g_ril_reply_parse_voice_reg_state(GRil *gril,
2218+ const struct ril_msg *message)
2219+{
2220+ struct parcel rilp;
2221+ struct parcel_str_array *str_arr;
2222+ struct reply_reg_state *reply = NULL;
2223+ int i;
2224+
2225+ g_ril_init_parcel(message, &rilp);
2226+
2227+ str_arr = parcel_r_str_array(&rilp);
2228+ if (str_arr == NULL) {
2229+ ofono_error("%s: parse error for %s", __func__,
2230+ ril_request_id_to_string(message->req));
2231+ goto out;
2232+ }
2233+
2234+ reply = g_try_malloc0(sizeof(*reply));
2235+ if (reply == NULL) {
2236+ ofono_error("%s: out of memory", __func__);
2237+ goto out;
2238+ }
2239+
2240+ reply->status = -1;
2241+ reply->lac = -1;
2242+ reply->ci = -1;
2243+
2244+ g_ril_append_print_buf(gril, "{");
2245+
2246+ for (i = 0; i < str_arr->num_str; ++i) {
2247+ char *str = str_arr->str[i];
2248+
2249+ if (i > 0)
2250+ g_ril_append_print_buf(gril, "%s,", print_buf);
2251+
2252+ switch (i) {
2253+ case RST_IX_STATE: case RST_IX_LAC:
2254+ case RST_IX_CID: case RST_IX_RAT:
2255+ set_reg_state(gril, reply, i, str);
2256+ break;
2257+ default:
2258+ g_ril_append_print_buf(gril, "%s%s", print_buf,
2259+ str ? str : "(null)");
2260+ }
2261+ }
2262+
2263+ g_ril_append_print_buf(gril, "%s}", print_buf);
2264+ g_ril_print_response(gril, message);
2265+
2266+ /* As a minimum we require a valid status string */
2267+ if (reply->status == -1) {
2268+ ofono_error("%s: invalid status", __func__);
2269+ g_free(reply);
2270+ reply = NULL;
2271+ }
2272+
2273+out:
2274+ parcel_free_str_array(str_arr);
2275+
2276+ return reply;
2277+}
2278+
2279+static void set_data_reg_state(GRil *gril, struct reply_data_reg_state *reply,
2280+ int i, const char *str)
2281+{
2282+ unsigned val;
2283+ char *endp;
2284+
2285+ if (str == NULL || *str == '\0')
2286+ goto no_val;
2287+
2288+ val = (unsigned) strtoul(str, &endp, 10);
2289+ if (*endp != '\0')
2290+ goto no_val;
2291+
2292+ switch (i) {
2293+ case RDST_IX_MAXDC:
2294+ /*
2295+ * MTK modem does not return max_cids, string for this index
2296+ * actually contains the maximum data bearer capability.
2297+ */
2298+ if (g_ril_vendor(gril) == OFONO_RIL_VENDOR_MTK)
2299+ reply->max_cids = MTK_MODEM_MAX_CIDS;
2300+ else
2301+ reply->max_cids = val;
2302+ g_ril_append_print_buf(gril, "%s%u", print_buf, val);
2303+ break;
2304+ default:
2305+ goto no_val;
2306+ }
2307+
2308+ return;
2309+
2310+no_val:
2311+ g_ril_append_print_buf(gril, "%s%s", print_buf, str ? str : "(null)");
2312+}
2313+
2314+struct reply_data_reg_state *g_ril_reply_parse_data_reg_state(GRil *gril,
2315+ const struct ril_msg *message)
2316+{
2317+ struct parcel rilp;
2318+ struct parcel_str_array *str_arr;
2319+ struct reply_data_reg_state *reply = NULL;
2320+ int i;
2321+
2322+ g_ril_init_parcel(message, &rilp);
2323+
2324+ str_arr = parcel_r_str_array(&rilp);
2325+ if (str_arr == NULL) {
2326+ ofono_error("%s: parse error for %s", __func__,
2327+ ril_request_id_to_string(message->req));
2328+ goto out;
2329+ }
2330+
2331+ reply = g_try_malloc0(sizeof(*reply));
2332+ if (reply == NULL) {
2333+ ofono_error("%s: out of memory", __func__);
2334+ goto out;
2335+ }
2336+
2337+ reply->reg_state.status = -1;
2338+ reply->reg_state.lac = -1;
2339+ reply->reg_state.ci = -1;
2340+
2341+ g_ril_append_print_buf(gril, "{");
2342+
2343+ for (i = 0; i < str_arr->num_str; ++i) {
2344+ char *str = str_arr->str[i];
2345+
2346+ if (i > 0)
2347+ g_ril_append_print_buf(gril, "%s,", print_buf);
2348+
2349+ switch (i) {
2350+ case RST_IX_STATE: case RST_IX_LAC:
2351+ case RST_IX_CID: case RST_IX_RAT:
2352+ set_reg_state(gril, &reply->reg_state, i, str);
2353+ break;
2354+ case RDST_IX_MAXDC:
2355+ set_data_reg_state(gril, reply, i, str);
2356+ break;
2357+ default:
2358+ g_ril_append_print_buf(gril, "%s%s", print_buf,
2359+ str ? str : "(null)");
2360+ }
2361+ }
2362+
2363+ g_ril_append_print_buf(gril, "%s}", print_buf);
2364+ g_ril_print_response(gril, message);
2365+
2366+ /* As a minimum we require a valid status string */
2367+ if (reply->reg_state.status == -1) {
2368+ ofono_error("%s: invalid status", __func__);
2369+ g_free(reply);
2370+ reply = NULL;
2371+ }
2372+
2373+out:
2374+ parcel_free_str_array(str_arr);
2375+
2376+ return reply;
2377 }
2378
2379 void g_ril_reply_free_sim_io(struct reply_sim_io *reply)
2380
2381=== modified file 'gril/grilreply.h'
2382--- gril/grilreply.h 2014-07-14 12:47:48 +0000
2383+++ gril/grilreply.h 2014-11-20 00:09:27 +0000
2384@@ -50,7 +50,10 @@
2385 int lac;
2386 int ci;
2387 int tech;
2388- int reason;
2389+};
2390+
2391+struct reply_data_reg_state {
2392+ struct reply_reg_state reg_state;
2393 unsigned int max_cids;
2394 };
2395
2396@@ -110,7 +113,9 @@
2397
2398 gchar *g_ril_reply_parse_imsi(GRil *gril, const struct ril_msg *message);
2399
2400-struct reply_reg_state *g_ril_reply_parse_reg_state(GRil *gril,
2401+struct reply_reg_state *g_ril_reply_parse_voice_reg_state(GRil *gril,
2402+ const struct ril_msg *message);
2403+struct reply_data_reg_state *g_ril_reply_parse_data_reg_state(GRil *gril,
2404 const struct ril_msg *message);
2405
2406 void g_ril_reply_free_sim_status(struct reply_sim_status *status);
2407
2408=== modified file 'gril/parcel.c'
2409--- gril/parcel.c 2014-07-14 12:47:48 +0000
2410+++ gril/parcel.c 2014-11-20 00:09:27 +0000
2411@@ -257,3 +257,38 @@
2412 {
2413 return (p->size - p->offset);
2414 }
2415+
2416+struct parcel_str_array *parcel_r_str_array(struct parcel *p)
2417+{
2418+ int i;
2419+ struct parcel_str_array *str_arr;
2420+ int num_str = parcel_r_int32(p);
2421+
2422+ if (p->malformed || num_str <= 0)
2423+ return NULL;
2424+
2425+ str_arr = g_try_malloc0(sizeof(*str_arr) + num_str * sizeof(char *));
2426+ if (str_arr == NULL)
2427+ return NULL;
2428+
2429+ str_arr->num_str = num_str;
2430+ for (i = 0; i < num_str; ++i)
2431+ str_arr->str[i] = parcel_r_string(p);
2432+
2433+ if (p->malformed) {
2434+ parcel_free_str_array(str_arr);
2435+ return NULL;
2436+ }
2437+
2438+ return str_arr;
2439+}
2440+
2441+void parcel_free_str_array(struct parcel_str_array *str_arr)
2442+{
2443+ if (str_arr) {
2444+ int i;
2445+ for (i = 0; i < str_arr->num_str; ++i)
2446+ g_free(str_arr->str[i]);
2447+ g_free(str_arr);
2448+ }
2449+}
2450
2451=== modified file 'gril/parcel.h'
2452--- gril/parcel.h 2014-07-14 12:47:48 +0000
2453+++ gril/parcel.h 2014-11-20 00:09:27 +0000
2454@@ -32,6 +32,11 @@
2455 int malformed;
2456 };
2457
2458+struct parcel_str_array {
2459+ int num_str;
2460+ char *str[];
2461+};
2462+
2463 void parcel_init(struct parcel *p);
2464 void parcel_grow(struct parcel *p, size_t size);
2465 void parcel_free(struct parcel *p);
2466@@ -42,5 +47,7 @@
2467 int parcel_w_raw(struct parcel *p, const void *data, size_t len);
2468 void *parcel_r_raw(struct parcel *p, int *len);
2469 size_t parcel_data_avail(struct parcel *p);
2470+struct parcel_str_array *parcel_r_str_array(struct parcel *p);
2471+void parcel_free_str_array(struct parcel_str_array *str_arr);
2472
2473 #endif
2474
2475=== modified file 'include/sim.h'
2476--- include/sim.h 2013-11-11 10:37:01 +0000
2477+++ include/sim.h 2014-11-20 00:09:27 +0000
2478@@ -104,6 +104,11 @@
2479 typedef void (*ofono_sim_file_read_cb_t)(int ok, int total_length, int record,
2480 const unsigned char *data,
2481 int record_length, void *userdata);
2482+
2483+typedef void (*ofono_sim_read_info_cb_t)(int ok, unsigned char file_status,
2484+ int total_length, int record_length,
2485+ void *userdata);
2486+
2487 typedef void (*ofono_sim_file_changed_cb_t)(int id, void *userdata);
2488
2489 typedef void (*ofono_sim_file_write_cb_t)(int ok, void *userdata);
2490@@ -220,7 +225,8 @@
2491 struct ofono_sim_context *ofono_sim_context_create(struct ofono_sim *sim);
2492 void ofono_sim_context_free(struct ofono_sim_context *context);
2493
2494-/* This will queue an operation to read all available records with id from the
2495+/*
2496+ * This will queue an operation to read all available records with id from the
2497 * SIM. Callback cb will be called every time a record has been read, or once
2498 * if an error has occurred. For transparent files, the callback will only
2499 * be called once.
2500@@ -231,6 +237,22 @@
2501 enum ofono_sim_file_structure expected,
2502 ofono_sim_file_read_cb_t cb, void *data);
2503
2504+int ofono_sim_read_path(struct ofono_sim_context *context, int id,
2505+ enum ofono_sim_file_structure expected_type,
2506+ const unsigned char *path, unsigned int path_len,
2507+ ofono_sim_file_read_cb_t cb, void *data);
2508+
2509+int ofono_sim_read_info(struct ofono_sim_context *context, int id,
2510+ enum ofono_sim_file_structure expected_type,
2511+ const unsigned char *path, unsigned int pth_len,
2512+ ofono_sim_read_info_cb_t cb, void *data);
2513+
2514+int ofono_sim_read_record(struct ofono_sim_context *context, int id,
2515+ enum ofono_sim_file_structure expected_type,
2516+ int record, int record_length,
2517+ const unsigned char *path, unsigned int pth_len,
2518+ ofono_sim_file_read_cb_t cb, void *data);
2519+
2520 int ofono_sim_write(struct ofono_sim_context *context, int id,
2521 ofono_sim_file_write_cb_t cb,
2522 enum ofono_sim_file_structure structure, int record,
2523
2524=== modified file 'plugins/mtk.c'
2525--- plugins/mtk.c 2014-09-16 08:03:09 +0000
2526+++ plugins/mtk.c 2014-11-20 00:09:27 +0000
2527@@ -66,6 +66,8 @@
2528 #include "drivers/mtkmodem/mtk_constants.h"
2529 #include "drivers/mtkmodem/mtkutil.h"
2530 #include "drivers/mtkmodem/mtkrequest.h"
2531+#include "drivers/mtkmodem/mtkreply.h"
2532+#include "drivers/mtkmodem/mtksettings.h"
2533
2534 #define MAX_SIM_STATUS_RETRIES 15
2535
2536@@ -76,16 +78,25 @@
2537 #define SIM_2_ACTIVE 2
2538 #define NO_SIM_ACTIVE 0
2539
2540+#define SOCKET_NUM_FOR_DBG_0 -1
2541+#define SOCKET_NUM_FOR_DBG_1 -2
2542+
2543 /* this gives 30s for rild to initialize */
2544 #define RILD_MAX_CONNECT_RETRIES 5
2545 #define RILD_CONNECT_RETRY_TIME_S 5
2546
2547+#define T_WAIT_DISCONN_MS 1000
2548+
2549+static const char hex_slot_0[] = "Slot 0: ";
2550+static const char hex_slot_1[] = "Slot 1: ";
2551+
2552 typedef void (*pending_cb_t)(struct cb_data *cbd);
2553
2554 struct mtk_data {
2555 GRil *modem;
2556 int sim_status_retries;
2557 ofono_bool_t ofono_online;
2558+ ofono_bool_t ofono_online_target;
2559 int radio_state;
2560 struct ofono_sim *sim;
2561 /* pending_* are used in case we are disconnected from the socket */
2562@@ -106,8 +117,12 @@
2563 struct ofono_call_settings *call_settings;
2564 struct ofono_call_forwarding *call_forwarding;
2565 struct ofono_call_barring *call_barring;
2566+ struct ofono_phonebook *phonebook;
2567 struct ofono_gprs *gprs;
2568 struct ofono_message_waiting *message_waiting;
2569+ struct ofono_modem *ofono_modem;
2570+ ofono_bool_t has_3g;
2571+ struct mtk_settings_data *mtk_settings;
2572 };
2573
2574 /*
2575@@ -119,11 +134,27 @@
2576 static struct mtk_data *mtk_0;
2577 static struct mtk_data *mtk_1;
2578
2579-static void send_get_sim_status(struct ofono_modem *modem);
2580+/* Some variables control global state of the modem and are then static */
2581+static gboolean disconnect_expected;
2582+static guint not_disconn_cb_id;
2583+
2584+struct socket_data {
2585+ GRil *gril;
2586+ const char *path;
2587+ int radio_state;
2588+ guint radio_state_ev_id;
2589+};
2590+
2591+static struct socket_data *sock_0, *sock_1;
2592+
2593 static int create_gril(struct ofono_modem *modem);
2594 static gboolean mtk_connected(gpointer user_data);
2595 static void mtk_set_online(struct ofono_modem *modem, ofono_bool_t online,
2596 ofono_modem_online_cb_t callback, void *data);
2597+static void query_3g_caps(struct socket_data *sock);
2598+static void socket_disconnected(gpointer user_data);
2599+static void start_slot(struct mtk_data *ril, struct socket_data *sock,
2600+ const char *hex_prefix);
2601
2602 static void mtk_debug(const char *str, void *user_data)
2603 {
2604@@ -140,6 +171,14 @@
2605 return mtk_0;
2606 }
2607
2608+static struct socket_data *socket_complement(struct socket_data *sock)
2609+{
2610+ if (sock == sock_0)
2611+ return sock_1;
2612+ else
2613+ return sock_0;
2614+}
2615+
2616 /*
2617 * mtk_set_attach_state and mtk_detach_received are called by mtkmodem's gprs
2618 * driver. They are needed to solve an issue with data attachment: in case
2619@@ -191,13 +230,34 @@
2620 }
2621 }
2622
2623-static gboolean sim_status_retry(gpointer user_data)
2624+static void radio_state_changed(struct ril_msg *message, gpointer user_data)
2625 {
2626- struct ofono_modem *modem = user_data;
2627- send_get_sim_status(modem);
2628-
2629- /* Makes this a single shot */
2630- return FALSE;
2631+ struct socket_data *sock = user_data;
2632+ int radio_state = g_ril_unsol_parse_radio_state_changed(sock->gril,
2633+ message);
2634+
2635+ if (radio_state != sock->radio_state) {
2636+ struct socket_data *sock_c = socket_complement(sock);
2637+
2638+ ofono_info("%s, state: %s", __func__,
2639+ ril_radio_state_to_string(radio_state));
2640+
2641+ /*
2642+ * If there is just one slot, just start it. Otherwise, we ask
2643+ * who owns the 3G capabilities in case both slots have already
2644+ * radio state different from UNAVAILABLE.
2645+ */
2646+ if (mtk_1 == NULL) {
2647+ mtk_0->has_3g = TRUE;
2648+ start_slot(mtk_0, sock, hex_slot_0);
2649+ } else if (sock->radio_state == RADIO_STATE_UNAVAILABLE &&
2650+ sock_c != NULL && sock_c->radio_state !=
2651+ RADIO_STATE_UNAVAILABLE) {
2652+ query_3g_caps(sock);
2653+ }
2654+
2655+ sock->radio_state = radio_state;
2656+ }
2657 }
2658
2659 static void mtk_radio_state_changed(struct ril_msg *message, gpointer user_data)
2660@@ -214,9 +274,6 @@
2661 ril_radio_state_to_string(radio_state),
2662 ril->ofono_online);
2663
2664- if (ril->radio_state == RADIO_STATE_UNAVAILABLE)
2665- mtk_connected(modem);
2666-
2667 ril->radio_state = radio_state;
2668
2669 switch (radio_state) {
2670@@ -269,65 +326,6 @@
2671 }
2672 }
2673
2674-static void sim_status_cb(struct ril_msg *message, gpointer user_data)
2675-{
2676- struct ofono_modem *modem = user_data;
2677- struct mtk_data *ril = ofono_modem_get_data(modem);
2678- struct reply_sim_status *status;
2679-
2680- DBG("slot %d", ril->slot);
2681-
2682- if (message->error != RIL_E_SUCCESS) {
2683- ril->sim_status_retries++;
2684-
2685- ofono_error("[slot %d] GET_SIM_STATUS request failed: "
2686- "%s; retries: %d",
2687- ril->slot, ril_error_to_string(message->error),
2688- ril->sim_status_retries);
2689-
2690- if (ril->sim_status_retries < MAX_SIM_STATUS_RETRIES)
2691- g_timeout_add_seconds(2, sim_status_retry, modem);
2692- else
2693- ofono_error("[slot %d] Max retries for GET_SIM_STATUS"
2694- " exceeded!", ril->slot);
2695- } else {
2696-
2697- /* Register for changes in SIM insertion */
2698- g_ril_register(ril->modem, MTK_RIL_UNSOL_SIM_PLUG_OUT,
2699- sim_removed, modem);
2700- g_ril_register(ril->modem, MTK_RIL_UNSOL_SIM_PLUG_IN,
2701- sim_inserted, modem);
2702-
2703- if ((status = g_ril_reply_parse_sim_status(ril->modem, message))
2704- != NULL) {
2705-
2706- if (status->card_state == RIL_CARDSTATE_PRESENT) {
2707- DBG("Card PRESENT; num_apps: %d",
2708- status->num_apps);
2709-
2710- ofono_sim_inserted_notify(ril->sim, TRUE);
2711- } else {
2712- ofono_warn("[slot %d] Card NOT_PRESENT",
2713- ril->slot);
2714-
2715- ofono_sim_inserted_notify(ril->sim, FALSE);
2716- }
2717- g_ril_reply_free_sim_status(status);
2718- }
2719- }
2720-}
2721-
2722-static void send_get_sim_status(struct ofono_modem *modem)
2723-{
2724- struct mtk_data *ril = ofono_modem_get_data(modem);
2725-
2726- DBG("slot %d", ril->slot);
2727-
2728- if (g_ril_send(ril->modem, RIL_REQUEST_GET_SIM_STATUS, NULL,
2729- sim_status_cb, modem, NULL) == 0)
2730- ofono_error("%s: failure sending request", __func__);
2731-}
2732-
2733 static int mtk_probe(struct ofono_modem *modem)
2734 {
2735 struct mtk_data *ril = g_try_new0(struct mtk_data, 1);
2736@@ -349,6 +347,8 @@
2737
2738 DBG("slot %d", ril->slot);
2739
2740+ ril->ofono_modem = modem;
2741+
2742 ofono_modem_set_data(modem, ril);
2743
2744 return 0;
2745@@ -434,7 +434,9 @@
2746 ril->call_barring =
2747 ofono_call_barring_create(modem, OFONO_RIL_VENDOR_MTK,
2748 RILMODEM, ril->modem);
2749-
2750+ ril->phonebook =
2751+ ofono_phonebook_create(modem, OFONO_RIL_VENDOR_MTK,
2752+ RILMODEM, modem);
2753 ril->gprs = ofono_gprs_create(modem, OFONO_RIL_VENDOR_MTK,
2754 MTKMODEM, &gprs_data);
2755
2756@@ -470,6 +472,10 @@
2757 ofono_gprs_remove(ril->gprs);
2758 ril->gprs = NULL;
2759 }
2760+ if (ril->phonebook) {
2761+ ofono_phonebook_remove(ril->phonebook);
2762+ ril->phonebook = NULL;
2763+ }
2764 if (ril->call_barring) {
2765 ofono_call_barring_remove(ril->call_barring);
2766 ril->call_barring = NULL;
2767@@ -515,9 +521,11 @@
2768 ofono_radio_settings_create(modem, OFONO_RIL_VENDOR_MTK,
2769 MTKMODEM, ril->modem);
2770
2771- /* Ask sim status */
2772- ril->sim_status_retries = 0;
2773- send_get_sim_status(modem);
2774+ /* Register for changes in SIM insertion */
2775+ g_ril_register(ril->modem, MTK_RIL_UNSOL_SIM_PLUG_OUT,
2776+ sim_removed, modem);
2777+ g_ril_register(ril->modem, MTK_RIL_UNSOL_SIM_PLUG_IN,
2778+ sim_inserted, modem);
2779 }
2780
2781 static void mtk_sim_mode_cb(struct ril_msg *message, gpointer user_data)
2782@@ -540,11 +548,18 @@
2783 CALLBACK_WITH_FAILURE(cb, cbd->data);
2784 }
2785
2786+ if (ril->ofono_online)
2787+ ril->mtk_settings =
2788+ mtk_settings_create(ril->ofono_modem, ril->modem,
2789+ ril->has_3g);
2790+ else
2791+ mtk_settings_remove(ril->mtk_settings);
2792+
2793 /* Execute possible pending operation on the other modem */
2794
2795 ril_c = ril_complement(ril);
2796
2797- if (ril_c->pending_online_cbd) {
2798+ if (ril_c != NULL && ril_c->pending_online_cbd) {
2799 struct cb_data *pending_cbd = ril_c->pending_online_cbd;
2800 ofono_modem_online_cb_t pending_cb = pending_cbd->cb;
2801
2802@@ -594,6 +609,18 @@
2803 }
2804 }
2805
2806+static gboolean no_disconnect_case(gpointer user_data)
2807+{
2808+ struct cb_data *cbd = user_data;
2809+
2810+ ofono_info("%s: Execute pending sim mode switch", __func__);
2811+ not_disconn_cb_id = 0;
2812+
2813+ mtk_send_sim_mode(mtk_sim_mode_cb, cbd);
2814+
2815+ return FALSE;
2816+}
2817+
2818 static void poweron_cb(struct ril_msg *message, gpointer user_data)
2819 {
2820 struct cb_data *cbd = user_data;
2821@@ -603,10 +630,41 @@
2822
2823 DBG("");
2824
2825+ /*
2826+ * MTK's rild behavior when a POWERON is sent to it is different
2827+ * depending on whether a previous POWEROFF had been sent. When
2828+ * the modem is initialized during device startup, POWERON is
2829+ * sent without a prior POWEROFF, rild responds with an OK reply,
2830+ * and the modem is brought up. Any subsequent POWERON requests
2831+ * are sent whenever both modems have been offlined before ( meaning a
2832+ * POWEROFF has been sent prior ). rild may respond to the POWERON
2833+ * request, but will usually ( always? ) trigger a socket disconnect in
2834+ * this case.
2835+ *
2836+ * This means there's a race condition between the POWERON reply
2837+ * callback and the socket disconnect function ( which triggers a
2838+ * SIM_MODE_SWITCH request ). In some cases rild is slower than
2839+ * usual closing the socket, so we add a timeout to avoid following
2840+ * the code path used when there is not a disconnection. Otherwise,
2841+ * there would be a race and some requests would return errors due to
2842+ * having been sent through the about-to-be-disconnected socket, leaving
2843+ * ofono in an inconsistent state. So, we delay sending the
2844+ * SIM_MODE_SWITCH for 1s, to allow the disconnect to happen when we
2845+ * know that we have sent previously a POWEROFF.
2846+ *
2847+ * Also, I saw once that sending SIM_MODE while the
2848+ * socket was being disconnected provoked a crash due to SIGPIPE being
2849+ * issued. The timeout should also fix this.
2850+ */
2851+
2852 if (message->error == RIL_E_SUCCESS) {
2853 g_ril_print_response_no_args(ril->modem, message);
2854
2855- mtk_send_sim_mode(mtk_sim_mode_cb, cbd);
2856+ if (disconnect_expected)
2857+ not_disconn_cb_id = g_timeout_add(T_WAIT_DISCONN_MS,
2858+ no_disconnect_case, cbd);
2859+ else
2860+ mtk_send_sim_mode(mtk_sim_mode_cb, cbd);
2861 } else {
2862 ofono_error("%s RADIO_POWERON error %s", __func__,
2863 ril_error_to_string(message->error));
2864@@ -632,6 +690,8 @@
2865 if (message->error == RIL_E_SUCCESS) {
2866 g_ril_print_response_no_args(ril->modem, message);
2867
2868+ mtk_settings_remove(ril->mtk_settings);
2869+
2870 CALLBACK_WITH_SUCCESS(cb, cbd->data);
2871 } else {
2872 ofono_error("%s: RIL error %s", __func__,
2873@@ -704,12 +764,47 @@
2874 ofono_error("%s: failure sending request", __func__);
2875 CALLBACK_WITH_FAILURE(cb, cbd->data);
2876 g_free(cbd);
2877+ } else {
2878+ disconnect_expected = TRUE;
2879 }
2880 } else {
2881 mtk_send_sim_mode(mtk_sim_mode_cb, cbd);
2882 }
2883 }
2884
2885+static void set_online_cb(const struct ofono_error *error, void *data)
2886+{
2887+ if (mtk_1->ofono_online_target && !mtk_1->ofono_online)
2888+ mtk_set_online(mtk_1->ofono_modem, TRUE, set_online_cb, NULL);
2889+}
2890+
2891+static void set_offline_cb(const struct ofono_error *error, void *data)
2892+{
2893+ if (mtk_1->ofono_online)
2894+ mtk_set_online(mtk_1->ofono_modem, FALSE, set_offline_cb, NULL);
2895+ else if (mtk_0->ofono_online_target)
2896+ mtk_set_online(mtk_0->ofono_modem, TRUE, set_online_cb, NULL);
2897+ else
2898+ mtk_set_online(mtk_1->ofono_modem, TRUE, set_online_cb, NULL);
2899+}
2900+
2901+void mtk_reset_all_modems(void)
2902+{
2903+ if (!mtk_0->ofono_online && !mtk_1->ofono_online)
2904+ return;
2905+
2906+ mtk_0->ofono_online_target = mtk_0->ofono_online;
2907+ mtk_1->ofono_online_target = mtk_1->ofono_online;
2908+
2909+ ofono_modem_set_powered(mtk_0->ofono_modem, FALSE);
2910+ ofono_modem_set_powered(mtk_1->ofono_modem, FALSE);
2911+
2912+ if (mtk_0->ofono_online)
2913+ mtk_set_online(mtk_0->ofono_modem, FALSE, set_offline_cb, NULL);
2914+ else
2915+ mtk_set_online(mtk_1->ofono_modem, FALSE, set_offline_cb, NULL);
2916+}
2917+
2918 static void create_atoms_on_connection(struct ofono_modem *modem)
2919 {
2920 struct mtk_data *ril = ofono_modem_get_data(modem);
2921@@ -728,14 +823,97 @@
2922 {
2923 struct mtk_data *ril = ofono_modem_get_data(modem);
2924
2925- ofono_call_volume_remove(ril->callvolume);
2926+ if (__ofono_modem_find_atom(modem, OFONO_ATOM_TYPES_CALL_VOLUME))
2927+ ofono_call_volume_remove(ril->callvolume);
2928 ril->callvolume = NULL;
2929- ofono_voicecall_remove(ril->voicecall);
2930+ if (__ofono_modem_find_atom(modem, OFONO_ATOM_TYPE_VOICECALL))
2931+ ofono_voicecall_remove(ril->voicecall);
2932 ril->voicecall = NULL;
2933- ofono_devinfo_remove(ril->devinfo);
2934+ if (__ofono_modem_find_atom(modem, OFONO_ATOM_TYPE_DEVINFO))
2935+ ofono_devinfo_remove(ril->devinfo);
2936 ril->devinfo = NULL;
2937 }
2938
2939+static void start_slot(struct mtk_data *ril, struct socket_data *sock,
2940+ const char *hex_prefix)
2941+{
2942+ ofono_info("Physical slot %d in socket %s", ril->slot, sock->path);
2943+
2944+ ril->modem = sock->gril;
2945+ ril->radio_state = sock->radio_state;
2946+
2947+ g_ril_set_slot(ril->modem, ril->slot);
2948+
2949+ if (getenv("OFONO_RIL_TRACE"))
2950+ g_ril_set_trace(ril->modem, TRUE);
2951+
2952+ if (getenv("OFONO_RIL_HEX_TRACE"))
2953+ g_ril_set_debugf(ril->modem, mtk_debug, (char *) hex_prefix);
2954+
2955+ g_ril_set_disconnect_function(ril->modem, socket_disconnected,
2956+ ril->ofono_modem);
2957+
2958+ g_ril_unregister(sock->gril, sock->radio_state_ev_id);
2959+
2960+ g_ril_register(ril->modem, RIL_UNSOL_RESPONSE_RADIO_STATE_CHANGED,
2961+ mtk_radio_state_changed, ril->ofono_modem);
2962+
2963+ mtk_connected(ril->ofono_modem);
2964+}
2965+
2966+static void query_3g_caps_cb(struct ril_msg *message, gpointer user_data)
2967+{
2968+ struct socket_data *sock = user_data;
2969+ struct socket_data *sock_for_mtk_0, *sock_for_mtk_1;
2970+ int slot_3g;
2971+
2972+ if (message->error != RIL_E_SUCCESS) {
2973+ ofono_error("%s: error %s", __func__,
2974+ ril_error_to_string(message->error));
2975+ return;
2976+ }
2977+
2978+ slot_3g = g_mtk_reply_parse_get_3g_capability(sock->gril, message);
2979+
2980+ /*
2981+ * The socket at sock_slot_0 always connects to the slot with 3G
2982+ * capabilities, while sock_slot_1 connects to the slot that is just 2G.
2983+ * However, the physical slot that owns the 3G capabilities can be
2984+ * changed dynamically using a RILd request, so the sockets can connect
2985+ * to different physical slots depending on the current configuration.
2986+ * We want to keep the relationship between the physical slots and
2987+ * the modem names in DBus (so /ril_0 and /ril_1 always refer to the
2988+ * same physical slots), so here we assign the sockets needed by mtk_0
2989+ * and mtk_1 structures to make sure that happens.
2990+ */
2991+ if (slot_3g == MULTISIM_SLOT_0) {
2992+ sock_for_mtk_0 = sock_0;
2993+ sock_for_mtk_1 = sock_1;
2994+ mtk_0->has_3g = TRUE;
2995+ mtk_1->has_3g = FALSE;
2996+ } else {
2997+ sock_for_mtk_0 = sock_1;
2998+ sock_for_mtk_1 = sock_0;
2999+ mtk_0->has_3g = FALSE;
3000+ mtk_1->has_3g = TRUE;
3001+ }
3002+
3003+ start_slot(mtk_0, sock_for_mtk_0, hex_slot_0);
3004+ start_slot(mtk_1, sock_for_mtk_1, hex_slot_1);
3005+
3006+ g_free(sock_0);
3007+ sock_0 = NULL;
3008+ g_free(sock_1);
3009+ sock_1 = NULL;
3010+}
3011+
3012+static void query_3g_caps(struct socket_data *sock)
3013+{
3014+ if (g_ril_send(sock->gril, MTK_RIL_REQUEST_GET_3G_CAPABILITY, NULL,
3015+ query_3g_caps_cb, sock, NULL) <= 0)
3016+ ofono_error("%s Error querying 3G capabilities", __func__);
3017+}
3018+
3019 static gboolean mtk_connected(gpointer user_data)
3020 {
3021 struct ofono_modem *modem = (struct ofono_modem *) user_data;
3022@@ -745,10 +923,14 @@
3023
3024 DBG("calling set_powered(TRUE)");
3025
3026- ofono_modem_set_powered(modem, TRUE);
3027+ if (!ofono_modem_get_powered(modem))
3028+ ofono_modem_set_powered(modem, TRUE);
3029
3030 create_atoms_on_connection(modem);
3031
3032+ if (ril->pending_cb)
3033+ ril->pending_cb(ril->pending_cbd);
3034+
3035 /* Call the function just once */
3036 return FALSE;
3037 }
3038@@ -763,11 +945,6 @@
3039 if (create_gril(modem) < 0)
3040 return TRUE;
3041
3042- create_atoms_on_connection(modem);
3043-
3044- if (ril->pending_cb)
3045- ril->pending_cb(ril->pending_cbd);
3046-
3047 /* Reconnected: do not call this again */
3048 return FALSE;
3049 }
3050@@ -787,36 +964,46 @@
3051 g_ril_unref(ril->modem);
3052 ril->modem = NULL;
3053
3054+ /* Disconnection happened so we do not call failsafe function */
3055+ if (not_disconn_cb_id != 0) {
3056+ g_source_remove(not_disconn_cb_id);
3057+ not_disconn_cb_id = 0;
3058+ }
3059+
3060 /* The disconnection happens because rild is re-starting, wait for it */
3061 g_timeout_add(WAIT_FOR_RILD_TO_RESTART_MS, reconnect_rild, modem);
3062 }
3063
3064 static const char sock_slot_0[] = "/dev/socket/rild";
3065 static const char sock_slot_1[] = "/dev/socket/rild2";
3066-static const char hex_slot_0[] = "Slot 0: ";
3067-static const char hex_slot_1[] = "Slot 1: ";
3068
3069 static int create_gril(struct ofono_modem *modem)
3070 {
3071 struct mtk_data *ril = ofono_modem_get_data(modem);
3072- const char *sock_path;
3073- const char *hex_prefix;
3074+ struct socket_data *sock;
3075+ int sock_num;
3076
3077 DBG("slot %d", ril->slot);
3078
3079 if (ril->modem != NULL)
3080 return 0;
3081
3082+ sock = g_try_malloc0(sizeof(*sock));
3083+ if (sock == NULL) {
3084+ ofono_error("%s: Cannot allocate socket_data", __func__);
3085+ return -ENOMEM;
3086+ }
3087+
3088 if (ril->slot == MULTISIM_SLOT_0) {
3089- sock_path = sock_slot_0;
3090- hex_prefix = hex_slot_0;
3091+ sock_num = SOCKET_NUM_FOR_DBG_0;
3092+ sock->path = sock_slot_0;
3093 } else {
3094- sock_path = sock_slot_1;
3095- hex_prefix = hex_slot_1;
3096+ sock_num = SOCKET_NUM_FOR_DBG_1;
3097+ sock->path = sock_slot_1;
3098 }
3099
3100 /* Opens the socket to RIL */
3101- ril->modem = g_ril_new(sock_path, OFONO_RIL_VENDOR_MTK);
3102+ sock->gril = g_ril_new(sock->path, OFONO_RIL_VENDOR_MTK);
3103
3104 /*
3105 * NOTE: Since AT modems open a tty, and then call
3106@@ -827,28 +1014,34 @@
3107 * abstraction... ( probaby not a bad idea ).
3108 */
3109
3110- if (ril->modem == NULL) {
3111- ofono_error("g_ril_new() failed to create modem %d!",
3112- ril->slot);
3113+ if (sock->gril == NULL) {
3114+ ofono_error("g_ril_new() failed to connect to %s!", sock->path);
3115+ g_free(sock);
3116 return -EIO;
3117+ } else if (ril->slot == MULTISIM_SLOT_0) {
3118+ sock_0 = sock;
3119+ } else {
3120+ sock_1 = sock;
3121 }
3122
3123- g_ril_set_slot(ril->modem, ril->slot);
3124-
3125- g_ril_set_vendor_print_msg_id_funcs(ril->modem,
3126+ sock->radio_state = RADIO_STATE_UNAVAILABLE;
3127+ sock->radio_state_ev_id =
3128+ g_ril_register(sock->gril,
3129+ RIL_UNSOL_RESPONSE_RADIO_STATE_CHANGED,
3130+ radio_state_changed, sock);
3131+
3132+ /* sock_num is negative to avoid confusion with physical slots */
3133+ g_ril_set_slot(sock->gril, sock_num);
3134+
3135+ g_ril_set_vendor_print_msg_id_funcs(sock->gril,
3136 mtk_request_id_to_string,
3137 mtk_unsol_request_to_string);
3138
3139 if (getenv("OFONO_RIL_TRACE"))
3140- g_ril_set_trace(ril->modem, TRUE);
3141+ g_ril_set_trace(sock->gril, TRUE);
3142
3143 if (getenv("OFONO_RIL_HEX_TRACE"))
3144- g_ril_set_debugf(ril->modem, mtk_debug, (char *) hex_prefix);
3145-
3146- g_ril_set_disconnect_function(ril->modem, socket_disconnected, modem);
3147-
3148- g_ril_register(ril->modem, RIL_UNSOL_RESPONSE_RADIO_STATE_CHANGED,
3149- mtk_radio_state_changed, modem);
3150+ g_ril_set_debugf(sock->gril, mtk_debug, (char *) sock->path);
3151
3152 return 0;
3153 }
3154@@ -875,14 +1068,14 @@
3155 {
3156 int ret;
3157
3158+ /* We handle SIM states due to MTK peculiarities */
3159+ ofono_modem_set_driver_watches_sim(modem, TRUE);
3160+
3161 ret = create_gril(modem);
3162 if (ret < 0)
3163 g_timeout_add_seconds(RILD_CONNECT_RETRY_TIME_S,
3164 connect_rild, modem);
3165
3166- /* We handle SIM states due to MTK peculiarities */
3167- ofono_modem_set_driver_watches_sim(modem, TRUE);
3168-
3169 /*
3170 * We will mark the modem as powered when we receive an event that
3171 * confirms that the radio is in a state different from unavailable
3172@@ -897,6 +1090,11 @@
3173
3174 DBG("%p", modem);
3175
3176+ if (ril->slot == MULTISIM_SLOT_0 && not_disconn_cb_id != 0) {
3177+ g_source_remove(not_disconn_cb_id);
3178+ not_disconn_cb_id = 0;
3179+ }
3180+
3181 if (ril->ofono_online) {
3182 ril->ofono_online = FALSE;
3183 mtk_send_sim_mode(NULL, NULL);
3184
3185=== modified file 'plugins/ril.c'
3186--- plugins/ril.c 2014-09-20 19:12:27 +0000
3187+++ plugins/ril.c 2014-11-20 00:09:27 +0000
3188@@ -84,8 +84,6 @@
3189 int rild_connect_retries;
3190 };
3191
3192-static void send_get_sim_status(struct ofono_modem *modem);
3193-
3194 static void ril_debug(const char *str, void *user_data)
3195 {
3196 const char *prefix = user_data;
3197@@ -93,15 +91,6 @@
3198 ofono_info("%s%s", prefix, str);
3199 }
3200
3201-static gboolean sim_status_retry(gpointer user_data)
3202-{
3203- struct ofono_modem *modem = user_data;
3204- send_get_sim_status(modem);
3205-
3206- /* Makes this a single shot */
3207- return FALSE;
3208-}
3209-
3210 static void ril_radio_state_changed(struct ril_msg *message, gpointer user_data)
3211 {
3212 struct ofono_modem *modem = user_data;
3213@@ -127,7 +116,6 @@
3214 ril->vendor, RILMODEM,
3215 ril->modem);
3216
3217- send_get_sim_status(modem);
3218 break;
3219
3220 case RADIO_STATE_UNAVAILABLE:
3221@@ -150,56 +138,6 @@
3222 }
3223 }
3224
3225-static void sim_status_cb(struct ril_msg *message, gpointer user_data)
3226-{
3227- struct ofono_modem *modem = user_data;
3228- struct ril_data *ril = ofono_modem_get_data(modem);
3229- struct reply_sim_status *status;
3230-
3231- DBG("");
3232-
3233- if (message->error != RIL_E_SUCCESS) {
3234- ril->sim_status_retries++;
3235-
3236- ofono_error("GET_SIM_STATUS request failed: %s; retries: %d",
3237- ril_error_to_string(message->error),
3238- ril->sim_status_retries);
3239-
3240- if (ril->sim_status_retries < MAX_SIM_STATUS_RETRIES)
3241- g_timeout_add_seconds(2, sim_status_retry, modem);
3242- else
3243- ofono_error("Max retries for GET_SIM_STATUS exceeded!");
3244- } else {
3245-
3246- if ((status = g_ril_reply_parse_sim_status(ril->modem, message))
3247- != NULL) {
3248-
3249- if (status->card_state == RIL_CARDSTATE_PRESENT) {
3250- DBG("Card PRESENT; num_apps: %d",
3251- status->num_apps);
3252-
3253- ofono_sim_inserted_notify(ril->sim, TRUE);
3254-
3255- } else {
3256- ofono_warn("Card NOT_PRESENT.");
3257-
3258- ofono_sim_inserted_notify(ril->sim, FALSE);
3259- }
3260- g_ril_reply_free_sim_status(status);
3261- }
3262- }
3263-}
3264-
3265-static void send_get_sim_status(struct ofono_modem *modem)
3266-{
3267- struct ril_data *ril = ofono_modem_get_data(modem);
3268-
3269- DBG("");
3270-
3271- g_ril_send(ril->modem, RIL_REQUEST_GET_SIM_STATUS, NULL,
3272- sim_status_cb, modem, NULL);
3273-}
3274-
3275 int ril_create(struct ofono_modem *modem, enum ofono_ril_vendor vendor)
3276 {
3277 struct ril_data *ril = g_try_new0(struct ril_data, 1);
3278@@ -302,6 +240,8 @@
3279 ofono_message_waiting_register(mw);
3280
3281 ofono_call_forwarding_create(modem, ril->vendor, RILMODEM, ril->modem);
3282+
3283+ ofono_phonebook_create(modem, ril->vendor, RILMODEM, modem);
3284 }
3285
3286 void ril_post_online(struct ofono_modem *modem)
3287
3288=== modified file 'src/sim.c'
3289--- src/sim.c 2014-09-16 08:03:09 +0000
3290+++ src/sim.c 2014-11-20 00:09:27 +0000
3291@@ -1604,7 +1604,7 @@
3292 if (sim_sst_is_active(sim->efsst, sim->efsst_length,
3293 SIM_SST_SERVICE_BDN)) {
3294 sim_fs_read_info(sim->context, SIM_EFBDN_FILEID,
3295- OFONO_SIM_FILE_STRUCTURE_FIXED,
3296+ OFONO_SIM_FILE_STRUCTURE_FIXED, NULL, 0,
3297 sim_efbdn_info_read_cb, sim);
3298 return TRUE;
3299 }
3300@@ -1658,7 +1658,7 @@
3301 if (sim_sst_is_active(sim->efsst, sim->efsst_length,
3302 SIM_SST_SERVICE_FDN)) {
3303 sim_fs_read_info(sim->context, SIM_EFADN_FILEID,
3304- OFONO_SIM_FILE_STRUCTURE_FIXED,
3305+ OFONO_SIM_FILE_STRUCTURE_FIXED, NULL, 0,
3306 sim_efadn_info_read_cb, sim);
3307 return;
3308 }
3309@@ -2206,6 +2206,34 @@
3310 return sim_fs_read(context, id, expected_type, 0, 0, NULL, 0, cb, data);
3311 }
3312
3313+int ofono_sim_read_path(struct ofono_sim_context *context, int id,
3314+ enum ofono_sim_file_structure expected_type,
3315+ const unsigned char *path, unsigned int path_len,
3316+ ofono_sim_file_read_cb_t cb, void *data)
3317+{
3318+ return sim_fs_read(context, id, expected_type, 0, 0,
3319+ path, path_len, cb, data);
3320+}
3321+
3322+int ofono_sim_read_info(struct ofono_sim_context *context, int id,
3323+ enum ofono_sim_file_structure expected_type,
3324+ const unsigned char *path, unsigned int pth_len,
3325+ ofono_sim_read_info_cb_t cb, void *data)
3326+{
3327+ return sim_fs_read_info(context, id, expected_type, path, pth_len,
3328+ cb, data);
3329+}
3330+
3331+int ofono_sim_read_record(struct ofono_sim_context *context, int id,
3332+ enum ofono_sim_file_structure expected_type,
3333+ int record, int record_length,
3334+ const unsigned char *path, unsigned int pth_len,
3335+ ofono_sim_file_read_cb_t cb, void *data)
3336+{
3337+ return sim_fs_read_record(context, id, expected_type, record,
3338+ record_length, path, pth_len, cb, data);
3339+}
3340+
3341 int ofono_sim_write(struct ofono_sim_context *context, int id,
3342 ofono_sim_file_write_cb_t cb,
3343 enum ofono_sim_file_structure structure, int record,
3344
3345=== modified file 'src/simfs.c'
3346--- src/simfs.c 2012-11-23 13:22:25 +0000
3347+++ src/simfs.c 2014-11-20 00:09:27 +0000
3348@@ -264,7 +264,7 @@
3349 }
3350
3351 if (op->info_only == TRUE)
3352- ((sim_fs_read_info_cb_t) op->cb)
3353+ ((ofono_sim_read_info_cb_t) op->cb)
3354 (0, 0, 0, 0, op->userdata);
3355 else if (op->is_read == TRUE)
3356 ((ofono_sim_file_read_cb_t) op->cb)
3357@@ -335,6 +335,27 @@
3358 sim_fs_end_current(fs);
3359 }
3360
3361+static void sim_fs_op_read_record_cb(const struct ofono_error *error,
3362+ const unsigned char *sdata, int length,
3363+ void *data)
3364+{
3365+ struct sim_fs *fs = data;
3366+ struct sim_fs_op *op = g_queue_peek_head(fs->op_q);
3367+ ofono_sim_file_read_cb_t cb = op->cb;
3368+
3369+ if (cb == NULL) {
3370+ sim_fs_end_current(fs);
3371+ return;
3372+ }
3373+
3374+ if (error->type == OFONO_ERROR_TYPE_NO_ERROR)
3375+ cb(1, -1, op->current, sdata, length, op->userdata);
3376+ else
3377+ cb(0, -1, op->current, NULL, 0, op->userdata);
3378+
3379+ sim_fs_end_current(fs);
3380+}
3381+
3382 static void sim_fs_op_read_block_cb(const struct ofono_error *error,
3383 const unsigned char *data, int len,
3384 void *user)
3385@@ -565,7 +586,8 @@
3386
3387 driver->read_file_linear(fs->sim, op->id, op->current,
3388 op->record_length,
3389- NULL, 0,
3390+ op->path_len ? op->path : NULL,
3391+ op->path_len,
3392 sim_fs_op_retrieve_cb, fs);
3393 break;
3394 case OFONO_SIM_FILE_STRUCTURE_CYCLIC:
3395@@ -576,7 +598,8 @@
3396
3397 driver->read_file_cyclic(fs->sim, op->id, op->current,
3398 op->record_length,
3399- NULL, 0,
3400+ op->path_len ? op->path : NULL,
3401+ op->path_len,
3402 sim_fs_op_retrieve_cb, fs);
3403 break;
3404 default:
3405@@ -700,7 +723,7 @@
3406 * It's an info-only request, so there is no need to request
3407 * actual contents of the EF. Just return the EF-info.
3408 */
3409- sim_fs_read_info_cb_t cb = op->cb;
3410+ ofono_sim_read_info_cb_t cb = op->cb;
3411
3412 cb(1, file_status, op->length,
3413 op->record_length, op->userdata);
3414@@ -778,7 +801,7 @@
3415 * It's an info-only request, so there is no need to request
3416 * actual contents of the EF. Just return the EF-info.
3417 */
3418- sim_fs_read_info_cb_t cb = op->cb;
3419+ ofono_sim_read_info_cb_t cb = op->cb;
3420
3421 cb(1, file_status, op->length,
3422 op->record_length, op->userdata);
3423@@ -820,7 +843,28 @@
3424 return FALSE;
3425 }
3426
3427- if (op->is_read == TRUE) {
3428+ if (op->is_read == TRUE && op->current > 0) {
3429+ switch (op->structure) {
3430+ case OFONO_SIM_FILE_STRUCTURE_FIXED:
3431+ driver->read_file_linear(fs->sim, op->id,
3432+ op->current, op->record_length,
3433+ op->path_len ? op->path : NULL,
3434+ op->path_len,
3435+ sim_fs_op_read_record_cb, fs);
3436+ break;
3437+ case OFONO_SIM_FILE_STRUCTURE_CYCLIC:
3438+ driver->read_file_cyclic(fs->sim, op->id,
3439+ op->current, op->record_length,
3440+ op->path_len ? op->path : NULL,
3441+ op->path_len,
3442+ sim_fs_op_read_record_cb, fs);
3443+ break;
3444+ case OFONO_SIM_FILE_STRUCTURE_TRANSPARENT:
3445+ default:
3446+ ofono_error("Wrong file structure for reading record");
3447+ break;
3448+ }
3449+ } else if (op->is_read == TRUE) {
3450 if (sim_fs_op_check_cached(fs))
3451 return FALSE;
3452
3453@@ -859,7 +903,8 @@
3454
3455 int sim_fs_read_info(struct ofono_sim_context *context, int id,
3456 enum ofono_sim_file_structure expected_type,
3457- sim_fs_read_info_cb_t cb, void *data)
3458+ const unsigned char *path, unsigned int pth_len,
3459+ ofono_sim_read_info_cb_t cb, void *data)
3460 {
3461 struct sim_fs *fs = context->fs;
3462 struct sim_fs_op *op;
3463@@ -887,6 +932,8 @@
3464 op->is_read = TRUE;
3465 op->info_only = TRUE;
3466 op->context = context;
3467+ memcpy(op->path, path, pth_len);
3468+ op->path_len = pth_len;
3469
3470 g_queue_push_tail(fs->op_q, op);
3471
3472@@ -943,6 +990,59 @@
3473 return 0;
3474 }
3475
3476+int sim_fs_read_record(struct ofono_sim_context *context, int id,
3477+ enum ofono_sim_file_structure expected_type,
3478+ int record, int record_length,
3479+ const unsigned char *path, unsigned int path_len,
3480+ ofono_sim_file_read_cb_t cb, void *data)
3481+{
3482+ struct sim_fs *fs = context->fs;
3483+ struct sim_fs_op *op;
3484+
3485+ if (cb == NULL)
3486+ return -EINVAL;
3487+
3488+ if (fs->driver == NULL)
3489+ return -EINVAL;
3490+
3491+ if (record < 1)
3492+ return -EINVAL;
3493+
3494+ if ((expected_type == OFONO_SIM_FILE_STRUCTURE_FIXED &&
3495+ fs->driver->read_file_linear == NULL) ||
3496+ (expected_type == OFONO_SIM_FILE_STRUCTURE_CYCLIC &&
3497+ fs->driver->read_file_cyclic == NULL)) {
3498+ cb(0, 0, 0, NULL, 0, data);
3499+ return -ENOSYS;
3500+ }
3501+
3502+ if (fs->op_q == NULL)
3503+ fs->op_q = g_queue_new();
3504+
3505+ op = g_try_new0(struct sim_fs_op, 1);
3506+ if (op == NULL)
3507+ return -ENOMEM;
3508+
3509+ op->id = id;
3510+ op->structure = expected_type;
3511+ op->cb = cb;
3512+ op->userdata = data;
3513+ op->is_read = TRUE;
3514+ op->info_only = FALSE;
3515+ op->context = context;
3516+ op->record_length = record_length;
3517+ op->current = record;
3518+ memcpy(op->path, path, path_len);
3519+ op->path_len = path_len;
3520+
3521+ g_queue_push_tail(fs->op_q, op);
3522+
3523+ if (g_queue_get_length(fs->op_q) == 1)
3524+ fs->op_source = g_idle_add(sim_fs_op_next, fs);
3525+
3526+ return 0;
3527+}
3528+
3529 int sim_fs_write(struct ofono_sim_context *context, int id,
3530 ofono_sim_file_write_cb_t cb,
3531 enum ofono_sim_file_structure structure, int record,
3532
3533=== modified file 'src/simfs.h'
3534--- src/simfs.h 2012-11-23 13:22:25 +0000
3535+++ src/simfs.h 2014-11-20 00:09:27 +0000
3536@@ -21,10 +21,6 @@
3537
3538 struct sim_fs;
3539
3540-typedef void (*sim_fs_read_info_cb_t)(int ok, unsigned char file_status,
3541- int total_length, int record_length,
3542- void *userdata);
3543-
3544 struct sim_fs *sim_fs_new(struct ofono_sim *sim,
3545 const struct ofono_sim_driver *driver);
3546 struct ofono_sim_context *sim_fs_context_new(struct sim_fs *fs);
3547@@ -45,9 +41,16 @@
3548 const unsigned char *path, unsigned int len,
3549 ofono_sim_file_read_cb_t cb, void *data);
3550
3551+int sim_fs_read_record(struct ofono_sim_context *context, int id,
3552+ enum ofono_sim_file_structure expected_type,
3553+ int record, int record_length,
3554+ const unsigned char *path, unsigned int len,
3555+ ofono_sim_file_read_cb_t cb, void *data);
3556+
3557 int sim_fs_read_info(struct ofono_sim_context *context, int id,
3558 enum ofono_sim_file_structure expected_type,
3559- sim_fs_read_info_cb_t cb, void *data);
3560+ const unsigned char *path, unsigned int pth_len,
3561+ ofono_sim_read_info_cb_t cb, void *data);
3562
3563 void sim_fs_check_version(struct sim_fs *fs);
3564
3565
3566=== modified file 'src/simutil.c'
3567--- src/simutil.c 2014-05-26 13:26:20 +0000
3568+++ src/simutil.c 2014-11-20 00:09:27 +0000
3569@@ -73,6 +73,8 @@
3570 { 0x2F05, ROOTMF, ROOTMF, EF, BINARY, 0, ALW, PIN },
3571 { 0x2FE2, ROOTMF, ROOTMF, EF, BINARY, 10, ALW, NEV },
3572 { 0x4F20, 0x5F50, 0x5F50, EF, BINARY, 0, PIN, ADM },
3573+{ 0x4F30, 0x5F3A, 0x5F3A, EF, RECORD, 0, PIN, ADM },
3574+{ 0x5F3A, 0x7F10, 0x7F10, DF, 0, 0, PIN, PIN },
3575 { 0x5F50, 0x7F10, 0x7F10, DF, 0, 0, PIN, ADM },
3576 { 0x6F05, 0x7F20, 0x7FFF, EF, BINARY, 0, ALW, PIN },
3577 { 0x6F07, 0x7F20, 0x7FFF, EF, BINARY, 9, PIN, ADM },
3578
3579=== modified file 'src/simutil.h'
3580--- src/simutil.h 2014-04-14 14:03:03 +0000
3581+++ src/simutil.h 2014-11-20 00:09:27 +0000
3582@@ -27,6 +27,7 @@
3583 SIM_EF_ICCID_FILEID = 0x2FE2,
3584 SIM_MF_FILEID = 0x3F00,
3585 SIM_EFIMG_FILEID = 0x4F20,
3586+ SIM_EFPBR_FILEID = 0x4F30,
3587 SIM_DFPHONEBOOK_FILEID = 0x5F3A,
3588 SIM_EFLI_FILEID = 0x6F05,
3589 SIM_EFARR_FILEID = 0x6F06,
3590
3591=== added file 'test/set-3g-slot'
3592--- test/set-3g-slot 1970-01-01 00:00:00 +0000
3593+++ test/set-3g-slot 2014-11-20 00:09:27 +0000
3594@@ -0,0 +1,20 @@
3595+#!/usr/bin/python3
3596+
3597+import dbus
3598+import sys
3599+
3600+bus = dbus.SystemBus()
3601+
3602+if len(sys.argv) == 2:
3603+ path = sys.argv[1]
3604+else:
3605+ manager = dbus.Interface(bus.get_object('org.ofono', '/'),
3606+ 'org.ofono.Manager')
3607+ modems = manager.GetModems()
3608+ path = modems[0][0]
3609+
3610+print("Activate 3G for %s..." % path)
3611+mtks = dbus.Interface(bus.get_object('org.ofono', path),
3612+ 'org.ofono.MtkSettings')
3613+
3614+mtks.SetProperty("Has3G", True)
3615
3616=== modified file 'unit/test-grilreply.c'
3617--- unit/test-grilreply.c 2014-09-22 17:39:35 +0000
3618+++ unit/test-grilreply.c 2014-11-20 00:09:27 +0000
3619@@ -679,7 +679,7 @@
3620 0x04, 0x00, 0x00, 0x00, 0x31, 0x00, 0x62, 0x00, 0x33, 0x00, 0x66, 0x00,
3621 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x30, 0x00, 0x37, 0x00,
3622 0x65, 0x00, 0x61, 0x00, 0x35, 0x00, 0x31, 0x00, 0x30, 0x00, 0x61, 0x00,
3623- 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x39, 0x00, 0x00, 0x00,
3624+ 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x39, 0x00, 0x00, 0x00,
3625 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
3626 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
3627 0x01, 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff,
3628@@ -1530,17 +1530,11 @@
3629 }
3630 };
3631
3632-static void test_reply_reg_state_invalid(gconstpointer data)
3633-{
3634- struct reply_reg_state *reply = g_ril_reply_parse_reg_state(NULL, data);
3635- g_assert(reply == NULL);
3636-}
3637-
3638-static void test_reply_reg_state_valid(gconstpointer data)
3639+static void test_reply_voice_reg_state_valid(gconstpointer data)
3640 {
3641 const reg_state_test *test = data;
3642 struct reply_reg_state *reply =
3643- g_ril_reply_parse_reg_state(NULL, &test->msg);
3644+ g_ril_reply_parse_voice_reg_state(NULL, &test->msg);
3645
3646 g_assert(reply != NULL);
3647 g_assert(reply->status == test->status);
3648@@ -1549,6 +1543,26 @@
3649 g_free(reply);
3650 }
3651
3652+static void test_reply_data_reg_state_invalid(gconstpointer data)
3653+{
3654+ struct reply_data_reg_state *reply =
3655+ g_ril_reply_parse_data_reg_state(NULL, data);
3656+ g_assert(reply == NULL);
3657+}
3658+
3659+static void test_reply_data_reg_state_valid(gconstpointer data)
3660+{
3661+ const reg_state_test *test = data;
3662+ struct reply_data_reg_state *reply =
3663+ g_ril_reply_parse_data_reg_state(NULL, &test->msg);
3664+
3665+ g_assert(reply != NULL);
3666+ g_assert(reply->reg_state.status == test->status);
3667+
3668+ g_assert(reply->reg_state.tech == test->tech);
3669+ g_free(reply);
3670+}
3671+
3672 static void test_reply_operator_invalid(gconstpointer data)
3673 {
3674 struct reply_operator *reply = g_ril_reply_parse_operator(NULL, data);
3675@@ -1778,127 +1792,127 @@
3676 g_test_add_data_func("/testgrilreply/gprs: "
3677 "invalid DATA_REG_STATE Test 1",
3678 &reply_data_reg_state_invalid_1,
3679- test_reply_reg_state_invalid);
3680+ test_reply_data_reg_state_invalid);
3681
3682 g_test_add_data_func("/testgrilreply/gprs: "
3683 "invalid DATA_REG_STATE Test 2",
3684 &reply_data_reg_state_invalid_2,
3685- test_reply_reg_state_invalid);
3686+ test_reply_data_reg_state_invalid);
3687
3688 g_test_add_data_func("/testgrilreply/gprs: "
3689 "invalid DATA_REG_STATE Test 3",
3690 &reply_data_reg_state_invalid_3,
3691- test_reply_reg_state_invalid);
3692+ test_reply_data_reg_state_invalid);
3693
3694 g_test_add_data_func("/testgrilreply/gprs: "
3695 "valid DATA_REG_STATE Test 1",
3696 &data_reg_valid_1,
3697- test_reply_reg_state_valid);
3698+ test_reply_data_reg_state_valid);
3699
3700 g_test_add_data_func("/testgrilreply/gprs: "
3701 "valid DATA_REG_STATE Test 2",
3702 &data_reg_valid_2,
3703- test_reply_reg_state_valid);
3704+ test_reply_data_reg_state_valid);
3705
3706 g_test_add_data_func("/testgrilreply/gprs: "
3707 "valid DATA_REG_STATE Test 3",
3708 &data_reg_valid_3,
3709- test_reply_reg_state_valid);
3710+ test_reply_data_reg_state_valid);
3711
3712 g_test_add_data_func("/testgrilreply/gprs: "
3713 "valid DATA_REG_STATE Test 4",
3714 &data_reg_valid_4,
3715- test_reply_reg_state_valid);
3716+ test_reply_data_reg_state_valid);
3717
3718 g_test_add_data_func("/testgrilreply/gprs: "
3719 "valid DATA_REG_STATE Test 5",
3720 &data_reg_valid_5,
3721- test_reply_reg_state_valid);
3722+ test_reply_data_reg_state_valid);
3723
3724 g_test_add_data_func("/testgrilreply/gprs: "
3725 "valid DATA_REG_STATE Test 6",
3726 &data_reg_valid_6,
3727- test_reply_reg_state_valid);
3728+ test_reply_data_reg_state_valid);
3729
3730 g_test_add_data_func("/testgrilreply/gprs: "
3731 "valid DATA_REG_STATE Test 7",
3732 &data_reg_valid_7,
3733- test_reply_reg_state_valid);
3734+ test_reply_data_reg_state_valid);
3735
3736 g_test_add_data_func("/testgrilreply/gprs: "
3737 "valid DATA_REG_STATE Test 8",
3738 &data_reg_valid_8,
3739- test_reply_reg_state_valid);
3740+ test_reply_data_reg_state_valid);
3741
3742 g_test_add_data_func("/testgrilreply/gprs: "
3743 "valid DATA_REG_STATE Test 9",
3744 &data_reg_valid_9,
3745- test_reply_reg_state_valid);
3746+ test_reply_data_reg_state_valid);
3747
3748 g_test_add_data_func("/testgrilreply/gprs: "
3749 "valid DATA_REG_STATE Test 10",
3750 &data_reg_valid_10,
3751- test_reply_reg_state_valid);
3752+ test_reply_data_reg_state_valid);
3753
3754 g_test_add_data_func("/testgrilreply/netreg: "
3755 "valid VOICE_REG_STATE Test 1",
3756 &voice_reg_valid_1,
3757- test_reply_reg_state_valid);
3758+ test_reply_voice_reg_state_valid);
3759
3760 g_test_add_data_func("/testgrilreply/netreg: "
3761 "valid VOICE_REG_STATE Test 2",
3762 &voice_reg_valid_2,
3763- test_reply_reg_state_valid);
3764+ test_reply_voice_reg_state_valid);
3765
3766 g_test_add_data_func("/testgrilreply/netreg: "
3767 "valid VOICE_REG_STATE Test 3",
3768 &voice_reg_valid_3,
3769- test_reply_reg_state_valid);
3770+ test_reply_voice_reg_state_valid);
3771
3772 g_test_add_data_func("/testgrilreply/netreg: "
3773 "valid VOICE_REG_STATE Test 4",
3774 &voice_reg_valid_4,
3775- test_reply_reg_state_valid);
3776+ test_reply_voice_reg_state_valid);
3777
3778 g_test_add_data_func("/testgrilreply/netreg: "
3779 "valid VOICE_REG_STATE Test 5",
3780 &voice_reg_valid_5,
3781- test_reply_reg_state_valid);
3782+ test_reply_voice_reg_state_valid);
3783
3784 g_test_add_data_func("/testgrilreply/netreg: "
3785 "valid VOICE_REG_STATE Test 6",
3786 &voice_reg_valid_6,
3787- test_reply_reg_state_valid);
3788+ test_reply_voice_reg_state_valid);
3789
3790 g_test_add_data_func("/testgrilreply/netreg: "
3791 "valid VOICE_REG_STATE Test 7",
3792 &voice_reg_valid_7,
3793- test_reply_reg_state_valid);
3794+ test_reply_voice_reg_state_valid);
3795
3796 g_test_add_data_func("/testgrilreply/netreg: "
3797 "valid VOICE_REG_STATE Test 8",
3798 &voice_reg_valid_8,
3799- test_reply_reg_state_valid);
3800+ test_reply_voice_reg_state_valid);
3801
3802 g_test_add_data_func("/testgrilreply/netreg: "
3803 "valid VOICE_REG_STATE Test 9",
3804 &voice_reg_valid_9,
3805- test_reply_reg_state_valid);
3806+ test_reply_voice_reg_state_valid);
3807
3808 g_test_add_data_func("/testgrilreply/netreg: "
3809 "valid VOICE_REG_STATE Test 10",
3810 &voice_reg_valid_10,
3811- test_reply_reg_state_valid);
3812+ test_reply_voice_reg_state_valid);
3813
3814 g_test_add_data_func("/testgrilreply/netreg: "
3815 "valid VOICE_REG_STATE Test 11",
3816 &voice_reg_valid_11,
3817- test_reply_reg_state_valid);
3818+ test_reply_voice_reg_state_valid);
3819
3820 g_test_add_data_func("/testgrilreply/netreg: "
3821 "valid VOICE_REG_STATE Test 12",
3822 &voice_reg_valid_12,
3823- test_reply_reg_state_valid);
3824+ test_reply_voice_reg_state_valid);
3825
3826 g_test_add_data_func("/testgrilreply/netreg: "
3827 "invalid GET_OPERATOR Test 1",
3828
3829=== modified file 'unit/test-mtkreply.c'
3830--- unit/test-mtkreply.c 2014-07-29 16:35:05 +0000
3831+++ unit/test-mtkreply.c 2014-11-20 00:09:27 +0000
3832@@ -53,7 +53,7 @@
3833 };
3834
3835 struct rep_3g_capability_test {
3836- int is_3g;
3837+ int slot_3g;
3838 const struct ril_msg msg;
3839 };
3840
3841@@ -113,7 +113,7 @@
3842 };
3843
3844 static const struct rep_3g_capability_test mtk_reply_3g_capability_valid_1 = {
3845- .is_3g = 1,
3846+ .slot_3g = 0,
3847 .msg = {
3848 .buf = (char *) &mtk_reply_3g_capability_valid_parcel1,
3849 .buf_len = sizeof(mtk_reply_3g_capability_valid_parcel1),
3850@@ -153,9 +153,9 @@
3851 {
3852 GRil *gril = g_ril_new(NULL, OFONO_RIL_VENDOR_MTK);
3853 const struct rep_3g_capability_test *test = data;
3854- int is_3g = g_mtk_reply_parse_get_3g_capability(gril, &test->msg);
3855+ int slot_3g = g_mtk_reply_parse_get_3g_capability(gril, &test->msg);
3856
3857- g_assert(is_3g == test->is_3g);
3858+ g_assert(slot_3g == test->slot_3g);
3859
3860 g_ril_unref(gril);
3861 }
3862
3863=== modified file 'unit/test-mtkrequest.c'
3864--- unit/test-mtkrequest.c 2014-06-12 11:02:03 +0000
3865+++ unit/test-mtkrequest.c 2014-11-20 00:09:27 +0000
3866@@ -207,6 +207,18 @@
3867 .parcel_size = sizeof(req_set_fd_mode_parcel_valid_2),
3868 };
3869
3870+/* MTK: set_3g_capability tests */
3871+
3872+static const guchar req_set_3g_capability_valid_1[] = {
3873+ 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
3874+};
3875+
3876+static const struct request_test_data set_set_3g_capability_valid_test_1 = {
3877+ .request = NULL,
3878+ .parcel_data = req_set_3g_capability_valid_1,
3879+ .parcel_size = sizeof(req_set_3g_capability_valid_1),
3880+};
3881+
3882 /* Test functions */
3883
3884 static void test_mtk_req_sim_read_binary_valid(gconstpointer data)
3885@@ -322,6 +334,19 @@
3886 parcel_free(&rilp);
3887 }
3888
3889+static void test_request_set_3g_capability(gconstpointer data)
3890+{
3891+ const struct request_test_data *test_data = data;
3892+ struct parcel rilp;
3893+
3894+ g_mtk_request_set_3g_capability(NULL, &rilp);
3895+
3896+ g_assert(!memcmp(rilp.data, test_data->parcel_data,
3897+ test_data->parcel_size));
3898+
3899+ parcel_free(&rilp);
3900+}
3901+
3902 #endif /* LITTLE_ENDIAN */
3903
3904 int main(int argc, char **argv)
3905@@ -376,6 +401,11 @@
3906 &set_fd_mode_valid_test_2,
3907 test_request_set_fd_mode);
3908
3909+ g_test_add_data_func("/testmtkrequest/mtk-settings: "
3910+ "valid SET_3G_CAPABILITY Test 1",
3911+ &set_set_3g_capability_valid_test_1,
3912+ test_request_set_3g_capability);
3913+
3914 #endif /* LITTLE_ENDIAN */
3915
3916 return g_test_run();

Subscribers

People subscribed via source and target branches

to all changes: