Linux bluetooth development
 help / color / mirror / Atom feed
* [PATCH 0/3] android: add support for hidhost to haltest
From: Jerzy Kasenberg @ 2013-10-22 11:02 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Jerzy Kasenberg

- adds support for hidhost
- adds tab completion for hidhost
- adds help for hidhost
- magic number to #define change for buffer sizes

Jerzy Kasenberg (3):
  android: Add definition of buffer sizes to haltest
  android: Add calls to hidhost interface to haltest
  android: Add help to hidhost in haltest

 Makefile.android          |    2 +
 android/Android.mk        |    1 +
 android/client/haltest.c  |    1 +
 android/client/if-bt.c    |   10 +-
 android/client/if-hh.c    |  431 +++++++++++++++++++++++++++++++++++++++++++++
 android/client/if-main.h  |    2 +
 android/client/textconv.c |    2 +-
 android/client/textconv.h |    2 +
 8 files changed, 445 insertions(+), 6 deletions(-)
 create mode 100644 android/client/if-hh.c

-- 
1.7.9.5


^ permalink raw reply

* [PATCH 2/2] android/hal: Add initial support for handling adapter notifications
From: Szymon Janc @ 2013-10-22 10:59 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Szymon Janc
In-Reply-To: <1382439549-18281-1-git-send-email-szymon.janc@tieto.com>

Only adapter state callback is handled for now.
---
 android/hal-bluetooth.c | 24 ++++++++++++++++++++++++
 android/hal-ipc.c       |  6 ++++++
 android/hal.h           |  2 ++
 3 files changed, 32 insertions(+)

diff --git a/android/hal-bluetooth.c b/android/hal-bluetooth.c
index 5b07070..37edb41 100644
--- a/android/hal-bluetooth.c
+++ b/android/hal-bluetooth.c
@@ -32,6 +32,30 @@
 
 bt_callbacks_t *bt_hal_cbacks = NULL;
 
