All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 0/4] Sim Access Profile
@ 2010-11-03 13:34 Waldemar Rymarkiewicz
  2010-11-03 13:34 ` [PATCH 1/4] Sim Access Profile API Waldemar Rymarkiewicz
                   ` (3 more replies)
  0 siblings, 4 replies; 21+ messages in thread
From: Waldemar Rymarkiewicz @ 2010-11-03 13:34 UTC (permalink / raw)
  To: linux-bluetooth
  Cc: suraj, Johan Hedberg, joakim.xj.ceder, Waldemar Rymarkiewicz

Hi,

I fixed some issues raised by  Johan.
I will send patches in seperate emails.

@Johan: If there is no more comments could you consider to push it upstream?

Regards,
/Waldek


Waldemar Rymarkiewicz (4):
  Sim Access Profile API
  Sim Access Profile Manager
  Sim Access Profile Server
  Sim Access Profile dummy driver

 .gitignore      |    1 +
 Makefile.am     |   21 +-
 acinclude.m4    |   12 +
 doc/sap-api.txt |   57 ++
 sap/main.c      |   54 ++
 sap/manager.c   |   94 ++++
 sap/manager.h   |   21 +
 sap/sap-dummy.c |  304 +++++++++++
 sap/sap.h       |  187 +++++++
 sap/server.c    | 1514 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
 sap/server.h    |   25 +
 11 files changed, 2288 insertions(+), 2 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.h
 create mode 100644 sap/server.c
 create mode 100644 sap/server.h


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

* [PATCH 1/4] Sim Access Profile API
  2010-11-03 13:34 [PATCH 0/4] Sim Access Profile Waldemar Rymarkiewicz
@ 2010-11-03 13:34 ` Waldemar Rymarkiewicz
  2010-11-10  5:33   ` Marcel Holtmann
  2010-11-03 13:34 ` [PATCH 2/4] Sim Access Profile Manager Waldemar Rymarkiewicz
                   ` (2 subsequent siblings)
  3 siblings, 1 reply; 21+ messages in thread
From: Waldemar Rymarkiewicz @ 2010-11-03 13:34 UTC (permalink / raw)
  To: linux-bluetooth
  Cc: suraj, Johan Hedberg, joakim.xj.ceder, Waldemar Rymarkiewicz

New API for Sim Access Profile.
---
 Makefile.am     |    2 +-
 doc/sap-api.txt |   57 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 58 insertions(+), 1 deletions(-)
 create mode 100644 doc/sap-api.txt

diff --git a/Makefile.am b/Makefile.am
index 873f2df..e1183de 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -352,7 +352,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
 
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.
+
-- 
1.7.0.4


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

* [PATCH 2/4] Sim Access Profile Manager
  2010-11-03 13:34 [PATCH 0/4] Sim Access Profile Waldemar Rymarkiewicz
  2010-11-03 13:34 ` [PATCH 1/4] Sim Access Profile API Waldemar Rymarkiewicz
@ 2010-11-03 13:34 ` Waldemar Rymarkiewicz
  2010-11-05  9:30   ` Johan Hedberg
  2010-11-03 13:34 ` [PATCH 3/4] Sim Access Profile Server Waldemar Rymarkiewicz
  2010-11-03 13:34 ` [PATCH 4/4] Sim Access Profile dummy driver Waldemar Rymarkiewicz
  3 siblings, 1 reply; 21+ messages in thread
From: Waldemar Rymarkiewicz @ 2010-11-03 13:34 UTC (permalink / raw)
  To: linux-bluetooth
  Cc: suraj, Johan Hedberg, joakim.xj.ceder, Waldemar Rymarkiewicz

Add a SAP plugin main file and the plugin manager. Also include the SAP
plugin in the Makefile.
---
 Makefile.am   |    7 ++++
 acinclude.m4  |    6 ++++
 sap/main.c    |   54 ++++++++++++++++++++++++++++++++
 sap/manager.c |   94 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 sap/manager.h |   21 +++++++++++++
 sap/server.c  |   48 +++++++++++++++++++++++++++++
 sap/server.h  |   25 +++++++++++++++
 7 files changed, 255 insertions(+), 0 deletions(-)
 create mode 100644 sap/main.c
 create mode 100644 sap/manager.c
 create mode 100644 sap/manager.h
 create mode 100644 sap/server.c
 create mode 100644 sap/server.h

diff --git a/Makefile.am b/Makefile.am
index e1183de..c767b4c 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -142,6 +142,13 @@ 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
+endif
+
 if INPUTPLUGIN
 builtin_modules += input
 builtin_sources += input/main.c \
diff --git a/acinclude.m4 b/acinclude.m4
index 287f07d..1f76b4d 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
@@ -210,6 +211,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}
 	])
@@ -351,6 +356,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/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/server.c b/sap/server.c
new file mode 100644
index 0000000..2728778
--- /dev/null
+++ b/sap/server.c
@@ -0,0 +1,48 @@
+/*
+ *  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
+ */
+
+#include "bluetooth.h"
+#include "log.h"
+
+#include "server.h"
+
+int sap_server_register(const char *path, bdaddr_t *src)
+{
+	DBG("Register SAP server.");
+	return 0;
+}
+
+int sap_server_unregister(const char *path)
+{
+	DBG("Unregister SAP server.");
+	return 0;
+}
+
+int sap_server_init(DBusConnection *conn)
+{
+	DBG("Init SAP server.");
+	return 0;
+}
+
+void sap_server_exit(void)
+{
+	DBG("Exit SAP server.");
+}
diff --git a/sap/server.h b/sap/server.h
new file mode 100644
index 0000000..cb77828
--- /dev/null
+++ b/sap/server.h
@@ -0,0 +1,25 @@
+/*
+ *  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
+ */
+
+#include <gdbus.h>
+
+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] 21+ messages in thread

* [PATCH 3/4] Sim Access Profile Server
  2010-11-03 13:34 [PATCH 0/4] Sim Access Profile Waldemar Rymarkiewicz
  2010-11-03 13:34 ` [PATCH 1/4] Sim Access Profile API Waldemar Rymarkiewicz
  2010-11-03 13:34 ` [PATCH 2/4] Sim Access Profile Manager Waldemar Rymarkiewicz
@ 2010-11-03 13:34 ` Waldemar Rymarkiewicz
  2010-11-05 10:05   ` Johan Hedberg
  2010-11-03 13:34 ` [PATCH 4/4] Sim Access Profile dummy driver Waldemar Rymarkiewicz
  3 siblings, 1 reply; 21+ messages in thread
From: Waldemar Rymarkiewicz @ 2010-11-03 13:34 UTC (permalink / raw)
  To: linux-bluetooth
  Cc: suraj, Johan Hedberg, joakim.xj.ceder, Waldemar Rymarkiewicz

Add a Sim Access Server to the SAP plugin and a framework for the dummy
sap driver as well.
---
 Makefile.am     |    3 +-
 sap/sap-dummy.c |   85 ++++
 sap/sap.h       |  187 +++++++
 sap/server.c    | 1476 ++++++++++++++++++++++++++++++++++++++++++++++++++++++-
 4 files changed, 1745 insertions(+), 6 deletions(-)
 create mode 100644 sap/sap-dummy.c
 create mode 100644 sap/sap.h

diff --git a/Makefile.am b/Makefile.am
index c767b4c..fe077f7 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -146,7 +146,8 @@ if SAPPLUGIN
 builtin_modules += sap
 builtin_sources += sap/main.c \
 			sap/manager.h sap/manager.c \
-			sap/server.h sap/server.c
+			sap/server.h sap/server.c \
+			sap/sap.h sap/sap-dummy.c
 endif
 
 if INPUTPLUGIN
diff --git a/sap/sap-dummy.c b/sap/sap-dummy.c
new file mode 100644
index 0000000..e04660f
--- /dev/null
+++ b/sap/sap-dummy.c
@@ -0,0 +1,85 @@
+/*
+ *  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
+ */
+
+#include "log.h"
+#include "sap.h"
+
+void sap_connect_req(void *sap_device, uint16_t maxmsgsize)
+{
+	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)
+{
+	sap_disconnect_rsp(sap_device);
+}
+
+void sap_transfer_apdu_req(void *sap_device, sap_parameter *param)
+{
+	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};
+
+	sap_transfer_atr_rsp(sap_device, SAP_RESULT_OK, atr, 0x0E);
+}
+
+void sap_power_sim_off_req(void *sap_device)
+{
+	sap_power_sim_off_rsp(sap_device, SAP_RESULT_OK);
+}
+
+void sap_power_sim_on_req(void *sap_device)
+{
+	sap_power_sim_on_rsp(sap_device, SAP_RESULT_OK);
+}
+
+void sap_reset_sim_req(void *sap_device)
+{
+	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)
+{
+	sap_transfer_card_reader_status_rsp(sap_device, SAP_RESULT_OK,
+						ICC_READER_CARD_POWERED_ON);
+}
+
+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)
+{
+	DBG("SAP driver init.");
+	return 0;
+}
+
+void sap_exit(void)
+{
+	DBG("SAP driver exit.");
+}
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
index 2728778..5683e66 100644
--- a/sap/server.c
+++ b/sap/server.c
@@ -2,7 +2,9 @@
  *  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
@@ -19,30 +21,1494 @@
  *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
  */
 
-#include "bluetooth.h"
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdio.h>
+#include <errno.h>
+#include <glib.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)
 {
-	DBG("Register SAP server.");
+	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)
 {
-	DBG("Unregister SAP server.");
+	g_dbus_unregister_interface(connection, path, SAP_SERVER_INTERFACE);
+	sap_exit();
 	return 0;
 }
 
 int sap_server_init(DBusConnection *conn)
 {
-	DBG("Init SAP server.");
+	connection = dbus_connection_ref(conn);
 	return 0;
 }
 
 void sap_server_exit(void)
 {
-	DBG("Exit SAP server.");
+	dbus_connection_unref(connection);
+	connection = NULL;
 }
