All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 0/1] Add Sim Access plugin
@ 2010-10-20  7:55 Waldemar Rymarkiewicz
  2010-10-20  7:55 ` [PATCH 1/1] Add Sim Access Plugin Waldemar Rymarkiewicz
  0 siblings, 1 reply; 4+ messages in thread
From: Waldemar Rymarkiewicz @ 2010-10-20  7:55 UTC (permalink / raw)
  To: linux-bluetooth
  Cc: Marcel Holtmann, suraj, Johan Hedberg, joakim.xj.ceder,
	arunkr.singh, Waldemar Rymarkiewicz

Hi,
Sorry, I sent on to wrong list, so agian ...

Here you are the SAP plugin modified to reflect the audio/telephony design. 
Could anyone interested in do a review and put any comments.

Regards,
/Waldek


Waldemar Rymarkiewicz (1):
  Add Sim Access Plugin

 .gitignore      |    1 +
 Makefile.am     |   25 +-
 acinclude.m4    |   14 +
 doc/sap-api.txt |   57 ++
 sap/main.c      |   54 ++
 sap/manager.c   |   94 ++++
 sap/manager.h   |   21 +
 sap/sap-dummy.c |  306 +++++++++++
 sap/sap-ste.c   | 1265 ++++++++++++++++++++++++++++++++++++++++++++++
 sap/sap.h       |  187 +++++++
 sap/server.c    | 1516 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
 sap/server.h    |   23 +
 12 files changed, 3559 insertions(+), 4 deletions(-)
 create mode 100644 doc/sap-api.txt
 create mode 100644 sap/main.c
 create mode 100644 sap/manager.c
 create mode 100644 sap/manager.h
 create mode 100644 sap/sap-dummy.c
 create mode 100644 sap/sap-ste.c
 create mode 100644 sap/sap.h
 create mode 100644 sap/server.c
 create mode 100644 sap/server.h

^ permalink raw reply	[flat|nested] 4+ messages in thread

* [PATCH 1/1] Add Sim Access Plugin
  2010-10-20  7:55 [PATCH 0/1] Add Sim Access plugin Waldemar Rymarkiewicz
@ 2010-10-20  7:55 ` Waldemar Rymarkiewicz
  2010-10-20  8:37   ` Suraj Sumangala
  0 siblings, 1 reply; 4+ messages in thread
From: Waldemar Rymarkiewicz @ 2010-10-20  7:55 UTC (permalink / raw)
  To: linux-bluetooth
  Cc: Marcel Holtmann, suraj, Johan Hedberg, joakim.xj.ceder,
	arunkr.singh, Waldemar Rymarkiewicz

Sim Access plugin implements Sim Access Profile server role
according to the Bluetooth Sim Access Profile v1.1 specification.
---
 .gitignore      |    1 +
 Makefile.am     |   25 +-
 acinclude.m4    |   14 +
 doc/sap-api.txt |   57 ++
 sap/main.c      |   54 ++
 sap/manager.c   |   94 ++++
 sap/manager.h   |   21 +
 sap/sap-dummy.c |  306 +++++++++++
 sap/sap-ste.c   | 1265 ++++++++++++++++++++++++++++++++++++++++++++++
 sap/sap.h       |  187 +++++++
 sap/server.c    | 1516 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
 sap/server.h    |   23 +
 12 files changed, 3559 insertions(+), 4 deletions(-)
 create mode 100644 doc/sap-api.txt
 create mode 100644 sap/main.c
 create mode 100644 sap/manager.c
 create mode 100644 sap/manager.h
 create mode 100644 sap/sap-dummy.c
 create mode 100644 sap/sap-ste.c
 create mode 100644 sap/sap.h
 create mode 100644 sap/server.c
 create mode 100644 sap/server.h

diff --git a/.gitignore b/.gitignore
index 07e239f..3e36a59 100644
--- a/.gitignore
+++ b/.gitignore
@@ -35,6 +35,7 @@ lib/bluetooth
 src/builtin.h
 src/bluetoothd
 audio/telephony.c
+sap/sap.c
 scripts/bluetooth.rules
 scripts/97-bluetooth.rules
 scripts/97-bluetooth-hid2hci.rules
diff --git a/Makefile.am b/Makefile.am
index 6e8fc7d..015d84e 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -142,6 +142,20 @@ audio_libtelephony_a_SOURCES = audio/telephony.h audio/telephony-dummy.c \
 				audio/telephony-maemo6.c
 endif
 
+if SAPPLUGIN
+builtin_modules += sap
+builtin_sources += sap/main.c \
+			sap/manager.h sap/manager.c \
+			sap/server.h sap/server.c \
+			sap/sap.h
+builtin_nodist += sap/sap.c
+
+noinst_LIBRARIES = sap/libsap.a
+
+sap_libsap_a_SOURCES = sap/sap.h sap/sap-dummy.c \
+				sap/sap-ste.c
+endif
+
 if INPUTPLUGIN
 builtin_modules += input
 builtin_sources += input/main.c \
@@ -263,8 +277,8 @@ EXTRA_DIST += src/genbuiltin src/bluetooth.conf \
 			input/input.conf serial/serial.conf \
 			audio/audio.conf audio/telephony-dummy.c \
 			audio/telephony-maemo5.c audio/telephony-ofono.c \
-			audio/telephony-maemo6.c
-
+			audio/telephony-maemo6.c \
+			sap/sap-dummy.c sap/sap-ste.c
 
 if ALSA
 alsadir = $(libdir)/alsa-lib
@@ -352,7 +366,7 @@ EXTRA_DIST += doc/manager-api.txt \
 		doc/service-api.txt doc/agent-api.txt doc/attribute-api.txt \
 		doc/serial-api.txt doc/network-api.txt \
 		doc/input-api.txt doc/audio-api.txt doc/control-api.txt \
-		doc/hfp-api.txt doc/assigned-numbers.txt
+		doc/hfp-api.txt doc/assigned-numbers.txt doc/sap-api.txt
 
 AM_YFLAGS = -d
 
@@ -387,6 +401,9 @@ src/builtin.h: src/genbuiltin $(builtin_sources)
 audio/telephony.c: audio/@TELEPHONY_DRIVER@
 	$(AM_V_GEN)$(LN_S) $(abs_top_srcdir)/$< $@
 
+sap/sap.c: sap/@SAP_DRIVER@
+	$(AM_V_GEN)$(LN_S) $(abs_top_srcdir)/$< $@
+
 scripts/%.rules:
 	$(AM_V_GEN)cp $(subst 97-,,$@) $@
 
@@ -397,4 +414,4 @@ lib/bluetooth/%.h: lib/%.h
 	$(AM_V_GEN)$(LN_S) $(abs_top_srcdir)/$< $@
 
 clean-local:
-	$(RM) -r lib/bluetooth
+	$(RM) -r lib/bluetooth
\ No newline at end of file
diff --git a/acinclude.m4 b/acinclude.m4
index 287f07d..093e9a6 100644
--- a/acinclude.m4
+++ b/acinclude.m4
@@ -174,6 +174,7 @@ AC_DEFUN([AC_ARG_BLUEZ], [
 	input_enable=yes
 	serial_enable=yes
 	network_enable=yes
+	sap_enable=yes
 	service_enable=yes
 	health_enable=no
 	pnat_enable=no
@@ -193,6 +194,7 @@ AC_DEFUN([AC_ARG_BLUEZ], [
 	configfiles_enable=yes
 	telephony_driver=dummy
 	maemo6_enable=no
+	sap_driver=dummy
 
 	AC_ARG_ENABLE(optimization, AC_HELP_STRING([--disable-optimization], [disable code optimization]), [
 		optimization_enable=${enableval}
@@ -210,6 +212,10 @@ AC_DEFUN([AC_ARG_BLUEZ], [
 		network_enable=${enableval}
 	])
 
+	AC_ARG_ENABLE(sap, AC_HELP_STRING([--disable-sap], [disable sap plugin]), [
+		sap_enable=${enableval}
+	])
+
 	AC_ARG_ENABLE(serial, AC_HELP_STRING([--disable-serial], [disable serial plugin]), [
 		serial_enable=${enableval}
 	])
@@ -320,6 +326,13 @@ AC_DEFUN([AC_ARG_BLUEZ], [
 		hal_enable=${enableval}
 	])
 
+	AC_ARG_WITH(sap, AC_HELP_STRING([--with-sap=DRIVER], [select SAP driver]), [
+		sap_driver=${withval}
+	])
+
+
+	AC_SUBST([SAP_DRIVER], [sap-${sap_driver}.c])
+
 	if (test "${fortify_enable}" = "yes"); then
 		CFLAGS="$CFLAGS -D_FORTIFY_SOURCE=2"
 	fi
@@ -351,6 +364,7 @@ AC_DEFUN([AC_ARG_BLUEZ], [
 	AM_CONDITIONAL(INPUTPLUGIN, test "${input_enable}" = "yes")
 	AM_CONDITIONAL(SERIALPLUGIN, test "${serial_enable}" = "yes")
 	AM_CONDITIONAL(NETWORKPLUGIN, test "${network_enable}" = "yes")
+	AM_CONDITIONAL(SAPPLUGIN, test "${sap_enable}" = "yes")
 	AM_CONDITIONAL(SERVICEPLUGIN, test "${service_enable}" = "yes")
 	AM_CONDITIONAL(HEALTHPLUGIN, test "${health_enable}" = "yes")
 	AM_CONDITIONAL(MCAP, test "${health_enable}" = "yes")
diff --git a/doc/sap-api.txt b/doc/sap-api.txt
new file mode 100644
index 0000000..7951f56
--- /dev/null
+++ b/doc/sap-api.txt
@@ -0,0 +1,57 @@
+BlueZ D-Bus Sim Access Profile API description
+***********************************
+
+Copyright (C) 2010 ST-Ericsson SA
+
+
+Sim Access Profile hierarchy
+============================
+
+Service		org.bluez
+Interface	org.bluez.SimAccess
+Object path	[variable prefix]/{hci0,hci1,...}
+
+Methods		void Enable()
+
+			Start up SAP server and register SDP record for it.
+
+			Possible errors: org.bluez.Error.Failed
+
+		void Disable()
+
+			Shudown SAP server and remove the SDP record.
+
+			Possible errors: org.bluez.Error.Failed
+
+		void Disconnect(boolean type)
+
+			Disconnect SAP client from the server. The 'type'
+			parameter indicates disconnection type.
+
+			True  - gracefull disconnection
+			False - immediate disconnection
+
+			Possible errors: org.bluez.Error.Failed
+
+		dict GetProperties()
+
+			Return all properties for the interface. See the
+			properties section for available properties.
+
+			Possible Errors: org.bluez.Error.Failed
+
+Signals		PropertyChanged(string name, variant value)
+
+			This signal indicates a changed value of the given
+			property.
+
+
+Properties	boolean Enabled [readonly]
+
+				Indicates the state of the server. True if the server
+				is enabled and False otherwise.
+
+			boolean Connected [readonly]
+
+				Indicates if SAP client is connected to the server.
+
diff --git a/sap/main.c b/sap/main.c
new file mode 100644
index 0000000..b3efcf8
--- /dev/null
+++ b/sap/main.c
@@ -0,0 +1,54 @@
+/*
+ *  BlueZ - Bluetooth protocol stack for Linux
+ *
+ *  Copyright (C) 2010 Claudio Takahasi<claudio.takahasi@openbossa.org>
+ *
+ *  This program 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; version 2 of the License.
+ *
+ *  This program 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 this program; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <errno.h>
+#include <gdbus.h>
+#include "plugin.h"
+#include "manager.h"
+
+static DBusConnection *connection;
+
+static int sap_init(void)
+{
+	connection = dbus_bus_get(DBUS_BUS_SYSTEM, NULL);
+
+	if (!connection)
+		return -EIO;
+
+	if (sap_manager_init(connection) < 0) {
+		dbus_connection_unref(connection);
+		return -EIO;
+	}
+
+	return 0;
+}
+
+static void sap_exit(void)
+{
+	sap_manager_exit();
+
+	dbus_connection_unref(connection);
+}
+
+BLUETOOTH_PLUGIN_DEFINE(sap, VERSION,
+		BLUETOOTH_PLUGIN_PRIORITY_DEFAULT, sap_init, sap_exit)
diff --git a/sap/manager.c b/sap/manager.c
new file mode 100644
index 0000000..972a46b
--- /dev/null
+++ b/sap/manager.c
@@ -0,0 +1,94 @@
+/*
+ *  BlueZ - Bluetooth protocol stack for Linux
+ *
+ *  Copyright (C) 2010 Claudio Takahasi<claudio.takahasi@openbossa.org>
+ *
+ *  This program 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; version 2 of the License.
+ *
+ *  This program 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 this program; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <errno.h>
+
+#include <bluetooth/bluetooth.h>
+#include <bluetooth/hci.h>
+#include <bluetooth/sdp.h>
+#include <bluetooth/sdp_lib.h>
+
+#include <gdbus.h>
+
+#include "log.h"
+#include "adapter.h"
+#include "device.h"
+
+#include "manager.h"
+
+#include "server.h"
+
+static DBusConnection *connection = NULL;
+
+
+static int sap_server_probe(struct btd_adapter *adapter)
+{
+	const gchar *path = adapter_get_path(adapter);
+	bdaddr_t src;
+
+	DBG("path %s", path);
+
+	adapter_get_address(adapter, &src);
+
+	return sap_server_register(path, &src);
+}
+
+static void sap_server_remove(struct btd_adapter *adapter)
+{
+	const gchar *path = adapter_get_path(adapter);
+
+	DBG("path %s", path);
+
+	sap_server_unregister(path);
+}
+
+static struct btd_adapter_driver sap_server_driver = {
+	.name	= "sap-server",
+	.probe	= sap_server_probe,
+	.remove	= sap_server_remove,
+};
+
+int sap_manager_init(DBusConnection *conn)
+{
+	connection = dbus_connection_ref(conn);
+
+	if (sap_server_init(connection) < 0) {
+		error("Can't init SAP server");
+		dbus_connection_unref(conn);
+		return -1;
+	}
+
+	btd_register_adapter_driver(&sap_server_driver);
+
+	return 0;
+}
+
+void sap_manager_exit(void)
+{
+	btd_unregister_adapter_driver(&sap_server_driver);
+
+	dbus_connection_unref(connection);
+	connection = NULL;
+
+	sap_server_exit();
+}
diff --git a/sap/manager.h b/sap/manager.h
new file mode 100644
index 0000000..5a779df
--- /dev/null
+++ b/sap/manager.h
@@ -0,0 +1,21 @@
+/*
+ *  BlueZ - Bluetooth protocol stack for Linux
+ *
+ *  Copyright (C) 2010 Claudio Takahasi<claudio.takahasi@openbossa.org>
+ *
+ *  This program 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; version 2 of the License.
+ *
+ *  This program 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 this program; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+int sap_manager_init(DBusConnection *conn);
+void sap_manager_exit(void);
diff --git a/sap/sap-dummy.c b/sap/sap-dummy.c
new file mode 100644
index 0000000..db1078b
--- /dev/null
+++ b/sap/sap-dummy.c
@@ -0,0 +1,306 @@
+/*
+ *  BlueZ - Bluetooth protocol stack for Linux
+ *
+ *  Copyright (C) 2010 ST-Ericsson SA
+ *
+ *  Author: Waldemar Rymarkiewicz <waldemar.rymarkiewicz@tieto.com> for ST-Ericsson
+ *
+ *  This program 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; version 2 of the License.
+ *
+ *  This program 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 this program; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <unistd.h>
+#include <stdlib.h>
+#include <stdint.h>
+
+#include <glib.h>
+#include <gdbus.h>
+
+#include "log.h"
+#include "sap.h"
+
+#define SAP_DUMMY_IFACE "org.bluez.SimAccessTest"
+#define SAP_DUMMY_PATH "/org/bluez/test"
+#define SAP_ONGOING_CALL_TIMER 5
+
+typedef enum {
+	SIM_CONNECTED	= 0x00,
+	SIM_DISCONNECTED= 0x01,
+	SIM_POWERED_OFF	= 0x02,
+	SIM_MISSING	= 0x03
+} sim_connection_status_t;
+
+static DBusConnection *connection = NULL;
+
+static sim_connection_status_t sim_card_connection_status = SIM_DISCONNECTED;
+static void *		sap_data = NULL;  /* SAP server private data.*/
+static gboolean		ongoing_call_status = FALSE;
+static int		max_msg_size_supported = 512;
+
+void sap_connect_req(void *sap_device, uint16_t maxmsgsize)
+{
+	if (sim_card_connection_status != SIM_CONNECTED) {
+		sap_connect_rsp(sap_device, SAP_STATUS_CONNECTION_FAILED,
+								maxmsgsize);
+		return;
+	} else if(max_msg_size_supported > maxmsgsize) {
+		sap_connect_rsp(sap_device, SAP_STATUS_MAX_MSG_SIZE_TOO_SMALL,
+						max_msg_size_supported);
+		return;
+	}else if (max_msg_size_supported < maxmsgsize) {
+		sap_connect_rsp(sap_device, SAP_STATUS_MAX_MSG_SIZE_NOT_SUPPORTED,
+					max_msg_size_supported);
+		return;
+	} else if(ongoing_call_status) {
+		sap_connect_rsp(sap_device, SAP_STATUS_OK_ONGOING_CALL,
+								maxmsgsize);
+		//run_timer
+		return;
+	} else {
+		sim_card_connection_status = SIM_CONNECTED;
+		sap_data = sap_device;
+
+		sap_connect_rsp(sap_device, SAP_STATUS_OK, maxmsgsize);
+		sap_status_ind(sap_device, SAP_STATUS_CHANGE_CARD_RESET);
+	}
+}
+
+void sap_disconnect_req(void *sap_device, uint8_t linkloss)
+{
+	sim_card_connection_status = SIM_DISCONNECTED;
+	sap_data = NULL;
+	ongoing_call_status = FALSE;
+
+	if(linkloss)
+		return;
+
+	sap_disconnect_rsp(sap_device);
+}
+
+void sap_transfer_apdu_req(void *sap_device, sap_parameter *param)
+{
+	if (sim_card_connection_status == SIM_MISSING)
+		sap_transfer_apdu_rsp(sap_device, SAP_RESULT_ERROR_CARD_REMOVED,
+								NULL, 0);
+	else if (sim_card_connection_status == SIM_POWERED_OFF)
+		sap_transfer_apdu_rsp(sap_device, SAP_RESULT_ERROR_POWERED_OFF,
+								NULL, 0);
+	else if (sim_card_connection_status != SIM_CONNECTED)
+		sap_transfer_apdu_rsp(sap_device, SAP_RESULT_ERROR_NOT_ACCESSIBLE,
+								NULL, 0);
+	else
+		sap_transfer_apdu_rsp(sap_device, SAP_RESULT_OK, NULL, 0);
+}
+
+void sap_transfer_atr_req(void * sap_device)
+{
+	uint8_t atr[] = {0x3b, 0x9a, 0x96, 0x00, 0x92, 0x01, 0x98, 0x93, 0x17,
+			 0x00, 0x02, 0x28, 0x03, 0x00};
+
+	if (sim_card_connection_status == SIM_MISSING)
+		sap_transfer_atr_rsp(sap_device, SAP_RESULT_ERROR_CARD_REMOVED,
+								NULL, 0);
+	else if (sim_card_connection_status == SIM_POWERED_OFF)
+		sap_transfer_atr_rsp(sap_device, SAP_RESULT_ERROR_POWERED_OFF,
+								NULL, 0);
+	else if (sim_card_connection_status != SIM_CONNECTED)
+		sap_transfer_atr_rsp(sap_device, SAP_RESULT_ERROR_NO_REASON,
+								NULL, 0);
+	else
+		sap_transfer_atr_rsp(sap_device, SAP_RESULT_OK, atr, 0x0E);
+}
+
+void sap_power_sim_off_req(void *sap_device)
+{
+	if(sim_card_connection_status == SIM_MISSING)
+		sap_power_sim_off_rsp(sap_device, SAP_RESULT_ERROR_CARD_REMOVED);
+	else if (sim_card_connection_status == SIM_POWERED_OFF)
+		sap_power_sim_off_rsp(sap_device, SAP_RESULT_ERROR_POWERED_OFF);
+	else if(sim_card_connection_status != SIM_CONNECTED)
+		sap_power_sim_off_rsp(sap_device, SAP_RESULT_ERROR_NO_REASON);
+	else {
+		sap_power_sim_off_rsp(sap_device, SAP_RESULT_OK);
+		sim_card_connection_status = SIM_POWERED_OFF;
+	}
+}
+
+void sap_power_sim_on_req(void *sap_device)
+{
+	if (sim_card_connection_status == SIM_MISSING)
+		sap_power_sim_on_rsp(sap_device, SAP_RESULT_ERROR_CARD_REMOVED);
+	else if (sim_card_connection_status == SIM_POWERED_OFF) {
+		sap_power_sim_on_rsp(sap_device, SAP_RESULT_OK);
+		sim_card_connection_status = SIM_CONNECTED;
+		return;
+	}else if(sim_card_connection_status != SIM_CONNECTED)
+		sap_power_sim_on_rsp(sap_device, SAP_RESULT_ERROR_NOT_ACCESSIBLE);
+	else {
+		sap_power_sim_on_rsp(sap_device, SAP_RESULT_ERROR_NO_REASON);
+	}
+}
+
+void sap_reset_sim_req(void *sap_device)
+{
+	if (sim_card_connection_status == SIM_MISSING)
+		sap_reset_sim_rsp(sap_device, SAP_RESULT_ERROR_CARD_REMOVED);
+	else if (sim_card_connection_status == SIM_POWERED_OFF)
+		sap_reset_sim_rsp(sap_device, SAP_RESULT_ERROR_POWERED_OFF);
+	else if (sim_card_connection_status != SIM_CONNECTED)
+		sap_reset_sim_rsp(sap_device, SAP_RESULT_ERROR_NO_REASON);
+	else {
+		sap_reset_sim_rsp(sap_device, SAP_RESULT_OK);
+		sap_status_ind(sap_device, SAP_STATUS_CHANGE_CARD_RESET);
+	}
+}
+
+void sap_transfer_card_reader_status_req(void * sap_device)
+{
+	if (sim_card_connection_status != SIM_CONNECTED) {
+		sap_transfer_card_reader_status_rsp(sap_device,
+					SAP_RESULT_ERROR_NO_REASON, 0xF1);
+		return;
+	}
+	sap_transfer_card_reader_status_rsp(sap_device, SAP_RESULT_OK, 0xF1);
+}
+
+void sap_set_transport_protocol_req(void * sap_device,sap_parameter * param)
+{
+	sap_transport_protocol_rsp(sap_device, SAP_RESULT_NOT_SUPPORTED);
+}
+
+static inline DBusMessage *invalid_args(DBusMessage *msg)
+{
+	return g_dbus_create_error(msg, "org.bluez.Error.InvalidArguments",
+					"Invalid arguments in method call");
+}
+
+static DBusMessage *ongoing_call(DBusConnection *conn, DBusMessage *msg,
+						void *data)
+{
+	dbus_bool_t ongoing;
+
+	if (!dbus_message_get_args(msg, NULL, DBUS_TYPE_BOOLEAN, &ongoing,
+						DBUS_TYPE_INVALID))
+		return invalid_args(msg);
+
+	if (ongoing_call_status && !ongoing) {
+		/* An ongoing call has finished. Continue connection.*/
+		sap_connect_rsp(sap_data, SAP_STATUS_OK, max_msg_size_supported);
+		sap_status_ind(sap_data, SAP_STATUS_CHANGE_CARD_RESET);
+		ongoing_call_status = ongoing;
+	} else if (!ongoing_call_status && ongoing) {
+		/* An ongoing call has started.*/
+		ongoing_call_status = ongoing;
+	}
+
+	DBG("sap-dummy: OngoingCall status set to %d", ongoing_call_status);
+
+	return dbus_message_new_method_return(msg);
+}
+
+static DBusMessage *max_msg_size(DBusConnection *conn, DBusMessage *msg,
+						void *data)
+{
+	dbus_uint32_t size;
+
+	if (sim_card_connection_status == SIM_CONNECTED)
+		return g_dbus_create_error(msg, "org.bluez.Error.Failed",
+				"Can't change msg size when connected.");
+
+	if (!dbus_message_get_args(msg, NULL, DBUS_TYPE_UINT32, &size,
+						DBUS_TYPE_INVALID))
+		return invalid_args(msg);
+
+	max_msg_size_supported = size;
+
+	DBG("sap-dummy: MaxMessageSize set to %d", max_msg_size_supported);
+
+	return dbus_message_new_method_return(msg);
+}
+
+static DBusMessage *disconnect(DBusConnection *conn, DBusMessage *msg,
+						void *data)
+{
+	sim_card_connection_status = SIM_DISCONNECTED;
+	sap_status_ind(sap_data, SAP_STATUS_CHANGE_CARD_NOT_ACCESSIBLE);
+
+	return dbus_message_new_method_return(msg);
+}
+
+static DBusMessage *card_status(DBusConnection *conn, DBusMessage *msg,
+						void *data)
+{
+	dbus_uint32_t status;
+
+	if(sim_card_connection_status != SIM_CONNECTED)
+		return g_dbus_create_error(msg, "org.bluez.Error.Failed",
+				"Can't change msg size when connected.");
+
+	if (!dbus_message_get_args(msg, NULL, DBUS_TYPE_UINT32, &status,
+						DBUS_TYPE_INVALID))
+		return invalid_args(msg);
+
+	if (status) {
+		if (sim_card_connection_status == SIM_MISSING) {
+			sim_card_connection_status = SIM_CONNECTED;
+			sap_status_ind(sap_data, SAP_STATUS_CHANGE_CARD_INSERTED);
+		}
+	} else {
+		sim_card_connection_status = SIM_MISSING;
+		sap_status_ind(sap_data, SAP_STATUS_CHANGE_CARD_REMOVED);
+	}
+
+	DBG("sap-dummy: Card status changed to %d", status);
+
+	return dbus_message_new_method_return(msg);
+}
+
+
+static GDBusMethodTable dummy_methods[] = {
+	{ "OngoingCall",	"b",	"",	ongoing_call},
+	{ "MaxMessageSize",	"u",	"",	max_msg_size},
+	{ "Disconnect",		"",	"",	disconnect},
+	{ "CardStatus",		"u",	"",	card_status},
+	{ }
+};
+
+static GDBusSignalTable dummy_signals[] = {
+	{ "","" },
+	{ }
+};
+
+int sap_init(void)
+{
+	connection = dbus_bus_get(DBUS_BUS_SYSTEM, NULL);
+
+	if (g_dbus_register_interface(connection, SAP_DUMMY_PATH,
+					SAP_DUMMY_IFACE,
+					dummy_methods, dummy_signals,
+					NULL, NULL, NULL) == FALSE) {
+		error("sap-dummy interface %s init failed on path %s",
+			SAP_DUMMY_IFACE, SAP_DUMMY_PATH);
+		return -1;
+	}
+
+	return 0;
+}
+
+void sap_exit(void)
+{
+	dbus_connection_unref(connection);
+	connection = NULL;
+}
diff --git a/sap/sap-ste.c b/sap/sap-ste.c
new file mode 100644
index 0000000..e9f99b5
--- /dev/null
+++ b/sap/sap-ste.c
@@ -0,0 +1,1265 @@
+/*
+ *  BlueZ - Bluetooth protocol stack for Linux
+ *
+ *  Copyright (C) 2010 ST-Ericsson SA
+ *
+ *  Author: Waldemar Rymarkiewicz <waldemar.rymarkiewicz@tieto.com> for
+ *  ST-Ericsson.
+ *
+ *  This program 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; version 2 of the License.
+ *
+ *  This program 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 this program; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#include <sys/socket.h>
+#include <sys/un.h>
+
+#include <fcntl.h>
+#include <errno.h>
+#include <glib.h>
+#include <unistd.h>
+
+#include "log.h"
+#include "sap.h"
+
+/** SAP_STE_MAX_MSG_SIZE - Maximum size of Sim Access Profile message
+ * supported by the server.
+ */
+#define SAP_STE_MAX_MSG_SIZE 	1024
+
+/** SAP_STE_MIN_MSG_SIZE - Minimal size of  Sim Access Profile message
+ * supported by the server.
+ */
+#define SAP_STE_MIN_MSG_SIZE 	512
+
+/** SAP_STE_UNIX_SOCKET_NAME - Unix socket name used to communicate with
+ * SIM daemon.
+ */
+#define SAP_STE_UNIX_SOCKET_NAME "/dev/socket/catd_a"
+
+/*Sizes of SIM message fields.*/
+#define SAP_STE_MSG_LEN_SIZE 		0x0002
+#define SAP_STE_MSG_TYPE_SIZE 		0x0002
+#define SAP_STE_MSG_CLIENT_TAG_SIZE 	0x0004
+#define SAP_STE_MSG_STATUS_SIZE 	0x0004
+
+/*Header size of SIM message */
+#define SAP_STE_MSG_HEADER_SIZE ((SAP_STE_MSG_LEN_SIZE) + \
+		(SAP_STE_MSG_TYPE_SIZE) + (SAP_STE_MSG_CLIENT_TAG_SIZE))
+
+#define SAP_STE_CLIENT_TAG 0x0000
+
+/** sap_ste_protocol_t - protocol used in communication with SIM.*/
+typedef enum {
+	SAP_STE_START_SAP_REQ 	= 0x2D01,
+	SAP_STE_START_SAP_RSP 	= 0x2E01,
+	SAP_STE_END_SAP_REQ	= 0x2D02,
+	SAP_STE_END_SAP_RSP 	= 0x2E02,
+	SAP_STE_POWER_OFF_REQ	= 0x2D03,
+	SAP_STE_POWER_OFF_RSP	= 0x2E03,
+	SAP_STE_POWER_ON_REQ 	= 0x2D04,
+	SAP_STE_POWER_ON_RSP	= 0x2E04,
+	SAP_STE_RESET_REQ	= 0x2D05,
+	SAP_STE_RESET_RSP	= 0x2E05,
+	SAP_STE_SEND_APDU_REQ	= 0x2D06,
+	SAP_STE_SEND_APDU_RSP	= 0x2E06,
+	SAP_STE_GET_ATR_REQ	= 0x2D07,
+	SAP_STE_GET_ATR_RSP	= 0x2E07,
+	SAP_STE_GET_STATUS_REQ	= 0x2D08,
+	SAP_STE_GET_STATUS_RSP	= 0x2E08,
+	SAP_STE_STATUS_IND	= 0x2F02
+} sap_ste_protocol_t;
+
+/** sap_ste_msg_t - Type of SIM message.*/
+typedef enum {
+	SAP_STE_SEND_APDU_MSG = 0,
+	SAP_STE_GET_ATR_MSG,
+	SAP_STE_POWER_OFF_MSG,
+	SAP_STE_POWER_ON_MSG,
+	SAP_STE_RESET_MSG,
+	SAP_STE_GET_STATUS_MSG,
+	SAP_STE_MSG_MAX,
+} sap_ste_msg_t;
+
+/** sap_ste_status_t - Status of a request.*/
+typedef enum {
+	SAP_STE_STATUS_OK 			= 0x00000000,
+	SAP_STE_STATUS_UNDEFINED_FAILURE 	= 0xFFFFFFFF,
+} sap_ste_status_t;
+
+/** sap_ste_card_status_t - Sim card status.*/
+typedef enum {
+	SAP_STE_CARD_STATUS_UNKNOWN = 0x00,
+	SAP_STE_CARD_STATUS_ACTIVE = 0x01,
+	SAP_STE_CARD_STATUS_NOT_ACTIVE = 0x02,
+	SAP_STE_CARD_STATUS_MISSING = 0x03,
+	SAP_STE_CARD_STATUS_INVALID = 0x04
+} sap_ste_card_status_t;
+
+/** SAP_STE_state_t - Sim connection state.*/
+typedef enum {
+		SAP_STE_DISABLED,	/* Reader not present or removed */
+		SAP_STE_POWERED_OFF,	/* Card in the reader but powered off */
+		SAP_STE_NO_CARD,	/* No card in the reader */
+		SAP_STE_ENABLED,	/* Card in the reader and powered on */
+		SAP_STE_STATE_MAX
+} sap_ste_state_t;
+
+/** sap_ste_message - Sim message format.
+ * @len;	Length of the message minus sizeof(len).
+ * @id;		Request type id.
+ * @client_tag;	SAP server cleint id.
+ * @payload;	Data.
+ */
+typedef struct {
+	uint16_t len;
+	uint16_t id;
+	uint32_t client_tag;
+	uint8_t payload[0];
+} __attribute__ ((packed)) sap_ste_message;
+
+/** sap_ste_connection - main admin structure that keeps data about connection
+ * with sim card.
+ */
+struct sap_ste_connection {
+	GIOChannel *io;
+	sap_ste_state_t state;
+	void *sap_data;
+};
+
+static struct sap_ste_connection *connection = NULL;
+
+/** sim2sap_result - Conversion table of sap result which varies with
+ * connection state and the message type.
+ */
+static const sap_result_t sim2sap_result[SAP_STE_MSG_MAX][SAP_STE_STATE_MAX] = {
+	/* SAP results for SEND APDU message */
+	{SAP_RESULT_ERROR_NOT_ACCESSIBLE,/*for SAP_STE_DISABLED state */
+	 SAP_RESULT_ERROR_POWERED_OFF,	/*for SAP_STE_POWERED_OFF state */
+	 SAP_RESULT_ERROR_CARD_REMOVED,	/*for SAP_STE_NO_CARD state */
+	 SAP_RESULT_ERROR_NO_REASON},	/*for SAP_STE_ENABLED state */
+	 /* SAP results for GET_ATR message */
+	{SAP_RESULT_ERROR_NO_REASON,
+	 SAP_RESULT_ERROR_POWERED_OFF,
+	 SAP_RESULT_ERROR_CARD_REMOVED,
+	 SAP_RESULT_ERROR_NO_REASON},
+	 /* SAP results POWER OFF message */
+	{SAP_RESULT_ERROR_NO_REASON,
+	 SAP_RESULT_ERROR_POWERED_OFF,
+	 SAP_RESULT_ERROR_CARD_REMOVED,
+	 SAP_RESULT_ERROR_NO_REASON},
+	 /* SAP results POWER ON message */
+	{SAP_RESULT_ERROR_NO_REASON,
+	 SAP_RESULT_ERROR_NOT_ACCESSIBLE,
+	 SAP_RESULT_ERROR_CARD_REMOVED,
+	 SAP_RESULT_ERROR_POWERED_ON},
+	 /* SAP results SIM RESET message */
+	{SAP_RESULT_ERROR_NO_REASON,
+	 SAP_RESULT_ERROR_POWERED_OFF,
+	 SAP_RESULT_ERROR_CARD_REMOVED,
+	 SAP_RESULT_ERROR_NOT_ACCESSIBLE},
+	 /* SAP results GET STATUS message */
+	{SAP_RESULT_ERROR_NO_REASON,
+	 SAP_RESULT_ERROR_NO_REASON,
+	 SAP_RESULT_ERROR_NO_REASON,
+	 SAP_RESULT_ERROR_NO_REASON}
+	};
+
+static void connection_uninit(struct sap_ste_connection *conn);
+static int connection_watch(int sock, void *sap_data);
+
+/**
+ * get_sap_result - Convert STE sim status to sap result.
+ * @conn;	Connection info structure.
+ * @msg;	Sim message type.
+ * @status;	Sim status.
+ *
+ * Returns:
+ *	SAP result.
+ */
+static sap_result_t get_sap_result(struct sap_ste_connection *conn,
+				sap_ste_msg_t msg, sap_ste_status_t status)
+{
+	if (!conn)
+		return SAP_RESULT_ERROR_NO_REASON;
+
+	switch (status){
+		case SAP_STE_STATUS_OK:
+			return SAP_RESULT_OK;
+
+		case SAP_STE_STATUS_UNDEFINED_FAILURE:
+			return sim2sap_result[msg][conn->state];
+
+		default:
+			error("Cannot convert sap_ste_status [status: %d] \
+						to sap_result.", status);
+			return SAP_RESULT_ERROR_NO_REASON;
+	}
+}
+
+/**
+ * get_sap_reader_status - Convert STE sim reader status to sap reader result.
+ * @status;	Sim card reader status.
+ *
+ * Returns:
+ *	SAP reader status.
+ */
+static icc_reader_status_t get_sap_reader_status(sap_ste_card_status_t status)
+{
+	switch (status){
+		case SAP_STE_CARD_STATUS_UNKNOWN:
+			return ICC_READER_UNSPECIFIED_ERROR;
+
+		case SAP_STE_CARD_STATUS_NOT_ACTIVE:
+			return ICC_READER_NOT_PRESENT;
+
+		case SAP_STE_CARD_STATUS_ACTIVE:
+			return ICC_READER_CARD_POWERED_ON;
+
+		case SAP_STE_CARD_STATUS_INVALID:
+			return ICC_READER_CARD_POWERED_OFF;
+
+		case SAP_STE_CARD_STATUS_MISSING:
+			return ICC_READER_NO_CARD;
+
+		default:
+			error("Cannot convert sap_ste_reader_status [status: %d]\
+					to icc_sap_reader_status.", status);
+			return ICC_READER_UNSPECIFIED_ERROR;
+	}
+}
+
+/**
+ * sap_status_change - Convert STE sim card status to sap change event.
+ * @conn;	Connection info structure.
+ * @status;	Sim card status.
+ *
+ * This also updates Sim connection state.
+ *
+ * Returns:
+ *	SAP change event.
+ */
+static sap_status_change_t sap_status_change(struct sap_ste_connection *conn,
+					sap_ste_card_status_t status)
+{
+	if (!conn)
+		return SAP_STATUS_CHANGE_UNKNOWN_ERROR;
+
+	switch (status){
+		case SAP_STE_CARD_STATUS_UNKNOWN:
+			return SAP_STATUS_CHANGE_UNKNOWN_ERROR;
+
+		case SAP_STE_CARD_STATUS_ACTIVE:
+			conn->state = SAP_STE_ENABLED;
+			return SAP_STATUS_CHANGE_CARD_RESET;
+
+		case SAP_STE_CARD_STATUS_NOT_ACTIVE:
+			conn->state = SAP_STE_DISABLED;
+			return SAP_STATUS_CHANGE_CARD_NOT_ACCESSIBLE;
+
+		case SAP_STE_CARD_STATUS_MISSING:
+			conn->state = SAP_STE_DISABLED;
+			return SAP_STATUS_CHANGE_CARD_REMOVED;
+
+		case SAP_STE_CARD_STATUS_INVALID:
+			conn->state = SAP_STE_DISABLED;
+			return SAP_STATUS_CHANGE_CARD_NOT_ACCESSIBLE;
+
+		default:
+			error("Cannot convert sap_ste_status_change to \
+							sap_status_change.");
+			return SAP_STATUS_CHANGE_UNKNOWN_ERROR;
+	}
+}
+/**
+ * send_message - Send Sim message to Sim daemon.
+ * @conn;	Connection info structure.
+ * @buf;	Sim message.
+ * @size;	Size of Sim message
+ *
+ * Returns:
+ *	O if success or negaive integer if error occured.
+ */
+static int send_message(struct sap_ste_connection *conn,
+					sap_ste_message *buf, gsize size)
+{
+	gsize written = 0;
+	GIOError gerr;
+
+	DBG("[STE_DRV] send_message: conn %p, buf %p size %d", conn, buf,
+								(int) size);
+
+	gerr = g_io_channel_write(conn->io, (const gchar *) buf, size, &written);
+
+	if (written != size) {
+		error("[STE_DRV] send_message: written only %d bytes out of %d"
+						, (int)written, (int)size);
+		return -1;
+	}
+
+	if (gerr != G_IO_ERROR_NONE) {
+		int err = errno;
+		error("write error: %s(%d)", strerror(err), err);
+		return -err;
+	}
+
+	return 0;
+}
+
+/**
+ * sap_ste_start_sap_req - Create and send start SAP request message.
+ * @conn;	Connection info structure.
+ *
+ * Returns:
+ *	O if success or negaive integer in case of error.
+ */
+static int sap_ste_start_sap_req(struct sap_ste_connection *conn)
+{
+	int err = 0;
+	sap_ste_message *msg = NULL;
+	gsize msg_size = SAP_STE_MSG_HEADER_SIZE;
+
+	DBG("[STE_DRV] sap_ste_start_sap_req: conn %p", conn);
+
+	msg = (sap_ste_message *)g_malloc0(msg_size);
+	if (!msg)
+		return -ENOMEM;
+
+	msg->len = msg_size - SAP_STE_MSG_LEN_SIZE;
+	msg->id = SAP_STE_START_SAP_REQ;
+	msg->client_tag = SAP_STE_CLIENT_TAG;
+
+	err = send_message(conn, msg, msg_size);
+
+	g_free(msg);
+	return err;
+}
+
+/**
+ * sap_ste_end_sap_req - Create and send end SAP request message.
+ * @conn;	Connection info structure.
+ *
+ * Returns:
+ *	O if success or negaive integer in case of error.
+ */
+static int sap_ste_end_sap_req(struct sap_ste_connection *conn)
+{
+	int err = 0;
+	sap_ste_message *msg = NULL;
+	gsize msg_size = SAP_STE_MSG_HEADER_SIZE;
+
+	DBG("[STE_DRV] sap_ste_end_sap_req: conn %p", conn);
+
+	msg = (sap_ste_message *)g_malloc0(msg_size);
+	if (!msg)
+		return -ENOMEM;
+
+	msg->len = msg_size - SAP_STE_MSG_LEN_SIZE;
+	msg->id = SAP_STE_END_SAP_REQ;
+	msg->client_tag = SAP_STE_CLIENT_TAG;
+
+	err = send_message(conn, msg, msg_size);
+
+	g_free(msg);
+	return err;
+}
+
+/**
+ * sap_ste_end_sap_req - Create and send transfer apdu request message.
+ * @conn;	Connection info structure.
+ *
+ * Returns:
+ *	O if success or negaive integer in case of error.
+ */
+static int sap_ste_send_apdu_req(struct sap_ste_connection *conn,
+						sap_parameter *param)
+{
+	int err = 0;
+	sap_ste_message *msg = NULL;
+	gsize msg_size = SAP_STE_MSG_HEADER_SIZE + param->len;
+
+	DBG("[STE_DRV] sap_ste_send_apdu_req: conn %p param %p len %d",
+							conn, param, param->len);
+
+	msg = (sap_ste_message *)g_malloc0(msg_size);
+	if (!msg)
+		return -ENOMEM;
+
+	msg->len = msg_size - SAP_STE_MSG_LEN_SIZE;
+	msg->id = SAP_STE_SEND_APDU_REQ;
+	msg->client_tag = SAP_STE_CLIENT_TAG;
+	memcpy(msg->payload, param->val, param->len);
+
+	err = send_message(conn, msg, msg_size);
+
+	g_free(msg);
+	return err;
+}
+
+/**
+ * sap_ste_get_atr_req - Create and send get ATR request message.
+ * @conn;	Connection info structure.
+ *
+ * Returns:
+ *	O if success or negaive integer in case of error.
+ */
+static int sap_ste_get_atr_req(struct sap_ste_connection *conn)
+{
+	int err = 0;
+	sap_ste_message *msg = NULL;
+	gsize msg_size = SAP_STE_MSG_HEADER_SIZE;
+
+	DBG("[STE_DRV] sap_ste_get_atr_req: conn %p", conn);
+
+	msg = (sap_ste_message *)g_malloc0(msg_size);
+	if (!msg)
+		return -ENOMEM;
+
+	msg->len = msg_size - SAP_STE_MSG_LEN_SIZE;
+	msg->id = SAP_STE_GET_ATR_REQ;
+	msg->client_tag = SAP_STE_CLIENT_TAG;
+
+	err = send_message(conn, msg, msg_size);
+
+	g_free(msg);
+	return err;
+}
+
+/**
+ * sap_ste_power_off_req - Create and send power off request message.
+ * @conn;	Connection info structure.
+ *
+ * Returns:
+ *	O if success or negaive integer in case of error.
+ */
+static int sap_ste_power_off_req(struct sap_ste_connection *conn)
+{
+	int err = 0;
+	sap_ste_message *msg = NULL;
+	gsize msg_size = SAP_STE_MSG_HEADER_SIZE;
+
+	DBG("[STE_DRV] sap_ste_power_off_req: conn %p", conn);
+
+	msg = (sap_ste_message *)g_malloc0(msg_size);
+	if (!msg)
+		return -ENOMEM;
+
+	msg->len = msg_size - SAP_STE_MSG_LEN_SIZE;
+	msg->id = SAP_STE_POWER_OFF_REQ;
+	msg->client_tag = SAP_STE_CLIENT_TAG;
+
+	err = send_message(conn, msg, msg_size);
+
+	g_free(msg);
+	return err;
+}
+
+/**
+ * sap_ste_power_on_req - Create and send power on request message.
+ * @conn;	Connection info structure.
+ *
+ * Returns:
+ *	O if success or negaive integer in case of error.
+ */
+static int sap_ste_power_on_req(struct sap_ste_connection *conn)
+{
+	int err = 0;
+	sap_ste_message *msg = NULL;
+	gsize msg_size = SAP_STE_MSG_HEADER_SIZE;
+
+	DBG("[STE_DRV] sap_ste_power_on_req: conn %p", conn);
+
+	msg = (sap_ste_message *)g_malloc0(msg_size);
+	if (!msg)
+		return -ENOMEM;
+
+	msg->len = msg_size - SAP_STE_MSG_LEN_SIZE;
+	msg->id = SAP_STE_POWER_ON_REQ;
+	msg->client_tag = SAP_STE_CLIENT_TAG;
+
+	err = send_message(conn, msg, msg_size);
+
+	g_free(msg);
+	return err;
+}
+
+/**
+ * sap_ste_reset_req - Create and send card reset request message.
+ * @conn;	Connection info structure.
+ *
+ * Returns:
+ *	O if success or negaive integer in case of error.
+ */
+static int sap_ste_reset_req(struct sap_ste_connection *conn)
+{
+	int err = 0;
+	sap_ste_message *msg = NULL;
+	gsize msg_size = SAP_STE_MSG_HEADER_SIZE;
+
+	DBG("[STE_DRV] sap_ste_reset_req: conn %p", conn);
+
+	msg = (sap_ste_message *)g_malloc0(msg_size);
+	if (!msg)
+		return -ENOMEM;
+
+	msg->len = msg_size - SAP_STE_MSG_LEN_SIZE;
+	msg->id = SAP_STE_RESET_REQ;
+	msg->client_tag = SAP_STE_CLIENT_TAG;
+
+	err = send_message(conn, msg, msg_size);
+
+	g_free(msg);
+	return err;
+}
+
+/**
+ * sap_ste_get_status_req - Create and send card status request message.
+ * @conn;	Connection info structure.
+ *
+ * Returns:
+ *	O if success or negaive integer in case of error.
+ */
+static int sap_ste_get_status_req(struct sap_ste_connection *conn)
+{
+	int err = 0;
+	sap_ste_message *msg = NULL;
+	gsize msg_size = SAP_STE_MSG_HEADER_SIZE;
+
+	DBG("[STE_DRV] sap_ste_get_status_req: conn %p", conn);
+
+	msg = (sap_ste_message *)g_malloc0(msg_size);
+	if (!msg)
+		return -ENOMEM;
+
+	msg->len = msg_size - SAP_STE_MSG_LEN_SIZE;
+	msg->id = SAP_STE_GET_STATUS_REQ;
+	msg->client_tag = SAP_STE_CLIENT_TAG;
+
+	err = send_message(conn, msg, msg_size);
+
+	g_free(msg);
+	return err;
+}
+
+/**
+ * sap_ste_start_sap_rsp - Handle start SAP response message.
+ * @conn;	Connection info structure.
+ * @msg;	Response message.
+ */
+static void sap_ste_start_sap_rsp(struct sap_ste_connection *conn,
+						sap_ste_message * msg)
+{
+	uint32_t *status;
+
+	DBG("[STE_DRV] sap_ste_start_sap_rsp: conn %p (conn %p) msg %p",
+							conn, connection, msg );
+	if (msg && conn) {
+		status = (uint32_t*) msg->payload;
+		if (*status == SAP_STE_STATUS_OK)
+			sap_connect_rsp(conn->sap_data, SAP_STATUS_OK, 0);
+		else {
+			sap_connect_rsp(conn->sap_data, SAP_STATUS_CONNECTION_FAILED, 0);
+			connection_uninit(conn);
+		}
+	}
+}
+
+/**
+ * sap_ste_end_sap_rsp - Handle end SAP response message.
+ * @conn;	Connection info structure.
+ * @msg;	Response message.
+ */
+static void sap_ste_end_sap_rsp(struct sap_ste_connection *conn,
+						sap_ste_message * msg)
+{
+	DBG("[STE_DRV] sap_ste_end_sap_rsp: conn %p (conn %p) msg %p",
+							conn, connection, msg );
+	if (msg && conn) {
+		sap_disconnect_rsp(conn->sap_data);
+		connection_uninit(conn);
+	}
+}
+
+/**
+ * sap_ste_send_apdu_rsp - Handle transfer apdu response message.
+ * @conn;	Connection info structure.
+ * @msg;	Response message.
+ */
+static void  sap_ste_send_apdu_rsp(struct sap_ste_connection *conn,
+						sap_ste_message * msg)
+{
+	uint32_t *status;
+	sap_result_t sr;
+	uint8_t *apdu = NULL;
+	uint16_t len = 0;
+
+	DBG("[STE_DRV] sap_ste_send_apdu_rsp: conn %p (conn %p) msg %p",
+							conn, connection, msg );
+
+	if (msg && conn) {
+		status = (uint32_t*) msg->payload;
+		if (*status == SAP_STE_STATUS_OK) {
+			apdu = (uint8_t *)(msg->payload + SAP_STE_MSG_STATUS_SIZE);
+			len = msg->len - (SAP_STE_MSG_HEADER_SIZE) +
+				SAP_STE_MSG_LEN_SIZE - SAP_STE_MSG_STATUS_SIZE;
+		}
+
+		sr = get_sap_result(conn, SAP_STE_SEND_APDU_MSG, *status);
+		sap_transfer_apdu_rsp(conn->sap_data, sr, apdu, len);
+	}
+}
+
+/**
+ * sap_ste_get_atr_rsp - Handle get ATR response message.
+ * @conn;	Connection info structure.
+ * @msg;	Response message.
+ */
+static void sap_ste_get_atr_rsp(struct sap_ste_connection *conn,
+						sap_ste_message * msg)
+{
+	uint32_t *status;
+	sap_result_t sr;
+	uint8_t *atr = NULL;
+	uint16_t len = 0;
+
+	DBG("[STE_DRV] sap_ste_get_atr_rsp: conn %p (conn %p) msg %p",
+							conn, connection, msg );
+
+	if (msg && conn) {
+		status = (uint32_t*) msg->payload;
+		if (*status == SAP_STE_STATUS_OK) {
+			atr = (uint8_t *)(msg->payload + SAP_STE_MSG_STATUS_SIZE);
+			len = msg->len - (SAP_STE_MSG_HEADER_SIZE) +
+							SAP_STE_MSG_LEN_SIZE;
+		}
+
+		sr = get_sap_result(conn, SAP_STE_GET_ATR_MSG, *status);
+		sap_transfer_atr_rsp(conn->sap_data, sr, atr, len);
+	}
+}
+
+/**
+ * sap_ste_power_off_rsp - Handle power off response message.
+ * @conn;	Connection info structure.
+ * @msg;	Response message.
+ */
+static void sap_ste_power_off_rsp(struct sap_ste_connection *conn,
+							sap_ste_message * msg)
+{
+	uint32_t *status;
+	sap_result_t sr;
+
+	DBG("[STE_DRV] sap_ste_power_off_rsp: conn %p (conn %p) msg %p",
+							conn, connection, msg );
+
+	if (msg && conn) {
+		status = (uint32_t *) msg->payload;
+		if (*status == SAP_STE_STATUS_OK)
+			conn->state = SAP_STE_POWERED_OFF;
+
+		sr = get_sap_result(conn, SAP_STE_POWER_OFF_MSG, *status);
+		sap_power_sim_off_rsp(conn->sap_data, sr);
+	}
+}
+
+/**
+ * sap_ste_power_on_rsp - Handle power on response message.
+ * @conn;	Connection info structure.
+ * @msg;	Response message.
+ */
+static void sap_ste_power_on_rsp(struct sap_ste_connection *conn,
+						sap_ste_message * msg)
+{
+	uint32_t *status;
+	sap_result_t sr;
+
+	DBG("[STE_DRV] sap_ste_power_on_rsp: conn %p (conn %p) msg %p",
+							conn, connection, msg );
+
+	if (msg && conn) {
+		status = (uint32_t *) msg->payload;
+		if (*status == SAP_STE_STATUS_OK)
+			conn->state = SAP_STE_ENABLED;
+
+		sr = get_sap_result(conn, SAP_STE_POWER_ON_MSG, *status);
+		sap_power_sim_on_rsp(conn->sap_data, sr);
+	}
+}
+
+/**
+ * sap_ste_reset_rsp - Handle reset response message.
+ * @conn;	Connection info structure.
+ * @msg;	Response message.
+ */
+static void sap_ste_reset_rsp(struct sap_ste_connection *conn,
+					sap_ste_message * msg)
+{
+	uint32_t *status;
+	sap_result_t sr;
+
+	DBG("[STE_DRV] sap_ste_reset_rsp: conn %p (conn %p) msg %p",
+							conn, connection, msg );
+
+	if (msg && conn) {
+		status = (uint32_t *) msg->payload;
+		if (*status == SAP_STE_STATUS_OK)
+			conn->state = SAP_STE_ENABLED;
+
+		sr = get_sap_result(conn, SAP_STE_RESET_MSG, *status);
+		sap_reset_sim_rsp(conn->sap_data, sr);
+	}
+}
+
+/**
+ * sap_ste_get_status_rsp - Handle card status response message.
+ * @conn;	Connection info structure.
+ * @msg;	Response message.
+ */
+static void sap_ste_get_status_rsp(struct sap_ste_connection *conn,
+						sap_ste_message * msg)
+{
+	uint8_t *p = NULL;
+	uint32_t *status;
+	sap_result_t sr;
+	sap_ste_card_status_t cs;
+	icc_reader_status_t iccrs;
+
+	DBG("[STE_DRV] sap_ste_get_status_rsp: conn %p (conn %p) msg %p",
+							conn, connection, msg );
+
+	if (msg && conn) {
+		p = msg->payload;
+		status = (uint32_t *)p; p += sizeof(uint32_t);
+		cs = *((uint16_t *)p);
+
+		iccrs = get_sap_reader_status(cs);
+		sr = get_sap_result(conn, SAP_STE_GET_STATUS_MSG, *status);
+		sap_transfer_card_reader_status_rsp(conn->sap_data, sr, iccrs);
+	}
+}
+
+/**
+ * sap_ste_status_ind - Handle status indication message.
+ * @conn;	Connection info structure.
+ * @msg;	Response message.
+ */
+static void sap_ste_status_ind(struct sap_ste_connection *conn,
+							sap_ste_message * msg)
+{
+	sap_status_change_t sc;
+	sap_ste_card_status_t cs;
+	uint32_t *status;
+
+	DBG("[STE_DRV] sap_ste_status_ind: conn %p (conn %p) msg %p",
+							conn, connection, msg );
+
+	if (msg && conn) {
+		status = (uint32_t *) msg->payload;
+		cs = *status;
+		sc = sap_status_change(conn, cs);
+
+		sap_status_ind(conn->sap_data, sc);
+	}
+}
+
+/**
+ * handle_msg - Handle messages from Sim daemon.
+ * @conn;	Connection info structure.
+ * @buf;	Data buffer.
+ * @size;	Size of data buffer.
+ *
+ * Returns:
+ *    0 if success or EBADMSG in case of bad message format.
+ */
+static int handle_msg(struct sap_ste_connection *conn, unsigned char *buf,
+								gsize size)
+{
+	unsigned char *iter = buf;
+	sap_ste_message * msg = (sap_ste_message *) buf;
+	gssize msize = (gssize) size;
+
+	DBG("[STE_DRV] handle_msg: msg %p conn %p", msg, conn);
+
+	if (msg == NULL || conn == NULL)
+		return -EFAULT;
+
+	do {
+		DBG("[STE_DRV] handle_msg: msize %d msg->len %d.",
+							(int)msize, msg->len);
+
+		/* Message must be at least size of header len */
+		if (msize < SAP_STE_MSG_HEADER_SIZE) {
+			error("[STE_DRV] Invalid message size.");
+			return -EBADMSG;
+		}
+
+		/* Message must be completed. */
+		if (msize < (SAP_STE_MSG_LEN_SIZE + msg->len)) {
+			error("[STE_DRV] Not complete message.");
+			return -EBADMSG;
+		}
+
+		switch (msg->id){
+			case SAP_STE_START_SAP_RSP:
+				sap_ste_start_sap_rsp(conn, msg);
+				break;
+
+			case SAP_STE_END_SAP_RSP:
+				sap_ste_end_sap_rsp(conn, msg);
+				break;
+
+			case SAP_STE_SEND_APDU_RSP:
+				sap_ste_send_apdu_rsp(conn, msg);
+				break;
+
+			case SAP_STE_GET_ATR_RSP:
+				sap_ste_get_atr_rsp(conn, msg);
+				break;
+
+			case SAP_STE_POWER_OFF_RSP:
+				sap_ste_power_off_rsp(conn, msg);
+				break;
+
+			case SAP_STE_POWER_ON_RSP:
+				sap_ste_power_on_rsp(conn, msg);
+				break;
+
+			case SAP_STE_RESET_RSP:
+				sap_ste_reset_rsp(conn, msg);
+				break;
+
+			case SAP_STE_GET_STATUS_RSP:
+				sap_ste_get_status_rsp(conn, msg);
+				break;
+
+			case SAP_STE_STATUS_IND:
+				sap_ste_status_ind(conn, msg);
+				break;
+
+			default:
+				error("[STE_DRV] Invalid or not supported \
+						frame [0x%02x].", msg->id);
+		}
+
+		/* Reduce total buffer size of just handled frame size*/
+		msize -= (SAP_STE_MSG_HEADER_SIZE +
+				(msg->len - (SAP_STE_MSG_HEADER_SIZE) +
+				 SAP_STE_MSG_LEN_SIZE));
+
+		/* Move msg ponter to then next message if any */
+		iter += (msg->len + SAP_STE_MSG_LEN_SIZE);
+		msg = (sap_ste_message *)iter;
+	} while (msize > 0);
+
+	return 0;
+}
+
+/**
+ * connection_io_data_cb - Handle data on socket to Sim daemon.
+ * @io;		Connection info structure.
+ * @conn;	Conndition that triggered this callback.
+ * @data;	Data buffor.
+ *
+ * Returns:
+ *    True if @data was handled, False otherwise.
+ */
+static gboolean connection_io_data_cb(GIOChannel *io, GIOCondition cond,
+							gpointer data)
+{
+	GIOError err = G_IO_ERROR_NONE;
+	unsigned char buf[SAP_STE_MAX_MSG_SIZE];
+	gsize read_bytes = 0;
+
+	if (cond & G_IO_NVAL) {
+		DBG("[STE_DRV] NVAL on sim socket");
+		return FALSE;
+	}
+
+	if (cond & G_IO_HUP) {
+		DBG("[STE_DRV] HUP on sim socket");
+		return FALSE;
+	}
+
+	if (cond & G_IO_ERR) {
+		DBG("[STE_DRV] ERR on sim socket");
+		return FALSE;
+	}
+
+	err = g_io_channel_read(io, (gchar *)buf, sizeof(buf), &read_bytes);
+	if (err != G_IO_ERROR_NONE) {
+		error("[STE_DRV] Error while reading from channel \
+						[err 0x%x io %p].", err, io);
+		return FALSE;
+	}
+
+	if (handle_msg(data, buf, read_bytes) < 0)
+		error("[STE_DRV] Invalid STE Sim message.");
+
+	return TRUE;
+}
+
+/**
+ * connection_io_destroy_cb - Clean up the SAP serer in case of socket closure.
+ * @data;	Private data.
+ *
+ * The callback is run if the connection with Sim daemon has been lost.
+ */
+static void connection_io_destroy_cb(void *data)
+{
+	struct sap_ste_connection *conn = (struct sap_ste_connection *)data;
+
+	if (conn && connection) {
+		DBG("[STE_DRV] connection_io_destroy_cb: conn %p conn %p io %p",
+						conn, connection, conn->io);
+
+		g_io_channel_unref(conn->io);
+		g_io_channel_shutdown(conn->io, TRUE, NULL);
+		g_free(conn);
+		connection = NULL;
+	}
+}
+
+/**
+ * connection_init - Initialize connection with Sim Daemon.
+ * @sap_data;	Private data of SAP Server.
+ *
+ * Returns:
+ *    0 if success, negative number in case of an error.
+ */
+static int connection_init(void * sap_data)
+{
+	int sock;
+	int len = 0;
+	struct sockaddr_un addr;
+	ssize_t addr_len;
+
+	/* Create a socket to communicate with SIMD*/
+	sock = socket(PF_UNIX, SOCK_STREAM, 0);
+	if (sock < 0) {
+		error("[STE_DRV] Create socket failed: %s", strerror(errno));
+		return -errno;
+	}
+
+	/*Connect to SIMD*/
+	memset(&addr, 0, sizeof(addr));
+	addr.sun_family = AF_UNIX;
+	len = sprintf(addr.sun_path, SAP_STE_UNIX_SOCKET_NAME);
+	addr_len = sizeof(addr.sun_family) + len;
+	if (connect(sock, (struct sockaddr *) &addr, addr_len) < 0) {
+		error("[STE_DRV] Connect to the socket failed:  %s",
+							strerror(errno));
+		goto drop;
+	}
+
+	if (fcntl(sock, F_SETFL, O_NONBLOCK) > 0) {
+		error("[STE_DRV] fcntl() failed: %s", strerror(errno));
+		goto drop;
+	}
+
+	DBG("[STE_DRV] connection_init: sock %d ",sock);
+
+	/* Start watching incoming data */
+	if (connection_watch(sock, sap_data) < 0)
+		goto drop;
+
+	return 0;
+
+drop:
+	DBG("[STE_DRV] connection_init: drop!");
+	close(sock);
+	return -errno;
+}
+
+/**
+ * connection_uninit - Disconnect from Sim daemon.
+ * @conn;	Connection info structure.
+ */
+static void connection_uninit(struct sap_ste_connection *conn)
+{
+	DBG("[STE_DRV] connection_uninit: conn %p connection %p", conn,
+								connection);
+
+	if (!conn)
+		return;
+
+	g_io_channel_shutdown(conn->io, TRUE, NULL);
+	g_io_channel_unref(conn->io);
+	g_free(conn);
+
+	connection = NULL;
+}
+
+
+/**
+ * connection_watch - Start watching Sim daemon connection.
+ * @sap_data;	Private data of SAP Server.
+ *
+ * Returns:
+ *    0 if success, negative number in case of an error.
+ */
+static int connection_watch(int sock, void *sap_data)
+{
+	GIOChannel *io = NULL;
+
+	DBG("[STE_DRV] connection_watch: sock %d, sap_data %p ", sock,
+								sap_data);
+
+	if (sock < 0)
+		return -1;
+
+	io = g_io_channel_unix_new(sock);
+	g_io_channel_set_close_on_unref(io, TRUE);
+
+
+	connection = g_new0(struct sap_ste_connection, 1);
+	if (!connection) {
+		error("[STE_DRV] connection_watch: connection %p io %p",
+								connection, io);
+		g_io_channel_shutdown(io, TRUE, NULL);
+		g_io_channel_unref(io);
+		return -1;
+	}
+
+	connection->io = io;
+	connection->sap_data = sap_data;
+	connection->state = SAP_STE_DISABLED;
+
+	g_io_add_watch_full(io, G_PRIORITY_DEFAULT,
+			G_IO_IN | G_IO_ERR | G_IO_HUP | G_IO_NVAL,
+			connection_io_data_cb, connection, connection_io_destroy_cb);
+
+	return 0;
+}
+
+/**
+ * sap_connect_req - Handle SAP connect request.
+ * @sap_data;	Private data of SAP Server.
+ * @maxmsgsize;	Message size supported by the SAP client.
+ */
+void sap_connect_req(void *sap_device, uint16_t maxmsgsize)
+{
+
+	DBG("[STE_DRV] sap_connect_req: conn %p sap_device %p maxmsgsize %d",
+			connection, sap_device, maxmsgsize);
+
+	if (maxmsgsize < SAP_STE_MIN_MSG_SIZE) {
+		sap_connect_rsp(sap_device, SAP_STATUS_MAX_MSG_SIZE_TOO_SMALL,
+							SAP_STE_MAX_MSG_SIZE);
+		return;
+	}
+
+	if (maxmsgsize > SAP_STE_MAX_MSG_SIZE) {
+		sap_connect_rsp(sap_device, SAP_STATUS_MAX_MSG_SIZE_NOT_SUPPORTED,
+							SAP_STE_MAX_MSG_SIZE);
+		return;
+	}
+
+	if (connection_init(sap_device) < 0) {
+		DBG("[STE_DRV] connection_init: failed!");
+		sap_connect_rsp(sap_device, SAP_STATUS_CONNECTION_FAILED, 0);
+		return;
+	}
+
+	if (connection && connection->state == SAP_STE_DISABLED) {
+		if (sap_ste_start_sap_req(connection) < 0) {
+			sap_connect_rsp(sap_device, SAP_STATUS_CONNECTION_FAILED,
+							SAP_STE_MAX_MSG_SIZE);
+			connection_uninit(connection);
+		}
+	} else {
+		DBG("[STE_DRV] Connection failed! (connection %p) ", connection);
+		sap_connect_rsp(sap_device, SAP_STATUS_CONNECTION_FAILED, 0);
+	}
+}
+
+/**
+ * sap_disconnect_req - Handle SAP disconnect request.
+ * @sap_data;	Private data of SAP Server.
+ * @linkloss;	Indicates thet link is being disconnected due to link loss.
+ */
+void sap_disconnect_req(void *sap_device, uint8_t linkloss)
+{
+	DBG("[STE_DRV] sap_disconnect_req: conn %p sap_device %p linkloss %d",
+					connection, sap_device, linkloss);
+	if (connection && linkloss) {
+		connection_uninit(connection);
+		return;
+	}
+
+	if (connection && connection->state != SAP_STE_DISABLED) {
+		if (sap_ste_end_sap_req(connection) < 0) {
+			sap_disconnect_rsp(sap_device);
+		}
+	} else {
+		sap_disconnect_rsp(sap_device);
+	}
+}
+
+/**
+ * sap_transfer_apdu_req - Handle SAP transfer apdu request.
+ * @sap_data;	Private data of SAP Server.
+ * @param;	SAP parameter of the request.
+ */
+void sap_transfer_apdu_req(void *sap_device, sap_parameter *param)
+{
+	sap_result_t sr;
+
+	DBG("[STE_DRV] sap_transfer_apdu_req: conn %p sap_device %p param %p\
+		param len %d", connection, sap_device, param, param->len);
+
+	if (connection && connection->state == SAP_STE_ENABLED) {
+		if (sap_ste_send_apdu_req(connection, param) < 0)
+			sap_transfer_apdu_rsp(sap_device,
+					SAP_RESULT_ERROR_NO_REASON, NULL, 0);
+	} else {
+		sr = get_sap_result(connection, SAP_STE_SEND_APDU_MSG,
+					SAP_STE_STATUS_UNDEFINED_FAILURE);
+		sap_transfer_apdu_rsp(sap_device, sr, NULL, 0);
+	}
+}
+
+/**
+ * sap_transfer_atr_req - Handle SAP ATR request.
+ * @sap_data;	Private data of SAP Server.
+ */
+void sap_transfer_atr_req(void * sap_device)
+{
+	sap_result_t sr;
+
+	DBG("[STE_DRV] sap_transfer_atr_req: conn %p, sap_device %p",
+							connection, sap_device);
+
+	if (connection && connection->state == SAP_STE_ENABLED) {
+		if (sap_ste_get_atr_req(connection) < 0)
+			sap_transfer_atr_rsp(sap_device,
+				SAP_RESULT_ERROR_NO_DATA, NULL, 0);
+	} else {
+		sr = get_sap_result(connection, SAP_STE_GET_ATR_MSG,
+					SAP_STE_STATUS_UNDEFINED_FAILURE);
+		sap_transfer_atr_rsp(sap_device, sr, NULL, 0);
+	}
+}
+
+/**
+ * sap_power_sim_off_req - Handle SAP power off request.
+ * @sap_data;	Private data of SAP Server.
+ */
+void sap_power_sim_off_req(void *sap_device)
+{
+	sap_result_t sr;
+
+	DBG("[STE_DRV] sap_power_sim_off_req: conn %p, sap_device %p",
+							connection, sap_device);
+
+	if (connection && connection->state == SAP_STE_ENABLED) {
+		if (sap_ste_power_off_req(connection) < 0)
+			sap_power_sim_off_rsp(sap_device,
+					SAP_RESULT_ERROR_NO_REASON);
+	} else {
+		sr = get_sap_result(connection, SAP_STE_POWER_OFF_MSG,
+					SAP_STE_STATUS_UNDEFINED_FAILURE);
+		sap_power_sim_off_rsp(sap_device, sr);
+	}
+}
+
+/**
+ * sap_power_sim_on_req - Handle SAP power on request.
+ * @sap_data;	Private data of SAP Server.
+ */
+void sap_power_sim_on_req(void *sap_device)
+{
+	sap_result_t sr;
+
+	DBG("[STE_DRV] sap_power_sim_on_req: conn %p, sap_device %p",
+							connection, sap_device);
+
+	if (connection && connection->state == SAP_STE_POWERED_OFF) {
+		if (sap_ste_power_on_req(connection) < 0)
+			sap_power_sim_on_rsp(sap_device,
+					SAP_RESULT_ERROR_NO_REASON);
+	} else {
+		sr = get_sap_result(connection, SAP_STE_POWER_ON_MSG,
+					SAP_STE_STATUS_UNDEFINED_FAILURE);
+		sap_power_sim_on_rsp(sap_device, sr);
+	}
+}
+
+/**
+ * sap_reset_sim_req - Handle SAP reset request.
+ * @sap_data;	Private data of SAP Server.
+ */
+void sap_reset_sim_req(void *sap_device)
+{
+	sap_result_t sr;
+
+	DBG("[STE_DRV] sap_reset_sim_req: conn %p, sap_device %p",
+							connection, sap_device);
+
+	if (connection && connection->state == SAP_STE_ENABLED) {
+		if (sap_ste_reset_req(connection) < 0)
+			sap_reset_sim_rsp(sap_device,
+						SAP_RESULT_ERROR_NO_REASON);
+	} else {
+		sr = get_sap_result(connection, SAP_STE_RESET_MSG,
+					SAP_STE_STATUS_UNDEFINED_FAILURE);
+		sap_reset_sim_rsp(sap_device, sr);
+	}
+}
+
+/**
+ * sap_transfer_card_reader_status_req - Handle get card reader status request.
+ * @sap_data;	Private data of SAP Server.
+ */
+void sap_transfer_card_reader_status_req(void * sap_device)
+{
+	sap_result_t sr;
+
+	DBG("[STE_DRV] sap_transfer_card_reader_status_req: conn %p, \
+					sap_device %p", connection, sap_device);
+
+	if (connection && connection->state != SAP_STE_DISABLED) {
+		if (sap_ste_get_status_req(connection) < 0)
+			sap_transfer_card_reader_status_rsp(sap_device,
+						SAP_RESULT_ERROR_NO_DATA,
+						ICC_READER_UNSPECIFIED_ERROR);
+	} else {
+		sr = get_sap_result(connection, SAP_STE_GET_STATUS_MSG,
+					SAP_STE_STATUS_UNDEFINED_FAILURE);
+		sap_transfer_card_reader_status_rsp(sap_device, sr,
+						ICC_READER_UNSPECIFIED_ERROR);
+	}
+}
+
+/**
+ * sap_set_transport_protocol_req - Handle set transport protocol request.
+ * @sap_data;	Private data of SAP Server.
+ */
+void sap_set_transport_protocol_req(void * sap_device,sap_parameter * param)
+{
+	sap_transport_protocol_rsp(sap_device, SAP_RESULT_NOT_SUPPORTED);
+}
+
+int sap_init(void)
+{
+	return 0;
+}
+
+void sap_exit(void)
+{
+}
diff --git a/sap/sap.h b/sap/sap.h
new file mode 100644
index 0000000..a9189fc
--- /dev/null
+++ b/sap/sap.h
@@ -0,0 +1,187 @@
+/*
+ *  BlueZ - Bluetooth protocol stack for Linux
+ *
+ *  Copyright (C) 2010 ST-Ericsson SA
+ *  Copyright (C) 2010 Claudio Takahasi<claudio.takahasi@openbossa.org>
+ *
+ *  Author: Marek Skowron <marek.skowron@tieto.com> for ST-Ericsson.
+ *  Author: Waldemar Rymarkiewicz <waldemar.rymarkiewicz@tieto.com> for ST-Ericsson.
+ *
+ *  This program 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; version 2 of the License.
+ *
+ *  This program 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 this program; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+#include <stdint.h>
+#include <glib.h>
+
+ #define SAP_VERSION 0x0101
+
+/* Connection Status - SAP v1.1 section 5.2.2 */
+typedef enum {
+	SAP_STATUS_OK 				= 0x00,
+	SAP_STATUS_CONNECTION_FAILED		= 0x01,
+	SAP_STATUS_MAX_MSG_SIZE_NOT_SUPPORTED	= 0x02,
+	SAP_STATUS_MAX_MSG_SIZE_TOO_SMALL	= 0x03,
+	SAP_STATUS_OK_ONGOING_CALL		= 0x04
+} sap_status_t;
+
+/* Disconnection Type - SAP v1.1 section 5.2.3 */
+typedef enum {
+	SAP_DISCONNECTION_TYPE_GRACEFUL  = 0x00,
+	SAP_DISCONNECTION_TYPE_IMMEDIATE = 0x01,
+	SAP_DISCONNECTION_TYPE_CLIENT    = 0xFF
+} sap_disconnection_type_t;
+
+/* Result codes - SAP v1.1 section 5.2.4 */
+typedef enum {
+	SAP_RESULT_OK 			= 0x00,
+	SAP_RESULT_ERROR_NO_REASON	= 0x01,
+	SAP_RESULT_ERROR_NOT_ACCESSIBLE	= 0x02,
+	SAP_RESULT_ERROR_POWERED_OFF	= 0x03,
+	SAP_RESULT_ERROR_CARD_REMOVED	= 0x04,
+	SAP_RESULT_ERROR_POWERED_ON	= 0x05,
+	SAP_RESULT_ERROR_NO_DATA	= 0x06,
+	SAP_RESULT_NOT_SUPPORTED	= 0x07
+} sap_result_t;
+
+/* Status Change - SAP v1.1 section 5.2.8 */
+typedef enum {
+	SAP_STATUS_CHANGE_UNKNOWN_ERROR	= 0x00,
+	SAP_STATUS_CHANGE_CARD_RESET	= 0x01,
+	SAP_STATUS_CHANGE_CARD_NOT_ACCESSIBLE = 0x02,
+	SAP_STATUS_CHANGE_CARD_REMOVED	= 0x03,
+	SAP_STATUS_CHANGE_CARD_INSERTED	= 0x04,
+	SAP_STATUS_CHANGE_CARD_RECOVERED = 0x05
+} sap_status_change_t;
+
+/* Message format - SAP v1.1 section 5.1 */
+typedef struct {
+	uint8_t id;
+	uint8_t reserved;
+	uint16_t len;
+	uint8_t val[0];
+	/*
+	 * Padding bytes 0-3 bytes
+	 */
+} __attribute__ ((packed)) sap_parameter;
+
+typedef struct {
+	uint8_t id;
+	uint8_t nparam;
+	uint16_t reserved;
+	sap_parameter param[0];
+} __attribute__ ((packed)) sap_message;
+
+
+typedef enum {
+	ICC_READER_UNSPECIFIED_ERROR, /* No further information available */
+	ICC_READER_NOT_PRESENT,       /* Card Reader removed or not present */
+	ICC_READER_BUSY,              /* Card Reader in use */
+	ICC_READER_CARD_POWERED_ON,   /* Card in reader and is powered on */
+	ICC_READER_DEACTIVATED,       /* Card Reader deactivated */
+	ICC_READER_CARD_POWERED_OFF,  /* Card in reader, but powered off */
+	ICC_READER_NO_CARD,           /* No card in reader */
+	ICC_READER_LAST
+} icc_reader_status_t;
+
+
+#define SAP_BUF_SIZE		512
+
+#define SAP_MSG_HEADER_SIZE	4
+
+typedef enum {
+	SAP_CONNECT_REQ		= 0x00,
+	SAP_CONNECT_RESP	= 0x01,
+	SAP_DISCONNECT_REQ	= 0x02,
+	SAP_DISCONNECT_RESP	= 0x03,
+	SAP_DISCONNECT_IND	= 0x04,
+	SAP_TRANSFER_APDU_REQ	= 0x05,
+	SAP_TRANSFER_APDU_RESP	= 0x06,
+	SAP_TRANSFER_ATR_REQ	= 0x07,
+	SAP_TRANSFER_ATR_RESP	= 0x08,
+	SAP_POWER_SIM_OFF_REQ	= 0x09,
+	SAP_POWER_SIM_OFF_RESP	= 0x0A,
+	SAP_POWER_SIM_ON_REQ	= 0x0B,
+	SAP_POWER_SIM_ON_RESP	= 0x0C,
+	SAP_RESET_SIM_REQ	= 0x0D,
+	SAP_RESET_SIM_RESP	= 0x0E,
+	SAP_TRANSFER_CARD_READER_STATUS_REQ	= 0x0F,
+	SAP_TRANSFER_CARD_READER_STATUS_RESP	= 0x10,
+	SAP_STATUS_IND	= 0x11,
+	SAP_ERROR_RESP	= 0x12,
+	SAP_SET_TRANSPORT_PROTOCOL_REQ	= 0x13,
+	SAP_SET_TRANSPORT_PROTOCOL_RESP	= 0x14,
+} sap_protocol;
+
+/* Parameters Ids - SAP 1.1 section 5.2 */
+#define SAP_PARAM_ID_MAX_MSG_SIZE             0x00
+#define SAP_PARAM_ID_MAX_MSG_SIZE_LEN         0x02
+
+#define SAP_PARAM_ID_CONN_STATUS            0x01
+#define SAP_PARAM_ID_CONN_STATUS_LEN        0x01
+
+#define SAP_PARAM_ID_RESULT_CODE            0x02
+#define SAP_PARAM_ID_RESULT_CODE_LEN        0x01
+
+#define SAP_PARAM_ID_DISCONNECT_IND         0x03
+#define SAP_PARAM_ID_DISCONNECT_IND_LEN     0x01
+
+#define SAP_PARAM_ID_COMMAND_APDU           0x04
+#define SAP_PARAM_ID_RESPONSE_APDU          0x05
+#define SAP_PARAM_ID_ATR                    0x06
+
+#define SAP_PARAM_ID_CARD_READER_STATUS     0x07
+#define SAP_PARAM_ID_CARD_READER_STATUS_LEN 0x01
+
+#define SAP_PARAM_ID_STATUS_CHANGE          0x08
+#define SAP_PARAM_ID_STATUS_CHANGE_LEN      0x01
+
+#define SAP_PARAM_ID_TRANSPORT_PROTOCOL     0x09
+#define SAP_PARAM_ID_TRANSPORT_PROTOCOL_LEN 0x01
+
+#define SAP_PARAM_ID_COMMAND_APDU7816       0x10
+
+/* Transport Protocol - SAP v1.1 section 5.2.9 */
+#define SAP_TRANSPORT_PROTOCOL_T0           0x00
+#define SAP_TRANSPORT_PROTOCOL_T1           0x01
+
+/*SAP driver init and exit routines. Implemented by sap-*.c */
+int sap_init(void);
+void sap_exit(void);
+
+/* SAP requests implemented by sap-*.c */
+void sap_connect_req(void *sap_device, uint16_t maxmsgsize);
+void sap_disconnect_req(void *sap_device, uint8_t linkloss);
+void sap_transfer_apdu_req(void *sap_device, sap_parameter *param);
+void sap_transfer_atr_req(void *sap_device);
+void sap_power_sim_off_req(void *sap_device);
+void sap_power_sim_on_req(void *sap_device);
+void sap_reset_sim_req(void *sap_device);
+void sap_transfer_card_reader_status_req(void *sap_device);
+void sap_set_transport_protocol_req(void *sap_device, sap_parameter *param);
+
+/*SAP responses to SAP requests. Implemented by server.c */
+int sap_connect_rsp(void *sap_device, sap_status_t status, uint16_t maxmsgsize);
+int sap_disconnect_rsp(void *sap_device);
+int sap_transfer_apdu_rsp(void *sap_device, sap_result_t result, uint8_t *sap_apdu_resp, uint16_t length);
+int sap_transfer_atr_rsp(void *sap_device, sap_result_t result, uint8_t *sap_atr, uint16_t length);
+int sap_power_sim_off_rsp(void *sap_device, sap_result_t result);
+int sap_power_sim_on_rsp(void *sap_device, sap_result_t result);
+int sap_reset_sim_rsp(void *sap_device, sap_result_t result);
+int sap_transfer_card_reader_status_rsp(void *sap_device, sap_result_t result, icc_reader_status_t status);
+int sap_error_rsp(void *sap_device);
+int sap_transport_protocol_rsp(void *sap_device, sap_result_t result);
+
+/* Event indication. Implemented by server.c*/
+int sap_status_ind(void *sap_device, sap_status_change_t status_change);
+
diff --git a/sap/server.c b/sap/server.c
new file mode 100644
index 0000000..683df5e
--- /dev/null
+++ b/sap/server.c
@@ -0,0 +1,1516 @@
+/*
+ *  BlueZ - Bluetooth protocol stack for Linux
+ *
+ *  Copyright (C) 2010 ST-Ericsson SA
+ *  Copyright (C) 2010 Claudio Takahasi<claudio.takahasi@openbossa.org>
+ *
+ *  Author: Marek Skowron <marek.skowron@tieto.com> for ST-Ericsson.
+ *  Author: Waldemar Rymarkiewicz <waldemar.rymarkiewicz@tieto.com> for ST-Ericsson.
+ *
+ *  This program 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; version 2 of the License.
+ *
+ *  This program 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 this program; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdio.h>
+#include <errno.h>
+#include <glib.h>
+#include <gdbus.h>
+#include <netinet/in.h>
+
+#include <bluetooth/bluetooth.h>
+#include <bluetooth/sdp.h>
+#include <bluetooth/sdp_lib.h>
+
+#include "adapter.h"
+#include "btio.h"
+#include "sdpd.h"
+#include "log.h"
+#include "error.h"
+#include "dbus-common.h"
+
+#include "sap.h"
+#include "server.h"
+
+#define SAP_SERVER_INTERFACE	"org.bluez.SimAccess"
+#define SAP_UUID		"0000112D-0000-1000-8000-00805F9B34FB"
+#define SAP_SERVER_CHANNEL	8
+#define SAP_BUF_SIZE		512
+
+#define PADDING4(x) (4 - (x & 0x03))
+#define PARAMETER_SIZE(x) (sizeof(sap_parameter) + x + PADDING4(x))
+
+#define SAP_NO_REQ 0xFF
+
+#define SAP_TIMER_GRACEFUL_DISCONNECT 30
+#define SAP_TIMER_NO_ACTIVITY 30
+
+typedef enum {
+	SAP_STATE_DISCONNECTED,
+	SAP_STATE_CONNECT_IN_PROGRESS,
+	SAP_STATE_CONNECTED,
+	SAP_STATE_GRACEFUL_DISCONNECT,
+	SAP_STATE_IMMEDIATE_DISCONNECT,
+	SAP_STATE_CLIENT_DISCONNECT
+} sap_state_t;
+
+struct sap_server {
+	bdaddr_t src;
+	char *path;
+	gboolean enable;
+	uint32_t record_id;
+	GIOChannel *listen_io;
+	GIOChannel *io;  /* Connected client channel.*/
+	sap_state_t state;
+	uint8_t processing_req;
+	guint timer_id;
+};
+
+static DBusConnection *connection = NULL;
+
+static void connect_req(void *data, sap_parameter *param);
+static int disconnect_req(void *data, sap_disconnection_type_t disc_type);
+static void transfer_apdu_req(void *data, sap_parameter *param);
+static void transfer_atr_req(void *data);
+static void power_sim_off_req(void *data);
+static void power_sim_on_req(void *data);
+static void reset_sim_req(void *data);
+static void transfer_card_reader_status_req(void *data);
+static void set_transport_protocol_req(void *data, sap_parameter *param);
+static int disconnect_ind(void *sap_device, sap_disconnection_type_t type);
+
+static gsize add_result_parameter(sap_result_t result, sap_parameter *param);
+
+static int is_power_sim_off_req_allowed(uint8_t processing_req);
+static int is_reset_sim_req_allowed(uint8_t processing_req);
+
+static int check_msg(sap_message *msg);
+
+static void start_guard_timer(struct sap_server *server, guint interval);
+static void stop_guard_timer(struct sap_server *server);
+static gboolean guard_timeout(gpointer data);
+
+static gsize add_result_parameter(sap_result_t result, sap_parameter *param)
+{
+	param->id = SAP_PARAM_ID_RESULT_CODE;
+	param->len = htons(SAP_PARAM_ID_RESULT_CODE_LEN);
+	*param->val = (uint8_t) result;
+	return PARAMETER_SIZE(SAP_PARAM_ID_RESULT_CODE_LEN);
+}
+
+
+static inline int is_power_sim_off_req_allowed(uint8_t processing_req)
+{
+	switch(processing_req) {
+	case SAP_NO_REQ:
+	case SAP_TRANSFER_APDU_REQ:
+	case SAP_TRANSFER_ATR_REQ:
+	case SAP_POWER_SIM_ON_REQ:
+	case SAP_RESET_SIM_REQ:
+	case SAP_TRANSFER_CARD_READER_STATUS_REQ:
+		return 1;
+	default:
+		return 0;
+	}
+}
+
+static inline int is_reset_sim_req_allowed(uint8_t processing_req)
+{
+	switch(processing_req) {
+	case SAP_NO_REQ:
+	case SAP_TRANSFER_APDU_REQ:
+	case SAP_TRANSFER_ATR_REQ:
+	case SAP_TRANSFER_CARD_READER_STATUS_REQ:
+		return 1;
+	default:
+		return 0;
+	}
+}
+
+static int check_msg(sap_message *msg)
+{
+	if(!msg)
+		return -EFAULT;
+
+	switch(msg->id) {
+	case SAP_CONNECT_REQ:
+		if (msg->nparam == 0x01 &&
+				msg->param->id == SAP_PARAM_ID_MAX_MSG_SIZE &&
+				ntohs(msg->param->len) == SAP_PARAM_ID_MAX_MSG_SIZE_LEN)
+			return 0;
+		break;
+	case SAP_TRANSFER_APDU_REQ:
+		if (msg->nparam == 0x01 &&
+				(msg->param->id == SAP_PARAM_ID_COMMAND_APDU ||
+				msg->param->id == SAP_PARAM_ID_COMMAND_APDU7816) &&
+				msg->param->len != 0x00)
+			return 0;
+		break;
+	case SAP_SET_TRANSPORT_PROTOCOL_REQ:
+		if (msg->nparam == 0x01 &&
+				msg->param->id == SAP_PARAM_ID_TRANSPORT_PROTOCOL &&
+				ntohs(msg->param->len) == SAP_PARAM_ID_TRANSPORT_PROTOCOL_LEN &&
+				(*msg->param->val  == SAP_TRANSPORT_PROTOCOL_T0 ||
+				*msg->param->val == SAP_TRANSPORT_PROTOCOL_T1))
+			return 0;
+		break;
+	case SAP_DISCONNECT_REQ:
+	case SAP_TRANSFER_ATR_REQ:
+	case SAP_POWER_SIM_OFF_REQ:
+	case SAP_POWER_SIM_ON_REQ:
+	case SAP_RESET_SIM_REQ:
+	case SAP_TRANSFER_CARD_READER_STATUS_REQ:
+		if (msg->nparam == 0x00)
+			return 0;
+		break;
+	}
+
+	error("Invalid message");
+	return -EBADMSG;
+}
+
+
+static void start_guard_timer(struct sap_server *server, guint interval)
+{
+	if(!server)
+		return;
+
+	if (!server->timer_id)
+		server->timer_id = g_timeout_add_seconds(interval,
+							guard_timeout, server);
+	else
+		error("Timer is already active.");
+}
+
+static void stop_guard_timer(struct sap_server *server)
+{
+	if (server && server->timer_id) {
+		g_source_remove(server->timer_id);
+		server->timer_id = 0;
+	}
+}
+
+static gboolean guard_timeout(gpointer data)
+{
+	struct sap_server *server = data;
+
+	if (!server)
+		return FALSE;
+
+	DBG("guard_timeout: state: %x pr %x", server->state,
+					server->processing_req);
+
+	server->timer_id = 0;
+
+	switch(server->state) {
+	case SAP_STATE_DISCONNECTED:
+		/* Client opened RFCOMM channel but didn't send CONNECT_REQ,
+		 * in fixed time or client disconnected SAP connection but
+		 * didn't closed RFCOMM channel in fixed time.*/
+		if (server->io)
+			g_io_channel_shutdown(server->io, TRUE, NULL);
+		break;
+	case SAP_STATE_GRACEFUL_DISCONNECT:
+		/* Client didn't disconnect SAP connection in fixed time,
+		 * so close SAP connection immediately. */
+		disconnect_req(server, SAP_DISCONNECTION_TYPE_IMMEDIATE);
+		break;
+	default:
+		error("guard_timeout: Unexpected state.");
+		break;
+	}
+
+	return FALSE;
+}
+
+static sdp_record_t *create_sap_record(uint8_t channel)
+{
+	sdp_list_t *apseq, *aproto, *profiles, *proto[2], *root, *svclass_id;
+	uuid_t sap_uuid, gt_uuid, root_uuid, l2cap, rfcomm;
+	sdp_profile_desc_t profile;
+	sdp_record_t *record;
+	sdp_data_t *ch;
+
+	record = sdp_record_alloc();
+	if (!record)
+		return NULL;
+
+	root = sdp_list_append(NULL, &root_uuid);
+	sdp_set_browse_groups(record, root);
+	sdp_list_free(root, NULL);
+
+	sdp_uuid16_create(&sap_uuid, SAP_SVCLASS_ID);
+	svclass_id = sdp_list_append(NULL, &sap_uuid);
+	sdp_uuid16_create(&gt_uuid, GENERIC_TELEPHONY_SVCLASS_ID);
+	svclass_id = sdp_list_append(svclass_id, &gt_uuid);
+
+	sdp_set_service_classes(record, svclass_id);
+	sdp_list_free(svclass_id, NULL);
+
+	sdp_uuid16_create(&profile.uuid, SAP_PROFILE_ID);
+	profile.version = SAP_VERSION;
+	profiles = sdp_list_append(NULL, &profile);
+	sdp_set_profile_descs(record, profiles);
+	sdp_list_free(profiles, NULL);
+
+	sdp_uuid16_create(&l2cap, L2CAP_UUID);
+	proto[0] = sdp_list_append(NULL, &l2cap);
+	apseq = sdp_list_append(NULL, proto[0]);
+
+	sdp_uuid16_create(&rfcomm, RFCOMM_UUID);
+	proto[1] = sdp_list_append(NULL, &rfcomm);
+	ch = sdp_data_alloc(SDP_UINT8, &channel);
+	proto[1] = sdp_list_append(proto[1], ch);
+	apseq = sdp_list_append(apseq, proto[1]);
+
+	aproto = sdp_list_append(NULL, apseq);
+	sdp_set_access_protos(record, aproto);
+
+	sdp_set_info_attr(record, "SIM Access Server",
+			NULL, NULL);
+
+	sdp_data_free(ch);
+	sdp_list_free(proto[0], NULL);
+	sdp_list_free(proto[1], NULL);
+	sdp_list_free(apseq, NULL);
+	sdp_list_free(aproto, NULL);
+
+	return record;
+}
+
+static int send_message(struct sap_server *server, gchar *buf, gssize size)
+{
+	gsize written = 0;
+	GError *gerr = NULL;
+	GIOStatus gstatus;
+
+	if(!server || !buf)
+		return -1;
+
+	DBG("send_message: size=%x",(unsigned int)size);
+
+	gstatus = g_io_channel_write_chars(server->io, buf, size, &written, &gerr);
+
+	if (gstatus != G_IO_STATUS_NORMAL) {
+		if (gerr)
+			g_error_free(gerr);
+
+		error("send_message:write error (%d)", gstatus);
+		return -1;
+	}
+	if(written != (gsize)size) {
+		error("send_message:write error. written %d size %d", written, size);
+	}
+	DBG("send_message: written=%x",(unsigned int)written);
+	return 0;
+}
+
+static void connect_req(void *data, sap_parameter *param)
+{
+	struct sap_server *server = data;
+	uint16_t maxmsgsize, *val;
+
+	if(!server || !param)
+		goto error_rsp;
+
+	if (server->state != SAP_STATE_DISCONNECTED)
+		goto error_rsp;
+
+	stop_guard_timer(server);
+
+	val = (uint16_t *) &param->val;
+	maxmsgsize = ntohs(*val);
+
+	DBG("Connect MaxMsgSize: 0x%04X(%d)", maxmsgsize, maxmsgsize);
+
+	server->state = SAP_STATE_CONNECT_IN_PROGRESS;
+
+	if (maxmsgsize <= SAP_BUF_SIZE){
+		server->processing_req = SAP_CONNECT_REQ;
+		sap_connect_req(server, maxmsgsize);
+	}else{
+		sap_connect_rsp(server, SAP_STATUS_MAX_MSG_SIZE_NOT_SUPPORTED,
+								SAP_BUF_SIZE);
+	}
+
+	return;
+
+error_rsp:
+	error("Wrong state (state %x pr %x)", server->state,
+						server->processing_req);
+	sap_error_rsp(data);
+}
+
+static int disconnect_req(void *data, sap_disconnection_type_t disc_type)
+{
+	struct sap_server *server = data;
+
+	if(!server)
+		goto error_rsp;
+
+	DBG("disconnect_req: type 0x%x state %d", disc_type, server->state);
+
+	switch(disc_type) {
+	case SAP_DISCONNECTION_TYPE_GRACEFUL:
+
+		if (server->state == SAP_STATE_DISCONNECTED ||
+				server->state == SAP_STATE_CONNECT_IN_PROGRESS)
+			goto error_req;
+
+		if (server->state == SAP_STATE_CONNECTED) {
+			server->state = SAP_STATE_GRACEFUL_DISCONNECT;
+			server->processing_req = SAP_NO_REQ;
+			disconnect_ind(server, disc_type);
+
+			/* Start guard timer - timer will disconnect connection
+			 * if client doesn't do it. */
+			start_guard_timer(server, SAP_TIMER_GRACEFUL_DISCONNECT);
+
+			return 0;
+		}
+		/* Disconnection is ongoing - do nothing. */
+		return 0;
+
+	case SAP_DISCONNECTION_TYPE_IMMEDIATE:
+
+		if (server->state == SAP_STATE_DISCONNECTED ||
+				server->state == SAP_STATE_CONNECT_IN_PROGRESS)
+			goto error_req;
+
+		if (server->state == SAP_STATE_CONNECTED ||
+				server->state == SAP_STATE_GRACEFUL_DISCONNECT) {
+			server->state = SAP_STATE_IMMEDIATE_DISCONNECT;
+			server->processing_req = SAP_NO_REQ;
+
+			stop_guard_timer(server);
+
+			disconnect_ind(server, disc_type);
+			sap_disconnect_req(server, 0);
+
+			return 0;
+		}
+		/* Disconnection is ongoing - do nothing. */
+		return 0;
+
+	case SAP_DISCONNECTION_TYPE_CLIENT:
+
+		if (server->state != SAP_STATE_CONNECTED &&
+				server->state != SAP_STATE_GRACEFUL_DISCONNECT)
+			goto error_rsp;
+
+		server->state = SAP_STATE_CLIENT_DISCONNECT;
+		server->processing_req = SAP_NO_REQ;
+
+		stop_guard_timer(server);
+
+		sap_disconnect_req(server, 0);
+
+		return 0;
+
+	default:
+		error("Unknown disconnection type (type %x).", disc_type);
+		return -EINVAL;
+	}
+
+error_rsp:
+	sap_error_rsp(server);
+error_req:
+	error("Wrong state (state %x pr %x)", server->state,
+						server->processing_req);
+	return -EPERM;
+}
+
+static void transfer_apdu_req(void * data, sap_parameter * param)
+{
+	struct sap_server *server = data;
+
+	if(!server || !param)
+		goto error_rsp;
+
+	param->len = ntohs(param->len);
+
+	DBG("transfer_apdu_req: data %p state %d", data, server->state);
+	DBG("transfer_apdu_req: apdu param id %d  val %s len %d ",
+					param->id, param->val, param->len);
+
+	if (server->state != SAP_STATE_CONNECTED &&
+			server->state != SAP_STATE_GRACEFUL_DISCONNECT)
+		goto error_rsp;
+
+	if (server->processing_req != SAP_NO_REQ)
+		goto error_rsp;
+
+	server->processing_req = SAP_TRANSFER_APDU_REQ;
+	sap_transfer_apdu_req(server, param);
+
+	return;
+
+error_rsp:
+	error("Wrong state (state %x pr %x)", server->state,
+						server->processing_req);
+	sap_error_rsp(server);
+}
+
+
+static void transfer_atr_req(void * data)
+{
+	struct sap_server *server = data;
+
+	if(!server)
+		goto error_rsp;
+
+	DBG("transfer_atr_req: data %p state %d", data, server->state);
+
+	if (server->state != SAP_STATE_CONNECTED)
+		goto error_rsp;
+
+	if (server->processing_req != SAP_NO_REQ)
+		goto error_rsp;
+
+	server->processing_req = SAP_TRANSFER_ATR_REQ;
+	sap_transfer_atr_req(server);
+
+	return;
+
+error_rsp:
+	error("Wrong state (state %x pr %x)", server->state,
+						server->processing_req);
+	sap_error_rsp(server);
+}
+
+
+static void power_sim_off_req(void *data)
+{
+	struct sap_server *server = data;
+
+	if(!server)
+		goto error_rsp;
+
+	DBG("power_sim_off_req: data %p state %d", data, server->state);
+
+	if (server->state != SAP_STATE_CONNECTED)
+		goto error_rsp;
+
+	if (!is_power_sim_off_req_allowed(server->processing_req))
+		goto error_rsp;
+
+	server->processing_req = SAP_POWER_SIM_OFF_REQ;
+	sap_power_sim_off_req(server);
+
+	return;
+
+error_rsp:
+	error("Wrong state (state %x pr %x)", server->state,
+						server->processing_req);
+	sap_error_rsp(server);
+}
+
+static void power_sim_on_req(void *data)
+{
+	struct sap_server *server = data;
+
+	if(!server)
+		goto error_rsp;
+
+	DBG("power_sim_on_req: data %p state %d", data, server->state);
+
+	if (server->state != SAP_STATE_CONNECTED)
+		goto error_rsp;
+
+	if (server->processing_req != SAP_NO_REQ)
+		goto error_rsp;
+
+	server->processing_req = SAP_POWER_SIM_ON_REQ;
+	sap_power_sim_on_req(server);
+
+	return;
+
+error_rsp:
+	error("Wrong state (state %x pr %x)", server->state,
+						server->processing_req);
+	sap_error_rsp(server);
+}
+
+static void reset_sim_req(void *data)
+{
+	struct sap_server *server = data;
+
+	if(!server)
+		goto error_rsp;
+
+	DBG("reset_sim_req: data %p state %d", data, server->state);
+
+	if (server->state != SAP_STATE_CONNECTED)
+		goto error_rsp;
+
+	if (!is_reset_sim_req_allowed(server->processing_req))
+		goto error_rsp;
+
+	server->processing_req = SAP_RESET_SIM_REQ;
+	sap_reset_sim_req(server);
+
+	return;
+
+error_rsp:
+	error("Wrong state (state %x pr %x)", server->state,
+						server->processing_req);
+	sap_error_rsp(server);
+}
+
+static void transfer_card_reader_status_req(void * data)
+{
+	struct sap_server *server = data;
+
+	if(!server)
+		goto error_rsp;
+
+	DBG("transfer_card_reader_status_req: data %p state %d",
+							data, server->state);
+
+	if (server->state != SAP_STATE_CONNECTED)
+		goto error_rsp;
+
+	if (server->processing_req != SAP_NO_REQ)
+		goto error_rsp;
+
+	server->processing_req = SAP_TRANSFER_CARD_READER_STATUS_REQ;
+	sap_transfer_card_reader_status_req(server);
+
+	return;
+
+error_rsp:
+	error("Wrong state (state %x pr %x)", server->state,
+						server->processing_req);
+	sap_error_rsp(server);
+}
+
+static void set_transport_protocol_req(void *data, sap_parameter *param)
+{
+	struct sap_server *server = data;
+
+	if(!server || !param)
+		goto error_rsp;
+
+	DBG("set_transport_protocol_req: data %p state %d param %p",
+						data, server->state, param);
+
+	if (server->state != SAP_STATE_CONNECTED)
+		goto error_rsp;
+
+	if (server->processing_req != SAP_NO_REQ)
+		goto error_rsp;
+
+	server->processing_req = SAP_SET_TRANSPORT_PROTOCOL_REQ;
+	sap_set_transport_protocol_req(server, param);
+
+	return;
+
+error_rsp:
+	error("Wrong state (state %x pr %x)", server->state,
+						server->processing_req);
+	sap_error_rsp(server);
+}
+
+static int disconnect_ind(void *sap_device, sap_disconnection_type_t type)
+{
+	struct sap_server *server = sap_device;
+	gchar buf[SAP_BUF_SIZE];
+	sap_message *msg = (sap_message *) buf;
+	sap_parameter *param = (sap_parameter *) msg->param;
+	gsize size = sizeof(sap_message);
+
+	if(!server)
+		return -1;
+
+	DBG("disconnect_ind: data %p state %d disc_type %d",
+						server, server->state, type);
+
+	if (server->state != SAP_STATE_GRACEFUL_DISCONNECT &&
+			server->state != SAP_STATE_IMMEDIATE_DISCONNECT)
+		goto error_ind;
+
+	memset(buf, 0, sizeof(buf));
+	msg->id = SAP_DISCONNECT_IND;
+	msg->nparam = 0x01;
+
+	/* Add disconnection type. */
+	param->id  = SAP_PARAM_ID_DISCONNECT_IND;
+	param->len = htons(SAP_PARAM_ID_DISCONNECT_IND_LEN);
+	*param->val = (uint8_t) type;
+	size += PARAMETER_SIZE(SAP_PARAM_ID_DISCONNECT_IND_LEN);
+
+	return send_message(sap_device, buf, size);
+
+error_ind:
+	error("Wrong state (state %x pr %x)", server->state,
+						server->processing_req);
+	return -EPERM;
+}
+
+int sap_connect_rsp(void *sap_device, sap_status_t status, uint16_t maxmsgsize)
+{
+	struct sap_server *server = sap_device;
+	gchar buf[SAP_BUF_SIZE];
+	sap_message *msg = (sap_message *) buf;
+	sap_parameter *param = (sap_parameter *) msg->param;
+	gsize size = sizeof(sap_message);
+
+	if(!server)
+		return -1;
+
+	DBG("sap_connect_rsp: state %x pr %x status %x", server->state,
+					server->processing_req, status);
+
+	if (server->state != SAP_STATE_CONNECT_IN_PROGRESS) {
+		return -EPERM;
+	}
+
+	memset(buf, 0, sizeof(buf));
+	msg->id = SAP_CONNECT_RESP;
+	msg->nparam = 0x01;
+
+	/* Add connection status */
+	param->id = SAP_PARAM_ID_CONN_STATUS;
+	param->len = htons(SAP_PARAM_ID_CONN_STATUS_LEN);
+	*param->val = (uint8_t)status;
+	size += PARAMETER_SIZE(SAP_PARAM_ID_CONN_STATUS_LEN);
+
+	/* Add MaxMsgSize */
+	if (maxmsgsize && (status == SAP_STATUS_MAX_MSG_SIZE_NOT_SUPPORTED ||
+			status == SAP_STATUS_MAX_MSG_SIZE_TOO_SMALL)) {
+		uint16_t *len;
+		msg->nparam++;
+		/* Skip the first param */
+		param = (sap_parameter *) &buf[size];
+		param->id = SAP_PARAM_ID_MAX_MSG_SIZE;
+		param->len = htons(SAP_PARAM_ID_MAX_MSG_SIZE_LEN);
+		len = (uint16_t *) &param->val;
+		*len = htons(maxmsgsize);
+		size += PARAMETER_SIZE(SAP_PARAM_ID_MAX_MSG_SIZE_LEN);
+	}
+
+	if (status == SAP_STATUS_OK) {
+		gboolean connected = TRUE;
+		emit_property_changed(connection, server->path, SAP_SERVER_INTERFACE,
+			"Connected", DBUS_TYPE_BOOLEAN, &connected);
+
+		server->state = SAP_STATE_CONNECTED;
+	} else {
+		server->state = SAP_STATE_DISCONNECTED;
+
+		/* Timer will shutdown channel if client doesn't send
+		 * CONNECT_REQ or doesn't shutdown channel itself.*/
+		start_guard_timer(server, SAP_TIMER_NO_ACTIVITY);
+	}
+
+	server->processing_req = SAP_NO_REQ;
+	return send_message(sap_device, buf, size);
+}
+
+int sap_disconnect_rsp(void *sap_device)
+{
+	struct sap_server *server = sap_device;
+	sap_message msg = {0};
+
+	if(!server)
+		return -1;
+
+	DBG("sap_disconnect_rsp: state %x pr %x", server->state,
+					server->processing_req);
+
+	switch(server->state) {
+	case SAP_STATE_CLIENT_DISCONNECT:
+		msg.id = SAP_DISCONNECT_RESP;
+
+		server->state = SAP_STATE_DISCONNECTED;
+		server->processing_req = SAP_NO_REQ;
+
+		/* Timer will close channel if client doesn't do it.*/
+		start_guard_timer(server, SAP_TIMER_NO_ACTIVITY);
+
+		return send_message(sap_device, (gchar *) &msg, sizeof(msg));
+
+	case SAP_STATE_IMMEDIATE_DISCONNECT:
+		server->state = SAP_STATE_DISCONNECTED;
+		server->processing_req = SAP_NO_REQ;
+
+		if (server->io)
+			g_io_channel_shutdown(server->io, TRUE, NULL);
+		return 0;
+	default:
+		break;
+	}
+
+	return 0;
+}
+
+int sap_transfer_apdu_rsp(void *sap_device, sap_result_t result, uint8_t *apdu,
+								uint16_t length)
+{
+	struct sap_server *server = sap_device;
+	gchar buf[SAP_BUF_SIZE] = {0};
+	sap_message *msg = (sap_message *) buf;
+	sap_parameter *param = (sap_parameter *) msg->param;
+	gsize size = sizeof(sap_message);
+
+	if(!server)
+		return -1;
+
+	DBG("sap_transfer_apdu_rsp: state %x pr %x", server->state,
+					server->processing_req);
+
+	if (server->processing_req != SAP_TRANSFER_APDU_REQ)
+		/* Ignore this response because processing (state) request
+		 * has been changed. This situation can happen e.g. when
+		 * client sends disconnect request while server is processing
+		 * another request.*/
+		return 0;
+
+	if (result == SAP_RESULT_OK && (!apdu || (apdu && length == 0x00)))
+		return -EINVAL;
+
+	msg->id = SAP_TRANSFER_APDU_RESP;
+
+	/* Add result code */
+	msg->nparam = 0x01;
+	size += add_result_parameter(result, param);
+
+	/* Add APDU response. */
+	if (result == SAP_RESULT_OK) {
+		msg->nparam++;
+		/* Skipping the first param. */
+		param = (sap_parameter *) &buf[size];
+		param->id = SAP_PARAM_ID_RESPONSE_APDU;
+		param->len = htons(length);
+
+		size += PARAMETER_SIZE(length);
+		if (size > SAP_BUF_SIZE)
+			return -EOVERFLOW;
+
+		memcpy(param->val, apdu, length);
+	}
+
+	server->processing_req = SAP_NO_REQ;
+	return send_message(sap_device, buf, size);
+}
+
+int sap_transfer_atr_rsp(void *sap_device, sap_result_t result, uint8_t *atr,
+								uint16_t length)
+{
+	struct sap_server *server = sap_device;
+	gchar buf[SAP_BUF_SIZE]= {0};
+	sap_message *msg = (sap_message *) buf;
+	sap_parameter *param = (sap_parameter *) msg->param;
+	gsize size = sizeof(sap_message);
+
+	if(!server)
+		return -1;
+
+	DBG("sap_transfer_atr_rsp: state %x pr %x", server->state,
+					server->processing_req);
+
+	if (server->processing_req != SAP_TRANSFER_ATR_REQ)
+		/* Ignore this response because processing (state) request
+		 * has been changed. This situation can happen e.g. when
+		 * client sends disconnect request while server is processing
+		 * another request.*/
+		return 0;
+
+	if (result == SAP_RESULT_OK && (!atr || (atr && length == 0x00)))
+		return -EINVAL;
+
+	msg->id = SAP_TRANSFER_ATR_RESP;
+
+	/* Add result code */
+	msg->nparam = 0x01;
+	size += add_result_parameter(result, param);
+
+	/* Add ATR response */
+	if (result == SAP_RESULT_OK) {
+		msg->nparam++;
+		/* Skip the first param */
+		param = (sap_parameter *) &buf[size];
+		param->id = SAP_PARAM_ID_ATR;
+		param->len = htons(length);
+
+		size += PARAMETER_SIZE(length);
+		if (size > SAP_BUF_SIZE)
+			return -EOVERFLOW;
+
+		memcpy(param->val, atr, length);
+	}
+
+	server->processing_req = SAP_NO_REQ;
+	return send_message(sap_device, buf, size);
+}
+
+int sap_power_sim_off_rsp(void *sap_device, sap_result_t result)
+{
+	struct sap_server *server = sap_device;
+	gchar buf[SAP_BUF_SIZE] = {0};
+	sap_message *msg = (sap_message *) buf;
+	gsize size = sizeof(sap_message);
+
+	if(!server)
+		return -1;
+
+	DBG("sap_power_sim_off_rsp: state %x pr %x", server->state,
+					server->processing_req);
+
+	if (server->processing_req != SAP_POWER_SIM_OFF_REQ)
+		/* Ignore this response because processing (state) request
+		 * has been changed. This situation can happen e.g. when
+		 * client sends disconnect request while server is processing
+		 * another request.*/
+		return 0;
+
+	msg->id = SAP_POWER_SIM_OFF_RESP;
+
+	/* Add result code.*/
+	msg->nparam = 0x01;
+	size += add_result_parameter(result, msg->param);
+
+	server->processing_req = SAP_NO_REQ;
+	return send_message(sap_device, buf, size);
+}
+
+int sap_power_sim_on_rsp(void *sap_device, sap_result_t result)
+{
+	struct sap_server *server = sap_device;
+	gchar buf[SAP_BUF_SIZE] = {0};
+	sap_message *msg = (sap_message *) buf;
+	gsize size = sizeof(sap_message);
+
+	if(!server)
+		return -1;
+
+	DBG("sap_power_sim_on_rsp: state %x pr %x", server->state,
+					server->processing_req);
+
+	if (server->processing_req != SAP_POWER_SIM_ON_REQ)
+		/* Ignore this response because processing (state) request
+		 * has been changed. This situation can happen e.g. when
+		 * client sends disconnect request while server is processing
+		 * another request.*/
+		return 0;
+
+	msg->id = SAP_POWER_SIM_ON_RESP;
+
+	/* Add result code */
+	msg->nparam = 0x01;
+	size += add_result_parameter(result, msg->param);
+
+	server->processing_req = SAP_NO_REQ;
+	return send_message(sap_device, buf, size);
+}
+
+int sap_reset_sim_rsp(void *sap_device, sap_result_t result)
+{
+	struct sap_server *server = sap_device;
+	gchar buf[SAP_BUF_SIZE] = {0};
+	sap_message *msg = (sap_message *) buf;
+	gsize size = sizeof(sap_message);
+
+	if(!server)
+		return -1;
+
+	DBG("sap_reset_sim_rsp: state %x pr %x", server->state,
+					server->processing_req);
+
+	if (server->processing_req != SAP_RESET_SIM_REQ)
+		/* Ignore this response because processing (state) request
+		 * has been changed. This situation can happen e.g. when
+		 * client sends disconnect request while server is processing
+		 * another request.*/
+		return 0;
+
+	msg->id = SAP_RESET_SIM_RESP;
+
+	/* Add result code */
+	msg->nparam = 0x01;
+	size += add_result_parameter(result, msg->param);
+
+	server->processing_req = SAP_NO_REQ;
+	return send_message(sap_device, buf, size);
+}
+
+int sap_transfer_card_reader_status_rsp(void *sap_device, sap_result_t result,
+						icc_reader_status_t status)
+{
+	struct sap_server *server = sap_device;
+	gchar buf[SAP_BUF_SIZE] = {0};
+	sap_message *msg = (sap_message *) buf;
+	sap_parameter *param = (sap_parameter *) msg->param;
+	gsize size = sizeof(sap_message);
+
+	if(!server)
+		return -1;
+
+	DBG("sap_transfer_card_reader_status_rsp: state %x pr %x", server->state,
+					server->processing_req);
+
+	if (server->processing_req != SAP_TRANSFER_CARD_READER_STATUS_REQ)
+		/* Ignore this response because processing (state) request
+		 * has been changed. This situation can happen e.g. when
+		 * client sends disconnect request while server is processing
+		 * another request.*/
+		return 0;
+
+	msg->id = SAP_TRANSFER_CARD_READER_STATUS_RESP;
+
+	/* Add result code */
+	msg->nparam = 0x01;
+	size += add_result_parameter(result, param);
+
+	/* Add card reader status. */
+	if (result == SAP_RESULT_OK) {
+		msg->nparam++;
+		/* Skipp the first param. */
+		param = (sap_parameter *) &buf[size];
+		param->id = SAP_PARAM_ID_CARD_READER_STATUS;
+		param->len = htons(SAP_PARAM_ID_CARD_READER_STATUS_LEN);
+		*param->val = (uint8_t) status;
+		size += PARAMETER_SIZE(SAP_PARAM_ID_CARD_READER_STATUS_LEN);
+	}
+
+	server->processing_req = SAP_NO_REQ;
+	return send_message(sap_device, buf, size);
+}
+
+int sap_transport_protocol_rsp(void *sap_device, sap_result_t result)
+{
+	struct sap_server *server = sap_device;
+	gchar buf[SAP_BUF_SIZE] = {0};
+	sap_message *msg = (sap_message *) buf;
+	gsize size = sizeof(sap_message);
+
+	if(!server)
+		return -1;
+
+	DBG("sap_transport_protocol_rsp: state %x pr %x", server->state,
+					server->processing_req);
+
+	if (server->processing_req != SAP_SET_TRANSPORT_PROTOCOL_REQ)
+		/* Ignore this response because processing (state) request
+		 * has been changed. This situation can happen e.g. when
+		 * client sends disconnect request while server is processing
+		 * another request.*/
+		return 0;
+
+	msg->id = SAP_SET_TRANSPORT_PROTOCOL_RESP;
+
+	/* Add result code */
+	msg->nparam = 0x01;
+	size += add_result_parameter(result, msg->param);
+
+	server->processing_req = SAP_NO_REQ;
+	return send_message(sap_device, buf, size);
+}
+
+int sap_error_rsp(void *sap_device)
+{
+	sap_message msg;
+
+	memset(&msg, 0, sizeof(msg));
+	msg.id = SAP_ERROR_RESP;
+
+	return send_message(sap_device, (gchar *) &msg, sizeof(msg));
+}
+
+int sap_status_ind(void *sap_device, sap_status_change_t status_change)
+{
+	struct sap_server *server = sap_device;
+	gchar buf[SAP_BUF_SIZE] = {0};
+	sap_message *msg = (sap_message *) buf;
+	sap_parameter *param = (sap_parameter *) msg->param;
+	gsize size = sizeof(sap_message);
+
+	if(!server)
+		return -1;
+
+	DBG("sap_status_ind: state %x pr %x", server->state,
+					server->processing_req);
+
+	if (server->state != SAP_STATE_CONNECTED &&
+			server->state != SAP_STATE_GRACEFUL_DISCONNECT)
+		/*Don't propagate status indication if client is not connected */
+		return 0;
+
+	msg->id = SAP_STATUS_IND;
+	msg->nparam = 0x01;
+
+	/* Add status change. */
+	param->id  = SAP_PARAM_ID_STATUS_CHANGE;
+	param->len = htons(SAP_PARAM_ID_STATUS_CHANGE_LEN);
+	*param->val = (uint8_t) status_change;
+	size += PARAMETER_SIZE(SAP_PARAM_ID_STATUS_CHANGE_LEN);
+
+	return send_message(sap_device, buf, size);
+}
+
+static int handle_cmd(void *data, gchar *buf, gsize size)
+{
+	sap_message *msg = (sap_message *) buf;
+
+	if (size < sizeof(sap_message))
+		goto error_rsp;
+
+	if (msg->nparam != 0 &&
+			size < (sizeof(sap_message) + sizeof(sap_parameter) + 4))
+		goto error_rsp;
+
+	if (check_msg(msg) < 0)
+		goto error_rsp;
+
+	switch(msg->id) {
+		case SAP_CONNECT_REQ:
+			DBG("SAP Connect.");
+			connect_req(data, msg->param);
+			return 0;
+		case SAP_DISCONNECT_REQ:
+			DBG("SAP Disconnect.");
+			disconnect_req(data, SAP_DISCONNECTION_TYPE_CLIENT);
+			return 0;
+		case SAP_TRANSFER_APDU_REQ:
+			DBG("SAP Transfer APDU.");
+			transfer_apdu_req(data, msg->param);
+			return 0;
+		case SAP_TRANSFER_ATR_REQ:
+			DBG("SAP Transfer ATR.");
+			transfer_atr_req(data);
+			return 0;
+		case SAP_POWER_SIM_OFF_REQ:
+			DBG("SAP SIM off.");
+			power_sim_off_req(data);
+			return 0;
+		case SAP_POWER_SIM_ON_REQ:
+			DBG("SAP SIM on.");
+			power_sim_on_req(data);
+			return 0;
+		case SAP_RESET_SIM_REQ:
+			DBG("SAP SIM reset.");
+			reset_sim_req(data);
+			return 0;
+		case SAP_TRANSFER_CARD_READER_STATUS_REQ:
+			DBG("SAP reader status.");
+			transfer_card_reader_status_req(data);
+			return 0;
+		case SAP_SET_TRANSPORT_PROTOCOL_REQ:
+			DBG("SAP set proto request.");
+			set_transport_protocol_req(data, msg->param);
+			return 0;
+		default:
+			DBG("SAP unknown message.");
+			break;
+	}
+
+error_rsp:
+	DBG("SAP ERROR RSP");
+	sap_error_rsp(data);
+	return -EBADMSG;
+}
+
+static gboolean sap_io_cb(GIOChannel *chan, GIOCondition cond, void *data)
+{
+	gchar buf[SAP_BUF_SIZE];
+	gsize bytes_read = 0;
+	GError *gerr = NULL;
+	GIOStatus gstatus;
+
+	if (cond & G_IO_NVAL){
+		DBG("ERR (G_IO_NVAL) on rfcomm socket.");
+		return FALSE;
+	}
+
+	if (cond & G_IO_ERR) {
+		DBG("ERR (G_IO_ERR) on rfcomm socket.");
+		return FALSE;
+	}
+
+	if (cond & G_IO_HUP ) {
+		DBG("HUP on rfcomm socket.");
+		return FALSE;
+	}
+
+	gstatus = g_io_channel_read_chars(chan, buf, sizeof(buf) - 1,
+				&bytes_read, &gerr);
+
+	if (gstatus != G_IO_STATUS_NORMAL) {
+		if(gerr)
+			g_error_free(gerr);
+		return TRUE;
+	}
+
+	if (handle_cmd(data, buf, bytes_read) < 0) {
+		error("Invalid SAP message.");
+	}
+
+	return TRUE;
+}
+
+static void sap_io_destroy(void *data)
+{
+	struct sap_server *server = data;
+
+	if (server && server->io) {
+		gboolean connected = FALSE;
+
+		stop_guard_timer(server);
+
+		g_io_channel_shutdown(server->io, TRUE, NULL);
+		g_io_channel_unref(server->io);
+
+		server->io = NULL;
+
+		if (server->state != SAP_STATE_CONNECT_IN_PROGRESS)
+			emit_property_changed(connection, server->path,
+				SAP_SERVER_INTERFACE,"Connected",
+				DBUS_TYPE_BOOLEAN, &connected);
+
+		if (server->state == SAP_STATE_CONNECT_IN_PROGRESS ||
+					server->state == SAP_STATE_CONNECTED ||
+					server->state == SAP_STATE_GRACEFUL_DISCONNECT){
+				sap_disconnect_req(NULL, 1);
+			}
+
+		server->state = SAP_STATE_DISCONNECTED;
+	}
+}
+
+static void sap_connect_cb(GIOChannel *chan, GError *gerr, gpointer data)
+{
+	struct sap_server *server = data;
+
+	if(!server)
+		return;
+
+	/* Timer will shutdown the channel in case of lack of client activity */
+	start_guard_timer(server, SAP_TIMER_NO_ACTIVITY);
+
+	g_io_add_watch_full(chan, G_PRIORITY_DEFAULT,
+			G_IO_IN | G_IO_ERR | G_IO_HUP| G_IO_NVAL,
+			(GIOFunc) sap_io_cb, server, sap_io_destroy);
+}
+
+static void connect_auth_cb(DBusError *derr, void *data)
+{
+	struct sap_server *server = data;
+	GError *gerr = NULL;
+
+	if(!server || !server->io)
+		return;
+
+	if (derr && dbus_error_is_set(derr)) {
+		error("Access denied: %s", derr->message);
+		goto drop;
+	}
+
+	if (!bt_io_accept(server->io, sap_connect_cb, server, NULL, &gerr)) {
+		error("bt_io_accept: %s", gerr->message);
+		g_error_free(gerr);
+		goto drop;
+	}
+	return;
+
+drop:
+	g_io_channel_shutdown(server->io, TRUE, NULL);
+	g_io_channel_unref(server->io);
+	server->io = NULL;
+}
+
+static void connect_confirm_cb(GIOChannel *chan, gpointer data)
+{
+	struct sap_server *server = data;
+	GError *gerr = NULL;
+	bdaddr_t src, dst;
+	int err;
+
+	if(!chan || !server)
+		return;
+
+	if (server->io)
+		goto drop;
+
+	bt_io_get(chan, BT_IO_RFCOMM, &gerr,
+			BT_IO_OPT_SOURCE_BDADDR, &src,
+			BT_IO_OPT_DEST_BDADDR, &dst,
+			BT_IO_OPT_INVALID);
+	if (gerr) {
+		error("%s", gerr->message);
+		g_error_free(gerr);
+		goto drop;
+	}
+
+	server->io = g_io_channel_ref(chan);
+
+	err = btd_request_authorization(&src, &dst, SAP_UUID, connect_auth_cb, server);
+
+	if (err < 0) {
+		DBG("Authorization denied: %s", strerror(err));
+		goto drop;
+	}
+
+	DBG("SAP incoming connection (sock %d) authorization.", g_io_channel_unix_get_fd(chan));
+
+	return;
+
+drop:
+	g_io_channel_shutdown(chan, TRUE, NULL);
+	if (server->io && server->io == chan) {
+		g_io_channel_unref(server->io);
+		server->io = NULL;
+	}
+}
+
+
+
+static inline DBusMessage *message_failed(DBusMessage *msg,
+					const char *description)
+{
+	return g_dbus_create_error(msg, ERROR_INTERFACE ".Failed",
+				"%s", description);
+}
+
+static DBusMessage *enable(DBusConnection *conn,
+			DBusMessage *msg, void *data)
+{
+	struct sap_server *server = data;
+	sdp_record_t *record = NULL;
+	GIOChannel *io = NULL;
+	GError *gerr = NULL;
+
+	if (!server)
+		return message_failed(msg, "Server internal error.");
+
+	if (server->enable)
+		return message_failed(msg, "Server already enabled.");
+
+	record = create_sap_record(SAP_SERVER_CHANNEL);
+	if (!record)
+		return message_failed(msg, "Can't create SDP record for SAP.");
+
+	if (add_record_to_server(&server->src, record) < 0) {
+		sdp_record_free(record);
+		return message_failed(msg, "SDP record registration failed.");
+	}
+
+	io = bt_io_listen(BT_IO_RFCOMM, NULL, connect_confirm_cb, server, NULL, &gerr,
+			BT_IO_OPT_SOURCE_BDADDR, &server->src,
+			BT_IO_OPT_CHANNEL, SAP_SERVER_CHANNEL,
+			BT_IO_OPT_SEC_LEVEL, BT_IO_SEC_HIGH,
+			BT_IO_OPT_MASTER, TRUE,
+			BT_IO_OPT_INVALID);
+	if (!io) {
+		g_error_free(gerr);
+		sdp_record_free(record);
+		return message_failed(msg, "Listen rfcomm channel failed.");
+	}
+
+	DBG("Listen socket %x", g_io_channel_unix_get_fd(io));
+
+	server->enable = TRUE;
+	server->record_id = record->handle;
+	server->listen_io = io;
+
+	emit_property_changed(connection, server->path, SAP_SERVER_INTERFACE,
+				"Enabled", DBUS_TYPE_BOOLEAN, &server->enable);
+
+	return dbus_message_new_method_return(msg);
+}
+
+static DBusMessage *disable(DBusConnection *conn,
+				DBusMessage *msg, void *data)
+{
+	struct sap_server *server = data;
+	DBusMessage *reply = NULL;
+
+	if(!server)
+		return message_failed(msg, "Server internal error.");
+
+	if (!server->enable)
+		return message_failed(msg, "Server already disabled.");
+
+	if (server->state != SAP_STATE_DISCONNECTED)
+		return message_failed(msg, "Ongoing connection exists.");
+
+	reply = dbus_message_new_method_return(msg);
+	if (!reply)
+		return NULL;
+
+	remove_record_from_server(server->record_id);
+
+	if (server->listen_io) {
+		g_io_channel_shutdown(server->listen_io, TRUE, NULL);
+		g_io_channel_unref(server->listen_io);
+		server->listen_io = NULL;
+	}
+
+	server->enable = FALSE;
+
+	emit_property_changed(connection, server->path, SAP_SERVER_INTERFACE,
+				"Enabled", DBUS_TYPE_BOOLEAN, &server->enable);
+
+	return reply;
+}
+
+static DBusMessage *get_properties(DBusConnection *conn,
+				DBusMessage *msg, void *data)
+{
+	struct sap_server *server = data;
+	DBusMessage *reply;
+	DBusMessageIter iter;
+	DBusMessageIter dict;
+	dbus_bool_t connected;
+
+	if(!server)
+		return message_failed(msg, "Server internal error.");
+
+	reply = dbus_message_new_method_return(msg);
+	if (!reply)
+		return NULL;
+
+	dbus_message_iter_init_append(reply, &iter);
+
+	dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY,
+			DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING
+			DBUS_TYPE_STRING_AS_STRING DBUS_TYPE_VARIANT_AS_STRING
+			DBUS_DICT_ENTRY_END_CHAR_AS_STRING, &dict);
+
+	dict_append_entry(&dict, "Enabled", DBUS_TYPE_BOOLEAN, &server->enable);
+
+	connected = (server->state == SAP_STATE_CONNECTED ||
+			server->state == SAP_STATE_GRACEFUL_DISCONNECT);
+	dict_append_entry(&dict, "Connected", DBUS_TYPE_BOOLEAN, &connected);
+
+	dbus_message_iter_close_container(&iter, &dict);
+
+	return reply;
+}
+
+static DBusMessage *disconnect(DBusConnection *conn, DBusMessage *msg, void *data)
+{
+	struct sap_server *server = data;
+	dbus_bool_t disc_type;
+	sap_disconnection_type_t sap_disc_type;
+
+	if (!server)
+		return message_failed(msg, "Server internal error.");
+
+	if (!server->enable)
+		return g_dbus_create_error(msg, ERROR_INTERFACE
+				".Failed",
+				"Server already disabled");
+
+	if (dbus_message_get_args(msg, NULL, DBUS_TYPE_BOOLEAN, &disc_type,
+						DBUS_TYPE_INVALID) == FALSE)
+		return NULL;
+
+	sap_disc_type = disc_type ? SAP_DISCONNECTION_TYPE_GRACEFUL :
+				SAP_DISCONNECTION_TYPE_IMMEDIATE;
+	if (disconnect_req(server, sap_disc_type) < 0)
+		return g_dbus_create_error(msg, ERROR_INTERFACE
+				".Failed",
+				"There is no active connection");
+
+	return dbus_message_new_method_return(msg);
+}
+
+static GDBusMethodTable server_methods[] = {
+	{ "Enable","","", enable },
+	{ "Disable","","", disable },
+	{ "GetProperties","","a{sv}",get_properties },
+	{ "Disconnect","b","", disconnect },
+	{ }
+};
+
+static GDBusSignalTable server_signals[] = {
+	{ "PropertyChanged",		"sv"},
+	{ }
+};
+
+static void server_free(struct sap_server *server)
+{
+	DBG("[%s::%s]", __FILE__, __FUNCTION__);
+
+	if (!server)
+		return;
+
+	g_free(server->path);
+	g_free(server);
+}
+
+static void destroy_sap_interface(void *data)
+{
+	struct sap_server *server = data;
+
+	DBG("Unregistered interface %s on path %s",
+			SAP_SERVER_INTERFACE, server->path);
+
+	server_free(server);
+}
+
+int sap_server_register(const char *path, bdaddr_t *src)
+{
+	struct sap_server *server;
+
+	if(sap_init() < 0) {
+		error("Sap driver initialization failed.");
+		return -1;
+	}
+
+	server = g_new0(struct sap_server, 1);
+
+	if (!server) {
+		sap_exit();
+		return -ENOMEM;
+	}
+
+	server->enable = FALSE;
+
+	if (!g_dbus_register_interface(connection, path, SAP_SERVER_INTERFACE,
+				server_methods, server_signals, NULL,
+				server, destroy_sap_interface)) {
+		error("D-Bus failed to register %s interface",
+						SAP_SERVER_INTERFACE);
+		server_free(server);
+		sap_exit();
+		return -1;
+	}
+
+	server->path = g_strdup(path);
+	bacpy(&server->src, src);
+
+	return 0;
+}
+
+int sap_server_unregister(const char *path)
+{
+	g_dbus_unregister_interface(connection, path, SAP_SERVER_INTERFACE);
+	sap_exit();
+	return 0;
+}
+
+int sap_server_init(DBusConnection *conn)
+{
+	connection = dbus_connection_ref(conn);
+	return 0;
+}
+
+void sap_server_exit(void)
+{
+	dbus_connection_unref(connection);
+	connection = NULL;
+}
diff --git a/sap/server.h b/sap/server.h
new file mode 100644
index 0000000..6e7f6fc
--- /dev/null
+++ b/sap/server.h
@@ -0,0 +1,23 @@
+/*
+ *  BlueZ - Bluetooth protocol stack for Linux
+ *
+ *  Copyright (C) 2010 Claudio Takahasi<claudio.takahasi@openbossa.org>
+ *
+ *  This program 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; version 2 of the License.
+ *
+ *  This program 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 this program; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+int sap_server_init(DBusConnection *conn);
+void sap_server_exit(void);
+int sap_server_register(const char *path, bdaddr_t *src);
+int sap_server_unregister(const char *path);
-- 
1.7.0.4

^ permalink raw reply related	[flat|nested] 4+ messages in thread

* Re: [PATCH 1/1] Add Sim Access Plugin
  2010-10-20  7:55 ` [PATCH 1/1] Add Sim Access Plugin Waldemar Rymarkiewicz
