Linux bluetooth development
 help / color / mirror / Atom feed
* [PATCH v3 BlueZ 04/27] alert: Add Phone Alert Status Service
From: Anderson Lizardo @ 2012-10-02 20:24 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Bruna Moreira
In-Reply-To: <1349209490-31830-1-git-send-email-anderson.lizardo@openbossa.org>

From: Bruna Moreira <bruna.moreira@openbossa.org>

Add Phone Alert Status service for PASP.
---
 profiles/alert/server.c |   21 +++++++++++++++++++++
 1 file changed, 21 insertions(+)

diff --git a/profiles/alert/server.c b/profiles/alert/server.c
index dc844d3..b39ef8a 100644
--- a/profiles/alert/server.c
+++ b/profiles/alert/server.c
@@ -27,14 +27,35 @@
 #endif
 
 #include <stdbool.h>
+#include <glib.h>
+#include <bluetooth/uuid.h>
 
+#include "att.h"
 #include "adapter.h"
+#include "gatt-service.h"
+#include "gattrib.h"
+#include "gatt.h"
 #include "server.h"
 #include "profile.h"
 
+#define PHONE_ALERT_STATUS_SVC_UUID		0x180E
+
+static void register_phone_alert_service(struct btd_adapter *adapter)
+{
+	bt_uuid_t uuid;
+
+	bt_uuid16_create(&uuid, PHONE_ALERT_STATUS_SVC_UUID);
+
+	/* Phone Alert Status Service */
+	gatt_service_add(adapter, GATT_PRIM_SVC_UUID, &uuid,
+			GATT_OPT_INVALID);
+}
+
 static int alert_server_probe(struct btd_profile *p,
 						struct btd_adapter *adapter)
 {
+	register_phone_alert_service(adapter);
+
 	return 0;
 }
 
-- 
1.7.9.5


^ permalink raw reply related

* [PATCH v3 BlueZ 03/27] alert: Initial profile registration
From: Anderson Lizardo @ 2012-10-02 20:24 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Anderson Lizardo
In-Reply-To: <1349209490-31830-1-git-send-email-anderson.lizardo@openbossa.org>

---
 profiles/alert/server.c |   24 ++++++++++++++++++++++++
 1 file changed, 24 insertions(+)

diff --git a/profiles/alert/server.c b/profiles/alert/server.c
index d91b156..dc844d3 100644
--- a/profiles/alert/server.c
+++ b/profiles/alert/server.c
@@ -26,13 +26,37 @@
 #include <config.h>
 #endif
 
+#include <stdbool.h>
+
+#include "adapter.h"
 #include "server.h"
+#include "profile.h"
+
+static int alert_server_probe(struct btd_profile *p,
+						struct btd_adapter *adapter)
+{
+	return 0;
+}
+
+static void alert_server_remove(struct btd_profile *p,
+						struct btd_adapter *adapter)
+{
+}
+
+static struct btd_profile alert_profile = {
+	.name = "gatt-alert-server",
+	.adapter_probe = alert_server_probe,
+	.adapter_remove = alert_server_remove,
+};
 
 int alert_server_init(void)
 {
+	btd_profile_register(&alert_profile);
+
 	return 0;
 }
 
 void alert_server_exit(void)
 {
+	btd_profile_unregister(&alert_profile);
 }
-- 
1.7.9.5


^ permalink raw reply related

* [PATCH v3 BlueZ 02/27] alert: Introduce manager abstraction layer
From: Anderson Lizardo @ 2012-10-02 20:24 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Anderson Lizardo
In-Reply-To: <1349209490-31830-1-git-send-email-anderson.lizardo@openbossa.org>

This abstraction layer makes the GATT Phone Alert Status and Alert
Notification implementation consistent with other GATT profiles.
---
 Makefile.am              |    3 ++-
 profiles/alert/main.c    |    6 +++---
 profiles/alert/manager.c |   40 ++++++++++++++++++++++++++++++++++++++++
 profiles/alert/manager.h |   26 ++++++++++++++++++++++++++
 4 files changed, 71 insertions(+), 4 deletions(-)
 create mode 100644 profiles/alert/manager.c
 create mode 100644 profiles/alert/manager.h

diff --git a/Makefile.am b/Makefile.am
index 470dbad..daa78d5 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -219,7 +219,8 @@ builtin_sources += profiles/thermometer/main.c \
 			profiles/thermometer/thermometer.h \
 			profiles/thermometer/thermometer.c \
 			profiles/alert/main.c profiles/alert/server.h \
-			profiles/alert/server.c \
+			profiles/alert/server.c profiles/alert/manager.h \
+			profiles/alert/manager.c \
 			profiles/time/main.c profiles/time/server.h \
 			profiles/time/server.c profiles/time/manager.c \
 			profiles/time/manager.h \
diff --git a/profiles/alert/main.c b/profiles/alert/main.c
index ec4ab6d..5e6910a 100644
--- a/profiles/alert/main.c
+++ b/profiles/alert/main.c
@@ -33,7 +33,7 @@
 #include "plugin.h"
 #include "hcid.h"
 #include "log.h"
-#include "server.h"
+#include "manager.h"
 
 static int alert_init(void)
 {
@@ -42,7 +42,7 @@ static int alert_init(void)
 		return -ENOTSUP;
 	}
 
-	return alert_server_init();
+	return alert_manager_init();
 }
 
 static void alert_exit(void)
@@ -50,7 +50,7 @@ static void alert_exit(void)
 	if (!main_opts.gatt_enabled)
 		return;
 
