Linux bluetooth development
 help / color / mirror / Atom feed
* Re: [RFC v2 4/7] Bluetooth: Enable 6LoWPAN support for BT LE devices
From: Marcel Holtmann @ 2013-10-30 12:11 UTC (permalink / raw)
  To: Jukka Rissanen; +Cc: linux-bluetooth@vger.kernel.org development
In-Reply-To: <1383123661-15087-5-git-send-email-jukka.rissanen@linux.intel.com>

Hi Jukka,

> Signed-off-by: Jukka Rissanen <jukka.rissanen@linux.intel.com>
> ---
> net/bluetooth/6lowpan.c | 1128 ++++++++++++++++++++++++++++++++++++++++++++++-
> 1 file changed, 1127 insertions(+), 1 deletion(-)
> 
> diff --git a/net/bluetooth/6lowpan.c b/net/bluetooth/6lowpan.c
> index aff478b..1cba7fd 100644
> --- a/net/bluetooth/6lowpan.c
> +++ b/net/bluetooth/6lowpan.c
> @@ -11,6 +11,20 @@
>    GNU General Public License for more details.
> */
> 
> +/*
> + * The compression, uncompression and IPv6 packet fragmentation code
> + * is from net/ieee802154/6lowpan.c with these copyrights
> + *
> + * Copyright 2011, Siemens AG
> + * written by Alexander Smirnov <alex.bluesman.smirnov@gmail.com>
> + *
> + * Based on patches from Jon Smirl <jonsmirl@gmail.com>
> + * Copyright (c) 2011 Jon Smirl <jonsmirl@gmail.com>
> + *
> + * Jon's code is based on 6lowpan implementation for Contiki which is:
> + * Copyright (c) 2008, Swedish Institute of Computer Science.
> + */
> +

I really think this should consolidated into either net/core/6lowpan.c or net/6lowpan/6lowpan.c.

Regards

Marcel


^ permalink raw reply

* Re: [RFC v2 7/7] Bluetooth: Manually enable or disable 6LoWPAN between devices
From: Marcel Holtmann @ 2013-10-30 12:10 UTC (permalink / raw)
  To: Jukka Rissanen; +Cc: linux-bluetooth@vger.kernel.org development
In-Reply-To: <1383123661-15087-8-git-send-email-jukka.rissanen@linux.intel.com>

Hi Jukka,

> This is a temporary patch where user can manually enable or
> disable BT 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/6lowpan
> root@dev2# echo 00:11:22:33:44:55 > /sys/kernel/debug/bluetooth/hci0/6lowpan
> 
> 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/6lowpan 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/6lowpan
> Rebooting or unloading the bluetooth kernel module will also clear the
> settings from the kernel.
> 
> Signed-off-by: Jukka Rissanen <jukka.rissanen@linux.intel.com>
> ---
> net/bluetooth/6lowpan.c    | 158 +++++++++++++++++++++++++++++++++++++++++++++
> net/bluetooth/6lowpan.h    |   2 +
> net/bluetooth/hci_core.c   |   4 ++
> net/bluetooth/l2cap_core.c |  12 ++--
> 4 files changed, 169 insertions(+), 7 deletions(-)
> 
> diff --git a/net/bluetooth/6lowpan.c b/net/bluetooth/6lowpan.c
> index 4ec3813..55f455a 100644
> --- a/net/bluetooth/6lowpan.c
> +++ b/net/bluetooth/6lowpan.c
> @@ -26,6 +26,7 @@
>  */
> 
> #include <linux/version.h>
> +#include <linux/debugfs.h>
> #include <linux/bitops.h>
> #include <linux/if_arp.h>
> #include <linux/netdevice.h>
> @@ -1553,6 +1554,163 @@ static struct notifier_block bt_6lowpan_dev_notifier = {
> 	.notifier_call = device_event,
> };
> 
> +static LIST_HEAD(user_enabled);
> +DEFINE_RWLOCK(user_enabled_list_lock);
> +
> +struct lowpan_enabled {
> +	__u8 dev_name[HCI_MAX_NAME_LENGTH];
> +	bdaddr_t addr;
> +	struct list_head list;
> +};

while I would not keep doing it like this and favor a simple switch like HCI_6LOWPAN_ENABLED in hdev->dev_flags, you however need to start also tracking the address type.

Personally I think we need to just make up a UUID-128 and just add it to AD data once HCI_6LOWPAN has been enabled. We are getting close to the background scanning patches. And then we can just have code that auto-connects devices with that specific UUID-128 if 6loWPAN is enabled. That will avoid all this list storage and complex debugfs. In the end it is just 6loWPAN on/off per hdev.

What we however do have to address is the case when one LE master is connected to two LE slaves. We should not have two 6loWPAN network devices. It should be only one since they form one network.

So maybe the creating of the net_device should be bound to debugfs/hci0/6lowpan switch for on/off. Just thinking out loud here.

> +
> +bool bt_6lowpan_is_enabled(struct hci_dev *hdev, bdaddr_t *dst)
> +{
> +	struct lowpan_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 lowpan_dev *entry, *tmp;
> +		struct lowpan_info *info;
> +
> +		write_lock(&net_dev_list_lock);
> +		list_for_each_entry_safe(entry, tmp, &bt_6lowpan_devices,
> +								list) {
> +			info = lowpan_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 debugfs_show(struct seq_file *f, void *p)
> +{
> +	struct lowpan_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 debugfs_open(struct inode *inode, struct file *file)
> +{
> +	return single_open(file, debugfs_show, inode->i_private);
> +}
> +
> +static ssize_t 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;
> +	struct lowpan_enabled *entry = NULL, *tmp;
> +	bdaddr_t bdaddr;
> +
> +        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)
> +		return ret;
> +
> +	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)
> +		return ret;
> +
> +	if (delete_mode) {
> +		write_lock(&user_enabled_list_lock);
> +		list_del(&entry->list);
> +		kfree(entry);
> +		write_unlock(&user_enabled_list_lock);
> +	} else {
> +		struct hci_dev *hdev = fp->f_inode->i_private;
> +
> +		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		= debugfs_open,
> +	.read		= seq_read,
> +	.write		= writer,
> +	.llseek		= seq_lseek,
> +	.release	= single_release,
> +};
> +
> +static struct dentry *bt_6lowpan_debugfs;
> +
> +void bt_6lowpan_add_debugfs(struct hci_dev *hdev)
> +{
> +	if (hdev->debugfs)

Please check if the calling place not already verified that hdev->debugfs is valid.

> +		bt_6lowpan_debugfs = debugfs_create_file("6lowpan", 0644,
> +			hdev->debugfs, hdev, &ble_6lowpan_debugfs_fops);

Also no point in bothering to store its return value. We use recursive cleanup. Nobody cares about the value.

> +}
> +
> int bt_6lowpan_init(void)
> {
> 	return register_netdevice_notifier(&bt_6lowpan_dev_notifier);
> diff --git a/net/bluetooth/6lowpan.h b/net/bluetooth/6lowpan.h
> index 680eac8..549fc51 100644
> --- a/net/bluetooth/6lowpan.h
> +++ b/net/bluetooth/6lowpan.h
> @@ -22,5 +22,7 @@ int bt_6lowpan_add_conn(struct l2cap_conn *conn);
> int bt_6lowpan_del_conn(struct l2cap_conn *conn);
> int bt_6lowpan_init(void);
> void bt_6lowpan_cleanup(void);
> +bool bt_6lowpan_is_enabled(struct hci_dev *hdev, bdaddr_t *dst);
> +void bt_6lowpan_add_debugfs(struct hci_dev *hdev);
> 
> #endif /* __6LOWPAN_H */
> diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c
> index 6ccc4eb..444b4bc 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 "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);
> 	}
> 
> +	bt_6lowpan_add_debugfs(hdev);
> +

Might only want to add 6lowpan debugfs when we actually support LE.

> 	return 0;
> }
> 
> diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c
> index c47215f..d02241e 100644
> --- a/net/bluetooth/l2cap_core.c
> +++ b/net/bluetooth/l2cap_core.c
> @@ -6512,11 +6512,6 @@ int l2cap_connect_ind(struct hci_dev *hdev, bdaddr_t *bdaddr)
> 	return exact ? lm1 : lm2;
> }
> 
> -static bool is_bt_6lowpan(void)
> -{
> -	return false;
> -}
> -
> void l2cap_connect_cfm(struct hci_conn *hcon, u8 status)
> {
> 	struct l2cap_conn *conn;
> @@ -6528,7 +6523,9 @@ void l2cap_connect_cfm(struct hci_conn *hcon, u8 status)
> 		if (conn) {
> 			l2cap_conn_ready(conn);
> 
> -			if (hcon->type == LE_LINK && is_bt_6lowpan())
> +			if (hcon->type == LE_LINK &&
> +					bt_6lowpan_is_enabled(hcon->hdev,
> +								&hcon->dst))
> 				bt_6lowpan_add_conn(conn);
> 		}
> 	} else {
> @@ -6551,7 +6548,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_bt_6lowpan())
> +	if (hcon->type == LE_LINK && bt_6lowpan_is_enabled(hcon->hdev,
> +							&hcon->dst))
> 		bt_6lowpan_del_conn(hcon->l2cap_data);
> 
> 	l2cap_conn_del(hcon, bt_to_errno(reason));

