sec: Send SIM I/O requests one after another
[samsung-ril.git] / sec.c
1 /**
2  * This file is part of samsung-ril.
3  *
4  * Copyright (C) 2010-2011 Joerie de Gram <j.de.gram@gmail.com>
5  * Copyright (C) 2011-2012 Paul Kocialkowski <contact@paulk.fr>
6  *
7  * samsung-ril is free software: you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License as published by
9  * the Free Software Foundation, either version 3 of the License, or
10  * (at your option) any later version.
11  *
12  * samsung-ril is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with samsung-ril.  If not, see <http://www.gnu.org/licenses/>.
19  *
20  */
21
22 #define LOG_TAG "RIL-SEC"
23 #include <utils/Log.h>
24
25 #include "samsung-ril.h"
26 #include "util.h"
27
28 ril_sim_state ipc2ril_sim_state(struct ipc_sec_sim_status_response *pin_status)
29 {
30         switch(pin_status->status) {
31                 case IPC_SEC_SIM_STATUS_INITIALIZING:
32                         return SIM_STATE_NOT_READY;
33                 case IPC_SEC_SIM_STATUS_LOCK_SC:
34                         switch(pin_status->facility_lock) {
35                                 case IPC_SEC_FACILITY_LOCK_TYPE_SC_UNLOCKED:
36                                         return SIM_STATE_READY;
37                                 case IPC_SEC_FACILITY_LOCK_TYPE_SC_PIN1_REQ:
38                                         return SIM_STATE_PIN;
39                                 case IPC_SEC_FACILITY_LOCK_TYPE_SC_PUK_REQ:
40                                         return SIM_STATE_PUK;
41                                 case IPC_SEC_FACILITY_LOCK_TYPE_SC_CARD_BLOCKED:
42                                         return SIM_STATE_BLOCKED;
43                                 default:
44                                         LOGE("Unknown SIM facility lock: 0x%x", pin_status->facility_lock);
45                                         return SIM_STATE_ABSENT;
46                         }
47                         break;
48                 case IPC_SEC_SIM_STATUS_LOCK_FD:
49                         return SIM_STATE_ABSENT;
50                 case IPC_SEC_SIM_STATUS_LOCK_PN:
51                         return SIM_STATE_NETWORK_PERSO;
52                 case IPC_SEC_SIM_STATUS_LOCK_PU:
53                         return SIM_STATE_NETWORK_SUBSET_PERSO;
54                 case IPC_SEC_SIM_STATUS_LOCK_PP:
55                         return SIM_STATE_SERVICE_PROVIDER_PERSO;
56                 case IPC_SEC_SIM_STATUS_LOCK_PC:
57                         return SIM_STATE_CORPORATE_PERSO;
58                 case IPC_SEC_SIM_STATUS_INIT_COMPLETE:
59                         return SIM_STATE_READY;
60                 case IPC_SEC_SIM_STATUS_PB_INIT_COMPLETE:
61                         // Ignore phone book init complete
62                         return ril_data.state.sim_state;
63                 case IPC_SEC_SIM_STATUS_SIM_LOCK_REQUIRED:
64                 case IPC_SEC_SIM_STATUS_INSIDE_PF_ERROR:
65                 case IPC_SEC_SIM_STATUS_CARD_NOT_PRESENT:
66                 case IPC_SEC_SIM_STATUS_CARD_ERROR:
67                 default:
68                         LOGE("Unknown SIM status: 0x%x", pin_status->status);
69                         return SIM_STATE_ABSENT;
70         }
71 }
72
73 /**
74  * Update the radio state based on SIM state
75  *
76  * Out: RIL_UNSOL_RESPONSE_RADIO_STATE_CHANGED
77  *   Indicate when value of RIL_RadioState has changed
78  *   Callee will invoke RIL_RadioStateRequest method on main thread
79  */
80 void ril_state_update(ril_sim_state sim_state)
81 {
82         RIL_RadioState radio_state;
83
84         /* If power mode isn't at least normal, don't update RIL state */
85         if (ril_data.state.power_state != IPC_PWR_PHONE_STATE_NORMAL)
86                 return;
87
88         ril_data.state.sim_state = sim_state;
89
90         switch(sim_state) {
91                 case SIM_STATE_READY:
92 #if RIL_VERSION >= 7
93                         radio_state = RADIO_STATE_ON;
94 #else
95                         radio_state = RADIO_STATE_SIM_READY;
96 #endif
97                         break;
98                 case SIM_STATE_NOT_READY:
99                         radio_state = RADIO_STATE_SIM_NOT_READY;
100                         break;
101                 case SIM_STATE_ABSENT:
102                 case SIM_STATE_PIN:
103                 case SIM_STATE_PUK:
104                 case SIM_STATE_BLOCKED:
105                 case SIM_STATE_NETWORK_PERSO:
106                 case SIM_STATE_NETWORK_SUBSET_PERSO:
107                 case SIM_STATE_CORPORATE_PERSO:
108                 case SIM_STATE_SERVICE_PROVIDER_PERSO:
109                         radio_state = RADIO_STATE_SIM_LOCKED_OR_ABSENT;
110                         break;
111                 default:
112                         radio_state = RADIO_STATE_SIM_NOT_READY;
113                         break;
114         }
115
116
117         ril_data.state.radio_state = radio_state;
118
119         ril_tokens_check();
120
121         ril_request_unsolicited(RIL_UNSOL_RESPONSE_RADIO_STATE_CHANGED, NULL, 0);
122 }
123
124 #if RIL_VERSION >= 6
125 void ipc2ril_card_status(struct ipc_sec_sim_status_response *pin_status, RIL_CardStatus_v6 *card_status)
126 #else
127 void ipc2ril_card_status(struct ipc_sec_sim_status_response *pin_status, RIL_CardStatus *card_status)
128 #endif
129 {
130         ril_sim_state sim_state;
131         int app_status_array_length;
132         int app_index;
133         int i;
134
135         static RIL_AppStatus app_status_array[] = {
136                 /* SIM_ABSENT = 0 */
137                 { RIL_APPTYPE_UNKNOWN, RIL_APPSTATE_UNKNOWN, RIL_PERSOSUBSTATE_UNKNOWN,
138                 NULL, NULL, 0, RIL_PINSTATE_UNKNOWN, RIL_PINSTATE_UNKNOWN },
139                 /* SIM_NOT_READY = 1 */
140                 { RIL_APPTYPE_SIM, RIL_APPSTATE_DETECTED, RIL_PERSOSUBSTATE_UNKNOWN,
141                 NULL, NULL, 0, RIL_PINSTATE_UNKNOWN, RIL_PINSTATE_UNKNOWN },
142                 /* SIM_READY = 2 */
143                 { RIL_APPTYPE_SIM, RIL_APPSTATE_READY, RIL_PERSOSUBSTATE_READY,
144                 NULL, NULL, 0, RIL_PINSTATE_UNKNOWN, RIL_PINSTATE_UNKNOWN },
145                 /* SIM_PIN = 3 */
146                 { RIL_APPTYPE_SIM, RIL_APPSTATE_PIN, RIL_PERSOSUBSTATE_UNKNOWN,
147                 NULL, NULL, 0, RIL_PINSTATE_ENABLED_NOT_VERIFIED, RIL_PINSTATE_UNKNOWN },
148                 /* SIM_PUK = 4 */
149                 { RIL_APPTYPE_SIM, RIL_APPSTATE_PUK, RIL_PERSOSUBSTATE_UNKNOWN,
150                 NULL, NULL, 0, RIL_PINSTATE_ENABLED_BLOCKED, RIL_PINSTATE_UNKNOWN },
151                 /* SIM_BLOCKED = 4 */
152                 { RIL_APPTYPE_SIM, RIL_APPSTATE_PUK, RIL_PERSOSUBSTATE_UNKNOWN,
153                 NULL, NULL, 0, RIL_PINSTATE_ENABLED_PERM_BLOCKED, RIL_PINSTATE_UNKNOWN },
154                 /* SIM_NETWORK_PERSO = 6 */
155                 { RIL_APPTYPE_SIM, RIL_APPSTATE_SUBSCRIPTION_PERSO, RIL_PERSOSUBSTATE_SIM_NETWORK,
156                 NULL, NULL, 0, RIL_PINSTATE_ENABLED_NOT_VERIFIED, RIL_PINSTATE_UNKNOWN },
157                 /* SIM_NETWORK_SUBSET_PERSO = 7 */
158                 { RIL_APPTYPE_SIM, RIL_APPSTATE_SUBSCRIPTION_PERSO, RIL_PERSOSUBSTATE_SIM_NETWORK_SUBSET,
159                 NULL, NULL, 0, RIL_PINSTATE_ENABLED_NOT_VERIFIED, RIL_PINSTATE_UNKNOWN },
160                 /* SIM_CORPORATE_PERSO = 8 */
161                 { RIL_APPTYPE_SIM, RIL_APPSTATE_SUBSCRIPTION_PERSO, RIL_PERSOSUBSTATE_SIM_CORPORATE,
162                 NULL, NULL, 0, RIL_PINSTATE_ENABLED_NOT_VERIFIED, RIL_PINSTATE_UNKNOWN },
163                 /* SIM_SERVICE_PROVIDER_PERSO = 9 */
164                 { RIL_APPTYPE_SIM, RIL_APPSTATE_SUBSCRIPTION_PERSO, RIL_PERSOSUBSTATE_SIM_SERVICE_PROVIDER,
165                 NULL, NULL, 0, RIL_PINSTATE_ENABLED_NOT_VERIFIED, RIL_PINSTATE_UNKNOWN },
166         };
167
168         app_status_array_length = sizeof(app_status_array) / sizeof(RIL_AppStatus);
169
170         if (app_status_array_length > RIL_CARD_MAX_APPS)
171                 app_status_array_length = RIL_CARD_MAX_APPS;
172
173         sim_state = ipc2ril_sim_state(pin_status);
174
175         /* Card is assumed to be present if not explicitly absent */
176         if (sim_state == SIM_STATE_ABSENT) {
177                 card_status->card_state = RIL_CARDSTATE_ABSENT;
178         } else {
179                 card_status->card_state = RIL_CARDSTATE_PRESENT;
180         }
181
182         // FIXME: How do we know that?
183         card_status->universal_pin_state = RIL_PINSTATE_UNKNOWN;
184
185         // Initialize the apps
186         for (i = 0 ; i < app_status_array_length ; i++) {
187                 memcpy((void *) &(card_status->applications[i]), (void *) &(app_status_array[i]), sizeof(RIL_AppStatus));
188         }
189         for (i = app_status_array_length ; i < RIL_CARD_MAX_APPS ; i++) {
190                 memset((void *) &(card_status->applications[i]), 0, sizeof(RIL_AppStatus));
191         }
192
193         // sim_state corresponds to the app index on the table
194         card_status->gsm_umts_subscription_app_index = (int) sim_state;
195         card_status->cdma_subscription_app_index = (int) sim_state;
196         card_status->num_applications = app_status_array_length;
197
198         LOGD("Selecting application #%d on %d", (int) sim_state, app_status_array_length);
199 }
200
201 void ril_tokens_pin_status_dump(void)
202 {
203         LOGD("ril_tokens_pin_status_dump:\n\
204         \tril_data.tokens.pin_status = %p\n", ril_data.tokens.pin_status);
205 }
206
207 /**
208  * In: IPC_SEC_SIM_STATUS
209  *   Provides SIM initialization/lock status
210  *
211  * Out: RIL_UNSOL_RESPONSE_SIM_STATUS_CHANGED
212  *   Indicates that SIM state changes.
213  *   Callee will invoke RIL_REQUEST_GET_SIM_STATUS on main thread
214  *
215  * Out: RIL_UNSOL_RESPONSE_RADIO_STATE_CHANGED
216  *   Indicate when value of RIL_RadioState has changed
217  *   Callee will invoke RIL_RadioStateRequest method on main thread
218  */
219 void ipc_sec_sim_status(struct ipc_message_info *info)
220 {
221         RIL_Token t = ril_request_get_token(info->aseq);
222         struct ipc_sec_sim_status_response *pin_status = (struct ipc_sec_sim_status_response *) info->data;
223 #if RIL_VERSION >= 6
224         RIL_CardStatus_v6 card_status;
225 #else
226         RIL_CardStatus card_status;
227 #endif
228         ril_sim_state sim_state;
229
230         switch(info->type) {
231                 case IPC_TYPE_NOTI:
232                         // Don't consider this if modem isn't in normal power mode
233                         if (ril_data.state.power_state != IPC_PWR_PHONE_STATE_NORMAL)
234                                 return;
235
236                         LOGD("Got UNSOL PIN status message");
237
238                         if (ril_data.tokens.pin_status != (RIL_Token) 0x00 && ril_data.tokens.pin_status != RIL_TOKEN_DATA_WAITING) {
239                                 LOGE("Another PIN status Req is in progress, skipping");
240                                 return;
241                         }
242
243                         sim_state = ipc2ril_sim_state(pin_status);
244                         ril_state_update(sim_state);
245
246                         memcpy(&(ril_data.state.sim_pin_status), pin_status, sizeof(struct ipc_sec_sim_status_response));
247
248                         ril_data.tokens.pin_status = RIL_TOKEN_DATA_WAITING;
249                         ril_request_unsolicited(RIL_UNSOL_RESPONSE_SIM_STATUS_CHANGED, NULL, 0);
250                         break;
251                 case IPC_TYPE_RESP:
252                         LOGD("Got SOL PIN status message");
253
254                         if (ril_data.tokens.pin_status != t)
255                                 LOGE("PIN status tokens mismatch");
256
257                         sim_state = ipc2ril_sim_state(pin_status);
258                         ril_state_update(sim_state);
259
260                         // Better keeping this up to date
261                         memcpy(&(ril_data.state.sim_pin_status), pin_status, sizeof(struct ipc_sec_sim_status_response));
262
263                         ipc2ril_card_status(pin_status, &card_status);
264                         ril_request_complete(t, RIL_E_SUCCESS, &card_status, sizeof(card_status));
265
266                         if (ril_data.tokens.pin_status != RIL_TOKEN_DATA_WAITING)
267                                 ril_data.tokens.pin_status = (RIL_Token) 0x00;
268                         break;
269                 default:
270                         LOGE("%s: unhandled ipc method: %d", __FUNCTION__, info->type);
271                         break;
272         }
273
274         ril_tokens_pin_status_dump();
275 }
276
277 /**
278  * In: RIL_REQUEST_GET_SIM_STATUS
279  *   Requests status of the SIM interface and the SIM card
280  */
281 void ril_request_get_sim_status(RIL_Token t)
282 {
283         struct ipc_sec_sim_status_response *pin_status;
284 #if RIL_VERSION >= 6
285         RIL_CardStatus_v6 card_status;
286 #else
287         RIL_CardStatus card_status;
288 #endif
289
290         if (ril_data.tokens.pin_status == RIL_TOKEN_DATA_WAITING) {
291                 LOGD("Got RILJ request for UNSOL data");
292                 hex_dump(&(ril_data.state.sim_pin_status), sizeof(struct ipc_sec_sim_status_response));
293                 pin_status = &(ril_data.state.sim_pin_status);
294
295                 ipc2ril_card_status(pin_status, &card_status);
296
297                 ril_request_complete(t, RIL_E_SUCCESS, &card_status, sizeof(card_status));
298
299                 ril_data.tokens.pin_status = (RIL_Token) 0x00;
300         } else if (ril_data.tokens.pin_status == (RIL_Token) 0x00) {
301                 LOGD("Got RILJ request for SOL data");
302
303                 /* Request data to the modem */
304                 ril_data.tokens.pin_status = t;
305
306                 ipc_fmt_send_get(IPC_SEC_SIM_STATUS, ril_request_get_id(t));
307         } else {
308                 LOGE("Another request is going on, returning UNSOL data");
309
310                 pin_status = &(ril_data.state.sim_pin_status);
311
312                 ipc2ril_card_status(pin_status, &card_status);
313                 ril_request_complete(t, RIL_E_SUCCESS, &card_status, sizeof(card_status));
314         }
315
316         ril_tokens_pin_status_dump();
317 }
318
319 /*
320  * SIM I/O
321  */
322
323 int ril_request_sim_io_register(RIL_Token t, unsigned char command, unsigned short fileid,
324         unsigned char p1, unsigned char p2, unsigned char p3, void *data, int length)
325 {
326         struct ril_request_sim_io_info *sim_io;
327         struct list_head *list_end;
328         struct list_head *list;
329
330         sim_io = calloc(1, sizeof(struct ril_request_sim_io_info));
331         if (sim_io == NULL)
332                 return -1;
333
334         sim_io->command = command;
335         sim_io->fileid = fileid;
336         sim_io->p1 = p1;
337         sim_io->p2 = p2;
338         sim_io->p3 = p3;
339         sim_io->data = data;
340         sim_io->length = length;
341         sim_io->token = t;
342
343         list_end = ril_data.sim_io;
344         while (list_end != NULL && list_end->next != NULL)
345                 list_end = list_end->next;
346
347         list = list_head_alloc((void *) sim_io, list_end, NULL);
348
349         if (ril_data.sim_io == NULL)
350                 ril_data.sim_io = list;
351
352         return 0;
353 }
354
355 void ril_request_sim_io_unregister(struct ril_request_sim_io_info *sim_io)
356 {
357         struct list_head *list;
358
359         if (sim_io == NULL)
360                 return;
361
362         list = ril_data.sim_io;
363         while (list != NULL) {
364                 if (list->data == (void *) sim_io) {
365                         memset(sim_io, 0, sizeof(struct ril_request_sim_io_info));
366                         free(sim_io);
367
368                         if (list == ril_data.sim_io)
369                                 ril_data.sim_io = list->next;
370
371                         list_head_free(list);
372
373                         break;
374                 }
375 list_continue:
376                 list = list->next;
377         }
378 }
379
380 struct ril_request_sim_io_info *ril_request_sim_io_info_find(void)
381 {
382         struct ril_request_sim_io_info *sim_io;
383         struct list_head *list;
384
385         list = ril_data.sim_io;
386         while (list != NULL) {
387                 sim_io = (struct ril_request_sim_io_info *) list->data;
388                 if (sim_io == NULL)
389                         goto list_continue;
390
391                 return sim_io;
392
393 list_continue:
394                 list = list->next;
395         }
396
397         return NULL;
398 }
399
400 void ril_request_sim_io_info_clear(struct ril_request_sim_io_info *sim_io)
401 {
402         if (sim_io == NULL)
403                 return;
404
405         if (sim_io->data != NULL)
406                 free(sim_io->data);
407 }
408
409 void ril_request_sim_io_next(void)
410 {
411         struct ril_request_sim_io_info *sim_io;
412         unsigned char command;
413         unsigned short fileid;
414         unsigned char p1;
415         unsigned char p2;
416         unsigned char p3;
417         void *data;
418         int length;
419         RIL_Token t;
420         int rc;
421
422         ril_data.tokens.sim_io = (RIL_Token) 0x00;
423
424         sim_io = ril_request_sim_io_info_find();
425         if (sim_io == NULL)
426                 return;
427
428         command = sim_io->command;
429         fileid = sim_io->fileid;
430         p1 = sim_io->p1;
431         p2 = sim_io->p2;
432         p3 = sim_io->p3;
433         data = sim_io->data;
434         length = sim_io->length;
435         t = sim_io->token;
436
437         ril_request_sim_io_unregister(sim_io);
438
439         ril_data.tokens.sim_io = t;
440
441         ril_request_sim_io_complete(t, command, fileid, p1, p2, p3, data, length);
442         if (data != NULL)
443                 free(data);
444 }
445
446 void ril_request_sim_io_complete(RIL_Token t, unsigned char command, unsigned short fileid,
447         unsigned char p1, unsigned char p2, unsigned char p3, void *data, int length)
448 {
449         struct ipc_sec_rsim_access_get *rsim_access = NULL;
450         void *rsim_access_data = NULL;
451         int rsim_access_length = 0;
452
453         rsim_access_length += sizeof(struct ipc_sec_rsim_access_get);
454
455         if (data != NULL && length > 0)
456                 rsim_access_length += length;
457
458         rsim_access_data = calloc(1, rsim_access_length);
459         rsim_access = (struct ipc_sec_rsim_access_get *) rsim_access_data;
460
461         rsim_access->command = command;
462         rsim_access->fileid = fileid;
463         rsim_access->p1 = p1;
464         rsim_access->p2 = p2;
465         rsim_access->p3 = p3;
466
467         if (data != NULL && length > 0)
468                 memcpy((void *) ((int) rsim_access_data + sizeof(struct ipc_sec_rsim_access_get)), data, length);
469
470         ipc_fmt_send(IPC_SEC_RSIM_ACCESS, IPC_TYPE_GET, rsim_access_data, rsim_access_length, ril_request_get_id(t));
471
472         free(rsim_access_data);
473 }
474
475 /**
476  * In: RIL_REQUEST_SIM_IO
477  *   Request SIM I/O operation.
478  *   This is similar to the TS 27.007 "restricted SIM" operation
479  *   where it assumes all of the EF selection will be done by the
480  *   callee.
481  *
482  * Out: IPC_SEC_RSIM_ACCESS
483  *   Performs a restricted SIM read operation
484  */
485 void ril_request_sim_io(RIL_Token t, void *data, int length)
486 {
487 #if RIL_VERSION >= 6
488         RIL_SIM_IO_v6 *sim_io = NULL;
489 #else
490         RIL_SIM_IO *sim_io = NULL;
491 #endif
492         void *sim_io_data = NULL;
493         int sim_io_data_length = 0;
494         int rc;
495
496         if (data == NULL || length < (int) sizeof(*sim_io))
497                 return;
498
499 #if RIL_VERSION >= 6
500         sim_io = (RIL_SIM_IO_v6 *) data;
501 #else
502         sim_io = (RIL_SIM_IO *) data;
503 #endif
504
505         // SIM IO data should be a string if present
506         if (sim_io->data != NULL) {
507                 sim_io_data_length = strlen(sim_io->data) / 2;
508                 if (sim_io_data_length > 0) {
509                         sim_io_data = calloc(1, sim_io_data_length);
510                         hex2bin(sim_io->data, sim_io_data_length * 2, sim_io_data);
511                 }
512         }
513
514         if (ril_data.tokens.sim_io != (RIL_Token) 0x00) {
515                 LOGD("Another SIM I/O is being processed, adding to the list");
516
517                 rc = ril_request_sim_io_register(t, sim_io->command, sim_io->fileid,
518                         sim_io->p1, sim_io->p2, sim_io->p3, sim_io_data, sim_io_data_length);
519                 if (rc < 0) {
520                         LOGE("Unable to add the request to the list");
521
522                         ril_request_complete(t, RIL_E_GENERIC_FAILURE, NULL, 0);
523                         if (sim_io_data != NULL)
524                                 free(sim_io_data);
525                         // Send the next SIM I/O in the list
526                         ril_request_sim_io_next();
527                 }
528
529                 return;
530         }
531
532         ril_data.tokens.sim_io = t;
533
534         ril_request_sim_io_complete(t, sim_io->command, sim_io->fileid,
535                 sim_io->p1, sim_io->p2, sim_io->p3, sim_io_data, sim_io_data_length);
536         if (sim_io_data != NULL)
537                 free(sim_io_data);
538 }
539
540 /**
541  * In: IPC_SEC_RSIM_ACCESS
542  *   Provides restricted SIM read operation result
543  *
544  * Out: RIL_REQUEST_SIM_IO
545  *   Request SIM I/O operation.
546  *   This is similar to the TS 27.007 "restricted SIM" operation
547  *   where it assumes all of the EF selection will be done by the
548  *   callee.
549  */
550 void ipc_sec_rsim_access(struct ipc_message_info *info)
551 {
552         RIL_SIM_IO_Response sim_io_response;
553         struct ipc_sec_rsim_access_response *rsim_access = NULL;
554         void *rsim_access_data = NULL;
555         char *sim_response = NULL;
556
557         if (info == NULL || info->data == NULL || info->length < sizeof(struct ipc_sec_rsim_access_response))
558                 return;
559
560         memset(&sim_io_response, 0, sizeof(sim_io_response));
561
562         rsim_access = (struct ipc_sec_rsim_access_response *) info->data;
563         rsim_access_data = (void *) ((int) info->data + sizeof(struct ipc_sec_rsim_access_response));
564
565         sim_io_response.sw1 = rsim_access->sw1;
566         sim_io_response.sw2 = rsim_access->sw2;
567
568         if (rsim_access->len > 0) {
569                 sim_response = (char *) malloc(rsim_access->len * 2 + 1);
570                 bin2hex(rsim_access_data, rsim_access->len, sim_response);
571                 sim_io_response.simResponse = sim_response;
572         } else {
573                 sim_io_response.simResponse = strdup("");
574         }
575
576         ril_request_complete(ril_request_get_token(info->aseq), RIL_E_SUCCESS, &sim_io_response, sizeof(sim_io_response));
577
578         free(sim_io_response.simResponse);
579
580         // Send the next SIM I/O in the list
581         ril_request_sim_io_next();
582 }
583
584 /**
585  * In: IPC_GEN_PHONE_RES
586  *   Provides result of IPC_SEC_SIM_STATUS SET
587  *
588  * Out: RIL_REQUEST_ENTER_SIM_PIN
589  *   Returns PIN SIM unlock result
590  */
591 void ipc_sec_sim_status_complete(struct ipc_message_info *info)
592 {
593         struct ipc_gen_phone_res *phone_res = (struct ipc_gen_phone_res *) info->data;
594         int rc;
595
596         int attempts = -1;
597
598         rc = ipc_gen_phone_res_check(phone_res);
599         if (rc < 0) {
600                 if ((phone_res->code & 0x00ff) == 0x10) {
601                         LOGE("Wrong password!");
602                         ril_request_complete(ril_request_get_token(info->aseq), RIL_E_PASSWORD_INCORRECT, &attempts, sizeof(attempts));
603                 } else if ((phone_res->code & 0x00ff) == 0x0c) {
604                         LOGE("Wrong password and no attempts left!");
605
606                         attempts = 0;
607                         ril_request_complete(ril_request_get_token(info->aseq), RIL_E_PASSWORD_INCORRECT, &attempts, sizeof(attempts));
608
609                         ril_request_unsolicited(RIL_UNSOL_RESPONSE_SIM_STATUS_CHANGED, NULL, 0);
610                 } else {
611                         LOGE("There was an error during pin status complete!");
612                         ril_request_complete(ril_request_get_token(info->aseq), RIL_E_GENERIC_FAILURE, NULL, 0);
613                 }
614                 return;
615         }
616
617         ril_request_complete(ril_request_get_token(info->aseq), RIL_E_SUCCESS, &attempts, sizeof(attempts));
618 }
619
620 /**
621  * In: IPC_SEC_LOCK_INFO
622  *   Provides number of retries left for a lock type
623  */
624 void ipc_sec_lock_info(struct ipc_message_info *info)
625 {
626         /*
627          * FIXME: solid way of handling lockinfo and sim unlock response together
628          * so we can return the number of attempts left in respondSecPinStatus
629          */
630         int attempts;
631         struct ipc_sec_lock_info_response *lock_info = (struct ipc_sec_lock_info_response *) info->data;
632
633         if (lock_info->type == IPC_SEC_PIN_TYPE_PIN1) {
634                 attempts = lock_info->attempts;
635                 LOGD("%s: PIN1 %d attempts left", __FUNCTION__, attempts);
636         } else {
637                 LOGE("%s: unhandled lock type %d", __FUNCTION__, lock_info->type);
638         }
639 }
640
641 /**
642  * In: RIL_REQUEST_ENTER_SIM_PIN
643  *   Supplies SIM PIN. Only called if RIL_CardStatus has RIL_APPSTATE_PIN state
644  * 
645  * Out: IPC_SEC_SIM_STATUS SET
646  *   Attempts to unlock SIM PIN1
647  *
648  * Out: IPC_SEC_LOCK_INFO
649  *   Retrieves PIN1 lock status
650  */
651 void ril_request_enter_sim_pin(RIL_Token t, void *data, size_t datalen)
652 {
653         struct ipc_sec_pin_status_set pin_status;
654         char *pin = ((char **) data)[0];
655         unsigned char buf[9];
656
657         /* 1. Send PIN */
658         if (strlen(data) > 16) {
659                 LOGE("%s: pin exceeds maximum length", __FUNCTION__);
660                 ril_request_complete(t, RIL_E_GENERIC_FAILURE, NULL, 0);
661         }
662
663         ipc_sec_pin_status_set_setup(&pin_status, IPC_SEC_PIN_TYPE_PIN1, pin, NULL);
664
665         ipc_gen_phone_res_expect_to_func(ril_request_get_id(t), IPC_SEC_SIM_STATUS,
666                 ipc_sec_sim_status_complete);
667
668         ipc_fmt_send_set(IPC_SEC_SIM_STATUS, ril_request_get_id(t), (unsigned char *) &pin_status, sizeof(pin_status));
669
670         /* 2. Get lock status */
671         // FIXME: This is not clean at all
672         memset(buf, 0, sizeof(buf));
673         buf[0] = 1;
674         buf[1] = IPC_SEC_PIN_TYPE_PIN1;
675
676         ipc_fmt_send(IPC_SEC_LOCK_INFO, IPC_TYPE_GET, buf, sizeof(buf), ril_request_get_id(t));
677 }
678
679 void ril_request_change_sim_pin(RIL_Token t, void *data, size_t datalen)
680 {
681         char *password_old = ((char **) data)[0];
682         char *password_new = ((char **) data)[1];
683         struct ipc_sec_change_locking_pw_set locking_pw;
684
685         memset(&locking_pw, 0, sizeof(locking_pw));
686
687         locking_pw.facility = IPC_SEC_SIM_STATUS_LOCK_SC;
688
689         locking_pw.length_new = strlen(password_new) > sizeof(locking_pw.password_new)
690                                 ? sizeof(locking_pw.password_new)
691                                 : strlen(password_new);
692
693         memcpy(locking_pw.password_new, password_new, locking_pw.length_new);
694
695         locking_pw.length_old = strlen(password_old) > sizeof(locking_pw.password_old)
696                                 ? sizeof(locking_pw.password_old)
697                                 : strlen(password_old);
698
699         memcpy(locking_pw.password_old, password_old, locking_pw.length_old);
700
701         ipc_gen_phone_res_expect_to_func(ril_request_get_id(t), IPC_SEC_CHANGE_LOCKING_PW,
702                 ipc_sec_sim_status_complete);
703
704         ipc_fmt_send_set(IPC_SEC_CHANGE_LOCKING_PW, ril_request_get_id(t), (unsigned char *) &locking_pw, sizeof(locking_pw));
705 }
706
707 void ril_request_enter_sim_puk(RIL_Token t, void *data, size_t datalen)
708 {
709         struct ipc_sec_pin_status_set pin_status;
710         char *puk = ((char **) data)[0];
711         char *pin = ((char **) data)[1];
712
713         ipc_sec_pin_status_set_setup(&pin_status, IPC_SEC_PIN_TYPE_PIN1, pin, puk);
714
715         ipc_gen_phone_res_expect_to_func(ril_request_get_id(t), IPC_SEC_SIM_STATUS,
716                 ipc_sec_sim_status_complete);
717
718         ipc_fmt_send_set(IPC_SEC_SIM_STATUS, ril_request_get_id(t), (unsigned char *) &pin_status, sizeof(pin_status));
719 }
720
721 /**
722  * In: IPC_SEC_PHONE_LOCK
723  *
724  * Out: RIL_REQUEST_QUERY_FACILITY_LOCK
725  *   Query the status of a facility lock state
726  */
727 void ipc_sec_phone_lock(struct ipc_message_info *info)
728 {
729         int status;
730         struct ipc_sec_phone_lock_response *lock = (struct ipc_sec_phone_lock_response *) info->data;
731
732         status = lock->status;
733
734         ril_request_complete(ril_request_get_token(info->aseq), RIL_E_SUCCESS, &status, sizeof(status));
735 }
736
737 /**
738  * In: RIL_REQUEST_QUERY_FACILITY_LOCK
739  *   Query the status of a facility lock state
740  *
741  * Out: IPC_SEC_PHONE_LOCK GET
742  */
743 void ril_request_query_facility_lock(RIL_Token t, void *data, size_t datalen)
744 {
745         struct ipc_sec_phone_lock_get lock_request;
746
747         char *facility = ((char **) data)[0];
748
749         if (!strcmp(facility, "SC")) {
750                 lock_request.facility = IPC_SEC_FACILITY_TYPE_SC;
751         } else if (!strcmp(facility, "FD")) {
752                 lock_request.facility = IPC_SEC_FACILITY_TYPE_FD;
753         } else if (!strcmp(facility, "PN")) {
754                 lock_request.facility = IPC_SEC_FACILITY_TYPE_PN;
755         } else if (!strcmp(facility, "PU")) {
756                 lock_request.facility = IPC_SEC_FACILITY_TYPE_PU;
757         } else if (!strcmp(facility, "PP")) {
758                 lock_request.facility = IPC_SEC_FACILITY_TYPE_PP;
759         } else if (!strcmp(facility, "PC")) {
760                 lock_request.facility = IPC_SEC_FACILITY_TYPE_PC;
761         } else {
762                 LOGE("%s: unsupported facility: %s", __FUNCTION__, facility);
763                 ril_request_complete(t, RIL_E_GENERIC_FAILURE, NULL, 0);
764         }
765
766         ipc_fmt_send(IPC_SEC_PHONE_LOCK, IPC_TYPE_GET, (void *) &lock_request, sizeof(lock_request), ril_request_get_id(t));
767 }
768
769 // Both functions were the same
770 #define ipc_sec_phone_lock_complete \
771         ipc_sec_sim_status_complete
772
773 /**
774  * In: RIL_REQUEST_SET_FACILITY_LOCK
775  *   Enable/disable one facility lock
776  *
777  * Out: IPC_SEC_PHONE_LOCK SET
778  */
779 void ril_request_set_facility_lock(RIL_Token t, void *data, size_t datalen)
780 {
781         struct ipc_sec_phone_lock_set lock_request;
782
783         char *facility = ((char **) data)[0];
784         char *lock = ((char **) data)[1];
785         char *password = ((char **) data)[2];
786         char *class = ((char **) data)[3];
787
788         memset(&lock_request, 0, sizeof(lock_request));
789
790         if (!strcmp(facility, "SC")) {
791                 lock_request.type = IPC_SEC_SIM_STATUS_LOCK_SC;
792         } else if (!strcmp(facility, "FD")) {
793                 lock_request.type = IPC_SEC_SIM_STATUS_LOCK_FD;
794         } else if (!strcmp(facility, "PN")) {
795                 lock_request.type = IPC_SEC_SIM_STATUS_LOCK_PN;
796         } else if (!strcmp(facility, "PU")) {
797                 lock_request.type = IPC_SEC_SIM_STATUS_LOCK_PU;
798         } else if (!strcmp(facility, "PP")) {
799                 lock_request.type = IPC_SEC_SIM_STATUS_LOCK_PP;
800         } else if (!strcmp(facility, "PC")) {
801                 lock_request.type = IPC_SEC_SIM_STATUS_LOCK_PC;
802         } else {
803                 LOGE("%s: unsupported facility: %s", __FUNCTION__, facility);
804                 ril_request_complete(t, RIL_E_GENERIC_FAILURE, NULL, 0);
805         }
806
807         lock_request.lock = lock[0] == '1' ? 1 : 0;
808         lock_request.length = strlen(password) > sizeof(lock_request.password)
809                                 ? sizeof(lock_request.password)
810                                 : strlen(password);
811
812         memcpy(lock_request.password, password, lock_request.length);
813
814         ipc_gen_phone_res_expect_to_func(ril_request_get_id(t), IPC_SEC_PHONE_LOCK,
815                 ipc_sec_phone_lock_complete);
816
817         ipc_fmt_send(IPC_SEC_PHONE_LOCK, IPC_TYPE_SET, (void *) &lock_request, sizeof(lock_request), ril_request_get_id(t));
818 }