9ee39a2dfc9d5bedfed4f1c9a6852e3d8305947f
[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@oaulk.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 SIM_Status ipc2ril_sim_status(struct ipc_sec_sim_status_response *pin_status)
29 {
30         switch(pin_status->status) {
31                 case IPC_SEC_SIM_STATUS_INITIALIZING:
32                         return SIM_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_READY;
37                                 case IPC_SEC_FACILITY_LOCK_TYPE_SC_PIN1_REQ:
38                                         return SIM_PIN;
39                                 case IPC_SEC_FACILITY_LOCK_TYPE_SC_PUK_REQ:
40                                         return SIM_PUK;
41                                 case IPC_SEC_FACILITY_LOCK_TYPE_SC_CARD_BLOCKED:
42                                         return SIM_BLOCKED;
43                                 default:
44                                         LOGE("%s: unknown SC substate %d --> setting SIM_ABSENT", __FUNCTION__, pin_status->facility_lock);
45                                         return SIM_ABSENT;
46                         }
47                         break;
48                 case IPC_SEC_SIM_STATUS_LOCK_FD:
49                         LOGE("%s: FD lock present (unhandled state --> setting SIM_ABSENT)", __FUNCTION__);
50                         return SIM_ABSENT;
51                 case IPC_SEC_SIM_STATUS_LOCK_PN:
52                         return SIM_NETWORK_PERSO;
53                 case IPC_SEC_SIM_STATUS_LOCK_PU:
54                         return SIM_NETWORK_SUBSET_PERSO;
55                 case IPC_SEC_SIM_STATUS_LOCK_PP:
56                         return SIM_SERVICE_PROVIDER_PERSO;
57                 case IPC_SEC_SIM_STATUS_LOCK_PC:
58                         return SIM_CORPORATE_PERSO;
59                 case IPC_SEC_SIM_STATUS_INIT_COMPLETE:
60                         return SIM_READY;
61                 case IPC_SEC_SIM_STATUS_PB_INIT_COMPLETE:
62                         /* Ignore phone book init complete */
63                         return ril_state.sim_status;
64                 case IPC_SEC_SIM_STATUS_SIM_LOCK_REQUIRED:
65                 case IPC_SEC_SIM_STATUS_INSIDE_PF_ERROR:
66                 case IPC_SEC_SIM_STATUS_CARD_NOT_PRESENT:
67                 case IPC_SEC_SIM_STATUS_CARD_ERROR:
68                 default:
69                         /* Catchall for locked, card error and unknown states */
70                         return SIM_ABSENT;
71         }
72 }
73
74 /**
75  * Update the radio state based on SIM status
76  *
77  * Out: RIL_UNSOL_RESPONSE_RADIO_STATE_CHANGED
78  *   Indicate when value of RIL_RadioState has changed
79  *   Callee will invoke RIL_RadioStateRequest method on main thread
80  */
81 void ril_state_update(SIM_Status status)
82 {
83         RIL_RadioState radio_state;
84
85         /* If power mode isn't at least normal, don't update RIL state */
86         if(ril_state.power_mode < POWER_MODE_NORMAL)
87                 return;
88
89         ril_state.sim_status = status;
90
91         switch(status) {
92                 case SIM_READY:
93 #if RIL_VERSION >= 7
94                         radio_state = RADIO_STATE_ON;
95 #else
96                         radio_state = RADIO_STATE_SIM_READY;
97 #endif
98                         break;
99                 case SIM_NOT_READY:
100                         radio_state = RADIO_STATE_SIM_NOT_READY;
101                         break;
102                 case SIM_ABSENT:
103                 case SIM_PIN:
104                 case SIM_PUK:
105                 case SIM_BLOCKED:
106                 case SIM_NETWORK_PERSO:
107                 case SIM_NETWORK_SUBSET_PERSO:
108                 case SIM_CORPORATE_PERSO:
109                 case SIM_SERVICE_PROVIDER_PERSO:
110                         radio_state = RADIO_STATE_SIM_LOCKED_OR_ABSENT;
111                         break;
112                 default:
113                         radio_state = RADIO_STATE_SIM_NOT_READY;
114                         break;
115         }
116
117
118         ril_state.radio_state = radio_state;
119
120         ril_tokens_check();
121
122         RIL_onUnsolicitedResponse(RIL_UNSOL_RESPONSE_RADIO_STATE_CHANGED, NULL, 0);
123 }
124
125 void ipc2ril_card_status(struct ipc_sec_sim_status_response *pin_status, RIL_CardStatus *card_status)
126 {
127         SIM_Status sim_status;
128         int app_status_array_length;
129         int app_index;
130         int i;
131
132         static RIL_AppStatus app_status_array[] = {
133                 /* SIM_ABSENT = 0 */
134                 { RIL_APPTYPE_UNKNOWN, RIL_APPSTATE_UNKNOWN, RIL_PERSOSUBSTATE_UNKNOWN,
135                 NULL, NULL, 0, RIL_PINSTATE_UNKNOWN, RIL_PINSTATE_UNKNOWN },
136                 /* SIM_NOT_READY = 1 */
137                 { RIL_APPTYPE_SIM, RIL_APPSTATE_DETECTED, RIL_PERSOSUBSTATE_UNKNOWN,
138                 NULL, NULL, 0, RIL_PINSTATE_UNKNOWN, RIL_PINSTATE_UNKNOWN },
139                 /* SIM_READY = 2 */
140                 { RIL_APPTYPE_SIM, RIL_APPSTATE_READY, RIL_PERSOSUBSTATE_READY,
141                 NULL, NULL, 0, RIL_PINSTATE_UNKNOWN, RIL_PINSTATE_UNKNOWN },
142                 /* SIM_PIN = 3 */
143                 { RIL_APPTYPE_SIM, RIL_APPSTATE_PIN, RIL_PERSOSUBSTATE_UNKNOWN,
144                 NULL, NULL, 0, RIL_PINSTATE_ENABLED_NOT_VERIFIED, RIL_PINSTATE_UNKNOWN },
145                 /* SIM_PUK = 4 */
146                 { RIL_APPTYPE_SIM, RIL_APPSTATE_PUK, RIL_PERSOSUBSTATE_UNKNOWN,
147                 NULL, NULL, 0, RIL_PINSTATE_ENABLED_BLOCKED, RIL_PINSTATE_UNKNOWN },
148                 /* SIM_BLOCKED = 4 */
149                 { RIL_APPTYPE_SIM, RIL_APPSTATE_PUK, RIL_PERSOSUBSTATE_UNKNOWN,
150                 NULL, NULL, 0, RIL_PINSTATE_ENABLED_PERM_BLOCKED, RIL_PINSTATE_UNKNOWN },
151                 /* SIM_NETWORK_PERSO = 6 */
152                 { RIL_APPTYPE_SIM, RIL_APPSTATE_SUBSCRIPTION_PERSO, RIL_PERSOSUBSTATE_SIM_NETWORK,
153                 NULL, NULL, 0, RIL_PINSTATE_ENABLED_NOT_VERIFIED, RIL_PINSTATE_UNKNOWN },
154                 /* SIM_NETWORK_SUBSET_PERSO = 7 */
155                 { RIL_APPTYPE_SIM, RIL_APPSTATE_SUBSCRIPTION_PERSO, RIL_PERSOSUBSTATE_SIM_NETWORK_SUBSET,
156                 NULL, NULL, 0, RIL_PINSTATE_ENABLED_NOT_VERIFIED, RIL_PINSTATE_UNKNOWN },
157                 /* SIM_CORPORATE_PERSO = 8 */
158                 { RIL_APPTYPE_SIM, RIL_APPSTATE_SUBSCRIPTION_PERSO, RIL_PERSOSUBSTATE_SIM_CORPORATE,
159                 NULL, NULL, 0, RIL_PINSTATE_ENABLED_NOT_VERIFIED, RIL_PINSTATE_UNKNOWN },
160                 /* SIM_SERVICE_PROVIDER_PERSO = 9 */
161                 { RIL_APPTYPE_SIM, RIL_APPSTATE_SUBSCRIPTION_PERSO, RIL_PERSOSUBSTATE_SIM_SERVICE_PROVIDER,
162                 NULL, NULL, 0, RIL_PINSTATE_ENABLED_NOT_VERIFIED, RIL_PINSTATE_UNKNOWN },
163         };
164
165         app_status_array_length = sizeof(app_status_array) / sizeof(RIL_AppStatus);
166
167         if(app_status_array_length > RIL_CARD_MAX_APPS)
168                 app_status_array_length = RIL_CARD_MAX_APPS;
169
170         sim_status = ipc2ril_sim_status(pin_status);
171
172         /* Card is assumed to be present if not explicitly absent */
173         if(sim_status == SIM_ABSENT) {
174                 card_status->card_state = RIL_CARDSTATE_ABSENT;
175         } else {
176                 card_status->card_state = RIL_CARDSTATE_PRESENT;
177         }
178
179         // FIXME: How do we know that?
180         card_status->universal_pin_state = RIL_PINSTATE_UNKNOWN;
181
182         // Initialize the apps
183         for (i = 0 ; i < app_status_array_length ; i++) {
184                 memcpy((void *) &(card_status->applications[i]), (void *) &(app_status_array[i]), sizeof(RIL_AppStatus));
185         }
186         for(i = app_status_array_length ; i < RIL_CARD_MAX_APPS ; i++) {
187                 memset((void *) &(card_status->applications[i]), 0, sizeof(RIL_AppStatus));
188         }
189
190         // sim_status corresponds to the app index on the table
191         card_status->gsm_umts_subscription_app_index = (int) sim_status;
192         card_status->cdma_subscription_app_index = (int) sim_status;
193         card_status->num_applications = app_status_array_length;
194
195         LOGD("Selecting application #%d on %d", (int) sim_status, app_status_array_length);
196 }
197
198 void ril_tokens_pin_status_dump(void)
199 {
200         LOGD("ril_tokens_pin_status_dump:\n\
201         \tril_state.tokens.pin_status = 0x%p\n", ril_state.tokens.pin_status);
202 }
203
204 /**
205  * In: IPC_SEC_SIM_STATUS
206  *   Provides SIM initialization/lock status
207  *
208  * Out: RIL_UNSOL_RESPONSE_SIM_STATUS_CHANGED
209  *   Indicates that SIM state changes.
210  *   Callee will invoke RIL_REQUEST_GET_SIM_STATUS on main thread
211  *
212  * Out: RIL_UNSOL_RESPONSE_RADIO_STATE_CHANGED
213  *   Indicate when value of RIL_RadioState has changed
214  *   Callee will invoke RIL_RadioStateRequest method on main thread
215  */
216 void ipc_sec_sim_status(struct ipc_message_info *info)
217 {
218         RIL_Token t = reqGetToken(info->aseq);
219         struct ipc_sec_sim_status_response *pin_status = (struct ipc_sec_sim_status_response *) info->data;
220         RIL_CardStatus card_status;
221         SIM_Status sim_status;
222
223         if(ril_state.power_mode == POWER_MODE_NORMAL && ril_state.tokens.radio_power != (RIL_Token) 0x00) {
224                 RIL_onRequestComplete(ril_state.tokens.radio_power, RIL_E_SUCCESS, NULL, 0);
225                 ril_state.tokens.radio_power = (RIL_Token) 0x00;
226         }
227
228         switch(info->type) {
229                 case IPC_TYPE_NOTI:
230                         // Don't consider this if modem isn't in normal power mode
231                         if(ril_state.power_mode < POWER_MODE_NORMAL)
232                                 return;
233
234                         LOGD("Got UNSOL PIN status message");
235
236                         if(ril_state.tokens.pin_status != (RIL_Token) 0x00 && ril_state.tokens.pin_status != RIL_TOKEN_DATA_WAITING) {
237                                 LOGE("Another PIN status Req is in progress, skipping");
238                                 return;
239                         }
240
241                         sim_status = ipc2ril_sim_status(pin_status);
242                         ril_state_update(sim_status);
243
244                         memcpy(&(ril_state.sim_pin_status), pin_status, sizeof(struct ipc_sec_sim_status_response));
245
246                         ril_state.tokens.pin_status = RIL_TOKEN_DATA_WAITING;
247                         RIL_onUnsolicitedResponse(RIL_UNSOL_RESPONSE_SIM_STATUS_CHANGED, NULL, 0);
248                         break;
249                 case IPC_TYPE_RESP:
250                         LOGD("Got SOL PIN status message");
251
252                         if(ril_state.tokens.pin_status != t)
253                                 LOGE("PIN status tokens mismatch");
254
255                         sim_status = ipc2ril_sim_status(pin_status);
256                         ril_state_update(sim_status);
257
258                         // Better keeping this up to date
259                         memcpy(&(ril_state.sim_pin_status), pin_status, sizeof(struct ipc_sec_sim_status_response));
260
261                         ipc2ril_card_status(pin_status, &card_status);
262                         RIL_onRequestComplete(t, RIL_E_SUCCESS, &card_status, sizeof(RIL_CardStatus));
263
264                         if(ril_state.tokens.pin_status != RIL_TOKEN_DATA_WAITING)
265                                 ril_state.tokens.pin_status = (RIL_Token) 0x00;
266                         break;
267                 default:
268                         LOGE("%s: unhandled ipc method: %d", __FUNCTION__, info->type);
269                         break;
270         }
271
272         ril_tokens_pin_status_dump();
273 }
274
275 /**
276  * In: RIL_REQUEST_GET_SIM_STATUS
277  *   Requests status of the SIM interface and the SIM card
278  */
279 void ril_request_get_sim_status(RIL_Token t)
280 {
281         struct ipc_sec_sim_status_response *pin_status;
282         RIL_CardStatus card_status;
283         SIM_Status sim_status;
284
285         if(ril_state.tokens.pin_status == RIL_TOKEN_DATA_WAITING) {
286                 LOGD("Got RILJ request for UNSOL data");
287                 hex_dump(&(ril_state.sim_pin_status), sizeof(struct ipc_sec_sim_status_response));
288                 pin_status = &(ril_state.sim_pin_status);
289
290                 ipc2ril_card_status(pin_status, &card_status);
291
292                 RIL_onRequestComplete(t, RIL_E_SUCCESS, &card_status, sizeof(RIL_CardStatus));
293
294                 ril_state.tokens.pin_status = (RIL_Token) 0x00;
295         } else if(ril_state.tokens.pin_status == (RIL_Token) 0x00) {
296                 LOGD("Got RILJ request for SOL data");
297
298                 /* Request data to the modem */
299                 ril_state.tokens.pin_status = t;
300
301                 ipc_fmt_send_get(IPC_SEC_SIM_STATUS, reqGetId(t));
302         } else {
303                 LOGE("Another request is going on, returning UNSOL data");
304
305                 pin_status = &(ril_state.sim_pin_status);
306
307                 ipc2ril_card_status(pin_status, &card_status);
308                 RIL_onRequestComplete(t, RIL_E_SUCCESS, &card_status, sizeof(card_status));
309         }
310
311         ril_tokens_pin_status_dump();
312 }
313
314 /**
315  * In: RIL_REQUEST_SIM_IO
316  *   Request SIM I/O operation.
317  *   This is similar to the TS 27.007 "restricted SIM" operation
318  *   where it assumes all of the EF selection will be done by the
319  *   callee.
320  *
321  * Out: IPC_SEC_RSIM_ACCESS
322  *   Performs a restricted SIM read operation
323  */
324 void ril_request_sim_io(RIL_Token t, void *data, size_t datalen)
325 {
326         const RIL_SIM_IO *sim_io;
327         unsigned char message[262];
328         struct ipc_sec_rsim_access_get *rsim_data;
329
330         unsigned char *rsim_payload;
331         int payload_length;
332
333         sim_io = (const RIL_SIM_IO*)data;
334         rsim_payload = message + sizeof(*rsim_data);
335
336         /* Set up RSIM header */
337         rsim_data = (struct ipc_sec_rsim_access_get*)message;
338         rsim_data->command = sim_io->command;
339         rsim_data->fileid = sim_io->fileid;
340         rsim_data->p1 = sim_io->p1;
341         rsim_data->p2 = sim_io->p2;
342         rsim_data->p3 = sim_io->p3;
343
344         /* Add payload if present */
345         if(sim_io->data) {
346                 payload_length = (2 * strlen(sim_io->data));
347
348                 if(sizeof(*rsim_data) + payload_length > sizeof(message))
349                         return;
350
351                 hex2bin(sim_io->data, strlen(sim_io->data), rsim_payload);
352         }
353
354         ipc_fmt_send(IPC_SEC_RSIM_ACCESS, IPC_TYPE_GET, (unsigned char*)&message, sizeof(message), reqGetId(t));
355 }
356
357 /**
358  * In: IPC_SEC_RSIM_ACCESS
359  *   Provides restricted SIM read operation result
360  *
361  * Out: RIL_REQUEST_SIM_IO
362  *   Request SIM I/O operation.
363  *   This is similar to the TS 27.007 "restricted SIM" operation
364  *   where it assumes all of the EF selection will be done by the
365  *   callee.
366  */
367 void ipc_sec_rsim_access(struct ipc_message_info *info)
368 {
369         struct ipc_sec_rsim_access_response *rsim_resp = (struct ipc_sec_rsim_access_response *) info->data;
370         const unsigned char *data_ptr = ((unsigned char *) info->data + sizeof(*rsim_resp));
371         char *sim_resp;
372         RIL_SIM_IO_Response response;
373
374         response.sw1 = rsim_resp->sw1;
375         response.sw2 = rsim_resp->sw2;
376
377         if(rsim_resp->len) {
378                 sim_resp = (char*)malloc(rsim_resp->len * 2 + 1);
379                 bin2hex(data_ptr, rsim_resp->len, sim_resp);
380                 response.simResponse = sim_resp;
381         } else {
382                 response.simResponse = malloc(1);
383                 response.simResponse[0] = '\0';
384         }
385
386         RIL_onRequestComplete(reqGetToken(info->aseq), RIL_E_SUCCESS, &response, sizeof(response));
387
388         free(response.simResponse);
389 }
390
391 /**
392  * In: IPC_GEN_PHONE_RES
393  *   Provides result of IPC_SEC_SIM_STATUS SET
394  *
395  * Out: RIL_REQUEST_ENTER_SIM_PIN
396  *   Returns PIN SIM unlock result
397  */
398 void ipc_sec_sim_status_complete(struct ipc_message_info *info)
399 {
400         struct ipc_gen_phone_res *phone_res = (struct ipc_gen_phone_res *) info->data;
401         int rc;
402
403         int attempts = -1;
404
405         rc = ipc_gen_phone_res_check(phone_res);
406         if(rc < 0) {
407                 if((phone_res->code & 0x00ff) == 0x10) {
408                         LOGE("Wrong password!");
409                         RIL_onRequestComplete(reqGetToken(info->aseq), RIL_E_PASSWORD_INCORRECT, &attempts, sizeof(attempts));
410                 } else if((phone_res->code & 0x00ff) == 0x0c) {
411                         LOGE("Wrong password and no attempts left!");
412
413                         attempts = 0;
414                         RIL_onRequestComplete(reqGetToken(info->aseq), RIL_E_PASSWORD_INCORRECT, &attempts, sizeof(attempts));
415
416                         RIL_onUnsolicitedResponse(RIL_UNSOL_RESPONSE_SIM_STATUS_CHANGED, NULL, 0);
417                 } else {
418                         LOGE("There was an error during pin status complete!");
419                         RIL_onRequestComplete(reqGetToken(info->aseq), RIL_E_GENERIC_FAILURE, NULL, 0);
420                 }
421                 return;
422         }
423
424         RIL_onRequestComplete(reqGetToken(info->aseq), RIL_E_SUCCESS, &attempts, sizeof(attempts));
425 }
426
427 /**
428  * In: IPC_SEC_LOCK_INFO
429  *   Provides number of retries left for a lock type
430  */
431 void ipc_sec_lock_info(struct ipc_message_info *info)
432 {
433         /*
434          * FIXME: solid way of handling lockinfo and sim unlock response together
435          * so we can return the number of attempts left in respondSecPinStatus
436          */
437         int attempts;
438         struct ipc_sec_lock_info_response *lock_info = (struct ipc_sec_lock_info_response *) info->data;
439
440         if(lock_info->type == IPC_SEC_PIN_TYPE_PIN1) {
441                 attempts = lock_info->attempts;
442                 LOGD("%s: PIN1 %d attempts left", __FUNCTION__, attempts);
443         } else {
444                 LOGE("%s: unhandled lock type %d", __FUNCTION__, lock_info->type);
445         }
446 }
447
448 /**
449  * In: RIL_REQUEST_ENTER_SIM_PIN
450  *   Supplies SIM PIN. Only called if RIL_CardStatus has RIL_APPSTATE_PIN state
451  * 
452  * Out: IPC_SEC_SIM_STATUS SET
453  *   Attempts to unlock SIM PIN1
454  *
455  * Out: IPC_SEC_LOCK_INFO
456  *   Retrieves PIN1 lock status
457  */
458 void ril_request_enter_sim_pin(RIL_Token t, void *data, size_t datalen)
459 {
460         struct ipc_sec_pin_status_set pin_status;
461         char *pin = ((char **) data)[0];
462         unsigned char buf[9];
463
464         /* 1. Send PIN */
465         if(strlen(data) > 16) {
466                 LOGE("%s: pin exceeds maximum length", __FUNCTION__);
467                 RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0);
468         }
469
470         ipc_sec_pin_status_set_setup(&pin_status, IPC_SEC_PIN_TYPE_PIN1, pin, NULL);
471
472         ipc_gen_phone_res_expect_to_func(reqGetId(t), IPC_SEC_SIM_STATUS,
473                 ipc_sec_sim_status_complete);
474
475         ipc_fmt_send_set(IPC_SEC_SIM_STATUS, reqGetId(t), (unsigned char *) &pin_status, sizeof(pin_status));
476
477         /* 2. Get lock status */
478         // FIXME: This is not clean at all
479         memset(buf, 0, sizeof(buf));
480         buf[0] = 1;
481         buf[1] = IPC_SEC_PIN_TYPE_PIN1;
482
483         ipc_fmt_send(IPC_SEC_LOCK_INFO, IPC_TYPE_GET, buf, sizeof(buf), reqGetId(t));
484 }
485
486 void ril_request_change_sim_pin(RIL_Token t, void *data, size_t datalen)
487 {
488         char *password_old = ((char **) data)[0];
489         char *password_new = ((char **) data)[1];
490         struct ipc_sec_change_locking_pw locking_pw;
491
492         memset(&locking_pw, 0, sizeof(locking_pw));
493
494         locking_pw.facility = IPC_SEC_SIM_STATUS_LOCK_SC;
495
496         locking_pw.length_new = strlen(password_new) > sizeof(locking_pw.password_new)
497                                 ? sizeof(locking_pw.password_new)
498                                 : strlen(password_new);
499
500         memcpy(locking_pw.password_new, password_new, locking_pw.length_new);
501
502         locking_pw.length_old = strlen(password_old) > sizeof(locking_pw.password_old)
503                                 ? sizeof(locking_pw.password_old)
504                                 : strlen(password_old);
505
506         memcpy(locking_pw.password_old, password_old, locking_pw.length_old);
507
508         ipc_gen_phone_res_expect_to_func(reqGetId(t), IPC_SEC_CHANGE_LOCKING_PW,
509                 ipc_sec_sim_status_complete);
510
511         ipc_fmt_send_set(IPC_SEC_CHANGE_LOCKING_PW, reqGetId(t), (unsigned char *) &locking_pw, sizeof(locking_pw));
512 }
513
514 void ril_request_enter_sim_puk(RIL_Token t, void *data, size_t datalen)
515 {
516         struct ipc_sec_pin_status_set pin_status;
517         char *puk = ((char **) data)[0];
518         char *pin = ((char **) data)[1];
519
520         ipc_sec_pin_status_set_setup(&pin_status, IPC_SEC_PIN_TYPE_PIN1, pin, puk);
521
522         ipc_gen_phone_res_expect_to_func(reqGetId(t), IPC_SEC_SIM_STATUS,
523                 ipc_sec_sim_status_complete);
524
525         ipc_fmt_send_set(IPC_SEC_SIM_STATUS, reqGetId(t), (unsigned char *) &pin_status, sizeof(pin_status));
526 }
527
528 /**
529  * In: IPC_SEC_PHONE_LOCK
530  *
531  * Out: RIL_REQUEST_QUERY_FACILITY_LOCK
532  *   Query the status of a facility lock state
533  */
534 void ipc_sec_phone_lock(struct ipc_message_info *info)
535 {
536         int status;
537         struct ipc_sec_phone_lock_response *lock = (struct ipc_sec_phone_lock_response *) info->data;
538
539         status = lock->status;
540
541         RIL_onRequestComplete(reqGetToken(info->aseq), RIL_E_SUCCESS, &status, sizeof(status));
542 }
543
544 /**
545  * In: RIL_REQUEST_QUERY_FACILITY_LOCK
546  *   Query the status of a facility lock state
547  *
548  * Out: IPC_SEC_PHONE_LOCK GET
549  */
550 void ril_request_query_facility_lock(RIL_Token t, void *data, size_t datalen)
551 {
552         struct ipc_sec_phone_lock_get lock_request;
553
554         char *facility = ((char **) data)[0];
555
556         if(!strcmp(facility, "SC")) {
557                 lock_request.facility = IPC_SEC_FACILITY_TYPE_SC;
558         } else if(!strcmp(facility, "FD")) {
559                 lock_request.facility = IPC_SEC_FACILITY_TYPE_FD;
560         } else if(!strcmp(facility, "PN")) {
561                 lock_request.facility = IPC_SEC_FACILITY_TYPE_PN;
562         } else if(!strcmp(facility, "PU")) {
563                 lock_request.facility = IPC_SEC_FACILITY_TYPE_PU;
564         } else if(!strcmp(facility, "PP")) {
565                 lock_request.facility = IPC_SEC_FACILITY_TYPE_PP;
566         } else if(!strcmp(facility, "PC")) {
567                 lock_request.facility = IPC_SEC_FACILITY_TYPE_PC;
568         } else {
569                 LOGE("%s: unsupported facility: %s", __FUNCTION__, facility);
570                 RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0);
571         }
572         ipc_fmt_send(IPC_SEC_PHONE_LOCK, IPC_TYPE_GET, &lock_request, sizeof(lock_request), reqGetId(t));
573 }
574
575 // Both functions were the same
576 #define ipc_sec_phone_lock_complete \
577         ipc_sec_sim_status_complete
578
579 /**
580  * In: RIL_REQUEST_SET_FACILITY_LOCK
581  *   Enable/disable one facility lock
582  *
583  * Out: IPC_SEC_PHONE_LOCK SET
584  */
585 void ril_request_set_facility_lock(RIL_Token t, void *data, size_t datalen)
586 {
587         struct ipc_sec_phone_lock_set lock_request;
588
589         char *facility = ((char **) data)[0];
590         char *lock = ((char **) data)[1];
591         char *password = ((char **) data)[2];
592         char *class = ((char **) data)[3];
593
594         memset(&lock_request, 0, sizeof(lock_request));
595
596         if(!strcmp(facility, "SC")) {
597                 lock_request.type = IPC_SEC_SIM_STATUS_LOCK_SC;
598         } else if(!strcmp(facility, "FD")) {
599                 lock_request.type = IPC_SEC_SIM_STATUS_LOCK_FD;
600         } else if(!strcmp(facility, "PN")) {
601                 lock_request.type = IPC_SEC_SIM_STATUS_LOCK_PN;
602         } else if(!strcmp(facility, "PU")) {
603                 lock_request.type = IPC_SEC_SIM_STATUS_LOCK_PU;
604         } else if(!strcmp(facility, "PP")) {
605                 lock_request.type = IPC_SEC_SIM_STATUS_LOCK_PP;
606         } else if(!strcmp(facility, "PC")) {
607                 lock_request.type = IPC_SEC_SIM_STATUS_LOCK_PC;
608         } else {
609                 LOGE("%s: unsupported facility: %s", __FUNCTION__, facility);
610                 RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0);
611         }
612
613         lock_request.lock = lock[0] == '1' ? 1 : 0;
614         lock_request.length = strlen(password) > sizeof(lock_request.password)
615                                 ? sizeof(lock_request.password)
616                                 : strlen(password);
617
618         memcpy(lock_request.password, password, lock_request.length);
619
620         ipc_gen_phone_res_expect_to_func(reqGetId(t), IPC_SEC_PHONE_LOCK,
621                 ipc_sec_phone_lock_complete);
622
623         ipc_fmt_send(IPC_SEC_PHONE_LOCK, IPC_TYPE_SET, &lock_request, sizeof(lock_request), reqGetId(t));
624 }