4 * Copyright (c) 2013 Samsung Electronics Co. Ltd. All rights reserved.
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
10 * http://www.apache.org/licenses/LICENSE-2.0
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.
28 #include <core_object.h>
37 #include "imc_common.h"
39 static TelSapResult __map_sap_status_to_result(int sap_status)
43 return TEL_SAP_RESULT_SUCCESS;
45 return TEL_SAP_RESULT_FAILURE_NO_REASON;
47 return TEL_SAP_RESULT_CARD_NOT_ACCESSIBLE;
49 return TEL_SAP_RESULT_CARD_ALREADY_POWERED_OFF;
51 return TEL_SAP_RESULT_CARD_REMOVED;
53 return TEL_SAP_RESULT_CARD_ALREADY_POWERED_ON;
55 return TEL_SAP_RESULT_DATA_NOT_AVAILABLE;
57 return TEL_SAP_RESULT_NOT_SUPPORTED;
59 return TEL_SAP_RESULT_FAILURE_NO_REASON;
64 static gboolean on_notification_imc_sap_status(CoreObject *co,
65 const void *event_info, void *user_data)
67 GSList *tokens = NULL;
69 const char *line = NULL;
70 TelSapCardStatus status;
74 lines = (GSList *) event_info;
75 if (g_slist_length(lines) != 1) {
76 err("unsolicited msg but multiple lines");
80 line = (char *)lines->data;
81 tokens = tcore_at_tok_new(line);
82 tcore_check_return_value(tokens != NULL, FALSE);
84 status = atoi(g_slist_nth_data(tokens, 0));
88 status = TEL_SAP_CARD_STATUS_UNKNOWN;
91 status = TEL_SAP_CARD_STATUS_RESET;
94 status = TEL_SAP_CARD_STATUS_NOT_ACCESSIBLE;
97 status = TEL_SAP_CARD_STATUS_REMOVED;
100 status = TEL_SAP_CARD_STATUS_INSERTED;
103 status = TEL_SAP_CARD_STATUS_RECOVERED;
106 status = TEL_SAP_CARD_STATUS_NOT_ACCESSIBLE;
110 tcore_at_tok_free(tokens);
111 tcore_object_send_notification(co,
112 TCORE_NOTIFICATION_SAP_STATUS,
113 sizeof(TelSapCardStatus), &status);
118 static void on_response_imc_sap_req_connect(TcorePending *p,
119 guint data_len, const void *data, void *user_data)
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;
128 tcore_check_return_assert(co != NULL);
129 tcore_check_return_assert(resp_cb_data != NULL);
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));
135 err("CME error[%s]", at_resp->lines->data);
136 /*TODO - need to map CME error to TelSapResult */
139 dbg("Request to sap connection : [%s]",
140 (result == TEL_SAP_RESULT_SUCCESS ? "SUCCESS" : "FAIL"));
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);
146 /* Free callback data */
147 imc_destroy_resp_cb_data(resp_cb_data);
150 static void on_response_imc_sap_req_disconnect(TcorePending *p,
151 guint data_len, const void *data, void *user_data)
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;
159 tcore_check_return_assert(co != NULL);
160 tcore_check_return_assert(resp_cb_data != NULL);
162 if (at_resp && at_resp->success) {
163 result = TEL_SAP_RESULT_SUCCESS;
165 err("CME error[%s]", at_resp->lines->data);
166 /*TODO - need to map CME error to TelSapResult */
169 dbg("Request to sap connection : [%s]",
170 (result == TEL_SAP_RESULT_SUCCESS ? "SUCCESS" : "FAIL"));
172 /* Invoke callback */
173 if (resp_cb_data->cb)
174 resp_cb_data->cb(co, (gint)result, NULL, resp_cb_data->cb_data);
176 /* Free callback data */
177 imc_destroy_resp_cb_data(resp_cb_data);
180 static void on_response_imc_sap_get_atr(TcorePending *p,
181 guint data_len, const void *data, void *user_data)
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,};
191 if (at_resp && at_resp->success) {
194 GSList *tokens = NULL;
197 if (at_resp->lines == NULL) {
198 err("invalid response recieved");
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);
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);
216 memcpy(atr_resp.atr, atr_data, atr_resp.atr_len);
218 result = __map_sap_status_to_result(atoi(g_slist_nth_data(tokens, 0)));
219 tcore_at_tok_free(tokens);
225 dbg("Request to get sap atr : [%s]",
226 (result == TEL_SAP_RESULT_SUCCESS ? "SUCCESS" : "FAIL"));
228 /* Invoke callback */
229 if (resp_cb_data->cb)
230 resp_cb_data->cb(co, (gint)result, &atr_resp, resp_cb_data->cb_data);
232 /* Free callback data */
233 imc_destroy_resp_cb_data(resp_cb_data);
236 static void on_response_imc_sap_req_transfer_apdu(TcorePending *p,
237 guint data_len, const void *data, void *user_data)
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,};
247 if (at_resp && at_resp->success) {
251 GSList *tokens = NULL;
254 if (at_resp->lines == NULL) {
255 err("invalid response recieved");
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);
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);
274 memcpy(apdu_resp.apdu_resp, apdu_data, apdu_resp.apdu_resp_len);
276 sap_status = atoi(g_slist_nth_data(tokens, 0));
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.
282 result = __map_sap_status_to_result(sap_status + 1);
284 result = __map_sap_status_to_result(sap_status);
286 tcore_at_tok_free(tokens);
292 dbg("Request to transfer apdu : [%s]",
293 (result == TEL_SAP_RESULT_SUCCESS ? "SUCCESS" : "FAIL"));
295 /* Invoke callback */
296 if (resp_cb_data->cb)
297 resp_cb_data->cb(co, (gint)result, &apdu_resp, resp_cb_data->cb_data);
299 /* Free callback data */
300 imc_destroy_resp_cb_data(resp_cb_data);
303 static void on_response_imc_sap_req_power_operation(TcorePending *p,
304 guint data_len, const void *data, void *user_data)
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;
313 if (at_resp && at_resp->success) {
315 GSList *tokens = NULL;
318 if (at_resp->lines == NULL) {
319 err("invalid response recieved");
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);
330 result = __map_sap_status_to_result(atoi(g_slist_nth_data(tokens, 0)));
331 tcore_at_tok_free(tokens);
337 dbg("Request to sap power operation : [%s]",
338 (result == TEL_SAP_RESULT_SUCCESS ? "SUCCESS" : "FAIL"));
340 /* Invoke callback */
341 if (resp_cb_data->cb)
342 resp_cb_data->cb(co, (gint)result, NULL, resp_cb_data->cb_data);
344 /* Free callback data */
345 imc_destroy_resp_cb_data(resp_cb_data);
348 static void on_response_imc_sap_get_cardreader_status(TcorePending *p,
349 guint data_len, const void *data, void *user_data)
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;
358 if (at_resp && at_resp->success) {
360 GSList *tokens = NULL;
361 unsigned char card_reader_status;
365 if (at_resp->lines == NULL) {
366 err("invalid response recieved");
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);
377 result = __map_sap_status_to_result(atoi(g_slist_nth_data(tokens, 0)));
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.
386 card_reader_status = card_reader_status << 1; //left shift by 1
388 tcore_at_tok_free(tokens);
391 result = TEL_SAP_RESULT_FAILURE_NO_REASON;
395 dbg("Request to get card reader status : [%s]",
396 (result == TEL_SAP_RESULT_SUCCESS ? "SUCCESS" : "FAIL"));
398 /* Invoke callback */
399 if (resp_cb_data->cb)
400 resp_cb_data->cb(co, (gint)result, &card_status, resp_cb_data->cb_data);
402 /* Free callback data */
403 imc_destroy_resp_cb_data(resp_cb_data);
409 * Operation - switch the modem to the BT SAP server mode.
412 * AT-Command: AT+ XBCON = <op_mode>, <change_mode>, <reject_mode>
415 * 0 - BT SAP Server modes
416 * 1 - BT SAP Client mode (Client mode is currently not supported)
418 * 0 - gracefully, or Time out
421 * 0 - Reject is not allowed.
422 * 1 - Reject is allowed.
424 * Success: (No Result)
427 * +CME ERROR: <error>
429 static TelReturn imc_sap_req_connect(CoreObject *co, unsigned int max_msg_size,
430 TcoreObjectResponseCallback cb, void *cb_data)
432 ImcRespCbData *resp_cb_data;
435 /* Response callback data */
436 resp_cb_data = imc_create_resp_cb_data(cb, cb_data,
437 &max_msg_size, sizeof(unsigned int));
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,
445 on_response_imc_sap_req_connect, resp_cb_data,
446 on_send_imc_request, NULL,
449 IMC_CHECK_REQUEST_RET(ret, resp_cb_data, "imc_sap_req_connect");
454 * Operation - disconnects BT SAP.
457 * AT-Command: AT+ XBDISC
460 * Success: (No Result)
463 * +CME ERROR: <error>
465 static TelReturn imc_sap_req_disconnect(CoreObject *co, TcoreObjectResponseCallback cb,
468 ImcRespCbData *resp_cb_data;
471 /* Response callback data */
472 resp_cb_data = imc_create_resp_cb_data(cb, cb_data,
475 /* Send Request to modem */
476 ret = tcore_at_prepare_and_send_request(co,
478 TCORE_AT_COMMAND_TYPE_NO_RESULT,
479 TCORE_PENDING_PRIORITY_DEFAULT,
481 on_response_imc_sap_req_disconnect, resp_cb_data,
482 on_send_imc_request, NULL,
485 IMC_CHECK_REQUEST_RET(ret, resp_cb_data, "imc_sap_req_disconnect");
490 * Operation - In BT SAP server mode, request the ATR from the stack to the Application.
493 * AT-Command: AT+ XBATR
496 * Success: +XBATR: <status>, <data_ATR>
500 * 0 OK, request processed correctly
501 * 1 No Reason defined
502 * 2 Card not accessible
503 * 3 Card (already) powered off
505 * 6 Data Not available
508 * Hex Data (an array of bytes)
511 * +CME ERROR: <error>
513 static TelReturn imc_sap_get_atr(CoreObject *co, TcoreObjectResponseCallback cb,
516 ImcRespCbData *resp_cb_data;
519 /* Response callback data */
520 resp_cb_data = imc_create_resp_cb_data(cb, cb_data,
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,
529 on_response_imc_sap_get_atr, resp_cb_data,
530 on_send_imc_request, NULL,
533 IMC_CHECK_REQUEST_RET(ret, resp_cb_data, "imc_sap_get_atr");
538 * Operation - BT SAP server mode, Forward command APDU from application to SIM.
541 * AT-Command: AT+ XBAPDU = <data: command_APDU >
543 * <data: command_APDU >
544 * Hex Data (an array of bytes). CP supports Command_APDU up to 261 bytes long.
547 * Success: +XBAPDU: <status>, [<data:Response_APDU>]
551 * 0 OK, request processed correctly
552 * 1 No Reason defined
553 * 2 Card not accessible
554 * 3 Card (already) powered off
556 * 5 Data not available
558 * <data:Response_APDU>
559 * Hex Data (an array of bytes). CP supports Response_APDU up to 258 bytes long
561 * +CME ERROR: <error>
563 static TelReturn imc_sap_req_transfer_apdu(CoreObject *co, const TelSapApdu *apdu_data,
564 TcoreObjectResponseCallback cb, void *cb_data)
566 ImcRespCbData *resp_cb_data;
571 at_cmd = g_strdup_printf("AT+XBAPDU=\"%s\"", apdu_data->apdu);
573 /* Response callback data */
574 resp_cb_data = imc_create_resp_cb_data(cb, cb_data,
577 /* Send Request to modem */
578 ret = tcore_at_prepare_and_send_request(co,
580 TCORE_AT_COMMAND_TYPE_SINGLELINE,
581 TCORE_PENDING_PRIORITY_DEFAULT,
583 on_response_imc_sap_req_transfer_apdu, resp_cb_data,
584 on_send_imc_request, NULL,
587 IMC_CHECK_REQUEST_RET(ret, resp_cb_data, "imc_sap_req_transfer_apdu");
592 static TelReturn imc_sap_req_transport_protocol(CoreObject *co, TelSimSapProtocol protocol,
593 TcoreObjectResponseCallback cb, void *cb_data)
595 err("Operation not supported");
596 return TEL_RETURN_OPERATION_NOT_SUPPORTED;
600 * Operation - In BT SAP server mode, Power ON,OFF and Reset the SIM.
603 * AT-Command: AT+ XBPWR =<action>
611 * Success: + XBPWR: <status>
615 * 0 OK, Request processed correctly
616 * 1 Error no reason defined
617 * 2 Card not Accessible
618 * 3 Card already powered OFF
620 * 5 Card already powered ON
621 * 6 Data Not vailable
624 * +CME ERROR: <error>
626 static TelReturn imc_sap_req_power_operation(CoreObject *co, TelSapPowerMode power_mode,
627 TcoreObjectResponseCallback cb, void *cb_data)
629 ImcRespCbData *resp_cb_data;
630 TelReturn ret = TEL_RETURN_FAILURE;
634 if(power_mode == TEL_SAP_SIM_POWER_ON_REQ) {
636 } else if(power_mode == TEL_SAP_SIM_POWER_OFF_REQ) {
638 } else if (power_mode == TEL_SAP_SIM_RESET_REQ) {
641 err("invalid power mode");
646 at_cmd = g_strdup_printf("AT+XBPWR=%d", action);
648 /* Response callback data */
649 resp_cb_data = imc_create_resp_cb_data(cb, cb_data,
652 /* Send Request to modem */
653 ret = tcore_at_prepare_and_send_request(co,
655 TCORE_AT_COMMAND_TYPE_SINGLELINE,
656 TCORE_PENDING_PRIORITY_DEFAULT,
658 on_response_imc_sap_req_power_operation, resp_cb_data,
659 on_send_imc_request, NULL,
662 IMC_CHECK_REQUEST_RET(ret, resp_cb_data, "imc_sap_req_power_operation");
668 * Operation - In BT SAP server mode, get the Card reader Status.
671 * AT-Command: AT+XBCRDSTAT
674 * Success: +XBCRDSTAT: <status>, <card_reader_status>
678 * 0 OK, Request processed correctly
679 * 1 Error no reason defined
680 * 2 Card not Accessible
681 * 3 Card already powered OFF
683 * 5 Card already powered ON
684 * 6 Data Not vailable
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
696 * +CME ERROR: <error>
698 static TelReturn imc_sap_get_cardreader_status(CoreObject *co, TcoreObjectResponseCallback cb,
701 ImcRespCbData *resp_cb_data;
704 /* Response callback data */
705 resp_cb_data = imc_create_resp_cb_data(cb, cb_data,
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,
714 on_response_imc_sap_get_cardreader_status, resp_cb_data,
715 on_send_imc_request, NULL,
718 IMC_CHECK_REQUEST_RET(ret, resp_cb_data, "imc_sap_get_cardreader_status");
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
733 gboolean imc_sap_init(TcorePlugin *p, CoreObject *co)
738 tcore_sap_set_ops(co, &imc_sap_ops);
741 tcore_object_add_callback(co, "+XBCSTAT", on_notification_imc_sap_status, NULL);
747 void imc_sap_exit(TcorePlugin *p, CoreObject *co)