Merge lp:~awe/phablet-extras/ofono-sim-support into lp:phablet-extras/ofono
- ofono-sim-support
- Merge into ofono
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 |
Related bugs: | |
Related blueprints: |
Telephony Support
(Undefined)
|
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
PS Jenkins bot (ps-jenkins) wrote : | # |
PS Jenkins bot (ps-jenkins) wrote : | # |
PASSED: Continuous integration, rev:42
http://
Executed test runs:
SUCCESS: http://
deb: http://
Click here to trigger a rebuild:
http://
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.
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.
PS Jenkins bot (ps-jenkins) wrote : | # |
PASSED: Continuous integration, rev:43
http://
Executed test runs:
SUCCESS: http://
deb: http://
Click here to trigger a rebuild:
http://
Ricardo Salveti (rsalveti) wrote : | # |
273 + cb(&error, -1, -1, -1, NULL, EF_STATUS_
274 + return;
292 + cb(&error, -1, -1, -1, NULL, EF_STATUS_
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_
301 + &str, access, NULL);
302 +
303 + file_status = EF_STATUS_VALID;
304 + } else
305 + ok = sim_parse_
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_
387 + cb(&error, NULL, 0, cbd->data);
396 + decode_
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.
ofonod[1023]: plugins/
ofonod[1023]: plugins/
ofonod[1023]: src/cdma-
ofonod[1023]: src/gprs-
ofonod[1023]: src/cdma-
ofonod[1023]: src/modem.
ofonod[1023]: src/cdma-
ofonod[1023]: src/modem.
ofonod[1023]: src/modem.
ofonod[1023]: src/gprs.
ofonod[1023]: src/ctm.
ofonod[1023]: plugins/
ofonod[1023]: src/voicecall.
ofonod[1023]: src/modem.
ofonod[1023]: src/network.
ofonod[1023]: src/call-
ofonod[1023]: src/handsfree.
ofonod[1023]: src/voicecall.
ofonod[1023]: src/modem.
ofonod[1023]: src/call-
Ricardo Salveti (rsalveti) wrote : | # |
Using raring image from http://
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.
PS Jenkins bot (ps-jenkins) wrote : | # |
PASSED: Continuous integration, rev:44
http://
Executed test runs:
SUCCESS: http://
deb: http://
Click here to trigger a rebuild:
http://
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 QualcommSharedR
I would hold off on further review until we can discuss further.
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.
PS Jenkins bot (ps-jenkins) wrote : | # |
PASSED: Continuous integration, rev:45
http://
Executed test runs:
SUCCESS: http://
deb: http://
Click here to trigger a rebuild:
http://
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_
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.
PS Jenkins bot (ps-jenkins) wrote : | # |
PASSED: Continuous integration, rev:46
http://
Executed test runs:
SUCCESS: http://
deb: http://
Click here to trigger a rebuild:
http://
Ricardo Salveti (rsalveti) : | # |
Preview Diff
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); |
PASSED: Continuous integration, rev:40 jenkins. qa.ubuntu. com/job/ phablet- extras- ofono-ci/ 8/ jenkins. qa.ubuntu. com/job/ phablet- extras- ofono-raring- armhf-ci/ 8 jenkins. qa.ubuntu. com/job/ phablet- extras- ofono-raring- armhf-ci/ 8/artifact/ work/output/ *zip*/output. zip
http://
Executed test runs:
SUCCESS: http://
deb: http://
Click here to trigger a rebuild: s-jenkins: 8080/job/ phablet- extras- ofono-ci/ 8/rebuild
http://