-	alert_server_exit();
+	alert_manager_exit();
 }
 
 BLUETOOTH_PLUGIN_DEFINE(alert, VERSION,
diff --git a/profiles/alert/manager.c b/profiles/alert/manager.c
new file mode 100644
index 0000000..eb2d627
--- /dev/null
+++ b/profiles/alert/manager.c
@@ -0,0 +1,40 @@
+/*
+ *
+ *  BlueZ - Bluetooth protocol stack for Linux
+ *
+ *  Copyright (C) 2012  Nokia Corporation
+ *  Copyright (C) 2012  Marcel Holtmann <marcel@holtmann.org>
+ *
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "manager.h"
+#include "server.h"
+
+int alert_manager_init(void)
+{
+	return alert_server_init();
+}
+
+void alert_manager_exit(void)
+{
+	alert_server_exit();
+}
diff --git a/profiles/alert/manager.h b/profiles/alert/manager.h
new file mode 100644
index 0000000..e4c6bd0
--- /dev/null
+++ b/profiles/alert/manager.h
@@ -0,0 +1,26 @@
+/*
+ *
+ *  BlueZ - Bluetooth protocol stack for Linux
+ *
+ *  Copyright (C) 2012  Nokia Corporation
+ *  Copyright (C) 2012  Marcel Holtmann <marcel@holtmann.org>
+ *
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+
+int alert_manager_init(void);
+void alert_manager_exit(void);
-- 
1.7.9.5


^ permalink raw reply related

* [PATCH v3 BlueZ 01/27] doc: Introduce Alert API
From: Anderson Lizardo @ 2012-10-02 20:24 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Anderson Lizardo
In-Reply-To: <1349209490-31830-1-git-send-email-anderson.lizardo@openbossa.org>

This API will be implemented and initially used by Phone Alert Status
and Alert Notification GATT profiles (server role).
---
 Makefile.am       |    2 +-
 doc/alert-api.txt |  109 +++++++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 110 insertions(+), 1 deletion(-)
 create mode 100644 doc/alert-api.txt

diff --git a/Makefile.am b/Makefile.am
index c27eb01..470dbad 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -396,7 +396,7 @@ EXTRA_DIST += doc/manager-api.txt \
 		doc/network-api.txt doc/input-api.txt doc/audio-api.txt \
 		doc/control-api.txt doc/hfp-api.txt doc/health-api.txt \
 		doc/sap-api.txt doc/media-api.txt doc/assigned-numbers.txt \
-		doc/supported-features.txt
+		doc/supported-features.txt doc/alert-api.txt
 
 AM_YFLAGS = -d
 
diff --git a/doc/alert-api.txt b/doc/alert-api.txt
new file mode 100644
index 0000000..e58430c
--- /dev/null
+++ b/doc/alert-api.txt
@@ -0,0 +1,109 @@
+BlueZ D-Bus Alert API description
+*********************************
+
+Copyright (C) 2012  Instituto Nokia de Tecnologia - INdT
+
+Introduction
+------------
+
+Currently, there are two different GATT server profiles that depend on
+receiving alerts or notifications from the platform: Phone Alert Status (PASP)
+and Alert Notification (ANP). PASP is very specific to mobile phones, and also
+allows limited control to alerts (i.e. mute once or switch to a silent mode).
+
+This document presents a unified API that allows to register and notify alerts,
+and to control some alerts (using the provided agent object).
+
+
+Alert hierarchy
+===============
+
+Service		org.bluez
+Interface	org.bluez.Alert
+Object path	/org/bluez
+
+Methods		void RegisterAlert(string category, object agent)
+
+			Register a new alert category and an agent for it. This
+			means the application will be responsible for notifying
+			BlueZ of any alerts of that category, using the
+			NewAlert() method.
+
+			Supported ANP categories: simple, email, news, call,
+				missed_call, sms_mms, voice_mail, schedule,
+				high_priority, instant_message
+			Supported PASP categories: ringer, vibrate, display
+
+			Possible Errors: org.bluez.Error.InvalidArguments
+
+		void NewAlert(string category, uint16 count, string description)
+
+			Notify BlueZ of new alert(s) for the given category. The
+			description is relative to the last received alert and
+			can be sender name, caller ID, title, or other
+			information specific to the category.
+
+			For ringer, vibrate and display categories, valid
+			descriptions are "active" and "not active". Alerts from
+			ringer category also accept "enabled" and "disabled",
+			depending on whether ringer is in silent mode or not.
+
+			Description must not exceed 18 bytes when encoded in
+			UTF-8 format, otherwise an error is returned. If there
+			is no description, an empty string should be used.
+
+			The count argument contains the number of alerts not
+			yet acknowledged by the user on the UI. To save D-Bus
+			traffic, events that may generate multiple alerts at
+			the same time (like email, sms, news) should trigger a
+			single NewAlert().
+
+			If there are more than 254 new alerts, count must be
+			set to 255. PASP alerts should always set count to 1.
+
+			Possible Errors: org.bluez.Error.InvalidArguments
+
+		void UnreadAlert(string category, uint16 count)
+
+			Some services (like SMS and e-mail) keep track of
+			number of unread items. This method allows to update
+			this counter, so peer devices can be notified using
+			Alert Notification Profile.
+
+			If there are more than 254 unread alerts, count must be
+			set to 255.
+
+			Possible Errors: org.bluez.Error.InvalidArguments
+
+Alert Agent hierarchy
+=====================
+
+Service		org.bluez
+Interface	org.bluez.AlertAgent
+Object path	freely definable
+
+Methods		void MuteOnce()
+
+			This method is only called if "ringer" alert category
+			is specified when registering the agent.
+
+			Mute the ringer once (e.g. during a incoming call). If
+			ringer is not active, does nothing.
+
+		void SetRinger(string mode)
+
+			This method is only called if "ringer" alert category
+			is specified when registering the agent.
+
+			Set ringer to the specified mode. If mode is "enabled",
+			ringer is set to the default mode, as defined by the
+			current active profile. If mode is "disabled", ringer
+			will not activate on incoming calls, until it is set
+			back to "enabled" mode.
+
+			Possible Errors: org.bluez.Error.InvalidArguments
+
+		void Release()
+
+			Release this agent. At this point, it will not be used
+			by BlueZ anymore and can be destroyed by the owner.
-- 
1.7.9.5


^ permalink raw reply related

* [PATCH v3 BlueZ 00/27] Add support for PASP and ANP server profiles
From: Anderson Lizardo @ 2012-10-02 20:24 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Anderson Lizardo
In-Reply-To: <1348770996-12236-1-git-send-email-anderson.lizardo@openbossa.org>

Hi,

This series implement most of mandatory features for Phone Alert Status (PASP)
and Alert Notification (ANP) profiles. The only major mandatory feature
currently missing is support for ANP control point (which will be added on a
future series).

Note: for those planning to use ANP/PASP in BlueZ using these patches, it is
necessary to implement an "agent" that forwards platform events (SMS, calls,
e-mail, and ringer/display/vibra status) to BlueZ. See doc/alert-api.txt and
test/test-alert for more details. Alternatively, the components that generate
these events can register themselves and report alerts directly to BlueZ.

This implementation was tested against PTS and all tests passed (except for the
features not yet implemented). The D-Bus API was implemented accordingly to the
previously proposed Alert API (documented on the first patch).

Comments/suggestions are welcome.

Changes since v2:

* Rebase and fix a minor conflict in Makefile.tools
* Fix issues detected by checkpatch.pl

Changes since v1:

* Rebase against latest btd_profile changes
* Add test-alert to Makefile.tools and alert-api.txt to Makefile.am
* Add org.bluez.AlertAgent to D-Bus policy file (patch 27/27)
* Implement Release() agent method (patch 26/27)
* Remove Suspend()/Resume() from documentation (they are not implemented, and
  they are optimizations that can be added later if necessary).

Anderson Lizardo (13):
  doc: Introduce Alert API
  alert: Introduce manager abstraction layer
  alert: Initial profile registration
  alert: Initial Alert Notification
  alert: Add initial support for UnreadAlert D-Bus method
  alert: Add per adapter attribute handle information
  alert: Update Supported New/Unread Category characteristic values
  alert: Update new alert characteristic value
  alert: Update unread alert characteristic value
  alert: Implement MuteOnce command
  alert: Update Alert Status and Ringer Setting characteristic values
  alert: Implement Release() agent method
  alert: Add org.bluez.AlertAgent to D-Bus policy file

Bruna Moreira (4):
  alert: Add Phone Alert Status Service
  alert: Add Ringer Control Point characteristic
  alert: Add Ringer Setting characteristic
  alert: Add Alert Status characteristic

Eder Ruiz Maria (10):
  alert: Implement category registration in RegisterAlert()
  alert: Add initial support for NewAlert D-Bus method
  alert: Automatically unregister alert when agent leaves D-Bus
  alert: Add support for calling MuteOnce()
  alert: Add support for calling SetRinger()
  alert: Add test-alert script
  alert: Add support for ringer setting notification
  alert: Add support for alert status notification
  alert: Add support for new alert notification
  alert: Add support for unread alert notification

 Makefile.am              |    5 +-
 Makefile.tools           |    2 +-
 doc/alert-api.txt        |  109 ++++++
 profiles/alert/main.c    |    6 +-
 profiles/alert/manager.c |   40 ++
 profiles/alert/manager.h |   26 ++
 profiles/alert/server.c  |  961 ++++++++++++++++++++++++++++++++++++++++++++++
 src/bluetooth.conf       |    1 +
 test/test-alert          |  180 +++++++++
 9 files changed, 1324 insertions(+), 6 deletions(-)
 create mode 100644 doc/alert-api.txt
 create mode 100644 profiles/alert/manager.c
 create mode 100644 profiles/alert/manager.h
 create mode 100755 test/test-alert

-- 
1.7.9.5


^ permalink raw reply

* Re: L2CAP Flush_Timeout  Error
From: Ajay @ 2012-10-02 20:21 UTC (permalink / raw)
  To: linux-bluetooth
In-Reply-To: <506B4479.3050105@globaledgesoft.com>



> On Tue, Oct 02, 2012 at 11:48:56PM +0530, Ajay wrote:
>> Hi,
>>      Im currently working in an A2DP stuff, where i noticed an error.
>> Here i wanted to monitor the flushed packets due to timeout.
>>
>>   I used the  l2test code for my testing purpose
>>
>>                On client side   "l2test  -R  -S <bdadddr> "
>>                and i set the flush timeout as 100 (opts.flush_to = 100)
>>
>>         But  later  when i print the getsockopt value of flush_to, it
>> was showing some default value (65532)  harcoded at kernel side.
>
> Try the patch in this thread.
>
> Best regards
> Andrei Emeltchenko
>

    Thanks for your patch , its working fine. Now even  if i set the
flush_timeout = 5 , i couldnt  able to see any packets missing at the
receiver side . Here in the sender  side  im giving proper sequence
number, and these same sequence is getting at the receiver side . i
doubted even though its flushing , controller is doing some
retransmission job...please help . My kernel is 2.6.39 , and im using
BASIC MODE of transmission. so shall i change it to STEAMING MODE ????

-- 
  Thanks & regards

AJAY KV
8892753703



^ permalink raw reply

* Re: L2CAP Flush_Timeout  Error
From: Ajay @ 2012-10-02 19:46 UTC (permalink / raw)
  To: Andrei Emeltchenko, linux-bluetooth
In-Reply-To: <20121008091144.GF2456@aemeltch-MOBL1>

On Monday 08 October 2012 02:41 PM, Andrei Emeltchenko wrote:
> On Tue, Oct 02, 2012 at 11:48:56PM +0530, Ajay wrote:
>> Hi,
>>      Im currently working in an A2DP stuff, where i noticed an error.
>> Here i wanted to monitor the flushed packets due to timeout.
>>
>>   I used the  l2test code for my testing purpose
>>
>>                On client side   "l2test  -R  -S <bdadddr> "
>>                and i set the flush timeout as 100 (opts.flush_to = 100)
>>
>>         But  later  when i print the getsockopt value of flush_to, it
>> was showing some default value (65532)  harcoded at kernel side.
>
> Try the patch in this thread.
>
> Best regards
> Andrei Emeltchenko
>

    Thanks for your patch , its working fine. Now even  if i set the 
flush_timeout = 5 , i couldnt  able to see any packets missing at the 
receiver side . Here in the sender  side  im giving proper sequence 
number, and these same sequence is getting at the receiver side . i 
doubted even though its flushing , controller is doing some 
retransmission job...please help . My kernel is 2.6.39 , and im using 
BASIC MODE of transmission. so shall i change it to STEAMING MODE ????

-- 
  Thanks & regards

AJAY KV
8892753703

^ permalink raw reply

* Re: [PATCH v0] audio: Fix missing gateway state check on Connect
From: Johan Hedberg @ 2012-10-02 18:52 UTC (permalink / raw)
  To: Mikel Astiz; +Cc: linux-bluetooth, Mikel Astiz
In-Reply-To: <1349200000-2696-1-git-send-email-mikel.astiz.oss@gmail.com>

Hi Mikel,

On Tue, Oct 02, 2012, Mikel Astiz wrote:
> If the gateway is already connected (or connecting) when Connect() is
> called, an error should be returned, exactly as other interfaces do.
> ---
>  audio/gateway.c | 5 +++++
>  1 file changed, 5 insertions(+)

Applied. Thanks.

Johan

^ permalink raw reply

* L2CAP Flush_Timeout  Error
From: Ajay @ 2012-10-02 18:18 UTC (permalink / raw)
  To: linux-bluetooth

Hi,
     Im currently working in an A2DP stuff, where i noticed an error. 
Here i wanted to monitor the flushed packets due to timeout.

  I used the  l2test code for my testing purpose

               On client side   "l2test  -R  -S <bdadddr> "
               and i set the flush timeout as 100 (opts.flush_to = 100)

        But  later  when i print the getsockopt value of flush_to, it 
was showing some default value (65532)  harcoded at kernel side.

     so  how can i flush some packets in the sender side,  without 
enabling any retransmission  and  able to monitor the sequence number in 
the receiver side.


   --
  Thanks & regards

AJAY KV
8892753703


^ permalink raw reply

* [PATCH v0] audio: Fix missing gateway state check on Connect
From: Mikel Astiz @ 2012-10-02 17:46 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Mikel Astiz

From: Mikel Astiz <mikel.astiz@bmw-carit.de>

If the gateway is already connected (or connecting) when Connect() is
called, an error should be returned, exactly as other interfaces do.
---
 audio/gateway.c | 5 +++++
 1 file changed, 5 insertions(+)

diff --git a/audio/gateway.c b/audio/gateway.c
index a9a576e..b4d96f0 100644
--- a/audio/gateway.c
+++ b/audio/gateway.c
@@ -572,6 +572,11 @@ static DBusMessage *ag_connect(DBusConnection *conn, DBusMessage *msg,
 	struct gateway *gw = au_dev->gateway;
 	int err;
 
+	if (gw->state == GATEWAY_STATE_CONNECTING)
+		return btd_error_in_progress(msg);
+	else if (gw->state > GATEWAY_STATE_CONNECTING)
+		return btd_error_already_connected(msg);
+
 	if (!gw->agent)
 		return btd_error_agent_not_available(msg);
 
-- 
1.7.11.4


^ permalink raw reply related

* [PATCH BlueZ v9 8/8] core: Suspend scanning before connect on pairing
From: João Paulo Rechi Vita @ 2012-10-02 17:22 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: João Paulo Rechi Vita
In-Reply-To: <1349198578-2818-1-git-send-email-jprvita@openbossa.org>

If there is a disconnected bonded device there will be a scanning
procedure active due to the General Connection Establishment Procedure.
This scan have to be suspended before trying to connect to the remote
device for pairing.
---
 src/device.c | 137 +++++++++++++++++++++++++++++++----------------------------
 1 file changed, 72 insertions(+), 65 deletions(-)

diff --git a/src/device.c b/src/device.c
index 89ab24a..bbde12f 100644
--- a/src/device.c
+++ b/src/device.c
@@ -2014,6 +2014,36 @@ done:
 	browse_request_free(req);
 }
 
+static void bonding_request_free(struct bonding_req *bonding)
+{
+	struct btd_device *device;
+
+	if (!bonding)
+		return;
+
+	if (bonding->listener_id)
+		g_dbus_remove_watch(btd_get_dbus_connection(),
+							bonding->listener_id);
+
+	if (bonding->msg)
+		dbus_message_unref(bonding->msg);
+
+	device = bonding->device;
+	g_free(bonding);
+
+	if (!device)
+		return;
+
+	device->bonding = NULL;
+
+	if (!device->agent)
+		return;
+
+	agent_cancel(device->agent);
+	agent_free(device->agent);
+	device->agent = NULL;
+}
+
 static void att_connect_cb(GIOChannel *io, GError *gerr, gpointer user_data)
 {
 	struct att_callbacks *attcb = user_data;
@@ -2043,6 +2073,21 @@ static void att_connect_cb(GIOChannel *io, GError *gerr, gpointer user_data)
 
 	if (attcb->success)
 		attcb->success(user_data);
+
+	if (device->bonding) {
+		/* this is a LE device during pairing */
+		int err = adapter_create_bonding(device->adapter,
+				&device->bdaddr, device->bdaddr_type,
+				agent_get_io_capability(device->agent));
+		if (err < 0) {
+			DBusMessage *reply = btd_error_failed(
+					device->bonding->msg, strerror(-err));
+			g_dbus_send_message(btd_get_dbus_connection(), reply);
+			bonding_request_cancel(device->bonding);
+			bonding_request_free(device->bonding);
+		}
+	}
+
 done:
 	g_free(attcb);
 }
