2010-10-20 12:11:18

by Rymarkiewicz Waldemar

[permalink] [raw]
Subject: [PATCH 1/4] Sim Access Profile API

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

diff --git a/Makefile.am b/Makefile.am
index 6e8fc7d..eeb1780 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -352,7 +352,7 @@ EXTRA_DIST += doc/manager-api.txt \
doc/service-api.txt doc/agent-api.txt doc/attribute-api.txt \
doc/serial-api.txt doc/network-api.txt \
doc/input-api.txt doc/audio-api.txt doc/control-api.txt \
- doc/hfp-api.txt doc/assigned-numbers.txt
+ doc/hfp-api.txt doc/assigned-numbers.txt doc/sap-api.txt

AM_YFLAGS = -d

diff --git a/doc/sap-api.txt b/doc/sap-api.txt
new file mode 100644
index 0000000..7951f56
--- /dev/null
+++ b/doc/sap-api.txt
@@ -0,0 +1,57 @@
+BlueZ D-Bus Sim Access Profile API description
+***********************************
+
+Copyright (C) 2010 ST-Ericsson SA
+
+
+Sim Access Profile hierarchy
+============================
+
+Service org.bluez
+Interface org.bluez.SimAccess
+Object path [variable prefix]/{hci0,hci1,...}
+
+Methods void Enable()
+
+ Start up SAP server and register SDP record for it.
+
+ Possible errors: org.bluez.Error.Failed
+
+ void Disable()
+
+ Shudown SAP server and remove the SDP record.
+
+ Possible errors: org.bluez.Error.Failed
+
+ void Disconnect(boolean type)
+
+ Disconnect SAP client from the server. The 'type'
+ parameter indicates disconnection type.
+
+ True - gracefull disconnection
+ False - immediate disconnection
+
+ Possible errors: org.bluez.Error.Failed
+
+ dict GetProperties()
+
+ Return all properties for the interface. See the
+ properties section for available properties.
+
+ Possible Errors: org.bluez.Error.Failed
+
+Signals PropertyChanged(string name, variant value)
+
+ This signal indicates a changed value of the given
+ property.
+
+
+Properties boolean Enabled [readonly]
+
+ Indicates the state of the server. True if the server
+ is enabled and False otherwise.
+
+ boolean Connected [readonly]
+
+ Indicates if SAP client is connected to the server.
+
--
1.7.0.4


2010-10-21 08:41:57

by Suraj Sumangala

[permalink] [raw]
Subject: Re: [PATCH 3/4] Sim Access Profile Server

Hi,

On 10/21/2010 2:08 PM, [email protected] wrote:
> Hi Suraj,
>
>>
>> Looks like this patch does not apply successfully on the
>> latest Bluez tree after applying the first two. Can you verify that?
>>
>
> I've just git pull the latest upstream, git am for all the patches and don't have the problem with applying them.
>
> /Waldek

Alright, may be it has something to do with my mail client.

Regards
Suraj

2010-10-21 08:38:00

by Rymarkiewicz Waldemar

[permalink] [raw]
Subject: RE: [PATCH 3/4] Sim Access Profile Server

Hi Suraj,

>
>Looks like this patch does not apply successfully on the=20
>latest Bluez tree after applying the first two. Can you verify that?
>

I've just git pull the latest upstream, git am for all the patches and don'=
t have the problem with applying them.

/Waldek=

2010-10-21 07:19:06

by Suraj Sumangala

[permalink] [raw]
Subject: Re: [PATCH 3/4] Sim Access Profile Server

Hi,

On 10/20/2010 5:41 PM, Waldemar Rymarkiewicz wrote:
> 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


Looks like this patch does not apply successfully on the latest Bluez
tree after applying the first two. Can you verify that?

Regards
Suraj

2010-10-20 12:11:21

by Rymarkiewicz Waldemar

[permalink] [raw]
Subject: [PATCH 4/4] Sim Access Profile dummy driver

Add SAP dummy driver implementation and extend configure
with --with-sap=<driver>.
---
.gitignore | 1 +
Makefile.am | 13 +++-
acinclude.m4 | 6 ++
sap/sap-dummy.c | 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 0facbe2..64c60f6 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

2010-10-20 12:11:20

by Rymarkiewicz Waldemar

[permalink] [raw]
Subject: [PATCH 3/4] Sim Access Profile Server

