Linux bluetooth development
 help / color / mirror / Atom feed
* [PATCH 2/2] Small fix in Health API documentation
From: Elvis Pfützenreuter @ 2010-11-03 14:06 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: epx
In-Reply-To: <1288793188-11514-1-git-send-email-epx@signove.com>

Channel path skeleton is fixed in documentation, in order to
reflect atual implementation.
---
 doc/health-api.txt |    3 +--
 1 files changed, 1 insertions(+), 2 deletions(-)

diff --git a/doc/health-api.txt b/doc/health-api.txt
index 3034666..a0a1685 100644
--- a/doc/health-api.txt
+++ b/doc/health-api.txt
@@ -119,8 +119,7 @@ Properties:
 
 Service		org.bluez
 Interface	org.bluez.HealthChannel
-Object path	[variable prefix]/{hci0,hci1,...}/dev_XX_XX_XX_XX_XX_XX/
-							hdp_YYYY/channel_ZZ
+Object path	[variable prefix]/{hci0,hci1,...}/dev_XX_XX_XX_XX_XX_XX/chanZZZ
 
 Only the process that created the data channel or the creator of the
 HealthApplication that received it will be able to call this methods.
-- 
1.7.0.4


^ permalink raw reply related

* [PATCH 1/2] Add Application property to HealthChannel
From: Elvis Pfützenreuter @ 2010-11-03 14:06 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: epx

This patch adds the Application property to HealthChannel, which
allows to unambiguously relate a channel to an application.

This property is useful when there are several processes interested
in accepting HealthChannels but device address is not sufficient
criteria to engage upon, or ignore, the ChannelConnected signal.
Having the application path allows to determine role and data type,
in the context of the process that has created that application.
---
 doc/health-api.txt |    5 +++++
 health/hdp.c       |    3 +++
 2 files changed, 8 insertions(+), 0 deletions(-)

diff --git a/doc/health-api.txt b/doc/health-api.txt
index 89d5ff9..3034666 100644
--- a/doc/health-api.txt
+++ b/doc/health-api.txt
@@ -160,3 +160,8 @@ Properties:
 
 		Identifies the Remote Device that is connected with. Maps with
 		a HealthDevice object.
