Upgrade ofono to 1.11 and merge to 2.0alpha
[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 *none_prefix[] = { NULL };
70
71 static void at_crsm_info_cb(gboolean ok, GAtResult *result, gpointer user_data)
72 {
73         struct cb_data *cbd = user_data;
74         GAtResultIter iter;
75         ofono_sim_file_info_cb_t cb = cbd->cb;
76         struct ofono_error error;
77         const guint8 *response;
78         gint sw1, sw2, len;
79         int flen, rlen;
80         int str;
81         unsigned char access[3];
82         unsigned char file_status;
83
84         decode_at_error(&error, g_at_result_final_response(result));
85
86         if (!ok) {
87                 cb(&error, -1, -1, -1, NULL, EF_STATUS_INVALIDATED, cbd->data);
88                 return;
89         }
90
91         g_at_result_iter_init(&iter, result);
92
93         if (!g_at_result_iter_next(&iter, "+CRSM:"))
94                 goto error;
95
96         g_at_result_iter_next_number(&iter, &sw1);
97         g_at_result_iter_next_number(&iter, &sw2);
98
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));
103
104                 error.type = OFONO_ERROR_TYPE_SIM;
105                 error.error = (sw1 << 8) | sw2;
106
107                 cb(&error, -1, -1, -1, NULL, EF_STATUS_INVALIDATED, cbd->data);
108                 return;
109         }
110
111         DBG("crsm_info_cb: %02x, %02x, %i", sw1, sw2, len);
112
113         if (response[0] == 0x62) {
114                 ok = sim_parse_3g_get_response(response, len, &flen, &rlen,
115                                                 &str, access, NULL);
116
117                 file_status = EF_STATUS_VALID;
118         } else
119                 ok = sim_parse_2g_get_response(response, len, &flen, &rlen,
120                                                 &str, access, &file_status);
121
122         if (!ok)
123                 goto error;
124
125         cb(&error, flen, str, rlen, access, file_status, cbd->data);
126
127         return;
128
129 error:
130         CALLBACK_WITH_FAILURE(cb, -1, -1, -1, NULL,
131                                 EF_STATUS_INVALIDATED, cbd->data);
132 }
133
134 static void at_sim_read_info(struct ofono_sim *sim, int fileid,
135                                         ofono_sim_file_info_cb_t cb,
136                                         void *data)
137 {
138         struct sim_data *sd = ofono_sim_get_data(sim);
139         struct cb_data *cbd;
140         char buf[64];
141
142         if (sd->vendor == OFONO_VENDOR_OPTION_HSO) {
143                 unsigned char access[3] = { 0x00, 0x00, 0x00 };
144
145                 if (fileid == SIM_EFAD_FILEID) {
146                         CALLBACK_WITH_SUCCESS(cb, 4, 0, 0, access,
147                                                 EF_STATUS_VALID, data);
148                         return;
149                 }
150         }
151
152         cbd = cb_data_new(cb, data);
153
154         snprintf(buf, sizeof(buf), "AT+CRSM=192,%i", fileid);
155
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 */
163                 break;
164         }
165
166         if (g_at_chat_send(sd->chat, buf, crsm_prefix,
167                                 at_crsm_info_cb, cbd, g_free) > 0)
168                 return;
169
170         g_free(cbd);
171
172         CALLBACK_WITH_FAILURE(cb, -1, -1, -1, NULL,
173                                 EF_STATUS_INVALIDATED, data);
174 }
175
176 static void at_crsm_read_cb(gboolean ok, GAtResult *result,
177                                 gpointer user_data)
178 {
179         struct cb_data *cbd = user_data;
180         GAtResultIter iter;
181         ofono_sim_read_cb_t cb = cbd->cb;
182         struct ofono_error error;
183         const guint8 *response;
184         gint sw1, sw2, len;
185
186         decode_at_error(&error, g_at_result_final_response(result));
187
188         if (!ok) {
189                 cb(&error, NULL, 0, cbd->data);
190                 return;
191         }
192
193         g_at_result_iter_init(&iter, result);
194
195         if (!g_at_result_iter_next(&iter, "+CRSM:")) {
196                 CALLBACK_WITH_FAILURE(cb, NULL, 0, cbd->data);
197                 return;
198         }
199
200         g_at_result_iter_next_number(&iter, &sw1);
201         g_at_result_iter_next_number(&iter, &sw2);
202
203         if ((sw1 != 0x90 && sw1 != 0x91 && sw1 != 0x92 && sw1 != 0x9f) ||
204                         (sw1 == 0x90 && sw2 != 0x00)) {
205                 memset(&error, 0, sizeof(error));
206
207                 error.type = OFONO_ERROR_TYPE_SIM;
208                 error.error = (sw1 << 8) | sw2;
209
210                 cb(&error, NULL, 0, cbd->data);
211                 return;
212         }
213
214         if (!g_at_result_iter_next_hexstring(&iter, &response, &len)) {
215                 CALLBACK_WITH_FAILURE(cb, NULL, 0, cbd->data);
216                 return;
217         }
218
219         DBG("crsm_read_cb: %02x, %02x, %d", sw1, sw2, len);
220
221         cb(&error, response, len, cbd->data);
222 }
223
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)
227 {
228         struct sim_data *sd = ofono_sim_get_data(sim);
229         struct cb_data *cbd = cb_data_new(cb, data);
230         char buf[64];
231
232         snprintf(buf, sizeof(buf), "AT+CRSM=176,%i,%i,%i,%i", fileid,
233                         start >> 8, start & 0xff, length);
234
235         if (g_at_chat_send(sd->chat, buf, crsm_prefix,
236                                 at_crsm_read_cb, cbd, g_free) > 0)
237                 return;
238
239         g_free(cbd);
240
241         CALLBACK_WITH_FAILURE(cb, NULL, 0, data);
242 }
243
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)
247 {
248         struct sim_data *sd = ofono_sim_get_data(sim);
249         struct cb_data *cbd = cb_data_new(cb, data);
250         char buf[64];
251
252         snprintf(buf, sizeof(buf), "AT+CRSM=178,%i,%i,4,%i", fileid,
253                         record, length);
254
255         if (g_at_chat_send(sd->chat, buf, crsm_prefix,
256                                 at_crsm_read_cb, cbd, g_free) > 0)
257                 return;
258
259         g_free(cbd);
260
261         CALLBACK_WITH_FAILURE(cb, NULL, 0, data);
262 }
263
264 static void at_crsm_update_cb(gboolean ok, GAtResult *result,
265                                 gpointer user_data)
266 {
267         struct cb_data *cbd = user_data;
268         GAtResultIter iter;
269         ofono_sim_write_cb_t cb = cbd->cb;
270         struct ofono_error error;
271         gint sw1, sw2;
272
273         decode_at_error(&error, g_at_result_final_response(result));
274
275         if (!ok) {
276                 cb(&error, cbd->data);
277                 return;
278         }
279
280         g_at_result_iter_init(&iter, result);
281
282         if (!g_at_result_iter_next(&iter, "+CRSM:")) {
283                 CALLBACK_WITH_FAILURE(cb, cbd->data);
284                 return;
285         }
286
287         g_at_result_iter_next_number(&iter, &sw1);
288         g_at_result_iter_next_number(&iter, &sw2);
289
290         if ((sw1 != 0x90 && sw1 != 0x91 && sw1 != 0x92 && sw1 != 0x9f) ||
291                         (sw1 == 0x90 && sw2 != 0x00)) {
292                 memset(&error, 0, sizeof(error));
293
294                 error.type = OFONO_ERROR_TYPE_SIM;
295                 error.error = (sw1 << 8) | sw2;
296         }
297
298         DBG("crsm_update_cb: %02x, %02x", sw1, sw2);
299
300         cb(&error, cbd->data);
301 }
302
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)
307 {
308         struct sim_data *sd = ofono_sim_get_data(sim);
309         struct cb_data *cbd = cb_data_new(cb, data);
310         char *buf;
311         gboolean quote = FALSE;
312         int len, ret;
313         int size = 36 + p3 * 2;
314
315         DBG("");
316
317         /* Add quotes */
318         switch (sd->vendor) {
319         case OFONO_VENDOR_MBM:
320         case OFONO_VENDOR_ZTE:
321         case OFONO_VENDOR_HUAWEI:
322         case OFONO_VENDOR_SPEEDUP:
323                 quote = TRUE;
324                 size += 2;
325                 break;
326         }
327
328         buf = g_try_new(char, size);
329         if (buf == NULL)
330                 goto error;
331
332         len = sprintf(buf, "AT+CRSM=%i,%i,%i,%i,%i,", cmd, fileid,p1, p2, p3);
333
334         if (quote)
335                 buf[len++] = '\"';
336
337         for (; p3; p3--)
338                 len += sprintf(buf + len, "%02hhX", *value++);
339
340         if (quote)
341                 buf[len++] = '\"';
342
343         ret = g_at_chat_send(sd->chat, buf, crsm_prefix,
344                                 at_crsm_update_cb, cbd, g_free);
345
346         g_free(buf);
347
348         if (ret > 0)
349                 return;
350
351 error:
352         g_free(cbd);
353
354         CALLBACK_WITH_FAILURE(cb, data);
355 }
356
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)
361 {
362         at_sim_update_file(sim, 214, fileid, start >> 8, start & 0xff,
363                                 length, value, cb, data);
364 }
365
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)
370 {
371         at_sim_update_file(sim, 220, fileid, record, 4, length,
372                                 value, cb, data);
373 }
374
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)
378 {
379         at_sim_update_file(sim, 220, fileid, 0, 3, length, value, cb, data);
380 }
381
382 static void at_cimi_cb(gboolean ok, GAtResult *result, gpointer user_data)
383 {
384         struct cb_data *cbd = user_data;
385         GAtResultIter iter;
386         ofono_sim_imsi_cb_t cb = cbd->cb;
387         struct ofono_error error;
388         const char *imsi;
389         int i;
390
391         decode_at_error(&error, g_at_result_final_response(result));
392
393         if (!ok) {
394                 cb(&error, NULL, cbd->data);
395                 return;
396         }
397
398         g_at_result_iter_init(&iter, result);
399
400         for (i = 0; i < g_at_result_num_response_lines(result); i++)
401                 g_at_result_iter_next(&iter, NULL);
402
403         imsi = g_at_result_iter_raw_line(&iter);
404
405         DBG("cimi_cb: %s", imsi);
406
407         cb(&error, imsi, cbd->data);
408 }
409
410 static void at_read_imsi(struct ofono_sim *sim, ofono_sim_imsi_cb_t cb,
411                                 void *data)
412 {
413         struct sim_data *sd = ofono_sim_get_data(sim);
414         struct cb_data *cbd = cb_data_new(cb, data);
415
416         if (g_at_chat_send(sd->chat, "AT+CIMI", NULL,
417                                 at_cimi_cb, cbd, g_free) > 0)
418                 return;
419
420         g_free(cbd);
421
422         CALLBACK_WITH_FAILURE(cb, NULL, data);
423 }
424
425 static struct {
426         enum ofono_sim_password_type type;
427         const char *name;
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"   },
445 };
446
447 #define BUILD_PIN_RETRIES_ARRAY(passwd_types, passwd_types_cnt, retry)  \
448         for (i = 0; i < OFONO_SIM_PASSWORD_INVALID; i++)                \
449                 retry[i] = -1;                                          \
450                                                                         \
451         for (i = 0; i < passwd_types_cnt; i++) {                        \
452                 int val;                                                \
453                                                                         \
454                 if (!g_at_result_iter_next_number(&iter, &val))         \
455                         goto error;                                     \
456                                                                         \
457                 retry[passwd_types[i]] = val;                           \
458                                                                         \
459                 DBG("retry counter id=%d, val=%d", passwd_types[i],     \
460                                         retry[passwd_types[i]]);        \
461         }                                                               \
462
463 static void huawei_cpin_cb(gboolean ok, GAtResult *result, gpointer user_data)
464 {
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);
468         GAtResultIter iter;
469         struct ofono_error error;
470         int retries[OFONO_SIM_PASSWORD_INVALID];
471         size_t i;
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,
477         };
478
479         decode_at_error(&error, final);
480
481         if (!ok) {
482                 cb(&error, NULL, cbd->data);
483                 return;
484         }
485
486         g_at_result_iter_init(&iter, result);
487
488         if (!g_at_result_iter_next(&iter, "^CPIN:"))
489                 goto error;
490
491         /* Skip status since we are not interested in this */
492         if (!g_at_result_iter_skip_next(&iter))
493                 goto error;
494
495         /* Skip "overall counter" since we'll grab each one individually */
496         if (!g_at_result_iter_skip_next(&iter))
497                 goto error;
498
499         BUILD_PIN_RETRIES_ARRAY(password_types, ARRAY_SIZE(password_types),
500                                 retries);
501
502         cb(&error, retries, cbd->data);
503
504         return;
505
506 error:
507         CALLBACK_WITH_FAILURE(cb, NULL, cbd->data);
508 }
509
510 static void pinnum_cb(gboolean ok, GAtResult *result, gpointer user_data)
511 {
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);
515         GAtResultIter iter;
516         struct ofono_error error;
517         int retries[OFONO_SIM_PASSWORD_INVALID];
518         size_t i;
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,
524         };
525
526
527         decode_at_error(&error, final);
528
529         if (!ok) {
530                 cb(&error, NULL, cbd->data);
531                 return;
532         }
533
534         g_at_result_iter_init(&iter, result);
535
536         if (!g_at_result_iter_next(&iter, "%PINNUM:"))
537                 goto error;
538
539         BUILD_PIN_RETRIES_ARRAY(password_types, ARRAY_SIZE(password_types),
540                                 retries);
541
542         cb(&error, retries, cbd->data);
543
544         return;
545
546 error:
547         CALLBACK_WITH_FAILURE(cb, NULL, cbd->data);
548 }
549
550 static void zpinpuk_cb(gboolean ok, GAtResult *result, gpointer user_data)
551 {
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);
555         GAtResultIter iter;
556         struct ofono_error error;
557         int retries[OFONO_SIM_PASSWORD_INVALID];
558         size_t i;
559         static enum ofono_sim_password_type password_types[] = {
560                 OFONO_SIM_PASSWORD_SIM_PIN,
561                 OFONO_SIM_PASSWORD_SIM_PUK,
562         };
563
564
565         decode_at_error(&error, final);
566
567         if (!ok) {
568                 cb(&error, NULL, cbd->data);
569                 return;
570         }
571
572         g_at_result_iter_init(&iter, result);
573
574         if (!g_at_result_iter_next(&iter, "+ZPINPUK:"))
575                 goto error;
576
577         BUILD_PIN_RETRIES_ARRAY(password_types, ARRAY_SIZE(password_types),
578                                 retries);
579
580         cb(&error, retries, cbd->data);
581
582         return;
583
584 error:
585         CALLBACK_WITH_FAILURE(cb, NULL, cbd->data);
586 }
587
588 static void xpincnt_cb(gboolean ok, GAtResult *result, gpointer user_data)
589 {
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);
593         GAtResultIter iter;
594         struct ofono_error error;
595         int retries[OFONO_SIM_PASSWORD_INVALID];
596         size_t i;
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,
602         };
603
604         decode_at_error(&error, final);
605
606         if (!ok) {
607                 cb(&error, NULL, cbd->data);
608                 return;
609         }
610
611         g_at_result_iter_init(&iter, result);
612
613         if (!g_at_result_iter_next(&iter, "+XPINCNT:"))
614                 goto error;
615
616         BUILD_PIN_RETRIES_ARRAY(password_types, ARRAY_SIZE(password_types),
617                                 retries);
618
619         cb(&error, retries, cbd->data);
620
621         return;
622
623 error:
624         CALLBACK_WITH_FAILURE(cb, NULL, cbd->data);
625 }
626
627 static void oercn_cb(gboolean ok, GAtResult *result, gpointer user_data)
628 {
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);
632         GAtResultIter iter;
633         struct ofono_error error;
634         int retries[OFONO_SIM_PASSWORD_INVALID];
635         size_t i;
636         static enum ofono_sim_password_type password_types[] = {
637                 OFONO_SIM_PASSWORD_SIM_PIN,
638                 OFONO_SIM_PASSWORD_SIM_PUK,
639         };
640
641         decode_at_error(&error, final);
642
643         if (!ok) {
644                 cb(&error, NULL, cbd->data);
645                 return;
646         }
647
648         g_at_result_iter_init(&iter, result);
649
650         if (!g_at_result_iter_next(&iter, "_OERCN:"))
651                 goto error;
652
653         BUILD_PIN_RETRIES_ARRAY(password_types, ARRAY_SIZE(password_types),
654                                 retries);
655
656         cb(&error, retries, cbd->data);
657
658         return;
659
660 error:
661         CALLBACK_WITH_FAILURE(cb, NULL, cbd->data);
662 }
663
664 static void cpnnum_cb(gboolean ok, GAtResult *result, gpointer user_data)
665 {
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);
669         GAtResultIter iter;
670         struct ofono_error error;
671         const char *line;
672         int num;
673         char **entries;
674         int retries[OFONO_SIM_PASSWORD_INVALID];
675         size_t i;
676
677         decode_at_error(&error, final);
678
679         if (!ok) {
680                 cb(&error, NULL, cbd->data);
681                 return;
682         }
683
684         g_at_result_iter_init(&iter, result);
685
686         for (num = 0; num < g_at_result_num_response_lines(result); num++)
687                 g_at_result_iter_next(&iter, NULL);
688
689         line = g_at_result_iter_raw_line(&iter);
690
691         DBG("%s", line);
692
693         for (i = 0; i < OFONO_SIM_PASSWORD_INVALID; i++)
694                 retries[i] = -1;
695
696         entries = g_strsplit(line, "; ", -1);
697
698         for (num = 0; entries[num]; num++) {
699                 int retry;
700
701                 if (strlen(entries[num]) < 5)
702                         continue;
703
704                 retry = strtol(entries[num] + 5, NULL, 10);
705                 if (retry == 0 && errno == EINVAL)
706                         continue;
707
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;
716         }
717
718         g_strfreev(entries);
719
720         cb(&error, retries, cbd->data);
721 }
722
723 static void at_epin_cb(gboolean ok, GAtResult *result, gpointer user_data)
724 {
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);
728         GAtResultIter iter;
729         struct ofono_error error;
730         int retries[OFONO_SIM_PASSWORD_INVALID];
731         size_t i;
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,
737         };
738
739         decode_at_error(&error, final);
740
741         if (!ok) {
742                 cb(&error, NULL, cbd->data);
743                 return;
744         }
745
746         g_at_result_iter_init(&iter, result);
747
748         if (!g_at_result_iter_next(&iter, "*EPIN:"))
749                 goto error;
750
751         BUILD_PIN_RETRIES_ARRAY(password_types, ARRAY_SIZE(password_types),
752                                 retries);
753
754         cb(&error, retries, cbd->data);
755
756         return;
757
758 error:
759         CALLBACK_WITH_FAILURE(cb, NULL, cbd->data);
760 }
761
762 static void at_cpinr_cb(gboolean ok, GAtResult *result, gpointer user_data)
763 {
764         struct cb_data *cbd = user_data;
765         ofono_sim_pin_retries_cb_t cb = cbd->cb;
766         GAtResultIter iter;
767         struct ofono_error error;
768         int retries[OFONO_SIM_PASSWORD_INVALID];
769         size_t len = sizeof(at_sim_name) / sizeof(*at_sim_name);
770         size_t i;
771
772         decode_at_error(&error, g_at_result_final_response(result));
773
774         if (!ok) {
775                 cb(&error, NULL, cbd->data);
776                 return;
777         }
778
779         for (i = 0; i < OFONO_SIM_PASSWORD_INVALID; i++)
780                 retries[i] = -1;
781
782         g_at_result_iter_init(&iter, result);
783
784         /* Ignore +CPINRE results... */
785         while (g_at_result_iter_next(&iter, "+CPINR:")) {
786                 const char *name;
787                 int val;
788
789                 if (!g_at_result_iter_next_unquoted_string(&iter, &name))
790                         continue;
791
792                 if (!g_at_result_iter_next_number(&iter, &val))
793                         continue;
794
795                 for (i = 1; i < len; i++) {
796                         if (!strcmp(name, at_sim_name[i].name)) {
797                                 retries[i] = val;
798                                 break;
799                         }
800                 }
801         }
802
803         cb(&error, retries, cbd->data);
804 }
805
806 static void at_spic_cb(gboolean ok, GAtResult *result, gpointer user_data)
807 {
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);
811         GAtResultIter iter;
812         struct ofono_error error;
813         int retries[OFONO_SIM_PASSWORD_INVALID];
814         size_t i;
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,
820         };
821
822         decode_at_error(&error, final);
823
824         if (!ok) {
825                 cb(&error, NULL, cbd->data);
826                 return;
827         }
828
829         g_at_result_iter_init(&iter, result);
830
831         if (!g_at_result_iter_next(&iter, "+SPIC:"))
832                 goto error;
833
834         BUILD_PIN_RETRIES_ARRAY(password_types, ARRAY_SIZE(password_types),
835                                 retries);
836
837         cb(&error, retries, cbd->data);
838
839         return;
840
841 error:
842         CALLBACK_WITH_FAILURE(cb, NULL, cbd->data);
843 }
844
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);
848
849 static void at_pct_cb(gboolean ok, GAtResult *result, gpointer user_data)
850 {
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);
855         GAtResultIter iter;
856         struct ofono_error error;
857         int retries[OFONO_SIM_PASSWORD_INVALID];
858         size_t i;
859         enum ofono_sim_password_type pin_type;
860
861         decode_at_error(&error, final);
862
863         if (!ok) {
864                 cb(&error, NULL, cbd->data);
865                 return;
866         }
867
868         g_at_result_iter_init(&iter, result);
869
870         for (i = 0; i < OFONO_SIM_PASSWORD_INVALID; i++)
871                 retries[i] = -1;
872
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:");
876
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);
881
882                 goto callback;
883         }
884
885         if (g_at_result_iter_next(&iter, "#PCT:") == FALSE)
886                 goto error;
887
888         if (g_at_result_iter_next_number(&iter, &retries[pin_type]) == FALSE)
889                 goto error;
890
891         DBG("retry counter id=%d, val=%d", pin_type, retries[pin_type]);
892
893 callback:
894         cb(&error, retries, cbd->data);
895
896         return;
897
898 error:
899         CALLBACK_WITH_FAILURE(cb, NULL, cbd->data);
900 }
901
902 static void at_pin_retries_query(struct ofono_sim *sim,
903                                         ofono_sim_pin_retries_cb_t cb,
904                                         void *data)
905 {
906         struct sim_data *sd = ofono_sim_get_data(sim);
907         struct cb_data *cbd = cb_data_new(cb, data);
908         cbd->user = sim;
909
910         DBG("");
911
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)
916                         return;
917                 break;
918         case OFONO_VENDOR_SPEEDUP:
919                 if (g_at_chat_send(sd->chat, "AT+CPNNUM", NULL,
920                                         cpnnum_cb, cbd, g_free) > 0)
921                         return;
922                 break;
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)
926                         return;
927                 break;
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)
931                         return;
932                 break;
933         case OFONO_VENDOR_ICERA:
934                 if (g_at_chat_send(sd->chat, "AT%PINNUM?", pinnum_prefix,
935                                         pinnum_cb, cbd, g_free) > 0)
936                         return;
937                 break;
938         case OFONO_VENDOR_ZTE:
939                 if (g_at_chat_send(sd->chat, "AT+ZPINPUK=?", zpinpuk_prefix,
940                                         zpinpuk_cb, cbd, g_free) > 0)
941                         return;
942                 break;
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)
946                         return;
947                 break;
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)
951                         return;
952                 break;
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)
956                         return;
957                 break;
958         default:
959                 if (g_at_chat_send(sd->chat, "AT+CPINR", cpinr_prefixes,
960                                         at_cpinr_cb, cbd, g_free) > 0)
961                         return;
962                 break;
963         }
964
965         g_free(cbd);
966
967         CALLBACK_WITH_FAILURE(cb, NULL, data);
968 }
969
970 static void at_cpin_cb(gboolean ok, GAtResult *result, gpointer user_data)
971 {
972         struct cb_data *cbd = user_data;
973         struct sim_data *sd = ofono_sim_get_data(cbd->user);
974         GAtResultIter iter;
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;
979         int i;
980         int len = sizeof(at_sim_name) / sizeof(*at_sim_name);
981         const char *final = g_at_result_final_response(result);
982
983         if (sd->vendor == OFONO_VENDOR_WAVECOM && ok && strlen(final) > 7)
984                 decode_at_error(&error, "OK");
985         else
986                 decode_at_error(&error, final);
987
988         if (!ok) {
989                 cb(&error, -1, cbd->data);
990                 return;
991         }
992
993         if (sd->vendor == OFONO_VENDOR_WAVECOM ||
994                         sd->vendor == OFONO_VENDOR_WAVECOM_Q2XXX) {
995                 /* +CPIN: <pin> */
996                 pin_required = final + 7;
997         } else {
998                 g_at_result_iter_init(&iter, result);
999
1000                 if (!g_at_result_iter_next(&iter, "+CPIN:")) {
1001                         CALLBACK_WITH_FAILURE(cb, -1, cbd->data);
1002                         return;
1003                 }
1004
1005                 g_at_result_iter_next_unquoted_string(&iter, &pin_required);
1006         }
1007
1008         for (i = 0; i < len; i++) {
1009                 if (strcmp(pin_required, at_sim_name[i].name))
1010                         continue;
1011
1012                 pin_type = at_sim_name[i].type;
1013                 break;
1014         }
1015
1016         if (pin_type == OFONO_SIM_PASSWORD_INVALID) {
1017                 CALLBACK_WITH_FAILURE(cb, -1, cbd->data);
1018                 return;
1019         }
1020
1021         DBG("crsm_pin_cb: %s", pin_required);
1022
1023         cb(&error, pin_type, cbd->data);
1024 }
1025
1026 static void at_pin_query(struct ofono_sim *sim, ofono_sim_passwd_cb_t cb,
1027                         void *data)
1028 {
1029         struct sim_data *sd = ofono_sim_get_data(sim);
1030         struct cb_data *cbd = cb_data_new(cb, data);
1031
1032         cbd->user = sim;
1033
1034         if (g_at_chat_send(sd->chat, "AT+CPIN?", cpin_prefix,
1035                                 at_cpin_cb, cbd, g_free) > 0)
1036                 return;
1037
1038         g_free(cbd);
1039
1040         CALLBACK_WITH_FAILURE(cb, -1, data);
1041 }
1042
1043 static void at_xsim_notify(GAtResult *result, gpointer user_data)
1044 {
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 };
1049         GAtResultIter iter;
1050         int state;
1051
1052         g_at_result_iter_init(&iter, result);
1053
1054         if (!g_at_result_iter_next(&iter, "+XSIM:"))
1055                 return;
1056
1057         if (!g_at_result_iter_next_number(&iter, &state))
1058                 return;
1059
1060         switch (state) {
1061         case 3: /* PIN verified â€“ Ready */
1062         case 7: /* ready for attach (+COPS) */
1063                 break;
1064         default:
1065                 return;
1066         }
1067
1068         cb(&error, cbd->data);
1069
1070         g_at_chat_unregister(sd->chat, sd->ready_id);
1071         sd->ready_id = 0;
1072 }
1073
1074 static void at_epev_notify(GAtResult *result, gpointer user_data)
1075 {
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 };
1080
1081         cb(&error, cbd->data);
1082
1083         g_at_chat_unregister(sd->chat, sd->ready_id);
1084         sd->ready_id = 0;
1085 }
1086
1087 static void at_qss_notify(GAtResult *result, gpointer user_data)
1088 {
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 };
1093         GAtResultIter iter;
1094         int state;
1095
1096         g_at_result_iter_init(&iter, result);
1097
1098         if (!g_at_result_iter_next(&iter, "#QSS:"))
1099                 return;
1100
1101         if (!g_at_result_iter_next_number(&iter, &state))
1102                 return;
1103
1104         switch (state) {
1105         case 2: /* PIN unlocked */
1106                 break;
1107         default:
1108                 return;
1109         }
1110
1111         cb(&error, cbd->data);
1112
1113         g_at_chat_unregister(sd->chat, sd->ready_id);
1114         sd->ready_id = 0;
1115 }
1116
1117 static void sim_state_cb(gboolean present, gpointer user_data)
1118 {
1119         struct cb_data *cbd = user_data;
1120         struct sim_data *sd = cbd->user;
1121         ofono_sim_lock_unlock_cb_t cb = cbd->cb;
1122
1123         at_util_sim_state_query_free(sd->sim_state_query);
1124         sd->sim_state_query = NULL;
1125
1126         if (present == 1)
1127                 CALLBACK_WITH_SUCCESS(cb, cbd->data);
1128         else
1129                 CALLBACK_WITH_FAILURE(cb, cbd->data);
1130 }
1131
1132 static void at_pin_send_cb(gboolean ok, GAtResult *result,
1133                                 gpointer user_data)
1134 {
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;
1139
1140         decode_at_error(&error, g_at_result_final_response(result));
1141
1142         if (!ok)
1143                 goto done;
1144
1145         switch (sd->vendor) {
1146         case OFONO_VENDOR_IFX:
1147                 /*
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.
1151                  */
1152                 sd->ready_id = g_at_chat_register(sd->chat, "+XSIM",
1153                                                         at_xsim_notify,
1154                                                         FALSE, cbd, g_free);
1155                 return;
1156         case OFONO_VENDOR_MBM:
1157                 /*
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.
1161                  */
1162                 sd->ready_id = g_at_chat_register(sd->chat, "*EPEV",
1163                                                         at_epev_notify,
1164                                                         FALSE, cbd, g_free);
1165                 return;
1166         case OFONO_VENDOR_TELIT:
1167                 /*
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.
1171                  */
1172                 sd->ready_id = g_at_chat_register(sd->chat, "#QSS",
1173                                                         at_qss_notify,
1174                                                         FALSE, cbd, g_free);
1175                 return;
1176         case OFONO_VENDOR_ZTE:
1177                 /*
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.
1181                  */
1182                 sd->sim_state_query = at_util_sim_state_query_new(sd->chat,
1183                                                 2, 20, sim_state_cb, cbd,
1184                                                 g_free);
1185                 return;
1186         }
1187
1188 done:
1189         cb(&error, cbd->data);
1190
1191         g_free(cbd);
1192 }
1193
1194 static void at_pin_send(struct ofono_sim *sim, const char *passwd,
1195                         ofono_sim_lock_unlock_cb_t cb, void *data)
1196 {
1197         struct sim_data *sd = ofono_sim_get_data(sim);
1198         struct cb_data *cbd = cb_data_new(cb, data);
1199         char buf[64];
1200         int ret;
1201
1202         cbd->user = sd;
1203
1204         snprintf(buf, sizeof(buf), "AT+CPIN=\"%s\"", passwd);
1205
1206         ret = g_at_chat_send(sd->chat, buf, none_prefix,
1207                                 at_pin_send_cb, cbd, NULL);
1208
1209         memset(buf, 0, sizeof(buf));
1210
1211         if (ret > 0)
1212                 return;
1213
1214         g_free(cbd);
1215
1216         CALLBACK_WITH_FAILURE(cb, data);
1217 }
1218
1219 static void at_pin_send_puk(struct ofono_sim *sim, const char *puk,
1220                                 const char *passwd,
1221                                 ofono_sim_lock_unlock_cb_t cb, void *data)
1222 {
1223         struct sim_data *sd = ofono_sim_get_data(sim);
1224         struct cb_data *cbd = cb_data_new(cb, data);
1225         char buf[64];
1226         int ret;
1227
1228         cbd->user = sd;
1229
1230         snprintf(buf, sizeof(buf), "AT+CPIN=\"%s\",\"%s\"", puk, passwd);
1231
1232         ret = g_at_chat_send(sd->chat, buf, none_prefix,
1233                                 at_pin_send_cb, cbd, NULL);
1234
1235         memset(buf, 0, sizeof(buf));
1236
1237         if (ret > 0)
1238                 return;
1239
1240         g_free(cbd);
1241
1242         CALLBACK_WITH_FAILURE(cb, data);
1243 }
1244
1245 static void at_lock_unlock_cb(gboolean ok, GAtResult *result,
1246                                 gpointer user_data)
1247 {
1248         struct cb_data *cbd = user_data;
1249         ofono_sim_lock_unlock_cb_t cb = cbd->cb;
1250         struct ofono_error error;
1251
1252         decode_at_error(&error, g_at_result_final_response(result));
1253
1254         cb(&error, cbd->data);
1255 }
1256
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",
1266 };
1267
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)
1272 {
1273         struct sim_data *sd = ofono_sim_get_data(sim);
1274         struct cb_data *cbd = cb_data_new(cb, data);
1275         char buf[64];
1276         int ret;
1277         unsigned int len = sizeof(at_clck_cpwd_fac) / sizeof(*at_clck_cpwd_fac);
1278
1279         if (passwd_type >= len || at_clck_cpwd_fac[passwd_type] == NULL)
1280                 goto error;
1281
1282         snprintf(buf, sizeof(buf), "AT+CLCK=\"%s\",%i,\"%s\"",
1283                         at_clck_cpwd_fac[passwd_type], enable ? 1 : 0, passwd);
1284
1285         ret = g_at_chat_send(sd->chat, buf, none_prefix,
1286                                 at_lock_unlock_cb, cbd, g_free);
1287
1288         memset(buf, 0, sizeof(buf));
1289
1290         if (ret > 0)
1291                 return;
1292
1293 error:
1294         g_free(cbd);
1295
1296         CALLBACK_WITH_FAILURE(cb, data);
1297 }
1298
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)
1303 {
1304         struct sim_data *sd = ofono_sim_get_data(sim);
1305         struct cb_data *cbd = cb_data_new(cb, data);
1306         char buf[64];
1307         int ret;
1308         unsigned int len = sizeof(at_clck_cpwd_fac) / sizeof(*at_clck_cpwd_fac);
1309
1310         if (passwd_type >= len ||
1311                         at_clck_cpwd_fac[passwd_type] == NULL)
1312                 goto error;
1313
1314         snprintf(buf, sizeof(buf), "AT+CPWD=\"%s\",\"%s\",\"%s\"",
1315                         at_clck_cpwd_fac[passwd_type], old_passwd, new_passwd);
1316
1317         ret = g_at_chat_send(sd->chat, buf, none_prefix,
1318                                 at_lock_unlock_cb, cbd, g_free);
1319
1320         memset(buf, 0, sizeof(buf));
1321
1322         if (ret > 0)
1323                 return;
1324
1325 error:
1326         g_free(cbd);
1327
1328         CALLBACK_WITH_FAILURE(cb, data);
1329 }
1330
1331 static void at_lock_status_cb(gboolean ok, GAtResult *result,
1332                                 gpointer user_data)
1333 {
1334         struct cb_data *cbd = user_data;
1335         GAtResultIter iter;
1336         ofono_sim_locked_cb_t cb = cbd->cb;
1337         struct ofono_error error;
1338         int locked;
1339
1340         decode_at_error(&error, g_at_result_final_response(result));
1341
1342         if (!ok) {
1343                 cb(&error, -1, cbd->data);
1344                 return;
1345         }
1346
1347         g_at_result_iter_init(&iter, result);
1348
1349         if (!g_at_result_iter_next(&iter, "+CLCK:")) {
1350                 CALLBACK_WITH_FAILURE(cb, -1, cbd->data);
1351                 return;
1352         }
1353
1354         g_at_result_iter_next_number(&iter, &locked);
1355
1356         DBG("lock_status_cb: %i", locked);
1357
1358         cb(&error, locked, cbd->data);
1359 }
1360
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)
1364 {
1365         struct sim_data *sd = ofono_sim_get_data(sim);
1366         struct cb_data *cbd = cb_data_new(cb, data);
1367         char buf[64];
1368         unsigned int len = sizeof(at_clck_cpwd_fac) / sizeof(*at_clck_cpwd_fac);
1369
1370         if (passwd_type >= len || at_clck_cpwd_fac[passwd_type] == NULL)
1371                 goto error;
1372
1373         snprintf(buf, sizeof(buf), "AT+CLCK=\"%s\",2",
1374                         at_clck_cpwd_fac[passwd_type]);
1375
1376         if (g_at_chat_send(sd->chat, buf, clck_prefix,
1377                                 at_lock_status_cb, cbd, g_free) > 0)
1378                 return;
1379
1380 error:
1381         g_free(cbd);
1382
1383         CALLBACK_WITH_FAILURE(cb, -1, data);
1384 }
1385
1386 static gboolean at_sim_register(gpointer user)
1387 {
1388         struct ofono_sim *sim = user;
1389
1390         ofono_sim_register(sim);
1391
1392         return FALSE;
1393 }
1394
1395 static int at_sim_probe(struct ofono_sim *sim, unsigned int vendor,
1396                                 void *data)
1397 {
1398         GAtChat *chat = data;
1399         struct sim_data *sd;
1400
1401         sd = g_new0(struct sim_data, 1);
1402         sd->chat = g_at_chat_clone(chat);
1403         sd->vendor = vendor;
1404
1405         switch (sd->vendor) {
1406         case OFONO_VENDOR_WAVECOM:
1407                 g_at_chat_add_terminator(sd->chat, "+CPIN:", 6, TRUE);
1408                 break;
1409         case OFONO_VENDOR_MBM:
1410                 g_at_chat_send(sd->chat, "AT*EPEE=1", NULL, NULL, NULL, NULL);
1411                 break;
1412         case OFONO_VENDOR_WAVECOM_Q2XXX:
1413                 g_at_chat_add_terminator(chat, "+CPIN: READY", -1, TRUE);
1414                 break;
1415         default:
1416                 break;
1417         }
1418
1419         ofono_sim_set_data(sim, sd);
1420         g_idle_add(at_sim_register, sim);
1421
1422         return 0;
1423 }
1424
1425 static void at_sim_remove(struct ofono_sim *sim)
1426 {
1427         struct sim_data *sd = ofono_sim_get_data(sim);
1428
1429         /* Cleanup potential SIM state polling */
1430         at_util_sim_state_query_free(sd->sim_state_query);
1431
1432         ofono_sim_set_data(sim, NULL);
1433
1434         g_at_chat_unref(sd->chat);
1435         g_free(sd);
1436 }
1437
1438 static struct ofono_sim_driver driver = {
1439         .name                   = "atmodem",
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,
1457 };
1458
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,
1471 };
1472
1473 void at_sim_init(void)
1474 {
1475         ofono_sim_driver_register(&driver);
1476         ofono_sim_driver_register(&driver_noef);
1477 }
1478
1479 void at_sim_exit(void)
1480 {
1481         ofono_sim_driver_unregister(&driver);
1482         ofono_sim_driver_unregister(&driver_noef);
1483 }