Merge lp:~awe/phablet-extras/ofono-sim-support into lp:phablet-extras/ofono

Proposed by Tony Espy
Status: Merged
Approved by: Ricardo Salveti
Approved revision: 46
Merged at revision: 32
Proposed branch: lp:~awe/phablet-extras/ofono-sim-support
Merge into: lp:phablet-extras/ofono
Diff against target: 1340 lines (+934/-92)
17 files modified
Makefile.am (+1/-0)
debian/changelog (+8/-0)
drivers/rilmodem/call-volume.c (+10/-0)
drivers/rilmodem/devinfo.c (+7/-5)
drivers/rilmodem/network-registration.c (+9/-5)
drivers/rilmodem/rilmodem.c (+2/-0)
drivers/rilmodem/rilmodem.h (+7/-0)
drivers/rilmodem/rilutil.c (+138/-0)
drivers/rilmodem/rilutil.h (+9/-1)
drivers/rilmodem/sim.c (+552/-0)
drivers/rilmodem/sms.c (+9/-5)
drivers/rilmodem/voicecall.c (+9/-5)
gril/grilutil.c (+41/-0)
gril/grilutil.h (+1/-0)
plugins/ril.c (+43/-71)
src/simutil.c (+87/-0)
src/simutil.h (+1/-0)
To merge this branch: bzr merge lp:~awe/phablet-extras/ofono-sim-support
Reviewer Review Type Date Requested Status
Ricardo Salveti (community) Approve
PS Jenkins bot continuous-integration Approve
Review via email: mp+158469@code.launchpad.net

Commit message

[RILD] Added basic SIM support.

Description of the change

This MP adds SIM support to rilmodem. Features include:

 * Basic SIM initilization ( no PIN/PUK support yet )

 * SIM filesystem read support ( required by SIM initialization code & GPRS )

 * SIM Subscriber Identity support ( ie. aka IMSI, now exposed as a SimManager property )

This MP also includes a re-working of the ril device plugin ( /plugins/ril.c ) due to the new SIM support. This sets the stage for eventual support of PIN/PUK support, and also allowed us to drop the set_online() function added to the core modem logic.

Tested on a Galaxy Nexus running yesterday's daily Quantal build. Verified the following:

 * oFono starts, and the ril plugin, and associated rilmodem code initialize properly
 * SimManager is now exported in the modem's Interfaces property ( tested with /tests/list-modems )
 * IMSI is exposed as a SimManager SubscriberIdentity property ( tested with /tests/list-modems )
 * Phone calls can be made/received
 * SMS messages can be sent/received
 * No obvious errors logged by oFono

To post a comment you must log in.
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Approve (continuous-integration)
41. By Tony Espy

[rilmodem] Fix problem with modem exit function.

42. By Tony Espy

[ril/rilmodem] Created a new changelog entry for SIM support.

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Approve (continuous-integration)
Revision history for this message
Mathieu Trudel-Lapierre (cyphermox) wrote :

Please fix debian/changelog...

At the very least, are you keeping track of the precise patches applied? Is it mostly concentrated into some file additions and few actual code changes?

Since this has been all done flatly into an ofono branch, it's going to be very difficult/painful to get the changes out and into patches unless someone has been keeping track of what aspects have been changed.

43. By Tony Espy

Fixed debian/changelog conflict.

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

@Mathieu

I fixed the changelog, thanks for the catch!

As for patches:

1. This work is being done on a fresh, flattened version of the raring ofono branch ( itself based on ofono 1.12 ).

2. As oFono hasn't really been used in a default Ubuntu build to-date, tracking Precise patches has not been a priority.

3. Please review the telephony blueprint, as it has a work item for splitting out the oFono/RILD plugin code into a separate project, which will make it easier to deal with any required patches to the oFono core. For the sake of agility, I purposely chose to use a flattened bzr tree, as trying to do heavy development using patches is royal PITA. bzr tracks the changes made on top of the flattened source tree, so getting changes out into patches shouldn't be a problem if/when done.

4. We also will need a plan to deal with the fact that an oFono install on a desktop/laptop may be subtly different than a build on a phone. Again, this is a post Raring work item.

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Approve (continuous-integration)
Revision history for this message
Ricardo Salveti (rsalveti) wrote :
Download full text (28.7 KiB)

273 + cb(&error, -1, -1, -1, NULL, EF_STATUS_INVALIDATED, cbd->data);
274 + return;

292 + cb(&error, -1, -1, -1, NULL, EF_STATUS_INVALIDATED, cbd->data);
293 + return;

Would prefer if both could use 'goto error' as well. The extra debug message can be printed right after the response result (and you can handle the free at the goto as well).

299 + if (response[0] == 0x62) {
300 + ok = sim_parse_3g_get_response(response, strlen((gchar *) response), &flen, &rlen,
301 + &str, access, NULL);
302 +
303 + file_status = EF_STATUS_VALID;
304 + } else
305 + ok = sim_parse_2g_get_response(response, strlen((gchar *) response), &flen, &rlen,
306 + &str, access, &file_status);
307 +
308 + g_free(response);
309 + }

Mind breaking this down in less columns? 80 should be a good target.

386 + decode_ril_error(&error, "FAIL");
387 + cb(&error, NULL, 0, cbd->data);

396 + decode_ril_error(&error, "FAIL");
397 + cb(&error, NULL, 0, cbd->data);

Could be handled in a single goto.

537 + DBG("g_ril_send failed...");

Mind removing this entry? Not generally used at the other calls, and the log will already point a failure when sending the command anyway.

When testing I also got quite a few GENERIC_FAILURE, not sure if they are critical though:

root@localhost:~# ofonod -d -n
ofonod[1023]: oFono version 1.12
ofonod[1023]: src/plugin.c:__ofono_plugin_init()
ofonod[1023]: plugins/push-notification.c:push_notification_init()
ofonod[1023]: plugins/smart-messaging.c:smart_messaging_init()
ofonod[1023]: src/cdma-provision.c:ofono_cdma_provision_driver_register() driver: 0xa76b0 name: CDMA provisioning
ofonod[1023]: src/gprs-provision.c:ofono_gprs_provision_driver_register() driver: 0xa7684 name: Provisioning
ofonod[1023]: src/cdma-voicecall.c:ofono_cdma_voicecall_driver_register() driver: 0xa762c, name: cdmamodem
ofonod[1023]: src/modem.c:ofono_devinfo_driver_register() driver: 0xa7654, name: cdmamodem
ofonod[1023]: src/cdma-connman.c:ofono_cdma_connman_driver_register() driver: 0xa7670, name: cdmamodem
ofonod[1023]: src/modem.c:ofono_modem_driver_register() driver: 0xa7594, name: phonesim
ofonod[1023]: src/modem.c:ofono_modem_driver_register() driver: 0xa75c4, name: localhfp
ofonod[1023]: src/gprs.c:ofono_gprs_context_driver_register() driver: 0xa757c, name: phonesim
ofonod[1023]: src/ctm.c:ofono_ctm_driver_register() driver: 0xa7568, name: phonesim
ofonod[1023]: plugins/phonesim.c:parse_config() filename /etc/ofono/phonesim.conf
ofonod[1023]: src/voicecall.c:ofono_voicecall_driver_register() driver: 0xa7484, name: hfpmodem
ofonod[1023]: src/modem.c:ofono_devinfo_driver_register() driver: 0xa7528, name: hfpmodem
ofonod[1023]: src/network.c:ofono_netreg_driver_register() driver: 0xa74dc, name: hfpmodem
ofonod[1023]: src/call-volume.c:ofono_call_volume_driver_register() driver: 0xa7510, name: hfpmodem
ofonod[1023]: src/handsfree.c:ofono_handsfree_driver_register() driver: 0xa7554, name: hfpmodem
ofonod[1023]: src/voicecall.c:ofono_voicecall_driver_register() driver: 0xa72e0, name: atmodem
ofonod[1023]: src/modem.c:ofono_devinfo_driver_register() driver: 0xa7378, name: atmodem
ofonod[1023]: src/call-barring.c:ofono_call_barring_driver_register() driver: 0xa7330, name...

