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 *none_prefix[] = { NULL };
71 static void at_crsm_info_cb(gboolean ok, GAtResult *result, gpointer user_data)
73 struct cb_data *cbd = user_data;
75 ofono_sim_file_info_cb_t cb = cbd->cb;
76 struct ofono_error error;
77 const guint8 *response;
81 unsigned char access[3];
82 unsigned char file_status;
84 decode_at_error(&error, g_at_result_final_response(result));
87 cb(&error, -1, -1, -1, NULL, EF_STATUS_INVALIDATED, cbd->data);
91 g_at_result_iter_init(&iter, result);
93 if (!g_at_result_iter_next(&iter, "+CRSM:"))
96 g_at_result_iter_next_number(&iter, &sw1);
97 g_at_result_iter_next_number(&iter, &sw2);
99 if (!g_at_result_iter_next_hexstring(&iter, &response, &len) ||
100 (sw1 != 0x90 && sw1 != 0x91 && sw1 != 0x92) ||
101 (sw1 == 0x90 && sw2 != 0x00)) {
102 memset(&error, 0, sizeof(error));
104 error.type = OFONO_ERROR_TYPE_SIM;
105 error.error = (sw1 << 8) | sw2;
107 cb(&error, -1, -1, -1, NULL, EF_STATUS_INVALIDATED, cbd->data);
111 DBG("crsm_info_cb: %02x, %02x, %i", sw1, sw2, len);
113 if (response[0] == 0x62) {
114 ok = sim_parse_3g_get_response(response, len, &flen, &rlen,
117 file_status = EF_STATUS_VALID;
119 ok = sim_parse_2g_get_response(response, len, &flen, &rlen,
120 &str, access, &file_status);
125 cb(&error, flen, str, rlen, access, file_status, cbd->data);
130 CALLBACK_WITH_FAILURE(cb, -1, -1, -1, NULL,
131 EF_STATUS_INVALIDATED, cbd->data);
134 static void at_sim_read_info(struct ofono_sim *sim, int fileid,
135 ofono_sim_file_info_cb_t cb,
138 struct sim_data *sd = ofono_sim_get_data(sim);
142 if (sd->vendor == OFONO_VENDOR_OPTION_HSO) {
143 unsigned char access[3] = { 0x00, 0x00, 0x00 };
145 if (fileid == SIM_EFAD_FILEID) {
146 CALLBACK_WITH_SUCCESS(cb, 4, 0, 0, access,
147 EF_STATUS_VALID, data);
152 cbd = cb_data_new(cb, data);
154 snprintf(buf, sizeof(buf), "AT+CRSM=192,%i", fileid);
156 switch (sd->vendor) {
157 case OFONO_VENDOR_ZTE:
158 case OFONO_VENDOR_HUAWEI:
159 case OFONO_VENDOR_SIERRA:
160 case OFONO_VENDOR_SPEEDUP:
161 case OFONO_VENDOR_QUALCOMM_MSM:
162 strcat(buf, ",0,0,255"); /* Maximum possible length */
166 if (g_at_chat_send(sd->chat, buf, crsm_prefix,
167 at_crsm_info_cb, cbd, g_free) > 0)
172 CALLBACK_WITH_FAILURE(cb, -1, -1, -1, NULL,
173 EF_STATUS_INVALIDATED, data);
176 static void at_crsm_read_cb(gboolean ok, GAtResult *result,
179 struct cb_data *cbd = user_data;
181 ofono_sim_read_cb_t cb = cbd->cb;
182 struct ofono_error error;
183 const guint8 *response;
186 decode_at_error(&error, g_at_result_final_response(result));
189 cb(&error, NULL, 0, cbd->data);
193 g_at_result_iter_init(&iter, result);
195 if (!g_at_result_iter_next(&iter, "+CRSM:")) {
196 CALLBACK_WITH_FAILURE(cb, NULL, 0, cbd->data);
200 g_at_result_iter_next_number(&iter, &sw1);
201 g_at_result_iter_next_number(&iter, &sw2);
203 if ((sw1 != 0x90 && sw1 != 0x91 && sw1 != 0x92 && sw1 != 0x9f) ||
204 (sw1 == 0x90 && sw2 != 0x00)) {
205 memset(&error, 0, sizeof(error));
207 error.type = OFONO_ERROR_TYPE_SIM;
208 error.error = (sw1 << 8) | sw2;
210 cb(&error, NULL, 0, cbd->data);
214 if (!g_at_result_iter_next_hexstring(&iter, &response, &len)) {
215 CALLBACK_WITH_FAILURE(cb, NULL, 0, cbd->data);
219 DBG("crsm_read_cb: %02x, %02x, %d", sw1, sw2, len);
221 cb(&error, response, len, cbd->data);
224 static void at_sim_read_binary(struct ofono_sim *sim, int fileid,
225 int start, int length,
226 ofono_sim_read_cb_t cb, void *data)
228 struct sim_data *sd = ofono_sim_get_data(sim);
229 struct cb_data *cbd = cb_data_new(cb, data);
232 snprintf(buf, sizeof(buf), "AT+CRSM=176,%i,%i,%i,%i", fileid,
233 start >> 8, start & 0xff, length);
235 if (g_at_chat_send(sd->chat, buf, crsm_prefix,
236 at_crsm_read_cb, cbd, g_free) > 0)
241 CALLBACK_WITH_FAILURE(cb, NULL, 0, data);
244 static void at_sim_read_record(struct ofono_sim *sim, int fileid,
245 int record, int length,
246 ofono_sim_read_cb_t cb, void *data)
248 struct sim_data *sd = ofono_sim_get_data(sim);
249 struct cb_data *cbd = cb_data_new(cb, data);
252 snprintf(buf, sizeof(buf), "AT+CRSM=178,%i,%i,4,%i", fileid,
255 if (g_at_chat_send(sd->chat, buf, crsm_prefix,
256 at_crsm_read_cb, cbd, g_free) > 0)
261 CALLBACK_WITH_FAILURE(cb, NULL, 0, data);
264 static void at_crsm_update_cb(gboolean ok, GAtResult *result,
267 struct cb_data *cbd = user_data;
269 ofono_sim_write_cb_t cb = cbd->cb;
270 struct ofono_error error;
273 decode_at_error(&error, g_at_result_final_response(result));
276 cb(&error, cbd->data);
280 g_at_result_iter_init(&iter, result);
282 if (!g_at_result_iter_next(&iter, "+CRSM:")) {
283 CALLBACK_WITH_FAILURE(cb, cbd->data);
287 g_at_result_iter_next_number(&iter, &sw1);
288 g_at_result_iter_next_number(&iter, &sw2);
290 if ((sw1 != 0x90 && sw1 != 0x91 && sw1 != 0x92 && sw1 != 0x9f) ||
291 (sw1 == 0x90 && sw2 != 0x00)) {
292 memset(&error, 0, sizeof(error));
294 error.type = OFONO_ERROR_TYPE_SIM;
295 error.error = (sw1 << 8) | sw2;
298 DBG("crsm_update_cb: %02x, %02x", sw1, sw2);
300 cb(&error, cbd->data);
303 static void at_sim_update_file(struct ofono_sim *sim, int cmd, int fileid,
304 int p1, int p2, int p3,
305 const unsigned char *value,
306 ofono_sim_write_cb_t cb, void *data)
308 struct sim_data *sd = ofono_sim_get_data(sim);
309 struct cb_data *cbd = cb_data_new(cb, data);
311 gboolean quote = FALSE;
313 int size = 36 + p3 * 2;
318 switch (sd->vendor) {
319 case OFONO_VENDOR_MBM:
320 case OFONO_VENDOR_ZTE:
321 case OFONO_VENDOR_HUAWEI:
322 case OFONO_VENDOR_SPEEDUP:
328 buf = g_try_new(char, size);
332 len = sprintf(buf, "AT+CRSM=%i,%i,%i,%i,%i,", cmd, fileid,p1, p2, p3);
338 len += sprintf(buf + len, "%02hhX", *value++);
343 ret = g_at_chat_send(sd->chat, buf, crsm_prefix,
344 at_crsm_update_cb, cbd, g_free);
354 CALLBACK_WITH_FAILURE(cb, data);
357 static void at_sim_update_binary(struct ofono_sim *sim, int fileid,
358 int start, int length,
359 const unsigned char *value,
360 ofono_sim_write_cb_t cb, void *data)
362 at_sim_update_file(sim, 214, fileid, start >> 8, start & 0xff,
363 length, value, cb, data);
366 static void at_sim_update_record(struct ofono_sim *sim, int fileid,
367 int record, int length,
368 const unsigned char *value,
369 ofono_sim_write_cb_t cb, void *data)
371 at_sim_update_file(sim, 220, fileid, record, 4, length,
375 static void at_sim_update_cyclic(struct ofono_sim *sim, int fileid,
376 int length, const unsigned char *value,
377 ofono_sim_write_cb_t cb, void *data)
379 at_sim_update_file(sim, 220, fileid, 0, 3, length, value, cb, data);
382 static void at_cimi_cb(gboolean ok, GAtResult *result, gpointer user_data)
384 struct cb_data *cbd = user_data;
386 ofono_sim_imsi_cb_t cb = cbd->cb;
387 struct ofono_error error;
391 decode_at_error(&error, g_at_result_final_response(result));
394 cb(&error, NULL, cbd->data);
398 g_at_result_iter_init(&iter, result);
400 for (i = 0; i < g_at_result_num_response_lines(result); i++)
401 g_at_result_iter_next(&iter, NULL);
403 imsi = g_at_result_iter_raw_line(&iter);
405 DBG("cimi_cb: %s", imsi);
407 cb(&error, imsi, cbd->data);
410 static void at_read_imsi(struct ofono_sim *sim, ofono_sim_imsi_cb_t cb,
413 struct sim_data *sd = ofono_sim_get_data(sim);
414 struct cb_data *cbd = cb_data_new(cb, data);
416 if (g_at_chat_send(sd->chat, "AT+CIMI", NULL,
417 at_cimi_cb, cbd, g_free) > 0)
422 CALLBACK_WITH_FAILURE(cb, NULL, data);
426 enum ofono_sim_password_type type;
428 } const at_sim_name[] = {
429 { OFONO_SIM_PASSWORD_NONE, "READY" },
430 { OFONO_SIM_PASSWORD_SIM_PIN, "SIM PIN" },
431 { OFONO_SIM_PASSWORD_SIM_PUK, "SIM PUK" },
432 { OFONO_SIM_PASSWORD_PHSIM_PIN, "PH-SIM PIN" },
433 { OFONO_SIM_PASSWORD_PHFSIM_PIN, "PH-FSIM PIN" },
434 { OFONO_SIM_PASSWORD_PHFSIM_PUK, "PH-FSIM PUK" },
435 { OFONO_SIM_PASSWORD_SIM_PIN2, "SIM PIN2" },
436 { OFONO_SIM_PASSWORD_SIM_PUK2, "SIM PUK2" },
437 { OFONO_SIM_PASSWORD_PHNET_PIN, "PH-NET PIN" },
438 { OFONO_SIM_PASSWORD_PHNET_PUK, "PH-NET PUK" },
439 { OFONO_SIM_PASSWORD_PHNETSUB_PIN, "PH-NETSUB PIN" },
440 { OFONO_SIM_PASSWORD_PHNETSUB_PUK, "PH-NETSUB PUK" },
441 { OFONO_SIM_PASSWORD_PHSP_PIN, "PH-SP PIN" },
442 { OFONO_SIM_PASSWORD_PHSP_PUK, "PH-SP PUK" },
443 { OFONO_SIM_PASSWORD_PHCORP_PIN, "PH-CORP PIN" },
444 { OFONO_SIM_PASSWORD_PHCORP_PUK, "PH-CORP PUK" },
447 #define BUILD_PIN_RETRIES_ARRAY(passwd_types, passwd_types_cnt, retry) \
448 for (i = 0; i < OFONO_SIM_PASSWORD_INVALID; i++) \
451 for (i = 0; i < passwd_types_cnt; i++) { \
454 if (!g_at_result_iter_next_number(&iter, &val)) \
457 retry[passwd_types[i]] = val; \
459 DBG("retry counter id=%d, val=%d", passwd_types[i], \
460 retry[passwd_types[i]]); \
463 static void huawei_cpin_cb(gboolean ok, GAtResult *result, gpointer user_data)
465 struct cb_data *cbd = user_data;
466 ofono_sim_pin_retries_cb_t cb = cbd->cb;
467 const char *final = g_at_result_final_response(result);
469 struct ofono_error error;
470 int retries[OFONO_SIM_PASSWORD_INVALID];
472 static enum ofono_sim_password_type password_types[] = {
473 OFONO_SIM_PASSWORD_SIM_PUK,
474 OFONO_SIM_PASSWORD_SIM_PIN,
475 OFONO_SIM_PASSWORD_SIM_PUK2,
476 OFONO_SIM_PASSWORD_SIM_PIN2,
479 decode_at_error(&error, final);
482 cb(&error, NULL, cbd->data);
486 g_at_result_iter_init(&iter, result);
488 if (!g_at_result_iter_next(&iter, "^CPIN:"))
491 /* Skip status since we are not interested in this */
492 if (!g_at_result_iter_skip_next(&iter))
495 /* Skip "overall counter" since we'll grab each one individually */
496 if (!g_at_result_iter_skip_next(&iter))
499 BUILD_PIN_RETRIES_ARRAY(password_types, ARRAY_SIZE(password_types),
502 cb(&error, retries, cbd->data);
507 CALLBACK_WITH_FAILURE(cb, NULL, cbd->data);
510 static void pinnum_cb(gboolean ok, GAtResult *result, gpointer user_data)
512 struct cb_data *cbd = user_data;
513 ofono_sim_pin_retries_cb_t cb = cbd->cb;
514 const char *final = g_at_result_final_response(result);
516 struct ofono_error error;
517 int retries[OFONO_SIM_PASSWORD_INVALID];
519 static enum ofono_sim_password_type password_types[] = {
520 OFONO_SIM_PASSWORD_SIM_PIN,
521 OFONO_SIM_PASSWORD_SIM_PUK,
522 OFONO_SIM_PASSWORD_SIM_PIN2,
523 OFONO_SIM_PASSWORD_SIM_PUK2,
527 decode_at_error(&error, final);
530 cb(&error, NULL, cbd->data);
534 g_at_result_iter_init(&iter, result);
536 if (!g_at_result_iter_next(&iter, "%PINNUM:"))
539 BUILD_PIN_RETRIES_ARRAY(password_types, ARRAY_SIZE(password_types),
542 cb(&error, retries, cbd->data);
547 CALLBACK_WITH_FAILURE(cb, NULL, cbd->data);
550 static void zpinpuk_cb(gboolean ok, GAtResult *result, gpointer user_data)
552 struct cb_data *cbd = user_data;
553 ofono_sim_pin_retries_cb_t cb = cbd->cb;
554 const char *final = g_at_result_final_response(result);
556 struct ofono_error error;
557 int retries[OFONO_SIM_PASSWORD_INVALID];
559 static enum ofono_sim_password_type password_types[] = {
560 OFONO_SIM_PASSWORD_SIM_PIN,
561 OFONO_SIM_PASSWORD_SIM_PUK,
565 decode_at_error(&error, final);
568 cb(&error, NULL, cbd->data);
572 g_at_result_iter_init(&iter, result);
574 if (!g_at_result_iter_next(&iter, "+ZPINPUK:"))
577 BUILD_PIN_RETRIES_ARRAY(password_types, ARRAY_SIZE(password_types),
580 cb(&error, retries, cbd->data);
585 CALLBACK_WITH_FAILURE(cb, NULL, cbd->data);
588 static void xpincnt_cb(gboolean ok, GAtResult *result, gpointer user_data)
590 struct cb_data *cbd = user_data;
591 ofono_sim_pin_retries_cb_t cb = cbd->cb;
592 const char *final = g_at_result_final_response(result);
594 struct ofono_error error;
595 int retries[OFONO_SIM_PASSWORD_INVALID];
597 static enum ofono_sim_password_type password_types[] = {
598 OFONO_SIM_PASSWORD_SIM_PIN,
599 OFONO_SIM_PASSWORD_SIM_PIN2,
600 OFONO_SIM_PASSWORD_SIM_PUK,
601 OFONO_SIM_PASSWORD_SIM_PUK2,
604 decode_at_error(&error, final);
607 cb(&error, NULL, cbd->data);
611 g_at_result_iter_init(&iter, result);
613 if (!g_at_result_iter_next(&iter, "+XPINCNT:"))
616 BUILD_PIN_RETRIES_ARRAY(password_types, ARRAY_SIZE(password_types),
619 cb(&error, retries, cbd->data);
624 CALLBACK_WITH_FAILURE(cb, NULL, cbd->data);
627 static void oercn_cb(gboolean ok, GAtResult *result, gpointer user_data)
629 struct cb_data *cbd = user_data;
630 ofono_sim_pin_retries_cb_t cb = cbd->cb;
631 const char *final = g_at_result_final_response(result);
633 struct ofono_error error;
634 int retries[OFONO_SIM_PASSWORD_INVALID];
636 static enum ofono_sim_password_type password_types[] = {
637 OFONO_SIM_PASSWORD_SIM_PIN,
638 OFONO_SIM_PASSWORD_SIM_PUK,
641 decode_at_error(&error, final);
644 cb(&error, NULL, cbd->data);
648 g_at_result_iter_init(&iter, result);
650 if (!g_at_result_iter_next(&iter, "_OERCN:"))
653 BUILD_PIN_RETRIES_ARRAY(password_types, ARRAY_SIZE(password_types),
656 cb(&error, retries, cbd->data);
661 CALLBACK_WITH_FAILURE(cb, NULL, cbd->data);
664 static void cpnnum_cb(gboolean ok, GAtResult *result, gpointer user_data)
666 struct cb_data *cbd = user_data;
667 ofono_sim_pin_retries_cb_t cb = cbd->cb;
668 const char *final = g_at_result_final_response(result);
670 struct ofono_error error;
674 int retries[OFONO_SIM_PASSWORD_INVALID];
677 decode_at_error(&error, final);
680 cb(&error, NULL, cbd->data);
684 g_at_result_iter_init(&iter, result);
686 for (num = 0; num < g_at_result_num_response_lines(result); num++)
687 g_at_result_iter_next(&iter, NULL);
689 line = g_at_result_iter_raw_line(&iter);
693 for (i = 0; i < OFONO_SIM_PASSWORD_INVALID; i++)
696 entries = g_strsplit(line, "; ", -1);
698 for (num = 0; entries[num]; num++) {
701 if (strlen(entries[num]) < 5)
704 retry = strtol(entries[num] + 5, NULL, 10);
705 if (retry == 0 && errno == EINVAL)
708 if (g_str_has_prefix(entries[num], "PIN1=") == TRUE)
709 retries[OFONO_SIM_PASSWORD_SIM_PIN] = retry;
710 else if (g_str_has_prefix(entries[num], "PUK1=") == TRUE)
711 retries[OFONO_SIM_PASSWORD_SIM_PUK] = retry;
712 else if (g_str_has_prefix(entries[num], "PIN2=") == TRUE)
713 retries[OFONO_SIM_PASSWORD_SIM_PIN2] = retry;
714 else if (g_str_has_prefix(entries[num], "PUK2=") == TRUE)
715 retries[OFONO_SIM_PASSWORD_SIM_PUK2] = retry;
720 cb(&error, retries, cbd->data);
723 static void at_epin_cb(gboolean ok, GAtResult *result, gpointer user_data)
725 struct cb_data *cbd = user_data;
726 ofono_sim_pin_retries_cb_t cb = cbd->cb;
727 const char *final = g_at_result_final_response(result);
729 struct ofono_error error;
730 int retries[OFONO_SIM_PASSWORD_INVALID];
732 static enum ofono_sim_password_type password_types[] = {
733 OFONO_SIM_PASSWORD_SIM_PIN,
734 OFONO_SIM_PASSWORD_SIM_PUK,
735 OFONO_SIM_PASSWORD_SIM_PIN2,
736 OFONO_SIM_PASSWORD_SIM_PUK2,
739 decode_at_error(&error, final);
742 cb(&error, NULL, cbd->data);
746 g_at_result_iter_init(&iter, result);
748 if (!g_at_result_iter_next(&iter, "*EPIN:"))
751 BUILD_PIN_RETRIES_ARRAY(password_types, ARRAY_SIZE(password_types),
754 cb(&error, retries, cbd->data);
759 CALLBACK_WITH_FAILURE(cb, NULL, cbd->data);
762 static void at_cpinr_cb(gboolean ok, GAtResult *result, gpointer user_data)
764 struct cb_data *cbd = user_data;
765 ofono_sim_pin_retries_cb_t cb = cbd->cb;
767 struct ofono_error error;
768 int retries[OFONO_SIM_PASSWORD_INVALID];
769 size_t len = sizeof(at_sim_name) / sizeof(*at_sim_name);
772 decode_at_error(&error, g_at_result_final_response(result));
775 cb(&error, NULL, cbd->data);
779 for (i = 0; i < OFONO_SIM_PASSWORD_INVALID; i++)
782 g_at_result_iter_init(&iter, result);
784 /* Ignore +CPINRE results... */
785 while (g_at_result_iter_next(&iter, "+CPINR:")) {
789 if (!g_at_result_iter_next_unquoted_string(&iter, &name))
792 if (!g_at_result_iter_next_number(&iter, &val))
795 for (i = 1; i < len; i++) {
796 if (!strcmp(name, at_sim_name[i].name)) {
803 cb(&error, retries, cbd->data);
806 static void at_spic_cb(gboolean ok, GAtResult *result, gpointer user_data)
808 struct cb_data *cbd = user_data;
809 ofono_sim_pin_retries_cb_t cb = cbd->cb;
810 const char *final = g_at_result_final_response(result);
812 struct ofono_error error;
813 int retries[OFONO_SIM_PASSWORD_INVALID];
815 static enum ofono_sim_password_type password_types[] = {
816 OFONO_SIM_PASSWORD_SIM_PIN,
817 OFONO_SIM_PASSWORD_SIM_PUK,
818 OFONO_SIM_PASSWORD_SIM_PIN2,
819 OFONO_SIM_PASSWORD_SIM_PUK2,
822 decode_at_error(&error, final);
825 cb(&error, NULL, cbd->data);
829 g_at_result_iter_init(&iter, result);
831 if (!g_at_result_iter_next(&iter, "+SPIC:"))
834 BUILD_PIN_RETRIES_ARRAY(password_types, ARRAY_SIZE(password_types),
837 cb(&error, retries, cbd->data);
842 CALLBACK_WITH_FAILURE(cb, NULL, cbd->data);
845 #define AT_PCT_SET_RETRIES(retries, pin_type, value) \
846 retries[pin_type] = value; \
847 DBG("retry counter id=%d, val=%d", pin_type, value);
849 static void at_pct_cb(gboolean ok, GAtResult *result, gpointer user_data)
851 struct cb_data *cbd = user_data;
852 ofono_sim_pin_retries_cb_t cb = cbd->cb;
853 struct ofono_sim *sim = cbd->user;
854 const char *final = g_at_result_final_response(result);
856 struct ofono_error error;
857 int retries[OFONO_SIM_PASSWORD_INVALID];
859 enum ofono_sim_password_type pin_type;
861 decode_at_error(&error, final);
864 cb(&error, NULL, cbd->data);
868 g_at_result_iter_init(&iter, result);
870 for (i = 0; i < OFONO_SIM_PASSWORD_INVALID; i++)
873 pin_type = ofono_sim_get_password_type(sim);
874 if (pin_type == OFONO_SIM_PASSWORD_NONE) {
875 DBG("Note: No password required, returning maximum retries:");
877 AT_PCT_SET_RETRIES(retries, OFONO_SIM_PASSWORD_SIM_PIN, 3);
878 AT_PCT_SET_RETRIES(retries, OFONO_SIM_PASSWORD_SIM_PIN2, 3);
879 AT_PCT_SET_RETRIES(retries, OFONO_SIM_PASSWORD_SIM_PUK, 10);
880 AT_PCT_SET_RETRIES(retries, OFONO_SIM_PASSWORD_SIM_PUK2, 10);
885 if (g_at_result_iter_next(&iter, "#PCT:") == FALSE)
888 if (g_at_result_iter_next_number(&iter, &retries[pin_type]) == FALSE)
891 DBG("retry counter id=%d, val=%d", pin_type, retries[pin_type]);
894 cb(&error, retries, cbd->data);
899 CALLBACK_WITH_FAILURE(cb, NULL, cbd->data);
902 static void at_pin_retries_query(struct ofono_sim *sim,
903 ofono_sim_pin_retries_cb_t cb,
906 struct sim_data *sd = ofono_sim_get_data(sim);
907 struct cb_data *cbd = cb_data_new(cb, data);
912 switch (sd->vendor) {
913 case OFONO_VENDOR_IFX:
914 if (g_at_chat_send(sd->chat, "AT+XPINCNT", xpincnt_prefix,
915 xpincnt_cb, cbd, g_free) > 0)
918 case OFONO_VENDOR_SPEEDUP:
919 if (g_at_chat_send(sd->chat, "AT+CPNNUM", NULL,
920 cpnnum_cb, cbd, g_free) > 0)
923 case OFONO_VENDOR_OPTION_HSO:
924 if (g_at_chat_send(sd->chat, "AT_OERCN?", oercn_prefix,
925 oercn_cb, cbd, g_free) > 0)
928 case OFONO_VENDOR_HUAWEI:
929 if (g_at_chat_send(sd->chat, "AT^CPIN?", huawei_cpin_prefix,
930 huawei_cpin_cb, cbd, g_free) > 0)
933 case OFONO_VENDOR_ICERA:
934 if (g_at_chat_send(sd->chat, "AT%PINNUM?", pinnum_prefix,
935 pinnum_cb, cbd, g_free) > 0)
938 case OFONO_VENDOR_ZTE:
939 if (g_at_chat_send(sd->chat, "AT+ZPINPUK=?", zpinpuk_prefix,
940 zpinpuk_cb, cbd, g_free) > 0)
943 case OFONO_VENDOR_MBM:
944 if (g_at_chat_send(sd->chat, "AT*EPIN?", epin_prefix,
945 at_epin_cb, cbd, g_free) > 0)
948 case OFONO_VENDOR_SIMCOM:
949 if (g_at_chat_send(sd->chat, "AT+SPIC", spic_prefix,
950 at_spic_cb, cbd, g_free) > 0)
953 case OFONO_VENDOR_TELIT:
954 if (g_at_chat_send(sd->chat, "AT#PCT", pct_prefix,
955 at_pct_cb, cbd, g_free) > 0)
959 if (g_at_chat_send(sd->chat, "AT+CPINR", cpinr_prefixes,
960 at_cpinr_cb, cbd, g_free) > 0)
967 CALLBACK_WITH_FAILURE(cb, NULL, data);
970 static void at_cpin_cb(gboolean ok, GAtResult *result, gpointer user_data)
972 struct cb_data *cbd = user_data;
973 struct sim_data *sd = ofono_sim_get_data(cbd->user);
975 ofono_sim_passwd_cb_t cb = cbd->cb;
976 struct ofono_error error;
977 const char *pin_required;
978 int pin_type = OFONO_SIM_PASSWORD_INVALID;
980 int len = sizeof(at_sim_name) / sizeof(*at_sim_name);
981 const char *final = g_at_result_final_response(result);
983 if (sd->vendor == OFONO_VENDOR_WAVECOM && ok && strlen(final) > 7)
984 decode_at_error(&error, "OK");
986 decode_at_error(&error, final);
989 cb(&error, -1, cbd->data);
993 if (sd->vendor == OFONO_VENDOR_WAVECOM ||
994 sd->vendor == OFONO_VENDOR_WAVECOM_Q2XXX) {
996 pin_required = final + 7;
998 g_at_result_iter_init(&iter, result);
1000 if (!g_at_result_iter_next(&iter, "+CPIN:")) {
1001 CALLBACK_WITH_FAILURE(cb, -1, cbd->data);
1005 g_at_result_iter_next_unquoted_string(&iter, &pin_required);
1008 for (i = 0; i < len; i++) {
1009 if (strcmp(pin_required, at_sim_name[i].name))
1012 pin_type = at_sim_name[i].type;
1016 if (pin_type == OFONO_SIM_PASSWORD_INVALID) {
1017 CALLBACK_WITH_FAILURE(cb, -1, cbd->data);
1021 DBG("crsm_pin_cb: %s", pin_required);
1023 cb(&error, pin_type, cbd->data);
1026 static void at_pin_query(struct ofono_sim *sim, ofono_sim_passwd_cb_t cb,
1029 struct sim_data *sd = ofono_sim_get_data(sim);
1030 struct cb_data *cbd = cb_data_new(cb, data);
1034 if (g_at_chat_send(sd->chat, "AT+CPIN?", cpin_prefix,
1035 at_cpin_cb, cbd, g_free) > 0)
1040 CALLBACK_WITH_FAILURE(cb, -1, data);
1043 static void at_xsim_notify(GAtResult *result, gpointer user_data)
1045 struct cb_data *cbd = user_data;
1046 struct sim_data *sd = cbd->user;
1047 ofono_sim_lock_unlock_cb_t cb = cbd->cb;
1048 struct ofono_error error = { .type = OFONO_ERROR_TYPE_NO_ERROR };
1052 g_at_result_iter_init(&iter, result);
1054 if (!g_at_result_iter_next(&iter, "+XSIM:"))
1057 if (!g_at_result_iter_next_number(&iter, &state))
1061 case 3: /* PIN verified – Ready */
1062 case 7: /* ready for attach (+COPS) */
1068 cb(&error, cbd->data);
1070 g_at_chat_unregister(sd->chat, sd->ready_id);
1074 static void at_epev_notify(GAtResult *result, gpointer user_data)
1076 struct cb_data *cbd = user_data;
1077 struct sim_data *sd = cbd->user;
1078 ofono_sim_lock_unlock_cb_t cb = cbd->cb;
1079 struct ofono_error error = { .type = OFONO_ERROR_TYPE_NO_ERROR };
1081 cb(&error, cbd->data);
1083 g_at_chat_unregister(sd->chat, sd->ready_id);
1087 static void at_qss_notify(GAtResult *result, gpointer user_data)
1089 struct cb_data *cbd = user_data;
1090 struct sim_data *sd = cbd->user;
1091 ofono_sim_lock_unlock_cb_t cb = cbd->cb;
1092 struct ofono_error error = { .type = OFONO_ERROR_TYPE_NO_ERROR };
1096 g_at_result_iter_init(&iter, result);
1098 if (!g_at_result_iter_next(&iter, "#QSS:"))
1101 if (!g_at_result_iter_next_number(&iter, &state))
1105 case 2: /* PIN unlocked */
1111 cb(&error, cbd->data);
1113 g_at_chat_unregister(sd->chat, sd->ready_id);
1117 static void sim_state_cb(gboolean present, gpointer user_data)
1119 struct cb_data *cbd = user_data;
1120 struct sim_data *sd = cbd->user;
1121 ofono_sim_lock_unlock_cb_t cb = cbd->cb;
1123 at_util_sim_state_query_free(sd->sim_state_query);
1124 sd->sim_state_query = NULL;
1127 CALLBACK_WITH_SUCCESS(cb, cbd->data);
1129 CALLBACK_WITH_FAILURE(cb, cbd->data);
1132 static void at_pin_send_cb(gboolean ok, GAtResult *result,
1135 struct cb_data *cbd = user_data;
1136 struct sim_data *sd = cbd->user;
1137 ofono_sim_lock_unlock_cb_t cb = cbd->cb;
1138 struct ofono_error error;
1140 decode_at_error(&error, g_at_result_final_response(result));
1145 switch (sd->vendor) {
1146 case OFONO_VENDOR_IFX:
1148 * On the IFX modem, AT+CPIN? can return READY too
1149 * early and so use +XSIM notification to detect
1150 * the ready state of the SIM.
1152 sd->ready_id = g_at_chat_register(sd->chat, "+XSIM",
1154 FALSE, cbd, g_free);
1156 case OFONO_VENDOR_MBM:
1158 * On the MBM modem, AT+CPIN? keeps returning SIM PIN
1159 * for a moment after successful AT+CPIN="..", but then
1160 * sends *EPEV when that changes.
1162 sd->ready_id = g_at_chat_register(sd->chat, "*EPEV",
1164 FALSE, cbd, g_free);
1166 case OFONO_VENDOR_TELIT:
1168 * On the Telit modem, AT+CPIN? can return READY too
1169 * early and so use #QSS notification to detect
1170 * the ready state of the SIM.
1172 sd->ready_id = g_at_chat_register(sd->chat, "#QSS",
1174 FALSE, cbd, g_free);
1176 case OFONO_VENDOR_ZTE:
1178 * On ZTE modems, after pin is entered, SIM state is checked
1179 * by polling CPIN as their modem doesn't provide unsolicited
1180 * notification of SIM readiness.
1182 sd->sim_state_query = at_util_sim_state_query_new(sd->chat,
1183 2, 20, sim_state_cb, cbd,
1189 cb(&error, cbd->data);
1194 static void at_pin_send(struct ofono_sim *sim, const char *passwd,
1195 ofono_sim_lock_unlock_cb_t cb, void *data)
1197 struct sim_data *sd = ofono_sim_get_data(sim);
1198 struct cb_data *cbd = cb_data_new(cb, data);
1204 snprintf(buf, sizeof(buf), "AT+CPIN=\"%s\"", passwd);
1206 ret = g_at_chat_send(sd->chat, buf, none_prefix,
1207 at_pin_send_cb, cbd, NULL);
1209 memset(buf, 0, sizeof(buf));
1216 CALLBACK_WITH_FAILURE(cb, data);
1219 static void at_pin_send_puk(struct ofono_sim *sim, const char *puk,
1221 ofono_sim_lock_unlock_cb_t cb, void *data)
1223 struct sim_data *sd = ofono_sim_get_data(sim);
1224 struct cb_data *cbd = cb_data_new(cb, data);
1230 snprintf(buf, sizeof(buf), "AT+CPIN=\"%s\",\"%s\"", puk, passwd);
1232 ret = g_at_chat_send(sd->chat, buf, none_prefix,
1233 at_pin_send_cb, cbd, NULL);
1235 memset(buf, 0, sizeof(buf));
1242 CALLBACK_WITH_FAILURE(cb, data);
1245 static void at_lock_unlock_cb(gboolean ok, GAtResult *result,
1248 struct cb_data *cbd = user_data;
1249 ofono_sim_lock_unlock_cb_t cb = cbd->cb;
1250 struct ofono_error error;
1252 decode_at_error(&error, g_at_result_final_response(result));
1254 cb(&error, cbd->data);
1257 static const char *const at_clck_cpwd_fac[] = {
1258 [OFONO_SIM_PASSWORD_SIM_PIN] = "SC",
1259 [OFONO_SIM_PASSWORD_SIM_PIN2] = "P2",
1260 [OFONO_SIM_PASSWORD_PHSIM_PIN] = "PS",
1261 [OFONO_SIM_PASSWORD_PHFSIM_PIN] = "PF",
1262 [OFONO_SIM_PASSWORD_PHNET_PIN] = "PN",
1263 [OFONO_SIM_PASSWORD_PHNETSUB_PIN] = "PU",
1264 [OFONO_SIM_PASSWORD_PHSP_PIN] = "PP",
1265 [OFONO_SIM_PASSWORD_PHCORP_PIN] = "PC",
1268 static void at_pin_enable(struct ofono_sim *sim,
1269 enum ofono_sim_password_type passwd_type,
1270 int enable, const char *passwd,
1271 ofono_sim_lock_unlock_cb_t cb, void *data)
1273 struct sim_data *sd = ofono_sim_get_data(sim);
1274 struct cb_data *cbd = cb_data_new(cb, data);
1277 unsigned int len = sizeof(at_clck_cpwd_fac) / sizeof(*at_clck_cpwd_fac);
1279 if (passwd_type >= len || at_clck_cpwd_fac[passwd_type] == NULL)
1282 snprintf(buf, sizeof(buf), "AT+CLCK=\"%s\",%i,\"%s\"",
1283 at_clck_cpwd_fac[passwd_type], enable ? 1 : 0, passwd);
1285 ret = g_at_chat_send(sd->chat, buf, none_prefix,
1286 at_lock_unlock_cb, cbd, g_free);
1288 memset(buf, 0, sizeof(buf));
1296 CALLBACK_WITH_FAILURE(cb, data);
1299 static void at_change_passwd(struct ofono_sim *sim,
1300 enum ofono_sim_password_type passwd_type,
1301 const char *old_passwd, const char *new_passwd,
1302 ofono_sim_lock_unlock_cb_t cb, void *data)
1304 struct sim_data *sd = ofono_sim_get_data(sim);
1305 struct cb_data *cbd = cb_data_new(cb, data);
1308 unsigned int len = sizeof(at_clck_cpwd_fac) / sizeof(*at_clck_cpwd_fac);
1310 if (passwd_type >= len ||
1311 at_clck_cpwd_fac[passwd_type] == NULL)
1314 snprintf(buf, sizeof(buf), "AT+CPWD=\"%s\",\"%s\",\"%s\"",
1315 at_clck_cpwd_fac[passwd_type], old_passwd, new_passwd);
1317 ret = g_at_chat_send(sd->chat, buf, none_prefix,
1318 at_lock_unlock_cb, cbd, g_free);
1320 memset(buf, 0, sizeof(buf));
1328 CALLBACK_WITH_FAILURE(cb, data);
1331 static void at_lock_status_cb(gboolean ok, GAtResult *result,
1334 struct cb_data *cbd = user_data;
1336 ofono_sim_locked_cb_t cb = cbd->cb;
1337 struct ofono_error error;
1340 decode_at_error(&error, g_at_result_final_response(result));
1343 cb(&error, -1, cbd->data);
1347 g_at_result_iter_init(&iter, result);
1349 if (!g_at_result_iter_next(&iter, "+CLCK:")) {
1350 CALLBACK_WITH_FAILURE(cb, -1, cbd->data);
1354 g_at_result_iter_next_number(&iter, &locked);
1356 DBG("lock_status_cb: %i", locked);
1358 cb(&error, locked, cbd->data);
1361 static void at_pin_query_enabled(struct ofono_sim *sim,
1362 enum ofono_sim_password_type passwd_type,
1363 ofono_sim_locked_cb_t cb, void *data)
1365 struct sim_data *sd = ofono_sim_get_data(sim);
1366 struct cb_data *cbd = cb_data_new(cb, data);
1368 unsigned int len = sizeof(at_clck_cpwd_fac) / sizeof(*at_clck_cpwd_fac);
1370 if (passwd_type >= len || at_clck_cpwd_fac[passwd_type] == NULL)
1373 snprintf(buf, sizeof(buf), "AT+CLCK=\"%s\",2",
1374 at_clck_cpwd_fac[passwd_type]);
1376 if (g_at_chat_send(sd->chat, buf, clck_prefix,
1377 at_lock_status_cb, cbd, g_free) > 0)
1383 CALLBACK_WITH_FAILURE(cb, -1, data);
1386 static gboolean at_sim_register(gpointer user)
1388 struct ofono_sim *sim = user;
1390 ofono_sim_register(sim);
1395 static int at_sim_probe(struct ofono_sim *sim, unsigned int vendor,
1398 GAtChat *chat = data;
1399 struct sim_data *sd;
1401 sd = g_new0(struct sim_data, 1);
1402 sd->chat = g_at_chat_clone(chat);
1403 sd->vendor = vendor;
1405 switch (sd->vendor) {
1406 case OFONO_VENDOR_WAVECOM:
1407 g_at_chat_add_terminator(sd->chat, "+CPIN:", 6, TRUE);
1409 case OFONO_VENDOR_MBM:
1410 g_at_chat_send(sd->chat, "AT*EPEE=1", NULL, NULL, NULL, NULL);
1412 case OFONO_VENDOR_WAVECOM_Q2XXX:
1413 g_at_chat_add_terminator(chat, "+CPIN: READY", -1, TRUE);
1419 ofono_sim_set_data(sim, sd);
1420 g_idle_add(at_sim_register, sim);
1425 static void at_sim_remove(struct ofono_sim *sim)
1427 struct sim_data *sd = ofono_sim_get_data(sim);
1429 /* Cleanup potential SIM state polling */
1430 at_util_sim_state_query_free(sd->sim_state_query);
1432 ofono_sim_set_data(sim, NULL);
1434 g_at_chat_unref(sd->chat);
1438 static struct ofono_sim_driver driver = {
1440 .probe = at_sim_probe,
1441 .remove = at_sim_remove,
1442 .read_file_info = at_sim_read_info,
1443 .read_file_transparent = at_sim_read_binary,
1444 .read_file_linear = at_sim_read_record,
1445 .read_file_cyclic = at_sim_read_record,
1446 .write_file_transparent = at_sim_update_binary,
1447 .write_file_linear = at_sim_update_record,
1448 .write_file_cyclic = at_sim_update_cyclic,
1449 .read_imsi = at_read_imsi,
1450 .query_passwd_state = at_pin_query,
1451 .query_pin_retries = at_pin_retries_query,
1452 .send_passwd = at_pin_send,
1453 .reset_passwd = at_pin_send_puk,
1454 .lock = at_pin_enable,
1455 .change_passwd = at_change_passwd,
1456 .query_locked = at_pin_query_enabled,
1459 static struct ofono_sim_driver driver_noef = {
1460 .name = "atmodem-noef",
1461 .probe = at_sim_probe,
1462 .remove = at_sim_remove,
1463 .read_imsi = at_read_imsi,
1464 .query_passwd_state = at_pin_query,
1465 .query_pin_retries = at_pin_retries_query,
1466 .send_passwd = at_pin_send,
1467 .reset_passwd = at_pin_send_puk,
1468 .lock = at_pin_enable,
1469 .change_passwd = at_change_passwd,
1470 .query_locked = at_pin_query_enabled,
1473 void at_sim_init(void)
1475 ofono_sim_driver_register(&driver);
1476 ofono_sim_driver_register(&driver_noef);
1479 void at_sim_exit(void)
1481 ofono_sim_driver_unregister(&driver);
1482 ofono_sim_driver_unregister(&driver_noef);