+static void handle_adapter_state_changed(void *buf)
+{
+	struct hal_msg_ev_bt_adapter_state_changed *ev = buf;
+
+	if (bt_hal_cbacks->adapter_state_changed_cb)
+		bt_hal_cbacks->adapter_state_changed_cb(ev->state);
+}
+
+/* will be called from notification thread context */
+void bt_notify_adapter(uint16_t opcode, void *buf, uint16_t len, int fd)
+{
+	if (!bt_hal_cbacks)
+		return;
+
+	switch (opcode) {
+	case HAL_MSG_EV_BT_ADAPTER_STATE_CHANGED:
+		handle_adapter_state_changed(buf);
+		break;
+	default:
+		DBG("Unhandled callback opcode=0x%x", opcode);
+		break;
+	}
+}
+
 static bool interface_ready(void)
 {
 	return bt_hal_cbacks != NULL;
diff --git a/android/hal-ipc.c b/android/hal-ipc.c
index ef58a7c..ccdcb9f 100644
--- a/android/hal-ipc.c
+++ b/android/hal-ipc.c
@@ -27,6 +27,9 @@
 
 #include <cutils/properties.h>
 
+#include <hardware/bluetooth.h>
+#include "hal.h"
+
 #include "hal-msg.h"
 #include "hal-log.h"
 #include "hal-ipc.h"
@@ -44,6 +47,9 @@ static pthread_t notif_th = 0;
 static void notification_dispatch(struct hal_msg_hdr *msg, int fd)
 {
 	switch (msg->service_id) {
+	case HAL_SERVICE_ID_BLUETOOTH:
+		bt_notify_adapter(msg->opcode, msg + 1, msg->len, fd);
+		break;
 	default:
 		DBG("Unhandled notification service=%d opcode=0x%x",
 						msg->service_id, msg->opcode);
diff --git a/android/hal.h b/android/hal.h
index d984336..889fce6 100644
--- a/android/hal.h
+++ b/android/hal.h
@@ -24,3 +24,5 @@ btsock_interface_t *bt_get_sock_interface(void);
 bthh_interface_t *bt_get_hidhost_interface(void);
 btpan_interface_t *bt_get_pan_interface(void);
 btav_interface_t *bt_get_av_interface(void);
+
+void bt_notify_adapter(uint16_t opcode, void *buf, uint16_t len, int fd);
-- 
1.8.4


^ permalink raw reply related

* [PATCH 1/2] android/hal: Add initial code for notification handling
From: Szymon Janc @ 2013-10-22 10:59 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Szymon Janc

This adds a dedicated thread that will read from notification sockets
and dispatch it to appropriate service notification function.
---
 Makefile.android  |   2 +
 android/hal-ipc.c | 107 +++++++++++++++++++++++++++++++++++++++++++++++++++++-
 2 files changed, 107 insertions(+), 2 deletions(-)

diff --git a/Makefile.android b/Makefile.android
index aebc715..889b36e 100644
--- a/Makefile.android
+++ b/Makefile.android
@@ -54,6 +54,8 @@ 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/log.c android/device.c \
diff --git a/android/hal-ipc.c b/android/hal-ipc.c
index 8d40271..ef58a7c 100644
--- a/android/hal-ipc.c
+++ b/android/hal-ipc.c
@@ -39,6 +39,95 @@ static int notif_sk = -1;
 
 static pthread_mutex_t cmd_sk_mutex = PTHREAD_MUTEX_INITIALIZER;
 
+static pthread_t notif_th = 0;
+
+static void notification_dispatch(struct hal_msg_hdr *msg, int fd)
+{
+	switch (msg->service_id) {
+	default:
+		DBG("Unhandled notification service=%d opcode=0x%x",
+						msg->service_id, msg->opcode);
+		break;
+	}
+}
+
+static void *notification_handler(void *data)
+{
+	struct msghdr msg;
+	struct iovec iv;
+	struct cmsghdr *cmsg;
+	char cmsgbuf[CMSG_SPACE(sizeof(int))];
+	char buf[BLUEZ_HAL_MTU];
+	struct hal_msg_hdr *hal_msg = (void *) buf;
+	ssize_t ret;
+	int fd;
+
+	while (true) {
+		memset(&msg, 0, sizeof(msg));
+		memset(buf, 0, sizeof(buf));
+		memset(cmsgbuf, 0, sizeof(cmsgbuf));
+
+		iv.iov_base = hal_msg;
+		iv.iov_len = sizeof(buf);
+
+		msg.msg_iov = &iv;
+		msg.msg_iovlen = 1;
+
+		msg.msg_control = cmsgbuf;
+		msg.msg_controllen = sizeof(cmsgbuf);
+
+		ret = recvmsg(notif_sk, &msg, 0);
+		if (ret < 0) {
+			error("Receiving notifications failed, aborting :%s",
+							strerror(errno));
+			exit(EXIT_FAILURE);
+		}
+
+		/* socket was shutdown */
+		if (ret == 0)
+			break;
+
+		if (ret < (ssize_t) sizeof(*hal_msg)) {
+			error("Too small notification (%zd bytes), aborting",
+									ret);
+			exit(EXIT_FAILURE);
+		}
+
+		if (hal_msg->opcode < HAL_MSG_EV_BT_ERROR) {
+			error("Invalid notification (0x%x), aborting",
+							hal_msg->opcode);
+			exit(EXIT_FAILURE);
+		}
+
+		if (ret != (ssize_t) (sizeof(*hal_msg) + hal_msg->len)) {
+			error("Malformed notification(%zd bytes), aborting",
+									ret);
+			exit(EXIT_FAILURE);
+		}
+
+		fd = -1;
+
+		/* Receive auxiliary data in msg */
+		for (cmsg = CMSG_FIRSTHDR(&msg); !cmsg;
+					cmsg = CMSG_NXTHDR(&msg, cmsg)) {
+			if (cmsg->cmsg_level == SOL_SOCKET
+					&& cmsg->cmsg_type == SCM_RIGHTS) {
+				memcpy(&fd, CMSG_DATA(cmsg), sizeof(int));
+				break;
+			}
+		}
+
+		notification_dispatch(hal_msg, fd);
+	}
+
+	close(notif_sk);
+	notif_sk = -1;
+
+	DBG("exit");
+
+	return NULL;
+}
+
 static int accept_connection(int sk)
 {
 	int err;
@@ -126,6 +215,18 @@ bool hal_ipc_init(void)
 
 	close(sk);
 
+	err = pthread_create(&notif_th, NULL, notification_handler, NULL);
+	if (err < 0) {
+		notif_th = 0;
+		error("Failed to start notification thread: %d (%s)", -err,
+							strerror(-err));
+		close(cmd_sk);
+		cmd_sk = -1;
+		close(notif_sk);
+		notif_sk = -1;
+		return false;
+	}
+
 	return true;
 }
 
@@ -134,8 +235,10 @@ void hal_ipc_cleanup(void)
 	close(cmd_sk);
 	cmd_sk = -1;
 
-	close(notif_sk);
-	notif_sk = -1;
+	shutdown(notif_sk, SHUT_RD);
+
+	pthread_join(notif_th, NULL);
+	notif_th = 0;
 }
 
 int hal_ipc_cmd(uint8_t service_id, uint8_t opcode, uint16_t len, void *param,
-- 
1.8.4


^ permalink raw reply related

* Re: [PATCH] android: Fix compilation error for Android 4.2.2
From: Johan Hedberg @ 2013-10-22 10:44 UTC (permalink / raw)
  To: Andrei Emeltchenko; +Cc: linux-bluetooth
In-Reply-To: <1382436600-8598-1-git-send-email-Andrei.Emeltchenko.news@gmail.com>

Hi Andrei,

On Tue, Oct 22, 2013, Andrei Emeltchenko wrote:
> ---
>  android/client/if-bt.c | 2 ++
>  1 file changed, 2 insertions(+)
> 
> diff --git a/android/client/if-bt.c b/android/client/if-bt.c
> index 5447e0c..330a3fa 100644
> --- a/android/client/if-bt.c
> +++ b/android/client/if-bt.c
> @@ -364,11 +364,13 @@ static void dut_mode_recv_cb(uint16_t opcode, uint8_t *buf, uint8_t len)
>  	haltest_info("%s\n", __func__);
>  }
>  
> +#if PLATFORM_SDK_VERSION > 17
>  static void le_test_mode_cb(bt_status_t status, uint16_t num_packets)
>  {
>  	haltest_info("%s %s %d\n", __func__, bt_state_t2str(status),
>  								num_packets);
>  }
> +#endif
>  
>  static bt_callbacks_t bt_callbacks = {
>  	.size = sizeof(bt_callbacks),

Seems like you're missing a matching conditional for the bt_callbacks
part.

Johan

^ permalink raw reply

* [PATCH] android: HID host
From: Andrei Emeltchenko @ 2013-10-22 10:43 UTC (permalink / raw)
  To: linux-bluetooth

From: Frederic Danis <frederic.danis@linux.intel.com>

Basic implementation of HID host for Android.
---
 android/hidhost-device.c | 975 +++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 975 insertions(+)
 create mode 100644 android/hidhost-device.c

diff --git a/android/hidhost-device.c b/android/hidhost-device.c
new file mode 100644
index 0000000..eb3849d
--- /dev/null
+++ b/android/hidhost-device.c
@@ -0,0 +1,975 @@
+/*
+ *
+ *  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
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdlib.h>
+#include <stdbool.h>
+#include <errno.h>
+#include <fcntl.h>
+
+#include <glib.h>
+
+#include <bluetooth/bluetooth.h>
+#include <bluetooth/sdp.h>
+#include <bluetooth/sdp_lib.h>
+#include <btio/btio.h>
+
+#include <linux/uhid.h>
+
+#include "log.h"
+#include "src/shared/mgmt.h"
+#include "adapter.h"
+#include "device.h"
+
+#define L2CAP_PSM_HIDP_CTRL	0x11
+#define L2CAP_PSM_HIDP_INTR	0x13
+
+#define UHID_DEVICE_FILE	"/dev/uhid"
+
+#define REPORT_MAP_MAX_SIZE	512
+
+enum reconnect_mode_t {
+	RECONNECT_NONE = 0,
+	RECONNECT_DEVICE,
+	RECONNECT_HOST,
+	RECONNECT_ANY
+};
+
+struct input_device {
+/*	struct btd_service	*service;
+*/
+	struct bt_device	*device;
+/*	char			*path;
+*/
+	bdaddr_t		src;
+	bdaddr_t		dst;
+/*	uint32_t		handle;
+*/
+	GIOChannel		*ctrl_io;
+	GIOChannel		*intr_io;
+	guint			ctrl_watch;
+	guint			intr_watch;
+/*	guint			sec_watch;
+*/
+	guint			uhid_watch_id;
+/*	struct hidp_connadd_req *req;
+*/
+	guint			dc_id;
+/*	bool			disable_sdp;
+	char			*name;
+*/
+	enum reconnect_mode_t	reconnect_mode;
+	guint			reconnect_timer;
+	uint32_t		reconnect_attempt;
+	int			uhid_fd;
+};
+
+static GSList *conns = NULL;
+
+static struct input_device *find_conn(GSList *list,
+						const bdaddr_t *bd_addr)
+{
+	for (; list; list = list->next) {
+		struct input_device *idev = list->data;
+
+		if (bacmp(bd_addr, bt_device_get_address(idev->device)))
+			return idev;
+	}
+
+	return NULL;
+}
+
+static void input_device_enter_reconnect_mode(struct input_device *idev);
+
+static gboolean intr_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 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);
+
+	bt_device_remove_disconnect_watch(idev->device, idev->dc_id);
+	idev->dc_id = 0;
+
+	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);
+
+	/* TODO:
+	btd_service_disconnecting_complete(idev->service, 0);
+	*/
+
+	/* Enter the auto-reconnect mode if needed */
+	input_device_enter_reconnect_mode(idev);
+
+	return FALSE;
+}
+
+static void ctrl_disconnected(struct input_device *idev, GIOChannel *chan,
+							GIOCondition cond)
+{
+	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;
+	}
+
+	/* Close interrupt channel */
+	if (idev->intr_io && !(cond & G_IO_NVAL))
+		g_io_channel_shutdown(idev->intr_io, TRUE, NULL);
+}
+
+static gboolean ctrl_watch_cb(GIOChannel *chan, GIOCondition cond,
+				gpointer data)
+{
+	struct input_device *idev = data;
+#if 0
+	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;
+	}
+
+	/* Close interrupt channel */
+	if (idev->intr_io && !(cond & G_IO_NVAL))
+		g_io_channel_shutdown(idev->intr_io, TRUE, NULL);
+
+	return FALSE;
+#else
+	if (cond & (G_IO_HUP | G_IO_ERR | G_IO_NVAL)) {
+		/* TODO: */
+		;
+	}
+
+	return TRUE;
+#endif
+}
+
+#ifndef STORAGEDIR
+#define STORAGEDIR "/var/lib/bluetooth"
+#endif
+
+sdp_record_t *record_from_string(const char *str)
+{
+	sdp_record_t *rec;
+	int size, i, len;
+	uint8_t *pdata;
+	char tmp[3];
+
+	size = strlen(str)/2;
+	pdata = g_malloc0(size);
+
+	tmp[2] = 0;
+	for (i = 0; i < size; i++) {
+		memcpy(tmp, str + (i * 2), 2);
+		pdata[i] = (uint8_t) strtol(tmp, NULL, 16);
+	}
+
+	rec = sdp_extract_pdu(pdata, size, &len);
+	g_free(pdata);
+
+	return rec;
+}
+
+#define HIDP_VIRTUAL_CABLE_UNPLUG	0
+#define HIDP_BOOT_PROTOCOL_MODE		1
+#define HIDP_BLUETOOTH_VENDOR_ID	9
+
+struct uhid_connadd_req {
+/*	int ctrl_sock;		/* Connected control socket */
+/*	int intr_sock;		/* Connected interrupt socket */
+	uint16_t parser;	/* Parser version */
+	uint16_t rd_size;	/* Report descriptor size */
+	uint8_t *rd_data;	/* Report descriptor data */
+	uint8_t  country;
+	uint8_t  subclass;
+	uint16_t vendor;
+	uint16_t product;
+/*	uint16_t version;
+*/
+	uint32_t flags;
+/*	uint32_t idle_to;
+*/
+	char name[128];		/* Device name */
+};
+
+static void epox_endian_quirk(unsigned char *data, int size)
+{
+	/* USAGE_PAGE (Keyboard)	05 07
+	 * USAGE_MINIMUM (0)		19 00
+	 * USAGE_MAXIMUM (65280)	2A 00 FF   <= must be FF 00
+	 * LOGICAL_MINIMUM (0)		15 00
+	 * LOGICAL_MAXIMUM (65280)	26 00 FF   <= must be FF 00
+	 */
+	unsigned char pattern[] = { 0x05, 0x07, 0x19, 0x00, 0x2a, 0x00, 0xff,
+						0x15, 0x00, 0x26, 0x00, 0xff };
+	unsigned int i;
+
+	if (!data)
+		return;
+
+	for (i = 0; i < size - sizeof(pattern); i++) {
+		if (!memcmp(data + i, pattern, sizeof(pattern))) {
+			data[i + 5] = 0xff;
+			data[i + 6] = 0x00;
+			data[i + 10] = 0xff;
+			data[i + 11] = 0x00;
+		}
+	}
+}
+
+static int create_hid_dev_name(sdp_record_t *rec, struct uhid_connadd_req *req)
+{
+	char sdesc[sizeof(req->name)];
+
+	if (sdp_get_service_desc(rec, sdesc, sizeof(sdesc)) == 0) {
+		char pname[sizeof(req->name)];
+
+		if (sdp_get_provider_name(rec, pname, sizeof(pname)) == 0 &&
+						strncmp(sdesc, pname, 5) != 0)
+			snprintf(req->name, sizeof(req->name), "%s %s", pname,
+									sdesc);
+		else
+			snprintf(req->name, sizeof(req->name), "%s", sdesc);
+	} else {
+		return sdp_get_service_name(rec, req->name, sizeof(req->name));
+	}
+
+	return 0;
+}
+
+/* See HID profile specification v1.0, "7.11.6 HIDDescriptorList" for details
+ * on the attribute format. */
+static int extract_hid_desc_data(sdp_record_t *rec,
+						struct uhid_connadd_req *req)
+{
+	sdp_data_t *d;
+
+	d = sdp_data_get(rec, SDP_ATTR_HID_DESCRIPTOR_LIST);
+	if (!d)
+		goto invalid_desc;
+
+	if (!SDP_IS_SEQ(d->dtd))
+		goto invalid_desc;
+
+	/* First HIDDescriptor */
+	d = d->val.dataseq;
+	if (!SDP_IS_SEQ(d->dtd))
+		goto invalid_desc;
+
+	/* ClassDescriptorType */
+	d = d->val.dataseq;
+	if (d->dtd != SDP_UINT8)
+		goto invalid_desc;
+
+	/* ClassDescriptorData */
+	d = d->next;
+	if (!d || !SDP_IS_TEXT_STR(d->dtd))
+		goto invalid_desc;
+
+	req->rd_data = g_try_malloc0(d->unitSize);
+	if (req->rd_data) {
+		memcpy(req->rd_data, d->val.str, d->unitSize);
+		req->rd_size = d->unitSize;
+		epox_endian_quirk(req->rd_data, req->rd_size);
+	}
+
+	return 0;
+
+invalid_desc:
+	error("Missing or invalid HIDDescriptorList SDP attribute");
+	return -EINVAL;
+}
+
+static int extract_hid_record(sdp_record_t *rec, struct uhid_connadd_req *req)
+{
+	sdp_data_t *pdlist;
+	uint8_t attr_val;
+	int err;
+
+	err = create_hid_dev_name(rec, req);
+	if (err < 0)
+		DBG("No valid Service Name or Service Description found");
+
+	pdlist = sdp_data_get(rec, SDP_ATTR_HID_PARSER_VERSION);
+	req->parser = pdlist ? pdlist->val.uint16 : 0x0100;
+
+	pdlist = sdp_data_get(rec, SDP_ATTR_HID_DEVICE_SUBCLASS);
+	req->subclass = pdlist ? pdlist->val.uint8 : 0;
+
+	pdlist = sdp_data_get(rec, SDP_ATTR_HID_COUNTRY_CODE);
+	req->country = pdlist ? pdlist->val.uint8 : 0;
+
+	pdlist = sdp_data_get(rec, SDP_ATTR_HID_VIRTUAL_CABLE);
+	attr_val = pdlist ? pdlist->val.uint8 : 0;
+	if (attr_val)
+		req->flags |= (1 << HIDP_VIRTUAL_CABLE_UNPLUG);
+
+	pdlist = sdp_data_get(rec, SDP_ATTR_HID_BOOT_DEVICE);
+	attr_val = pdlist ? pdlist->val.uint8 : 0;
+	if (attr_val)
+		req->flags |= (1 << HIDP_BOOT_PROTOCOL_MODE);
+
+	err = extract_hid_desc_data(rec, req);
+	if (err < 0)
+		return err;
+
+	return 0;
+}
+
+static int uhid_add_connection(struct input_device *idev)
+{
+	struct uhid_connadd_req *req;
+	sdp_record_t *rec;
+	char src_addr[18], dst_addr[18];
+	char filename[PATH_MAX + 1];
+	GKeyFile *key_file;
+	char handle[11], *str;
+	uint8_t value[REPORT_MAP_MAX_SIZE];
+	struct uhid_event ev;
+	int i;
+	int err;
+
+	/* TODO: */
+#if 1
+	req = g_new0(struct uhid_connadd_req, 1);
+
+	ba2str(&idev->src, src_addr);
+	ba2str(&idev->dst, dst_addr);
+
+	snprintf(filename, PATH_MAX, STORAGEDIR "/%s/cache/%s", src_addr,
+								dst_addr);
+	filename[PATH_MAX] = '\0';
+#if 0
+	sprintf(handle, "0x%8.8X", idev->handle);
+#else
+	sprintf(handle, "0x00010000");
+#endif
+
+	key_file = g_key_file_new();
+	g_key_file_load_from_file(key_file, filename, 0, NULL);
+	str = g_key_file_get_string(key_file, "ServiceRecords", handle, NULL);
+	g_key_file_free(key_file);
+
+	if (!str) {
+		error("Rejected connection from unknown device %s", dst_addr);
+#if 0
+		err = -EPERM;
+		goto cleanup;
+#else
+		return -1;
+#endif
+	}
+
+	rec = record_from_string(str);
+	g_free(str);
+
+	err = extract_hid_record(rec, req);
+	sdp_record_free(rec);
+	if (err < 0) {
+		error("Could not parse HID SDP record: %s (%d)", strerror(-err),
+									-err);
+#if 0
+		goto cleanup;
+#else
+		return -1;
+#endif
+	}
+#endif
+
+	DBG("Report MAP:");
+	for (i = 0; i < req->rd_size; i++) {
+#if 0
+		switch (value[i]) {
+		case 0x85:
+		case 0x86:
+		case 0x87:
+			hogdev->has_report_id = TRUE;
+		}
+#endif
+
+		if (i % 2 == 0) {
+			if (i + 1 == req->rd_size)
+				DBG("\t %02x", req->rd_data[i]);
+			else
+				DBG("\t %02x %02x", req->rd_data[i],
+							req->rd_data[i + 1]);
+		}
+	}
+
+#if 0
+	vendor_src = btd_device_get_vendor_src(idev->device);
+	vendor = btd_device_get_vendor(idev->device);
+	product = btd_device_get_product(idev->device);
+	version = btd_device_get_version(idev->device);
+/*	DBG("DIS information: vendor_src=0x%X, vendor=0x%X, product=0x%X, "
+			"version=0x%X",	vendor_src, vendor, product, version);
+*/
+#else
+	DBG("DIS information: vendor=0x%X, product=0x%X, version=0x%X",
+					req->vendor, req->product, req->parser);
+#endif
+
+	/* create uHID device */
+	memset(&ev, 0, sizeof(ev));
+	ev.type = UHID_CREATE;
+	strcpy((char *) ev.u.create.name, "bluez-hid-device");
+#if 0
+	ev.u.create.vendor = vendor;
+	ev.u.create.product = product;
+	ev.u.create.version = version;
+	ev.u.create.country = hogdev->bcountrycode;
+#else
+	ev.u.create.vendor = req->vendor;
+	ev.u.create.product = req->product;
+	ev.u.create.version = req->parser;
+	ev.u.create.country = req->country;
+#endif
+	ev.u.create.bus = BUS_BLUETOOTH;
+	ev.u.create.rd_data = req->rd_data;
+	ev.u.create.rd_size = req->rd_size;
+
+	if (write(idev->uhid_fd, &ev, sizeof(ev)) < 0)
+		error("Failed to create uHID device: %s", strerror(errno));
+
+	return 0;
+}
+
+static int is_connected(struct input_device *idev)
+{
+	/* TODO: */
+#if 0
+	struct hidp_conninfo ci;
+	int ctl;
+
+	/* Standard HID */
+	ctl = socket(AF_BLUETOOTH, SOCK_RAW, BTPROTO_HIDP);
+	if (ctl < 0)
+		return 0;
+
+	memset(&ci, 0, sizeof(ci));
+	bacpy(&ci.bdaddr, &idev->dst);
+	if (ioctl(ctl, HIDPGETCONNINFO, &ci) < 0) {
+		close(ctl);
+		return 0;
+	}
+
+	close(ctl);
+
+	if (ci.state != BT_CONNECTED)
+		return 0;
+	else
+		return 1;
+#else
+	return 0;
+#endif
+}
+
+static void disconnect_cb(struct bt_device *device, gboolean removal,
+				void *user_data)
+{
+	/* TODO: */
+#if 0
+	struct input_device *idev = user_data;
+	int flags;
+
+	info("Input: disconnect %s", idev->path);
+
+	flags = removal ? (1 << HIDP_VIRTUAL_CABLE_UNPLUG) : 0;
+
+	connection_disconnect(idev, flags);
+#endif
+}
+
+static int input_device_connected(struct input_device *idev)
+{
+	int err;
+
+	if (idev->intr_io == NULL || idev->ctrl_io == NULL)
+		return -ENOTCONN;
+
+	err = uhid_add_connection(idev);
+	if (err < 0)
+		return err;
+
+	idev->dc_id = bt_device_add_disconnect_watch(idev->device,
+							disconnect_cb,
+							idev, NULL);
+
+	/* TODO:
+	btd_service_connecting_complete(idev->service, 0);
+	*/
+
+	return 0;
+}
+
+static void interrupt_connect_cb(GIOChannel *chan, GError *conn_err,
+							gpointer user_data)
+{
+	struct input_device *idev = user_data;
+	int err;
+
+	if (conn_err) {
+		err = -EIO;
+		goto failed;
+	}
+
+	err = input_device_connected(idev);
+	if (err < 0)
+		goto failed;
+
+	idev->intr_watch = g_io_add_watch(idev->intr_io,
+					G_IO_HUP | G_IO_ERR | G_IO_NVAL,
+					intr_watch_cb, idev);
+
+	return;
+
+failed:
+	/* TODO:
+	btd_service_connecting_complete(idev->service, err);
+	*/
+
+	/* 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;
+	GIOChannel *io;
+	GError *err = NULL;
+
+	if (conn_err) {
+		error("%s", conn_err->message);
+		goto failed;
+	}
+
+	/* Connect to the HID interrupt channel */
+	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 (!io) {
+		error("%s", err->message);
+		g_error_free(err);
+		goto failed;
+	}
+
+	idev->intr_io = io;
+
+	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:
+	/* TODO:
+	btd_service_connecting_complete(idev->service, -EIO);
+	*/
+	g_io_channel_unref(idev->ctrl_io);
+	idev->ctrl_io = NULL;
+}
+
+static int dev_connect(struct input_device *idev)
+{
+	GError *err = NULL;
+	GIOChannel *io;
+
+	/* TODO: */
+#if 0
+	if (idev->disable_sdp)
+		bt_clear_cached_session(&idev->src, &idev->dst);
+#endif
+
+	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);
+	idev->ctrl_io = io;
+
+	if (err == NULL)
+		return 0;
+
+	error("%s", err->message);
+	g_error_free(err);
+
+	return -EIO;
+}
+
+static gboolean input_device_auto_reconnect(gpointer user_data)
+{
+	struct input_device *idev = user_data;
+
+	/* TODO: */
+#if 0
+	DBG("path=%s, attempt=%d", idev->path, idev->reconnect_attempt);
+
+	/* Stop the recurrent reconnection attempts if the device is reconnected
+	 * or is marked for removal. */
+	if (device_is_temporary(idev->device) ||
+					device_is_connected(idev->device))
+		return FALSE;
+#else
+	DBG("attempt=%d", idev->reconnect_attempt);
+#endif
+
+	/* Only attempt an auto-reconnect for at most 3 minutes (6 * 30s). */
+	if (idev->reconnect_attempt >= 6)
+		return FALSE;
+
+	/* Check if the profile is already connected. */
+	if (idev->ctrl_io)
+		return FALSE;
+
+	if (is_connected(idev))
+		return FALSE;
+
+	idev->reconnect_attempt++;
+	dev_connect(idev);
+
+	return TRUE;
+}
+
+static const char * const _reconnect_mode_str[] = {
+	"none",
+	"device",
+	"host",
+	"any"
+};
+
+static const char *reconnect_mode_to_string(const enum reconnect_mode_t mode)
+{
+	return _reconnect_mode_str[mode];
+}
+
+static void input_device_enter_reconnect_mode(struct input_device *idev)
+{
+#if 0
+	DBG("path=%s reconnect_mode=%s", idev->path,
+				reconnect_mode_to_string(idev->reconnect_mode));
+#else
+	DBG("reconnect_mode=%s",
+		reconnect_mode_to_string(idev->reconnect_mode));
+#endif
+
+	/* Only attempt an auto-reconnect when the device is required to accept
+	 * reconnections from the host. */
+	if (idev->reconnect_mode != RECONNECT_ANY &&
+				idev->reconnect_mode != RECONNECT_HOST)
+		return;
+
+	/* TODO: */
+#if 0
+	/* If the device is temporary we are not required to reconnect with the
+	 * device. This is likely the case of a removing device. */
+	if (device_is_temporary(idev->device) ||
+					device_is_connected(idev->device))
+		return;
+#endif
+
+	if (idev->reconnect_timer > 0)
+		g_source_remove(idev->reconnect_timer);
+
+	DBG("registering auto-reconnect");
+	idev->reconnect_attempt = 0;
+	idev->reconnect_timer = g_timeout_add_seconds(30,
+					input_device_auto_reconnect, idev);
+
+}
+
+int input_device_connect(bdaddr_t *bd_addr)
+{
+	struct input_device *idev;
+
+	DBG("");
+
+	idev = find_conn(conns, bd_addr);
+
+	if (idev->ctrl_io)
+		return -EBUSY;
+
+	if (is_connected(idev))
+		return -EALREADY;
+
+	return dev_connect(idev);
+}
+
+static void forward_report(struct input_device *idev,
+						struct uhid_event *ev)
+{
+	/* TODO: */
+#if 0
+	struct report *report;
+	GSList *l;
+	void *data;
+	int size;
+	guint type;
+
+	if (idev->has_report_id) {
+		data = ev->u.output.data + 1;
+		size = ev->u.output.size - 1;
+	} else {
+		data = ev->u.output.data;
+		size = ev->u.output.size;
+	}
+
+	switch (ev->type) {
+	case UHID_OUTPUT:
+		type = HOG_REPORT_TYPE_OUTPUT;
+		break;
+	case UHID_FEATURE:
+		type = HOG_REPORT_TYPE_FEATURE;
+		break;
+	default:
+		return;
+	}
+
+	l = g_slist_find_custom(hogdev->reports, GUINT_TO_POINTER(type),
+							report_type_cmp);
+	if (!l)
+		return;
+
+	report = l->data;
+
+	DBG("Sending report type %d to device 0x%04X handle 0x%X", type,
+			idev->id, report->decl->value_handle);
+
+	if (idev->attrib == NULL)
+		return;
+
+	if (report->decl->properties & ATT_CHAR_PROPER_WRITE)
+		gatt_write_char(idev->attrib, report->decl->value_handle,
+				data, size, output_written_cb, idev);
+	else if (report->decl->properties & ATT_CHAR_PROPER_WRITE_WITHOUT_RESP)
+		gatt_write_cmd(idev->attrib, report->decl->value_handle,
+						data, size, NULL, NULL);
+#endif
+}
+
+static gboolean uhid_event_cb(GIOChannel *io, GIOCondition cond,
+							gpointer user_data)
+{
+	struct input_device *idev = user_data;
+	struct uhid_event ev;
+	ssize_t bread;
+	int fd;
+
+	if (cond & (G_IO_ERR | G_IO_NVAL))
+		goto failed;
+
+	fd = g_io_channel_unix_get_fd(io);
+	memset(&ev, 0, sizeof(ev));
+
+	bread = read(fd, &ev, sizeof(ev));
+	if (bread < 0) {
+		int err = -errno;
+		DBG("uhid-dev read: %s(%d)", strerror(-err), -err);
+		goto failed;
+	}
+
+	DBG("uHID event type %d received", ev.type);
+
+	switch (ev.type) {
+	case UHID_START:
+	case UHID_STOP:
+		/* These are called to start and stop the underlying hardware.
+		 * For HoG we open the channels before creating the device so
+		 * the hardware is always ready. No need to handle these.
+		 * Note that these are also called when the kernel switches
+		 * between device-drivers loaded on the HID device. But we can
+		 * simply keep the hardware alive during transitions and it
+		 * works just fine.
+		 * The kernel never destroys a device itself! Only an explicit
+		 * UHID_DESTROY request can remove a device. */
+		break;
+	case UHID_OPEN:
+	case UHID_CLOSE:
+		/* OPEN/CLOSE are sent whenever user-space opens any interface
+		 * provided by the kernel HID device. Whenever the open-count
+		 * is non-zero we must be ready for I/O. As long as it is zero,
+		 * we can decide to drop all I/O and put the device
+		 * asleep This is optional, though. Moreover, some
+		 * special device drivers are buggy in that regard, so
+		 * maybe we just keep I/O always awake like HIDP in the
+		 * kernel does. */
+		break;
+	case UHID_OUTPUT:
+	case UHID_FEATURE:
+		forward_report(idev, &ev);
+		break;
+	case UHID_OUTPUT_EV:
+		/* This is only sent by kernels prior to linux-3.11. It
+		 * requires us to parse HID-descriptors in user-space to
+		 * properly handle it. This is redundant as the kernel
+		 * does it already. That's why newer kernels assemble
+		 * the output-reports and send it to us via UHID_OUTPUT.
+		 * We never implemented this, so we rely on users to use
+		 * recent-enough kernels if they want this feature. No reason
+		 * to implement this for older kernels. */
+		DBG("Unsupported uHID output event: type %d code %d value %d",
+			ev.u.output_ev.type, ev.u.output_ev.code,
+			ev.u.output_ev.value);
+		break;
+	default:
+		warn("unexpected uHID event");
+		break;
+	}
+
+	return TRUE;
+
+failed:
+	idev->uhid_watch_id = 0;
+	return FALSE;
+}
+
+static struct input_device *input_new_device(struct bt_device *device)
+{
+	struct input_device *idev;
+
+	idev = g_try_new0(struct input_device, 1);
+	if (!idev)
+		return NULL;
+
+	idev->device = bt_device_ref(device);
+
+	return idev;
+}
+
+static void input_free_device(struct input_device *idev)
+{
+	bt_device_unref(idev->device);
+/*	g_slist_free_full(idev->reports, report_free);
+*/	g_free(idev);
+}
+
+struct input_device *input_register_device(struct bt_device *device)
+{
+	struct input_device *idev;
+	GIOCondition cond = G_IO_IN | G_IO_ERR | G_IO_NVAL;
+	GIOChannel *io;
+
+	idev = input_new_device(device);
+	if (!idev)
+		return NULL;
+
+	idev->uhid_fd = open(UHID_DEVICE_FILE, O_RDWR | O_CLOEXEC);
+	if (idev->uhid_fd < 0) {
+		error("Failed to open uHID device: %s(%d)", strerror(errno),
+									errno);
+		input_free_device(idev);
+		return NULL;
+	}
+
+	io = g_io_channel_unix_new(idev->uhid_fd);
+	g_io_channel_set_encoding(io, NULL, NULL);
+	idev->uhid_watch_id = g_io_add_watch(io, cond, uhid_event_cb, idev);
+	g_io_channel_unref(io);
+
+	return idev;
+}
+
+int input_unregister_device(struct input_device *idev)
+{
+	struct uhid_event ev;
+
+	if (idev->uhid_watch_id) {
+		g_source_remove(idev->uhid_watch_id);
+		idev->uhid_watch_id = 0;
+	}
+
+	memset(&ev, 0, sizeof(ev));
+	ev.type = UHID_DESTROY;
+	if (write(idev->uhid_fd, &ev, sizeof(ev)) < 0)
+		error("Failed to destroy uHID device: %s", strerror(errno));
+
+	close(idev->uhid_fd);
+	idev->uhid_fd = -1;
+
+	input_free_device(idev);
+
+	return 0;
+}
-- 
1.8.1.2