review: Needs Fixing
Revision history for this message
Ricardo Salveti (rsalveti) wrote :

Using raring image from http://cdimage.ubuntu.com/ubuntu-touch-preview/daily-preinstalled/20130422/ on Mako. Didn't yet test on maguro.

44. By Tony Espy

[rilmodem] Fix SIM IO response parsing.

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

Cleaned up error handling/extraneous comments per review.

Also, turns out the SIM IO response is returned from RILD as a Parcel-based ASCII hexadecimal string which needs to be converted to a byte string ( eg. "00AF" --> 0x00AF ).

Re-tested on latest Raring build on maguro. Incoming/Outgoing phone calls and SMS messages worked as expected.

No testing on mako, due to that fact that I don't have a valid microSIM. I'm going to get my ATT SIM cutdown this afternoon.

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Approve (continuous-integration)
Revision history for this message
Tony Espy (awe) wrote :

Looks like we have our first instance of device-specific RIL behavior. After testing the latest Raring build on my Nexus4, I'm seeing failures reading the IMSI ( Subscriber Identity ) and SIM IO calls.

Turns out the CM 10.1 source tree includes a QualcommSharedRIL.java class which looks like it overrides the IMSI and SIM IO logic. We'll need to discuss how we implement a similar mechanism.

I would hold off on further review until we can discuss further.

45. By Tony Espy

[rilmodem] Re-factored SIM IO to use AID string (if present), and correctly set SIM file paths.

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

Turns out that the mako RILD is Qualcomm-based, whereas maguro is Samsung-based.

The Qualcomm RIL code is sensitive to file paths ( ie. directory specifier ) that need to be specified in addition to the file ID. The Samsung RIL code doesn't really care and treats file paths as optional.

When the Raring oFono merge was done, I removed code that I'd written to handle paths and had made an incorrect assumption that since file path was added as a parameter to all of the file IO operations in the sim_driver, that the oFono core would correctly specify paths for each of it's file operations. This wasn't the case.

So, the latest code now uses the oFono ef_db to look up file paths ( which then have to be converted to ASCII hex ).

I also added support to grab the UMTS/GSM application ID (AID) and app type ( should always be USIM ) from the the SIM status reply. AID is another optional parameter for SIM file IO, so if correctly read from the SIM, it will be passed to all file IO calls.

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Approve (continuous-integration)
Revision history for this message
Ricardo Salveti (rsalveti) wrote :

Just some minor comments.