@@ -2101,6 +2146,23 @@ GIOChannel *device_att_connect(gpointer user_data)
 					BT_IO_OPT_PSM, ATT_PSM,
 					BT_IO_OPT_SEC_LEVEL, BT_IO_SEC_MEDIUM,
 					BT_IO_OPT_INVALID);
+	} else if (device->bonding) {
+		/* this is a LE device during pairing, using low sec level */
+		io = bt_io_connect(att_connect_cb,
+				attcb, NULL, &gerr,
+				BT_IO_OPT_SOURCE_BDADDR, &sba,
+				BT_IO_OPT_DEST_BDADDR, &device->bdaddr,
+				BT_IO_OPT_DEST_TYPE, device->bdaddr_type,
+				BT_IO_OPT_CID, ATT_CID,
+				BT_IO_OPT_SEC_LEVEL, BT_IO_SEC_LOW,
+				BT_IO_OPT_INVALID);
+		if (io == NULL) {
+			DBusMessage *reply = btd_error_failed(
+					device->bonding->msg, gerr->message);
+			g_dbus_send_message(btd_get_dbus_connection(), reply);
+			bonding_request_cancel(device->bonding);
+			bonding_request_free(device->bonding);
+		}
 	} else {
 		io = bt_io_connect(att_connect_cb,
 				attcb, NULL, &gerr,
@@ -2423,36 +2485,6 @@ static DBusMessage *new_authentication_return(DBusMessage *msg, uint8_t status)
 	}
 }
 