Regards

Marcel


^ permalink raw reply

* Re: [RFC v2 3/7] Bluetooth: Initial skeleton code for BT 6LoWPAN
From: Marcel Holtmann @ 2013-10-30 12:02 UTC (permalink / raw)
  To: Jukka Rissanen; +Cc: linux-bluetooth@vger.kernel.org development
In-Reply-To: <1383123661-15087-4-git-send-email-jukka.rissanen@linux.intel.com>

Hi Jukka,

> Signed-off-by: Jukka Rissanen <jukka.rissanen@linux.intel.com>
> ---
> include/net/bluetooth/l2cap.h |   1 +
> net/bluetooth/6lowpan.c       | 401 ++++++++++++++++++++++++++++++++++++++++++
> net/bluetooth/6lowpan.h       |  26 +++
> net/bluetooth/Makefile        |   2 +-
> net/bluetooth/l2cap_core.c    |  22 ++-
> 5 files changed, 450 insertions(+), 2 deletions(-)
> create mode 100644 net/bluetooth/6lowpan.c
> create mode 100644 net/bluetooth/6lowpan.h
> 
> diff --git a/include/net/bluetooth/l2cap.h b/include/net/bluetooth/l2cap.h
> index 5132990..c28ac0d 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/6lowpan.c b/net/bluetooth/6lowpan.c
> new file mode 100644
> index 0000000..aff478b
> --- /dev/null
> +++ b/net/bluetooth/6lowpan.c
> @@ -0,0 +1,401 @@
> +/*
> +   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 */

this is fine for now, but please check on netdev (aka send patches) to see if we should have something like net/core/6lowpan.[ch]. Or if they prefer net/6lowpan/6lowpan.[ch].

> +
> +#define IFACE_NAME_TEMPLATE "bt%d"
> +
> +/*
> + * The devices list contains those devices that we are acting
> + * as a proxy. The BT 6LoWPAN device is a virtual device that
> + * connects to the Bluetooth LE device. The real connection to
> + * BT device is done via l2cap layer. There exists one
> + * virtual device / one BT 6LoWPAN device. The list contains
> + * struct lowpan_dev elements.
> + */
> +static LIST_HEAD(bt_6lowpan_devices);
> +DEFINE_RWLOCK(net_dev_list_lock);

You need to find a better name for the lock. And you can also make that one static I assume.

> +
> +struct lowpan_dev {
> +	struct net_device *dev;
> +	struct delayed_work delete_timer;
> +	struct list_head list;
> +};
> +
> +struct lowpan_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;
> +};
> +
> +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)

Maybe a comment why this is 1 msecs would be good here. It is a rather tiny timeout.

> +
> +/* TTL uncompression values */
> +static const u8 lowpan_ttl_values[] = {0, 1, 64, 255};

Personally I would have { 0, .., 255 }; here. So extra spaces between { and }.

> +
> +static inline struct
> +lowpan_info *lowpan_info(const struct net_device *dev)

Linebreak between struct and lowpan_info looks weird to me.

> +{
> +	return netdev_priv(dev);
> +}

Not sure what the standard in the network subsystem here, but maybe a #define would be better.

> +
> +/* print data in line */
> +static inline void 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 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 recv_pkt(struct sk_buff *skb, struct net_device *dev)
> +{
> +	kfree_skb(skb);
> +	return NET_RX_DROP;
> +}
> +
> +/* Packet from BT LE device */
> +int bt_6lowpan_recv(struct l2cap_conn *conn, struct sk_buff *skb)
> +{
> +	struct lowpan_dev *entry, *tmp;
> +	struct net_device *dev = NULL;
> +	int status = -ENOENT;
> +
> +	write_lock(&net_dev_list_lock);
> +
> +	list_for_each_entry_safe(entry, tmp, &bt_6lowpan_devices, list) {
> +		if (lowpan_info(entry->dev)->conn == conn) {
> +			dev = lowpan_info(entry->dev)->net;
> +			break;
> +		}
> +	}
> +
> +	write_unlock(&net_dev_list_lock);
> +
> +	if (dev) {
> +		status = recv_pkt(skb, dev);
> +		BT_DBG("recv pkt %d", status);
> +	}
> +
> +	return status;
> +}
> +
> +static void 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 conn_send(struct l2cap_conn *conn,
> +			void *msg, size_t len, u32 priority,
> +			struct net_device *dev)
> +{
> +	struct sk_buff *skb = {0};
> +
> +	do_send(conn, skb);
> +	return 0;
> +}
> +
> +/* Packet to BT LE device */
> +static int send_pkt(struct l2cap_conn *conn, const void *saddr,
> +			const void *daddr, struct sk_buff *skb,
> +			struct net_device *dev)

This goes for all the function, we need to follow the network subsystem coding style. Aka calling checkpatch.pl with --strict or the better name —subjective.

I know that there are still bad examples in some places, but for new code, we have to follow it.

