Linux bluetooth development
 help / color / mirror / Atom feed
* [PATCH v3] android: Fix build error for Android
From: Lukasz Rymanowski @ 2013-10-23 12:49 UTC (permalink / raw)
  To: linux-bluetooth
  Cc: szymon.janc, andrei.emeltchenko, johan.hedberg, Lukasz Rymanowski

Android uses functions and defines from sys/capability.h which
requires additional include. However file capability.h shows up
in bionic in version Android 4.3, therefore we do check
PLATFORM_SDK_VERSION to no break builds of previous Android versions.
In previous Android version unistd.h contain this functionality.
---
 android/Android.mk | 3 ++-
 android/main.c     | 6 ++++++
 2 files changed, 8 insertions(+), 1 deletion(-)

diff --git a/android/Android.mk b/android/Android.mk
index c4b0621..a569650 100644
--- a/android/Android.mk
+++ b/android/Android.mk
@@ -36,7 +36,8 @@ LOCAL_C_INCLUDES += \
 	$(LOCAL_PATH)/../src \
 	$(LOCAL_PATH)/../lib \
 
-LOCAL_CFLAGS := -DVERSION=\"$(BLUEZ_VERSION)\"
+LOCAL_CFLAGS := -DVERSION=\"$(BLUEZ_VERSION)\" \
+	-DPLATFORM_SDK_VERSION=$(PLATFORM_SDK_VERSION)
 
 LOCAL_SHARED_LIBRARIES := \
 	libglib \
diff --git a/android/main.c b/android/main.c
index 988d08b..5a85f74 100644
--- a/android/main.c
+++ b/android/main.c
@@ -52,6 +52,12 @@
 #include "hal-msg.h"
 #include "ipc.h"
 
+/* TODO: Consider to remove PLATFORM_SDKVERSION check if requirement
+*  for minimal Android platform version increases. */
+#if defined(ANDROID) && PLATFORM_SDK_VERSION >= 18
+#include <sys/capability.h>
+#endif
+
 static GMainLoop *event_loop;
 static struct mgmt *mgmt_if = NULL;
 
-- 
1.8.4


^ permalink raw reply related

* [PATCH] android: Make use of Android system headers instead of local one
From: Andrei Emeltchenko @ 2013-10-23 12:44 UTC (permalink / raw)
  To: linux-bluetooth

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

Since the headers were copied to android/ folder Android build started
to use those instead of original Android system headers. The patch
puts Android system headers first.
---
 android/Android.mk | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/android/Android.mk b/android/Android.mk
index 3163763..0640842 100644
--- a/android/Android.mk
+++ b/android/Android.mk
@@ -71,6 +71,9 @@ LOCAL_SRC_FILES := \
 	hal-pan.c \
 	hal-av.c \
 
+LOCAL_C_INCLUDES += \
+	system/core/include \
+
 LOCAL_SHARED_LIBRARIES := \
 	libcutils \
 
-- 
1.8.1.2


^ permalink raw reply related

* Re: [RFC 3/5] route: Exporting ip6_route_add() so that BLE 6LoWPAN can use it
From: Jukka Rissanen @ 2013-10-23 12:41 UTC (permalink / raw)
  To: Marcel Holtmann; +Cc: linux-bluetooth
In-Reply-To: <30925AE8-AE7B-43D9-9E5D-4898C0CF8390@holtmann.org>

Hi Marcel,

On 23.10.2013 15:00, Marcel Holtmann wrote:
> Hi Jukka,
>
>> net/ipv6/route.c | 1 +
>> 1 file changed, 1 insertion(+)
>>
>> diff --git a/net/ipv6/route.c b/net/ipv6/route.c
>> index c979dd9..d7c200f 100644
>> --- a/net/ipv6/route.c
>> +++ b/net/ipv6/route.c
>> @@ -1662,6 +1662,7 @@ out:
>> 		dst_free(&rt->dst);
>> 	return err;
>> }
>> +EXPORT_SYMBOL_GPL(ip6_route_add);
>
> check with netdev is this is something that would be accepted upstream.

We could also tell userspace (bluez or connman) to create the route if 
needed.

>
> For the time being, can we work around this internally for testing? I like to just build and load a new Bluetooth module for testing and not have to replace IPv6 as well.

Sure, just do

ip -6 route add <peer>

after connecting the devices.

The peer link local address is perhaps easiest to get by using online 
calculator like http://ben.akrin.com/?p=1347



-- 
Cheers,
Jukka

^ permalink raw reply

* Re: [RFC 5/5] Bluetooth: Manually enable or disable 6LoWPAN between devices
From: Marcel Holtmann @ 2013-10-23 12:09 UTC (permalink / raw)
  To: Jukka Rissanen; +Cc: linux-bluetooth
In-Reply-To: <1382511164-1989-6-git-send-email-jukka.rissanen@linux.intel.com>

Hi Jukka,

> This is a temporary patch where user can manually enable or
> disable BT LE 6LoWPAN functionality between devices.
> Eventually the connection is established automatically if
> the devices are advertising suitable capability and this patch
> can be removed.
> 
> If you have two devices with these BT addresses
>        device1  00:11:22:33:44:55
>        device2  66:77:88:99:00:11
> 
> First add the desired devices manually into kernel
> 
> root@dev1# echo 66:77:88:99:00:11 > /sys/kernel/debug/bluetooth/hci0/ble6lowpan
> root@dev2# echo 00:11:22:33:44:55 > /sys/kernel/debug/bluetooth/hci0/ble6lowpan
> 
> then connect the devices
> 
> root@dev1# hciconfig hci0 leadv
> root@dev2# hcitool lecc 00:11:22:33:44:55
> 
> if the connection is established, then you can send IPv6 packets
> between these two systems using the link local addresses
> 
> root@dev1# ping6 fe80::6477:88ff:fe99:0011
> root@dev2# ping6 fe80::211:22ff:fe33:4455
> 
> By default 6LoWPAN connection is not established between devices,
> so you need to add the MAC addresses manually into the
> /sys/kernel/debug/bluetooth/hci0/ble6lowpan file.
> If you want to prevent further connections you can remove
> MAC address from the debugfs file like this
> echo "00:11:22:33:44:55 d" > /sys/kernel/debug/bluetooth/hci0/ble6lowpan
> Rebooting or unloading the bluetooth kernel module will also clear the
> settings from the kernel.
> ---
> net/bluetooth/ble_6lowpan.c | 164 ++++++++++++++++++++++++++++++++++++++++++++
> net/bluetooth/ble_6lowpan.h |   1 +
> net/bluetooth/hci_core.c    |   4 ++
> net/bluetooth/l2cap_core.c  |  12 ++--
> 4 files changed, 174 insertions(+), 7 deletions(-)
> 
> diff --git a/net/bluetooth/ble_6lowpan.c b/net/bluetooth/ble_6lowpan.c
> index 44d65b3..0baf211 100644
> --- a/net/bluetooth/ble_6lowpan.c
> +++ b/net/bluetooth/ble_6lowpan.c
> @@ -12,6 +12,7 @@
> */
> 
> #include <linux/version.h>
> +#include <linux/debugfs.h>
> #include <linux/bitops.h>
> #include <linux/if_arp.h>
> #include <linux/netdevice.h>
> @@ -1535,6 +1536,169 @@ static struct notifier_block ble_6lowpan_dev_notifier = {
> 	.notifier_call = ble_6lowpan_device_event,
> };
> 
> +static LIST_HEAD(user_enabled);
> +DEFINE_RWLOCK(user_enabled_list_lock);
> +
> +struct ble_6lowpan_enabled {
> +	__u8 dev_name[HCI_MAX_NAME_LENGTH];
> +	bdaddr_t addr;
> +	struct list_head list;
> +};
> +
> +bool ble_6lowpan_is_enabled(struct hci_dev *hdev, bdaddr_t *dst)
> +{
> +	struct ble_6lowpan_enabled *entry, *tmp;
> +	bool found = false;
> +
> +	write_lock(&user_enabled_list_lock);
> +	list_for_each_entry_safe(entry, tmp, &user_enabled, list) {
> +		if (!strncmp(entry->dev_name, hdev->dev_name,
> +				HCI_MAX_NAME_LENGTH) &&
> +				!bacmp(dst, &entry->addr)) {
> +			found = true;
> +			break;
> +		}
> +	}
> +	write_unlock(&user_enabled_list_lock);
> +
> +	/* Check also the device list just in case we removed the
> +	 * device from debugfs before disconnecting.
> +	 */
> +	if (!found) {
> +		struct ble_6lowpan_dev_record *entry, *tmp;
> +		struct ble_6lowpan_dev_info *info;
> +
> +		write_lock(&net_dev_list_lock);
> +		list_for_each_entry_safe(entry, tmp,
> +					&ble_6lowpan_devices,
> +					list) {
> +			info = ble_6lowpan_dev_info(entry->dev);
> +			if (info->conn->hcon->hdev == hdev &&
> +						!bacmp(&info->addr, dst)) {
> +				found = true;
> +				break;
> +			}
> +		}
> +		write_unlock(&net_dev_list_lock);
> +	}
> +
> +	return found;
> +}
> +
> +static int ble_6lowpan_debugfs_show(struct seq_file *f, void *p)
> +{
> +	struct ble_6lowpan_enabled *entry, *tmp;
> +
> +	write_lock(&user_enabled_list_lock);
> +	list_for_each_entry_safe(entry, tmp, &user_enabled, list)
> +		seq_printf(f, "%pMR\n", &entry->addr);
> +
> +	write_unlock(&user_enabled_list_lock);
> +
> +	return 0;
> +}
> +
> +static int ble_6lowpan_debugfs_open(struct inode *inode, struct file *file)
> +{
> +	return single_open(file, ble_6lowpan_debugfs_show, inode->i_private);
> +}
> +
> +static ssize_t ble_6lowpan_writer(struct file *fp,
> +				const char __user *user_buffer,
> +                                size_t count, loff_t *position)
> +{
> +#define MAC_STR_LEN 17
> +	char mac_buf[MAC_STR_LEN + 1];
> +	ssize_t ret;
> +	bool delete_mode = false;
> +
> +        if(count > (MAC_STR_LEN + 1))
> +		delete_mode = true;
> +	else if (count < MAC_STR_LEN)
> +		return count;
> +
> +	BT_DBG("count %zd mode %d", count, delete_mode);
> +
> +	memset(mac_buf, 0, MAC_STR_LEN + 1);
> +        ret = simple_write_to_buffer(mac_buf, MAC_STR_LEN, position,
> +							user_buffer, count);
> +	if (ret > 0) {

You need to get rid of this nesting. 

	if (ret < 0)
		return ret;

> +		struct ble_6lowpan_enabled *entry = NULL, *tmp;
> +		bdaddr_t bdaddr;
> +
> +		if (sscanf(mac_buf, "%hhx:%hhx:%hhx:%hhx:%hhx:%hhx",
> +				&bdaddr.b[5], &bdaddr.b[4],
> +				&bdaddr.b[3], &bdaddr.b[2],
> +				&bdaddr.b[1], &bdaddr.b[0]) != 6)
> +			return -EINVAL;
> +
> +		BT_DBG("user %pMR", &bdaddr);
> +
> +		write_lock(&user_enabled_list_lock);
> +		list_for_each_entry_safe(entry, tmp, &user_enabled, list) {
> +			if (!bacmp(&entry->addr, &bdaddr)) {
> +				struct hci_dev *hdev = fp->f_inode->i_private;
> +
> +				if (!strncmp(entry->dev_name, hdev->dev_name,
> +						HCI_MAX_NAME_LENGTH) &&
> +								delete_mode) {
> +					break;
> +				} else {
> +					ret = -EEXIST;
> +					break;
> +				}
> +			}
> +		}
> +		write_unlock(&user_enabled_list_lock);
> +
> +		if (ret > 0) {

And here as well. If you keep nesting, you cramp everything into 20 characters and it becomes unreadable.

> +			struct hci_dev *hdev = fp->f_inode->i_private;
> +
> +			if (delete_mode) {
> +				write_lock(&user_enabled_list_lock);
> +				list_del(&entry->list);
> +				kfree(entry);
> +				write_unlock(&user_enabled_list_lock);
> +			} else {
> +				entry = kzalloc(sizeof(*entry), GFP_KERNEL);
> +				if (!entry)
> +					return -ENOMEM;
> +
> +				strncpy(entry->dev_name, hdev->dev_name,
> +					HCI_MAX_NAME_LENGTH);
> +				entry->addr = bdaddr;
> +
> +				write_lock(&user_enabled_list_lock);
> +				INIT_LIST_HEAD(&entry->list);
> +				list_add(&entry->list, &user_enabled);
> +				write_unlock(&user_enabled_list_lock);
> +			}
> +		}
> +	}
> +
> +	return ret;
> +}
> +
> +static const struct file_operations ble_6lowpan_debugfs_fops = {
> +	.open		= ble_6lowpan_debugfs_open,
> +	.read		= seq_read,
> +	.write		= ble_6lowpan_writer,
> +	.llseek		= seq_lseek,
> +	.release	= single_release,
> +};
> +
> +static struct dentry *ble_6lowpan_debugfs;
> +
> +void ble_6lowpan_add_debugfs(struct hci_dev *hdev)
> +{
> +	if (hdev->debugfs) {

	if (!hdev->debugs)
		return;

> +		ble_6lowpan_debugfs = debugfs_create_file("ble6lowpan", 0644,

Use 6lowpan as name.

> +			hdev->debugfs, hdev, &ble_6lowpan_debugfs_fops);
> +		if (!ble_6lowpan_debugfs)
> +			BT_ERR("Failed to create 6LoWPAN debug file");

Don't bother with an error code here. We removed all of these. They are pointless and debugfs failures are not really failures.

> +	}
> +}
> +
> int ble_6lowpan_init(void)
> {
> 	int err;
> diff --git a/net/bluetooth/ble_6lowpan.h b/net/bluetooth/ble_6lowpan.h
> index 7975a55..047b8b7 100644
> --- a/net/bluetooth/ble_6lowpan.h
> +++ b/net/bluetooth/ble_6lowpan.h
> @@ -23,5 +23,6 @@ int ble_6lowpan_del_conn(struct l2cap_conn *conn);
> int ble_6lowpan_init(void);
> void ble_6lowpan_cleanup(void);
> bool ble_6lowpan_is_enabled(struct hci_dev *hdev, bdaddr_t *dst);
> +void ble_6lowpan_add_debugfs(struct hci_dev *hdev);
> 
> #endif /* __BLE_LOWPAN_H */
> diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c
> index 6ccc4eb..d0db818 100644
> --- a/net/bluetooth/hci_core.c
> +++ b/net/bluetooth/hci_core.c
> @@ -34,6 +34,8 @@
> #include <net/bluetooth/bluetooth.h>
> #include <net/bluetooth/hci_core.h>
> 
> +#include "ble_6lowpan.h"
> +
> static void hci_rx_work(struct work_struct *work);
> static void hci_cmd_work(struct work_struct *work);
> static void hci_tx_work(struct work_struct *work);
> @@ -1406,6 +1408,8 @@ static int __hci_init(struct hci_dev *hdev)
> 				    hdev, &conn_max_interval_fops);
> 	}
> 
> +	ble_6lowpan_add_debugfs(hdev);
> +
> 	return 0;
> }