@ 2010-10-20  8:37   ` Suraj Sumangala
  2010-10-20  8:47     ` Waldemar.Rymarkiewicz
  0 siblings, 1 reply; 4+ messages in thread
From: Suraj Sumangala @ 2010-10-20  8:37 UTC (permalink / raw)
  To: Waldemar Rymarkiewicz
  Cc: linux-bluetooth@vger.kernel.org, Marcel Holtmann, Suraj Sumangala,
	Johan Hedberg, joakim.xj.ceder@stericsson.com,
	arunkr.singh@stericsson.com

Hi Waldemar,

On 10/20/2010 1:25 PM, Waldemar Rymarkiewicz wrote:
> Sim Access plugin implements Sim Access Profile server role
> according to the Bluetooth Sim Access Profile v1.1 specification.
> ---
>   .gitignore      |    1 +
>   Makefile.am     |   25 +-
>   acinclude.m4    |   14 +
>   doc/sap-api.txt |   57 ++
>   sap/main.c      |   54 ++
>   sap/manager.c   |   94 ++++
>   sap/manager.h   |   21 +
>   sap/sap-dummy.c |  306 +++++++++++
>   sap/sap-ste.c   | 1265 ++++++++++++++++++++++++++++++++++++++++++++++
>   sap/sap.h       |  187 +++++++
>   sap/server.c    | 1516 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
>   sap/server.h    |   23 +
>   12 files changed, 3559 insertions(+), 4 deletions(-)
>   create mode 100644 doc/sap-api.txt
>   create mode 100644 sap/main.c
>   create mode 100644 sap/manager.c
>   create mode 100644 sap/manager.h
>   create mode 100644 sap/sap-dummy.c
>   create mode 100644 sap/sap-ste.c
I am assuming that this is the ST specific plugin. May be you can just 
keep the dummy plugin only so that someone can use that as a reference.
>   create mode 100644 sap/sap.h
>   create mode 100644 sap/server.c
>   create mode 100644 sap/server.h