Add a Sim Access Server to the SAP plugin and a framework for the dummy
sap driver as well.
---
Makefile.am | 3 +-
sap/sap-dummy.c | 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 4c91469..0facbe2 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 <[email protected]> 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<[email protected]>
+ *
+ * Author: Marek Skowron <[email protected]> for ST-Ericsson.
+ * Author: Waldemar Rymarkiewicz <[email protected]> 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<[email protected]>
*
+ * Author: Marek Skowron <[email protected]> for ST-Ericsson.
* Author: Waldemar Rymarkiewicz <[email protected]> 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

2010-10-20 12:11:19

by Rymarkiewicz Waldemar

[permalink] [raw]
Subject: [PATCH 2/4] Sim Access Profile Manager

Add a SAP plugin main file and the plugin manager. Also include the SAP
plugin in the Makefile.
---
Makefile.am | 7 ++++
acinclude.m4 | 6 ++++
sap/main.c | 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 eeb1780..4c91469 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<[email protected]>
+ *
+ * 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<[email protected]>
+ *
+ * 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<[email protected]>
+ *
+ * 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 <[email protected]> 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<[email protected]>
+ *
+ * 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

2010-11-15 17:29:53

by Rymarkiewicz Waldemar

[permalink] [raw]
Subject: RE: [PATCH 1/4] Sim Access Profile API

Hi,=20

>Hi,

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

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

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

Methods void Disconnect()

Disconnects SAP client from the server.

Possible errors: org.bluez.Error.Failed

void SetProperty(string name, variant value)

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

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

dict GetProperties()

Return all properties for the interface. See the
properties section for available properties.

Possible Errors: org.bluez.Error.Failed

Signals PropertyChanged(string name, variant value)

This signal indicates a changed value of the given
property.

Properties boolean Enabled [readwrite]

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

boolean Connected [readonly]

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


More comments ?

Thanks,
/Waldek

2010-11-10 21:46:27

by Luiz Augusto von Dentz

[permalink] [raw]
Subject: Re: [PATCH 1/4] Sim Access Profile API

Hi,

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

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

--=20
Luiz Augusto von Dentz
Computer Engineer

2010-11-10 16:07:57

by Gustavo Padovan

[permalink] [raw]
Subject: Re: [PATCH 1/4] Sim Access Profile API

Hi Waldemar,

* [email protected] <[email protected]> [2010-11-10 13:12:53 +0200]:

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

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

>
> >> +
> >> + void Disconnect(boolean type)
> >> +
> >> + Disconnect SAP client from the server.
> >The 'type'
> >> + parameter indicates disconnection type.
> >> +
> >> + True - gracefull disconnection
> >> + False - immediate disconnection
> >> +
> >> + Possible errors: org.bluez.Error.Failed
> >
> >I don't like this style of method names at all. Using method
> >names like GracefulDisconnect and ImmediateDisconnect would be better.
>
> That's fine.
>
> >However I am not sure we should differentiate here at all. We
> >should always to the graceful disconnect. What will the
> >immediate disconnect bring us?
>
> That's actually intended for testing only. One of PTS test cases expects the tester to trigger immediate disconnect.
> In practce, it is only used when connection to sim card is lost, but this is obviously done internally.


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

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

2010-11-10 11:12:53

by Rymarkiewicz Waldemar

[permalink] [raw]
Subject: RE: [PATCH 1/4] Sim Access Profile API

Hi Marcel,=20

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

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

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

That's fine.

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

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

Thanks,
/Waldek=

2010-11-10 05:33:10

by Marcel Holtmann

[permalink] [raw]
Subject: Re: [PATCH 1/4] Sim Access Profile API

Hi Waldemar,