I wonder if the list of enabled IPv6 devices should be actually part of hci_core.c. And we just have functions for it to call it. At the end of the day, we might just have a UUID in the advertising data and that will be in hci_core.c anyway.

> 
> diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c
> index fb1a49c..e3b30dd 100644
> --- a/net/bluetooth/l2cap_core.c
> +++ b/net/bluetooth/l2cap_core.c
> @@ -6542,11 +6542,6 @@ int l2cap_connect_ind(struct hci_dev *hdev, bdaddr_t *bdaddr)
> 	return exact ? lm1 : lm2;
> }
> 
> -static bool is_ble_6lowpan(void)
> -{
> -	return false;
> -}
> -
> void l2cap_connect_cfm(struct hci_conn *hcon, u8 status)
> {
> 	struct l2cap_conn *conn;
> @@ -6558,7 +6553,9 @@ void l2cap_connect_cfm(struct hci_conn *hcon, u8 status)
> 		if (conn) {
> 			l2cap_conn_ready(conn);
> 
> -			if (hcon->type == LE_LINK && is_ble_6lowpan())
> +			if (hcon->type == LE_LINK &&
> +					ble_6lowpan_is_enabled(hcon->hdev,
> +								&hcon->dst))
> 				ble_6lowpan_add_conn(conn);
> 		}

We have an l2cap_le_conn_ready function just for LE GATT. Maybe that should be used instead.

> 	} else {
> @@ -6581,7 +6578,8 @@ void l2cap_disconn_cfm(struct hci_conn *hcon, u8 reason)
> {
> 	BT_DBG("hcon %p reason %d", hcon, reason);
> 
> -	if (hcon->type == LE_LINK && is_ble_6lowpan())
> +	if (hcon->type == LE_LINK && ble_6lowpan_is_enabled(hcon->hdev,
> +							&hcon->dst))
> 		ble_6lowpan_del_conn(hcon->l2cap_data);
> 
> 	l2cap_conn_del(hcon, bt_to_errno(reason));

Regards

Marcel


^ permalink raw reply

* Re: [RFC 3/5] route: Exporting ip6_route_add() so that BLE 6LoWPAN can use it
From: Marcel Holtmann @ 2013-10-23 12:00 UTC (permalink / raw)
  To: Jukka Rissanen; +Cc: linux-bluetooth
In-Reply-To: <1382511164-1989-4-git-send-email-jukka.rissanen@linux.intel.com>

Hi Jukka,

> net/ipv6/route.c | 1 +
> 1 file changed, 1 insertion(+)
> 
> diff --git a/net/ipv6/route.c b/net/ipv6/route.c
> index c979dd9..d7c200f 100644
> --- a/net/ipv6/route.c
> +++ b/net/ipv6/route.c
> @@ -1662,6 +1662,7 @@ out:
> 		dst_free(&rt->dst);
> 	return err;
> }
> +EXPORT_SYMBOL_GPL(ip6_route_add);

check with netdev is this is something that would be accepted upstream.

For the time being, can we work around this internally for testing? I like to just build and load a new Bluetooth module for testing and not have to replace IPv6 as well.

Regards

Marcel


^ permalink raw reply

* Re: [RFC 1/5] Bluetooth: Initial skeleton code for BT LE 6LoWPAN
From: Marcel Holtmann @ 2013-10-23 11:58 UTC (permalink / raw)
  To: Jukka Rissanen; +Cc: linux-bluetooth
In-Reply-To: <1382511164-1989-2-git-send-email-jukka.rissanen@linux.intel.com>

Hi Jukka,

> include/net/bluetooth/l2cap.h |   1 +
> net/bluetooth/Makefile        |   2 +-
> net/bluetooth/ble_6lowpan.c   | 404 ++++++++++++++++++++++++++++++++++++++++++
> net/bluetooth/ble_6lowpan.h   |  27 +++
> net/bluetooth/l2cap_core.c    |  22 ++-
> 5 files changed, 454 insertions(+), 2 deletions(-)
> create mode 100644 net/bluetooth/ble_6lowpan.c
> create mode 100644 net/bluetooth/ble_6lowpan.h
> 
> diff --git a/include/net/bluetooth/l2cap.h b/include/net/bluetooth/l2cap.h
> index 3d922b9..645cd30 100644
> --- a/include/net/bluetooth/l2cap.h
> +++ b/include/net/bluetooth/l2cap.h
> @@ -133,6 +133,7 @@ struct l2cap_conninfo {
> #define L2CAP_FC_L2CAP		0x02
> #define L2CAP_FC_CONNLESS	0x04
> #define L2CAP_FC_A2MP		0x08
> +#define L2CAP_FC_6LOWPAN        0x3e
> 
> /* L2CAP Control Field bit masks */
> #define L2CAP_CTRL_SAR			0xC000
> diff --git a/net/bluetooth/Makefile b/net/bluetooth/Makefile
> index 6a791e7..a70625b 100644
> --- a/net/bluetooth/Makefile
> +++ b/net/bluetooth/Makefile
> @@ -10,6 +10,6 @@ obj-$(CONFIG_BT_HIDP)	+= hidp/
> 
> bluetooth-y := af_bluetooth.o hci_core.o hci_conn.o hci_event.o mgmt.o \
> 	hci_sock.o hci_sysfs.o l2cap_core.o l2cap_sock.o smp.o sco.o lib.o \
> -	a2mp.o amp.o
> +	a2mp.o amp.o ble_6lowpan.o

we tried to not use ble prefix. I would just name it 6lowpan.c here.

> subdir-ccflags-y += -D__CHECK_ENDIAN__
> diff --git a/net/bluetooth/ble_6lowpan.c b/net/bluetooth/ble_6lowpan.c
> new file mode 100644
> index 0000000..0fd3302
> --- /dev/null
> +++ b/net/bluetooth/ble_6lowpan.c
> @@ -0,0 +1,404 @@
> +/*
> +   Copyright (c) 2013 Intel Corp.
> +
> +   This program is free software; you can redistribute it and/or modify
> +   it under the terms of the GNU General Public License version 2 and
> +   only version 2 as published by the Free Software Foundation.
> +
> +   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.
> +*/
> +
> +#include <linux/version.h>
> +#include <linux/bitops.h>
> +#include <linux/if_arp.h>
> +#include <linux/netdevice.h>
> +#include <linux/etherdevice.h>
> +
> +#include <net/ipv6.h>
> +#include <net/ip6_route.h>
> +#include <net/addrconf.h>
> +
> +#include <net/af_ieee802154.h>
> +
> +#include <net/bluetooth/bluetooth.h>
> +#include <net/bluetooth/hci_core.h>
> +#include <net/bluetooth/l2cap.h>
> +
> +#include "../ieee802154/6lowpan.h" /* for the compression defines */
> +
> +#define IFACE_NAME_TEMPLATE "ble6lowpan%d"

Wonder what would be a good template name here. Maybe just calling them bt%d is good enough. At the end of the day nobody cares that this is 6loWPAN. We just want IPv6 over Bluetooth.

> +
> +/*
> + * The devices list contains those devices that we are acting
> + * as a proxy. The BT LE 6LoWPAN device is a virtual device that
> + * connects to the Bluetooth LE device. The real connection to
> + * BT LE device is done via l2cap layer. There exists one
> + * virtual device / one BT LE 6LoWPAN device. The list contains
> + * struct ble_6lowpan_dev_record elements.
> + */
> +static LIST_HEAD(ble_6lowpan_devices);
> +DEFINE_RWLOCK(net_dev_list_lock);
> +
> +struct ble_6lowpan_dev_record {
> +	struct net_device *dev;
> +	struct delayed_work delete_timer;
> +	struct list_head list;
> +};
> +
> +struct ble_6lowpan_dev_info {
> +	struct net_device *net;
> +	struct l2cap_conn *conn;
> +	uint16_t ifindex;
> +	bdaddr_t myaddr;
> +
> +	/* peer addresses in various formats */
> +	bdaddr_t addr;
> +	unsigned char ieee802154_addr[IEEE802154_ADDR_LEN];
> +	struct in6_addr peer;
> +};

Instead of ble_ use bt_ as prefix.

> +
> +struct lowpan_fragment {
> +	struct sk_buff		*skb;		/* skb to be assembled */
> +	u16			length;		/* length to be assemled */
> +	u32			bytes_rcv;	/* bytes received */
> +	u16			tag;		/* current fragment tag */
> +	struct timer_list	timer;		/* assembling timer */
> +	struct list_head	list;		/* fragments list */
> +};
> +
> +#define DELETE_TIMEOUT msecs_to_jiffies(1)
> +
> +/* TTL uncompression values */
> +static const u8 lowpan_ttl_values[] = {0, 1, 64, 255};
> +
> +static inline struct
> +ble_6lowpan_dev_info *ble_6lowpan_dev_info(const struct net_device *dev)
> +{
> +	return netdev_priv(dev);
> +}
> +
> +/* print data in line */
> +static inline void ble_6lowpan_raw_dump_inline(const char *caller, char *msg,
> +				   unsigned char *buf, int len)
> +{
> +#ifdef DEBUG
> +	if (msg)
> +		pr_debug("%s():%s: ", caller, msg);
> +	print_hex_dump(KERN_DEBUG, "", DUMP_PREFIX_NONE,
> +		       16, 1, buf, len, false);
> +#endif /* DEBUG */
> +}
> +
> +/*
> + * print data in a table format:
> + *
> + * addr: xx xx xx xx xx xx
> + * addr: xx xx xx xx xx xx
> + * ...
> + */
> +static inline void ble_6lowpan_raw_dump_table(const char *caller, char *msg,
> +				   unsigned char *buf, int len)
> +{
> +#ifdef DEBUG
> +	if (msg)
> +		pr_debug("%s():%s:\n", caller, msg);
> +	print_hex_dump(KERN_DEBUG, "\t", DUMP_PREFIX_OFFSET,
> +		       16, 1, buf, len, false);
> +#endif /* DEBUG */
> +}
> +
> +static int ble_6lowpan_recv_pkt(struct sk_buff *skb, struct net_device *dev)
> +{
> +	kfree_skb(skb);
> +	return NET_RX_DROP;
> +}
> +
> +/* Packet from BT LE device */
> +int ble_6lowpan_recv(struct l2cap_conn *conn, struct sk_buff *skb)
> +{
> +	struct ble_6lowpan_dev_record *entry, *tmp;
> +	struct net_device *dev = NULL;
> +	int status = -ENOENT;
> +
> +	write_lock(&net_dev_list_lock);
> +
> +	list_for_each_entry_safe(entry, tmp, &ble_6lowpan_devices, list) {
> +		if (ble_6lowpan_dev_info(entry->dev)->conn == conn) {
> +			dev = ble_6lowpan_dev_info(entry->dev)->net;
> +			break;
> +		}
> +	}
> +
> +	write_unlock(&net_dev_list_lock);
> +
> +	if (dev) {
> +		status = ble_6lowpan_recv_pkt(skb, dev);
> +		BT_DBG("recv pkt %d", status);
> +	}
> +
> +	return status;
> +}
> +
> +static void ble_6lowpan_do_send(struct l2cap_conn *conn, struct sk_buff *skb)
> +{
> +	BT_DBG("conn %p, skb %p len %d priority %u", conn, skb, skb->len,
> +	       skb->priority);
> +
> +	return;
> +}
> +
> +static int lowpan_conn_send(struct l2cap_conn *conn,
> +			void *msg, size_t len, u32 priority,
> +			struct net_device *dev)
> +{
> +	struct sk_buff *skb = {0};
> +
> +	ble_6lowpan_do_send(conn, skb);
> +	return 0;
> +}
> +
> +/* Packet to BT LE device */
> +static int ble_6lowpan_send(struct l2cap_conn *conn, const void *saddr,
> +			const void *daddr, struct sk_buff *skb,
> +			struct net_device *dev)
> +{
> +	ble_6lowpan_raw_dump_table(__func__,
> +				"raw skb data dump before fragmentation",
> +				skb->data, skb->len);
> +
> +	return lowpan_conn_send(conn, skb->data, skb->len, 0, dev);
> +}
> +
> +static netdev_tx_t ble_6lowpan_xmit(struct sk_buff *skb, struct net_device *dev)
> +{
> +	int err = -1;
> +
> +	pr_debug("ble 6lowpan packet xmit\n");
> +
> +	if (ble_6lowpan_dev_info(dev)->conn)
> +		err = ble_6lowpan_send(ble_6lowpan_dev_info(dev)->conn,
> +				dev->dev_addr,
> +				&ble_6lowpan_dev_info(dev)->ieee802154_addr,
> +				skb,
> +				dev);
> +	else
> +		BT_DBG("ERROR: no BT LE 6LoWPAN device found");
> +
> +	dev_kfree_skb(skb);
> +
> +	if (err)
> +		BT_DBG("ERROR: xmit failed (%d)", err);
> +
> +	return (err < 0) ? NET_XMIT_DROP : err;
> +}
> +
> +static const struct net_device_ops ble_6lowpan_netdev_ops = {
> +	.ndo_start_xmit		= ble_6lowpan_xmit,
> +};
> +
> +static void ble_6lowpan_setup(struct net_device *dev)
> +{
> +	dev->addr_len		= IEEE802154_ADDR_LEN;
> +	dev->type		= ARPHRD_IEEE802154;

Seems like we need to ask for a new ARP header type included in include/linux/uapi/if_arp.h.

I wonder if this should be a generic one for 6loWPAN or a Bluetooth specific one. Maybe it is a good idea to prepare a patch for netdev mailing list and see what these people thing.

> +
> +	dev->hard_header_len	= 0;
> +	dev->needed_tailroom	= 0;
> +	dev->mtu		= IPV6_MIN_MTU;
> +	dev->tx_queue_len	= 0;
> +	dev->flags		= IFF_RUNNING | IFF_POINTOPOINT;
> +	dev->watchdog_timeo	= 0;
> +
> +	dev->netdev_ops		= &ble_6lowpan_netdev_ops;
> +	dev->destructor		= free_netdev;
> +}
> +
> +static struct device_type ble_type = {
> +	.name	= "ble6lowpan",
> +};
> +
> +static void set_addr(u8 *eui, u8 *addr)
> +{
> +	/* addr is the BT address in little-endian format */
> +	eui[0] = addr[5];
> +	eui[1] = addr[4];
> +	eui[2] = addr[3];
> +	eui[3] = 0xFF;
> +	eui[4] = 0xFE;
> +	eui[5] = addr[2];
> +	eui[6] = addr[1];
> +	eui[7] = addr[0];
> +
> +	eui[0] ^= 2;
> +}
> +
> +static void set_dev_addr(struct net_device *net, bdaddr_t *addr)
> +{
> +	net->addr_assign_type = NET_ADDR_PERM;
> +	set_addr(net->dev_addr, addr->b);
> +	net->dev_addr[0] ^= 2;
> +}

So now it gets a bit tricky. LE has public and random addresses and we do now support controller having both. We also support controllers that have no public address. So question is what do we do when a controller only has a random address.

> +
> +static void ifup(struct net_device *net)
> +{
> +	int status;
> +
> +	rtnl_lock();
> +	if ((status = dev_open(net)) < 0)
> +		BT_INFO("iface %s cannot be opened (%d)", net->name,
> +			status);
> +	rtnl_unlock();
> +}
> +
> +/*
> + * This gets called when BT LE 6LoWPan device is connected. We then
> + * create network device that acts as a proxy between BT LE device
> + * and kernel network stack.
> + */
> +int ble_6lowpan_add_conn(struct l2cap_conn *conn)
> +{
> +	struct net_device *net;
> +	struct ble_6lowpan_dev_info *dev;
> +	struct ble_6lowpan_dev_record *entry;
> +	int status;
> +
> +	net = alloc_netdev(sizeof(struct ble_6lowpan_dev_info),
> +			IFACE_NAME_TEMPLATE, ble_6lowpan_setup);
> +	if (!net)
> +		return -ENOMEM;
> +
> +	dev = netdev_priv(net);
> +	dev->net = net;
> +
> +	memcpy(&dev->myaddr, &conn->hcon->hdev->bdaddr, sizeof(bdaddr_t));
> +	memcpy(&dev->addr, &conn->hcon->dst, sizeof(bdaddr_t));

You need to use hcon->src and hcon->src_type for the source address. hdev->bdaddr is always the public address, but we not always use that. I fixed this lately to make sure that hcon->src always gives you the address that was really used when establishing the connection. There is also a hcon->dst_type for the remote address since that can be easily a random address as well.

Check own_address_type in debugfs if you want to play with using a random address. You need to first use the mgmt command set static address to program one before powering on the controller.

> +
> +	set_dev_addr(net, &dev->myaddr);
> +
> +	dev->conn = conn;
> +
> +	net->netdev_ops = &ble_6lowpan_netdev_ops;
> +	SET_NETDEV_DEV(net, &conn->hcon->dev);
> +	SET_NETDEV_DEVTYPE(net, &ble_type);

I am not sure this should be some other devtype. It should clearly not be empty since that would be confusing ConnMan. However I get the feeling this should stay as bluetooth devtype like we do for BNEP. We can use the ARP header type to see if this is an Ethernet emulation or native IP.

This reminds me, we tried to introduce a raw IP ARP header type for WiMAX. Not sure if that ever went upstream. In the end we decided for Ethernet emulation for WiMAX. For IPv6 over LE, the Ethernet emulation is clearly not an option.

> +
> +	status = register_netdev(net);
> +	if (status < 0) {
> +		BT_INFO("register_netdev failed %d", status);
> +		free_netdev(net);
> +		return status;
> +	} else {

I would just not bother with an else part here. You already left the function with return. So you can just continue.

> +		struct inet6_dev *idev;
> +
> +		BT_DBG("ifindex %d peer bdaddr %pMR my addr %pMR",
> +			net->ifindex, &dev->addr, &dev->myaddr);
> +		dev->ifindex = net->ifindex;
> +		set_bit(__LINK_STATE_PRESENT, &net->state);
> +
> +		idev = in6_dev_get(net);
> +		if (idev) {
> +			idev->cnf.autoconf = 1;
> +			idev->cnf.forwarding = 1;
> +			idev->cnf.accept_ra = 2;
> +
> +			in6_dev_put(idev);
> +		}
> +
> +		entry = kzalloc(sizeof(struct ble_6lowpan_dev_record),
> +				GFP_KERNEL);
> +		if (!entry)
> +			return -ENOMEM;
> +
> +		entry->dev = net;
> +
> +		write_lock(&net_dev_list_lock);
> +		INIT_LIST_HEAD(&entry->list);
> +		list_add(&entry->list, &ble_6lowpan_devices);
> +		write_unlock(&net_dev_list_lock);
> +
> +		ifup(net);
> +	}
> +
> +	return 0;
> +}
> +
> +static void delete_timeout(struct work_struct *work)
> +{
> +	struct ble_6lowpan_dev_record *entry = container_of(work,
> +						struct ble_6lowpan_dev_record,
> +						delete_timer.work);

You need to find a shorter struct name ;)

> +
> +	unregister_netdev(entry->dev);
> +	kfree(entry);
> +}
> +
> +int ble_6lowpan_del_conn(struct l2cap_conn *conn)
> +{
> +	struct ble_6lowpan_dev_record *entry, *tmp;
> +	int status = -ENOENT;
> +
> +	write_lock(&net_dev_list_lock);
> +
> +	list_for_each_entry_safe(entry, tmp, &ble_6lowpan_devices, list) {
> +		if (ble_6lowpan_dev_info(entry->dev)->conn == conn) {
> +			list_del(&entry->list);
> +			status = 0;
> +			break;
> +		}
> +	}
> +
> +	write_unlock(&net_dev_list_lock);
> +
> +	if (!status) {
> +		INIT_DELAYED_WORK(&entry->delete_timer, delete_timeout);
> +		schedule_delayed_work(&entry->delete_timer, DELETE_TIMEOUT);
> +	}
> +
> +	return status;
> +}
> +
> +static int ble_6lowpan_device_event(struct notifier_block *unused,
> +				unsigned long event, void *ptr)
> +{
> +	struct net_device *dev = netdev_notifier_info_to_dev(ptr);
> +	struct ble_6lowpan_dev_record *entry, *tmp;
> +
> +	if (dev->type == ARPHRD_IEEE802154) {

Just check for the ARP header type we are looking for. If not, then just return. No need for the extra nesting here.

> +		switch (event) {
> +		case NETDEV_UNREGISTER:
> +			write_lock(&net_dev_list_lock);
> +			list_for_each_entry_safe(entry, tmp,
> +						&ble_6lowpan_devices,
> +						list) {
> +				if (entry->dev == dev) {
> +					list_del(&entry->list);
> +					kfree(entry);
> +					break;
> +				}
> +			}
> +			write_unlock(&net_dev_list_lock);
> +			break;
> +		}
> +	}
> +
> +	return NOTIFY_DONE;
> +}
> +
> +static struct notifier_block ble_6lowpan_dev_notifier = {
> +	.notifier_call = ble_6lowpan_device_event,
> +};
> +
> +int ble_6lowpan_init(void)
> +{
> +	int err;
> +
> +	err = register_netdevice_notifier(&ble_6lowpan_dev_notifier);
> +
> +	return err;
> +}

return register_netdevice_…

> +
> +void ble_6lowpan_cleanup(void)
> +{
> +	unregister_netdevice_notifier(&ble_6lowpan_dev_notifier);
> +}
> diff --git a/net/bluetooth/ble_6lowpan.h b/net/bluetooth/ble_6lowpan.h
> new file mode 100644
> index 0000000..7975a55
> --- /dev/null
> +++ b/net/bluetooth/ble_6lowpan.h
> @@ -0,0 +1,27 @@
> +/*
> +   Copyright (c) 2013 Intel Corp.
> +
> +   This program is free software; you can redistribute it and/or modify
> +   it under the terms of the GNU General Public License version 2 and
> +   only version 2 as published by the Free Software Foundation.
> +
> +   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.
> +*/
> +
> +#ifndef __BLE_LOWPAN_H
> +#define __BLE_LOWPAN_H
> +
> +#include <linux/skbuff.h>
> +#include <net/bluetooth/l2cap.h>
> +
> +int ble_6lowpan_recv(struct l2cap_conn *conn, struct sk_buff *skb);
> +int ble_6lowpan_add_conn(struct l2cap_conn *conn);
> +int ble_6lowpan_del_conn(struct l2cap_conn *conn);
> +int ble_6lowpan_init(void);
> +void ble_6lowpan_cleanup(void);
> +bool ble_6lowpan_is_enabled(struct hci_dev *hdev, bdaddr_t *dst);
> +
> +#endif /* __BLE_LOWPAN_H */
> diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c
> index d52bd0d..fb1a49c 100644
> --- a/net/bluetooth/l2cap_core.c
> +++ b/net/bluetooth/l2cap_core.c
> @@ -40,6 +40,7 @@
> #include "smp.h"
> #include "a2mp.h"
> #include "amp.h"
> +#include "ble_6lowpan.h"
> 
> bool disable_ertm;
> 
> @@ -6500,6 +6501,10 @@ static void l2cap_recv_frame(struct l2cap_conn *conn, struct sk_buff *skb)
> 			l2cap_conn_del(conn->hcon, EACCES);
> 		break;
> 
> +	case L2CAP_FC_6LOWPAN:
> +		ble_6lowpan_recv(conn, skb);
> +		break;
> +
> 	default:
> 		l2cap_data_channel(conn, cid, skb);
> 		break;
> @@ -6537,6 +6542,11 @@ int l2cap_connect_ind(struct hci_dev *hdev, bdaddr_t *bdaddr)
> 	return exact ? lm1 : lm2;
> }
> 
> +static bool is_ble_6lowpan(void)
> +{
> +	return false;
> +}
> +
> void l2cap_connect_cfm(struct hci_conn *hcon, u8 status)
> {
> 	struct l2cap_conn *conn;
> @@ -6545,8 +6555,12 @@ void l2cap_connect_cfm(struct hci_conn *hcon, u8 status)
> 
> 	if (!status) {
> 		conn = l2cap_conn_add(hcon);
> -		if (conn)
> +		if (conn) {
> 			l2cap_conn_ready(conn);
> +
> +			if (hcon->type == LE_LINK && is_ble_6lowpan())
> +				ble_6lowpan_add_conn(conn);
> +		}
> 	} else {
> 		l2cap_conn_del(hcon, bt_to_errno(status));
> 	}
> @@ -6567,6 +6581,9 @@ void l2cap_disconn_cfm(struct hci_conn *hcon, u8 reason)
> {
> 	BT_DBG("hcon %p reason %d", hcon, reason);
> 
> +	if (hcon->type == LE_LINK && is_ble_6lowpan())
> +		ble_6lowpan_del_conn(hcon->l2cap_data);
> +
> 	l2cap_conn_del(hcon, bt_to_errno(reason));
> }
> 
> @@ -6849,11 +6866,14 @@ int __init l2cap_init(void)
> 	l2cap_debugfs = debugfs_create_file("l2cap", 0444, bt_debugfs,
> 					    NULL, &l2cap_debugfs_fops);
> 
> +	ble_6lowpan_init();
> +
> 	return 0;
> }
> 
> void l2cap_exit(void)
> {
> +	ble_6lowpan_cleanup();
> 	debugfs_remove(l2cap_debugfs);
> 	l2cap_cleanup_sockets();
> }

