IMC plugin update
[platform/core/telephony/tel-plugin-imc.git] / src / imc_sap.c
1 /*
2  * tel-plugin-imc
3  *
4  * Copyright (c) 2013 Samsung Electronics Co. Ltd. All rights reserved.
5  *
6  * Licensed under the Apache License, Version 2.0 (the "License");
7  * you may not use this file except in compliance with the License.
8  * You may obtain a copy of the License at
9  *
10  * http://www.apache.org/licenses/LICENSE-2.0
11  *
12  * Unless required by applicable law or agreed to in writing, software
13  * distributed under the License is distributed on an "AS IS" BASIS,
14  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15  * See the License for the specific language governing permissions and
16  * limitations under the License.
17  */
18
19 #include <stdio.h>
20 #include <stdlib.h>
21 #include <string.h>
22
23 #include <glib.h>
24
25 #include <tcore.h>
26 #include <server.h>
27 #include <plugin.h>
28 #include <core_object.h>
29 #include <hal.h>
30 #include <queue.h>
31 #include <storage.h>
32 #include <at.h>
33
34 #include <co_sap.h>
35
36 #include "imc_sap.h"
37 #include "imc_common.h"
38
39 static TelSapResult __imc_sap_convert_cme_error_tel_sap_result(const TcoreAtResponse *at_resp)
40 {
41         TelSapResult result = TEL_SAP_RESULT_FAILURE_NO_REASON;
42         const gchar *line;
43         GSList *tokens = NULL;
44
45         dbg("Entry");
46
47         if (!at_resp || !at_resp->lines) {
48                 err("Invalid response data");
49                 return result;
50         }
51
52         line = (const gchar *)at_resp->lines->data;
53         tokens = tcore_at_tok_new(line);
54         if (g_slist_length(tokens) > 0) {
55                 gchar *resp_str;
56                 gint cme_err;
57
58                 resp_str = g_slist_nth_data(tokens, 0);
59                 if (!resp_str) {
60                         err("Invalid CME Error data");
61                         tcore_at_tok_free(tokens);
62                         return result;
63                 }
64                 cme_err = atoi(resp_str);
65                 dbg("CME Error: [%d]", cme_err);
66
67                 switch (cme_err) {
68                 case 3:
69                 case 4:
70                         result = TEL_SAP_RESULT_OPERATION_NOT_PERMITTED;
71                 break;
72
73                 case 14:
74                         result = TEL_SAP_RESULT_ONGOING_CALL;
75                 break;
76
77                 default:
78                         result = TEL_SAP_RESULT_FAILURE_NO_REASON;
79                 }
80         }
81         tcore_at_tok_free(tokens);
82
83         return result;
84 }
85
86 static TelSapResult __map_sap_status_to_result(int sap_status)
87 {
88         switch(sap_status){
89         case 0:
90                 return TEL_SAP_RESULT_SUCCESS;
91         case 1:
92                 return TEL_SAP_RESULT_FAILURE_NO_REASON;
93         case 2:
94                 return TEL_SAP_RESULT_CARD_NOT_ACCESSIBLE;
95         case 3:
96                 return TEL_SAP_RESULT_CARD_ALREADY_POWERED_OFF;
97         case 4:
98                 return TEL_SAP_RESULT_CARD_REMOVED;
99         case 5:
100                 return TEL_SAP_RESULT_CARD_ALREADY_POWERED_ON;
101         case 6:
102                 return TEL_SAP_RESULT_DATA_NOT_AVAILABLE;
103         case 7:
104                 return TEL_SAP_RESULT_NOT_SUPPORTED;
105         default:
106                 return TEL_SAP_RESULT_FAILURE_NO_REASON;
107         }
108 }
109
110 /* Notification */
111 static gboolean on_notification_imc_sap_status(CoreObject *co,
112         const void *event_info, void *user_data)
113 {
114         GSList *tokens = NULL;
115         GSList *lines = NULL;
116         const char *line = NULL;
117         TelSapCardStatus status;
118
119         dbg("Entry");
120
121         lines = (GSList *) event_info;
122         if (g_slist_length(lines) != 1) {
123                 err("unsolicited msg but multiple lines");
124                 return FALSE;
125         }
126
127         line = (char *)lines->data;
128         tokens = tcore_at_tok_new(line);
129         tcore_check_return_value(tokens != NULL, FALSE);
130
131         status = atoi(g_slist_nth_data(tokens, 0));
132
133         switch(status){
134         case 0:
135                 status = TEL_SAP_CARD_STATUS_UNKNOWN;
136                 break;
137         case 1:
138                 status = TEL_SAP_CARD_STATUS_RESET;
139                 break;
140         case 2:
141                 status = TEL_SAP_CARD_STATUS_NOT_ACCESSIBLE;
142                 break;
143         case 3:
144                 status = TEL_SAP_CARD_STATUS_REMOVED;
145                 break;
146         case 4:
147                 status = TEL_SAP_CARD_STATUS_INSERTED;
148                 break;
149         case 5:
150                 status = TEL_SAP_CARD_STATUS_RECOVERED;
151                 break;
152         default:
153                 status = TEL_SAP_CARD_STATUS_NOT_ACCESSIBLE;
154                 break;
155         }
156
157         tcore_at_tok_free(tokens);
158         tcore_object_send_notification(co,
159                 TCORE_NOTIFICATION_SAP_STATUS,
160                 sizeof(TelSapCardStatus), &status);
161         return TRUE;
162 }
163
164 /* Response */
165 static void on_response_imc_sap_req_connect(TcorePending *p,
166         guint data_len, const void *data, void *user_data)
167 {
168         const TcoreAtResponse *at_resp = data;
169         CoreObject *co = tcore_pending_ref_core_object(p);
170         ImcRespCbData *resp_cb_data = user_data;
171         TelSapResult result = TEL_SAP_RESULT_UNABLE_TO_ESTABLISH;
172         unsigned int max_msg_size = 0;
173         dbg("entry");
174
175         tcore_check_return_assert(co != NULL);
176         tcore_check_return_assert(resp_cb_data != NULL);
177
178         if (at_resp && at_resp->success) {
179                 result = TEL_SAP_RESULT_SUCCESS;
180                 memcpy(&max_msg_size, IMC_GET_DATA_FROM_RESP_CB_DATA(resp_cb_data), sizeof(unsigned int));
181         } else {
182                 err("RESPONSE NOK");
183                 result = __imc_sap_convert_cme_error_tel_sap_result(at_resp);
184         }
185
186         dbg("Request to sap connection : [%s]",
187         (result == TEL_SAP_RESULT_SUCCESS ? "SUCCESS" : "FAIL"));
188
189         /* Invoke callback */
190         if (resp_cb_data->cb)
191                 resp_cb_data->cb(co, (gint)result, &max_msg_size, resp_cb_data->cb_data);
192
193         /* Free callback data */
194         imc_destroy_resp_cb_data(resp_cb_data);
195 }
196
197 static void on_response_imc_sap_req_disconnect(TcorePending *p,
198         guint data_len, const void *data, void *user_data)
199 {
200         const TcoreAtResponse *at_resp = data;
201         CoreObject *co = tcore_pending_ref_core_object(p);
202         ImcRespCbData *resp_cb_data = user_data;
203         TelSapResult result = TEL_SAP_RESULT_FAILURE_NO_REASON;
204         dbg("entry");
205
206         tcore_check_return_assert(co != NULL);
207         tcore_check_return_assert(resp_cb_data != NULL);
208
209         if (at_resp && at_resp->success) {
210                 result = TEL_SAP_RESULT_SUCCESS;
211         } else {
212                 err("RESPONSE NOK");
213                 result = __imc_sap_convert_cme_error_tel_sap_result(at_resp);
214         }
215
216         dbg("Request to sap connection : [%s]",
217         (result == TEL_SAP_RESULT_SUCCESS ? "SUCCESS" : "FAIL"));
218
219         /* Invoke callback */
220         if (resp_cb_data->cb)
221                 resp_cb_data->cb(co, (gint)result, NULL, resp_cb_data->cb_data);
222
223         /* Free callback data */
224         imc_destroy_resp_cb_data(resp_cb_data);
225 }
226
227 static void on_response_imc_sap_get_atr(TcorePending *p,
228         guint data_len, const void *data, void *user_data)
229 {
230         const TcoreAtResponse *at_resp = data;
231         CoreObject *co = tcore_pending_ref_core_object(p);
232         ImcRespCbData *resp_cb_data = user_data;
233         TelSapResult result = TEL_SAP_RESULT_FAILURE_NO_REASON;
234         TelSapAtr atr_resp = {0,};
235
236         dbg("entry");
237
238         if (at_resp && at_resp->success) {
239                 const gchar *line;
240                 char *atr_data;
241                 GSList *tokens = NULL;
242
243                 dbg("RESPONSE OK");
244                 if (at_resp->lines == NULL) {
245                         err("invalid response recieved");
246                         goto END;
247                 }
248
249                 line = (const char*)at_resp->lines->data;
250                 tokens = tcore_at_tok_new(line);
251                 if (g_slist_length(tokens) < 1) {
252                         err("invalid response message");
253                         tcore_at_tok_free(tokens);
254                         goto END;
255                 }
256                 atr_data = (char *) g_slist_nth_data(tokens, 1);
257                 atr_resp.atr_len = strlen(atr_data);
258                 if (atr_resp.atr_len > TEL_SAP_ATR_LEN_MAX) {
259                         err(" invalid atr data length");
260                         tcore_at_tok_free(tokens);
261                         goto END;
262                 }
263                 memcpy(atr_resp.atr, atr_data, atr_resp.atr_len);
264
265                 result = __map_sap_status_to_result(atoi(g_slist_nth_data(tokens, 0)));
266                 tcore_at_tok_free(tokens);
267         } else {
268                 err("RESPONSE NOK");
269                 result = __imc_sap_convert_cme_error_tel_sap_result(at_resp);
270         }
271
272 END:
273         dbg("Request to get sap atr : [%s]",
274                 (result == TEL_SAP_RESULT_SUCCESS ? "SUCCESS" : "FAIL"));
275
276         /* Invoke callback */
277         if (resp_cb_data->cb)
278                 resp_cb_data->cb(co, (gint)result, &atr_resp, resp_cb_data->cb_data);
279
280         /* Free callback data */
281         imc_destroy_resp_cb_data(resp_cb_data);
282 }
283
284 static void on_response_imc_sap_req_transfer_apdu(TcorePending *p,
285         guint data_len, const void *data, void *user_data)
286 {
287         const TcoreAtResponse *at_resp = data;
288         CoreObject *co = tcore_pending_ref_core_object(p);
289         ImcRespCbData *resp_cb_data = user_data;
290         TelSapResult result = TEL_SAP_RESULT_FAILURE_NO_REASON;
291         TelSapApduResp apdu_resp = {0,};
292
293         dbg("entry");
294
295         if (at_resp && at_resp->success) {
296                 const gchar *line;
297                 int sap_status;
298                 char *apdu_data;
299                 GSList *tokens = NULL;
300
301                 dbg("RESPONSE OK");
302                 if (at_resp->lines == NULL) {
303                         err("invalid response recieved");
304                         goto END;
305                 }
306
307                 line = (const char*)at_resp->lines->data;
308                 tokens = tcore_at_tok_new(line);
309                 if (g_slist_length(tokens) < 1) {
310                         err("invalid response message");
311                         tcore_at_tok_free(tokens);
312                         goto END;
313                 }
314
315                 apdu_data = (char *) g_slist_nth_data(tokens, 1);
316                 apdu_resp.apdu_resp_len = strlen(apdu_data);
317                 if (apdu_resp.apdu_resp_len > TEL_SAP_APDU_RESP_LEN_MAX) {
318                         err(" invalid apdu data length");
319                         tcore_at_tok_free(tokens);
320                         goto END;
321                 }
322                 memcpy(apdu_resp.apdu_resp, apdu_data, apdu_resp.apdu_resp_len);
323
324                 sap_status = atoi(g_slist_nth_data(tokens, 0));
325                 if (sap_status > 4)
326                 /* In this case modem does not provide sap_status 5 ('Card already powered ON'),
327                    instead it will provide status 5 ('Data not available') and 6 ('Not Supported'),
328                    So to align 'sap_status' value with __map_sap_status_to_result(), it is increased by 1.
329                 */
330                         result = __map_sap_status_to_result(sap_status + 1);
331                 else
332                         result = __map_sap_status_to_result(sap_status);
333
334                 tcore_at_tok_free(tokens);
335         } else {
336                 err("RESPONSE NOK");
337                 result = __imc_sap_convert_cme_error_tel_sap_result(at_resp);
338         }
339
340 END:
341         dbg("Request to transfer apdu : [%s]",
342                 (result == TEL_SAP_RESULT_SUCCESS ? "SUCCESS" : "FAIL"));
343
344         /* Invoke callback */
345         if (resp_cb_data->cb)
346                 resp_cb_data->cb(co, (gint)result, &apdu_resp, resp_cb_data->cb_data);
347
348         /* Free callback data */
349         imc_destroy_resp_cb_data(resp_cb_data);
350 }
351
352 static void on_response_imc_sap_req_power_operation(TcorePending *p,
353         guint data_len, const void *data, void *user_data)
354 {
355         const TcoreAtResponse *at_resp = data;
356         CoreObject *co = tcore_pending_ref_core_object(p);
357         ImcRespCbData *resp_cb_data = user_data;
358         TelSapResult result = TEL_SAP_RESULT_FAILURE_NO_REASON;
359
360         dbg("entry");
361
362         if (at_resp && at_resp->success) {
363                 const gchar *line;
364                 GSList *tokens = NULL;
365
366                 dbg("RESPONSE OK");
367                 if (at_resp->lines == NULL) {
368                         err("invalid response recieved");
369                         goto END;
370                 }
371
372                 line = (const char*)at_resp->lines->data;
373                 tokens = tcore_at_tok_new(line);
374                 if (g_slist_length(tokens) < 1) {
375                         err("invalid response message");
376                         tcore_at_tok_free(tokens);
377                         goto END;
378                 }
379                 result = __map_sap_status_to_result(atoi(g_slist_nth_data(tokens, 0)));
380                 tcore_at_tok_free(tokens);
381         } else {
382                 err("RESPONSE NOK");
383                 result = __imc_sap_convert_cme_error_tel_sap_result(at_resp);
384         }
385
386 END:
387         dbg("Request to sap power operation : [%s]",
388                 (result == TEL_SAP_RESULT_SUCCESS ? "SUCCESS" : "FAIL"));
389
390         /* Invoke callback */
391         if (resp_cb_data->cb)
392                 resp_cb_data->cb(co, (gint)result, NULL, resp_cb_data->cb_data);
393
394         /* Free callback data */
395         imc_destroy_resp_cb_data(resp_cb_data);
396 }
397
398 static void on_response_imc_sap_get_cardreader_status(TcorePending *p,
399         guint data_len, const void *data, void *user_data)
400 {
401         const TcoreAtResponse *at_resp = data;
402         CoreObject *co = tcore_pending_ref_core_object(p);
403         ImcRespCbData *resp_cb_data = user_data;
404         TelSapResult result = TEL_SAP_RESULT_FAILURE_NO_REASON;
405         TelSapCardStatus card_status = TEL_SAP_CARD_STATUS_UNKNOWN;
406         dbg("entry");
407
408         if (at_resp && at_resp->success) {
409                 const gchar *line;
410                 GSList *tokens = NULL;
411                 unsigned char card_reader_status;
412                 int count;
413
414                 dbg("RESPONSE OK");
415                 if (at_resp->lines == NULL) {
416                         err("invalid response recieved");
417                         goto END;
418                 }
419
420                 line = (const char*)at_resp->lines->data;
421                 tokens = tcore_at_tok_new(line);
422                 if (g_slist_length(tokens) < 1) {
423                         err("invalid response message");
424                         tcore_at_tok_free(tokens);
425                         goto END;
426                 }
427                 result = __map_sap_status_to_result(atoi(g_slist_nth_data(tokens, 0)));
428
429                 card_reader_status = (unsigned char)atoi(g_slist_nth_data(tokens, 1));
430                 card_reader_status = card_reader_status >> 3;
431                 for (count = 8; count > 3; count--) { //check bit 8 to 3
432                         /*TODO - Need to map card reader status to TelSapCardStatus.
433                         if ((card_reader_status & 0x80) == TRUE) { //Check most significant bit
434                                 //card_status =  TEL_SAP_CARD_STATUS_UNKNOWN;
435                                 break;
436                         }
437                         */
438                         card_reader_status = card_reader_status << 1; //left shift by 1
439                 }
440                 tcore_at_tok_free(tokens);
441         } else {
442                 err("RESPONSE NOK");
443                 result = __imc_sap_convert_cme_error_tel_sap_result(at_resp);
444         }
445
446 END:
447         dbg("Request to get card reader status : [%s]",
448                 (result == TEL_SAP_RESULT_SUCCESS ? "SUCCESS" : "FAIL"));
449
450         /* Invoke callback */
451         if (resp_cb_data->cb)
452                 resp_cb_data->cb(co, (gint)result, &card_status, resp_cb_data->cb_data);
453
454         /* Free callback data */
455         imc_destroy_resp_cb_data(resp_cb_data);
456 }
457
458 /* Sap operations */
459
460 /*
461  * Operation - switch the modem to the  BT SAP server mode.
462  *
463  * Request -
464  * AT-Command: AT+ XBCON = <op_mode>, <change_mode>, <reject_mode>
465  * where,
466  * <op_mode>
467  * 0 - BT SAP Server modes
468  * 1 - BT SAP Client mode (Client mode is currently not supported)
469  * <change_mode>
470  * 0 - gracefully, or Time out
471  * 1 - immediately
472  * <reject_mode>
473  * 0 - Reject is not allowed.
474  * 1 - Reject is allowed.
475  * Response -
476  * Success: (No Result)
477  *      OK
478  * Failure:
479  *      +CME ERROR: <error>
480  */
481 static TelReturn imc_sap_req_connect(CoreObject *co, unsigned int max_msg_size,
482         TcoreObjectResponseCallback cb, void *cb_data)
483 {
484         ImcRespCbData *resp_cb_data;
485         TelReturn ret;
486
487         /* Response callback data */
488         resp_cb_data = imc_create_resp_cb_data(cb, cb_data,
489                                 &max_msg_size, sizeof(unsigned int));
490
491         /* Send Request to modem */
492         ret = tcore_at_prepare_and_send_request(co,
493                 "AT+XBCON=0,0,0", NULL,
494                 TCORE_AT_COMMAND_TYPE_NO_RESULT,
495                 NULL,
496                 on_response_imc_sap_req_connect, resp_cb_data,
497                 on_send_imc_request, NULL);
498         IMC_CHECK_REQUEST_RET(ret, resp_cb_data, "imc_sap_req_connect");
499
500         return ret;
501 }
502
503 /*
504  * Operation - disconnects BT SAP.
505  *
506  * Request -
507  * AT-Command: AT+ XBDISC
508  *
509  * Response -
510  * Success: (No Result)
511  *      OK
512  * Failure:
513  *      +CME ERROR: <error>
514  */
515 static TelReturn imc_sap_req_disconnect(CoreObject *co, TcoreObjectResponseCallback cb,
516         void *cb_data)
517 {
518         ImcRespCbData *resp_cb_data;
519         TelReturn ret;
520
521         /* Response callback data */
522         resp_cb_data = imc_create_resp_cb_data(cb, cb_data,
523                                 NULL, 0);
524
525         /* Send Request to modem */
526         ret = tcore_at_prepare_and_send_request(co,
527                 "AT+XBDISC", NULL,
528                 TCORE_AT_COMMAND_TYPE_NO_RESULT,
529                 NULL,
530                 on_response_imc_sap_req_disconnect, resp_cb_data,
531                 on_send_imc_request, NULL);
532         IMC_CHECK_REQUEST_RET(ret, resp_cb_data, "imc_sap_req_disconnect");
533
534         return ret;
535 }
536
537 /*
538  * Operation - In BT SAP server mode, request the ATR from the stack to the Application.
539  *
540  * Request -
541  * AT-Command: AT+ XBATR
542  *
543  * Response -
544  * Success: +XBATR: <status>, <data_ATR>
545  * OK
546  * where
547  * <status>
548  * 0 OK, request processed correctly
549  * 1 No Reason defined
550  * 2 Card not accessible
551  * 3 Card (already) powered off
552  * 4 Card Removed
553  * 6 Data Not available
554  * 7 Not Supported
555  * <data_ATR>
556  * Hex Data (an array of bytes)
557  *
558  * Failure:
559  *      +CME ERROR: <error>
560  */
561 static TelReturn imc_sap_get_atr(CoreObject *co, TcoreObjectResponseCallback cb,
562         void *cb_data)
563 {
564         ImcRespCbData *resp_cb_data;
565         TelReturn ret;
566
567         /* Response callback data */
568         resp_cb_data = imc_create_resp_cb_data(cb, cb_data,
569                                 NULL, 0);
570
571         /* Send Request to modem */
572         ret = tcore_at_prepare_and_send_request(co,
573                 "AT+XBATR", "+XBATR:",
574                 TCORE_AT_COMMAND_TYPE_SINGLELINE,
575                 NULL,
576                 on_response_imc_sap_get_atr, resp_cb_data,
577                 on_send_imc_request, NULL);
578         IMC_CHECK_REQUEST_RET(ret, resp_cb_data, "imc_sap_get_atr");
579
580         return ret;
581 }
582
583 /*
584  * Operation - BT SAP server mode, Forward command APDU from application to SIM.
585  *
586  * Request -
587  * AT-Command: AT+ XBAPDU = <data: command_APDU >
588  * where
589  * <data: command_APDU >
590  * Hex Data (an array of bytes). CP supports Command_APDU up to 261 bytes long.
591  *
592  * Response -
593  * Success: +XBAPDU: <status>, [<data:Response_APDU>]
594  * OK
595  * where
596  * <status>
597  * 0 OK, request processed correctly
598  * 1 No Reason defined
599  * 2 Card not accessible
600  * 3 Card (already) powered off
601  * 4 Card Removed
602  * 5 Data not available
603  * 6 Not Supported
604  * <data:Response_APDU>
605  * Hex Data (an array of bytes). CP supports Response_APDU up to 258 bytes long
606  * Failure:
607  * +CME ERROR: <error>
608  */
609 static TelReturn imc_sap_req_transfer_apdu(CoreObject *co, const TelSapApdu *apdu_data,
610         TcoreObjectResponseCallback cb, void *cb_data)
611 {
612         ImcRespCbData *resp_cb_data;
613         TelReturn ret;
614         gchar *at_cmd;
615
616         /* AT-Command */
617         at_cmd = g_strdup_printf("AT+XBAPDU=\"%s\"", apdu_data->apdu);
618
619         /* Response callback data */
620         resp_cb_data = imc_create_resp_cb_data(cb, cb_data,
621                                 NULL, 0);
622
623         /* Send Request to modem */
624         ret = tcore_at_prepare_and_send_request(co,
625                 at_cmd, "+XBAPDU:",
626                 TCORE_AT_COMMAND_TYPE_SINGLELINE,
627                 NULL,
628                 on_response_imc_sap_req_transfer_apdu, resp_cb_data,
629                 on_send_imc_request, NULL);
630         IMC_CHECK_REQUEST_RET(ret, resp_cb_data, "imc_sap_req_transfer_apdu");
631
632         g_free(at_cmd);
633         return ret;
634 }
635
636 static TelReturn imc_sap_req_transport_protocol(CoreObject *co, TelSimSapProtocol protocol,
637         TcoreObjectResponseCallback cb, void *cb_data)
638 {
639         err("Operation not supported");
640         return TEL_RETURN_OPERATION_NOT_SUPPORTED;
641 }
642
643 /*
644  * Operation - In BT SAP server mode, Power ON,OFF and Reset the SIM.
645  *
646  * Request -
647  * AT-Command: AT+ XBPWR =<action>
648  * where
649  * <Action>:
650  * 0 SIM Power ON
651  * 1 SIM Power OFF
652  * 2 SIM RESET
653  *
654  * Response -
655  * Success: + XBPWR: <status>
656  * OK
657  * where
658  * <status>
659  * 0 OK, Request processed correctly
660  * 1 Error no reason defined
661  * 2 Card not Accessible
662  * 3 Card already powered OFF
663  * 4 Card removed
664  * 5 Card already powered ON
665  * 6 Data Not vailable
666  * 7 Not Supported
667  * Failure:
668  * +CME ERROR: <error>
669  */
670 static TelReturn imc_sap_req_power_operation(CoreObject *co, TelSapPowerMode power_mode,
671         TcoreObjectResponseCallback cb, void *cb_data)
672 {
673         ImcRespCbData *resp_cb_data;
674         TelReturn ret = TEL_RETURN_FAILURE;
675         gchar *at_cmd;
676         int action;
677
678         if(power_mode == TEL_SAP_SIM_POWER_ON_REQ) {
679                 action = 0;
680         } else if(power_mode == TEL_SAP_SIM_POWER_OFF_REQ) {
681                 action  = 1;
682         } else if (power_mode == TEL_SAP_SIM_RESET_REQ) {
683                 action = 2;
684         } else {
685                 err("invalid power mode");
686                 return ret;
687         }
688
689         /* AT-Command */
690         at_cmd = g_strdup_printf("AT+XBPWR=%d", action);
691
692         /* Response callback data */
693         resp_cb_data = imc_create_resp_cb_data(cb, cb_data,
694                                 NULL, 0);
695
696         /* Send Request to modem */
697         ret = tcore_at_prepare_and_send_request(co,
698                 at_cmd, "+XBPWR:",
699                 TCORE_AT_COMMAND_TYPE_SINGLELINE,
700                 NULL,
701                 on_response_imc_sap_req_power_operation, resp_cb_data,
702                 on_send_imc_request, NULL);
703         IMC_CHECK_REQUEST_RET(ret, resp_cb_data, "imc_sap_req_power_operation");
704
705         g_free(at_cmd);
706         return ret;
707 }
708
709 /*
710  * Operation - In BT SAP server mode, get the Card reader Status.
711  *
712  * Request -
713  * AT-Command: AT+XBCRDSTAT
714  *
715  * Response -
716  * Success: +XBCRDSTAT: <status>, <card_reader_status>
717  * OK
718  * where
719  * <status>
720  * 0 OK, Request processed correctly
721  * 1 Error no reason defined
722  * 2 Card not Accessible
723  * 3 Card already powered OFF
724  * 4 Card removed
725  * 5 Card already powered ON
726  * 6 Data Not vailable
727  * 7 Not Supported
728  * <card_reader_status>
729  * One byte. It represents card reader identity and status.
730  * The value of this byte indicates the identity and status of a card reader.
731  * Bits 1-3 = identity of card reader x.
732  * bit 4, 0 = Card reader is not removable, 1 = Card reader is removable
733  * bit 5, 0 = Card reader is not present, 1 = Card reader is present
734  * bit 6, 0 = Card reader present is not ID-1 size, 1 = Card reader present is ID-1 size
735  * bit 7, 0 = No card present, 1 = Card is present in reader
736  * bit 8, 0 = No card powered, 1 = Card in reader is powered
737  * Failure:
738  * +CME ERROR: <error>
739  */
740 static TelReturn imc_sap_get_cardreader_status(CoreObject *co, TcoreObjectResponseCallback cb,
741         void *cb_data)
742 {
743         ImcRespCbData *resp_cb_data;
744         TelReturn ret;
745
746         /* Response callback data */
747         resp_cb_data = imc_create_resp_cb_data(cb, cb_data,
748                                 NULL, 0);
749
750         /* Send Request to modem */
751         ret = tcore_at_prepare_and_send_request(co,
752                 "AT+XBCRDSTAT", "+XBCRDSTAT:",
753                 TCORE_AT_COMMAND_TYPE_SINGLELINE,
754                 NULL,
755                 on_response_imc_sap_get_cardreader_status, resp_cb_data,
756                 on_send_imc_request, NULL);
757         IMC_CHECK_REQUEST_RET(ret, resp_cb_data, "imc_sap_get_cardreader_status");
758
759         return ret;
760 }
761
762 /* SAP Operations */
763 static TcoreSapOps imc_sap_ops = {
764         .req_connect = imc_sap_req_connect,
765         .req_disconnect = imc_sap_req_disconnect,
766         .get_atr = imc_sap_get_atr,
767         .req_transfer_apdu = imc_sap_req_transfer_apdu,
768         .req_transport_protocol = imc_sap_req_transport_protocol,
769         .req_power_operation = imc_sap_req_power_operation,
770         .get_cardreader_status = imc_sap_get_cardreader_status
771 };
772
773 gboolean imc_sap_init(TcorePlugin *p, CoreObject *co)
774 {
775         dbg("Entry");
776
777         /* Set operations */
778         tcore_sap_set_ops(co, &imc_sap_ops);
779
780         /* Add Callbacks */
781         tcore_object_add_callback(co, "+XBCSTAT", on_notification_imc_sap_status, NULL);
782
783         dbg("Exit");
784         return TRUE;
785 }
786
787 void imc_sap_exit(TcorePlugin *p, CoreObject *co)
788 {
789         dbg("Exit");
790 }