-- 
1.7.0.4


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

* [PATCH 4/4] Sim Access Profile dummy driver
  2010-11-03 13:34 [PATCH 0/4] Sim Access Profile Waldemar Rymarkiewicz
                   ` (2 preceding siblings ...)
  2010-11-03 13:34 ` [PATCH 3/4] Sim Access Profile Server Waldemar Rymarkiewicz
@ 2010-11-03 13:34 ` Waldemar Rymarkiewicz
  2010-11-05 10:16   ` Johan Hedberg
  3 siblings, 1 reply; 21+ messages in thread
From: Waldemar Rymarkiewicz @ 2010-11-03 13:34 UTC (permalink / raw)
  To: linux-bluetooth
  Cc: suraj, Johan Hedberg, joakim.xj.ceder, Waldemar Rymarkiewicz

Add SAP dummy driver implementation and extend configure
with --with-sap=<driver>.
---
 .gitignore      |    1 +
 Makefile.am     |   13 +++-
 acinclude.m4    |    6 ++
 sap/sap-dummy.c |  243 ++++++++++++++++++++++++++++++++++++++++++++++++++++---
 4 files changed, 249 insertions(+), 14 deletions(-)

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 fe077f7..1d3dd53 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -147,7 +147,13 @@ builtin_modules += sap
 builtin_sources += sap/main.c \
 			sap/manager.h sap/manager.c \
 			sap/server.h sap/server.c \
-			sap/sap.h sap/sap-dummy.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
 endif
 
 if INPUTPLUGIN
@@ -271,7 +277,7 @@ 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
 
 
 if ALSA
@@ -395,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-,,$@) $@
 
diff --git a/acinclude.m4 b/acinclude.m4
index 1f76b4d..0ebeb11 100644
--- a/acinclude.m4
+++ b/acinclude.m4
@@ -194,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}
@@ -219,6 +220,11 @@ AC_DEFUN([AC_ARG_BLUEZ], [
 		serial_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])
+
 	AC_ARG_ENABLE(input, AC_HELP_STRING([--disable-input], [disable input plugin]), [
 		input_enable=${enableval}
 	])
diff --git a/sap/sap-dummy.c b/sap/sap-dummy.c
index e04660f..da72369 100644
--- a/sap/sap-dummy.c
+++ b/sap/sap-dummy.c
@@ -19,23 +19,89 @@
  *  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"
+
+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)
 {
-	sap_connect_rsp(sap_device, SAP_STATUS_OK, maxmsgsize);
-	sap_status_ind(sap_device, SAP_STATUS_CHANGE_CARD_RESET);
+	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);
+		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)
 {
-	sap_transfer_apdu_rsp(sap_device, SAP_RESULT_OK, NULL, 0);
+	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)
@@ -43,29 +109,70 @@ 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};
 
-	sap_transfer_atr_rsp(sap_device, SAP_RESULT_OK, atr, 0x0E);
+	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)
 {
-	sap_power_sim_off_rsp(sap_device, SAP_RESULT_OK);
+	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)
 {
-	sap_power_sim_on_rsp(sap_device, SAP_RESULT_OK);
+	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)
 {
-	sap_reset_sim_rsp(sap_device, SAP_RESULT_OK);
-	sap_status_ind(sap_device, SAP_STATUS_CHANGE_CARD_RESET);
+	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)
 {
-	sap_transfer_card_reader_status_rsp(sap_device, SAP_RESULT_OK,
-						ICC_READER_CARD_POWERED_ON);
+	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)
@@ -73,13 +180,125 @@ 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)
 {
-	DBG("SAP driver init.");
+	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)
 {
-	DBG("SAP driver exit.");
+	dbus_connection_unref(connection);
+	connection = NULL;
 }
-- 
1.7.0.4


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

* Re: [PATCH 2/4] Sim Access Profile Manager
  2010-11-03 13:34 ` [PATCH 2/4] Sim Access Profile Manager Waldemar Rymarkiewicz
@ 2010-11-05  9:30   ` Johan Hedberg
  2010-11-05 13:31     ` Waldemar.Rymarkiewicz
  0 siblings, 1 reply; 21+ messages in thread
From: Johan Hedberg @ 2010-11-05  9:30 UTC (permalink / raw)
  To: Waldemar Rymarkiewicz; +Cc: linux-bluetooth, suraj, joakim.xj.ceder

Hi Waldek,

On Wed, Nov 03, 2010, Waldemar Rymarkiewicz wrote:
> +++ b/sap/main.c
> @@ -0,0 +1,54 @@
> +/*
> + *  BlueZ - Bluetooth protocol stack for Linux
> + *
> + *  Copyright (C) 2010 Claudio Takahasi<claudio.takahasi@openbossa.org>

As discussed off-list, this needs fixing.

> +++ b/sap/manager.c
> @@ -0,0 +1,94 @@
> +/*
> + *  BlueZ - Bluetooth protocol stack for Linux
> + *
> + *  Copyright (C) 2010 Claudio Takahasi<claudio.takahasi@openbossa.org>

Same here.

> +static DBusConnection *connection = NULL;
> +
> +
> +static int sap_server_probe(struct btd_adapter *adapter)

There should never be the need to have two consecutive empty lines.
Please remove one.

> +	const gchar *path = adapter_get_path(adapter);

Please avoid using the glib specific types when standard C types can be
used. I.e. use just "char" here.

> +static void sap_server_remove(struct btd_adapter *adapter)
> +{
> +	const gchar *path = adapter_get_path(adapter);

Same here.

> +++ b/sap/manager.h
> @@ -0,0 +1,21 @@
> +/*
> + *  BlueZ - Bluetooth protocol stack for Linux
> + *
> + *  Copyright (C) 2010 Claudio Takahasi<claudio.takahasi@openbossa.org>

Same copyright fix needed as previously discussed.

> +++ b/sap/server.h
> @@ -0,0 +1,25 @@
> +/*
> + *  BlueZ - Bluetooth protocol stack for Linux
> + *
> + *  Copyright (C) 2010 Claudio Takahasi<claudio.takahasi@openbossa.org>

Same here.

Johan

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

* Re: [PATCH 3/4] Sim Access Profile Server
  2010-11-03 13:34 ` [PATCH 3/4] Sim Access Profile Server Waldemar Rymarkiewicz
@ 2010-11-05 10:05   ` Johan Hedberg
  2010-11-05 15:12     ` Waldemar.Rymarkiewicz
  0 siblings, 1 reply; 21+ messages in thread
From: Johan Hedberg @ 2010-11-05 10:05 UTC (permalink / raw)
  To: Waldemar Rymarkiewicz; +Cc: linux-bluetooth, suraj, joakim.xj.ceder

Hi Waldek,

On Wed, Nov 03, 2010, Waldemar Rymarkiewicz wrote:
> +	uint8_t atr[] = {0x3b, 0x9a, 0x96, 0x00, 0x92, 0x01, 0x98, 0x93, 0x17,

Space after {

> +			 0x00, 0x02, 0x28, 0x03, 0x00};

Mixed spaces and tabs for indentation. Just use tabs. Space before }

> +void sap_transfer_card_reader_status_req(void * sap_device)

No space between * and sap_device

> +void sap_set_transport_protocol_req(void * sap_device,sap_parameter * param)

White space again. It should be "void *sap_device, sap_parameter *param)"

> + *  Copyright (C) 2010 Claudio Takahasi<claudio.takahasi@openbossa.org>

Same copyright issue as previously discussed.