Regards

Marcel


^ permalink raw reply

* Re: [PATCH 1/6] android: Add initial code for services register
From: Johan Hedberg @ 2013-10-23 11:29 UTC (permalink / raw)
  To: Szymon Janc; +Cc: linux-bluetooth
In-Reply-To: <1382526281-19711-1-git-send-email-szymon.janc@tieto.com>

Hi Szymon,

On Wed, Oct 23, 2013, Szymon Janc wrote:
> This will be used to enable services on respective HAL init calls.
> ---
>  android/main.c | 14 ++++++++++----
>  1 file changed, 10 insertions(+), 4 deletions(-)

All six patches have been applied. Thanks.

Johan

^ permalink raw reply

* [PATCH 6/6] android: Add support for  registering and unregistering hid service
From: Szymon Janc @ 2013-10-23 11:04 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Szymon Janc
In-Reply-To: <1382526281-19711-1-git-send-email-szymon.janc@tieto.com>

---
 android/hid.c  | 21 +++++++++++++++++++++
 android/hid.h  |  3 +++
 android/main.c |  8 ++++++++
 3 files changed, 32 insertions(+)

diff --git a/android/hid.c b/android/hid.c
index 31de20d..2c74352 100644
--- a/android/hid.c
+++ b/android/hid.c
@@ -22,14 +22,18 @@
  */
 
 #include <stdint.h>