> +{
> +	raw_dump_table(__func__, "raw skb data dump before fragmentation",
> +				skb->data, skb->len);
> +
> +	return conn_send(conn, skb->data, skb->len, 0, dev);
> +}
> +
> +static netdev_tx_t xmit(struct sk_buff *skb, struct net_device *dev)
> +{
> +	int err = -1;
> +
> +	pr_debug("ble 6lowpan packet xmit\n");
> +
> +	if (lowpan_info(dev)->conn)
> +		err = send_pkt(lowpan_info(dev)->conn,
> +				dev->dev_addr,
> +				&lowpan_info(dev)->ieee802154_addr,
> +				skb,
> +				dev);
> +	else
> +		BT_DBG("ERROR: no BT LE 6LoWPAN device found”);

Can this case actually happen? In case our LE connection goes away, we should just flush all queues, bring the netdev down and unregister it.

> +
> +	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 netdev_ops = {
> +	.ndo_start_xmit		= xmit,
> +};
> +
> +static void setup(struct net_device *dev)

Maybe netdev_setup, lowpan_netdev, rawip_setup or something is better name than just setup.

> +{
> +	dev->addr_len		= IEEE802154_ADDR_LEN;
> +	dev->type		= ARPHRD_RAWIP;
> +
> +	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		= &netdev_ops;
> +	dev->destructor		= free_netdev;
> +}
> +
> +static struct device_type bt_type = {
> +	.name	= "bluetooth",
> +};
> +
> +static void set_addr(u8 *eui, u8 *addr, u8 addr_type)
> +{
> +	/* 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;
> +
> +	if (addr_type == BDADDR_LE_PUBLIC)
> +		eui[0] &= ~1;
> +	else
> +		eui[0] |= 1;

I would quote the RFC here to mention how the address is assigned.

> +}
> +
> +static void set_dev_addr(struct net_device *net, bdaddr_t *addr,
> +			u8 addr_type)
> +{
> +	net->addr_assign_type = NET_ADDR_PERM;
> +	set_addr(net->dev_addr, addr->b, addr_type);
> +	net->dev_addr[0] ^= 2;
> +}
> +
> +static void ifup(struct net_device *net)
> +{
> +	int status;
> +
> +	rtnl_lock();
> +	if ((status = dev_open(net)) < 0)

Assign it to status first and then check status. I know it is valid C code, but we normally don’t do this. Or if we did in the past, we are stepping away from these constructs.

Also you might want to call the variable err instead of status. I do not know where the status is coming from. At least in the Bluetooth subsystem we never used it like that. Is that some netdev thing?

> +		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 bt_6lowpan_add_conn(struct l2cap_conn *conn)
> +{
> +	struct net_device *net;
> +	struct lowpan_info *dev;
> +	struct lowpan_dev *entry;
> +	struct inet6_dev *idev;
> +	int status;
> +
> +	net = alloc_netdev(sizeof(struct lowpan_info), IFACE_NAME_TEMPLATE,
> +								setup);

This ones also need to properly aligned according to the network subsystem coding style.

> +	if (!net)
> +		return -ENOMEM;
> +
> +	dev = netdev_priv(net);
> +	dev->net = net;
> +
> +	memcpy(&dev->myaddr, &conn->hcon->src, sizeof(bdaddr_t));
> +	memcpy(&dev->addr, &conn->hcon->dst, sizeof(bdaddr_t));

Do we need to really store these addresses? It is rather useless to just store the address, we also need to store the address type.

> +
> +	set_dev_addr(net, &dev->myaddr, conn->hcon->src_type);
> +
> +	dev->conn = conn;
> +
> +	net->netdev_ops = &netdev_ops;
> +	SET_NETDEV_DEV(net, &conn->hcon->dev);
> +	SET_NETDEV_DEVTYPE(net, &bt_type);
> +
> +	status = register_netdev(net);
> +	if (status < 0) {

Same here. I would use err instead of status. Maybe ret in the cases where it makes more sense. Personally I prefer actually err.

> +		BT_INFO("register_netdev failed %d", status);
> +		free_netdev(net);

I think you better create an error label for this and use goto.

> +		return status;
> +	}
> +
> +	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 lowpan_dev), GFP_KERNEL);
> +	if (!entry)
> +		return -ENOMEM;

Isn’t this leaking the net_device.

> +
> +	entry->dev = net;
> +
> +	write_lock(&net_dev_list_lock);
> +	INIT_LIST_HEAD(&entry->list);
> +	list_add(&entry->list, &bt_6lowpan_devices);
> +	write_unlock(&net_dev_list_lock);
> +
> +	ifup(net);
> +
> +	return 0;
> +}
> +
> +static void delete_timeout(struct work_struct *work)
> +{
> +	struct lowpan_dev *entry = container_of(work, struct lowpan_dev,
> +						delete_timer.work);
> +
> +	unregister_netdev(entry->dev);
> +	kfree(entry);
> +}

I was wondering why we need this. You might need to explain it so I stop asking stupid questions. At least for me this is not obvious.

> +
> +int bt_6lowpan_del_conn(struct l2cap_conn *conn)
> +{
> +	struct lowpan_dev *entry, *tmp;
> +	int status = -ENOENT;
> +
> +	write_lock(&net_dev_list_lock);
> +
> +	list_for_each_entry_safe(entry, tmp, &bt_6lowpan_devices, list) {
> +		if (lowpan_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 device_event(struct notifier_block *unused,
> +				unsigned long event, void *ptr)
> +{
> +	struct net_device *dev = netdev_notifier_info_to_dev(ptr);
> +	struct lowpan_dev *entry, *tmp;
> +
> +	if (dev->type != ARPHRD_RAWIP)
> +		return NOTIFY_DONE;
> +
> +	switch (event) {
> +	case NETDEV_UNREGISTER:
> +		write_lock(&net_dev_list_lock);
> +		list_for_each_entry_safe(entry, tmp, &bt_6lowpan_devices,
> +					list) {
> +			if (entry->dev == dev) {
> +				list_del(&entry->list);
> +				kfree(entry);
> +				break;
> +			}
> +		}
> +		write_unlock(&net_dev_list_lock);
> +		break;
> +	}
> +
> +	return NOTIFY_DONE;
> +}

I think we have a bit of too much duplicated code that is all just deleting the device. Can we clean this out please.

> +
> +static struct notifier_block bt_6lowpan_dev_notifier = {
> +	.notifier_call = device_event,
> +};
> +
> +int bt_6lowpan_init(void)
> +{
> +	return register_netdevice_notifier(&bt_6lowpan_dev_notifier);
> +}
> +
> +void bt_6lowpan_cleanup(void)
> +{
> +	unregister_netdevice_notifier(&bt_6lowpan_dev_notifier);
> +}
> diff --git a/net/bluetooth/6lowpan.h b/net/bluetooth/6lowpan.h
> new file mode 100644
> index 0000000..680eac8
> --- /dev/null
> +++ b/net/bluetooth/6lowpan.h
> @@ -0,0 +1,26 @@
> +/*
> +   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 __6LOWPAN_H
> +#define __6LOWPAN_H
> +
> +#include <linux/skbuff.h>
> +#include <net/bluetooth/l2cap.h>
> +
> +int bt_6lowpan_recv(struct l2cap_conn *conn, struct sk_buff *skb);
> +int bt_6lowpan_add_conn(struct l2cap_conn *conn);
> +int bt_6lowpan_del_conn(struct l2cap_conn *conn);
> +int bt_6lowpan_init(void);
> +void bt_6lowpan_cleanup(void);
> +
> +#endif /* __6LOWPAN_H */
> diff --git a/net/bluetooth/Makefile b/net/bluetooth/Makefile
> index 6a791e7..80cb215 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 6lowpan.o
> 
> subdir-ccflags-y += -D__CHECK_ENDIAN__
> diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c
> index 0cef677..c47215f 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 "6lowpan.h"
> 
> bool disable_ertm;
> 
> @@ -6470,6 +6471,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:
> +		bt_6lowpan_recv(conn, skb);
> +		break;
> +
> 	default:
> 		l2cap_data_channel(conn, cid, skb);
> 		break;
> @@ -6507,6 +6512,11 @@ int l2cap_connect_ind(struct hci_dev *hdev, bdaddr_t *bdaddr)
> 	return exact ? lm1 : lm2;
> }
> 
> +static bool is_bt_6lowpan(void)
> +{
> +	return false;
> +}
> +
> void l2cap_connect_cfm(struct hci_conn *hcon, u8 status)
> {
> 	struct l2cap_conn *conn;
> @@ -6515,8 +6525,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_bt_6lowpan())
> +				bt_6lowpan_add_conn(conn);

So I am actually thinking that we might be a bit more aggressive with this code. At least this gives us a bit better testing exposure.

One idea might be to just create a hdev->dev_flags with HCI_6LOWPAN_ENABLED that you can set via debugfs (which defaults to off). And for every LE connection we have a hcon->flags with HCI_CONN_6LOWPAN that defaults to the value from hdev. And we just try to run 6loWPAN. Only if it fails, we delete the net_device.

Since this code is still in testing, we can be a bit more aggressive. Actually I like to see what happens if we have LE connections and use 6loWPAN against other LE devices that do not have it.

> +		}
> 	} else {
> 		l2cap_conn_del(hcon, bt_to_errno(status));
> 	}
> @@ -6537,6 +6551,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_bt_6lowpan())
> +		bt_6lowpan_del_conn(hcon->l2cap_data);

Is using l2cap_data here really a good idea. Don’t you have l2cap_conn or l2cap_chan available.

> +
> 	l2cap_conn_del(hcon, bt_to_errno(reason));
> }
> 
> @@ -6814,11 +6831,14 @@ int __init l2cap_init(void)
> 	l2cap_debugfs = debugfs_create_file("l2cap", 0444, bt_debugfs,
> 					    NULL, &l2cap_debugfs_fops);
> 
> +	bt_6lowpan_init();
> +
> 	return 0;
> }
> 
> void l2cap_exit(void)
> {
> +	bt_6lowpan_cleanup();
> 	debugfs_remove(l2cap_debugfs);
> 	l2cap_cleanup_sockets();
> }

Regards

Marcel


^ permalink raw reply

* Re: l2cap sockets not properly multiplexed on ARM
From: Alexander Holler @ 2013-10-30 11:46 UTC (permalink / raw)
  To: Tim Tisdall; +Cc: linux-bluetooth@vger.kernel.org
In-Reply-To: <5270EC62.6070705@ahsoftware.de>