^ permalink raw reply related

* Re: [PATCH BlueZ] core: Fix crash while processing SDP records
From: Johan Hedberg @ 2013-10-22 10:38 UTC (permalink / raw)
  To: Luiz Augusto von Dentz; +Cc: linux-bluetooth
In-Reply-To: <1382432600-6101-1-git-send-email-luiz.dentz@gmail.com>

Hi Luiz,

On Tue, Oct 22, 2013, Luiz Augusto von Dentz wrote:
> This was introduced by commit 073714c3ff70379131be3e19d9ccb8b85fe3f0d9
> which attempted to treat the return of sdp_process but caused the crash
> bellow because sdp_process actually calls search_completed_cb if it
> fails:
> Invalid read of size 8
>    at 0x44FC93: search_process_cb (sdp-client.c:214)
>    by 0x3D46047E05: g_main_context_dispatch (in /usr/lib64/libglib-2.0.so.0.3600.3)
>    by 0x3D46048157: ??? (in /usr/lib64/libglib-2.0.so.0.3600.3)
>    by 0x3D46048559: g_main_loop_run (in /usr/lib64/libglib-2.0.so.0.3600.3)
>    by 0x40A2DF: main (main.c:587)
>  Address 0x59febd0 is 16 bytes inside a block of size 72 free'd
>    at 0x4A074C4: free (in /usr/lib64/valgrind/vgpreload_memcheck-amd64-linux.so)
>    by 0x3D4604D9AE: g_free (in /usr/lib64/libglib-2.0.so.0.3600.3)
>    by 0x44FE44: search_completed_cb (sdp-client.c:192)
>    by 0x4732E7: sdp_process (sdp.c:4341)
>    by 0x44FCD8: search_process_cb (sdp-client.c:206)
>    by 0x3D46047E05: g_main_context_dispatch (in /usr/lib64/libglib-2.0.so.0.3600.3)
>    by 0x3D46048157: ??? (in /usr/lib64/libglib-2.0.so.0.3600.3)
>    by 0x3D46048559: g_main_loop_run (in /usr/lib64/libglib-2.0.so.0.3600.3)
>    by 0x40A2DF: main (main.c:587)
> ---
>  src/sdp-client.c | 22 +++++++---------------
>  1 file changed, 7 insertions(+), 15 deletions(-)