+#include <stdbool.h>
 
 #include <glib.h>
 
+#include "lib/bluetooth.h"
 #include "log.h"
 #include "hal-msg.h"
 #include "ipc.h"
 #include "hid.h"
 
+static GIOChannel *notification_io = NULL;
+
 void bt_hid_handle_cmd(GIOChannel *io, uint8_t opcode, void *buf, uint16_t len)
 {
 	uint8_t status = HAL_ERROR_FAILED;
@@ -46,3 +50,20 @@ void bt_hid_handle_cmd(GIOChannel *io, uint8_t opcode, void *buf, uint16_t len)
 
 	ipc_send_error(io, HAL_SERVICE_ID_HIDHOST, status);
 }
+
+bool bt_hid_register(GIOChannel *io, const bdaddr_t *addr)
+{
+	DBG("");
+
+	notification_io = g_io_channel_ref(io);
+
+	return true;
+}
+
+void bt_hid_unregister(void)
+{
+	DBG("");
+
+	g_io_channel_unref(notification_io);
+	notification_io = NULL;
+}
diff --git a/android/hid.h b/android/hid.h
index 1247488..674b35a 100644
--- a/android/hid.h
+++ b/android/hid.h
@@ -22,3 +22,6 @@
  */
 
 void bt_hid_handle_cmd(GIOChannel *io, uint8_t opcode, void *buf, uint16_t len);
+
+bool bt_hid_register(GIOChannel *io, const bdaddr_t *addr);
+void bt_hid_unregister(void);
diff --git a/android/main.c b/android/main.c
index e8b584d..edcca73 100644
--- a/android/main.c
+++ b/android/main.c
@@ -88,6 +88,11 @@ static void service_register(void *buf, uint16_t len)
 			goto error;
 
 		break;
+	case HAL_SERVICE_ID_HIDHOST:
+		if (!bt_hid_register(hal_notif_io, bt_adapter_get_address()))
+			goto error;
+
+		break;
 	default:
 		DBG("service %u not supported", m->service_id);
 		goto error;
@@ -118,6 +123,9 @@ static void service_unregister(void *buf, uint16_t len)
 	case HAL_SERVICE_ID_SOCK:
 		bt_socket_unregister();
 		break;
+	case HAL_SERVICE_ID_HIDHOST:
+		bt_hid_unregister();
+		break;
 	default:
 		/* This would indicate bug in HAL, as unregister should not be
 		 * called in init failed */
-- 
1.8.4


^ permalink raw reply related

* [PATCH 5/6] android: Add initial code for socket service
From: Szymon Janc @ 2013-10-23 11:04 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Szymon Janc
In-Reply-To: <1382526281-19711-1-git-send-email-szymon.janc@tieto.com>

Only handle register/unregister for now.
---
 Makefile.android   |  3 ++-
 android/Android.mk |  1 +
 android/main.c     | 10 ++++++++++
 android/socket.c   | 41 +++++++++++++++++++++++++++++++++++++++++
 android/socket.h   | 25 +++++++++++++++++++++++++
 5 files changed, 79 insertions(+), 1 deletion(-)
 create mode 100644 android/socket.c
 create mode 100644 android/socket.h

diff --git a/Makefile.android b/Makefile.android
index 0a05e9e..a398537 100644
--- a/Makefile.android
+++ b/Makefile.android
@@ -10,7 +10,8 @@ android_bluetoothd_SOURCES =	android/main.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/ipc.h android/ipc.c \
+				android/socket.h android/socket.c
 
 android_bluetoothd_LDADD = lib/libbluetooth-internal.la @GLIB_LIBS@
 
diff --git a/android/Android.mk b/android/Android.mk
index 9f91576..dd5d6f7 100644
--- a/android/Android.mk
+++ b/android/Android.mk
@@ -17,6 +17,7 @@ LOCAL_SRC_FILES := \
 	log.c \
 	adapter.c \
 	hid.c \
+	socket.c \
 	ipc.c ipc.h \
 	../src/shared/mgmt.c \
 	../src/shared/util.c \
diff --git a/android/main.c b/android/main.c
index b18b8d4..e8b584d 100644
--- a/android/main.c
+++ b/android/main.c
@@ -49,6 +49,7 @@
 #include "src/shared/mgmt.h"
 
 #include "adapter.h"
+#include "socket.h"
 #include "hid.h"
 #include "hal-msg.h"
 #include "ipc.h"
@@ -81,6 +82,12 @@ static void service_register(void *buf, uint16_t len)
 			goto error;
 
 		break;
