3 * oFono - Open Source Telephony
5 * Copyright (C) 2008-2011 Intel Corporation. All rights reserved.
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License version 2 as
9 * published by the Free Software Foundation.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
34 #include <ofono/log.h>
35 #include <ofono/modem.h>
36 #include <ofono/sim.h>
39 #include "gatresult.h"
45 #define EF_STATUS_INVALIDATED 0
46 #define EF_STATUS_VALID 1
48 #define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
54 struct at_util_sim_state_query *sim_state_query;
57 static const char *crsm_prefix[] = { "+CRSM:", NULL };
58 static const char *cpin_prefix[] = { "+CPIN:", NULL };
59 static const char *clck_prefix[] = { "+CLCK:", NULL };
60 static const char *huawei_cpin_prefix[] = { "^CPIN:", NULL };
61 static const char *xpincnt_prefix[] = { "+XPINCNT:", NULL };
62 static const char *zpinpuk_prefix[] = { "+ZPINPUK:", NULL };
63 static const char *pinnum_prefix[] = { "%PINNUM:", NULL };
64 static const char *oercn_prefix[] = { "_OERCN:", NULL };
65 static const char *cpinr_prefixes[] = { "+CPINR:", "+CPINRE:", NULL };
66 static const char *epin_prefix[] = { "*EPIN:", NULL };
67 static const char *spic_prefix[] = { "+SPIC:", NULL };
68 static const char *none_prefix[] = { NULL };
70 static void at_crsm_info_cb(gboolean ok, GAtResult *result, gpointer user_data)
72 struct cb_data *cbd = user_data;
74 ofono_sim_file_info_cb_t cb = cbd->cb;
75 struct ofono_error error;
76 const guint8 *response;
80 unsigned char access[3];
81 unsigned char file_status;
83 decode_at_error(&error, g_at_result_final_response(result));
86 cb(&error, -1, -1, -1, NULL, EF_STATUS_INVALIDATED, cbd->data);
90 g_at_result_iter_init(&iter, result);
92 if (!g_at_result_iter_next(&iter, "+CRSM:"))
95 g_at_result_iter_next_number(&iter, &sw1);
96 g_at_result_iter_next_number(&iter, &sw2);
98 if (!g_at_result_iter_next_hexstring(&iter, &response, &len) ||
99 (sw1 != 0x90 && sw1 != 0x91 && sw1 != 0x92) ||
100 (sw1 == 0x90 && sw2 != 0x00)) {
101 memset(&error, 0, sizeof(error));
103 error.type = OFONO_ERROR_TYPE_SIM;
104 error.error = (sw1 << 8) | sw2;
106 cb(&error, -1, -1, -1, NULL, EF_STATUS_INVALIDATED, cbd->data);
110 DBG("crsm_info_cb: %02x, %02x, %i", sw1, sw2, len);
112 if (response[0] == 0x62) {
113 ok = sim_parse_3g_get_response(response, len, &flen, &rlen,
116 file_status = EF_STATUS_VALID;
118 ok = sim_parse_2g_get_response(response, len, &flen, &rlen,
119 &str, access, &file_status);
124 cb(&error, flen, str, rlen, access, file_status, cbd->data);
129 CALLBACK_WITH_FAILURE(cb, -1, -1, -1, NULL,
130 EF_STATUS_INVALIDATED, cbd->data);
133 static void at_sim_read_info(struct ofono_sim *sim, int fileid,
134 ofono_sim_file_info_cb_t cb,
137 struct sim_data *sd = ofono_sim_get_data(sim);
141 if (sd->vendor == OFONO_VENDOR_OPTION_HSO) {
142 unsigned char access[3] = { 0x00, 0x00, 0x00 };
144 if (fileid == SIM_EFAD_FILEID) {
145 CALLBACK_WITH_SUCCESS(cb, 4, 0, 0, access,
146 EF_STATUS_VALID, data);
151 cbd = cb_data_new(cb, data);
153 snprintf(buf, sizeof(buf), "AT+CRSM=192,%i", fileid);
155 switch (sd->vendor) {
156 case OFONO_VENDOR_ZTE:
157 case OFONO_VENDOR_HUAWEI:
158 case OFONO_VENDOR_SIERRA:
159 case OFONO_VENDOR_SPEEDUP:
160 case OFONO_VENDOR_QUALCOMM_MSM:
161 strcat(buf, ",0,0,255"); /* Maximum possible length */
165 if (g_at_chat_send(sd->chat, buf, crsm_prefix,
166 at_crsm_info_cb, cbd, g_free) > 0)
171 CALLBACK_WITH_FAILURE(cb, -1, -1, -1, NULL,
172 EF_STATUS_INVALIDATED, data);
175 static void at_crsm_read_cb(gboolean ok, GAtResult *result,
178 struct cb_data *cbd = user_data;
180 ofono_sim_read_cb_t cb = cbd->cb;
181 struct ofono_error error;
182 const guint8 *response;
185 decode_at_error(&error, g_at_result_final_response(result));
188 cb(&error, NULL, 0, cbd->data);
192 g_at_result_iter_init(&iter, result);
194 if (!g_at_result_iter_next(&iter, "+CRSM:")) {
195 CALLBACK_WITH_FAILURE(cb, NULL, 0, cbd->data);
199 g_at_result_iter_next_number(&iter, &sw1);
200 g_at_result_iter_next_number(&iter, &sw2);
202 if ((sw1 != 0x90 && sw1 != 0x91 && sw1 != 0x92 && sw1 != 0x9f) ||
203 (sw1 == 0x90 && sw2 != 0x00)) {
204 memset(&error, 0, sizeof(error));
206 error.type = OFONO_ERROR_TYPE_SIM;
207 error.error = (sw1 << 8) | sw2;
209 cb(&error, NULL, 0, cbd->data);
213 if (!g_at_result_iter_next_hexstring(&iter, &response, &len)) {
214 CALLBACK_WITH_FAILURE(cb, NULL, 0, cbd->data);
218 DBG("crsm_read_cb: %02x, %02x, %d", sw1, sw2, len);
220 cb(&error, response, len, cbd->data);
223 static void at_sim_read_binary(struct ofono_sim *sim, int fileid,
224 int start, int length,
225 ofono_sim_read_cb_t cb, void *data)
227 struct sim_data *sd = ofono_sim_get_data(sim);
228 struct cb_data *cbd = cb_data_new(cb, data);
231 snprintf(buf, sizeof(buf), "AT+CRSM=176,%i,%i,%i,%i", fileid,
232 start >> 8, start & 0xff, length);
234 if (g_at_chat_send(sd->chat, buf, crsm_prefix,
235 at_crsm_read_cb, cbd, g_free) > 0)
240 CALLBACK_WITH_FAILURE(cb, NULL, 0, data);
243 static void at_sim_read_record(struct ofono_sim *sim, int fileid,
244 int record, int length,
245 ofono_sim_read_cb_t cb, void *data)
247 struct sim_data *sd = ofono_sim_get_data(sim);
248 struct cb_data *cbd = cb_data_new(cb, data);
251 snprintf(buf, sizeof(buf), "AT+CRSM=178,%i,%i,4,%i", fileid,
254 if (g_at_chat_send(sd->chat, buf, crsm_prefix,
255 at_crsm_read_cb, cbd, g_free) > 0)
260 CALLBACK_WITH_FAILURE(cb, NULL, 0, data);
263 static void at_crsm_update_cb(gboolean ok, GAtResult *result,
266 struct cb_data *cbd = user_data;
268 ofono_sim_write_cb_t cb = cbd->cb;
269 struct ofono_error error;
272 decode_at_error(&error, g_at_result_final_response(result));
275 cb(&error, cbd->data);
279 g_at_result_iter_init(&iter, result);
281 if (!g_at_result_iter_next(&iter, "+CRSM:")) {
282 CALLBACK_WITH_FAILURE(cb, cbd->data);
286 g_at_result_iter_next_number(&iter, &sw1);
287 g_at_result_iter_next_number(&iter, &sw2);
289 if ((sw1 != 0x90 && sw1 != 0x91 && sw1 != 0x92 && sw1 != 0x9f) ||
290 (sw1 == 0x90 && sw2 != 0x00)) {
291 memset(&error, 0, sizeof(error));
293 error.type = OFONO_ERROR_TYPE_SIM;
294 error.error = (sw1 << 8) | sw2;
297 DBG("crsm_update_cb: %02x, %02x", sw1, sw2);
299 cb(&error, cbd->data);
302 static void at_sim_update_file(struct ofono_sim *sim, int cmd, int fileid,
303 int p1, int p2, int p3,
304 const unsigned char *value,
305 ofono_sim_write_cb_t cb, void *data)
307 struct sim_data *sd = ofono_sim_get_data(sim);
308 struct cb_data *cbd = cb_data_new(cb, data);
310 gboolean quote = FALSE;
312 int size = 36 + p3 * 2;
317 switch (sd->vendor) {
318 case OFONO_VENDOR_MBM:
319 case OFONO_VENDOR_ZTE:
320 case OFONO_VENDOR_HUAWEI:
321 case OFONO_VENDOR_SPEEDUP:
327 buf = g_try_new(char, size);
331 len = sprintf(buf, "AT+CRSM=%i,%i,%i,%i,%i,", cmd, fileid,p1, p2, p3);
337 len += sprintf(buf + len, "%02hhX", *value++);
342 ret = g_at_chat_send(sd->chat, buf, crsm_prefix,
343 at_crsm_update_cb, cbd, g_free);
353 CALLBACK_WITH_FAILURE(cb, data);
356 static void at_sim_update_binary(struct ofono_sim *sim, int fileid,
357 int start, int length,
358 const unsigned char *value,
359 ofono_sim_write_cb_t cb, void *data)
361 at_sim_update_file(sim, 214, fileid, start >> 8, start & 0xff,
362 length, value, cb, data);
365 static void at_sim_update_record(struct ofono_sim *sim, int fileid,
366 int record, int length,
367 const unsigned char *value,
368 ofono_sim_write_cb_t cb, void *data)
370 at_sim_update_file(sim, 220, fileid, record, 4, length,
374 static void at_sim_update_cyclic(struct ofono_sim *sim, int fileid,
375 int length, const unsigned char *value,
376 ofono_sim_write_cb_t cb, void *data)
378 at_sim_update_file(sim, 220, fileid, 0, 3, length, value, cb, data);
381 static void at_cimi_cb(gboolean ok, GAtResult *result, gpointer user_data)
383 struct cb_data *cbd = user_data;
385 ofono_sim_imsi_cb_t cb = cbd->cb;
386 struct ofono_error error;
390 decode_at_error(&error, g_at_result_final_response(result));
393 cb(&error, NULL, cbd->data);
397 g_at_result_iter_init(&iter, result);
399 for (i = 0; i < g_at_result_num_response_lines(result); i++)
400 g_at_result_iter_next(&iter, NULL);
402 imsi = g_at_result_iter_raw_line(&iter);
404 DBG("cimi_cb: %s", imsi);
406 cb(&error, imsi, cbd->data);
409 static void at_read_imsi(struct ofono_sim *sim, ofono_sim_imsi_cb_t cb,
412 struct sim_data *sd = ofono_sim_get_data(sim);
413 struct cb_data *cbd = cb_data_new(cb, data);
415 if (g_at_chat_send(sd->chat, "AT+CIMI", NULL,
416 at_cimi_cb, cbd, g_free) > 0)
421 CALLBACK_WITH_FAILURE(cb, NULL, data);
425 enum ofono_sim_password_type type;
427 } const at_sim_name[] = {
428 { OFONO_SIM_PASSWORD_NONE, "READY" },
429 { OFONO_SIM_PASSWORD_SIM_PIN, "SIM PIN" },
430 { OFONO_SIM_PASSWORD_SIM_PUK, "SIM PUK" },
431 { OFONO_SIM_PASSWORD_PHSIM_PIN, "PH-SIM PIN" },
432 { OFONO_SIM_PASSWORD_PHFSIM_PIN, "PH-FSIM PIN" },
433 { OFONO_SIM_PASSWORD_PHFSIM_PUK, "PH-FSIM PUK" },
434 { OFONO_SIM_PASSWORD_SIM_PIN2, "SIM PIN2" },
435 { OFONO_SIM_PASSWORD_SIM_PUK2, "SIM PUK2" },
436 { OFONO_SIM_PASSWORD_PHNET_PIN, "PH-NET PIN" },
437 { OFONO_SIM_PASSWORD_PHNET_PUK, "PH-NET PUK" },
438 { OFONO_SIM_PASSWORD_PHNETSUB_PIN, "PH-NETSUB PIN" },
439 { OFONO_SIM_PASSWORD_PHNETSUB_PUK, "PH-NETSUB PUK" },
440 { OFONO_SIM_PASSWORD_PHSP_PIN, "PH-SP PIN" },
441 { OFONO_SIM_PASSWORD_PHSP_PUK, "PH-SP PUK" },
442 { OFONO_SIM_PASSWORD_PHCORP_PIN, "PH-CORP PIN" },
443 { OFONO_SIM_PASSWORD_PHCORP_PUK, "PH-CORP PUK" },
446 #define BUILD_PIN_RETRIES_ARRAY(passwd_types, passwd_types_cnt, retry) \
447 for (i = 0; i < OFONO_SIM_PASSWORD_INVALID; i++) \
450 for (i = 0; i < passwd_types_cnt; i++) { \
453 if (!g_at_result_iter_next_number(&iter, &val)) \
456 retry[passwd_types[i]] = val; \
458 DBG("retry counter id=%d, val=%d", passwd_types[i], \
459 retry[passwd_types[i]]); \
462 static void huawei_cpin_cb(gboolean ok, GAtResult *result, gpointer user_data)
464 struct cb_data *cbd = user_data;
465 ofono_sim_pin_retries_cb_t cb = cbd->cb;
466 const char *final = g_at_result_final_response(result);
468 struct ofono_error error;
469 int retries[OFONO_SIM_PASSWORD_INVALID];
471 static enum ofono_sim_password_type password_types[] = {
472 OFONO_SIM_PASSWORD_SIM_PUK,
473 OFONO_SIM_PASSWORD_SIM_PIN,
474 OFONO_SIM_PASSWORD_SIM_PUK2,
475 OFONO_SIM_PASSWORD_SIM_PIN2,
478 decode_at_error(&error, final);
481 cb(&error, NULL, cbd->data);
485 g_at_result_iter_init(&iter, result);
487 if (!g_at_result_iter_next(&iter, "^CPIN:"))
490 /* Skip status since we are not interested in this */
491 if (!g_at_result_iter_skip_next(&iter))
494 /* Skip "overall counter" since we'll grab each one individually */
495 if (!g_at_result_iter_skip_next(&iter))
498 BUILD_PIN_RETRIES_ARRAY(password_types, ARRAY_SIZE(password_types),
501 cb(&error, retries, cbd->data);
506 CALLBACK_WITH_FAILURE(cb, NULL, cbd->data);
509 static void pinnum_cb(gboolean ok, GAtResult *result, gpointer user_data)
511 struct cb_data *cbd = user_data;
512 ofono_sim_pin_retries_cb_t cb = cbd->cb;
513 const char *final = g_at_result_final_response(result);
515 struct ofono_error error;
516 int retries[OFONO_SIM_PASSWORD_INVALID];
518 static enum ofono_sim_password_type password_types[] = {
519 OFONO_SIM_PASSWORD_SIM_PIN,
520 OFONO_SIM_PASSWORD_SIM_PUK,
521 OFONO_SIM_PASSWORD_SIM_PIN2,
522 OFONO_SIM_PASSWORD_SIM_PUK2,
526 decode_at_error(&error, final);
529 cb(&error, NULL, cbd->data);
533 g_at_result_iter_init(&iter, result);
535 if (!g_at_result_iter_next(&iter, "%PINNUM:"))
538 BUILD_PIN_RETRIES_ARRAY(password_types, ARRAY_SIZE(password_types),
541 cb(&error, retries, cbd->data);
546 CALLBACK_WITH_FAILURE(cb, NULL, cbd->data);
549 static void zpinpuk_cb(gboolean ok, GAtResult *result, gpointer user_data)
551 struct cb_data *cbd = user_data;
552 ofono_sim_pin_retries_cb_t cb = cbd->cb;
553 const char *final = g_at_result_final_response(result);
555 struct ofono_error error;
556 int retries[OFONO_SIM_PASSWORD_INVALID];
558 static enum ofono_sim_password_type password_types[] = {
559 OFONO_SIM_PASSWORD_SIM_PIN,
560 OFONO_SIM_PASSWORD_SIM_PUK,
564 decode_at_error(&error, final);
567 cb(&error, NULL, cbd->data);
571 g_at_result_iter_init(&iter, result);
573 if (!g_at_result_iter_next(&iter, "+ZPINPUK:"))
576 BUILD_PIN_RETRIES_ARRAY(password_types, ARRAY_SIZE(password_types),
579 cb(&error, retries, cbd->data);
584 CALLBACK_WITH_FAILURE(cb, NULL, cbd->data);
587 static void xpincnt_cb(gboolean ok, GAtResult *result, gpointer user_data)
589 struct cb_data *cbd = user_data;
590 ofono_sim_pin_retries_cb_t cb = cbd->cb;
591 const char *final = g_at_result_final_response(result);
593 struct ofono_error error;
594 int retries[OFONO_SIM_PASSWORD_INVALID];
596 static enum ofono_sim_password_type password_types[] = {
597 OFONO_SIM_PASSWORD_SIM_PIN,
598 OFONO_SIM_PASSWORD_SIM_PIN2,
599 OFONO_SIM_PASSWORD_SIM_PUK,
600 OFONO_SIM_PASSWORD_SIM_PUK2,
603 decode_at_error(&error, final);
606 cb(&error, NULL, cbd->data);
610 g_at_result_iter_init(&iter, result);
612 if (!g_at_result_iter_next(&iter, "+XPINCNT:"))
615 BUILD_PIN_RETRIES_ARRAY(password_types, ARRAY_SIZE(password_types),
618 cb(&error, retries, cbd->data);
623 CALLBACK_WITH_FAILURE(cb, NULL, cbd->data);
626 static void oercn_cb(gboolean ok, GAtResult *result, gpointer user_data)
628 struct cb_data *cbd = user_data;
629 ofono_sim_pin_retries_cb_t cb = cbd->cb;
630 const char *final = g_at_result_final_response(result);
632 struct ofono_error error;
633 int retries[OFONO_SIM_PASSWORD_INVALID];
635 static enum ofono_sim_password_type password_types[] = {
636 OFONO_SIM_PASSWORD_SIM_PIN,
637 OFONO_SIM_PASSWORD_SIM_PUK,
640 decode_at_error(&error, final);
643 cb(&error, NULL, cbd->data);
647 g_at_result_iter_init(&iter, result);
649 if (!g_at_result_iter_next(&iter, "_OERCN:"))
652 BUILD_PIN_RETRIES_ARRAY(password_types, ARRAY_SIZE(password_types),
655 cb(&error, retries, cbd->data);
660 CALLBACK_WITH_FAILURE(cb, NULL, cbd->data);
663 static void cpnnum_cb(gboolean ok, GAtResult *result, gpointer user_data)
665 struct cb_data *cbd = user_data;
666 ofono_sim_pin_retries_cb_t cb = cbd->cb;
667 const char *final = g_at_result_final_response(result);
669 struct ofono_error error;
673 int retries[OFONO_SIM_PASSWORD_INVALID];
676 decode_at_error(&error, final);
679 cb(&error, NULL, cbd->data);
683 g_at_result_iter_init(&iter, result);
685 for (num = 0; num < g_at_result_num_response_lines(result); num++)
686 g_at_result_iter_next(&iter, NULL);
688 line = g_at_result_iter_raw_line(&iter);
692 for (i = 0; i < OFONO_SIM_PASSWORD_INVALID; i++)
695 entries = g_strsplit(line, "; ", -1);
697 for (num = 0; entries[num]; num++) {
700 if (strlen(entries[num]) < 5)
703 retry = strtol(entries[num] + 5, NULL, 10);
704 if (retry == 0 && errno == EINVAL)
707 if (g_str_has_prefix(entries[num], "PIN1=") == TRUE)
708 retries[OFONO_SIM_PASSWORD_SIM_PIN] = retry;
709 else if (g_str_has_prefix(entries[num], "PUK1=") == TRUE)
710 retries[OFONO_SIM_PASSWORD_SIM_PUK] = retry;
711 else if (g_str_has_prefix(entries[num], "PIN2=") == TRUE)
712 retries[OFONO_SIM_PASSWORD_SIM_PIN2] = retry;
713 else if (g_str_has_prefix(entries[num], "PUK2=") == TRUE)
714 retries[OFONO_SIM_PASSWORD_SIM_PUK2] = retry;
719 cb(&error, retries, cbd->data);
722 static void at_epin_cb(gboolean ok, GAtResult *result, gpointer user_data)
724 struct cb_data *cbd = user_data;
725 ofono_sim_pin_retries_cb_t cb = cbd->cb;
726 const char *final = g_at_result_final_response(result);
728 struct ofono_error error;
729 int retries[OFONO_SIM_PASSWORD_INVALID];
731 static enum ofono_sim_password_type password_types[] = {
732 OFONO_SIM_PASSWORD_SIM_PIN,
733 OFONO_SIM_PASSWORD_SIM_PUK,
734 OFONO_SIM_PASSWORD_SIM_PIN2,
735 OFONO_SIM_PASSWORD_SIM_PUK2,
738 decode_at_error(&error, final);
741 cb(&error, NULL, cbd->data);
745 g_at_result_iter_init(&iter, result);
747 if (!g_at_result_iter_next(&iter, "*EPIN:"))
750 BUILD_PIN_RETRIES_ARRAY(password_types, ARRAY_SIZE(password_types),
753 cb(&error, retries, cbd->data);
758 CALLBACK_WITH_FAILURE(cb, NULL, cbd->data);
761 static void at_cpinr_cb(gboolean ok, GAtResult *result, gpointer user_data)
763 struct cb_data *cbd = user_data;
764 ofono_sim_pin_retries_cb_t cb = cbd->cb;
766 struct ofono_error error;
767 int retries[OFONO_SIM_PASSWORD_INVALID];
768 size_t len = sizeof(at_sim_name) / sizeof(*at_sim_name);
771 decode_at_error(&error, g_at_result_final_response(result));
774 cb(&error, NULL, cbd->data);
778 for (i = 0; i < OFONO_SIM_PASSWORD_INVALID; i++)
781 g_at_result_iter_init(&iter, result);
783 /* Ignore +CPINRE results... */
784 while (g_at_result_iter_next(&iter, "+CPINR:")) {
788 if (!g_at_result_iter_next_unquoted_string(&iter, &name))
791 if (!g_at_result_iter_next_number(&iter, &val))
794 for (i = 1; i < len; i++) {
795 if (!strcmp(name, at_sim_name[i].name)) {
802 cb(&error, retries, cbd->data);
805 static void at_spic_cb(gboolean ok, GAtResult *result, gpointer user_data)
807 struct cb_data *cbd = user_data;
808 ofono_sim_pin_retries_cb_t cb = cbd->cb;
809 const char *final = g_at_result_final_response(result);
811 struct ofono_error error;
812 int retries[OFONO_SIM_PASSWORD_INVALID];
814 static enum ofono_sim_password_type password_types[] = {
815 OFONO_SIM_PASSWORD_SIM_PIN,
816 OFONO_SIM_PASSWORD_SIM_PUK,
817 OFONO_SIM_PASSWORD_SIM_PIN2,
818 OFONO_SIM_PASSWORD_SIM_PUK2,
821 decode_at_error(&error, final);
824 cb(&error, NULL, cbd->data);
828 g_at_result_iter_init(&iter, result);
830 if (!g_at_result_iter_next(&iter, "+SPIC:"))
833 BUILD_PIN_RETRIES_ARRAY(password_types, ARRAY_SIZE(password_types),
836 cb(&error, retries, cbd->data);
841 CALLBACK_WITH_FAILURE(cb, NULL, cbd->data);
844 static void at_pin_retries_query(struct ofono_sim *sim,
845 ofono_sim_pin_retries_cb_t cb,
848 struct sim_data *sd = ofono_sim_get_data(sim);
849 struct cb_data *cbd = cb_data_new(cb, data);
853 switch (sd->vendor) {
854 case OFONO_VENDOR_IFX:
855 if (g_at_chat_send(sd->chat, "AT+XPINCNT", xpincnt_prefix,
856 xpincnt_cb, cbd, g_free) > 0)
859 case OFONO_VENDOR_SPEEDUP:
860 if (g_at_chat_send(sd->chat, "AT+CPNNUM", NULL,
861 cpnnum_cb, cbd, g_free) > 0)
864 case OFONO_VENDOR_OPTION_HSO:
865 if (g_at_chat_send(sd->chat, "AT_OERCN?", oercn_prefix,
866 oercn_cb, cbd, g_free) > 0)
869 case OFONO_VENDOR_HUAWEI:
870 if (g_at_chat_send(sd->chat, "AT^CPIN?", huawei_cpin_prefix,
871 huawei_cpin_cb, cbd, g_free) > 0)
874 case OFONO_VENDOR_ICERA:
875 if (g_at_chat_send(sd->chat, "AT%PINNUM?", pinnum_prefix,
876 pinnum_cb, cbd, g_free) > 0)
879 case OFONO_VENDOR_ZTE:
880 if (g_at_chat_send(sd->chat, "AT+ZPINPUK=?", zpinpuk_prefix,
881 zpinpuk_cb, cbd, g_free) > 0)
884 case OFONO_VENDOR_MBM:
885 if (g_at_chat_send(sd->chat, "AT*EPIN?", epin_prefix,
886 at_epin_cb, cbd, g_free) > 0)
889 case OFONO_VENDOR_SIMCOM:
890 if (g_at_chat_send(sd->chat, "AT+SPIC", spic_prefix,
891 at_spic_cb, cbd, g_free) > 0)
895 if (g_at_chat_send(sd->chat, "AT+CPINR", cpinr_prefixes,
896 at_cpinr_cb, cbd, g_free) > 0)
903 CALLBACK_WITH_FAILURE(cb, NULL, data);
906 static void at_cpin_cb(gboolean ok, GAtResult *result, gpointer user_data)
908 struct cb_data *cbd = user_data;
909 struct sim_data *sd = ofono_sim_get_data(cbd->user);
911 ofono_sim_passwd_cb_t cb = cbd->cb;
912 struct ofono_error error;
913 const char *pin_required;
914 int pin_type = OFONO_SIM_PASSWORD_INVALID;
916 int len = sizeof(at_sim_name) / sizeof(*at_sim_name);
917 const char *final = g_at_result_final_response(result);
919 if (sd->vendor == OFONO_VENDOR_WAVECOM && ok && strlen(final) > 7)
920 decode_at_error(&error, "OK");
922 decode_at_error(&error, final);
925 cb(&error, -1, cbd->data);
929 if (sd->vendor == OFONO_VENDOR_WAVECOM ||
930 sd->vendor == OFONO_VENDOR_WAVECOM_Q2XXX) {
932 pin_required = final + 7;
934 g_at_result_iter_init(&iter, result);
936 if (!g_at_result_iter_next(&iter, "+CPIN:")) {
937 CALLBACK_WITH_FAILURE(cb, -1, cbd->data);
941 g_at_result_iter_next_unquoted_string(&iter, &pin_required);
944 for (i = 0; i < len; i++) {
945 if (strcmp(pin_required, at_sim_name[i].name))
948 pin_type = at_sim_name[i].type;
952 if (pin_type == OFONO_SIM_PASSWORD_INVALID) {
953 CALLBACK_WITH_FAILURE(cb, -1, cbd->data);
957 DBG("crsm_pin_cb: %s", pin_required);
959 cb(&error, pin_type, cbd->data);
962 static void at_pin_query(struct ofono_sim *sim, ofono_sim_passwd_cb_t cb,
965 struct sim_data *sd = ofono_sim_get_data(sim);
966 struct cb_data *cbd = cb_data_new(cb, data);
970 if (g_at_chat_send(sd->chat, "AT+CPIN?", cpin_prefix,
971 at_cpin_cb, cbd, g_free) > 0)
976 CALLBACK_WITH_FAILURE(cb, -1, data);
979 static void at_xsim_notify(GAtResult *result, gpointer user_data)
981 struct cb_data *cbd = user_data;
982 struct sim_data *sd = cbd->user;
983 ofono_sim_lock_unlock_cb_t cb = cbd->cb;
984 struct ofono_error error = { .type = OFONO_ERROR_TYPE_NO_ERROR };
988 g_at_result_iter_init(&iter, result);
990 if (!g_at_result_iter_next(&iter, "+XSIM:"))
993 if (!g_at_result_iter_next_number(&iter, &state))
997 case 3: /* PIN verified – Ready */
998 case 7: /* ready for attach (+COPS) */
1004 cb(&error, cbd->data);
1006 g_at_chat_unregister(sd->chat, sd->ready_id);
1010 static void at_epev_notify(GAtResult *result, gpointer user_data)
1012 struct cb_data *cbd = user_data;
1013 struct sim_data *sd = cbd->user;
1014 ofono_sim_lock_unlock_cb_t cb = cbd->cb;
1015 struct ofono_error error = { .type = OFONO_ERROR_TYPE_NO_ERROR };
1017 cb(&error, cbd->data);
1019 g_at_chat_unregister(sd->chat, sd->ready_id);
1023 static void sim_state_cb(gboolean present, gpointer user_data)
1025 struct cb_data *cbd = user_data;
1026 struct sim_data *sd = cbd->user;
1027 ofono_sim_lock_unlock_cb_t cb = cbd->cb;
1029 at_util_sim_state_query_free(sd->sim_state_query);
1030 sd->sim_state_query = NULL;
1033 CALLBACK_WITH_SUCCESS(cb, cbd->data);
1035 CALLBACK_WITH_FAILURE(cb, cbd->data);
1038 static void at_pin_send_cb(gboolean ok, GAtResult *result,
1041 struct cb_data *cbd = user_data;
1042 struct sim_data *sd = cbd->user;
1043 ofono_sim_lock_unlock_cb_t cb = cbd->cb;
1044 struct ofono_error error;
1046 decode_at_error(&error, g_at_result_final_response(result));
1051 switch (sd->vendor) {
1052 case OFONO_VENDOR_IFX:
1054 * On the IFX modem, AT+CPIN? can return READY too
1055 * early and so use +XSIM notification to detect
1056 * the ready state of the SIM.
1058 sd->ready_id = g_at_chat_register(sd->chat, "+XSIM",
1060 FALSE, cbd, g_free);
1062 case OFONO_VENDOR_MBM:
1064 * On the MBM modem, AT+CPIN? keeps returning SIM PIN
1065 * for a moment after successful AT+CPIN="..", but then
1066 * sends *EPEV when that changes.
1068 sd->ready_id = g_at_chat_register(sd->chat, "*EPEV",
1070 FALSE, cbd, g_free);
1072 case OFONO_VENDOR_ZTE:
1074 * On ZTE modems, after pin is entered, SIM state is checked
1075 * by polling CPIN as their modem doesn't provide unsolicited
1076 * notification of SIM readiness.
1078 sd->sim_state_query = at_util_sim_state_query_new(sd->chat,
1079 2, 20, sim_state_cb, cbd,
1085 cb(&error, cbd->data);
1090 static void at_pin_send(struct ofono_sim *sim, const char *passwd,
1091 ofono_sim_lock_unlock_cb_t cb, void *data)
1093 struct sim_data *sd = ofono_sim_get_data(sim);
1094 struct cb_data *cbd = cb_data_new(cb, data);
1100 snprintf(buf, sizeof(buf), "AT+CPIN=\"%s\"", passwd);
1102 ret = g_at_chat_send(sd->chat, buf, none_prefix,
1103 at_pin_send_cb, cbd, NULL);
1105 memset(buf, 0, sizeof(buf));
1112 CALLBACK_WITH_FAILURE(cb, data);
1115 static void at_pin_send_puk(struct ofono_sim *sim, const char *puk,
1117 ofono_sim_lock_unlock_cb_t cb, void *data)
1119 struct sim_data *sd = ofono_sim_get_data(sim);
1120 struct cb_data *cbd = cb_data_new(cb, data);
1126 snprintf(buf, sizeof(buf), "AT+CPIN=\"%s\",\"%s\"", puk, passwd);
1128 ret = g_at_chat_send(sd->chat, buf, none_prefix,
1129 at_pin_send_cb, cbd, NULL);
1131 memset(buf, 0, sizeof(buf));
1138 CALLBACK_WITH_FAILURE(cb, data);
1141 static void at_lock_unlock_cb(gboolean ok, GAtResult *result,
1144 struct cb_data *cbd = user_data;
1145 ofono_sim_lock_unlock_cb_t cb = cbd->cb;
1146 struct ofono_error error;
1148 decode_at_error(&error, g_at_result_final_response(result));
1150 cb(&error, cbd->data);
1153 static const char *const at_clck_cpwd_fac[] = {
1154 [OFONO_SIM_PASSWORD_SIM_PIN] = "SC",
1155 [OFONO_SIM_PASSWORD_SIM_PIN2] = "P2",
1156 [OFONO_SIM_PASSWORD_PHSIM_PIN] = "PS",
1157 [OFONO_SIM_PASSWORD_PHFSIM_PIN] = "PF",
1158 [OFONO_SIM_PASSWORD_PHNET_PIN] = "PN",
1159 [OFONO_SIM_PASSWORD_PHNETSUB_PIN] = "PU",
1160 [OFONO_SIM_PASSWORD_PHSP_PIN] = "PP",
1161 [OFONO_SIM_PASSWORD_PHCORP_PIN] = "PC",
1164 static void at_pin_enable(struct ofono_sim *sim,
1165 enum ofono_sim_password_type passwd_type,
1166 int enable, const char *passwd,
1167 ofono_sim_lock_unlock_cb_t cb, void *data)
1169 struct sim_data *sd = ofono_sim_get_data(sim);
1170 struct cb_data *cbd = cb_data_new(cb, data);
1173 unsigned int len = sizeof(at_clck_cpwd_fac) / sizeof(*at_clck_cpwd_fac);
1175 if (passwd_type >= len || at_clck_cpwd_fac[passwd_type] == NULL)
1178 snprintf(buf, sizeof(buf), "AT+CLCK=\"%s\",%i,\"%s\"",
1179 at_clck_cpwd_fac[passwd_type], enable ? 1 : 0, passwd);
1181 ret = g_at_chat_send(sd->chat, buf, none_prefix,
1182 at_lock_unlock_cb, cbd, g_free);
1184 memset(buf, 0, sizeof(buf));
1192 CALLBACK_WITH_FAILURE(cb, data);
1195 static void at_change_passwd(struct ofono_sim *sim,
1196 enum ofono_sim_password_type passwd_type,
1197 const char *old_passwd, const char *new_passwd,
1198 ofono_sim_lock_unlock_cb_t cb, void *data)
1200 struct sim_data *sd = ofono_sim_get_data(sim);
1201 struct cb_data *cbd = cb_data_new(cb, data);
1204 unsigned int len = sizeof(at_clck_cpwd_fac) / sizeof(*at_clck_cpwd_fac);
1206 if (passwd_type >= len ||
1207 at_clck_cpwd_fac[passwd_type] == NULL)
1210 snprintf(buf, sizeof(buf), "AT+CPWD=\"%s\",\"%s\",\"%s\"",
1211 at_clck_cpwd_fac[passwd_type], old_passwd, new_passwd);
1213 ret = g_at_chat_send(sd->chat, buf, none_prefix,
1214 at_lock_unlock_cb, cbd, g_free);
1216 memset(buf, 0, sizeof(buf));
1224 CALLBACK_WITH_FAILURE(cb, data);
1227 static void at_lock_status_cb(gboolean ok, GAtResult *result,
1230 struct cb_data *cbd = user_data;
1232 ofono_sim_locked_cb_t cb = cbd->cb;
1233 struct ofono_error error;
1236 decode_at_error(&error, g_at_result_final_response(result));
1239 cb(&error, -1, cbd->data);
1243 g_at_result_iter_init(&iter, result);
1245 if (!g_at_result_iter_next(&iter, "+CLCK:")) {
1246 CALLBACK_WITH_FAILURE(cb, -1, cbd->data);
1250 g_at_result_iter_next_number(&iter, &locked);
1252 DBG("lock_status_cb: %i", locked);
1254 cb(&error, locked, cbd->data);
1257 static void at_pin_query_enabled(struct ofono_sim *sim,
1258 enum ofono_sim_password_type passwd_type,
1259 ofono_sim_locked_cb_t cb, void *data)
1261 struct sim_data *sd = ofono_sim_get_data(sim);
1262 struct cb_data *cbd = cb_data_new(cb, data);
1264 unsigned int len = sizeof(at_clck_cpwd_fac) / sizeof(*at_clck_cpwd_fac);
1266 if (passwd_type >= len || at_clck_cpwd_fac[passwd_type] == NULL)
1269 snprintf(buf, sizeof(buf), "AT+CLCK=\"%s\",2",
1270 at_clck_cpwd_fac[passwd_type]);
1272 if (g_at_chat_send(sd->chat, buf, clck_prefix,
1273 at_lock_status_cb, cbd, g_free) > 0)
1279 CALLBACK_WITH_FAILURE(cb, -1, data);
1282 static gboolean at_sim_register(gpointer user)
1284 struct ofono_sim *sim = user;
1286 ofono_sim_register(sim);
1291 static int at_sim_probe(struct ofono_sim *sim, unsigned int vendor,
1294 GAtChat *chat = data;
1295 struct sim_data *sd;
1297 sd = g_new0(struct sim_data, 1);
1298 sd->chat = g_at_chat_clone(chat);
1299 sd->vendor = vendor;
1301 switch (sd->vendor) {
1302 case OFONO_VENDOR_WAVECOM:
1303 g_at_chat_add_terminator(sd->chat, "+CPIN:", 6, TRUE);
1305 case OFONO_VENDOR_MBM:
1306 g_at_chat_send(sd->chat, "AT*EPEE=1", NULL, NULL, NULL, NULL);
1308 case OFONO_VENDOR_WAVECOM_Q2XXX:
1309 g_at_chat_add_terminator(chat, "+CPIN: READY", -1, TRUE);
1315 ofono_sim_set_data(sim, sd);
1316 g_idle_add(at_sim_register, sim);
1321 static void at_sim_remove(struct ofono_sim *sim)
1323 struct sim_data *sd = ofono_sim_get_data(sim);
1325 /* Cleanup potential SIM state polling */
1326 at_util_sim_state_query_free(sd->sim_state_query);
1328 ofono_sim_set_data(sim, NULL);
1330 g_at_chat_unref(sd->chat);
1334 static struct ofono_sim_driver driver = {
1336 .probe = at_sim_probe,
1337 .remove = at_sim_remove,
1338 .read_file_info = at_sim_read_info,
1339 .read_file_transparent = at_sim_read_binary,
1340 .read_file_linear = at_sim_read_record,
1341 .read_file_cyclic = at_sim_read_record,
1342 .write_file_transparent = at_sim_update_binary,
1343 .write_file_linear = at_sim_update_record,
1344 .write_file_cyclic = at_sim_update_cyclic,
1345 .read_imsi = at_read_imsi,
1346 .query_passwd_state = at_pin_query,
1347 .query_pin_retries = at_pin_retries_query,
1348 .send_passwd = at_pin_send,
1349 .reset_passwd = at_pin_send_puk,
1350 .lock = at_pin_enable,
1351 .change_passwd = at_change_passwd,
1352 .query_locked = at_pin_query_enabled,
1355 static struct ofono_sim_driver driver_noef = {
1356 .name = "atmodem-noef",
1357 .probe = at_sim_probe,
1358 .remove = at_sim_remove,
1359 .read_imsi = at_read_imsi,
1360 .query_passwd_state = at_pin_query,
1361 .query_pin_retries = at_pin_retries_query,
1362 .send_passwd = at_pin_send,
1363 .reset_passwd = at_pin_send_puk,
1364 .lock = at_pin_enable,
1365 .change_passwd = at_change_passwd,
1366 .query_locked = at_pin_query_enabled,
1369 void at_sim_init(void)
1371 ofono_sim_driver_register(&driver);
1372 ofono_sim_driver_register(&driver_noef);
1375 void at_sim_exit(void)
1377 ofono_sim_driver_unregister(&driver);
1378 ofono_sim_driver_unregister(&driver_noef);