Linux bluetooth development
 help / color / mirror / Atom feed
* [PATCH 1/2] android: Add helper functions for converting bdaddr transmitted over IPC
From: Szymon Janc @ 2013-10-28 13:45 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Szymon Janc

Android holds Bluetooth address in reverse order comparing to
bluetoothd. Add convenient functions for converting to and from that
format.

Convertion will done on daemon side to keep HAL library simple.
---
 android/utils.h | 33 +++++++++++++++++++++++++++++++++
 1 file changed, 33 insertions(+)
 create mode 100644 android/utils.h

diff --git a/android/utils.h b/android/utils.h
new file mode 100644
index 0000000..5b009bc
--- /dev/null
+++ b/android/utils.h
@@ -0,0 +1,33 @@
+/*
+ *
+ *  BlueZ - Bluetooth protocol stack for Linux
+ *
+ *  Copyright (C) 2013  Intel Corporation. All rights reserved.
+ *
+ *
+ *  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
+ *
+ */
+
+
+static inline void android2bdaddr(const void *buf, bdaddr_t *dst)
+{
+	baswap(dst, buf);
+}
+
+static inline void bdaddr2android(const bdaddr_t *src, void *buf)
+{
+	baswap(buf, src);
+}
-- 
1.8.4.1


^ permalink raw reply related

* [PATCH 2/2] android: Use helper function to convert bdaddr to android format
From: Szymon Janc @ 2013-10-28 13:45 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Szymon Janc
In-Reply-To: <1382967914-11102-1-git-send-email-szymon.janc@tieto.com>

This will make easier to understand why swap is needed.
---
 Makefile.android  | 1 +
 android/adapter.c | 3 ++-
 2 files changed, 3 insertions(+), 1 deletion(-)

diff --git a/Makefile.android b/Makefile.android
index fd8043c..2b57daa 100644
--- a/Makefile.android
+++ b/Makefile.android
@@ -4,6 +4,7 @@ noinst_PROGRAMS += android/bluetoothd
 android_bluetoothd_SOURCES =	android/main.c \
 				src/log.c \
 				android/hal-msg.h \
+				android/utils.h \
 				src/sdpd-database.c src/sdpd-server.c \
 				src/sdpd-service.c src/sdpd-request.c \
 				src/shared/util.h src/shared/util.c \
diff --git a/android/adapter.c b/android/adapter.c
index f393c49..15b65e5 100644
--- a/android/adapter.c
+++ b/android/adapter.c
@@ -31,6 +31,7 @@
 #include "log.h"
 #include "hal-msg.h"
 #include "ipc.h"
+#include "utils.h"
 #include "adapter.h"
 
 static GIOChannel *notification_io = NULL;
@@ -384,7 +385,7 @@ static void send_adapter_address(void)
 
 	ev->props[0].type = HAL_PROP_ADAPTER_ADDR;
 	ev->props[0].len = sizeof(bdaddr_t);
-	baswap((bdaddr_t *) ev->props[0].val, &adapter->bdaddr);
+	bdaddr2android(&adapter->bdaddr, ev->props[0].val);
 
 	ipc_send(notification_io, HAL_SERVICE_ID_BLUETOOTH,
 				HAL_EV_ADAPTER_PROPS_CHANGED, len, ev, -1);
-- 
1.8.4.1


^ permalink raw reply related

* Re: [PATCH 5/5] android: Add and remove uuids in mgmt interface
From: Marcel Holtmann @ 2013-10-28 13:47 UTC (permalink / raw)
  To: Johan Hedberg; +Cc: Marcin Kraglak, linux-bluetooth@vger.kernel.org development
In-Reply-To: <20131028132354.GA13148@x220.p-661hnu-f1>

Hi Johan,