+	case HAL_SERVICE_ID_SOCK:
+		if (!bt_socket_register(hal_notif_io,
+						bt_adapter_get_address()))
+			goto error;
+
+		break;
 	default:
 		DBG("service %u not supported", m->service_id);
 		goto error;
@@ -108,6 +115,9 @@ static void service_unregister(void *buf, uint16_t len)
 	case HAL_SERVICE_ID_BLUETOOTH:
 		bt_adapter_unregister();
 		break;
+	case HAL_SERVICE_ID_SOCK:
+		bt_socket_unregister();
+		break;
 	default:
 		/* This would indicate bug in HAL, as unregister should not be
 		 * called in init failed */
diff --git a/android/socket.c b/android/socket.c
new file mode 100644
index 0000000..22d2acb
--- /dev/null
+++ b/android/socket.c
@@ -0,0 +1,41 @@
+/*
+ *
+ *  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
+ *
+ */
+
+#include <glib.h>
+#include <stdbool.h>
+
+#include "lib/bluetooth.h"
+#include "log.h"
+#include "socket.h"
+
+bool bt_socket_register(GIOChannel *io, const bdaddr_t *addr)
+{
+	DBG("");
+
+	return true;
+}
+
+void bt_socket_unregister(void)
+{
+	DBG("");
+}
diff --git a/android/socket.h b/android/socket.h
new file mode 100644
index 0000000..b13e84c
--- /dev/null
+++ b/android/socket.h
@@ -0,0 +1,25 @@
+/*
+ *
+ *  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
+ *
+ */
+
+bool bt_socket_register(GIOChannel *io, const bdaddr_t *addr);
+void bt_socket_unregister(void);
-- 
1.8.4


^ permalink raw reply related

* [PATCH 4/6] android: Add bt_adapter_get_address function
From: Szymon Janc @ 2013-10-23 11:04 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Szymon Janc
In-Reply-To: <1382526281-19711-1-git-send-email-szymon.janc@tieto.com>

It will be used to obtain adapter address.
---
 android/adapter.c | 5 +++++
 android/adapter.h | 2 ++
 2 files changed, 7 insertions(+)

diff --git a/android/adapter.c b/android/adapter.c
index 059a5be..f9843d1 100644
--- a/android/adapter.c
+++ b/android/adapter.c
@@ -364,6 +364,11 @@ void bt_adapter_handle_cmd(GIOChannel *io, uint8_t opcode, void *buf,
 	ipc_send_error(io, HAL_SERVICE_ID_BLUETOOTH, status);
 }
 
