diff --git a/TCardEmulator/.cproject b/TCardEmulator/.cproject
new file mode 100644
index 0000000..ec57683
--- /dev/null
+++ b/TCardEmulator/.cproject
@@ -0,0 +1,455 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/TCardEmulator/.exportMap b/TCardEmulator/.exportMap
new file mode 100644
index 0000000..43e310e
--- /dev/null
+++ b/TCardEmulator/.exportMap
@@ -0,0 +1,4 @@
+{
+ global: main;
+ local: *;
+};
diff --git a/TCardEmulator/.gitignore b/TCardEmulator/.gitignore
new file mode 100644
index 0000000..65fa71e
--- /dev/null
+++ b/TCardEmulator/.gitignore
@@ -0,0 +1,2 @@
+/Debug
+/SA_Report
diff --git a/TCardEmulator/.project b/TCardEmulator/.project
new file mode 100644
index 0000000..1b8a612
--- /dev/null
+++ b/TCardEmulator/.project
@@ -0,0 +1,52 @@
+
+
+ TCardEmulator
+
+
+
+
+
+ org.tizen.nativecore.apichecker.apicheckerbuilder
+
+
+
+
+ org.eclipse.cdt.managedbuilder.core.genmakebuilder
+
+
+
+
+ org.eclipse.cdt.managedbuilder.core.ScannerConfigBuilder
+ full,incremental,
+
+
+
+
+
+ org.eclipse.cdt.core.cnature
+ org.eclipse.cdt.core.ccnature
+ org.eclipse.cdt.managedbuilder.core.managedBuildNature
+ org.eclipse.cdt.managedbuilder.core.ScannerConfigNature
+ org.tizen.nativecore.apichecker.apicheckernature
+
+
+
+ 1464204018079
+
+ 26
+
+ org.eclipse.ui.ide.multiFilter
+ 1.0-projectRelativePath-matches-false-false-*/.tpk
+
+
+
+ 1464204018094
+
+ 6
+
+ org.eclipse.ui.ide.multiFilter
+ 1.0-name-matches-false-false-project_def.prop
+
+
+
+
diff --git a/TCardEmulator/.tproject b/TCardEmulator/.tproject
new file mode 100644
index 0000000..8259637
--- /dev/null
+++ b/TCardEmulator/.tproject
@@ -0,0 +1,12 @@
+
+
+
+
+ wearable-2.3.1
+
+
+
+
+
+
+
diff --git a/TCardEmulator/inc/tcardemulator.h b/TCardEmulator/inc/tcardemulator.h
new file mode 100644
index 0000000..7784530
--- /dev/null
+++ b/TCardEmulator/inc/tcardemulator.h
@@ -0,0 +1,26 @@
+#ifndef __tcardemulator_H__
+#define __tcardemulator_H__
+
+#define LOG_TAG "tcardemulator"
+
+#if !defined(PACKAGE)
+#define PACKAGE "com.vsmartcard.tcardemulator"
+#endif
+
+#include
+#include
+
+extern unsigned char *rapdu;
+extern size_t rapdu_length;
+extern gboolean rapdu_received;
+
+#define HELLO_ACC_ASPID "/sample/hello"
+#define HELLO_ACC_CHANNELID 104
+
+void initialize_sap();
+gboolean find_peers();
+gboolean request_service_connection(void);
+gboolean terminate_service_connection(void);
+gboolean send_data(void *message, unsigned int message_len);
+
+#endif /* __tcardemulator_H__ */
diff --git a/TCardEmulator/res/accessoryservices.xml b/TCardEmulator/res/accessoryservices.xml
new file mode 100644
index 0000000..e73a26d
--- /dev/null
+++ b/TCardEmulator/res/accessoryservices.xml
@@ -0,0 +1,15 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/TCardEmulator/shared/res/ic_launcher.png b/TCardEmulator/shared/res/ic_launcher.png
new file mode 100644
index 0000000..b02b6cf
Binary files /dev/null and b/TCardEmulator/shared/res/ic_launcher.png differ
diff --git a/TCardEmulator/shared/res/tcardemulator.png b/TCardEmulator/shared/res/tcardemulator.png
new file mode 100644
index 0000000..9765b1b
Binary files /dev/null and b/TCardEmulator/shared/res/tcardemulator.png differ
diff --git a/TCardEmulator/shared/res/wallet.xml b/TCardEmulator/shared/res/wallet.xml
new file mode 100644
index 0000000..e895b95
--- /dev/null
+++ b/TCardEmulator/shared/res/wallet.xml
@@ -0,0 +1,23 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/TCardEmulator/src/sap.c b/TCardEmulator/src/sap.c
new file mode 100644
index 0000000..f7ef2fb
--- /dev/null
+++ b/TCardEmulator/src/sap.c
@@ -0,0 +1,370 @@
+#include "tcardemulator.h"
+#include
+#include
+#include
+
+#define HELLO_ACCESSORY_PROFILE_ID "/sample/hello"
+#define HELLO_ACCESSORY_CHANNELID 104
+
+struct priv {
+ sap_agent_h agent;
+ sap_socket_h socket;
+ sap_peer_agent_h peer_agent;
+};
+
+static gboolean agent_created = FALSE;
+
+static struct priv priv_data = { 0 };
+
+void on_peer_agent_updated(sap_peer_agent_h peer_agent,
+ sap_peer_agent_status_e peer_status,
+ sap_peer_agent_found_result_e result,
+ void *user_data)
+{
+ switch (result) {
+ case SAP_PEER_AGENT_FOUND_RESULT_DEVICE_NOT_CONNECTED:
+ dlog_print(DLOG_INFO, LOG_TAG, "device is not connected");
+ break;
+
+ case SAP_PEER_AGENT_FOUND_RESULT_FOUND:
+ if (peer_status == SAP_PEER_AGENT_STATUS_AVAILABLE) {
+ priv_data.peer_agent = peer_agent;
+ dlog_print(DLOG_INFO, LOG_TAG, "Find Peer Success!!");
+ request_service_connection();
+ } else {
+ dlog_print(DLOG_INFO, LOG_TAG, "peer agent removed");
+ sap_peer_agent_destroy(peer_agent);
+ }
+ break;
+
+ case SAP_PEER_AGENT_FOUND_RESULT_SERVICE_NOT_FOUND:
+ dlog_print(DLOG_INFO, LOG_TAG, "service not found");
+ break;
+
+ case SAP_PEER_AGENT_FOUND_RESULT_TIMEDOUT:
+ dlog_print(DLOG_INFO, LOG_TAG, "peer agent find timed out");
+ break;
+
+ case SAP_PEER_AGENT_FOUND_RESULT_INTERNAL_ERROR:
+ dlog_print(DLOG_INFO, LOG_TAG, "peer agent find search failed");
+ break;
+ }
+}
+
+
+static void on_service_connection_terminated(sap_peer_agent_h peer_agent,
+ sap_socket_h socket,
+ sap_service_connection_result_e result,
+ void *user_data)
+{
+ switch (result) {
+ case SAP_CONNECTION_TERMINATED_REASON_PEER_DISCONNECTED:
+ dlog_print(DLOG_INFO, LOG_TAG, "disconnected because peer lost");
+ break;
+
+ case SAP_CONNECTION_TERMINATED_REASON_DEVICE_DETACHED:
+ dlog_print(DLOG_INFO, LOG_TAG, "disconnected because device is detached");
+ break;
+
+ default:
+ // fall through
+ case SAP_CONNECTION_TERMINATED_REASON_UNKNOWN:
+ dlog_print(DLOG_INFO, LOG_TAG, "disconnected because of unknown reason");
+ break;
+ }
+
+ sap_socket_destroy(priv_data.socket);
+ priv_data.socket = NULL;
+}
+
+
+static void on_data_recieved(sap_socket_h socket,
+ unsigned short int channel_id,
+ unsigned int payload_length,
+ void *buffer,
+ void *user_data)
+{
+ dlog_print(DLOG_INFO, LOG_TAG, "received data: %p, len:%d", buffer, payload_length);
+ unsigned char *p = realloc(rapdu, payload_length);
+ if (p) {
+ rapdu = p;
+ rapdu_length = payload_length;
+ } else {
+ dlog_print(DLOG_ERROR, LOG_TAG, "not enough for storing data");
+ if (rapdu && rapdu_length >= 2) {
+ dlog_print(DLOG_ERROR, LOG_TAG,
+ "not enough memory, returning 0x6D00 as R-APDU");
+ rapdu[0] = 0x6D;
+ rapdu[1] = 0x00;
+ rapdu_length = 2;
+ } else {
+ dlog_print(DLOG_ERROR, LOG_TAG,
+ "not enough memory, setting R-APDU to nothing");
+ rapdu_length = 0;
+ }
+ }
+
+ rapdu_received = TRUE;
+}
+
+
+static void on_service_connection_created(sap_peer_agent_h peer_agent,
+ sap_socket_h socket,
+ sap_service_connection_result_e result,
+ void *user_data)
+{
+ switch (result) {
+ case SAP_CONNECTION_SUCCESS:
+ dlog_print(DLOG_INFO, LOG_TAG, "peer agent connection is successful, pa :%u", peer_agent);
+ sap_peer_agent_set_service_connection_terminated_cb(priv_data.peer_agent,
+ on_service_connection_terminated,
+ NULL);
+
+ sap_socket_set_data_received_cb(socket, on_data_recieved, peer_agent);
+ priv_data.socket = socket;
+ break;
+
+ case SAP_CONNECTION_ALREADY_EXIST:
+ dlog_print(DLOG_INFO, LOG_TAG, "connection is already exist");
+ priv_data.socket = socket;
+ break;
+
+ case SAP_CONNECTION_FAILURE_DEVICE_UNREACHABLE:
+ dlog_print(DLOG_INFO, LOG_TAG, "device is not unreachable");
+ break;
+
+ case SAP_CONNECTION_FAILURE_INVALID_PEERAGENT:
+ dlog_print(DLOG_INFO, LOG_TAG, "invalid peer agent");
+ break;
+
+ case SAP_CONNECTION_FAILURE_NETWORK:
+ dlog_print(DLOG_INFO, LOG_TAG, "network failure");
+ break;
+
+ case SAP_CONNECTION_FAILURE_PEERAGENT_NO_RESPONSE:
+ dlog_print(DLOG_INFO, LOG_TAG, "peer agent is no response");
+ break;
+
+ case SAP_CONNECTION_FAILURE_PEERAGENT_REJECTED:
+ dlog_print(DLOG_INFO, LOG_TAG, "peer agent is rejected");
+ break;
+
+ case SAP_CONNECTION_FAILURE_UNKNOWN:
+ dlog_print(DLOG_INFO, LOG_TAG, "unknown error");
+ break;
+ }
+}
+
+static gboolean _create_service_connection(gpointer user_data)
+{
+ struct priv *priv = NULL;
+ sap_result_e result = SAP_RESULT_FAILURE;
+
+ priv = (struct priv *)user_data;
+ result = sap_agent_request_service_connection(priv->agent,
+ priv->peer_agent,
+ on_service_connection_created,
+ NULL);
+
+ if (result == SAP_RESULT_SUCCESS) {
+ dlog_print(DLOG_DEBUG, LOG_TAG, "req service conn call succeeded");
+ } else {
+ dlog_print(DLOG_ERROR, LOG_TAG, "req service conn call is failed (%d)", result);
+ }
+
+ return FALSE;
+}
+
+gboolean request_service_connection(void)
+{
+ g_idle_add(_create_service_connection, &priv_data);
+
+ dlog_print(DLOG_DEBUG, LOG_TAG, "request_service_connection call over");
+ return TRUE;
+}
+
+static gboolean _terminate_service_connection(gpointer user_data)
+{
+ struct priv *priv = NULL;
+ sap_result_e result = SAP_RESULT_FAILURE;
+
+ priv = (struct priv *)user_data;
+
+ if (priv->socket)
+ result = sap_peer_agent_terminate_service_connection(priv->peer_agent);
+ else {
+ return FALSE;
+ }
+
+ if (result == SAP_RESULT_SUCCESS) {
+ dlog_print(DLOG_DEBUG, LOG_TAG, "req service conn call succeeded");
+ } else {
+ dlog_print(DLOG_ERROR, LOG_TAG, "req service conn call is failed (%d)", result);
+ }
+
+ return FALSE;
+}
+
+gboolean terminate_service_connection(void)
+{
+ g_idle_add(_terminate_service_connection, &priv_data);
+
+ return TRUE;
+}
+
+static gboolean _find_peer_agent(gpointer user_data)
+{
+ struct priv *priv = NULL;
+ sap_result_e result = SAP_RESULT_FAILURE;
+
+ priv = (struct priv *)user_data;
+
+ result = sap_agent_find_peer_agent(priv->agent, on_peer_agent_updated, NULL);
+
+ if (result == SAP_RESULT_SUCCESS) {
+ dlog_print(DLOG_DEBUG, LOG_TAG, "find peer call succeeded");
+ } else {
+ dlog_print(DLOG_ERROR, LOG_TAG, "find peer call failed (%d)", result);
+ }
+
+ return FALSE;
+}
+
+gboolean find_peers()
+{
+ g_idle_add(_find_peer_agent, &priv_data);
+ dlog_print(DLOG_DEBUG, LOG_TAG, "find peer called");
+ return TRUE;
+}
+
+gboolean send_data(void *message, unsigned int message_len)
+{
+ int result;
+ if (priv_data.socket) {
+ result = sap_socket_send_data(priv_data.socket,
+ HELLO_ACCESSORY_CHANNELID, message_len, message);
+ } else {
+ return FALSE;
+ }
+ return TRUE;
+}
+
+static void on_agent_initialized(sap_agent_h agent,
+ sap_agent_initialized_result_e result,
+ void *user_data)
+{
+ switch (result) {
+ case SAP_AGENT_INITIALIZED_RESULT_SUCCESS:
+ dlog_print(DLOG_INFO, LOG_TAG, "agent is initialized");
+
+ priv_data.agent = agent;
+ agent_created = TRUE;
+ break;
+
+ case SAP_AGENT_INITIALIZED_RESULT_DUPLICATED:
+ dlog_print(DLOG_INFO, LOG_TAG, "duplicate registration");
+ break;
+
+ case SAP_AGENT_INITIALIZED_RESULT_INVALID_ARGUMENTS:
+ dlog_print(DLOG_INFO, LOG_TAG, "invalid arguments");
+ break;
+
+ case SAP_AGENT_INITIALIZED_RESULT_INTERNAL_ERROR:
+ dlog_print(DLOG_INFO, LOG_TAG, "internal sap error");
+ break;
+
+ default:
+ dlog_print(DLOG_INFO, LOG_TAG, "unknown status (%d)", result);
+ break;
+ }
+}
+
+static void on_device_status_changed(sap_device_status_e status, sap_transport_type_e transport_type,
+ void *user_data)
+{
+ switch (transport_type) {
+ case SAP_TRANSPORT_TYPE_BT:
+ dlog_print(DLOG_INFO, LOG_TAG, "connectivity type(%d): bt", transport_type);
+ break;
+
+ case SAP_TRANSPORT_TYPE_BLE:
+ dlog_print(DLOG_INFO, LOG_TAG, "connectivity type(%d): ble", transport_type);
+ break;
+
+ case SAP_TRANSPORT_TYPE_TCP:
+ dlog_print(DLOG_INFO, LOG_TAG, "connectivity type(%d): tcp/ip", transport_type);
+ break;
+
+ case SAP_TRANSPORT_TYPE_USB:
+ dlog_print(DLOG_INFO, LOG_TAG, "connectivity type(%d): usb", transport_type);
+ break;
+
+ case SAP_TRANSPORT_TYPE_MOBILE:
+ dlog_print(DLOG_INFO, LOG_TAG, "connectivity type(%d): mobile", transport_type);
+ break;
+
+ default:
+ dlog_print(DLOG_INFO, LOG_TAG, "unknown connectivity type (%d)", transport_type);
+ break;
+ }
+
+ switch (status) {
+ case SAP_DEVICE_STATUS_DETACHED:
+
+ if (priv_data.peer_agent) {
+ sap_socket_destroy(priv_data.socket);
+ priv_data.socket = NULL;
+ sap_peer_agent_destroy(priv_data.peer_agent);
+ priv_data.peer_agent = NULL;
+ }
+ break;
+
+ case SAP_DEVICE_STATUS_ATTACHED:
+ if (agent_created) {
+ g_idle_add(_find_peer_agent, &priv_data);
+ }
+ break;
+
+ default:
+ dlog_print(DLOG_INFO, LOG_TAG, "unknown status (%d)", status);
+ break;
+ }
+}
+
+gboolean agent_initialize()
+{
+ int result = 0, i = 1;
+ gboolean agent_initialized = TRUE;
+
+ do {
+ if (i > 100) {
+ agent_initialized = FALSE;
+ break;
+ }
+ result = sap_agent_initialize(priv_data.agent,
+ HELLO_ACCESSORY_PROFILE_ID, SAP_AGENT_ROLE_CONSUMER,
+ on_agent_initialized, NULL);
+ dlog_print(DLOG_DEBUG, LOG_TAG, "sap_agent_initialize >>> %d", result);
+ i++;
+ } while (result != SAP_RESULT_SUCCESS);
+
+ return agent_initialized;
+}
+
+void initialize_sap()
+{
+ sap_agent_h agent = NULL;
+
+ sap_agent_create(&agent);
+
+ if (agent == NULL)
+ dlog_print(DLOG_ERROR, LOG_TAG, "ERROR in creating agent");
+ else
+ dlog_print(DLOG_INFO, LOG_TAG, "SUCCESSFULLY create sap agent");
+
+ priv_data.agent = agent;
+
+ sap_set_device_status_changed_cb(on_device_status_changed, NULL);
+
+ agent_initialize();
+}
diff --git a/TCardEmulator/src/tcardemulator.c b/TCardEmulator/src/tcardemulator.c
new file mode 100644
index 0000000..cf7dc47
--- /dev/null
+++ b/TCardEmulator/src/tcardemulator.c
@@ -0,0 +1,166 @@
+#include "tcardemulator.h"
+#include
+#include
+#include
+#include
+#include
+
+unsigned char *rapdu = NULL;
+size_t rapdu_length = 0;
+gboolean rapdu_received = FALSE;
+
+ static void
+hce_event_cb(nfc_se_h handle, nfc_hce_event_type_e event,
+ unsigned char *apdu, unsigned int apdu_len, void *user_data)
+{
+ switch (event) {
+ case NFC_HCE_EVENT_DEACTIVATED:
+ // Do something when NFC_HCE_EVENT_DEACTIVATED event arrives
+ // When the event arrives, apdu and apdu len is NULL and 0
+ terminate_service_connection();
+ break;
+
+ case NFC_HCE_EVENT_ACTIVATED:
+ // Do something when NFC_HCE_EVENT_ACTIVATED event arrives
+ // When the event arrives, apdu and apdu len is NULL and 0
+ find_peers();
+ break;
+
+ case NFC_HCE_EVENT_APDU_RECEIVED:
+ rapdu_received = FALSE;
+ send_data(apdu, apdu_len);
+ size_t count = 0;
+ while (!rapdu_received && count < 10) {
+ dlog_print(DLOG_INFO, LOG_TAG, "waiting for response");
+ usleep(100);
+ count++;
+ }
+ nfc_hce_send_apdu_response(handle, rapdu, rapdu_length);
+ rapdu_received = FALSE;
+ break;
+
+ default:
+ // Error handling
+ break;
+ }
+}
+
+ bool
+service_app_create(void *data)
+{
+ int ret = NFC_ERROR_NONE;
+ bool r = false;
+ nfc_se_card_emulation_mode_type_e ce_type;
+
+ ret = nfc_manager_initialize();
+ if (ret != NFC_ERROR_NONE) {
+ dlog_print(DLOG_ERROR, LOG_TAG, "nfc_manager_initialize failed : %d", ret);
+ goto err;
+ }
+
+ ret = nfc_se_get_card_emulation_mode(&ce_type);
+ if (ret != NFC_ERROR_NONE) {
+ dlog_print(DLOG_ERROR, LOG_TAG, "nfc_se_get_card_emulation_mode failed : %d", ret);
+ goto err;
+ }
+
+ if (ce_type == NFC_SE_CARD_EMULATION_MODE_OFF) {
+ nfc_se_enable_card_emulation();
+ if (ret != NFC_ERROR_NONE) {
+ dlog_print(DLOG_ERROR, LOG_TAG, "nfc_se_enable_card_emulation failed : %d", ret);
+ goto err;
+ }
+ }
+
+ ret = nfc_manager_set_hce_event_cb(hce_event_cb, NULL);
+ if (ret != NFC_ERROR_NONE) {
+ dlog_print(DLOG_ERROR, LOG_TAG, "nfc_manager_set_hce_event_cb failed : %d", ret);
+ goto err;
+ }
+
+ initialize_sap();
+
+ r = true;
+
+err:
+ return r;
+}
+
+ void
+service_app_terminate(void *data)
+{
+ int ret = NFC_ERROR_NONE;
+
+ nfc_manager_unset_hce_event_cb();
+
+ ret = nfc_manager_deinitialize();
+ if (ret != NFC_ERROR_NONE)
+ {
+ dlog_print(DLOG_ERROR, LOG_TAG, "nfc_manager_deinitialize failed : %d", ret);
+ }
+
+ terminate_service_connection();
+
+ free(rapdu);
+ rapdu = NULL;
+ rapdu_length = 0;
+ rapdu_received = FALSE;
+
+ return;
+}
+
+ void
+service_app_control(app_control_h app_control, void *data)
+{
+ // Todo: add your code here
+
+ return;
+}
+
+ void
+service_app_low_memory_callback(void *data)
+{
+ // Todo: add your code here
+ service_app_exit();
+
+ return;
+}
+
+ void
+service_app_low_battery_callback(void *data)
+{
+ // Todo: add your code here
+ service_app_exit();
+
+ return;
+}
+
+ int
+main(int argc, char* argv[])
+{
+ char ad[50] = {0,};
+
+ service_app_event_callback_s event_callback;
+
+ event_callback.create = service_app_create;
+ event_callback.terminate = service_app_terminate;
+ event_callback.app_control = service_app_control;
+ event_callback.low_memory = service_app_low_memory_callback;
+ event_callback.low_battery = service_app_low_battery_callback;
+
+#if 1
+ initialize_sap();
+ find_peers();
+ rapdu_received = FALSE;
+ unsigned char apdu[] = {0x00, 0xa4, 0x00, 0x00};
+ send_data(apdu, sizeof apdu);
+ size_t count = 0;
+ while (!rapdu_received && count < 10) {
+ dlog_print(DLOG_INFO, LOG_TAG, "waiting for response");
+ usleep(100);
+ count++;
+ }
+#endif
+
+ return svc_app_main(argc, argv, &event_callback, ad);
+}
diff --git a/TCardEmulator/tizen-manifest.xml b/TCardEmulator/tizen-manifest.xml
new file mode 100644
index 0000000..f099c89
--- /dev/null
+++ b/TCardEmulator/tizen-manifest.xml
@@ -0,0 +1,15 @@
+
+
+
+
+
+ ic_launcher.png
+
+
+
+
+ http://developer.samsung.com/tizen/privilege/accessoryprotocol
+ http://tizen.org/privilege/nfc.cardemulation
+
+ true
+