> New API for Sim Access Profile.
> ---
> Makefile.am | 2 +-
> doc/sap-api.txt | 57 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
> 2 files changed, 58 insertions(+), 1 deletions(-)
> create mode 100644 doc/sap-api.txt
>
> diff --git a/Makefile.am b/Makefile.am
> index 873f2df..e1183de 100644
> --- a/Makefile.am
> +++ b/Makefile.am
> @@ -352,7 +352,7 @@ EXTRA_DIST += doc/manager-api.txt \
> doc/service-api.txt doc/agent-api.txt doc/attribute-api.txt \
> doc/serial-api.txt doc/network-api.txt \
> doc/input-api.txt doc/audio-api.txt doc/control-api.txt \
> - doc/hfp-api.txt doc/assigned-numbers.txt
> + doc/hfp-api.txt doc/assigned-numbers.txt doc/sap-api.txt
>
> AM_YFLAGS = -d
>
> diff --git a/doc/sap-api.txt b/doc/sap-api.txt
> new file mode 100644
> index 0000000..7951f56
> --- /dev/null
> +++ b/doc/sap-api.txt
> @@ -0,0 +1,57 @@
> +BlueZ D-Bus Sim Access Profile API description
> +***********************************
> +
> +Copyright (C) 2010 ST-Ericsson SA
> +
> +
> +Sim Access Profile hierarchy
> +============================
> +
> +Service org.bluez
> +Interface org.bluez.SimAccess
> +Object path [variable prefix]/{hci0,hci1,...}
> +
> +Methods void Enable()
> +
> + Start up SAP server and register SDP record for it.
> +
> + Possible errors: org.bluez.Error.Failed
> +
> + void Disable()
> +
> + Shudown SAP server and remove the SDP record.
> +
> + Possible errors: org.bluez.Error.Failed

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

> +
> + void Disconnect(boolean type)
> +
> + Disconnect SAP client from the server. The 'type'
> + parameter indicates disconnection type.
> +
> + True - gracefull disconnection
> + False - immediate disconnection
> +
> + Possible errors: org.bluez.Error.Failed

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

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

Regards

Marcel



2010-11-05 15:14:43

by Rymarkiewicz Waldemar

[permalink] [raw]
Subject: RE: [PATCH 4/4] Sim Access Profile dummy driver

Hi Johan,

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


Thanks again for comments and see attached patch.

/Waldek


Attachments:
0004-Sim-Access-Profile-dummy-driver.patch (12.04 kB)
0004-Sim-Access-Profile-dummy-driver.patch

2010-11-05 15:12:49

by Rymarkiewicz Waldemar

[permalink] [raw]
Subject: RE: [PATCH 3/4] Sim Access Profile Server


Hi Johan,

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

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

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

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

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


Thanks for comments and have a look on fixed patch.

/Waldek


Attachments:
0003-Sim-Access-Profile-Server.patch (47.68 kB)
0003-Sim-Access-Profile-Server.patch

2010-11-05 13:31:15

by Rymarkiewicz Waldemar

[permalink] [raw]
Subject: RE: [PATCH 2/4] Sim Access Profile Manager

Hi Johan

>
>> +++ b/sap/server.h
>> @@ -0,0 +1,25 @@
>> +/*
>> + * BlueZ - Bluetooth protocol stack for Linux
>> + *
>> + * Copyright (C) 2010 Claudio
>> +Takahasi<[email protected]>
>
>Same here.
>

Thanks for comments. I updated the patch.

Regards,
/Waldek


Attachments:
0002-Sim-Access-Profile-Manager.patch (9.89 kB)
0002-Sim-Access-Profile-Manager.patch

2010-11-05 10:16:00

by Johan Hedberg

[permalink] [raw]
Subject: Re: [PATCH 4/4] Sim Access Profile dummy driver

Hi Waldek,

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

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

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

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

> + if(sim_card_connection_status == SIM_MISSING)

Space before (

> + }else if(sim_card_connection_status != SIM_CONNECTED)

Space after } and before (

> + sap_power_sim_on_rsp(sap_device, SAP_RESULT_ERROR_NOT_ACCESSIBLE);
> + else {
> + sap_power_sim_on_rsp(sap_device, SAP_RESULT_ERROR_NO_REASON);
> + }

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

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

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

> + if(sim_card_connection_status != SIM_CONNECTED)

Space before (

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

Remove the other empty line.

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

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

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

Johan

2010-11-05 10:05:48

by Johan Hedberg

[permalink] [raw]
Subject: Re: [PATCH 3/4] Sim Access Profile Server

Hi Waldek,

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

Space after {

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

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

> +void sap_transfer_card_reader_status_req(void * sap_device)

No space between * and sap_device

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

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

> + * Copyright (C) 2010 Claudio Takahasi<[email protected]>

Same copyright issue as previously discussed.

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

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

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

Same here.

> +/* Status Change - SAP v1.1 section 5.2.8 */
> +typedef enum {
> + SAP_STATUS_CHANGE_UNKNOWN_ERROR = 0x00,
> + SAP_STATUS_CHANGE_CARD_RESET = 0x01,
> + SAP_STATUS_CHANGE_CARD_NOT_ACCESSIBLE = 0x02,
> + SAP_STATUS_CHANGE_CARD_REMOVED = 0x03,
> + SAP_STATUS_CHANGE_CARD_INSERTED = 0x04,
> + SAP_STATUS_CHANGE_CARD_RECOVERED = 0x05
> +} sap_status_change_t;

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

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