Am 30.10.2013 12:24, schrieb Alexander Holler:
> Am 29.10.2013 21:44, schrieb Tim Tisdall:
>
>> L2CAP sockets
>> -------------
>>
>> socket(AF_BLUETOOTH, SOCK_SEQPACKET, BTPROTO_L2CAP)
>> bind(bdaddr, 0)  // bind to bluetooth address and PSM 0 (Python
>> doesn't support LE directly,
>>                   // but this is enough for binding to the right device
>
> That looks wrong. Try to bind to ATT_CID (4).
>

And don't forget to check the return code of bind (as well as of 
setsockopt and other calls).

Regards,

Alexander Holler


^ permalink raw reply

* Re: [PATCH] android: Disable format warnings in Android
From: Marcel Holtmann @ 2013-10-30 11:25 UTC (permalink / raw)
  To: Andrei Emeltchenko; +Cc: linux-bluetooth@vger.kernel.org development
In-Reply-To: <1383129043-30582-1-git-send-email-Andrei.Emeltchenko.news@gmail.com>

Hi Andrei,

> Android's bionic library has bug defining ssize_t (which is fixed in
> Android 4.3). This seems to be the most appropriate solution until
> we move to Android 4.3.
> ---
> android/Android.mk |    4 ++++
> 1 file changed, 4 insertions(+)
> 
> diff --git a/android/Android.mk b/android/Android.mk
> index fc1b276..db55d37 100644
> --- a/android/Android.mk
> +++ b/android/Android.mk
> @@ -12,6 +12,10 @@ BLUEZ_COMMON_CFLAGS := -DVERSION=\"$(BLUEZ_VERSION)\"
> # Disable warnings enabled by Android but not enabled in autotools build
> BLUEZ_COMMON_CFLAGS += -Wno-pointer-arith
> 
> +# Disable warning: format '%zd' expects argument of type 'signed size_t',
> +# but argument 4 has type 'ssize_t'
> +BLUEZ_COMMON_CFLAGS += -Wno-format

this disables now all format warnings. Even the useful ones. I am not in favor of doing this since it just leads to more error that otherwise the compiler would have caught.

Regards

Marcel


^ permalink raw reply

* Re: l2cap sockets not properly multiplexed on ARM
From: Alexander Holler @ 2013-10-30 11:24 UTC (permalink / raw)
  To: Tim Tisdall; +Cc: linux-bluetooth@vger.kernel.org
In-Reply-To: <D9B9EB3A112B8F489DFFA00A6D5C0FE20324078F@AD-BR-EX-2.adroot.flemingc.local>

Am 29.10.2013 21:44, schrieb Tim Tisdall:

> L2CAP sockets
> -------------
>
> socket(AF_BLUETOOTH, SOCK_SEQPACKET, BTPROTO_L2CAP)
> bind(bdaddr, 0)  // bind to bluetooth address and PSM 0 (Python doesn't support LE directly,
>                   // but this is enough for binding to the right device

That looks wrong. Try to bind to ATT_CID (4).

Regards,

Alexander Holler



^ permalink raw reply

* [PATCH] android: Fix sending scan mode property
From: Szymon Janc @ 2013-10-30 11:23 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Szymon Janc

This fix setting adapter discoverable from Android UI.

This type is enum on HAL side and we need to pass right number of
bytes. Otherwise will get exceptions from Java TLV handling code.

This patch makes assumption that size of enum is 4 bytes.
---
 android/adapter.c | 14 +++++++-------
 1 file changed, 7 insertions(+), 7 deletions(-)

diff --git a/android/adapter.c b/android/adapter.c
index 15b65e5..16db4dd 100644
--- a/android/adapter.c
+++ b/android/adapter.c
@@ -87,7 +87,7 @@ static void powered_changed(void)
 			HAL_EV_ADAPTER_STATE_CHANGED, sizeof(ev), &ev, -1);
 }
 
-static uint8_t settings2scan_mode(void)
+static uint32_t settings2scan_mode(void)
 {
 	bool connectable, discoverable;
 
@@ -106,9 +106,9 @@ static uint8_t settings2scan_mode(void)
 static void scan_mode_changed(void)
 {
 	struct hal_ev_adapter_props_changed *ev;
-	uint8_t *mode;
+	uint32_t mode;
 	int len;
-	len = sizeof(*ev) + sizeof(struct hal_property) + 1;
+	len = sizeof(*ev) + sizeof(struct hal_property) + sizeof(mode);
 
 	ev = g_malloc(len);
 
@@ -116,12 +116,12 @@ static void scan_mode_changed(void)
 	ev->status = HAL_STATUS_SUCCESS;
 
 	ev->props[0].type = HAL_PROP_ADAPTER_SCAN_MODE;
-	ev->props[0].len = 1;
+	ev->props[0].len = sizeof(mode);
 
-	mode = ev->props[0].val;
-	*mode = settings2scan_mode();
+	mode = settings2scan_mode();
+	memcpy(ev->props[0].val, &mode, sizeof(mode));
 
-	DBG("mode %u", *mode);
+	DBG("mode %u", mode);
 
 	ipc_send(notification_io, HAL_SERVICE_ID_BLUETOOTH,
 				HAL_EV_ADAPTER_PROPS_CHANGED, len, ev, -1);
-- 
1.8.4.1


^ permalink raw reply related

* [PATCH] android: Disable format warnings in Android
From: Andrei Emeltchenko @ 2013-10-30 10:30 UTC (permalink / raw)
  To: linux-bluetooth

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

Android's bionic library has bug defining ssize_t (which is fixed in
Android 4.3). This seems to be the most appropriate solution until
we move to Android 4.3.
---
 android/Android.mk |    4 ++++
 1 file changed, 4 insertions(+)

diff --git a/android/Android.mk b/android/Android.mk
index fc1b276..db55d37 100644
--- a/android/Android.mk
+++ b/android/Android.mk
@@ -12,6 +12,10 @@ BLUEZ_COMMON_CFLAGS := -DVERSION=\"$(BLUEZ_VERSION)\"
 # Disable warnings enabled by Android but not enabled in autotools build
 BLUEZ_COMMON_CFLAGS += -Wno-pointer-arith
 
+# Disable warning: format '%zd' expects argument of type 'signed size_t',
+# but argument 4 has type 'ssize_t'
+BLUEZ_COMMON_CFLAGS += -Wno-format
+
 #
 # Android BlueZ daemon (bluetoothd)
 #
-- 
1.7.10.4


^ permalink raw reply related

* Re: [PATCH v2 0/6] Initial HAL support for device discovery
From: Johan Hedberg @ 2013-10-30 10:13 UTC (permalink / raw)
  To: Jakub Tyszkowski; +Cc: linux-bluetooth
In-Reply-To: <1383127232-25147-1-git-send-email-jakub.tyszkowski@tieto.com>

Hi Jakub,

On Wed, Oct 30, 2013, Jakub Tyszkowski wrote:
> v2 Changes:
> 	* fixed coding style issues pointed by jhe and niko1
> 	* extracted property repacking code for reuse
> 
> Jakub Tyszkowski (6):
>   android/hal: Add support for start/cancel device discovery commands
>   android/hal: Add support for handling discovery state change event
>   android/hal: Extract bt property repacking code for further reuse
>   android/hal: Add device found event handler
>   android/hal: Add device state changed event handler
>   android: Add missing discovery state definitions to IPC header
> 
>  android/hal-bluetooth.c | 92 +++++++++++++++++++++++++++++++++++++++----------
>  android/hal-msg.h       |  3 ++
>  2 files changed, 76 insertions(+), 19 deletions(-)

All patches have been applied. Thanks.

Johan

^ permalink raw reply

* Re: [PATCH 1/2] android: Add common place for adding compiler flags in Android.mk
From: Johan Hedberg @ 2013-10-30 10:10 UTC (permalink / raw)
  To: Szymon Janc; +Cc: linux-bluetooth
In-Reply-To: <1383060218-25693-1-git-send-email-szymon.janc@tieto.com>

Hi Szymon,

On Tue, Oct 29, 2013, Szymon Janc wrote:
> This will contain CFLAGS common for all BlueZ code.
> ---
>  android/Android.mk | 9 +++++++--
>  1 file changed, 7 insertions(+), 2 deletions(-)

Both patches have been applied. Thanks.

Johan

^ permalink raw reply

* Re: [PATCH v2] android/client: Fix crash in tab completion
From: Johan Hedberg @ 2013-10-30 10:07 UTC (permalink / raw)
  To: Jerzy Kasenberg; +Cc: linux-bluetooth
In-Reply-To: <1383125472-6813-1-git-send-email-jerzy.kasenberg@tieto.com>

Hi Jerzy,

On Wed, Oct 30, 2013, Jerzy Kasenberg wrote:
> When user pressed tab on third or later argument when
> first two did not make sense tool crashed.
> Now method is checked for NULL before accessing help field.
> ---
> First version was doing to much (crash was gone but so was
> completion when completion function was not provided, just help
> string)
> 
>  android/client/tabcompletion.c |    2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)