>> +static int uuid_cmp(const void *a, const void *b)
>> +{
>> +	const sdp_record_t *rec = a;
>> +	const uuid_t *uuid = b;
>> +
>> +	return sdp_uuid_cmp(&rec->svclass, uuid);
>> +}
>> +
>> +static void uuid_to_uuid128(uuid_t *uuid128, const uuid_t *uuid)
>> +{
>> +	if (uuid->type == SDP_UUID16)
>> +		sdp_uuid16_to_uuid128(uuid128, uuid);
>> +	else if (uuid->type == SDP_UUID32)
>> +		sdp_uuid32_to_uuid128(uuid128, uuid);
>> +	else
>> +		memcpy(uuid128, uuid, sizeof(*uuid));
>> +}
>> +
>> +static uint8_t get_uuid_mask(const uuid_t *uuid)
>> +{
>> +	if (uuid->type != SDP_UUID16)
>> +		return 0;
>> +
>> +	switch (uuid->value.uuid16) {
>> +	case DIALUP_NET_SVCLASS_ID:
>> +	case CIP_SVCLASS_ID:
>> +		return 0x42;    /* Telephony & Networking */
>> +	case IRMC_SYNC_SVCLASS_ID:
>> +	case OBEX_OBJPUSH_SVCLASS_ID:
>> +	case OBEX_FILETRANS_SVCLASS_ID:
>> +	case IRMC_SYNC_CMD_SVCLASS_ID:
>> +	case PBAP_PSE_SVCLASS_ID:
>> +		return 0x10;    /* Object Transfer */
>> +	case HEADSET_SVCLASS_ID:
>> +	case HANDSFREE_SVCLASS_ID:
>> +		return 0x20;    /* Audio */
>> +	case CORDLESS_TELEPHONY_SVCLASS_ID:
>> +	case INTERCOM_SVCLASS_ID:
>> +	case FAX_SVCLASS_ID:
>> +	case SAP_SVCLASS_ID:
>> +	/*
>> +	* Setting the telephony bit for the handsfree audio gateway
>> +	* role is not required by the HFP specification, but the
>> +	* Nokia 616 carkit is just plain broken! It will refuse
>> +	* pairing without this bit set.
>> +	*/
>> +	case HANDSFREE_AGW_SVCLASS_ID:
>> +		return 0x40;    /* Telephony */
>> +	case AUDIO_SOURCE_SVCLASS_ID:
>> +	case VIDEO_SOURCE_SVCLASS_ID:
>> +		return 0x08;    /* Capturing */
>> +	case AUDIO_SINK_SVCLASS_ID:
>> +	case VIDEO_SINK_SVCLASS_ID:
>> +		return 0x04;    /* Rendering */
>> +	case PANU_SVCLASS_ID:
>> +	case NAP_SVCLASS_ID:
>> +	case GN_SVCLASS_ID:
>> +		return 0x02;    /* Networking */
>> +	default:
>> +		return 0;
>> +	}
>> +}
> 
> I don't think it makes sense to duplicate this code in bluez.git,
> especially not the last function. Instead, I think it should be
> refactored to the appropriate common place (lib/sdp.c maybe? Or maybe
> not if we don't want to pollute the already deprecated libbluetooth - in
> which case I'd expect a proposal where to put this).

I was actually thinking that we just make this static. In Android all SDP records are normally registered ahead of time. They even did this when they used BlueZ. It was essentially a sdptool add for all the records they needed.

This is also means we can just use the service class hint as a static value.

>> +static int add_uuid(uuid_t *uuid, uint8_t svc_hint)
>> +{
>> +	struct mgmt_cp_add_uuid cp;
>> +	uuid_t uuid128;
>> +	uint128_t uint128;
>> +
>> +	uuid_to_uuid128(&uuid128, uuid);
>> +
>> +	ntoh128((uint128_t *) uuid128.value.uuid128.data, &uint128);
>> +	htob128(&uint128, (uint128_t *) cp.uuid);
>> +	cp.svc_hint = svc_hint;
>> +
>> +	if (mgmt_send(adapter->mgmt, MGMT_OP_ADD_UUID,
>> +			0, sizeof(cp), &cp,
>> +			add_uuid_complete, adapter, NULL) > 0)
>> +		return 0;
> 
> Since you're skipping the "is_supported_uuid" check that we're doing in
> the normal bluetoothd I suppose we at least have a proper check for a
> minimum mgmt version when initializing the android bluetoothd? Otherwise
> your patch is broken.

We should require a minimum mgmt version for Android. One that has all the bugs fixed. There is no point in planning on supporting older kernels anyway.

Regards

Marcel


^ permalink raw reply

* [RFC 0/2] Make HAL debug thread-safe
From: Andrei Emeltchenko @ 2013-10-28 14:06 UTC (permalink / raw)
  To: linux-bluetooth

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

Since HAL is threaded this makes it safe to print properties and bdaddr.
This is slightly modified bionic thread-safe code.

Please comment.

Andrei Emeltchenko (2):
  android: Add thread-safe helpers
  android: Use thread-safe helpers

 android/client/textconv.c |   15 ++++++++-----
 android/pthread-local.h   |   51 +++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 61 insertions(+), 5 deletions(-)
 create mode 100644 android/pthread-local.h

-- 
1.7.10.4


^ permalink raw reply

* [RFC 1/2] android: Add thread-safe helpers
From: Andrei Emeltchenko @ 2013-10-28 14:06 UTC (permalink / raw)
  To: linux-bluetooth
In-Reply-To: <1382969211-7402-1-git-send-email-Andrei.Emeltchenko.news@gmail.com>

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

Add thread safe helpers to make HAL debug printing thread-safe. The code
is inherited from Android bionic and it is used for strerror, strsignal,
etc.
---
 android/pthread-local.h |   51 +++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 51 insertions(+)
 create mode 100644 android/pthread-local.h

diff --git a/android/pthread-local.h b/android/pthread-local.h
new file mode 100644
index 0000000..07012f3
--- /dev/null
+++ b/android/pthread-local.h
@@ -0,0 +1,51 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ * Copyright (C) 2013 Intel Corp.
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *  * Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *  * Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+
+#include <pthread.h>
+
+#define GLOBAL_INIT_THREAD_LOCAL_BUFFER(name) \
+  static pthread_key_t __bionic_tls_ ## name ## _key; \
+  static void __bionic_tls_ ## name ## _key_destroy(void* buffer) { \
+    free(buffer); \
+  } \
+  __attribute__((constructor)) static void __bionic_tls_ ## name ## _key_init() { \
+    pthread_key_create(&__bionic_tls_ ## name ## _key, __bionic_tls_ ## name ## _key_destroy); \
+  }
+
+// Leaves "name_tls_buffer" and "name_tls_buffer_size" defined and initialized.
+#define LOCAL_INIT_THREAD_LOCAL_BUFFER(type, name, byte_count) \
+  type name ## _tls_buffer = \
+      (pthread_getspecific(__bionic_tls_ ## name ## _key)); \
+  if (name ## _tls_buffer == NULL) { \
+    name ## _tls_buffer = (calloc(1, byte_count)); \
+    pthread_setspecific(__bionic_tls_ ## name ## _key, name ## _tls_buffer); \
+  } \
+  const size_t name ## _tls_buffer_size __attribute__((unused)) = byte_count
-- 
1.7.10.4


^ permalink raw reply related

* [RFC 2/2] android: Use thread-safe helpers
From: Andrei Emeltchenko @ 2013-10-28 14:06 UTC (permalink / raw)
  To: linux-bluetooth
In-Reply-To: <1382969211-7402-1-git-send-email-Andrei.Emeltchenko.news@gmail.com>

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

Make use of thread-safe helpers.
---
 android/client/textconv.c |   15 ++++++++++-----
 1 file changed, 10 insertions(+), 5 deletions(-)

diff --git a/android/client/textconv.c b/android/client/textconv.c
index 16392c2..6e75c28 100644
--- a/android/client/textconv.c
+++ b/android/client/textconv.c
@@ -19,6 +19,8 @@
 #include <stdio.h>
 #include <hardware/bluetooth.h>
 
+#include "../pthread-local.h"
+
 #include "textconv.h"
 
 /*
@@ -227,11 +229,12 @@ const char *enum_one_string(void *v, int i)
 	return (i == 0) && (m[0] != 0) ? m : NULL;
 }
 
+GLOBAL_INIT_THREAD_LOCAL_BUFFER(bdaddr_buf);
 char *bdaddr2str(const bt_bdaddr_t *bd_addr)
 {
-	static char buf[MAX_ADDR_STR_LEN];
+	LOCAL_INIT_THREAD_LOCAL_BUFFER(char*, bdaddr_buf, MAX_ADDR_STR_LEN);
 
-	return bt_bdaddr_t2str(bd_addr, buf);
+	return bt_bdaddr_t2str(bd_addr, bdaddr_buf_tls_buffer);
 }
 
 char *btuuid2str(const bt_uuid_t *uuid)
@@ -241,12 +244,14 @@ char *btuuid2str(const bt_uuid_t *uuid)
 	return bt_uuid_t2str(uuid, buf);
 }
 
+GLOBAL_INIT_THREAD_LOCAL_BUFFER(property_buf);
 char *btproperty2str(const bt_property_t *property)
 {
-	static char buf[4096];
+	LOCAL_INIT_THREAD_LOCAL_BUFFER(char*, property_buf, 4096);
 	char *p;
 
-	p = buf + sprintf(buf, "type=%s len=%d val=",
+	p = property_buf_tls_buffer + sprintf(property_buf_tls_buffer,
+					"type=%s len=%d val=",
 					bt_property_type_t2str(property->type),
 					property->len);
 
@@ -334,5 +339,5 @@ char *btproperty2str(const bt_property_t *property)
 		sprintf(p, "%p", property->val);
 	}
 
-	return buf;
+	return property_buf_tls_buffer;
 }
-- 
1.7.10.4


^ permalink raw reply related

* [PATCH 0/2] Initial HID connect disconnect methods
From: Ravi kumar Veeramally @ 2013-10-28 14:47 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Ravi kumar Veeramally

Patchset adds hid connect and disconnect mechanisms at
L2CAP level. It opens the control channel and interrupt
channel and listens on io events. UHID, hid server and
reconnect related features not yet done.

Ravi kumar Veeramally (2):
  android: Add initial HID connect implementation
  android: Add initial HID disconnect implementation.

 Makefile.android   |    3 +-
 android/Android.mk |    1 +
 android/hid.c      |  260 ++++++++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 263 insertions(+), 1 deletion(-)

-- 
1.7.9.5


^ permalink raw reply

* [PATCH 1/2] android: Add initial HID connect implementation
From: Ravi kumar Veeramally @ 2013-10-28 14:47 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Ravi kumar Veeramally
In-Reply-To: <1382971653-11727-1-git-send-email-ravikumar.veeramally@linux.intel.com>

Implemented basic HID connect method. Host connects to
bt device at L2CAP level.
---
 Makefile.android   |    3 +-
 android/Android.mk |    1 +
 android/hid.c      |  237 ++++++++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 240 insertions(+), 1 deletion(-)

diff --git a/Makefile.android b/Makefile.android
index 2b57daa..22002be 100644
--- a/Makefile.android
+++ b/Makefile.android
@@ -12,7 +12,8 @@ android_bluetoothd_SOURCES =	android/main.c \
 				android/adapter.h android/adapter.c \
 				android/hid.h android/hid.c \
 				android/ipc.h android/ipc.c \
-				android/socket.h android/socket.c
+				android/socket.h android/socket.c \
+				btio/btio.h btio/btio.c
 
 android_bluetoothd_LDADD = lib/libbluetooth-internal.la @GLIB_LIBS@
 
diff --git a/android/Android.mk b/android/Android.mk
index 22208e0..28ec465 100644
--- a/android/Android.mk
+++ b/android/Android.mk
@@ -28,6 +28,7 @@ LOCAL_SRC_FILES := \
 	../lib/sdp.c \
 	../lib/bluetooth.c \
 	../lib/hci.c \
+	../btio/btio.c
 
 LOCAL_C_INCLUDES := \
 	$(call include-path-for, glib) \
diff --git a/android/hid.c b/android/hid.c
index f2da0d3..b7bdc07 100644
--- a/android/hid.c
+++ b/android/hid.c
@@ -23,16 +23,252 @@
 
 #include <stdint.h>
 #include <stdbool.h>
+#include <errno.h>
+#include <unistd.h>
+#include <fcntl.h>
 
 #include <glib.h>
 
+#include "btio/btio.h"
 #include "lib/bluetooth.h"
+#include "src/shared/mgmt.h"
+
 #include "log.h"
 #include "hal-msg.h"
 #include "ipc.h"
 #include "hid.h"
+#include "adapter.h"
+#include "utils.h"
+
+#define L2CAP_PSM_HIDP_CTRL	0x11
+#define L2CAP_PSM_HIDP_INTR	0x13
+#define MAX_READ_BUFFER		4096
 
 static GIOChannel *notification_io = NULL;
+static GSList *devices = NULL;
+
+struct input_device {
+	bdaddr_t	src;
+	bdaddr_t	dst;
+	GIOChannel	*ctrl_io;
+	GIOChannel	*intr_io;
+	guint		ctrl_watch;
+	guint		intr_watch;
+};
+
+static int device_cmp(gconstpointer s, gconstpointer user_data)
+{
+	const struct input_device *idev = s;
+	const bdaddr_t *dst = user_data;
+
+	return bacmp(&idev->dst, dst);
+}
+
+static void input_device_free(struct input_device *idev)
+{
+	if (idev->ctrl_watch > 0)
+		g_source_remove(idev->ctrl_watch);
+
+	if (idev->intr_watch > 0)
+		g_source_remove(idev->intr_watch);
+
+	if (idev->intr_io)
+		g_io_channel_unref(idev->intr_io);
+
+	if (idev->ctrl_io)
+		g_io_channel_unref(idev->ctrl_io);
+
+	devices = g_slist_remove(devices, idev);
+	g_free(idev);
+}
+
+static gboolean intr_io_watch_cb(GIOChannel *chan, gpointer data)
+{
+	char buf[MAX_READ_BUFFER];
+	int fd, bread;
+
+	fd = g_io_channel_unix_get_fd(chan);
+	bread = read(fd, buf, sizeof(buf));
+	if (bread < 0) {
+		error("read: %s(%d)", strerror(-errno), -errno);
+		return TRUE;
+	}
+
+	DBG("bytes read %d", bread);
+
+	/* TODO: At this moment only baseband is connected, i.e. mouse
+	 * movements keyboard events doesn't effect on UI. Have to send
+	 * this data to uhid fd for profile connection. */
+
+	return TRUE;
+}
+
+static gboolean intr_watch_cb(GIOChannel *chan, GIOCondition cond,
+								gpointer data)
+{
+	struct input_device *idev = data;
+	char address[18];
+
+	if (cond & G_IO_IN)
+		return intr_io_watch_cb(chan, data);
+
+	ba2str(&idev->dst, address);
+	DBG("Device %s disconnected", address);
+
+	/* Checking for ctrl_watch avoids a double g_io_channel_shutdown since
+	 * it's likely that ctrl_watch_cb has been queued for dispatching in
+	 * this mainloop iteration */
+	if ((cond & (G_IO_HUP | G_IO_ERR)) && idev->ctrl_watch)
+		g_io_channel_shutdown(chan, TRUE, NULL);
+
+	idev->intr_watch = 0;
+
+	if (idev->intr_io) {
+		g_io_channel_unref(idev->intr_io);
+		idev->intr_io = NULL;
+	}
+
+	/* Close control channel */
+	if (idev->ctrl_io && !(cond & G_IO_NVAL))
+		g_io_channel_shutdown(idev->ctrl_io, TRUE, NULL);
+
+	return FALSE;
+}
+
+static gboolean ctrl_watch_cb(GIOChannel *chan, GIOCondition cond,
+								gpointer data)
+{
+	struct input_device *idev = data;
+	char address[18];
+
+	ba2str(&idev->dst, address);
+	DBG("Device %s disconnected", address);
+
+	/* Checking for intr_watch avoids a double g_io_channel_shutdown since
+	 * it's likely that intr_watch_cb has been queued for dispatching in
+	 * this mainloop iteration */
+	if ((cond & (G_IO_HUP | G_IO_ERR)) && idev->intr_watch)
+		g_io_channel_shutdown(chan, TRUE, NULL);
+
+	idev->ctrl_watch = 0;
+
+	if (idev->ctrl_io) {
+		g_io_channel_unref(idev->ctrl_io);
+		idev->ctrl_io = NULL;
+	}
+
+	if (idev->intr_io && !(cond & G_IO_NVAL))
+		g_io_channel_shutdown(idev->intr_io, TRUE, NULL);
+
+	return FALSE;
+}
+
+static void interrupt_connect_cb(GIOChannel *chan, GError *conn_err,
+							gpointer user_data)
+{
+	struct input_device *idev = user_data;
+
+	DBG("");
+
+	if (conn_err)
+		goto failed;
+
+	/*TODO: Get device details through SDP and create UHID fd and start
+	 * listening on uhid events */
+	idev->intr_watch = g_io_add_watch(idev->intr_io,
+				G_IO_IN | G_IO_HUP | G_IO_ERR | G_IO_NVAL,
+				intr_watch_cb, idev);
+
+	return;
+
+failed:
+	/* So we guarantee the interrupt channel is closed before the
+	 * control channel (if we only do unref GLib will close it only
+	 * after returning control to the mainloop */
+	if (!conn_err)
+		g_io_channel_shutdown(idev->intr_io, FALSE, NULL);
+
+	g_io_channel_unref(idev->intr_io);
+	idev->intr_io = NULL;
+
+	if (idev->ctrl_io) {
+		g_io_channel_unref(idev->ctrl_io);
+		idev->ctrl_io = NULL;
+	}
+}
+
+static void control_connect_cb(GIOChannel *chan, GError *conn_err,
+							gpointer user_data)
+{
+	struct input_device *idev = user_data;
+	GError *err = NULL;
+
+	DBG("");
+
+	if (conn_err) {
+		error("%s", conn_err->message);
+		goto failed;
+	}
+
+	/* Connect to the HID interrupt channel */
+	idev->intr_io = bt_io_connect(interrupt_connect_cb, idev, NULL, &err,
+					BT_IO_OPT_SOURCE_BDADDR, &idev->src,
+					BT_IO_OPT_DEST_BDADDR, &idev->dst,
+					BT_IO_OPT_PSM, L2CAP_PSM_HIDP_INTR,
+					BT_IO_OPT_SEC_LEVEL, BT_IO_SEC_LOW,
+					BT_IO_OPT_INVALID);
+	if (!idev->intr_io) {
+		error("%s", err->message);
+		g_error_free(err);
+		goto failed;
+	}
+
+	idev->ctrl_watch = g_io_add_watch(idev->ctrl_io,
+					G_IO_HUP | G_IO_ERR | G_IO_NVAL,
+					ctrl_watch_cb, idev);
+
+	return;
+
+failed:
+	g_io_channel_unref(idev->ctrl_io);
+	idev->ctrl_io = NULL;
+}
+
+static uint8_t dev_connect(struct hal_cmd_hid_connect *cmd, uint16_t len)
+{
+	struct input_device *idev;
+	char addr[18];
+	GError *err = NULL;
+
+	DBG("");
+
+	if (len < sizeof(*cmd))
+		return HAL_STATUS_INVALID;
+
+	idev = g_new0(struct input_device, 1);
+	bacpy(&idev->src, bt_adapter_get_address());
+	android2bdaddr((bdaddr_t *)&cmd->bdaddr, &idev->dst);
+	ba2str(&idev->dst, addr);
+
+	DBG("connecting to %s", addr);
+
+	idev->ctrl_io = bt_io_connect(control_connect_cb, idev, NULL, &err,
+					BT_IO_OPT_SOURCE_BDADDR, &idev->src,
+					BT_IO_OPT_DEST_BDADDR, &idev->dst,
+					BT_IO_OPT_PSM, L2CAP_PSM_HIDP_CTRL,
+					BT_IO_OPT_SEC_LEVEL, BT_IO_SEC_LOW,
+					BT_IO_OPT_INVALID);
+	if (err) {
+		error("%s", err->message);
+		g_error_free(err);
+		input_device_free(idev);
+		return HAL_STATUS_FAILED;
+	}
+
+	devices = g_slist_append(devices, idev);
+
+	return HAL_STATUS_SUCCESS;
+}
 
 void bt_hid_handle_cmd(GIOChannel *io, uint8_t opcode, void *buf, uint16_t len)
 {
@@ -40,6 +276,7 @@ void bt_hid_handle_cmd(GIOChannel *io, uint8_t opcode, void *buf, uint16_t len)
 
 	switch (opcode) {
 	case HAL_OP_HID_CONNECT:
+		status = dev_connect((struct hal_cmd_hid_connect *) buf, len);
 		break;
 	case HAL_OP_HID_DISCONNECT:
 		break;
-- 
1.7.9.5


^ permalink raw reply related

* [PATCH 2/2] android: Add initial HID disconnect implementation.
From: Ravi kumar Veeramally @ 2013-10-28 14:47 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Ravi kumar Veeramally
In-Reply-To: <1382971653-11727-1-git-send-email-ravikumar.veeramally@linux.intel.com>

Implemented basic HID disconnect method. Host disconnects
with bt device at L2CAP level.
---
 android/hid.c |   23 +++++++++++++++++++++++
 1 file changed, 23 insertions(+)

diff --git a/android/hid.c b/android/hid.c
index b7bdc07..3e7ac0d 100644
--- a/android/hid.c
+++ b/android/hid.c
@@ -270,6 +270,27 @@ static uint8_t dev_connect(struct hal_cmd_hid_connect *cmd, uint16_t len)
 	return HAL_STATUS_SUCCESS;
 }
 
+static uint8_t dev_disconnect(struct hal_cmd_hid_disconnect *cmd, uint16_t len)
+{
+	GSList *l;
+	bdaddr_t dst;
+
+	DBG("");
+
+	if (len < sizeof(*cmd))
+		return HAL_STATUS_INVALID;
+
+	android2bdaddr((bdaddr_t *)&cmd->bdaddr, &dst);
+
+	l = g_slist_find_custom(devices, &dst, device_cmp);
+	if (!l)
+		return HAL_STATUS_FAILED;
+
+	input_device_free(l->data);
+
+	return HAL_STATUS_SUCCESS;
+}
+
 void bt_hid_handle_cmd(GIOChannel *io, uint8_t opcode, void *buf, uint16_t len)
 {
 	uint8_t status = HAL_STATUS_FAILED;
@@ -279,6 +300,8 @@ void bt_hid_handle_cmd(GIOChannel *io, uint8_t opcode, void *buf, uint16_t len)
 		status = dev_connect((struct hal_cmd_hid_connect *) buf, len);
 		break;
 	case HAL_OP_HID_DISCONNECT:
+		status = dev_disconnect((struct hal_cmd_hid_disconnect *) buf,
+									len);
 		break;
 	default:
 		DBG("Unhandled command, opcode 0x%x", opcode);
-- 
1.7.9.5


^ permalink raw reply related

* Re: [PATCH 2/2] android: Add initial HID disconnect implementation.
From: Luiz Augusto von Dentz @ 2013-10-28 14:53 UTC (permalink / raw)
  To: Ravi kumar Veeramally; +Cc: linux-bluetooth@vger.kernel.org
In-Reply-To: <1382971653-11727-3-git-send-email-ravikumar.veeramally@linux.intel.com>

Hi Ravi,

On Mon, Oct 28, 2013 at 4:47 PM, Ravi kumar Veeramally
<ravikumar.veeramally@linux.intel.com> wrote:
> Implemented basic HID disconnect method. Host disconnects
> with bt device at L2CAP level.
> ---
>  android/hid.c |   23 +++++++++++++++++++++++
>  1 file changed, 23 insertions(+)
>
> diff --git a/android/hid.c b/android/hid.c
> index b7bdc07..3e7ac0d 100644
> --- a/android/hid.c
> +++ b/android/hid.c
> @@ -270,6 +270,27 @@ static uint8_t dev_connect(struct hal_cmd_hid_connect *cmd, uint16_t len)
>         return HAL_STATUS_SUCCESS;
>  }
>
> +static uint8_t dev_disconnect(struct hal_cmd_hid_disconnect *cmd, uint16_t len)
> +{
> +       GSList *l;
> +       bdaddr_t dst;
> +
> +       DBG("");
> +
> +       if (len < sizeof(*cmd))
> +               return HAL_STATUS_INVALID;
> +
> +       android2bdaddr((bdaddr_t *)&cmd->bdaddr, &dst);
> +
> +       l = g_slist_find_custom(devices, &dst, device_cmp);
> +       if (!l)
> +               return HAL_STATUS_FAILED;
> +
> +       input_device_free(l->data);
> +
> +       return HAL_STATUS_SUCCESS;
> +}
> +
>  void bt_hid_handle_cmd(GIOChannel *io, uint8_t opcode, void *buf, uint16_t len)
>  {
>         uint8_t status = HAL_STATUS_FAILED;
> @@ -279,6 +300,8 @@ void bt_hid_handle_cmd(GIOChannel *io, uint8_t opcode, void *buf, uint16_t len)
>                 status = dev_connect((struct hal_cmd_hid_connect *) buf, len);
>                 break;
>         case HAL_OP_HID_DISCONNECT:
> +               status = dev_disconnect((struct hal_cmd_hid_disconnect *) buf,
> +                                                                       len);

Look at the other files, we are not doing the casts upfront but in the
function itself.


-- 
Luiz Augusto von Dentz

^ permalink raw reply

* Re: [PATCH] Regression fix revert: "Bluetooth: Add missing reset_resume dev_pm_ops"
From: Hans de Goede @ 2013-10-28 14:54 UTC (permalink / raw)
  To: Gustavo Padovan
  Cc: USB list, linux-bluetooth, Shuah Khan, Gustavo Padovan, stable
In-Reply-To: <508150F6-D142-4406-8CC9-57DDE754F391@holtmann.org>

Hi Gustavo,

> Patch has been applied to bluetooth.git. Thanks.

Hmm, I'm not seeing this in 3.12 yet, not only should this be added
to 3.12 asap, it should also really get added to 3.11.x soon.

The regression this patch fixes is breaking btusb for lots of users, see:
https://bugs.launchpad.net/ubuntu/+source/linux/+bug/1213239
https://bugzilla.redhat.com/show_bug.cgi?id=988481

Where lots of people are adding me too comments (and some are building
their own kernels with the revert and confirming it fixes things for
them).

Regards,

Hans

^ permalink raw reply

* Re: [PATCH 1/2] android: Add initial HID connect implementation
From: Luiz Augusto von Dentz @ 2013-10-28 15:06 UTC (permalink / raw)
  To: Ravi kumar Veeramally; +Cc: linux-bluetooth@vger.kernel.org
In-Reply-To: <1382971653-11727-2-git-send-email-ravikumar.veeramally@linux.intel.com>

Hi Ravi,

On Mon, Oct 28, 2013 at 4:47 PM, Ravi kumar Veeramally
<ravikumar.veeramally@linux.intel.com> wrote:
> Implemented basic HID connect method. Host connects to
> bt device at L2CAP level.
> ---
>  Makefile.android   |    3 +-
>  android/Android.mk |    1 +
>  android/hid.c      |  237 ++++++++++++++++++++++++++++++++++++++++++++++++++++
>  3 files changed, 240 insertions(+), 1 deletion(-)
>
> diff --git a/Makefile.android b/Makefile.android
> index 2b57daa..22002be 100644
> --- a/Makefile.android
> +++ b/Makefile.android
> @@ -12,7 +12,8 @@ android_bluetoothd_SOURCES =  android/main.c \
>                                 android/adapter.h android/adapter.c \
>                                 android/hid.h android/hid.c \
>                                 android/ipc.h android/ipc.c \
> -                               android/socket.h android/socket.c
> +                               android/socket.h android/socket.c \
> +                               btio/btio.h btio/btio.c
>
>  android_bluetoothd_LDADD = lib/libbluetooth-internal.la @GLIB_LIBS@
>
> diff --git a/android/Android.mk b/android/Android.mk
> index 22208e0..28ec465 100644
> --- a/android/Android.mk
> +++ b/android/Android.mk
> @@ -28,6 +28,7 @@ LOCAL_SRC_FILES := \
>         ../lib/sdp.c \
>         ../lib/bluetooth.c \
>         ../lib/hci.c \
> +       ../btio/btio.c
>
>  LOCAL_C_INCLUDES := \
>         $(call include-path-for, glib) \
> diff --git a/android/hid.c b/android/hid.c
> index f2da0d3..b7bdc07 100644
> --- a/android/hid.c
> +++ b/android/hid.c
> @@ -23,16 +23,252 @@
>
>  #include <stdint.h>
>  #include <stdbool.h>
> +#include <errno.h>
> +#include <unistd.h>
> +#include <fcntl.h>
>
>  #include <glib.h>
>
> +#include "btio/btio.h"
>  #include "lib/bluetooth.h"
> +#include "src/shared/mgmt.h"
> +
>  #include "log.h"
>  #include "hal-msg.h"
>  #include "ipc.h"
>  #include "hid.h"
> +#include "adapter.h"
> +#include "utils.h"
> +
> +#define L2CAP_PSM_HIDP_CTRL    0x11
> +#define L2CAP_PSM_HIDP_INTR    0x13
> +#define MAX_READ_BUFFER                4096
>
>  static GIOChannel *notification_io = NULL;
> +static GSList *devices = NULL;
> +
> +struct input_device {
> +       bdaddr_t        src;
> +       bdaddr_t        dst;
> +       GIOChannel      *ctrl_io;
> +       GIOChannel      *intr_io;
> +       guint           ctrl_watch;
> +       guint           intr_watch;
> +};


You probably don't need the address of the adapter as there could be
only one in android you can always query its value via
bt_adapter_get_address.

> +static uint8_t dev_connect(struct hal_cmd_hid_connect *cmd, uint16_t len)
> +{
> +       struct input_device *idev;
> +       char addr[18];
> +       GError *err = NULL;
> +
> +       DBG("");
> +
> +       if (len < sizeof(*cmd))
> +               return HAL_STATUS_INVALID;
> +
> +       idev = g_new0(struct input_device, 1);
> +       bacpy(&idev->src, bt_adapter_get_address());
> +       android2bdaddr((bdaddr_t *)&cmd->bdaddr, &idev->dst);
> +       ba2str(&idev->dst, addr);

Might be worth checking if there a connection ongoing before you
create a new data, I would also avoid having the same struct names
from our input plugin, just use something else like hid_data.

> +
> +       DBG("connecting to %s", addr);
> +
> +       idev->ctrl_io = bt_io_connect(control_connect_cb, idev, NULL, &err,
> +                                       BT_IO_OPT_SOURCE_BDADDR, &idev->src,
> +                                       BT_IO_OPT_DEST_BDADDR, &idev->dst,
> +                                       BT_IO_OPT_PSM, L2CAP_PSM_HIDP_CTRL,
> +                                       BT_IO_OPT_SEC_LEVEL, BT_IO_SEC_LOW,
> +                                       BT_IO_OPT_INVALID);
> +       if (err) {
> +               error("%s", err->message);
> +               g_error_free(err);
> +               input_device_free(idev);
> +               return HAL_STATUS_FAILED;
> +       }
> +
> +       devices = g_slist_append(devices, idev);
> +
> +       return HAL_STATUS_SUCCESS;
> +}
>
>  void bt_hid_handle_cmd(GIOChannel *io, uint8_t opcode, void *buf, uint16_t len)
>  {
> @@ -40,6 +276,7 @@ void bt_hid_handle_cmd(GIOChannel *io, uint8_t opcode, void *buf, uint16_t len)
>
>         switch (opcode) {
>         case HAL_OP_HID_CONNECT:
> +               status = dev_connect((struct hal_cmd_hid_connect *) buf, len);

Call it hid_connect or bt_hid_connect.



-- 
Luiz Augusto von Dentz

^ permalink raw reply

* [PATCH 1/2] android: Add thread-safe helpers
From: Andrei Emeltchenko @ 2013-10-28 15:30 UTC (permalink / raw)
  To: linux-bluetooth
In-Reply-To: <1382969211-7402-1-git-send-email-Andrei.Emeltchenko.news@gmail.com>

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

Add thread safe helpers to make HAL debug printing thread-safe. The code
is inherited from Android bionic and it is used for strerror, strsignal,
etc.
---
 android/pthread-local.h |   53 +++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 53 insertions(+)
 create mode 100644 android/pthread-local.h

diff --git a/android/pthread-local.h b/android/pthread-local.h
new file mode 100644
index 0000000..4bf22f3
--- /dev/null
+++ b/android/pthread-local.h
@@ -0,0 +1,53 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ * Copyright (C) 2013 Intel Corp.
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *  * Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *  * Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <pthread.h>
+#include <stdlib.h>
+
+#define GLOBAL_INIT_THREAD_LOCAL_BUFFER(name) \
+  static pthread_key_t __bionic_tls_ ## name ## _key; \
+  static void __bionic_tls_ ## name ## _key_destroy(void* buffer) { \
+    free(buffer); \
+  } \
+  __attribute__((constructor)) static void __bionic_tls_ ## name ## _key_init() { \
+    pthread_key_create(&__bionic_tls_ ## name ## _key, __bionic_tls_ ## name ## _key_destroy); \
+  }
+
+/*
+ * Leaves "name_tls_buffer" and "name_tls_buffer_size" defined and initialized.
+ */
+#define LOCAL_INIT_THREAD_LOCAL_BUFFER(type, name, byte_count) \
+  const size_t name ## _tls_buffer_size __attribute__((unused)) = byte_count; \
+  type name ## _tls_buffer = \
+      (pthread_getspecific(__bionic_tls_ ## name ## _key)); \
+  if (name ## _tls_buffer == NULL) { \
+    name ## _tls_buffer = (calloc(1, byte_count)); \
+    pthread_setspecific(__bionic_tls_ ## name ## _key, name ## _tls_buffer); \
+  }
-- 
1.7.10.4


^ permalink raw reply related

* [PATCH 2/2] android: Use thread-safe helpers
From: Andrei Emeltchenko @ 2013-10-28 15:30 UTC (permalink / raw)
  To: linux-bluetooth
In-Reply-To: <1382974225-13855-1-git-send-email-Andrei.Emeltchenko.news@gmail.com>

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

Make use of thread-safe helpers.
---
 android/client/textconv.c |   15 ++++++++++-----
 1 file changed, 10 insertions(+), 5 deletions(-)

diff --git a/android/client/textconv.c b/android/client/textconv.c
index 1dc6ad0..c09f47d 100644
--- a/android/client/textconv.c
+++ b/android/client/textconv.c
@@ -19,6 +19,8 @@
 #include <stdio.h>
 #include <hardware/bluetooth.h>
 
+#include "../pthread-local.h"
+
 #include "textconv.h"
 
 /*
@@ -227,11 +229,12 @@ const char *enum_one_string(void *v, int i)
 	return (i == 0) && (m[0] != 0) ? m : NULL;
 }
 
+GLOBAL_INIT_THREAD_LOCAL_BUFFER(bdaddr_buf);
 char *bdaddr2str(const bt_bdaddr_t *bd_addr)
 {
-	static char buf[MAX_ADDR_STR_LEN];
+	LOCAL_INIT_THREAD_LOCAL_BUFFER(char*, bdaddr_buf, MAX_ADDR_STR_LEN);
 
-	return bt_bdaddr_t2str(bd_addr, buf);
+	return bt_bdaddr_t2str(bd_addr, bdaddr_buf_tls_buffer);
 }
 
 static char *btuuid2str(const bt_uuid_t *uuid)
@@ -241,12 +244,14 @@ static char *btuuid2str(const bt_uuid_t *uuid)
 	return bt_uuid_t2str(uuid, buf);
 }
 
+GLOBAL_INIT_THREAD_LOCAL_BUFFER(property_buf);
 char *btproperty2str(const bt_property_t *property)
 {
-	static char buf[4096];
 	char *p;
+	LOCAL_INIT_THREAD_LOCAL_BUFFER(char*, property_buf, 4096);
 
-	p = buf + sprintf(buf, "type=%s len=%d val=",
+	p = property_buf_tls_buffer + sprintf(property_buf_tls_buffer,
+					"type=%s len=%d val=",
 					bt_property_type_t2str(property->type),
 					property->len);
 
@@ -334,5 +339,5 @@ char *btproperty2str(const bt_property_t *property)
 		sprintf(p, "%p", property->val);
 	}
 
-	return buf;
+	return property_buf_tls_buffer;
 }
-- 
1.7.10.4


^ permalink raw reply related

* [PATCH] android/hal: Set callbacks before initializing IPC
From: Szymon Janc @ 2013-10-28 15:45 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Szymon Janc

Notification thread is started on IPC init and it can be scheduled
before main thread.

Fix following crash on HAL init:

pid: 3392, tid: 3492, name: droid.bluetooth  >>> com.android.bluetooth <<<
signal 11 (SIGSEGV), code 1 (SEGV_MAPERR), fault addr 00000028
    eax 00000000  ebx ce047f64  ecx ce0405d0  edx f7763724
    esi cdf3af00  edi f837fb90
    xcs 00000023  xds 0000002b  xes 0000002b  xfs 00000000  xss 0000002b
    eip ce042289  ebp cdf3a9f8  esp cdf3a9e0  flags 00010292

backtrace:
    #00  pc 00003289  /system/lib/hw/bluetooth.default.so (bt_thread_associate+25)
    #01  pc 000015f8  /system/lib/hw/bluetooth.default.so (notification_handler+40)
    #02  pc 0000f804  /system/lib/libc.so (__thread_entry+276)
    #03  pc 0002999d  /system/lib/libc.so
    #04  pc 00082ae7  /system/lib/libdvm.so (dvmThreadSelf()+39)
    #05  pc 00010db9  /system/lib/libc.so (pthread_mutex_unlock+25)
---
 android/hal-bluetooth.c | 8 +++++---
 1 file changed, 5 insertions(+), 3 deletions(-)

diff --git a/android/hal-bluetooth.c b/android/hal-bluetooth.c
index 5929fff..5f6dcbe 100644
--- a/android/hal-bluetooth.c
+++ b/android/hal-bluetooth.c
@@ -114,11 +114,13 @@ static int init(bt_callbacks_t *callbacks)
 	if (interface_ready())
 		return BT_STATUS_SUCCESS;
 
-	if (!hal_ipc_init())
-		return BT_STATUS_FAIL;
-
 	bt_hal_cbacks = callbacks;
 
+	if (!hal_ipc_init()) {
+		bt_hal_cbacks = NULL;
+		return BT_STATUS_FAIL;
+	}
+
 	cmd.service_id = HAL_SERVICE_ID_BLUETOOTH;
 
 	status = hal_ipc_cmd(HAL_SERVICE_ID_CORE, HAL_OP_REGISTER_MODULE,
-- 
1.8.4.1


^ permalink raw reply related

* [PATCH] build: Move Makefile.android to android/Makefile.am
From: Szymon Janc @ 2013-10-28 16:37 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Szymon Janc

This will keep all Android related changes within android directory.
---

Will also fix messing with Marcel's tab completion habits :-)

 Makefile.am         |   2 +-
 Makefile.android    | 113 ----------------------------------------------------
 android/Makefile.am | 113 ++++++++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 114 insertions(+), 114 deletions(-)
 delete mode 100644 Makefile.android
 create mode 100644 android/Makefile.am

diff --git a/Makefile.am b/Makefile.am
index 8aed6f7..69a2805 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -179,7 +179,7 @@ test_scripts =
 
 include Makefile.tools
 include Makefile.obexd
-include Makefile.android
+include android/Makefile.am
 
 if HID2HCI
 rulesdir = @UDEV_DIR@/rules.d
diff --git a/Makefile.android b/Makefile.android
deleted file mode 100644
index 2b57daa..0000000
--- a/Makefile.android
+++ /dev/null
@@ -1,113 +0,0 @@
-if ANDROID
-noinst_PROGRAMS += android/bluetoothd
-
-android_bluetoothd_SOURCES =	android/main.c \
-				src/log.c \
-				android/hal-msg.h \
-				android/utils.h \
-				src/sdpd-database.c src/sdpd-server.c \
-				src/sdpd-service.c src/sdpd-request.c \
-				src/shared/util.h src/shared/util.c \
-				src/shared/mgmt.h src/shared/mgmt.c \
-				android/adapter.h android/adapter.c \
-				android/hid.h android/hid.c \
-				android/ipc.h android/ipc.c \
-				android/socket.h android/socket.c
-
-android_bluetoothd_LDADD = lib/libbluetooth-internal.la @GLIB_LIBS@
-
-noinst_LTLIBRARIES += android/libhal-internal.la
-
-android_libhal_internal_la_SOURCES = android/hal.h android/hal-bluetooth.c \
-					android/hal-sock.c \
-					android/hal-hidhost.c \
-					android/hal-pan.c \
-					android/hal-av.c \
-					android/hardware/bluetooth.h \
-					android/hardware/bt_av.h \
-					android/hardware/bt_gatt.h \
-					android/hardware/bt_gatt_client.h \
-					android/hardware/bt_gatt_server.h \
-					android/hardware/bt_gatt_types.h \
-					android/hardware/bt_hf.h \
-					android/hardware/bt_hh.h \
-					android/hardware/bt_hl.h \
-					android/hardware/bt_pan.h \
-					android/hardware/bt_rc.h \
-					android/hardware/bt_sock.h \
-					android/hardware/hardware.h \
-					android/cutils/properties.h \
-					android/hal-log.h \
-					android/hal-ipc.h android/hal-ipc.c
-
-android_libhal_internal_la_CPPFLAGS = -I$(srcdir)/android
-
-noinst_PROGRAMS += android/haltest
-
-android_haltest_SOURCES = android/client/haltest.c \
-				android/client/pollhandler.c \
-				android/client/terminal.c \
-				android/client/history.c \
-				android/client/textconv.c \
-				android/client/tabcompletion.c \
-				android/client/if-av.c \
-				android/client/if-bt.c \
-				android/client/if-hf.c \
-				android/client/if-hh.c \
-				android/client/if-pan.c \
-				android/client/if-sock.c \
-				android/client/hwmodule.c
-
-android_haltest_LDADD = android/libhal-internal.la
-
-android_haltest_CFLAGS = $(AM_CFLAGS) -I$(srcdir)/android
-
-android_haltest_LDFLAGS = -pthread
-
-endif
-
-EXTRA_DIST += android/Android.mk android/device.c android/adapter.c\
-		android/main.c android/hal-msg.h android/hal.h
-
-EXTRA_DIST += android/hal-bluetooth.c \
-		android/hal-sock.c \
-		android/hal-hidhost.c \
-		android/hal-pan.c \
-		android/hal-av.c \
-		android/hal-log.h
-
-EXTRA_DIST += android/client/terminal.c \
-		android/client/haltest.c \
-		android/client/hwmodule.c \
-		android/client/pollhandler.c \
-		android/client/history.c \
-		android/client/if-av.c \
-		android/client/if-bt.c \
-		android/client/if-hf.c \
-		android/client/if-hh.c \
-		android/client/if-pan.c \
-		android/client/if-sock.c \
-		android/client/textconv.c \
-		android/client/tabcompletion.c \
-		android/client/textconv.h \
-		android/client/if-main.h \
-		android/client/pollhandler.h \
-		android/client/history.h \
-		android/client/terminal.h
-
-EXTRA_DIST += android/hal-ipc-api.txt
-
-EXTRA_DIST += android/hardware/bluetooth.h \
-		android/hardware/bt_av.h \
-		android/hardware/bt_gatt.h \
-		android/hardware/bt_gatt_client.h \
-		android/hardware/bt_gatt_server.h \
-		android/hardware/bt_gatt_types.h \
-		android/hardware/bt_hf.h \
-		android/hardware/bt_hh.h \
-		android/hardware/bt_hl.h \
-		android/hardware/bt_pan.h \
-		android/hardware/bt_rc.h \
-		android/hardware/bt_sock.h \
-		android/hardware/hardware.h \
-		android/cutils/properties.h
diff --git a/android/Makefile.am b/android/Makefile.am
new file mode 100644
index 0000000..2b57daa
--- /dev/null
+++ b/android/Makefile.am
@@ -0,0 +1,113 @@
+if ANDROID
+noinst_PROGRAMS += android/bluetoothd
+
+android_bluetoothd_SOURCES =	android/main.c \
+				src/log.c \
+				android/hal-msg.h \
+				android/utils.h \
+				src/sdpd-database.c src/sdpd-server.c \
+				src/sdpd-service.c src/sdpd-request.c \
+				src/shared/util.h src/shared/util.c \
+				src/shared/mgmt.h src/shared/mgmt.c \
+				android/adapter.h android/adapter.c \
+				android/hid.h android/hid.c \
+				android/ipc.h android/ipc.c \
+				android/socket.h android/socket.c
+
+android_bluetoothd_LDADD = lib/libbluetooth-internal.la @GLIB_LIBS@
+
+noinst_LTLIBRARIES += android/libhal-internal.la
+
+android_libhal_internal_la_SOURCES = android/hal.h android/hal-bluetooth.c \
+					android/hal-sock.c \
+					android/hal-hidhost.c \
+					android/hal-pan.c \
+					android/hal-av.c \
+					android/hardware/bluetooth.h \
+					android/hardware/bt_av.h \
+					android/hardware/bt_gatt.h \
+					android/hardware/bt_gatt_client.h \
+					android/hardware/bt_gatt_server.h \
+					android/hardware/bt_gatt_types.h \
+					android/hardware/bt_hf.h \
+					android/hardware/bt_hh.h \
+					android/hardware/bt_hl.h \
+					android/hardware/bt_pan.h \
+					android/hardware/bt_rc.h \
+					android/hardware/bt_sock.h \
+					android/hardware/hardware.h \
+					android/cutils/properties.h \
+					android/hal-log.h \
+					android/hal-ipc.h android/hal-ipc.c
+
+android_libhal_internal_la_CPPFLAGS = -I$(srcdir)/android
+
+noinst_PROGRAMS += android/haltest
+
+android_haltest_SOURCES = android/client/haltest.c \
+				android/client/pollhandler.c \
+				android/client/terminal.c \
+				android/client/history.c \
+				android/client/textconv.c \
+				android/client/tabcompletion.c \
+				android/client/if-av.c \
+				android/client/if-bt.c \
+				android/client/if-hf.c \
+				android/client/if-hh.c \
+				android/client/if-pan.c \
+				android/client/if-sock.c \
+				android/client/hwmodule.c
+
+android_haltest_LDADD = android/libhal-internal.la
+
+android_haltest_CFLAGS = $(AM_CFLAGS) -I$(srcdir)/android
+
+android_haltest_LDFLAGS = -pthread
+
+endif
+
+EXTRA_DIST += android/Android.mk android/device.c android/adapter.c\
+		android/main.c android/hal-msg.h android/hal.h
+
+EXTRA_DIST += android/hal-bluetooth.c \
+		android/hal-sock.c \
+		android/hal-hidhost.c \
+		android/hal-pan.c \
+		android/hal-av.c \
+		android/hal-log.h
+
+EXTRA_DIST += android/client/terminal.c \
+		android/client/haltest.c \
+		android/client/hwmodule.c \
+		android/client/pollhandler.c \
+		android/client/history.c \
+		android/client/if-av.c \
+		android/client/if-bt.c \
+		android/client/if-hf.c \
+		android/client/if-hh.c \
+		android/client/if-pan.c \
+		android/client/if-sock.c \
+		android/client/textconv.c \
+		android/client/tabcompletion.c \
+		android/client/textconv.h \
+		android/client/if-main.h \
+		android/client/pollhandler.h \
+		android/client/history.h \
+		android/client/terminal.h
+
+EXTRA_DIST += android/hal-ipc-api.txt
+
+EXTRA_DIST += android/hardware/bluetooth.h \
+		android/hardware/bt_av.h \
+		android/hardware/bt_gatt.h \
+		android/hardware/bt_gatt_client.h \
+		android/hardware/bt_gatt_server.h \
+		android/hardware/bt_gatt_types.h \
+		android/hardware/bt_hf.h \
+		android/hardware/bt_hh.h \
+		android/hardware/bt_hl.h \
+		android/hardware/bt_pan.h \
+		android/hardware/bt_rc.h \
+		android/hardware/bt_sock.h \
+		android/hardware/hardware.h \
+		android/cutils/properties.h
-- 
1.8.4.1


^ permalink raw reply related

* Re: Bluetooth tools
From: Vinicius Costa Gomes @ 2013-10-28 19:18 UTC (permalink / raw)
  To: Kevin Wilson; +Cc: linux-bluetooth
In-Reply-To: <CAGXs5wULS_dYYCCyimg3y9Fv6smMp8kOQbN3BfYJ+=bBhbhHxQ@mail.gmail.com>

Hi Kevin,

On 09:40 Sat 26 Oct, Kevin Wilson wrote:
> Hello,
> 
> I saw that bluetoothctl and btmon are the newer tool of Bluetooth.
> 
> What are the advantages of bluetoothctl over hciconfig/hcitool?

I would not say advantages, as they have very different aims, bluetoothctl is
meant to be used in the day-to-day (think scanning for a device, pairing
with it, changing the discoverability, etc); hciconfig/hcitool are more for
development/debugging (think disabling SSP mode, enabling periodic inquiry,
etc), they are more similar to btmgmt than to bluetoothctl.

> 
> What are the advantages of btmon over hcidump ?

btmon also tracks events from the Management interface. And colors ;-)

> 
> 
> Regards,
> Kevin
> --
> To unsubscribe from this list: send the line "unsubscribe linux-bluetooth" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html


Cheers,
-- 
Vinicius

^ permalink raw reply

* [PATCH_v2 1/2] android: Add initial HID connect implementation
From: Ravi kumar Veeramally @ 2013-10-29  8:38 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Ravi kumar Veeramally

Implemented basic HID connect method. Host connects to
bt device at L2CAP level.
---
v2: Updated patches as per Luiz comments

v1: Patchset adds hid connect and disconnect mechanisms at
    L2CAP level. It opens the control channel and interrupt
    channel and listens on io events. UHID, hid server and
    reconnect related features not yet done.
---
 Makefile.android   |    3 +-
 android/Android.mk |    1 +
 android/hid.c      |  245 ++++++++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 248 insertions(+), 1 deletion(-)

diff --git a/Makefile.android b/Makefile.android
index 2b57daa..22002be 100644
--- a/Makefile.android
+++ b/Makefile.android
@@ -12,7 +12,8 @@ android_bluetoothd_SOURCES =	android/main.c \
 				android/adapter.h android/adapter.c \
 				android/hid.h android/hid.c \
 				android/ipc.h android/ipc.c \
-				android/socket.h android/socket.c
+				android/socket.h android/socket.c \
+				btio/btio.h btio/btio.c
 
 android_bluetoothd_LDADD = lib/libbluetooth-internal.la @GLIB_LIBS@
 
diff --git a/android/Android.mk b/android/Android.mk
index 22208e0..28ec465 100644
--- a/android/Android.mk
+++ b/android/Android.mk
@@ -28,6 +28,7 @@ LOCAL_SRC_FILES := \
 	../lib/sdp.c \
 	../lib/bluetooth.c \
 	../lib/hci.c \
+	../btio/btio.c
 
 LOCAL_C_INCLUDES := \
 	$(call include-path-for, glib) \
diff --git a/android/hid.c b/android/hid.c
index f2da0d3..7f9e386 100644
--- a/android/hid.c
+++ b/android/hid.c
@@ -23,16 +23,260 @@
 
 #include <stdint.h>
 #include <stdbool.h>
+#include <errno.h>
+#include <unistd.h>
+#include <fcntl.h>
 
 #include <glib.h>
 
+#include "btio/btio.h"
 #include "lib/bluetooth.h"
+#include "src/shared/mgmt.h"
+
 #include "log.h"
 #include "hal-msg.h"
 #include "ipc.h"
 #include "hid.h"
+#include "adapter.h"
+#include "utils.h"
+
+#define L2CAP_PSM_HIDP_CTRL	0x11
+#define L2CAP_PSM_HIDP_INTR	0x13
+#define MAX_READ_BUFFER		4096
 
 static GIOChannel *notification_io = NULL;
+static GSList *devices = NULL;
+
+struct hid_device {
+	bdaddr_t	dst;
+	GIOChannel	*ctrl_io;
+	GIOChannel	*intr_io;
+	guint		ctrl_watch;
+	guint		intr_watch;
+};
+
+static int device_cmp(gconstpointer s, gconstpointer user_data)
+{
+	const struct hid_device *hdev = s;
+	const bdaddr_t *dst = user_data;
+
+	return bacmp(&hdev->dst, dst);
+}
+
+static void hid_device_free(struct hid_device *hdev)
+{
+	if (hdev->ctrl_watch > 0)
+		g_source_remove(hdev->ctrl_watch);
+
+	if (hdev->intr_watch > 0)
+		g_source_remove(hdev->intr_watch);
+
+	if (hdev->intr_io)
+		g_io_channel_unref(hdev->intr_io);
+
+	if (hdev->ctrl_io)
+		g_io_channel_unref(hdev->ctrl_io);
+
+	devices = g_slist_remove(devices, hdev);
+	g_free(hdev);
+}
+
+static gboolean intr_io_watch_cb(GIOChannel *chan, gpointer data)
+{
+	char buf[MAX_READ_BUFFER];
+	int fd, bread;
+
+	fd = g_io_channel_unix_get_fd(chan);
+	bread = read(fd, buf, sizeof(buf));
+	if (bread < 0) {
+		error("read: %s(%d)", strerror(-errno), -errno);
+		return TRUE;
+	}
+
+	DBG("bytes read %d", bread);
+
+	/* TODO: At this moment only baseband is connected, i.e. mouse
+	 * movements keyboard events doesn't effect on UI. Have to send
+	 * this data to uhid fd for profile connection. */
+
+	return TRUE;
+}
+
+static gboolean intr_watch_cb(GIOChannel *chan, GIOCondition cond,
+								gpointer data)
+{
+	struct hid_device *hdev = data;
+	char address[18];
+
+	if (cond & G_IO_IN)
+		return intr_io_watch_cb(chan, data);
+
+	ba2str(&hdev->dst, address);
+	DBG("Device %s disconnected", address);
+
+	/* Checking for ctrl_watch avoids a double g_io_channel_shutdown since
+	 * it's likely that ctrl_watch_cb has been queued for dispatching in
+	 * this mainloop iteration */
+	if ((cond & (G_IO_HUP | G_IO_ERR)) && hdev->ctrl_watch)
+		g_io_channel_shutdown(chan, TRUE, NULL);
+
+	hdev->intr_watch = 0;
+
+	if (hdev->intr_io) {
+		g_io_channel_unref(hdev->intr_io);
+		hdev->intr_io = NULL;
+	}
+
+	/* Close control channel */
+	if (hdev->ctrl_io && !(cond & G_IO_NVAL))
+		g_io_channel_shutdown(hdev->ctrl_io, TRUE, NULL);
+
+	return FALSE;
+}
+
+static gboolean ctrl_watch_cb(GIOChannel *chan, GIOCondition cond,
+								gpointer data)
+{
+	struct hid_device *hdev = data;
+	char address[18];
+
+	ba2str(&hdev->dst, address);
+	DBG("Device %s disconnected", address);
+
+	/* Checking for intr_watch avoids a double g_io_channel_shutdown since
+	 * it's likely that intr_watch_cb has been queued for dispatching in
+	 * this mainloop iteration */
+	if ((cond & (G_IO_HUP | G_IO_ERR)) && hdev->intr_watch)
+		g_io_channel_shutdown(chan, TRUE, NULL);
+
+	hdev->ctrl_watch = 0;
+
+	if (hdev->ctrl_io) {
+		g_io_channel_unref(hdev->ctrl_io);
+		hdev->ctrl_io = NULL;
+	}
+
+	if (hdev->intr_io && !(cond & G_IO_NVAL))
+		g_io_channel_shutdown(hdev->intr_io, TRUE, NULL);
+
+	return FALSE;
+}
+
+static void interrupt_connect_cb(GIOChannel *chan, GError *conn_err,
+							gpointer user_data)
+{
+	struct hid_device *hdev = user_data;
+
+	DBG("");
+
+	if (conn_err)
+		goto failed;
+
+	/*TODO: Get device details through SDP and create UHID fd and start
+	 * listening on uhid events */
+	hdev->intr_watch = g_io_add_watch(hdev->intr_io,
+				G_IO_IN | G_IO_HUP | G_IO_ERR | G_IO_NVAL,
+				intr_watch_cb, hdev);
+
+	return;
+
+failed:
+	/* So we guarantee the interrupt channel is closed before the
+	 * control channel (if we only do unref GLib will close it only
+	 * after returning control to the mainloop */
+	if (!conn_err)
+		g_io_channel_shutdown(hdev->intr_io, FALSE, NULL);
+
+	g_io_channel_unref(hdev->intr_io);
+	hdev->intr_io = NULL;
+
+	if (hdev->ctrl_io) {
+		g_io_channel_unref(hdev->ctrl_io);
+		hdev->ctrl_io = NULL;
+	}
+}
+
+static void control_connect_cb(GIOChannel *chan, GError *conn_err,
+							gpointer user_data)
+{
+	struct hid_device *hdev = user_data;
+	GError *err = NULL;
+	const bdaddr_t *src = bt_adapter_get_address();
+
+	DBG("");
+
+	if (conn_err) {
+		error("%s", conn_err->message);
+		goto failed;
+	}
+
+	/* Connect to the HID interrupt channel */
+	hdev->intr_io = bt_io_connect(interrupt_connect_cb, hdev, NULL, &err,
+					BT_IO_OPT_SOURCE_BDADDR, src,
+					BT_IO_OPT_DEST_BDADDR, &hdev->dst,
+					BT_IO_OPT_PSM, L2CAP_PSM_HIDP_INTR,
+					BT_IO_OPT_SEC_LEVEL, BT_IO_SEC_LOW,
+					BT_IO_OPT_INVALID);
+	if (!hdev->intr_io) {
+		error("%s", err->message);
+		g_error_free(err);
+		goto failed;
+	}
+
+	hdev->ctrl_watch = g_io_add_watch(hdev->ctrl_io,
+					G_IO_HUP | G_IO_ERR | G_IO_NVAL,
+					ctrl_watch_cb, hdev);
+
+	return;
+
+failed:
+	g_io_channel_unref(hdev->ctrl_io);
+	hdev->ctrl_io = NULL;
+}
+
+static uint8_t bt_hid_connect(struct hal_cmd_hid_connect *cmd, uint16_t len)
+{
+	struct hid_device *hdev;
+	char addr[18];
+	bdaddr_t dst;
+	GSList *l;
+	GError *err = NULL;
+	const bdaddr_t *src = bt_adapter_get_address();
+
+	DBG("");
+
+	if (len < sizeof(*cmd))
+		return HAL_STATUS_INVALID;
+
+	android2bdaddr((bdaddr_t *)&cmd->bdaddr, &dst);
+
+	l = g_slist_find_custom(devices, &dst, device_cmp);
+	if (l)
+		return HAL_STATUS_FAILED;
+
+	hdev = g_new0(struct hid_device, 1);
+	android2bdaddr((bdaddr_t *)&cmd->bdaddr, &hdev->dst);
+	ba2str(&hdev->dst, addr);
+
+	DBG("connecting to %s", addr);
+
+	hdev->ctrl_io = bt_io_connect(control_connect_cb, hdev, NULL, &err,
+					BT_IO_OPT_SOURCE_BDADDR, src,
+					BT_IO_OPT_DEST_BDADDR, &hdev->dst,
+					BT_IO_OPT_PSM, L2CAP_PSM_HIDP_CTRL,
+					BT_IO_OPT_SEC_LEVEL, BT_IO_SEC_LOW,
+					BT_IO_OPT_INVALID);
+	if (err) {
+		error("%s", err->message);
+		g_error_free(err);
+		hid_device_free(hdev);
+		return HAL_STATUS_FAILED;
+	}
+
+	devices = g_slist_append(devices, hdev);
+
+	return HAL_STATUS_SUCCESS;
+}
 
 void bt_hid_handle_cmd(GIOChannel *io, uint8_t opcode, void *buf, uint16_t len)
 {
@@ -40,6 +284,7 @@ void bt_hid_handle_cmd(GIOChannel *io, uint8_t opcode, void *buf, uint16_t len)
 
 	switch (opcode) {
 	case HAL_OP_HID_CONNECT:
+		status = bt_hid_connect(buf, len);
 		break;
 	case HAL_OP_HID_DISCONNECT:
 		break;
-- 
1.7.9.5


^ permalink raw reply related

* [PATCH_v2 2/2] android: Add initial HID disconnect implementation.
From: Ravi kumar Veeramally @ 2013-10-29  8:38 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Ravi kumar Veeramally
In-Reply-To: <1383035920-21599-1-git-send-email-ravikumar.veeramally@linux.intel.com>

Implemented basic HID disconnect method. Host disconnects
with bt device at L2CAP level.
---
 android/hid.c |   23 +++++++++++++++++++++++
 1 file changed, 23 insertions(+)

diff --git a/android/hid.c b/android/hid.c
index 7f9e386..0a26bfe 100644
--- a/android/hid.c
+++ b/android/hid.c
@@ -278,6 +278,28 @@ static uint8_t bt_hid_connect(struct hal_cmd_hid_connect *cmd, uint16_t len)
 	return HAL_STATUS_SUCCESS;
 }
 
+static uint8_t bt_hid_disconnect(struct hal_cmd_hid_disconnect *cmd,
+								uint16_t len)
+{
+	GSList *l;
+	bdaddr_t dst;
+
+	DBG("");
+
+	if (len < sizeof(*cmd))
+		return HAL_STATUS_INVALID;
+
+	android2bdaddr((bdaddr_t *)&cmd->bdaddr, &dst);
+
+	l = g_slist_find_custom(devices, &dst, device_cmp);
+	if (!l)
+		return HAL_STATUS_FAILED;
+
+	hid_device_free(l->data);
+
+	return HAL_STATUS_SUCCESS;
+}
+
 void bt_hid_handle_cmd(GIOChannel *io, uint8_t opcode, void *buf, uint16_t len)
 {
 	uint8_t status = HAL_STATUS_FAILED;
@@ -287,6 +309,7 @@ void bt_hid_handle_cmd(GIOChannel *io, uint8_t opcode, void *buf, uint16_t len)
 		status = bt_hid_connect(buf, len);
 		break;
 	case HAL_OP_HID_DISCONNECT:
+		status = bt_hid_disconnect(buf,	len);
 		break;
 	default:
 		DBG("Unhandled command, opcode 0x%x", opcode);
-- 
1.7.9.5


^ permalink raw reply related

* [PATCH_v3 1/2] android: Add initial HID connect implementation
From: Ravi kumar Veeramally @ 2013-10-29  9:48 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Ravi kumar Veeramally

Implemented basic HID connect method. Host connects to
bt device at L2CAP level.
---
v3: Updated patches as per Luiz comments (remove unnecessary
    type cast and tabs)

v2: Updated patches as per Luiz comments

v1: Patchset adds hid connect and disconnect mechanisms at
    L2CAP level. It opens the control channel and interrupt
    channel and listens on io events. UHID, hid server and
---
 Makefile.android   |    3 +-
 android/Android.mk |    1 +
 android/hid.c      |  245 ++++++++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 248 insertions(+), 1 deletion(-)

diff --git a/Makefile.android b/Makefile.android
index 2b57daa..22002be 100644
--- a/Makefile.android
+++ b/Makefile.android
@@ -12,7 +12,8 @@ android_bluetoothd_SOURCES =	android/main.c \
 				android/adapter.h android/adapter.c \
 				android/hid.h android/hid.c \
 				android/ipc.h android/ipc.c \
-				android/socket.h android/socket.c
+				android/socket.h android/socket.c \
+				btio/btio.h btio/btio.c
 
 android_bluetoothd_LDADD = lib/libbluetooth-internal.la @GLIB_LIBS@
 
diff --git a/android/Android.mk b/android/Android.mk
index 22208e0..28ec465 100644
--- a/android/Android.mk
+++ b/android/Android.mk
@@ -28,6 +28,7 @@ LOCAL_SRC_FILES := \
 	../lib/sdp.c \
 	../lib/bluetooth.c \
 	../lib/hci.c \
+	../btio/btio.c
 
 LOCAL_C_INCLUDES := \
 	$(call include-path-for, glib) \
diff --git a/android/hid.c b/android/hid.c
index f2da0d3..913dab4 100644
--- a/android/hid.c
+++ b/android/hid.c
@@ -23,16 +23,260 @@
 
 #include <stdint.h>
 #include <stdbool.h>
+#include <errno.h>
+#include <unistd.h>
+#include <fcntl.h>
 
 #include <glib.h>
 
+#include "btio/btio.h"
 #include "lib/bluetooth.h"
+#include "src/shared/mgmt.h"
+
 #include "log.h"
 #include "hal-msg.h"
 #include "ipc.h"
 #include "hid.h"
+#include "adapter.h"
+#include "utils.h"
+
+#define L2CAP_PSM_HIDP_CTRL	0x11
+#define L2CAP_PSM_HIDP_INTR	0x13
+#define MAX_READ_BUFFER		4096
 
 static GIOChannel *notification_io = NULL;
+static GSList *devices = NULL;
+
+struct hid_device {
+	bdaddr_t	dst;
+	GIOChannel	*ctrl_io;
+	GIOChannel	*intr_io;
+	guint		ctrl_watch;
+	guint		intr_watch;
+};
+
+static int device_cmp(gconstpointer s, gconstpointer user_data)
+{
+	const struct hid_device *hdev = s;
+	const bdaddr_t *dst = user_data;
+
+	return bacmp(&hdev->dst, dst);
+}
+
+static void hid_device_free(struct hid_device *hdev)
+{
+	if (hdev->ctrl_watch > 0)
+		g_source_remove(hdev->ctrl_watch);
+
+	if (hdev->intr_watch > 0)
+		g_source_remove(hdev->intr_watch);
+
+	if (hdev->intr_io)
+		g_io_channel_unref(hdev->intr_io);
+
+	if (hdev->ctrl_io)
+		g_io_channel_unref(hdev->ctrl_io);
+
+	devices = g_slist_remove(devices, hdev);
+	g_free(hdev);
+}
+
+static gboolean intr_io_watch_cb(GIOChannel *chan, gpointer data)
+{
+	char buf[MAX_READ_BUFFER];
+	int fd, bread;
+
+	fd = g_io_channel_unix_get_fd(chan);
+	bread = read(fd, buf, sizeof(buf));
+	if (bread < 0) {
+		error("read: %s(%d)", strerror(errno), -errno);
+		return TRUE;
+	}
+
+	DBG("bytes read %d", bread);
+
+	/* TODO: At this moment only baseband is connected, i.e. mouse
+	 * movements keyboard events doesn't effect on UI. Have to send
+	 * this data to uhid fd for profile connection. */
+
+	return TRUE;
+}
+
+static gboolean intr_watch_cb(GIOChannel *chan, GIOCondition cond,
+								gpointer data)
+{
+	struct hid_device *hdev = data;
+	char address[18];
+
+	if (cond & G_IO_IN)
+		return intr_io_watch_cb(chan, data);
+
+	ba2str(&hdev->dst, address);
+	DBG("Device %s disconnected", address);
+
+	/* Checking for ctrl_watch avoids a double g_io_channel_shutdown since
+	 * it's likely that ctrl_watch_cb has been queued for dispatching in
+	 * this mainloop iteration */
+	if ((cond & (G_IO_HUP | G_IO_ERR)) && hdev->ctrl_watch)
+		g_io_channel_shutdown(chan, TRUE, NULL);
+
+	hdev->intr_watch = 0;
+
+	if (hdev->intr_io) {
+		g_io_channel_unref(hdev->intr_io);
+		hdev->intr_io = NULL;
+	}
+
+	/* Close control channel */
+	if (hdev->ctrl_io && !(cond & G_IO_NVAL))
+		g_io_channel_shutdown(hdev->ctrl_io, TRUE, NULL);
+
+	return FALSE;
+}
+
+static gboolean ctrl_watch_cb(GIOChannel *chan, GIOCondition cond,
+								gpointer data)
+{
+	struct hid_device *hdev = data;
+	char address[18];
+
+	ba2str(&hdev->dst, address);
+	DBG("Device %s disconnected", address);
+
+	/* Checking for intr_watch avoids a double g_io_channel_shutdown since
+	 * it's likely that intr_watch_cb has been queued for dispatching in
+	 * this mainloop iteration */
+	if ((cond & (G_IO_HUP | G_IO_ERR)) && hdev->intr_watch)
+		g_io_channel_shutdown(chan, TRUE, NULL);
+
+	hdev->ctrl_watch = 0;
+
+	if (hdev->ctrl_io) {
+		g_io_channel_unref(hdev->ctrl_io);
+		hdev->ctrl_io = NULL;
+	}
+
+	if (hdev->intr_io && !(cond & G_IO_NVAL))
+		g_io_channel_shutdown(hdev->intr_io, TRUE, NULL);
+
+	return FALSE;
+}
+
+static void interrupt_connect_cb(GIOChannel *chan, GError *conn_err,
+							gpointer user_data)
+{
+	struct hid_device *hdev = user_data;
+
+	DBG("");
+
+	if (conn_err)
+		goto failed;
+
+	/*TODO: Get device details through SDP and create UHID fd and start
+	 * listening on uhid events */
+	hdev->intr_watch = g_io_add_watch(hdev->intr_io,
+				G_IO_IN | G_IO_HUP | G_IO_ERR | G_IO_NVAL,
+				intr_watch_cb, hdev);
+
+	return;
+
+failed:
+	/* So we guarantee the interrupt channel is closed before the
+	 * control channel (if we only do unref GLib will close it only
+	 * after returning control to the mainloop */
+	if (!conn_err)
+		g_io_channel_shutdown(hdev->intr_io, FALSE, NULL);
+
+	g_io_channel_unref(hdev->intr_io);
+	hdev->intr_io = NULL;
+
+	if (hdev->ctrl_io) {
+		g_io_channel_unref(hdev->ctrl_io);
+		hdev->ctrl_io = NULL;
+	}
+}
+
+static void control_connect_cb(GIOChannel *chan, GError *conn_err,
+							gpointer user_data)
+{
+	struct hid_device *hdev = user_data;
+	GError *err = NULL;
+	const bdaddr_t *src = bt_adapter_get_address();
+
+	DBG("");
+
+	if (conn_err) {
+		error("%s", conn_err->message);
+		goto failed;
+	}
+
+	/* Connect to the HID interrupt channel */
+	hdev->intr_io = bt_io_connect(interrupt_connect_cb, hdev, NULL, &err,
+					BT_IO_OPT_SOURCE_BDADDR, src,
+					BT_IO_OPT_DEST_BDADDR, &hdev->dst,
+					BT_IO_OPT_PSM, L2CAP_PSM_HIDP_INTR,
+					BT_IO_OPT_SEC_LEVEL, BT_IO_SEC_LOW,
+					BT_IO_OPT_INVALID);
+	if (!hdev->intr_io) {
+		error("%s", err->message);
+		g_error_free(err);
+		goto failed;
+	}
+
+	hdev->ctrl_watch = g_io_add_watch(hdev->ctrl_io,
+					G_IO_HUP | G_IO_ERR | G_IO_NVAL,
+					ctrl_watch_cb, hdev);
+
+	return;
+
+failed:
+	g_io_channel_unref(hdev->ctrl_io);
+	hdev->ctrl_io = NULL;
+}
+
+static uint8_t bt_hid_connect(struct hal_cmd_hid_connect *cmd, uint16_t len)
+{
+	struct hid_device *hdev;
+	char addr[18];
+	bdaddr_t dst;
+	GSList *l;
+	GError *err = NULL;
+	const bdaddr_t *src = bt_adapter_get_address();
+
+	DBG("");
+
+	if (len < sizeof(*cmd))
+		return HAL_STATUS_INVALID;
+
+	android2bdaddr(&cmd->bdaddr, &dst);
+
+	l = g_slist_find_custom(devices, &dst, device_cmp);
+	if (l)
+		return HAL_STATUS_FAILED;
+
+	hdev = g_new0(struct hid_device, 1);
+	android2bdaddr(&cmd->bdaddr, &hdev->dst);
+	ba2str(&hdev->dst, addr);
+
+	DBG("connecting to %s", addr);
+
+	hdev->ctrl_io = bt_io_connect(control_connect_cb, hdev, NULL, &err,
+					BT_IO_OPT_SOURCE_BDADDR, src,
+					BT_IO_OPT_DEST_BDADDR, &hdev->dst,
+					BT_IO_OPT_PSM, L2CAP_PSM_HIDP_CTRL,
+					BT_IO_OPT_SEC_LEVEL, BT_IO_SEC_LOW,
+					BT_IO_OPT_INVALID);
+	if (err) {
+		error("%s", err->message);
+		g_error_free(err);
+		hid_device_free(hdev);
+		return HAL_STATUS_FAILED;
+	}
+
+	devices = g_slist_append(devices, hdev);
+
+	return HAL_STATUS_SUCCESS;
+}
 
 void bt_hid_handle_cmd(GIOChannel *io, uint8_t opcode, void *buf, uint16_t len)
 {
@@ -40,6 +284,7 @@ void bt_hid_handle_cmd(GIOChannel *io, uint8_t opcode, void *buf, uint16_t len)
 
 	switch (opcode) {
 	case HAL_OP_HID_CONNECT:
+		status = bt_hid_connect(buf, len);
 		break;
 	case HAL_OP_HID_DISCONNECT:
 		break;
-- 
1.7.9.5


^ permalink raw reply related

* [PATCH_v3 2/2] android: Add initial HID disconnect implementation.
From: Ravi kumar Veeramally @ 2013-10-29  9:48 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Ravi kumar Veeramally
In-Reply-To: <1383040097-15475-1-git-send-email-ravikumar.veeramally@linux.intel.com>

Implemented basic HID disconnect method. Host disconnects
with bt device at L2CAP level.
---
 android/hid.c |   23 +++++++++++++++++++++++
 1 file changed, 23 insertions(+)

diff --git a/android/hid.c b/android/hid.c
index 913dab4..3479f80 100644
--- a/android/hid.c
+++ b/android/hid.c
@@ -278,6 +278,28 @@ static uint8_t bt_hid_connect(struct hal_cmd_hid_connect *cmd, uint16_t len)
 	return HAL_STATUS_SUCCESS;
 }
 
+static uint8_t bt_hid_disconnect(struct hal_cmd_hid_disconnect *cmd,
+								uint16_t len)
+{
+	GSList *l;
+	bdaddr_t dst;
+
+	DBG("");
+
+	if (len < sizeof(*cmd))
+		return HAL_STATUS_INVALID;
+
+	android2bdaddr(&cmd->bdaddr, &dst);
+
+	l = g_slist_find_custom(devices, &dst, device_cmp);
+	if (!l)
+		return HAL_STATUS_FAILED;
+
+	hid_device_free(l->data);
+
+	return HAL_STATUS_SUCCESS;
+}
+
 void bt_hid_handle_cmd(GIOChannel *io, uint8_t opcode, void *buf, uint16_t len)
 {
 	uint8_t status = HAL_STATUS_FAILED;
@@ -287,6 +309,7 @@ void bt_hid_handle_cmd(GIOChannel *io, uint8_t opcode, void *buf, uint16_t len)
 		status = bt_hid_connect(buf, len);
 		break;
 	case HAL_OP_HID_DISCONNECT:
+		status = bt_hid_disconnect(buf,	len);
 		break;
 	default:
 		DBG("Unhandled command, opcode 0x%x", opcode);
-- 
1.7.9.5


^ permalink raw reply related

* Intel 7260 bluetooth malfunction when it is connected to EHCI bus
From: Hui Wang @ 2013-10-29 10:03 UTC (permalink / raw)
  To: tedd.an, johan.hedberg, marcel, xiong.y.zhang, gustavo.padovan
  Cc: linux-bluetooth

The problem is:
On the machine which has Intel 7260 BT module, i use it to connect a 
bluetooth headset,
it can successfully scan and connect to the headset, when i play sound 
to the bt headset,
the problem comes, if the bt module is connected to the XHCI, it can 
work very well.

u@u-Lenovo-B4400:~$ lsusb -t
1-7:1.0: No such file or directory
/: Bus 02.Port 1: Dev 1, Class=root_hub, Driver=xhci_hcd/4p, 5000M
/: Bus 01.Port 1: Dev 1, Class=root_hub, Driver=xhci_hcd/14p, 480M
     |__ Port 6: Dev 8, If 0, Class=HID, Driver=usbhid, 1.5M
     |__ Port 7: Dev 2, If 0, Class=vend., Driver=, 12M
     |__ Port 11: Dev 3, If 0, Class='bInterfaceClass 0xe0 not yet 
handled', Driver=btusb, 12M
     |__ Port 11: Dev 3, If 1, Class='bInterfaceClass 0xe0 not yet 
handled', Driver=btusb, 12M

But if the bt module is connected to the EHCI, it always fails to play 
sound.

u@u-Lenovo-B4400:~$ lsusb -t
/: Bus 04.Port 1: Dev 1, Class=root_hub, Driver=xhci_hcd/4p, 5000M
/: Bus 03.Port 1: Dev 1, Class=root_hub, Driver=xhci_hcd/14p, 480M
/: Bus 02.Port 1: Dev 1, Class=root_hub, Driver=ehci_hcd/3p, 480M
     |__ Port 1: Dev 2, If 0, Class=hub, Driver=hub/8p, 480M
/: Bus 01.Port 1: Dev 1, Class=root_hub, Driver=ehci_hcd/3p, 480M
     |__ Port 1: Dev 2, If 0, Class=hub, Driver=hub/6p, 480M
         |__ Port 5: Dev 3, If 0, Class='bInterfaceClass 0xe0 not yet 
handled', Driver=btusb, 12M
         |__ Port 5: Dev 3, If 1, Class='bInterfaceClass 0xe0 not yet 
handled', Driver=btusb, 12M
         |__ Port 6: Dev 4, If 0, Class='bInterfaceClass 0x0e not yet 
handled', Driver=uvcvideo, 480M
         |__ Port 6: Dev 4, If 1, Class='bInterfaceClass 0x0e not yet 
handled', Driver=uvcvideo, 480M

---------------------------------------------------------------------------------------------------------
The BT moudle version, firmware version and linux kernel version:
dmesg snippet,
[    2.164386] Bluetooth: hci0: read Intel version: 370710018002030d00
[    2.200701] Bluetooth: hci0: Intel Bluetooth firmware file: 
intel/ibt-hw-37.7.10-fw-1.80.2.3.d.bseq

And the firmware was got from 
http://permalink.gmane.org/gmane.linux.bluez.kernel/37580.

To verify the firmware is the latest, i execute following commands,
u@u-Lenovo-B4400:~$ sudo hcitool cmd 0x3f 0x005 0x00
< HCI Command: ogf 0x3f, ocf 0x0005, plen 1
   00
 > HCI Event: 0x0e plen 13
   01 05 FC 00 37 07 10 01 80 02 03 0D 2E

On the machine, i installed ubuntu-12.04 (kernel is 3.5), then i 
replaced the kernel to the linux-3.8 and
the latest upstream kernel linux-3.12.0-rc6, the situation had no 
difference, the problem still can be
reproduced on very linux kernel version.

----------------------------------------------------------------------------------------------------------
My investigation:

I did the test on dozens of laptops on which all installed intel 7260 
wifi+bt combo, in case the bt module
is connected to EHCI bus, it will 100% fail to play sound to the bt 
headset. If the bt module is connected
to the XHCI bus, it will work very well, including play audio to a bt 
headset.

And more investigation show, if the bt module is on the EHCI bus, it 
can't receive any SCO packet like this,
u@u-Lenovo-B4400:~$ hciconfig
hci0: Type: BR/EDR Bus: USB
  BD Address: 00:15:00:CC:2D:D2 ACL MTU: 1021:5 SCO MTU: 96:5
  UP RUNNING PSCAN
  RX bytes:6687 acl:61 sco:0 events:308 errors:0
  TX bytes:19367 acl:70 sco:3 commands:179 errors:0

if the bt module is on the XHCI bus, it can transmit and receive SCO 
packets very well,
u@u-Lenovo-B4400:~$ hciconfig
hci0: Type: BR/EDR Bus: USB
  BD Address: 00:15:00:CC:2D:D2 ACL MTU: 1021:5 SCO MTU: 96:5
  UP RUNNING PSCAN
  RX bytes:572756 acl:47 sco:11173 events:221 errors:0
  TX bytes:586261 acl:55 sco:11137 commands:137 errors:0

----------------------------------------------------------------------------------------------------------
So could anybody be kindly help to confirm this problem,  and could the 
maintainer of intel 7260 bt driver/firmware
be kindly to solve this problem?

Thanks in advance.

Hui.

^ permalink raw reply

* [PATCH 1/5] android: Define class of device as four bytes in IPC doc
From: Szymon Janc @ 2013-10-29 10:07 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Szymon Janc

For PIN and SSP requests callback define CoD as 4 bytes. This will
allow HAL library to pass CoD direclty to callback. Will also match
how CoD is passed as property.
---
 android/hal-ipc-api.txt | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/android/hal-ipc-api.txt b/android/hal-ipc-api.txt
index dc0d067..e7af8a3 100644
--- a/android/hal-ipc-api.txt
+++ b/android/hal-ipc-api.txt
@@ -354,13 +354,13 @@ Notifications:
 
 		Notification parameters: Remote address (6 octets)
 		                         Remote name (249 octets)
-		                         Class of device (3 octets)
+		                         Class of device (4 octets)
 
 	Opcode 0x87 - SSP Request notification
 
 		Notification parameters: Remote address (6 octets)
 		                         Remote name (249 octets)
-		                         Class of device (3 octets)
+		                         Class of device (4 octets)
 		                         Pairing variant (1 octet)
 		                         Passkey (4 octets)
 
-- 
1.8.4.1


^ permalink raw reply related

* [PATCH 2/5] android: Update IPC headers to match SSP and PIN requests events
From: Szymon Janc @ 2013-10-29 10:07 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Szymon Janc
In-Reply-To: <1383041255-26549-1-git-send-email-szymon.janc@tieto.com>

Name should be 249 bytes so it is always NULL terminated string.
Class of device is send as uint32. This will allow to make simple
passing of data in HAL library without need of copying data.
---
 android/hal-msg.h | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/android/hal-msg.h b/android/hal-msg.h
index a4eb2a8..80b47d6 100644
--- a/android/hal-msg.h
+++ b/android/hal-msg.h
@@ -356,15 +356,15 @@ struct hal_ev_discovery_state_changed {
 #define HAL_EV_PIN_REQUEST		0x86
 struct hal_ev_pin_request {
 	uint8_t bdaddr[6];
-	uint8_t name[249 - 1];
-	uint8_t class_of_dev[3];
+	uint8_t name[249];
+	uint32_t class_of_dev;
 } __attribute__((packed));
 
 #define HAL_EV_SSP_REQUEST		0x87
 struct hal_ev_ssp_request {
 	uint8_t  bdaddr[6];
-	uint8_t  name[249 - 1];
-	uint8_t  class_of_dev[3];
+	uint8_t  name[249];
+	uint32_t  class_of_dev;
 	uint8_t  pairing_variant;
 	uint32_t passkey;
 } __attribute__((packed));
-- 
1.8.4.1


^ permalink raw reply related

* [PATCH 3/5] android/hal: Add support for handling bond state change event
From: Szymon Janc @ 2013-10-29 10:07 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Szymon Janc
In-Reply-To: <1383041255-26549-1-git-send-email-szymon.janc@tieto.com>

---
 android/hal-bluetooth.c | 14 ++++++++++++++
 1 file changed, 14 insertions(+)

diff --git a/android/hal-bluetooth.c b/android/hal-bluetooth.c
index 5f6dcbe..067f420 100644
--- a/android/hal-bluetooth.c
+++ b/android/hal-bluetooth.c
@@ -68,6 +68,17 @@ static void handle_adapter_props_changed(void *buf, uint16_t len)
 	bt_hal_cbacks->adapter_properties_cb(ev->status, ev->num_props, props);
 }
 
+static void handle_bond_state_change(void *buf)
+{
+	struct hal_ev_bond_state_changed *ev = buf;
+	bt_bdaddr_t *addr = (bt_bdaddr_t *) ev->bdaddr;
+
+	if (!bt_hal_cbacks->bond_state_changed_cb)
+		return;
+
+	bt_hal_cbacks->bond_state_changed_cb(ev->status, addr, ev->state);
+}
+
 void bt_thread_associate(void)
 {
 	if (bt_hal_cbacks->thread_evt_cb)
@@ -98,6 +109,9 @@ void bt_notify_adapter(uint16_t opcode, void *buf, uint16_t len)
 	case HAL_EV_ADAPTER_PROPS_CHANGED:
 		handle_adapter_props_changed(buf, len);
 		break;
+	case HAL_EV_BOND_STATE_CHANGED:
+		handle_bond_state_change(buf);
+		break;
 	default:
 		DBG("Unhandled callback opcode=0x%x", opcode);
 		break;
-- 
1.8.4.1


^ permalink raw reply related


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