170 + /* Minimum length of SIM_IO_v6 is 12:

Here the struct parsed is actually RIL_SIM_IO_Response instead of SIM_IO_v6.

269 + if (aid_str && strlen(aid_str)) {

Why the extra check with strlen here? Parcel will return null in case it's invalid.

770 + if (app.app_id && strlen(app.app_id))
771 + sd->app_id = app.app_id;

Same here.

+ } else if (fileid == 0x2FE2 || fileid == 0x2FE0) {

Shouldn't 0x2FE2 be SIM_EF_ICCID_FILEID? It'd also be good to have a const for 0x2FE0.

474 + guchar file_status = 0x01;

If initialized with EF_STATUS_VALID (would be nice to replace it with the defined const), you don't need to set it to valid later (line 517).

Rest of the code looks good, we just need to improve the parcel handling and the power-on conditions (for emergency call, as you added as TODO).

Tested with mako an maguro using latest raring-based build. Old functionality still working as expected.

review: Needs Fixing
46. By Tony Espy

[rildmodem] Minor changes from MP comments.

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Approve (continuous-integration)
Revision history for this message
Ricardo Salveti (rsalveti) :
review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'Makefile.am'
2--- Makefile.am 2013-04-09 18:34:11 +0000
3+++ Makefile.am 2013-05-20 19:19:27 +0000
4@@ -120,6 +120,7 @@
5 drivers/rilmodem/network-registration.c \
6 drivers/rilmodem/voicecall.c \
7 drivers/rilmodem/call-volume.c \
8+ drivers/rilmodem/sim.c \
9 drivers/rilmodem/sms.c \
10 drivers/rilmodem/rilutil.c \
11 drivers/rilmodem/rilutil.h
12
13=== modified file 'debian/changelog'
14--- debian/changelog 2013-04-11 01:25:19 +0000
15+++ debian/changelog 2013-05-20 19:19:27 +0000
16@@ -1,3 +1,11 @@
17+ofono (1.12phablet2) UNRELEASED; urgency=low
18+
19+ * [ril/rilmodem] Initial SIM support, includes:
20+ - read filesystem support
21+ - proper modem initialization
22+
23+ -- Tony Espy <espy@canonical.com> Fri, 12 Apr 2013 14:56:01 -0400
24+
25 ofono (1.12phablet1) raring; urgency=low
26
27 [ Ricardo Salveti de Araujo ]
28
29=== modified file 'drivers/rilmodem/call-volume.c'
30--- drivers/rilmodem/call-volume.c 2013-03-28 12:50:26 +0000
31+++ drivers/rilmodem/call-volume.c 2013-05-20 19:19:27 +0000
32@@ -153,6 +153,16 @@
33
34 ofono_call_volume_set_data(cv, cvd);
35
36+ /*
37+ * TODO: analyze if capability check is needed
38+ * and/or timer should be adjusted.
39+ *
40+ * ofono_call_volume_register() needs to be called after
41+ * the driver has been set in ofono_call_volume_create(),
42+ * which calls this function. Most other drivers make
43+ * some kind of capabilities query to the modem, and then
44+ * call register in the callback; we use a timer instead.
45+ */
46 g_timeout_add_seconds(2, ril_delayed_register, cv);
47
48 return 0;
49
50=== modified file 'drivers/rilmodem/devinfo.c'
51--- drivers/rilmodem/devinfo.c 2013-03-28 12:50:26 +0000
52+++ drivers/rilmodem/devinfo.c 2013-05-20 19:19:27 +0000
53@@ -128,13 +128,15 @@
54
55 DBG("");
56
57- /* Nothing to send...
58+ /*
59+ * TODO: analyze if capability check is needed
60+ * and/or timer should be adjusted.
61 *
62 * ofono_devinfo_register() needs to be called after
63- * the driver has been set in devinfo_create() which
64- * calls this function. Most other drivers use a
65- * callback after getting some return from the modem
66- * itself...
67+ * the driver has been set in ofono_devinfo_create(),
68+ * which calls this function. Most other drivers make
69+ * some kind of capabilities query to the modem, and then
70+ * call register in the callback; we use a timer instead.
71 */
72 g_timeout_add_seconds(1, ril_delayed_register, info);
73
74
75=== modified file 'drivers/rilmodem/network-registration.c'
76--- drivers/rilmodem/network-registration.c 2013-03-28 12:50:26 +0000
77+++ drivers/rilmodem/network-registration.c 2013-05-20 19:19:27 +0000
78@@ -548,11 +548,15 @@
79 nd->time.utcoff = 0;
80 ofono_netreg_set_data(netreg, nd);
81
82- /* ofono_netreg_register() needs to be called after
83- * the driver has been set in devinfo_create() which
84- * calls this function. Most other drivers use a
85- * callback after getting some return from the modem
86- * itself...
87+ /*
88+ * TODO: analyze if capability check is needed
89+ * and/or timer should be adjusted.
90+ *
91+ * ofono_netreg_register() needs to be called after
92+ * the driver has been set in ofono_netreg_create(),
93+ * which calls this function. Most other drivers make
94+ * some kind of capabilities query to the modem, and then
95+ * call register in the callback; we use a timer instead.
96 */
97 g_timeout_add_seconds(1, ril_delayed_register, netreg);
98
99
100=== modified file 'drivers/rilmodem/rilmodem.c'
101--- drivers/rilmodem/rilmodem.c 2013-03-28 12:50:26 +0000
102+++ drivers/rilmodem/rilmodem.c 2013-05-20 19:19:27 +0000
103@@ -38,6 +38,7 @@
104 DBG("");
105
106 ril_devinfo_init();
107+ ril_sim_init();
108 ril_voicecall_init();
109 ril_sms_init();
110 ril_netreg_init();
111@@ -51,6 +52,7 @@
112 DBG("");
113
114 ril_devinfo_exit();
115+ ril_sim_exit();
116 ril_voicecall_exit();
117 ril_sms_exit();
118 ril_netreg_exit();
119
120=== modified file 'drivers/rilmodem/rilmodem.h'
121--- drivers/rilmodem/rilmodem.h 2013-03-28 12:50:26 +0000
122+++ drivers/rilmodem/rilmodem.h 2013-05-20 19:19:27 +0000
123@@ -22,6 +22,10 @@
124
125 #include "rilutil.h"
126
127+/* Shared constants */
128+#define EF_STATUS_INVALIDATED 0
129+#define EF_STATUS_VALID 1
130+
131 extern void ril_devinfo_init(void);
132 extern void ril_devinfo_exit(void);
133
134@@ -31,6 +35,9 @@
135 extern void ril_voicecall_init(void);
136 extern void ril_voicecall_exit(void);
137
138+extern void ril_sim_init(void);
139+extern void ril_sim_exit(void);
140+
141 extern void ril_sms_init(void);
142 extern void ril_sms_exit(void);
143
144
145=== modified file 'drivers/rilmodem/rilutil.c'
146--- drivers/rilmodem/rilutil.c 2013-03-28 12:50:26 +0000
147+++ drivers/rilmodem/rilutil.c 2013-05-20 19:19:27 +0000
148@@ -36,6 +36,9 @@
149 #include "common.h"
150 #include "rilutil.h"
151 #include "parcel.h"
152+#include "simutil.h"
153+#include "util.h"
154+#include "ril_constants.h"
155
156 struct ril_util_sim_state_query {
157 GRil *ril;
158@@ -215,6 +218,141 @@
159 return l;
160 }
161
162+char *ril_util_parse_sim_io_rsp(struct ril_msg *message,
163+ int *sw1, int *sw2,
164+ int *hex_len)
165+{
166+ struct parcel rilp;
167+ char *response = NULL;
168+ char *hex_response = NULL;
169+
170+ /* Minimum length of SIM_IO_Response is 12:
171+ * sw1 (int32)
172+ * sw2 (int32)
173+ * simResponse (string)
174+ */
175+ if (message->buf_len < 12) {
176+ DBG("message->buf_len < 12");
177+ return FALSE;
178+ }
179+
180+ /* Set up Parcel struct for proper parsing */
181+ rilp.data = message->buf;
182+ rilp.size = message->buf_len;
183+ rilp.capacity = message->buf_len;
184+ rilp.offset = 0;
185+
186+ *sw1 = parcel_r_int32(&rilp);
187+ *sw2 = parcel_r_int32(&rilp);
188+
189+ response = parcel_r_string(&rilp);
190+ if (response) {
191+ hex_response = (char *) decode_hex((const char *) response, strlen(response),
192+ (long *) hex_len, -1);
193+ g_free(response);
194+ }
195+
196+ return hex_response;
197+}
198+
199+gboolean ril_util_parse_sim_status(struct ril_msg *message, struct sim_app *app)
200+{
201+ struct parcel rilp;
202+ gboolean result = FALSE;
203+ char *aid_str = NULL;
204+ char *app_str = NULL;
205+ int i, card_state, num_apps, pin_state, gsm_umts_index, ims_index;
206+ int app_state, app_type, pin_replaced, pin1_state, pin2_state;
207+
208+ DBG("");
209+
210+ if (app) {
211+ app->app_type = RIL_APPTYPE_UNKNOWN;
212+ app->app_id = NULL;
213+ }
214+
215+ /* Set up Parcel struct for proper parsing */
216+ rilp.data = message->buf;
217+ rilp.size = message->buf_len;
218+ rilp.capacity = message->buf_len;
219+ rilp.offset = 0;
220+
221+ /*
222+ * FIXME: Need to come up with a common scheme for verifying the
223+ * size of RIL message and properly reacting to bad messages.
224+ * This could be a runtime assertion, disconnect, drop/ignore
225+ * the message, ...
226+ *
227+ * Currently if the message is smaller than expected, our parcel
228+ * code happily walks off the end of the buffer and segfaults.
229+ *
230+ * 20 is the min length of RIL_CardStatus_v6 as the AppState
231+ * array can be 0-length.
232+ */
233+ if (message->buf_len < 20)
234+ goto done;
235+
236+ card_state = parcel_r_int32(&rilp);
237+ pin_state = parcel_r_int32(&rilp);
238+ gsm_umts_index = parcel_r_int32(&rilp);
239+ parcel_r_int32(&rilp); /* ignore: cdma_subscription_app_index */
240+ ims_index = parcel_r_int32(&rilp);
241+ num_apps = parcel_r_int32(&rilp);
242+
243+ for (i = 0; i < num_apps; i++) {
244+ app_type = parcel_r_int32(&rilp);
245+ app_state = parcel_r_int32(&rilp);
246+ parcel_r_int32(&rilp); /* Ignore perso_substate for now */
247+
248+ /* TODO: we need a way to instruct parcel to skip
249+ * a string, without allocating memory...
250+ */
251+ aid_str = parcel_r_string(&rilp); /* application ID (AID) */
252+ app_str = parcel_r_string(&rilp); /* application label */
253+
254+ pin_replaced = parcel_r_int32(&rilp);
255+ pin1_state = parcel_r_int32(&rilp);
256+ pin2_state = parcel_r_int32(&rilp);
257+
258+ DBG("SIM app type: %s state: %s",
259+ ril_apptype_to_string(app_type),
260+ ril_appstate_to_string(app_state));
261+
262+ DBG("pin_replaced: %d pin1_state: %s pin2_state: %s",
263+ pin_replaced,
264+ ril_pinstate_to_string(pin1_state),
265+ ril_pinstate_to_string(pin2_state));
266+
267+ /* FIXME: CDMA/IMS -- see comment @ top-of-source. */
268+ if (i == gsm_umts_index && app) {
269+ if (aid_str) {
270+ app->app_id = aid_str;
271+ DBG("setting app_id (AID) to: %s", aid_str);
272+ }
273+
274+ app->app_type = app_type;
275+ } else
276+ g_free(aid_str);
277+
278+ g_free(app_str);
279+ }
280+
281+ DBG("card_state: %s (%d) pin_state: %s (%d) num_apps: %d",
282+ ril_cardstate_to_string(card_state),
283+ card_state,
284+ ril_pinstate_to_string(pin_state),
285+ pin_state,
286+ num_apps);
287+
288+ DBG("gsm_umts_index: %d; ims_index: %d",
289+ gsm_umts_index, ims_index);
290+
291+ if (card_state == RIL_CARDSTATE_PRESENT)
292+ result = TRUE;
293+done:
294+ return result;
295+}
296+
297 gboolean ril_util_parse_reg(struct ril_msg *message, int *status,
298 int *lac, int *ci, int *tech)
299 {
300
301=== modified file 'drivers/rilmodem/rilutil.h'
302--- drivers/rilmodem/rilutil.h 2013-03-28 12:50:26 +0000
303+++ drivers/rilmodem/rilutil.h 2013-05-20 19:19:27 +0000
304@@ -49,6 +49,11 @@
305 RIL_UTIL_CHARSET_8859_H = 0x10000,
306 };
307
308+struct sim_app {
309+ char *app_id;
310+ guint app_type;
311+};
312+
313 typedef void (*ril_util_sim_inserted_cb_t)(gboolean present, void *userdata);
314
315 void decode_ril_error(struct ofono_error *error, const char *final);
316@@ -65,7 +70,10 @@
317 void ril_util_sim_state_query_free(struct ril_util_sim_state_query *req);
318
319 GSList *ril_util_parse_clcc(struct ril_msg *message);
320-
321+char *ril_util_parse_sim_io_rsp(struct ril_msg *message,
322+ int *sw1, int *sw2,
323+ int *hex_len);
324+gboolean ril_util_parse_sim_status(struct ril_msg *message, struct sim_app *app);
325 gboolean ril_util_parse_reg(struct ril_msg *message, int *status,
326 int *lac, int *ci, int *tech);
327
328
329=== added file 'drivers/rilmodem/sim.c'
330--- drivers/rilmodem/sim.c 1970-01-01 00:00:00 +0000
331+++ drivers/rilmodem/sim.c 2013-05-20 19:19:27 +0000
332@@ -0,0 +1,552 @@
333+/*
334+ *
335+ * oFono - Open Source Telephony - RIL Modem Support
336+ *
337+ * Copyright (C) 2008-2011 Intel Corporation. All rights reserved.
338+ * Copyright (C) 2013 Canonical, Ltd. All rights reserved.
339+ *
340+ * This program is free software; you can redistribute it and/or modify
341+ * it under the terms of the GNU General Public License version 2 as
342+ * published by the Free Software Foundation.
343+ *
344+ * This program is distributed in the hope that it will be useful,
345+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
346+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
347+ * GNU General Public License for more details.
348+ *
349+ * You should have received a copy of the GNU General Public License
350+ * along with this program; if not, write to the Free Software
351+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
352+ *
353+ */
354+
355+#ifdef HAVE_CONFIG_H
356+#include <config.h>
357+#endif
358+
359+#define _GNU_SOURCE
360+#include <string.h>
361+#include <stdlib.h>
362+#include <stdio.h>
363+#include <errno.h>
364+
365+#include <glib.h>
366+
367+#include <ofono/log.h>
368+#include <ofono/modem.h>
369+#include <ofono/sim.h>
370+#include "simutil.h"
371+#include "util.h"
372+
373+#include "gril.h"
374+#include "grilutil.h"
375+#include "parcel.h"
376+#include "ril_constants.h"
377+#include "rilmodem.h"
378+
379+/* Based on ../drivers/atmodem/sim.c.
380+ *
381+ * TODO:
382+ * 1. Defines constants for hex literals
383+ * 2. Document P1-P3 usage (+CSRM)
384+ */
385+
386+/* Commands defined for TS 27.007 +CRSM */
387+#define CMD_READ_BINARY 176 /* 0xB0 */
388+#define CMD_READ_RECORD 178 /* 0xB2 */
389+#define CMD_GET_RESPONSE 192 /* 0xC0 */
390+#define CMD_UPDATE_BINARY 214 /* 0xD6 */
391+#define CMD_UPDATE_RECORD 220 /* 0xDC */
392+#define CMD_STATUS 242 /* 0xF2 */
393+#define CMD_RETRIEVE_DATA 203 /* 0xCB */
394+#define CMD_SET_DATA 219 /* 0xDB */
395+
396+/* FID/path of SIM/USIM root directory */
397+#define ROOTMF "3F00"
398+
399+/*
400+ * TODO: CDMA/IMS
401+ *
402+ * This code currently only grabs the AID/application ID from
403+ * the gsm_umts application on the SIM card. This code will
404+ * need to be modified for CDMA support, and possibly IMS-based
405+ * applications. In this case, app_id should be changed to an
406+ * array or HashTable of app_status structures.
407+ *
408+ * The same applies to the app_type.
409+ */
410+struct sim_data {
411+ GRil *ril;
412+ char *app_id;
413+ guint app_type;
414+};
415+
416+static void sim_debug(const gchar *str, gpointer user_data)
417+{
418+ const char *prefix = user_data;
419+
420+ ofono_info("%s%s", prefix, str);
421+}
422+
423+static void set_path(struct sim_data *sd, struct parcel *rilp,
424+ const int fileid, const guchar *path,
425+ const guint path_len)
426+{
427+ guchar db_path[6] = { 0x00 };
428+ char *hex_path = NULL;
429+ int len = 0;
430+
431+ if (path_len > 0 && path_len < 7) {
432+ memcpy(db_path, path, path_len);
433+ len = path_len;
434+ } else if (sd->app_type == RIL_APPTYPE_USIM) {
435+ len = sim_ef_db_get_path_3g(fileid, db_path);
436+ } else if (sd->app_type == RIL_APPTYPE_SIM) {
437+ len = sim_ef_db_get_path_2g(fileid, db_path);
438+ } else {
439+ DBG("Unsupported app_type: 0%x", sd->app_type);
440+ }
441+
442+ if (len > 0) {
443+ hex_path = encode_hex(db_path, len, 0);
444+ parcel_w_string(rilp, (char *) hex_path);
445+ DBG("encoded path is: %s", hex_path);
446+ g_free(hex_path);
447+ } else if (fileid == SIM_EF_ICCID_FILEID || fileid == SIM_EFPL_FILEID) {
448+ /*
449+ * Special catch-all for EF_ICCID (unique card ID)
450+ * and EF_PL files which exist in the root directory.
451+ * As the sim_info_cb function may not have yet
452+ * recorded the app_type for the SIM, and the path
453+ * for both files is the same for 2g|3g, just hard-code.
454+ *
455+ * See 'struct ef_db' in:
456+ * ../../src/simutil.c for more details.
457+ */
458+ parcel_w_string(rilp, (char *) ROOTMF);
459+ DBG("encoded path is: %s", ROOTMF);
460+ }
461+}
462+
463+static void ril_file_info_cb(struct ril_msg *message, gpointer user_data)
464+{
465+ struct cb_data *cbd = user_data;
466+ ofono_sim_file_info_cb_t cb = cbd->cb;
467+ struct ofono_error error;
468+ gboolean ok = FALSE;
469+ int sw1 = 0, sw2 = 0, response_len = 0;
470+ int flen = 0, rlen = 0, str = 0;
471+ guchar *response = NULL;
472+ guchar access[3] = { 0x00, 0x00, 0x00 };
473+ guchar file_status = EF_STATUS_VALID;
474+
475+ DBG("");
476+
477+ if (message->error == RIL_E_SUCCESS) {
478+ decode_ril_error(&error, "OK");
479+ } else {
480+ DBG("Reply failure: %s", ril_error_to_string(message->error));
481+ decode_ril_error(&error, "FAIL");
482+ goto error;
483+ }
484+
485+ if ((response = (guchar *)
486+ ril_util_parse_sim_io_rsp(message,
487+ &sw1,
488+ &sw2,
489+ &response_len)) == NULL) {
490+ DBG("Can't parse SIM IO response from RILD");
491+ decode_ril_error(&error, "FAIL");
492+ goto error;
493+ }
494+
495+ if ((sw1 != 0x90 && sw1 != 0x91 && sw1 != 0x92 && sw1 != 0x9f) ||
496+ (sw1 == 0x90 && sw2 != 0x00)) {
497+ DBG("Error reply, invalid values: sw1: %02x sw2: %02x", sw1, sw2);
498+ memset(&error, 0, sizeof(error));
499+
500+ /* TODO: fix decode_ril_error to take type & error */
501+
502+ error.type = OFONO_ERROR_TYPE_SIM;
503+ error.error = (sw1 << 8) | sw2;
504+
505+ goto error;
506+ }
507+
508+ if (response_len) {
509+ g_ril_util_debug_hexdump(FALSE, response, response_len,
510+ sim_debug, "sim response: ");
511+
512+ if (response[0] == 0x62) {
513+ ok = sim_parse_3g_get_response(response, response_len,
514+ &flen, &rlen, &str, access, NULL);
515+ } else
516+ ok = sim_parse_2g_get_response(response, response_len,
517+ &flen, &rlen, &str, access, &file_status);
518+ }
519+
520+ if (!ok) {
521+ DBG("parse response failed");
522+ decode_ril_error(&error, "FAIL");
523+ goto error;
524+ }
525+
526+ cb(&error, flen, str, rlen, access, file_status, cbd->data);
527+ g_free(response);
528+ return;
529+
530+error:
531+ cb(&error, -1, -1, -1, NULL, EF_STATUS_INVALIDATED, cbd->data);
532+ g_free(response);
533+}
534+
535+static void ril_sim_read_info(struct ofono_sim *sim, int fileid,
536+ const unsigned char *path, unsigned int path_len,
537+ ofono_sim_file_info_cb_t cb,
538+ void *data)
539+{
540+ struct sim_data *sd = ofono_sim_get_data(sim);
541+ struct cb_data *cbd = cb_data_new(cb, data);
542+ struct parcel rilp;
543+ int ret;
544+
545+ parcel_init(&rilp);
546+ parcel_w_int32(&rilp, CMD_GET_RESPONSE);
547+ parcel_w_int32(&rilp, fileid);
548+
549+ set_path(sd, &rilp, fileid, path, path_len);
550+
551+ DBG("fileid: %s (%x)", sim_fileid_to_string(fileid), fileid);
552+
553+ parcel_w_int32(&rilp, 0); /* P1 */
554+ parcel_w_int32(&rilp, 0); /* P2 */
555+
556+ /*
557+ * TODO: review parameters values used by Android.
558+ * The values of P1-P3 in this code were based on
559+ * values used by the atmodem driver impl.
560+ *
561+ * NOTE:
562+ * GET_RESPONSE_EF_SIZE_BYTES == 15; !255
563+ */
564+ parcel_w_int32(&rilp, 15); /* P3 - max length */
565+ parcel_w_string(&rilp, NULL); /* data; only req'd for writes */
566+ parcel_w_string(&rilp, NULL); /* pin2; only req'd for writes */
567+ parcel_w_string(&rilp, sd->app_id); /* AID (Application ID) */
568+
569+ ret = g_ril_send(sd->ril,
570+ RIL_REQUEST_SIM_IO,
571+ rilp.data,
572+ rilp.size,
573+ ril_file_info_cb, cbd, g_free);
574+
575+ parcel_free(&rilp);
576+
577+ if (ret <= 0) {
578+ g_free(cbd);
579+ CALLBACK_WITH_FAILURE(cb, -1, -1, -1, NULL,
580+ EF_STATUS_INVALIDATED, data);
581+ }
582+}
583+
584+static void ril_file_io_cb(struct ril_msg *message, gpointer user_data)
585+{
586+ struct cb_data *cbd = user_data;
587+ ofono_sim_read_cb_t cb = cbd->cb;
588+ struct ofono_error error;
589+ int sw1 = 0, sw2 = 0, response_len = 0;
590+ guchar *response = NULL;
591+
592+ DBG("");
593+
594+ if (message->error == RIL_E_SUCCESS) {
595+ decode_ril_error(&error, "OK");
596+ } else {
597+ DBG("RILD reply failure: %s", ril_error_to_string(message->error));
598+ goto error;
599+ }
600+
601+ if ((response = (guchar *)
602+ ril_util_parse_sim_io_rsp(message,
603+ &sw1,
604+ &sw2,
605+ &response_len)) == NULL) {
606+ DBG("Error parsing IO response");
607+ goto error;
608+ }
609+
610+ cb(&error, response, response_len, cbd->data);
611+ g_free(response);
612+ return;
613+
614+error:
615+ decode_ril_error(&error, "FAIL");
616+ cb(&error, NULL, 0, cbd->data);
617+}
618+
619+static void ril_sim_read_binary(struct ofono_sim *sim, int fileid,
620+ int start, int length,
621+ const unsigned char *path, unsigned int path_len,
622+ ofono_sim_read_cb_t cb, void *data)
623+{
624+ struct sim_data *sd = ofono_sim_get_data(sim);
625+ struct cb_data *cbd = cb_data_new(cb, data);
626+ struct parcel rilp;
627+ int ret;
628+
629+ DBG("fileid: %s (%x) path: %s", sim_fileid_to_string(fileid),
630+ fileid, path);
631+
632+ parcel_init(&rilp);
633+ parcel_w_int32(&rilp, CMD_READ_BINARY);
634+ parcel_w_int32(&rilp, fileid);
635+
636+ set_path(sd, &rilp, fileid, path, path_len);
637+
638+ parcel_w_int32(&rilp, (start >> 8)); /* P1 */
639+ parcel_w_int32(&rilp, (start & 0xff)); /* P2 */
640+ parcel_w_int32(&rilp, length); /* P3 */
641+ parcel_w_string(&rilp, NULL); /* data; only req'd for writes */
642+ parcel_w_string(&rilp, NULL); /* pin2; only req'd for writes */
643+ parcel_w_string(&rilp, sd->app_id); /* AID (Application ID) */
644+
645+ ret = g_ril_send(sd->ril,
646+ RIL_REQUEST_SIM_IO,
647+ rilp.data,
648+ rilp.size,
649+ ril_file_io_cb, cbd, g_free);
650+ parcel_free(&rilp);
651+
652+ if (ret <= 0) {
653+ g_free(cbd);
654+ CALLBACK_WITH_FAILURE(cb, NULL, 0, data);
655+ }
656+}
657+
658+static void ril_sim_read_record(struct ofono_sim *sim, int fileid,
659+ int record, int length,
660+ const unsigned char *path, unsigned int path_len,
661+ ofono_sim_read_cb_t cb, void *data)
662+{
663+ struct sim_data *sd = ofono_sim_get_data(sim);
664+ struct cb_data *cbd = cb_data_new(cb, data);
665+ struct parcel rilp;
666+ int ret;
667+
668+ DBG("fileid: %s (%x) path: %s", sim_fileid_to_string(fileid),
669+ fileid, path);
670+
671+ parcel_init(&rilp);
672+ parcel_w_int32(&rilp, CMD_READ_RECORD);
673+ parcel_w_int32(&rilp, fileid);
674+
675+ set_path(sd, &rilp, fileid, path, path_len);
676+
677+ parcel_w_int32(&rilp, record); /* P1 */
678+ parcel_w_int32(&rilp, 4); /* P2 */
679+ parcel_w_int32(&rilp, length); /* P3 */
680+ parcel_w_string(&rilp, NULL); /* data; only req'd for writes */
681+ parcel_w_string(&rilp, NULL); /* pin2; only req'd for writes */
682+ parcel_w_string(&rilp, sd->app_id); /* AID (Application ID) */
683+
684+ ret = g_ril_send(sd->ril,
685+ RIL_REQUEST_SIM_IO,
686+ rilp.data,
687+ rilp.size,
688+ ril_file_io_cb, cbd, g_free);
689+
690+ parcel_free(&rilp);
691+
692+ if (ret <= 0) {
693+ g_free(cbd);
694+ CALLBACK_WITH_FAILURE(cb, NULL, 0, data);
695+ }
696+}
697+
698+static void ril_imsi_cb(struct ril_msg *message, gpointer user_data)
699+{
700+ struct cb_data *cbd = user_data;
701+ ofono_sim_imsi_cb_t cb = cbd->cb;
702+ struct ofono_error error;
703+ struct parcel rilp;
704+ gchar *imsi;
705+
706+ if (message->error == RIL_E_SUCCESS) {
707+ DBG("GET IMSI reply - OK");
708+ decode_ril_error(&error, "OK");
709+ } else {
710+ DBG("Reply failure: %s", ril_error_to_string(message->error));
711+ decode_ril_error(&error, "FAIL");
712+ cb(&error, NULL, cbd->data);
713+ return;
714+ }
715+
716+ /* Set up Parcel struct for proper parsing */
717+ rilp.data = message->buf;
718+ rilp.size = message->buf_len;
719+ rilp.capacity = message->buf_len;
720+ rilp.offset = 0;
721+
722+ /* 15 is the max length of IMSI
723+ * add 4 bytes for string length */
724+ /* FIXME: g_assert(message->buf_len <= 19); */
725+
726+ imsi = parcel_r_string(&rilp);
727+
728+ DBG("ril_imsi_cb: IMSI: %s", imsi);
729+
730+ cb(&error, imsi, cbd->data);
731+ g_free(imsi);
732+}
733+
734+static void ril_read_imsi(struct ofono_sim *sim, ofono_sim_imsi_cb_t cb,
735+ void *data)
736+{
737+ struct sim_data *sd = ofono_sim_get_data(sim);
738+ struct cb_data *cbd = cb_data_new(cb, data);
739+ struct parcel rilp;
740+ int ret;
741+
742+ DBG("");
743+
744+ parcel_init(&rilp);
745+ parcel_w_int32(&rilp, 1); /* Number of params */
746+ parcel_w_string(&rilp, sd->app_id); /* AID (Application ID) */
747+
748+ ret = g_ril_send(sd->ril, RIL_REQUEST_GET_IMSI,
749+ rilp.data, rilp.size, ril_imsi_cb, cbd, g_free);
750+ parcel_free(&rilp);
751+
752+ if (ret <= 0) {
753+ g_free(cbd);
754+ CALLBACK_WITH_FAILURE(cb, NULL, data);
755+ }
756+}
757+
758+static void sim_status_cb(struct ril_msg *message, gpointer user_data)
759+{
760+ struct ofono_sim *sim = user_data;
761+ struct sim_data *sd = ofono_sim_get_data(sim);
762+ struct sim_app app;
763+
764+ DBG("");
765+
766+ if (ril_util_parse_sim_status(message, &app)) {
767+ if (app.app_id)
768+ sd->app_id = app.app_id;
769+
770+ if (app.app_type != RIL_APPTYPE_UNKNOWN)
771+ sd->app_type = app.app_type;
772+ }
773+}
774+
775+static int send_get_sim_status(struct ofono_sim *sim)
776+{
777+ struct sim_data *sd = ofono_sim_get_data(sim);
778+
779+ return g_ril_send(sd->ril, RIL_REQUEST_GET_SIM_STATUS,
780+ NULL, 0, sim_status_cb, sim, NULL);
781+}
782+
783+static gboolean ril_sim_register(gpointer user)
784+{
785+ struct ofono_sim *sim = user;
786+
787+ DBG("");
788+
789+ send_get_sim_status(sim);
790+
791+ /* TODO: consider replacing idle call of register
792+ * with call in sim_status_cb().
793+ */
794+ ofono_sim_register(sim);
795+
796+ return FALSE;
797+}
798+
799+static int ril_sim_probe(struct ofono_sim *sim, unsigned int vendor,
800+ void *data)
801+{
802+ GRil *ril = data;
803+ struct sim_data *sd;
804+
805+ DBG("");
806+
807+ sd = g_new0(struct sim_data, 1);
808+ sd->ril = g_ril_clone(ril);
809+ sd->app_id = NULL;
810+ sd->app_type = RIL_APPTYPE_UNKNOWN;
811+
812+ ofono_sim_set_data(sim, sd);
813+
814+ /*
815+ * TODO: analyze if capability check is needed
816+ * and/or timer should be adjusted.
817+ *
818+ * ofono_sim_register() needs to be called after the
819+ * driver has been set in ofono_sim_create(), which
820+ * calls this function. Most other drivers make some
821+ * kind of capabilities query to the modem, and then
822+ * call register in the callback; we use an idle event
823+ * instead.
824+ */
825+ g_idle_add(ril_sim_register, sim);
826+
827+ return 0;
828+}
829+
830+static void ril_sim_remove(struct ofono_sim *sim)
831+{
832+ struct sim_data *sd = ofono_sim_get_data(sim);
833+
834+ ofono_sim_set_data(sim, NULL);
835+
836+ g_ril_unref(sd->ril);
837+ g_free(sd);
838+}
839+
840+static struct ofono_sim_driver driver = {
841+ .name = "rilmodem",
842+ .probe = ril_sim_probe,
843+ .remove = ril_sim_remove,
844+ .read_file_info = ril_sim_read_info,
845+ .read_file_transparent = ril_sim_read_binary,
846+ .read_file_linear = ril_sim_read_record,
847+ .read_file_cyclic = ril_sim_read_record,
848+ .read_imsi = ril_read_imsi,
849+/*
850+ * TODO: Implmenting PIN/PUK support requires defining
851+ * the following driver methods.
852+ *
853+ * In the meanwhile, as long as the SIM card is present,
854+ * and unlocked, the core SIM code will check for the
855+ * presence of query_passwd_state, and if null, then the
856+ * function sim_initialize_after_pin() is called.
857+ *
858+ * .query_passwd_state = ril_pin_query,
859+ * .query_pin_retries = ril_pin_retries_query,
860+ * .send_passwd = ril_pin_send,
861+ * .reset_passwd = ril_pin_send_puk,
862+ * .lock = ril_pin_enable,
863+ * .change_passwd = ril_change_passwd,
864+ * .query_locked = ril_pin_query_enabled,
865+ *
866+ * TODO: Implementing SIM write file IO support requires
867+ * the following functions to be defined.
868+ *
869+ * .write_file_transparent = ril_sim_update_binary,
870+ * .write_file_linear = ril_sim_update_record,
871+ * .write_file_cyclic = ril_sim_update_cyclic,
872+ */
873+};
874+
875+void ril_sim_init(void)
876+{
877+ DBG("");
878+ ofono_sim_driver_register(&driver);
879+}
880+
881+void ril_sim_exit(void)
882+{
883+ ofono_sim_driver_unregister(&driver);
884+}
885
886=== modified file 'drivers/rilmodem/sms.c'
887--- drivers/rilmodem/sms.c 2013-03-28 12:50:26 +0000
888+++ drivers/rilmodem/sms.c 2013-05-20 19:19:27 +0000
889@@ -309,11 +309,15 @@
890
891 ofono_sms_set_data(sms, data);
892
893- /* ofono_devinfo_register() needs to be called after
894- * the driver has been set in devinfo_create() which
895- * calls this function. Most other drivers use a
896- * callback after getting some return from the modem
897- * itself...
898+ /*
899+ * TODO: analyze if capability check is needed
900+ * and/or timer should be adjusted.
901+ *
902+ * ofono_sms_register() needs to be called after
903+ * the driver has been set in ofono_sms_create(), which
904+ * calls this function. Most other drivers make some
905+ * kind of capabilities query to the modem, and then
906+ * call register in the callback; we use a timer instead.
907 */
908 g_timeout_add_seconds(2, ril_delayed_register, sms);
909
910
911=== modified file 'drivers/rilmodem/voicecall.c'
912--- drivers/rilmodem/voicecall.c 2013-03-28 12:50:26 +0000
913+++ drivers/rilmodem/voicecall.c 2013-05-20 19:19:27 +0000
914@@ -486,11 +486,15 @@
915
916 ofono_voicecall_set_data(vc, vd);
917
918- /* ofono_devinfo_register() needs to be called after
919- * the driver has been set in devinfo_create() which
920- * calls this function. Most other drivers use a
921- * callback after getting some return from the modem
922- * itself...
923+ /*
924+ * TODO: analyze if capability check is needed
925+ * and/or timer should be adjusted.
926+ *
927+ * ofono_voicecall_register() needs to be called after
928+ * the driver has been set in ofono_voicecall_create(),
929+ * which calls this function. Most other drivers make
930+ * some kind of capabilities query to the modem, and then
931+ * call register in the callback; we use a timer instead.
932 */
933 g_timeout_add_seconds(2, ril_delayed_register, vc);
934
935
936=== modified file 'gril/grilutil.c'
937--- gril/grilutil.c 2013-03-28 12:50:26 +0000
938+++ gril/grilutil.c 2013-05-20 19:19:27 +0000
939@@ -88,6 +88,47 @@
940 }
941 }
942
943+const char *ril_error_to_string(int error)
944+{
945+
946+ switch (error) {
947+ case RIL_E_SUCCESS:
948+ return "SUCCESS";
949+ case RIL_E_RADIO_NOT_AVAILABLE:
950+ return "RADIO_NOT_AVAILABLE";
951+ case RIL_E_GENERIC_FAILURE:
952+ return "GENERIC_FAILURE";
953+ case RIL_E_PASSWORD_INCORRECT:
954+ return "PASSWORD_INCORRECT";
955+ case RIL_E_SIM_PIN2:
956+ return "SIM_PIN2";
957+ case RIL_E_SIM_PUK2:
958+ return "SIM_PUK2";
959+ case RIL_E_REQUEST_NOT_SUPPORTED:
960+ return "REQUEST_NOT_SUPPORTED";
961+ case RIL_E_CANCELLED:
962+ return "CANCELLED";
963+ case RIL_E_OP_NOT_ALLOWED_DURING_VOICE_CALL:
964+ return "OP_NOT_ALLOWED_DURING_VOICE_CALL";
965+ case RIL_E_OP_NOT_ALLOWED_BEFORE_REG_TO_NW:
966+ return "OP_NOT_ALLOWED_BEFORE_REG_TO_NW";
967+ case RIL_E_SMS_SEND_FAIL_RETRY:
968+ return "SMS_SEND_FAIL_RETRY";
969+ case RIL_E_SIM_ABSENT:
970+ return "SIM_ABSENT";
971+ case RIL_E_SUBSCRIPTION_NOT_AVAILABLE:
972+ return "SUBSCRIPTION_NOT_AVAILABLE";
973+ case RIL_E_MODE_NOT_SUPPORTED:
974+ return "MODE_NOT_SUPPORTED";
975+ case RIL_E_FDN_CHECK_FAILURE:
976+ return "FDN_CHECK_FAILURE";
977+ case RIL_E_ILLEGAL_SIM_OR_ME:
978+ return "ILLEGAL_SIM_OR_ME";
979+ default:
980+ return "<Unknown Error>";
981+ }
982+}
983+
984 const char *ril_pinstate_to_string(int pin_state)
985 {
986 switch (pin_state) {
987
988=== modified file 'gril/grilutil.h'
989--- gril/grilutil.h 2013-03-28 12:50:26 +0000
990+++ gril/grilutil.h 2013-05-20 19:19:27 +0000
991@@ -32,6 +32,7 @@
992 const char *ril_appstate_to_string(int app_state);
993 const char *ril_apptype_to_string(int app_type);
994 const char *ril_cardstate_to_string(int card_state);
995+const char *ril_error_to_string(int error);
996 const char *ril_pinstate_to_string(int pin_state);
997 const char *ril_request_id_to_string(int req);
998
999
1000=== modified file 'plugins/ril.c'
1001--- plugins/ril.c 2013-03-28 12:50:26 +0000
1002+++ plugins/ril.c 2013-05-20 19:19:27 +0000
1003@@ -58,23 +58,12 @@
1004
1005 #define MAX_POWER_ON_RETRIES 5
1006
1007-enum {
1008- SIM_STATE_INVALID_OR_LOCKED = 0,
1009- SIM_STATE_VALID = 1,
1010- SIM_STATE_INVALID_CS = 2,
1011- SIM_STATE_INVALID_PS = 3,
1012- SIM_STATE_INVALID_PS_AND_CS = 4,
1013- SIM_STATE_ROMSIM = 240,
1014- SIM_STATE_NOT_EXISTENT = 255,
1015-};
1016-
1017 struct ril_data {
1018 const char *ifname;
1019 GRil *modem;
1020- int sim_state;
1021 int power_on_retries;
1022
1023- ofono_bool_t enabled;
1024+ ofono_bool_t have_sim;
1025 ofono_bool_t online;
1026 ofono_bool_t reported;
1027 };
1028@@ -88,23 +77,6 @@
1029 ofono_info("%s%s", prefix, str);
1030 }
1031
1032-static void report_powered(struct ofono_modem *modem, struct ril_data *ril,
1033- ofono_bool_t powered)
1034-{
1035- if (powered == ril->reported) {
1036- DBG("powered == reported; returning");
1037- return;
1038- }
1039-
1040- DBG("%s", powered ? "Powered on"
1041- : ril->enabled ? "Reset"
1042- : "Powered off");
1043-
1044- ril->reported = powered;
1045- ofono_modem_set_powered(modem, powered);
1046-
1047-}
1048-
1049 static void power_cb(struct ril_msg *message, gpointer user_data)
1050 {
1051 struct ofono_modem *modem = user_data;
1052@@ -120,9 +92,8 @@
1053 else
1054 ofono_error("Max retries for radio power on exceeded!");
1055 } else {
1056- DBG("Radio POWER-ON OK, setting modem online.");
1057-
1058- ofono_modem_set_online(modem, TRUE);
1059+ DBG("Radio POWER-ON OK, calling set_powered(TRUE).");
1060+ ofono_modem_set_powered(modem, TRUE);
1061 }
1062 }
1063
1064@@ -151,45 +122,20 @@
1065 {
1066 struct ofono_modem *modem = user_data;
1067 struct ril_data *ril = ofono_modem_get_data(modem);
1068- struct parcel rilp;
1069- int card_state, num_apps, pin_state;
1070
1071 DBG("");
1072
1073- /* Set up Parcel struct for proper parsing */
1074- rilp.data = message->buf;
1075- rilp.size = message->buf_len;
1076- rilp.capacity = message->buf_len;
1077- rilp.offset = 0;
1078-
1079- /* 20 is the min length of RIL_CardStatus_v6
1080- * as the AppState array can be 0-len */
1081- g_assert(message->buf_len >= 20);
1082-
1083- card_state = parcel_r_int32(&rilp);
1084- pin_state = parcel_r_int32(&rilp);
1085- parcel_r_int32(&rilp); /* ignore: gsm_umts_subscription_app_index */
1086- parcel_r_int32(&rilp); /* ignore: cdma_subscription_app_index */
1087- parcel_r_int32(&rilp); /* ignore: ims_subscription_app_index */
1088- num_apps = parcel_r_int32(&rilp);
1089-
1090- /* skip AppState array */
1091-
1092- if (card_state == RIL_CARDSTATE_PRESENT) {
1093+ /* Returns TRUE if cardstate == PRESENT */
1094+ if (ril_util_parse_sim_status(message, NULL)) {
1095+ DBG("have_sim = TRUE; powering on modem.");
1096
1097 /* TODO: check PinState=DISABLED, for now just
1098 * set state to valid... */
1099- ril->sim_state = SIM_STATE_VALID;
1100-
1101+ ril->have_sim = TRUE;
1102 power_on(modem);
1103 }
1104
1105- DBG("card_state: %s (%d) pin_state: %s (%d) num_apps: %d",
1106- ril_cardstate_to_string(card_state),
1107- card_state,
1108- ril_pinstate_to_string(pin_state),
1109- pin_state,
1110- num_apps);
1111+ /* TODO: handle emergency calls if SIM !present or locked */
1112 }
1113
1114 static int send_get_sim_status(struct ofono_modem *modem)
1115@@ -251,13 +197,16 @@
1116 static void ril_pre_sim(struct ofono_modem *modem)
1117 {
1118 struct ril_data *ril = ofono_modem_get_data(modem);
1119+ struct ofono_sim *sim;
1120
1121 DBG("(%p) with %s", modem, ril->ifname);
1122
1123+ sim = ofono_sim_create(modem, 0, "rilmodem", ril->modem);
1124 ofono_devinfo_create(modem, 0, "rilmodem", ril->modem);
1125 ofono_voicecall_create(modem, 0, "rilmodem", ril->modem);
1126
1127- send_get_sim_status(modem);
1128+ if (sim && ril->have_sim)
1129+ ofono_sim_inserted_notify(sim, TRUE);
1130 }
1131
1132 static void ril_post_sim(struct ofono_modem *modem)
1133@@ -265,6 +214,14 @@
1134 struct ril_data *ril = ofono_modem_get_data(modem);
1135
1136 DBG("(%p) with %s", modem, ril->ifname);
1137+
1138+ /* TODO: this function should setup:
1139+ * - phonebook
1140+ * - stk ( SIM toolkit )
1141+ * - radio_settings (why?)
1142+ * - sms ( this could go to post_online ); ask ofono upstream...
1143+ */
1144+ ofono_sms_create(modem, 0, "rilmodem", ril->modem);
1145 }
1146
1147 static void ril_post_online(struct ofono_modem *modem)
1148@@ -275,7 +232,6 @@
1149
1150 ofono_call_volume_create(modem, 0, "rilmodem", ril->modem);
1151 ofono_netreg_create(modem, 0, "rilmodem", ril->modem);
1152- ofono_sms_create(modem, 0, "rilmodem", ril->modem);
1153 }
1154
1155 static int ril_enable(struct ofono_modem *modem)
1156@@ -284,8 +240,7 @@
1157
1158 DBG("modem=%p with %s", modem, ril ? ril->ifname : NULL);
1159
1160- ril->enabled = TRUE;
1161- ril->sim_state = SIM_STATE_NOT_EXISTENT;
1162+ ril->have_sim = FALSE;
1163
1164 ril->modem = g_ril_new();
1165
1166@@ -307,7 +262,9 @@
1167 g_ril_set_debug(ril->modem, ril_debug, "Device: ");
1168 }
1169
1170- return 0;
1171+ send_get_sim_status(modem);
1172+
1173+ return -EINPROGRESS;
1174 }
1175
1176 static int ril_disable(struct ofono_modem *modem)
1177@@ -316,8 +273,6 @@
1178
1179 DBG("modem=%p with %p", modem, ril ? ril->ifname : NULL);
1180
1181- ril->enabled = FALSE;
1182-
1183 return 0;
1184 }
1185
1186@@ -365,7 +320,7 @@
1187 * non-standard ( see udev comment above ).
1188 * usually called by undevng::create_modem
1189 *
1190- * args are name (optional) & type
1191+ * args are name (optional) & type
1192 */
1193 modem = ofono_modem_create(NULL, "ril");
1194 if (modem == NULL) {
1195@@ -373,13 +328,29 @@
1196 return -ENODEV;
1197 }
1198
1199+ /* TODO: these are both placeholders; we should
1200+ * determine if they can be removed.
1201+ */
1202 ofono_modem_set_string(modem, "Interface", "ttys");
1203 ofono_modem_set_integer(modem, "Address", 0);
1204
1205+ /* This causes driver->probe() to be called... */
1206 retval = ofono_modem_register(modem);
1207 DBG("ofono_modem_register returned: %d", retval);
1208
1209- /* kickstart the modem */
1210+ /* kickstart the modem:
1211+ * causes core modem code to call
1212+ * - set_powered(TRUE) - which in turn
1213+ * calls driver->enable()
1214+ *
1215+ * - driver->pre_sim()
1216+ *
1217+ * Could also be done via:
1218+ *
1219+ * - a DBus call to SetProperties w/"Powered=TRUE" *1
1220+ * - sim_state_watch ( handles SIM removal? LOCKED states? **2
1221+ * - ofono_modem_set_powered()
1222+ */
1223 ofono_modem_reset(modem);
1224
1225 return retval;
1226@@ -393,3 +364,4 @@
1227
1228 OFONO_PLUGIN_DEFINE(ril, "RIL modem driver", VERSION,
1229 OFONO_PLUGIN_PRIORITY_DEFAULT, ril_init, ril_exit)
1230+
1231
1232=== modified file 'src/simutil.c'
1233--- src/simutil.c 2013-01-28 16:25:32 +0000
1234+++ src/simutil.c 2013-05-20 19:19:27 +0000
1235@@ -1084,6 +1084,93 @@
1236 g_free(eons);
1237 }
1238
1239+const char *sim_fileid_to_string(int fileid)
1240+{
1241+ switch (fileid) {
1242+ case SIM_EFPL_FILEID:
1243+ return "SIM_EFPL_FILEID";
1244+ case SIM_EF_ICCID_FILEID:
1245+ return "SIM_EF_ICCID";
1246+ case SIM_MF_FILEID:
1247+ return "SIM_MF_FILEID";
1248+ case SIM_EFIMG_FILEID:
1249+ return "SIM_EFIMG_FILEID";
1250+ case SIM_DFPHONEBOOK_FILEID:
1251+ return "SIM_DFPHONEBOOK_FILEID";
1252+ case SIM_EFLI_FILEID:
1253+ return "SIM_EFLI_FILEID";
1254+ case SIM_EFARR_FILEID:
1255+ return "SIM_EFARR_FILEID";
1256+ case SIM_EFIMSI_FILEID:
1257+ return "SIM_EFIMSI_FILEID";
1258+ case SIM_EF_CPHS_MWIS_FILEID:
1259+ return "SIM_EF_CPHS_MWIS_FILEID";
1260+ case SIM_EF_CPHS_CFF_FILEID:
1261+ return "SIM_EF_CPHS_CFF_FILEID";
1262+ case SIM_EF_CPHS_SPN_FILEID:
1263+ return "SIM_EF_CPHS_SPN_FILEID";
1264+ case SIM_EF_CPHS_CSP_FILEID:
1265+ return "SIM_EF_CPHS_CSP_FILEID";
1266+ case SIM_EF_CPHS_INFORMATION_FILEID:
1267+ return "SIM_EF_CPHS_INFORMATION_FILEID";
1268+ case SIM_EF_CPHS_MBDN_FILEID:
1269+ return "SIM_EF_CPHS_MBDN_FILEID";
1270+ case SIM_EF_CPHS_SPN_SHORT_FILEID:
1271+ return "SIM_EF_CPHS_SPN_SHORT_FILEID";
1272+ case SIM_EFSST_FILEID:
1273+ return "SIM_EFSST/EFUST_FILEID";
1274+ case SIM_EFADN_FILEID:
1275+ return "SIM_EFADN_FILEID";
1276+ case SIM_EFMSISDN_FILEID:
1277+ return "SIM_EFMSISDN_FILEID";
1278+ case SIM_EFSMSP_FILEID:
1279+ return "SIM_EFSMSP_FILEID";
1280+ case SIM_EFCBMI_FILEID:
1281+ return "SIM_EFCBMI_FILEID";
1282+ case SIM_EFSPN_FILEID:
1283+ return "SIM_EFSPN_FILEID";
1284+ case SIM_EFCBMID_FILEID:
1285+ return "SIM_EFCBMID_FILEID";
1286+ case SIM_EFSDN_FILEID:
1287+ return "SIM_EFSDN_FILEID";
1288+ case SIM_EFEXT1_FILEID:
1289+ return "SIM_EFEXT1_FILEID";
1290+ case SIM_EFBDN_FILEID:
1291+ return "SIM_EFBDN_FILEID";
1292+ case SIM_EFCBMIR_FILEID:
1293+ return "SIM_EFCBMIR_FILEID";
1294+ case SIM_EFEST_FILEID:
1295+ return "SIM_EFEST_FILEID";
1296+ case SIM_EFAD_FILEID:
1297+ return "SIM_EFAD_FILEID";
1298+ case SIM_EFPHASE_FILEID:
1299+ return "SIM_EFPHASE_FILEID";
1300+ case SIM_EFECC_FILEID:
1301+ return "SIM_EFECC_FILEID";
1302+ case SIM_EFPNN_FILEID:
1303+ return "SIM_EFPNN_FILEID";
1304+ case SIM_EFOPL_FILEID:
1305+ return "SIM_EFOPL_FILEID";
1306+ case SIM_EFMBDN_FILEID:
1307+ return "SIM_EFMBDN_FILEID";
1308+ case SIM_EFMBI_FILEID:
1309+ return "SIM_EFMBI_FILEID";
1310+ case SIM_EFMWIS_FILEID:
1311+ return "SIM_EFMWIS_FILEID";
1312+ case SIM_EFCFIS_FILEID:
1313+ return "SIM_EFCFIS_FILEID";
1314+ case SIM_EFSPDI_FILEID:
1315+ return "SIM_EFSPDI_FILEID";
1316+ case SIM_DFTELECOM_FILEID:
1317+ return "SIM_DFTELECOM_FILEID";
1318+ case SIM_DFGSM_FILEID:
1319+ return "SIM_DFGSM_FILEID";
1320+ default:
1321+ return "<INVALID_FILEID>";
1322+ }
1323+
1324+}
1325+
1326 static const struct sim_eons_operator_info *
1327 sim_eons_lookup_common(struct sim_eons *eons,
1328 const char *mcc, const char *mnc,
1329
1330=== modified file 'src/simutil.h'
1331--- src/simutil.h 2013-01-28 16:25:32 +0000
1332+++ src/simutil.h 2013-05-20 19:19:27 +0000
1333@@ -446,6 +446,7 @@
1334 const char *mnc);
1335 void sim_eons_free(struct sim_eons *eons);
1336
1337+const char *sim_fileid_to_string(int fileid);
1338 void sim_parse_mcc_mnc(const guint8 *bcd, char *mcc, char *mnc);
1339 void sim_encode_mcc_mnc(guint8 *out, const char *mcc, const char *mnc);
1340 struct sim_spdi *sim_spdi_new(const guint8 *tlv, int length);

Subscribers

People subscribed via source and target branches