Applied. Thanks.

Johan

^ permalink raw reply

* [PATCH v2 6/6] android: Add missing discovery state definitions to IPC header
From: Jakub Tyszkowski @ 2013-10-30 10:00 UTC (permalink / raw)
  To: linux-bluetooth
In-Reply-To: <1383127232-25147-1-git-send-email-jakub.tyszkowski@tieto.com>

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

diff --git a/android/hal-msg.h b/android/hal-msg.h
index 80b47d6..d2a0e2a 100644
--- a/android/hal-msg.h
+++ b/android/hal-msg.h
@@ -348,6 +348,9 @@ struct hal_ev_device_found {
 	struct hal_property props[0];
 } __attribute__((packed));
 
+#define HAL_DISCOVERY_STATE_STOPPED	0x00
+#define HAL_DISCOVERY_STATE_STARTED	0x01
+
 #define HAL_EV_DISCOVERY_STATE_CHANGED	0x85
 struct hal_ev_discovery_state_changed {
 	uint8_t state;
-- 
1.8.4.1


^ permalink raw reply related

* [PATCH v2 5/6] android/hal: Add device state changed event handler
From: Jakub Tyszkowski @ 2013-10-30 10:00 UTC (permalink / raw)
  To: linux-bluetooth
In-Reply-To: <1383127232-25147-1-git-send-email-jakub.tyszkowski@tieto.com>

This is used to report property change of already reported remote
device.

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

diff --git a/android/hal-bluetooth.c b/android/hal-bluetooth.c
index 3f9df96..2237063 100644
--- a/android/hal-bluetooth.c
+++ b/android/hal-bluetooth.c
@@ -145,6 +145,21 @@ static void handle_device_found(void *buf, uint16_t len)
 	bt_hal_cbacks->device_found_cb(ev->num_props, props);
 }
 
+static void handle_device_state_changed(void *buf, uint16_t len)
+{
+	struct hal_ev_remote_device_props *ev = buf;
+	bt_property_t props[ev->num_props];
+
+	if (!bt_hal_cbacks->remote_device_properties_cb)
+		return;
+
+	repack_properties(props, ev->props, ev->num_props, buf + len);
+
+	bt_hal_cbacks->remote_device_properties_cb(ev->status,
+						(bt_bdaddr_t *)ev->bdaddr,
+						ev->num_props, props);
+}
+
 /* will be called from notification thread context */
 void bt_notify_adapter(uint16_t opcode, void *buf, uint16_t len)
 {
@@ -164,6 +179,9 @@ void bt_notify_adapter(uint16_t opcode, void *buf, uint16_t len)
 	case HAL_EV_DEVICE_FOUND:
 		handle_device_found(buf, len);
 		break;
+	case HAL_EV_REMOTE_DEVICE_PROPS:
+		handle_device_state_changed(buf, len);
+		break;
 	case HAL_EV_BOND_STATE_CHANGED:
 		handle_bond_state_change(buf);
 		break;
-- 
1.8.4.1


^ permalink raw reply related

* [PATCH v2 4/6] android/hal: Add device found event handler
From: Jakub Tyszkowski @ 2013-10-30 10:00 UTC (permalink / raw)
  To: linux-bluetooth
In-Reply-To: <1383127232-25147-1-git-send-email-jakub.tyszkowski@tieto.com>

This is called when new remote device is found.

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

diff --git a/android/hal-bluetooth.c b/android/hal-bluetooth.c
index 06d85e3..3f9df96 100644
--- a/android/hal-bluetooth.c
+++ b/android/hal-bluetooth.c
@@ -132,6 +132,19 @@ static void handle_discovery_state_changed(void *buf)
 		bt_hal_cbacks->discovery_state_changed_cb(ev->state);
 }
 
+static void handle_device_found(void *buf, uint16_t len)
+{
+	struct hal_ev_device_found *ev = buf;
+	bt_property_t props[ev->num_props];
+
+	if (!bt_hal_cbacks->device_found_cb)
+		return;
+
+	repack_properties(props, ev->props, ev->num_props, buf + len);
+
+	bt_hal_cbacks->device_found_cb(ev->num_props, props);
+}
+
 /* will be called from notification thread context */
 void bt_notify_adapter(uint16_t opcode, void *buf, uint16_t len)
 {
@@ -148,6 +161,9 @@ void bt_notify_adapter(uint16_t opcode, void *buf, uint16_t len)
 	case HAL_EV_DISCOVERY_STATE_CHANGED:
 		handle_discovery_state_changed(buf);
 		break;
+	case HAL_EV_DEVICE_FOUND:
+		handle_device_found(buf, len);
+		break;
 	case HAL_EV_BOND_STATE_CHANGED:
 		handle_bond_state_change(buf);
 		break;
-- 
1.8.4.1


^ permalink raw reply related

* [PATCH v2 3/6] android/hal: Extract bt property repacking code for further reuse
From: Jakub Tyszkowski @ 2013-10-30 10:00 UTC (permalink / raw)
  To: linux-bluetooth
In-Reply-To: <1383127232-25147-1-git-send-email-jakub.tyszkowski@tieto.com>

This extracted part of code can be reused for repacking remote device
properties.

---
 android/hal-bluetooth.c | 39 ++++++++++++++++++++++-----------------
 1 file changed, 22 insertions(+), 17 deletions(-)

diff --git a/android/hal-bluetooth.c b/android/hal-bluetooth.c
index 18a5e1c..06d85e3 100644
--- a/android/hal-bluetooth.c
+++ b/android/hal-bluetooth.c
@@ -37,33 +37,38 @@ static void handle_adapter_state_changed(void *buf)
 		bt_hal_cbacks->adapter_state_changed_cb(ev->state);
 }
 
