7b48cd9a86b74705d6bec39c14b3e708a9c315d6
[platform/upstream/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 *none_prefix[] = { NULL };
69
70 static void at_crsm_info_cb(gboolean ok, GAtResult *result, gpointer user_data)
71 {
72         struct cb_data *cbd = user_data;
73         GAtResultIter iter;
74         ofono_sim_file_info_cb_t cb = cbd->cb;
75         struct ofono_error error;
76         const guint8 *response;
77         gint sw1, sw2, len;
78         int flen, rlen;
79         int str;
80         unsigned char access[3];
81         unsigned char file_status;
82
83         decode_at_error(&error, g_at_result_final_response(result));
84
85         if (!ok) {
86                 cb(&error, -1, -1, -1, NULL, EF_STATUS_INVALIDATED, cbd->data);
87                 return;
88         }
89
90         g_at_result_iter_init(&iter, result);
91
92         if (!g_at_result_iter_next(&iter, "+CRSM:"))
93                 goto error;
94
95         g_at_result_iter_next_number(&iter, &sw1);
96         g_at_result_iter_next_number(&iter, &sw2);
97
98         if (!g_at_result_iter_next_hexstring(&iter, &response, &len) ||
99                         (sw1 != 0x90 && sw1 != 0x91 && sw1 != 0x92) ||
100                         (sw1 == 0x90 && sw2 != 0x00)) {
101                 memset(&error, 0, sizeof(error));
102
103                 error.type = OFONO_ERROR_TYPE_SIM;
104                 error.error = (sw1 << 8) | sw2;
105
106                 cb(&error, -1, -1, -1, NULL, EF_STATUS_INVALIDATED, cbd->data);
107                 return;
108         }
109
110         DBG("crsm_info_cb: %02x, %02x, %i", sw1, sw2, len);
111
112         if (response[0] == 0x62) {
113                 ok = sim_parse_3g_get_response(response, len, &flen, &rlen,
114                                                 &str, access, NULL);
115
116                 file_status = EF_STATUS_VALID;
117         } else
118                 ok = sim_parse_2g_get_response(response, len, &flen, &rlen,
119                                                 &str, access, &file_status);
120
121         if (!ok)
122                 goto error;
123
124         cb(&error, flen, str, rlen, access, file_status, cbd->data);
125
126         return;
127
128 error:
129         CALLBACK_WITH_FAILURE(cb, -1, -1, -1, NULL,
130                                 EF_STATUS_INVALIDATED, cbd->data);
131 }
132
133 static void at_sim_read_info(struct ofono_sim *sim, int fileid,
134                                         ofono_sim_file_info_cb_t cb,
135                                         void *data)
136 {
137         struct sim_data *sd = ofono_sim_get_data(sim);
138         struct cb_data *cbd;
139         char buf[64];
140
141         if (sd->vendor == OFONO_VENDOR_OPTION_HSO) {
142                 unsigned char access[3] = { 0x00, 0x00, 0x00 };
143
144                 if (fileid == SIM_EFAD_FILEID) {
145                         CALLBACK_WITH_SUCCESS(cb, 4, 0, 0, access,
146                                                 EF_STATUS_VALID, data);
147                         return;
148                 }
149         }
150
151         cbd = cb_data_new(cb, data);
152
153         snprintf(buf, sizeof(buf), "AT+CRSM=192,%i", fileid);
154
155         switch (sd->vendor) {
156         case OFONO_VENDOR_ZTE:
157         case OFONO_VENDOR_HUAWEI:
158         case OFONO_VENDOR_SIERRA:
159         case OFONO_VENDOR_SPEEDUP:
160         case OFONO_VENDOR_QUALCOMM_MSM:
161                 strcat(buf, ",0,0,255"); /* Maximum possible length */
162                 break;
163         }
164
165         if (g_at_chat_send(sd->chat, buf, crsm_prefix,
166                                 at_crsm_info_cb, cbd, g_free) > 0)
167                 return;
168
169         g_free(cbd);
170
171         CALLBACK_WITH_FAILURE(cb, -1, -1, -1, NULL,
172                                 EF_STATUS_INVALIDATED, data);
173 }
174
175 static void at_crsm_read_cb(gboolean ok, GAtResult *result,
176                                 gpointer user_data)
177 {
178         struct cb_data *cbd = user_data;
179         GAtResultIter iter;
180         ofono_sim_read_cb_t cb = cbd->cb;
181         struct ofono_error error;
182         const guint8 *response;
183         gint sw1, sw2, len;
184
185         decode_at_error(&error, g_at_result_final_response(result));
186
187         if (!ok) {
188                 cb(&error, NULL, 0, cbd->data);
189                 return;
190         }
191
192         g_at_result_iter_init(&iter, result);
193
194         if (!g_at_result_iter_next(&iter, "+CRSM:")) {
195                 CALLBACK_WITH_FAILURE(cb, NULL, 0, cbd->data);
196                 return;
197         }
198
199         g_at_result_iter_next_number(&iter, &sw1);
200         g_at_result_iter_next_number(&iter, &sw2);
201
202         if ((sw1 != 0x90 && sw1 != 0x91 && sw1 != 0x92 && sw1 != 0x9f) ||
203                         (sw1 == 0x90 && sw2 != 0x00)) {
204                 memset(&error, 0, sizeof(error));
205
206                 error.type = OFONO_ERROR_TYPE_SIM;
207                 error.error = (sw1 << 8) | sw2;
208
209                 cb(&error, NULL, 0, cbd->data);
210                 return;
211         }
212
213         if (!g_at_result_iter_next_hexstring(&iter, &response, &len)) {
214                 CALLBACK_WITH_FAILURE(cb, NULL, 0, cbd->data);
215                 return;
216         }
217
218         DBG("crsm_read_cb: %02x, %02x, %d", sw1, sw2, len);
219
220         cb(&error, response, len, cbd->data);
221 }
222
223 static void at_sim_read_binary(struct ofono_sim *sim, int fileid,
224                                         int start, int length,
225                                         ofono_sim_read_cb_t cb, void *data)
226 {
227         struct sim_data *sd = ofono_sim_get_data(sim);
228         struct cb_data *cbd = cb_data_new(cb, data);
229         char buf[64];
230
231         snprintf(buf, sizeof(buf), "AT+CRSM=176,%i,%i,%i,%i", fileid,
232                         start >> 8, start & 0xff, length);
233
234         if (g_at_chat_send(sd->chat, buf, crsm_prefix,
235                                 at_crsm_read_cb, cbd, g_free) > 0)
236                 return;
237
238         g_free(cbd);
239
240         CALLBACK_WITH_FAILURE(cb, NULL, 0, data);
241 }
242
243 static void at_sim_read_record(struct ofono_sim *sim, int fileid,
244                                         int record, int length,
245                                         ofono_sim_read_cb_t cb, void *data)
246 {
247         struct sim_data *sd = ofono_sim_get_data(sim);
248         struct cb_data *cbd = cb_data_new(cb, data);
249         char buf[64];
250
251         snprintf(buf, sizeof(buf), "AT+CRSM=178,%i,%i,4,%i", fileid,
252                         record, length);
253
254         if (g_at_chat_send(sd->chat, buf, crsm_prefix,
255                                 at_crsm_read_cb, cbd, g_free) > 0)
256                 return;
257
258         g_free(cbd);
259
260         CALLBACK_WITH_FAILURE(cb, NULL, 0, data);
261 }
262
263 static void at_crsm_update_cb(gboolean ok, GAtResult *result,
264                                 gpointer user_data)
265 {
266         struct cb_data *cbd = user_data;
267         GAtResultIter iter;
268         ofono_sim_write_cb_t cb = cbd->cb;
269         struct ofono_error error;
270         gint sw1, sw2;
271
272         decode_at_error(&error, g_at_result_final_response(result));
273
274         if (!ok) {
275                 cb(&error, cbd->data);
276                 return;
277         }
278
279         g_at_result_iter_init(&iter, result);
280
281         if (!g_at_result_iter_next(&iter, "+CRSM:")) {
282                 CALLBACK_WITH_FAILURE(cb, cbd->data);
283                 return;
284         }
285
286         g_at_result_iter_next_number(&iter, &sw1);
287         g_at_result_iter_next_number(&iter, &sw2);
288
289         if ((sw1 != 0x90 && sw1 != 0x91 && sw1 != 0x92 && sw1 != 0x9f) ||
290                         (sw1 == 0x90 && sw2 != 0x00)) {
291                 memset(&error, 0, sizeof(error));
292
293                 error.type = OFONO_ERROR_TYPE_SIM;
294                 error.error = (sw1 << 8) | sw2;
295         }
296
297         DBG("crsm_update_cb: %02x, %02x", sw1, sw2);
298
299         cb(&error, cbd->data);
300 }
301
302 static void at_sim_update_file(struct ofono_sim *sim, int cmd, int fileid,
303                                 int p1, int p2, int p3,
304                                 const unsigned char *value,
305                                 ofono_sim_write_cb_t cb, void *data)
306 {
307         struct sim_data *sd = ofono_sim_get_data(sim);
308         struct cb_data *cbd = cb_data_new(cb, data);
309         char *buf;
310         gboolean quote = FALSE;
311         int len, ret;
312         int size = 36 + p3 * 2;
313
314         DBG("");
315
316         /* Add quotes */
317         switch (sd->vendor) {
318         case OFONO_VENDOR_MBM:
319         case OFONO_VENDOR_ZTE:
320         case OFONO_VENDOR_HUAWEI:
321         case OFONO_VENDOR_SPEEDUP:
322                 quote = TRUE;
323                 size += 2;
324                 break;
325         }
326
327         buf = g_try_new(char, size);
328         if (buf == NULL)
329                 goto error;
330
331         len = sprintf(buf, "AT+CRSM=%i,%i,%i,%i,%i,", cmd, fileid,p1, p2, p3);
332
333         if (quote)
334                 buf[len++] = '\"';
335
336         for (; p3; p3--)
337                 len += sprintf(buf + len, "%02hhX", *value++);
338
339         if (quote)
340                 buf[len++] = '\"';
341
342         ret = g_at_chat_send(sd->chat, buf, crsm_prefix,
343                                 at_crsm_update_cb, cbd, g_free);
344
345         g_free(buf);
346
347         if (ret > 0)
348                 return;
349
350 error:
351         g_free(cbd);
352
353         CALLBACK_WITH_FAILURE(cb, data);
354 }
355
356 static void at_sim_update_binary(struct ofono_sim *sim, int fileid,
357                                         int start, int length,
358                                         const unsigned char *value,
359                                         ofono_sim_write_cb_t cb, void *data)
360 {
361         at_sim_update_file(sim, 214, fileid, start >> 8, start & 0xff,
362                                 length, value, cb, data);
363 }
364
365 static void at_sim_update_record(struct ofono_sim *sim, int fileid,
366                                         int record, int length,
367                                         const unsigned char *value,
368                                         ofono_sim_write_cb_t cb, void *data)
369 {
370         at_sim_update_file(sim, 220, fileid, record, 4, length,
371                                 value, cb, data);
372 }
373
374 static void at_sim_update_cyclic(struct ofono_sim *sim, int fileid,
375                                         int length, const unsigned char *value,
376                                         ofono_sim_write_cb_t cb, void *data)
377 {
378         at_sim_update_file(sim, 220, fileid, 0, 3, length, value, cb, data);
379 }
380
381 static void at_cimi_cb(gboolean ok, GAtResult *result, gpointer user_data)
382 {
383         struct cb_data *cbd = user_data;
384         GAtResultIter iter;
385         ofono_sim_imsi_cb_t cb = cbd->cb;
386         struct ofono_error error;
387         const char *imsi;
388         int i;
389
390         decode_at_error(&error, g_at_result_final_response(result));
391
392         if (!ok) {
393                 cb(&error, NULL, cbd->data);
394                 return;
395         }
396
397         g_at_result_iter_init(&iter, result);
398
399         for (i = 0; i < g_at_result_num_response_lines(result); i++)
400                 g_at_result_iter_next(&iter, NULL);
401
402         imsi = g_at_result_iter_raw_line(&iter);
403
404         DBG("cimi_cb: %s", imsi);
405
406         cb(&error, imsi, cbd->data);
407 }
408
409 static void at_read_imsi(struct ofono_sim *sim, ofono_sim_imsi_cb_t cb,
410                                 void *data)
411 {
412         struct sim_data *sd = ofono_sim_get_data(sim);
413         struct cb_data *cbd = cb_data_new(cb, data);
414
415         if (g_at_chat_send(sd->chat, "AT+CIMI", NULL,
416                                 at_cimi_cb, cbd, g_free) > 0)
417                 return;
418
419         g_free(cbd);
420
421         CALLBACK_WITH_FAILURE(cb, NULL, data);
422 }
423
424 static struct {
425         enum ofono_sim_password_type type;
426         const char *name;
427 } const at_sim_name[] = {
428         { OFONO_SIM_PASSWORD_NONE,              "READY"         },
429         { OFONO_SIM_PASSWORD_SIM_PIN,           "SIM PIN"       },
430         { OFONO_SIM_PASSWORD_SIM_PUK,           "SIM PUK"       },
431         { OFONO_SIM_PASSWORD_PHSIM_PIN,         "PH-SIM PIN"    },
432         { OFONO_SIM_PASSWORD_PHFSIM_PIN,        "PH-FSIM PIN"   },
433         { OFONO_SIM_PASSWORD_PHFSIM_PUK,        "PH-FSIM PUK"   },
434         { OFONO_SIM_PASSWORD_SIM_PIN2,          "SIM PIN2"      },
435         { OFONO_SIM_PASSWORD_SIM_PUK2,          "SIM PUK2"      },
436         { OFONO_SIM_PASSWORD_PHNET_PIN,         "PH-NET PIN"    },
437         { OFONO_SIM_PASSWORD_PHNET_PUK,         "PH-NET PUK"    },
438         { OFONO_SIM_PASSWORD_PHNETSUB_PIN,      "PH-NETSUB PIN" },
439         { OFONO_SIM_PASSWORD_PHNETSUB_PUK,      "PH-NETSUB PUK" },
440         { OFONO_SIM_PASSWORD_PHSP_PIN,          "PH-SP PIN"     },
441         { OFONO_SIM_PASSWORD_PHSP_PUK,          "PH-SP PUK"     },
442         { OFONO_SIM_PASSWORD_PHCORP_PIN,        "PH-CORP PIN"   },
443         { OFONO_SIM_PASSWORD_PHCORP_PUK,        "PH-CORP PUK"   },
444 };
445
446 #define BUILD_PIN_RETRIES_ARRAY(passwd_types, passwd_types_cnt, retry)  \
447         for (i = 0; i < OFONO_SIM_PASSWORD_INVALID; i++)                \
448                 retry[i] = -1;                                          \
449                                                                         \
450         for (i = 0; i < passwd_types_cnt; i++) {                        \
451                 int val;                                                \
452                                                                         \
453                 if (!g_at_result_iter_next_number(&iter, &val))         \
454                         goto error;                                     \
455                                                                         \
456                 retry[passwd_types[i]] = val;                           \
457                                                                         \
458                 DBG("retry counter id=%d, val=%d", passwd_types[i],     \
459                                         retry[passwd_types[i]]);        \
460         }                                                               \
461
462 static void huawei_cpin_cb(gboolean ok, GAtResult *result, gpointer user_data)
463 {
464         struct cb_data *cbd = user_data;
465         ofono_sim_pin_retries_cb_t cb = cbd->cb;
466         const char *final = g_at_result_final_response(result);
467         GAtResultIter iter;
468         struct ofono_error error;
469         int retries[OFONO_SIM_PASSWORD_INVALID];
470         size_t i;
471         static enum ofono_sim_password_type password_types[] = {
472                 OFONO_SIM_PASSWORD_SIM_PUK,
473                 OFONO_SIM_PASSWORD_SIM_PIN,
474                 OFONO_SIM_PASSWORD_SIM_PUK2,
475                 OFONO_SIM_PASSWORD_SIM_PIN2,
476         };
477
478         decode_at_error(&error, final);
479
480         if (!ok) {
481                 cb(&error, NULL, cbd->data);
482                 return;
483         }
484
485         g_at_result_iter_init(&iter, result);
486
487         if (!g_at_result_iter_next(&iter, "^CPIN:"))
488                 goto error;
489
490         /* Skip status since we are not interested in this */
491         if (!g_at_result_iter_skip_next(&iter))
492                 goto error;
493
494         /* Skip "overall counter" since we'll grab each one individually */
495         if (!g_at_result_iter_skip_next(&iter))
496                 goto error;
497
498         BUILD_PIN_RETRIES_ARRAY(password_types, ARRAY_SIZE(password_types),
499                                 retries);
500
501         cb(&error, retries, cbd->data);
502
503         return;
504
505 error:
506         CALLBACK_WITH_FAILURE(cb, NULL, cbd->data);
507 }
508
509 static void pinnum_cb(gboolean ok, GAtResult *result, gpointer user_data)
510 {
511         struct cb_data *cbd = user_data;
512         ofono_sim_pin_retries_cb_t cb = cbd->cb;
513         const char *final = g_at_result_final_response(result);
514         GAtResultIter iter;
515         struct ofono_error error;
516         int retries[OFONO_SIM_PASSWORD_INVALID];
517         size_t i;
518         static enum ofono_sim_password_type password_types[] = {
519                 OFONO_SIM_PASSWORD_SIM_PIN,
520                 OFONO_SIM_PASSWORD_SIM_PUK,
521                 OFONO_SIM_PASSWORD_SIM_PIN2,
522                 OFONO_SIM_PASSWORD_SIM_PUK2,
523         };
524
525
526         decode_at_error(&error, final);
527
528         if (!ok) {
529                 cb(&error, NULL, cbd->data);
530                 return;
531         }
532
533         g_at_result_iter_init(&iter, result);
534
535         if (!g_at_result_iter_next(&iter, "%PINNUM:"))
536                 goto error;
537
538         BUILD_PIN_RETRIES_ARRAY(password_types, ARRAY_SIZE(password_types),
539                                 retries);
540
541         cb(&error, retries, cbd->data);
542
543         return;
544
545 error:
546         CALLBACK_WITH_FAILURE(cb, NULL, cbd->data);
547 }
548
549 static void zpinpuk_cb(gboolean ok, GAtResult *result, gpointer user_data)
550 {
551         struct cb_data *cbd = user_data;
552         ofono_sim_pin_retries_cb_t cb = cbd->cb;
553         const char *final = g_at_result_final_response(result);
554         GAtResultIter iter;
555         struct ofono_error error;
556         int retries[OFONO_SIM_PASSWORD_INVALID];
557         size_t i;
558         static enum ofono_sim_password_type password_types[] = {
559                 OFONO_SIM_PASSWORD_SIM_PIN,
560                 OFONO_SIM_PASSWORD_SIM_PUK,
561         };
562
563
564         decode_at_error(&error, final);
565
566         if (!ok) {
567                 cb(&error, NULL, cbd->data);
568                 return;
569         }
570
571         g_at_result_iter_init(&iter, result);
572
573         if (!g_at_result_iter_next(&iter, "+ZPINPUK:"))
574                 goto error;
575
576         BUILD_PIN_RETRIES_ARRAY(password_types, ARRAY_SIZE(password_types),
577                                 retries);
578
579         cb(&error, retries, cbd->data);
580
581         return;
582
583 error:
584         CALLBACK_WITH_FAILURE(cb, NULL, cbd->data);
585 }
586
587 static void xpincnt_cb(gboolean ok, GAtResult *result, gpointer user_data)
588 {
589         struct cb_data *cbd = user_data;
590         ofono_sim_pin_retries_cb_t cb = cbd->cb;
591         const char *final = g_at_result_final_response(result);
592         GAtResultIter iter;
593         struct ofono_error error;
594         int retries[OFONO_SIM_PASSWORD_INVALID];
595         size_t i;
596         static enum ofono_sim_password_type password_types[] = {
597                 OFONO_SIM_PASSWORD_SIM_PIN,
598                 OFONO_SIM_PASSWORD_SIM_PIN2,
599                 OFONO_SIM_PASSWORD_SIM_PUK,
600                 OFONO_SIM_PASSWORD_SIM_PUK2,
601         };
602
603         decode_at_error(&error, final);
604
605         if (!ok) {
606                 cb(&error, NULL, cbd->data);
607                 return;
608         }
609
610         g_at_result_iter_init(&iter, result);
611
612         if (!g_at_result_iter_next(&iter, "+XPINCNT:"))
613                 goto error;
614
615         BUILD_PIN_RETRIES_ARRAY(password_types, ARRAY_SIZE(password_types),
616                                 retries);
617
618         cb(&error, retries, cbd->data);
619
620         return;
621
622 error:
623         CALLBACK_WITH_FAILURE(cb, NULL, cbd->data);
624 }
625
626 static void oercn_cb(gboolean ok, GAtResult *result, gpointer user_data)
627 {
628         struct cb_data *cbd = user_data;
629         ofono_sim_pin_retries_cb_t cb = cbd->cb;
630         const char *final = g_at_result_final_response(result);
631         GAtResultIter iter;
632         struct ofono_error error;
633         int retries[OFONO_SIM_PASSWORD_INVALID];
634         size_t i;
635         static enum ofono_sim_password_type password_types[] = {
636                 OFONO_SIM_PASSWORD_SIM_PIN,
637                 OFONO_SIM_PASSWORD_SIM_PUK,
638         };
639
640         decode_at_error(&error, final);
641
642         if (!ok) {
643                 cb(&error, NULL, cbd->data);
644                 return;
645         }
646
647         g_at_result_iter_init(&iter, result);
648
649         if (!g_at_result_iter_next(&iter, "_OERCN:"))
650                 goto error;
651
652         BUILD_PIN_RETRIES_ARRAY(password_types, ARRAY_SIZE(password_types),
653                                 retries);
654
655         cb(&error, retries, cbd->data);
656
657         return;
658
659 error:
660         CALLBACK_WITH_FAILURE(cb, NULL, cbd->data);
661 }
662
663 static void cpnnum_cb(gboolean ok, GAtResult *result, gpointer user_data)
664 {
665         struct cb_data *cbd = user_data;
666         ofono_sim_pin_retries_cb_t cb = cbd->cb;
667         const char *final = g_at_result_final_response(result);
668         GAtResultIter iter;
669         struct ofono_error error;
670         const char *line;
671         int num;
672         char **entries;
673         int retries[OFONO_SIM_PASSWORD_INVALID];
674         size_t i;
675
676         decode_at_error(&error, final);
677
678         if (!ok) {
679                 cb(&error, NULL, cbd->data);
680                 return;
681         }
682
683         g_at_result_iter_init(&iter, result);
684
685         for (num = 0; num < g_at_result_num_response_lines(result); num++)
686                 g_at_result_iter_next(&iter, NULL);
687
688         line = g_at_result_iter_raw_line(&iter);
689
690         DBG("%s", line);
691
692         for (i = 0; i < OFONO_SIM_PASSWORD_INVALID; i++)
693                 retries[i] = -1;
694
695         entries = g_strsplit(line, "; ", -1);
696
697         for (num = 0; entries[num]; num++) {
698                 int retry;
699
700                 if (strlen(entries[num]) < 5)
701                         continue;
702
703                 retry = strtol(entries[num] + 5, NULL, 10);
704                 if (retry == 0 && errno == EINVAL)
705                         continue;
706
707                 if (g_str_has_prefix(entries[num], "PIN1=") == TRUE)
708                         retries[OFONO_SIM_PASSWORD_SIM_PIN] = retry;
709                 else if (g_str_has_prefix(entries[num], "PUK1=") == TRUE)
710                         retries[OFONO_SIM_PASSWORD_SIM_PUK] = retry;
711                 else if (g_str_has_prefix(entries[num], "PIN2=") == TRUE)
712                         retries[OFONO_SIM_PASSWORD_SIM_PIN2] = retry;
713                 else if (g_str_has_prefix(entries[num], "PUK2=") == TRUE)
714                         retries[OFONO_SIM_PASSWORD_SIM_PUK2] = retry;
715         }
716
717         g_strfreev(entries);
718
719         cb(&error, retries, cbd->data);
720 }
721
722 static void at_epin_cb(gboolean ok, GAtResult *result, gpointer user_data)
723 {
724         struct cb_data *cbd = user_data;
725         ofono_sim_pin_retries_cb_t cb = cbd->cb;
726         const char *final = g_at_result_final_response(result);
727         GAtResultIter iter;
728         struct ofono_error error;
729         int retries[OFONO_SIM_PASSWORD_INVALID];
730         size_t i;
731         static enum ofono_sim_password_type password_types[] = {
732                 OFONO_SIM_PASSWORD_SIM_PIN,
733                 OFONO_SIM_PASSWORD_SIM_PUK,
734                 OFONO_SIM_PASSWORD_SIM_PIN2,
735                 OFONO_SIM_PASSWORD_SIM_PUK2,
736         };
737
738         decode_at_error(&error, final);
739
740         if (!ok) {
741                 cb(&error, NULL, cbd->data);
742                 return;
743         }
744
745         g_at_result_iter_init(&iter, result);
746
747         if (!g_at_result_iter_next(&iter, "*EPIN:"))
748                 goto error;
749
750         BUILD_PIN_RETRIES_ARRAY(password_types, ARRAY_SIZE(password_types),
751                                 retries);
752
753         cb(&error, retries, cbd->data);
754
755         return;
756
757 error:
758         CALLBACK_WITH_FAILURE(cb, NULL, cbd->data);
759 }
760
761 static void at_cpinr_cb(gboolean ok, GAtResult *result, gpointer user_data)
762 {
763         struct cb_data *cbd = user_data;
764         ofono_sim_pin_retries_cb_t cb = cbd->cb;
765         GAtResultIter iter;
766         struct ofono_error error;
767         int retries[OFONO_SIM_PASSWORD_INVALID];
768         size_t len = sizeof(at_sim_name) / sizeof(*at_sim_name);
769         size_t i;
770
771         decode_at_error(&error, g_at_result_final_response(result));
772
773         if (!ok) {
774                 cb(&error, NULL, cbd->data);
775                 return;
776         }
777
778         for (i = 0; i < OFONO_SIM_PASSWORD_INVALID; i++)
779                 retries[i] = -1;
780
781         g_at_result_iter_init(&iter, result);
782
783         /* Ignore +CPINRE results... */
784         while (g_at_result_iter_next(&iter, "+CPINR:")) {
785                 const char *name;
786                 int val;
787
788                 if (!g_at_result_iter_next_unquoted_string(&iter, &name))
789                         continue;
790
791                 if (!g_at_result_iter_next_number(&iter, &val))
792                         continue;
793
794                 for (i = 1; i < len; i++) {
795                         if (!strcmp(name, at_sim_name[i].name)) {
796                                 retries[i] = val;
797                                 break;
798                         }
799                 }
800         }
801
802         cb(&error, retries, cbd->data);
803 }
804
805 static void at_spic_cb(gboolean ok, GAtResult *result, gpointer user_data)
806 {
807         struct cb_data *cbd = user_data;
808         ofono_sim_pin_retries_cb_t cb = cbd->cb;
809         const char *final = g_at_result_final_response(result);
810         GAtResultIter iter;
811         struct ofono_error error;
812         int retries[OFONO_SIM_PASSWORD_INVALID];
813         size_t i;
814         static enum ofono_sim_password_type password_types[] = {
815                 OFONO_SIM_PASSWORD_SIM_PIN,
816                 OFONO_SIM_PASSWORD_SIM_PUK,
817                 OFONO_SIM_PASSWORD_SIM_PIN2,
818                 OFONO_SIM_PASSWORD_SIM_PUK2,
819         };
820
821         decode_at_error(&error, final);
822
823         if (!ok) {
824                 cb(&error, NULL, cbd->data);
825                 return;
826         }
827
828         g_at_result_iter_init(&iter, result);
829
830         if (!g_at_result_iter_next(&iter, "+SPIC:"))
831                 goto error;
832
833         BUILD_PIN_RETRIES_ARRAY(password_types, ARRAY_SIZE(password_types),
834                                 retries);
835
836         cb(&error, retries, cbd->data);
837
838         return;
839
840 error:
841         CALLBACK_WITH_FAILURE(cb, NULL, cbd->data);
842 }
843
844 static void at_pin_retries_query(struct ofono_sim *sim,
845                                         ofono_sim_pin_retries_cb_t cb,
846                                         void *data)
847 {
848         struct sim_data *sd = ofono_sim_get_data(sim);
849         struct cb_data *cbd = cb_data_new(cb, data);
850
851         DBG("");
852
853         switch (sd->vendor) {
854         case OFONO_VENDOR_IFX:
855                 if (g_at_chat_send(sd->chat, "AT+XPINCNT", xpincnt_prefix,
856                                         xpincnt_cb, cbd, g_free) > 0)
857                         return;
858                 break;
859         case OFONO_VENDOR_SPEEDUP:
860                 if (g_at_chat_send(sd->chat, "AT+CPNNUM", NULL,
861                                         cpnnum_cb, cbd, g_free) > 0)
862                         return;
863                 break;
864         case OFONO_VENDOR_OPTION_HSO:
865                 if (g_at_chat_send(sd->chat, "AT_OERCN?", oercn_prefix,
866                                         oercn_cb, cbd, g_free) > 0)
867                         return;
868                 break;
869         case OFONO_VENDOR_HUAWEI:
870                 if (g_at_chat_send(sd->chat, "AT^CPIN?", huawei_cpin_prefix,
871                                         huawei_cpin_cb, cbd, g_free) > 0)
872                         return;
873                 break;
874         case OFONO_VENDOR_ICERA:
875                 if (g_at_chat_send(sd->chat, "AT%PINNUM?", pinnum_prefix,
876                                         pinnum_cb, cbd, g_free) > 0)
877                         return;
878                 break;
879         case OFONO_VENDOR_ZTE:
880                 if (g_at_chat_send(sd->chat, "AT+ZPINPUK=?", zpinpuk_prefix,
881                                         zpinpuk_cb, cbd, g_free) > 0)
882                         return;
883                 break;
884         case OFONO_VENDOR_MBM:
885                 if (g_at_chat_send(sd->chat, "AT*EPIN?", epin_prefix,
886                                         at_epin_cb, cbd, g_free) > 0)
887                         return;
888                 break;
889         case OFONO_VENDOR_SIMCOM:
890                 if (g_at_chat_send(sd->chat, "AT+SPIC", spic_prefix,
891                                         at_spic_cb, cbd, g_free) > 0)
892                         return;
893                 break;
894         default:
895                 if (g_at_chat_send(sd->chat, "AT+CPINR", cpinr_prefixes,
896                                         at_cpinr_cb, cbd, g_free) > 0)
897                         return;
898                 break;
899         }
900
901         g_free(cbd);
902
903         CALLBACK_WITH_FAILURE(cb, NULL, data);
904 }
905
906 static void at_cpin_cb(gboolean ok, GAtResult *result, gpointer user_data)
907 {
908         struct cb_data *cbd = user_data;
909         struct sim_data *sd = ofono_sim_get_data(cbd->user);
910         GAtResultIter iter;
911         ofono_sim_passwd_cb_t cb = cbd->cb;
912         struct ofono_error error;
913         const char *pin_required;
914         int pin_type = OFONO_SIM_PASSWORD_INVALID;
915         int i;
916         int len = sizeof(at_sim_name) / sizeof(*at_sim_name);
917         const char *final = g_at_result_final_response(result);
918
919         if (sd->vendor == OFONO_VENDOR_WAVECOM && ok && strlen(final) > 7)
920                 decode_at_error(&error, "OK");
921         else
922                 decode_at_error(&error, final);
923
924         if (!ok) {
925                 cb(&error, -1, cbd->data);
926                 return;
927         }
928
929         if (sd->vendor == OFONO_VENDOR_WAVECOM ||
930                         sd->vendor == OFONO_VENDOR_WAVECOM_Q2XXX) {
931                 /* +CPIN: <pin> */
932                 pin_required = final + 7;
933         } else {
934                 g_at_result_iter_init(&iter, result);
935
936                 if (!g_at_result_iter_next(&iter, "+CPIN:")) {
937                         CALLBACK_WITH_FAILURE(cb, -1, cbd->data);
938                         return;
939                 }
940
941                 g_at_result_iter_next_unquoted_string(&iter, &pin_required);
942         }
943
944         for (i = 0; i < len; i++) {
945                 if (strcmp(pin_required, at_sim_name[i].name))
946                         continue;
947
948                 pin_type = at_sim_name[i].type;
949                 break;
950         }
951
952         if (pin_type == OFONO_SIM_PASSWORD_INVALID) {
953                 CALLBACK_WITH_FAILURE(cb, -1, cbd->data);
954                 return;
955         }
956
957         DBG("crsm_pin_cb: %s", pin_required);
958
959         cb(&error, pin_type, cbd->data);
960 }
961
962 static void at_pin_query(struct ofono_sim *sim, ofono_sim_passwd_cb_t cb,
963                         void *data)
964 {
965         struct sim_data *sd = ofono_sim_get_data(sim);
966         struct cb_data *cbd = cb_data_new(cb, data);
967
968         cbd->user = sim;
969
970         if (g_at_chat_send(sd->chat, "AT+CPIN?", cpin_prefix,
971                                 at_cpin_cb, cbd, g_free) > 0)
972                 return;
973
974         g_free(cbd);
975
976         CALLBACK_WITH_FAILURE(cb, -1, data);
977 }
978
979 static void at_xsim_notify(GAtResult *result, gpointer user_data)
980 {
981         struct cb_data *cbd = user_data;
982         struct sim_data *sd = cbd->user;
983         ofono_sim_lock_unlock_cb_t cb = cbd->cb;
984         struct ofono_error error = { .type = OFONO_ERROR_TYPE_NO_ERROR };
985         GAtResultIter iter;
986         int state;
987
988         g_at_result_iter_init(&iter, result);
989
990         if (!g_at_result_iter_next(&iter, "+XSIM:"))
991                 return;
992
993         if (!g_at_result_iter_next_number(&iter, &state))
994                 return;
995
996         switch (state) {
997         case 3: /* PIN verified â€“ Ready */
998         case 7: /* ready for attach (+COPS) */
999                 break;
1000         default:
1001                 return;
1002         }
1003
1004         cb(&error, cbd->data);
1005
1006         g_at_chat_unregister(sd->chat, sd->ready_id);
1007         sd->ready_id = 0;
1008 }
1009
1010 static void at_epev_notify(GAtResult *result, gpointer user_data)
1011 {
1012         struct cb_data *cbd = user_data;
1013         struct sim_data *sd = cbd->user;
1014         ofono_sim_lock_unlock_cb_t cb = cbd->cb;
1015         struct ofono_error error = { .type = OFONO_ERROR_TYPE_NO_ERROR };
1016
1017         cb(&error, cbd->data);
1018
1019         g_at_chat_unregister(sd->chat, sd->ready_id);
1020         sd->ready_id = 0;
1021 }
1022
1023 static void sim_state_cb(gboolean present, gpointer user_data)
1024 {
1025         struct cb_data *cbd = user_data;
1026         struct sim_data *sd = cbd->user;
1027         ofono_sim_lock_unlock_cb_t cb = cbd->cb;
1028
1029         at_util_sim_state_query_free(sd->sim_state_query);
1030         sd->sim_state_query = NULL;
1031
1032         if (present == 1)
1033                 CALLBACK_WITH_SUCCESS(cb, cbd->data);
1034         else
1035                 CALLBACK_WITH_FAILURE(cb, cbd->data);
1036 }
1037
1038 static void at_pin_send_cb(gboolean ok, GAtResult *result,
1039                                 gpointer user_data)
1040 {
1041         struct cb_data *cbd = user_data;
1042         struct sim_data *sd = cbd->user;
1043         ofono_sim_lock_unlock_cb_t cb = cbd->cb;
1044         struct ofono_error error;
1045
1046         decode_at_error(&error, g_at_result_final_response(result));
1047
1048         if (!ok)
1049                 goto done;
1050
1051         switch (sd->vendor) {
1052         case OFONO_VENDOR_IFX:
1053                 /*
1054                  * On the IFX modem, AT+CPIN? can return READY too
1055                  * early and so use +XSIM notification to detect
1056                  * the ready state of the SIM.
1057                  */
1058                 sd->ready_id = g_at_chat_register(sd->chat, "+XSIM",
1059                                                         at_xsim_notify,
1060                                                         FALSE, cbd, g_free);
1061                 return;
1062         case OFONO_VENDOR_MBM:
1063                 /*
1064                  * On the MBM modem, AT+CPIN? keeps returning SIM PIN
1065                  * for a moment after successful AT+CPIN="..", but then
1066                  * sends *EPEV when that changes.
1067                  */
1068                 sd->ready_id = g_at_chat_register(sd->chat, "*EPEV",
1069                                                         at_epev_notify,
1070                                                         FALSE, cbd, g_free);
1071                 return;
1072         case OFONO_VENDOR_ZTE:
1073                 /*
1074                  * On ZTE modems, after pin is entered, SIM state is checked
1075                  * by polling CPIN as their modem doesn't provide unsolicited
1076                  * notification of SIM readiness.
1077                  */
1078                 sd->sim_state_query = at_util_sim_state_query_new(sd->chat,
1079                                                 2, 20, sim_state_cb, cbd,
1080                                                 g_free);
1081                 return;
1082         }
1083
1084 done:
1085         cb(&error, cbd->data);
1086
1087         g_free(cbd);
1088 }
1089
1090 static void at_pin_send(struct ofono_sim *sim, const char *passwd,
1091                         ofono_sim_lock_unlock_cb_t cb, void *data)
1092 {
1093         struct sim_data *sd = ofono_sim_get_data(sim);
1094         struct cb_data *cbd = cb_data_new(cb, data);
1095         char buf[64];
1096         int ret;
1097
1098         cbd->user = sd;
1099
1100         snprintf(buf, sizeof(buf), "AT+CPIN=\"%s\"", passwd);
1101
1102         ret = g_at_chat_send(sd->chat, buf, none_prefix,
1103                                 at_pin_send_cb, cbd, NULL);
1104
1105         memset(buf, 0, sizeof(buf));
1106
1107         if (ret > 0)
1108                 return;
1109
1110         g_free(cbd);
1111
1112         CALLBACK_WITH_FAILURE(cb, data);
1113 }
1114
1115 static void at_pin_send_puk(struct ofono_sim *sim, const char *puk,
1116                                 const char *passwd,
1117                                 ofono_sim_lock_unlock_cb_t cb, void *data)
1118 {
1119         struct sim_data *sd = ofono_sim_get_data(sim);
1120         struct cb_data *cbd = cb_data_new(cb, data);
1121         char buf[64];
1122         int ret;
1123
1124         cbd->user = sd;
1125
1126         snprintf(buf, sizeof(buf), "AT+CPIN=\"%s\",\"%s\"", puk, passwd);
1127
1128         ret = g_at_chat_send(sd->chat, buf, none_prefix,
1129                                 at_pin_send_cb, cbd, NULL);
1130
1131         memset(buf, 0, sizeof(buf));
1132
1133         if (ret > 0)
1134                 return;
1135
1136         g_free(cbd);
1137
1138         CALLBACK_WITH_FAILURE(cb, data);
1139 }
1140
1141 static void at_lock_unlock_cb(gboolean ok, GAtResult *result,
1142                                 gpointer user_data)
1143 {
1144         struct cb_data *cbd = user_data;
1145         ofono_sim_lock_unlock_cb_t cb = cbd->cb;
1146         struct ofono_error error;
1147
1148         decode_at_error(&error, g_at_result_final_response(result));
1149
1150         cb(&error, cbd->data);
1151 }
1152
1153 static const char *const at_clck_cpwd_fac[] = {
1154         [OFONO_SIM_PASSWORD_SIM_PIN] = "SC",
1155         [OFONO_SIM_PASSWORD_SIM_PIN2] = "P2",
1156         [OFONO_SIM_PASSWORD_PHSIM_PIN] = "PS",
1157         [OFONO_SIM_PASSWORD_PHFSIM_PIN] = "PF",
1158         [OFONO_SIM_PASSWORD_PHNET_PIN] = "PN",
1159         [OFONO_SIM_PASSWORD_PHNETSUB_PIN] = "PU",
1160         [OFONO_SIM_PASSWORD_PHSP_PIN] = "PP",
1161         [OFONO_SIM_PASSWORD_PHCORP_PIN] = "PC",
1162 };
1163
1164 static void at_pin_enable(struct ofono_sim *sim,
1165                                 enum ofono_sim_password_type passwd_type,
1166                                 int enable, const char *passwd,
1167                                 ofono_sim_lock_unlock_cb_t cb, void *data)
1168 {
1169         struct sim_data *sd = ofono_sim_get_data(sim);
1170         struct cb_data *cbd = cb_data_new(cb, data);
1171         char buf[64];
1172         int ret;
1173         unsigned int len = sizeof(at_clck_cpwd_fac) / sizeof(*at_clck_cpwd_fac);
1174
1175         if (passwd_type >= len || at_clck_cpwd_fac[passwd_type] == NULL)
1176                 goto error;
1177
1178         snprintf(buf, sizeof(buf), "AT+CLCK=\"%s\",%i,\"%s\"",
1179                         at_clck_cpwd_fac[passwd_type], enable ? 1 : 0, passwd);
1180
1181         ret = g_at_chat_send(sd->chat, buf, none_prefix,
1182                                 at_lock_unlock_cb, cbd, g_free);
1183
1184         memset(buf, 0, sizeof(buf));
1185
1186         if (ret > 0)
1187                 return;
1188
1189 error:
1190         g_free(cbd);
1191
1192         CALLBACK_WITH_FAILURE(cb, data);
1193 }
1194
1195 static void at_change_passwd(struct ofono_sim *sim,
1196                                 enum ofono_sim_password_type passwd_type,
1197                                 const char *old_passwd, const char *new_passwd,
1198                                 ofono_sim_lock_unlock_cb_t cb, void *data)
1199 {
1200         struct sim_data *sd = ofono_sim_get_data(sim);
1201         struct cb_data *cbd = cb_data_new(cb, data);
1202         char buf[64];
1203         int ret;
1204         unsigned int len = sizeof(at_clck_cpwd_fac) / sizeof(*at_clck_cpwd_fac);
1205
1206         if (passwd_type >= len ||
1207                         at_clck_cpwd_fac[passwd_type] == NULL)
1208                 goto error;
1209
1210         snprintf(buf, sizeof(buf), "AT+CPWD=\"%s\",\"%s\",\"%s\"",
1211                         at_clck_cpwd_fac[passwd_type], old_passwd, new_passwd);
1212
1213         ret = g_at_chat_send(sd->chat, buf, none_prefix,
1214                                 at_lock_unlock_cb, cbd, g_free);
1215
1216         memset(buf, 0, sizeof(buf));
1217
1218         if (ret > 0)
1219                 return;
1220
1221 error:
1222         g_free(cbd);
1223
1224         CALLBACK_WITH_FAILURE(cb, data);
1225 }
1226
1227 static void at_lock_status_cb(gboolean ok, GAtResult *result,
1228                                 gpointer user_data)
1229 {
1230         struct cb_data *cbd = user_data;
1231         GAtResultIter iter;
1232         ofono_sim_locked_cb_t cb = cbd->cb;
1233         struct ofono_error error;
1234         int locked;
1235
1236         decode_at_error(&error, g_at_result_final_response(result));
1237
1238         if (!ok) {
1239                 cb(&error, -1, cbd->data);
1240                 return;
1241         }
1242
1243         g_at_result_iter_init(&iter, result);
1244
1245         if (!g_at_result_iter_next(&iter, "+CLCK:")) {
1246                 CALLBACK_WITH_FAILURE(cb, -1, cbd->data);
1247                 return;
1248         }
1249
1250         g_at_result_iter_next_number(&iter, &locked);
1251
1252         DBG("lock_status_cb: %i", locked);
1253
1254         cb(&error, locked, cbd->data);
1255 }
1256
1257 static void at_pin_query_enabled(struct ofono_sim *sim,
1258                                 enum ofono_sim_password_type passwd_type,
1259                                 ofono_sim_locked_cb_t cb, void *data)
1260 {
1261         struct sim_data *sd = ofono_sim_get_data(sim);
1262         struct cb_data *cbd = cb_data_new(cb, data);
1263         char buf[64];
1264         unsigned int len = sizeof(at_clck_cpwd_fac) / sizeof(*at_clck_cpwd_fac);
1265
1266         if (passwd_type >= len || at_clck_cpwd_fac[passwd_type] == NULL)
1267                 goto error;
1268
1269         snprintf(buf, sizeof(buf), "AT+CLCK=\"%s\",2",
1270                         at_clck_cpwd_fac[passwd_type]);
1271
1272         if (g_at_chat_send(sd->chat, buf, clck_prefix,
1273                                 at_lock_status_cb, cbd, g_free) > 0)
1274                 return;
1275
1276 error:
1277         g_free(cbd);
1278
1279         CALLBACK_WITH_FAILURE(cb, -1, data);
1280 }
1281
1282 static gboolean at_sim_register(gpointer user)
1283 {
1284         struct ofono_sim *sim = user;
1285
1286         ofono_sim_register(sim);
1287
1288         return FALSE;
1289 }
1290
1291 static int at_sim_probe(struct ofono_sim *sim, unsigned int vendor,
1292                                 void *data)
1293 {
1294         GAtChat *chat = data;
1295         struct sim_data *sd;
1296
1297         sd = g_new0(struct sim_data, 1);
1298         sd->chat = g_at_chat_clone(chat);
1299         sd->vendor = vendor;
1300
1301         switch (sd->vendor) {
1302         case OFONO_VENDOR_WAVECOM:
1303                 g_at_chat_add_terminator(sd->chat, "+CPIN:", 6, TRUE);
1304                 break;
1305         case OFONO_VENDOR_MBM:
1306                 g_at_chat_send(sd->chat, "AT*EPEE=1", NULL, NULL, NULL, NULL);
1307                 break;
1308         case OFONO_VENDOR_WAVECOM_Q2XXX:
1309                 g_at_chat_add_terminator(chat, "+CPIN: READY", -1, TRUE);
1310                 break;
1311         default:
1312                 break;
1313         }
1314
1315         ofono_sim_set_data(sim, sd);
1316         g_idle_add(at_sim_register, sim);
1317
1318         return 0;
1319 }
1320
1321 static void at_sim_remove(struct ofono_sim *sim)
1322 {
1323         struct sim_data *sd = ofono_sim_get_data(sim);
1324
1325         /* Cleanup potential SIM state polling */
1326         at_util_sim_state_query_free(sd->sim_state_query);
1327
1328         ofono_sim_set_data(sim, NULL);
1329
1330         g_at_chat_unref(sd->chat);
1331         g_free(sd);
1332 }
1333
1334 static struct ofono_sim_driver driver = {
1335         .name                   = "atmodem",
1336         .probe                  = at_sim_probe,
1337         .remove                 = at_sim_remove,
1338         .read_file_info         = at_sim_read_info,
1339         .read_file_transparent  = at_sim_read_binary,
1340         .read_file_linear       = at_sim_read_record,
1341         .read_file_cyclic       = at_sim_read_record,
1342         .write_file_transparent = at_sim_update_binary,
1343         .write_file_linear      = at_sim_update_record,
1344         .write_file_cyclic      = at_sim_update_cyclic,
1345         .read_imsi              = at_read_imsi,
1346         .query_passwd_state     = at_pin_query,
1347         .query_pin_retries      = at_pin_retries_query,
1348         .send_passwd            = at_pin_send,
1349         .reset_passwd           = at_pin_send_puk,
1350         .lock                   = at_pin_enable,
1351         .change_passwd          = at_change_passwd,
1352         .query_locked           = at_pin_query_enabled,
1353 };
1354
1355 static struct ofono_sim_driver driver_noef = {
1356         .name                   = "atmodem-noef",
1357         .probe                  = at_sim_probe,
1358         .remove                 = at_sim_remove,
1359         .read_imsi              = at_read_imsi,
1360         .query_passwd_state     = at_pin_query,
1361         .query_pin_retries      = at_pin_retries_query,
1362         .send_passwd            = at_pin_send,
1363         .reset_passwd           = at_pin_send_puk,
1364         .lock                   = at_pin_enable,
1365         .change_passwd          = at_change_passwd,
1366         .query_locked           = at_pin_query_enabled,
1367 };
1368
1369 void at_sim_init(void)
1370 {
1371         ofono_sim_driver_register(&driver);
1372         ofono_sim_driver_register(&driver_noef);
1373 }
1374
1375 void at_sim_exit(void)
1376 {
1377         ofono_sim_driver_unregister(&driver);
1378         ofono_sim_driver_unregister(&driver_noef);
1379 }