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 *pct_prefix[] = { "#PCT:", NULL };
69 static const char *pnnm_prefix[] = { "+PNNM:", NULL };
70 static const char *none_prefix[] = { NULL };
72 static void at_crsm_info_cb(gboolean ok, GAtResult *result, gpointer user_data)
74 struct cb_data *cbd = user_data;
76 ofono_sim_file_info_cb_t cb = cbd->cb;
77 struct ofono_error error;
78 const guint8 *response;
82 unsigned char access[3];
83 unsigned char file_status;
85 decode_at_error(&error, g_at_result_final_response(result));
88 cb(&error, -1, -1, -1, NULL, EF_STATUS_INVALIDATED, cbd->data);
92 g_at_result_iter_init(&iter, result);
94 if (!g_at_result_iter_next(&iter, "+CRSM:"))
97 g_at_result_iter_next_number(&iter, &sw1);
98 g_at_result_iter_next_number(&iter, &sw2);
100 if (!g_at_result_iter_next_hexstring(&iter, &response, &len) ||
101 (sw1 != 0x90 && sw1 != 0x91 && sw1 != 0x92) ||
102 (sw1 == 0x90 && sw2 != 0x00)) {
103 memset(&error, 0, sizeof(error));
105 error.type = OFONO_ERROR_TYPE_SIM;
106 error.error = (sw1 << 8) | sw2;
108 cb(&error, -1, -1, -1, NULL, EF_STATUS_INVALIDATED, cbd->data);
112 DBG("crsm_info_cb: %02x, %02x, %i", sw1, sw2, len);
114 if (response[0] == 0x62) {
115 ok = sim_parse_3g_get_response(response, len, &flen, &rlen,
118 file_status = EF_STATUS_VALID;
120 ok = sim_parse_2g_get_response(response, len, &flen, &rlen,
121 &str, access, &file_status);
126 cb(&error, flen, str, rlen, access, file_status, cbd->data);
131 CALLBACK_WITH_FAILURE(cb, -1, -1, -1, NULL,
132 EF_STATUS_INVALIDATED, cbd->data);
135 static void at_sim_read_info(struct ofono_sim *sim, int fileid,
136 const unsigned char *path,
137 unsigned int path_len,
138 ofono_sim_file_info_cb_t cb, void *data)
140 struct sim_data *sd = ofono_sim_get_data(sim);
145 if (sd->vendor == OFONO_VENDOR_OPTION_HSO) {
146 unsigned char access[3] = { 0x00, 0x00, 0x00 };
148 if (fileid == SIM_EFAD_FILEID) {
149 CALLBACK_WITH_SUCCESS(cb, 4, 0, 0, access,
150 EF_STATUS_VALID, data);
155 cbd = cb_data_new(cb, data);
157 len = snprintf(buf, sizeof(buf), "AT+CRSM=192,%i", fileid);
159 switch (sd->vendor) {
165 case OFONO_VENDOR_ZTE:
166 case OFONO_VENDOR_HUAWEI:
167 case OFONO_VENDOR_SIERRA:
168 case OFONO_VENDOR_SPEEDUP:
169 case OFONO_VENDOR_QUALCOMM_MSM:
170 /* Maximum possible length */
171 len += sprintf(buf + len, ",0,0,255");
176 len += sprintf(buf + len, ",,\"");
178 for (; path_len; path_len--)
179 len += sprintf(buf + len, "%02hhX", *path++);
185 if (g_at_chat_send(sd->chat, buf, crsm_prefix,
186 at_crsm_info_cb, cbd, g_free) > 0)
191 CALLBACK_WITH_FAILURE(cb, -1, -1, -1, NULL,
192 EF_STATUS_INVALIDATED, data);
195 static void at_crsm_read_cb(gboolean ok, GAtResult *result,
198 struct cb_data *cbd = user_data;
200 ofono_sim_read_cb_t cb = cbd->cb;
201 struct ofono_error error;
202 const guint8 *response;
205 decode_at_error(&error, g_at_result_final_response(result));
208 cb(&error, NULL, 0, cbd->data);
212 g_at_result_iter_init(&iter, result);
214 if (!g_at_result_iter_next(&iter, "+CRSM:")) {
215 CALLBACK_WITH_FAILURE(cb, NULL, 0, cbd->data);
219 g_at_result_iter_next_number(&iter, &sw1);
220 g_at_result_iter_next_number(&iter, &sw2);
222 if ((sw1 != 0x90 && sw1 != 0x91 && sw1 != 0x92 && sw1 != 0x9f) ||
223 (sw1 == 0x90 && sw2 != 0x00)) {
224 memset(&error, 0, sizeof(error));
226 error.type = OFONO_ERROR_TYPE_SIM;
227 error.error = (sw1 << 8) | sw2;
229 cb(&error, NULL, 0, cbd->data);
233 if (!g_at_result_iter_next_hexstring(&iter, &response, &len)) {
234 CALLBACK_WITH_FAILURE(cb, NULL, 0, cbd->data);
238 DBG("crsm_read_cb: %02x, %02x, %d", sw1, sw2, len);
240 cb(&error, response, len, cbd->data);
243 static void at_sim_read_binary(struct ofono_sim *sim, int fileid,
244 int start, int length,
245 const unsigned char *path,
246 unsigned int path_len,
247 ofono_sim_read_cb_t cb, void *data)
249 struct sim_data *sd = ofono_sim_get_data(sim);
250 struct cb_data *cbd = cb_data_new(cb, data);
254 len = snprintf(buf, sizeof(buf), "AT+CRSM=176,%i,%i,%i,%i", fileid,
255 start >> 8, start & 0xff, length);
262 for (; path_len; path_len--)
263 len += sprintf(buf + len, "%02hhX", *path++);
269 if (g_at_chat_send(sd->chat, buf, crsm_prefix,
270 at_crsm_read_cb, cbd, g_free) > 0)
275 CALLBACK_WITH_FAILURE(cb, NULL, 0, data);
278 static void at_sim_read_record(struct ofono_sim *sim, int fileid,
279 int record, int length,
280 const unsigned char *path,
281 unsigned int path_len,
282 ofono_sim_read_cb_t cb, void *data)
284 struct sim_data *sd = ofono_sim_get_data(sim);
285 struct cb_data *cbd = cb_data_new(cb, data);
288 snprintf(buf, sizeof(buf), "AT+CRSM=178,%i,%i,4,%i", fileid,
291 if (g_at_chat_send(sd->chat, buf, crsm_prefix,
292 at_crsm_read_cb, cbd, g_free) > 0)
297 CALLBACK_WITH_FAILURE(cb, NULL, 0, data);
300 static void at_crsm_update_cb(gboolean ok, GAtResult *result,
303 struct cb_data *cbd = user_data;
305 ofono_sim_write_cb_t cb = cbd->cb;
306 struct ofono_error error;
309 decode_at_error(&error, g_at_result_final_response(result));
312 cb(&error, cbd->data);
316 g_at_result_iter_init(&iter, result);
318 if (!g_at_result_iter_next(&iter, "+CRSM:")) {
319 CALLBACK_WITH_FAILURE(cb, cbd->data);
323 g_at_result_iter_next_number(&iter, &sw1);
324 g_at_result_iter_next_number(&iter, &sw2);
326 if ((sw1 != 0x90 && sw1 != 0x91 && sw1 != 0x92 && sw1 != 0x9f) ||
327 (sw1 == 0x90 && sw2 != 0x00)) {
328 memset(&error, 0, sizeof(error));
330 error.type = OFONO_ERROR_TYPE_SIM;
331 error.error = (sw1 << 8) | sw2;
334 DBG("crsm_update_cb: %02x, %02x", sw1, sw2);
336 cb(&error, cbd->data);
339 static void at_sim_update_file(struct ofono_sim *sim, int cmd, int fileid,
340 int p1, int p2, int p3,
341 const unsigned char *value,
342 const unsigned char *path,
343 unsigned int path_len,
344 ofono_sim_write_cb_t cb, void *data)
346 struct sim_data *sd = ofono_sim_get_data(sim);
347 struct cb_data *cbd = cb_data_new(cb, data);
350 int size = 38 + p3 * 2;
354 buf = g_try_new(char, size);
358 len = sprintf(buf, "AT+CRSM=%i,%i,%i,%i,%i,\"", cmd, fileid,p1, p2, p3);
361 len += sprintf(buf + len, "%02hhX", *value++);
366 ret = g_at_chat_send(sd->chat, buf, crsm_prefix,
367 at_crsm_update_cb, cbd, g_free);
377 CALLBACK_WITH_FAILURE(cb, data);
380 static void at_sim_update_binary(struct ofono_sim *sim, int fileid,
381 int start, int length,
382 const unsigned char *value,
383 const unsigned char *path,
384 unsigned int path_len,
385 ofono_sim_write_cb_t cb, void *data)
387 at_sim_update_file(sim, 214, fileid, start >> 8, start & 0xff,
388 length, value, path, path_len, cb, data);
391 static void at_sim_update_record(struct ofono_sim *sim, int fileid,
392 int record, int length,
393 const unsigned char *value,
394 const unsigned char *path,
395 unsigned int path_len,
396 ofono_sim_write_cb_t cb, void *data)
398 at_sim_update_file(sim, 220, fileid, record, 4, length,
399 value, path, path_len, cb, data);
402 static void at_sim_update_cyclic(struct ofono_sim *sim, int fileid,
403 int length, const unsigned char *value,
404 const unsigned char *path,
405 unsigned int path_len,
406 ofono_sim_write_cb_t cb, void *data)
408 at_sim_update_file(sim, 220, fileid, 0, 3, length, value,
409 path, path_len, cb, data);
412 static void at_cimi_cb(gboolean ok, GAtResult *result, gpointer user_data)
414 struct cb_data *cbd = user_data;
416 ofono_sim_imsi_cb_t cb = cbd->cb;
417 struct ofono_error error;
421 decode_at_error(&error, g_at_result_final_response(result));
424 cb(&error, NULL, cbd->data);
428 g_at_result_iter_init(&iter, result);
430 for (i = 0; i < g_at_result_num_response_lines(result); i++)
431 g_at_result_iter_next(&iter, NULL);
433 imsi = g_at_result_iter_raw_line(&iter);
435 DBG("cimi_cb: %s", imsi);
437 cb(&error, imsi, cbd->data);
440 static void at_read_imsi(struct ofono_sim *sim, ofono_sim_imsi_cb_t cb,
443 struct sim_data *sd = ofono_sim_get_data(sim);
444 struct cb_data *cbd = cb_data_new(cb, data);
446 if (g_at_chat_send(sd->chat, "AT+CIMI", NULL,
447 at_cimi_cb, cbd, g_free) > 0)
452 CALLBACK_WITH_FAILURE(cb, NULL, data);
456 enum ofono_sim_password_type type;
458 } const at_sim_name[] = {
459 { OFONO_SIM_PASSWORD_NONE, "READY" },
460 { OFONO_SIM_PASSWORD_SIM_PIN, "SIM PIN" },
461 { OFONO_SIM_PASSWORD_SIM_PUK, "SIM PUK" },
462 { OFONO_SIM_PASSWORD_PHSIM_PIN, "PH-SIM PIN" },
463 { OFONO_SIM_PASSWORD_PHFSIM_PIN, "PH-FSIM PIN" },
464 { OFONO_SIM_PASSWORD_PHFSIM_PUK, "PH-FSIM PUK" },
465 { OFONO_SIM_PASSWORD_SIM_PIN2, "SIM PIN2" },
466 { OFONO_SIM_PASSWORD_SIM_PUK2, "SIM PUK2" },
467 { OFONO_SIM_PASSWORD_PHNET_PIN, "PH-NET PIN" },
468 { OFONO_SIM_PASSWORD_PHNET_PUK, "PH-NET PUK" },
469 { OFONO_SIM_PASSWORD_PHNETSUB_PIN, "PH-NETSUB PIN" },
470 { OFONO_SIM_PASSWORD_PHNETSUB_PUK, "PH-NETSUB PUK" },
471 { OFONO_SIM_PASSWORD_PHSP_PIN, "PH-SP PIN" },
472 { OFONO_SIM_PASSWORD_PHSP_PUK, "PH-SP PUK" },
473 { OFONO_SIM_PASSWORD_PHCORP_PIN, "PH-CORP PIN" },
474 { OFONO_SIM_PASSWORD_PHCORP_PUK, "PH-CORP PUK" },
477 #define BUILD_PIN_RETRIES_ARRAY(passwd_types, passwd_types_cnt, retry) \
478 for (i = 0; i < OFONO_SIM_PASSWORD_INVALID; i++) \
481 for (i = 0; i < passwd_types_cnt; i++) { \
484 if (!g_at_result_iter_next_number(&iter, &val)) \
487 retry[passwd_types[i]] = val; \
489 DBG("retry counter id=%d, val=%d", passwd_types[i], \
490 retry[passwd_types[i]]); \
493 static void huawei_cpin_cb(gboolean ok, GAtResult *result, gpointer user_data)
495 struct cb_data *cbd = user_data;
496 ofono_sim_pin_retries_cb_t cb = cbd->cb;
497 const char *final = g_at_result_final_response(result);
499 struct ofono_error error;
500 int retries[OFONO_SIM_PASSWORD_INVALID];
502 static enum ofono_sim_password_type password_types[] = {
503 OFONO_SIM_PASSWORD_SIM_PUK,
504 OFONO_SIM_PASSWORD_SIM_PIN,
505 OFONO_SIM_PASSWORD_SIM_PUK2,
506 OFONO_SIM_PASSWORD_SIM_PIN2,
509 decode_at_error(&error, final);
512 cb(&error, NULL, cbd->data);
516 g_at_result_iter_init(&iter, result);
518 if (!g_at_result_iter_next(&iter, "^CPIN:"))
521 /* Skip status since we are not interested in this */
522 if (!g_at_result_iter_skip_next(&iter))
525 /* Skip "overall counter" since we'll grab each one individually */
526 if (!g_at_result_iter_skip_next(&iter))
529 BUILD_PIN_RETRIES_ARRAY(password_types, ARRAY_SIZE(password_types),
532 cb(&error, retries, cbd->data);
537 CALLBACK_WITH_FAILURE(cb, NULL, cbd->data);
540 static void pinnum_cb(gboolean ok, GAtResult *result, gpointer user_data)
542 struct cb_data *cbd = user_data;
543 ofono_sim_pin_retries_cb_t cb = cbd->cb;
544 const char *final = g_at_result_final_response(result);
546 struct ofono_error error;
547 int retries[OFONO_SIM_PASSWORD_INVALID];
549 static enum ofono_sim_password_type password_types[] = {
550 OFONO_SIM_PASSWORD_SIM_PIN,
551 OFONO_SIM_PASSWORD_SIM_PUK,
552 OFONO_SIM_PASSWORD_SIM_PIN2,
553 OFONO_SIM_PASSWORD_SIM_PUK2,
557 decode_at_error(&error, final);
560 cb(&error, NULL, cbd->data);
564 g_at_result_iter_init(&iter, result);
566 if (!g_at_result_iter_next(&iter, "%PINNUM:"))
569 BUILD_PIN_RETRIES_ARRAY(password_types, ARRAY_SIZE(password_types),
572 cb(&error, retries, cbd->data);
577 CALLBACK_WITH_FAILURE(cb, NULL, cbd->data);
580 static void zpinpuk_cb(gboolean ok, GAtResult *result, gpointer user_data)
582 struct cb_data *cbd = user_data;
583 ofono_sim_pin_retries_cb_t cb = cbd->cb;
584 const char *final = g_at_result_final_response(result);
586 struct ofono_error error;
587 int retries[OFONO_SIM_PASSWORD_INVALID];
589 static enum ofono_sim_password_type password_types[] = {
590 OFONO_SIM_PASSWORD_SIM_PIN,
591 OFONO_SIM_PASSWORD_SIM_PUK,
595 decode_at_error(&error, final);
598 cb(&error, NULL, cbd->data);
602 g_at_result_iter_init(&iter, result);
604 if (!g_at_result_iter_next(&iter, "+ZPINPUK:"))
607 BUILD_PIN_RETRIES_ARRAY(password_types, ARRAY_SIZE(password_types),
610 cb(&error, retries, cbd->data);
615 CALLBACK_WITH_FAILURE(cb, NULL, cbd->data);
618 static void xpincnt_cb(gboolean ok, GAtResult *result, gpointer user_data)
620 struct cb_data *cbd = user_data;
621 ofono_sim_pin_retries_cb_t cb = cbd->cb;
622 const char *final = g_at_result_final_response(result);
624 struct ofono_error error;
625 int retries[OFONO_SIM_PASSWORD_INVALID];
627 static enum ofono_sim_password_type password_types[] = {
628 OFONO_SIM_PASSWORD_SIM_PIN,
629 OFONO_SIM_PASSWORD_SIM_PIN2,
630 OFONO_SIM_PASSWORD_SIM_PUK,
631 OFONO_SIM_PASSWORD_SIM_PUK2,
634 decode_at_error(&error, final);
637 cb(&error, NULL, cbd->data);
641 g_at_result_iter_init(&iter, result);
643 if (!g_at_result_iter_next(&iter, "+XPINCNT:"))
646 BUILD_PIN_RETRIES_ARRAY(password_types, ARRAY_SIZE(password_types),
649 cb(&error, retries, cbd->data);
654 CALLBACK_WITH_FAILURE(cb, NULL, cbd->data);
657 static void oercn_cb(gboolean ok, GAtResult *result, gpointer user_data)
659 struct cb_data *cbd = user_data;
660 ofono_sim_pin_retries_cb_t cb = cbd->cb;
661 const char *final = g_at_result_final_response(result);
663 struct ofono_error error;
664 int retries[OFONO_SIM_PASSWORD_INVALID];
666 static enum ofono_sim_password_type password_types[] = {
667 OFONO_SIM_PASSWORD_SIM_PIN,
668 OFONO_SIM_PASSWORD_SIM_PUK,
671 decode_at_error(&error, final);
674 cb(&error, NULL, cbd->data);
678 g_at_result_iter_init(&iter, result);
680 if (!g_at_result_iter_next(&iter, "_OERCN:"))
683 BUILD_PIN_RETRIES_ARRAY(password_types, ARRAY_SIZE(password_types),
686 cb(&error, retries, cbd->data);
691 CALLBACK_WITH_FAILURE(cb, NULL, cbd->data);
694 static void cpnnum_cb(gboolean ok, GAtResult *result, gpointer user_data)
696 struct cb_data *cbd = user_data;
697 ofono_sim_pin_retries_cb_t cb = cbd->cb;
698 const char *final = g_at_result_final_response(result);
700 struct ofono_error error;
704 int retries[OFONO_SIM_PASSWORD_INVALID];
707 decode_at_error(&error, final);
710 cb(&error, NULL, cbd->data);
714 g_at_result_iter_init(&iter, result);
716 for (num = 0; num < g_at_result_num_response_lines(result); num++)
717 g_at_result_iter_next(&iter, NULL);
719 line = g_at_result_iter_raw_line(&iter);
723 for (i = 0; i < OFONO_SIM_PASSWORD_INVALID; i++)
726 entries = g_strsplit(line, "; ", -1);
728 for (num = 0; entries[num]; num++) {
731 if (strlen(entries[num]) < 5)
734 retry = strtol(entries[num] + 5, NULL, 10);
735 if (retry == 0 && errno == EINVAL)
738 if (g_str_has_prefix(entries[num], "PIN1=") == TRUE)
739 retries[OFONO_SIM_PASSWORD_SIM_PIN] = retry;
740 else if (g_str_has_prefix(entries[num], "PUK1=") == TRUE)
741 retries[OFONO_SIM_PASSWORD_SIM_PUK] = retry;
742 else if (g_str_has_prefix(entries[num], "PIN2=") == TRUE)
743 retries[OFONO_SIM_PASSWORD_SIM_PIN2] = retry;
744 else if (g_str_has_prefix(entries[num], "PUK2=") == TRUE)
745 retries[OFONO_SIM_PASSWORD_SIM_PUK2] = retry;
750 cb(&error, retries, cbd->data);
753 static void at_epin_cb(gboolean ok, GAtResult *result, gpointer user_data)
755 struct cb_data *cbd = user_data;
756 ofono_sim_pin_retries_cb_t cb = cbd->cb;
757 const char *final = g_at_result_final_response(result);
759 struct ofono_error error;
760 int retries[OFONO_SIM_PASSWORD_INVALID];
762 static enum ofono_sim_password_type password_types[] = {
763 OFONO_SIM_PASSWORD_SIM_PIN,
764 OFONO_SIM_PASSWORD_SIM_PUK,
765 OFONO_SIM_PASSWORD_SIM_PIN2,
766 OFONO_SIM_PASSWORD_SIM_PUK2,
769 decode_at_error(&error, final);
772 cb(&error, NULL, cbd->data);
776 g_at_result_iter_init(&iter, result);
778 if (!g_at_result_iter_next(&iter, "*EPIN:"))
781 BUILD_PIN_RETRIES_ARRAY(password_types, ARRAY_SIZE(password_types),
784 cb(&error, retries, cbd->data);
789 CALLBACK_WITH_FAILURE(cb, NULL, cbd->data);
792 static void at_cpinr_cb(gboolean ok, GAtResult *result, gpointer user_data)
794 struct cb_data *cbd = user_data;
795 ofono_sim_pin_retries_cb_t cb = cbd->cb;
797 struct ofono_error error;
798 int retries[OFONO_SIM_PASSWORD_INVALID];
799 size_t len = sizeof(at_sim_name) / sizeof(*at_sim_name);
802 decode_at_error(&error, g_at_result_final_response(result));
805 cb(&error, NULL, cbd->data);
809 for (i = 0; i < OFONO_SIM_PASSWORD_INVALID; i++)
812 g_at_result_iter_init(&iter, result);
814 /* Ignore +CPINRE results... */
815 while (g_at_result_iter_next(&iter, "+CPINR:")) {
819 if (!g_at_result_iter_next_unquoted_string(&iter, &name))
822 if (!g_at_result_iter_next_number(&iter, &val))
825 for (i = 1; i < len; i++) {
826 if (!strcmp(name, at_sim_name[i].name)) {
833 cb(&error, retries, cbd->data);
836 static void at_spic_cb(gboolean ok, GAtResult *result, gpointer user_data)
838 struct cb_data *cbd = user_data;
839 ofono_sim_pin_retries_cb_t cb = cbd->cb;
840 const char *final = g_at_result_final_response(result);
842 struct ofono_error error;
843 int retries[OFONO_SIM_PASSWORD_INVALID];
845 static enum ofono_sim_password_type password_types[] = {
846 OFONO_SIM_PASSWORD_SIM_PIN,
847 OFONO_SIM_PASSWORD_SIM_PUK,
848 OFONO_SIM_PASSWORD_SIM_PIN2,
849 OFONO_SIM_PASSWORD_SIM_PUK2,
852 decode_at_error(&error, final);
855 cb(&error, NULL, cbd->data);
859 g_at_result_iter_init(&iter, result);
861 if (!g_at_result_iter_next(&iter, "+SPIC:"))
864 BUILD_PIN_RETRIES_ARRAY(password_types, ARRAY_SIZE(password_types),
867 cb(&error, retries, cbd->data);
872 CALLBACK_WITH_FAILURE(cb, NULL, cbd->data);
875 #define AT_PCT_SET_RETRIES(retries, pin_type, value) \
876 retries[pin_type] = value; \
877 DBG("retry counter id=%d, val=%d", pin_type, value);
879 static void at_pct_cb(gboolean ok, GAtResult *result, gpointer user_data)
881 struct cb_data *cbd = user_data;
882 ofono_sim_pin_retries_cb_t cb = cbd->cb;
883 struct ofono_sim *sim = cbd->user;
884 const char *final = g_at_result_final_response(result);
886 struct ofono_error error;
887 int retries[OFONO_SIM_PASSWORD_INVALID];
889 enum ofono_sim_password_type pin_type;
891 decode_at_error(&error, final);
894 cb(&error, NULL, cbd->data);
898 g_at_result_iter_init(&iter, result);
900 for (i = 0; i < OFONO_SIM_PASSWORD_INVALID; i++)
903 pin_type = ofono_sim_get_password_type(sim);
904 if (pin_type == OFONO_SIM_PASSWORD_NONE) {
905 DBG("Note: No password required, returning maximum retries:");
907 AT_PCT_SET_RETRIES(retries, OFONO_SIM_PASSWORD_SIM_PIN, 3);
908 AT_PCT_SET_RETRIES(retries, OFONO_SIM_PASSWORD_SIM_PIN2, 3);
909 AT_PCT_SET_RETRIES(retries, OFONO_SIM_PASSWORD_SIM_PUK, 10);
910 AT_PCT_SET_RETRIES(retries, OFONO_SIM_PASSWORD_SIM_PUK2, 10);
915 if (g_at_result_iter_next(&iter, "#PCT:") == FALSE)
918 if (g_at_result_iter_next_number(&iter, &retries[pin_type]) == FALSE)
921 DBG("retry counter id=%d, val=%d", pin_type, retries[pin_type]);
924 cb(&error, retries, cbd->data);
929 CALLBACK_WITH_FAILURE(cb, NULL, cbd->data);
932 static void at_pnnm_cb(gboolean ok, GAtResult *result, gpointer user_data)
934 struct cb_data *cbd = user_data;
935 ofono_sim_pin_retries_cb_t cb = cbd->cb;
936 const char *final = g_at_result_final_response(result);
938 struct ofono_error error;
939 int retries[OFONO_SIM_PASSWORD_INVALID];
941 static enum ofono_sim_password_type password_types[] = {
942 OFONO_SIM_PASSWORD_SIM_PIN,
943 OFONO_SIM_PASSWORD_SIM_PUK,
946 decode_at_error(&error, final);
949 cb(&error, NULL, cbd->data);
953 g_at_result_iter_init(&iter, result);
955 if (!g_at_result_iter_next(&iter, "+PNNM:"))
958 BUILD_PIN_RETRIES_ARRAY(password_types, ARRAY_SIZE(password_types),
961 cb(&error, retries, cbd->data);
966 CALLBACK_WITH_FAILURE(cb, NULL, cbd->data);
969 static void at_pin_retries_query(struct ofono_sim *sim,
970 ofono_sim_pin_retries_cb_t cb,
973 struct sim_data *sd = ofono_sim_get_data(sim);
974 struct cb_data *cbd = cb_data_new(cb, data);
979 switch (sd->vendor) {
980 case OFONO_VENDOR_IFX:
981 if (g_at_chat_send(sd->chat, "AT+XPINCNT", xpincnt_prefix,
982 xpincnt_cb, cbd, g_free) > 0)
985 case OFONO_VENDOR_SPEEDUP:
986 if (g_at_chat_send(sd->chat, "AT+CPNNUM", NULL,
987 cpnnum_cb, cbd, g_free) > 0)
990 case OFONO_VENDOR_OPTION_HSO:
991 if (g_at_chat_send(sd->chat, "AT_OERCN?", oercn_prefix,
992 oercn_cb, cbd, g_free) > 0)
995 case OFONO_VENDOR_HUAWEI:
996 if (g_at_chat_send(sd->chat, "AT^CPIN?", huawei_cpin_prefix,
997 huawei_cpin_cb, cbd, g_free) > 0)
1000 case OFONO_VENDOR_ICERA:
1001 if (g_at_chat_send(sd->chat, "AT%PINNUM?", pinnum_prefix,
1002 pinnum_cb, cbd, g_free) > 0)
1005 case OFONO_VENDOR_ZTE:
1006 if (g_at_chat_send(sd->chat, "AT+ZPINPUK=?", zpinpuk_prefix,
1007 zpinpuk_cb, cbd, g_free) > 0)
1010 case OFONO_VENDOR_MBM:
1011 if (g_at_chat_send(sd->chat, "AT*EPIN?", epin_prefix,
1012 at_epin_cb, cbd, g_free) > 0)
1015 case OFONO_VENDOR_SIMCOM:
1016 if (g_at_chat_send(sd->chat, "AT+SPIC", spic_prefix,
1017 at_spic_cb, cbd, g_free) > 0)
1020 case OFONO_VENDOR_TELIT:
1021 if (g_at_chat_send(sd->chat, "AT#PCT", pct_prefix,
1022 at_pct_cb, cbd, g_free) > 0)
1025 case OFONO_VENDOR_ALCATEL:
1026 if (g_at_chat_send(sd->chat, "AT+PNNM?", pnnm_prefix,
1027 at_pnnm_cb, cbd, g_free) > 0)
1031 if (g_at_chat_send(sd->chat, "AT+CPINR", cpinr_prefixes,
1032 at_cpinr_cb, cbd, g_free) > 0)
1039 CALLBACK_WITH_FAILURE(cb, NULL, data);
1042 static int needs_wavecom_sim_quirk(int vendor)
1044 return vendor == OFONO_VENDOR_WAVECOM ||
1045 vendor == OFONO_VENDOR_WAVECOM_Q2XXX;
1048 static void at_cpin_cb(gboolean ok, GAtResult *result, gpointer user_data)
1050 struct cb_data *cbd = user_data;
1051 struct sim_data *sd = ofono_sim_get_data(cbd->user);
1053 ofono_sim_passwd_cb_t cb = cbd->cb;
1054 struct ofono_error error;
1055 const char *pin_required;
1056 int pin_type = OFONO_SIM_PASSWORD_INVALID;
1058 int len = sizeof(at_sim_name) / sizeof(*at_sim_name);
1059 const char *final = g_at_result_final_response(result);
1061 if (needs_wavecom_sim_quirk(sd->vendor) && ok && strlen(final) > 7)
1062 decode_at_error(&error, "OK");
1064 decode_at_error(&error, final);
1067 cb(&error, -1, cbd->data);
1071 if (needs_wavecom_sim_quirk(sd->vendor)) {
1073 pin_required = final + 7;
1075 g_at_result_iter_init(&iter, result);
1077 if (!g_at_result_iter_next(&iter, "+CPIN:")) {
1078 CALLBACK_WITH_FAILURE(cb, -1, cbd->data);
1082 g_at_result_iter_next_unquoted_string(&iter, &pin_required);
1085 for (i = 0; i < len; i++) {
1086 if (strcmp(pin_required, at_sim_name[i].name))
1089 pin_type = at_sim_name[i].type;
1093 if (pin_type == OFONO_SIM_PASSWORD_INVALID) {
1094 CALLBACK_WITH_FAILURE(cb, -1, cbd->data);
1098 DBG("crsm_pin_cb: %s", pin_required);
1100 cb(&error, pin_type, cbd->data);
1103 static void at_pin_query(struct ofono_sim *sim, ofono_sim_passwd_cb_t cb,
1106 struct sim_data *sd = ofono_sim_get_data(sim);
1107 struct cb_data *cbd = cb_data_new(cb, data);
1111 if (g_at_chat_send(sd->chat, "AT+CPIN?", cpin_prefix,
1112 at_cpin_cb, cbd, g_free) > 0)
1117 CALLBACK_WITH_FAILURE(cb, -1, data);
1120 static void at_xsim_notify(GAtResult *result, gpointer user_data)
1122 struct cb_data *cbd = user_data;
1123 struct sim_data *sd = cbd->user;
1124 ofono_sim_lock_unlock_cb_t cb = cbd->cb;
1125 struct ofono_error error = { .type = OFONO_ERROR_TYPE_NO_ERROR };
1129 g_at_result_iter_init(&iter, result);
1131 if (!g_at_result_iter_next(&iter, "+XSIM:"))
1134 if (!g_at_result_iter_next_number(&iter, &state))
1138 case 3: /* PIN verified – Ready */
1144 cb(&error, cbd->data);
1146 g_at_chat_unregister(sd->chat, sd->ready_id);
1150 static void at_epev_notify(GAtResult *result, gpointer user_data)
1152 struct cb_data *cbd = user_data;
1153 struct sim_data *sd = cbd->user;
1154 ofono_sim_lock_unlock_cb_t cb = cbd->cb;
1155 struct ofono_error error = { .type = OFONO_ERROR_TYPE_NO_ERROR };
1157 cb(&error, cbd->data);
1159 g_at_chat_unregister(sd->chat, sd->ready_id);
1163 static void at_qss_notify(GAtResult *result, gpointer user_data)
1165 struct cb_data *cbd = user_data;
1166 struct sim_data *sd = cbd->user;
1167 ofono_sim_lock_unlock_cb_t cb = cbd->cb;
1168 struct ofono_error error = { .type = OFONO_ERROR_TYPE_NO_ERROR };
1172 g_at_result_iter_init(&iter, result);
1174 if (!g_at_result_iter_next(&iter, "#QSS:"))
1177 if (!g_at_result_iter_next_number(&iter, &state))
1181 case 3: /* SIM inserted and READY. */
1187 cb(&error, cbd->data);
1189 g_at_chat_unregister(sd->chat, sd->ready_id);
1193 static void sim_state_cb(gboolean present, gpointer user_data)
1195 struct cb_data *cbd = user_data;
1196 struct sim_data *sd = cbd->user;
1197 ofono_sim_lock_unlock_cb_t cb = cbd->cb;
1199 at_util_sim_state_query_free(sd->sim_state_query);
1200 sd->sim_state_query = NULL;
1203 CALLBACK_WITH_SUCCESS(cb, cbd->data);
1205 CALLBACK_WITH_FAILURE(cb, cbd->data);
1208 static void at_pin_send_cb(gboolean ok, GAtResult *result,
1211 struct cb_data *cbd = user_data;
1212 struct sim_data *sd = cbd->user;
1213 ofono_sim_lock_unlock_cb_t cb = cbd->cb;
1214 struct ofono_error error;
1216 decode_at_error(&error, g_at_result_final_response(result));
1221 switch (sd->vendor) {
1222 case OFONO_VENDOR_IFX:
1224 * On the IFX modem, AT+CPIN? can return READY too
1225 * early and so use +XSIM notification to detect
1226 * the ready state of the SIM.
1228 sd->ready_id = g_at_chat_register(sd->chat, "+XSIM",
1230 FALSE, cbd, g_free);
1232 case OFONO_VENDOR_MBM:
1234 * On the MBM modem, AT+CPIN? keeps returning SIM PIN
1235 * for a moment after successful AT+CPIN="..", but then
1236 * sends *EPEV when that changes.
1238 sd->ready_id = g_at_chat_register(sd->chat, "*EPEV",
1240 FALSE, cbd, g_free);
1242 case OFONO_VENDOR_TELIT:
1244 * On the Telit modem, AT+CPIN? can return READY too
1245 * early and so use #QSS notification to detect
1246 * the ready state of the SIM.
1248 sd->ready_id = g_at_chat_register(sd->chat, "#QSS",
1250 FALSE, cbd, g_free);
1252 case OFONO_VENDOR_ZTE:
1253 case OFONO_VENDOR_ALCATEL:
1254 case OFONO_VENDOR_HUAWEI:
1256 * On ZTE modems, after pin is entered, SIM state is checked
1257 * by polling CPIN as their modem doesn't provide unsolicited
1258 * notification of SIM readiness.
1260 sd->sim_state_query = at_util_sim_state_query_new(sd->chat,
1261 2, 20, sim_state_cb, cbd,
1267 cb(&error, cbd->data);
1272 static void at_pin_send(struct ofono_sim *sim, const char *passwd,
1273 ofono_sim_lock_unlock_cb_t cb, void *data)
1275 struct sim_data *sd = ofono_sim_get_data(sim);
1276 struct cb_data *cbd = cb_data_new(cb, data);
1282 snprintf(buf, sizeof(buf), "AT+CPIN=\"%s\"", passwd);
1284 ret = g_at_chat_send(sd->chat, buf, none_prefix,
1285 at_pin_send_cb, cbd, NULL);
1287 memset(buf, 0, sizeof(buf));
1294 CALLBACK_WITH_FAILURE(cb, data);
1297 static void at_pin_send_puk(struct ofono_sim *sim, const char *puk,
1299 ofono_sim_lock_unlock_cb_t cb, void *data)
1301 struct sim_data *sd = ofono_sim_get_data(sim);
1302 struct cb_data *cbd = cb_data_new(cb, data);
1308 snprintf(buf, sizeof(buf), "AT+CPIN=\"%s\",\"%s\"", puk, passwd);
1310 ret = g_at_chat_send(sd->chat, buf, none_prefix,
1311 at_pin_send_cb, cbd, NULL);
1313 memset(buf, 0, sizeof(buf));
1320 CALLBACK_WITH_FAILURE(cb, data);
1323 static void at_lock_unlock_cb(gboolean ok, GAtResult *result,
1326 struct cb_data *cbd = user_data;
1327 ofono_sim_lock_unlock_cb_t cb = cbd->cb;
1328 struct ofono_error error;
1330 decode_at_error(&error, g_at_result_final_response(result));
1332 cb(&error, cbd->data);
1335 static const char *const at_clck_cpwd_fac[] = {
1336 [OFONO_SIM_PASSWORD_SIM_PIN] = "SC",
1337 [OFONO_SIM_PASSWORD_SIM_PIN2] = "P2",
1338 [OFONO_SIM_PASSWORD_PHSIM_PIN] = "PS",
1339 [OFONO_SIM_PASSWORD_PHFSIM_PIN] = "PF",
1340 [OFONO_SIM_PASSWORD_PHNET_PIN] = "PN",
1341 [OFONO_SIM_PASSWORD_PHNETSUB_PIN] = "PU",
1342 [OFONO_SIM_PASSWORD_PHSP_PIN] = "PP",
1343 [OFONO_SIM_PASSWORD_PHCORP_PIN] = "PC",
1346 static void at_pin_enable(struct ofono_sim *sim,
1347 enum ofono_sim_password_type passwd_type,
1348 int enable, const char *passwd,
1349 ofono_sim_lock_unlock_cb_t cb, void *data)
1351 struct sim_data *sd = ofono_sim_get_data(sim);
1352 struct cb_data *cbd = cb_data_new(cb, data);
1355 unsigned int len = sizeof(at_clck_cpwd_fac) / sizeof(*at_clck_cpwd_fac);
1357 if (passwd_type >= len || at_clck_cpwd_fac[passwd_type] == NULL)
1360 snprintf(buf, sizeof(buf), "AT+CLCK=\"%s\",%i,\"%s\"",
1361 at_clck_cpwd_fac[passwd_type], enable ? 1 : 0, passwd);
1363 ret = g_at_chat_send(sd->chat, buf, none_prefix,
1364 at_lock_unlock_cb, cbd, g_free);
1366 memset(buf, 0, sizeof(buf));
1374 CALLBACK_WITH_FAILURE(cb, data);
1377 static void at_change_passwd(struct ofono_sim *sim,
1378 enum ofono_sim_password_type passwd_type,
1379 const char *old_passwd, const char *new_passwd,
1380 ofono_sim_lock_unlock_cb_t cb, void *data)
1382 struct sim_data *sd = ofono_sim_get_data(sim);
1383 struct cb_data *cbd = cb_data_new(cb, data);
1386 unsigned int len = sizeof(at_clck_cpwd_fac) / sizeof(*at_clck_cpwd_fac);
1388 if (passwd_type >= len ||
1389 at_clck_cpwd_fac[passwd_type] == NULL)
1392 snprintf(buf, sizeof(buf), "AT+CPWD=\"%s\",\"%s\",\"%s\"",
1393 at_clck_cpwd_fac[passwd_type], old_passwd, new_passwd);
1395 ret = g_at_chat_send(sd->chat, buf, none_prefix,
1396 at_lock_unlock_cb, cbd, g_free);
1398 memset(buf, 0, sizeof(buf));
1406 CALLBACK_WITH_FAILURE(cb, data);
1409 static void at_lock_status_cb(gboolean ok, GAtResult *result,
1412 struct cb_data *cbd = user_data;
1414 ofono_sim_locked_cb_t cb = cbd->cb;
1415 struct ofono_error error;
1418 decode_at_error(&error, g_at_result_final_response(result));
1421 cb(&error, -1, cbd->data);
1425 g_at_result_iter_init(&iter, result);
1427 if (!g_at_result_iter_next(&iter, "+CLCK:")) {
1428 CALLBACK_WITH_FAILURE(cb, -1, cbd->data);
1432 g_at_result_iter_next_number(&iter, &locked);
1434 DBG("lock_status_cb: %i", locked);
1436 cb(&error, locked, cbd->data);
1439 static void at_pin_query_enabled(struct ofono_sim *sim,
1440 enum ofono_sim_password_type passwd_type,
1441 ofono_sim_locked_cb_t cb, void *data)
1443 struct sim_data *sd = ofono_sim_get_data(sim);
1444 struct cb_data *cbd = cb_data_new(cb, data);
1446 unsigned int len = sizeof(at_clck_cpwd_fac) / sizeof(*at_clck_cpwd_fac);
1448 if (passwd_type >= len || at_clck_cpwd_fac[passwd_type] == NULL)
1451 snprintf(buf, sizeof(buf), "AT+CLCK=\"%s\",2",
1452 at_clck_cpwd_fac[passwd_type]);
1454 if (g_at_chat_send(sd->chat, buf, clck_prefix,
1455 at_lock_status_cb, cbd, g_free) > 0)
1461 CALLBACK_WITH_FAILURE(cb, -1, data);
1464 static gboolean at_sim_register(gpointer user)
1466 struct ofono_sim *sim = user;
1468 ofono_sim_register(sim);
1473 static int at_sim_probe(struct ofono_sim *sim, unsigned int vendor,
1476 GAtChat *chat = data;
1477 struct sim_data *sd;
1479 sd = g_new0(struct sim_data, 1);
1480 sd->chat = g_at_chat_clone(chat);
1481 sd->vendor = vendor;
1483 if (sd->vendor == OFONO_VENDOR_MBM)
1484 g_at_chat_send(sd->chat, "AT*EPEE=1", NULL, NULL, NULL, NULL);
1486 ofono_sim_set_data(sim, sd);
1487 g_idle_add(at_sim_register, sim);
1492 static void at_sim_remove(struct ofono_sim *sim)
1494 struct sim_data *sd = ofono_sim_get_data(sim);
1496 g_idle_remove_by_data(sim);
1497 /* Cleanup potential SIM state polling */
1498 at_util_sim_state_query_free(sd->sim_state_query);
1500 ofono_sim_set_data(sim, NULL);
1502 g_at_chat_unref(sd->chat);
1506 static struct ofono_sim_driver driver = {
1508 .probe = at_sim_probe,
1509 .remove = at_sim_remove,
1510 .read_file_info = at_sim_read_info,
1511 .read_file_transparent = at_sim_read_binary,
1512 .read_file_linear = at_sim_read_record,
1513 .read_file_cyclic = at_sim_read_record,
1514 .write_file_transparent = at_sim_update_binary,
1515 .write_file_linear = at_sim_update_record,
1516 .write_file_cyclic = at_sim_update_cyclic,
1517 .read_imsi = at_read_imsi,
1518 .query_passwd_state = at_pin_query,
1519 .query_pin_retries = at_pin_retries_query,
1520 .send_passwd = at_pin_send,
1521 .reset_passwd = at_pin_send_puk,
1522 .lock = at_pin_enable,
1523 .change_passwd = at_change_passwd,
1524 .query_locked = at_pin_query_enabled,
1527 static struct ofono_sim_driver driver_noef = {
1528 .name = "atmodem-noef",
1529 .probe = at_sim_probe,
1530 .remove = at_sim_remove,
1531 .read_imsi = at_read_imsi,
1532 .query_passwd_state = at_pin_query,
1533 .query_pin_retries = at_pin_retries_query,
1534 .send_passwd = at_pin_send,
1535 .reset_passwd = at_pin_send_puk,
1536 .lock = at_pin_enable,
1537 .change_passwd = at_change_passwd,
1538 .query_locked = at_pin_query_enabled,
1541 void at_sim_init(void)
1543 ofono_sim_driver_register(&driver);
1544 ofono_sim_driver_register(&driver_noef);
1547 void at_sim_exit(void)
1549 ofono_sim_driver_unregister(&driver);
1550 ofono_sim_driver_unregister(&driver_noef);