Please don't use typedefs with structs.

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

Remove one of the consequtive empty lines.

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

Same here.

> +/*SAP responses to SAP requests. Implemented by server.c */
> +int sap_connect_rsp(void *sap_device, sap_status_t status, uint16_t maxmsgsize);
> +int sap_disconnect_rsp(void *sap_device);
> +int sap_transfer_apdu_rsp(void *sap_device, sap_result_t result, uint8_t *sap_apdu_resp, uint16_t length);
> +int sap_transfer_atr_rsp(void *sap_device, sap_result_t result, uint8_t *sap_atr, uint16_t length);
> +int sap_power_sim_off_rsp(void *sap_device, sap_result_t result);
> +int sap_power_sim_on_rsp(void *sap_device, sap_result_t result);
> +int sap_reset_sim_rsp(void *sap_device, sap_result_t result);
> +int sap_transfer_card_reader_status_rsp(void *sap_device, sap_result_t result, icc_reader_status_t status);
> +int sap_error_rsp(void *sap_device);
> +int sap_transport_protocol_rsp(void *sap_device, sap_result_t result);

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

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

Same copyright issue as before.

> +static void connect_req(void *data, sap_parameter *param);
> +static int disconnect_req(void *data, sap_disconnection_type_t disc_type);
> +static void transfer_apdu_req(void *data, sap_parameter *param);
> +static void transfer_atr_req(void *data);
> +static void power_sim_off_req(void *data);
> +static void power_sim_on_req(void *data);
> +static void reset_sim_req(void *data);
> +static void transfer_card_reader_status_req(void *data);
> +static void set_transport_protocol_req(void *data, sap_parameter *param);
> +static int disconnect_ind(void *sap_device, sap_disconnection_type_t type);

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

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

Use size_t instead of gsize.

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

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

> + switch(processing_req) {

Space before )

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

Same here.

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

And here.

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

Remove one of the empty lines.