-static void handle_adapter_props_changed(void *buf, uint16_t len)
+static void repack_properties(bt_property_t *send_props,
+					struct hal_property *hal_prop,
+					uint8_t num_props,
+					void *buff_end)
 {
-	struct hal_ev_adapter_props_changed *ev = buf;
-	bt_property_t props[ev->num_props];
-	struct hal_property *hal_prop;
-	void *p;
-	int i;
+	void *p = hal_prop;
+	uint8_t i;
 
-	if (!bt_hal_cbacks->adapter_properties_cb)
-		return;
-
-	hal_prop = ev->props;
-	p = ev->props;
-
-	for (i = 0; i < ev->num_props; i++) {
-		if (p + sizeof(*hal_prop) + hal_prop->len > buf + len) {
+	for (i = 0; i < num_props; i++) {
+		if (p + sizeof(*hal_prop) + hal_prop->len > buff_end) {
 			error("invalid adapter properties event, aborting");
 			exit(EXIT_FAILURE);
 		}
 
-		props[i].type = hal_prop->type;
-		props[i].len = hal_prop->len;
-		props[i].val = hal_prop->val;
+		send_props[i].type = hal_prop->type;
+		send_props[i].len = hal_prop->len;
+		send_props[i].val = hal_prop->val;
 
 		p += sizeof(*hal_prop) + hal_prop->len;
 		hal_prop = p;
 	}
+}
+
+static void handle_adapter_props_changed(void *buf, uint16_t len)
+{
+	struct hal_ev_adapter_props_changed *ev = buf;
+	bt_property_t props[ev->num_props];
+
+	if (!bt_hal_cbacks->adapter_properties_cb)
+		return;
+
+	repack_properties(props, ev->props, ev->num_props, buf + len);
 
 	bt_hal_cbacks->adapter_properties_cb(ev->status, ev->num_props, props);
 }
-- 
1.8.4.1


^ permalink raw reply related

* [PATCH v2 2/6] android/hal: Add support for handling discovery state change event
From: Jakub Tyszkowski @ 2013-10-30 10:00 UTC (permalink / raw)
  To: linux-bluetooth
In-Reply-To: <1383127232-25147-1-git-send-email-jakub.tyszkowski@tieto.com>

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

diff --git a/android/hal-bluetooth.c b/android/hal-bluetooth.c
index 9d1c3f7..18a5e1c 100644
--- a/android/hal-bluetooth.c
+++ b/android/hal-bluetooth.c
@@ -119,6 +119,14 @@ static bool interface_ready(void)
 	return bt_hal_cbacks != NULL;
 }
 
+static void handle_discovery_state_changed(void *buf)
+{
+	struct hal_ev_discovery_state_changed *ev = buf;
+
+	if (bt_hal_cbacks->discovery_state_changed_cb)
+		bt_hal_cbacks->discovery_state_changed_cb(ev->state);
+}
+
 /* will be called from notification thread context */
 void bt_notify_adapter(uint16_t opcode, void *buf, uint16_t len)
 {
@@ -132,6 +140,9 @@ void bt_notify_adapter(uint16_t opcode, void *buf, uint16_t len)
 	case HAL_EV_ADAPTER_PROPS_CHANGED:
 		handle_adapter_props_changed(buf, len);
 		break;
+	case HAL_EV_DISCOVERY_STATE_CHANGED:
+		handle_discovery_state_changed(buf);
+		break;
 	case HAL_EV_BOND_STATE_CHANGED:
 		handle_bond_state_change(buf);
 		break;
-- 
1.8.4.1


^ permalink raw reply related

* [PATCH v2 1/6] android/hal: Add support for start/cancel device discovery commands
From: Jakub Tyszkowski @ 2013-10-30 10:00 UTC (permalink / raw)
  To: linux-bluetooth
In-Reply-To: <1383127232-25147-1-git-send-email-jakub.tyszkowski@tieto.com>

---
 android/hal-bluetooth.c | 8 ++++++--
 1 file changed, 6 insertions(+), 2 deletions(-)

diff --git a/android/hal-bluetooth.c b/android/hal-bluetooth.c
index ffaf8da..9d1c3f7 100644
--- a/android/hal-bluetooth.c
+++ b/android/hal-bluetooth.c
@@ -353,7 +353,9 @@ static int start_discovery(void)
 	if (!interface_ready())
 		return BT_STATUS_NOT_READY;
 
-	return BT_STATUS_UNSUPPORTED;
+	return hal_ipc_cmd(HAL_SERVICE_ID_BLUETOOTH,
+				HAL_OP_START_DISCOVERY, 0, NULL, 0,
+				NULL, NULL);
 }
 
 static int cancel_discovery(void)
@@ -363,7 +365,9 @@ static int cancel_discovery(void)
 	if (!interface_ready())
 		return BT_STATUS_NOT_READY;
 
-	return BT_STATUS_UNSUPPORTED;
+	return hal_ipc_cmd(HAL_SERVICE_ID_BLUETOOTH,
+				HAL_OP_CANCEL_DISCOVERY, 0, NULL, 0,
+				NULL, NULL);
 }
 
 static int create_bond(const bt_bdaddr_t *bd_addr)
-- 
1.8.4.1


^ permalink raw reply related

* [PATCH v2 0/6] Initial HAL support for device discovery
From: Jakub Tyszkowski @ 2013-10-30 10:00 UTC (permalink / raw)
  To: linux-bluetooth

v2 Changes:
	* fixed coding style issues pointed by jhe and niko1
	* extracted property repacking code for reuse

Jakub Tyszkowski (6):
  android/hal: Add support for start/cancel device discovery commands
  android/hal: Add support for handling discovery state change event
  android/hal: Extract bt property repacking code for further reuse
  android/hal: Add device found event handler
  android/hal: Add device state changed event handler
  android: Add missing discovery state definitions to IPC header

 android/hal-bluetooth.c | 92 +++++++++++++++++++++++++++++++++++++++----------
 android/hal-msg.h       |  3 ++
 2 files changed, 76 insertions(+), 19 deletions(-)

--
1.8.4.1


^ permalink raw reply

* Re: [PATCH] android/daemon: Solves warnings when compiling for Android
From: Andrei Emeltchenko @ 2013-10-30  9:35 UTC (permalink / raw)
  To: Marcel Holtmann; +Cc: linux-bluetooth@vger.kernel.org development
In-Reply-To: <7DDFBD1F-03E5-469A-9609-4F336890D521@holtmann.org>

Hi Marcel,

On Tue, Oct 29, 2013 at 02:34:43PM +0100, Marcel Holtmann wrote:
> Hi Andrei,
> 
> > When compiling for Android I get very annoying warnings shown below.
> > Though the issue is with android this really helps to clear Android
> > build screen.
> > 
> > external/bluetooth/bluez/android/main.c: In function 'cmd_watch_cb':
> > external/bluetooth/bluez/android/main.c:192:3: warning: format '%zd' expects
> >  argument of type 'signed size_t', but argument 2 has type 'ssize_t' [-Wformat]
> > external/bluetooth/bluez/android/main.c:197:3: warning: format '%zd' expects
> >  argument of type 'signed size_t', but argument 2 has type 'ssize_t' [-Wformat]
> 
> do we actually know piece inside Android is causing this stupid warning. Is this a bug in bionic and should be fixed.
> 

This is fixed with HEAD bionic but if I use bionic from HEAD or backport
patches I have compiling errors for projects which expects ssize_t to be
long int like 

bootable/iago/installer/imagewriter.c has:
print format "%ld" for ssize_t and warnings are treated as errors ...

So what would be the appropriate solution until we get next fixed Android
release for android-ia?

- Use -Wno-format
- Use int instead of ssize_t

Best regards 
Andrei Emeltchenko 