-static void bonding_request_free(struct bonding_req *bonding)
-{
-	struct btd_device *device;
-
-	if (!bonding)
-		return;
-
-	if (bonding->listener_id)
-		g_dbus_remove_watch(btd_get_dbus_connection(),
-							bonding->listener_id);
-
-	if (bonding->msg)
-		dbus_message_unref(bonding->msg);
-
-	device = bonding->device;
-	g_free(bonding);
-
-	if (!device)
-		return;
-
-	device->bonding = NULL;
-
-	if (!device->agent)
-		return;
-
-	agent_cancel(device->agent);
-	agent_free(device->agent);
-	device->agent = NULL;
-}
-
 void device_set_paired(struct btd_device *device, gboolean value)
 {
 	if (device->paired == value)
@@ -2542,41 +2574,6 @@ DBusMessage *device_create_bonding(struct btd_device *device,
 	if (device_is_bonded(device))
 		return btd_error_already_exists(msg);
 
-	if (device_is_le(device)) {
-		struct att_callbacks *attcb;
-		GError *gerr = NULL;
-		bdaddr_t sba;
-
-		adapter_get_address(adapter, &sba);
-
-		attcb = g_new0(struct att_callbacks, 1);
-		attcb->user_data = device;
-
-		device->att_io = bt_io_connect(att_connect_cb,
-				attcb, NULL, &gerr,
-				BT_IO_OPT_SOURCE_BDADDR, &sba,
-				BT_IO_OPT_DEST_BDADDR, &device->bdaddr,
-				BT_IO_OPT_DEST_TYPE, device->bdaddr_type,
-				BT_IO_OPT_CID, ATT_CID,
-				BT_IO_OPT_SEC_LEVEL, BT_IO_SEC_LOW,
-				BT_IO_OPT_INVALID);
-
-		if (device->att_io == NULL) {
-			DBusMessage *reply = btd_error_failed(msg,
-								gerr->message);
-
-			error("Bonding bt_io_connect(): %s", gerr->message);
-			g_error_free(gerr);
-			g_free(attcb);
-			return reply;
-		}
-	}
-
-	err = adapter_create_bonding(adapter, &device->bdaddr,
-					device->bdaddr_type, capability);
-	if (err < 0)
-		return btd_error_failed(msg, strerror(-err));
-
 	bonding = bonding_request_new(msg, device, agent_path,
 					capability);
 
@@ -2589,6 +2586,16 @@ DBusMessage *device_create_bonding(struct btd_device *device,
 	device->bonding = bonding;
 	bonding->device = device;
 
+	if (device_is_le(device)) {
+		adapter_connect_list_add(adapter, device);
+		return NULL;
+	}
+
+	err = adapter_create_bonding(adapter, &device->bdaddr,
+					device->bdaddr_type, capability);
+	if (err < 0)
+		return btd_error_failed(msg, strerror(-err));
+
 	return NULL;
 }
 
-- 
1.7.11.4


^ permalink raw reply related

* [PATCH BlueZ v9 7/8] mgmt: Add address type to bonding debug message
From: João Paulo Rechi Vita @ 2012-10-02 17:22 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: João Paulo Rechi Vita
In-Reply-To: <1349198578-2818-1-git-send-email-jprvita@openbossa.org>

---
 src/mgmt.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/src/mgmt.c b/src/mgmt.c
index fc0e5e4..4354dc4 100644
--- a/src/mgmt.c
+++ b/src/mgmt.c
@@ -2383,7 +2383,8 @@ int mgmt_create_bonding(int index, bdaddr_t *bdaddr, uint8_t addr_type, uint8_t
 	char addr[18];
 
 	ba2str(bdaddr, addr);
-	DBG("hci%d bdaddr %s io_cap 0x%02x", index, addr, io_cap);
+	DBG("hci%d bdaddr %s type %d io_cap 0x%02x",
+					index, addr, addr_type, io_cap);
 
 	memset(buf, 0, sizeof(buf));
 	hdr->opcode = htobs(MGMT_OP_PAIR_DEVICE);
-- 
1.7.11.4


^ permalink raw reply related

* [PATCH BlueZ v9 6/8] core: Re-connect for ECONNRESET or ECONNABORTED
From: João Paulo Rechi Vita @ 2012-10-02 17:22 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Claudio Takahasi
In-Reply-To: <1349198578-2818-1-git-send-email-jprvita@openbossa.org>

From: Claudio Takahasi <claudio.takahasi@openbossa.org>

This patch keeps scanning and re-connections active if the disconnection
reason is ECONNRESET(Remote Initiated Disconnection).

Re-connection is a behaviour determined by Profiles or by the upper
layer(user actions). For instance, HoG requires re-connection always
active, no matter if the previous disconnection reason was page timeout
or remote initiated disconnection (ECONNRESET). Some devices disconnects
after some idle time, connectable advertises are sent by the peripheral
when commanded by the user(eg: key pressed). Disconnection can be also
triggered by the local host (ECONNABORTED) using command line tools or
Disconnect method in the Device interface.

The peripheral dictates the re-connection controlling the connectable
advertises, BlueZ(central) needs to keep the scanning always active to
able to detect the advertises and trigger the connection.
---
 src/device.c | 12 ++++++++++--
 1 file changed, 10 insertions(+), 2 deletions(-)

diff --git a/src/device.c b/src/device.c
index d28adeb..89ab24a 100644
--- a/src/device.c
+++ b/src/device.c
@@ -1944,10 +1944,18 @@ static gboolean attrib_disconnected_cb(GIOChannel *io, GIOCondition cond,
 
 	g_slist_foreach(device->attios, attio_disconnected, NULL);
 
-	if (device->auto_connect == FALSE || err != ETIMEDOUT)
+	if (device->auto_connect == FALSE) {
+		DBG("Automatic connection disabled");
 		goto done;
+	}
 
-	adapter_connect_list_add(device_get_adapter(device), device);
+	/*
+	 * Keep scanning/re-connection active if disconnection reason
+	 * is connection timeout, remote user terminated connection or local
+	 * initiated disconnection.
+	 */
+	if (err == ETIMEDOUT || err == ECONNRESET || err == ECONNABORTED)
+		adapter_connect_list_add(device_get_adapter(device), device);
 
 done:
 	attio_cleanup(device);
-- 
1.7.11.4


^ permalink raw reply related

* [PATCH BlueZ v9 5/8] core: Disable unnecessary auto connections
From: João Paulo Rechi Vita @ 2012-10-02 17:22 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Paulo Alcantara
In-Reply-To: <1349198578-2818-1-git-send-email-jprvita@openbossa.org>

From: Paulo Alcantara <paulo.alcantara@openbossa.org>

BlueZ host disconnects the link when encryption fails. ECONNABORTED
error is returned by the kernel when the connection is terminated by the
local host. This scenario commonly happens when authentication fails due
PIN or Key Missing.
---
 src/device.c | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/src/device.c b/src/device.c
index 7221f93..d28adeb 100644
--- a/src/device.c
+++ b/src/device.c
@@ -2044,6 +2044,9 @@ static void att_error_cb(const GError *gerr, gpointer user_data)
 	struct att_callbacks *attcb = user_data;
 	struct btd_device *device = attcb->user_data;
 
+	if (g_error_matches(gerr, BT_IO_ERROR, ECONNABORTED))
+		return;
+
 	if (device->auto_connect == FALSE)
 		return;
 
-- 
1.7.11.4


^ permalink raw reply related

* [PATCH BlueZ v9 4/8] core: Start LE scanning when a device requests
From: João Paulo Rechi Vita @ 2012-10-02 17:22 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Claudio Takahasi
In-Reply-To: <1349198578-2818-1-git-send-email-jprvita@openbossa.org>

From: Claudio Takahasi <claudio.takahasi@openbossa.org>

This patch enables the LE scanning when a device requires connection and
there isn't discovery sessions, triggering the General Connection
Establishment Procedure.
---
 src/adapter.c | 70 ++++++++++++++++++++++++++++++++++++++++++++---------------
 1 file changed, 53 insertions(+), 17 deletions(-)

diff --git a/src/adapter.c b/src/adapter.c
index d7f8c14..07b915e 100644
--- a/src/adapter.c
+++ b/src/adapter.c
@@ -133,6 +133,7 @@ struct btd_adapter {
 	GSList *devices;		/* Devices structure pointers */
 	GSList *mode_sessions;		/* Request Mode sessions */
 	GSList *disc_sessions;		/* Discovery sessions */
+	struct session_req *scanning_session;
 	GSList *connect_list;		/* Devices to connect when found */
 	guint discov_id;		/* Discovery timer */
 	gboolean discovering;		/* Discovery active */
@@ -224,17 +225,22 @@ static struct session_req *create_session(struct btd_adapter *adapter,
 					DBusMessage *msg, uint8_t mode,
 					GDBusWatchFunction cb)
 {
-	const char *sender = dbus_message_get_sender(msg);
+	const char *sender;
 	struct session_req *req;
 
 	req = g_new0(struct session_req, 1);
 	req->adapter = adapter;
-	req->msg = dbus_message_ref(msg);
 	req->mode = mode;
 
-	if (cb == NULL)
+	if (msg == NULL)
+		return session_ref(req);
+
+	req->msg = dbus_message_ref(msg);
+
+	if(cb == NULL)
 		return session_ref(req);
 
+	sender = dbus_message_get_sender(msg);
 	req->owner = g_strdup(sender);
 	req->id = g_dbus_add_disconnect_watch(btd_get_dbus_connection(),
 							sender, cb, req, NULL);
@@ -445,7 +451,9 @@ static struct session_req *find_session(GSList *list, const char *sender)
 	for (; list; list = list->next) {
 		struct session_req *req = list->data;
 
-		if (g_str_equal(req->owner, sender))
+		/* req->owner may be NULL if the session has been added by the
+		 * daemon itself, so we use g_strcmp0 instead of g_str_equal */
+		if (g_strcmp0(req->owner, sender) == 0)
 			return req;
 	}
 
@@ -520,7 +528,7 @@ static void session_remove(struct session_req *req)
 	struct btd_adapter *adapter = req->adapter;
 
 	/* Ignore set_mode session */
-	if (req->owner == NULL)
+	if (req->owner == NULL && adapter->pending_mode)
 		return;
 
 	DBG("%s session %p with %s deactivated",
@@ -1028,7 +1036,12 @@ static gboolean discovery_cb(gpointer user_data)
 	struct btd_adapter *adapter = user_data;
 
 	adapter->discov_id = 0;
-	mgmt_start_discovery(adapter->dev_id);
+
+	if (adapter->scanning_session &&
+			(g_slist_length(adapter->disc_sessions) == 1))
+		mgmt_start_le_scanning(adapter->dev_id);
+	else
+		mgmt_start_discovery(adapter->dev_id);
 
 	return FALSE;
 }
@@ -2249,6 +2262,8 @@ const char *btd_adapter_get_name(struct btd_adapter *adapter)
 void adapter_connect_list_add(struct btd_adapter *adapter,
 					struct btd_device *device)
 {
+	struct session_req *req;
+
 	if (g_slist_find(adapter->connect_list, device)) {
 		DBG("ignoring already added device %s",
 						device_get_path(device));
@@ -2259,6 +2274,22 @@ void adapter_connect_list_add(struct btd_adapter *adapter,
 						btd_device_ref(device));
 	DBG("%s added to %s's connect_list", device_get_path(device),
 								adapter->name);
+
+	if (!adapter->up)
+		return;
+
+	if (adapter->off_requested)
+		return;
+
+	if (adapter->scanning_session)
+		return;
+
+	if (adapter->disc_sessions == NULL)
+		adapter->discov_id = g_idle_add(discovery_cb, adapter);
+
+	req = create_session(adapter, NULL, 0, NULL);
+	adapter->disc_sessions = g_slist_append(adapter->disc_sessions, req);
+	adapter->scanning_session = req;
 }
 
 void adapter_connect_list_remove(struct btd_adapter *adapter,
@@ -2278,6 +2309,7 @@ void adapter_connect_list_remove(struct btd_adapter *adapter,
 
 void btd_adapter_start(struct btd_adapter *adapter)
 {
+	struct session_req *req;
 	char address[18];
 	gboolean powered;
 
@@ -2304,8 +2336,15 @@ void btd_adapter_start(struct btd_adapter *adapter)
 
 	info("Adapter %s has been enabled", adapter->path);
 
-	if (g_slist_length(adapter->connect_list) > 0)
-		mgmt_start_le_scanning(adapter->dev_id);
+	if (g_slist_length(adapter->connect_list) == 0 ||
+					adapter->disc_sessions != NULL)
+		return;
+
+	req = create_session(adapter, NULL, 0, NULL);
+	adapter->disc_sessions = g_slist_append(adapter->disc_sessions, req);
+	adapter->scanning_session = req;
+
+	adapter->discov_id = g_idle_add(discovery_cb, adapter);
 }
 
 static void reply_pending_requests(struct btd_adapter *adapter)
@@ -2652,6 +2691,11 @@ void adapter_set_discovering(struct btd_adapter *adapter,
 
 	connect_list_len = g_slist_length(adapter->connect_list);
 
+	if (connect_list_len == 0 && adapter->scanning_session) {
+		session_unref(adapter->scanning_session);
+		adapter->scanning_session = NULL;
+	}
+
 	if (adapter_has_discov_sessions(adapter)) {
 		adapter->discov_id = g_idle_add(discovery_cb, adapter);
 
@@ -2660,14 +2704,6 @@ void adapter_set_discovering(struct btd_adapter *adapter,
 				g_slist_length(adapter->disc_sessions));
 		return;
 	}
-
-	if (connect_list_len > 0) {
-		mgmt_start_le_scanning(adapter->dev_id);
-
-		DBG("hci%u restarting scanning connect_list_len %u",
-				adapter->dev_id, connect_list_len);
-		return;
-	}
 }
 
 static void suspend_discovery(struct btd_adapter *adapter)
@@ -2982,7 +3018,7 @@ static gboolean clean_connecting_state(GIOChannel *io, GIOCondition cond,
 
 	if (adapter->waiting_to_connect == 0 &&
 				g_slist_length(adapter->connect_list) > 0)
-		mgmt_start_le_scanning(adapter->dev_id);
+		adapter->discov_id = g_idle_add(discovery_cb, adapter);
 
 	btd_device_unref(device);
 
-- 
1.7.11.4


^ permalink raw reply related

* [PATCH BlueZ v9 3/8] core: Replace interleaved by LE scanning
From: João Paulo Rechi Vita @ 2012-10-02 17:22 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Claudio Takahasi
In-Reply-To: <1349198578-2818-1-git-send-email-jprvita@openbossa.org>

From: Claudio Takahasi <claudio.takahasi@openbossa.org>

This patches replaces the interleaved discovery by LE scanning when LE
re-connection is required.
---
 src/adapter.c | 22 +++++++++++++++-------
 1 file changed, 15 insertions(+), 7 deletions(-)

diff --git a/src/adapter.c b/src/adapter.c
index 11ae0e9..d7f8c14 100644
--- a/src/adapter.c
+++ b/src/adapter.c
@@ -2305,7 +2305,7 @@ void btd_adapter_start(struct btd_adapter *adapter)
 	info("Adapter %s has been enabled", adapter->path);
 
 	if (g_slist_length(adapter->connect_list) > 0)
-		mgmt_start_discovery(adapter->dev_id);
+		mgmt_start_le_scanning(adapter->dev_id);
 }
 
 static void reply_pending_requests(struct btd_adapter *adapter)
@@ -2652,14 +2652,22 @@ void adapter_set_discovering(struct btd_adapter *adapter,
 
 	connect_list_len = g_slist_length(adapter->connect_list);
 
-	if (!adapter_has_discov_sessions(adapter) && connect_list_len == 0)
+	if (adapter_has_discov_sessions(adapter)) {
+		adapter->discov_id = g_idle_add(discovery_cb, adapter);
+
+		DBG("hci%u restarting discovery: disc_sessions %u",
+				adapter->dev_id,
+				g_slist_length(adapter->disc_sessions));
 		return;
+	}
 
-	DBG("hci%u restarting discovery: disc_sessions %u connect_list_len %u",
-		adapter->dev_id, g_slist_length(adapter->disc_sessions),
-							connect_list_len);
+	if (connect_list_len > 0) {
+		mgmt_start_le_scanning(adapter->dev_id);
 
-	adapter->discov_id = g_idle_add(discovery_cb, adapter);
+		DBG("hci%u restarting scanning connect_list_len %u",
+				adapter->dev_id, connect_list_len);
+		return;
+	}
 }
 
 static void suspend_discovery(struct btd_adapter *adapter)
@@ -2974,7 +2982,7 @@ static gboolean clean_connecting_state(GIOChannel *io, GIOCondition cond,
 
 	if (adapter->waiting_to_connect == 0 &&
 				g_slist_length(adapter->connect_list) > 0)
-		mgmt_start_discovery(adapter->dev_id);
+		mgmt_start_le_scanning(adapter->dev_id);
 
 	btd_device_unref(device);
 
-- 
1.7.11.4


^ permalink raw reply related

* [PATCH BlueZ v9 2/8] mgmt: Add LE scanning callback
From: João Paulo Rechi Vita @ 2012-10-02 17:22 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Claudio Takahasi
In-Reply-To: <1349198578-2818-1-git-send-email-jprvita@openbossa.org>

From: Claudio Takahasi <claudio.takahasi@openbossa.org>

This patch adds a new callback to allow the adapter to control LE
scanning. The current approach uses the active scanning with default
windows and intervals defined by the core spec without any filtering.
---
 src/mgmt.c | 34 ++++++++++++++++++++++++++++++++++
 src/mgmt.h |  1 +
 2 files changed, 35 insertions(+)

diff --git a/src/mgmt.c b/src/mgmt.c
index e368b8a..fc0e5e4 100644
--- a/src/mgmt.c
+++ b/src/mgmt.c
@@ -2055,6 +2055,40 @@ int mgmt_start_discovery(int index)
 	return 0;
 }
 
+int mgmt_start_le_scanning(int index)
+{
+	char buf[MGMT_HDR_SIZE + sizeof(struct mgmt_cp_start_discovery)];
+	struct mgmt_hdr *hdr = (void *) buf;
+	struct mgmt_cp_start_discovery *cp = (void *) &buf[sizeof(*hdr)];
+	struct controller_info *info = &controllers[index];
+
+	DBG("index %d", index);
+
+	if (!mgmt_low_energy(info->current_settings)) {
+		error("scanning failed: Low Energy not enabled/supported");
+		return -ENOTSUP;
+	}
+
+	info->discov_type = 0;
+	hci_set_bit(BDADDR_LE_PUBLIC, &info->discov_type);
+	hci_set_bit(BDADDR_LE_RANDOM, &info->discov_type);
+
+	memset(buf, 0, sizeof(buf));
+	hdr->opcode = htobs(MGMT_OP_START_DISCOVERY);
+	hdr->len = htobs(sizeof(*cp));
+	hdr->index = htobs(index);
+
+	cp->type = info->discov_type;
+
+	if (write(mgmt_sock, buf, sizeof(buf)) < 0) {
+		int err = -errno;
+		error("failed to write to MGMT socket: %s", strerror(-err));
+		return err;
+	}
+
+	return 0;
+}
+
 int mgmt_stop_discovery(int index)
 {
 	char buf[MGMT_HDR_SIZE + sizeof(struct mgmt_cp_start_discovery)];
diff --git a/src/mgmt.h b/src/mgmt.h
index 95245d2..1d25cb0 100644
--- a/src/mgmt.h
+++ b/src/mgmt.h
@@ -33,6 +33,7 @@ int mgmt_set_dev_class(int index, uint8_t major, uint8_t minor);
 int mgmt_set_fast_connectable(int index, gboolean enable);
 
 int mgmt_start_discovery(int index);
+int mgmt_start_le_scanning(int index);
 int mgmt_stop_discovery(int index);
 
 int mgmt_read_clock(int index, bdaddr_t *bdaddr, int which, int timeout,
-- 
1.7.11.4


^ permalink raw reply related

* [PATCH BlueZ v9 1/8] core: Mutually exclude concurrent connections
From: João Paulo Rechi Vita @ 2012-10-02 17:22 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: João Paulo Rechi Vita

Since controllers don't support more than one ongoing connection
procedure at the same time, new connection attempts needs to yield if
there is an ongoing connection procedure already.
---
 src/adapter.c | 66 +++++++++++++++++++++++++++++++++++++++++++++++++++--------
 src/device.c  |  6 +++---
 src/device.h  |  2 +-
 3 files changed, 62 insertions(+), 12 deletions(-)

diff --git a/src/adapter.c b/src/adapter.c
index f11be70..11ae0e9 100644
--- a/src/adapter.c
+++ b/src/adapter.c
@@ -136,6 +136,8 @@ struct btd_adapter {
 	GSList *connect_list;		/* Devices to connect when found */
 	guint discov_id;		/* Discovery timer */
 	gboolean discovering;		/* Discovery active */
+	gboolean connecting;		/* Connect active */
+	guint waiting_to_connect;	/* # of devices waiting to connect */
 	gboolean discov_suspended;	/* Discovery suspended */
 	guint auto_timeout_id;		/* Automatic connections timeout */
 	sdp_list_t *services;		/* Services associated to adapter */
@@ -2301,6 +2303,9 @@ void btd_adapter_start(struct btd_adapter *adapter)
 	call_adapter_powered_callbacks(adapter, TRUE);
 
 	info("Adapter %s has been enabled", adapter->path);
+
+	if (g_slist_length(adapter->connect_list) > 0)
+		mgmt_start_discovery(adapter->dev_id);
 }
 
 static void reply_pending_requests(struct btd_adapter *adapter)
@@ -2627,6 +2632,7 @@ void adapter_set_discovering(struct btd_adapter *adapter,
 						gboolean discovering)
 {
 	const char *path = adapter->path;
+	guint connect_list_len;
 
 	adapter->discovering = discovering;
 
@@ -2641,11 +2647,17 @@ void adapter_set_discovering(struct btd_adapter *adapter,
 	g_slist_free_full(adapter->oor_devices, dev_info_free);
 	adapter->oor_devices = g_slist_copy(adapter->found_devices);
 
-	if (!adapter_has_discov_sessions(adapter) || adapter->discov_suspended)
+	if (adapter->discov_suspended)
+		return;
+
+	connect_list_len = g_slist_length(adapter->connect_list);
+
+	if (!adapter_has_discov_sessions(adapter) && connect_list_len == 0)
 		return;
 
-	DBG("hci%u restarting discovery, disc_sessions %u", adapter->dev_id,
-					g_slist_length(adapter->disc_sessions));
+	DBG("hci%u restarting discovery: disc_sessions %u connect_list_len %u",
+		adapter->dev_id, g_slist_length(adapter->disc_sessions),
+							connect_list_len);
 
 	adapter->discov_id = g_idle_add(discovery_cb, adapter);
 }
@@ -2952,17 +2964,48 @@ static char *read_stored_data(bdaddr_t *local, bdaddr_t *peer,
 	return textfile_get(filename, key);
 }
 
+static gboolean clean_connecting_state(GIOChannel *io, GIOCondition cond,
+							gpointer user_data)
+{
+	struct btd_device *device = user_data;
+	struct btd_adapter *adapter = device_get_adapter(device);
+
+	adapter->connecting = FALSE;
+
+	if (adapter->waiting_to_connect == 0 &&
+				g_slist_length(adapter->connect_list) > 0)
+		mgmt_start_discovery(adapter->dev_id);
+
+	btd_device_unref(device);
+
+	return FALSE;
+}
+
 static gboolean connect_pending_cb(gpointer user_data)
 {
 	struct btd_device *device = user_data;
 	struct btd_adapter *adapter = device_get_adapter(device);
+	GIOChannel *io;
 
 	/* in the future we may want to check here if the controller supports
 	 * scanning and connecting at the same time */
 	if (adapter->discovering)
 		return TRUE;
 
-	device_att_connect(device);
+	if (adapter->connecting)
+		return TRUE;
+
+	adapter->connecting = TRUE;
+	adapter->waiting_to_connect--;
+
+	io = device_att_connect(device);
+	if (io != NULL) {
+		g_io_add_watch(io, G_IO_OUT | G_IO_ERR, clean_connecting_state,
+						btd_device_ref(device));
+		g_io_channel_unref(io);
+	}
+
+	btd_device_unref(device);
 
 	return FALSE;
 }
@@ -3055,12 +3098,19 @@ void adapter_update_found_devices(struct btd_adapter *adapter,
 
 	if (bdaddr_type == BDADDR_LE_PUBLIC ||
 					bdaddr_type == BDADDR_LE_RANDOM) {
+		struct btd_device *device;
+
 		l = g_slist_find_custom(adapter->connect_list, bdaddr,
 					(GCompareFunc) device_bdaddr_cmp);
-		if (l) {
-			g_idle_add(connect_pending_cb, l->data);
-			stop_discovery(adapter);
-		}
+		if (!l)
+			goto done;
+
+		device = l->data;
+		adapter_connect_list_remove(adapter, device);
+
+		g_idle_add(connect_pending_cb, btd_device_ref(device));
+		stop_discovery(adapter);
+		adapter->waiting_to_connect++;
 	}
 
 done:
diff --git a/src/device.c b/src/device.c
index fb7c4f8..7221f93 100644
--- a/src/device.c
+++ b/src/device.c
@@ -2062,7 +2062,7 @@ static void att_success_cb(gpointer user_data)
 	g_slist_foreach(device->attios, attio_connected, device->attrib);
 }
 
-gboolean device_att_connect(gpointer user_data)
+GIOChannel *device_att_connect(gpointer user_data)
 {
 	struct btd_device *device = user_data;
 	struct btd_adapter *adapter = device->adapter;
@@ -2105,12 +2105,12 @@ gboolean device_att_connect(gpointer user_data)
 		error("ATT bt_io_connect(%s): %s", addr, gerr->message);
 		g_error_free(gerr);
 		g_free(attcb);
-		return FALSE;
+		return NULL;
 	}
 
 	device->att_io = io;
 
-	return FALSE;
+	return g_io_channel_ref(io);
 }
 
 static void att_browse_error_cb(const GError *gerr, gpointer user_data)
diff --git a/src/device.h b/src/device.h
index e82fd0e..462b9a1 100644
--- a/src/device.h
+++ b/src/device.h
@@ -124,4 +124,4 @@ int device_unblock(struct btd_device *device, gboolean silent,
 void device_set_pnpid(struct btd_device *device, uint8_t vendor_id_src,
 			uint16_t vendor_id, uint16_t product_id,
 			uint16_t product_ver);
-gboolean device_att_connect(gpointer user_data);
+GIOChannel *device_att_connect(gpointer user_data);
-- 
1.7.11.4


^ permalink raw reply related

* [RFC v3] Convert storage to use per-remote device directories
From: Frederic Danis @ 2012-10-02 15:51 UTC (permalink / raw)
  To: linux-bluetooth@vger.kernel.org

Hi everyone,

Here is my proposal for new storage directory structure using ini-file 
format.

Each adapter directory (/var/lib/bluetooth/<adapter address>/) will contain:
  - an adapter.conf file for the local adapter
  - an attribute_db.conf file containing attributes of supported LE services
  - one directory per remote device, named by remote device address. A 
directory will contain:
     - a device.conf file
     - a key file accessible only by root
     - an attribute_db.conf file containing attributes of remote LE services

So the directory structure should be:
     /var/lib/bluetooth/<adapter address>/
         ./adapter.conf
         ./attribute_db.conf
         ./<remote device address>/
             ./device.conf
             ./keys.conf
             ./attribute_db.conf
         ./<remote device address>/
             ./device.conf
             ./keys.conf
             ./attribute_db.conf
         ...


The adapter config file just need to be converted to ini-file format 
with only 1 [General] group, for example:
   [General]
   Name=desktop-0
   Class=0x780011
   Pairable=true
   OnMode=discoverable
   Mode=discoverable

The attribute_db.conf file should be a list of handles (group name) with 
UUID and Value as keys, for example:
   [0x0001]
   UUID=00002800-0000-1000-8000-00805f9b34fb
   Value=0018

   [0x0004]
   UUID=00002803-0000-1000-8000-00805f9b34fb
   Value=020600002A

   [0x0006]
   UUID=00002a00-0000-1000-8000-00805f9b34fb
   Value=4578616D706C6520446576696365


Remote device config file will include a [General] group with device 
infos (name, alias, profiles list, ...) and a [DeviceID] group with 
related infos (Assigner, Vendor, Product and Version), for example:
   [General]
   Name=MyPhone
   Alias=Fred's phone
   Class=0x180204
   EIR=040D040218
   Manufacturer=15
   LmpVersion=2
   LmpSubversion=777
   Features=FFFE0D0008080000
   LastSeen=2012-09-26 11:19:40 GMT
   LastUsed=2012-09-26 11:43:42 GMT
   Trusted=true
 
Profiles=00001101-0000-1000-8000-00805f9b34fb;00001103-0000-1000-8000-00805f9b34fb

   [DeviceID]
   Assigner=
   Vendor=
   Product=
   Version=

For LE devices, LEAddressType entry should exist to distinguish 
LE-Public from LE-Random address.

Keys file will include informations related to link key or long term 
link key, for example:
   [LinkKey]
   Key=9EF4BDFA68C5438A176DF42ACD59816C
   Type=0
   PINLength=4

   [LongTermKey]
   Key=
   Authenticated=
   EncSize=
   EDiv=
   Rand=

-- 
Frederic Danis                            Open Source Technology Center
frederic.danis@intel.com                              Intel Corporation


^ permalink raw reply

* Re: [PATCH BlueZ 02/10] gdbus: Remove connection from g_dbus_remove_watch
From: Luiz Augusto von Dentz @ 2012-10-02 13:57 UTC (permalink / raw)
  To: Lucas De Marchi; +Cc: linux-bluetooth
In-Reply-To: <CAMOw1v5Gcz47GfSNkpccKG2FDwzF1aJQ9nVO2VMKChGQXcP_Cg@mail.gmail.com>

Hi Lucas,

On Tue, Oct 2, 2012 at 1:49 PM, Lucas De Marchi
<lucas.demarchi@profusion.mobi> wrote:
> On Tue, Oct 2, 2012 at 5:05 AM, Luiz Augusto von Dentz
> <luiz.dentz@gmail.com> wrote:
>> Hi Lucas,
>>
>> On Tue, Oct 2, 2012 at 7:23 AM, Lucas De Marchi
>> <lucas.demarchi@profusion.mobi> wrote:
>>> On Mon, Oct 1, 2012 at 2:53 PM, Luiz Augusto von Dentz
>>> <luiz.dentz@gmail.com> wrote:
>>>> From: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
>>>>
>>>> The connection is not really needed since the list of listeners is
>>>> global not per connection, besides it is more convenient this way as
>>>> only the id is needed.
>>>> ---
>>>>  gdbus/gdbus.h | 2 +-
>>>>  gdbus/watch.c | 4 ++--
>>>>  2 files changed, 3 insertions(+), 3 deletions(-)
>>>>
>>>> diff --git a/gdbus/gdbus.h b/gdbus/gdbus.h
>>>> index 0a8a27c..3bd8986 100644
>>>> --- a/gdbus/gdbus.h
>>>> +++ b/gdbus/gdbus.h
>>>> @@ -217,7 +217,7 @@ guint g_dbus_add_signal_watch(DBusConnection *connection,
>>>>                                 const char *interface, const char *member,
>>>>                                 GDBusSignalFunction function, void *user_data,
>>>>                                 GDBusDestroyFunction destroy);
>>>> -gboolean g_dbus_remove_watch(DBusConnection *connection, guint tag);
>>>> +gboolean g_dbus_remove_watch(guint id);
>>>>  void g_dbus_remove_all_watches(DBusConnection *connection);
>>>>
>>>>  #ifdef __cplusplus
>>>> diff --git a/gdbus/watch.c b/gdbus/watch.c
>>>> index 07feb61..00cedae 100644
>>>> --- a/gdbus/watch.c
>>>> +++ b/gdbus/watch.c
>>>> @@ -285,7 +285,7 @@ static void filter_data_free(struct filter_data *data)
>>>>                 g_free(l->data);
>>>>
>>>>         g_slist_free(data->callbacks);
>>>> -       g_dbus_remove_watch(data->connection, data->name_watch);
>>>> +       g_dbus_remove_watch(data->name_watch);
>>>>         g_free(data->name);
>>>>         g_free(data->owner);
>>>>         g_free(data->path);
>>>> @@ -752,7 +752,7 @@ guint g_dbus_add_signal_watch(DBusConnection *connection,
>>>>         return cb->id;
>>>>  }
>>>>
>>>> -gboolean g_dbus_remove_watch(DBusConnection *connection, guint id)
>>>> +gboolean g_dbus_remove_watch(guint id)
>>>>  {
>>>>         struct filter_data *data;
>>>>         struct filter_callback *cb;
>>>> --
>>>
>>> This will lead to a broken build which is not nice to bisect. Any
>>> other option besides adding with another name, converting everybody
>>> and then renaming?
>>>
>>> The only other option I can think of is adding an ifdef and an option
>>> to build-sys... this would avoid the final renaming.
>>
>> I guess this time it worth having the break of bisect in favor of a
>> more convenient API, if you look at what the code is doing the
>> connection is useless and normally we end up having to call the core
>> to figure out a connection that is not used for anything.
>
> Ahn? did you read what I proposed as an option? I proposed splitting
> the patch in 4 as opposed to 2 as you did.
>
> 0001) WARNING, whitespace error below
>
> diff --git a/gdbus/gdbus.h b/gdbus/gdbus.h
> index 0a8a27c..d254562 100644
> --- a/gdbus/gdbus.h
> +++ b/gdbus/gdbus.h
> @@ -217,7 +217,12 @@ guint g_dbus_add_signal_watch(DBusConnection *connection,
>                                 const char *interface, const char *member,
>                                 GDBusSignalFunction function, void *user_data,
>                                 GDBusDestroyFunction destroy);
> -gboolean g_dbus_remove_watch(DBusConnection *connection, guint tag);
> +#ifdef _GDBUS_WITH_NEW_REMOVE_WATCH
> +gboolean g_dbus_remove_watch(guint tag);
> +#else
> +gboolean g_dbus_remove_watch(DBusConnection *connection, guint tag);
> +#endif
> +
>  void g_dbus_remove_all_watches(DBusConnection *connection);
>
>  #ifdef __cplusplus
>
>
> 0002) Convert everybody adding the definition on Makefile.am
>
> 0003) Remove the define from Makefile.am
>
> 0004) Remove the old code from gdbus/

That sounds overkill for so simple change, I will send updates to
other projects using gdbus to see their reception, if they are
receptive to the changes I think we can ignore the bisect problem.

-- 
Luiz Augusto von Dentz

^ permalink raw reply

* Re: [PATCH BlueZ] attrib: Get address type using gatt_get_address()
From: Johan Hedberg @ 2012-10-02 13:45 UTC (permalink / raw)
  To: Anderson Lizardo; +Cc: linux-bluetooth
In-Reply-To: <1349182220-525-1-git-send-email-anderson.lizardo@openbossa.org>

Hi Lizardo,

On Tue, Oct 02, 2012, Anderson Lizardo wrote:
> This avoids a separate call to device_get_addr_type().
> ---
>  attrib/client.c |    5 +----
>  1 file changed, 1 insertion(+), 4 deletions(-)

Applied. Thanks.

Johan

^ permalink raw reply

* Unreliable communication with multiple bluetooth devices and some delay
From: Sietse Achterop @ 2012-10-02 13:37 UTC (permalink / raw)
  To: linux-bluetooth


     Dear list,

not sure wheather this for this list, but if so please tell me.
I have problems with unreliable bluetooth communication.

I have 7 bluetooth devices (epucks, educational robots:  http://www.e-puck.org/).
They use the lmx9838 device for bluetooth and are seen as rfcomm-devices on linux.
The lmx-device is used in transparent mode.
This is on various linuxes, with kernels 2.6.32, 3.0.0 and 3.2, e.g. as in the latest ubuntu 12.04.1.

The test program is a simple loop that continuously sends each epuck a small message,
a string of say 6 characters.
I use stdio's fprintf to send chars to the /dev/rfcomm devices.
In pseudo code:
  open_devices();
  while true do
    for i = 1 to 7 do
       fprintf(fp[i], "l,1,2\n");
    od
    delay( 0.5 seconds);
  od

This works perfectly if the delay statement is REMOVED.
Then each 2 milliseconds a message is send to the next epuck.
But if the delay is ADDED again it gets very UNRELIABLE.
After 1 to 30 seconds a communication is failing and after a
20 second delay the connection of a epuck is dropped.
After a longer time all connections are dropped.

I tried a lot, but am at a loss at the moment.
The question is, where the problem. Why is the delay the problem?
Are the short messages the problem?
Is it a bug in the linux driver?

Hopefully someone on the list can help me a step in the right direction.

   Thanks in advance.
      Sietse Achterop
      University of Groningen
      The Netherlands

^ permalink raw reply

* [PATCH BlueZ] attrib: Get address type using gatt_get_address()
From: Anderson Lizardo @ 2012-10-02 12:50 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Anderson Lizardo

This avoids a separate call to device_get_addr_type().
---
 attrib/client.c |    5 +----
 1 file changed, 1 insertion(+), 4 deletions(-)

diff --git a/attrib/client.c b/attrib/client.c
index ece16bf..d49804c 100644
--- a/attrib/client.c
+++ b/attrib/client.c
@@ -705,7 +705,6 @@ static GSList *load_characteristics(struct gatt_service *gatt, uint16_t start)
 static void store_attribute(struct gatt_service *gatt, uint16_t handle,
 				uint16_t type, uint8_t *value, gsize len)
 {
-	struct btd_device *device = gatt->dev;
 	bdaddr_t sba, dba;
 	uint8_t bdaddr_type;
 	bt_uuid_t uuid;
@@ -722,9 +721,7 @@ static void store_attribute(struct gatt_service *gatt, uint16_t handle,
 	for (i = 0, tmp = str + MAX_LEN_UUID_STR; i < len; i++, tmp += 2)
 		sprintf(tmp, "%02X", value[i]);
 
-	gatt_get_address(gatt, &sba, &dba, NULL);
-
-	bdaddr_type = device_get_addr_type(device);
+	gatt_get_address(gatt, &sba, &dba, &bdaddr_type);
 
 	write_device_attribute(&sba, &dba, bdaddr_type, handle, str);
 
-- 
1.7.9.5


^ permalink raw reply related

* Re: [RFC v2] Convert storage to use per-remote device directories
From: Johan Hedberg @ 2012-10-02 12:41 UTC (permalink / raw)
  To: Frederic Danis; +Cc: linux-bluetooth@vger.kernel.org
In-Reply-To: <506AD942.5020902@linux.intel.com>

Hi Frederic,

On Tue, Oct 02, 2012, Frederic Danis wrote:
> The adapter config file just need to be converted to ini-file format
> with only 1 group called [adapter], for example:
>   [Adapter]
>   Name=desktop-0
>   Class=0x780011
>   Pairable=true
>   OnMode=discoverable
>   Mode=discoverable

Looks ok, except I'd call the main section [General] to make it more
natural to extend the file with new sections in the future. This is also
consistent with what we have under /etc/bluetooth.

> Remote device config file will include a [device] group with general
> device infos (name, alias, profiles or primary services list, ...),
> for example:
>   [Device]

Same thing as with adapter.conf, i.e. I'd call this simply [General]

>   DeviceId=FFFF 0000 0000 0000

I'd move this into its own [DeviceID] section with separate Assigner,
Vendor, Product and Version fields.

> Keys file will include informations related to link key or long term
> link key, for example:
>   [LinkKey]
>   Key=9EF4BDFA68C5438A176DF42ACD59816C
>   Type=0
>   Length=4

I suppose s/Length/PINLength/ would be in order here.

Johan

^ permalink raw reply

* [RFC v2] Convert storage to use per-remote device directories
From: Frederic Danis @ 2012-10-02 12:08 UTC (permalink / raw)
  To: linux-bluetooth@vger.kernel.org

Hi everyone,

Here is my proposal for new storage directory structure using ini-file 
format.

Each adapter directory (/var/lib/bluetooth/<adapter address>/) will contain:
  - an adapter.conf file for the local adapter
  - an attribute_db.conf file containing attributes of supported LE services
  - one directory per remote device, named by remote device address. A 
directory will contain:
     - a device.conf file
     - a key file accessible only by root
     - an attribute_db.conf file containing attributes of remote LE services

So the directory structure should be:
     /var/lib/bluetooth/<adapter address>/
         ./adapter.conf
         ./attribute_db.conf
         ./<remote device address>/
             ./device.conf
             ./keys.conf
             ./attribute_db.conf
         ./<remote device address>/
             ./device.conf
             ./keys.conf
             ./attribute_db.conf
         ...


The adapter config file just need to be converted to ini-file format 
with only 1 group called [adapter], for example:
   [Adapter]
   Name=desktop-0
   Class=0x780011
   Pairable=true
   OnMode=discoverable
   Mode=discoverable

The attribute_db.conf file should be a list of handles (group name) with 
UUID and Value as keys, for example:
   [0x0001]
   UUID=00002800-0000-1000-8000-00805f9b34fb
   Value=0018

   [0x0004]
   UUID=00002803-0000-1000-8000-00805f9b34fb
   Value=020600002A

   [0x0006]
   UUID=00002a00-0000-1000-8000-00805f9b34fb
   Value=4578616D706C6520446576696365


Remote device config file will include a [device] group with general 
device infos (name, alias, profiles or primary services list, ...), for 
example:
   [Device]
   Name=MyPhone
   Alias=Fred's phone
   Class=0x180204
   DeviceId=FFFF 0000 0000 0000
   EIR=040D040218
   Manufacturer=15
   LmpVersion=2
   LmpSubversion=777
   Features=FFFE0D0008080000
   LastSeen=2012-09-26 11:19:40 GMT
   LastUsed=2012-09-26 11:43:42 GMT
   Trusted=true
 
Profiles=00001101-0000-1000-8000-00805f9b34fb;00001103-0000-1000-8000-00805f9b34fb

For LE devices, LEAddressType entry should exist to distinguish 
LE-Public from LE-Random address.

Keys file will include informations related to link key or long term 
link key, for example:
   [LinkKey]
   Key=9EF4BDFA68C5438A176DF42ACD59816C
   Type=0
   Length=4

   [LongTermKey]
   Key=
   Authenticated=
   EncSize=
   EDiv=
   Rand=

-- 
Frederic Danis                            Open Source Technology Center
frederic.danis@intel.com                              Intel Corporation




^ permalink raw reply


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