Merge lp:~phablet-team/ofono/vivid-update-1 into lp:~phablet-team/ofono/ubuntu
- vivid-update-1
- Merge into ubuntu
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 |
Related bugs: |
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-
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)
PS Jenkins bot (ps-jenkins) wrote : | # |
Alfonso Sanchez-Beato (alfonsosanchezbeato) wrote : | # |
Diff seems good, approving.
Alfonso Sanchez-Beato (alfonsosanchezbeato) wrote : | # |
Tested on krillin, image #169, following https:/
All test cases but the supplementary services ones executed and passed, plus tests for targeted bugs and new features.
Preview Diff
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(); |
PASSED: Continuous integration, rev:6882 jenkins. qa.ubuntu. com/job/ phablet- team-ofono- ubuntu- ci/63/ jenkins. qa.ubuntu. com/job/ phablet- team-ofono- ubuntu- vivid-amd64- ci/1 jenkins. qa.ubuntu. com/job/ phablet- team-ofono- ubuntu- vivid-armhf- ci/1 jenkins. qa.ubuntu. com/job/ phablet- team-ofono- ubuntu- vivid-armhf- ci/1/artifact/ work/output/ *zip*/output. zip jenkins. qa.ubuntu. com/job/ phablet- team-ofono- ubuntu- vivid-i386- ci/1
http://
Executed test runs:
SUCCESS: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
Click here to trigger a rebuild: s-jenkins. ubuntu- ci:8080/ job/phablet- team-ofono- ubuntu- ci/63/rebuild
http://