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 *qpinc_prefix[] = { "+QPINC:", NULL };
71 static const char *upincnt_prefix[] = { "+UPINCNT:", NULL };
72 static const char *none_prefix[] = { NULL };
74 static void at_crsm_info_cb(gboolean ok, GAtResult *result, gpointer user_data)
76 struct cb_data *cbd = user_data;
78 ofono_sim_file_info_cb_t cb = cbd->cb;
79 struct ofono_error error;
80 const guint8 *response;
84 unsigned char access[3];
85 unsigned char file_status;
87 decode_at_error(&error, g_at_result_final_response(result));
90 cb(&error, -1, -1, -1, NULL, EF_STATUS_INVALIDATED, cbd->data);
94 g_at_result_iter_init(&iter, result);
96 if (!g_at_result_iter_next(&iter, "+CRSM:"))
99 g_at_result_iter_next_number(&iter, &sw1);
100 g_at_result_iter_next_number(&iter, &sw2);
102 if (!g_at_result_iter_next_hexstring(&iter, &response, &len) ||
103 (sw1 != 0x90 && sw1 != 0x91 && sw1 != 0x92) ||
104 (sw1 == 0x90 && sw2 != 0x00)) {
105 memset(&error, 0, sizeof(error));
107 error.type = OFONO_ERROR_TYPE_SIM;
108 error.error = (sw1 << 8) | sw2;
110 cb(&error, -1, -1, -1, NULL, EF_STATUS_INVALIDATED, cbd->data);
114 DBG("crsm_info_cb: %02x, %02x, %i", sw1, sw2, len);
116 if (response[0] == 0x62) {
117 ok = sim_parse_3g_get_response(response, len, &flen, &rlen,
120 file_status = EF_STATUS_VALID;
122 ok = sim_parse_2g_get_response(response, len, &flen, &rlen,
123 &str, access, &file_status);
128 cb(&error, flen, str, rlen, access, file_status, cbd->data);
133 CALLBACK_WITH_FAILURE(cb, -1, -1, -1, NULL,
134 EF_STATUS_INVALIDATED, cbd->data);
137 static void at_sim_read_info(struct ofono_sim *sim, int fileid,
138 const unsigned char *path,
139 unsigned int path_len,
140 ofono_sim_file_info_cb_t cb, void *data)
142 struct sim_data *sd = ofono_sim_get_data(sim);
147 if (sd->vendor == OFONO_VENDOR_OPTION_HSO) {
148 unsigned char access[3] = { 0x00, 0x00, 0x00 };
150 if (fileid == SIM_EFAD_FILEID) {
151 CALLBACK_WITH_SUCCESS(cb, 4, 0, 0, access,
152 EF_STATUS_VALID, data);
157 cbd = cb_data_new(cb, data);
159 len = snprintf(buf, sizeof(buf), "AT+CRSM=192,%i", fileid);
161 switch (sd->vendor) {
167 case OFONO_VENDOR_ZTE:
168 case OFONO_VENDOR_HUAWEI:
169 case OFONO_VENDOR_SIERRA:
170 case OFONO_VENDOR_SPEEDUP:
171 case OFONO_VENDOR_QUALCOMM_MSM:
172 case OFONO_VENDOR_SIMCOM:
173 /* Maximum possible length */
174 len += sprintf(buf + len, ",0,0,255");
179 len += sprintf(buf + len, ",,\"");
181 for (; path_len; path_len--)
182 len += sprintf(buf + len, "%02hhX", *path++);
188 if (g_at_chat_send(sd->chat, buf, crsm_prefix,
189 at_crsm_info_cb, cbd, g_free) > 0)
194 CALLBACK_WITH_FAILURE(cb, -1, -1, -1, NULL,
195 EF_STATUS_INVALIDATED, data);
198 static void at_crsm_read_cb(gboolean ok, GAtResult *result,
201 struct cb_data *cbd = user_data;
203 ofono_sim_read_cb_t cb = cbd->cb;
204 struct ofono_error error;
205 const guint8 *response;
208 decode_at_error(&error, g_at_result_final_response(result));
211 cb(&error, NULL, 0, cbd->data);
215 g_at_result_iter_init(&iter, result);
217 if (!g_at_result_iter_next(&iter, "+CRSM:")) {
218 CALLBACK_WITH_FAILURE(cb, NULL, 0, cbd->data);
222 g_at_result_iter_next_number(&iter, &sw1);
223 g_at_result_iter_next_number(&iter, &sw2);
225 if ((sw1 != 0x90 && sw1 != 0x91 && sw1 != 0x92 && sw1 != 0x9f) ||
226 (sw1 == 0x90 && sw2 != 0x00)) {
227 memset(&error, 0, sizeof(error));
229 error.type = OFONO_ERROR_TYPE_SIM;
230 error.error = (sw1 << 8) | sw2;
232 cb(&error, NULL, 0, cbd->data);
236 if (!g_at_result_iter_next_hexstring(&iter, &response, &len)) {
237 CALLBACK_WITH_FAILURE(cb, NULL, 0, cbd->data);
241 DBG("crsm_read_cb: %02x, %02x, %d", sw1, sw2, len);
243 cb(&error, response, len, cbd->data);
246 static void at_sim_read_binary(struct ofono_sim *sim, int fileid,
247 int start, int length,
248 const unsigned char *path,
249 unsigned int path_len,
250 ofono_sim_read_cb_t cb, void *data)
252 struct sim_data *sd = ofono_sim_get_data(sim);
253 struct cb_data *cbd = cb_data_new(cb, data);
257 len = snprintf(buf, sizeof(buf), "AT+CRSM=176,%i,%i,%i,%i", fileid,
258 start >> 8, start & 0xff, length);
265 for (; path_len; path_len--)
266 len += sprintf(buf + len, "%02hhX", *path++);
272 if (g_at_chat_send(sd->chat, buf, crsm_prefix,
273 at_crsm_read_cb, cbd, g_free) > 0)
278 CALLBACK_WITH_FAILURE(cb, NULL, 0, data);
281 static void at_sim_read_record(struct ofono_sim *sim, int fileid,
282 int record, int length,
283 const unsigned char *path,
284 unsigned int path_len,
285 ofono_sim_read_cb_t cb, void *data)
287 struct sim_data *sd = ofono_sim_get_data(sim);
288 struct cb_data *cbd = cb_data_new(cb, data);
291 snprintf(buf, sizeof(buf), "AT+CRSM=178,%i,%i,4,%i", fileid,
294 if (g_at_chat_send(sd->chat, buf, crsm_prefix,
295 at_crsm_read_cb, cbd, g_free) > 0)
300 CALLBACK_WITH_FAILURE(cb, NULL, 0, data);
303 static void at_crsm_update_cb(gboolean ok, GAtResult *result,
306 struct cb_data *cbd = user_data;
308 ofono_sim_write_cb_t cb = cbd->cb;
309 struct ofono_error error;
312 decode_at_error(&error, g_at_result_final_response(result));
315 cb(&error, cbd->data);
319 g_at_result_iter_init(&iter, result);
321 if (!g_at_result_iter_next(&iter, "+CRSM:")) {
322 CALLBACK_WITH_FAILURE(cb, cbd->data);
326 g_at_result_iter_next_number(&iter, &sw1);
327 g_at_result_iter_next_number(&iter, &sw2);
329 if ((sw1 != 0x90 && sw1 != 0x91 && sw1 != 0x92 && sw1 != 0x9f) ||
330 (sw1 == 0x90 && sw2 != 0x00)) {
331 memset(&error, 0, sizeof(error));
333 error.type = OFONO_ERROR_TYPE_SIM;
334 error.error = (sw1 << 8) | sw2;
337 DBG("crsm_update_cb: %02x, %02x", sw1, sw2);
339 cb(&error, cbd->data);
342 static void at_sim_update_file(struct ofono_sim *sim, int cmd, int fileid,
343 int p1, int p2, int p3,
344 const unsigned char *value,
345 const unsigned char *path,
346 unsigned int path_len,
347 ofono_sim_write_cb_t cb, void *data)
349 struct sim_data *sd = ofono_sim_get_data(sim);
350 struct cb_data *cbd = cb_data_new(cb, data);
353 int size = 38 + p3 * 2;
357 buf = g_try_new(char, size);
361 len = sprintf(buf, "AT+CRSM=%i,%i,%i,%i,%i,\"", cmd, fileid,p1, p2, p3);
364 len += sprintf(buf + len, "%02hhX", *value++);
369 ret = g_at_chat_send(sd->chat, buf, crsm_prefix,
370 at_crsm_update_cb, cbd, g_free);
380 CALLBACK_WITH_FAILURE(cb, data);
383 static void at_sim_update_binary(struct ofono_sim *sim, int fileid,
384 int start, int length,
385 const unsigned char *value,
386 const unsigned char *path,
387 unsigned int path_len,
388 ofono_sim_write_cb_t cb, void *data)
390 at_sim_update_file(sim, 214, fileid, start >> 8, start & 0xff,
391 length, value, path, path_len, cb, data);
394 static void at_sim_update_record(struct ofono_sim *sim, int fileid,
395 int record, int length,
396 const unsigned char *value,
397 const unsigned char *path,
398 unsigned int path_len,
399 ofono_sim_write_cb_t cb, void *data)
401 at_sim_update_file(sim, 220, fileid, record, 4, length,
402 value, path, path_len, cb, data);
405 static void at_sim_update_cyclic(struct ofono_sim *sim, int fileid,
406 int length, const unsigned char *value,
407 const unsigned char *path,
408 unsigned int path_len,
409 ofono_sim_write_cb_t cb, void *data)
411 at_sim_update_file(sim, 220, fileid, 0, 3, length, value,
412 path, path_len, cb, data);
415 static void at_cimi_cb(gboolean ok, GAtResult *result, gpointer user_data)
417 struct cb_data *cbd = user_data;
419 ofono_sim_imsi_cb_t cb = cbd->cb;
420 struct ofono_error error;
424 decode_at_error(&error, g_at_result_final_response(result));
427 cb(&error, NULL, cbd->data);
431 g_at_result_iter_init(&iter, result);
433 for (i = 0; i < g_at_result_num_response_lines(result); i++)
434 g_at_result_iter_next(&iter, NULL);
436 imsi = g_at_result_iter_raw_line(&iter);
438 DBG("cimi_cb: %s", imsi);
440 cb(&error, imsi, cbd->data);
443 static void at_read_imsi(struct ofono_sim *sim, ofono_sim_imsi_cb_t cb,
446 struct sim_data *sd = ofono_sim_get_data(sim);
447 struct cb_data *cbd = cb_data_new(cb, data);
449 if (g_at_chat_send(sd->chat, "AT+CIMI", NULL,
450 at_cimi_cb, cbd, g_free) > 0)
455 CALLBACK_WITH_FAILURE(cb, NULL, data);
459 enum ofono_sim_password_type type;
461 } const at_sim_name[] = {
462 { OFONO_SIM_PASSWORD_NONE, "READY" },
463 { OFONO_SIM_PASSWORD_SIM_PIN, "SIM PIN" },
464 { OFONO_SIM_PASSWORD_SIM_PUK, "SIM PUK" },
465 { OFONO_SIM_PASSWORD_PHSIM_PIN, "PH-SIM PIN" },
466 { OFONO_SIM_PASSWORD_PHFSIM_PIN, "PH-FSIM PIN" },
467 { OFONO_SIM_PASSWORD_PHFSIM_PUK, "PH-FSIM PUK" },
468 { OFONO_SIM_PASSWORD_SIM_PIN2, "SIM PIN2" },
469 { OFONO_SIM_PASSWORD_SIM_PUK2, "SIM PUK2" },
470 { OFONO_SIM_PASSWORD_PHNET_PIN, "PH-NET PIN" },
471 { OFONO_SIM_PASSWORD_PHNET_PUK, "PH-NET PUK" },
472 { OFONO_SIM_PASSWORD_PHNETSUB_PIN, "PH-NETSUB PIN" },
473 { OFONO_SIM_PASSWORD_PHNETSUB_PUK, "PH-NETSUB PUK" },
474 { OFONO_SIM_PASSWORD_PHSP_PIN, "PH-SP PIN" },
475 { OFONO_SIM_PASSWORD_PHSP_PUK, "PH-SP PUK" },
476 { OFONO_SIM_PASSWORD_PHCORP_PIN, "PH-CORP PIN" },
477 { OFONO_SIM_PASSWORD_PHCORP_PUK, "PH-CORP PUK" },
480 #define BUILD_PIN_RETRIES_ARRAY(passwd_types, passwd_types_cnt, retry) \
481 for (i = 0; i < OFONO_SIM_PASSWORD_INVALID; i++) \
484 for (i = 0; i < passwd_types_cnt; i++) { \
487 if (!g_at_result_iter_next_number(&iter, &val)) \
490 retry[passwd_types[i]] = val; \
492 DBG("retry counter id=%d, val=%d", passwd_types[i], \
493 retry[passwd_types[i]]); \
496 static void huawei_cpin_cb(gboolean ok, GAtResult *result, gpointer user_data)
498 struct cb_data *cbd = user_data;
499 ofono_sim_pin_retries_cb_t cb = cbd->cb;
500 const char *final = g_at_result_final_response(result);
502 struct ofono_error error;
503 int retries[OFONO_SIM_PASSWORD_INVALID];
505 static enum ofono_sim_password_type password_types[] = {
506 OFONO_SIM_PASSWORD_SIM_PUK,
507 OFONO_SIM_PASSWORD_SIM_PIN,
508 OFONO_SIM_PASSWORD_SIM_PUK2,
509 OFONO_SIM_PASSWORD_SIM_PIN2,
512 decode_at_error(&error, final);
515 cb(&error, NULL, cbd->data);
519 g_at_result_iter_init(&iter, result);
521 if (!g_at_result_iter_next(&iter, "^CPIN:"))
524 /* Skip status since we are not interested in this */
525 if (!g_at_result_iter_skip_next(&iter))
528 /* Skip "overall counter" since we'll grab each one individually */
529 if (!g_at_result_iter_skip_next(&iter))
532 BUILD_PIN_RETRIES_ARRAY(password_types, ARRAY_SIZE(password_types),
535 cb(&error, retries, cbd->data);
540 CALLBACK_WITH_FAILURE(cb, NULL, cbd->data);
543 static void pinnum_cb(gboolean ok, GAtResult *result, gpointer user_data)
545 struct cb_data *cbd = user_data;
546 ofono_sim_pin_retries_cb_t cb = cbd->cb;
547 const char *final = g_at_result_final_response(result);
549 struct ofono_error error;
550 int retries[OFONO_SIM_PASSWORD_INVALID];
552 static enum ofono_sim_password_type password_types[] = {
553 OFONO_SIM_PASSWORD_SIM_PIN,
554 OFONO_SIM_PASSWORD_SIM_PUK,
555 OFONO_SIM_PASSWORD_SIM_PIN2,
556 OFONO_SIM_PASSWORD_SIM_PUK2,
560 decode_at_error(&error, final);
563 cb(&error, NULL, cbd->data);
567 g_at_result_iter_init(&iter, result);
569 if (!g_at_result_iter_next(&iter, "%PINNUM:"))
572 BUILD_PIN_RETRIES_ARRAY(password_types, ARRAY_SIZE(password_types),
575 cb(&error, retries, cbd->data);
580 CALLBACK_WITH_FAILURE(cb, NULL, cbd->data);
583 static void zpinpuk_cb(gboolean ok, GAtResult *result, gpointer user_data)
585 struct cb_data *cbd = user_data;
586 ofono_sim_pin_retries_cb_t cb = cbd->cb;
587 const char *final = g_at_result_final_response(result);
589 struct ofono_error error;
590 int retries[OFONO_SIM_PASSWORD_INVALID];
592 static enum ofono_sim_password_type password_types[] = {
593 OFONO_SIM_PASSWORD_SIM_PIN,
594 OFONO_SIM_PASSWORD_SIM_PUK,
598 decode_at_error(&error, final);
601 cb(&error, NULL, cbd->data);
605 g_at_result_iter_init(&iter, result);
607 if (!g_at_result_iter_next(&iter, "+ZPINPUK:"))
610 BUILD_PIN_RETRIES_ARRAY(password_types, ARRAY_SIZE(password_types),
613 cb(&error, retries, cbd->data);
618 CALLBACK_WITH_FAILURE(cb, NULL, cbd->data);
621 static void xpincnt_cb(gboolean ok, GAtResult *result, gpointer user_data)
623 struct cb_data *cbd = user_data;
624 ofono_sim_pin_retries_cb_t cb = cbd->cb;
625 const char *final = g_at_result_final_response(result);
627 struct ofono_error error;
628 int retries[OFONO_SIM_PASSWORD_INVALID];
630 static enum ofono_sim_password_type password_types[] = {
631 OFONO_SIM_PASSWORD_SIM_PIN,
632 OFONO_SIM_PASSWORD_SIM_PIN2,
633 OFONO_SIM_PASSWORD_SIM_PUK,
634 OFONO_SIM_PASSWORD_SIM_PUK2,
637 decode_at_error(&error, final);
640 cb(&error, NULL, cbd->data);
644 g_at_result_iter_init(&iter, result);
646 if (!g_at_result_iter_next(&iter, "+XPINCNT:"))
649 BUILD_PIN_RETRIES_ARRAY(password_types, ARRAY_SIZE(password_types),
652 cb(&error, retries, cbd->data);
657 CALLBACK_WITH_FAILURE(cb, NULL, cbd->data);
660 static void oercn_cb(gboolean ok, GAtResult *result, gpointer user_data)
662 struct cb_data *cbd = user_data;
663 ofono_sim_pin_retries_cb_t cb = cbd->cb;
664 const char *final = g_at_result_final_response(result);
666 struct ofono_error error;
667 int retries[OFONO_SIM_PASSWORD_INVALID];
669 static enum ofono_sim_password_type password_types[] = {
670 OFONO_SIM_PASSWORD_SIM_PIN,
671 OFONO_SIM_PASSWORD_SIM_PUK,
674 decode_at_error(&error, final);
677 cb(&error, NULL, cbd->data);
681 g_at_result_iter_init(&iter, result);
683 if (!g_at_result_iter_next(&iter, "_OERCN:"))
686 BUILD_PIN_RETRIES_ARRAY(password_types, ARRAY_SIZE(password_types),
689 cb(&error, retries, cbd->data);
694 CALLBACK_WITH_FAILURE(cb, NULL, cbd->data);
697 static void cpnnum_cb(gboolean ok, GAtResult *result, gpointer user_data)
699 struct cb_data *cbd = user_data;
700 ofono_sim_pin_retries_cb_t cb = cbd->cb;
701 const char *final = g_at_result_final_response(result);
703 struct ofono_error error;
707 int retries[OFONO_SIM_PASSWORD_INVALID];
710 decode_at_error(&error, final);
713 cb(&error, NULL, cbd->data);
717 g_at_result_iter_init(&iter, result);
719 for (num = 0; num < g_at_result_num_response_lines(result); num++)
720 g_at_result_iter_next(&iter, NULL);
722 line = g_at_result_iter_raw_line(&iter);
726 for (i = 0; i < OFONO_SIM_PASSWORD_INVALID; i++)
729 entries = g_strsplit(line, "; ", -1);
731 for (num = 0; entries[num]; num++) {
734 if (strlen(entries[num]) < 5)
737 retry = strtol(entries[num] + 5, NULL, 10);
738 if (retry == 0 && errno == EINVAL)
741 if (g_str_has_prefix(entries[num], "PIN1=") == TRUE)
742 retries[OFONO_SIM_PASSWORD_SIM_PIN] = retry;
743 else if (g_str_has_prefix(entries[num], "PUK1=") == TRUE)
744 retries[OFONO_SIM_PASSWORD_SIM_PUK] = retry;
745 else if (g_str_has_prefix(entries[num], "PIN2=") == TRUE)
746 retries[OFONO_SIM_PASSWORD_SIM_PIN2] = retry;
747 else if (g_str_has_prefix(entries[num], "PUK2=") == TRUE)
748 retries[OFONO_SIM_PASSWORD_SIM_PUK2] = retry;
753 cb(&error, retries, cbd->data);
756 static void at_epin_cb(gboolean ok, GAtResult *result, gpointer user_data)
758 struct cb_data *cbd = user_data;
759 ofono_sim_pin_retries_cb_t cb = cbd->cb;
760 const char *final = g_at_result_final_response(result);
762 struct ofono_error error;
763 int retries[OFONO_SIM_PASSWORD_INVALID];
765 static enum ofono_sim_password_type password_types[] = {
766 OFONO_SIM_PASSWORD_SIM_PIN,
767 OFONO_SIM_PASSWORD_SIM_PUK,
768 OFONO_SIM_PASSWORD_SIM_PIN2,
769 OFONO_SIM_PASSWORD_SIM_PUK2,
772 decode_at_error(&error, final);
775 cb(&error, NULL, cbd->data);
779 g_at_result_iter_init(&iter, result);
781 if (!g_at_result_iter_next(&iter, "*EPIN:"))
784 BUILD_PIN_RETRIES_ARRAY(password_types, ARRAY_SIZE(password_types),
787 cb(&error, retries, cbd->data);
792 CALLBACK_WITH_FAILURE(cb, NULL, cbd->data);
795 static void at_cpinr_cb(gboolean ok, GAtResult *result, gpointer user_data)
797 struct cb_data *cbd = user_data;
798 ofono_sim_pin_retries_cb_t cb = cbd->cb;
800 struct ofono_error error;
801 int retries[OFONO_SIM_PASSWORD_INVALID];
802 size_t len = sizeof(at_sim_name) / sizeof(*at_sim_name);
805 decode_at_error(&error, g_at_result_final_response(result));
808 cb(&error, NULL, cbd->data);
812 for (i = 0; i < OFONO_SIM_PASSWORD_INVALID; i++)
815 g_at_result_iter_init(&iter, result);
817 /* Ignore +CPINRE results... */
818 while (g_at_result_iter_next(&iter, "+CPINR:")) {
822 if (!g_at_result_iter_next_unquoted_string(&iter, &name))
825 if (!g_at_result_iter_next_number(&iter, &val))
828 for (i = 1; i < len; i++) {
829 if (!strcmp(name, at_sim_name[i].name)) {
830 retries[at_sim_name[i].type] = val;
836 cb(&error, retries, cbd->data);
839 static void at_spic_cb(gboolean ok, GAtResult *result, gpointer user_data)
841 struct cb_data *cbd = user_data;
842 ofono_sim_pin_retries_cb_t cb = cbd->cb;
843 const char *final = g_at_result_final_response(result);
845 struct ofono_error error;
846 int retries[OFONO_SIM_PASSWORD_INVALID];
848 static enum ofono_sim_password_type password_types[] = {
849 OFONO_SIM_PASSWORD_SIM_PIN,
850 OFONO_SIM_PASSWORD_SIM_PUK,
851 OFONO_SIM_PASSWORD_SIM_PIN2,
852 OFONO_SIM_PASSWORD_SIM_PUK2,
855 decode_at_error(&error, final);
858 cb(&error, NULL, cbd->data);
862 g_at_result_iter_init(&iter, result);
864 if (!g_at_result_iter_next(&iter, "+SPIC:"))
867 BUILD_PIN_RETRIES_ARRAY(password_types, ARRAY_SIZE(password_types),
870 cb(&error, retries, cbd->data);
875 CALLBACK_WITH_FAILURE(cb, NULL, cbd->data);
878 #define AT_PCT_SET_RETRIES(retries, pin_type, value) \
879 retries[pin_type] = value; \
880 DBG("retry counter id=%d, val=%d", pin_type, value);
882 static void at_pct_cb(gboolean ok, GAtResult *result, gpointer user_data)
884 struct cb_data *cbd = user_data;
885 ofono_sim_pin_retries_cb_t cb = cbd->cb;
886 struct ofono_sim *sim = cbd->user;
887 const char *final = g_at_result_final_response(result);
889 struct ofono_error error;
890 int retries[OFONO_SIM_PASSWORD_INVALID];
892 enum ofono_sim_password_type pin_type;
894 decode_at_error(&error, final);
897 cb(&error, NULL, cbd->data);
901 g_at_result_iter_init(&iter, result);
903 for (i = 0; i < OFONO_SIM_PASSWORD_INVALID; i++)
906 pin_type = ofono_sim_get_password_type(sim);
907 if (pin_type == OFONO_SIM_PASSWORD_NONE) {
908 DBG("Note: No password required, returning maximum retries:");
910 AT_PCT_SET_RETRIES(retries, OFONO_SIM_PASSWORD_SIM_PIN, 3);
911 AT_PCT_SET_RETRIES(retries, OFONO_SIM_PASSWORD_SIM_PIN2, 3);
912 AT_PCT_SET_RETRIES(retries, OFONO_SIM_PASSWORD_SIM_PUK, 10);
913 AT_PCT_SET_RETRIES(retries, OFONO_SIM_PASSWORD_SIM_PUK2, 10);
918 if (g_at_result_iter_next(&iter, "#PCT:") == FALSE)
921 if (g_at_result_iter_next_number(&iter, &retries[pin_type]) == FALSE)
924 DBG("retry counter id=%d, val=%d", pin_type, retries[pin_type]);
927 cb(&error, retries, cbd->data);
932 CALLBACK_WITH_FAILURE(cb, NULL, cbd->data);
935 static void at_pnnm_cb(gboolean ok, GAtResult *result, gpointer user_data)
937 struct cb_data *cbd = user_data;
938 ofono_sim_pin_retries_cb_t cb = cbd->cb;
939 const char *final = g_at_result_final_response(result);
941 struct ofono_error error;
942 int retries[OFONO_SIM_PASSWORD_INVALID];
944 static enum ofono_sim_password_type password_types[] = {
945 OFONO_SIM_PASSWORD_SIM_PIN,
946 OFONO_SIM_PASSWORD_SIM_PUK,
949 decode_at_error(&error, final);
952 cb(&error, NULL, cbd->data);
956 g_at_result_iter_init(&iter, result);
958 if (!g_at_result_iter_next(&iter, "+PNNM:"))
961 BUILD_PIN_RETRIES_ARRAY(password_types, ARRAY_SIZE(password_types),
964 cb(&error, retries, cbd->data);
969 CALLBACK_WITH_FAILURE(cb, NULL, cbd->data);
972 static void at_qpinc_cb(gboolean ok, GAtResult *result, gpointer user_data)
974 struct cb_data *cbd = user_data;
975 ofono_sim_pin_retries_cb_t cb = cbd->cb;
976 const char *final = g_at_result_final_response(result);
978 struct ofono_error error;
979 int retries[OFONO_SIM_PASSWORD_INVALID];
982 decode_at_error(&error, final);
985 cb(&error, NULL, cbd->data);
989 for (i = 0; i < OFONO_SIM_PASSWORD_INVALID; i++)
992 g_at_result_iter_init(&iter, result);
994 while (g_at_result_iter_next(&iter, "+QPINC:")) {
998 if (!g_at_result_iter_next_string(&iter, &name))
1000 if (!g_at_result_iter_next_number(&iter, &pin))
1002 if (!g_at_result_iter_next_number(&iter, &puk))
1005 if (!strcmp(name, "SC")) {
1006 retries[OFONO_SIM_PASSWORD_SIM_PIN] = pin;
1007 retries[OFONO_SIM_PASSWORD_SIM_PUK] = puk;
1008 } else if (!strcmp(name, "P2")) {
1009 retries[OFONO_SIM_PASSWORD_SIM_PIN2] = pin;
1010 retries[OFONO_SIM_PASSWORD_SIM_PUK2] = puk;
1014 cb(&error, retries, cbd->data);
1017 static void upincnt_cb(gboolean ok, GAtResult *result, gpointer user_data)
1019 struct cb_data *cbd = user_data;
1020 ofono_sim_pin_retries_cb_t cb = cbd->cb;
1021 const char *final = g_at_result_final_response(result);
1023 struct ofono_error error;
1024 int retries[OFONO_SIM_PASSWORD_INVALID];
1026 static enum ofono_sim_password_type password_types[] = {
1027 OFONO_SIM_PASSWORD_SIM_PIN,
1028 OFONO_SIM_PASSWORD_SIM_PIN2,
1029 OFONO_SIM_PASSWORD_SIM_PUK,
1030 OFONO_SIM_PASSWORD_SIM_PUK2,
1033 decode_at_error(&error, final);
1036 cb(&error, NULL, cbd->data);
1040 g_at_result_iter_init(&iter, result);
1042 if (!g_at_result_iter_next(&iter, "+UPINCNT:"))
1045 BUILD_PIN_RETRIES_ARRAY(password_types, ARRAY_SIZE(password_types),
1048 cb(&error, retries, cbd->data);
1053 CALLBACK_WITH_FAILURE(cb, NULL, cbd->data);
1056 static void at_pin_retries_query(struct ofono_sim *sim,
1057 ofono_sim_pin_retries_cb_t cb,
1060 struct sim_data *sd = ofono_sim_get_data(sim);
1061 struct cb_data *cbd = cb_data_new(cb, data);
1066 switch (sd->vendor) {
1067 case OFONO_VENDOR_IFX:
1068 if (g_at_chat_send(sd->chat, "AT+XPINCNT", xpincnt_prefix,
1069 xpincnt_cb, cbd, g_free) > 0)
1072 case OFONO_VENDOR_SPEEDUP:
1073 if (g_at_chat_send(sd->chat, "AT+CPNNUM", NULL,
1074 cpnnum_cb, cbd, g_free) > 0)
1077 case OFONO_VENDOR_OPTION_HSO:
1078 if (g_at_chat_send(sd->chat, "AT_OERCN?", oercn_prefix,
1079 oercn_cb, cbd, g_free) > 0)
1082 case OFONO_VENDOR_HUAWEI:
1083 if (g_at_chat_send(sd->chat, "AT^CPIN?", huawei_cpin_prefix,
1084 huawei_cpin_cb, cbd, g_free) > 0)
1087 case OFONO_VENDOR_ICERA:
1088 if (g_at_chat_send(sd->chat, "AT%PINNUM?", pinnum_prefix,
1089 pinnum_cb, cbd, g_free) > 0)
1092 case OFONO_VENDOR_ZTE:
1093 if (g_at_chat_send(sd->chat, "AT+ZPINPUK=?", zpinpuk_prefix,
1094 zpinpuk_cb, cbd, g_free) > 0)
1097 case OFONO_VENDOR_MBM:
1098 if (g_at_chat_send(sd->chat, "AT*EPIN?", epin_prefix,
1099 at_epin_cb, cbd, g_free) > 0)
1102 case OFONO_VENDOR_SIMCOM:
1103 if (g_at_chat_send(sd->chat, "AT+SPIC", spic_prefix,
1104 at_spic_cb, cbd, g_free) > 0)
1107 case OFONO_VENDOR_TELIT:
1108 if (g_at_chat_send(sd->chat, "AT#PCT", pct_prefix,
1109 at_pct_cb, cbd, g_free) > 0)
1112 case OFONO_VENDOR_ALCATEL:
1113 if (g_at_chat_send(sd->chat, "AT+PNNM?", pnnm_prefix,
1114 at_pnnm_cb, cbd, g_free) > 0)
1117 case OFONO_VENDOR_QUECTEL:
1118 if (g_at_chat_send(sd->chat, "AT+QPINC?", qpinc_prefix,
1119 at_qpinc_cb, cbd, g_free) > 0)
1122 case OFONO_VENDOR_UBLOX:
1123 if (g_at_chat_send(sd->chat, "AT+UPINCNT", upincnt_prefix,
1124 upincnt_cb, cbd, g_free) > 0)
1128 if (g_at_chat_send(sd->chat, "AT+CPINR", cpinr_prefixes,
1129 at_cpinr_cb, cbd, g_free) > 0)
1136 CALLBACK_WITH_FAILURE(cb, NULL, data);
1139 static int needs_wavecom_sim_quirk(int vendor)
1141 return vendor == OFONO_VENDOR_WAVECOM ||
1142 vendor == OFONO_VENDOR_WAVECOM_Q2XXX;
1145 static void at_cpin_cb(gboolean ok, GAtResult *result, gpointer user_data)
1147 struct cb_data *cbd = user_data;
1148 struct sim_data *sd = ofono_sim_get_data(cbd->user);
1150 ofono_sim_passwd_cb_t cb = cbd->cb;
1151 struct ofono_error error;
1152 const char *pin_required;
1153 int pin_type = OFONO_SIM_PASSWORD_INVALID;
1155 int len = sizeof(at_sim_name) / sizeof(*at_sim_name);
1156 const char *final = g_at_result_final_response(result);
1158 if (needs_wavecom_sim_quirk(sd->vendor) && ok && strlen(final) > 7)
1159 decode_at_error(&error, "OK");
1161 decode_at_error(&error, final);
1164 cb(&error, -1, cbd->data);
1168 if (needs_wavecom_sim_quirk(sd->vendor)) {
1170 pin_required = final + 7;
1172 g_at_result_iter_init(&iter, result);
1174 if (!g_at_result_iter_next(&iter, "+CPIN:")) {
1175 CALLBACK_WITH_FAILURE(cb, -1, cbd->data);
1179 g_at_result_iter_next_unquoted_string(&iter, &pin_required);
1182 for (i = 0; i < len; i++) {
1183 if (strcmp(pin_required, at_sim_name[i].name))
1186 pin_type = at_sim_name[i].type;
1190 if (pin_type == OFONO_SIM_PASSWORD_INVALID) {
1191 CALLBACK_WITH_FAILURE(cb, -1, cbd->data);
1195 DBG("crsm_pin_cb: %s", pin_required);
1197 cb(&error, pin_type, cbd->data);
1200 static void at_pin_query(struct ofono_sim *sim, ofono_sim_passwd_cb_t cb,
1203 struct sim_data *sd = ofono_sim_get_data(sim);
1204 struct cb_data *cbd = cb_data_new(cb, data);
1208 if (g_at_chat_send(sd->chat, "AT+CPIN?", cpin_prefix,
1209 at_cpin_cb, cbd, g_free) > 0)
1214 CALLBACK_WITH_FAILURE(cb, -1, data);
1217 static void at_xsim_notify(GAtResult *result, gpointer user_data)
1219 struct cb_data *cbd = user_data;
1220 struct sim_data *sd = cbd->user;
1221 ofono_sim_lock_unlock_cb_t cb = cbd->cb;
1222 struct ofono_error error = { .type = OFONO_ERROR_TYPE_NO_ERROR };
1226 g_at_result_iter_init(&iter, result);
1228 if (!g_at_result_iter_next(&iter, "+XSIM:"))
1231 if (!g_at_result_iter_next_number(&iter, &state))
1235 case 3: /* PIN verified – Ready */
1241 cb(&error, cbd->data);
1243 g_at_chat_unregister(sd->chat, sd->ready_id);
1247 static void at_epev_notify(GAtResult *result, gpointer user_data)
1249 struct cb_data *cbd = user_data;
1250 struct sim_data *sd = cbd->user;
1251 ofono_sim_lock_unlock_cb_t cb = cbd->cb;
1252 struct ofono_error error = { .type = OFONO_ERROR_TYPE_NO_ERROR };
1254 cb(&error, cbd->data);
1256 g_at_chat_unregister(sd->chat, sd->ready_id);
1260 static void at_qss_notify(GAtResult *result, gpointer user_data)
1262 struct cb_data *cbd = user_data;
1263 struct sim_data *sd = cbd->user;
1264 ofono_sim_lock_unlock_cb_t cb = cbd->cb;
1265 struct ofono_error error = { .type = OFONO_ERROR_TYPE_NO_ERROR };
1269 g_at_result_iter_init(&iter, result);
1271 if (!g_at_result_iter_next(&iter, "#QSS:"))
1274 if (!g_at_result_iter_next_number(&iter, &state))
1278 case 3: /* SIM inserted and READY. */
1284 cb(&error, cbd->data);
1286 g_at_chat_unregister(sd->chat, sd->ready_id);
1290 static void sim_state_cb(gboolean present, gpointer user_data)
1292 struct cb_data *cbd = user_data;
1293 struct sim_data *sd = cbd->user;
1294 ofono_sim_lock_unlock_cb_t cb = cbd->cb;
1296 at_util_sim_state_query_free(sd->sim_state_query);
1297 sd->sim_state_query = NULL;
1300 CALLBACK_WITH_SUCCESS(cb, cbd->data);
1302 CALLBACK_WITH_FAILURE(cb, cbd->data);
1305 static void at_pin_send_cb(gboolean ok, GAtResult *result,
1308 struct cb_data *cbd = user_data;
1309 struct sim_data *sd = cbd->user;
1310 ofono_sim_lock_unlock_cb_t cb = cbd->cb;
1311 struct ofono_error error;
1313 decode_at_error(&error, g_at_result_final_response(result));
1318 switch (sd->vendor) {
1319 case OFONO_VENDOR_IFX:
1321 * On the IFX modem, AT+CPIN? can return READY too
1322 * early and so use +XSIM notification to detect
1323 * the ready state of the SIM.
1325 sd->ready_id = g_at_chat_register(sd->chat, "+XSIM",
1327 FALSE, cbd, g_free);
1329 case OFONO_VENDOR_MBM:
1331 * On the MBM modem, AT+CPIN? keeps returning SIM PIN
1332 * for a moment after successful AT+CPIN="..", but then
1333 * sends *EPEV when that changes.
1335 sd->ready_id = g_at_chat_register(sd->chat, "*EPEV",
1337 FALSE, cbd, g_free);
1339 case OFONO_VENDOR_TELIT:
1341 * On the Telit modem, AT+CPIN? can return READY too
1342 * early and so use #QSS notification to detect
1343 * the ready state of the SIM.
1345 sd->ready_id = g_at_chat_register(sd->chat, "#QSS",
1347 FALSE, cbd, g_free);
1349 case OFONO_VENDOR_ZTE:
1350 case OFONO_VENDOR_ALCATEL:
1351 case OFONO_VENDOR_HUAWEI:
1352 case OFONO_VENDOR_SIMCOM:
1353 case OFONO_VENDOR_SIERRA:
1355 * On ZTE modems, after pin is entered, SIM state is checked
1356 * by polling CPIN as their modem doesn't provide unsolicited
1357 * notification of SIM readiness.
1359 * On SIMCOM modems, SIM is busy after pin is entered (we
1360 * got a "+CME ERROR: 14" for the "AT+CPIN?" request) and
1361 * ofono don't catch the "+CPIN: READY" message sent by the
1362 * modem when SIM is ready. So, use extra CPIN to check the
1365 sd->sim_state_query = at_util_sim_state_query_new(sd->chat,
1366 2, 20, sim_state_cb, cbd,
1372 cb(&error, cbd->data);
1377 static void at_pin_send(struct ofono_sim *sim, const char *passwd,
1378 ofono_sim_lock_unlock_cb_t cb, void *data)
1380 struct sim_data *sd = ofono_sim_get_data(sim);
1381 struct cb_data *cbd = cb_data_new(cb, data);
1387 snprintf(buf, sizeof(buf), "AT+CPIN=\"%s\"", passwd);
1389 ret = g_at_chat_send(sd->chat, buf, none_prefix,
1390 at_pin_send_cb, cbd, NULL);
1392 memset(buf, 0, sizeof(buf));
1399 CALLBACK_WITH_FAILURE(cb, data);
1402 static void at_pin_send_puk(struct ofono_sim *sim, const char *puk,
1404 ofono_sim_lock_unlock_cb_t cb, void *data)
1406 struct sim_data *sd = ofono_sim_get_data(sim);
1407 struct cb_data *cbd = cb_data_new(cb, data);
1413 snprintf(buf, sizeof(buf), "AT+CPIN=\"%s\",\"%s\"", puk, passwd);
1415 ret = g_at_chat_send(sd->chat, buf, none_prefix,
1416 at_pin_send_cb, cbd, NULL);
1418 memset(buf, 0, sizeof(buf));
1425 CALLBACK_WITH_FAILURE(cb, data);
1428 static void at_lock_unlock_cb(gboolean ok, GAtResult *result,
1431 struct cb_data *cbd = user_data;
1432 ofono_sim_lock_unlock_cb_t cb = cbd->cb;
1433 struct ofono_error error;
1435 decode_at_error(&error, g_at_result_final_response(result));
1437 cb(&error, cbd->data);
1440 static const char *const at_clck_cpwd_fac[] = {
1441 [OFONO_SIM_PASSWORD_SIM_PIN] = "SC",
1442 [OFONO_SIM_PASSWORD_SIM_PIN2] = "P2",
1443 [OFONO_SIM_PASSWORD_PHSIM_PIN] = "PS",
1444 [OFONO_SIM_PASSWORD_PHFSIM_PIN] = "PF",
1445 [OFONO_SIM_PASSWORD_PHNET_PIN] = "PN",
1446 [OFONO_SIM_PASSWORD_PHNETSUB_PIN] = "PU",
1447 [OFONO_SIM_PASSWORD_PHSP_PIN] = "PP",
1448 [OFONO_SIM_PASSWORD_PHCORP_PIN] = "PC",
1451 static void at_pin_enable(struct ofono_sim *sim,
1452 enum ofono_sim_password_type passwd_type,
1453 int enable, const char *passwd,
1454 ofono_sim_lock_unlock_cb_t cb, void *data)
1456 struct sim_data *sd = ofono_sim_get_data(sim);
1457 struct cb_data *cbd = cb_data_new(cb, data);
1460 unsigned int len = sizeof(at_clck_cpwd_fac) / sizeof(*at_clck_cpwd_fac);
1462 if (passwd_type >= len || at_clck_cpwd_fac[passwd_type] == NULL)
1465 snprintf(buf, sizeof(buf), "AT+CLCK=\"%s\",%i,\"%s\"",
1466 at_clck_cpwd_fac[passwd_type], enable ? 1 : 0, passwd);
1468 ret = g_at_chat_send(sd->chat, buf, none_prefix,
1469 at_lock_unlock_cb, cbd, g_free);
1471 memset(buf, 0, sizeof(buf));
1479 CALLBACK_WITH_FAILURE(cb, data);
1482 static void at_change_passwd(struct ofono_sim *sim,
1483 enum ofono_sim_password_type passwd_type,
1484 const char *old_passwd, const char *new_passwd,
1485 ofono_sim_lock_unlock_cb_t cb, void *data)
1487 struct sim_data *sd = ofono_sim_get_data(sim);
1488 struct cb_data *cbd = cb_data_new(cb, data);
1491 unsigned int len = sizeof(at_clck_cpwd_fac) / sizeof(*at_clck_cpwd_fac);
1493 if (passwd_type >= len ||
1494 at_clck_cpwd_fac[passwd_type] == NULL)
1497 snprintf(buf, sizeof(buf), "AT+CPWD=\"%s\",\"%s\",\"%s\"",
1498 at_clck_cpwd_fac[passwd_type], old_passwd, new_passwd);
1500 ret = g_at_chat_send(sd->chat, buf, none_prefix,
1501 at_lock_unlock_cb, cbd, g_free);
1503 memset(buf, 0, sizeof(buf));
1511 CALLBACK_WITH_FAILURE(cb, data);
1514 static void at_lock_status_cb(gboolean ok, GAtResult *result,
1517 struct cb_data *cbd = user_data;
1519 ofono_sim_locked_cb_t cb = cbd->cb;
1520 struct ofono_error error;
1523 decode_at_error(&error, g_at_result_final_response(result));
1526 cb(&error, -1, cbd->data);
1530 g_at_result_iter_init(&iter, result);
1532 if (!g_at_result_iter_next(&iter, "+CLCK:")) {
1533 CALLBACK_WITH_FAILURE(cb, -1, cbd->data);
1537 g_at_result_iter_next_number(&iter, &locked);
1539 DBG("lock_status_cb: %i", locked);
1541 cb(&error, locked, cbd->data);
1544 static void at_pin_query_enabled(struct ofono_sim *sim,
1545 enum ofono_sim_password_type passwd_type,
1546 ofono_sim_locked_cb_t cb, void *data)
1548 struct sim_data *sd = ofono_sim_get_data(sim);
1549 struct cb_data *cbd = cb_data_new(cb, data);
1551 unsigned int len = sizeof(at_clck_cpwd_fac) / sizeof(*at_clck_cpwd_fac);
1553 if (passwd_type >= len || at_clck_cpwd_fac[passwd_type] == NULL)
1556 snprintf(buf, sizeof(buf), "AT+CLCK=\"%s\",2",
1557 at_clck_cpwd_fac[passwd_type]);
1559 if (g_at_chat_send(sd->chat, buf, clck_prefix,
1560 at_lock_status_cb, cbd, g_free) > 0)
1566 CALLBACK_WITH_FAILURE(cb, -1, data);
1569 static gboolean at_sim_register(gpointer user)
1571 struct ofono_sim *sim = user;
1573 ofono_sim_register(sim);
1578 static int at_sim_probe(struct ofono_sim *sim, unsigned int vendor,
1581 GAtChat *chat = data;
1582 struct sim_data *sd;
1584 sd = g_new0(struct sim_data, 1);
1585 sd->chat = g_at_chat_clone(chat);
1586 sd->vendor = vendor;
1588 if (sd->vendor == OFONO_VENDOR_MBM)
1589 g_at_chat_send(sd->chat, "AT*EPEE=1", NULL, NULL, NULL, NULL);
1591 ofono_sim_set_data(sim, sd);
1592 g_idle_add(at_sim_register, sim);
1597 static void at_sim_remove(struct ofono_sim *sim)
1599 struct sim_data *sd = ofono_sim_get_data(sim);
1601 g_idle_remove_by_data(sim);
1602 /* Cleanup potential SIM state polling */
1603 at_util_sim_state_query_free(sd->sim_state_query);
1605 ofono_sim_set_data(sim, NULL);
1607 g_at_chat_unref(sd->chat);
1611 static struct ofono_sim_driver driver = {
1613 .probe = at_sim_probe,
1614 .remove = at_sim_remove,
1615 .read_file_info = at_sim_read_info,
1616 .read_file_transparent = at_sim_read_binary,
1617 .read_file_linear = at_sim_read_record,
1618 .read_file_cyclic = at_sim_read_record,
1619 .write_file_transparent = at_sim_update_binary,
1620 .write_file_linear = at_sim_update_record,
1621 .write_file_cyclic = at_sim_update_cyclic,
1622 .read_imsi = at_read_imsi,
1623 .query_passwd_state = at_pin_query,
1624 .query_pin_retries = at_pin_retries_query,
1625 .send_passwd = at_pin_send,
1626 .reset_passwd = at_pin_send_puk,
1627 .lock = at_pin_enable,
1628 .change_passwd = at_change_passwd,
1629 .query_locked = at_pin_query_enabled,
1632 static struct ofono_sim_driver driver_noef = {
1633 .name = "atmodem-noef",
1634 .probe = at_sim_probe,
1635 .remove = at_sim_remove,
1636 .read_imsi = at_read_imsi,
1637 .query_passwd_state = at_pin_query,
1638 .query_pin_retries = at_pin_retries_query,
1639 .send_passwd = at_pin_send,
1640 .reset_passwd = at_pin_send_puk,
1641 .lock = at_pin_enable,
1642 .change_passwd = at_change_passwd,
1643 .query_locked = at_pin_query_enabled,
1646 void at_sim_init(void)
1648 ofono_sim_driver_register(&driver);
1649 ofono_sim_driver_register(&driver_noef);
1652 void at_sim_exit(void)
1654 ofono_sim_driver_unregister(&driver);
1655 ofono_sim_driver_unregister(&driver_noef);