Applied. Thanks.

Johan

^ permalink raw reply

* [PATCH] android: Fix compilation error for Android 4.2.2
From: Andrei Emeltchenko @ 2013-10-22 10:37 UTC (permalink / raw)
  To: linux-bluetooth
In-Reply-To: <1382436600-8598-1-git-send-email-Andrei.Emeltchenko.news@gmail.com>

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

On our current target the tools cannot be compiled.
---
 android/Android.mk        | 2 ++
 android/client/if-bt.c    | 6 ++++++
 android/client/if-main.h  | 3 +++
 android/client/textconv.c | 2 ++
 4 files changed, 13 insertions(+)

diff --git a/android/Android.mk b/android/Android.mk
index 679c12b..657ab3e 100644
--- a/android/Android.mk
+++ b/android/Android.mk
@@ -84,6 +84,8 @@ LOCAL_SRC_FILES := \
 	client/tabcompletion.c \
 	client/if-bt.c \
 
+LOCAL_CFLAGS := -DPLATFORM_SDK_VERSION=$(PLATFORM_SDK_VERSION)
+
 LOCAL_SHARED_LIBRARIES := libhardware
 
 LOCAL_MODULE_TAGS := optional
diff --git a/android/client/if-bt.c b/android/client/if-bt.c
index 30b41cd..330a3fa 100644
--- a/android/client/if-bt.c
+++ b/android/client/if-bt.c
@@ -364,11 +364,13 @@ static void dut_mode_recv_cb(uint16_t opcode, uint8_t *buf, uint8_t len)
 	haltest_info("%s\n", __func__);
 }
 
+#if PLATFORM_SDK_VERSION > 17
 static void le_test_mode_cb(bt_status_t status, uint16_t num_packets)
 {
 	haltest_info("%s %s %d\n", __func__, bt_state_t2str(status),
 								num_packets);
 }
+#endif
 
 static bt_callbacks_t bt_callbacks = {
 	.size = sizeof(bt_callbacks),
@@ -383,7 +385,9 @@ static bt_callbacks_t bt_callbacks = {
 	.acl_state_changed_cb = acl_state_changed_cb,
 	.thread_evt_cb = thread_evt_cb,
 	.dut_mode_recv_cb = dut_mode_recv_cb,
+#if PLATFORM_SDK_VERSION > 17
 	.le_test_mode_cb = le_test_mode_cb
+#endif
 };
 
 static void init_p(int argc, const char **argv)
@@ -808,8 +812,10 @@ static void get_profile_interface_p(int argc, const char **argv)
 		pif = &dummy; /* TODO: change when if_hh is there */
 	else if (strcmp(BT_PROFILE_PAN_ID, id) == 0)
 		pif = &dummy; /* TODO: change when if_pan is there */
+#if PLATFORM_SDK_VERSION > 17
 	else if (strcmp(BT_PROFILE_AV_RC_ID, id) == 0)
 		pif = &dummy; /* TODO: change when if_rc is there */
+#endif
 	else
 		haltest_error("%s is not correct for get_profile_interface\n",
 		     id);
diff --git a/android/client/if-main.h b/android/client/if-main.h
index 6d2b0cb..5f4a434 100644
--- a/android/client/if-main.h
+++ b/android/client/if-main.h
@@ -35,7 +35,10 @@
 #include <hardware/bt_sock.h>
 #include <hardware/bt_hf.h>
 #include <hardware/bt_hl.h>
+
+#if PLATFORM_SDK_VERSION > 17
 #include <hardware/bt_rc.h>
+#endif
 
 #include "textconv.h"
 
diff --git a/android/client/textconv.c b/android/client/textconv.c
index 3493b1c..cdd443e 100644
--- a/android/client/textconv.c
+++ b/android/client/textconv.c
@@ -94,7 +94,9 @@ INTMAP(bt_property_type_t, -1, "(unknown)")
 	DELEMENT(BT_PROPERTY_ADAPTER_DISCOVERY_TIMEOUT),
 	DELEMENT(BT_PROPERTY_REMOTE_FRIENDLY_NAME),
 	DELEMENT(BT_PROPERTY_REMOTE_RSSI),
+#if PLATFORM_SDK_VERSION > 17
 	DELEMENT(BT_PROPERTY_REMOTE_VERSION_INFO),
+#endif
 	DELEMENT(BT_PROPERTY_REMOTE_DEVICE_TIMESTAMP),
 ENDMAP
 
-- 
1.8.1.2


^ permalink raw reply related

* Re: [PATCH] android: Add hidhost defines and structures to header file
From: Johan Hedberg @ 2013-10-22 10:34 UTC (permalink / raw)
  To: Ravi kumar Veeramally; +Cc: linux-bluetooth
In-Reply-To: <1382431088-14122-1-git-send-email-ravikumar.veeramally@linux.intel.com>

Hi Ravi,

On Tue, Oct 22, 2013, Ravi kumar Veeramally wrote:
> ---
>  android/hal-msg.h |   67 +++++++++++++++++++++++++++++++++++++++++++++++++++++
>  1 file changed, 67 insertions(+)

Applied. Thanks.

Johan

^ permalink raw reply

* [PATCH] android: Fix compilation error for Android 4.2.2
From: Andrei Emeltchenko @ 2013-10-22 10:10 UTC (permalink / raw)
  To: linux-bluetooth

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

---
 android/client/if-bt.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/android/client/if-bt.c b/android/client/if-bt.c
index 5447e0c..330a3fa 100644
--- a/android/client/if-bt.c
+++ b/android/client/if-bt.c
@@ -364,11 +364,13 @@ static void dut_mode_recv_cb(uint16_t opcode, uint8_t *buf, uint8_t len)
 	haltest_info("%s\n", __func__);
 }
 
