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