I guess it would be better if you can split this into multiple patches 
so that it would be easier to review.

Regards
Suraj

^ permalink raw reply	[flat|nested] 4+ messages in thread

* RE: [PATCH 1/1] Add Sim Access Plugin
  2010-10-20  8:37   ` Suraj Sumangala
@ 2010-10-20  8:47     ` Waldemar.Rymarkiewicz
  0 siblings, 0 replies; 4+ messages in thread
From: Waldemar.Rymarkiewicz @ 2010-10-20  8:47 UTC (permalink / raw)
  To: suraj
  Cc: linux-bluetooth, marcel, Suraj.Sumangala, johan.hedberg,
	joakim.xj.ceder, arunkr.singh

Hi Suraj,

>>   create mode 100644 sap/sap-ste.c
>I am assuming that this is the ST specific plugin. May be you=20
>can just keep the dummy plugin only so that someone can use=20
>that as a reference.

In fact, you are right. Will remove this for the time being.=20

>>   create mode 100644 sap/sap.h
>>   create mode 100644 sap/server.c
>>   create mode 100644 sap/server.h
>
>I guess it would be better if you can split this into multiple=20
>patches so that it would be easier to review.

Ok.=20

Regards,
/Waldek

^ permalink raw reply	[flat|nested] 4+ messages in thread

end of thread, other threads:[~2010-10-20  8:47 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2010-10-20  7:55 [PATCH 0/1] Add Sim Access plugin Waldemar Rymarkiewicz
2010-10-20  7:55 ` [PATCH 1/1] Add Sim Access Plugin Waldemar Rymarkiewicz
2010-10-20  8:37   ` Suraj Sumangala
2010-10-20  8:47     ` Waldemar.Rymarkiewicz

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.