Upgrade ofono to 1.2
[profile/ivi/ofono.git] / drivers / atmodem / sim.c
1 /*
2  *
3  *  oFono - Open Source Telephony
4  *
5  *  Copyright (C) 2008-2011  Intel Corporation. All rights reserved.
6  *
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.
10  *
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.
15  *
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
19  *
20  */
21
22 #ifdef HAVE_CONFIG_H
23 #include <config.h>
24 #endif
25
26 #define _GNU_SOURCE
27 #include <string.h>
28 #include <stdlib.h>
29 #include <stdio.h>
30 #include <errno.h>
31
32 #include <glib.h>
33
34 #include <ofono/log.h>
35 #include <ofono/modem.h>
36 #include <ofono/sim.h>
37
38 #include "gatchat.h"
39 #include "gatresult.h"
40 #include "simutil.h"
41 #include "vendor.h"
42
43 #include "atmodem.h"
44
45 #define EF_STATUS_INVALIDATED 0
46 #define EF_STATUS_VALID 1
47
48 #define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
49
50 struct sim_data {
51         GAtChat *chat;
52         unsigned int vendor;
53         guint ready_id;
54         struct at_util_sim_state_query *sim_state_query;
55 };
56
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 };
71
72 static void at_crsm_info_cb(gboolean ok, GAtResult *result, gpointer user_data)
73 {
74         struct cb_data *cbd = user_data;
75         GAtResultIter iter;
76         ofono_sim_file_info_cb_t cb = cbd->cb;
77         struct ofono_error error;
78         const guint8 *response;
79         gint sw1, sw2, len;
80         int flen, rlen;
81         int str;
82         unsigned char access[3];
83         unsigned char file_status;
84
85         decode_at_error(&error, g_at_result_final_response(result));
86
87         if (!ok) {
88                 cb(&error, -1, -1, -1, NULL, EF_STATUS_INVALIDATED, cbd->data);
89                 return;
90         }
91
92         g_at_result_iter_init(&iter, result);
93
94         if (!g_at_result_iter_next(&iter, "+CRSM:"))
95                 goto error;
96
97         g_at_result_iter_next_number(&iter, &sw1);
98         g_at_result_iter_next_number(&iter, &sw2);
99
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));
104
105                 error.type = OFONO_ERROR_TYPE_SIM;
106                 error.error = (sw1 << 8) | sw2;
107
108                 cb(&error, -1, -1, -1, NULL, EF_STATUS_INVALIDATED, cbd->data);
109                 return;
110         }
111
112         DBG("crsm_info_cb: %02x, %02x, %i", sw1, sw2, len);
113
114         if (response[0] == 0x62) {
115                 ok = sim_parse_3g_get_response(response, len, &flen, &rlen,
116                                                 &str, access, NULL);
117
118                 file_status = EF_STATUS_VALID;
119         } else
120                 ok = sim_parse_2g_get_response(response, len, &flen, &rlen,
121                                                 &str, access, &file_status);
122
123         if (!ok)
124                 goto error;
125
126         cb(&error, flen, str, rlen, access, file_status, cbd->data);
127
128         return;
129
130 error:
131         CALLBACK_WITH_FAILURE(cb, -1, -1, -1, NULL,
132                                 EF_STATUS_INVALIDATED, cbd->data);
133 }
134
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)
139 {
140         struct sim_data *sd = ofono_sim_get_data(sim);
141         struct cb_data *cbd;
142         char buf[128];
143         unsigned int len;
144
145         if (sd->vendor == OFONO_VENDOR_OPTION_HSO) {
146                 unsigned char access[3] = { 0x00, 0x00, 0x00 };
147
148                 if (fileid == SIM_EFAD_FILEID) {
149                         CALLBACK_WITH_SUCCESS(cb, 4, 0, 0, access,
150                                                 EF_STATUS_VALID, data);
151                         return;
152                 }
153         }
154
155         cbd = cb_data_new(cb, data);
156
157         len = snprintf(buf, sizeof(buf), "AT+CRSM=192,%i", fileid);
158
159         switch (sd->vendor) {
160         default:
161                 if (path_len == 0)
162                         break;
163
164                 /* Fall through */
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");
172                 break;
173         }
174
175         if (path_len > 0) {
176                 len += sprintf(buf + len, ",,\"");
177
178                 for (; path_len; path_len--)
179                         len += sprintf(buf + len, "%02hhX", *path++);
180
181                 buf[len++] = '\"';
182                 buf[len] = '\0';
183         }
184
185         if (g_at_chat_send(sd->chat, buf, crsm_prefix,
186                                 at_crsm_info_cb, cbd, g_free) > 0)
187                 return;
188
189         g_free(cbd);
190
191         CALLBACK_WITH_FAILURE(cb, -1, -1, -1, NULL,
192                                 EF_STATUS_INVALIDATED, data);
193 }
194
195 static void at_crsm_read_cb(gboolean ok, GAtResult *result,
196                                 gpointer user_data)
197 {
198         struct cb_data *cbd = user_data;
199         GAtResultIter iter;
200         ofono_sim_read_cb_t cb = cbd->cb;
201         struct ofono_error error;
202         const guint8 *response;
203         gint sw1, sw2, len;
204
205         decode_at_error(&error, g_at_result_final_response(result));
206
207         if (!ok) {
208                 cb(&error, NULL, 0, cbd->data);
209                 return;
210         }
211
212         g_at_result_iter_init(&iter, result);
213
214         if (!g_at_result_iter_next(&iter, "+CRSM:")) {
215                 CALLBACK_WITH_FAILURE(cb, NULL, 0, cbd->data);
216                 return;
217         }
218
219         g_at_result_iter_next_number(&iter, &sw1);
220         g_at_result_iter_next_number(&iter, &sw2);
221
222         if ((sw1 != 0x90 && sw1 != 0x91 && sw1 != 0x92 && sw1 != 0x9f) ||
223                         (sw1 == 0x90 && sw2 != 0x00)) {
224                 memset(&error, 0, sizeof(error));
225
226                 error.type = OFONO_ERROR_TYPE_SIM;
227                 error.error = (sw1 << 8) | sw2;
228
229                 cb(&error, NULL, 0, cbd->data);
230                 return;
231         }
232
233         if (!g_at_result_iter_next_hexstring(&iter, &response, &len)) {
234                 CALLBACK_WITH_FAILURE(cb, NULL, 0, cbd->data);
235                 return;
236         }
237
238         DBG("crsm_read_cb: %02x, %02x, %d", sw1, sw2, len);
239
240         cb(&error, response, len, cbd->data);
241 }
242
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)
248 {
249         struct sim_data *sd = ofono_sim_get_data(sim);
250         struct cb_data *cbd = cb_data_new(cb, data);
251         char buf[64];
252         unsigned int len;
253
254         len = snprintf(buf, sizeof(buf), "AT+CRSM=176,%i,%i,%i,%i", fileid,
255                         start >> 8, start & 0xff, length);
256
257         if (path_len > 0) {
258                 buf[len++] = ',';
259                 buf[len++] = ',';
260                 buf[len++] = '\"';
261
262                 for (; path_len; path_len--)
263                         len += sprintf(buf + len, "%02hhX", *path++);
264
265                 buf[len++] = '\"';
266                 buf[len] = '\0';
267         }
268
269         if (g_at_chat_send(sd->chat, buf, crsm_prefix,
270                                 at_crsm_read_cb, cbd, g_free) > 0)
271                 return;
272
273         g_free(cbd);
274
275         CALLBACK_WITH_FAILURE(cb, NULL, 0, data);
276 }
277
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)
283 {
284         struct sim_data *sd = ofono_sim_get_data(sim);
285         struct cb_data *cbd = cb_data_new(cb, data);
286         char buf[128];
287
288         snprintf(buf, sizeof(buf), "AT+CRSM=178,%i,%i,4,%i", fileid,
289                         record, length);
290
291         if (g_at_chat_send(sd->chat, buf, crsm_prefix,
292                                 at_crsm_read_cb, cbd, g_free) > 0)
293                 return;
294
295         g_free(cbd);
296
297         CALLBACK_WITH_FAILURE(cb, NULL, 0, data);
298 }
299
300 static void at_crsm_update_cb(gboolean ok, GAtResult *result,
301                                 gpointer user_data)
302 {
303         struct cb_data *cbd = user_data;
304         GAtResultIter iter;
305         ofono_sim_write_cb_t cb = cbd->cb;
306         struct ofono_error error;
307         gint sw1, sw2;
308
309         decode_at_error(&error, g_at_result_final_response(result));
310
311         if (!ok) {
312                 cb(&error, cbd->data);
313                 return;
314         }
315
316         g_at_result_iter_init(&iter, result);
317
318         if (!g_at_result_iter_next(&iter, "+CRSM:")) {
319                 CALLBACK_WITH_FAILURE(cb, cbd->data);
320                 return;
321         }
322
323         g_at_result_iter_next_number(&iter, &sw1);
324         g_at_result_iter_next_number(&iter, &sw2);
325
326         if ((sw1 != 0x90 && sw1 != 0x91 && sw1 != 0x92 && sw1 != 0x9f) ||
327                         (sw1 == 0x90 && sw2 != 0x00)) {
328                 memset(&error, 0, sizeof(error));
329
330                 error.type = OFONO_ERROR_TYPE_SIM;
331                 error.error = (sw1 << 8) | sw2;
332         }
333
334         DBG("crsm_update_cb: %02x, %02x", sw1, sw2);
335
336         cb(&error, cbd->data);
337 }
338
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)
345 {
346         struct sim_data *sd = ofono_sim_get_data(sim);
347         struct cb_data *cbd = cb_data_new(cb, data);
348         char *buf;
349         int len, ret;
350         int size = 38 + p3 * 2;
351
352         DBG("");
353
354         buf = g_try_new(char, size);
355         if (buf == NULL)
356                 goto error;
357
358         len = sprintf(buf, "AT+CRSM=%i,%i,%i,%i,%i,\"", cmd, fileid,p1, p2, p3);
359
360         for (; p3; p3--)
361                 len += sprintf(buf + len, "%02hhX", *value++);
362
363         buf[len++] = '\"';
364         buf[len] = '\0';
365
366         ret = g_at_chat_send(sd->chat, buf, crsm_prefix,
367                                 at_crsm_update_cb, cbd, g_free);
368
369         g_free(buf);
370
371         if (ret > 0)
372                 return;
373
374 error:
375         g_free(cbd);
376
377         CALLBACK_WITH_FAILURE(cb, data);
378 }
379
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)
386 {
387         at_sim_update_file(sim, 214, fileid, start >> 8, start & 0xff,
388                                 length, value, path, path_len, cb, data);
389 }
390
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)
397 {
398         at_sim_update_file(sim, 220, fileid, record, 4, length,
399                                 value, path, path_len, cb, data);
400 }
401
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)
407 {
408         at_sim_update_file(sim, 220, fileid, 0, 3, length, value,
409                                 path, path_len, cb, data);
410 }
411
412 static void at_cimi_cb(gboolean ok, GAtResult *result, gpointer user_data)
413 {
414         struct cb_data *cbd = user_data;
415         GAtResultIter iter;
416         ofono_sim_imsi_cb_t cb = cbd->cb;
417         struct ofono_error error;
418         const char *imsi;
419         int i;
420
421         decode_at_error(&error, g_at_result_final_response(result));
422
423         if (!ok) {
424                 cb(&error, NULL, cbd->data);
425                 return;
426         }
427
428         g_at_result_iter_init(&iter, result);
429
430         for (i = 0; i < g_at_result_num_response_lines(result); i++)
431                 g_at_result_iter_next(&iter, NULL);
432
433         imsi = g_at_result_iter_raw_line(&iter);
434
435         DBG("cimi_cb: %s", imsi);
436
437         cb(&error, imsi, cbd->data);
438 }
439
440 static void at_read_imsi(struct ofono_sim *sim, ofono_sim_imsi_cb_t cb,
441                                 void *data)
442 {
443         struct sim_data *sd = ofono_sim_get_data(sim);
444         struct cb_data *cbd = cb_data_new(cb, data);
445
446         if (g_at_chat_send(sd->chat, "AT+CIMI", NULL,
447                                 at_cimi_cb, cbd, g_free) > 0)
448                 return;
449
450         g_free(cbd);
451
452         CALLBACK_WITH_FAILURE(cb, NULL, data);
453 }
454
455 static struct {
456         enum ofono_sim_password_type type;
457         const char *name;
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"   },
475 };
476
477 #define BUILD_PIN_RETRIES_ARRAY(passwd_types, passwd_types_cnt, retry)  \
478         for (i = 0; i < OFONO_SIM_PASSWORD_INVALID; i++)                \
479                 retry[i] = -1;                                          \
480                                                                         \
481         for (i = 0; i < passwd_types_cnt; i++) {                        \
482                 int val;                                                \
483                                                                         \
484                 if (!g_at_result_iter_next_number(&iter, &val))         \
485                         goto error;                                     \
486                                                                         \
487                 retry[passwd_types[i]] = val;                           \
488                                                                         \
489                 DBG("retry counter id=%d, val=%d", passwd_types[i],     \
490                                         retry[passwd_types[i]]);        \
491         }                                                               \
492
493 static void huawei_cpin_cb(gboolean ok, GAtResult *result, gpointer user_data)
494 {
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);
498         GAtResultIter iter;
499         struct ofono_error error;
500         int retries[OFONO_SIM_PASSWORD_INVALID];
501         size_t i;
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,
507         };
508
509         decode_at_error(&error, final);
510
511         if (!ok) {
512                 cb(&error, NULL, cbd->data);
513                 return;
514         }
515
516         g_at_result_iter_init(&iter, result);
517
518         if (!g_at_result_iter_next(&iter, "^CPIN:"))
519                 goto error;
520
521         /* Skip status since we are not interested in this */
522         if (!g_at_result_iter_skip_next(&iter))
523                 goto error;
524
525         /* Skip "overall counter" since we'll grab each one individually */
526         if (!g_at_result_iter_skip_next(&iter))
527                 goto error;
528
529         BUILD_PIN_RETRIES_ARRAY(password_types, ARRAY_SIZE(password_types),
530                                 retries);
531
532         cb(&error, retries, cbd->data);
533
534         return;
535
536 error:
537         CALLBACK_WITH_FAILURE(cb, NULL, cbd->data);
538 }
539
540 static void pinnum_cb(gboolean ok, GAtResult *result, gpointer user_data)
541 {
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);
545         GAtResultIter iter;
546         struct ofono_error error;
547         int retries[OFONO_SIM_PASSWORD_INVALID];
548         size_t i;
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,
554         };
555
556
557         decode_at_error(&error, final);
558
559         if (!ok) {
560                 cb(&error, NULL, cbd->data);
561                 return;
562         }
563
564         g_at_result_iter_init(&iter, result);
565
566         if (!g_at_result_iter_next(&iter, "%PINNUM:"))
567                 goto error;
568
569         BUILD_PIN_RETRIES_ARRAY(password_types, ARRAY_SIZE(password_types),
570                                 retries);
571
572         cb(&error, retries, cbd->data);
573
574         return;
575
576 error:
577         CALLBACK_WITH_FAILURE(cb, NULL, cbd->data);
578 }
579
580 static void zpinpuk_cb(gboolean ok, GAtResult *result, gpointer user_data)
581 {
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);
585         GAtResultIter iter;
586         struct ofono_error error;
587         int retries[OFONO_SIM_PASSWORD_INVALID];
588         size_t i;
589         static enum ofono_sim_password_type password_types[] = {
590                 OFONO_SIM_PASSWORD_SIM_PIN,
591                 OFONO_SIM_PASSWORD_SIM_PUK,
592         };
593
594
595         decode_at_error(&error, final);
596
597         if (!ok) {
598                 cb(&error, NULL, cbd->data);
599                 return;
600         }
601
602         g_at_result_iter_init(&iter, result);
603
604         if (!g_at_result_iter_next(&iter, "+ZPINPUK:"))
605                 goto error;
606
607         BUILD_PIN_RETRIES_ARRAY(password_types, ARRAY_SIZE(password_types),
608                                 retries);
609
610         cb(&error, retries, cbd->data);
611
612         return;
613
614 error:
615         CALLBACK_WITH_FAILURE(cb, NULL, cbd->data);
616 }
617
618 static void xpincnt_cb(gboolean ok, GAtResult *result, gpointer user_data)
619 {
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);
623         GAtResultIter iter;
624         struct ofono_error error;
625         int retries[OFONO_SIM_PASSWORD_INVALID];
626         size_t i;
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,
632         };
633
634         decode_at_error(&error, final);
635
636         if (!ok) {
637                 cb(&error, NULL, cbd->data);
638                 return;
639         }
640
641         g_at_result_iter_init(&iter, result);
642
643         if (!g_at_result_iter_next(&iter, "+XPINCNT:"))
644                 goto error;
645
646         BUILD_PIN_RETRIES_ARRAY(password_types, ARRAY_SIZE(password_types),
647                                 retries);
648
649         cb(&error, retries, cbd->data);
650
651         return;
652
653 error:
654         CALLBACK_WITH_FAILURE(cb, NULL, cbd->data);
655 }
656
657 static void oercn_cb(gboolean ok, GAtResult *result, gpointer user_data)
658 {
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);
662         GAtResultIter iter;
663         struct ofono_error error;
664         int retries[OFONO_SIM_PASSWORD_INVALID];
665         size_t i;
666         static enum ofono_sim_password_type password_types[] = {
667                 OFONO_SIM_PASSWORD_SIM_PIN,
668                 OFONO_SIM_PASSWORD_SIM_PUK,
669         };
670
671         decode_at_error(&error, final);
672
673         if (!ok) {
674                 cb(&error, NULL, cbd->data);
675                 return;
676         }
677
678         g_at_result_iter_init(&iter, result);
679
680         if (!g_at_result_iter_next(&iter, "_OERCN:"))
681                 goto error;
682
683         BUILD_PIN_RETRIES_ARRAY(password_types, ARRAY_SIZE(password_types),
684                                 retries);
685
686         cb(&error, retries, cbd->data);
687
688         return;
689
690 error:
691         CALLBACK_WITH_FAILURE(cb, NULL, cbd->data);
692 }
693
694 static void cpnnum_cb(gboolean ok, GAtResult *result, gpointer user_data)
695 {
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);
699         GAtResultIter iter;
700         struct ofono_error error;
701         const char *line;
702         int num;
703         char **entries;
704         int retries[OFONO_SIM_PASSWORD_INVALID];
705         size_t i;
706
707         decode_at_error(&error, final);
708
709         if (!ok) {
710                 cb(&error, NULL, cbd->data);
711                 return;
712         }
713
714         g_at_result_iter_init(&iter, result);
715
716         for (num = 0; num < g_at_result_num_response_lines(result); num++)
717                 g_at_result_iter_next(&iter, NULL);
718
719         line = g_at_result_iter_raw_line(&iter);
720
721         DBG("%s", line);
722
723         for (i = 0; i < OFONO_SIM_PASSWORD_INVALID; i++)
724                 retries[i] = -1;
725
726         entries = g_strsplit(line, "; ", -1);
727
728         for (num = 0; entries[num]; num++) {
729                 int retry;
730
731                 if (strlen(entries[num]) < 5)
732                         continue;
733
734                 retry = strtol(entries[num] + 5, NULL, 10);
735                 if (retry == 0 && errno == EINVAL)
736                         continue;
737
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;
746         }
747
748         g_strfreev(entries);
749
750         cb(&error, retries, cbd->data);
751 }
752
753 static void at_epin_cb(gboolean ok, GAtResult *result, gpointer user_data)
754 {
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);
758         GAtResultIter iter;
759         struct ofono_error error;
760         int retries[OFONO_SIM_PASSWORD_INVALID];
761         size_t i;
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,
767         };
768
769         decode_at_error(&error, final);
770
771         if (!ok) {
772                 cb(&error, NULL, cbd->data);
773                 return;
774         }
775
776         g_at_result_iter_init(&iter, result);
777
778         if (!g_at_result_iter_next(&iter, "*EPIN:"))
779                 goto error;
780
781         BUILD_PIN_RETRIES_ARRAY(password_types, ARRAY_SIZE(password_types),
782                                 retries);
783
784         cb(&error, retries, cbd->data);
785
786         return;
787
788 error:
789         CALLBACK_WITH_FAILURE(cb, NULL, cbd->data);
790 }
791
792 static void at_cpinr_cb(gboolean ok, GAtResult *result, gpointer user_data)
793 {
794         struct cb_data *cbd = user_data;
795         ofono_sim_pin_retries_cb_t cb = cbd->cb;
796         GAtResultIter iter;
797         struct ofono_error error;
798         int retries[OFONO_SIM_PASSWORD_INVALID];
799         size_t len = sizeof(at_sim_name) / sizeof(*at_sim_name);
800         size_t i;
801
802         decode_at_error(&error, g_at_result_final_response(result));
803
804         if (!ok) {
805                 cb(&error, NULL, cbd->data);
806                 return;
807         }
808
809         for (i = 0; i < OFONO_SIM_PASSWORD_INVALID; i++)
810                 retries[i] = -1;
811
812         g_at_result_iter_init(&iter, result);
813
814         /* Ignore +CPINRE results... */
815         while (g_at_result_iter_next(&iter, "+CPINR:")) {
816                 const char *name;
817                 int val;
818
819                 if (!g_at_result_iter_next_unquoted_string(&iter, &name))
820                         continue;
821
822                 if (!g_at_result_iter_next_number(&iter, &val))
823                         continue;
824
825                 for (i = 1; i < len; i++) {
826                         if (!strcmp(name, at_sim_name[i].name)) {
827                                 retries[i] = val;
828                                 break;
829                         }
830                 }
831         }
832
833         cb(&error, retries, cbd->data);
834 }
835
836 static void at_spic_cb(gboolean ok, GAtResult *result, gpointer user_data)
837 {
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);
841         GAtResultIter iter;
842         struct ofono_error error;
843         int retries[OFONO_SIM_PASSWORD_INVALID];
844         size_t i;
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,
850         };
851
852         decode_at_error(&error, final);
853
854         if (!ok) {
855                 cb(&error, NULL, cbd->data);
856                 return;
857         }
858
859         g_at_result_iter_init(&iter, result);
860
861         if (!g_at_result_iter_next(&iter, "+SPIC:"))
862                 goto error;
863
864         BUILD_PIN_RETRIES_ARRAY(password_types, ARRAY_SIZE(password_types),
865                                 retries);
866
867         cb(&error, retries, cbd->data);
868
869         return;
870
871 error:
872         CALLBACK_WITH_FAILURE(cb, NULL, cbd->data);
873 }
874
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);
878
879 static void at_pct_cb(gboolean ok, GAtResult *result, gpointer user_data)
880 {
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);
885         GAtResultIter iter;
886         struct ofono_error error;
887         int retries[OFONO_SIM_PASSWORD_INVALID];
888         size_t i;
889         enum ofono_sim_password_type pin_type;
890
891         decode_at_error(&error, final);
892
893         if (!ok) {
894                 cb(&error, NULL, cbd->data);
895                 return;
896         }
897
898         g_at_result_iter_init(&iter, result);
899
900         for (i = 0; i < OFONO_SIM_PASSWORD_INVALID; i++)
901                 retries[i] = -1;
902
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:");
906
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);
911
912                 goto callback;
913         }
914
915         if (g_at_result_iter_next(&iter, "#PCT:") == FALSE)
916                 goto error;
917
918         if (g_at_result_iter_next_number(&iter, &retries[pin_type]) == FALSE)
919                 goto error;
920
921         DBG("retry counter id=%d, val=%d", pin_type, retries[pin_type]);
922
923 callback:
924         cb(&error, retries, cbd->data);
925
926         return;
927
928 error:
929         CALLBACK_WITH_FAILURE(cb, NULL, cbd->data);
930 }
931
932 static void at_pnnm_cb(gboolean ok, GAtResult *result, gpointer user_data)
933 {
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);
937         GAtResultIter iter;
938         struct ofono_error error;
939         int retries[OFONO_SIM_PASSWORD_INVALID];
940         size_t i;
941         static enum ofono_sim_password_type password_types[] = {
942                 OFONO_SIM_PASSWORD_SIM_PIN,
943                 OFONO_SIM_PASSWORD_SIM_PUK,
944         };
945
946         decode_at_error(&error, final);
947
948         if (!ok) {
949                 cb(&error, NULL, cbd->data);
950                 return;
951         }
952
953         g_at_result_iter_init(&iter, result);
954
955         if (!g_at_result_iter_next(&iter, "+PNNM:"))
956                 goto error;
957
958         BUILD_PIN_RETRIES_ARRAY(password_types, ARRAY_SIZE(password_types),
959                                 retries);
960
961         cb(&error, retries, cbd->data);
962
963         return;
964
965 error:
966         CALLBACK_WITH_FAILURE(cb, NULL, cbd->data);
967 }
968
969 static void at_pin_retries_query(struct ofono_sim *sim,
970                                         ofono_sim_pin_retries_cb_t cb,
971                                         void *data)
972 {
973         struct sim_data *sd = ofono_sim_get_data(sim);
974         struct cb_data *cbd = cb_data_new(cb, data);
975         cbd->user = sim;
976
977         DBG("");
978
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)
983                         return;
984                 break;
985         case OFONO_VENDOR_SPEEDUP:
986                 if (g_at_chat_send(sd->chat, "AT+CPNNUM", NULL,
987                                         cpnnum_cb, cbd, g_free) > 0)
988                         return;
989                 break;
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)
993                         return;
994                 break;
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)
998                         return;
999                 break;
1000         case OFONO_VENDOR_ICERA:
1001                 if (g_at_chat_send(sd->chat, "AT%PINNUM?", pinnum_prefix,
1002                                         pinnum_cb, cbd, g_free) > 0)
1003                         return;
1004                 break;
1005         case OFONO_VENDOR_ZTE:
1006                 if (g_at_chat_send(sd->chat, "AT+ZPINPUK=?", zpinpuk_prefix,
1007                                         zpinpuk_cb, cbd, g_free) > 0)
1008                         return;
1009                 break;
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)
1013                         return;
1014                 break;
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)
1018                         return;
1019                 break;
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)
1023                         return;
1024                 break;
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)
1028                         return;
1029                 break;
1030         default:
1031                 if (g_at_chat_send(sd->chat, "AT+CPINR", cpinr_prefixes,
1032                                         at_cpinr_cb, cbd, g_free) > 0)
1033                         return;
1034                 break;
1035         }
1036
1037         g_free(cbd);
1038
1039         CALLBACK_WITH_FAILURE(cb, NULL, data);
1040 }
1041
1042 static int needs_wavecom_sim_quirk(int vendor)
1043 {
1044         return vendor == OFONO_VENDOR_WAVECOM ||
1045                         vendor == OFONO_VENDOR_WAVECOM_Q2XXX;
1046 }
1047
1048 static void at_cpin_cb(gboolean ok, GAtResult *result, gpointer user_data)
1049 {
1050         struct cb_data *cbd = user_data;
1051         struct sim_data *sd = ofono_sim_get_data(cbd->user);
1052         GAtResultIter iter;
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;
1057         int i;
1058         int len = sizeof(at_sim_name) / sizeof(*at_sim_name);
1059         const char *final = g_at_result_final_response(result);
1060
1061         if (needs_wavecom_sim_quirk(sd->vendor) && ok && strlen(final) > 7)
1062                 decode_at_error(&error, "OK");
1063         else
1064                 decode_at_error(&error, final);
1065
1066         if (!ok) {
1067                 cb(&error, -1, cbd->data);
1068                 return;
1069         }
1070
1071         if (needs_wavecom_sim_quirk(sd->vendor)) {
1072                 /* +CPIN: <pin> */
1073                 pin_required = final + 7;
1074         } else {
1075                 g_at_result_iter_init(&iter, result);
1076
1077                 if (!g_at_result_iter_next(&iter, "+CPIN:")) {
1078                         CALLBACK_WITH_FAILURE(cb, -1, cbd->data);
1079                         return;
1080                 }
1081
1082                 g_at_result_iter_next_unquoted_string(&iter, &pin_required);
1083         }
1084
1085         for (i = 0; i < len; i++) {
1086                 if (strcmp(pin_required, at_sim_name[i].name))
1087                         continue;
1088
1089                 pin_type = at_sim_name[i].type;
1090                 break;
1091         }
1092
1093         if (pin_type == OFONO_SIM_PASSWORD_INVALID) {
1094                 CALLBACK_WITH_FAILURE(cb, -1, cbd->data);
1095                 return;
1096         }
1097
1098         DBG("crsm_pin_cb: %s", pin_required);
1099
1100         cb(&error, pin_type, cbd->data);
1101 }
1102
1103 static void at_pin_query(struct ofono_sim *sim, ofono_sim_passwd_cb_t cb,
1104                         void *data)
1105 {
1106         struct sim_data *sd = ofono_sim_get_data(sim);
1107         struct cb_data *cbd = cb_data_new(cb, data);
1108
1109         cbd->user = sim;
1110
1111         if (g_at_chat_send(sd->chat, "AT+CPIN?", cpin_prefix,
1112                                 at_cpin_cb, cbd, g_free) > 0)
1113                 return;
1114
1115         g_free(cbd);
1116
1117         CALLBACK_WITH_FAILURE(cb, -1, data);
1118 }
1119
1120 static void at_xsim_notify(GAtResult *result, gpointer user_data)
1121 {
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 };
1126         GAtResultIter iter;
1127         int state;
1128
1129         g_at_result_iter_init(&iter, result);
1130
1131         if (!g_at_result_iter_next(&iter, "+XSIM:"))
1132                 return;
1133
1134         if (!g_at_result_iter_next_number(&iter, &state))
1135                 return;
1136
1137         switch (state) {
1138         case 3: /* PIN verified â€“ Ready */
1139                 break;
1140         default:
1141                 return;
1142         }
1143
1144         cb(&error, cbd->data);
1145
1146         g_at_chat_unregister(sd->chat, sd->ready_id);
1147         sd->ready_id = 0;
1148 }
1149
1150 static void at_epev_notify(GAtResult *result, gpointer user_data)
1151 {
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 };
1156
1157         cb(&error, cbd->data);
1158
1159         g_at_chat_unregister(sd->chat, sd->ready_id);
1160         sd->ready_id = 0;
1161 }
1162
1163 static void at_qss_notify(GAtResult *result, gpointer user_data)
1164 {
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 };
1169         GAtResultIter iter;
1170         int state;
1171
1172         g_at_result_iter_init(&iter, result);
1173
1174         if (!g_at_result_iter_next(&iter, "#QSS:"))
1175                 return;
1176
1177         if (!g_at_result_iter_next_number(&iter, &state))
1178                 return;
1179
1180         switch (state) {
1181         case 3: /* SIM inserted and READY. */
1182                 break;
1183         default:
1184                 return;
1185         }
1186
1187         cb(&error, cbd->data);
1188
1189         g_at_chat_unregister(sd->chat, sd->ready_id);
1190         sd->ready_id = 0;
1191 }
1192
1193 static void sim_state_cb(gboolean present, gpointer user_data)
1194 {
1195         struct cb_data *cbd = user_data;
1196         struct sim_data *sd = cbd->user;
1197         ofono_sim_lock_unlock_cb_t cb = cbd->cb;
1198
1199         at_util_sim_state_query_free(sd->sim_state_query);
1200         sd->sim_state_query = NULL;
1201
1202         if (present == 1)
1203                 CALLBACK_WITH_SUCCESS(cb, cbd->data);
1204         else
1205                 CALLBACK_WITH_FAILURE(cb, cbd->data);
1206 }
1207
1208 static void at_pin_send_cb(gboolean ok, GAtResult *result,
1209                                 gpointer user_data)
1210 {
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;
1215
1216         decode_at_error(&error, g_at_result_final_response(result));
1217
1218         if (!ok)
1219                 goto done;
1220
1221         switch (sd->vendor) {
1222         case OFONO_VENDOR_IFX:
1223                 /*
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.
1227                  */
1228                 sd->ready_id = g_at_chat_register(sd->chat, "+XSIM",
1229                                                         at_xsim_notify,
1230                                                         FALSE, cbd, g_free);
1231                 return;
1232         case OFONO_VENDOR_MBM:
1233                 /*
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.
1237                  */
1238                 sd->ready_id = g_at_chat_register(sd->chat, "*EPEV",
1239                                                         at_epev_notify,
1240                                                         FALSE, cbd, g_free);
1241                 return;
1242         case OFONO_VENDOR_TELIT:
1243                 /*
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.
1247                  */
1248                 sd->ready_id = g_at_chat_register(sd->chat, "#QSS",
1249                                                         at_qss_notify,
1250                                                         FALSE, cbd, g_free);
1251                 return;
1252         case OFONO_VENDOR_ZTE:
1253         case OFONO_VENDOR_ALCATEL:
1254         case OFONO_VENDOR_HUAWEI:
1255                 /*
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.
1259                  */
1260                 sd->sim_state_query = at_util_sim_state_query_new(sd->chat,
1261                                                 2, 20, sim_state_cb, cbd,
1262                                                 g_free);
1263                 return;
1264         }
1265
1266 done:
1267         cb(&error, cbd->data);
1268
1269         g_free(cbd);
1270 }
1271
1272 static void at_pin_send(struct ofono_sim *sim, const char *passwd,
1273                         ofono_sim_lock_unlock_cb_t cb, void *data)
1274 {
1275         struct sim_data *sd = ofono_sim_get_data(sim);
1276         struct cb_data *cbd = cb_data_new(cb, data);
1277         char buf[64];
1278         int ret;
1279
1280         cbd->user = sd;
1281
1282         snprintf(buf, sizeof(buf), "AT+CPIN=\"%s\"", passwd);
1283
1284         ret = g_at_chat_send(sd->chat, buf, none_prefix,
1285                                 at_pin_send_cb, cbd, NULL);
1286
1287         memset(buf, 0, sizeof(buf));
1288
1289         if (ret > 0)
1290                 return;
1291
1292         g_free(cbd);
1293
1294         CALLBACK_WITH_FAILURE(cb, data);
1295 }
1296
1297 static void at_pin_send_puk(struct ofono_sim *sim, const char *puk,
1298                                 const char *passwd,
1299                                 ofono_sim_lock_unlock_cb_t cb, void *data)
1300 {
1301         struct sim_data *sd = ofono_sim_get_data(sim);
1302         struct cb_data *cbd = cb_data_new(cb, data);
1303         char buf[64];
1304         int ret;
1305
1306         cbd->user = sd;
1307
1308         snprintf(buf, sizeof(buf), "AT+CPIN=\"%s\",\"%s\"", puk, passwd);
1309
1310         ret = g_at_chat_send(sd->chat, buf, none_prefix,
1311                                 at_pin_send_cb, cbd, NULL);
1312
1313         memset(buf, 0, sizeof(buf));
1314
1315         if (ret > 0)
1316                 return;
1317
1318         g_free(cbd);
1319
1320         CALLBACK_WITH_FAILURE(cb, data);
1321 }
1322
1323 static void at_lock_unlock_cb(gboolean ok, GAtResult *result,
1324                                 gpointer user_data)
1325 {
1326         struct cb_data *cbd = user_data;
1327         ofono_sim_lock_unlock_cb_t cb = cbd->cb;
1328         struct ofono_error error;
1329
1330         decode_at_error(&error, g_at_result_final_response(result));
1331
1332         cb(&error, cbd->data);
1333 }
1334
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",
1344 };
1345
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)
1350 {
1351         struct sim_data *sd = ofono_sim_get_data(sim);
1352         struct cb_data *cbd = cb_data_new(cb, data);
1353         char buf[64];
1354         int ret;
1355         unsigned int len = sizeof(at_clck_cpwd_fac) / sizeof(*at_clck_cpwd_fac);
1356
1357         if (passwd_type >= len || at_clck_cpwd_fac[passwd_type] == NULL)
1358                 goto error;
1359
1360         snprintf(buf, sizeof(buf), "AT+CLCK=\"%s\",%i,\"%s\"",
1361                         at_clck_cpwd_fac[passwd_type], enable ? 1 : 0, passwd);
1362
1363         ret = g_at_chat_send(sd->chat, buf, none_prefix,
1364                                 at_lock_unlock_cb, cbd, g_free);
1365
1366         memset(buf, 0, sizeof(buf));
1367
1368         if (ret > 0)
1369                 return;
1370
1371 error:
1372         g_free(cbd);
1373
1374         CALLBACK_WITH_FAILURE(cb, data);
1375 }
1376
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)
1381 {
1382         struct sim_data *sd = ofono_sim_get_data(sim);
1383         struct cb_data *cbd = cb_data_new(cb, data);
1384         char buf[64];
1385         int ret;
1386         unsigned int len = sizeof(at_clck_cpwd_fac) / sizeof(*at_clck_cpwd_fac);
1387
1388         if (passwd_type >= len ||
1389                         at_clck_cpwd_fac[passwd_type] == NULL)
1390                 goto error;
1391
1392         snprintf(buf, sizeof(buf), "AT+CPWD=\"%s\",\"%s\",\"%s\"",
1393                         at_clck_cpwd_fac[passwd_type], old_passwd, new_passwd);
1394
1395         ret = g_at_chat_send(sd->chat, buf, none_prefix,
1396                                 at_lock_unlock_cb, cbd, g_free);
1397
1398         memset(buf, 0, sizeof(buf));
1399
1400         if (ret > 0)
1401                 return;
1402
1403 error:
1404         g_free(cbd);
1405
1406         CALLBACK_WITH_FAILURE(cb, data);
1407 }
1408
1409 static void at_lock_status_cb(gboolean ok, GAtResult *result,
1410                                 gpointer user_data)
1411 {
1412         struct cb_data *cbd = user_data;
1413         GAtResultIter iter;
1414         ofono_sim_locked_cb_t cb = cbd->cb;
1415         struct ofono_error error;
1416         int locked;
1417
1418         decode_at_error(&error, g_at_result_final_response(result));
1419
1420         if (!ok) {
1421                 cb(&error, -1, cbd->data);
1422                 return;
1423         }
1424
1425         g_at_result_iter_init(&iter, result);
1426
1427         if (!g_at_result_iter_next(&iter, "+CLCK:")) {
1428                 CALLBACK_WITH_FAILURE(cb, -1, cbd->data);
1429                 return;
1430         }
1431
1432         g_at_result_iter_next_number(&iter, &locked);
1433
1434         DBG("lock_status_cb: %i", locked);
1435
1436         cb(&error, locked, cbd->data);
1437 }
1438
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)
1442 {
1443         struct sim_data *sd = ofono_sim_get_data(sim);
1444         struct cb_data *cbd = cb_data_new(cb, data);
1445         char buf[64];
1446         unsigned int len = sizeof(at_clck_cpwd_fac) / sizeof(*at_clck_cpwd_fac);
1447
1448         if (passwd_type >= len || at_clck_cpwd_fac[passwd_type] == NULL)
1449                 goto error;
1450
1451         snprintf(buf, sizeof(buf), "AT+CLCK=\"%s\",2",
1452                         at_clck_cpwd_fac[passwd_type]);
1453
1454         if (g_at_chat_send(sd->chat, buf, clck_prefix,
1455                                 at_lock_status_cb, cbd, g_free) > 0)
1456                 return;
1457
1458 error:
1459         g_free(cbd);
1460
1461         CALLBACK_WITH_FAILURE(cb, -1, data);
1462 }
1463
1464 static gboolean at_sim_register(gpointer user)
1465 {
1466         struct ofono_sim *sim = user;
1467
1468         ofono_sim_register(sim);
1469
1470         return FALSE;
1471 }
1472
1473 static int at_sim_probe(struct ofono_sim *sim, unsigned int vendor,
1474                                 void *data)
1475 {
1476         GAtChat *chat = data;
1477         struct sim_data *sd;
1478
1479         sd = g_new0(struct sim_data, 1);
1480         sd->chat = g_at_chat_clone(chat);
1481         sd->vendor = vendor;
1482
1483         if (sd->vendor == OFONO_VENDOR_MBM)
1484                 g_at_chat_send(sd->chat, "AT*EPEE=1", NULL, NULL, NULL, NULL);
1485
1486         ofono_sim_set_data(sim, sd);
1487         g_idle_add(at_sim_register, sim);
1488
1489         return 0;
1490 }
1491
1492 static void at_sim_remove(struct ofono_sim *sim)
1493 {
1494         struct sim_data *sd = ofono_sim_get_data(sim);
1495
1496         g_idle_remove_by_data(sim);
1497         /* Cleanup potential SIM state polling */
1498         at_util_sim_state_query_free(sd->sim_state_query);
1499
1500         ofono_sim_set_data(sim, NULL);
1501
1502         g_at_chat_unref(sd->chat);
1503         g_free(sd);
1504 }
1505
1506 static struct ofono_sim_driver driver = {
1507         .name                   = "atmodem",
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,
1525 };
1526
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,
1539 };
1540
1541 void at_sim_init(void)
1542 {
1543         ofono_sim_driver_register(&driver);
1544         ofono_sim_driver_register(&driver_noef);
1545 }
1546
1547 void at_sim_exit(void)
1548 {
1549         ofono_sim_driver_unregister(&driver);
1550         ofono_sim_driver_unregister(&driver_noef);
1551 }