> +/* Connection Status - SAP v1.1 section 5.2.2 */
> +typedef enum {
> +	SAP_STATUS_OK 				= 0x00,

There's an extra space after OK. Just use tabs.

> +/* Result codes - SAP v1.1 section 5.2.4 */
> +typedef enum {
> +	SAP_RESULT_OK 			= 0x00,

Same here.

> +/* 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;

Why don't you use similar alignmenth here as for the other enums?

> +/* Message format - SAP v1.1 section 5.1 */
> +typedef struct {

Please don't use typedefs with structs. 

> +} __attribute__ ((packed)) sap_message;
> +
> +
> +typedef enum {

Remove one of the consequtive empty lines.

> +} icc_reader_status_t;
> +
> +
> +#define SAP_BUF_SIZE		512

Same here.

> +/*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);

Several of the above lines go beyond 79 columns. Please split them.

> +++ b/sap/server.c
> @@ -2,7 +2,9 @@
>   *  BlueZ - Bluetooth protocol stack for Linux
>   *
>   *  Copyright (C) 2010 ST-Ericsson SA
> + *  Copyright (C) 2010 Claudio Takahasi<claudio.takahasi@openbossa.org>

Same copyright issue as before.

> +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);

Are all these forward-declarations really needed? If you can avoid them
by sorting the functions within the c file differently, please do so.

> +static gsize add_result_parameter(sap_result_t result, sap_parameter *param);

Use size_t instead of gsize.

> +}
> +
> +
> +static inline int is_power_sim_off_req_allowed(uint8_t processing_req)

Remove one of the consecutive empty lines. Remove the "inline" unless
you really profiled this and discovered that this has a measurable
impact and that the compiler fails to optimize this without the
"inline".

> +	switch(processing_req) {

Space before )

> +static inline int is_reset_sim_req_allowed(uint8_t processing_req)
> +{
> +	switch(processing_req) {

Same here.

> +static int check_msg(sap_message *msg)
> +{
> +	if(!msg)

And here.

> +}
> +
> +
> +static void start_guard_timer(struct sap_server *server, guint interval)

Remove one of the empty lines.

> +{
> +	if(!server)

Space before (

> +	switch(server->state) {

Same here.

> +	if(!server || !buf)

And here.

> +	if(written != (gsize)size) {

And here.

> +		error("send_message:write error. written %d size %d", written, size);
> +	}
> +	DBG("send_message: written=%x",(unsigned int)written);

Empty line after }

> +	if(!server || !param)

Space before (

> +	val = (uint16_t *) &param->val;
> +	maxmsgsize = ntohs(*val);

Is this unaligned access safe?

> +	if (maxmsgsize <= SAP_BUF_SIZE){
> +		server->processing_req = SAP_CONNECT_REQ;
> +		sap_connect_req(server, maxmsgsize);
> +	}else{

Space before and after else

> +	if(!server)

Space before (

> +	switch(disc_type) {

Same here.

> +static void transfer_apdu_req(void * data, sap_parameter * param)

No spaces after *

> +	if(!server || !param)

Space before (

> +}
> +
> +
> +static void transfer_atr_req(void * data)

Remove one of the empty lines. No space before data.

> +	if(!server)

Space before (

> +}
> +
> +
> +static void power_sim_off_req(void *data)

Remove one of the empty lines.

> +	if(!server)

Space before (

> +static void power_sim_on_req(void *data)
> +{
> +	struct sap_server *server = data;
> +
> +	if(!server)

Space before (

> +static void reset_sim_req(void *data)
> +{
> +	struct sap_server *server = data;
> +
> +	if(!server)

Same here.

> +static void transfer_card_reader_status_req(void * data)

No space before data.

> +{
> +	struct sap_server *server = data;
> +
> +	if(!server)

Space before (

> +static void set_transport_protocol_req(void *data, sap_parameter *param)
> +{
> +	struct sap_server *server = data;
> +
> +	if(!server || !param)

Same here.

> +	gchar buf[SAP_BUF_SIZE];

Use char instead of gchar.

> +	gsize size = sizeof(sap_message);

Use size_t instead of gsize.

> +	if(!server)

Space before (

> +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);

size_t

> +	if(!server)

Space before (

> +	if (server->state != SAP_STATE_CONNECT_IN_PROGRESS) {
> +		return -EPERM;
> +	}

{} not needed for one-line scopes.

> +int sap_disconnect_rsp(void *sap_device)
> +{
> +	struct sap_server *server = sap_device;
> +	sap_message msg = {0};

Space before and after 0

> +	if(!server)

Space before (

> +	gchar buf[SAP_BUF_SIZE] = {0};

Use char instead of gchar. Is the initialization upon declaration really
necessary?

> +	gsize size = sizeof(sap_message);

sizt_t

> +	if(!server)

Space before (

> +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;

Same comments as for the previous function.

> +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;

Same here.

> +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;

And here.

> +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;

And here.

> +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;

And here.

> +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;

And here.

> +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));

char instead of gchar. Worth considering if the second parameter to
send_message should be void * to avoid these type casts.

> +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;

Same comments as for the few other functions above.

> +		/*Don't propagate status indication if client is not connected */

Space before D

> +static int handle_cmd(void *data, gchar *buf, gsize size)

char instead of gchar, size_t instead of gsize

> +	sap_message *msg = (sap_message *) buf;

Maybe the function should take void * so you don't need the explicit
type cast?

> +	switch(msg->id) {

Space befor e(

> +		case SAP_CONNECT_REQ:

Incorrect indentation. This should have the same as the initial switch
line. Same goes for all other case statements.

> +static gboolean sap_io_cb(GIOChannel *chan, GIOCondition cond, void *data)
> +{
> +	gchar buf[SAP_BUF_SIZE];
> +	gsize bytes_read = 0;

char and size_t

> +	if (handle_cmd(data, buf, bytes_read) < 0) {
> +		error("Invalid SAP message.");
> +	}

No {} for one-line scopes.

> +	if(!server)

Space before (

> +	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);

Instead of type casting to GIOFunc just fix sap_io_cp to have the right
type and then do necessary assignments to correct variable types inside
that function.

> +	if(!server || !server->io)

Space before (

> +	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;

Empty line before return

> +	if(!chan || !server)

Space before (

> +	DBG("SAP incoming connection (sock %d) authorization.", g_io_channel_unix_get_fd(chan));

Too long line.

> +}
> +
> +
> +

Three empty lines? :)

> +static inline DBusMessage *message_failed(DBusMessage *msg,

Remove the inline unless you've really done the profiling and concluded
that it's necessary.

> +	sdp_record_t *record = NULL;
> +	GIOChannel *io = NULL;

Unnecessary initialization since the variables gets unconditionally
initialized before usage in the function. Pay attention to this kind of
stuff everywhere in your code and fix other places too in case I missed
them.

> +	io = bt_io_listen(BT_IO_RFCOMM, NULL, connect_confirm_cb, server, NULL, &gerr,

Looks like that one goes over 79 columns.

> +static DBusMessage *disable(DBusConnection *conn,
> +				DBusMessage *msg, void *data)

Looks like at least the DBusMessage parameter would still fit on the
previous line.

> +	DBusMessage *reply = NULL;

Unnecessary initialization upon declaration.

> +	if(!server)

Space before (

> +static DBusMessage *disconnect(DBusConnection *conn, DBusMessage *msg, void *data)

Looks like that goes over 79 columns.

> +	server = g_new0(struct sap_server, 1);
> +
> +	if (!server) {

g_new0 is guaranteed to succeed or call abort(). It will never return
NULL. If you really want to have the possibility for checking for
allocation errors use the g_try_new variants.

Johan

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

* Re: [PATCH 4/4] Sim Access Profile dummy driver
  2010-11-03 13:34 ` [PATCH 4/4] Sim Access Profile dummy driver Waldemar Rymarkiewicz
@ 2010-11-05 10:16   ` Johan Hedberg
  2010-11-05 15:14     ` Waldemar.Rymarkiewicz
  0 siblings, 1 reply; 21+ messages in thread
From: Johan Hedberg @ 2010-11-05 10:16 UTC (permalink / raw)
  To: Waldemar Rymarkiewicz; +Cc: linux-bluetooth, suraj, joakim.xj.ceder

Hi Waldek,

On Wed, Nov 03, 2010, Waldemar Rymarkiewicz wrote:
> +static sim_connection_status_t sim_card_connection_status = SIM_DISCONNECTED;

Consider shortening these names. At least one of them (either the type
or the variable).

> +static void *		sap_data = NULL;  /* SAP server private data.*/

No whitespace between * and sap_data. Why is this void instead of a
specific type when its static and therefore wont be seen by other
modules?

> +	if(sim_card_connection_status == SIM_MISSING)

Space before (

> +	}else if(sim_card_connection_status != SIM_CONNECTED)

Space after } and before (

> +		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);
> +	}

Why do you have {} for one branch but not for the other? In general
one-line branches/scopes shouldn't have braces, though the kernel coding
guideline does allow them if at least one part of the same if-else
statement has them.

> +static inline DBusMessage *invalid_args(DBusMessage *msg)

Never mind the previous comment I had about this. I checked the rest of
the tree and it seems this inline convention for D-Bus error generating
functions is quite common (though imho might not be needed at all).

> +	if(sim_card_connection_status != SIM_CONNECTED)

Space before (

> +}
> +
> +
> +static GDBusMethodTable dummy_methods[] = {

Remove the other empty line.

> +	{ "OngoingCall",	"b",	"",	ongoing_call},
> +	{ "MaxMessageSize",	"u",	"",	max_msg_size},
> +	{ "Disconnect",		"",	"",	disconnect},
> +	{ "CardStatus",		"u",	"",	card_status},
> +	{ }

> +static GDBusSignalTable dummy_signals[] = {
> +	{ "","" },
> +	{ }
> +};

If you have no signals just pass NULL to g_dbus_register_interface
instead of declaring an (almost) empty table. Also, "" isn't a valid
value for the signal name.

Johan

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

* RE: [PATCH 2/4] Sim Access Profile Manager
  2010-11-05  9:30   ` Johan Hedberg
@ 2010-11-05 13:31     ` Waldemar.Rymarkiewicz
  0 siblings, 0 replies; 21+ messages in thread
From: Waldemar.Rymarkiewicz @ 2010-11-05 13:31 UTC (permalink / raw)
  To: johan.hedberg; +Cc: linux-bluetooth, suraj, joakim.xj.ceder

[-- Attachment #1: Type: text/plain, Size: 299 bytes --]

Hi Johan 

>
>> +++ b/sap/server.h
>> @@ -0,0 +1,25 @@
>> +/*
>> + *  BlueZ - Bluetooth protocol stack for Linux
>> + *
>> + *  Copyright (C) 2010 Claudio 
>> +Takahasi<claudio.takahasi@openbossa.org>
>
>Same here.
>

Thanks for comments. I updated the patch. 

Regards,
/Waldek


[-- Attachment #2: 0002-Sim-Access-Profile-Manager.patch --]
[-- Type: application/octet-stream, Size: 10127 bytes --]

From 2896b2af5da20c69823c6df602f3594125e92aae Mon Sep 17 00:00:00 2001
From: Waldemar Rymarkiewicz <waldemar.rymarkiewicz@tieto.com>
Date: Wed, 20 Oct 2010 11:59:43 +0200
Subject: [PATCH 2/4] Sim Access Profile Manager

Add a SAP plugin main file and the plugin manager. Also include the SAP
plugin in the Makefile.
---
 Makefile.am   |    7 ++++
 acinclude.m4  |    6 ++++
 sap/main.c    |   55 +++++++++++++++++++++++++++++++++
 sap/manager.c |   93 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 sap/manager.h |   22 +++++++++++++
 sap/server.c  |   48 +++++++++++++++++++++++++++++
 sap/server.h  |   26 ++++++++++++++++
 7 files changed, 257 insertions(+), 0 deletions(-)
 create mode 100644 sap/main.c
 create mode 100644 sap/manager.c
 create mode 100644 sap/manager.h
 create mode 100644 sap/server.c
 create mode 100644 sap/server.h

diff --git a/Makefile.am b/Makefile.am
index e1183de..c767b4c 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -142,6 +142,13 @@ 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
+endif
+
 if INPUTPLUGIN
 builtin_modules += input
 builtin_sources += input/main.c \
diff --git a/acinclude.m4 b/acinclude.m4
index 287f07d..1f76b4d 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
@@ -210,6 +211,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}
 	])
@@ -351,6 +356,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/sap/main.c b/sap/main.c
new file mode 100644
index 0000000..c9c90bd
--- /dev/null
+++ b/sap/main.c
@@ -0,0 +1,55 @@
+/*
+ *  BlueZ - Bluetooth protocol stack for Linux
+ *
+ *  Copyright (C) 2010 Instituto Nokia de Tecnologia - INdT
+ *
+ *  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; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  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..a97f434
--- /dev/null
+++ b/sap/manager.c
@@ -0,0 +1,93 @@
+/*
+ *  BlueZ - Bluetooth protocol stack for Linux
+ *
+ *  Copyright (C) 2010 Instituto Nokia de Tecnologia - INdT
+ *
+ *  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; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  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 char *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 char *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..e08c882
--- /dev/null
+++ b/sap/manager.h
@@ -0,0 +1,22 @@
+/*
+ *  BlueZ - Bluetooth protocol stack for Linux
+ *
+ *  Copyright (C) 2010 Instituto Nokia de Tecnologia - INdT
+ *
+ *  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; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  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/server.c b/sap/server.c
new file mode 100644
index 0000000..2728778
--- /dev/null
+++ b/sap/server.c
@@ -0,0 +1,48 @@
+/*
+ *  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
+ */
+
+#include "bluetooth.h"
+#include "log.h"
+
+#include "server.h"
+
+int sap_server_register(const char *path, bdaddr_t *src)
+{
+	DBG("Register SAP server.");
+	return 0;
+}
+
+int sap_server_unregister(const char *path)
+{
+	DBG("Unregister SAP server.");
+	return 0;
+}
+
+int sap_server_init(DBusConnection *conn)
+{
+	DBG("Init SAP server.");
+	return 0;
+}
+
+void sap_server_exit(void)
+{
+	DBG("Exit SAP server.");
+}
diff --git a/sap/server.h b/sap/server.h
new file mode 100644
index 0000000..ef2b7b8
--- /dev/null
+++ b/sap/server.h
@@ -0,0 +1,26 @@
+/*
+ *  BlueZ - Bluetooth protocol stack for Linux
+ *
+ *  Copyright (C) 2010 ST-Ericsson SA
+ *
+ *  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; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  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 <gdbus.h>
+
+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] 21+ messages in thread

* RE: [PATCH 3/4] Sim Access Profile Server
  2010-11-05 10:05   ` Johan Hedberg
@ 2010-11-05 15:12     ` Waldemar.Rymarkiewicz
  0 siblings, 0 replies; 21+ messages in thread
From: Waldemar.Rymarkiewicz @ 2010-11-05 15:12 UTC (permalink / raw)
  To: johan.hedberg; +Cc: linux-bluetooth, suraj, joakim.xj.ceder

[-- Attachment #1: Type: text/plain, Size: 733 bytes --]

 
Hi Johan,

>> +	val = (uint16_t *) &param->val;
>> +	maxmsgsize = ntohs(*val);
>
>Is this unaligned access safe?

In theory this is safe :) param-> val  should be always aligned to 4 bytes according to sap spec

struct sap_parameter {
	uint8_t id;
	uint8_t reserved;
	uint16_t len;
	uint8_t val[0];
	/*
	 * Padding bytes 0-3 bytes
	 */
} __attribute__ ((packed));

However, I tried
	maxmsgsize = ntohs(bt_get_unaligned((uint16_t *) &param->val));
and got gcc error: dereferencing type-punned pointer will break strict-aliasing rules.

Strange as it's already used in bluetoothd and it compiles without such errors. Do I missed something ?


Thanks for comments and  have a look on fixed patch.

/Waldek

[-- Attachment #2: 0003-Sim-Access-Profile-Server.patch --]
[-- Type: application/octet-stream, Size: 48824 bytes --]

From f29febfca6b2c3faae6d8d8a9c53b90e5f6d39a7 Mon Sep 17 00:00:00 2001
From: Waldemar Rymarkiewicz <waldemar.rymarkiewicz@tieto.com>
Date: Wed, 20 Oct 2010 12:21:40 +0200
Subject: [PATCH 3/4] Sim Access Profile Server

Add a Sim Access Server to the SAP plugin and a framework for the dummy
sap driver as well.
---
 Makefile.am     |    3 +-
 sap/sap-dummy.c |   83 ++++
 sap/sap.h       |  192 ++++++++
 sap/server.c    | 1470 ++++++++++++++++++++++++++++++++++++++++++++++++++++++-
 4 files changed, 1741 insertions(+), 7 deletions(-)
 create mode 100644 sap/sap-dummy.c
 create mode 100644 sap/sap.h

diff --git a/Makefile.am b/Makefile.am
index c767b4c..fe077f7 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -146,7 +146,8 @@ if SAPPLUGIN
 builtin_modules += sap
 builtin_sources += sap/main.c \
 			sap/manager.h sap/manager.c \
-			sap/server.h sap/server.c
+			sap/server.h sap/server.c \
+			sap/sap.h sap/sap-dummy.c
 endif
 
 if INPUTPLUGIN
diff --git a/sap/sap-dummy.c b/sap/sap-dummy.c
new file mode 100644
index 0000000..92d73ef
--- /dev/null
+++ b/sap/sap-dummy.c
@@ -0,0 +1,83 @@
+/*
+ *  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
+ */
+
+#include "log.h"
+#include "sap.h"
+
+void sap_connect_req(void *sap_device, uint16_t maxmsgsize)
+{
+	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)
+{
+	sap_disconnect_rsp(sap_device);
+}
+
+void sap_transfer_apdu_req(void *sap_device, struct sap_parameter *param)
+{
+	sap_transfer_apdu_rsp(sap_device, SAP_RESULT_OK, NULL, 0);
+}
+
+void sap_transfer_atr_req(void *sap_device)
+{
+	sap_transfer_atr_rsp(sap_device, SAP_RESULT_OK, NULL, 0);
+}
+
+void sap_power_sim_off_req(void *sap_device)
+{
+	sap_power_sim_off_rsp(sap_device, SAP_RESULT_OK);
+}
+
+void sap_power_sim_on_req(void *sap_device)
+{
+	sap_power_sim_on_rsp(sap_device, SAP_RESULT_OK);
+}
+
+void sap_reset_sim_req(void *sap_device)
+{
+	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)
+{
+	sap_transfer_card_reader_status_rsp(sap_device, SAP_RESULT_OK,
+						ICC_READER_CARD_POWERED_ON);
+}
+
+void sap_set_transport_protocol_req(void * sap_device,
+					struct sap_parameter *param)
+{
+	sap_transport_protocol_rsp(sap_device, SAP_RESULT_NOT_SUPPORTED);
+}
+
+int sap_init(void)
+{
+	DBG("SAP driver init.");
+	return 0;
+}
+
+void sap_exit(void)
+{
+	DBG("SAP driver exit.");
+}
diff --git a/sap/sap.h b/sap/sap.h
new file mode 100644
index 0000000..7154e96
--- /dev/null
+++ b/sap/sap.h
@@ -0,0 +1,192 @@
+/*
+ *  BlueZ - Bluetooth protocol stack for Linux
+ *
+ *  Copyright (C) 2010 Instituto Nokia de Tecnologia - INdT
+ *  Copyright (C) 2010 ST-Ericsson SA
+ *
+ *  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; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  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 */
+struct sap_parameter {
+	uint8_t id;
+	uint8_t reserved;
+	uint16_t len;
+	uint8_t val[0];
+	/*
+	 * Padding bytes 0-3 bytes
+	 */
+} __attribute__ ((packed));
+
+struct sap_message {
+	uint8_t id;
+	uint8_t nparam;
+	uint16_t reserved;
+	struct sap_parameter param[0];
+} __attribute__ ((packed));
+
+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
+
+enum sap_protocol {
+	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,
+};
+
+/* 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, struct 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,
+					struct 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
index 2728778..395aeaa 100644
--- a/sap/server.c
+++ b/sap/server.c
@@ -1,13 +1,16 @@
 /*
  *  BlueZ - Bluetooth protocol stack for Linux
  *
+ *  Copyright (C) 2010 Instituto Nokia de Tecnologia - INdT
  *  Copyright (C) 2010 ST-Ericsson SA
  *
+ *  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.
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
  *
  *  This program is distributed in the hope that it will be useful,
  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
@@ -19,30 +22,1485 @@
  *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
  */
 
-#include "bluetooth.h"
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdio.h>
+#include <errno.h>
+#include <glib.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(struct sap_parameter) + x + PADDING4(x))
+
+#define SAP_NO_REQ 0xFF
+
+#define SAP_TIMER_GRACEFUL_DISCONNECT 30
+#define SAP_TIMER_NO_ACTIVITY 30
+
+enum {
+	SAP_STATE_DISCONNECTED,
+	SAP_STATE_CONNECT_IN_PROGRESS,
+	SAP_STATE_CONNECTED,
+	SAP_STATE_GRACEFUL_DISCONNECT,
+	SAP_STATE_IMMEDIATE_DISCONNECT,
+	SAP_STATE_CLIENT_DISCONNECT
+};
+
+struct sap_server {
+	bdaddr_t src;
+	char *path;
+	gboolean enable;
+	uint32_t record_id;
+	GIOChannel *listen_io;
+	GIOChannel *io;  /* Connected client channel.*/
+	uint32_t state;
+	uint8_t processing_req;
+	guint timer_id;
+};
+
+static DBusConnection *connection = NULL;
+
+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 size_t add_result_parameter(sap_result_t result,
+					struct 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 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 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(struct 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 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, void *buf, gssize size)
+{
+	gsize written = 0;
+	GError *gerr;
+	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 int disconnect_ind(void *sap_device, sap_disconnection_type_t type)
+{
+	struct sap_server *server = sap_device;
+	char buf[SAP_BUF_SIZE];
+	struct sap_message *msg = (struct sap_message *) buf;
+	struct sap_parameter *param = (struct sap_parameter *) msg->param;
+	size_t size = sizeof(struct 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;
+}
+
+static void connect_req(void *data, struct 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, struct 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, struct 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 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;
+}
+
+
+int sap_connect_rsp(void *sap_device, sap_status_t status, uint16_t maxmsgsize)
+{
+	struct sap_server *server = sap_device;
+	char buf[SAP_BUF_SIZE];
+	struct sap_message *msg = (struct sap_message *) buf;
+	struct sap_parameter *param = (struct sap_parameter *) msg->param;
+	size_t size = sizeof(struct 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 = (struct 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;
+	struct sap_message msg;
+
+	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, &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;
+	char buf[SAP_BUF_SIZE];
+	struct sap_message *msg = (struct sap_message *) buf;
+	struct sap_parameter *param = (struct sap_parameter *) msg->param;
+	size_t size = sizeof(struct 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 = (struct 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;
+	char buf[SAP_BUF_SIZE];
+	struct sap_message *msg = (struct sap_message *) buf;
+	struct sap_parameter *param = (struct sap_parameter *) msg->param;
+	size_t size = sizeof(struct 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 = (struct 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;
+	char buf[SAP_BUF_SIZE];
+	struct sap_message *msg = (struct sap_message *) buf;
+	size_t size = sizeof(struct 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;
+	char buf[SAP_BUF_SIZE];
+	struct sap_message *msg = (struct sap_message *) buf;
+	size_t size = sizeof(struct 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;
+	char buf[SAP_BUF_SIZE];
+	struct sap_message *msg = (struct sap_message *) buf;
+	size_t size = sizeof(struct 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;
+	char buf[SAP_BUF_SIZE];
+	struct sap_message *msg = (struct sap_message *) buf;
+	struct sap_parameter *param = (struct sap_parameter *) msg->param;
+	size_t size = sizeof(struct 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 = (struct 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;
+	char buf[SAP_BUF_SIZE];
+	struct sap_message *msg = (struct sap_message *) buf;
+	size_t size = sizeof(struct 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)
+{
+	struct sap_message msg;
+
+	memset(&msg, 0, sizeof(msg));
+	msg.id = SAP_ERROR_RESP;
+
+	return send_message(sap_device, &msg, sizeof(msg));
+}
+
+int sap_status_ind(void *sap_device, sap_status_change_t status_change)
+{
+	struct sap_server *server = sap_device;
+	char buf[SAP_BUF_SIZE];
+	struct sap_message *msg = (struct sap_message *) buf;
+	struct sap_parameter *param = (struct sap_parameter *) msg->param;
+	size_t size = sizeof(struct 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 ind. 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, void *buf, size_t size)
+{
+	struct sap_message *msg = buf;
+
+	if (size < sizeof(struct sap_message))
+		goto error_rsp;
+
+	if (msg->nparam != 0 &&
+			size < (sizeof(struct sap_message) +
+			sizeof(struct 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, gpointer data)
+{
+	char buf[SAP_BUF_SIZE];
+	size_t bytes_read = 0;
+	GError *gerr;
+	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,
+			sap_io_cb, server, sap_io_destroy);
+}
+
+static void connect_auth_cb(DBusError *derr, void *data)
+{
+	struct sap_server *server = data;
+	GError *gerr;
+
+	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;
+	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;
+	GIOChannel *io;
+	GError *gerr;
+
+	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;
+
+	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)
 {
-	DBG("Register SAP server.");
+	struct sap_server *server;
+
+	if (sap_init() < 0) {
+		error("Sap driver initialization failed.");
+		return -1;
+	}
+
+	server = g_try_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)
 {
-	DBG("Unregister SAP server.");
+	g_dbus_unregister_interface(connection, path, SAP_SERVER_INTERFACE);
+	sap_exit();
 	return 0;
 }
 
 int sap_server_init(DBusConnection *conn)
 {
-	DBG("Init SAP server.");
+	connection = dbus_connection_ref(conn);
 	return 0;
 }
 
 void sap_server_exit(void)
 {
-	DBG("Exit SAP server.");
+	dbus_connection_unref(connection);
+	connection = NULL;
 }
-- 
1.7.0.4


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

* RE: [PATCH 4/4] Sim Access Profile dummy driver
  2010-11-05 10:16   ` Johan Hedberg
@ 2010-11-05 15:14     ` Waldemar.Rymarkiewicz
  0 siblings, 0 replies; 21+ messages in thread
From: Waldemar.Rymarkiewicz @ 2010-11-05 15:14 UTC (permalink / raw)
  To: johan.hedberg; +Cc: linux-bluetooth, suraj, joakim.xj.ceder

[-- Attachment #1: Type: text/plain, Size: 948 bytes --]

Hi  Johan, 

>
>Never mind the previous comment I had about this. I checked 
>the rest of the tree and it seems this inline convention for 
>D-Bus error generating functions is quite common (though imho 
>might not be needed at all).
>
>> +	if(sim_card_connection_status != SIM_CONNECTED)
>
>Space before (
>
>> +}
>> +
>> +
>> +static GDBusMethodTable dummy_methods[] = {
>
>Remove the other empty line.
>
>> +	{ "OngoingCall",	"b",	"",	ongoing_call},
>> +	{ "MaxMessageSize",	"u",	"",	max_msg_size},
>> +	{ "Disconnect",		"",	"",	disconnect},
>> +	{ "CardStatus",		"u",	"",	card_status},
>> +	{ }
>
>> +static GDBusSignalTable dummy_signals[] = {
>> +	{ "","" },
>> +	{ }
>> +};
>
>If you have no signals just pass NULL to 
>g_dbus_register_interface instead of declaring an (almost) 
>empty table. Also, "" isn't a valid value for the signal name.


Thanks again for comments and see attached patch.

/Waldek

[-- Attachment #2: 0004-Sim-Access-Profile-dummy-driver.patch --]
[-- Type: application/octet-stream, Size: 12326 bytes --]

From 7e2e1e832e51d22a3acac76a76db1a5c2d95dffe Mon Sep 17 00:00:00 2001
From: Waldemar Rymarkiewicz <waldemar.rymarkiewicz@tieto.com>
Date: Wed, 20 Oct 2010 12:42:48 +0200
Subject: [PATCH 4/4] Sim Access Profile dummy driver

Add SAP dummy driver implementation and extend configure
with --with-sap=<driver>.
---
 .gitignore      |    1 +
 Makefile.am     |   13 +++-
 acinclude.m4    |    6 ++
 sap/sap-dummy.c |  254 +++++++++++++++++++++++++++++++++++++++++++++++++++---
 4 files changed, 257 insertions(+), 17 deletions(-)

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 fe077f7..1d3dd53 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -147,7 +147,13 @@ builtin_modules += sap
 builtin_sources += sap/main.c \
 			sap/manager.h sap/manager.c \
 			sap/server.h sap/server.c \
-			sap/sap.h sap/sap-dummy.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
 endif
 
 if INPUTPLUGIN
@@ -271,7 +277,7 @@ 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
 
 
 if ALSA
@@ -395,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-,,$@) $@
 
diff --git a/acinclude.m4 b/acinclude.m4
index 1f76b4d..0ebeb11 100644
--- a/acinclude.m4
+++ b/acinclude.m4
@@ -194,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}
@@ -219,6 +220,11 @@ AC_DEFUN([AC_ARG_BLUEZ], [
 		serial_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])
+
 	AC_ARG_ENABLE(input, AC_HELP_STRING([--disable-input], [disable input plugin]), [
 		input_enable=${enableval}
 	])
diff --git a/sap/sap-dummy.c b/sap/sap-dummy.c
index 92d73ef..c9897f5 100644
--- a/sap/sap-dummy.c
+++ b/sap/sap-dummy.c
@@ -3,11 +3,13 @@
  *
  *  Copyright (C) 2010 ST-Ericsson SA
  *
- *  Author: Waldemar Rymarkiewicz <waldemar.rymarkiewicz@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.
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
  *
  *  This program is distributed in the hope that it will be useful,
  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
@@ -19,65 +21,287 @@
  *  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"
+
+enum {
+	SIM_CONNECTED	= 0x00,
+	SIM_DISCONNECTED= 0x01,
+	SIM_POWERED_OFF	= 0x02,
+	SIM_MISSING	= 0x03
+};
+
+static DBusConnection *connection = NULL;
+
+static int sim_card_conn_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)
 {
-	sap_connect_rsp(sap_device, SAP_STATUS_OK, maxmsgsize);
-	sap_status_ind(sap_device, SAP_STATUS_CHANGE_CARD_RESET);
+	if (sim_card_conn_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);
+		return;
+	} else {
+		sim_card_conn_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_conn_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, struct sap_parameter *param)
 {
-	sap_transfer_apdu_rsp(sap_device, SAP_RESULT_OK, NULL, 0);
+	if (sim_card_conn_status == SIM_MISSING)
+		sap_transfer_apdu_rsp(sap_device,
+				SAP_RESULT_ERROR_CARD_REMOVED, NULL, 0);
+	else if (sim_card_conn_status == SIM_POWERED_OFF)
+		sap_transfer_apdu_rsp(sap_device, SAP_RESULT_ERROR_POWERED_OFF,
+								NULL, 0);
+	else if (sim_card_conn_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)
 {
-	sap_transfer_atr_rsp(sap_device, SAP_RESULT_OK, NULL, 0);
+	if (sim_card_conn_status == SIM_MISSING)
+		sap_transfer_atr_rsp(sap_device, SAP_RESULT_ERROR_CARD_REMOVED,
+								NULL, 0);
+	else if (sim_card_conn_status == SIM_POWERED_OFF)
+		sap_transfer_atr_rsp(sap_device, SAP_RESULT_ERROR_POWERED_OFF,
+								NULL, 0);
+	else if (sim_card_conn_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, NULL, 0);
 }
 
 void sap_power_sim_off_req(void *sap_device)
 {
-	sap_power_sim_off_rsp(sap_device, SAP_RESULT_OK);
+	if (sim_card_conn_status == SIM_MISSING) {
+		sap_power_sim_off_rsp(sap_device,
+					SAP_RESULT_ERROR_CARD_REMOVED);
+	} else if (sim_card_conn_status == SIM_POWERED_OFF) {
+		sap_power_sim_off_rsp(sap_device,
+					SAP_RESULT_ERROR_POWERED_OFF);
+	} else if (sim_card_conn_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_conn_status = SIM_POWERED_OFF;
+	}
 }
 
 void sap_power_sim_on_req(void *sap_device)
 {
-	sap_power_sim_on_rsp(sap_device, SAP_RESULT_OK);
+	if (sim_card_conn_status == SIM_MISSING) {
+		sap_power_sim_on_rsp(sap_device,
+					SAP_RESULT_ERROR_CARD_REMOVED);
+	} else if (sim_card_conn_status == SIM_POWERED_OFF) {
+		sap_power_sim_on_rsp(sap_device, SAP_RESULT_OK);
+		sim_card_conn_status = SIM_CONNECTED;
+		return;
+	} else if (sim_card_conn_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)
 {
-	sap_reset_sim_rsp(sap_device, SAP_RESULT_OK);
-	sap_status_ind(sap_device, SAP_STATUS_CHANGE_CARD_RESET);
+	if (sim_card_conn_status == SIM_MISSING) {
+		sap_reset_sim_rsp(sap_device, SAP_RESULT_ERROR_CARD_REMOVED);
+	} else if (sim_card_conn_status == SIM_POWERED_OFF) {
+		sap_reset_sim_rsp(sap_device, SAP_RESULT_ERROR_POWERED_OFF);
+	} else if (sim_card_conn_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)
 {
-	sap_transfer_card_reader_status_rsp(sap_device, SAP_RESULT_OK,
-						ICC_READER_CARD_POWERED_ON);
+	if (sim_card_conn_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,
+void sap_set_transport_protocol_req(void *sap_device,
 					struct 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_conn_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_conn_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_conn_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_conn_status == SIM_MISSING) {
+			sim_card_conn_status = SIM_CONNECTED;
+			sap_status_ind(sap_data,
+					SAP_STATUS_CHANGE_CARD_INSERTED);
+		}
+	} else {
+		sim_card_conn_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},
+	{ }
+};
+
 int sap_init(void)
 {
-	DBG("SAP driver init.");
+	connection = dbus_bus_get(DBUS_BUS_SYSTEM, NULL);
+
+	if (g_dbus_register_interface(connection, SAP_DUMMY_PATH,
+					SAP_DUMMY_IFACE,
+					dummy_methods, NULL,
+					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)
 {
-	DBG("SAP driver exit.");
+	dbus_connection_unref(connection);
+	connection = NULL;
 }
-- 
1.7.0.4


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

* Re: [PATCH 1/4] Sim Access Profile API
  2010-11-03 13:34 ` [PATCH 1/4] Sim Access Profile API Waldemar Rymarkiewicz
@ 2010-11-10  5:33   ` Marcel Holtmann
  2010-11-10 11:12     ` Waldemar.Rymarkiewicz
  0 siblings, 1 reply; 21+ messages in thread
From: Marcel Holtmann @ 2010-11-10  5:33 UTC (permalink / raw)
  To: Waldemar Rymarkiewicz
  Cc: linux-bluetooth, suraj, Johan Hedberg, joakim.xj.ceder

Hi Waldemar,

> New API for Sim Access Profile.
> ---
>  Makefile.am     |    2 +-
>  doc/sap-api.txt |   57 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
>  2 files changed, 58 insertions(+), 1 deletions(-)
>  create mode 100644 doc/sap-api.txt
> 
> diff --git a/Makefile.am b/Makefile.am
> index 873f2df..e1183de 100644
> --- a/Makefile.am
> +++ b/Makefile.am
> @@ -352,7 +352,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
>  
> 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

I don't like this. If you have properties then just changing the
property should be enough. So a SetProperty is more appropriate.

> +
> +		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

I don't like this style of method names at all. Using method names like
GracefulDisconnect and ImmediateDisconnect would be better.

However I am not sure we should differentiate here at all. We should
always to the graceful disconnect. What will the immediate disconnect
bring us?

Regards

Marcel



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

* RE: [PATCH 1/4] Sim Access Profile API
  2010-11-10  5:33   ` Marcel Holtmann
@ 2010-11-10 11:12     ` Waldemar.Rymarkiewicz
  2010-11-10 16:07       ` Gustavo F. Padovan
  0 siblings, 1 reply; 21+ messages in thread
From: Waldemar.Rymarkiewicz @ 2010-11-10 11:12 UTC (permalink / raw)
  To: marcel; +Cc: linux-bluetooth, suraj, johan.hedberg, joakim.xj.ceder

Hi Marcel,=20

>> +		void Disable()
>> +
>> +			Shudown SAP server and remove the SDP record.
>> +
>> +			Possible errors: org.bluez.Error.Failed
>
>I don't like this. If you have properties then just changing=20
>the property should be enough. So a SetProperty is more appropriate.

I see another option to get rid of 'Enabled' property and leave the methods=
. What would you say on that?

>> +
>> +		void Disconnect(boolean type)
>> +
>> +			Disconnect SAP client from the server.=20
>The 'type'
>> +			parameter indicates disconnection type.
>> +
>> +			True  - gracefull disconnection
>> +			False - immediate disconnection
>> +
>> +			Possible errors: org.bluez.Error.Failed
>
>I don't like this style of method names at all. Using method=20
>names like GracefulDisconnect and ImmediateDisconnect would be better.

That's fine.

>However I am not sure we should differentiate here at all. We=20
>should always to the graceful disconnect. What will the=20
>immediate disconnect bring us?

That's actually intended for testing only. One of PTS test cases expects th=
e tester to trigger immediate disconnect.
In practce, it is only used when connection to sim card is lost, but this i=
s obviously done internally.

Thanks,
/Waldek=

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

* Re: [PATCH 1/4] Sim Access Profile API
  2010-11-10 11:12     ` Waldemar.Rymarkiewicz
@ 2010-11-10 16:07       ` Gustavo F. Padovan
  2010-11-10 21:46         ` Luiz Augusto von Dentz
  0 siblings, 1 reply; 21+ messages in thread
From: Gustavo F. Padovan @ 2010-11-10 16:07 UTC (permalink / raw)
  To: Waldemar.Rymarkiewicz
  Cc: marcel, linux-bluetooth, suraj, johan.hedberg, joakim.xj.ceder

Hi Waldemar,

* Waldemar.Rymarkiewicz@tieto.com <Waldemar.Rymarkiewicz@tieto.com> [2010-11-10 13:12:53 +0200]:

> Hi Marcel, 
> 
> >> +		void Disable()
> >> +
> >> +			Shudown SAP server and remove the SDP record.
> >> +
> >> +			Possible errors: org.bluez.Error.Failed
> >
> >I don't like this. If you have properties then just changing 
> >the property should be enough. So a SetProperty is more appropriate.
> 
> I see another option to get rid of 'Enabled' property and leave the methods. What would you say on that?

It's not a good a idea. We have been moving everything we can to a set
property operation instead of a method call. Do that as method is add
unnecessary code to BlueZ once we already have set property there.

> 
> >> +
> >> +		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
> >
> >I don't like this style of method names at all. Using method 
> >names like GracefulDisconnect and ImmediateDisconnect would be better.
> 
> That's fine.
> 
> >However I am not sure we should differentiate here at all. We 
> >should always to the graceful disconnect. What will the 
> >immediate disconnect bring us?
> 
> That's actually intended for testing only. One of PTS test cases expects the tester to trigger immediate disconnect.
> In practce, it is only used when connection to sim card is lost, but this is obviously done internally.


So this shouldn't be in the API, no one is going to use it. You can
create something internally for the immediate disconnection that you go
and set manually inside the code. Make sure to comment in the code why
you are adding this there. That can also be a option in some of the
bluetooth config files. Let's see what others think here.

-- 
Gustavo F. Padovan
http://profusion.mobi

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

* Re: [PATCH 1/4] Sim Access Profile API
  2010-11-10 16:07       ` Gustavo F. Padovan
@ 2010-11-10 21:46         ` Luiz Augusto von Dentz
  2010-11-15 17:29           ` Waldemar.Rymarkiewicz
  0 siblings, 1 reply; 21+ messages in thread
From: Luiz Augusto von Dentz @ 2010-11-10 21:46 UTC (permalink / raw)
  To: Gustavo F. Padovan
  Cc: Waldemar.Rymarkiewicz, marcel, linux-bluetooth, suraj,
	johan.hedberg, joakim.xj.ceder

Hi,

On Wed, Nov 10, 2010 at 6:07 PM, Gustavo F. Padovan
<padovan@profusion.mobi> wrote:
> Hi Waldemar,
>
> * Waldemar.Rymarkiewicz@tieto.com <Waldemar.Rymarkiewicz@tieto.com> [2010=
-11-10 13:12:53 +0200]:
>
>> Hi Marcel,
>>
>> >> + =A0 =A0 =A0 =A0 =A0void Disable()
>> >> +
>> >> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0Shudown SAP server and remove th=
e SDP record.
>> >> +
>> >> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0Possible errors: org.bluez.Error=
.Failed
>> >
>> >I don't like this. If you have properties then just changing
>> >the property should be enough. So a SetProperty is more appropriate.
>>
>> I see another option to get rid of 'Enabled' property and leave the meth=
ods. What would you say on that?
>
> It's not a good a idea. We have been moving everything we can to a set
> property operation instead of a method call. Do that as method is add
> unnecessary code to BlueZ once we already have set property there.
>
>>
>> >> +
>> >> + =A0 =A0 =A0 =A0 =A0void Disconnect(boolean type)
>> >> +
>> >> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0Disconnect SAP client from the s=
erver.
>> >The 'type'
>> >> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0parameter indicates disconnectio=
n type.
>> >> +
>> >> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0True =A0- gracefull disconnectio=
n
>> >> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0False - immediate disconnection
>> >> +
>> >> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0Possible errors: org.bluez.Error=
.Failed
>> >
>> >I don't like this style of method names at all. Using method
>> >names like GracefulDisconnect and ImmediateDisconnect would be better.
>>
>> That's fine.
>>
>> >However I am not sure we should differentiate here at all. We
>> >should always to the graceful disconnect. What will the
>> >immediate disconnect bring us?
>>
>> That's actually intended for testing only. One of PTS test cases expects=
 the tester to trigger immediate disconnect.
>> In practce, it is only used when connection to sim card is lost, but thi=
s is obviously done internally.
>
>
> So this shouldn't be in the API, no one is going to use it. You can
> create something internally for the immediate disconnection that you go
> and set manually inside the code. Make sure to comment in the code why
> you are adding this there. That can also be a option in some of the
> bluetooth config files. Let's see what others think here.

Actually this looks a lot like virtual cable unplug that PTS wants to
hid, it is just crap that nobody use, so maybe e.g.
--enable-pts-bullshit would actually make sense to activate the
nonsense that pts wants, well it is still annoying to recompile just
to run PTS tests. For hid the virtual cable unplug can be emulate via
RemoveDevice, so maybe it make sense to do a immediate disconnect in
such case for sap too, but this is still inconvenient since you have
to repair after doing it.

--=20
Luiz Augusto von Dentz
Computer Engineer

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

* RE: [PATCH 1/4] Sim Access Profile API
  2010-11-10 21:46         ` Luiz Augusto von Dentz
@ 2010-11-15 17:29           ` Waldemar.Rymarkiewicz
  0 siblings, 0 replies; 21+ messages in thread
From: Waldemar.Rymarkiewicz @ 2010-11-15 17:29 UTC (permalink / raw)
  To: luiz.dentz, padovan
  Cc: marcel, linux-bluetooth, suraj, johan.hedberg, joakim.xj.ceder

Hi,=20

>Hi,

>>> >> + =A0 =A0 =A0 =A0 =A0void Disconnect(boolean type)
>>> >> +
>>> >> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0Disconnect SAP client from the =
server.
>>> >The 'type'
>>> >> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0parameter indicates disconnecti=
on type.
>>> >> +
>>> >> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0True =A0- gracefull disconnecti=
on
>>> >> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0False - immediate disconnection
>>> >> +
>>> >> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0Possible errors: org.bluez.Erro=
r.Failed
>>> >
>>> >I don't like this style of method names at all. Using method names=20
>>> >like GracefulDisconnect and ImmediateDisconnect would be better.
>>>
>>> That's fine.
>>>
>>> >However I am not sure we should differentiate here at all.=20
>We should=20
>>> >always to the graceful disconnect. What will the immediate=20
>>> >disconnect bring us?
>>>
>>> That's actually intended for testing only. One of PTS test=20
>cases expects the tester to trigger immediate disconnect.
>>> In practce, it is only used when connection to sim card is=20
>lost, but this is obviously done internally.
>>
>>
>> So this shouldn't be in the API, no one is going to use it. You can=20
>> create something internally for the immediate disconnection that you=20
>> go and set manually inside the code. Make sure to comment in=20
>the code=20
>> why you are adding this there. That can also be a option in some of=20
>> the bluetooth config files. Let's see what others think here.
>
>Actually this looks a lot like virtual cable unplug that PTS=20
>wants to hid, it is just crap that nobody use, so maybe e.g.
>--enable-pts-bullshit would actually make sense to activate=20
>the nonsense that pts wants, well it is still annoying to=20
>recompile just to run PTS tests. For hid the virtual cable=20
>unplug can be emulate via RemoveDevice, so maybe it make sense=20
>to do a immediate disconnect in such case for sap too, but=20
>this is still inconvenient since you have to repair after doing it.
>

So, simply let's get rid of immediate disconnect from sap api and leave if =
for sap-driver (sap-*.c file ) provider. I could extend sap-dummy api just =
for an example.

Service		org.bluez=20
Interface	org.bluez.SimAccess=20
Object path	[variable prefix]/{hci0,hci1,...}

Methods		void Disconnect()

			Disconnects SAP client from the server.

			Possible errors: org.bluez.Error.Failed

		void SetProperty(string name, variant value)

			Changes the value of the specified property. Only
			properties that are listed a read-write are changeable.

			Possible Errors: org.bluez.Error.DoesNotExist=20
					org.bluez.Error.InvalidArguments

		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 [readwrite]

			Set to true to start-up SAP server and register SDP record for=20
			it. Set to false to shutdown SAP server and remove the SDP record.

		boolean Connected [readonly]

			Indicates if SAP client is connected to the server.=20


More comments ?

Thanks,
/Waldek

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

* RE: [PATCH 1/4] Sim Access Profile API
  2010-12-02 15:23   ` Waldemar.Rymarkiewicz
@ 2010-12-14 15:16     ` Waldemar.Rymarkiewicz
  0 siblings, 0 replies; 21+ messages in thread
From: Waldemar.Rymarkiewicz @ 2010-12-14 15:16 UTC (permalink / raw)
  To: marcel; +Cc: linux-bluetooth, johan.hedberg


I see no more comments on this API. Does it mean it's fine.

/Waldek

>-----Original Message-----
>From: linux-bluetooth-owner@vger.kernel.org=20
>[mailto:linux-bluetooth-owner@vger.kernel.org] On Behalf Of=20
>Waldemar.Rymarkiewicz@tieto.com
>Sent: Thursday, December 02, 2010 4:23 PM
>To: padovan@profusion.mobi
>Cc: linux-bluetooth@vger.kernel.org; marcel@holtmann.org;=20
>johan.hedberg@gmail.com
>Subject: RE: [PATCH 1/4] Sim Access Profile API
>
>Hi Gustavo,
>
>>-----Original Message-----
>>From: Gustavo F. Padovan [mailto:pao@profusion.mobi] On Behalf Of=20
>>Gustavo F. Padovan
>>Sent: Thursday, December 02, 2010 4:20 PM
>>To: Rymarkiewicz Waldemar
>>Cc: linux-bluetooth@vger.kernel.org; Marcel Holtmann; Johan Hedberg
>>Subject: Re: [PATCH 1/4] Sim Access Profile API
>>
>>Hi Waldemar,
>>
>>* Waldemar Rymarkiewicz <waldemar.rymarkiewicz@tieto.com>
>>[2010-12-02 15:14:21 +0100]:
>>
>>> New API for Sim Access Profile.
>>> ---
>>>  Makefile.am     |    2 +-
>>>  doc/sap-api.txt |   34 ++++++++++++++++++++++++++++++++++
>>>  2 files changed, 35 insertions(+), 1 deletions(-)  create
>>mode 100644
>>> doc/sap-api.txt
>>>=20
>>> diff --git a/Makefile.am b/Makefile.am index 5f96975..97345a3 100644
>>> --- a/Makefile.am
>>> +++ b/Makefile.am
>>> @@ -354,7 +354,7 @@ EXTRA_DIST +=3D 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
>>
>>Leave assigned-numbers.txt in the end.
>> =20
>>>  AM_YFLAGS =3D -d
>>> =20
>>> diff --git a/doc/sap-api.txt b/doc/sap-api.txt new file mode 100644=20
>>> index 0000000..b8b7253
>>> --- /dev/null
>>> +++ b/doc/sap-api.txt
>>> @@ -0,0 +1,34 @@
>>> +BlueZ D-Bus Sim Access Profile API description
>>> +***********************************
>>> +
>>> +Copyright (C) 2010 ST-Ericsson SA
>>> +
>>> +
>>> +Sim Access Profile hierarchy
>>> +=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D
>>> +
>>> +Service		org.bluez
>>> +Interface	org.bluez.SimAccess
>>> +Object path	[variable prefix]/{hci0,hci1,...}
>>> +
>>> +Methods		void Disconnect()
>>> +
>>> +			Disconnects SAP client from the server.
>>> +
>>> +			Possible errors: org.bluez.Error.Failed
>>
>>Don't you need a Connect() method?
>
>It'a a server, not a client.  We will never initialize a connection.
>
>Thanks,
>/Waldek
>--
>To unsubscribe from this list: send the line "unsubscribe=20
>linux-bluetooth" in the body of a message to=20
>majordomo@vger.kernel.org More majordomo info at =20
>http://vger.kernel.org/majordomo-info.html
>=

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

* RE: [PATCH 1/4] Sim Access Profile API
  2010-12-02 15:19 ` Gustavo F. Padovan
@ 2010-12-02 15:23   ` Waldemar.Rymarkiewicz
  2010-12-14 15:16     ` Waldemar.Rymarkiewicz
  0 siblings, 1 reply; 21+ messages in thread
From: Waldemar.Rymarkiewicz @ 2010-12-02 15:23 UTC (permalink / raw)
  To: padovan; +Cc: linux-bluetooth, marcel, johan.hedberg

Hi Gustavo,

>-----Original Message-----
>From: Gustavo F. Padovan [mailto:pao@profusion.mobi] On Behalf=20
>Of Gustavo F. Padovan
>Sent: Thursday, December 02, 2010 4:20 PM
>To: Rymarkiewicz Waldemar
>Cc: linux-bluetooth@vger.kernel.org; Marcel Holtmann; Johan Hedberg
>Subject: Re: [PATCH 1/4] Sim Access Profile API
>
>Hi Waldemar,
>
>* Waldemar Rymarkiewicz <waldemar.rymarkiewicz@tieto.com>=20
>[2010-12-02 15:14:21 +0100]:
>
>> New API for Sim Access Profile.
>> ---
>>  Makefile.am     |    2 +-
>>  doc/sap-api.txt |   34 ++++++++++++++++++++++++++++++++++
>>  2 files changed, 35 insertions(+), 1 deletions(-)  create=20
>mode 100644=20
>> doc/sap-api.txt
>>=20
>> diff --git a/Makefile.am b/Makefile.am index 5f96975..97345a3 100644
>> --- a/Makefile.am
>> +++ b/Makefile.am
>> @@ -354,7 +354,7 @@ EXTRA_DIST +=3D doc/manager-api.txt \
>>  		doc/service-api.txt doc/agent-api.txt=20
>doc/attribute-api.txt \
>>  		doc/serial-api.txt doc/network-api.txt \
>>  		doc/input-api.txt doc/audio-api.txt=20
>doc/control-api.txt \
>> -		doc/hfp-api.txt doc/assigned-numbers.txt
>> +		doc/hfp-api.txt doc/assigned-numbers.txt doc/sap-api.txt
>
>Leave assigned-numbers.txt in the end.
> =20
>>  AM_YFLAGS =3D -d
>> =20
>> diff --git a/doc/sap-api.txt b/doc/sap-api.txt new file mode 100644=20
>> index 0000000..b8b7253
>> --- /dev/null
>> +++ b/doc/sap-api.txt
>> @@ -0,0 +1,34 @@
>> +BlueZ D-Bus Sim Access Profile API description
>> +***********************************
>> +
>> +Copyright (C) 2010 ST-Ericsson SA
>> +
>> +
>> +Sim Access Profile hierarchy
>> +=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D
>> +
>> +Service		org.bluez
>> +Interface	org.bluez.SimAccess
>> +Object path	[variable prefix]/{hci0,hci1,...}
>> +
>> +Methods		void Disconnect()
>> +
>> +			Disconnects SAP client from the server.
>> +
>> +			Possible errors: org.bluez.Error.Failed
>
>Don't you need a Connect() method?

It'a a server, not a client.  We will never initialize a connection.

Thanks,
/Waldek

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

* Re: [PATCH 1/4] Sim Access Profile API
  2010-12-02 14:14 [PATCH 1/4] Sim Access Profile API Waldemar Rymarkiewicz
@ 2010-12-02 15:19 ` Gustavo F. Padovan
  2010-12-02 15:23   ` Waldemar.Rymarkiewicz
  0 siblings, 1 reply; 21+ messages in thread
From: Gustavo F. Padovan @ 2010-12-02 15:19 UTC (permalink / raw)
  To: Waldemar Rymarkiewicz; +Cc: linux-bluetooth, Marcel Holtmann, Johan Hedberg

Hi Waldemar,

* Waldemar Rymarkiewicz <waldemar.rymarkiewicz@tieto.com> [2010-12-02 15:14:21 +0100]:

> New API for Sim Access Profile.
> ---
>  Makefile.am     |    2 +-
>  doc/sap-api.txt |   34 ++++++++++++++++++++++++++++++++++
>  2 files changed, 35 insertions(+), 1 deletions(-)
>  create mode 100644 doc/sap-api.txt
> 
> diff --git a/Makefile.am b/Makefile.am
> index 5f96975..97345a3 100644
> --- a/Makefile.am
> +++ b/Makefile.am
> @@ -354,7 +354,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

Leave assigned-numbers.txt in the end.

>  
>  AM_YFLAGS = -d
>  
> diff --git a/doc/sap-api.txt b/doc/sap-api.txt
> new file mode 100644
> index 0000000..b8b7253
> --- /dev/null
> +++ b/doc/sap-api.txt
> @@ -0,0 +1,34 @@
> +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 Disconnect()
> +
> +			Disconnects SAP client from the server.
> +
> +			Possible errors: org.bluez.Error.Failed

Don't you need a Connect() method?

-- 
Gustavo F. Padovan
http://profusion.mobi

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

* [PATCH 1/4] Sim Access Profile API
@ 2010-12-02 14:14 Waldemar Rymarkiewicz
  2010-12-02 15:19 ` Gustavo F. Padovan
  0 siblings, 1 reply; 21+ messages in thread
From: Waldemar Rymarkiewicz @ 2010-12-02 14:14 UTC (permalink / raw)
  To: linux-bluetooth, Marcel Holtmann, Johan Hedberg; +Cc: Waldemar Rymarkiewicz

New API for Sim Access Profile.
---
 Makefile.am     |    2 +-
 doc/sap-api.txt |   34 ++++++++++++++++++++++++++++++++++
 2 files changed, 35 insertions(+), 1 deletions(-)
 create mode 100644 doc/sap-api.txt

diff --git a/Makefile.am b/Makefile.am
index 5f96975..97345a3 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -354,7 +354,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
 
diff --git a/doc/sap-api.txt b/doc/sap-api.txt
new file mode 100644
index 0000000..b8b7253
--- /dev/null
+++ b/doc/sap-api.txt
@@ -0,0 +1,34 @@
+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 Disconnect()
+
+			Disconnects SAP client from the server.
+
+			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 Connected [readonly]
+
+			Indicates if SAP client is connected to the server.
-- 
1.7.0.4

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

* [PATCH 1/4] Sim Access Profile API
@ 2010-10-20 12:11 Waldemar Rymarkiewicz
  0 siblings, 0 replies; 21+ messages in thread
From: Waldemar Rymarkiewicz @ 2010-10-20 12:11 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Marcel Holtmann, suraj, Waldemar Rymarkiewicz

New API for Sim Access Profile.
---
 Makefile.am     |    2 +-
 doc/sap-api.txt |   57 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 58 insertions(+), 1 deletions(-)
 create mode 100644 doc/sap-api.txt

diff --git a/Makefile.am b/Makefile.am
index 6e8fc7d..eeb1780 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -352,7 +352,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
 
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.
+
-- 
1.7.0.4

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

end of thread, other threads:[~2010-12-14 15:16 UTC | newest]

Thread overview: 21+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2010-11-03 13:34 [PATCH 0/4] Sim Access Profile Waldemar Rymarkiewicz
2010-11-03 13:34 ` [PATCH 1/4] Sim Access Profile API Waldemar Rymarkiewicz
2010-11-10  5:33   ` Marcel Holtmann
2010-11-10 11:12     ` Waldemar.Rymarkiewicz
2010-11-10 16:07       ` Gustavo F. Padovan
2010-11-10 21:46         ` Luiz Augusto von Dentz
2010-11-15 17:29           ` Waldemar.Rymarkiewicz
2010-11-03 13:34 ` [PATCH 2/4] Sim Access Profile Manager Waldemar Rymarkiewicz
2010-11-05  9:30   ` Johan Hedberg
2010-11-05 13:31     ` Waldemar.Rymarkiewicz
2010-11-03 13:34 ` [PATCH 3/4] Sim Access Profile Server Waldemar Rymarkiewicz
2010-11-05 10:05   ` Johan Hedberg
2010-11-05 15:12     ` Waldemar.Rymarkiewicz
2010-11-03 13:34 ` [PATCH 4/4] Sim Access Profile dummy driver Waldemar Rymarkiewicz
2010-11-05 10:16   ` Johan Hedberg
2010-11-05 15:14     ` Waldemar.Rymarkiewicz
  -- strict thread matches above, loose matches on Subject: below --
2010-12-02 14:14 [PATCH 1/4] Sim Access Profile API Waldemar Rymarkiewicz
2010-12-02 15:19 ` Gustavo F. Padovan
2010-12-02 15:23   ` Waldemar.Rymarkiewicz
2010-12-14 15:16     ` Waldemar.Rymarkiewicz
2010-10-20 12:11 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.