+const bdaddr_t *bt_adapter_get_address(void)
+{
+	return &default_adapter->bdaddr;
+}
+
 bool bt_adapter_register(GIOChannel *io)
 {
 	DBG("");
diff --git a/android/adapter.h b/android/adapter.h
index 194950b..b8d0a58 100644
--- a/android/adapter.h
+++ b/android/adapter.h
@@ -38,5 +38,7 @@ bool bt_adapter_init(uint16_t index, struct mgmt *mgmt_if,
 void bt_adapter_handle_cmd(GIOChannel *io, uint8_t opcode, void *buf,
 								uint16_t len);
 
+const bdaddr_t *bt_adapter_get_address(void);
+
 bool bt_adapter_register(GIOChannel *io);
 void bt_adapter_unregister(void);
-- 
1.8.4


^ permalink raw reply related

* [PATCH 3/6] android: Add support for registering "bluetooth" service
From: Szymon Janc @ 2013-10-23 11:04 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Szymon Janc
In-Reply-To: <1382526281-19711-1-git-send-email-szymon.janc@tieto.com>

---
 android/adapter.c | 19 +++++++++++++++++++
 android/adapter.h |  3 +++
 android/main.c    |  8 ++++++++
 3 files changed, 30 insertions(+)

diff --git a/android/adapter.c b/android/adapter.c
index de3660d..059a5be 100644
--- a/android/adapter.c
+++ b/android/adapter.c
@@ -33,6 +33,8 @@
 #include "ipc.h"
 #include "adapter.h"
 
+static GIOChannel *notification_io = NULL;
+
 struct bt_adapter {
 	uint16_t index;
 	struct mgmt *mgmt;
@@ -361,3 +363,20 @@ void bt_adapter_handle_cmd(GIOChannel *io, uint8_t opcode, void *buf,
 
 	ipc_send_error(io, HAL_SERVICE_ID_BLUETOOTH, status);
 }
+
+bool bt_adapter_register(GIOChannel *io)
+{
+	DBG("");
+
+	notification_io = g_io_channel_ref(io);
+
+	return true;
+}
+
+void bt_adapter_unregister(void)
+{
+	DBG("");
+
+	g_io_channel_unref(notification_io);
+	notification_io = NULL;
+}
diff --git a/android/adapter.h b/android/adapter.h
index bfd4932..194950b 100644
--- a/android/adapter.h
+++ b/android/adapter.h
@@ -37,3 +37,6 @@ bool bt_adapter_init(uint16_t index, struct mgmt *mgmt_if,
 
 void bt_adapter_handle_cmd(GIOChannel *io, uint8_t opcode, void *buf,
 								uint16_t len);
+
+bool bt_adapter_register(GIOChannel *io);
+void bt_adapter_unregister(void);
diff --git a/android/main.c b/android/main.c
index 73ff3ee..b18b8d4 100644
--- a/android/main.c
+++ b/android/main.c
@@ -76,6 +76,11 @@ static void service_register(void *buf, uint16_t len)
 		goto error;
 
 	switch (m->service_id) {
+	case HAL_SERVICE_ID_BLUETOOTH:
+		if (!bt_adapter_register(hal_notif_io))
+			goto error;
+
+		break;
 	default:
 		DBG("service %u not supported", m->service_id);
 		goto error;
@@ -100,6 +105,9 @@ static void service_unregister(void *buf, uint16_t len)
 		goto error;
 
 	switch (m->service_id) {
+	case HAL_SERVICE_ID_BLUETOOTH:
+		bt_adapter_unregister();
+		break;
 	default:
 		/* This would indicate bug in HAL, as unregister should not be
 		 * called in init failed */
-- 
1.8.4


^ permalink raw reply related

* [PATCH 2/6] android: Add initial code for services unregister
From: Szymon Janc @ 2013-10-23 11:04 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Szymon Janc
In-Reply-To: <1382526281-19711-1-git-send-email-szymon.janc@tieto.com>

This will be used to disable services on respective HAL cleanup calls.
---
 android/main.c | 16 ++++++++++++----
 1 file changed, 12 insertions(+), 4 deletions(-)

diff --git a/android/main.c b/android/main.c
index af7ebf3..73ff3ee 100644
--- a/android/main.c
+++ b/android/main.c
@@ -96,10 +96,15 @@ static void service_unregister(void *buf, uint16_t len)
 {
 	struct hal_msg_cmd_unregister_module *m = buf;
 
-	if (m->service_id > HAL_SERVICE_ID_MAX || !services[m->service_id]) {
-		ipc_send_error(hal_cmd_io, HAL_SERVICE_ID_CORE,
-							HAL_ERROR_FAILED);
-		return;
+	if (m->service_id > HAL_SERVICE_ID_MAX || !services[m->service_id])
+		goto error;
+
+	switch (m->service_id) {
+	default:
+		/* This would indicate bug in HAL, as unregister should not be
+		 * called in init failed */
+		DBG("service %u not supported", m->service_id);
+		goto error;
 	}
 
 	services[m->service_id] = false;
@@ -108,6 +113,9 @@ static void service_unregister(void *buf, uint16_t len)
 								0, NULL, -1);
 
 	info("Service ID=%u unregistered", m->service_id);
+	return;
+error:
+	ipc_send_error(hal_cmd_io, HAL_SERVICE_ID_CORE, HAL_ERROR_FAILED);
 }
 
 static void handle_service_core(uint8_t opcode, void *buf, uint16_t len)
-- 
1.8.4


^ permalink raw reply related

* [PATCH 1/6] android: Add initial code for services register
From: Szymon Janc @ 2013-10-23 11:04 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Szymon Janc

This will be used to enable services on respective HAL init calls.
---
 android/main.c | 14 ++++++++++----
 1 file changed, 10 insertions(+), 4 deletions(-)

diff --git a/android/main.c b/android/main.c
index e13e5b0..af7ebf3 100644
--- a/android/main.c
+++ b/android/main.c
@@ -72,10 +72,13 @@ static void service_register(void *buf, uint16_t len)
 {
 	struct hal_msg_cmd_register_module *m = buf;
 
-	if (m->service_id > HAL_SERVICE_ID_MAX || services[m->service_id]) {
-		ipc_send_error(hal_cmd_io, HAL_SERVICE_ID_CORE,
-							HAL_ERROR_FAILED);
-		return;
+	if (m->service_id > HAL_SERVICE_ID_MAX || services[m->service_id])
+		goto error;
+
+	switch (m->service_id) {
+	default:
+		DBG("service %u not supported", m->service_id);
+		goto error;
 	}
 
 	services[m->service_id] = true;
@@ -84,6 +87,9 @@ static void service_register(void *buf, uint16_t len)
 								NULL, -1);
 
 	info("Service ID=%u registered", m->service_id);
+	return;
+error:
+	ipc_send_error(hal_cmd_io, HAL_SERVICE_ID_CORE, HAL_ERROR_FAILED);
 }
 
 static void service_unregister(void *buf, uint16_t len)
-- 
1.8.4


^ permalink raw reply related

* Re: [PATCH] android: Check that service is started
From: Johan Hedberg @ 2013-10-23 11:03 UTC (permalink / raw)
  To: Andrei Emeltchenko; +Cc: linux-bluetooth
In-Reply-To: <1382523998-30722-1-git-send-email-Andrei.Emeltchenko.news@gmail.com>

Hi Andrei,

On Wed, Oct 23, 2013, Andrei Emeltchenko wrote:
> Add check that we are able to start Bluetooth service in
> Android. If service is not started we should not try to connect to it.
> ---
>  android/hal-ipc.c | 6 +++++-
>  1 file changed, 5 insertions(+), 1 deletion(-)

Applied. Thanks.

Johan

^ permalink raw reply

* [PATCH] android: Check that service is started
From: Andrei Emeltchenko @ 2013-10-23 10:26 UTC (permalink / raw)
  To: linux-bluetooth

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

Add check that we are able to start Bluetooth service in
Android. If service is not started we should not try to connect to it.
---
 android/hal-ipc.c | 6 +++++-
 1 file changed, 5 insertions(+), 1 deletion(-)

diff --git a/android/hal-ipc.c b/android/hal-ipc.c
index 2d58038..a7948a6 100644
--- a/android/hal-ipc.c
+++ b/android/hal-ipc.c
@@ -204,7 +204,11 @@ bool hal_ipc_init(void)
 	}
 
 	/* Start Android Bluetooth daemon service */
-	property_set("ctl.start", SERVICE_NAME);
+	if (property_set("ctl.start", SERVICE_NAME) < 0) {
+		error("Failed to start service %s", SERVICE_NAME);
+		close(sk);
+		return false;
+	}
 
 	cmd_sk = accept_connection(sk);
 	if (cmd_sk < 0) {
-- 
1.8.1.2


^ permalink raw reply related

* Re: [PATCH 0/2] Add support to pan and socket in haltest
From: Johan Hedberg @ 2013-10-23 10:05 UTC (permalink / raw)
  To: Jerzy Kasenberg; +Cc: linux-bluetooth
In-Reply-To: <1382517298-28093-1-git-send-email-jerzy.kasenberg@tieto.com>

Hi Jerzy,

On Wed, Oct 23, 2013, Jerzy Kasenberg wrote:
> - Add calls to methods of socket and pan
> 
> Jerzy Kasenberg (2):
>   android: Add calls to socket methods in haltest
>   android: Add calls to pan methods to haltest
> 
>  Makefile.android         |    4 +
>  android/Android.mk       |    2 +
>  android/client/haltest.c |    2 +
>  android/client/if-bt.c   |    4 +-
>  android/client/if-main.h |    4 +
>  android/client/if-pan.c  |  209 +++++++++++++++++++++++++++++
>  android/client/if-sock.c |  334 ++++++++++++++++++++++++++++++++++++++++++++++
>  7 files changed, 557 insertions(+), 2 deletions(-)
>  create mode 100644 android/client/if-pan.c
>  create mode 100644 android/client/if-sock.c

Both patches have been applied. Thanks.

Johan

^ permalink raw reply

* Re: [PATCH] android: Fix build error for Android
From: Emeltchenko, Andrei @ 2013-10-23  9:18 UTC (permalink / raw)
  To: Lukasz Rymanowski; +Cc: linux-bluetooth, johan.hedberg, szymon.janc
In-Reply-To: <1382516789-374-1-git-send-email-lukasz.rymanowski@tieto.com>

Hi Lukasz,

On Wed, Oct 23, 2013 at 11:26 AM, Lukasz Rymanowski
<lukasz.rymanowski@tieto.com> wrote:
> Android uses functions and defines from sys/capability.h which
> requires additional include
> ---
>  android/main.c | 4 ++++
>  1 file changed, 4 insertions(+)
>
> diff --git a/android/main.c b/android/main.c
> index 988d08b..606baf2 100644
> --- a/android/main.c
> +++ b/android/main.c
> @@ -52,6 +52,10 @@
>  #include "hal-msg.h"
>  #include "ipc.h"
>
> +#if defined(ANDROID)

check also for platform version in order to compile for 4.2.2

Regards,
Andrei

> +#include <sys/capability.h>
> +#endif
> +
>  static GMainLoop *event_loop;
>  static struct mgmt *mgmt_if = NULL;
>
> --
> 1.8.4
>
> ---------------------------------------------------------------------
> Intel Finland Oy
> Registered Address: PL 281, 00181 Helsinki
> Business Identity Code: 0357606 - 4
> Domiciled in Helsinki
>
> This e-mail and any attachments may contain confidential material for
> the sole use of the intended recipient(s). Any review or distribution
> by others is strictly prohibited. If you are not the intended
> recipient, please contact the sender and delete all copies.
>



-- 
Best regards,
Andrei Emeltchenko
Intel / OTC / Helsinki

^ permalink raw reply

* [PATCH v3 BlueZ 4/4] android: Add variable ROOT_PATH to Android.mk
From: Luiz Augusto von Dentz @ 2013-10-23  8:50 UTC (permalink / raw)
  To: linux-bluetooth
In-Reply-To: <1382518240-31896-1-git-send-email-luiz.dentz@gmail.com>

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

This makes it simpler to include files from other parts of the code.
---
 android/Android.mk | 13 +++++++------
 1 file changed, 7 insertions(+), 6 deletions(-)

diff --git a/android/Android.mk b/android/Android.mk
index 93dcc23..2dffe71 100644
--- a/android/Android.mk
+++ b/android/Android.mk
@@ -1,7 +1,8 @@
 LOCAL_PATH := $(call my-dir)
+ROOT_PATH := $(LOCAL_PATH)/..
 
 # Retrieve BlueZ version from configure.ac file
-BLUEZ_VERSION := $(shell grep ^AC_INIT $(LOCAL_PATH)/../configure.ac | cpp -P -D'AC_INIT(_,v)=v')
+BLUEZ_VERSION := $(shell grep ^AC_INIT $(ROOT_PATH)/configure.ac | cpp -P -D'AC_INIT(_,v)=v')
 
 # Specify pathmap for glib
 pathmap_INCL += glib:external/bluetooth/glib
@@ -34,9 +35,9 @@ LOCAL_C_INCLUDES := \
 	$(call include-path-for, glib)/glib \
 
 LOCAL_C_INCLUDES += \
-	$(LOCAL_PATH)/../ \
-	$(LOCAL_PATH)/../src \
-	$(LOCAL_PATH)/../lib \
+	$(ROOT_PATH)/ \
+	$(ROOT_PATH)/src \
+	$(ROOT_PATH)/lib \
 
 LOCAL_CFLAGS := -DVERSION=\"$(BLUEZ_VERSION)\"
 
@@ -51,9 +52,9 @@ lib_headers := \
 	sdp_lib.h \
 	sdp.h \
 
-$(shell mkdir -p $(LOCAL_PATH)/../lib/bluetooth)
+$(shell mkdir -p $(ROOT_PATH)/lib/bluetooth)
 
-$(foreach file,$(lib_headers), $(shell ln -sf ../$(file) $(LOCAL_PATH)/../lib/bluetooth/$(file)))
+$(foreach file,$(lib_headers), $(shell ln -sf ../$(file) $(ROOT_PATH)/lib/bluetooth/$(file)))
 
 LOCAL_MODULE := bluetoothd
 
-- 
1.8.3.1


^ permalink raw reply related

* [PATCH v3 BlueZ 3/4] android: Fix build dependency of haltest on target
From: Luiz Augusto von Dentz @ 2013-10-23  8:50 UTC (permalink / raw)
  To: linux-bluetooth
In-Reply-To: <1382518240-31896-1-git-send-email-luiz.dentz@gmail.com>

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

This adds missing headers necessary to build haltest.
---
 android/Android.mk | 9 +++++----
 1 file changed, 5 insertions(+), 4 deletions(-)

diff --git a/android/Android.mk b/android/Android.mk
index 6d707c2..93dcc23 100644
--- a/android/Android.mk
+++ b/android/Android.mk
@@ -92,11 +92,12 @@ include $(CLEAR_VARS)
 
 LOCAL_SRC_FILES := \
 	client/haltest.c \
-	client/pollhandler.c \
-	client/terminal.c \
-	client/history.c \
-	client/textconv.c \
+	client/pollhandler.c client/pollhandler.h \
+	client/terminal.c client/terminal.h \
+	client/history.c client/history.h \
+	client/textconv.c client/textconv.h \
 	client/tabcompletion.c \
+	client/if-main.h \
 	client/if-bt.c \
 	client/if-hh.c \
 
-- 
1.8.3.1


^ permalink raw reply related

* [PATCH v3 BlueZ 2/4] android: Fix build dependency of bluetooth.default.so HAL on target
From: Luiz Augusto von Dentz @ 2013-10-23  8:50 UTC (permalink / raw)
  To: linux-bluetooth
In-Reply-To: <1382518240-31896-1-git-send-email-luiz.dentz@gmail.com>

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

This adds missing headers necessary to build bluetooth.default.so
---
 android/Android.mk | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/android/Android.mk b/android/Android.mk
index d67a62d..6d707c2 100644
--- a/android/Android.mk
+++ b/android/Android.mk
@@ -66,7 +66,8 @@ include $(BUILD_EXECUTABLE)
 include $(CLEAR_VARS)
 
 LOCAL_SRC_FILES := \
-	hal-ipc.c \
+	hal.h hal-msg.h hal-log.h \
+	hal-ipc.c hal-ipc.h \
 	hal-bluetooth.c \
 	hal-sock.c \
 	hal-hidhost.c \
-- 
1.8.3.1


^ permalink raw reply related

* [PATCH v3 BlueZ 1/4] android: Fix build dependency of bluetoothd on target
From: Luiz Augusto von Dentz @ 2013-10-23  8:50 UTC (permalink / raw)
  To: linux-bluetooth

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

This adds missing headers necessary to build bluetoothd.
---
 android/Android.mk | 5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)

diff --git a/android/Android.mk b/android/Android.mk
index 7132279..d67a62d 100644
--- a/android/Android.mk
+++ b/android/Android.mk
@@ -15,9 +15,10 @@ include $(CLEAR_VARS)
 LOCAL_SRC_FILES := \
 	main.c \
 	log.c \
-	adapter.c \
-	hid.c \
+	adapter.c adapter.h \
+	hid.c hid.h \
 	ipc.c ipc.h \
+	../src/sdp.h \
 	../src/shared/mgmt.c \
 	../src/shared/util.c \
 	../src/sdpd-database.c \
-- 
1.8.3.1


^ permalink raw reply related

* [PATCH 2/2] android: Add calls to pan methods to haltest
From: Jerzy Kasenberg @ 2013-10-23  8:34 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Jerzy Kasenberg
In-Reply-To: <1382517298-28093-1-git-send-email-jerzy.kasenberg@tieto.com>

This patch allows to call pan methods in haltest.
---
 Makefile.android         |    2 +
 android/Android.mk       |    1 +
 android/client/haltest.c |    1 +
 android/client/if-bt.c   |    2 +-
 android/client/if-main.h |    2 +
 android/client/if-pan.c  |  209 ++++++++++++++++++++++++++++++++++++++++++++++
 6 files changed, 216 insertions(+), 1 deletion(-)
 create mode 100644 android/client/if-pan.c

diff --git a/Makefile.android b/Makefile.android
index 30e9110..0a05e9e 100644
--- a/Makefile.android
+++ b/Makefile.android
@@ -50,6 +50,7 @@ android_haltest_SOURCES = android/client/haltest.c \
 				android/client/tabcompletion.c \
 				android/client/if-bt.c \
 				android/client/if-hh.c \
+				android/client/if-pan.c \
 				android/client/if-sock.c \
 				android/client/hwmodule.c
 
@@ -79,6 +80,7 @@ EXTRA_DIST += android/client/terminal.c \
 		android/client/history.c \
 		android/client/if-bt.c \
 		android/client/if-hh.c \
+		android/client/if-pan.c \
 		android/client/if-sock.c \
 		android/client/textconv.c \
 		android/client/tabcompletion.c \
diff --git a/android/Android.mk b/android/Android.mk
index 7fdd70c..9f91576 100644
--- a/android/Android.mk
+++ b/android/Android.mk
@@ -97,6 +97,7 @@ LOCAL_SRC_FILES := \
 	client/tabcompletion.c \
 	client/if-bt.c \
 	client/if-hh.c \
+	client/if-pan.c \
 	client/if-sock.c \
 
 LOCAL_CFLAGS := -DPLATFORM_SDK_VERSION=$(PLATFORM_SDK_VERSION)
diff --git a/android/client/haltest.c b/android/client/haltest.c
index 49c05e9..7168dfd 100644
--- a/android/client/haltest.c
+++ b/android/client/haltest.c
@@ -32,6 +32,7 @@
 const struct interface *interfaces[] = {
 	&bluetooth_if,
 	&hh_if,
+	&pan_if,
 	&sock_if,
 	NULL
 };
diff --git a/android/client/if-bt.c b/android/client/if-bt.c
index d90786a..2d9c0b5 100644
--- a/android/client/if-bt.c
+++ b/android/client/if-bt.c
@@ -811,7 +811,7 @@ static void get_profile_interface_p(int argc, const char **argv)
 	else if (strcmp(BT_PROFILE_HIDHOST_ID, id) == 0)
 		pif = (const void **)&if_hh;
 	else if (strcmp(BT_PROFILE_PAN_ID, id) == 0)
-		pif = &dummy; /* TODO: change when if_pan is there */
+		pif = (const void **)&if_pan;
 #if PLATFORM_SDK_VERSION > 17
 	else if (strcmp(BT_PROFILE_AV_RC_ID, id) == 0)
 		pif = &dummy; /* TODO: change when if_rc is there */
diff --git a/android/client/if-main.h b/android/client/if-main.h
index 9c732c1..e214ed0 100644
--- a/android/client/if-main.h
+++ b/android/client/if-main.h
@@ -45,6 +45,7 @@
 /* Interfaces from hal that can be populated during application lifetime */
 extern const bt_interface_t *if_bluetooth;
 extern const bthh_interface_t *if_hh;
+extern const btpan_interface_t *if_pan;
 extern const btsock_interface_t *if_sock;
 
 /*
@@ -57,6 +58,7 @@ struct interface {
 };
 
 extern const struct interface bluetooth_if;
+extern const struct interface pan_if;
 extern const struct interface sock_if;
 extern const struct interface hh_if;
 
diff --git a/android/client/if-pan.c b/android/client/if-pan.c
new file mode 100644
index 0000000..fc296a6
--- /dev/null
+++ b/android/client/if-pan.c
@@ -0,0 +1,209 @@
+/*
+ * Copyright (C) 2013 Intel Corporation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#include <hardware/bluetooth.h>
+
+#include "if-main.h"
+
+const btpan_interface_t *if_pan = NULL;
+
+typedef int btpan_role_t;
+
+SINTMAP(btpan_role_t, -1, "(unknown)")
+	DELEMENT(BTPAN_ROLE_NONE),
+	DELEMENT(BTPAN_ROLE_PANNAP),
+	DELEMENT(BTPAN_ROLE_PANU),
+ENDMAP
+
+SINTMAP(btpan_connection_state_t, -1, "(unknown)")
+	DELEMENT(BTPAN_STATE_CONNECTED),
+	DELEMENT(BTPAN_STATE_CONNECTING),
+	DELEMENT(BTPAN_STATE_DISCONNECTED),
+	DELEMENT(BTPAN_STATE_DISCONNECTING),
+ENDMAP
+
+SINTMAP(btpan_control_state_t, -1, "(unknown)")
+	DELEMENT(BTPAN_STATE_ENABLED),
+	DELEMENT(BTPAN_STATE_DISABLED),
+ENDMAP
+
+static void control_state_cb(btpan_control_state_t state, bt_status_t error,
+					int local_role, const char *ifname)
+{
+	haltest_info("%s: state=%s error=%s local_role=%s ifname=%s\n",
+		       __func__, btpan_control_state_t2str(state),
+		       bt_status_t2str(error), btpan_role_t2str(local_role),
+								       ifname);
+}
+
+static char last_used_addr[18];
+
+static void connection_state_cb(btpan_connection_state_t state,
+				bt_status_t error, const bt_bdaddr_t *bd_addr,
+				int local_role, int remote_role)
+{
+	haltest_info("%s: state=%s error=%s bd_addr=%s local_role=%s remote_role=%s\n",
+			__func__, btpan_connection_state_t2str(state),
+			bt_status_t2str(error),
+			bt_bdaddr_t2str(bd_addr, last_used_addr),
+			btpan_role_t2str(local_role),
+			btpan_role_t2str(remote_role));
+}
+
+static btpan_callbacks_t pan_cbacks = {
+	.size = sizeof(pan_cbacks),
+	.control_state_cb = control_state_cb,
+	.connection_state_cb = connection_state_cb
+};
+
+static void init_p(int argc, const char **argv)
+{
+	RETURN_IF_NULL(if_pan);
+
+	EXEC(if_pan->init, &pan_cbacks);
+}
+
+/* enable */
+
+static void enable_c(int argc, const const char **argv,
+					enum_func *penum_func, void **puser)
+{
+	if (argc == 3) {
+		*puser = TYPE_ENUM(btpan_role_t);
+		*penum_func = enum_defines;
+	}
+}
+
+static void enable_p(int argc, const char **argv)
+{
+	int local_role;
+
+	RETURN_IF_NULL(if_pan);
+
+	/* local role */
+	if (argc < 3) {
+		haltest_error("No local mode specified\n");
+		return;
+	}
+	local_role = str2btpan_role_t(argv[2]);
+	if (local_role == -1)
+		local_role = atoi(argv[2]);
+
+	EXEC(if_pan->enable, local_role);
+}
+
+/* get_local_role */
+
+static void get_local_role_p(int argc, const char **argv)
+{
+	int local_role;
+
+	RETURN_IF_NULL(if_pan);
+
+	local_role = if_pan->get_local_role();
+	haltest_info("local_role: %s\n", btpan_role_t2str(local_role));
+}
+
+/* connect */
+
+static void connect_c(int argc, const const char **argv,
+					enum_func *penum_func, void **puser)
+{
+	if (argc == 3) {
+		*puser = NULL;
+		*penum_func = enum_devices;
+	} else if (argc == 4 || argc == 5) {
+		*puser = TYPE_ENUM(btpan_role_t);
+		*penum_func = enum_defines;
+	}
+}
+
+static void connect_p(int argc, const char **argv)
+{
+	bt_bdaddr_t addr;
+	int local_role;
+	int remote_role;
+
+	RETURN_IF_NULL(if_pan);
+	VERIFY_ADDR_ARG(2, &addr);
+
+	/* local role */
+	if (argc < 4) {
+		haltest_error("No local mode specified\n");
+		return;
+	}
+	local_role = str2btpan_role_t(argv[3]);
+	if (local_role == -1)
+		local_role = atoi(argv[3]);
+
+	/* remote role */
+	if (argc < 5) {
+		haltest_error("No remote mode specified\n");
+		return;
+	}
+	remote_role = str2btpan_role_t(argv[4]);
+	if (remote_role == -1)
+		remote_role = atoi(argv[4]);
+
+	EXEC(if_pan->connect, &addr, local_role, remote_role);
+}
+
+/* disconnect */
+
+static void disconnect_c(int argc, const const char **argv,
+					enum_func *penum_func, void **puser)
+{
+	if (argc == 3) {
+		*puser = last_used_addr;
+		*penum_func = enum_one_string;
+	}
+}
+
+static void disconnect_p(int argc, const char **argv)
+{
+	bt_bdaddr_t addr;
+
+	RETURN_IF_NULL(if_pan);
+	VERIFY_ADDR_ARG(2, &addr);
+
+	EXEC(if_pan->disconnect, &addr);
+}
+
+/* cleanup */
+
+static void cleanup_p(int argc, const char **argv)
+{
+	RETURN_IF_NULL(if_pan);
+
+	EXECV(if_pan->cleanup);
+	if_pan = NULL;
+}
+
+static struct method methods[] = {
+	STD_METHOD(init),
+	STD_METHODCH(connect, "<addr> <local_role> <remote_role>"),
+	STD_METHODCH(enable, "<local_role>"),
+	STD_METHOD(get_local_role),
+	STD_METHODCH(disconnect, "<addr>"),
+	STD_METHOD(cleanup),
+	END_METHOD
+};
+
+const struct interface pan_if = {
+	.name = "pan",
+	.methods = methods
+};
-- 
1.7.9.5


^ permalink raw reply related

* [PATCH 1/2] android: Add calls to socket methods in haltest
From: Jerzy Kasenberg @ 2013-10-23  8:34 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Jerzy Kasenberg
In-Reply-To: <1382517298-28093-1-git-send-email-jerzy.kasenberg@tieto.com>

This patch adds calls to socket methods.
---
 Makefile.android         |    2 +
 android/Android.mk       |    1 +
 android/client/haltest.c |    1 +
 android/client/if-bt.c   |    2 +-
 android/client/if-main.h |    2 +
 android/client/if-sock.c |  334 ++++++++++++++++++++++++++++++++++++++++++++++
 6 files changed, 341 insertions(+), 1 deletion(-)
 create mode 100644 android/client/if-sock.c

diff --git a/Makefile.android b/Makefile.android
index 90d5973..30e9110 100644
--- a/Makefile.android
+++ b/Makefile.android
@@ -50,6 +50,7 @@ android_haltest_SOURCES = android/client/haltest.c \
 				android/client/tabcompletion.c \
 				android/client/if-bt.c \
 				android/client/if-hh.c \
+				android/client/if-sock.c \
 				android/client/hwmodule.c
 
 android_haltest_LDADD = android/libhal-internal.la
@@ -78,6 +79,7 @@ EXTRA_DIST += android/client/terminal.c \
 		android/client/history.c \
 		android/client/if-bt.c \
 		android/client/if-hh.c \
+		android/client/if-sock.c \
 		android/client/textconv.c \
 		android/client/tabcompletion.c \
 		android/client/textconv.h \
diff --git a/android/Android.mk b/android/Android.mk
index 7132279..7fdd70c 100644
--- a/android/Android.mk
+++ b/android/Android.mk
@@ -97,6 +97,7 @@ LOCAL_SRC_FILES := \
 	client/tabcompletion.c \
 	client/if-bt.c \
 	client/if-hh.c \
+	client/if-sock.c \
 
 LOCAL_CFLAGS := -DPLATFORM_SDK_VERSION=$(PLATFORM_SDK_VERSION)
 
diff --git a/android/client/haltest.c b/android/client/haltest.c
index 2894565..49c05e9 100644
--- a/android/client/haltest.c
+++ b/android/client/haltest.c
@@ -32,6 +32,7 @@
 const struct interface *interfaces[] = {
 	&bluetooth_if,
 	&hh_if,
+	&sock_if,
 	NULL
 };
 
diff --git a/android/client/if-bt.c b/android/client/if-bt.c
index 01bf1d1..d90786a 100644
--- a/android/client/if-bt.c
+++ b/android/client/if-bt.c
@@ -807,7 +807,7 @@ static void get_profile_interface_p(int argc, const char **argv)
 	else if (strcmp(BT_PROFILE_HEALTH_ID, id) == 0)
 		pif = &dummy; /* TODO: change when if_hl is there */
 	else if (strcmp(BT_PROFILE_SOCKETS_ID, id) == 0)
-		pif = &dummy; /* TODO: change when if_sock is there */
+		pif = (const void **)&if_sock;
 	else if (strcmp(BT_PROFILE_HIDHOST_ID, id) == 0)
 		pif = (const void **)&if_hh;
 	else if (strcmp(BT_PROFILE_PAN_ID, id) == 0)
diff --git a/android/client/if-main.h b/android/client/if-main.h
index 21fdcfe..9c732c1 100644
--- a/android/client/if-main.h
+++ b/android/client/if-main.h
@@ -45,6 +45,7 @@
 /* Interfaces from hal that can be populated during application lifetime */
 extern const bt_interface_t *if_bluetooth;
 extern const bthh_interface_t *if_hh;
+extern const btsock_interface_t *if_sock;
 
 /*
  * Structure defines top level interfaces that can be used in test tool
@@ -56,6 +57,7 @@ struct interface {
 };
 
 extern const struct interface bluetooth_if;
+extern const struct interface sock_if;
 extern const struct interface hh_if;
 
 /* Interfaces that will show up in tool (first part of command line) */
diff --git a/android/client/if-sock.c b/android/client/if-sock.c
new file mode 100644
index 0000000..f761a0f
--- /dev/null
+++ b/android/client/if-sock.c
@@ -0,0 +1,334 @@
+/*
+ * Copyright (C) 2013 Intel Corporation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#include <stdio.h>
+#include <ctype.h>
+#include <unistd.h>
+
+#include "if-main.h"
+#include "pollhandler.h"
+
+const btsock_interface_t *if_sock = NULL;
+
+SINTMAP(btsock_type_t, -1, "(unknown)")
+	DELEMENT(BTSOCK_RFCOMM),
+	DELEMENT(BTSOCK_SCO),
+	DELEMENT(BTSOCK_L2CAP),
+ENDMAP
+
+#define MAX_LISTEN_FD 15
+static int listen_fd[MAX_LISTEN_FD];
+static int listen_fd_count;
+
+/*
+ * This function reads data from file descriptor and
+ * prints it to the user
+ */
+static void receive_from_client(struct pollfd *pollfd)
+{
+	char buf[16];
+	/* Buffer for lines:
+	 * 41 42 43 20 20 00 31 32 00 07 04 00 00 00 00 00 ABC  .12.....
+	 */
+	char outbuf[sizeof(buf) * 4 + 2];
+	int i;
+	int ret;
+
+	if (pollfd->revents & POLLHUP) {
+		haltest_error("Disconnected fd=%d\n", pollfd->fd);
+		poll_unregister_fd(pollfd->fd, receive_from_client);
+	} else if (pollfd->revents & POLLIN) {
+
+		haltest_info("receiving from client fd=%d\n", pollfd->fd);
+
+		do {
+			memset(outbuf, ' ', sizeof(outbuf));
+			outbuf[sizeof(outbuf) - 1] = 0;
+			ret = recv(pollfd->fd, buf, sizeof(buf), MSG_DONTWAIT);
+
+			for (i = 0; i < ret; ++i)
+				sprintf(outbuf + i * 3, "%02X ",
+							(unsigned) buf[i]);
+			outbuf[i * 3] = ' ';
+			for (i = 0; i < ret; ++i)
+				sprintf(outbuf + 48 + i, "%c",
+					(isprint(buf[i]) ? buf[i] : '.'));
+			if (ret > 0)
+				haltest_info("%s\n", outbuf);
+		} while (ret > 0);
+	} else {
+		/* For now disconnect on all other events */
+		haltest_error("Poll event %x\n", pollfd->revents);
+		poll_unregister_fd(pollfd->fd, receive_from_client);
+	}
+}
+
+/*
+ * This function read from fd socket information about
+ * connected socket
+ */
+static void receive_sock_connect_signal(struct pollfd *pollfd)
+{
+	sock_connect_signal_t cs;
+	char addr_str[MAX_ADDR_STR_LEN];
+
+	if (pollfd->revents & POLLIN) {
+		int ret;
+
+		poll_unregister_fd(pollfd->fd, receive_sock_connect_signal);
+		ret = read(pollfd->fd, &cs, sizeof(cs));
+		if (ret != sizeof(cs)) {
+			haltest_info("Read on connect return %d\n", ret);
+			return;
+		}
+		haltest_info("Connection to %s channel %d status=%d\n",
+				bt_bdaddr_t2str(&cs.bd_addr, addr_str),
+							cs.channel, cs.status);
+
+		if (cs.status == 0)
+			poll_register_fd(pollfd->fd, POLLIN,
+							receive_from_client);
+	}
+
+	if (pollfd->revents & POLLHUP) {
+		haltest_error("Disconnected fd=%d revents=0x%X\n", pollfd->fd,
+				pollfd->revents);
+		poll_unregister_fd(pollfd->fd, receive_sock_connect_signal);
+	}
+}
+
+/*
+ * This function read from fd socket information about
+ * incoming connection and starts monitoring new connection
+ * on file descriptor read from fd.
+ */
+static void read_accepted(int fd)
+{
+	int ret;
+	struct msghdr msg;
+	struct iovec iv;
+	char cmsgbuf[CMSG_SPACE(1)];
+	struct cmsghdr *cmsgptr;
+	sock_connect_signal_t cs;
+	int accepted_fd = -1;
+	char addr_str[MAX_ADDR_STR_LEN];
+
+	memset(&msg, 0, sizeof(msg));
+	memset(&iv, 0, sizeof(iv));
+
+	iv.iov_base = &cs;
+	iv.iov_len = sizeof(cs);
+
+	msg.msg_iov = &iv;
+	msg.msg_iovlen = 1;
+	msg.msg_control = cmsgbuf;
+	msg.msg_controllen = sizeof(cmsgbuf);
+
+	do {
+		ret = recvmsg(fd, &msg, MSG_NOSIGNAL);
+	} while (ret < 0 && errno == EINTR);
+
+	if (ret < 16 ||
+		(msg.msg_flags & (MSG_CTRUNC | MSG_OOB | MSG_ERRQUEUE)) != 0)
+		haltest_error("Failed to accept connection\n");
+
+	for (cmsgptr = CMSG_FIRSTHDR(&msg);
+		cmsgptr != NULL; cmsgptr = CMSG_NXTHDR(&msg, cmsgptr)) {
+		int *descs;
+		int count;
+
+		if (cmsgptr->cmsg_level != SOL_SOCKET ||
+			cmsgptr->cmsg_type != SCM_RIGHTS)
+			continue;
+
+		descs = (int *) CMSG_DATA(cmsgptr);
+		count = ((cmsgptr->cmsg_len - CMSG_LEN(0)) / sizeof(int));
+
+		if (count != 1)
+			haltest_error("Failed to accept descriptors count=%d\n",
+									count);
+
+		accepted_fd = descs[0];
+		break;
+	}
+	haltest_info("Incoming connection from %s channel %d status=%d fd=%d\n",
+			bt_bdaddr_t2str(&cs.bd_addr, addr_str), cs.channel,
+							cs.status, accepted_fd);
+	poll_register_fd(accepted_fd, POLLIN, receive_from_client);
+}
+
+/* handles incoming connections on socket */
+static void client_connected(struct pollfd *pollfd)
+{
+	haltest_info("client connected %x\n", pollfd->revents);
+
+	if (pollfd->revents & POLLHUP)
+		poll_unregister_fd(pollfd->fd, client_connected);
+	else if (pollfd->revents & POLLIN)
+		read_accepted(pollfd->fd);
+}
+
+/** listen */
+
+static void listen_c(int argc, const char **argv,
+					enum_func *penum_func, void **puser)
+{
+	if (argc == 3) {
+		*puser = TYPE_ENUM(btsock_type_t);
+		*penum_func = enum_defines;
+	}
+}
+
+static void listen_p(int argc, const char **argv)
+{
+	btsock_type_t type;
+	const char *service_name;
+	bt_uuid_t service_uuid;
+	int channel;
+	int sock_fd;
+	int flags;
+
+	RETURN_IF_NULL(if_sock);
+
+	/* Socket type */
+	if (argc < 3) {
+		haltest_error("No socket type specified\n");
+		return;
+	}
+	type = str2btsock_type_t(argv[2]);
+	if ((int) type == -1)
+		type = atoi(argv[2]);
+
+	/* service name */
+	if (argc < 4) {
+		haltest_error("No service name specified\n");
+		return;
+	}
+	service_name = argv[3];
+
+	/* uuid */
+	if (argc < 5) {
+		haltest_error("No uuid specified\n");
+		return;
+	}
+	str2bt_uuid_t(argv[4], &service_uuid);
+
+	/* channel */
+	channel = argc > 5 ? atoi(argv[5]) : 0;
+
+	/* flags */
+	flags = argc > 6 ? atoi(argv[6]) : 0;
+
+	if (listen_fd_count >= MAX_LISTEN_FD) {
+		haltest_error("Max (%d) listening sockets exceeded\n",
+							listen_fd_count);
+		return;
+	}
+	EXEC(if_sock->listen, type, service_name,
+				&service_uuid.uu[0], channel, &sock_fd, flags);
+	if (sock_fd > 0) {
+		int channel = 0;
+		int ret = read(sock_fd, &channel, 4);
+		if (ret != 4)
+			haltest_info("Read channel failed\n");
+		haltest_info("Channel returned from first read %d\n", channel);
+		listen_fd[listen_fd_count++] = sock_fd;
+		poll_register_fd(sock_fd, POLLIN, client_connected);
+	}
+}
+
+/** connect */
+
+static void connect_c(int argc, const char **argv,
+					enum_func *penum_func, void **puser)
+{
+	if (argc == 3) {
+		*penum_func = enum_devices;
+	} else if (argc == 4) {
+		*puser = TYPE_ENUM(btsock_type_t);
+		*penum_func = enum_defines;
+	}
+}
+
+static void connect_p(int argc, const char **argv)
+{
+	bt_bdaddr_t addr;
+	btsock_type_t type;
+	bt_uuid_t uuid;
+	int channel;
+	int sock_fd;
+	int flags;
+
+	/* Address */
+	if (argc <= 2) {
+		haltest_error("No address specified\n");
+		return;
+	}
+	str2bt_bdaddr_t(argv[2], &addr);
+
+	/* Socket type */
+	if (argc <= 3) {
+		haltest_error("No socket type specified\n");
+		return;
+	}
+	type = str2btsock_type_t(argv[3]);
+	if ((int) type == -1)
+		type = atoi(argv[3]);
+
+	/* uuid */
+	if (argc <= 4) {
+		haltest_error("No uuid specified\n");
+		return;
+	}
+	str2bt_uuid_t(argv[4], &uuid);
+
+	/* channel */
+	if (argc <= 5) {
+		haltest_error("No channel specified\n");
+		return;
+	}
+	channel = atoi(argv[5]);
+
+	/* flags */
+	flags = argc <= 6 ? 0 : atoi(argv[6]);
+
+	RETURN_IF_NULL(if_sock);
+
+	EXEC(if_sock->connect, &addr, type, &uuid.uu[0], channel, &sock_fd,
+									flags);
+	if (sock_fd > 0) {
+		int channel = 0;
+		int ret = read(sock_fd, &channel, 4);
+		if (ret != 4)
+			haltest_info("Read channel failed\n");
+		haltest_info("Channel returned from first read %d\n", channel);
+		listen_fd[listen_fd_count++] = sock_fd;
+		poll_register_fd(sock_fd, POLLIN, receive_sock_connect_signal);
+	}
+}
+
+/* Methods available in btsock_interface_t */
+static struct method methods[] = {
+	STD_METHODCH(listen, "<sock_type> <srvc_name> <uuid> [<channle>] [<flags>]"),
+	STD_METHODCH(connect, "<addr> <sock_type> <uuid> <channle> [<flags>]"),
+	END_METHOD
+};
+
+const struct interface sock_if = {
+	.name = "socket",
+	.methods = methods
+};
-- 
1.7.9.5


^ permalink raw reply related

* [PATCH 0/2] Add support to pan and socket in haltest
From: Jerzy Kasenberg @ 2013-10-23  8:34 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Jerzy Kasenberg

- Add calls to methods of socket and pan

Jerzy Kasenberg (2):
  android: Add calls to socket methods in haltest
  android: Add calls to pan methods to haltest

 Makefile.android         |    4 +
 android/Android.mk       |    2 +
 android/client/haltest.c |    2 +
 android/client/if-bt.c   |    4 +-
 android/client/if-main.h |    4 +
 android/client/if-pan.c  |  209 +++++++++++++++++++++++++++++
 android/client/if-sock.c |  334 ++++++++++++++++++++++++++++++++++++++++++++++
 7 files changed, 557 insertions(+), 2 deletions(-)
 create mode 100644 android/client/if-pan.c
 create mode 100644 android/client/if-sock.c

-- 
1.7.9.5


^ permalink raw reply

* [PATCH] android: Fix build error for Android
From: Lukasz Rymanowski @ 2013-10-23  8:26 UTC (permalink / raw)
  To: linux-bluetooth
  Cc: johan.hedberg, andrei.emeltchenko, szymon.janc, Lukasz Rymanowski

Android uses functions and defines from sys/capability.h which
requires additional include
---
 android/main.c | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/android/main.c b/android/main.c
index 988d08b..606baf2 100644
--- a/android/main.c
+++ b/android/main.c
@@ -52,6 +52,10 @@
 #include "hal-msg.h"
 #include "ipc.h"
 
+#if defined(ANDROID)
+#include <sys/capability.h>
+#endif
+
 static GMainLoop *event_loop;
 static struct mgmt *mgmt_if = NULL;
 
-- 
1.8.4


^ 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