+#if PLATFORM_SDK_VERSION > 17
 static void le_test_mode_cb(bt_status_t status, uint16_t num_packets)
 {
 	haltest_info("%s %s %d\n", __func__, bt_state_t2str(status),
 								num_packets);
 }
+#endif
 
 static bt_callbacks_t bt_callbacks = {
 	.size = sizeof(bt_callbacks),
-- 
1.8.1.2


^ permalink raw reply related

* [PATCH_v2] android: Add hidhost defines and structures to header file
From: Ravi kumar Veeramally @ 2013-10-22  9:07 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Ravi kumar Veeramally

	v2: Changed 2 byte arrays to uint16_t as per Luiz comments
---
 android/hal-msg.h |   67 +++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 67 insertions(+)

diff --git a/android/hal-msg.h b/android/hal-msg.h
index 6266903..9dcfbf6 100644
--- a/android/hal-msg.h
+++ b/android/hal-msg.h
@@ -179,6 +179,73 @@ struct hal_msg_cmd_bt_le_test_mode {
 	uint8_t  data[0];
 } __attribute__((packed));
 
+#define HAL_MSG_OP_BT_HID_CONNECT	0x01
+struct hal_msg_cmd_bt_hid_connect {
+	uint8_t bdaddr[6];
+} __attribute__((packed));
+
+#define HAL_MSG_OP_BT_HID_DISCONNECT	0x02
+struct hal_msg_cmd_bt_hid_disconnect {
+	uint8_t bdaddr[6];
+} __attribute__((packed));
+
+#define HAL_MSG_OP_BT_HID_VP		0x03
+struct hal_msg_cmd_bt_hid_vp {
+	uint8_t bdaddr[6];
+} __attribute__((packed));
+
+#define HAL_MSG_OP_BT_HID_SET_INFO	0x04
+struct hal_msg_cmd_bt_hid_set_info {
+	uint8_t bdaddr[6];
+	uint8_t attr;
+	uint8_t subclass;
+	uint8_t app_id;
+	uint16_t vendor;
+	uint16_t product;
+	uint16_t country;
+	uint16_t descr_len;
+	uint8_t descr[0];
+} __attribute__((packed));
+
+#define HAL_MSG_BT_HID_REPORT_PROTOCOL		0x00
+#define HAL_MSG_BT_HID_BOOT_PROTOCOL		0x01
+#define HAL_MSG_BT_HID_UNSUPPORTED_PROTOCOL	0xff
+
+#define HAL_MSG_OP_BT_HID_GET_PROTOCOL	0x05
+struct hal_msg_cmd_bt_hid_get_protocol {
+	uint8_t bdaddr[6];
+	uint8_t mode;
+} __attribute__((packed));
+
+#define HAL_MSG_OP_BT_HID_SET_PROTOCOL	0x06
+struct hal_msg_cmd_bt_hid_set_protocol {
+	uint8_t bdaddr[6];
+	uint8_t mode;
+} __attribute__((packed));
+
+#define HAL_MSG_BT_HID_INPUT_REPORT	0x01
+#define HAL_MSG_BT_HID_OUTPUT_REPORT	0x02
+#define HAL_MSG_BT_HID_FEATURE_REPORT	0x03
+
+#define HAL_MSG_OP_BT_HID_GET_REPORT	0x07
+struct hal_msg_cmd_bt_hid_get_report {
+	uint8_t bdaddr[6];
+	uint8_t type;
+	uint8_t id;
+	uint16_t buf;
+} __attribute__((packed));
+
+#define HAL_MSG_OP_BT_HID_SET_REPORT	0x08
+struct hal_msg_cmd_bt_hid_set_report {
+	uint8_t bdaddr[6];
+	uint8_t type;
+} __attribute__((packed));
+
+#define HAL_MSG_OP_BT_HID_SEND_DATA	0x09
+struct hal_msg_cmd_bt_hid_send_data {
+	uint8_t bdaddr[6];
+} __attribute__((packed));
+
 /* Notifications and confirmations */
 
 #define HAL_MSG_EV_BT_ERROR			0x80
-- 
1.7.9.5


^ permalink raw reply related

* [PATCH BlueZ] core: Fix crash while processing SDP records
From: Luiz Augusto von Dentz @ 2013-10-22  9:03 UTC (permalink / raw)
  To: linux-bluetooth

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

This was introduced by commit 073714c3ff70379131be3e19d9ccb8b85fe3f0d9
which attempted to treat the return of sdp_process but caused the crash
bellow because sdp_process actually calls search_completed_cb if it
fails:
Invalid read of size 8
   at 0x44FC93: search_process_cb (sdp-client.c:214)
   by 0x3D46047E05: g_main_context_dispatch (in /usr/lib64/libglib-2.0.so.0.3600.3)
   by 0x3D46048157: ??? (in /usr/lib64/libglib-2.0.so.0.3600.3)
   by 0x3D46048559: g_main_loop_run (in /usr/lib64/libglib-2.0.so.0.3600.3)
   by 0x40A2DF: main (main.c:587)
 Address 0x59febd0 is 16 bytes inside a block of size 72 free'd
   at 0x4A074C4: free (in /usr/lib64/valgrind/vgpreload_memcheck-amd64-linux.so)
   by 0x3D4604D9AE: g_free (in /usr/lib64/libglib-2.0.so.0.3600.3)
   by 0x44FE44: search_completed_cb (sdp-client.c:192)
   by 0x4732E7: sdp_process (sdp.c:4341)
   by 0x44FCD8: search_process_cb (sdp-client.c:206)
   by 0x3D46047E05: g_main_context_dispatch (in /usr/lib64/libglib-2.0.so.0.3600.3)
   by 0x3D46048157: ??? (in /usr/lib64/libglib-2.0.so.0.3600.3)
   by 0x3D46048559: g_main_loop_run (in /usr/lib64/libglib-2.0.so.0.3600.3)
   by 0x40A2DF: main (main.c:587)
---
 src/sdp-client.c | 22 +++++++---------------
 1 file changed, 7 insertions(+), 15 deletions(-)

diff --git a/src/sdp-client.c b/src/sdp-client.c
index 1221f5e..51f3048 100644
--- a/src/sdp-client.c
+++ b/src/sdp-client.c
@@ -196,31 +196,23 @@ static gboolean search_process_cb(GIOChannel *chan, GIOCondition cond,
 							gpointer user_data)
 {
 	struct search_context *ctxt = user_data;
-	int err;
 
 	if (cond & (G_IO_ERR | G_IO_HUP | G_IO_NVAL)) {
-		err = -EIO;
-		goto failed;
-	}
-
-	err = sdp_process(ctxt->session);
-	if (err < 0)
-		goto failed;
-
-	return TRUE;
-
-failed:
-	if (err) {
 		sdp_close(ctxt->session);
 		ctxt->session = NULL;
 
 		if (ctxt->cb)
-			ctxt->cb(NULL, err, ctxt->user_data);
+			ctxt->cb(NULL, -EIO, ctxt->user_data);
 
 		search_context_cleanup(ctxt);
+		return FALSE;
 	}
 
-	return FALSE;
+	/* If sdp_process fails it calls search_completed_cb */
+	if (sdp_process(ctxt->session) < 0)
+		return FALSE;
+
+	return TRUE;
 }
 
 static gboolean connect_watch(GIOChannel *chan, GIOCondition cond,
-- 
1.8.3.1


^ permalink raw reply related

* [PATCH] android: Add hidhost defines and structures to header file
From: Ravi kumar Veeramally @ 2013-10-22  8:38 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Ravi kumar Veeramally

---
 android/hal-msg.h |   67 +++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 67 insertions(+)

diff --git a/android/hal-msg.h b/android/hal-msg.h
index 6266903..8dadd64 100644
--- a/android/hal-msg.h
+++ b/android/hal-msg.h
@@ -179,6 +179,73 @@ struct hal_msg_cmd_bt_le_test_mode {
 	uint8_t  data[0];
 } __attribute__((packed));
 
+#define HAL_MSG_OP_BT_HID_CONNECT	0x01
+struct hal_msg_cmd_bt_hid_connect {
+	uint8_t bdaddr[6];
+} __attribute__((packed));
+
+#define HAL_MSG_OP_BT_HID_DISCONNECT	0x02
+struct hal_msg_cmd_bt_hid_disconnect {
+	uint8_t bdaddr[6];
+} __attribute__((packed));
+
+#define HAL_MSG_OP_BT_HID_VP		0x03
+struct hal_msg_cmd_bt_hid_vp {
+	uint8_t bdaddr[6];
+} __attribute__((packed));
+
+#define HAL_MSG_OP_BT_HID_SET_INFO	0x04
+struct hal_msg_cmd_bt_hid_set_info {
+	uint8_t bdaddr[6];
+	uint8_t attr;
+	uint8_t subclass;
+	uint8_t app_id;
+	uint8_t vendor[2];
+	uint8_t product[2];
+	uint8_t country[2];
+	uint8_t descr_len[2];
+	uint8_t descr[0];
+} __attribute__((packed));
+
+#define HAL_MSG_BT_HID_REPORT_PROTOCOL		0x00
+#define HAL_MSG_BT_HID_BOOT_PROTOCOL		0x01
+#define HAL_MSG_BT_HID_UNSUPPORTED_PROTOCOL	0xff
+
+#define HAL_MSG_OP_BT_HID_GET_PROTOCOL	0x05
+struct hal_msg_cmd_bt_hid_get_protocol {
+	uint8_t bdaddr[6];
+	uint8_t mode;
+} __attribute__((packed));
+
+#define HAL_MSG_OP_BT_HID_SET_PROTOCOL	0x06
+struct hal_msg_cmd_bt_hid_set_protocol {
+	uint8_t bdaddr[6];
+	uint8_t mode;
+} __attribute__((packed));
+
+#define HAL_MSG_BT_HID_INPUT_REPORT	0x01
+#define HAL_MSG_BT_HID_OUTPUT_REPORT	0x02
+#define HAL_MSG_BT_HID_FEATURE_REPORT	0x03
+
+#define HAL_MSG_OP_BT_HID_GET_REPORT	0x07
+struct hal_msg_cmd_bt_hid_get_report {
+	uint8_t bdaddr[6];
+	uint8_t type;
+	uint8_t id;
+	uint8_t buf[2];
+} __attribute__((packed));
+
+#define HAL_MSG_OP_BT_HID_SET_REPORT	0x08
+struct hal_msg_cmd_bt_hid_set_report {
+	uint8_t bdaddr[6];
+	uint8_t type;
+} __attribute__((packed));
+
+#define HAL_MSG_OP_BT_HID_SEND_DATA	0x09
+struct hal_msg_cmd_bt_hid_send_data {
+	uint8_t bdaddr[6];
+} __attribute__((packed));
+
 /* Notifications and confirmations */
 
 #define HAL_MSG_EV_BT_ERROR			0x80
-- 
1.7.9.5


^ permalink raw reply related

* Re: [PATCH 0/3] Add basic commands to haltest
From: Johan Hedberg @ 2013-10-22  7:59 UTC (permalink / raw)
  To: Jerzy Kasenberg; +Cc: linux-bluetooth
In-Reply-To: <CAHCYCoyszrDFjxZA8yini=QY4A0zOP6msZPGG3WHs0C2mfjUHg@mail.gmail.com>

Hi Jerzy,

On Tue, Oct 22, 2013, Jerzy Kasenberg wrote:
> On 21 October 2013 18:18, Johan Hedberg <johan.hedberg@gmail.com> wrote:
> > Hi Jerzy,
> >
> > On Mon, Oct 21, 2013, Jerzy Kasenberg wrote:
> >> - Adds handling of Ctrl-c Ctrl-d as requested
> >> - Prompted changed to includ space
> >> - Added commands: quit exit help
> >> - Added completion for help
> >> - Terminal settings restored on exit
> >>
> >> Jerzy Kasenberg (3):
> >>   android: Add space in prompt in haltest
> >>   android: Add handling of Ctrl-c to haltest
> >>   android: Add help and quit to haltest
> >>
> >>  android/client/haltest.c       |  151 ++++++++++++++++++++++++++++++++++------
> >>  android/client/if-main.h       |    6 ++
> >>  android/client/tabcompletion.c |  151 ++++++++++++++++++++++++++++------------
> >>  android/client/terminal.c      |  100 ++++++++++++++++++--------
> >>  4 files changed, 312 insertions(+), 96 deletions(-)
> >
> > Patches 1 and 3 have been applied. It seems we had a bit of a
> > misunderstanding about 2 though. I was looking for ctrl-d (i.e. EOF)
> > support. Sorry for not being more precise here. Right now when I try
> > it the following just happens:
> >
> > jh@x220:bluez{master}$ android/haltest
> >> char-0x04
> 
> Patch 2 handles Ctrl-c and Ctrl-d.
> When I tried on two terminals in bash Ctrl-d act like delete if line
> is not empty.

Seems you're right. Anyway, this was part of the same request as adding
basic "exit" or "quit" commands. When a user ends up in an unknown shell
and wants to get out from it those are usually the first things tried
(including ctrl-d).

> You or Szymon asked me to add Ctrl-c to clear current line like in
> other tools.

It wasn't me since ctrl-c was already getting me out from the tool.

> So maybe it wold be better to put Ctrl-d in patch title instead of
> Ctrl-c

Ctrl-d should be generating an EOF indicator just like feeding a file to
the program through stdin does. So in this sense "ctrl-d" isn't really
the best description as there are more ways of accomplishing the same.

> This  is what patch 2 handles by setting atexit() cleanup function
> that restore terminal settings.

Sounds like this should have been split into a separate patch then.

Johan

^ permalink raw reply

* Re: [PATCH 0/3] Add basic commands to haltest
From: Jerzy Kasenberg @ 2013-10-22  7:42 UTC (permalink / raw)
  To: Jerzy Kasenberg, linux-bluetooth
In-Reply-To: <20131021161859.GA9153@x220.p-661hnu-f1>

Hi Johan,

On 21 October 2013 18:18, Johan Hedberg <johan.hedberg@gmail.com> wrote:
> Hi Jerzy,
>
> On Mon, Oct 21, 2013, Jerzy Kasenberg wrote:
>> - Adds handling of Ctrl-c Ctrl-d as requested
>> - Prompted changed to includ space
>> - Added commands: quit exit help
>> - Added completion for help
>> - Terminal settings restored on exit
>>
>> Jerzy Kasenberg (3):
>>   android: Add space in prompt in haltest
>>   android: Add handling of Ctrl-c to haltest
>>   android: Add help and quit to haltest
>>
>>  android/client/haltest.c       |  151 ++++++++++++++++++++++++++++++++++------
>>  android/client/if-main.h       |    6 ++
>>  android/client/tabcompletion.c |  151 ++++++++++++++++++++++++++++------------
>>  android/client/terminal.c      |  100 ++++++++++++++++++--------
>>  4 files changed, 312 insertions(+), 96 deletions(-)
>
> Patches 1 and 3 have been applied. It seems we had a bit of a
> misunderstanding about 2 though. I was looking for ctrl-d (i.e. EOF)
> support. Sorry for not being more precise here. Right now when I try
> it the following just happens:
>
> jh@x220:bluez{master}$ android/haltest
>> char-0x04

Patch 2 handles Ctrl-c and Ctrl-d.
When I tried on two terminals in bash Ctrl-d act like delete if line
is not empty.
(this is emax style). When line is empty it terminates.
You or Szymon asked me to add Ctrl-c to clear current line like in other tools.
So maybe it wold be better to put Ctrl-d in patch title instead of Ctrl-c

>
> I wouldn't have expected this to be an issue if stdin is processed
> properly, but it seems even something like the following doesn't result
> in the expected behavior right now (to run all commands in the file and
> then exit the tool):
>
> $ tools/haltest < my-script.txt

This I haven't tried yet so this will probably not work.
But I can handle it some other way not related to Ctrl-d (later :)).

>
> Another thing I'd like to see fixed is getting the terminal back to a
> sane state when exiting. Right now even after a clean exit I seem to
> have to do a hard terminal reset to get normal behavior back. As an
> example, the following is what I get after cleanly exiting using "exit"
> and then pressing enter a couple of times:
>
> jh@x220:bluez{master}$ android/haltest
>> exit

This  is what patch 2 handles by setting atexit() cleanup function that restore
terminal settings. Before there was exit command, ctrl-c did it automatically.

> jh@x220:bluez{master}$ jh@x220:bluez{master}$ jh@x220:bluez{master}$
>
> Johan


-- 
Jerzy Kasenberg

^ permalink raw reply

* Re: [PATCH] android: Improve hal_ipc_cmd helper
From: Johan Hedberg @ 2013-10-22  7:34 UTC (permalink / raw)
  To: Szymon Janc; +Cc: linux-bluetooth
In-Reply-To: <1382426248-10793-1-git-send-email-szymon.janc@tieto.com>

Hi Szymon,

On Tue, Oct 22, 2013, Szymon Janc wrote:
> Handle error response inside helper so that users don't expecting any
> response don't need to provide dummy buffer only for error (which is
> already return value of helper).
> ---
>  android/hal-bluetooth.c | 7 ++-----
>  android/hal-ipc.c       | 6 ++++++
>  2 files changed, 8 insertions(+), 5 deletions(-)