> +{
> + if(!server)

Space before (

> + switch(server->state) {

Same here.

> + if(!server || !buf)

And here.

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

And here.

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

Empty line after }

> + if(!server || !param)

Space before (

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

Is this unaligned access safe?

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

Space before and after else

> + if(!server)

Space before (

> + switch(disc_type) {

Same here.

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

No spaces after *

> + if(!server || !param)

Space before (

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

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

> + if(!server)

Space before (

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

Remove one of the empty lines.

> + if(!server)

Space before (

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

Space before (

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

Same here.

> +static void transfer_card_reader_status_req(void * data)

No space before data.

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

Space before (

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

Same here.

> + gchar buf[SAP_BUF_SIZE];

Use char instead of gchar.

> + gsize size = sizeof(sap_message);

Use size_t instead of gsize.

> + if(!server)

Space before (

> +int sap_connect_rsp(void *sap_device, sap_status_t status, uint16_t maxmsgsize)
> +{
> + struct sap_server *server = sap_device;
> + gchar buf[SAP_BUF_SIZE];
> + sap_message *msg = (sap_message *) buf;
> + sap_parameter *param = (sap_parameter *) msg->param;
> + gsize size = sizeof(sap_message);

size_t

> + if(!server)

Space before (

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

{} not needed for one-line scopes.

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

Space before and after 0

> + if(!server)

Space before (

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

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

> + gsize size = sizeof(sap_message);

sizt_t

> + if(!server)

Space before (

> +int sap_transfer_atr_rsp(void *sap_device, sap_result_t result, uint8_t *atr,
> + uint16_t length)
> +{
> + struct sap_server *server = sap_device;
> + gchar buf[SAP_BUF_SIZE]= {0};
> + sap_message *msg = (sap_message *) buf;
> + sap_parameter *param = (sap_parameter *) msg->param;
> + gsize size = sizeof(sap_message);
> +
> + if(!server)
> + return -1;

Same comments as for the previous function.

> +int sap_power_sim_off_rsp(void *sap_device, sap_result_t result)
> +{
> + struct sap_server *server = sap_device;
> + gchar buf[SAP_BUF_SIZE] = {0};
> + sap_message *msg = (sap_message *) buf;
> + gsize size = sizeof(sap_message);
> +
> + if(!server)
> + return -1;

Same here.

> +int sap_power_sim_on_rsp(void *sap_device, sap_result_t result)
> +{
> + struct sap_server *server = sap_device;
> + gchar buf[SAP_BUF_SIZE] = {0};
> + sap_message *msg = (sap_message *) buf;
> + gsize size = sizeof(sap_message);
> +
> + if(!server)
> + return -1;

And here.

> +int sap_reset_sim_rsp(void *sap_device, sap_result_t result)
> +{
> + struct sap_server *server = sap_device;
> + gchar buf[SAP_BUF_SIZE] = {0};
> + sap_message *msg = (sap_message *) buf;
> + gsize size = sizeof(sap_message);
> +
> + if(!server)
> + return -1;

And here.

> +int sap_transfer_card_reader_status_rsp(void *sap_device, sap_result_t result,
> + icc_reader_status_t status)
> +{
> + struct sap_server *server = sap_device;
> + gchar buf[SAP_BUF_SIZE] = {0};
> + sap_message *msg = (sap_message *) buf;
> + sap_parameter *param = (sap_parameter *) msg->param;
> + gsize size = sizeof(sap_message);
> +
> + if(!server)
> + return -1;

And here.

> +int sap_transport_protocol_rsp(void *sap_device, sap_result_t result)
> +{
> + struct sap_server *server = sap_device;
> + gchar buf[SAP_BUF_SIZE] = {0};
> + sap_message *msg = (sap_message *) buf;
> + gsize size = sizeof(sap_message);
> +
> + if(!server)
> + return -1;

And here.

> +int sap_error_rsp(void *sap_device)
> +{
> + sap_message msg;
> +
> + memset(&msg, 0, sizeof(msg));
> + msg.id = SAP_ERROR_RESP;
> +
> + return send_message(sap_device, (gchar *) &msg, sizeof(msg));

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

> +int sap_status_ind(void *sap_device, sap_status_change_t status_change)
> +{
> + struct sap_server *server = sap_device;
> + gchar buf[SAP_BUF_SIZE] = {0};
> + sap_message *msg = (sap_message *) buf;
> + sap_parameter *param = (sap_parameter *) msg->param;
> + gsize size = sizeof(sap_message);
> +
> + if(!server)
> + return -1;

Same comments as for the few other functions above.

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

Space before D

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

char instead of gchar, size_t instead of gsize

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

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

> + switch(msg->id) {

Space befor e(

> + case SAP_CONNECT_REQ:

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

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

char and size_t

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

No {} for one-line scopes.

> + if(!server)

Space before (

> + g_io_add_watch_full(chan, G_PRIORITY_DEFAULT,
> + G_IO_IN | G_IO_ERR | G_IO_HUP| G_IO_NVAL,
> + (GIOFunc) sap_io_cb, server, sap_io_destroy);

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

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

Space before (

> + if (!bt_io_accept(server->io, sap_connect_cb, server, NULL, &gerr)) {
> + error("bt_io_accept: %s", gerr->message);
> + g_error_free(gerr);
> + goto drop;
> + }
> + return;

Empty line before return

> + if(!chan || !server)

Space before (

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

Too long line.

> +}
> +
> +
> +

Three empty lines? :)

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

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

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

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

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

Looks like that one goes over 79 columns.

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

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

> + DBusMessage *reply = NULL;

Unnecessary initialization upon declaration.

> + if(!server)

Space before (

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

Looks like that goes over 79 columns.

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

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

Johan

2010-11-05 09:30:32

by Johan Hedberg

[permalink] [raw]
Subject: Re: [PATCH 2/4] Sim Access Profile Manager

Hi Waldek,

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

As discussed off-list, this needs fixing.

> +++ b/sap/manager.c
> @@ -0,0 +1,94 @@
> +/*
> + * BlueZ - Bluetooth protocol stack for Linux
> + *
> + * Copyright (C) 2010 Claudio Takahasi<[email protected]>

Same here.

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

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

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

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

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

Same here.

> +++ b/sap/manager.h
> @@ -0,0 +1,21 @@
> +/*
> + * BlueZ - Bluetooth protocol stack for Linux
> + *
> + * Copyright (C) 2010 Claudio Takahasi<[email protected]>

Same copyright fix needed as previously discussed.

> +++ b/sap/server.h
> @@ -0,0 +1,25 @@
> +/*
> + * BlueZ - Bluetooth protocol stack for Linux
> + *
> + * Copyright (C) 2010 Claudio Takahasi<[email protected]>

Same here.

Johan