SIM: Completed SIM status handling
[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                                 return RADIO_STATE_SIM_LOCKED_OR_ABSENT;
50                         case AT_CME_ERROR_SIM_FAILURE:
51                         case AT_CME_ERROR_SIM_BUSY:
52                         case AT_CME_ERROR_SIM_WRONG:
53                         case AT_CME_ERROR_SIM_POWERED_DOWN:
54                         default:
55                                 return RADIO_STATE_SIM_NOT_READY;
56                 }
57         } else if(status == AT_STATUS_OK) {
58                 if(data != NULL && data_count > 0) {
59                         for(i=0 ; i < data_count ; i++) {
60                                 if(at_strings_raw_compare("SIM PIN", data[i])) {
61                                         return RADIO_STATE_SIM_LOCKED_OR_ABSENT;
62                                 } else if(at_strings_raw_compare("SIM PUK", data[i])) {
63                                         return RADIO_STATE_SIM_LOCKED_OR_ABSENT;
64                                 } else if(at_strings_raw_compare("READY", data[i])) {
65                                         return RADIO_STATE_SIM_READY;
66                                 }
67                         }
68                 }
69
70                 // Fallback
71                 return RADIO_STATE_SIM_NOT_READY;
72         } else {
73                 // Various error codes, not helping here, don't change anything
74                 return ril_globals.radio_state;
75         }
76
77 }
78
79 RIL_RadioState at2ril_card_status(RIL_CardStatus *card_status, int status, char *error, char **data, int data_count)
80 {
81         RIL_RadioState radio_state;
82         int code = 0;
83
84         int app_status_array_length = 0;
85         int app_index = -1;
86         int i;
87
88         static RIL_AppStatus app_status_array[] = {
89                 // SIM_ABSENT = 0
90                 { RIL_APPTYPE_UNKNOWN, RIL_APPSTATE_UNKNOWN, RIL_PERSOSUBSTATE_UNKNOWN,
91                 NULL, NULL, 0, RIL_PINSTATE_UNKNOWN, RIL_PINSTATE_UNKNOWN },
92                 // SIM_NOT_READY = 1
93                 { RIL_APPTYPE_SIM, RIL_APPSTATE_DETECTED, RIL_PERSOSUBSTATE_UNKNOWN,
94                 NULL, NULL, 0, RIL_PINSTATE_UNKNOWN, RIL_PINSTATE_UNKNOWN },
95                 // SIM_READY = 2
96                 { RIL_APPTYPE_SIM, RIL_APPSTATE_READY, RIL_PERSOSUBSTATE_READY,
97                 NULL, NULL, 0, RIL_PINSTATE_UNKNOWN, RIL_PINSTATE_UNKNOWN },
98                 // SIM_PIN = 3
99                 { RIL_APPTYPE_SIM, RIL_APPSTATE_PIN, RIL_PERSOSUBSTATE_UNKNOWN,
100                 NULL, NULL, 0, RIL_PINSTATE_ENABLED_NOT_VERIFIED, RIL_PINSTATE_UNKNOWN },
101                 // SIM_PUK = 4
102                 { RIL_APPTYPE_SIM, RIL_APPSTATE_PUK, RIL_PERSOSUBSTATE_UNKNOWN,
103                 NULL, NULL, 0, RIL_PINSTATE_ENABLED_BLOCKED, RIL_PINSTATE_UNKNOWN },
104                 // SIM_BLOCKED = 5
105                 { RIL_APPTYPE_SIM, RIL_APPSTATE_PUK, RIL_PERSOSUBSTATE_UNKNOWN,
106                 NULL, NULL, 0, RIL_PINSTATE_ENABLED_PERM_BLOCKED, RIL_PINSTATE_UNKNOWN },
107                 // SIM_NETWORK_PERSO = 6
108                 { RIL_APPTYPE_SIM, RIL_APPSTATE_SUBSCRIPTION_PERSO, RIL_PERSOSUBSTATE_SIM_NETWORK,
109                 NULL, NULL, 0, RIL_PINSTATE_ENABLED_NOT_VERIFIED, RIL_PINSTATE_UNKNOWN },
110                 // SIM_NETWORK_SUBSET_PERSO = 7
111                 { RIL_APPTYPE_SIM, RIL_APPSTATE_SUBSCRIPTION_PERSO, RIL_PERSOSUBSTATE_SIM_NETWORK_SUBSET,
112                 NULL, NULL, 0, RIL_PINSTATE_ENABLED_NOT_VERIFIED, RIL_PINSTATE_UNKNOWN },
113                 // SIM_CORPORATE_PERSO = 8
114                 { RIL_APPTYPE_SIM, RIL_APPSTATE_SUBSCRIPTION_PERSO, RIL_PERSOSUBSTATE_SIM_CORPORATE,
115                 NULL, NULL, 0, RIL_PINSTATE_ENABLED_NOT_VERIFIED, RIL_PINSTATE_UNKNOWN },
116                 // SIM_SERVICE_PROVIDER_PERSO = 9
117                 { RIL_APPTYPE_SIM, RIL_APPSTATE_SUBSCRIPTION_PERSO, RIL_PERSOSUBSTATE_SIM_SERVICE_PROVIDER,
118                 NULL, NULL, 0, RIL_PINSTATE_ENABLED_NOT_VERIFIED, RIL_PINSTATE_UNKNOWN },
119         };
120
121         app_status_array_length = sizeof(app_status_array) / sizeof(RIL_AppStatus);
122
123         if(app_status_array_length > RIL_CARD_MAX_APPS)
124                 app_status_array_length = RIL_CARD_MAX_APPS;
125
126         radio_state = at2ril_sim_status(status, error, data, data_count);
127
128         if(status == AT_STATUS_CME_ERROR && error != NULL) {
129                 code = atoi(error);
130
131                 switch(code) {
132                         case AT_CME_ERROR_SIM_NOT_INSERTED:
133                                 card_status->card_state = RIL_CARDSTATE_ABSENT;
134                                 card_status->universal_pin_state = RIL_PINSTATE_UNKNOWN;
135                                 app_index = 0;
136                                 break;
137                         case AT_CME_ERROR_PH_SIM_PIN_REQD:
138                         case AT_CME_ERROR_PH_FSIM_PIN_REQD:
139                         case AT_CME_ERROR_SIM_PIN_REQD:
140                                 card_status->card_state = RIL_CARDSTATE_PRESENT;
141                                 card_status->universal_pin_state = RIL_PINSTATE_ENABLED_NOT_VERIFIED;
142                                 app_index = 3;
143                                 break;
144                         case AT_CME_ERROR_PH_SIM_PUK_REQD:
145                         case AT_CME_ERROR_PH_FSIM_PUK_REQD:
146                         case AT_CME_ERROR_SIM_PUK_REQD:
147                                 card_status->card_state = RIL_CARDSTATE_PRESENT;
148                                 card_status->universal_pin_state = RIL_PINSTATE_ENABLED_BLOCKED;
149                                 app_index = 4;
150                                 break;
151                         case AT_CME_ERROR_SIM_PIN2_REQD:
152                         case AT_CME_ERROR_SIM_PUK2_REQD:
153                         case AT_CME_ERROR_SIM_BLOCKED:
154                                 card_status->card_state = RIL_CARDSTATE_PRESENT;
155                                 card_status->universal_pin_state = RIL_PINSTATE_ENABLED_PERM_BLOCKED;
156                                 app_index = 5;
157                                 break;
158                         case AT_CME_ERROR_SIM_FAILURE:
159                         case AT_CME_ERROR_SIM_BUSY:
160                         case AT_CME_ERROR_SIM_WRONG:
161                         case AT_CME_ERROR_SIM_POWERED_DOWN:
162                         default:
163                                 card_status->card_state = RIL_CARDSTATE_PRESENT;
164                                 card_status->universal_pin_state = RIL_PINSTATE_UNKNOWN;
165                                 app_index = 1;
166                                 break;
167                 }
168         } else if(status == AT_STATUS_OK) {
169                 if(data != NULL && data_count > 0) {
170                         for(i=0 ; i < data_count ; i++) {
171                                 if(at_strings_raw_compare("SIM PIN", data[i])) {
172                                         card_status->card_state = RIL_CARDSTATE_PRESENT;
173                                         card_status->universal_pin_state = RIL_PINSTATE_ENABLED_NOT_VERIFIED;
174                                         app_index = 3;
175                                 } else if(at_strings_raw_compare("SIM PUK", data[i])) {
176                                         card_status->card_state = RIL_CARDSTATE_PRESENT;
177                                         card_status->universal_pin_state = RIL_PINSTATE_ENABLED_BLOCKED;
178                                         app_index = 4;
179                                 } else if(at_strings_raw_compare("READY", data[i])) {
180                                         card_status->card_state = RIL_CARDSTATE_PRESENT;
181                                         card_status->universal_pin_state = RIL_PINSTATE_UNKNOWN;
182                                         app_index = 2;
183                                 }
184                         }
185                 }
186         }
187
188         // Fallback
189         if(app_index == -1) {
190                 card_status->card_state = RIL_CARDSTATE_PRESENT;
191                 card_status->universal_pin_state = RIL_PINSTATE_UNKNOWN;
192                 app_index = 1;
193         }
194
195         // Initialize the apps
196         for (i = 0 ; i < app_status_array_length ; i++) {
197                 memcpy((void *) &(card_status->applications[i]), (void *) &(app_status_array[i]), sizeof(RIL_AppStatus));
198         }
199         for(i = app_status_array_length ; i < RIL_CARD_MAX_APPS ; i++) {
200                 memset((void *) &(card_status->applications[i]), 0, sizeof(RIL_AppStatus));
201         }
202
203         card_status->gsm_umts_subscription_app_index = app_index;
204         card_status->cdma_subscription_app_index = app_index;
205         card_status->num_applications = app_status_array_length;
206
207         LOGD("Selecting application #%d on %d", app_index, app_status_array_length);
208
209         return radio_state;
210 }
211
212 int at_cpin_expect(struct at_response *response, void *data, RIL_Token t)
213 {
214         RIL_CardStatus card_status;
215         RIL_RadioState radio_state;
216
217         if(response->status == AT_STATUS_UNDEF)
218                 return AT_RESPONSE_UNHANDELD_REASON_STATUS;
219
220         if(t != (RIL_Token) 0x0000) {
221                 radio_state = at2ril_card_status(&card_status, response->status, response->error, response->data, response->data_count);
222                 ril_globals.radio_state = radio_state;
223
224                 RIL_onRequestComplete(t, RIL_E_SUCCESS, &card_status, sizeof(card_status));
225         } else {
226                 radio_state = at2ril_sim_status(response->status, response->error, response->data, response->data_count);
227                 if(ril_globals.radio_state != radio_state) {
228                         ril_globals.radio_state = radio_state;
229                         RIL_onUnsolicitedResponse(RIL_UNSOL_RESPONSE_RADIO_STATE_CHANGED, NULL, 0);
230                 }
231         }
232
233         LOGD("Handled AT+CPIN response");
234
235         return AT_RESPONSE_HANDLED_OK;
236 }
237
238 void ril_request_get_sim_status(RIL_Token t, void *data, size_t length)
239 {
240         at_send_expect_to_func("AT+CPIN?", NULL, NULL, t, at_cpin_expect);
241 }