Applied. Thanks.

Johan

^ permalink raw reply

* Re: [PATCH] Bluetooth: Add function name to debug prints
From: Johan Hedberg @ 2013-10-22  7:29 UTC (permalink / raw)
  To: Jukka Rissanen; +Cc: linux-bluetooth
In-Reply-To: <1382425751-9018-1-git-send-email-jukka.rissanen@linux.intel.com>

Hi Jukka,

On Tue, Oct 22, 2013, Jukka Rissanen wrote:
> the debug prints are quite useless without the function name.
> Without this patch one sees lot of "hci0" lines which is not
> very helpful.
> 
> Cheers,
> Jukka
> 
>  include/net/bluetooth/bluetooth.h | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
> 
> diff --git a/include/net/bluetooth/bluetooth.h b/include/net/bluetooth/bluetooth.h
> index bf2ddff..0b1eacd 100644
> --- a/include/net/bluetooth/bluetooth.h
> +++ b/include/net/bluetooth/bluetooth.h
> @@ -122,7 +122,7 @@ int bt_err(const char *fmt, ...);
>  
>  #define BT_INFO(fmt, ...)	bt_info(fmt "\n", ##__VA_ARGS__)
>  #define BT_ERR(fmt, ...)	bt_err(fmt "\n", ##__VA_ARGS__)
> -#define BT_DBG(fmt, ...)	pr_debug(fmt "\n", ##__VA_ARGS__)
> +#define BT_DBG(fmt, ...)	pr_debug("%s():" fmt "\n", __FUNCTION__, ##__VA_ARGS__)

This shouldn't be necessary since you can ask the function name to be
printed using standard dynamic debug control syntax, e.g:

echo "file hci_event.c +pf" > /sys/kernel/debug/dynamic_debug/control

Johan

^ permalink raw reply

* [PATCH] android: Improve hal_ipc_cmd helper
From: Szymon Janc @ 2013-10-22  7:17 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Szymon Janc

Handle error response inside helper so that users don't expecting any
response don't need to provide dummy buffer only for error (which is
already return value of helper).
---
 android/hal-bluetooth.c | 7 ++-----
 android/hal-ipc.c       | 6 ++++++
 2 files changed, 8 insertions(+), 5 deletions(-)

diff --git a/android/hal-bluetooth.c b/android/hal-bluetooth.c
index f408a7d..5b07070 100644
--- a/android/hal-bluetooth.c
+++ b/android/hal-bluetooth.c
@@ -40,7 +40,6 @@ static bool interface_ready(void)
 static int init(bt_callbacks_t *callbacks)
 {
 	struct hal_msg_cmd_register_module cmd;
-	struct hal_msg_rsp_error rsp;
 
 	DBG("");
 
@@ -55,8 +54,7 @@ static int init(bt_callbacks_t *callbacks)
 	cmd.service_id = HAL_SERVICE_ID_BLUETOOTH;
 
 	if (hal_ipc_cmd(HAL_SERVICE_ID_CORE, HAL_MSG_OP_REGISTER_MODULE,
-						sizeof(cmd), &cmd,
-						sizeof(rsp), &rsp, NULL) < 0) {
+				sizeof(cmd), &cmd, 0, NULL, NULL) < 0) {
 		error("Failed to register 'bluetooth' service");
 		goto fail;
 	}
@@ -64,8 +62,7 @@ static int init(bt_callbacks_t *callbacks)
 	cmd.service_id = HAL_SERVICE_ID_SOCK;
 
 	if (hal_ipc_cmd(HAL_SERVICE_ID_CORE, HAL_MSG_OP_REGISTER_MODULE,
-						sizeof(cmd), &cmd,
-						sizeof(rsp), &rsp, NULL) < 0) {
+				sizeof(cmd), &cmd, 0, NULL, NULL) < 0) {
 		error("Failed to register 'socket' service");
 		goto fail;
 	}
