diff --git a/.gitignore b/.gitignore
index 9e7e35b..add4a36 100644
--- a/.gitignore
+++ b/.gitignore
@@ -84,3 +84,13 @@ local.properties
/virtualsmartcard/lib
/virtualsmartcard/win32/BixVReader/Release
/virtualsmartcard/win32/Release
+
+ACardEmulator/build
+build/
+crash-info/
+.sign/
+.sdk_delta.info
+.rds_delta
+
+*.apk
+keystore.properties
\ No newline at end of file
diff --git a/ACardEmulator/app/.gitignore b/ACardEmulator/app/.gitignore
index 796b96d..42afabf 100644
--- a/ACardEmulator/app/.gitignore
+++ b/ACardEmulator/app/.gitignore
@@ -1 +1 @@
-/build
+/build
\ No newline at end of file
diff --git a/ACardEmulator/app/app.iml b/ACardEmulator/app/app.iml
index 37d5d64..1c17e52 100644
--- a/ACardEmulator/app/app.iml
+++ b/ACardEmulator/app/app.iml
@@ -32,12 +32,14 @@
+
+
@@ -87,12 +89,8 @@
-
-
-
-
@@ -101,39 +99,32 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/ACardEmulator/app/build.gradle b/ACardEmulator/app/build.gradle
index a1eb2b5..6f5295e 100644
--- a/ACardEmulator/app/build.gradle
+++ b/ACardEmulator/app/build.gradle
@@ -3,7 +3,6 @@ apply plugin: 'com.android.application'
android {
compileSdkVersion 23
buildToolsVersion "23.0.1"
-
defaultConfig {
applicationId "com.vsmartcard.acardemulator"
minSdkVersion 19
@@ -49,12 +48,12 @@ android.applicationVariants.all { variant ->
}
dependencies {
- compile fileTree(dir: 'libs', include: ['*.jar'])
+ compile fileTree(include: ['*.jar'], dir: 'libs')
compile 'com.android.support:appcompat-v7:23.0.1'
compile 'com.android.support:support-v4:23.0.1'
compile 'com.android.support:design:23.2.1'
-
compile 'com.journeyapps:zxing-android-embedded:3.2.0@aar'
compile 'com.google.zxing:core:3.2.1'
- compile group: 'com.madgag.spongycastle', name: 'core', version: '1.51.0.0'
+ compile 'com.madgag.spongycastle:core:1.51.0.0'
+ compile files('libs/sdk-v1.0.0.jar')
}
diff --git a/ACardEmulator/app/libs/accessory-v2.3.2.jar b/ACardEmulator/app/libs/accessory-v2.3.2.jar
new file mode 100644
index 0000000..107a3f5
Binary files /dev/null and b/ACardEmulator/app/libs/accessory-v2.3.2.jar differ
diff --git a/ACardEmulator/app/libs/sdk-v1.0.0.jar b/ACardEmulator/app/libs/sdk-v1.0.0.jar
new file mode 100644
index 0000000..070d65d
Binary files /dev/null and b/ACardEmulator/app/libs/sdk-v1.0.0.jar differ
diff --git a/ACardEmulator/app/src/main/AndroidManifest.xml b/ACardEmulator/app/src/main/AndroidManifest.xml
index a78ad84..9cd3a62 100644
--- a/ACardEmulator/app/src/main/AndroidManifest.xml
+++ b/ACardEmulator/app/src/main/AndroidManifest.xml
@@ -6,6 +6,13 @@
+
+
+
+
+
+
+
-
@@ -47,6 +54,24 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/ACardEmulator/app/src/main/java/com/vsmartcard/acardemulator/EmulatorHostApduService.java b/ACardEmulator/app/src/main/java/com/vsmartcard/acardemulator/EmulatorHostApduService.java
new file mode 100644
index 0000000..a0fe639
--- /dev/null
+++ b/ACardEmulator/app/src/main/java/com/vsmartcard/acardemulator/EmulatorHostApduService.java
@@ -0,0 +1,65 @@
+/*
+ * Copyright (C) 2015 Frank Morgner
+ *
+ * This file is part of ACardEmulator.
+ *
+ * ACardEmulator is free software: you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or (at your
+ * option) any later version.
+ *
+ * ACardEmulator is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * ACardEmulator. If not, see .
+ */
+
+package com.vsmartcard.acardemulator;
+
+import android.content.Intent;
+import android.nfc.cardemulation.HostApduService;
+import android.os.Bundle;
+import android.support.v4.content.LocalBroadcastManager;
+import android.util.Log;
+
+import com.vsmartcard.acardemulator.emulators.EmulatorSingleton;
+
+public class EmulatorHostApduService extends HostApduService {
+
+ @Override
+ public void onCreate() {
+ super.onCreate();
+ EmulatorSingleton.createEmulator(this);
+ }
+
+ @Override
+ public void onDestroy() {
+ super.onDestroy();
+ }
+
+ @Override
+ public byte[] processCommandApdu(byte[] capdu, Bundle extras) {
+ return EmulatorSingleton.process(this, capdu);
+ }
+
+ @Override
+ public void onDeactivated(int reason) {
+ Intent i = new Intent(EmulatorSingleton.TAG);
+
+ Log.d("", "End transaction");
+ switch (reason) {
+ case DEACTIVATION_LINK_LOSS:
+ i.putExtra(EmulatorSingleton.EXTRA_DESELECT, "link lost");
+ EmulatorSingleton.deactivate();
+ break;
+ case DEACTIVATION_DESELECTED:
+ EmulatorSingleton.deactivate();
+ break;
+ }
+
+ LocalBroadcastManager.getInstance(this).sendBroadcast(i);
+ }
+}
diff --git a/ACardEmulator/app/src/main/java/com/vsmartcard/acardemulator/MainActivity.java b/ACardEmulator/app/src/main/java/com/vsmartcard/acardemulator/MainActivity.java
index e151d6e..d88f470 100644
--- a/ACardEmulator/app/src/main/java/com/vsmartcard/acardemulator/MainActivity.java
+++ b/ACardEmulator/app/src/main/java/com/vsmartcard/acardemulator/MainActivity.java
@@ -41,6 +41,8 @@ import android.view.View;
import android.widget.TextView;
import android.widget.Toast;
+import com.vsmartcard.acardemulator.emulators.EmulatorSingleton;
+
public class MainActivity extends AppCompatActivity {
@@ -48,12 +50,12 @@ public class MainActivity extends AppCompatActivity {
private BroadcastReceiver bReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
- if (intent.getAction().equals(EmulatorService.TAG)) {
- String capdu = intent.getStringExtra(EmulatorService.EXTRA_CAPDU);
- String rapdu = intent.getStringExtra(EmulatorService.EXTRA_RAPDU);
- String error = intent.getStringExtra(EmulatorService.EXTRA_ERROR);
- String deselect = intent.getStringExtra(EmulatorService.EXTRA_DESELECT);
- String install = intent.getStringExtra(EmulatorService.EXTRA_INSTALL);
+ if (intent.getAction().equals(EmulatorSingleton.TAG)) {
+ String capdu = intent.getStringExtra(EmulatorSingleton.EXTRA_CAPDU);
+ String rapdu = intent.getStringExtra(EmulatorSingleton.EXTRA_RAPDU);
+ String error = intent.getStringExtra(EmulatorSingleton.EXTRA_ERROR);
+ String deselect = intent.getStringExtra(EmulatorSingleton.EXTRA_DESELECT);
+ String install = intent.getStringExtra(EmulatorSingleton.EXTRA_INSTALL);
if (install != null)
textViewVPCDStatus.append(getResources().getString(R.string.status_install) + ":" + install + "\n");
if (capdu != null)
@@ -102,7 +104,7 @@ public class MainActivity extends AppCompatActivity {
if (emulator != getString(R.string.vicc)) {
Snackbar.make(view, "Scheduled re-installation of all applets...", Snackbar.LENGTH_LONG)
.setAction("Action", null).show();
- EmulatorService.destroySimulator(getApplicationContext());
+ EmulatorSingleton.destroyEmulator();
}
}
});
@@ -116,8 +118,11 @@ public class MainActivity extends AppCompatActivity {
LocalBroadcastManager bManager = LocalBroadcastManager.getInstance(this);
IntentFilter intentFilter = new IntentFilter();
- intentFilter.addAction(EmulatorService.TAG);
+ intentFilter.addAction(EmulatorSingleton.TAG);
bManager.registerReceiver(bReceiver, intentFilter);
+
+ Intent serviceIntent = new Intent(this.getApplicationContext(), SmartcardProviderService.class);
+ startService(serviceIntent);
}
@Override
diff --git a/ACardEmulator/app/src/main/java/com/vsmartcard/acardemulator/SettingsActivity.java b/ACardEmulator/app/src/main/java/com/vsmartcard/acardemulator/SettingsActivity.java
index a108105..f7e7c94 100644
--- a/ACardEmulator/app/src/main/java/com/vsmartcard/acardemulator/SettingsActivity.java
+++ b/ACardEmulator/app/src/main/java/com/vsmartcard/acardemulator/SettingsActivity.java
@@ -200,6 +200,8 @@ public class SettingsActivity extends AppCompatPreferenceActivity {
return true;
}
});
+
+ bindPreferenceSummaryToValue(findPreference("nfc"));
}
@Override
diff --git a/ACardEmulator/app/src/main/java/com/vsmartcard/acardemulator/SmartcardProviderService.java b/ACardEmulator/app/src/main/java/com/vsmartcard/acardemulator/SmartcardProviderService.java
new file mode 100644
index 0000000..fa35f93
--- /dev/null
+++ b/ACardEmulator/app/src/main/java/com/vsmartcard/acardemulator/SmartcardProviderService.java
@@ -0,0 +1,220 @@
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd. All rights reserved.
+ * Redistribution and use in source and binary forms, with or without modification, are permitted provided that
+ * the following conditions are met:
+ *
+ * * Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation and/or
+ * other materials provided with the distribution.
+ * * Neither the name of Samsung Electronics Co., Ltd. nor the names of its contributors may be used to endorse
+ * or promote products derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+ * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+package com.vsmartcard.acardemulator;
+
+import android.content.Intent;
+import android.os.Binder;
+import android.os.Handler;
+import android.os.IBinder;
+import android.text.TextUtils;
+import android.util.Log;
+import android.widget.Toast;
+
+import com.samsung.android.sdk.SsdkUnsupportedException;
+import com.samsung.android.sdk.accessory.SA;
+import com.samsung.android.sdk.accessory.SAAgent;
+import com.samsung.android.sdk.accessory.SAAuthenticationToken;
+import com.samsung.android.sdk.accessory.SAPeerAgent;
+import com.samsung.android.sdk.accessory.SASocket;
+import com.vsmartcard.acardemulator.emulators.EmulatorSingleton;
+
+import java.io.IOException;
+
+public class SmartcardProviderService extends SAAgent {
+ private static final String TAG = "ACardEmulator";
+ private static final int ACCESSORY_CHANNEL_ID = 104;
+ private static final Class SASOCKET_CLASS = ServiceConnection.class;
+ private final IBinder mBinder = new LocalBinder();
+ private ServiceConnection mConnectionHandler = null;
+ Handler mHandler = new Handler();
+
+ public SmartcardProviderService() {
+ super(TAG, SASOCKET_CLASS);
+ }
+
+ @Override
+ public void onCreate() {
+ super.onCreate();
+ SA mAccessory = new SA();
+ try {
+ mAccessory.initialize(this);
+ EmulatorSingleton.createEmulator(this);
+ } catch (SsdkUnsupportedException e) {
+ // try to handle SsdkUnsupportedException
+ if (processUnsupportedException(e)) {
+ EmulatorSingleton.createEmulator(this);
+ return;
+ }
+ } catch (Exception e1) {
+ e1.printStackTrace();
+ /*
+ * Your application can not use Samsung Accessory SDK. Your application should work smoothly
+ * without using this SDK, or you may want to notify user and close your application gracefully
+ * (release resources, stop Service threads, close UI thread, etc.)
+ */
+ stopSelf();
+ }
+ findPeerAgents();
+ }
+
+ @Override
+ public IBinder onBind(Intent intent) {
+ return mBinder;
+ }
+
+ @Override
+ protected void onFindPeerAgentsResponse(SAPeerAgent[] peerAgents, int result) {
+ switch (result) {
+ case PEER_AGENT_FOUND:
+ break;
+ case FINDPEER_SERVICE_NOT_FOUND:
+ break;
+ case FINDPEER_DEVICE_NOT_CONNECTED:
+ break;
+ default:
+ break;
+ }
+ Log.d(TAG, "onFindPeerAgentResponse : result =" + result);
+ }
+
+ @Override
+ protected void onServiceConnectionRequested(SAPeerAgent peerAgent) {
+ if (peerAgent != null) {
+ //TODO: Check for keys and everything
+ acceptServiceConnectionRequest(peerAgent);
+ }
+ }
+
+ @Override
+ protected void onServiceConnectionResponse(SAPeerAgent peerAgent, SASocket socket, int result) {
+ if (result == SAAgent.CONNECTION_SUCCESS) {
+ if (socket != null) {
+ mConnectionHandler = (ServiceConnection) socket;
+ Toast.makeText(getBaseContext(), "connection established", Toast.LENGTH_SHORT).show();
+ }
+ } else if (result == SAAgent.CONNECTION_ALREADY_EXIST) {
+ Log.e(TAG, "onServiceConnectionResponse, CONNECTION_ALREADY_EXIST");
+ }
+ }
+
+ @Override
+ protected void onAuthenticationResponse(SAPeerAgent peerAgent, SAAuthenticationToken authToken, int error) {
+ /*
+ * The authenticatePeerAgent(peerAgent) API may not be working properly depending on the firmware
+ * version of accessory device. Please refer to another sample application for Security.
+ */
+ }
+
+ @Override
+ protected void onError(SAPeerAgent peerAgent, String errorMessage, int errorCode) {
+ super.onError(peerAgent, errorMessage, errorCode);
+ }
+
+ private boolean processUnsupportedException(SsdkUnsupportedException e) {
+ e.printStackTrace();
+ int errType = e.getType();
+ if (errType == SsdkUnsupportedException.VENDOR_NOT_SUPPORTED
+ || errType == SsdkUnsupportedException.DEVICE_NOT_SUPPORTED) {
+ /*
+ * Your application can not use Samsung Accessory SDK. You application should work smoothly
+ * without using this SDK, or you may want to notify user and close your app gracefully (release
+ * resources, stop Service threads, close UI thread, etc.)
+ */
+ stopSelf();
+ } else if (errType == SsdkUnsupportedException.LIBRARY_NOT_INSTALLED) {
+ Log.e(TAG, "You need to install Samsung Accessory SDK to use this application.");
+ } else if (errType == SsdkUnsupportedException.LIBRARY_UPDATE_IS_REQUIRED) {
+ Log.e(TAG, "You need to update Samsung Accessory SDK to use this application.");
+ } else if (errType == SsdkUnsupportedException.LIBRARY_UPDATE_IS_RECOMMENDED) {
+ Log.e(TAG, "We recommend that you update your Samsung Accessory SDK before using this application.");
+ return false;
+ }
+ return true;
+ }
+
+ public class LocalBinder extends Binder {
+ public SmartcardProviderService getService() {
+ return SmartcardProviderService.this;
+ }
+ }
+
+ public class ServiceConnection extends SASocket {
+ public ServiceConnection() {
+ super(ServiceConnection.class.getName());
+ }
+
+ @Override
+ public void onError(int channelId, String errorMessage, int errorCode) {
+ }
+
+ @Override
+ public void onReceive(int channelId, byte[] data) {
+ if (mConnectionHandler == null) {
+ return;
+ }
+ final byte[] sendResponse;
+ if (data[0] == 'd') {
+ // APDU is sent
+ byte[] newData = new byte[data.length - 1];
+ System.arraycopy(data, 1, newData, 0, data.length - 1);
+ byte[] response = EmulatorSingleton.process(getApplicationContext(), newData);
+ sendResponse = new byte[response.length + 1];
+ sendResponse[0] = 'd';
+ System.arraycopy(response, 0, sendResponse, 1, response.length);
+ } else if (data[0] == 'a') {
+ // request for aids
+ String[] aidList = EmulatorSingleton.getRegisteredAids(getApplicationContext());
+ String aidListJoined = TextUtils.join(",", aidList);
+ sendResponse = new byte[aidListJoined.length() + 1];
+ sendResponse[0] = 'a';
+ byte[] aids = aidListJoined.getBytes();
+ System.arraycopy(aids, 0, sendResponse, 1, aids.length);
+ } else {
+ Log.e(TAG, "unknown message from consumer: " + new String(data));
+ return;
+ }
+ new Thread(new Runnable() {
+ public void run() {
+ try {
+ mConnectionHandler.send(ACCESSORY_CHANNEL_ID, sendResponse);
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ }
+ }).start();
+ }
+
+ @Override
+ protected void onServiceConnectionLost(int reason) {
+ mConnectionHandler = null;
+ EmulatorSingleton.deactivate();
+ mHandler.post(new Runnable() {
+ @Override
+ public void run() {
+ Toast.makeText(getBaseContext(), "connection lost", Toast.LENGTH_SHORT).show();
+ }
+ });
+ }
+ }
+}
diff --git a/ACardEmulator/app/src/main/java/com/vsmartcard/acardemulator/EmulatorService.java b/ACardEmulator/app/src/main/java/com/vsmartcard/acardemulator/emulators/EmulatorSingleton.java
similarity index 58%
rename from ACardEmulator/app/src/main/java/com/vsmartcard/acardemulator/EmulatorService.java
rename to ACardEmulator/app/src/main/java/com/vsmartcard/acardemulator/emulators/EmulatorSingleton.java
index d462bb0..d0fcdbd 100644
--- a/ACardEmulator/app/src/main/java/com/vsmartcard/acardemulator/EmulatorService.java
+++ b/ACardEmulator/app/src/main/java/com/vsmartcard/acardemulator/emulators/EmulatorSingleton.java
@@ -17,28 +17,31 @@
* ACardEmulator. If not, see .
*/
-package com.vsmartcard.acardemulator;
+package com.vsmartcard.acardemulator.emulators;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
-import android.nfc.cardemulation.HostApduService;
-import android.os.Bundle;
-import android.os.StrictMode;
+import android.content.res.Resources;
+import android.content.res.XmlResourceParser;
+import android.nfc.NfcAdapter;
+import android.nfc.cardemulation.CardEmulation;
import android.preference.PreferenceManager;
+import android.support.annotation.XmlRes;
import android.support.v4.content.LocalBroadcastManager;
import android.util.Log;
+import com.vsmartcard.acardemulator.R;
+import com.vsmartcard.acardemulator.Util;
+
+import org.xmlpull.v1.XmlPullParser;
+import org.xmlpull.v1.XmlPullParserException;
+
import java.io.IOException;
-import java.net.InetAddress;
-import java.net.Socket;
-
-import com.vsmartcard.acardemulator.emulators.Emulator;
-import com.vsmartcard.acardemulator.emulators.JCEmulator;
-import com.vsmartcard.acardemulator.emulators.VICCEmulator;
-
-public class EmulatorService extends HostApduService {
+import java.util.ArrayList;
+import java.util.List;
+public class EmulatorSingleton {
public static final String TAG = "com.vsmartcard.acardemulator.EmulatorService";
public static final String EXTRA_CAPDU = "MSG_CAPDU";
public static final String EXTRA_RAPDU = "MSG_RAPDU";
@@ -49,22 +52,35 @@ public class EmulatorService extends HostApduService {
private static Emulator emulator = null;
private static boolean do_destroy = false;
- @Override
- public void onCreate () {
- super.onCreate();
+ private static void destroyEmulatorIfRequested(Context context) {
+ if (do_destroy) {
+ emulator.destroy();
+ emulator = null;
+ do_destroy = false;
+ Intent i = new Intent(TAG);
+ i.putExtra(EXTRA_DESELECT, "Uninstalled all applets.");
+ LocalBroadcastManager.getInstance(context).sendBroadcast(i);
+ }
+ }
+
+ public static void destroyEmulator() {
+ do_destroy = true;
+ }
+
+ public static void createEmulator(Context context) {
// force reloading applets if requested
- do_destroy();
+ destroyEmulatorIfRequested(context);
if (emulator == null) {
Log.d("", "Begin transaction");
- SharedPreferences SP = PreferenceManager.getDefaultSharedPreferences(this);
+ SharedPreferences SP = PreferenceManager.getDefaultSharedPreferences(context);
String str_emulator = SP.getString("emulator", "");
- if (str_emulator.equals(getString(R.string.vicc))) {
+ if (str_emulator.equals(context.getString(R.string.vicc))) {
emulator = new VICCEmulator(
SP.getString("hostname", VICCEmulator.DEFAULT_HOSTNAME),
Integer.parseInt(SP.getString("port", Integer.toString(VICCEmulator.DEFAULT_PORT))));
} else {
- emulator = new JCEmulator(this,
+ emulator = new JCEmulator(context,
SP.getBoolean("activate_helloworld", false),
SP.getBoolean("activate_openpgp", false),
SP.getBoolean("activate_oath", false),
@@ -74,55 +90,45 @@ public class EmulatorService extends HostApduService {
}
}
- public static void destroySimulator(Context context) {
- do_destroy = true;
- }
-
- private void do_destroy() {
- if (do_destroy) {
- emulator.destroy();
- emulator = null;
- do_destroy = false;
- Intent i = new Intent(TAG);
- i.putExtra(EXTRA_DESELECT, "Uninstalled all applets.");
- LocalBroadcastManager.getInstance(this).sendBroadcast(i);
- }
- }
-
- @Override
- public void onDestroy() {
- do_destroy();
- super.onDestroy();
- }
-
- @Override
- public byte[] processCommandApdu(byte[] capdu, Bundle extras) {
+ public static byte[] process(Context context, byte[] capdu) {
byte[] rapdu = emulator.process(capdu);
Intent i = new Intent(TAG);
i.putExtra(EXTRA_CAPDU, Util.byteArrayToHexString(capdu));
if (rapdu != null)
i.putExtra(EXTRA_RAPDU, Util.byteArrayToHexString(rapdu));
- LocalBroadcastManager.getInstance(this).sendBroadcast(i);
+ LocalBroadcastManager.getInstance(context).sendBroadcast(i);
return rapdu;
}
- @Override
- public void onDeactivated(int reason) {
- Intent i = new Intent(TAG);
+ public static String[] getRegisteredAids(Context context) {
+ List aidList = new ArrayList<>();
+ XmlResourceParser aidXmlParser = context.getResources().getXml(R.xml.aid_list);
- Log.d("", "End transaction");
- switch (reason) {
- case DEACTIVATION_LINK_LOSS:
- i.putExtra(EXTRA_DESELECT, "link lost");
- emulator.deactivate();
- break;
- case DEACTIVATION_DESELECTED:
- emulator.deactivate();
- break;
+ try {
+ while (aidXmlParser.getEventType() != XmlPullParser.END_DOCUMENT) {
+ if (aidXmlParser.getEventType() == XmlPullParser.START_TAG) {
+ if (aidXmlParser.getName().equals("aid-filter")) {
+ int aid = aidXmlParser.getAttributeResourceValue(0, -1);
+ if (aid != -1) {
+ aidList.add(context.getResources().getString(aid));
+ }
+ }
+ }
+
+ aidXmlParser.next();
+ }
+
+ aidXmlParser.close();
+ } catch (XmlPullParserException | IOException e) {
+ Log.e(TAG.substring(0, 23), "Couldn't parse aid xml list.");
}
- LocalBroadcastManager.getInstance(this).sendBroadcast(i);
+ return aidList.toArray(new String[0]);
}
-}
+
+ public static void deactivate() {
+ emulator.deactivate();
+ }
+}
\ No newline at end of file
diff --git a/ACardEmulator/app/src/main/java/com/vsmartcard/acardemulator/emulators/JCEmulator.java b/ACardEmulator/app/src/main/java/com/vsmartcard/acardemulator/emulators/JCEmulator.java
index 99470d4..1ff6967 100644
--- a/ACardEmulator/app/src/main/java/com/vsmartcard/acardemulator/emulators/JCEmulator.java
+++ b/ACardEmulator/app/src/main/java/com/vsmartcard/acardemulator/emulators/JCEmulator.java
@@ -9,7 +9,6 @@ import com.licel.jcardsim.base.SimulatorRuntime;
import com.licel.jcardsim.samples.HelloWorldApplet;
import com.licel.jcardsim.utils.AIDUtil;
import com.mysmartlogon.gidsApplet.GidsApplet;
-import com.vsmartcard.acardemulator.EmulatorService;
import com.vsmartcard.acardemulator.R;
import com.vsmartcard.acardemulator.Util;
@@ -100,11 +99,11 @@ public class JCEmulator implements Emulator {
}
}
- Intent i = new Intent(EmulatorService.TAG);
+ Intent i = new Intent(EmulatorSingleton.TAG);
if (!extra_error.isEmpty())
- i.putExtra(EmulatorService.EXTRA_ERROR, extra_error);
+ i.putExtra(EmulatorSingleton.EXTRA_ERROR, extra_error);
if (!extra_install.isEmpty())
- i.putExtra(EmulatorService.EXTRA_INSTALL, extra_install);
+ i.putExtra(EmulatorSingleton.EXTRA_INSTALL, extra_install);
LocalBroadcastManager.getInstance(context).sendBroadcast(i);
}
diff --git a/ACardEmulator/app/src/main/res/layout/activity_main.xml b/ACardEmulator/app/src/main/res/layout/activity_main.xml
index 8b0042d..cc41a10 100644
--- a/ACardEmulator/app/src/main/res/layout/activity_main.xml
+++ b/ACardEmulator/app/src/main/res/layout/activity_main.xml
@@ -4,7 +4,7 @@
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true"
- tools:context="com.vsmartcard.smartcardemulator.MainActivity">
+ tools:context="com.vsmartcard.acardemulator.MainActivity">
Builtin Java Card Simulator
Remote Virtual Smart Card
+
+
+ - @string/nfc
+ - @string/gear
+
+ Builtin NFC
+ Samsung Accessory
+
If you choose the virtual smart card (VICC) as emulator, you need to start the it on your computer with the `--reversed` flag and configure the connection parameters here accordingly.
VICC Port
VICC Hostname
diff --git a/ACardEmulator/app/src/main/res/xml/accessoryservices.xml b/ACardEmulator/app/src/main/res/xml/accessoryservices.xml
new file mode 100644
index 0000000..1a5c7cf
--- /dev/null
+++ b/ACardEmulator/app/src/main/res/xml/accessoryservices.xml
@@ -0,0 +1,51 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ ]>
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/ACardEmulator/app/src/main/res/xml/settings.xml b/ACardEmulator/app/src/main/res/xml/settings.xml
index ed95cc3..17148a2 100644
--- a/ACardEmulator/app/src/main/res/xml/settings.xml
+++ b/ACardEmulator/app/src/main/res/xml/settings.xml
@@ -81,4 +81,11 @@
+
+
\ No newline at end of file
diff --git a/ACardEmulator/build.gradle b/ACardEmulator/build.gradle
index f6e9073..b193299 100644
--- a/ACardEmulator/build.gradle
+++ b/ACardEmulator/build.gradle
@@ -5,7 +5,7 @@ buildscript {
jcenter()
}
dependencies {
- classpath 'com.android.tools.build:gradle:2.1.0'
+ classpath 'com.android.tools.build:gradle:2.2.0'
// NOTE: Do not place your application dependencies here; they belong
// in the individual module build.gradle files
diff --git a/ACardEmulator/gradle/wrapper/gradle-wrapper.properties b/ACardEmulator/gradle/wrapper/gradle-wrapper.properties
index 12caca0..e92364a 100644
--- a/ACardEmulator/gradle/wrapper/gradle-wrapper.properties
+++ b/ACardEmulator/gradle/wrapper/gradle-wrapper.properties
@@ -1,6 +1,6 @@
-#Thu May 12 09:46:58 CEST 2016
+#Tue Oct 04 22:11:09 CEST 2016
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
-distributionUrl=https\://services.gradle.org/distributions/gradle-2.10-all.zip
+distributionUrl=https\://services.gradle.org/distributions/gradle-2.14.1-all.zip
diff --git a/TCardEmulator/.cproject b/TCardEmulator/.cproject
new file mode 100644
index 0000000..b235747
--- /dev/null
+++ b/TCardEmulator/.cproject
@@ -0,0 +1,460 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
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/sap_app.h b/TCardEmulator/inc/sap_app.h
new file mode 100644
index 0000000..38e8a75
--- /dev/null
+++ b/TCardEmulator/inc/sap_app.h
@@ -0,0 +1,11 @@
+#ifndef __sap_H__
+#define __sap_H__
+
+#include
+
+void send_apdu_response(nfc_se_h handle, unsigned char *resp, unsigned int resp_len);
+void install_aids(void *buffer, unsigned int buffer_size);
+
+extern gboolean agent_connected;
+
+#endif /* __tcardemulator_H__ */
diff --git a/TCardEmulator/inc/tcardemulator.h b/TCardEmulator/inc/tcardemulator.h
new file mode 100644
index 0000000..ca74f0d
--- /dev/null
+++ b/TCardEmulator/inc/tcardemulator.h
@@ -0,0 +1,21 @@
+#ifndef __tcardemulator_H__
+#define __tcardemulator_H__
+
+#define LOG_TAG "tcardemulator"
+
+#if !defined(PACKAGE)
+#define PACKAGE "com.vsmartcard.tcardemulator"
+#endif
+
+#include
+#include
+#include
+#include
+
+void initialize_sap();
+gboolean find_peers();
+gboolean request_service_connection(void);
+gboolean terminate_service_connection(void);
+gboolean send_data(nfc_se_h nfc_handle, char* prefix, unsigned int prefix_len, 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..e2265f1
--- /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..1eb92ca
--- /dev/null
+++ b/TCardEmulator/src/sap.c
@@ -0,0 +1,372 @@
+#include "tcardemulator.h"
+#include "sap_app.h"
+#include
+#include
+#include
+#include
+#include
+#include
+
+#define ACCESSORY_PROFILE_ID "/com/vsmcartcard"
+#define ACCESSORY_CHANNELID 104
+
+typedef struct priv {
+ sap_agent_h agent;
+ sap_socket_h socket;
+ sap_peer_agent_h peer_agent;
+ nfc_se_h nfc_handle;
+} priv_s;
+
+gboolean agent_created = FALSE;
+gboolean agent_connected = FALSE;
+
+static priv_s 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, "requesting service connection");
+ 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;
+ agent_connected = FALSE;
+}
+
+
+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);
+
+ char* string_buffer = (char*) buffer;
+ if (string_buffer[0] == 'a') {
+ install_aids(buffer + sizeof(char), payload_length - 1);
+ } else if (string_buffer[0] == 'd') {
+ send_apdu_response(priv_data.nfc_handle, buffer + sizeof(char), payload_length - 1);
+ }
+}
+
+gboolean send_data(nfc_se_h nfc_handle, char* prefix, unsigned int prefix_len, void *message, unsigned int message_len) {
+ gboolean result;
+ if (nfc_handle != NULL) {
+ priv_data.nfc_handle = nfc_handle;
+ }
+ void *final_message = malloc(prefix_len + message_len);
+ memcpy(final_message, prefix, prefix_len);
+ memcpy(final_message + prefix_len * sizeof(char), message, message_len);
+ result = sap_socket_send_data(priv_data.socket,
+ ACCESSORY_CHANNELID, prefix_len + message_len, final_message);
+
+ if (result != SAP_RESULT_SUCCESS) {
+ dlog_print(DLOG_INFO, LOG_TAG, "couldn't send sap message: %d", result);
+ }
+
+ free(final_message);
+ return result;
+}
+
+gboolean request_installed_aids() {
+ return send_data(NULL, "a", 1, "", 0);
+}
+
+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;
+ agent_connected = TRUE;
+
+ request_installed_aids();
+ break;
+
+ case SAP_CONNECTION_ALREADY_EXIST:
+ dlog_print(DLOG_INFO, LOG_TAG, "connection already exists");
+ priv_data.socket = socket;
+ agent_connected = TRUE;
+ 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);
+ 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, "terminate service conn call succeeded");
+
+ priv->socket = NULL;
+ agent_connected = FALSE;
+ } else {
+ dlog_print(DLOG_ERROR, LOG_TAG, "terminate 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;
+}
+
+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;
+ agent_connected = FALSE;
+ }
+ 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,
+ 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..530092e
--- /dev/null
+++ b/TCardEmulator/src/tcardemulator.c
@@ -0,0 +1,159 @@
+#include "tcardemulator.h"
+#include "sap_app.h"
+#include
+#include
+#include
+#include
+#include
+#include
+
+typedef struct appdata {
+
+} appdata_s;
+
+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:
+ dlog_print(DLOG_DEBUG, LOG_TAG, "received NFC_HCE_EVENT_DEACTIVATED event on NFC handle %d", handle);
+ break;
+
+ case NFC_HCE_EVENT_ACTIVATED:
+ dlog_print(DLOG_DEBUG, LOG_TAG, "received NFC_HCE_EVENT_ACTIVATED event on NFC handle %d", handle);
+ if (!agent_connected) {
+ find_peers();
+ }
+ break;
+
+ case NFC_HCE_EVENT_APDU_RECEIVED:
+ dlog_print(DLOG_DEBUG, LOG_TAG, "received NFC_HCE_EVENT_APDU_RECEIVED event on NFC handle %d", handle);
+ if (agent_connected) {
+ send_data(handle, "d", 1, apdu, apdu_len);
+ } else {
+ dlog_print(DLOG_INFO, LOG_TAG, "couldn't send message on SAP channel because agent is not connected");
+ }
+ break;
+
+ default:
+ dlog_print(DLOG_DEBUG, LOG_TAG, "received unknown event on NFC handle %d", handle);
+ break;
+ }
+}
+
+void register_aid(gpointer data) {
+ int result = nfc_se_register_aid(NFC_SE_TYPE_HCE, NFC_CARD_EMULATION_CATEGORY_OTHER, data);
+ if (result != NFC_ERROR_NONE) {
+ dlog_print(DLOG_ERROR, LOG_TAG, "nfc_se_register_aid for aid %s failed: %d", data, result);
+ } else {
+ dlog_print(DLOG_DEBUG, LOG_TAG, "nfc_se_register_aid for aid %s succeeded.", data);
+ }
+}
+
+void install_aids(void *buffer, unsigned int buffer_size) {
+ gchar aid_string[buffer_size + 1];
+ g_strlcpy(aid_string, (gchar *)buffer, buffer_size + 1);
+
+ gchar **aid_buffer = g_strsplit(aid_string, ",", 0);
+ int i;
+ int aid_len = g_strv_length(aid_buffer);
+ for (i = 0; i < aid_len; i++) {
+ register_aid((gpointer)aid_buffer[i]);
+ }
+ g_strfreev(aid_buffer);
+}
+
+void send_apdu_response(nfc_se_h handle, unsigned char *resp, unsigned int resp_len) {
+ dlog_print(DLOG_DEBUG, LOG_TAG, "sending data to nfc handle: %d", handle);
+ int result = nfc_hce_send_apdu_response(handle, resp, resp_len);
+ if (result != NFC_ERROR_NONE) {
+ dlog_print(DLOG_DEBUG, LOG_TAG, "error sending data to nfc handle %d: ", handle);
+ }
+}
+
+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;
+ } else {
+ dlog_print(DLOG_DEBUG, LOG_TAG, "nfc_manager_set_hce_event_cb succeeded");
+ }
+
+ initialize_sap();
+
+ find_peers();
+
+ 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();
+
+ return;
+}
+
+void service_app_control(app_control_h app_control, void *data) {
+ return;
+}
+
+void service_app_low_memory(void *data) {
+ service_app_terminate(&data);
+
+ return;
+}
+
+void service_app_low_battery(void *data) {
+ service_app_terminate(&data);
+
+ return;
+}
+
+int main(int argc, char* argv[]) {
+ appdata_s ad = {};
+
+ 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;
+ event_callback.low_battery = service_app_low_battery;
+
+ 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
+