2 * This file is part of hayes-ril.
4 * Copyright (C) 2012 Paul Kocialkowski <contact@paulk.fr>
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
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
14 * http://www.apache.org/licenses/LICENSE-2.0
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.
25 #define LOG_TAG "RIL-SIM"
26 #include <utils/Log.h>
27 #include <telephony/ril.h>
29 #include <hayes-ril.h>
31 RIL_RadioState at2ril_sim_status(int status, char *error, char **data, int data_count)
36 if(status == AT_STATUS_CME_ERROR && error != NULL) {
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:
56 return RADIO_STATE_SIM_NOT_READY;
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;
72 return RADIO_STATE_SIM_NOT_READY;
74 // Various error codes, not helping here, don't change anything
75 return ril_globals.radio_state;
80 RIL_RadioState at2ril_card_status(RIL_CardStatus *card_status, int status, char *error, char **data, int data_count)
82 RIL_RadioState radio_state;
85 int app_status_array_length = 0;
89 static RIL_AppStatus app_status_array[] = {
91 { RIL_APPTYPE_UNKNOWN, RIL_APPSTATE_UNKNOWN, RIL_PERSOSUBSTATE_UNKNOWN,
92 NULL, NULL, 0, RIL_PINSTATE_UNKNOWN, RIL_PINSTATE_UNKNOWN },
94 { RIL_APPTYPE_SIM, RIL_APPSTATE_DETECTED, RIL_PERSOSUBSTATE_UNKNOWN,
95 NULL, NULL, 0, RIL_PINSTATE_UNKNOWN, RIL_PINSTATE_UNKNOWN },
97 { RIL_APPTYPE_SIM, RIL_APPSTATE_READY, RIL_PERSOSUBSTATE_READY,
98 NULL, NULL, 0, RIL_PINSTATE_UNKNOWN, RIL_PINSTATE_UNKNOWN },
100 { RIL_APPTYPE_SIM, RIL_APPSTATE_PIN, RIL_PERSOSUBSTATE_UNKNOWN,
101 NULL, NULL, 0, RIL_PINSTATE_ENABLED_NOT_VERIFIED, RIL_PINSTATE_UNKNOWN },
103 { RIL_APPTYPE_SIM, RIL_APPSTATE_PUK, RIL_PERSOSUBSTATE_UNKNOWN,
104 NULL, NULL, 0, RIL_PINSTATE_ENABLED_BLOCKED, RIL_PINSTATE_UNKNOWN },
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 },
122 app_status_array_length = sizeof(app_status_array) / sizeof(RIL_AppStatus);
124 if(app_status_array_length > RIL_CARD_MAX_APPS)
125 app_status_array_length = RIL_CARD_MAX_APPS;
127 radio_state = at2ril_sim_status(status, error, data, data_count);
129 if(status == AT_STATUS_CME_ERROR && error != NULL) {
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;
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;
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;
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;
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:
165 card_status->card_state = RIL_CARDSTATE_PRESENT;
166 card_status->universal_pin_state = RIL_PINSTATE_UNKNOWN;
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;
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;
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;
191 if(app_index == -1) {
192 card_status->card_state = RIL_CARDSTATE_PRESENT;
193 card_status->universal_pin_state = RIL_PINSTATE_UNKNOWN;
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));
201 for(i = app_status_array_length ; i < RIL_CARD_MAX_APPS ; i++) {
202 memset((void *) &(card_status->applications[i]), 0, sizeof(RIL_AppStatus));
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;
209 LOGD("Selecting application #%d on %d", app_index, app_status_array_length);
214 int at_cpin_expect(struct at_response *response, void *data, RIL_Token t)
216 RIL_CardStatus card_status;
217 RIL_RadioState radio_state;
219 if(response->status == AT_STATUS_UNDEF)
220 return AT_RESPONSE_UNHANDELD_REASON_STATUS;
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;
226 RIL_onRequestComplete(t, RIL_E_SUCCESS, &card_status, sizeof(card_status));
228 radio_state = at2ril_sim_status(response->status, response->error, response->data, response->data_count);
229 ril_globals.radio_state = radio_state;
231 RIL_onUnsolicitedResponse(RIL_UNSOL_RESPONSE_RADIO_STATE_CHANGED, NULL, 0);
234 LOGD("Handled AT+CPIN response");
236 return AT_RESPONSE_HANDLED_OK;
239 int at_cpin_unlock_expect(struct at_response *response, void *data, RIL_Token t)
244 if(response->status == AT_STATUS_UNDEF)
245 return AT_RESPONSE_UNHANDELD_REASON_STATUS;
247 if(at_status_error(response->status)) {
248 if(response->status == AT_STATUS_CME_ERROR && response->error != NULL) {
249 code = atoi(response->error);
251 if(code == AT_CME_ERROR_INCORRECT_PASSWORD)
252 RIL_onRequestComplete(t, RIL_E_PASSWORD_INCORRECT, &tries, sizeof(int *));
254 RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0);
257 RIL_onRequestComplete(t, RIL_E_SUCCESS, &tries, sizeof(int *));
260 // Update radio state
261 at_send_expect_to_func("AT+CPIN?", NULL, NULL, 0x0000, at_cpin_expect);
263 return AT_RESPONSE_HANDLED_OK;
266 void ril_request_get_sim_status(RIL_Token t, void *data, size_t length)
268 at_send_expect_to_func("AT+CPIN?", NULL, NULL, t, at_cpin_expect);
271 void ril_request_enter_sim_pin(RIL_Token t, void *data, size_t length)
273 char *pin = ((char **) data)[0];
275 at_send_expect_to_func("AT+CPIN", pin, NULL, t, at_cpin_unlock_expect);
278 int at_crsm_expect(struct at_response *response, void *data, RIL_Token t)
280 RIL_SIM_IO_Response sim_io_response;
281 struct at_response_data **response_data = NULL;
282 int response_data_count = 0;
284 if(response->status == AT_STATUS_UNDEF)
285 return AT_RESPONSE_UNHANDELD_REASON_STATUS;
287 if(response->data == NULL || response->data_count <= 0) {
288 LOGE("No data given to AT+CRSM response!");
289 return AT_RESPONSE_HANDLED_ERROR;
292 LOGE("Caught valid +CRSM response!");
294 response_data_count = at_response_data_process(&response_data, response->data[0], strlen(response->data[0]));
295 if(response_data_count < 3)
298 memset(&sim_io_response, 0, sizeof(RIL_SIM_IO_Response));
300 if(response_data[0]->type != AT_RESPONSE_DATA_NUMERIC)
302 sim_io_response.sw1 = response_data[0]->value.n;
304 if(response_data[1]->type != AT_RESPONSE_DATA_NUMERIC)
306 sim_io_response.sw2 = response_data[1]->value.n;
308 if(response_data[2]->type != AT_RESPONSE_DATA_STRING)
310 sim_io_response.simResponse = response_data[2]->value.s;
312 RIL_onRequestComplete(t, RIL_E_SUCCESS, &sim_io_response, sizeof(RIL_SIM_IO_Response));
314 at_response_data_free(response_data, response_data_count);
316 return AT_RESPONSE_HANDLED_OK;
319 LOGE("No valid data fiven to AT+CRSM response!");
321 at_response_data_free(response_data, response_data_count);
322 return AT_RESPONSE_HANDLED_ERROR;
325 void ril_request_sim_io(RIL_Token t, void *data, size_t length)
327 RIL_SIM_IO *sim_io_request = NULL;
330 if(data == NULL || length <= 0) {
331 RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0);
335 sim_io_request = (RIL_SIM_IO *) data;
337 // TODO: add delay if SIM is slow (from device flags)
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);
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);
349 at_send_expect_to_func("AT+CRSM", sim_io_data, NULL, t, at_crsm_expect);