diff --git a/android/hal-ipc.c b/android/hal-ipc.c
index 5b77adf..8d40271 100644
--- a/android/hal-ipc.c
+++ b/android/hal-ipc.c
@@ -146,10 +146,16 @@ int hal_ipc_cmd(uint8_t service_id, uint8_t opcode, uint16_t len, void *param,
 	struct iovec iv[2];
 	struct hal_msg_hdr hal_msg;
 	char cmsgbuf[CMSG_SPACE(sizeof(int))];
+	struct hal_msg_rsp_error err;
 
 	if (cmd_sk < 0)
 		return -EBADF;
 
+	if (!rsp || rsp_len == 0) {
+		memset(&err, 0, sizeof(err));
+		rsp = &err;
+	}
+
 	memset(&msg, 0, sizeof(msg));
 	memset(&hal_msg, 0, sizeof(hal_msg));
 
-- 
1.8.4


^ permalink raw reply related

* [PATCH] Bluetooth: Add function name to debug prints
From: Jukka Rissanen @ 2013-10-22  7:09 UTC (permalink / raw)
  To: linux-bluetooth

---
Hi,

the debug prints are quite useless without the function name.
Without this patch one sees lot of "hci0" lines which is not
very helpful.

Cheers,
Jukka

 include/net/bluetooth/bluetooth.h | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/include/net/bluetooth/bluetooth.h b/include/net/bluetooth/bluetooth.h
index bf2ddff..0b1eacd 100644
--- a/include/net/bluetooth/bluetooth.h
+++ b/include/net/bluetooth/bluetooth.h
@@ -122,7 +122,7 @@ int bt_err(const char *fmt, ...);
 
 #define BT_INFO(fmt, ...)	bt_info(fmt "\n", ##__VA_ARGS__)
 #define BT_ERR(fmt, ...)	bt_err(fmt "\n", ##__VA_ARGS__)
-#define BT_DBG(fmt, ...)	pr_debug(fmt "\n", ##__VA_ARGS__)
+#define BT_DBG(fmt, ...)	pr_debug("%s():" fmt "\n", __FUNCTION__, ##__VA_ARGS__)
 
 /* Connection and socket states */
 enum {
-- 
1.7.11.7


^ permalink raw reply related

* Re: [PATCH] android: Add missing HAL IPC error status definitions
From: Johan Hedberg @ 2013-10-22  7:03 UTC (permalink / raw)
  To: Szymon Janc; +Cc: linux-bluetooth
In-Reply-To: <1382424852-8049-1-git-send-email-szymon.janc@tieto.com>

Hi Szymon,

On Tue, Oct 22, 2013, Szymon Janc wrote:
> ---
>  android/hal-msg.h | 9 +++++++++
>  1 file changed, 9 insertions(+)
> 
> diff --git a/android/hal-msg.h b/android/hal-msg.h
> index 1f77586..7d91ed1 100644
> --- a/android/hal-msg.h
> +++ b/android/hal-msg.h
> @@ -47,6 +47,15 @@ struct hal_msg_hdr {
>  /* Core Service */
>  
>  #define HAL_ERROR_FAILED		0x01
> +#define HAL_ERROR_NOT_READY		0x02
> +#define HAL_ERROR_NOMEM			0x03
> +#define HAL_ERROR_BUSY			0x04
> +#define HAL_ERROR_DONE			0x05
> +#define HAL_ERROR_UNSUPPORTED		0x06
> +#define HAL_ERROR_INVALID		0x07
> +#define HAL_ERROR_UNHANDLED		0x08
> +#define HAL_ERROR_AUTH_FAILURE		0x09
> +#define HAL_ERROR_REMOTE_DEVICE_DOWN	0x0A

Applied after a minor s/0A/0a/ change to make this consistent with the
rest of the header file.

Johan

^ permalink raw reply

* [PATCH] android: Add missing HAL IPC error status definitions
From: Szymon Janc @ 2013-10-22  6:54 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Szymon Janc

---
 android/hal-msg.h | 9 +++++++++
 1 file changed, 9 insertions(+)

diff --git a/android/hal-msg.h b/android/hal-msg.h
index 1f77586..7d91ed1 100644
--- a/android/hal-msg.h
+++ b/android/hal-msg.h
@@ -47,6 +47,15 @@ struct hal_msg_hdr {
 /* Core Service */
 
 #define HAL_ERROR_FAILED		0x01
+#define HAL_ERROR_NOT_READY		0x02
+#define HAL_ERROR_NOMEM			0x03
+#define HAL_ERROR_BUSY			0x04
+#define HAL_ERROR_DONE			0x05
+#define HAL_ERROR_UNSUPPORTED		0x06
+#define HAL_ERROR_INVALID		0x07
+#define HAL_ERROR_UNHANDLED		0x08
+#define HAL_ERROR_AUTH_FAILURE		0x09
+#define HAL_ERROR_REMOTE_DEVICE_DOWN	0x0A
 
 #define HAL_MSG_OP_ERROR		0x00
 struct hal_msg_rsp_error {
-- 
1.8.4


^ permalink raw reply related

* [PATCH] android: Add capabilities and set userid
From: Andrei Emeltchenko @ 2013-10-22  6:35 UTC (permalink / raw)
  To: linux-bluetooth

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

The patch set UID as standard Bluetooth user for Android (AID_BLUETOOTH).
It also sets the same capability needed for systemd service (found
in src/bluetooth.service.
---
 android/main.c | 53 +++++++++++++++++++++++++++++++++++++++++++++++++++++
 configure.ac   |  4 ++++
 2 files changed, 57 insertions(+)

diff --git a/android/main.c b/android/main.c
index fac1003..e7f842e 100644
--- a/android/main.c
+++ b/android/main.c
@@ -33,10 +33,17 @@
 #include <stdbool.h>
 #include <string.h>
 #include <errno.h>
+#include <unistd.h>
+
 #include <sys/signalfd.h>
 #include <sys/socket.h>
 #include <sys/un.h>
 
+#if defined(ANDROID)
+#include <sys/prctl.h>
+#include <private/android_filesystem_config.h>
+#endif
+
 #include <glib.h>
 
 #include "log.h"
@@ -409,6 +416,49 @@ static void cleanup_hal_connection(void)
 	}
 }
 
+static bool set_capabilities(void)
+{
+#if defined(ANDROID)
+	struct __user_cap_header_struct header;
+	struct __user_cap_data_struct cap;
+
+	DBG("pid %d uid %d gid %d", getpid(), getuid(), getgid());
+
+	header.version = _LINUX_CAPABILITY_VERSION;
+
+	prctl(PR_SET_KEEPCAPS, 1, 0, 0, 0);
+
+	if (setgid(AID_BLUETOOTH) < 0)
+		warn("%s: setgid(): %s", __func__, strerror(errno));
+
+	if (setuid(AID_BLUETOOTH) < 0)
+		warn("%s: setuid(): %s", __func__, strerror(errno));
+
+	header.version = _LINUX_CAPABILITY_VERSION;
+	header.pid = 0;
+
+	cap.effective = cap.permitted =
+		CAP_TO_MASK(CAP_NET_RAW) |
+		CAP_TO_MASK(CAP_NET_ADMIN) |
+		CAP_TO_MASK(CAP_NET_BIND_SERVICE);
+	cap.inheritable = 0;
+
+	if (capset(&header, &cap) < 0) {
+		error("%s: capset(): %s", __func__, strerror(errno));
+		return false;
+	}
+
+	if (capget(&header, &cap) < 0)
+		error("%s: capget(): %s", __func__, strerror(errno));
+	else
+		DBG("Caps: eff: 0x%x, perm: 0x%x, inh: 0x%x", cap.effective,
+					cap.permitted, cap.inheritable);
+
+	DBG("pid %d uid %d gid %d", getpid(), getuid(), getgid());
+#endif
+	return true;
+}
+
 int main(int argc, char *argv[])
 {
 	GOptionContext *context;
@@ -442,6 +492,9 @@ int main(int argc, char *argv[])
 
 	__btd_log_init("*", 0);
 
+	if (!set_capabilities())
+		return EXIT_FAILURE;
+
 	if (!init_mgmt_interface())
 		return EXIT_FAILURE;
 
diff --git a/configure.ac b/configure.ac
index b4d3998..e3b5220 100644
--- a/configure.ac
+++ b/configure.ac
@@ -247,4 +247,8 @@ AC_ARG_ENABLE(android, AC_HELP_STRING([--enable-android],
 					[enable_android=${enableval}])
 AM_CONDITIONAL(ANDROID, test "${enable_android}" = "yes")
 
+if (test "${enable_android}" = "yes"); then
+	AC_CHECK_LIB(cap, capget, dummy=yes, AC_MSG_ERROR(libcap is required))
+fi
+
 AC_OUTPUT(Makefile src/bluetoothd.8 lib/bluez.pc)
-- 
1.8.1.2


^ permalink raw reply related

* [PATCH] android: Add capabilities and set userid
From: Andrei Emeltchenko @ 2013-10-22  6:28 UTC (permalink / raw)
  To: linux-bluetooth

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

The patch set UID as standard Bluetooth user for Android (AID_BLUETOOTH).
It also sets the same capability needed for systemd service (found
in src/bluetooth.service.
---
 android/main.c | 53 +++++++++++++++++++++++++++++++++++++++++++++++++++++
 configure.ac   |  4 ++++
 2 files changed, 57 insertions(+)

diff --git a/android/main.c b/android/main.c
index fac1003..e7f842e 100644
--- a/android/main.c
+++ b/android/main.c
@@ -33,10 +33,17 @@
 #include <stdbool.h>
 #include <string.h>
 #include <errno.h>
+#include <unistd.h>
+
 #include <sys/signalfd.h>
 #include <sys/socket.h>
 #include <sys/un.h>
 
+#if defined(ANDROID)
+#include <sys/prctl.h>
+#include <private/android_filesystem_config.h>
+#endif
+
 #include <glib.h>
 
 #include "log.h"
@@ -409,6 +416,49 @@ static void cleanup_hal_connection(void)
 	}
 }
 
+static bool set_capabilities(void)
+{
+#if defined(ANDROID)
+	struct __user_cap_header_struct header;
+	struct __user_cap_data_struct cap;
+
+	DBG("pid %d uid %d gid %d", getpid(), getuid(), getgid());
+
+	header.version = _LINUX_CAPABILITY_VERSION;
+
+	prctl(PR_SET_KEEPCAPS, 1, 0, 0, 0);
+
+	if (setgid(AID_BLUETOOTH) < 0)
+		warn("%s: setgid(): %s", __func__, strerror(errno));
+
+	if (setuid(AID_BLUETOOTH) < 0)
+		warn("%s: setuid(): %s", __func__, strerror(errno));
+
+	header.version = _LINUX_CAPABILITY_VERSION;
+	header.pid = 0;
+
+	cap.effective = cap.permitted =
+		CAP_TO_MASK(CAP_NET_RAW) |
+		CAP_TO_MASK(CAP_NET_ADMIN) |
+		CAP_TO_MASK(CAP_NET_BIND_SERVICE);
+	cap.inheritable = 0;
+
+	if (capset(&header, &cap) < 0) {
+		error("%s: capset(): %s", __func__, strerror(errno));
+		return false;
+	}
+
+	if (capget(&header, &cap) < 0)
+		error("%s: capget(): %s", __func__, strerror(errno));
+	else
+		DBG("Caps: eff: 0x%x, perm: 0x%x, inh: 0x%x", cap.effective,
+					cap.permitted, cap.inheritable);
+
+	DBG("pid %d uid %d gid %d", getpid(), getuid(), getgid());
+#endif
+	return true;
+}
+
 int main(int argc, char *argv[])
 {
 	GOptionContext *context;
@@ -442,6 +492,9 @@ int main(int argc, char *argv[])
 
 	__btd_log_init("*", 0);
 
+	if (!set_capabilities())
+		return EXIT_FAILURE;
+
 	if (!init_mgmt_interface())
 		return EXIT_FAILURE;
 
diff --git a/configure.ac b/configure.ac
index b4d3998..e3b5220 100644
--- a/configure.ac
+++ b/configure.ac
@@ -247,4 +247,8 @@ AC_ARG_ENABLE(android, AC_HELP_STRING([--enable-android],
 					[enable_android=${enableval}])
 AM_CONDITIONAL(ANDROID, test "${enable_android}" = "yes")
 
+if (test "${enable_android}" = "yes"); then
+	AC_CHECK_LIB(cap, capget, dummy=yes, AC_MSG_ERROR(libcap is required))
+fi
+
 AC_OUTPUT(Makefile src/bluetoothd.8 lib/bluez.pc)
-- 
1.8.1.2


^ permalink raw reply related

* Re: GATT - How to mark an attribute as requiring encryption
From: Anderson Lizardo @ 2013-10-22  1:31 UTC (permalink / raw)
  To: Scott James Remnant; +Cc: linux-bluetooth@vger.kernel.org
In-Reply-To: <CAHZ1yC=vh0PUS7ZgZ_zUff_gPzLwjYx8EABxbT71uU5zQAChTQ@mail.gmail.com>

Hi Scott,

On Mon, Oct 21, 2013 at 9:01 PM, Scott James Remnant <keybuk@google.com> wrote:
> While there is a way to mark an attribute as needing authentication
> and/or authorization, there does not seem to be a way to mark an
> attribute as requiring encryption (or a particular key size), and I
> couldn't find any code that would return the ATT_ECODE_INSUFF_ENC or
> ATT_ECODE_INSUFF_ENCR_KEY_SIZE responses.

There is a FIXME for this on function att_check_reqs()
(src/attrib-server.c). Feel free to fix it :)

Note that, as part of the ongoing implementation of a D-Bus API for
implementing external GATT services, we have patches (currently being
cleaned up for upstream submission) that will refactor the internal C
API for creating GATT services. If you are interested, take a look at
(note that it is work-in-progress code):

git://git.infradead.org/users/cktakahasi/bluez.git (branch gatt-api-devel)

Also take a look at the API document sent by Claudio a few days ago:
"[RFC BlueZ v0] doc: Add GATT API"

Best Regards,
-- 
Anderson Lizardo
Instituto Nokia de Tecnologia - INdT
Manaus - Brazil

^ permalink raw reply

* GATT - How to mark an attribute as requiring encryption
From: Scott James Remnant @ 2013-10-22  1:01 UTC (permalink / raw)
  To: linux-bluetooth@vger.kernel.org

While there is a way to mark an attribute as needing authentication
and/or authorization, there does not seem to be a way to mark an
attribute as requiring encryption (or a particular key size), and I
couldn't find any code that would return the ATT_ECODE_INSUFF_ENC or
ATT_ECODE_INSUFF_ENCR_KEY_SIZE responses.

There is an explicit test case in the GATT TS for this:

  TP/GAR/SR/BI-05-C [Read Characteristic Value - Insufficient
Encryption Key Size]

The TRCL maps this:

  (GATT:3/8 AND ATT:5/2)
  OR
  (ATT:3/1 AND ATT:3/10 AND ATT:5/2)

GATT:3/8 [Read Characteristic Value] is Mandatory
ATT:5/2 - [LE Security Mode 1] is Optional, but without it none of the
authentication or authorization stuff makes sense either

Reference:
 GATT 4.8.1
 ATT 3.4.11, 3.4.4.3

Thoughts?

Scott
-- 
Scott James Remnant | Chrome OS Systems | keybuk@google.com | Google

^ permalink raw reply

* pull request: bluetooth-next 2013-10-21
From: Gustavo Padovan @ 2013-10-21 22:37 UTC (permalink / raw)
  To: linville; +Cc: linux-wireless, linux-bluetooth, linux-kernel

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

Hi John,

One more big pull request for 3.13. These are the patches we queued during
last week. Here you will find a lot of improvements to the HCI and L2CAP and
MGMT layers with the main ones being a better debugfs support and end of work
of splitting L2CAP into Core and Socket parts.

Please pull!

	Gustavo

---
The following changes since commit 4b836f393bd8ed111857a6ee1865e44627266ec6:

  Bluetooth: Read current IAC LAP on controller setup (2013-10-14 19:31:18 -0300)

are available in the git repository at:

  git://git.kernel.org/pub/scm/linux/kernel/git/bluetooth/bluetooth-next for-upstream

for you to fetch changes up to d78a32a8fcf775111ccc9ba611a08ca5c29784b6:

  Bluetooth: Remove sk member from struct l2cap_chan (2013-10-21 13:50:56 -0700)

----------------------------------------------------------------
Gustavo Padovan (14):
      Bluetooth: Extend state_change() call to report errors too
      Bluetooth: Add l2cap_state_change_and_error()
      Bluetooth: Access sk_sndtimeo indirectly in l2cap_core.c
      Bluetooth: Add chan->ops->set_shutdown()
      Bluetooth: Move l2cap_wait_ack() to l2cap_sock.c
      Bluetooth: use l2cap_chan_ready() instead of duplicate code
      Bluetooth: Remove not used struct sock
      Bluetooth: Do not access chan->sk directly
      Bluetooth: Hold socket in defer callback in L2CAP socket
      Bluetooth: Remove socket lock from l2cap_state_change()
      Bluetooth: Remove parent socket usage from l2cap_core.c
      Bluetooth: Add L2CAP channel to skb private data
      Bluetooth: Use bt_cb(skb)->chan to send raw data back
      Bluetooth: Remove sk member from struct l2cap_chan

Johan Hedberg (20):
      Bluetooth: Fix L2CAP "Command Reject: Invalid CID" response
      Bluetooth: Remove unused command reject mapping for EMSGSIZE
      Bluetooth: Remove useless l2cap_err_to_reason function
      Bluetooth: Ignore A2MP data on non-BR/EDR links
      Bluetooth: Ignore SMP data on non-LE links
      Bluetooth: Fix updating the right variable in update_scan_rsp_data()
      Bluetooth: Reintroduce socket restrictions for LE sockets
      Bluetooth: Convert auto accept timer to use delayed work
      Bluetooth: Convert idle timer to use delayed work
      Bluetooth: Fix ATT socket backwards compatibility with user space
      Bluetooth: Check for flag instead of features in update_scan_rsp_data()
      Bluetooth: Check for flag instead of features in update_adv_data()
      Bluetooth: Add missing check for BREDR_ENABLED flag in update_class()
      Bluetooth: Refactor set_connectable settings update to separate function
      Bluetooth: Fix updating settings when there are no HCI commands to send
      Bluetooth: Move mgmt_pending_find to avoid forward declarations
      Bluetooth: Fix sending write_scan_enable when BR/EDR is disabled
      Bluetooth: Move HCI_LIMITED_DISCOVERABLE changes to a general place
      Bluetooth: Update Set Discoverable to support LE
      Bluetooth: Fix enabling fast connectable on LE-only controllers

Marcel Holtmann (71):
      Bluetooth: Fix minor coding style issue in set_connectable()
      Bluetooth: Use hci_request for discoverable timeout handling
      Bluetooth: Update advertising data based on management commands
      Bluetooth: Introduce flag for limited discoverable mode
      Bluetooth: Make mgmt_discoverable() return void
      Bluetooth: Make mgmt_connectable() return void
      Bluetooth: Make mgmt_write_scan_failed() return void
      Bluetooth: Update class of device after changing discoverable mode
      Bluetooth: Move arming of discoverable timeout to complete handler
      Bluetooth: Simplify the code for re-arming discoverable timeout
      Bluetooth: Add HCI command structure for writing current IAC LAP
      Bluetooth: Add support for entering limited discoverable mode
      Bluetooth: Make mgmt_new_link_key() return void
      Bluetooth: Move eir_append_data() function into mgmt.c
      Bluetooth: Move eir_get_length() function into hci_event.c
      Bluetooth: Update class of device on discoverable timeout
      Bluetooth: Add l2cap_chan_no_resume stub for A2MP
      Bluetooth: Make mgmt_pin_code_request() return void
      Bluetooth: Make mgmt_pin_code_reply_complete() return void
      Bluetooth: Make mgmt_pin_code_neg_reply_complete() return void
      Bluetooth: Make mgmt_auth_failed() return void
      Bluetooth: Make mgmt_auth_enable_complete() return void
      Bluetooth: Make mgmt_ssp_enable_complete() return void
      Bluetooth: Make mgmt_set_class_of_dev_complete() return void
      Bluetooth: Make mgmt_set_local_name_complete() return void
      Bluetooth: Make mgmt_read_local_oob_data_reply_complete() return void
      Bluetooth: Make mgmt_new_ltk() return void
      Bluetooth: Rename create_ad into create_adv_data
      Bluetooth: Store scan response data in HCI device
      Bluetooth: Set the scan response data when needed
      Bluetooth: Store device name in scan response data
      Bluetooth: Rename update_ad into update_adv_data
      Bluetooth: Remove duplicate definitions for advertising event types
      Bluetooth: Remove enable_hs declaration
      Bluetooth: Socket address parameter for CID is in little endian
      Bluetooth: Expose inquiry_cache debugfs only on BR/EDR controllers
      Bluetooth: Expose auto_accept_delay debugfs only when SSP is supported
      Bluetooth: Expose static address value for LE capable controllers
      Bluetooth: Expose current voice setting in debugfs
      Bluetooth: Add address type to device blacklist table
      Bluetooth: Move blacklist debugfs entry creation into hci_core.c
      Bluetooth: Move uuids debugfs entry creation into hci_core.c
      Bluetooth: Use IS_ERR_OR_NULL for checking bt_debugfs
      Bluetooth: Create HCI device debugfs directory in hci_register_dev
      Bluetooth: Create root debugfs directory during module init
      Bluetooth: Move device_add handling into hci_register_dev
      Bluetooth: Include address type in blacklist debugfs data
      Bluetooth: Move idle_timeout and sniff_{min,max}_interval to hci_core.c
      Bluetooth: Use BDADDR_BREDR type for old blacklist ioctl interface
      Bluetooth: Use hcon directly instead of conn->hcon where possible
      Bluetooth: Block ATT connection on LE when device is blocked
      Bluetooth: Move HCI device features into hci_core.c
      Bluetooth: Add workaround for buggy max_page features page value
      Bluetooth: Remove debug entry for connection features
      Bluetooth: Move manufacturer, hci_ver and hci_rev into hci_core.c
      Bluetooth: Store local version information only during setup phase
      Bluetooth: Move export of class of device information into hci_core.c
      Bluetooth: Expose current list of link keys via debugfs
      Bluetooth: Remove bus attribute in favor of hierarchy
      Bluetooth: Expose white list size information in debugfs
      Bluetooth: Expose current list of long term keys via debugfs
      Bluetooth: Select the own address type during initial setup phase
      Bluetooth: Expose debugfs entry read/write own address type
      Bluetooth: Expose setting if debug keys are used or not
      Bluetooth: Add LE features to debugfs if available
      Bluetooth: Remove interval parameter from HCI connection
      Bluetooth: Add support for setting SSP debug mode
      Bluetooth: Expose debugfs settings for LE connection interval
      Bluetooth: Add support for setting DUT mode
      Bluetooth: Fix UUID values in debugfs file
      Bluetooth: Fix minor coding style issue in hci_core.c

 include/net/bluetooth/bluetooth.h |   1 +
 include/net/bluetooth/hci.h       |  35 ++-
 include/net/bluetooth/hci_core.h  |  89 +++----
 include/net/bluetooth/l2cap.h     |  20 +-
 net/bluetooth/a2mp.c              |   9 +-
 net/bluetooth/af_bluetooth.c      |   9 +-
 net/bluetooth/hci_conn.c          |  48 ++--
 net/bluetooth/hci_core.c          | 803 +++++++++++++++++++++++++++++++++++++++++++++++++--------
 net/bluetooth/hci_event.c         |  59 +++--
 net/bluetooth/hci_sock.c          |   4 +-
 net/bluetooth/hci_sysfs.c         | 373 ---------------------------
 net/bluetooth/l2cap_core.c        | 227 ++++++----------
 net/bluetooth/l2cap_sock.c        | 120 ++++++++-
 net/bluetooth/mgmt.c              | 637 ++++++++++++++++++++++++++++++++-------------
 net/bluetooth/rfcomm/core.c       |  14 +-
 net/bluetooth/rfcomm/sock.c       |  14 +-
 net/bluetooth/sco.c               |  13 +-
 net/bluetooth/smp.c               |   4 +-
 18 files changed, 1506 insertions(+), 973 deletions(-)


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

^ 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