+
+	object Application [readonly]
+
+		Identifies the HealthApplication to which this channel is
+		related to (which indirectly defines its role and data type).
diff --git a/health/hdp.c b/health/hdp.c
index be30204..1eba8e1 100644
--- a/health/hdp.c
+++ b/health/hdp.c
@@ -423,6 +423,9 @@ static DBusMessage *channel_get_properties(DBusConnection *conn,
 	path = device_get_path(chan->dev->dev);
 	dict_append_entry(&dict, "Device", DBUS_TYPE_OBJECT_PATH, &path);
 
+	path = chan->app->path;
+	dict_append_entry(&dict, "Application", DBUS_TYPE_OBJECT_PATH, &path);
+
 	if (chan->config == HDP_RELIABLE_DC)
 		type = g_strdup("Reliable");
 	else
-- 
1.7.0.4


^ permalink raw reply related

* [PATCH 4/4] Sim Access Profile dummy driver
From: Waldemar Rymarkiewicz @ 2010-11-03 13:34 UTC (permalink / raw)
  To: linux-bluetooth
  Cc: suraj, Johan Hedberg, joakim.xj.ceder, Waldemar Rymarkiewicz
In-Reply-To: <1288791271-13857-1-git-send-email-waldemar.rymarkiewicz@tieto.com>

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

* [PATCH 3/4] Sim Access Profile Server
From: Waldemar Rymarkiewicz @ 2010-11-03 13:34 UTC (permalink / raw)
  To: linux-bluetooth
  Cc: suraj, Johan Hedberg, joakim.xj.ceder, Waldemar Rymarkiewicz
In-Reply-To: <1288791271-13857-1-git-send-email-waldemar.rymarkiewicz@tieto.com>

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

* [PATCH 2/4] Sim Access Profile Manager
From: Waldemar Rymarkiewicz @ 2010-11-03 13:34 UTC (permalink / raw)
  To: linux-bluetooth
  Cc: suraj, Johan Hedberg, joakim.xj.ceder, Waldemar Rymarkiewicz
In-Reply-To: <1288791271-13857-1-git-send-email-waldemar.rymarkiewicz@tieto.com>

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

* [PATCH 1/4] Sim Access Profile API
From: Waldemar Rymarkiewicz @ 2010-11-03 13:34 UTC (permalink / raw)
  To: linux-bluetooth
  Cc: suraj, Johan Hedberg, joakim.xj.ceder, Waldemar Rymarkiewicz
In-Reply-To: <1288791271-13857-1-git-send-email-waldemar.rymarkiewicz@tieto.com>

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

* [PATCH 0/4] Sim Access Profile
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

* Re: [PATCH v2] Add support for sending small data through obex
From: Anderson Lizardo @ 2010-11-03 11:44 UTC (permalink / raw)
  To: Radoslaw Jablonski; +Cc: linux-bluetooth
In-Reply-To: <1288689911-18507-1-git-send-email-ext-jablonski.radoslaw@nokia.com>

On Tue, Nov 2, 2010 at 5:25 AM, Radoslaw Jablonski
<ext-jablonski.radoslaw@nokia.com> wrote:
> @@ -642,18 +642,39 @@ static int obex_write_stream(struct obex_session *os,
>                goto add_header;
>        }
>
> -       len = os->driver->read(os->object, os->buf, os->tx_mtu, &hi);
> -       if (len < 0) {
> -               error("read(): %s (%zd)", strerror(-len), -len);
> -               if (len == -EAGAIN)
> -                       return len;
> -               else if (len == -ENOSTR)
> -                       return 0;
> +       /* Copying data from source until we reach end of the stream. Sending
> +        * data only if MTU will be filled in 100% or we reach end of data.
> +        * Remaining data in buffer will be sent with next amount of data
> +        * from source.*/
> +       do {
> +               r_len = os->driver->read(os->object, os->buf + os->pending,
> +                                               os->tx_mtu - os->pending, &hi);
>
> -               g_free(os->buf);
> -               os->buf = NULL;
> -               return len;
> -       }
> +               if (r_len == 0)
> +                       break;
> +               else if (r_len < 0) {
> +                       error("read(): %s (%zd)", strerror(-r_len), -r_len);
> +
> +                       switch(r_len) {

Small coding style issue above: a missing space between "switch" and "(".

Regards,
-- 
Anderson Lizardo
OpenBossa Labs - INdT
Manaus - Brazil

^ permalink raw reply

* [PATCHv4 2/2] Bluetooth: timer check sk is not owned before freeing
From: Emeltchenko Andrei @ 2010-11-03 10:32 UTC (permalink / raw)
  To: linux-bluetooth
In-Reply-To: <1288780365-32099-1-git-send-email-Andrei.Emeltchenko.news@gmail.com>

From: Andrei Emeltchenko <andrei.emeltchenko@nokia.com>

In timer context we might delete l2cap channel used by krfcommd.
The check makes sure that sk is not owned. If sk is owned we
restart timer for HZ/5.

Signed-off-by: Andrei Emeltchenko <andrei.emeltchenko@nokia.com>
---
 net/bluetooth/l2cap.c |   32 ++++++++++++++++++++------------
 1 files changed, 20 insertions(+), 12 deletions(-)

diff --git a/net/bluetooth/l2cap.c b/net/bluetooth/l2cap.c
index b5436f7..b2f309d 100644
--- a/net/bluetooth/l2cap.c
+++ b/net/bluetooth/l2cap.c
@@ -83,6 +83,18 @@ static struct sk_buff *l2cap_build_cmd(struct l2cap_conn *conn,
 static int l2cap_ertm_data_rcv(struct sock *sk, struct sk_buff *skb);
 
 /* ---- L2CAP timers ---- */
+static void l2cap_sock_set_timer(struct sock *sk, long timeout)
+{
+	BT_DBG("sk %p state %d timeout %ld", sk, sk->sk_state, timeout);
+	sk_reset_timer(sk, &sk->sk_timer, jiffies + timeout);
+}
+
+static void l2cap_sock_clear_timer(struct sock *sk)
+{
+	BT_DBG("sock %p state %d", sk, sk->sk_state);
+	sk_stop_timer(sk, &sk->sk_timer);
+}
+
 static void l2cap_sock_timeout(unsigned long arg)
 {
 	struct sock *sk = (struct sock *) arg;
@@ -92,6 +104,14 @@ static void l2cap_sock_timeout(unsigned long arg)
 
 	bh_lock_sock(sk);
 
+	if (sock_owned_by_user(sk)) {
+		/* sk is owned by user. Try again later */
+		l2cap_sock_set_timer(sk, HZ / 5);
+		bh_unlock_sock(sk);
+		sock_put(sk);
+		return;
+	}
+
 	if (sk->sk_state == BT_CONNECTED || sk->sk_state == BT_CONFIG)
 		reason = ECONNREFUSED;
 	else if (sk->sk_state == BT_CONNECT &&
@@ -108,18 +128,6 @@ static void l2cap_sock_timeout(unsigned long arg)
 	sock_put(sk);
 }
 
-static void l2cap_sock_set_timer(struct sock *sk, long timeout)
-{
-	BT_DBG("sk %p state %d timeout %ld", sk, sk->sk_state, timeout);
-	sk_reset_timer(sk, &sk->sk_timer, jiffies + timeout);
-}
-
-static void l2cap_sock_clear_timer(struct sock *sk)
-{
-	BT_DBG("sock %p state %d", sk, sk->sk_state);
-	sk_stop_timer(sk, &sk->sk_timer);
-}
-
 /* ---- L2CAP channels ---- */
 static struct sock *__l2cap_get_chan_by_dcid(struct l2cap_chan_list *l, u16 cid)
 {
-- 
1.7.0.4


^ permalink raw reply related

* [PATCHv4 1/2] Bluetooth: Check sk is not owned before freeing l2cap_conn
From: Emeltchenko Andrei @ 2010-11-03 10:32 UTC (permalink / raw)
  To: linux-bluetooth
In-Reply-To: <1288780365-32099-1-git-send-email-Andrei.Emeltchenko.news@gmail.com>

From: Andrei Emeltchenko <andrei.emeltchenko@nokia.com>

Check that socket sk is not locked in user process before removing
l2cap connection handler.

lock_sock and release_sock do not hold a normal spinlock directly but
instead hold the owner field. This means bh_lock_sock can still execute
even if the socket is "locked". More info can be found here:
http://www.linuxfoundation.org/collaborate/workgroups/networking/socketlocks

krfcommd kernel thread may be preempted with l2cap tasklet which remove
l2cap_conn structure. If krfcommd is in process of sending of RFCOMM reply
(like "RFCOMM UA" reply to "RFCOMM DISC") then kernel crash happens.

...
[  694.175933] Unable to handle kernel NULL pointer dereference at virtual address 00000000
[  694.184936] pgd = c0004000
[  694.187683] [00000000] *pgd=00000000
[  694.191711] Internal error: Oops: 5 [#1] PREEMPT
[  694.196350] last sysfs file: /sys/devices/platform/hci_h4p/firmware/hci_h4p/loading
[  694.260375] CPU: 0    Not tainted  (2.6.32.10 #1)
[  694.265106] PC is at l2cap_sock_sendmsg+0x43c/0x73c [l2cap]
[  694.270721] LR is at 0xd7017303
...
[  694.525085] Backtrace:
[  694.527587] [<bf266be0>] (l2cap_sock_sendmsg+0x0/0x73c [l2cap]) from [<c02f2cc8>] (sock_sendmsg+0xb8/0xd8)
[  694.537292] [<c02f2c10>] (sock_sendmsg+0x0/0xd8) from [<c02f3044>] (kernel_sendmsg+0x48/0x80)

Signed-off-by: Andrei Emeltchenko <andrei.emeltchenko@nokia.com>
---
 net/bluetooth/l2cap.c |   26 ++++++++++++++++++++++++++
 1 files changed, 26 insertions(+), 0 deletions(-)

diff --git a/net/bluetooth/l2cap.c b/net/bluetooth/l2cap.c
index 6f931cc..b5436f7 100644
--- a/net/bluetooth/l2cap.c
+++ b/net/bluetooth/l2cap.c
@@ -3078,6 +3078,14 @@ static inline int l2cap_connect_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hd
 		break;
 
 	default:
+		/* don't delete l2cap channel if sk is owned by user */
+		if (sock_owned_by_user(sk)) {
+			sk->sk_state = BT_DISCONN;
+			l2cap_sock_clear_timer(sk);
+			l2cap_sock_set_timer(sk, HZ / 5);
+			break;
+		}
+
 		l2cap_chan_del(sk, ECONNREFUSED);
 		break;
 	}
@@ -3283,6 +3291,15 @@ static inline int l2cap_disconnect_req(struct l2cap_conn *conn, struct l2cap_cmd
 
 	sk->sk_shutdown = SHUTDOWN_MASK;
 
+	/* don't delete l2cap channel if sk is owned by user */
+	if (sock_owned_by_user(sk)) {
+		sk->sk_state = BT_DISCONN;
+		l2cap_sock_clear_timer(sk);
+		l2cap_sock_set_timer(sk, HZ / 5);
+		bh_unlock_sock(sk);
+		return 0;
+	}
+
 	l2cap_chan_del(sk, ECONNRESET);
 	bh_unlock_sock(sk);
 
@@ -3305,6 +3322,15 @@ static inline int l2cap_disconnect_rsp(struct l2cap_conn *conn, struct l2cap_cmd
 	if (!sk)
 		return 0;
 
+	/* don't delete l2cap channel if sk is owned by user */
+	if (sock_owned_by_user(sk)) {
+		sk->sk_state = BT_DISCONN;
+		l2cap_sock_clear_timer(sk);
+		l2cap_sock_set_timer(sk, HZ / 5);
+		bh_unlock_sock(sk);
+		return 0;
+	}
+
 	l2cap_chan_del(sk, 0);
 	bh_unlock_sock(sk);
 
-- 
1.7.0.4


^ permalink raw reply related

* [PATCHv4 0/2] Fix kernel crash in rfcomm/l2cap
From: Emeltchenko Andrei @ 2010-11-03 10:32 UTC (permalink / raw)
  To: linux-bluetooth

From: Andrei Emeltchenko <andrei.emeltchenko@nokia.com>

Yet another version of patches fixing kernel crash in RFCOMM / L2CAP.
*v4: taken Gustavo comments about timer HZ -> HZ/5

Do not delete l2cap channel and socket sk when sk is owned by user.
To delete l2cap channel standard timer is used.

lock_sock and release_sock do not hold a normal spinlock directly but 
instead hold the owner field. This means bh_lock_sock can still execute
even if the socket is "locked". More info can be found here:
http://www.linuxfoundation.org/collaborate/workgroups/networking/socketlocks

When sending following sequence:
...
No.     Time        Source                Destination           Protocol Info
    89 1.951202            RFCOMM   Rcvd DISC DLCI=20
    90 1.951324            RFCOMM   Sent UA DLCI=20
    91 1.959381            HCI_EVT   Number of Completed Packets
    92 1.966461            RFCOMM   Rcvd DISC DLCI=0
    93 1.966492            L2CAP    Rcvd Disconnect Request
    94 1.972595            L2CAP    Sent Disconnect Response

...

krfcommd kernel thread is preempted with l2cap tasklet which remove l2cap_conn
(L2CAP connection handler structure). Then rfcomm thread tries to send RFCOMM
UA which is reply to RFCOMM DISC and when de-referencing l2cap_conn crash
happens.

Andrei Emeltchenko (2):
  Bluetooth: Check sk is not owned before freeing l2cap_conn
  Bluetooth: timer check sk is not owned before freeing

 net/bluetooth/l2cap.c |   58 ++++++++++++++++++++++++++++++++++++++----------
 1 files changed, 46 insertions(+), 12 deletions(-)


^ permalink raw reply

* [PATCH] Fix folder listing not able to use name header to list sub folders
From: Luiz Augusto von Dentz @ 2010-11-03  9:56 UTC (permalink / raw)
  To: linux-bluetooth

From: Luiz Augusto von Dentz <luiz.dentz-von@nokia.com>

---
 plugins/ftp.c |    3 ---
 1 files changed, 0 insertions(+), 3 deletions(-)

diff --git a/plugins/ftp.c b/plugins/ftp.c
index 007fe4a..91c77a3 100644
--- a/plugins/ftp.c
+++ b/plugins/ftp.c
@@ -171,9 +171,6 @@ static int get_by_type(struct ftp_session *ftp, const char *type)
 	if (g_strcmp0(type, CAP_TYPE) == 0)
 		return obex_get_stream_start(os, capability);
 
-	if (g_strcmp0(type, LST_TYPE) == 0)
-		return obex_get_stream_start(os, ftp->folder);
-
 	path = g_build_filename(ftp->folder, name, NULL);
 	err = obex_get_stream_start(os, path);
 
-- 
1.7.1


^ permalink raw reply related

* [PATCHv4 1/2] Bluetooth: Check sk is not owned before freeing l2cap_conn
From: Emeltchenko Andrei @ 2010-11-03  7:47 UTC (permalink / raw)
  To: linux-bluetooth
In-Reply-To: <1288770478-22978-1-git-send-email-Andrei.Emeltchenko.news@gmail.com>

From: Andrei Emeltchenko <andrei.emeltchenko@nokia.com>

Check that socket sk is not locked in user process before removing
l2cap connection handler.

lock_sock and release_sock do not hold a normal spinlock directly but
instead hold the owner field. This means bh_lock_sock can still execute
even if the socket is "locked". More info can be found here:
http://www.linuxfoundation.org/collaborate/workgroups/networking/socketlocks

krfcommd kernel thread may be preempted with l2cap tasklet which remove
l2cap_conn structure. If krfcommd is in process of sending of RFCOMM reply
(like "RFCOMM UA" reply to "RFCOMM DISC") then kernel crash happens.

...
[  694.175933] Unable to handle kernel NULL pointer dereference at virtual address 00000000
[  694.184936] pgd = c0004000
[  694.187683] [00000000] *pgd=00000000
[  694.191711] Internal error: Oops: 5 [#1] PREEMPT
[  694.196350] last sysfs file: /sys/devices/platform/hci_h4p/firmware/hci_h4p/loading
[  694.260375] CPU: 0    Not tainted  (2.6.32.10 #1)
[  694.265106] PC is at l2cap_sock_sendmsg+0x43c/0x73c [l2cap]
[  694.270721] LR is at 0xd7017303
...
[  694.525085] Backtrace:
[  694.527587] [<bf266be0>] (l2cap_sock_sendmsg+0x0/0x73c [l2cap]) from [<c02f2cc8>] (sock_sendmsg+0xb8/0xd8)
[  694.537292] [<c02f2c10>] (sock_sendmsg+0x0/0xd8) from [<c02f3044>] (kernel_sendmsg+0x48/0x80)

Signed-off-by: Andrei Emeltchenko <andrei.emeltchenko@nokia.com>
---
 net/bluetooth/l2cap.c |   26 ++++++++++++++++++++++++++
 1 files changed, 26 insertions(+), 0 deletions(-)

diff --git a/net/bluetooth/l2cap.c b/net/bluetooth/l2cap.c
index 6f931cc..b5436f7 100644
--- a/net/bluetooth/l2cap.c
+++ b/net/bluetooth/l2cap.c
@@ -3078,6 +3078,14 @@ static inline int l2cap_connect_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hd
 		break;
 
 	default:
+		/* don't delete l2cap channel if sk is owned by user */
+		if (sock_owned_by_user(sk)) {
+			sk->sk_state = BT_DISCONN;
+			l2cap_sock_clear_timer(sk);
+			l2cap_sock_set_timer(sk, HZ / 5);
+			break;
+		}
+
 		l2cap_chan_del(sk, ECONNREFUSED);
 		break;
 	}
@@ -3283,6 +3291,15 @@ static inline int l2cap_disconnect_req(struct l2cap_conn *conn, struct l2cap_cmd
 
 	sk->sk_shutdown = SHUTDOWN_MASK;
 
+	/* don't delete l2cap channel if sk is owned by user */
+	if (sock_owned_by_user(sk)) {
+		sk->sk_state = BT_DISCONN;
+		l2cap_sock_clear_timer(sk);
+		l2cap_sock_set_timer(sk, HZ / 5);
+		bh_unlock_sock(sk);
+		return 0;
+	}
+
 	l2cap_chan_del(sk, ECONNRESET);
 	bh_unlock_sock(sk);
 
@@ -3305,6 +3322,15 @@ static inline int l2cap_disconnect_rsp(struct l2cap_conn *conn, struct l2cap_cmd
 	if (!sk)
 		return 0;
 
+	/* don't delete l2cap channel if sk is owned by user */
+	if (sock_owned_by_user(sk)) {
+		sk->sk_state = BT_DISCONN;
+		l2cap_sock_clear_timer(sk);
+		l2cap_sock_set_timer(sk, HZ / 5);
+		bh_unlock_sock(sk);
+		return 0;
+	}
+
 	l2cap_chan_del(sk, 0);
 	bh_unlock_sock(sk);
 
-- 
1.7.0.4


^ permalink raw reply related

* Re: [PATCH] Cleanup set_mode code
From: Johan Hedberg @ 2010-11-02 22:25 UTC (permalink / raw)
  To: Luiz Augusto von Dentz; +Cc: linux-bluetooth
In-Reply-To: <1288709056-7551-1-git-send-email-luiz.dentz@gmail.com>

Hi Luiz,

On Tue, Nov 02, 2010, Luiz Augusto von Dentz wrote:
> From: Luiz Augusto von Dentz <luiz.dentz-von@nokia.com>
> 
> Now that MODE_LIMITED was removed there is no need to compare string mode
> to determine if scan mode will change or not.
> ---
>  src/adapter.c |   21 +++++----------------
>  1 files changed, 5 insertions(+), 16 deletions(-)

Pushed upstream. Thanks.

Johan

^ permalink raw reply

* RE: [RFC] LE connections and advertising management
From: Brian Redding @ 2010-11-02 20:23 UTC (permalink / raw)
  To: 'Mike Tsai', 'Claudio Takahasi'
  Cc: 'BlueZ development'
In-Reply-To: <35B17FE5076C7040809188FBE7913F983F847B44A8@SC1EXMB-MBCL.global.atheros.com>

> [Claudio]
> Is it allowed duplicated UUIDs for the same primary service? We are
> not handling this right now.
> It seems that you already have a proprietary implementation ;-)
> 
> [Mike Tsai] I think it is probably not allowed to duplicate
> characteristic within the same primary services. However, there may be
> duplicated primary services within a server or duplicated included
> service within a server, or same characteristic inside 2 different
> primary services. So I don't know if you have any mechanism to let
> GAttrib get the correct characteristic within all these duplicated
> services by just passing the 128 bits UUID?

The GATT places no limitation on multiple instances of characteristics or
services.  The recommendation to profile writers when duplicate
characteristics exist within a service is that each characteristic has a
characteristic presentation descriptor that distinguishes each instance of
the characteristic.  The same would apply to multiple instances of a
service.  There are other methods to distinguish multiple instances of
services and characteristics including different UUIDs so there isn't a
single approach.  The approach though is specified by the profile.

Brian
---
Brian A. Redding
Employee of Qualcomm Innovation Center, Inc.
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum


^ permalink raw reply

* Re: >net-wireless/bluez-4.63 unable to connect audio streams due commit
From: Peter Hurley @ 2010-11-02 17:25 UTC (permalink / raw)
  To: pacho
  Cc: Uwe Kleine-König, Luiz Augusto von Dentz, Johan Hedberg,
	linux-bluetooth
In-Reply-To: <1288524358.2654.4.camel@localhost.localdomain>

Hi Pacho,

On Sun, 2010-10-31 at 12:25 +0100, Pacho Ramos wrote:
> El lun, 18-10-2010 a las 20:24 +0200, Pacho Ramos escribió:
> > El lun, 04-10-2010 a las 14:35 +0200, Uwe Kleine-König escribió:
> > > Hello Pacho,
> > > 
> > > On Mon, Oct 04, 2010 at 12:25:46PM +0200, Pacho Ramos wrote:
> > > > > I would say this was because of double authentication request, but it
> > > > > seems it is not the case, actually ssp doesn't seems to be used at all
> > > > > here so this must be something else, maybe you should try this:
> > > > > 
> > > > > http://thread.gmane.org/gmane.linux.bluez.kernel/7256
> > > > > 
> > > > 
> > > > Thanks but, how should I try to apply that patch? Looks like
> > > > net/bluetooth/rfcomm/core.c is not present on bluez-4.72 sources
> > > I guess this is a patch to apply to your kernel, not bluez.
> > > 
> > > Best regards
> > > Uwe
> > > 
> > 
> > Downstream affected reported told me it's still failing even with the
> > patch:
> > 
> > http://bugs.gentoo.org/show_bug.cgi?id=327705#c19
> > 
> > Attached is the new hcidump output
> > 
> > Thanks a lot for your help :-)
> > 
> 
> There is no possible solution to this? :-(
> 
> Thanks

The hcidump output reported is unfortunately insufficient to determine
the actual cause of failure. The indicated cause of failure appears to
be an error return from the Set Connection Encryption cmd (as indicated
by the absence of an Encryption Change evt). The actual error code is
not indicated in the hcidump output -- really, 'hcidump -tVx' is more
helpful for troubleshooting remotely.

The "Function not implemented (38)" message (which is in the bluetoothd
output capture in the downstream report) is the kernel bt stack's
translation to errno for bluetooth error codes primarily associated with
piconet errors (like Reserved Slot Violation(s), LMP Response Timeout,
etc. Actually, it's a catchall for errors the kernel bt stack thinks it
can't really do anything about).

Although I'd be happy to take a look at a more complete hcidump, the
reality is that there are bluetooth device incompatibilities/bugs that
are often unfixable - even when the hardware's available. My own bt
dongle reports that it's eSCO capable but hangs the LM when actually
attempting to negotiate an eSCO connection.

Hope that helps,
Peter Hurley


^ permalink raw reply

* Re: Downstream patches
From: Marcel Holtmann @ 2010-11-02 15:39 UTC (permalink / raw)
  To: Johan Hedberg; +Cc: Bastien Nocera, BlueZ development
In-Reply-To: <20101027221627.GA24756@jh-x301>

Hi Bastien,

> > 0001-systemd-install-systemd-unit-files.patch installs a systemd unit,
> > which, when systemd is used, replaces the udev rule to launch
> > bluetoothd. This was pretty heavily tested as part of the alpha for
> > Fedora 14, though systemd was not included in the end.
> > 
> > This patch is used in Fedora 15 now.
> 
> I'll let Marcel comment on this since IIRC he had previously some issues
> with systemd related patches.

I still have the systemd patches in my queue. I wanna do some proper
cleanup to move over to systemd full scale. And just remove everything
else from the source repository and the packages.

Regards

Marcel



^ permalink raw reply

* Re: [PATCH 3/6] MacBookAir3,1(3,2) btusb support
From: Marcel Holtmann @ 2010-11-02 15:38 UTC (permalink / raw)
  To: Dmitry Torokhov; +Cc: linux-bluetooth, linux-kernel, gimli
In-Reply-To: <20101102152454.GC11778@core.coreip.homeip.net>

Hi Dmitry,

> Not sure of you guys monitor LKML...

not on a regular basis.

> > This patch add support for the MacBookAir3,1 and MacBookAir3,2 to the btusb
> > driver.
> > 
> > Signed-off-by: Edgar (gimli) Hucek <gimli@dark-green.com>
> 
> > --- a/drivers/bluetooth/btusb.c	2010-10-30 21:08:45.170492002 +0200
> > +++ b/drivers/bluetooth/btusb.c	2010-10-30 21:18:11.820492000 +0200
> > @@ -62,6 +62,9 @@
> >  	/* Apple iMac11,1 */
> >  	{ USB_DEVICE(0x05ac, 0x8215) },
> >  
> > +	/* Apple MacBookAir3,1, MacBookAir3,2 */
> > +	{ USB_DEVICE(0x05ac, 0x821b) },
> > +
> >  	/* AVM BlueFRITZ! USB v2.0 */
> >  	{ USB_DEVICE(0x057c, 0x3800) },

patch looks fine to me, but it should be send to linux-bluetooth mailing
list.

Acked-by: Marcel Holtmann <marcel@holtmann.org>

Regards

Marcel



^ permalink raw reply

* Re: [PATCH] bluetooth: hidp: fix information leak to userland
From: Marcel Holtmann @ 2010-11-02 15:36 UTC (permalink / raw)
  To: Vasiliy Kulikov
  Cc: kernel-janitors, Gustavo F. Padovan, David S. Miller, Jiri Kosina,
	Michael Poole, Bastien Nocera, linux-bluetooth, netdev,
	linux-kernel
In-Reply-To: <1288448791-6009-1-git-send-email-segooon@gmail.com>

Hi Vasiliy,

> Structure hidp_conninfo is copied to userland with version, product,
> vendor and name fields unitialized if both session->input and session->hid
> are NULL.  It leads to leaking of contents of kernel stack memory.
> 
> Signed-off-by: Vasiliy Kulikov <segooon@gmail.com>

Acked-by: Marcel Holtmann <marcel@holtmann.org>

Regards

Marcel



^ permalink raw reply

* Re: [PATCH] bluetooth: cmtp: fix information leak to userland
From: Marcel Holtmann @ 2010-11-02 15:35 UTC (permalink / raw)
  To: Vasiliy Kulikov
  Cc: kernel-janitors, Gustavo F. Padovan, David S. Miller,
	Eric Dumazet, linux-bluetooth, netdev, linux-kernel
In-Reply-To: <1288448787-5848-1-git-send-email-segooon@gmail.com>

Hi Vasiliy,

> Structure cmtp_conninfo is copied to userland with some padding fields
> unitialized.  It leads to leaking of contents of kernel stack memory.
> 
> Signed-off-by: Vasiliy Kulikov <segooon@gmail.com>

Acked-by: Marcel Holtmann <marcel@holtmann.org>

Regards

Marcel



^ permalink raw reply

* Re: [PATCH] bluetooth: bnep: fix information leak to userland
From: Marcel Holtmann @ 2010-11-02 15:35 UTC (permalink / raw)
  To: Vasiliy Kulikov
  Cc: kernel-janitors, Gustavo F. Padovan, David S. Miller,
	Eric Dumazet, Thadeu Lima de Souza Cascardo, Tejun Heo,
	Jiri Kosina, linux-bluetooth, netdev, linux-kernel
In-Reply-To: <1288448782-5582-1-git-send-email-segooon@gmail.com>

Hi Vasiiy,

> Structure bnep_conninfo is copied to userland with the field "device"
> that has the last elements unitialized.  It leads to leaking of
> contents of kernel stack memory.
> 
> Signed-off-by: Vasiliy Kulikov <segooon@gmail.com>

Acked-by: Marcel Holtmann <marcel@holtmann.org>

Regards

Marcel



^ permalink raw reply

* Re: [PATCH 3/6] MacBookAir3,1(3,2) btusb support
From: Dmitry Torokhov @ 2010-11-02 15:24 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: linux-kernel, gimli, Marcel Holtmann
In-Reply-To: <9e7738c0461aa509dd55fe470df3855e@mognix.dark-green.com>

Not sure of you guys monitor LKML...

On Tue, Nov 02, 2010 at 08:19:43AM +0100, gimli wrote:
> This patch add support for the MacBookAir3,1 and MacBookAir3,2 to the btusb
> driver.
> 
> Signed-off-by: Edgar (gimli) Hucek <gimli@dark-green.com>

> --- a/drivers/bluetooth/btusb.c	2010-10-30 21:08:45.170492002 +0200
> +++ b/drivers/bluetooth/btusb.c	2010-10-30 21:18:11.820492000 +0200
> @@ -62,6 +62,9 @@
>  	/* Apple iMac11,1 */
>  	{ USB_DEVICE(0x05ac, 0x8215) },
>  
> +	/* Apple MacBookAir3,1, MacBookAir3,2 */
> +	{ USB_DEVICE(0x05ac, 0x821b) },
> +
>  	/* AVM BlueFRITZ! USB v2.0 */
>  	{ USB_DEVICE(0x057c, 0x3800) },
>  


-- 
Dmitry

^ permalink raw reply

* Re: [PATCHv3 2/2] Bluetooth: timer check sk is not owned before freeing
From: Gustavo F. Padovan @ 2010-11-02 15:15 UTC (permalink / raw)
  To: Andrei Emeltchenko; +Cc: linux-bluetooth
In-Reply-To: <AANLkTiksc7jKPqxkFEZqvgBJ5ATvGh0nurWS9SZcdtit@mail.gmail.com>

Hi Andrei,

* Andrei Emeltchenko <andrei.emeltchenko.news@gmail.com> [2010-11-01 16:20:15 +0200]:

> Hi Gustavo
> 
> On Sat, Oct 30, 2010 at 12:17 AM, Gustavo F. Padovan
> <padovan@profusion.mobi> wrote:
> > Hi Andrei,
> >
> > * Emeltchenko Andrei <Andrei.Emeltchenko.news@gmail.com> [2010-10-29 16:43:01 +0300]:
> >
> >> From: Andrei Emeltchenko <andrei.emeltchenko@nokia.com>
> >>
> >> In timer context we might delete l2cap channel used by krfcommd.
> >> The check makes sure that sk is not owned. If sk is owned we
> >> restart timer for HZ/5.
> >>
> >> Signed-off-by: Andrei Emeltchenko <andrei.emeltchenko@nokia.com>
> >> ---
> >>  net/bluetooth/l2cap.c |   32 ++++++++++++++++++++------------
> >>  1 files changed, 20 insertions(+), 12 deletions(-)
> >>
> >> diff --git a/net/bluetooth/l2cap.c b/net/bluetooth/l2cap.c
> >> index b1344d8..c67b3c6 100644
> >> --- a/net/bluetooth/l2cap.c
> >> +++ b/net/bluetooth/l2cap.c
> >> @@ -83,6 +83,18 @@ static struct sk_buff *l2cap_build_cmd(struct l2cap_conn *conn,
> >>  static int l2cap_ertm_data_rcv(struct sock *sk, struct sk_buff *skb);
> >>
> >>  /* ---- L2CAP timers ---- */
> >> +static void l2cap_sock_set_timer(struct sock *sk, long timeout)
> >> +{
> >> +     BT_DBG("sk %p state %d timeout %ld", sk, sk->sk_state, timeout);
> >> +     sk_reset_timer(sk, &sk->sk_timer, jiffies + timeout);
> >> +}
> >> +
> >> +static void l2cap_sock_clear_timer(struct sock *sk)
> >> +{
> >> +     BT_DBG("sock %p state %d", sk, sk->sk_state);
> >> +     sk_stop_timer(sk, &sk->sk_timer);
> >> +}
> >> +
> >>  static void l2cap_sock_timeout(unsigned long arg)
> >>  {
> >>       struct sock *sk = (struct sock *) arg;
> >> @@ -92,6 +104,14 @@ static void l2cap_sock_timeout(unsigned long arg)
> >>
> >>       bh_lock_sock(sk);
> >>
> >> +     if (sock_owned_by_user(sk)) {
> >> +             /* sk is owned by user. Try again later */
> >> +             l2cap_sock_set_timer(sk, HZ / 5);
> >> +             bh_unlock_sock(sk);
> >> +             sock_put(sk);
> >
> > You can't do a sock_put() here, you have to keep the referencee to the
> > socket while the timer is enabled.
> 
> sk_reset_timer is holding sock when timer restarts. The same way done
> in TCP code in function:
> static void tcp_delack_timer(unsigned long data)

Yes, I got confused, you're right.

-- 
Gustavo F. Padovan
ProFUSION embedded systems - http://profusion.mobi

^ permalink raw reply

* [PATCH 7/7] Bluetooth: Fix not returning proper error in RFCOMM
From: Gustavo F. Padovan @ 2010-11-02 15:03 UTC (permalink / raw)
  To: linux-bluetooth
In-Reply-To: <1288710198-6108-6-git-send-email-padovan@profusion.mobi>

Return 0 in that situation could lead to errors in the caller.

Signed-off-by: Gustavo F. Padovan <padovan@profusion.mobi>
---
 net/bluetooth/rfcomm/sock.c |    2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)

diff --git a/net/bluetooth/rfcomm/sock.c b/net/bluetooth/rfcomm/sock.c
index e48fbca..cd7e27a 100644
--- a/net/bluetooth/rfcomm/sock.c
+++ b/net/bluetooth/rfcomm/sock.c
@@ -930,7 +930,7 @@ int rfcomm_connect_ind(struct rfcomm_session *s, u8 channel, struct rfcomm_dlc *
 	/* Check if we have socket listening on channel */
 	parent = rfcomm_get_sock_by_channel(BT_LISTEN, channel, &src);
 	if (!parent)
-		return 0;
+		return -EINVAL;
 
 	bh_lock_sock(parent);
 
-- 
1.7.3.1


^ permalink raw reply related

* [PATCH 6/7] Bluetooth: Fix not returning proper error in SCO
From: Gustavo F. Padovan @ 2010-11-02 15:03 UTC (permalink / raw)
  To: linux-bluetooth
In-Reply-To: <1288710198-6108-5-git-send-email-padovan@profusion.mobi>

Return 0 in that situation could lead to errors in the caller.

Signed-off-by: Gustavo F. Padovan <padovan@profusion.mobi>
---
 net/bluetooth/sco.c |    6 +++---
 1 files changed, 3 insertions(+), 3 deletions(-)

diff --git a/net/bluetooth/sco.c b/net/bluetooth/sco.c
index 85b5498..f031b62 100644
--- a/net/bluetooth/sco.c
+++ b/net/bluetooth/sco.c
@@ -880,7 +880,7 @@ static int sco_connect_ind(struct hci_dev *hdev, bdaddr_t *bdaddr, __u8 type)
 	int lm = 0;
 
 	if (type != SCO_LINK && type != ESCO_LINK)
-		return 0;
+		return -EINVAL;
 
 	BT_DBG("hdev %s, bdaddr %s", hdev->name, batostr(bdaddr));
 
@@ -906,7 +906,7 @@ static int sco_connect_cfm(struct hci_conn *hcon, __u8 status)
 	BT_DBG("hcon %p bdaddr %s status %d", hcon, batostr(&hcon->dst), status);
 
 	if (hcon->type != SCO_LINK && hcon->type != ESCO_LINK)
-		return 0;
+		return -EINVAL;
 
 	if (!status) {
 		struct sco_conn *conn;
@@ -925,7 +925,7 @@ static int sco_disconn_cfm(struct hci_conn *hcon, __u8 reason)
 	BT_DBG("hcon %p reason %d", hcon, reason);
 
 	if (hcon->type != SCO_LINK && hcon->type != ESCO_LINK)
-		return 0;
+		return -EINVAL;
 
 	sco_conn_del(hcon, bt_err(reason));
 
-- 
1.7.3.1


^ permalink raw reply related


This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox