Linux bluetooth development
 help / color / mirror / Atom feed
* [RFC 1/2] android: Add Adapter Bluetooth HAL template
From: Andrei Emeltchenko @ 2013-09-24  8:31 UTC (permalink / raw)
  To: linux-bluetooth
In-Reply-To: <1380011516-7847-1-git-send-email-Andrei.Emeltchenko.news@gmail.com>

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

Add template for bluetooth.h Android HAL.
---
 android/Android.mk      |   19 +++
 android/hal_bluetooth.c |  367 +++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 386 insertions(+)
 create mode 100644 android/hal_bluetooth.c

diff --git a/android/Android.mk b/android/Android.mk
index 5d09f00..ca9501f 100644
--- a/android/Android.mk
+++ b/android/Android.mk
@@ -23,3 +23,22 @@ LOCAL_SHARED_LIBRARIES := \
 LOCAL_MODULE := bluezd
 
 include $(BUILD_EXECUTABLE)
+
+#
+# bluetooth.default.so HAL
+#
+
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES := \
+	hal_bluetooth.c \
+
+LOCAL_SHARED_LIBRARIES := \
+	libcutils \
+
+LOCAL_MODULE := bluetooth.default
+LOCAL_MODULE_PATH := $(TARGET_OUT_SHARED_LIBRARIES)/hw
+LOCAL_MODULE_TAGS := optional
+LOCAL_MODULE_CLASS := SHARED_LIBRARIES
+
+include $(BUILD_SHARED_LIBRARY)
diff --git a/android/hal_bluetooth.c b/android/hal_bluetooth.c
new file mode 100644
index 0000000..4447bed
--- /dev/null
+++ b/android/hal_bluetooth.c
@@ -0,0 +1,367 @@
+/*
+ * Copyright (C) 2013 Intel Corporation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <stdbool.h>
+
+#include <hardware/bluetooth.h>
+
+#define LOG_TAG "BlueZ"
+#include <cutils/log.h>
+
+bt_callbacks_t *bt_hal_cbacks = NULL;
+
+static bool interface_ready(void)
+{
+	return bt_hal_cbacks != NULL;
+}
+
+static int init(bt_callbacks_t *callbacks)
+{
+	ALOGI(__func__);
+
+	/* sanity check */
+	if (interface_ready() == true)
+		return BT_STATUS_SUCCESS;
+
+	/* store reference to user callbacks */
+	bt_hal_cbacks = callbacks;
+
+	/* TODO: Init here bluezd task */
+
+	return BT_STATUS_UNSUPPORTED;
+}
+
+static int enable(void)
+{
+	ALOGI(__func__);
+
+	return BT_STATUS_UNSUPPORTED;
+}
+
+static int disable(void)
+{
+	ALOGI(__func__);
+
+	/* sanity check */
+	if (interface_ready() == false)
+		return BT_STATUS_NOT_READY;
+
+	return BT_STATUS_UNSUPPORTED;
+}
+
+static void cleanup(void)
+{
+	ALOGI(__func__);
+
+	/* sanity check */
+	if (interface_ready() == false)
+		return;
+
+	bt_hal_cbacks = NULL;
+}
+
+static int get_adapter_properties(void)
+{
+	ALOGI(__func__);
+
+	/* sanity check */
+	if (interface_ready() == false)
+		return BT_STATUS_NOT_READY;
+
+	return BT_STATUS_UNSUPPORTED;
+}
+
+static int get_adapter_property(bt_property_type_t type)
+{
+	ALOGI(__func__);
+
+	/* sanity check */
+	if (interface_ready() == false)
+		return BT_STATUS_NOT_READY;
+
+	return BT_STATUS_UNSUPPORTED;
+}
+
+static int set_adapter_property(const bt_property_t *property)
+{
+	ALOGI(__func__);
+
+	/* sanity check */
+	if (interface_ready() == false)
+		return BT_STATUS_NOT_READY;
+
+	if (property == NULL)
+		return BT_STATUS_PARM_INVALID;
+
+	return BT_STATUS_UNSUPPORTED;
+}
+
+int get_remote_device_properties(bt_bdaddr_t *remote_addr)
+{
+	ALOGI(__func__);
+
+	/* sanity check */
+	if (interface_ready() == false)
+		return BT_STATUS_NOT_READY;
+
+	return BT_STATUS_UNSUPPORTED;
+}
+
+int get_remote_device_property(bt_bdaddr_t *remote_addr,
+						bt_property_type_t type)
+{
+	ALOGI(__func__);
+
+	/* sanity check */
+	if (interface_ready() == false)
+		return BT_STATUS_NOT_READY;
+
+	return BT_STATUS_UNSUPPORTED;
+}
+
+int set_remote_device_property(bt_bdaddr_t *remote_addr,
+						const bt_property_t *property)
+{
+	ALOGI(__func__);
+
+	/* sanity check */
+	if (interface_ready() == false)
+		return BT_STATUS_NOT_READY;
+
+	return BT_STATUS_UNSUPPORTED;
+}
+
+int get_remote_service_record(bt_bdaddr_t *remote_addr, bt_uuid_t *uuid)
+{
+	ALOGI(__func__);
+
+	/* sanity check */
+	if (interface_ready() == false)
+		return BT_STATUS_NOT_READY;
+
+	return BT_STATUS_UNSUPPORTED;
+}
+
+int get_remote_services(bt_bdaddr_t *remote_addr)
+{
+	ALOGI(__func__);
+
+	/* sanity check */
+	if (interface_ready() == false)
+		return BT_STATUS_NOT_READY;
+
+	return BT_STATUS_UNSUPPORTED;
+}
+
+static int start_discovery(void)
+{
+	ALOGI(__func__);
+
+	/* sanity check */
+	if (interface_ready() == false)
+		return BT_STATUS_NOT_READY;
+
+	return BT_STATUS_UNSUPPORTED;
+}
+
+static int cancel_discovery(void)
+{
+	ALOGI(__func__);
+
+	/* sanity check */
+	if (interface_ready() == false)
+		return BT_STATUS_NOT_READY;
+
+	return BT_STATUS_UNSUPPORTED;
+}
+
+static int create_bond(const bt_bdaddr_t *bd_addr)
+{
+	ALOGI(__func__);
+
+	/* sanity check */
+	if (interface_ready() == false)
+		return BT_STATUS_NOT_READY;
+
+	if (bd_addr == NULL)
+		return BT_STATUS_PARM_INVALID;
+
+	return BT_STATUS_UNSUPPORTED;
+}
+
+static int cancel_bond(const bt_bdaddr_t *bd_addr)
+{
+	ALOGI(__func__);
+
+	/* sanity check */
+	if (interface_ready() == false)
+		return BT_STATUS_NOT_READY;
+
+	return BT_STATUS_UNSUPPORTED;
+}
+
+static int remove_bond(const bt_bdaddr_t *bd_addr)
+{
+	ALOGI(__func__);
+
+	/* sanity check */
+	if (interface_ready() == false)
+		return BT_STATUS_NOT_READY;
+
+	return BT_STATUS_UNSUPPORTED;
+}
+
+static int pin_reply(const bt_bdaddr_t *bd_addr, uint8_t accept,
+				uint8_t pin_len, bt_pin_code_t *pin_code)
+{
+	ALOGI(__func__);
+
+	/* sanity check */
+	if (interface_ready() == false)
+		return BT_STATUS_NOT_READY;
+
+	return BT_STATUS_UNSUPPORTED;
+}
+
+static int ssp_reply(const bt_bdaddr_t *bd_addr, bt_ssp_variant_t variant,
+					uint8_t accept, uint32_t passkey)
+{
+
+	ALOGI(__func__);
+
+	/* sanity check */
+	if (interface_ready() == false)
+		return BT_STATUS_NOT_READY;
+
+	if (bd_addr == NULL)
+		return BT_STATUS_PARM_INVALID;
+
+	return BT_STATUS_UNSUPPORTED;
+}
+
+static const void *get_profile_interface(const char *profile_id)
+{
+	ALOGI("%s: %s", __func__, profile_id);
+
+	/* sanity check */
+	if (interface_ready() == false)
+		return NULL;
+
+	return NULL;
+}
+
+int dut_mode_configure(uint8_t enable)
+{
+	ALOGI(__func__);
+
+	/* sanity check */
+	if (interface_ready() == false)
+		return BT_STATUS_NOT_READY;
+
+	return BT_STATUS_UNSUPPORTED;
+}
+
+int dut_mode_send(uint16_t opcode, uint8_t *buf, uint8_t len)
+{
+	ALOGI(__func__);
+
+	/* sanity check */
+	if (interface_ready() == false)
+		return BT_STATUS_NOT_READY;
+
+	return BT_STATUS_UNSUPPORTED;
+}
+
+/**
+ * HAL Interface declaration
+ */
+static const bt_interface_t bluetoothInterface = {
+	sizeof(bt_interface_t),
+	init,
+	enable,
+	disable,
+	cleanup,
+	get_adapter_properties,
+	get_adapter_property,
+	set_adapter_property,
+	get_remote_device_properties,
+	get_remote_device_property,
+	set_remote_device_property,
+	get_remote_service_record,
+	get_remote_services,
+	start_discovery,
+	cancel_discovery,
+	create_bond,
+	remove_bond,
+	cancel_bond,
+	pin_reply,
+	ssp_reply,
+	get_profile_interface,
+	dut_mode_configure,
+	dut_mode_send
+};
+
+const bt_interface_t *bluetooth__get_bluetooth_interface(void)
+{
+	ALOGI(__func__);
+
+	return &bluetoothInterface;
+}
+
+static int close_bluetooth_stack(struct hw_device_t *device)
+{
+	ALOGI(__func__);
+
+	cleanup();
+
+	return 0;
+}
+
+static int open_bluetooth_stack(const struct hw_module_t *module,
+			char const *name, struct hw_device_t **abstraction)
+{
+	bluetooth_device_t *stack = malloc(sizeof(bluetooth_device_t));
+
+	ALOGI(__func__);
+
+	memset(stack, 0, sizeof(bluetooth_device_t));
+	stack->common.tag = HARDWARE_DEVICE_TAG;
+	stack->common.version = 0;
+	stack->common.module = (struct hw_module_t *) module;
+	stack->common.close = close_bluetooth_stack;
+	stack->get_bluetooth_interface = bluetooth__get_bluetooth_interface;
+	*abstraction = (struct hw_device_t *) stack;
+
+	return 0;
+}
+
+static struct hw_module_methods_t bt_stack_module_methods = {
+	.open = open_bluetooth_stack,
+};
+
+struct hw_module_t HAL_MODULE_INFO_SYM = {
+	.tag = HARDWARE_MODULE_TAG,
+	.version_major = 1,
+	.version_minor = 0,
+	.id = BT_HARDWARE_MODULE_ID,
+	.name = "Bluetooth Stack",
+	.author = "The Android Open Source Project",
+	.methods = &bt_stack_module_methods
+};
-- 
1.7.10.4


^ permalink raw reply related

* [RFC 0/2] Adapter and Socket templates
From: Andrei Emeltchenko @ 2013-09-24  8:31 UTC (permalink / raw)
  To: linux-bluetooth

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

First versions of adapter and socket templates.

Andrei Emeltchenko (2):
  android: Add Adapter Bluetooth HAL template
  android: Add Socket Bluetooth HAL template

 android/Android.mk      |   20 +++
 android/hal_bluetooth.c |  367 +++++++++++++++++++++++++++++++++++++++++++++++
 android/hal_bt_sock.c   |   86 +++++++++++
 3 files changed, 473 insertions(+)
 create mode 100644 android/hal_bluetooth.c
 create mode 100644 android/hal_bt_sock.c

-- 
1.7.10.4


^ permalink raw reply

* [PATCH 2/2] obexd:Add get_address property to transfer properties
From: Wu Zheng @ 2013-09-24  7:37 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Wu Zheng

Sometime, address is needed by the Bluetooth OBEX APP.
Therefore, add the property to transfer properties
---
 obexd/src/manager.c |   37 +++++++++++++++++++++++++++++++++++++
 1 files changed, 37 insertions(+), 0 deletions(-)

diff --git a/obexd/src/manager.c b/obexd/src/manager.c
index 96976ec..b338a72 100644
--- a/obexd/src/manager.c
+++ b/obexd/src/manager.c
@@ -551,6 +551,41 @@ static gboolean transfer_get_operation(const GDBusPropertyTable *property,
 	return TRUE;
 }
 
+static gboolean transfer_address_exists(const GDBusPropertyTable *property,
+								void *data)
+{
+	struct obex_transfer *transfer = data;
+	struct obex_session *session = transfer->session;
+	char *address;
+	int err;
+
+	err = obex_getpeername(session, &address);
+	if (err < 0)
+		return FALSE;
+
+	g_free(address);
+
+	return TRUE;
+}
+
+static gboolean transfer_get_address(const GDBusPropertyTable *property,
+					DBusMessageIter *iter, void *data)
+{
+	struct obex_transfer *transfer = data;
+	struct obex_session *session = transfer->session;
+	char *address;
+	int err;
+
+	err = obex_getpeername(session, &address);
+	if (err < 0)
+		return FALSE;
+
+	dbus_message_iter_append_basic(iter, DBUS_TYPE_STRING, &address);
+	g_free(address);
+
+	return TRUE;
+}
+
 static gboolean transfer_get_transferred(const GDBusPropertyTable *property,
 					DBusMessageIter *iter, void *data)
 {
@@ -587,6 +622,8 @@ static const GDBusPropertyTable transfer_properties[] = {
 						transfer_filename_exists },
 	{ "Operation", "s", transfer_get_operation, NULL,
 						transfer_operation_exists },
+	{ "Address", "s", transfer_get_address, NULL,
+						transfer_address_exists },
 	{ "Transferred", "t", transfer_get_transferred },
 	{ }
 };
-- 
1.7.7


^ permalink raw reply related

* [PATCH 1/2] obexd:Add Operation property to transfer properties
From: Wu Zheng @ 2013-09-24  7:37 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Wu Zheng

Sometime, operation property is needed by the Bluetooth APP.
Therefore, add the property to transfer properties
---
 obexd/src/manager.c |   38 ++++++++++++++++++++++++++++++++++++++
 1 files changed, 38 insertions(+), 0 deletions(-)

diff --git a/obexd/src/manager.c b/obexd/src/manager.c
index f64b7b9..96976ec 100644
--- a/obexd/src/manager.c
+++ b/obexd/src/manager.c
@@ -35,6 +35,7 @@
 
 #include <btio/btio.h>
 #include <gobex/gobex.h>
+#include <gobex/gobex-packet.h>
 
 #include "obexd.h"
 #include "obex.h"
@@ -515,6 +516,41 @@ static gboolean transfer_get_filename(const GDBusPropertyTable *property,
 	return TRUE;
 }
 
+static gboolean transfer_operation_exists(const GDBusPropertyTable *property,
+								void *data)
+{
+	struct obex_transfer *transfer = data;
+	struct obex_session *session = transfer->session;
+
+	if (session->cmd == G_OBEX_OP_PUT &&
+				session->size != OBJECT_SIZE_DELETE)
+		return TRUE;
+	else if (session->cmd == G_OBEX_OP_GET)
+		return TRUE;
+	else
+		return FALSE;
+}
+
+static gboolean transfer_get_operation(const GDBusPropertyTable *property,
+					DBusMessageIter *iter, void *data)
+{
+	struct obex_transfer *transfer = data;
+	struct obex_session *session = transfer->session;
+	const char *operation;
+
+	if (session->cmd == G_OBEX_OP_PUT &&
+				session->size != OBJECT_SIZE_DELETE)
+		operation = "PUT";
+	else if (session->cmd == G_OBEX_OP_GET)
+		operation = "GET";
+	else
+		return FALSE;
+
+	dbus_message_iter_append_basic(iter, DBUS_TYPE_STRING, &operation);
+
+	return TRUE;
+}
+
 static gboolean transfer_get_transferred(const GDBusPropertyTable *property,
 					DBusMessageIter *iter, void *data)
 {
@@ -549,6 +585,8 @@ static const GDBusPropertyTable transfer_properties[] = {
 	{ "Time", "t", transfer_get_time, NULL, transfer_time_exists },
 	{ "Filename", "s", transfer_get_filename, NULL,
 						transfer_filename_exists },
+	{ "Operation", "s", transfer_get_operation, NULL,
+						transfer_operation_exists },
 	{ "Transferred", "t", transfer_get_transferred },
 	{ }
 };
-- 
1.7.7


^ permalink raw reply related

* Re: [PATCH 1/2] android: Add skeleton of BlueZ Android daemon
From: Andrei Emeltchenko @ 2013-09-24  7:32 UTC (permalink / raw)
  To: Lukasz Rymanowski; +Cc: Frederic Danis, Marcel Holtmann, linux-bluetooth
In-Reply-To: <CAN_7+YYSLwsPTfJoYwJKcVtP6EMxOeD8MHox+Pvzcrk_YKcSaQ@mail.gmail.com>

Hi All,

On Mon, Sep 23, 2013 at 09:28:44PM +0200, Lukasz Rymanowski wrote:
> Hi Marcel,
> 
> On Mon, Sep 23, 2013 at 11:51 AM, Frederic Danis
> <frederic.danis@linux.intel.com> wrote:
> > Hello Marcel,
> >
> > On 21/09/2013 19:14, Marcel Holtmann wrote:
> >>
> >> Hi Fred,
> >>
> >>> Define local mapping to glib path, otherwise this has to be inside
> >>> central
> >>> place in the build repository.
> >>>
> >>> Retrieve Bluetooth version from configure.ac.
> >>> ---
> >>> .gitignore         |    2 +
> >>> Android.mk         |    9 ++++
> >>> Makefile.am        |    1 +
> >>> Makefile.android   |    7 ++++
> >>> android/Android.mk |   24 +++++++++++
> >>> android/main.c     |  119
> >>> ++++++++++++++++++++++++++++++++++++++++++++++++++++
> >>> configure.ac       |    5 +++
> >>> 7 files changed, 167 insertions(+)
> >>> create mode 100644 Android.mk
> >>> create mode 100644 Makefile.android
> >>> create mode 100644 android/Android.mk
> >>> create mode 100644 android/main.c
> >>
> >>
> >> lets split this out a little bit. Code additions should not be intermixed
> >> with additions to the build system and especially configure options.
> >>
> >> I rather not have a top-level Android.mk. It should be enough to provide
> >> an android/Android.mk.
> 
>  BTW, do you expect to have only one Android.mk for the whole project or
> this is OK for you to have smaller Android.mk in different subfolders like
> /src/shared etc. Both ways are valid.

While having a single huge Android makefile is somehow make sense it would have
several disadvantages:
- we cannot use local build with "mm" for building for example only tools
  or libs
- Android.mk will become very large and difficult to read

Best regards 
Andrei Emeltchenko 

^ permalink raw reply

* [PATCH] sdptool: Clarify 'add' and 'remove' commands in manual
From: Szymon Janc @ 2013-09-24  7:09 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Szymon Janc

Adapters are no longer notified about external changes in SDP
database. This results in 'add' and 'remove' commands being
usefull only for SDP testing or qualification.
---
 tools/sdptool.1 | 6 ++++++
 1 file changed, 6 insertions(+)

diff --git a/tools/sdptool.1 b/tools/sdptool.1
index 88ad818..ea95933 100644
--- a/tools/sdptool.1
+++ b/tools/sdptool.1
@@ -91,9 +91,15 @@ the \fB--handle\fP option.
 .IP "" 10
 You can specify a channel to add the service on
 using the \fB--channel\fP option.
+.IP "" 10
+NOTE: Local adapters configuration will not be updated and this command should
+be used only for SDP testing.
 .IP "\fBdel record_handle\fP" 10
 Remove a service from the local
 SDP database.
+.IP "" 10
+NOTE: Local adapters configuration will not be updated and this command should
+be used only for SDP testing.
 .IP "\fBget [--tree] [--raw] [--xml] [--bdaddr bdaddr] record_handle\fP" 10
 Retrieve a service from the local
 SDP database.
-- 
1.8.4


^ permalink raw reply related

* Re: [PATCH 08/12] bluetooth: Remove extern from function prototypes
From: Marcel Holtmann @ 2013-09-24  4:24 UTC (permalink / raw)
  To: Joe Perches
  Cc: netdev, David S. Miller, linux-kernel, Gustavo Padovan,
	Johan Hedberg, linux-bluetooth
In-Reply-To: <e9994a2b839277a9237364b59e655060f1fcb957.1379961014.git.joe@perches.com>

Hi Joe,

> There are a mix of function prototypes with and without extern
> in the kernel sources.  Standardize on not using extern for
> function prototypes.
> 
> Function prototypes don't need to be written with extern.
> extern is assumed by the compiler.  Its use is as unnecessary as
> using auto to declare automatic/local variables in a block.
> 
> Signed-off-by: Joe Perches <joe@perches.com>
> ---
> include/net/bluetooth/bluetooth.h | 16 ++++++++--------
> include/net/bluetooth/hci_core.h  | 23 +++++++++++------------
> include/net/bluetooth/rfcomm.h    |  4 ++--
> 3 files changed, 21 insertions(+), 22 deletions(-)

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

Regards

Marcel


^ permalink raw reply

* Re: [PATCH v5 1/2] Bluetooth: btmrvl: add setup handler
From: Marcel Holtmann @ 2013-09-24  4:23 UTC (permalink / raw)
  To: Bing Zhao
  Cc: linux-bluetooth@vger.kernel.org, Gustavo Padovan, Johan Hedberg,
	linux-wireless@vger.kernel.org, Mike Frysinger, Hyuckjoo Lee,
	Amitkumar Karwar
In-Reply-To: <477F20668A386D41ADCC57781B1F70430F44C59418@SC-VEXCH1.marvell.com>

Hi Bing,

>>> -	btmrvl_send_module_cfg_cmd(priv, MODULE_BRINGUP_REQ);
>>> +	hdev->setup = btmrvl_setup;
>> 
>> just to make sure you guys understand how ->setup() works. It is only called once. Bringing the
>> adapter down and up again does not call ->setup() a second time. So do you guys need this setup_done
>> variable and if so, then you need to be a bit more verbose and help me understand why.
> 
> It's observed that sometimes the setup handler is called twice when Bluetooth daemon is running in background. We will rebase to latest commit on bluetooth-next tree and test again. If the issue is gone with the latest code in -next tree we will remove the setup_done flag.

that is a bug. It should only be ever called once. Could this be due to RFKILL issue we had? Please re-test with Johan's patches applied and check if it makes a difference. Otherwise please send some logs since we want to get this fixed.

Regards

Marcel


^ permalink raw reply

* Re: [PATCH v5 2/2] Bluetooth: btmrvl: add calibration data download support
From: Marcel Holtmann @ 2013-09-24  4:21 UTC (permalink / raw)
  To: Bing Zhao
  Cc: linux-bluetooth@vger.kernel.org, Gustavo Padovan, Johan Hedberg,
	linux-wireless@vger.kernel.org, Mike Frysinger, Hyuckjoo Lee,
	Amitkumar Karwar
In-Reply-To: <477F20668A386D41ADCC57781B1F70430F44C59423@SC-VEXCH1.marvell.com>

Hi Bing,

>>> +	cmd = (struct btmrvl_cmd *)skb->data;
>>> +	cmd->ocf_ogf =
>>> +		cpu_to_le16(hci_opcode_pack(OGF, BT_CMD_LOAD_CONFIG_DATA));
>>> +	cmd->length = BT_CMD_DATA_SIZE;
>>> +	cmd->data[0] = 0x00;
>>> +	cmd->data[1] = 0x00;
>>> +	cmd->data[2] = 0x00;
>>> +	cmd->data[3] = BT_CMD_DATA_SIZE - 4;
>> 
>> why not use __hci_cmd_sync() here. It is designed to be used from ->setup() where it is guaranteed
>> that the HCI request lock is held. And it is guaranteed that ->setup() is executed in a workqueue.
> 
> The reason of not using __hci_cmd_sync() is that we are sending vendor specific command here (MRVL_VENDOR_PKT). The __hci_cmd_sync seems handle HCI_COMMAND_PKT only.
> Please let us know if you have any suggestion to solve this problem.

what is a MRVL_VENDOR_PKT actually?

If you guys are not using standard HCI command/event for vendor operation, then this obviously does not fit. However a similar model might make sense instead of manually building packets all the time.

Regards

Marcel


^ permalink raw reply

* pull request: bluetooth 2013-09-23
From: Gustavo Padovan @ 2013-09-23 21:00 UTC (permalink / raw)
  To: linville; +Cc: linux-wireless, linux-bluetooth, linux-kernel

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

Hi John,

First Bluetooth fixes to 3.12, it includes:

* 3 patches to add device id for 3 new hardwares.

* 2 patches from Johan to fix the rfkill behaviour during setup stage

* a small clean up in the rfcomm TTY code that fixes a potential racy
condition (by Gianluca Anzolin)

* 2 fixes to proper set encryption key size and security level in the
peripheral role of Bluetooth LE devices. (by Andre Guedes)

* a fix for dealing devices where pairing is not necessary, we were keeping
the Bluetooth ACL connection alive for too much time. (by Syam Sidhardhan)

Please pull or let me know of any problems! Thanks!


	Gustavo

---
The following changes since commit f4e1a4d3ecbb9e42bdf8e7869ee8a4ebfa27fb20:

  rt2800: change initialization sequence to fix system freeze (2013-09-09 14:44:34 -0400)

are available in the git repository at:

  git://git.kernel.org/pub/scm/linux/kernel/git/bluetooth/bluetooth master

for you to fetch changes up to 5bcecf325378218a8e248bb6bcae96ec7362f8ef:

  Bluetooth: btusb: Add support for Belkin F8065bf (2013-09-23 17:44:25 -0300)

----------------------------------------------------------------
Andre Guedes (2):
      Bluetooth: Fix security level for peripheral role
      Bluetooth: Fix encryption key size for peripheral role

Gianluca Anzolin (1):
      Bluetooth: don't release the port in rfcomm_dev_state_change()

Johan Hedberg (2):
      Bluetooth: Introduce a new HCI_RFKILLED flag
      Bluetooth: Fix rfkill functionality during the HCI setup stage

Ken O'Brien (1):
      Bluetooth: btusb: Add support for Belkin F8065bf

Peng Chen (1):
      Bluetooth: Add a new PID/VID 0cf3/e005 for AR3012.

Raphael Kubo da Costa (1):
      Bluetooth: Add support for BCM20702A0 [0b05, 17cb]

Syam Sidhardhan (1):
      Bluetooth: Fix ACL alive for long in case of non pariable devices

 drivers/bluetooth/ath3k.c   |  2 ++
 drivers/bluetooth/btusb.c   |  5 +++++
 include/net/bluetooth/hci.h |  1 +
 net/bluetooth/hci_core.c    | 26 ++++++++++++++++++++------
 net/bluetooth/hci_event.c   |  6 +++++-
 net/bluetooth/l2cap_core.c  |  7 +++++++
 net/bluetooth/rfcomm/tty.c  | 35 ++---------------------------------
 7 files changed, 42 insertions(+), 40 deletions(-)


[-- Attachment #2: Type: application/pgp-signature, Size: 836 bytes --]

^ permalink raw reply

* Re: [PATCH] drivers: bluetooth: btusb: Added support for Belkin F8065bf usb bluetooth device
From: Gustavo Padovan @ 2013-09-23 20:45 UTC (permalink / raw)
  To: Ken O'Brien; +Cc: marcel, johan.hedberg, linux-bluetooth, linux-kernel
In-Reply-To: <1379787283-5579-1-git-send-email-kernel@kenobrien.org>

Hi Ken,

2013-09-21 Ken O'Brien <kernel@kenobrien.org>:

> Adding generic rule on encountering Belkin bluetooth usb device F8065bf.
> 
> Relevant section from /sys/kernel/debug/usb/devices:
> 
> T:  Bus=03 Lev=01 Prnt=01 Port=00 Cnt=01 Dev#=  2 Spd=12   MxCh= 0
> D:  Ver= 2.00 Cls=ff(vend.) Sub=01 Prot=01 MxPS=64 #Cfgs=  1
> P:  Vendor=050d ProdID=065a Rev= 1.12
> S:  Manufacturer=Broadcom Corp
> S:  Product=BCM20702A0
> S:  SerialNumber=0002723E2D29
> C:* #Ifs= 4 Cfg#= 1 Atr=a0 MxPwr=100mA
> I:* If#= 0 Alt= 0 #EPs= 3 Cls=ff(vend.) Sub=01 Prot=01 Driver=btusb
> E:  Ad=81(I) Atr=03(Int.) MxPS=  16 Ivl=1ms
> E:  Ad=82(I) Atr=02(Bulk) MxPS=  64 Ivl=0ms
> E:  Ad=02(O) Atr=02(Bulk) MxPS=  64 Ivl=0ms
> I:* If#= 1 Alt= 0 #EPs= 2 Cls=ff(vend.) Sub=01 Prot=01 Driver=btusb
> E:  Ad=83(I) Atr=01(Isoc) MxPS=   0 Ivl=1ms
> E:  Ad=03(O) Atr=01(Isoc) MxPS=   0 Ivl=1ms
> I:  If#= 1 Alt= 1 #EPs= 2 Cls=ff(vend.) Sub=01 Prot=01 Driver=btusb
> E:  Ad=83(I) Atr=01(Isoc) MxPS=   9 Ivl=1ms
> E:  Ad=03(O) Atr=01(Isoc) MxPS=   9 Ivl=1ms
> I:  If#= 1 Alt= 2 #EPs= 2 Cls=ff(vend.) Sub=01 Prot=01 Driver=btusb
> E:  Ad=83(I) Atr=01(Isoc) MxPS=  17 Ivl=1ms
> E:  Ad=03(O) Atr=01(Isoc) MxPS=  17 Ivl=1ms
> I:  If#= 1 Alt= 3 #EPs= 2 Cls=ff(vend.) Sub=01 Prot=01 Driver=btusb
> E:  Ad=83(I) Atr=01(Isoc) MxPS=  25 Ivl=1ms
> E:  Ad=03(O) Atr=01(Isoc) MxPS=  25 Ivl=1ms
> I:  If#= 1 Alt= 4 #EPs= 2 Cls=ff(vend.) Sub=01 Prot=01 Driver=btusb
> E:  Ad=83(I) Atr=01(Isoc) MxPS=  33 Ivl=1ms
> E:  Ad=03(O) Atr=01(Isoc) MxPS=  33 Ivl=1ms
> I:  If#= 1 Alt= 5 #EPs= 2 Cls=ff(vend.) Sub=01 Prot=01 Driver=btusb
> E:  Ad=83(I) Atr=01(Isoc) MxPS=  49 Ivl=1ms
> E:  Ad=03(O) Atr=01(Isoc) MxPS=  49 Ivl=1ms
> I:* If#= 2 Alt= 0 #EPs= 2 Cls=ff(vend.) Sub=ff Prot=ff Driver=(none)
> E:  Ad=84(I) Atr=02(Bulk) MxPS=  32 Ivl=0ms
> E:  Ad=04(O) Atr=02(Bulk) MxPS=  32 Ivl=0ms
> I:* If#= 3 Alt= 0 #EPs= 0 Cls=fe(app. ) Sub=01 Prot=01 Driver=(none)
> 
> Signed-off-by: Ken O'Brien <kernel@kenobrien.org>
> ---
>  drivers/bluetooth/btusb.c | 5 ++++-
>  1 file changed, 4 insertions(+), 1 deletion(-)

Patch has been applied to bluetooth.git. Thanks.

	Gustavo

^ permalink raw reply

* RE: [PATCH v5 2/2] Bluetooth: btmrvl: add calibration data download support
From: Bing Zhao @ 2013-09-23 19:35 UTC (permalink / raw)
  To: Marcel Holtmann
  Cc: linux-bluetooth@vger.kernel.org, Gustavo Padovan, Johan Hedberg,
	linux-wireless@vger.kernel.org, Mike Frysinger, Hyuckjoo Lee,
	Amitkumar Karwar
In-Reply-To: <05172D80-CE30-4B7D-A64E-11B8E320EF7F@holtmann.org>

Hi Marcel,

> > +	cmd =3D (struct btmrvl_cmd *)skb->data;
> > +	cmd->ocf_ogf =3D
> > +		cpu_to_le16(hci_opcode_pack(OGF, BT_CMD_LOAD_CONFIG_DATA));
> > +	cmd->length =3D BT_CMD_DATA_SIZE;
> > +	cmd->data[0] =3D 0x00;
> > +	cmd->data[1] =3D 0x00;
> > +	cmd->data[2] =3D 0x00;
> > +	cmd->data[3] =3D BT_CMD_DATA_SIZE - 4;
>=20
> why not use __hci_cmd_sync() here. It is designed to be used from ->setup=
() where it is guaranteed
> that the HCI request lock is held. And it is guaranteed that ->setup() is=
 executed in a workqueue.

The reason of not using __hci_cmd_sync() is that we are sending vendor spec=
ific command here (MRVL_VENDOR_PKT). The __hci_cmd_sync seems handle HCI_CO=
MMAND_PKT only.
Please let us know if you have any suggestion to solve this problem.

Thanks,
Bing

^ permalink raw reply

* Re: [PATCH 1/2] android: Add skeleton of BlueZ Android daemon
From: Lukasz Rymanowski @ 2013-09-23 19:28 UTC (permalink / raw)
  To: Frederic Danis; +Cc: Marcel Holtmann, linux-bluetooth
In-Reply-To: <52400F2B.9010501@linux.intel.com>

Hi Marcel,

On Mon, Sep 23, 2013 at 11:51 AM, Frederic Danis
<frederic.danis@linux.intel.com> wrote:
> Hello Marcel,
>
> On 21/09/2013 19:14, Marcel Holtmann wrote:
>>
>> Hi Fred,
>>
>>> Define local mapping to glib path, otherwise this has to be inside
>>> central
>>> place in the build repository.
>>>
>>> Retrieve Bluetooth version from configure.ac.
>>> ---
>>> .gitignore         |    2 +
>>> Android.mk         |    9 ++++
>>> Makefile.am        |    1 +
>>> Makefile.android   |    7 ++++
>>> android/Android.mk |   24 +++++++++++
>>> android/main.c     |  119
>>> ++++++++++++++++++++++++++++++++++++++++++++++++++++
>>> configure.ac       |    5 +++
>>> 7 files changed, 167 insertions(+)
>>> create mode 100644 Android.mk
>>> create mode 100644 Makefile.android
>>> create mode 100644 android/Android.mk
>>> create mode 100644 android/main.c
>>
>>
>> lets split this out a little bit. Code additions should not be intermixed
>> with additions to the build system and especially configure options.
>>
>> I rather not have a top-level Android.mk. It should be enough to provide
>> an android/Android.mk.

 BTW, do you expect to have only one Android.mk for the whole project or
this is OK for you to have smaller Android.mk in different subfolders like
/src/shared etc. Both ways are valid.

Br
Lukasz

^ permalink raw reply

* Re: [PATCH 1/2] android: Add skeleton of BlueZ Android daemon
From: Lukasz Rymanowski @ 2013-09-23 19:26 UTC (permalink / raw)
  To: Frederic Danis; +Cc: Marcel Holtmann, linux-bluetooth
In-Reply-To: <52400F2B.9010501@linux.intel.com>

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

Hi Marcel


On Mon, Sep 23, 2013 at 11:51 AM, Frederic Danis <
frederic.danis@linux.intel.com> wrote:

> Hello Marcel,
>
> On 21/09/2013 19:14, Marcel Holtmann wrote:
>
>> Hi Fred,
>>
>>  Define local mapping to glib path, otherwise this has to be inside
>>> central
>>> place in the build repository.
>>>
>>> Retrieve Bluetooth version from configure.ac.
>>> ---
>>> .gitignore         |    2 +
>>> Android.mk         |    9 ++++
>>> Makefile.am        |    1 +
>>> Makefile.android   |    7 ++++
>>> android/Android.mk |   24 +++++++++++
>>> android/main.c     |  119 ++++++++++++++++++++++++++++++**
>>> ++++++++++++++++++++++
>>> configure.ac       |    5 +++
>>> 7 files changed, 167 insertions(+)
>>> create mode 100644 Android.mk
>>> create mode 100644 Makefile.android
>>> create mode 100644 android/Android.mk
>>> create mode 100644 android/main.c
>>>
>>
>> lets split this out a little bit. Code additions should not be intermixed
>> with additions to the build system and especially configure options.
>>
>> I rather not have a top-level Android.mk. It should be enough to provide
>> an android/Android.mk.
>>
>> BTW, do you expect to have only one Android.mk for the whole project or
this is OK for you to have smaller Android.mk in different subfolders like
/src/shared etc. Both ways are valid.

BR
Lukasz

[-- Attachment #2: Type: text/html, Size: 2206 bytes --]

^ permalink raw reply

* RE: [PATCH v5 1/2] Bluetooth: btmrvl: add setup handler
From: Bing Zhao @ 2013-09-23 19:18 UTC (permalink / raw)
  To: Marcel Holtmann
  Cc: linux-bluetooth@vger.kernel.org, Gustavo Padovan, Johan Hedberg,
	linux-wireless@vger.kernel.org, Mike Frysinger, Hyuckjoo Lee,
	Amitkumar Karwar
In-Reply-To: <18678858-E711-43E5-AFE6-E637D1CECFFB@holtmann.org>

Hi Marcel,

> > -	btmrvl_send_module_cfg_cmd(priv, MODULE_BRINGUP_REQ);
> > +	hdev->setup =3D btmrvl_setup;
>=20
> just to make sure you guys understand how ->setup() works. It is only cal=
led once. Bringing the
> adapter down and up again does not call ->setup() a second time. So do yo=
u guys need this setup_done
> variable and if so, then you need to be a bit more verbose and help me un=
derstand why.

It's observed that sometimes the setup handler is called twice when Bluetoo=
th daemon is running in background. We will rebase to latest commit on blue=
tooth-next tree and test again. If the issue is gone with the latest code i=
n -next tree we will remove the setup_done flag.

Thanks,
Bing

^ permalink raw reply

* [PATCH 08/12] bluetooth: Remove extern from function prototypes
From: Joe Perches @ 2013-09-23 18:37 UTC (permalink / raw)
  To: netdev
  Cc: David S. Miller, linux-kernel, Marcel Holtmann, Gustavo Padovan,
	Johan Hedberg, linux-bluetooth
In-Reply-To: <445209f8885ccd8234fa787c30d63e63fc7917d7.1379961014.git.joe@perches.com>

There are a mix of function prototypes with and without extern
in the kernel sources.  Standardize on not using extern for
function prototypes.

Function prototypes don't need to be written with extern.
extern is assumed by the compiler.  Its use is as unnecessary as
using auto to declare automatic/local variables in a block.

Signed-off-by: Joe Perches <joe@perches.com>
---
 include/net/bluetooth/bluetooth.h | 16 ++++++++--------
 include/net/bluetooth/hci_core.h  | 23 +++++++++++------------
 include/net/bluetooth/rfcomm.h    |  4 ++--
 3 files changed, 21 insertions(+), 22 deletions(-)

diff --git a/include/net/bluetooth/bluetooth.h b/include/net/bluetooth/bluetooth.h
index 10d43d8..13d6c39 100644
--- a/include/net/bluetooth/bluetooth.h
+++ b/include/net/bluetooth/bluetooth.h
@@ -331,16 +331,16 @@ out:
 
 int bt_to_errno(__u16 code);
 
-extern int hci_sock_init(void);
-extern void hci_sock_cleanup(void);
+int hci_sock_init(void);
+void hci_sock_cleanup(void);
 
-extern int bt_sysfs_init(void);
-extern void bt_sysfs_cleanup(void);
+int bt_sysfs_init(void);
+void bt_sysfs_cleanup(void);
 
-extern int  bt_procfs_init(struct net *net, const char *name,
-			   struct bt_sock_list* sk_list,
-			   int (* seq_show)(struct seq_file *, void *));
-extern void bt_procfs_cleanup(struct net *net, const char *name);
+int bt_procfs_init(struct net *net, const char *name,
+		   struct bt_sock_list *sk_list,
+		   int (*seq_show)(struct seq_file *, void *));
+void bt_procfs_cleanup(struct net *net, const char *name);
 
 extern struct dentry *bt_debugfs;
 
diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h
index 3ede820..5769061 100644
--- a/include/net/bluetooth/hci_core.h
+++ b/include/net/bluetooth/hci_core.h
@@ -367,18 +367,17 @@ extern rwlock_t hci_dev_list_lock;
 extern rwlock_t hci_cb_list_lock;
 
 /* ----- HCI interface to upper protocols ----- */
-extern int l2cap_connect_ind(struct hci_dev *hdev, bdaddr_t *bdaddr);
-extern void l2cap_connect_cfm(struct hci_conn *hcon, u8 status);
-extern int l2cap_disconn_ind(struct hci_conn *hcon);
-extern void l2cap_disconn_cfm(struct hci_conn *hcon, u8 reason);
-extern int l2cap_security_cfm(struct hci_conn *hcon, u8 status, u8 encrypt);
-extern int l2cap_recv_acldata(struct hci_conn *hcon, struct sk_buff *skb,
-			      u16 flags);
-
-extern int sco_connect_ind(struct hci_dev *hdev, bdaddr_t *bdaddr, __u8 *flags);
-extern void sco_connect_cfm(struct hci_conn *hcon, __u8 status);
-extern void sco_disconn_cfm(struct hci_conn *hcon, __u8 reason);
-extern int sco_recv_scodata(struct hci_conn *hcon, struct sk_buff *skb);
+int l2cap_connect_ind(struct hci_dev *hdev, bdaddr_t *bdaddr);
+void l2cap_connect_cfm(struct hci_conn *hcon, u8 status);
+int l2cap_disconn_ind(struct hci_conn *hcon);
+void l2cap_disconn_cfm(struct hci_conn *hcon, u8 reason);
+int l2cap_security_cfm(struct hci_conn *hcon, u8 status, u8 encrypt);
+int l2cap_recv_acldata(struct hci_conn *hcon, struct sk_buff *skb, u16 flags);
+
+int sco_connect_ind(struct hci_dev *hdev, bdaddr_t *bdaddr, __u8 *flags);
+void sco_connect_cfm(struct hci_conn *hcon, __u8 status);
+void sco_disconn_cfm(struct hci_conn *hcon, __u8 reason);
+int sco_recv_scodata(struct hci_conn *hcon, struct sk_buff *skb);
 
 /* ----- Inquiry cache ----- */
 #define INQUIRY_CACHE_AGE_MAX   (HZ*30)   /* 30 seconds */
diff --git a/include/net/bluetooth/rfcomm.h b/include/net/bluetooth/rfcomm.h
index 7afd419..b7f43e7 100644
--- a/include/net/bluetooth/rfcomm.h
+++ b/include/net/bluetooth/rfcomm.h
@@ -256,8 +256,8 @@ static inline void rfcomm_dlc_put(struct rfcomm_dlc *d)
 		rfcomm_dlc_free(d);
 }
 
-extern void __rfcomm_dlc_throttle(struct rfcomm_dlc *d);
-extern void __rfcomm_dlc_unthrottle(struct rfcomm_dlc *d);
+void __rfcomm_dlc_throttle(struct rfcomm_dlc *d);
+void __rfcomm_dlc_unthrottle(struct rfcomm_dlc *d);
 
 static inline void rfcomm_dlc_throttle(struct rfcomm_dlc *d)
 {
-- 
1.8.1.2.459.gbcd45b4.dirty

^ permalink raw reply related

* Re: [PATCH 1/2] android: Add skeleton of BlueZ Android daemon
From: Frederic Danis @ 2013-09-23  9:51 UTC (permalink / raw)
  To: Marcel Holtmann; +Cc: linux-bluetooth
In-Reply-To: <226042C8-264A-469E-8D6A-F41141DC0552@holtmann.org>

Hello Marcel,

On 21/09/2013 19:14, Marcel Holtmann wrote:
> Hi Fred,
>
>> Define local mapping to glib path, otherwise this has to be inside central
>> place in the build repository.
>>
>> Retrieve Bluetooth version from configure.ac.
>> ---
>> .gitignore         |    2 +
>> Android.mk         |    9 ++++
>> Makefile.am        |    1 +
>> Makefile.android   |    7 ++++
>> android/Android.mk |   24 +++++++++++
>> android/main.c     |  119 ++++++++++++++++++++++++++++++++++++++++++++++++++++
>> configure.ac       |    5 +++
>> 7 files changed, 167 insertions(+)
>> create mode 100644 Android.mk
>> create mode 100644 Makefile.android
>> create mode 100644 android/Android.mk
>> create mode 100644 android/main.c
>
> lets split this out a little bit. Code additions should not be intermixed with additions to the build system and especially configure options.
>
> I rather not have a top-level Android.mk. It should be enough to provide an android/Android.mk.
>
>> diff --git a/.gitignore b/.gitignore
>> index 8a25a3e..331a18b 100644
>> --- a/.gitignore
>> +++ b/.gitignore
>> @@ -98,3 +98,5 @@ unit/test-gobex-packet
>> unit/test-gobex-transfer
>> unit/test-*.log
>> unit/test-*.trs
>> +
>> +android/bluezd
>
> If we keep using prefix btd_ for certain set of functions, then it might be better if the daemon is build as android/bluetoothd or android/btd.

OK, I will rename it android/bluetoothd

>
> <snip>
>
>> +
>> +#ifdef HAVE_CONFIG_H
>> +#include <config.h>
>> +#endif
>> +
>> +#include <signal.h>
>> +#include <stdint.h>
>> +#include <stdio.h>
>> +#include <stdlib.h>
>> +#include <string.h>
>> +
>> +#include <glib.h>
>> +
>> +#include "hcid.h"
>
> I do not think we need to include hcid.h here. If we for some reason still do, then please try to cleanup that first.

OK, I will remove it

>
>> +
>> +#define SHUTDOWN_GRACE_SECONDS 10
>> +
>> +static GMainLoop *event_loop;
>> +
>> +void btd_exit(void)
>> +{
>> +	g_main_loop_quit(event_loop);
>> +}
>> +
>> +static gboolean quit_eventloop(gpointer user_data)
>> +{
>> +	btd_exit();
>> +	return FALSE;
>> +}
>> +
>> +static void signal_handler(int sig)
>> +{
>> +	static unsigned int __terminated = 0;
>
> Make this static volatile bool __terminated = false instead. Remember that you are actually using signals here and not signalfd.

OK, I will do this.

>
>> +
>> +	switch (sig) {
>> +	case SIGINT:
>> +	case SIGTERM:
>> +		if (__terminated == 0) {
>> +			g_timeout_add_seconds(SHUTDOWN_GRACE_SECONDS,
>> +							quit_eventloop, NULL);
>> +		}
>> +
>> +		__terminated = 1;
>> +		break;
>> +	}
>> +}
>> +
>> +static gboolean option_detach = TRUE;
>> +static gboolean option_version = FALSE;
>> +
>> +static GOptionEntry options[] = {
>> +	{ "nodetach", 'n', G_OPTION_FLAG_REVERSE,
>> +				G_OPTION_ARG_NONE, &option_detach,
>> +				"Run with logging in foreground", NULL },
>
> Do we need this option at all. I think we should always run in foreground and the system manager need to make sure we are spawned.

I think this is useful when debugging in conjonction with debug option 
and logging to console.

>
>> +	{ "version", 'v', 0, G_OPTION_ARG_NONE, &option_version,
>> +				"Show version information and exit", NULL },
>> +	{ NULL }
>> +};
>> +
>> +int main(int argc, char *argv[])
>> +{
>> +	GOptionContext *context;
>> +	GError *err = NULL;
>> +	struct sigaction sa;
>> +
>> +	context = g_option_context_new(NULL);
>> +	g_option_context_add_main_entries(context, options, NULL);
>> +
>> +	if (g_option_context_parse(context, &argc, &argv, &err) == FALSE) {
>> +		if (err != NULL) {
>> +			g_printerr("%s\n", err->message);
>> +			g_error_free(err);
>> +		} else
>> +			g_printerr("An unknown error occurred\n");
>> +		exit(1);
>> +	}
>> +
>> +	g_option_context_free(context);
>> +
>> +	if (option_version == TRUE) {
>> +		printf("%s\n", VERSION);
>> +		exit(0);
>
> I prefer if we start using return EXIT_SUCCESS and in error case EXIT_FAILURE.

OK, I will do this.

>
>> +	}
>> +
>> +	event_loop = g_main_loop_new(NULL, FALSE);
>> +
>> +	memset(&sa, 0, sizeof(sa));
>> +	sa.sa_handler = signal_handler;
>> +	sigaction(SIGINT, &sa, NULL);
>> +	sigaction(SIGTERM, &sa, NULL);
>> +
>> +	g_main_loop_run(event_loop);
>> +
>> +	g_main_loop_unref(event_loop);
>> +
>> +	return 0;
>> +}
>> diff --git a/configure.ac b/configure.ac
>> index 41c2935..3b7a5d9 100644
>> --- a/configure.ac
>> +++ b/configure.ac
>> @@ -242,4 +242,9 @@ AC_DEFINE_UNQUOTED(CONFIGDIR, "${configdir}",
>> 			[Directory for the configuration files])
>> AC_SUBST(CONFIGDIR, "${configdir}")
>>
>> +AC_ARG_ENABLE(android-daemon, AC_HELP_STRING([--enable-android-daemon],
>> +			[enable BlueZ Android daemon]),
>> +					[android_daemon=${enableval}])
>> +AM_CONDITIONAL(ANDROID_DAEMON, test "${android_daemon}" = "yes")
>> +
>
> This needs to be a separate patch. And it should just say --enable-android.
>
> In addition it needs to be added to bootstrap-configure and distcheck handling.

OK

Regards

Fred

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

^ permalink raw reply

* [PATCH v2 4/4] obexd: Clarify the folder property of PushMessage
From: Christian Fetzer @ 2013-09-23  9:24 UTC (permalink / raw)
  To: linux-bluetooth
In-Reply-To: <1379928269-14651-1-git-send-email-christian.fetzer@oss.bmw-carit.de>

From: Christian Fetzer <christian.fetzer@bmw-carit.de>

The folder property of PushMessages does not accept path information,
it allows only to request the messages to be added to a subfolder of the
current folder.
---
 doc/obex-api.txt | 5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)

diff --git a/doc/obex-api.txt b/doc/obex-api.txt
index 28343f6..eda7cb9 100644
--- a/doc/obex-api.txt
+++ b/doc/obex-api.txt
@@ -638,8 +638,9 @@ Methods		void SetFolder(string name)
 			Transfer a message (in bMessage format) to the
 			remote device.
 
-			The message is transferred either to the given folder,
-			or to the current folder if folder is omitted.
+			The message is transferred either to the given
+			subfolder of the current folder, or to the current
+			folder if folder is empty.
 
 			Possible args: Transparent, Retry, Charset
 
-- 
1.8.3.4


^ permalink raw reply related

* [PATCH v2 3/4] obexd: Clarify the folder property of ListMessages
From: Christian Fetzer @ 2013-09-23  9:24 UTC (permalink / raw)
  To: linux-bluetooth
In-Reply-To: <1379928269-14651-1-git-send-email-christian.fetzer@oss.bmw-carit.de>

From: Christian Fetzer <christian.fetzer@bmw-carit.de>

The folder property of ListMessages does not accept path information,
it allows only to request the messages of a subfolder of the current
folder.
---
 doc/obex-api.txt | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/doc/obex-api.txt b/doc/obex-api.txt
index 0a8e632..28343f6 100644
--- a/doc/obex-api.txt
+++ b/doc/obex-api.txt
@@ -538,7 +538,8 @@ Methods		void SetFolder(string name)
 		array{object, dict} ListMessages(string folder, dict filter)
 
 			Returns an array containing the messages found in the
-			given folder.
+			given subfolder of the current folder, or in the
+			current folder if folder is empty.
 
 			Possible Filters: Offset, MaxCount, SubjectLength, Fields,
 			Type, PeriodStart, PeriodEnd, Status, Recipient, Sender,
-- 
1.8.3.4


^ permalink raw reply related

* [PATCH v2 2/4] obexd: Fix setting message folder for relative folder in ListMessages
From: Christian Fetzer @ 2013-09-23  9:24 UTC (permalink / raw)
  To: linux-bluetooth
In-Reply-To: <1379928269-14651-1-git-send-email-christian.fetzer@oss.bmw-carit.de>

From: Christian Fetzer <christian.fetzer@bmw-carit.de>

The method ListMessages allows to specify a relative subfolder.
This subfolder needs to be added to the current path when registering
a new message interface.
---
 obexd/client/map.c | 18 ++++++++++++++++--
 1 file changed, 16 insertions(+), 2 deletions(-)

diff --git a/obexd/client/map.c b/obexd/client/map.c
index 131b140..45b4ef1 100644
--- a/obexd/client/map.c
+++ b/obexd/client/map.c
@@ -103,6 +103,7 @@ struct map_data {
 struct pending_request {
 	struct map_data *map;
 	DBusMessage *msg;
+	char *folder;
 };
 
 #define MAP_MSG_FLAG_PRIORITY	0x01
@@ -154,6 +155,7 @@ static void pending_request_free(struct pending_request *p)
 {
 	dbus_message_unref(p->msg);
 
+	g_free(p->folder);
 	g_free(p);
 }
 
@@ -1098,8 +1100,7 @@ static void msg_element(GMarkupParseContext *ctxt, const char *element,
 
 	msg = g_hash_table_lookup(data->messages, values[i]);
 	if (msg == NULL) {
-		msg = map_msg_create(data, values[i],
-					obc_session_get_folder(data->session));
+		msg = map_msg_create(data, values[i], parser->request->folder);
 		if (msg == NULL)
 			return;
 	}
@@ -1195,6 +1196,17 @@ done:
 	pending_request_free(request);
 }
 
+static char *get_absolute_folder(const char *root, const char *subfolder)
+{
+	if (!subfolder || strlen(subfolder) == 0)
+		return g_strdup(root);
+	else
+		if (g_str_has_suffix(root, "/"))
+			return g_strconcat(root, subfolder, NULL);
+		else
+			return g_strconcat(root, "/", subfolder, NULL);
+}
+
 static DBusMessage *get_message_listing(struct map_data *map,
 							DBusMessage *message,
 							const char *folder,
@@ -1214,6 +1226,8 @@ static DBusMessage *get_message_listing(struct map_data *map,
 	obc_transfer_set_apparam(transfer, apparam);
 
 	request = pending_request_new(map, message);
+	request->folder = get_absolute_folder(obc_session_get_folder(
+							map->session), folder);
 
 	if (!obc_session_queue(map->session, transfer, message_listing_cb,
 							request, &err)) {
-- 
1.8.3.4


^ permalink raw reply related

* [PATCH v2 1/4] obexd: Add folder property to map_msg_create
From: Christian Fetzer @ 2013-09-23  9:24 UTC (permalink / raw)
  To: linux-bluetooth
In-Reply-To: <1379928269-14651-1-git-send-email-christian.fetzer@oss.bmw-carit.de>

From: Christian Fetzer <christian.fetzer@bmw-carit.de>

Message interfaces are not necessarily created for the current folder,
therefore the folder needs to be specified in a parameter.

For example, messages can be created for sub folders when using the folder
parameter in ListMessages.
---
 obexd/client/map.c | 8 +++++---
 1 file changed, 5 insertions(+), 3 deletions(-)

diff --git a/obexd/client/map.c b/obexd/client/map.c
index 9fe872d..131b140 100644
--- a/obexd/client/map.c
+++ b/obexd/client/map.c
@@ -809,7 +809,8 @@ static const GDBusPropertyTable map_msg_properties[] = {
 	{ }
 };
 
-static struct map_msg *map_msg_create(struct map_data *data, const char *handle)
+static struct map_msg *map_msg_create(struct map_data *data, const char *handle,
+							const char *folder)
 {
 	struct map_msg *msg;
 
@@ -818,7 +819,7 @@ static struct map_msg *map_msg_create(struct map_data *data, const char *handle)
 	msg->path = g_strdup_printf("%s/message%s",
 					obc_session_get_path(data->session),
 					handle);
-	msg->folder = g_strdup(obc_session_get_folder(data->session));
+	msg->folder = g_strdup(folder);
 
 	if (!g_dbus_register_interface(conn, msg->path, MAP_MSG_INTERFACE,
 						map_msg_methods, NULL,
@@ -1097,7 +1098,8 @@ static void msg_element(GMarkupParseContext *ctxt, const char *element,
 
 	msg = g_hash_table_lookup(data->messages, values[i]);
 	if (msg == NULL) {
-		msg = map_msg_create(data, values[i]);
+		msg = map_msg_create(data, values[i],
+					obc_session_get_folder(data->session));
 		if (msg == NULL)
 			return;
 	}
-- 
1.8.3.4


^ permalink raw reply related

* [PATCH v2 0/4] obexd: Fix setting message folder
From: Christian Fetzer @ 2013-09-23  9:24 UTC (permalink / raw)
  To: linux-bluetooth

From: Christian Fetzer <christian.fetzer@bmw-carit.de>

This fixes an issue that the folder property for messages was set incorrectly
when ListMessages got called with a subfolder parameter.

Calling ListMessages within /telecom/msg for the subfolder inbox would set the
folder property to /telecom/msg instead of /telecom/msg/inbox.

The patchset therefore changes map_msg_create to not set the folder property
to the current folder, but to a folder given as parameter. This change will be
needed as well for new message notifications (that can indicate new messages
for any folder).

In addition I've updated the documentation to clarify that the folder property
for ListMessages and PushMessage can be used only for a subfolder of the
current folder. It's not possible to specify an absolute or relative path.

--
v2: Store folder in MAP pending request

Christian Fetzer (4):
  obexd: Add folder property to map_msg_create
  obexd: Fix setting message folder for relative folder in ListMessages
  obexd: Clarify the folder property of ListMessages
  obexd: Clarify the folder property of PushMessage

 doc/obex-api.txt   |  8 +++++---
 obexd/client/map.c | 22 +++++++++++++++++++---
 2 files changed, 24 insertions(+), 6 deletions(-)

-- 
1.8.3.4


^ permalink raw reply

* Problems with too many connections
From: Markus Roppelt @ 2013-09-23  9:04 UTC (permalink / raw)
  To: linux-bluetooth

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

Hi,

I want to write an application which repeats the following procedure
for several (100+) bluetooth (low energy) devices:

1. connect
2. read register values
3. disconnect

Therefore I modified the source code from /attrib/interactive.c.  For
testing purposes I am only looping  over one device. See attached
source code.

The code works fine. It connects, reads the values and disconnects.
However, after 1020 repetitions, the following error occurs:
(process:10205): GLib-WARNING **: poll(2) failed due to: Invalid argument.

I think the problem has to do with some sockets / file descriptors not
being closed properly.

Can someone help me to get this fixed?

Thank you
 Markus

[-- Attachment #2: loop.c --]
[-- Type: text/x-csrc, Size: 22672 bytes --]

/*
 *
 *  BlueZ - Bluetooth protocol stack for Linux
 *
 *  Copyright (C) 2011  Nokia Corporation
 *
 *
 *  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 <string.h>
#include <stdlib.h>
#include <stdarg.h>
#include <errno.h>
#include <stdio.h>
#include <unistd.h>
#include <signal.h>
#include <sys/signalfd.h>
#include <glib.h>

#include <readline/readline.h>
#include <readline/history.h>

#include "lib/uuid.h"
#include <btio/btio.h>
#include "att.h"
#include "gattrib.h"
#include "gatt.h"
#include "gatttool.h"
#include "client/display.h"

static GIOChannel *iochannel = NULL;
static GAttrib *attrib = NULL;
static GMainLoop *event_loop;
static GString *prompt;

static char *opt_src = NULL;
static char *opt_dst = NULL;
static char *opt_dst_type = NULL;
static char *opt_sec_level = NULL;
static int opt_psm = 0;
static int opt_mtu = 0;
static int start;
static int end;

static gboolean requested_read;
static gboolean done_read;

static void cmd_help(int argcp, char **argvp);

static enum state {
	STATE_DISCONNECTED,
	STATE_CONNECTING,
	STATE_CONNECTED
} conn_state;

static int loop_counter;

#define error(fmt, arg...) \
	rl_printf(COLOR_RED "Error: " COLOR_OFF fmt, ## arg)

#define failed(fmt, arg...) \
	rl_printf(COLOR_RED "Command Failed: " COLOR_OFF fmt, ## arg)

static char *get_prompt(void)
{
	if (conn_state == STATE_CONNECTED)
		g_string_assign(prompt, COLOR_BLUE);
	else
		g_string_assign(prompt, "");

	if (opt_dst)
		g_string_append_printf(prompt, "[%17s]", opt_dst);
	else
		g_string_append_printf(prompt, "[%17s]", "");

	if (conn_state == STATE_CONNECTED)
		g_string_append(prompt, COLOR_OFF);

	if (opt_psm)
		g_string_append(prompt, "[BR]");
	else
		g_string_append(prompt, "[LE]");

	g_string_append(prompt, "> ");

	return prompt->str;
}


static void set_state(enum state st)
{
	conn_state = st;
	rl_set_prompt(get_prompt());
}

static void events_handler(const uint8_t *pdu, uint16_t len, gpointer user_data)
{
	uint8_t *opdu;
	uint16_t handle, i, olen;
	size_t plen;
	GString *s;

	handle = att_get_u16(&pdu[1]);

	switch (pdu[0]) {
	case ATT_OP_HANDLE_NOTIFY:
		s = g_string_new(NULL);
		g_string_printf(s, "Notification handle = 0x%04x value: ",
									handle);
		break;
	case ATT_OP_HANDLE_IND:
		s = g_string_new(NULL);
		g_string_printf(s, "Indication   handle = 0x%04x value: ",
									handle);
		break;
	default:
		error("Invalid opcode\n");
		return;
	}

	for (i = 3; i < len; i++)
		g_string_append_printf(s, "%02x ", pdu[i]);

	rl_printf("%s\n", s->str);
	g_string_free(s, TRUE);

	if (pdu[0] == ATT_OP_HANDLE_NOTIFY)
		return;

	opdu = g_attrib_get_buffer(attrib, &plen);
	olen = enc_confirmation(opdu, plen);

	if (olen > 0)
		g_attrib_send(attrib, 0, opdu, olen, NULL, NULL, NULL);
}

static void connect_cb(GIOChannel *io, GError *err, gpointer user_data)
{
	if (err) {
		set_state(STATE_DISCONNECTED);
		error("%s\n", err->message);
		return;
	}

	attrib = g_attrib_new(iochannel);
	g_attrib_register(attrib, ATT_OP_HANDLE_NOTIFY, GATTRIB_ALL_HANDLES,
						events_handler, attrib, NULL);
	g_attrib_register(attrib, ATT_OP_HANDLE_IND, GATTRIB_ALL_HANDLES,
						events_handler, attrib, NULL);
	set_state(STATE_CONNECTED);
	rl_printf("Connection successful\n");
}

static void disconnect_io()
{
	if (conn_state == STATE_DISCONNECTED)
		return;

	g_attrib_unref(attrib);
	attrib = NULL;
	opt_mtu = 0;

	g_io_channel_shutdown(iochannel, FALSE, NULL);
	g_io_channel_unref(iochannel);
	iochannel = NULL;

	set_state(STATE_DISCONNECTED);
}

static void primary_all_cb(GSList *services, guint8 status, gpointer user_data)
{
	GSList *l;

	if (status) {
		error("Discover all primary services failed: %s\n",
						att_ecode2str(status));
		return;
	}

	if (services == NULL) {
		error("No primary service found\n");
		return;
	}

	for (l = services; l; l = l->next) {
		struct gatt_primary *prim = l->data;
		rl_printf("attr handle: 0x%04x, end grp handle: 0x%04x uuid: %s\n",
				prim->range.start, prim->range.end, prim->uuid);
	}
}

static void primary_by_uuid_cb(GSList *ranges, guint8 status,
							gpointer user_data)
{
	GSList *l;

	if (status) {
		error("Discover primary services by UUID failed: %s\n",
							att_ecode2str(status));
		return;
	}

	if (ranges == NULL) {
		error("No service UUID found\n");
		return;
	}

	for (l = ranges; l; l = l->next) {
		struct att_range *range = l->data;
		rl_printf("Starting handle: 0x%04x Ending handle: 0x%04x\n",
						range->start, range->end);
	}
}

static void included_cb(GSList *includes, guint8 status, gpointer user_data)
{
	GSList *l;

	if (status) {
		error("Find included services failed: %s\n",
							att_ecode2str(status));
		return;
	}

	if (includes == NULL) {
		rl_printf("No included services found for this range\n");
		return;
	}

	for (l = includes; l; l = l->next) {
		struct gatt_included *incl = l->data;
		rl_printf("handle: 0x%04x, start handle: 0x%04x, "
					"end handle: 0x%04x uuid: %s\n",
					incl->handle, incl->range.start,
					incl->range.end, incl->uuid);
	}
}

static void char_cb(GSList *characteristics, guint8 status, gpointer user_data)
{
	GSList *l;

	if (status) {
		error("Discover all characteristics failed: %s\n",
							att_ecode2str(status));
		return;
	}

	for (l = characteristics; l; l = l->next) {
		struct gatt_char *chars = l->data;

		rl_printf("handle: 0x%04x, char properties: 0x%02x, char value "
				"handle: 0x%04x, uuid: %s\n", chars->handle,
				chars->properties, chars->value_handle,
				chars->uuid);
	}
}

static void char_desc_cb(guint8 status, const guint8 *pdu, guint16 plen,
							gpointer user_data)
{
	struct att_data_list *list;
	guint8 format;
	uint16_t handle = 0xffff;
	int i;

	if (status != 0) {
		rl_printf("Discover descriptors finished: %s\n",
						att_ecode2str(status));
		return;
	}

	list = dec_find_info_resp(pdu, plen, &format);
	if (list == NULL)
		return;

	for (i = 0; i < list->num; i++) {
		char uuidstr[MAX_LEN_UUID_STR];
		uint8_t *value;
		bt_uuid_t uuid;

		value = list->data[i];
		handle = att_get_u16(value);

		if (format == 0x01)
			uuid = att_get_uuid16(&value[2]);
		else
			uuid = att_get_uuid128(&value[2]);

		bt_uuid_to_string(&uuid, uuidstr, MAX_LEN_UUID_STR);
		rl_printf("handle: 0x%04x, uuid: %s\n", handle, uuidstr);
	}

	att_data_list_free(list);

	if (handle != 0xffff && handle < end)
		gatt_discover_char_desc(attrib, handle + 1, end, char_desc_cb,
									NULL);
}

static void char_read_cb(guint8 status, const guint8 *pdu, guint16 plen,
							gpointer user_data)
{
	uint8_t value[plen];
	ssize_t vlen;
	int i;
	GString *s;

	if (status != 0) {
		error("Characteristic value/descriptor read failed: %s\n",
							att_ecode2str(status));
		return;
	}

	vlen = dec_read_resp(pdu, plen, value, sizeof(value));
	if (vlen < 0) {
		error("Protocol error\n");
		return;
	}

	s = g_string_new("Characteristic value/descriptor: ");
	for (i = 0; i < vlen; i++)
		g_string_append_printf(s, "%02x ", value[i]);

	rl_printf("%s\n", s->str);
	g_string_free(s, TRUE);
}

static void char_read_by_uuid_cb(guint8 status, const guint8 *pdu,
					guint16 plen, gpointer user_data)
{
	struct att_data_list *list;
	int i;
	GString *s;

	if (status != 0) {
		error("Read characteristics by UUID failed: %s\n",
							att_ecode2str(status));
		return;
	}

	list = dec_read_by_type_resp(pdu, plen);
	if (list == NULL)
		return;

	s = g_string_new(NULL);
	for (i = 0; i < list->num; i++) {
		uint8_t *value = list->data[i];
		int j;

		g_string_printf(s, "handle: 0x%04x \t value: ",
							att_get_u16(value));
		value += 2;
		for (j = 0; j < list->len - 2; j++, value++)
			g_string_append_printf(s, "%02x ", *value);

		rl_printf("%s\n", s->str);
	}

	att_data_list_free(list);
	g_string_free(s, TRUE);
	
	done_read = 1;
}

static void cmd_exit(int argcp, char **argvp)
{
	rl_callback_handler_remove();
	g_main_loop_quit(event_loop);
}

static gboolean channel_watcher(GIOChannel *chan, GIOCondition cond,
				gpointer user_data)
{
	disconnect_io();

	return FALSE;
}

static void cmd_connect(int argcp, char **argvp)
{
	GError *gerr = NULL;

	if (conn_state != STATE_DISCONNECTED)
		return;

	if (argcp > 1) {
		g_free(opt_dst);
		opt_dst = g_strdup(argvp[1]);

		g_free(opt_dst_type);
		if (argcp > 2)
			opt_dst_type = g_strdup(argvp[2]);
		else
			opt_dst_type = g_strdup("public");
	}

	if (opt_dst == NULL) {
		error("Remote Bluetooth address required\n");
		return;
	}

	rl_printf("Attempting to connect to %s\n", opt_dst);
	set_state(STATE_CONNECTING);
	iochannel = gatt_connect(opt_src, opt_dst, opt_dst_type, opt_sec_level,
					opt_psm, opt_mtu, connect_cb, &gerr);
	if (iochannel == NULL) {
		set_state(STATE_DISCONNECTED);
		error("%s\n", gerr->message);
		g_error_free(gerr);
	} else
		g_io_add_watch(iochannel, G_IO_HUP, channel_watcher, NULL);
}

static void cmd_disconnect(int argcp, char **argvp)
{
	disconnect_io();
}

static void cmd_primary(int argcp, char **argvp)
{
	bt_uuid_t uuid;

	if (conn_state != STATE_CONNECTED) {
		failed("Disconnected\n");
		return;
	}

	if (argcp == 1) {
		gatt_discover_primary(attrib, NULL, primary_all_cb, NULL);
		return;
	}

	if (bt_string_to_uuid(&uuid, argvp[1]) < 0) {
		error("Invalid UUID\n");
		return;
	}

	gatt_discover_primary(attrib, &uuid, primary_by_uuid_cb, NULL);
}

static int strtohandle(const char *src)
{
	char *e;
	int dst;

	errno = 0;
	dst = strtoll(src, &e, 16);
	if (errno != 0 || *e != '\0')
		return -EINVAL;

	return dst;
}

static void cmd_included(int argcp, char **argvp)
{
	int start = 0x0001;
	int end = 0xffff;

	if (conn_state != STATE_CONNECTED) {
		failed("Disconnected\n");
		return;
	}

	if (argcp > 1) {
		start = strtohandle(argvp[1]);
		if (start < 0) {
			error("Invalid start handle: %s\n", argvp[1]);
			return;
		}
		end = start;
	}

	if (argcp > 2) {
		end = strtohandle(argvp[2]);
		if (end < 0) {
			error("Invalid end handle: %s\n", argvp[2]);
			return;
		}
	}

	gatt_find_included(attrib, start, end, included_cb, NULL);
}

static void cmd_char(int argcp, char **argvp)
{
	int start = 0x0001;
	int end = 0xffff;

	if (conn_state != STATE_CONNECTED) {
		failed("Disconnected\n");
		return;
	}

	if (argcp > 1) {
		start = strtohandle(argvp[1]);
		if (start < 0) {
			error("Invalid start handle: %s\n", argvp[1]);
			return;
		}
	}

	if (argcp > 2) {
		end = strtohandle(argvp[2]);
		if (end < 0) {
			error("Invalid end handle: %s\n", argvp[2]);
			return;
		}
	}

	if (argcp > 3) {
		bt_uuid_t uuid;

		if (bt_string_to_uuid(&uuid, argvp[3]) < 0) {
			error("Invalid UUID\n");
			return;
		}

		gatt_discover_char(attrib, start, end, &uuid, char_cb, NULL);
		return;
	}

	gatt_discover_char(attrib, start, end, NULL, char_cb, NULL);
}

static void cmd_char_desc(int argcp, char **argvp)
{
	if (conn_state != STATE_CONNECTED) {
		failed("Disconnected\n");
		return;
	}

	if (argcp > 1) {
		start = strtohandle(argvp[1]);
		if (start < 0) {
			error("Invalid start handle: %s\n", argvp[1]);
			return;
		}
	} else
		start = 0x0001;

	if (argcp > 2) {
		end = strtohandle(argvp[2]);
		if (end < 0) {
			error("Invalid end handle: %s\n", argvp[2]);
			return;
		}
	} else
		end = 0xffff;

	gatt_discover_char_desc(attrib, start, end, char_desc_cb, NULL);
}

static void cmd_read_hnd(int argcp, char **argvp)
{
	int handle;

	if (conn_state != STATE_CONNECTED) {
		failed("Disconnected\n");
		return;
	}

	if (argcp < 2) {
		error("Missing argument: handle\n");
		return;
	}

	handle = strtohandle(argvp[1]);
	if (handle < 0) {
		error("Invalid handle: %s\n", argvp[1]);
		return;
	}

	gatt_read_char(attrib, handle, char_read_cb, attrib);
}

static void cmd_read_uuid(int argcp, char **argvp)
{
	int start = 0x0001;
	int end = 0xffff;
	bt_uuid_t uuid;

	if (conn_state != STATE_CONNECTED) {
		failed("Disconnected\n");
		return;
	}

	if (argcp < 2) {
		error("Missing argument: UUID\n");
		return;
	}

	if (bt_string_to_uuid(&uuid, argvp[1]) < 0) {
		error("Invalid UUID\n");
		return;
	}

	if (argcp > 2) {
		start = strtohandle(argvp[2]);
		if (start < 0) {
			error("Invalid start handle: %s\n", argvp[1]);
			return;
		}
	}

	if (argcp > 3) {
		end = strtohandle(argvp[3]);
		if (end < 0) {
			error("Invalid end handle: %s\n", argvp[2]);
			return;
		}
	}

	gatt_read_char_by_uuid(attrib, start, end, &uuid, char_read_by_uuid_cb,
									NULL);
	
	requested_read = 1;
}

static void char_write_req_cb(guint8 status, const guint8 *pdu, guint16 plen,
							gpointer user_data)
{
	if (status != 0) {
		error("Characteristic Write Request failed: "
						"%s\n", att_ecode2str(status));
		return;
	}

	if (!dec_write_resp(pdu, plen) && !dec_exec_write_resp(pdu, plen)) {
		error("Protocol error\n");
		return;
	}

	rl_printf("Characteristic value was written successfully\n");
}

static void cmd_char_write(int argcp, char **argvp)
{
	uint8_t *value;
	size_t plen;
	int handle;

	if (conn_state != STATE_CONNECTED) {
		failed("Disconnected\n");
		return;
	}

	if (argcp < 3) {
		rl_printf("Usage: %s <handle> <new value>\n", argvp[0]);
		return;
	}

	handle = strtohandle(argvp[1]);
	if (handle <= 0) {
		error("A valid handle is required\n");
		return;
	}

	plen = gatt_attr_data_from_string(argvp[2], &value);
	if (plen == 0) {
		error("Invalid value\n");
		return;
	}

	if (g_strcmp0("char-write-req", argvp[0]) == 0)
		gatt_write_char(attrib, handle, value, plen,
					char_write_req_cb, NULL);
	else
		gatt_write_cmd(attrib, handle, value, plen, NULL, NULL);

	g_free(value);
}

static void cmd_sec_level(int argcp, char **argvp)
{
	GError *gerr = NULL;
	BtIOSecLevel sec_level;

	if (argcp < 2) {
		rl_printf("sec-level: %s\n", opt_sec_level);
		return;
	}

	if (strcasecmp(argvp[1], "medium") == 0)
		sec_level = BT_IO_SEC_MEDIUM;
	else if (strcasecmp(argvp[1], "high") == 0)
		sec_level = BT_IO_SEC_HIGH;
	else if (strcasecmp(argvp[1], "low") == 0)
		sec_level = BT_IO_SEC_LOW;
	else {
		rl_printf("Allowed values: low | medium | high\n");
		return;
	}

	g_free(opt_sec_level);
	opt_sec_level = g_strdup(argvp[1]);

	if (conn_state != STATE_CONNECTED)
		return;

	if (opt_psm) {
		rl_printf("Change will take effect on reconnection\n");
		return;
	}

	bt_io_set(iochannel, &gerr,
			BT_IO_OPT_SEC_LEVEL, sec_level,
			BT_IO_OPT_INVALID);
	if (gerr) {
		error("%s\n", gerr->message);
		g_error_free(gerr);
	}
}

static void exchange_mtu_cb(guint8 status, const guint8 *pdu, guint16 plen,
							gpointer user_data)
{
	uint16_t mtu;

	if (status != 0) {
		error("Exchange MTU Request failed: %s\n",
						att_ecode2str(status));
		return;
	}

	if (!dec_mtu_resp(pdu, plen, &mtu)) {
		error("Protocol error\n");
		return;
	}

	mtu = MIN(mtu, opt_mtu);
	/* Set new value for MTU in client */
	if (g_attrib_set_mtu(attrib, mtu))
		rl_printf("MTU was exchanged successfully: %d\n", mtu);
	else
		error("Error exchanging MTU\n");
}

static void cmd_mtu(int argcp, char **argvp)
{
	if (conn_state != STATE_CONNECTED) {
		failed("Disconnected\n");
		return;
	}

	if (opt_psm) {
		failed("Operation is only available for LE transport.\n");
		return;
	}

	if (argcp < 2) {
		rl_printf("Usage: mtu <value>\n");
		return;
	}

	if (opt_mtu) {
		failed("MTU exchange can only occur once per connection.\n");
		return;
	}

	errno = 0;
	opt_mtu = strtoll(argvp[1], NULL, 0);
	if (errno != 0 || opt_mtu < ATT_DEFAULT_LE_MTU) {
		error("Invalid value. Minimum MTU size is %d\n",
							ATT_DEFAULT_LE_MTU);
		return;
	}

	gatt_exchange_mtu(attrib, opt_mtu, exchange_mtu_cb, NULL);
}

static struct {
	const char *cmd;
	void (*func)(int argcp, char **argvp);
	const char *params;
	const char *desc;
} commands[] = {
	{ "help",		cmd_help,	"",
		"Show this help"},
	{ "exit",		cmd_exit,	"",
		"Exit interactive mode" },
	{ "quit",		cmd_exit,	"",
		"Exit interactive mode" },
	{ "connect",		cmd_connect,	"[address [address type]]",
		"Connect to a remote device" },
	{ "disconnect",		cmd_disconnect,	"",
		"Disconnect from a remote device" },
	{ "primary",		cmd_primary,	"[UUID]",
		"Primary Service Discovery" },
	{ "included",		cmd_included,	"[start hnd [end hnd]]",
		"Find Included Services" },
	{ "characteristics",	cmd_char,	"[start hnd [end hnd [UUID]]]",
		"Characteristics Discovery" },
	{ "char-desc",		cmd_char_desc,	"[start hnd] [end hnd]",
		"Characteristics Descriptor Discovery" },
	{ "char-read-hnd",	cmd_read_hnd,	"<handle>",
		"Characteristics Value/Descriptor Read by handle" },
	{ "char-read-uuid",	cmd_read_uuid,	"<UUID> [start hnd] [end hnd]",
		"Characteristics Value/Descriptor Read by UUID" },
	{ "char-write-req",	cmd_char_write,	"<handle> <new value>",
		"Characteristic Value Write (Write Request)" },
	{ "char-write-cmd",	cmd_char_write,	"<handle> <new value>",
		"Characteristic Value Write (No response)" },
	{ "sec-level",		cmd_sec_level,	"[low | medium | high]",
		"Set security level. Default: low" },
	{ "mtu",		cmd_mtu,	"<value>",
		"Exchange MTU for GATT/ATT" },
	{ NULL, NULL, NULL}
};

static void cmd_help(int argcp, char **argvp)
{
	int i;

	for (i = 0; commands[i].cmd; i++)
		rl_printf("%-15s %-30s %s\n", commands[i].cmd,
				commands[i].params, commands[i].desc);
}

static void parse_line(char *line_read)
{
	char **argvp;
	int argcp;
	int i;

	if (line_read == NULL) {
		rl_printf("\n");
		//cmd_exit(0, NULL);
		return;
	}

	line_read = g_strstrip(line_read);

	if (*line_read == '\0')
		goto done;

	add_history(line_read);

	if (g_shell_parse_argv(line_read, &argcp, &argvp, NULL) == FALSE)
		goto done;

	for (i = 0; commands[i].cmd; i++)
		if (strcasecmp(commands[i].cmd, argvp[0]) == 0)
			break;

	if (commands[i].cmd)
		commands[i].func(argcp, argvp);
	else
		error("%s: command not found\n", argvp[0]);

	g_strfreev(argvp);

done:
	;
	//free(line_read);
}

static gboolean prompt_read(GIOChannel *chan, GIOCondition cond,
							gpointer user_data)
{
	if (cond & (G_IO_HUP | G_IO_ERR | G_IO_NVAL)) {
		g_io_channel_unref(chan);
		return FALSE;
	}

	rl_callback_read_char();

	return TRUE;
}

static char *completion_generator(const char *text, int state)
{
	static int index = 0, len = 0;
	const char *cmd = NULL;

	if (state == 0) {
		index = 0;
		len = strlen(text);
	}

	while ((cmd = commands[index].cmd) != NULL) {
		index++;
		if (strncmp(cmd, text, len) == 0)
			return strdup(cmd);
	}

	return NULL;
}

static char **commands_completion(const char *text, int start, int end)
{
	if (start == 0)
		return rl_completion_matches(text, &completion_generator);
	else
		return NULL;
}

static guint setup_standard_input(void)
{
	GIOChannel *channel;
	guint source;

	channel = g_io_channel_unix_new(fileno(stdin));

	source = g_io_add_watch(channel,
				G_IO_IN | G_IO_HUP | G_IO_ERR | G_IO_NVAL,
				prompt_read, NULL);

	g_io_channel_unref(channel);

	return source;
}

static gboolean signal_handler(GIOChannel *channel, GIOCondition condition,
							gpointer user_data)
{
	static unsigned int __terminated = 0;
	struct signalfd_siginfo si;
	ssize_t result;
	int fd;

	if (condition & (G_IO_NVAL | G_IO_ERR | G_IO_HUP)) {
		g_main_loop_quit(event_loop);
		return FALSE;
	}

	fd = g_io_channel_unix_get_fd(channel);

	result = read(fd, &si, sizeof(si));
	if (result != sizeof(si))
		return FALSE;

	switch (si.ssi_signo) {
	case SIGINT:
		rl_replace_line("", 0);
		rl_crlf();
		rl_on_new_line();
		rl_redisplay();
		break;
	case SIGTERM:
		if (__terminated == 0) {
			rl_replace_line("", 0);
			rl_crlf();
			g_main_loop_quit(event_loop);
		}

		__terminated = 1;
		break;
	}

	return TRUE;
}

static guint setup_signalfd(void)
{
	GIOChannel *channel;
	guint source;
	sigset_t mask;
	int fd;

	sigemptyset(&mask);
	sigaddset(&mask, SIGINT);
	sigaddset(&mask, SIGTERM);

	if (sigprocmask(SIG_BLOCK, &mask, NULL) < 0) {
		perror("Failed to set signal mask");
		return 0;
	}

	fd = signalfd(-1, &mask, 0);
	if (fd < 0) {
		perror("Failed to create signal descriptor");
		return 0;
	}

	channel = g_io_channel_unix_new(fd);

	g_io_channel_set_close_on_unref(channel, TRUE);
	g_io_channel_set_encoding(channel, NULL, NULL);
	g_io_channel_set_buffered(channel, FALSE);

	source = g_io_add_watch(channel,
				G_IO_IN | G_IO_HUP | G_IO_ERR | G_IO_NVAL,
				signal_handler, NULL);

	g_io_channel_unref(channel);

	return source;
}

gboolean callback_fastloop(GIOChannel *source, GIOCondition condition,gpointer data)
{
	if (conn_state == STATE_DISCONNECTED)
	{	
		if (conn_state != STATE_CONNECTING)
		{
		//request
		rl_printf("Requesting Connection \r\n");
		char cmdstring[] = "connect D1:83:15:3C:26:F0 random";
		parse_line((char *) &cmdstring);
		}	
		else
		{
		//wait for connection to be established
		usleep(1000);
		}
	}
	if (conn_state == STATE_CONNECTED)
	{
	// We are connected
		//if not connected 
		if (!requested_read)
		{
		rl_printf("Requesting Reading\r\n");
		//request read
		char cmdstring[] = "char-read-uuid 2a5b";
		parse_line((char *) &cmdstring);	
		requested_read = 1;		
		}	
		else
		{
		//wait until values are read
		usleep(1000);
		}
	}
	if (done_read)
	{
	rl_printf("Done Reading. Disconnecting\r\n");
	
	char cmdstring[] = "disconnect";
	parse_line((char *) &cmdstring);	
		
	//Reset values
	requested_read = 0;
	done_read = 0;
	
	rl_printf("Loop is %d\r\n",loop_counter);
	loop_counter += 1;
	}
    
	return 1;
}

int main(int argc, char *argv[]) {
    guint input;
    guint signal;

    opt_sec_level = g_strdup("low");

//	opt_src = g_strdup(src);
//	opt_dst = g_strdup(dst);
//	opt_dst_type = g_strdup(dst_type);
//	opt_psm = psm;

	conn_state = STATE_DISCONNECTED;
    prompt = g_string_new(NULL);

    event_loop = g_main_loop_new(NULL, FALSE);
	
	
	input = setup_standard_input();
    signal = setup_signalfd();
	
	requested_read = 0;
	done_read = 0;
	

	loop_counter = 0;
	
    g_timeout_add(1, (GSourceFunc) callback_fastloop, NULL);	
    g_main_loop_run(event_loop);
	

	rl_callback_handler_remove();
    cmd_disconnect(0, NULL);
    g_source_remove(input);
    g_source_remove(signal);
    g_main_loop_unref(event_loop);


    g_string_free(prompt, TRUE);

    g_free(opt_src);
    g_free(opt_dst);
    g_free(opt_sec_level);

    return 0;
}

^ permalink raw reply

* Re: [PATCH 1/2] android: Add skeleton of BlueZ Android daemon
From: Andrei Emeltchenko @ 2013-09-23  7:59 UTC (permalink / raw)
  To: Marcel Holtmann; +Cc: Frederic Danis, linux-bluetooth
In-Reply-To: <226042C8-264A-469E-8D6A-F41141DC0552@holtmann.org>

On Sat, Sep 21, 2013 at 12:14:55PM -0500, Marcel Holtmann wrote:
> Hi Fred,
> 
> > Define local mapping to glib path, otherwise this has to be inside central
> > place in the build repository.
> > 
> > Retrieve Bluetooth version from configure.ac.
> > ---
> > .gitignore         |    2 +
> > Android.mk         |    9 ++++
> > Makefile.am        |    1 +
> > Makefile.android   |    7 ++++
> > android/Android.mk |   24 +++++++++++
> > android/main.c     |  119 ++++++++++++++++++++++++++++++++++++++++++++++++++++
> > configure.ac       |    5 +++
> > 7 files changed, 167 insertions(+)
> > create mode 100644 Android.mk
> > create mode 100644 Makefile.android
> > create mode 100644 android/Android.mk
> > create mode 100644 android/main.c
> 
> lets split this out a little bit. Code additions should not be intermixed with additions to the build system and especially configure options.
> 
> I rather not have a top-level Android.mk. It should be enough to provide an android/Android.mk.
> 

I believe this way we cannot build our project.

Best regards 
Andrei Emeltchenko 

^ permalink raw reply

* Re: [PATCH 2/2] android: Android version of log.c
From: Andrei Emeltchenko @ 2013-09-23  7:48 UTC (permalink / raw)
  To: Marcel Holtmann; +Cc: Frederic Danis, linux-bluetooth
In-Reply-To: <708DB870-5A40-4056-86C8-79092784757C@holtmann.org>

Hi all,

On Sat, Sep 21, 2013 at 12:20:52PM -0500, Marcel Holtmann wrote:
> Hi Fred,
> > +
> > +static void android_log(int pri, const char *fmt, va_list ap)
> > +{
> > +	char *msg;
> > +	struct iovec vec[3];
> > +
> > +	msg = g_strdup_vprintf(fmt, ap);
> > +
> > +	if (!detached) {
> > +		vec[0].iov_base = (void *) msg;
> > +		vec[0].iov_len = strlen(msg) + 1;
> > +		vec[1].iov_base = "\n";
> > +		vec[1].iov_len = 1;
> > +		writev(STDERR_FILENO, vec, 2);
> > +	}
> 
> Lets not worry about logging to stderr at all.

Then I believe this might be simplified a lot. We might use
__android_log_print - like functions in this case.

Best regards 
Andrei Emeltchenko 


^ 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