AT: Better failure handling and removed wrong unlock
[hayes-ril.git] / sim.c
1 /*
2  * This file is part of hayes-ril.
3  *
4  * Copyright (C) 2012 Paul Kocialkowski <contact@paulk.fr>
5  *
6  * Parts of this code are based on htcgeneric-ril, reference-ril:
7  * Copyright 2006-2011, htcgeneric-ril contributors
8  * Copyright 2006, The Android Open Source Project
9  *
10  * Licensed under the Apache License, Version 2.0 (the "License");
11  * you may not use this file except in compliance with the License.
12  * You may obtain a copy of the License at
13  *
14  *     http://www.apache.org/licenses/LICENSE-2.0
15  *
16  * Unless required by applicable law or agreed to in writing, software
17  * distributed under the License is distributed on an "AS IS" BASIS,
18  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
19  * See the License for the specific language governing permissions and
20  * limitations under the License.
21  */
22
23 #include <ctype.h>
24
25 #define LOG_TAG "RIL-SIM"
26 #include <utils/Log.h>
27 #include <telephony/ril.h>
28
29 #include <hayes-ril.h>
30
31 RIL_RadioState at2ril_sim_status(int status, char *error, char **data, int data_count)
32 {
33         int code = 0;
34         int i;
35
36         if(status == AT_STATUS_CME_ERROR && error != NULL) {
37                 code = atoi(error);
38                 switch(code) {
39                         case AT_CME_ERROR_PH_SIM_PIN_REQD:
40                         case AT_CME_ERROR_PH_SIM_PUK_REQD:
41                         case AT_CME_ERROR_PH_FSIM_PIN_REQD:
42                         case AT_CME_ERROR_PH_FSIM_PUK_REQD:
43                         case AT_CME_ERROR_SIM_NOT_INSERTED:
44                         case AT_CME_ERROR_SIM_PIN_REQD:
45                         case AT_CME_ERROR_SIM_PUK_REQD:
46                         case AT_CME_ERROR_SIM_PIN2_REQD:
47                         case AT_CME_ERROR_SIM_PUK2_REQD:
48                         case AT_CME_ERROR_SIM_BLOCKED:
49                         case AT_CME_ERROR_INCORRECT_PASSWORD:
50                                 return RADIO_STATE_SIM_LOCKED_OR_ABSENT;
51                         case AT_CME_ERROR_SIM_FAILURE:
52                         case AT_CME_ERROR_SIM_BUSY:
53                         case AT_CME_ERROR_SIM_POWERED_DOWN:
54                         case AT_CME_ERROR_SIM_WRONG:
55                         default:
56                                 return RADIO_STATE_SIM_NOT_READY;
57                 }
58         } else if(status == AT_STATUS_OK) {
59                 if(data != NULL && data_count > 0) {
60                         for(i=0 ; i < data_count ; i++) {
61                                 if(at_strings_raw_compare("SIM PIN", data[i])) {
62                                         return RADIO_STATE_SIM_LOCKED_OR_ABSENT;
63                                 } else if(at_strings_raw_compare("SIM PUK", data[i])) {
64                                         return RADIO_STATE_SIM_LOCKED_OR_ABSENT;
65                                 } else if(at_strings_raw_compare("READY", data[i])) {
66                                         return RADIO_STATE_SIM_READY;
67                                 }
68                         }
69                 }
70
71                 // Fallback
72                 return RADIO_STATE_SIM_NOT_READY;
73         } else {
74                 // Various error codes, not helping here, don't change anything
75                 return ril_globals.radio_state;
76         }
77
78 }
79
80 RIL_RadioState at2ril_card_status(RIL_CardStatus *card_status, int status, char *error, char **data, int data_count)
81 {
82         RIL_RadioState radio_state;
83         int code = 0;
84
85         int app_status_array_length = 0;
86         int app_index = -1;
87         int i;
88
89         static RIL_AppStatus app_status_array[] = {
90                 // SIM_ABSENT = 0
91                 { RIL_APPTYPE_UNKNOWN, RIL_APPSTATE_UNKNOWN, RIL_PERSOSUBSTATE_UNKNOWN,
92                 NULL, NULL, 0, RIL_PINSTATE_UNKNOWN, RIL_PINSTATE_UNKNOWN },
93                 // SIM_NOT_READY = 1
94                 { RIL_APPTYPE_SIM, RIL_APPSTATE_DETECTED, RIL_PERSOSUBSTATE_UNKNOWN,
95                 NULL, NULL, 0, RIL_PINSTATE_UNKNOWN, RIL_PINSTATE_UNKNOWN },
96                 // SIM_READY = 2
97                 { RIL_APPTYPE_SIM, RIL_APPSTATE_READY, RIL_PERSOSUBSTATE_READY,
98                 NULL, NULL, 0, RIL_PINSTATE_UNKNOWN, RIL_PINSTATE_UNKNOWN },
99                 // SIM_PIN = 3
100                 { RIL_APPTYPE_SIM, RIL_APPSTATE_PIN, RIL_PERSOSUBSTATE_UNKNOWN,
101                 NULL, NULL, 0, RIL_PINSTATE_ENABLED_NOT_VERIFIED, RIL_PINSTATE_UNKNOWN },
102                 // SIM_PUK = 4
103                 { RIL_APPTYPE_SIM, RIL_APPSTATE_PUK, RIL_PERSOSUBSTATE_UNKNOWN,
104                 NULL, NULL, 0, RIL_PINSTATE_ENABLED_BLOCKED, RIL_PINSTATE_UNKNOWN },
105                 // SIM_BLOCKED = 5
106                 { RIL_APPTYPE_SIM, RIL_APPSTATE_PUK, RIL_PERSOSUBSTATE_UNKNOWN,
107                 NULL, NULL, 0, RIL_PINSTATE_ENABLED_PERM_BLOCKED, RIL_PINSTATE_UNKNOWN },
108                 // SIM_NETWORK_PERSO = 6
109                 { RIL_APPTYPE_SIM, RIL_APPSTATE_SUBSCRIPTION_PERSO, RIL_PERSOSUBSTATE_SIM_NETWORK,
110                 NULL, NULL, 0, RIL_PINSTATE_ENABLED_NOT_VERIFIED, RIL_PINSTATE_UNKNOWN },
111                 // SIM_NETWORK_SUBSET_PERSO = 7
112                 { RIL_APPTYPE_SIM, RIL_APPSTATE_SUBSCRIPTION_PERSO, RIL_PERSOSUBSTATE_SIM_NETWORK_SUBSET,
113                 NULL, NULL, 0, RIL_PINSTATE_ENABLED_NOT_VERIFIED, RIL_PINSTATE_UNKNOWN },
114                 // SIM_CORPORATE_PERSO = 8
115                 { RIL_APPTYPE_SIM, RIL_APPSTATE_SUBSCRIPTION_PERSO, RIL_PERSOSUBSTATE_SIM_CORPORATE,
116                 NULL, NULL, 0, RIL_PINSTATE_ENABLED_NOT_VERIFIED, RIL_PINSTATE_UNKNOWN },
117                 // SIM_SERVICE_PROVIDER_PERSO = 9
118                 { RIL_APPTYPE_SIM, RIL_APPSTATE_SUBSCRIPTION_PERSO, RIL_PERSOSUBSTATE_SIM_SERVICE_PROVIDER,
119                 NULL, NULL, 0, RIL_PINSTATE_ENABLED_NOT_VERIFIED, RIL_PINSTATE_UNKNOWN },
120         };
121
122         app_status_array_length = sizeof(app_status_array) / sizeof(RIL_AppStatus);
123
124         if(app_status_array_length > RIL_CARD_MAX_APPS)
125                 app_status_array_length = RIL_CARD_MAX_APPS;
126
127         radio_state = at2ril_sim_status(status, error, data, data_count);
128
129         if(status == AT_STATUS_CME_ERROR && error != NULL) {
130                 code = atoi(error);
131
132                 switch(code) {
133                         case AT_CME_ERROR_SIM_NOT_INSERTED:
134                                 card_status->card_state = RIL_CARDSTATE_ABSENT;
135                                 card_status->universal_pin_state = RIL_PINSTATE_UNKNOWN;
136                                 app_index = 0;
137                                 break;
138                         case AT_CME_ERROR_PH_SIM_PIN_REQD:
139                         case AT_CME_ERROR_PH_FSIM_PIN_REQD:
140                         case AT_CME_ERROR_SIM_PIN_REQD:
141                         case AT_CME_ERROR_INCORRECT_PASSWORD:
142                                 card_status->card_state = RIL_CARDSTATE_PRESENT;
143                                 card_status->universal_pin_state = RIL_PINSTATE_ENABLED_NOT_VERIFIED;
144                                 app_index = 3;
145                                 break;
146                         case AT_CME_ERROR_PH_SIM_PUK_REQD:
147                         case AT_CME_ERROR_PH_FSIM_PUK_REQD:
148                         case AT_CME_ERROR_SIM_PUK_REQD:
149                                 card_status->card_state = RIL_CARDSTATE_PRESENT;
150                                 card_status->universal_pin_state = RIL_PINSTATE_ENABLED_BLOCKED;
151                                 app_index = 4;
152                                 break;
153                         case AT_CME_ERROR_SIM_PIN2_REQD:
154                         case AT_CME_ERROR_SIM_PUK2_REQD:
155                         case AT_CME_ERROR_SIM_BLOCKED:
156                                 card_status->card_state = RIL_CARDSTATE_PRESENT;
157                                 card_status->universal_pin_state = RIL_PINSTATE_ENABLED_PERM_BLOCKED;
158                                 app_index = 5;
159                                 break;
160                         case AT_CME_ERROR_SIM_FAILURE:
161                         case AT_CME_ERROR_SIM_BUSY:
162                         case AT_CME_ERROR_SIM_POWERED_DOWN:
163                         case AT_CME_ERROR_SIM_WRONG:
164                         default:
165                                 card_status->card_state = RIL_CARDSTATE_PRESENT;
166                                 card_status->universal_pin_state = RIL_PINSTATE_UNKNOWN;
167                                 app_index = 1;
168                                 break;
169                 }
170         } else if(status == AT_STATUS_OK) {
171                 if(data != NULL && data_count > 0) {
172                         for(i=0 ; i < data_count ; i++) {
173                                 if(at_strings_raw_compare("SIM PIN", data[i])) {
174                                         card_status->card_state = RIL_CARDSTATE_PRESENT;
175                                         card_status->universal_pin_state = RIL_PINSTATE_ENABLED_NOT_VERIFIED;
176                                         app_index = 3;
177                                 } else if(at_strings_raw_compare("SIM PUK", data[i])) {
178                                         card_status->card_state = RIL_CARDSTATE_PRESENT;
179                                         card_status->universal_pin_state = RIL_PINSTATE_ENABLED_BLOCKED;
180                                         app_index = 4;
181                                 } else if(at_strings_raw_compare("READY", data[i])) {
182                                         card_status->card_state = RIL_CARDSTATE_PRESENT;
183                                         card_status->universal_pin_state = RIL_PINSTATE_UNKNOWN;
184                                         app_index = 2;
185                                 }
186                         }
187                 }
188         }
189
190         // Fallback
191         if(app_index == -1) {
192                 card_status->card_state = RIL_CARDSTATE_PRESENT;
193                 card_status->universal_pin_state = RIL_PINSTATE_UNKNOWN;
194                 app_index = 1;
195         }
196
197         // Initialize the apps
198         for (i = 0 ; i < app_status_array_length ; i++) {
199                 memcpy((void *) &(card_status->applications[i]), (void *) &(app_status_array[i]), sizeof(RIL_AppStatus));
200         }
201         for(i = app_status_array_length ; i < RIL_CARD_MAX_APPS ; i++) {
202                 memset((void *) &(card_status->applications[i]), 0, sizeof(RIL_AppStatus));
203         }
204
205         card_status->gsm_umts_subscription_app_index = app_index;
206         card_status->cdma_subscription_app_index = app_index;
207         card_status->num_applications = app_status_array_length;
208
209         LOGD("Selecting application #%d on %d", app_index, app_status_array_length);
210
211         return radio_state;
212 }
213
214 int at_cpin_expect(struct at_response *response, void *data, RIL_Token t)
215 {
216         RIL_CardStatus card_status;
217         RIL_RadioState radio_state;
218
219         if(response->status == AT_STATUS_UNDEF)
220                 return AT_RESPONSE_UNHANDELD_REASON_STATUS;
221
222         if(t != (RIL_Token) 0x0000) {
223                 radio_state = at2ril_card_status(&card_status, response->status, response->error, response->data, response->data_count);
224                 ril_globals.radio_state = radio_state;
225
226                 RIL_onRequestComplete(t, RIL_E_SUCCESS, &card_status, sizeof(card_status));
227         } else {
228                 radio_state = at2ril_sim_status(response->status, response->error, response->data, response->data_count);
229                 ril_globals.radio_state = radio_state;
230
231                 RIL_onUnsolicitedResponse(RIL_UNSOL_RESPONSE_RADIO_STATE_CHANGED, NULL, 0);
232         }
233
234         LOGD("Handled AT+CPIN response");
235
236         return AT_RESPONSE_HANDLED_OK;
237 }
238
239 int at_cpin_unlock_expect(struct at_response *response, void *data, RIL_Token t)
240 {
241         int tries = -1;
242         int code = 0;
243
244         if(response->status == AT_STATUS_UNDEF)
245                 return AT_RESPONSE_UNHANDELD_REASON_STATUS;
246
247         if(at_status_error(response->status)) {
248                 if(response->status == AT_STATUS_CME_ERROR && response->error != NULL) {
249                         code = atoi(response->error);
250
251                         if(code == AT_CME_ERROR_INCORRECT_PASSWORD)
252                                 RIL_onRequestComplete(t, RIL_E_PASSWORD_INCORRECT, &tries, sizeof(int *));
253                 } else {
254                         RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0);
255                 }
256         } else {
257                 RIL_onRequestComplete(t, RIL_E_SUCCESS, &tries, sizeof(int *));
258         }
259
260         // Update radio state
261         at_send_expect_to_func("AT+CPIN?", NULL, NULL, 0x0000, at_cpin_expect);
262
263         return AT_RESPONSE_HANDLED_OK;
264 }
265
266 void ril_request_get_sim_status(RIL_Token t, void *data, size_t length)
267 {
268         at_send_expect_to_func("AT+CPIN?", NULL, NULL, t, at_cpin_expect);
269 }
270
271 void ril_request_enter_sim_pin(RIL_Token t, void *data, size_t length)
272 {
273         char *pin = ((char **) data)[0];
274
275         at_send_expect_to_func("AT+CPIN", pin, NULL, t, at_cpin_unlock_expect);
276 }
277
278 int at_crsm_expect(struct at_response *response, void *data, RIL_Token t)
279 {
280         RIL_SIM_IO_Response sim_io_response;
281         struct at_response_data **response_data = NULL;
282         int response_data_count = 0;
283
284         if(response->status == AT_STATUS_UNDEF)
285                 return AT_RESPONSE_UNHANDELD_REASON_STATUS;
286
287         if(response->data == NULL || response->data_count <= 0) {
288                 LOGE("No data given to AT+CRSM response!");
289                 return AT_RESPONSE_HANDLED_ERROR;
290         }
291
292         LOGE("Caught valid AT+CRSM response!");
293
294         response_data_count = at_response_data_process(&response_data, response->data[0], strlen(response->data[0]));
295         if(response_data_count < 3)
296                 goto error_data;
297
298         memset(&sim_io_response, 0, sizeof(RIL_SIM_IO_Response));
299
300         if(response_data[0]->type != AT_RESPONSE_DATA_NUMERIC)
301                 goto error_data;
302         sim_io_response.sw1 = response_data[0]->value.n;
303
304         if(response_data[1]->type != AT_RESPONSE_DATA_NUMERIC)
305                 goto error_data;
306         sim_io_response.sw2 = response_data[1]->value.n;
307
308         if(response_data[2]->type != AT_RESPONSE_DATA_STRING)
309                 goto error_data;
310         sim_io_response.simResponse = response_data[2]->value.s;
311
312         RIL_onRequestComplete(t, RIL_E_SUCCESS, &sim_io_response, sizeof(RIL_SIM_IO_Response));
313
314         at_response_data_free(response_data, response_data_count);
315
316         return AT_RESPONSE_HANDLED_OK;
317
318 error_data:
319         LOGE("No valid data given to AT+CRSM response!");
320
321         at_response_data_free(response_data, response_data_count);
322         return AT_RESPONSE_HANDLED_ERROR;
323 }
324
325 void ril_request_sim_io(RIL_Token t, void *data, size_t length)
326 {
327         RIL_SIM_IO *sim_io_request = NULL;
328         char *sim_io_data;
329
330         if(data == NULL || length <= 0) {
331                 RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0);
332                 return;
333         }
334
335         sim_io_request = (RIL_SIM_IO *) data;
336
337         // TODO: add delay if SIM is slow (from device flags)
338
339         if(sim_io_request->data == NULL) {
340                 asprintf(&sim_io_data, "%d,%d,%d,%d,%d",
341                         sim_io_request->command, sim_io_request->fileid,
342                         sim_io_request->p1, sim_io_request->p2, sim_io_request->p3);
343         } else {
344                 asprintf(&sim_io_data, "%d,%d,%d,%d,%d,%s",
345                         sim_io_request->command, sim_io_request->fileid,
346                         sim_io_request->p1, sim_io_request->p2, sim_io_request->p3, sim_io_request->data);
347         }
348
349         at_send_expect_to_func("AT+CRSM", sim_io_data, NULL, t, at_crsm_expect);
350
351         free(sim_io_data);
352 }