> > ---
> > Let me know if this solution is OK and I will change other parts as well.
> > 
> > android/main.c |    6 +++---
> > 1 file changed, 3 insertions(+), 3 deletions(-)
> > 
> > diff --git a/android/main.c b/android/main.c
> > index 6ff30a9..63c9eda 100644
> > --- a/android/main.c
> > +++ b/android/main.c
> > @@ -171,7 +171,7 @@ static gboolean cmd_watch_cb(GIOChannel *io, GIOCondition cond,
> > {
> > 	char buf[BLUEZ_HAL_MTU];
> > 	struct hal_hdr *msg = (void *) buf;
> > -	ssize_t ret;
> > +	int ret;
> > 	int fd;
> > 
> > 	if (cond & (G_IO_NVAL | G_IO_ERR | G_IO_HUP)) {
> > @@ -189,12 +189,12 @@ static gboolean cmd_watch_cb(GIOChannel *io, GIOCondition cond,
> > 	}
> > 
> > 	if (ret < (ssize_t) sizeof(*msg)) {
> 
> And why is this cast still ssize_t.
> 
> > -		error("HAL command too small, terminating (%zd)", ret);
> > +		error("HAL command too small, terminating (%d)", ret);
> > 		goto fail;
> > 	}
> > 
> > 	if (ret != (ssize_t) (sizeof(*msg) + msg->len)) {
> 
> And here as well.
> 
> > -		error("Malformed HAL command (%zd bytes), terminating", ret);
> > +		error("Malformed HAL command (%d bytes), terminating", ret);
> > 		goto fail;
> > 	}
> 
> Regards
> 
> Marcel
> 

^ permalink raw reply

* [PATCH v2] android/client: Fix crash in tab completion
From: Jerzy Kasenberg @ 2013-10-30  9:31 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Jerzy Kasenberg

When user pressed tab on third or later argument when
first two did not make sense tool crashed.
Now method is checked for NULL before accessing help field.
---
First version was doing to much (crash was gone but so was
completion when completion function was not provided, just help
string)

 android/client/tabcompletion.c |    2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/android/client/tabcompletion.c b/android/client/tabcompletion.c
index 69af609..cc1a5d3 100644
--- a/android/client/tabcompletion.c
+++ b/android/client/tabcompletion.c
@@ -332,7 +332,7 @@ static void param_completion(int argc, const split_arg_t *arg,
 	if (args.func != NULL) {
 		args.typed = argv[argc - 1];
 		args.help = method_help;
-		args.user_help = (void *) method->help;
+		args.user_help = method ? (void *) method->help : NULL;
 
 		tab_completion(&args);
 	}
-- 
1.7.9.5


^ permalink raw reply related

* Re: [PATCH v4] android: Add README file with instructions
From: Johan Hedberg @ 2013-10-30  9:16 UTC (permalink / raw)
  To: Szymon Janc; +Cc: linux-bluetooth
In-Reply-To: <1383123916-20721-1-git-send-email-szymon.janc@tieto.com>

Hi Szymon,

On Wed, Oct 30, 2013, Szymon Janc wrote:
> This file cotains help on how BlueZ for Android should be build, run
> and test. Some hints and examples on how BlueZ can be intergrated into
> Android are present as well.
> ---
> v4:
>  - workarounded issue with leftover conflicting markers
>   
>   for the record: it appears that double appearance of lines with
>   =======
>   (7 equality marks) confuses git that there is unresolved conflict.
> 
>  android/Makefile.am |  2 +-
>  android/README      | 90 +++++++++++++++++++++++++++++++++++++++++++++++++++++
>  2 files changed, 91 insertions(+), 1 deletion(-)
>  create mode 100644 android/README

Applied. Thanks.

Johan

^ permalink raw reply

* Re: [PATCH 2/2] android: Suppress compiler warnings not used in autotools build
From: Szymon Janc @ 2013-10-30  9:07 UTC (permalink / raw)
  To: Andrei Emeltchenko; +Cc: linux-bluetooth
In-Reply-To: <1664552.rzmdhg2vR5@uw000953>

On Wednesday 30 of October 2013 09:25:03 Szymon Janc wrote:
> Hi Andrei,
> 
> On Wednesday 30 of October 2013 10:19:15 Andrei Emeltchenko wrote:
> > Hi Szymon,
> > 
> > On Tue, Oct 29, 2013 at 04:23:38PM +0100, Szymon Janc wrote:
> > > Android build system is enabling some additional warnings that are not
> > > enabled when building with autotools. This avoids spurious warnings
> > > while building on Android.
> > > ---
> > >  android/Android.mk | 3 +++
> > >  1 file changed, 3 insertions(+)
> > > 
> > > diff --git a/android/Android.mk b/android/Android.mk
> > > index c88b27e..fc1b276 100644
> > > --- a/android/Android.mk
> > > +++ b/android/Android.mk
> > > @@ -9,6 +9,9 @@ pathmap_INCL += glib:external/bluetooth/glib
> > >  # Specify common compiler flags
> > >  BLUEZ_COMMON_CFLAGS := -DVERSION=\"$(BLUEZ_VERSION)\"
> > >  
> > > +# Disable warnings enabled by Android but not enabled in autotools build
> > > +BLUEZ_COMMON_CFLAGS += -Wno-pointer-arith
> > 
> > I wouldn't put this to BLUEZ_COMMON_CFLAGS, maybe only bluetoothd target
> > CFLAGS, the issue withing HAL might be easily fixed. We use void pointer
> > in math operations.
> 
> This is done on purpose as using void* to operation is simply convenient as
> there is no need for char* casting (and sizeof(void *) == 1 is documented GCC

sizeof(void) == 1   that is.

> feature). Further more I think it will be easier for developers if we can have
> same code guidelines and warnings while building on host and android for all
> components.
> 
> 



^ permalink raw reply

* [PATCH v4] android: Add README file with instructions
From: Szymon Janc @ 2013-10-30  9:05 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Szymon Janc

This file cotains help on how BlueZ for Android should be build, run
and test. Some hints and examples on how BlueZ can be intergrated into
Android are present as well.
---
v4:
 - workarounded issue with leftover conflicting markers
  
  for the record: it appears that double appearance of lines with
  =======
  (7 equality marks) confuses git that there is unresolved conflict.

 android/Makefile.am |  2 +-
 android/README      | 90 +++++++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 91 insertions(+), 1 deletion(-)
 create mode 100644 android/README

diff --git a/android/Makefile.am b/android/Makefile.am
index 22002be..5690e93 100644
--- a/android/Makefile.am
+++ b/android/Makefile.am
@@ -96,7 +96,7 @@ EXTRA_DIST += android/client/terminal.c \
 		android/client/history.h \
 		android/client/terminal.h
 
-EXTRA_DIST += android/hal-ipc-api.txt
+EXTRA_DIST += android/hal-ipc-api.txt android/README
 
 EXTRA_DIST += android/hardware/bluetooth.h \
 		android/hardware/bt_av.h \
diff --git a/android/README b/android/README
new file mode 100644
index 0000000..6c2c53f
--- /dev/null
+++ b/android/README
@@ -0,0 +1,90 @@
+BlueZ for Android
+*****************
+
+Since Android 4.2 there exists a well standardized HAL interface that the
+Bluetooth stack is expected to provide and which enables the easy replacement
+of the stack of choice on Android. Android BlueZ is intended as a drop-in
+replacement to Android provided Bluetooth stack.
+
+More details about BlueZ for Android architecture and components can be found
+in android/hal-apc-api.txt file.
+
+===============================
+Building and running on Android
+===============================
+
+Build requirements
+==================
+
+- GLib - Android 4.2 or later don't provide GLib and one must provide it in
+'external/bluetooth/glib' folder of Android tree. Sample Android GLib port
+is available at https://code.google.com/p/android-bluez.glib/
+
+- Bionic support - BlueZ requires signalfd and timerfd APIs to be provided
+by libc library. Currently only 'master' branch available at
+https://android.googlesource.com/platform/bionic provides all required
+functionality and running BlueZ on older branch requires backporting missing
+features. Sample Bionic for Android on Intel Architecture (Android-IA) with all
+required features backported is available at
+https://code.google.com/p/android-bluez.bionic/
+
+Runtime requirements
+====================
+
+BlueZ HAL library requires 'bluetoothd' service to be available on Android
+system. This can be done by defining service in init.rc file of targeted board:
+
+service bluetoothd /system/bin/logwrapper /system/bin/bluetoothd
+  class main
+  group bluetooth net_admin
+  disabled
+  oneshot
+
+It is required that bluetooth user could start and stop bluetoothd service by
+setting 'ctl.start' or 'ctl.stop' property. This can be achieved by
+whitelisting bluetooth user and bluetoothd service in init source code.
+
+Required Android init system modifications can be found at
+https://code.google.com/p/android-bluez.system-core/
+
+Downloading and building
+========================
+
+Building for Android requires full Android AOSP source tree. Sample Android-IA
+tree with all required components present is available at
+http://code.google.com/p/android-bluez/
+
+Downloading:
+repo init -u https://code.google.com/p/android-bluez.manifest/ -m topics/bluez
+repo sync
+
+Build for Intel ultrabook:
+'source build/envsetup.sh'
+'lunch core_mesa-eng'
+'make allimages -j8'
+
+After full build is done it is possible to rebuild only BlueZ:
+'cd external/bluetooth/bluez/android/'
+'mm' (or 'mm -B' to force rebuilding of all files)
+'adb sync' to update target device.
+
+=============================
+Building and running on Linux
+=============================
+
+It is possible to build and test BlueZ for Android daemon on Linux (eg. PC).
+Simply follow instructions available at README file in BlueZ top directory.
+Android daemon binary is located at android/bluetoothd. See next section on
+how to test Android daemon on Linux.
+
+============
+Testing tool
+============
+
+BT HAL test tools located in android/haltest is provided for HAL level testing
+of both Android daemon and HAL library. Start it and type 'adapter init' in
+prompt to initialize HAL library. On Android required bluetoothd service will
+be started automatically. On Linux it is required to start android/bluetoothd
+manually before init command timeout. To deinitialize HAL library and stop
+daemon type 'adapter cleanup'. Type 'help' for more information. Tab completion
+is also supported.
-- 
1.8.4.1


^ permalink raw reply related

* [RFC v2 7/7] Bluetooth: Manually enable or disable 6LoWPAN between devices
From: Jukka Rissanen @ 2013-10-30  9:01 UTC (permalink / raw)
  To: linux-bluetooth
In-Reply-To: <1383123661-15087-1-git-send-email-jukka.rissanen@linux.intel.com>

This is a temporary patch where user can manually enable or
disable BT 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/6lowpan
root@dev2# echo 00:11:22:33:44:55 > /sys/kernel/debug/bluetooth/hci0/6lowpan

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/6lowpan 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/6lowpan
Rebooting or unloading the bluetooth kernel module will also clear the
settings from the kernel.

Signed-off-by: Jukka Rissanen <jukka.rissanen@linux.intel.com>
---
 net/bluetooth/6lowpan.c    | 158 +++++++++++++++++++++++++++++++++++++++++++++
 net/bluetooth/6lowpan.h    |   2 +
 net/bluetooth/hci_core.c   |   4 ++
 net/bluetooth/l2cap_core.c |  12 ++--
 4 files changed, 169 insertions(+), 7 deletions(-)

diff --git a/net/bluetooth/6lowpan.c b/net/bluetooth/6lowpan.c
index 4ec3813..55f455a 100644
--- a/net/bluetooth/6lowpan.c
+++ b/net/bluetooth/6lowpan.c
@@ -26,6 +26,7 @@
  */
 
 #include <linux/version.h>
+#include <linux/debugfs.h>
 #include <linux/bitops.h>
 #include <linux/if_arp.h>
 #include <linux/netdevice.h>
@@ -1553,6 +1554,163 @@ static struct notifier_block bt_6lowpan_dev_notifier = {
 	.notifier_call = device_event,
 };
 
+static LIST_HEAD(user_enabled);
+DEFINE_RWLOCK(user_enabled_list_lock);
+
+struct lowpan_enabled {
+	__u8 dev_name[HCI_MAX_NAME_LENGTH];
+	bdaddr_t addr;
+	struct list_head list;
+};
+
+bool bt_6lowpan_is_enabled(struct hci_dev *hdev, bdaddr_t *dst)
+{
+	struct lowpan_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 lowpan_dev *entry, *tmp;
+		struct lowpan_info *info;
+
+		write_lock(&net_dev_list_lock);
+		list_for_each_entry_safe(entry, tmp, &bt_6lowpan_devices,
+								list) {
+			info = lowpan_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 debugfs_show(struct seq_file *f, void *p)
+{
+	struct lowpan_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 debugfs_open(struct inode *inode, struct file *file)
+{
+	return single_open(file, debugfs_show, inode->i_private);
+}
+
+static ssize_t 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;
+	struct lowpan_enabled *entry = NULL, *tmp;
+	bdaddr_t bdaddr;
+
+        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)
+		return ret;
+
+	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)
+		return ret;
+
+	if (delete_mode) {
+		write_lock(&user_enabled_list_lock);
+		list_del(&entry->list);
+		kfree(entry);
+		write_unlock(&user_enabled_list_lock);
+	} else {
+		struct hci_dev *hdev = fp->f_inode->i_private;
+
+		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		= debugfs_open,
+	.read		= seq_read,
+	.write		= writer,
+	.llseek		= seq_lseek,
+	.release	= single_release,
+};
+
+static struct dentry *bt_6lowpan_debugfs;
+
+void bt_6lowpan_add_debugfs(struct hci_dev *hdev)
+{
+	if (hdev->debugfs)
+		bt_6lowpan_debugfs = debugfs_create_file("6lowpan", 0644,
+			hdev->debugfs, hdev, &ble_6lowpan_debugfs_fops);
+}
+
 int bt_6lowpan_init(void)
 {
 	return register_netdevice_notifier(&bt_6lowpan_dev_notifier);
diff --git a/net/bluetooth/6lowpan.h b/net/bluetooth/6lowpan.h
index 680eac8..549fc51 100644
--- a/net/bluetooth/6lowpan.h
+++ b/net/bluetooth/6lowpan.h
@@ -22,5 +22,7 @@ int bt_6lowpan_add_conn(struct l2cap_conn *conn);
 int bt_6lowpan_del_conn(struct l2cap_conn *conn);
 int bt_6lowpan_init(void);
 void bt_6lowpan_cleanup(void);
+bool bt_6lowpan_is_enabled(struct hci_dev *hdev, bdaddr_t *dst);
+void bt_6lowpan_add_debugfs(struct hci_dev *hdev);
 
 #endif /* __6LOWPAN_H */
diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c
index 6ccc4eb..444b4bc 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 "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);
 	}
 
+	bt_6lowpan_add_debugfs(hdev);
+
 	return 0;
 }
 
diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c
index c47215f..d02241e 100644
--- a/net/bluetooth/l2cap_core.c
+++ b/net/bluetooth/l2cap_core.c
@@ -6512,11 +6512,6 @@ int l2cap_connect_ind(struct hci_dev *hdev, bdaddr_t *bdaddr)
 	return exact ? lm1 : lm2;
 }
 
-static bool is_bt_6lowpan(void)
-{
-	return false;
-}
-
 void l2cap_connect_cfm(struct hci_conn *hcon, u8 status)
 {
 	struct l2cap_conn *conn;
@@ -6528,7 +6523,9 @@ void l2cap_connect_cfm(struct hci_conn *hcon, u8 status)
 		if (conn) {
 			l2cap_conn_ready(conn);
 
-			if (hcon->type == LE_LINK && is_bt_6lowpan())
+			if (hcon->type == LE_LINK &&
+					bt_6lowpan_is_enabled(hcon->hdev,
+								&hcon->dst))
 				bt_6lowpan_add_conn(conn);
 		}
 	} else {
@@ -6551,7 +6548,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_bt_6lowpan())
+	if (hcon->type == LE_LINK && bt_6lowpan_is_enabled(hcon->hdev,
+							&hcon->dst))
 		bt_6lowpan_del_conn(hcon->l2cap_data);
 
 	l2cap_conn_del(hcon, bt_to_errno(reason));
-- 
1.7.11.7


^ permalink raw reply related

* [RFC v2 6/7] Bluetooth: Set route to peer for 6LoWPAN
From: Jukka Rissanen @ 2013-10-30  9:01 UTC (permalink / raw)
  To: linux-bluetooth
In-Reply-To: <1383123661-15087-1-git-send-email-jukka.rissanen@linux.intel.com>

Signed-off-by: Jukka Rissanen <jukka.rissanen@linux.intel.com>
---
 net/bluetooth/6lowpan.c | 37 +++++++++++++++++++++++++++++++++++++
 1 file changed, 37 insertions(+)

diff --git a/net/bluetooth/6lowpan.c b/net/bluetooth/6lowpan.c
index 1cba7fd..4ec3813 100644
--- a/net/bluetooth/6lowpan.c
+++ b/net/bluetooth/6lowpan.c
@@ -1372,6 +1372,39 @@ static void set_dev_addr(struct net_device *net, bdaddr_t *addr,
 	net->dev_addr[0] ^= 2;
 }
 
+static int add_peer_route(struct lowpan_info *dev, struct net_device *net,
+			bdaddr_t *addr, u8 addr_type)
+{
+	struct in6_addr peer;
+	struct fib6_config cfg = {
+		.fc_table	= RT6_TABLE_MAIN,
+		.fc_metric	= IP6_RT_PRIO_ADDRCONF,
+		.fc_ifindex	= net->ifindex,
+		.fc_dst_len	= 128,
+		.fc_flags	= RTF_ADDRCONF | RTF_UP |
+					RTF_PREF(ICMPV6_ROUTER_PREF_MEDIUM),
+		.fc_nlinfo.portid = 0,
+		.fc_nlinfo.nlh = NULL,
+		.fc_nlinfo.nl_net = dev_net(net),
+	};
+
+	memset(&peer, 0, sizeof(struct in6_addr));
+
+	/* RFC 2464 ch. 5 */
+	peer.s6_addr[0] = 0xFE;
+	peer.s6_addr[1] = 0x80;
+	set_addr((u8 *)&peer.s6_addr + 8, addr->b, addr_type);
+
+	memcpy(&dev->ieee802154_addr, (u8 *)&peer.s6_addr + 8,
+						IEEE802154_ADDR_LEN);
+
+	BT_DBG("peer address %pI6c", (u8 *)&peer.s6_addr);
+
+	cfg.fc_dst = dev->peer = peer;
+
+	return ip6_route_add(&cfg);
+}
+
 static void ifup(struct net_device *net)
 {
 	int status;
@@ -1448,6 +1481,10 @@ int bt_6lowpan_add_conn(struct l2cap_conn *conn)
 
 	ifup(net);
 
+	if ((status = add_peer_route(dev, net, &dev->addr,
+						conn->hcon->dst_type)) < 0)
+		BT_INFO("Setting route failed %d", status);
+
 	return 0;
 }
 
-- 
1.7.11.7


^ 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