Linux bluetooth development
 help / color / mirror / Atom feed
* [RFC v3 3/8] Bluetooth: Initial skeleton code for BT 6LoWPAN
From: Jukka Rissanen @ 2013-11-08 15:23 UTC (permalink / raw)
  To: linux-bluetooth
In-Reply-To: <1383924195-7936-1-git-send-email-jukka.rissanen@linux.intel.com>

Signed-off-by: Jukka Rissanen <jukka.rissanen@linux.intel.com>
---
 include/net/bluetooth/l2cap.h |   1 +
 net/bluetooth/6lowpan.c       | 546 ++++++++++++++++++++++++++++++++++++++++++
 net/bluetooth/6lowpan.h       |  26 ++
 net/bluetooth/Makefile        |   2 +-
 net/bluetooth/l2cap_core.c    |  22 +-
 5 files changed, 595 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..2982a4e
--- /dev/null
+++ b/net/bluetooth/6lowpan.c
@@ -0,0 +1,546 @@
+/*
+   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 "bt%d"
+#define EUI64_ADDR_LEN 8
+
+struct skb_cb {
+	struct in6_addr addr;
+	struct l2cap_conn *conn;
+};
+#define lowpan_cb(skb) ((struct skb_cb *)((skb)->cb))
+
+/*
+ * 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 network (=hciX device).
+ * The list contains struct lowpan_dev elements.
+ */
+static LIST_HEAD(bt_6lowpan_devices);
+static DEFINE_RWLOCK(devices_lock);
+
+struct lowpan_dev {
+	struct net_device *dev;
+	struct work_struct delete_netdev;
+	struct list_head list;
+};
+
+struct peer {
+	struct list_head list;
+	struct l2cap_conn *conn;
+
+	/* peer addresses in various formats */
+	unsigned char eui64_addr[EUI64_ADDR_LEN];
+	struct in6_addr peer_addr;
+};
+
+struct lowpan_info {
+	struct net_device *net;
+	struct list_head peers;
+	int peer_count;
+};
+
+static inline struct lowpan_info *lowpan_info(const struct net_device *dev)
+{
+	return netdev_priv(dev);
+}
+
+static inline void peer_add(struct lowpan_info *info, struct peer *peer)
+{
+	list_add(&peer->list, &info->peers);
+	info->peer_count++;
+}
+
+static inline void peer_del(struct lowpan_info *info, struct peer *peer)
+{
+	list_del(&peer->list);
+	info->peer_count--;
+	if (info->peer_count < 0) {
+		BT_ERR("peer count underflow");
+		info->peer_count = 0;
+	}
+}
+
+static inline struct peer *peer_lookup_ba(struct lowpan_info *info,
+						__u8 type, bdaddr_t *ba)
+{
+	struct peer *peer, *tmp;
+
+	BT_DBG("peers %d addr %pMR type %d", info->peer_count, ba, type);
+
+	list_for_each_entry_safe(peer, tmp, &info->peers, list) {
+		BT_DBG("addr %pMR type %d",
+			&peer->conn->hcon->dst, peer->conn->hcon->dst_type);
+
+		if (!bacmp(&peer->conn->hcon->dst, ba))
+			return peer;
+	}
+
+	return NULL;
+}
+
+static inline struct peer *peer_lookup_conn(struct lowpan_info *info,
+						struct l2cap_conn *conn)
+{
+	struct peer *peer, *tmp;
+
+	list_for_each_entry_safe(peer, tmp, &info->peers, list) {
+		if (peer->conn == conn)
+			return peer;
+	}
+
+	return NULL;
+}
+
+static struct peer *lookup_peer(struct l2cap_conn *conn,
+				struct lowpan_info **dev)
+{
+	struct lowpan_dev *entry, *tmp;
+	struct peer *peer = NULL;
+
+	write_lock(&devices_lock);
+
+	list_for_each_entry_safe(entry, tmp, &bt_6lowpan_devices, list) {
+		struct lowpan_info *info = lowpan_info(entry->dev);
+
+		if (dev)
+			*dev = info;
+
+		peer = peer_lookup_conn(info, conn);
+		if (peer)
+			break;
+	}
+
+	write_unlock(&devices_lock);
+
+	return peer;
+}
+
+/* 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_info *info = NULL;
+	struct peer *peer;
+	int err = -ENOENT;
+
+	peer = lookup_peer(conn, &info);
+	if (!peer)
+		return -ENOENT;
+
+	if (info && info->net) {
+		err = recv_pkt(skb, info->net, conn);
+		BT_DBG("recv pkt %d", err);
+	}
+
+	return err;
+}
+
+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)
+{
+	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 int send_mcast_pkt(struct sk_buff *skb, struct net_device *dev)
+{
+	struct sk_buff *local_skb;
+	struct lowpan_dev *entry, *tmp;
+	int err = 0;
+
+	write_lock(&devices_lock);
+
+	list_for_each_entry_safe(entry, tmp, &bt_6lowpan_devices, list) {
+		struct peer *pentry, *ptmp;
+		struct lowpan_info *info;
+
+		if (entry->dev != dev)
+			continue;
+
+		info = lowpan_info(entry->dev);
+
+		list_for_each_entry_safe(pentry, ptmp, &info->peers, list) {
+			local_skb = skb_clone(skb, GFP_ATOMIC);
+
+			err = send_pkt(pentry->conn, dev->dev_addr,
+					pentry->eui64_addr,
+					local_skb, dev);
+
+			kfree_skb(local_skb);
+		}
+	}
+
+	write_unlock(&devices_lock);
+
+	return err;
+}
+
+static netdev_tx_t xmit(struct sk_buff *skb, struct net_device *dev)
+{
+	int err = -ENOENT;
+	unsigned char *eui64_addr;
+	struct lowpan_info *info;
+	struct peer *peer;
+	bdaddr_t addr;
+	u8 addr_type;
+
+	if (ipv6_addr_is_multicast(&lowpan_cb(skb)->addr)) {
+		/*
+		 * We need to send the packet to every device
+		 * behind this interface.
+		 */
+		err = send_mcast_pkt(skb, dev);
+	} else {
+		get_dest_bdaddr(&lowpan_cb(skb)->addr, &addr, &addr_type);
+		eui64_addr = lowpan_cb(skb)->addr.s6_addr + 8;
+		info = lowpan_info(dev);
+
+		write_lock(&devices_lock);
+		peer = peer_lookup_ba(info, addr_type, &addr);
+		write_unlock(&devices_lock);
+
+		BT_DBG("xmit from %s to %pMR (%pI6c), peer %p", dev->name,
+			&addr, &lowpan_cb(skb)->addr, peer);
+
+		if (peer && peer->conn)
+			err = send_pkt(peer->conn,
+					dev->dev_addr,
+					eui64_addr,
+					skb,
+					dev);
+	}
+	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 netdev_setup(struct net_device *dev)
+{
+	dev->addr_len		= EUI64_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;
+
+	/*
+	 * Universal/local bit set, RFC 4291
+	 */
+	if (addr_type == BDADDR_LE_PUBLIC)
+		eui[0] |= 1;
+	else
+		eui[0] &= ~1;
+}
+
+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 err;
+
+	rtnl_lock();
+	err = dev_open(net);
+	if (err < 0)
+		BT_INFO("iface %s cannot be opened (%d)", net->name, err);
+	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 lowpan_info *dev = NULL;
+	struct peer *peer = NULL;
+	struct net_device *net;
+	struct lowpan_dev *entry;
+	struct inet6_dev *idev;
+	int err;
+
+	peer = lookup_peer(conn, &dev);
+	if (peer)
+		return -EEXIST;
+
+	/*
+	 * If net device exists already, just add route.
+	 */
+	if (dev && !peer)
+		goto add_peer;
+
+	net = alloc_netdev(sizeof(struct lowpan_info), IFACE_NAME_TEMPLATE,
+			netdev_setup);
+	if (!net)
+		return -ENOMEM;
+
+	dev = netdev_priv(net);
+	dev->net = net;
+	INIT_LIST_HEAD(&dev->peers);
+
+	set_dev_addr(net, &conn->hcon->src, conn->hcon->src_type);
+
+	net->netdev_ops = &netdev_ops;
+	SET_NETDEV_DEV(net, &conn->hcon->dev);
+	SET_NETDEV_DEVTYPE(net, &bt_type);
+
+	err = register_netdev(net);
+	if (err < 0) {
+		BT_INFO("register_netdev failed %d", err);
+		free_netdev(net);
+		goto out;
+	}
+
+	BT_DBG("ifindex %d peer bdaddr %pMR my addr %pMR",
+		net->ifindex, &conn->hcon->dst, &conn->hcon->src);
+	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) {
+		unregister_netdev(net);
+		return -ENOMEM;
+	}
+
+	entry->dev = net;
+
+	write_lock(&devices_lock);
+	INIT_LIST_HEAD(&entry->list);
+	list_add(&entry->list, &bt_6lowpan_devices);
+	write_unlock(&devices_lock);
+
+	ifup(net);
+
+add_peer:
+	peer = kzalloc(sizeof(struct peer), GFP_KERNEL);
+	if (!peer)
+		return -ENOMEM;
+
+	peer->conn = conn;
+
+	write_lock(&devices_lock);
+	INIT_LIST_HEAD(&peer->list);
+	peer_add(dev, peer);
+	write_unlock(&devices_lock);
+
+out:
+	return err;
+}
+
+static void delete_netdev(struct work_struct *work)
+{
+	struct lowpan_dev *entry = container_of(work, struct lowpan_dev,
+						delete_netdev);
+
+	unregister_netdev(entry->dev);
+
+	/* The entry pointer is deleted in device_event() */
+}
+
+int bt_6lowpan_del_conn(struct l2cap_conn *conn)
+{
+	struct lowpan_dev *entry, *tmp;
+	struct lowpan_info *info = NULL;
+	struct peer *peer;
+	int err = -ENOENT;
+
+	write_lock(&devices_lock);
+
+	list_for_each_entry_safe(entry, tmp, &bt_6lowpan_devices, list) {
+		info = lowpan_info(entry->dev);
+		peer = peer_lookup_conn(info, conn);
+		if (peer) {
+			peer_del(info, peer);
+			err = 0;
+			break;
+		}
+	}
+
+	write_unlock(&devices_lock);
+
+	if (!err && info && info->peer_count == 0) {
+		/*
+		 * This function is called with hci dev lock held which means
+		 * that we must delete the netdevice in worker thread.
+		 */
+		INIT_WORK(&entry->delete_netdev, delete_netdev);
+		schedule_work(&entry->delete_netdev);
+	}
+
+	return err;
+}
+
+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(&devices_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(&devices_lock);
+		break;
+	}
+
+	return NOTIFY_DONE;
+}
+
+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 4af3821..155485f 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;
 
@@ -6473,6 +6474,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;
@@ -6510,6 +6515,11 @@ int l2cap_connect_ind(struct hci_dev *hdev, bdaddr_t *bdaddr)
 	return exact ? lm1 : lm2;
 }
 
+static bool is_bt_6lowpan(struct hci_conn *hcon)
+{
+	return false;
+}
+
 void l2cap_connect_cfm(struct hci_conn *hcon, u8 status)
 {
 	struct l2cap_conn *conn;
@@ -6518,8 +6528,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 (is_bt_6lowpan(hcon))
+				bt_6lowpan_add_conn(conn);
+		}
 	} else {
 		l2cap_conn_del(hcon, bt_to_errno(status));
 	}
@@ -6540,6 +6554,9 @@ void l2cap_disconn_cfm(struct hci_conn *hcon, u8 reason)
 {
 	BT_DBG("hcon %p reason %d", hcon, reason);
 
+	if (is_bt_6lowpan(hcon))
+		bt_6lowpan_del_conn(hcon->l2cap_data);
+
 	l2cap_conn_del(hcon, bt_to_errno(reason));
 }
 
@@ -6817,11 +6834,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();
 }
-- 
1.8.3.1


^ permalink raw reply related

* [RFC v3 2/8] ipv6: Add checks for RAWIP ARP type
From: Jukka Rissanen @ 2013-11-08 15:23 UTC (permalink / raw)
  To: linux-bluetooth
In-Reply-To: <1383924195-7936-1-git-send-email-jukka.rissanen@linux.intel.com>

Signed-off-by: Jukka Rissanen <jukka.rissanen@linux.intel.com>
---
 net/ipv6/addrconf.c | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c
index d6ff126..cde1061 100644
--- a/net/ipv6/addrconf.c
+++ b/net/ipv6/addrconf.c
@@ -1797,6 +1797,7 @@ static int ipv6_generate_eui64(u8 *eui, struct net_device *dev)
 		return addrconf_ifid_sit(eui, dev);
 	case ARPHRD_IPGRE:
 		return addrconf_ifid_gre(eui, dev);
+	case ARPHRD_RAWIP:
 	case ARPHRD_IEEE802154:
 		return addrconf_ifid_eui64(eui, dev);
 	case ARPHRD_IEEE1394:
@@ -2681,7 +2682,8 @@ static void addrconf_dev_config(struct net_device *dev)
 	    (dev->type != ARPHRD_INFINIBAND) &&
 	    (dev->type != ARPHRD_IEEE802154) &&
 	    (dev->type != ARPHRD_IEEE1394) &&
-	    (dev->type != ARPHRD_TUNNEL6)) {
+	    (dev->type != ARPHRD_TUNNEL6) &&
+	    (dev->type != ARPHRD_RAWIP)) {
 		/* Alas, we support only Ethernet autoconfiguration. */
 		return;
 	}
-- 
1.8.3.1


^ permalink raw reply related

* [RFC v3 1/8] net: if_arp: add ARPHRD_RAWIP type
From: Jukka Rissanen @ 2013-11-08 15:23 UTC (permalink / raw)
  To: linux-bluetooth
In-Reply-To: <1383924195-7936-1-git-send-email-jukka.rissanen@linux.intel.com>

This is used when there is no L2 header before IP header.
Example of this is Bluetooth 6LoWPAN network.

The RAWIP header type value is already used in some Android kernels
so same value is used here in order not to break userspace.

Signed-off-by: Jukka Rissanen <jukka.rissanen@linux.intel.com>
---
 include/uapi/linux/if_arp.h | 1 +
 1 file changed, 1 insertion(+)

diff --git a/include/uapi/linux/if_arp.h b/include/uapi/linux/if_arp.h
index d7fea34..06fc69f 100644
--- a/include/uapi/linux/if_arp.h
+++ b/include/uapi/linux/if_arp.h
@@ -59,6 +59,7 @@
 #define ARPHRD_LAPB	516		/* LAPB				*/
 #define ARPHRD_DDCMP    517		/* Digital's DDCMP protocol     */
 #define ARPHRD_RAWHDLC	518		/* Raw HDLC			*/
+#define ARPHRD_RAWIP	530	        /* Raw IP                       */
 
 #define ARPHRD_TUNNEL	768		/* IPIP tunnel			*/
 #define ARPHRD_TUNNEL6	769		/* IP6IP6 tunnel       		*/
-- 
1.8.3.1


^ permalink raw reply related

* [RFC v3 0/8] Bluetooth LE 6LoWPAN
From: Jukka Rissanen @ 2013-11-08 15:23 UTC (permalink / raw)
  To: linux-bluetooth

Hi,

this is 6LoWPAN code for BT LE as described in
http://tools.ietf.org/html/draft-ietf-6lowpan-btle-12

v3:
- misc changes according to Marcel's comments
- supports multiple connections / interface
- removed unused fragmentation code
- setup 6lowpan connection automatically if enabled via debugfs

The automatic 6lowpan enabling is done by setting

echo 1 > /sys/kernel/debug/bluetooth/hci0/6lowpan

before devices are connected.


v2:
- Change ARPHRD_IEEE802154 to ARPHRD_RAWIP. The generic code
  in patches 1 and 2 is also sent to netdev mailing list.
- Sending route exporting patch 5 to netdev ml
- Check private/public BT address and toggle universal/local bit
  accordingly in patch 3.
- The virtual interface template name is now shorter (bt%d)
- Various function name renames
- devtype of the interface set to "bluetooth"


v1:
- initial release


TODO:
- Discovery of 6LoWPAN service needs be automatic.
- Refactor compression and uncompression code after these are fixed
  in net/ieee802154/6lowpan.c. Bluetooth 6LoWPAN should be able to share
  that part of the code.

Known issues:
- route to peer is not removed when connection is dropped
- no UUID handling yet


Cheers,
Jukka


Jukka Rissanen (8):
  net: if_arp: add ARPHRD_RAWIP type
  ipv6: Add checks for RAWIP ARP type
  Bluetooth: Initial skeleton code for BT 6LoWPAN
  Bluetooth: Enable 6LoWPAN support for BT LE devices
  Bluetooth: Enable 6LoWPAN if device supports it
  route: Exporting ip6_route_add() so that Bluetooth 6LoWPAN can use it
  Bluetooth: Set route to peer for 6LoWPAN
  Bluetooth: Manually enable or disable 6LoWPAN between devices

 include/net/bluetooth/hci.h      |    1 +
 include/net/bluetooth/hci_core.h |    1 +
 include/net/bluetooth/l2cap.h    |    1 +
 include/uapi/linux/if_arp.h      |    1 +
 net/bluetooth/6lowpan.c          | 1723 ++++++++++++++++++++++++++++++++++++++
 net/bluetooth/6lowpan.h          |   27 +
 net/bluetooth/Makefile           |    2 +-
 net/bluetooth/hci_core.c         |    4 +
 net/bluetooth/hci_event.c        |    3 +
 net/bluetooth/l2cap_core.c       |   25 +-
 net/ipv6/addrconf.c              |    4 +-
 net/ipv6/route.c                 |    1 +
 12 files changed, 1790 insertions(+), 3 deletions(-)
 create mode 100644 net/bluetooth/6lowpan.c
 create mode 100644 net/bluetooth/6lowpan.h

-- 
1.8.3.1


^ permalink raw reply

* [RFC] android/debug: Move debug functions to hal-utils.c
From: Andrei Emeltchenko @ 2013-11-08 15:05 UTC (permalink / raw)
  To: linux-bluetooth

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

Debug functions will be used by HALs and haltest.
---
 android/Android.mk        |    2 -
 android/Makefile.am       |    3 -
 android/client/if-av.c    |    1 +
 android/client/if-bt.c    |    1 +
 android/client/if-hf.c    |    1 +
 android/client/if-hh.c    |    1 +
 android/client/if-main.h  |    2 -
 android/client/if-pan.c   |    1 +
 android/client/if-sock.c  |    1 +
 android/client/textconv.c |  300 ---------------------------------------------
 android/client/textconv.h |  120 ------------------
 android/hal-bluetooth.c   |    3 +-
 android/hal-utils.c       |  269 ++++++++++++++++++++++++++++++++++++++++
 android/hal-utils.h       |  103 ++++++++++++++++
 14 files changed, 379 insertions(+), 429 deletions(-)
 delete mode 100644 android/client/textconv.c
 delete mode 100644 android/client/textconv.h

diff --git a/android/Android.mk b/android/Android.mk
index 0bc0e82..53c766b 100644
--- a/android/Android.mk
+++ b/android/Android.mk
@@ -87,7 +87,6 @@ LOCAL_SRC_FILES := \
 	hal-hidhost.c \
 	hal-pan.c \
 	hal-a2dp.c \
-	client/textconv.c \
 	hal-utils.c \
 
 LOCAL_C_INCLUDES += \
@@ -118,7 +117,6 @@ LOCAL_SRC_FILES := \
 	client/pollhandler.c \
 	client/terminal.c \
 	client/history.c \
-	client/textconv.c \
 	client/tabcompletion.c \
 	client/if-av.c \
 	client/if-bt.c \
diff --git a/android/Makefile.am b/android/Makefile.am
index debe7c1..e81d1a5 100644
--- a/android/Makefile.am
+++ b/android/Makefile.am
@@ -59,7 +59,6 @@ android_haltest_SOURCES = android/client/haltest.c \
 				android/client/pollhandler.c \
 				android/client/terminal.c \
 				android/client/history.c \
-				android/client/textconv.c \
 				android/client/tabcompletion.c \
 				android/client/if-av.c \
 				android/client/if-bt.c \
@@ -102,9 +101,7 @@ EXTRA_DIST += android/client/terminal.c \
 		android/client/if-hh.c \
 		android/client/if-pan.c \
 		android/client/if-sock.c \
-		android/client/textconv.c \
 		android/client/tabcompletion.c \
-		android/client/textconv.h \
 		android/client/if-main.h \
 		android/client/pollhandler.h \
 		android/client/history.h \
diff --git a/android/client/if-av.c b/android/client/if-av.c
index 3f133eb..0470e0d 100644
--- a/android/client/if-av.c
+++ b/android/client/if-av.c
@@ -16,6 +16,7 @@
  */
 
 #include "if-main.h"
+#include "../hal-utils.h"
 
 const btav_interface_t *if_av = NULL;
 
diff --git a/android/client/if-bt.c b/android/client/if-bt.c
index 10ae125..0cd43db 100644
--- a/android/client/if-bt.c
+++ b/android/client/if-bt.c
@@ -17,6 +17,7 @@
 
 #include "if-main.h"
 #include "terminal.h"
+#include "../hal-utils.h"
 
 const bt_interface_t *if_bluetooth;
 
diff --git a/android/client/if-hf.c b/android/client/if-hf.c
index c23fb13..d0e7a66 100644
--- a/android/client/if-hf.c
+++ b/android/client/if-hf.c
@@ -16,6 +16,7 @@
  */
 
 #include "if-main.h"
+#include "../hal-utils.h"
 
 const bthf_interface_t *if_hf = NULL;
 
diff --git a/android/client/if-hh.c b/android/client/if-hh.c
index 005b13a..b8ebc8e 100644
--- a/android/client/if-hh.c
+++ b/android/client/if-hh.c
@@ -23,6 +23,7 @@
 
 #include "if-main.h"
 #include "pollhandler.h"
+#include "../hal-utils.h"
 
 const bthh_interface_t *if_hh = NULL;
 
diff --git a/android/client/if-main.h b/android/client/if-main.h
index dea7237..a83f48b 100644
--- a/android/client/if-main.h
+++ b/android/client/if-main.h
@@ -44,8 +44,6 @@
 #include <hardware/bt_gatt_server.h>
 #endif
 
-#include "textconv.h"
-
 /* Interfaces from hal that can be populated during application lifetime */
 extern const bt_interface_t *if_bluetooth;
 extern const btav_interface_t *if_av;
diff --git a/android/client/if-pan.c b/android/client/if-pan.c
index dcc7e80..a11f2a3 100644
--- a/android/client/if-pan.c
+++ b/android/client/if-pan.c
@@ -18,6 +18,7 @@
 #include <hardware/bluetooth.h>
 
 #include "if-main.h"
+#include "../hal-utils.h"
 
 const btpan_interface_t *if_pan = NULL;
 
diff --git a/android/client/if-sock.c b/android/client/if-sock.c
index dcaf048..2cd06e8 100644
--- a/android/client/if-sock.c
+++ b/android/client/if-sock.c
@@ -21,6 +21,7 @@
 
 #include "if-main.h"
 #include "pollhandler.h"
+#include "../hal-utils.h"
 
 const btsock_interface_t *if_sock = NULL;
 
diff --git a/android/client/textconv.c b/android/client/textconv.c
deleted file mode 100644
index dcbe53e..0000000
--- a/android/client/textconv.c
+++ /dev/null
@@ -1,300 +0,0 @@
-/*
- * 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 <string.h>
-#include <stdio.h>
-#include <hardware/bluetooth.h>
-
-#include "../hal-utils.h"
-
-#include "textconv.h"
-
-/*
- * Following are maps of defines found in bluetooth header files to strings
- *
- * Those mappings are used to accurately use defines as input parameters in
- * command line as well as for printing of statuses
- */
-
-INTMAP(bt_status_t, -1, "(unknown)")
-	DELEMENT(BT_STATUS_SUCCESS),
-	DELEMENT(BT_STATUS_FAIL),
-	DELEMENT(BT_STATUS_NOT_READY),
-	DELEMENT(BT_STATUS_NOMEM),
-	DELEMENT(BT_STATUS_BUSY),
-	DELEMENT(BT_STATUS_DONE),
-	DELEMENT(BT_STATUS_UNSUPPORTED),
-	DELEMENT(BT_STATUS_PARM_INVALID),
-	DELEMENT(BT_STATUS_UNHANDLED),
-	DELEMENT(BT_STATUS_AUTH_FAILURE),
-	DELEMENT(BT_STATUS_RMT_DEV_DOWN),
-ENDMAP
-
-INTMAP(bt_state_t, -1, "(unknown)")
-	DELEMENT(BT_STATE_OFF),
-	DELEMENT(BT_STATE_ON),
-ENDMAP
-
-INTMAP(bt_device_type_t, -1, "(unknown)")
-	DELEMENT(BT_DEVICE_DEVTYPE_BREDR),
-	DELEMENT(BT_DEVICE_DEVTYPE_BLE),
-	DELEMENT(BT_DEVICE_DEVTYPE_DUAL),
-ENDMAP
-
-INTMAP(bt_scan_mode_t, -1, "(unknown)")
-	DELEMENT(BT_SCAN_MODE_NONE),
-	DELEMENT(BT_SCAN_MODE_CONNECTABLE),
-	DELEMENT(BT_SCAN_MODE_CONNECTABLE_DISCOVERABLE),
-ENDMAP
-
-INTMAP(bt_discovery_state_t, -1, "(unknown)")
-	DELEMENT(BT_DISCOVERY_STOPPED),
-	DELEMENT(BT_DISCOVERY_STARTED),
-ENDMAP
-
-INTMAP(bt_acl_state_t, -1, "(unknown)")
-	DELEMENT(BT_ACL_STATE_CONNECTED),
-	DELEMENT(BT_ACL_STATE_DISCONNECTED),
-ENDMAP
-
-INTMAP(bt_bond_state_t, -1, "(unknown)")
-	DELEMENT(BT_BOND_STATE_NONE),
-	DELEMENT(BT_BOND_STATE_BONDING),
-	DELEMENT(BT_BOND_STATE_BONDED),
-ENDMAP
-
-INTMAP(bt_ssp_variant_t, -1, "(unknown)")
-	DELEMENT(BT_SSP_VARIANT_PASSKEY_CONFIRMATION),
-	DELEMENT(BT_SSP_VARIANT_PASSKEY_ENTRY),
-	DELEMENT(BT_SSP_VARIANT_CONSENT),
-	DELEMENT(BT_SSP_VARIANT_PASSKEY_NOTIFICATION),
-ENDMAP
-
-INTMAP(bt_property_type_t, -1, "(unknown)")
-	DELEMENT(BT_PROPERTY_BDNAME),
-	DELEMENT(BT_PROPERTY_BDADDR),
-	DELEMENT(BT_PROPERTY_UUIDS),
-	DELEMENT(BT_PROPERTY_CLASS_OF_DEVICE),
-	DELEMENT(BT_PROPERTY_TYPE_OF_DEVICE),
-	DELEMENT(BT_PROPERTY_SERVICE_RECORD),
-	DELEMENT(BT_PROPERTY_ADAPTER_SCAN_MODE),
-	DELEMENT(BT_PROPERTY_ADAPTER_BONDED_DEVICES),
-	DELEMENT(BT_PROPERTY_ADAPTER_DISCOVERY_TIMEOUT),
-	DELEMENT(BT_PROPERTY_REMOTE_FRIENDLY_NAME),
-	DELEMENT(BT_PROPERTY_REMOTE_RSSI),
-#if PLATFORM_SDK_VERSION > 17
-	DELEMENT(BT_PROPERTY_REMOTE_VERSION_INFO),
-#endif
-	DELEMENT(BT_PROPERTY_REMOTE_DEVICE_TIMESTAMP),
-ENDMAP
-
-INTMAP(bt_cb_thread_evt, -1, "(unknown)")
-	DELEMENT(ASSOCIATE_JVM),
-	DELEMENT(DISASSOCIATE_JVM),
-ENDMAP
-
-/* Find first index of given value in table m */
-int int2str_findint(int v, const struct int2str m[])
-{
-	int i;
-
-	for (i = 0; m[i].str; ++i) {
-		if (m[i].val == v)
-			return i;
-	}
-	return -1;
-}
-
-/* Find first index of given string in table m */
-int int2str_findstr(const char *str, const struct int2str m[])
-{
-	int i;
-
-	for (i = 0; m[i].str; ++i) {
-		if (strcmp(m[i].str, str) == 0)
-			return i;
-	}
-	return -1;
-}
-
-/*
- * convert bd_addr to string
- * buf must be at least 18 char long
- *
- * returns buf
- */
-const char *bt_bdaddr_t2str(const bt_bdaddr_t *bd_addr, char *buf)
-{
-	const uint8_t *p = bd_addr->address;
-
-	snprintf(buf, MAX_ADDR_STR_LEN, "%02x:%02x:%02x:%02x:%02x:%02x",
-					p[0], p[1], p[2], p[3], p[4], p[5]);
-
-	return buf;
-}
-
-/* converts string to bt_bdaddr_t */
-void str2bt_bdaddr_t(const char *str, bt_bdaddr_t *bd_addr)
-{
-	uint8_t *p = bd_addr->address;
-
-	sscanf(str, "%02hhx:%02hhx:%02hhx:%02hhx:%02hhx:%02hhx",
-				&p[0], &p[1], &p[2], &p[3], &p[4], &p[5]);
-}
-
-/* converts string to uuid */
-void str2bt_uuid_t(const char *str, bt_uuid_t *uuid)
-{
-	int i = 0;
-
-	memcpy(uuid, BT_BASE_UUID, sizeof(bt_uuid_t));
-
-	while (*str && i < (int) sizeof(bt_uuid_t)) {
-		while (*str == '-')
-			str++;
-
-		if (sscanf(str, "%02hhx", &uuid->uu[i]) != 1)
-			break;
-
-		i++;
-		str += 2;
-	}
-}
-
-const char *enum_defines(void *v, int i)
-{
-	const struct int2str *m = v;
-
-	return m[i].str != NULL ? m[i].str : NULL;
-}
-
-const char *enum_strings(void *v, int i)
-{
-	const char **m = v;
-
-	return m[i] != NULL ? m[i] : NULL;
-}
-
-const char *enum_one_string(void *v, int i)
-{
-	const char *m = v;
-
-	return (i == 0) && (m[0] != 0) ? m : NULL;
-}
-
-const char *bdaddr2str(const bt_bdaddr_t *bd_addr)
-{
-	static char buf[MAX_ADDR_STR_LEN];
-
-	return bt_bdaddr_t2str(bd_addr, buf);
-}
-
-const char *btproperty2str(const bt_property_t *property)
-{
-	static char buf[4096];
-	char *p;
-
-	p = buf + sprintf(buf, "type=%s len=%d val=",
-					bt_property_type_t2str(property->type),
-					property->len);
-
-	switch (property->type) {
-	case BT_PROPERTY_BDNAME:
-	case BT_PROPERTY_REMOTE_FRIENDLY_NAME:
-		snprintf(p, property->len + 1, "%s",
-					((bt_bdname_t *) property->val)->name);
-		break;
-
-	case BT_PROPERTY_BDADDR:
-		sprintf(p, "%s", bdaddr2str((bt_bdaddr_t *) property->val));
-		break;
-
-	case BT_PROPERTY_CLASS_OF_DEVICE:
-		sprintf(p, "%06x", *((int *) property->val));
-		break;
-
-	case BT_PROPERTY_TYPE_OF_DEVICE:
-		sprintf(p, "%s", bt_device_type_t2str(
-				*((bt_device_type_t *) property->val)));
-		break;
-
-	case BT_PROPERTY_REMOTE_RSSI:
-		sprintf(p, "%d", *((char *) property->val));
-		break;
-
-	case BT_PROPERTY_ADAPTER_SCAN_MODE:
-		sprintf(p, "%s",
-			bt_scan_mode_t2str(*((bt_scan_mode_t *) property->val)));
-		break;
-
-	case BT_PROPERTY_ADAPTER_DISCOVERY_TIMEOUT:
-		sprintf(p, "%d", *((int *) property->val));
-		break;
-
-	case BT_PROPERTY_ADAPTER_BONDED_DEVICES:
-		{
-			int count = property->len / sizeof(bt_bdaddr_t);
-			char *ptr = property->val;
-
-			strcat(p, "{");
-
-			while (count--) {
-				strcat(p, bdaddr2str((bt_bdaddr_t *) ptr));
-				if (count)
-					strcat(p, ", ");
-				ptr += sizeof(bt_bdaddr_t);
-			}
-
-			strcat(p, "}");
-
-		}
-		break;
-
-	case BT_PROPERTY_UUIDS:
-		{
-			int count = property->len / sizeof(bt_uuid_t);
-			uint8_t *ptr = property->val;
-
-			strcat(p, "{");
-
-			while (count--) {
-				strcat(p, btuuid2str(ptr));
-				if (count)
-					strcat(p, ", ");
-				ptr += sizeof(bt_uuid_t);
-			}
-
-			strcat(p, "}");
-
-		}
-		break;
-
-	case BT_PROPERTY_SERVICE_RECORD:
-		{
-			bt_service_record_t *rec = property->val;
-
-			sprintf(p, "{%s, %d, %s}", btuuid2str(rec->uuid.uu),
-						rec->channel, rec->name);
-		}
-		break;
-
-	default:
-		sprintf(p, "%p", property->val);
-	}
-
-	return buf;
-}
diff --git a/android/client/textconv.h b/android/client/textconv.h
deleted file mode 100644
index 0a72805..0000000
--- a/android/client/textconv.h
+++ /dev/null
@@ -1,120 +0,0 @@
-/*
- * 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.
- *
- */
-
-/**
- * Begin mapping section
- *
- * There are some mappings between integer values (enums) and strings
- * to be presented to user. To make it easier to convert between those two
- * set of macros is given. It is specially useful when we want to have
- * strings that match constants from header files like:
- *  BT_STATUS_SUCCESS (0) and corresponding "BT_STATUS_SUCCESS"
- * Example of usage:
- *
- * INTMAP(int, -1, "invalid")
- *   DELEMENT(BT_STATUS_SUCCESS)
- *   DELEMENT(BT_STATUS_FAIL)
- *   MELEMENT(123, "Some strange value")
- * ENDMAP
- *
- * Just by doing this we have mapping table plus two functions:
- *  int str2int(const char *str);
- *  const char *int2str(int v);
- *
- * second argument to INTMAP specifies value to be returned from
- * str2int function when there is not mapping for such number
- * third argument specifies default value to be returned from int2str
- *
- * If same mapping is to be used in several source files put
- * INTMAP in c file and DECINTMAP in h file.
- *
- * For mappings that are to be used in single file only
- * use SINTMAP which will create the same but everything will be marked
- * as static.
- */
-
-struct int2str {
-	int val;		/* int value */
-	const char *str;	/* corresponding string */
-};
-
-int int2str_findint(int v, const struct int2str m[]);
-int int2str_findstr(const char *str, const struct int2str m[]);
-const char *enum_defines(void *v, int i);
-const char *enum_strings(void *v, int i);
-const char *enum_one_string(void *v, int i);
-
-#define TYPE_ENUM(type) ((void *) &__##type##2str[0])
-#define DECINTMAP(type) \
-extern struct int2str __##type##2str[]; \
-const char *type##2##str(type v); \
-type str##2##type(const char *str); \
-
-#define INTMAP(type, deft, defs) \
-const char *type##2##str(type v) \
-{ \
-	int i = int2str_findint((int) v, __##type##2str); \
-	return (i < 0) ? defs : __##type##2str[i].str; \
-} \
-type str##2##type(const char *str) \
-{ \
-	int i = int2str_findstr(str, __##type##2str); \
-	return (i < 0) ? (type) deft : (type) (__##type##2str[i].val); \
-} \
-struct int2str __##type##2str[] = {
-
-#define SINTMAP(type, deft, defs) \
-static struct int2str __##type##2str[]; \
-static inline const char *type##2##str(type v) \
-{ \
-	int i = int2str_findint((int) v, __##type##2str); \
-	return (i < 0) ? defs : __##type##2str[i].str; \
-} \
-static inline type str##2##type(const char *str) \
-{ \
-	int i = int2str_findstr(str, __##type##2str); \
-	return (i < 0) ? (type) deft : (type) (__##type##2str[i].val); \
-} \
-static struct int2str __##type##2str[] = {
-
-#define ENDMAP {0, NULL} };
-
-/* use this to generate string from header file constant */
-#define MELEMENT(v, s) {v, s}
-/* use this to have arbitrary mapping from int to string */
-#define DELEMENT(s) {s, #s}
-/* End of mapping section */
-
-#define MAX_ADDR_STR_LEN 18
-const char *bt_bdaddr_t2str(const bt_bdaddr_t *bd_addr, char *buf);
-void str2bt_bdaddr_t(const char *str, bt_bdaddr_t *bd_addr);
-
-void str2bt_uuid_t(const char *str, bt_uuid_t *uuid);
-
-const char *btproperty2str(const bt_property_t *property);
-const char *bdaddr2str(const bt_bdaddr_t *bd_addr);
-
-DECINTMAP(bt_status_t);
-DECINTMAP(bt_state_t);
-DECINTMAP(bt_device_type_t);
-DECINTMAP(bt_scan_mode_t);
-DECINTMAP(bt_discovery_state_t);
-DECINTMAP(bt_acl_state_t);
-DECINTMAP(bt_bond_state_t);
-DECINTMAP(bt_ssp_variant_t);
-DECINTMAP(bt_property_type_t);
-DECINTMAP(bt_cb_thread_evt);
diff --git a/android/hal-bluetooth.c b/android/hal-bluetooth.c
index 3e5d41f..5c14649 100644
--- a/android/hal-bluetooth.c
+++ b/android/hal-bluetooth.c
@@ -24,8 +24,7 @@
 #include "hal.h"
 #include "hal-msg.h"
 #include "hal-ipc.h"
-
-#include "client/textconv.h"
+#include "hal-utils.h"
 
 static const bt_callbacks_t *bt_hal_cbacks = NULL;
 
diff --git a/android/hal-utils.c b/android/hal-utils.c
index 7ac5047..4f44d98 100644
--- a/android/hal-utils.c
+++ b/android/hal-utils.c
@@ -55,3 +55,272 @@ const char *btuuid2str(const uint8_t *uuid)
 
 	return bt_uuid_t2str(uuid, buf);
 }
+
+INTMAP(bt_status_t, -1, "(unknown)")
+	DELEMENT(BT_STATUS_SUCCESS),
+	DELEMENT(BT_STATUS_FAIL),
+	DELEMENT(BT_STATUS_NOT_READY),
+	DELEMENT(BT_STATUS_NOMEM),
+	DELEMENT(BT_STATUS_BUSY),
+	DELEMENT(BT_STATUS_DONE),
+	DELEMENT(BT_STATUS_UNSUPPORTED),
+	DELEMENT(BT_STATUS_PARM_INVALID),
+	DELEMENT(BT_STATUS_UNHANDLED),
+	DELEMENT(BT_STATUS_AUTH_FAILURE),
+	DELEMENT(BT_STATUS_RMT_DEV_DOWN),
+ENDMAP
+
+INTMAP(bt_state_t, -1, "(unknown)")
+	DELEMENT(BT_STATE_OFF),
+	DELEMENT(BT_STATE_ON),
+ENDMAP
+
+INTMAP(bt_device_type_t, -1, "(unknown)")
+	DELEMENT(BT_DEVICE_DEVTYPE_BREDR),
+	DELEMENT(BT_DEVICE_DEVTYPE_BLE),
+	DELEMENT(BT_DEVICE_DEVTYPE_DUAL),
+ENDMAP
+
+INTMAP(bt_scan_mode_t, -1, "(unknown)")
+	DELEMENT(BT_SCAN_MODE_NONE),
+	DELEMENT(BT_SCAN_MODE_CONNECTABLE),
+	DELEMENT(BT_SCAN_MODE_CONNECTABLE_DISCOVERABLE),
+ENDMAP
+
+INTMAP(bt_discovery_state_t, -1, "(unknown)")
+	DELEMENT(BT_DISCOVERY_STOPPED),
+	DELEMENT(BT_DISCOVERY_STARTED),
+ENDMAP
+
+INTMAP(bt_acl_state_t, -1, "(unknown)")
+	DELEMENT(BT_ACL_STATE_CONNECTED),
+	DELEMENT(BT_ACL_STATE_DISCONNECTED),
+ENDMAP
+
+INTMAP(bt_bond_state_t, -1, "(unknown)")
+	DELEMENT(BT_BOND_STATE_NONE),
+	DELEMENT(BT_BOND_STATE_BONDING),
+	DELEMENT(BT_BOND_STATE_BONDED),
+ENDMAP
+
+INTMAP(bt_ssp_variant_t, -1, "(unknown)")
+	DELEMENT(BT_SSP_VARIANT_PASSKEY_CONFIRMATION),
+	DELEMENT(BT_SSP_VARIANT_PASSKEY_ENTRY),
+	DELEMENT(BT_SSP_VARIANT_CONSENT),
+	DELEMENT(BT_SSP_VARIANT_PASSKEY_NOTIFICATION),
+ENDMAP
+
+INTMAP(bt_property_type_t, -1, "(unknown)")
+	DELEMENT(BT_PROPERTY_BDNAME),
+	DELEMENT(BT_PROPERTY_BDADDR),
+	DELEMENT(BT_PROPERTY_UUIDS),
+	DELEMENT(BT_PROPERTY_CLASS_OF_DEVICE),
+	DELEMENT(BT_PROPERTY_TYPE_OF_DEVICE),
+	DELEMENT(BT_PROPERTY_SERVICE_RECORD),
+	DELEMENT(BT_PROPERTY_ADAPTER_SCAN_MODE),
+	DELEMENT(BT_PROPERTY_ADAPTER_BONDED_DEVICES),
+	DELEMENT(BT_PROPERTY_ADAPTER_DISCOVERY_TIMEOUT),
+	DELEMENT(BT_PROPERTY_REMOTE_FRIENDLY_NAME),
+	DELEMENT(BT_PROPERTY_REMOTE_RSSI),
+#if PLATFORM_SDK_VERSION > 17
+	DELEMENT(BT_PROPERTY_REMOTE_VERSION_INFO),
+#endif
+	DELEMENT(BT_PROPERTY_REMOTE_DEVICE_TIMESTAMP),
+ENDMAP
+
+INTMAP(bt_cb_thread_evt, -1, "(unknown)")
+	DELEMENT(ASSOCIATE_JVM),
+	DELEMENT(DISASSOCIATE_JVM),
+ENDMAP
+
+/* Find first index of given value in table m */
+int int2str_findint(int v, const struct int2str m[])
+{
+	int i;
+
+	for (i = 0; m[i].str; ++i) {
+		if (m[i].val == v)
+			return i;
+	}
+	return -1;
+}
+
+/* Find first index of given string in table m */
+int int2str_findstr(const char *str, const struct int2str m[])
+{
+	int i;
+
+	for (i = 0; m[i].str; ++i) {
+		if (strcmp(m[i].str, str) == 0)
+			return i;
+	}
+	return -1;
+}
+
+/*
+ * convert bd_addr to string
+ * buf must be at least 18 char long
+ *
+ * returns buf
+ */
+const char *bt_bdaddr_t2str(const bt_bdaddr_t *bd_addr, char *buf)
+{
+	const uint8_t *p = bd_addr->address;
+
+	snprintf(buf, MAX_ADDR_STR_LEN, "%02x:%02x:%02x:%02x:%02x:%02x",
+					p[0], p[1], p[2], p[3], p[4], p[5]);
+
+	return buf;
+}
+
+/* converts string to bt_bdaddr_t */
+void str2bt_bdaddr_t(const char *str, bt_bdaddr_t *bd_addr)
+{
+	uint8_t *p = bd_addr->address;
+
+	sscanf(str, "%02hhx:%02hhx:%02hhx:%02hhx:%02hhx:%02hhx",
+				&p[0], &p[1], &p[2], &p[3], &p[4], &p[5]);
+}
+
+/* converts string to uuid */
+void str2bt_uuid_t(const char *str, bt_uuid_t *uuid)
+{
+	int i = 0;
+
+	memcpy(uuid, BT_BASE_UUID, sizeof(bt_uuid_t));
+
+	while (*str && i < (int) sizeof(bt_uuid_t)) {
+		while (*str == '-')
+			str++;
+
+		if (sscanf(str, "%02hhx", &uuid->uu[i]) != 1)
+			break;
+
+		i++;
+		str += 2;
+	}
+}
+
+const char *enum_defines(void *v, int i)
+{
+	const struct int2str *m = v;
+
+	return m[i].str != NULL ? m[i].str : NULL;
+}
+
+const char *enum_strings(void *v, int i)
+{
+	const char **m = v;
+
+	return m[i] != NULL ? m[i] : NULL;
+}
+
+const char *enum_one_string(void *v, int i)
+{
+	const char *m = v;
+
+	return (i == 0) && (m[0] != 0) ? m : NULL;
+}
+
+const char *bdaddr2str(const bt_bdaddr_t *bd_addr)
+{
+	static char buf[MAX_ADDR_STR_LEN];
+
+	return bt_bdaddr_t2str(bd_addr, buf);
+}
+
+const char *btproperty2str(const bt_property_t *property)
+{
+	static char buf[4096];
+	char *p;
+
+	p = buf + sprintf(buf, "type=%s len=%d val=",
+					bt_property_type_t2str(property->type),
+					property->len);
+
+	switch (property->type) {
+	case BT_PROPERTY_BDNAME:
+	case BT_PROPERTY_REMOTE_FRIENDLY_NAME:
+		snprintf(p, property->len + 1, "%s",
+					((bt_bdname_t *) property->val)->name);
+		break;
+
+	case BT_PROPERTY_BDADDR:
+		sprintf(p, "%s", bdaddr2str((bt_bdaddr_t *) property->val));
+		break;
+
+	case BT_PROPERTY_CLASS_OF_DEVICE:
+		sprintf(p, "%06x", *((int *) property->val));
+		break;
+
+	case BT_PROPERTY_TYPE_OF_DEVICE:
+		sprintf(p, "%s", bt_device_type_t2str(
+				*((bt_device_type_t *) property->val)));
+		break;
+
+	case BT_PROPERTY_REMOTE_RSSI:
+		sprintf(p, "%d", *((char *) property->val));
+		break;
+
+	case BT_PROPERTY_ADAPTER_SCAN_MODE:
+		sprintf(p, "%s",
+			bt_scan_mode_t2str(*((bt_scan_mode_t *) property->val)));
+		break;
+
+	case BT_PROPERTY_ADAPTER_DISCOVERY_TIMEOUT:
+		sprintf(p, "%d", *((int *) property->val));
+		break;
+
+	case BT_PROPERTY_ADAPTER_BONDED_DEVICES:
+		{
+			int count = property->len / sizeof(bt_bdaddr_t);
+			char *ptr = property->val;
+
+			strcat(p, "{");
+
+			while (count--) {
+				strcat(p, bdaddr2str((bt_bdaddr_t *) ptr));
+				if (count)
+					strcat(p, ", ");
+				ptr += sizeof(bt_bdaddr_t);
+			}
+
+			strcat(p, "}");
+
+		}
+		break;
+
+	case BT_PROPERTY_UUIDS:
+		{
+			int count = property->len / sizeof(bt_uuid_t);
+			uint8_t *ptr = property->val;
+
+			strcat(p, "{");
+
+			while (count--) {
+				strcat(p, btuuid2str(ptr));
+				if (count)
+					strcat(p, ", ");
+				ptr += sizeof(bt_uuid_t);
+			}
+
+			strcat(p, "}");
+
+		}
+		break;
+
+	case BT_PROPERTY_SERVICE_RECORD:
+		{
+			bt_service_record_t *rec = property->val;
+
+			sprintf(p, "{%s, %d, %s}", btuuid2str(rec->uuid.uu),
+						rec->channel, rec->name);
+		}
+		break;
+
+	default:
+		sprintf(p, "%p", property->val);
+	}
+
+	return buf;
+}
diff --git a/android/hal-utils.h b/android/hal-utils.h
index 8c74653..75de7e9 100644
--- a/android/hal-utils.h
+++ b/android/hal-utils.h
@@ -15,8 +15,11 @@
  *
  */
 
+#include <hardware/bluetooth.h>
+
 #define MAX_UUID_STR_LEN	37
 #define HAL_UUID_LEN		16
+#define MAX_ADDR_STR_LEN	18
 
 static const char BT_BASE_UUID[] = {
 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00,
@@ -25,3 +28,103 @@ static const char BT_BASE_UUID[] = {
 
 const char *bt_uuid_t2str(const uint8_t *uuid, char *buf);
 const char *btuuid2str(const uint8_t *uuid);
+const char *bt_bdaddr_t2str(const bt_bdaddr_t *bd_addr, char *buf);
+void str2bt_bdaddr_t(const char *str, bt_bdaddr_t *bd_addr);
+void str2bt_uuid_t(const char *str, bt_uuid_t *uuid);
+const char *btproperty2str(const bt_property_t *property);
+const char *bdaddr2str(const bt_bdaddr_t *bd_addr);
+
+/**
+ * Begin mapping section
+ *
+ * There are some mappings between integer values (enums) and strings
+ * to be presented to user. To make it easier to convert between those two
+ * set of macros is given. It is specially useful when we want to have
+ * strings that match constants from header files like:
+ *  BT_STATUS_SUCCESS (0) and corresponding "BT_STATUS_SUCCESS"
+ * Example of usage:
+ *
+ * INTMAP(int, -1, "invalid")
+ *   DELEMENT(BT_STATUS_SUCCESS)
+ *   DELEMENT(BT_STATUS_FAIL)
+ *   MELEMENT(123, "Some strange value")
+ * ENDMAP
+ *
+ * Just by doing this we have mapping table plus two functions:
+ *  int str2int(const char *str);
+ *  const char *int2str(int v);
+ *
+ * second argument to INTMAP specifies value to be returned from
+ * str2int function when there is not mapping for such number
+ * third argument specifies default value to be returned from int2str
+ *
+ * If same mapping is to be used in several source files put
+ * INTMAP in c file and DECINTMAP in h file.
+ *
+ * For mappings that are to be used in single file only
+ * use SINTMAP which will create the same but everything will be marked
+ * as static.
+ */
+
+struct int2str {
+	int val;		/* int value */
+	const char *str;	/* corresponding string */
+};
+
+int int2str_findint(int v, const struct int2str m[]);
+int int2str_findstr(const char *str, const struct int2str m[]);
+const char *enum_defines(void *v, int i);
+const char *enum_strings(void *v, int i);
+const char *enum_one_string(void *v, int i);
+
+#define TYPE_ENUM(type) ((void *) &__##type##2str[0])
+#define DECINTMAP(type) \
+extern struct int2str __##type##2str[]; \
+const char *type##2##str(type v); \
+type str##2##type(const char *str); \
+
+#define INTMAP(type, deft, defs) \
+const char *type##2##str(type v) \
+{ \
+	int i = int2str_findint((int) v, __##type##2str); \
+	return (i < 0) ? defs : __##type##2str[i].str; \
+} \
+type str##2##type(const char *str) \
+{ \
+	int i = int2str_findstr(str, __##type##2str); \
+	return (i < 0) ? (type) deft : (type) (__##type##2str[i].val); \
+} \
+struct int2str __##type##2str[] = {
+
+#define SINTMAP(type, deft, defs) \
+static struct int2str __##type##2str[]; \
+static inline const char *type##2##str(type v) \
+{ \
+	int i = int2str_findint((int) v, __##type##2str); \
+	return (i < 0) ? defs : __##type##2str[i].str; \
+} \
+static inline type str##2##type(const char *str) \
+{ \
+	int i = int2str_findstr(str, __##type##2str); \
+	return (i < 0) ? (type) deft : (type) (__##type##2str[i].val); \
+} \
+static struct int2str __##type##2str[] = {
+
+#define ENDMAP {0, NULL} };
+
+/* use this to generate string from header file constant */
+#define MELEMENT(v, s) {v, s}
+/* use this to have arbitrary mapping from int to string */
+#define DELEMENT(s) {s, #s}
+/* End of mapping section */
+
+DECINTMAP(bt_status_t);
+DECINTMAP(bt_state_t);
+DECINTMAP(bt_device_type_t);
+DECINTMAP(bt_scan_mode_t);
+DECINTMAP(bt_discovery_state_t);
+DECINTMAP(bt_acl_state_t);
+DECINTMAP(bt_bond_state_t);
+DECINTMAP(bt_ssp_variant_t);
+DECINTMAP(bt_property_type_t);
+DECINTMAP(bt_cb_thread_evt);
-- 
1.7.10.4


^ permalink raw reply related

* [PATCH] android: Avoid unneeded includes
From: Andrei Emeltchenko @ 2013-11-08 14:26 UTC (permalink / raw)
  To: linux-bluetooth

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

Declare struct mgmt in adapter.h. This avoids including mgmt.h in
every file using adapter functions like socket and hid.
---
 android/adapter.h |    2 ++
 android/hidhost.c |    1 -
 2 files changed, 2 insertions(+), 1 deletion(-)

diff --git a/android/adapter.h b/android/adapter.h
index c62b859..3bda9d9 100644
--- a/android/adapter.h
+++ b/android/adapter.h
@@ -23,6 +23,8 @@
 
 typedef void (*bt_adapter_ready)(int err);
 
+struct mgmt;
+
 void bt_adapter_init(uint16_t index, struct mgmt *mgmt_if,
 							bt_adapter_ready cb);
 
diff --git a/android/hidhost.c b/android/hidhost.c
index d36cb82..6054c1c 100644
--- a/android/hidhost.c
+++ b/android/hidhost.c
@@ -38,7 +38,6 @@
 #include "lib/sdp.h"
 #include "lib/sdp_lib.h"
 #include "lib/uuid.h"
-#include "src/shared/mgmt.h"
 #include "src/sdp-client.h"
 #include "src/glib-helper.h"
 #include "profiles/input/uhid_copy.h"
-- 
1.7.10.4


^ permalink raw reply related

* Re: [PATCH 1/2] androi/haltest: Make debug functions return const string
From: Johan Hedberg @ 2013-11-08 14:22 UTC (permalink / raw)
  To: Andrei Emeltchenko; +Cc: linux-bluetooth
In-Reply-To: <1383919730-13597-1-git-send-email-Andrei.Emeltchenko.news@gmail.com>

Hi Andrei,

On Fri, Nov 08, 2013, Andrei Emeltchenko wrote:
> ---
>  android/client/textconv.c |    6 +++---
>  android/client/textconv.h |    6 +++---
>  2 files changed, 6 insertions(+), 6 deletions(-)

Both patches have been applied. Thanks.

Johan

^ permalink raw reply

* Re: [PATCH] android: Fix error handling in adapter_ready
From: Johan Hedberg @ 2013-11-08 14:15 UTC (permalink / raw)
  To: Szymon Janc; +Cc: linux-bluetooth
In-Reply-To: <1383919259-11782-1-git-send-email-szymon.janc@tieto.com>

Hi Szymon,

On Fri, Nov 08, 2013, Szymon Janc wrote:
> On error negative value is passed to adapter_ready callback. This fix
> passing negative error code to strerror.
> ---
>  android/main.c | 4 ++--
>  1 file changed, 2 insertions(+), 2 deletions(-)

Applied. Thanks.

Johan

^ permalink raw reply

* [RFC] android/hid: Handle virtual unplug event from hid device
From: Ravi kumar Veeramally @ 2013-11-08 14:14 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Ravi kumar Veeramally

If hid host receives the virtual unplug event from hid device
recipient shall destroy or invalidate all bluetooth bonding and
virtual cable information
---
 android/hal-msg.h |  1 +
 android/hidhost.c | 28 ++++++++++++++++++++++++++++
 2 files changed, 29 insertions(+)

diff --git a/android/hal-msg.h b/android/hal-msg.h
index 4c7d344..569c8ea 100644
--- a/android/hal-msg.h
+++ b/android/hal-msg.h
@@ -449,6 +449,7 @@ struct hal_ev_hidhost_conn_state {
 } __attribute__((packed));
 
 #define HAL_HIDHOST_STATUS_OK		0x00
+#define HAL_HIDHOST_GENERAL_ERROR	0x06
 
 #define HAL_EV_HIDHOST_INFO			0x82
 struct hal_ev_hidhost_info {
diff --git a/android/hidhost.c b/android/hidhost.c
index d36cb82..683938f 100644
--- a/android/hidhost.c
+++ b/android/hidhost.c
@@ -379,6 +379,31 @@ send:
 	g_free(ev);
 }
 
+static void bt_hid_notify_virtual_unplug(struct hid_device *dev,
+							uint8_t *buf, int len)
+{
+	struct hal_ev_hidhost_virtual_unplug ev;
+	char address[18];
+
+	ba2str(&dev->dst, address);
+	DBG("device %s", address);
+	bdaddr2android(&dev->dst, ev.bdaddr);
+
+	ev.status = HAL_HIDHOST_GENERAL_ERROR;
+
+	/* Wait either channels to HUP */
+	if (dev->intr_io && dev->ctrl_io) {
+		g_io_channel_shutdown(dev->intr_io, TRUE, NULL);
+		g_io_channel_shutdown(dev->ctrl_io, TRUE, NULL);
+		bt_hid_notify_state(dev, HAL_HIDHOST_STATE_DISCONNECTING);
+		ev.status = HAL_HIDHOST_STATUS_OK;
+	}
+
+	ipc_send(notification_sk, HAL_SERVICE_ID_HIDHOST,
+			HAL_EV_HIDHOST_VIRTUAL_UNPLUG, sizeof(ev), &ev, -1);
+
+}
+
 static gboolean ctrl_io_watch_cb(GIOChannel *chan, gpointer data)
 {
 	struct hid_device *dev = data;
@@ -404,6 +429,9 @@ static gboolean ctrl_io_watch_cb(GIOChannel *chan, gpointer data)
 		break;
 	}
 
+	if (buf[0] == (HID_MSG_CONTROL | HID_VIRTUAL_CABLE_UNPLUG))
+		bt_hid_notify_virtual_unplug(dev, buf, bread);
+
 	/* reset msg type request */
 	dev->last_hid_msg = 0;
 
-- 
1.8.3.2


^ permalink raw reply related

* [PATCH 2/2] android/hal-utils: Make hal-utils functions return const string
From: Andrei Emeltchenko @ 2013-11-08 14:08 UTC (permalink / raw)
  To: linux-bluetooth
In-Reply-To: <1383919730-13597-1-git-send-email-Andrei.Emeltchenko.news@gmail.com>

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

---
 android/hal-utils.c |    4 ++--
 android/hal-utils.h |    4 ++--
 2 files changed, 4 insertions(+), 4 deletions(-)

diff --git a/android/hal-utils.c b/android/hal-utils.c
index 96dc234..7ac5047 100644
--- a/android/hal-utils.c
+++ b/android/hal-utils.c
@@ -27,7 +27,7 @@
  *
  * returns string representation of uuid
  */
-char *bt_uuid_t2str(const uint8_t *uuid, char *buf)
+const char *bt_uuid_t2str(const uint8_t *uuid, char *buf)
 {
 	int shift = 0;
 	unsigned int i;
@@ -49,7 +49,7 @@ char *bt_uuid_t2str(const uint8_t *uuid, char *buf)
 	return buf;
 }
 
-char *btuuid2str(const uint8_t *uuid)
+const char *btuuid2str(const uint8_t *uuid)
 {
 	static char buf[MAX_UUID_STR_LEN];
 
diff --git a/android/hal-utils.h b/android/hal-utils.h
index 5287180..8c74653 100644
--- a/android/hal-utils.h
+++ b/android/hal-utils.h
@@ -23,5 +23,5 @@ static const char BT_BASE_UUID[] = {
 	0x80, 0x00, 0x00, 0x80, 0x5f, 0x9b, 0x34, 0xfb
 };
 
-char *bt_uuid_t2str(const uint8_t *uuid, char *buf);
-char *btuuid2str(const uint8_t *uuid);
+const char *bt_uuid_t2str(const uint8_t *uuid, char *buf);
+const char *btuuid2str(const uint8_t *uuid);
-- 
1.7.10.4


^ permalink raw reply related

* [PATCH 1/2] androi/haltest: Make debug functions return const string
From: Andrei Emeltchenko @ 2013-11-08 14:08 UTC (permalink / raw)
  To: linux-bluetooth

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

---
 android/client/textconv.c |    6 +++---
 android/client/textconv.h |    6 +++---
 2 files changed, 6 insertions(+), 6 deletions(-)

diff --git a/android/client/textconv.c b/android/client/textconv.c
index 60ac08a..dcbe53e 100644
--- a/android/client/textconv.c
+++ b/android/client/textconv.c
@@ -137,7 +137,7 @@ int int2str_findstr(const char *str, const struct int2str m[])
  *
  * returns buf
  */
-char *bt_bdaddr_t2str(const bt_bdaddr_t *bd_addr, char *buf)
+const char *bt_bdaddr_t2str(const bt_bdaddr_t *bd_addr, char *buf)
 {
 	const uint8_t *p = bd_addr->address;
 
@@ -196,14 +196,14 @@ const char *enum_one_string(void *v, int i)
 	return (i == 0) && (m[0] != 0) ? m : NULL;
 }
 
-char *bdaddr2str(const bt_bdaddr_t *bd_addr)
+const char *bdaddr2str(const bt_bdaddr_t *bd_addr)
 {
 	static char buf[MAX_ADDR_STR_LEN];
 
 	return bt_bdaddr_t2str(bd_addr, buf);
 }
 
-char *btproperty2str(const bt_property_t *property)
+const char *btproperty2str(const bt_property_t *property)
 {
 	static char buf[4096];
 	char *p;
diff --git a/android/client/textconv.h b/android/client/textconv.h
index 837eb4e..0a72805 100644
--- a/android/client/textconv.h
+++ b/android/client/textconv.h
@@ -100,13 +100,13 @@ static struct int2str __##type##2str[] = {
 /* End of mapping section */
 
 #define MAX_ADDR_STR_LEN 18
-char *bt_bdaddr_t2str(const bt_bdaddr_t *bd_addr, char *buf);
+const char *bt_bdaddr_t2str(const bt_bdaddr_t *bd_addr, char *buf);
 void str2bt_bdaddr_t(const char *str, bt_bdaddr_t *bd_addr);
 
 void str2bt_uuid_t(const char *str, bt_uuid_t *uuid);
 
-char *btproperty2str(const bt_property_t *property);
-char *bdaddr2str(const bt_bdaddr_t *bd_addr);
+const char *btproperty2str(const bt_property_t *property);
+const char *bdaddr2str(const bt_bdaddr_t *bd_addr);
 
 DECINTMAP(bt_status_t);
 DECINTMAP(bt_state_t);
-- 
1.7.10.4


^ permalink raw reply related

* [PATCH] android: Fix error handling in adapter_ready
From: Szymon Janc @ 2013-11-08 14:00 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Szymon Janc

On error negative value is passed to adapter_ready callback. This fix
passing negative error code to strerror.
---
 android/main.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/android/main.c b/android/main.c
index 93870d0..36cc8aa 100644
--- a/android/main.c
+++ b/android/main.c
@@ -465,8 +465,8 @@ static GOptionEntry options[] = {
 
 static void adapter_ready(int err)
 {
-	if (err) {
-		error("Adapter initialization failed: %s", strerror(err));
+	if (err < 0) {
+		error("Adapter initialization failed: %s", strerror(-err));
 		exit(EXIT_FAILURE);
 	}
 
-- 
1.8.4.2


^ permalink raw reply related

* [PATCHv5 [2/3]] android/debug: Convert uuid helper to use uint8_t buffer
From: Andrei Emeltchenko @ 2013-11-08 13:48 UTC (permalink / raw)
  To: linux-bluetooth
In-Reply-To: <1383916561-9719-2-git-send-email-Andrei.Emeltchenko.news@gmail.com>

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

At this moment Android uses uint8_t * and bt_uuid_t for representing
UUID for different HALs. Convert debug helper to use uint8_t * string.
---
 android/client/textconv.c |    6 +++---
 android/hal-utils.c       |   15 +++++++--------
 android/hal-utils.h       |    7 ++++---
 3 files changed, 14 insertions(+), 14 deletions(-)

diff --git a/android/client/textconv.c b/android/client/textconv.c
index 469b2c3..60ac08a 100644
--- a/android/client/textconv.c
+++ b/android/client/textconv.c
@@ -267,12 +267,12 @@ char *btproperty2str(const bt_property_t *property)
 	case BT_PROPERTY_UUIDS:
 		{
 			int count = property->len / sizeof(bt_uuid_t);
-			char *ptr = property->val;
+			uint8_t *ptr = property->val;
 
 			strcat(p, "{");
 
 			while (count--) {
-				strcat(p, btuuid2str((bt_uuid_t *) ptr));
+				strcat(p, btuuid2str(ptr));
 				if (count)
 					strcat(p, ", ");
 				ptr += sizeof(bt_uuid_t);
@@ -287,7 +287,7 @@ char *btproperty2str(const bt_property_t *property)
 		{
 			bt_service_record_t *rec = property->val;
 
-			sprintf(p, "{%s, %d, %s}", btuuid2str(&rec->uuid),
+			sprintf(p, "{%s, %d, %s}", btuuid2str(rec->uuid.uu),
 						rec->channel, rec->name);
 		}
 		break;
diff --git a/android/hal-utils.c b/android/hal-utils.c
index 84cfad1..96dc234 100644
--- a/android/hal-utils.c
+++ b/android/hal-utils.c
@@ -17,8 +17,7 @@
 
 #include <stdio.h>
 #include <string.h>
-
-#include <hardware/bluetooth.h>
+#include <stdint.h>
 
 #include "hal-utils.h"
 
@@ -28,15 +27,15 @@
  *
  * returns string representation of uuid
  */
-char *bt_uuid_t2str(const bt_uuid_t *uuid, char *buf)
+char *bt_uuid_t2str(const uint8_t *uuid, char *buf)
 {
 	int shift = 0;
-	int i;
+	unsigned int i;
 	int is_bt;
 
-	is_bt = !memcmp(&uuid->uu[4], &BT_BASE_UUID[4], sizeof(bt_uuid_t) - 4);
+	is_bt = !memcmp(&uuid[4], &BT_BASE_UUID[4], HAL_UUID_LEN - 4);
 
-	for (i = 0; i < (int) sizeof(bt_uuid_t); i++) {
+	for (i = 0; i < HAL_UUID_LEN; i++) {
 		if (i == 4 && is_bt)
 			break;
 
@@ -44,13 +43,13 @@ char *bt_uuid_t2str(const bt_uuid_t *uuid, char *buf)
 			buf[i * 2 + shift] = '-';
 			shift++;
 		}
-		sprintf(buf + i * 2 + shift, "%02x", uuid->uu[i]);
+		sprintf(buf + i * 2 + shift, "%02x", uuid[i]);
 	}
 
 	return buf;
 }
 
-char *btuuid2str(const bt_uuid_t *uuid)
+char *btuuid2str(const uint8_t *uuid)
 {
 	static char buf[MAX_UUID_STR_LEN];
 
diff --git a/android/hal-utils.h b/android/hal-utils.h
index d40b430..5287180 100644
--- a/android/hal-utils.h
+++ b/android/hal-utils.h
@@ -15,12 +15,13 @@
  *
  */
 
-#define MAX_UUID_STR_LEN 37
+#define MAX_UUID_STR_LEN	37
+#define HAL_UUID_LEN		16
 
 static const char BT_BASE_UUID[] = {
 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00,
 	0x80, 0x00, 0x00, 0x80, 0x5f, 0x9b, 0x34, 0xfb
 };
 
-char *btuuid2str(const bt_uuid_t *uuid);
-char *bt_uuid_t2str(const bt_uuid_t *uuid, char *buf);
+char *bt_uuid_t2str(const uint8_t *uuid, char *buf);
+char *btuuid2str(const uint8_t *uuid);
-- 
1.7.10.4


^ permalink raw reply related

* Re: [PATCHv5 1/3] android: Create debug hal-utils helpers
From: Johan Hedberg @ 2013-11-08 13:48 UTC (permalink / raw)
  To: Andrei Emeltchenko; +Cc: linux-bluetooth
In-Reply-To: <1383916561-9719-1-git-send-email-Andrei.Emeltchenko.news@gmail.com>

Hi Andrei,

On Fri, Nov 08, 2013, Andrei Emeltchenko wrote:
> Create hal-utils helpers which helps to decode packets Android
> sends through HAL interface.
> ---
>  android/Android.mk        |    2 ++
>  android/Makefile.am       |    3 ++-
>  android/client/if-gatt.c  |    1 +
>  android/client/textconv.c |   42 ++------------------------------
>  android/client/textconv.h |    2 --
>  android/hal-utils.c       |   58 +++++++++++++++++++++++++++++++++++++++++++++
>  android/hal-utils.h       |   26 ++++++++++++++++++++
>  7 files changed, 91 insertions(+), 43 deletions(-)
>  create mode 100644 android/hal-utils.c
>  create mode 100644 android/hal-utils.h

This first patch has been applied, however I'm waiting for v6 of the
other two as we discussed offline.

Johan

^ permalink raw reply

* Re: [PATCH_v6 1/5] android/hid: Fill send data command struct in hal-hidhost
From: Johan Hedberg @ 2013-11-08 13:32 UTC (permalink / raw)
  To: Ravi kumar Veeramally; +Cc: linux-bluetooth
In-Reply-To: <1383916984-11010-1-git-send-email-ravikumar.veeramally@linux.intel.com>

Hi Ravi,

On Fri, Nov 08, 2013, Ravi kumar Veeramally wrote:
> ---
>  android/hal-hidhost.c | 18 ++++++++++--------
>  android/hal-msg.h     |  2 +-
>  2 files changed, 11 insertions(+), 9 deletions(-)

All patches in this set have now been applied. Thanks.

Johan

^ permalink raw reply

* [PATCH_v6 3/5] android/hid: Fill send data command struct in hal-hidhost
From: Ravi kumar Veeramally @ 2013-11-08 13:23 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Ravi kumar Veeramally
In-Reply-To: <1383916984-11010-1-git-send-email-ravikumar.veeramally@linux.intel.com>

---
 android/hal-hidhost.c | 9 ++++++---
 1 file changed, 6 insertions(+), 3 deletions(-)

diff --git a/android/hal-hidhost.c b/android/hal-hidhost.c
index e8570bc..97a1aa0 100644
--- a/android/hal-hidhost.c
+++ b/android/hal-hidhost.c
@@ -334,7 +334,8 @@ static bt_status_t set_report(bt_bdaddr_t *bd_addr,
 
 static bt_status_t send_data(bt_bdaddr_t *bd_addr, char *data)
 {
-	struct hal_cmd_hidhost_send_data cmd;
+	uint8_t buf[BLUEZ_HAL_MTU];
+	struct hal_cmd_hidhost_send_data *cmd = (void *) buf;
 
 	DBG("");
 
@@ -344,10 +345,12 @@ static bt_status_t send_data(bt_bdaddr_t *bd_addr, char *data)
 	if (!bd_addr || !data)
 		return BT_STATUS_PARM_INVALID;
 
-	memcpy(cmd.bdaddr, bd_addr, sizeof(cmd.bdaddr));
+	memcpy(cmd->bdaddr, bd_addr, sizeof(cmd->bdaddr));
+	cmd->len = strlen(data);
+	memcpy(cmd->data, data, cmd->len);
 
 	return hal_ipc_cmd(HAL_SERVICE_ID_HIDHOST, HAL_OP_HIDHOST_SEND_DATA,
-					sizeof(cmd), &cmd, 0, NULL, NULL);
+				sizeof(*cmd) + cmd->len, buf, 0, NULL, NULL);
 }
 
 static bt_status_t init(bthh_callbacks_t *callbacks)
-- 
1.8.3.2


^ permalink raw reply related

* [PATCH_v6 1/5] android/hid: Fill send data command struct in hal-hidhost
From: Ravi kumar Veeramally @ 2013-11-08 13:23 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Ravi kumar Veeramally

---
 android/hal-hidhost.c | 18 ++++++++++--------
 android/hal-msg.h     |  2 +-
 2 files changed, 11 insertions(+), 9 deletions(-)

diff --git a/android/hal-hidhost.c b/android/hal-hidhost.c
index 94f7e01..e8570bc 100644
--- a/android/hal-hidhost.c
+++ b/android/hal-hidhost.c
@@ -18,6 +18,7 @@
 #include <stdbool.h>
 #include <stddef.h>
 #include <string.h>
+#include <stdlib.h>
 
 #include "hal-log.h"
 #include "hal.h"
@@ -298,7 +299,8 @@ static bt_status_t set_report(bt_bdaddr_t *bd_addr,
 						bthh_report_type_t report_type,
 						char *report)
 {
-	struct hal_cmd_hidhost_set_report cmd;
+	uint8_t buf[BLUEZ_HAL_MTU];
+	struct hal_cmd_hidhost_set_report *cmd = (void *) buf;
 
 	DBG("");
 
@@ -308,26 +310,26 @@ static bt_status_t set_report(bt_bdaddr_t *bd_addr,
 	if (!bd_addr || !report)
 		return BT_STATUS_PARM_INVALID;
 
-	memcpy(cmd.bdaddr, bd_addr, sizeof(cmd.bdaddr));
-	cmd.len = strlen(report);
-	memcpy(cmd.data, report, cmd.len);
+	memcpy(cmd->bdaddr, bd_addr, sizeof(cmd->bdaddr));
+	cmd->len = strlen(report);
+	memcpy(cmd->data, report, cmd->len);
 
 	switch (report_type) {
 	case BTHH_INPUT_REPORT:
-		cmd.type = HAL_HIDHOST_INPUT_REPORT;
+		cmd->type = HAL_HIDHOST_INPUT_REPORT;
 		break;
 	case BTHH_OUTPUT_REPORT:
-		cmd.type = HAL_HIDHOST_OUTPUT_REPORT;
+		cmd->type = HAL_HIDHOST_OUTPUT_REPORT;
 		break;
 	case BTHH_FEATURE_REPORT:
-		cmd.type = HAL_HIDHOST_FEATURE_REPORT;
+		cmd->type = HAL_HIDHOST_FEATURE_REPORT;
 		break;
 	default:
 		return BT_STATUS_PARM_INVALID;
 	}
 
 	return hal_ipc_cmd(HAL_SERVICE_ID_HIDHOST, HAL_OP_HIDHOST_SET_REPORT,
-				sizeof(cmd), &cmd, 0, NULL, NULL);
+				sizeof(*cmd) + cmd->len, buf, 0, NULL, NULL);
 }
 
 static bt_status_t send_data(bt_bdaddr_t *bd_addr, char *data)
diff --git a/android/hal-msg.h b/android/hal-msg.h
index 4af86de..4c7d344 100644
--- a/android/hal-msg.h
+++ b/android/hal-msg.h
@@ -293,7 +293,7 @@ struct hal_cmd_hidhost_set_report {
 	uint8_t  bdaddr[6];
 	uint8_t  type;
 	uint16_t len;
-	uint8_t  data[670];
+	uint8_t  data[0];
 } __attribute__((packed));
 
 #define HAL_OP_HIDHOST_SEND_DATA		0x09
-- 
1.8.3.2


^ permalink raw reply related

* Re: [PATCH 0/8] Improve user experience
From: Johan Hedberg @ 2013-11-08 13:16 UTC (permalink / raw)
  To: Jerzy Kasenberg; +Cc: linux-bluetooth
In-Reply-To: <1383914910-2304-1-git-send-email-jerzy.kasenberg@tieto.com>

Hi Jerzy,

On Fri, Nov 08, 2013, Jerzy Kasenberg wrote:
> This patchset works towards improving user interface.
> - Command line parsing (--help, --version, --no-init)
> - All interfaces are now initialized at start by default
> - --no-init allows to disable this initialization
> - pin_request_cb will now present prompt and send reply
> - ssp_request_cb will now present prompt and sent reply
> 
> As part of adding those features terminal.c was restructured.
> Big switch inside terminal_process_char was distributed between
> number of small functions. This work was necessary due to input
> handling of prompted data.
> 
> Version print may need to be changed according to bluez culture. 
> 
> Jerzy Kasenberg (8):
>   android/client: Export get_interface_method
>   android/client: Add NELEM macro for count elements
>   android/client: Initialize all interfaces at start
>   android/client: Add command line arguments
>   android/client: Split terminal_process_char
>   android/client: Add prompting for answer
>   android/client: Add pin handling for bind
>   android/client: Add ssp key confirmation helper
> 
>  android/client/haltest.c       |  102 ++++++-
>  android/client/if-bt.c         |   46 +++
>  android/client/if-main.h       |    4 +
>  android/client/tabcompletion.c |    2 +-
>  android/client/terminal.c      |  605 +++++++++++++++++++++++++++-------------
>  android/client/terminal.h      |    5 +-
>  6 files changed, 567 insertions(+), 197 deletions(-)

All eight patches have been applied. Thanks.

Johan

^ permalink raw reply

* [PATCHv5 3/3] android/hal-sock: Add UUID debug print in socket HAL
From: Andrei Emeltchenko @ 2013-11-08 13:16 UTC (permalink / raw)
  To: linux-bluetooth
In-Reply-To: <1383916561-9719-1-git-send-email-Andrei.Emeltchenko.news@gmail.com>

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

Socket HAL uses uint8_t * strings which are of size bt_uuid_t.
---
 android/hal-sock.c |   17 ++++++++++-------
 1 file changed, 10 insertions(+), 7 deletions(-)

diff --git a/android/hal-sock.c b/android/hal-sock.c
index 32c7939..d24276e 100644
--- a/android/hal-sock.c
+++ b/android/hal-sock.c
@@ -25,6 +25,8 @@
 #include "hal-msg.h"
 #include "hal.h"
 
+#include "hal-utils.h"
+
 static bt_status_t sock_listen_rfcomm(const char *service_name,
 					const uint8_t *uuid, int chan,
 					int *sock, int flags)
@@ -49,13 +51,13 @@ static bt_status_t sock_listen(btsock_type_t type, const char *service_name,
 					int *sock, int flags)
 {
 	if ((!uuid && chan <= 0) || !sock) {
-		error("%s: invalid params: uuid %p, chan %d, sock %p",
-						__func__, uuid, chan, sock);
+		error("Invalid params: uuid %s, chan %d, sock %p",
+						btuuid2str(uuid), chan, sock);
 		return BT_STATUS_PARM_INVALID;
 	}
 
-	DBG("uuid %p chan %d sock %p type %d service_name %s",
-					uuid, chan, sock, type, service_name);
+	DBG("uuid %s chan %d sock %p type %d service_name %s",
+			btuuid2str(uuid), chan, sock, type, service_name);
 
 	switch (type) {
 	case BTSOCK_RFCOMM:
@@ -76,12 +78,13 @@ static bt_status_t sock_connect(const bt_bdaddr_t *bdaddr, btsock_type_t type,
 	struct hal_cmd_sock_connect cmd;
 
 	if ((!uuid && chan <= 0) || !bdaddr || !sock) {
-		error("invalid params: bd_addr %p, uuid %p, chan %d, sock %p",
-					bdaddr, uuid, chan, sock);
+		error("Invalid params: bd_addr %p, uuid %s, chan %d, sock %p",
+					bdaddr, btuuid2str(uuid), chan, sock);
 		return BT_STATUS_PARM_INVALID;
 	}
 
-	DBG("uuid %p chan %d sock %p type %d", uuid, chan, sock, type);
+	DBG("uuid %s chan %d sock %p type %d", btuuid2str(uuid), chan, sock,
+									type);
 
 	if (type != BTSOCK_RFCOMM) {
 		error("Socket type %u not supported", type);
-- 
1.7.10.4


^ permalink raw reply related

* [PATCHv5 2/3] android/debug: Convert uuid helper to use uint8_t buffer
From: Andrei Emeltchenko @ 2013-11-08 13:16 UTC (permalink / raw)
  To: linux-bluetooth
In-Reply-To: <1383916561-9719-1-git-send-email-Andrei.Emeltchenko.news@gmail.com>

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

At this moment Android uses uint8_t * and bt_uuid_t for representing
UUID for different HALs. Convert debug helper to use uint8_t * string.
---
 android/client/textconv.c |    7 +++++--
 android/hal-utils.c       |   15 +++++++--------
 android/hal-utils.h       |    7 ++++---
 3 files changed, 16 insertions(+), 13 deletions(-)

diff --git a/android/client/textconv.c b/android/client/textconv.c
index 469b2c3..ebf6316 100644
--- a/android/client/textconv.c
+++ b/android/client/textconv.c
@@ -272,7 +272,9 @@ char *btproperty2str(const bt_property_t *property)
 			strcat(p, "{");
 
 			while (count--) {
-				strcat(p, btuuid2str((bt_uuid_t *) ptr));
+				bt_uuid_t *uuid = (bt_uuid_t *) ptr;
+
+				strcat(p, btuuid2str(uuid->uu));
 				if (count)
 					strcat(p, ", ");
 				ptr += sizeof(bt_uuid_t);
@@ -286,8 +288,9 @@ char *btproperty2str(const bt_property_t *property)
 	case BT_PROPERTY_SERVICE_RECORD:
 		{
 			bt_service_record_t *rec = property->val;
+			bt_uuid_t *uuid = &rec->uuid;
 
-			sprintf(p, "{%s, %d, %s}", btuuid2str(&rec->uuid),
+			sprintf(p, "{%s, %d, %s}", btuuid2str(uuid->uu),
 						rec->channel, rec->name);
 		}
 		break;
diff --git a/android/hal-utils.c b/android/hal-utils.c
index 84cfad1..96dc234 100644
--- a/android/hal-utils.c
+++ b/android/hal-utils.c
@@ -17,8 +17,7 @@
 
 #include <stdio.h>
 #include <string.h>
-
-#include <hardware/bluetooth.h>
+#include <stdint.h>
 
 #include "hal-utils.h"
 
@@ -28,15 +27,15 @@
  *
  * returns string representation of uuid
  */
-char *bt_uuid_t2str(const bt_uuid_t *uuid, char *buf)
+char *bt_uuid_t2str(const uint8_t *uuid, char *buf)
 {
 	int shift = 0;
-	int i;
+	unsigned int i;
 	int is_bt;
 
-	is_bt = !memcmp(&uuid->uu[4], &BT_BASE_UUID[4], sizeof(bt_uuid_t) - 4);
+	is_bt = !memcmp(&uuid[4], &BT_BASE_UUID[4], HAL_UUID_LEN - 4);
 
-	for (i = 0; i < (int) sizeof(bt_uuid_t); i++) {
+	for (i = 0; i < HAL_UUID_LEN; i++) {
 		if (i == 4 && is_bt)
 			break;
 
@@ -44,13 +43,13 @@ char *bt_uuid_t2str(const bt_uuid_t *uuid, char *buf)
 			buf[i * 2 + shift] = '-';
 			shift++;
 		}
-		sprintf(buf + i * 2 + shift, "%02x", uuid->uu[i]);
+		sprintf(buf + i * 2 + shift, "%02x", uuid[i]);
 	}
 
 	return buf;
 }
 
-char *btuuid2str(const bt_uuid_t *uuid)
+char *btuuid2str(const uint8_t *uuid)
 {
 	static char buf[MAX_UUID_STR_LEN];
 
diff --git a/android/hal-utils.h b/android/hal-utils.h
index d40b430..5287180 100644
--- a/android/hal-utils.h
+++ b/android/hal-utils.h
@@ -15,12 +15,13 @@
  *
  */
 
-#define MAX_UUID_STR_LEN 37
+#define MAX_UUID_STR_LEN	37
+#define HAL_UUID_LEN		16
 
 static const char BT_BASE_UUID[] = {
 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00,
 	0x80, 0x00, 0x00, 0x80, 0x5f, 0x9b, 0x34, 0xfb
 };
 
-char *btuuid2str(const bt_uuid_t *uuid);
-char *bt_uuid_t2str(const bt_uuid_t *uuid, char *buf);
+char *bt_uuid_t2str(const uint8_t *uuid, char *buf);
+char *btuuid2str(const uint8_t *uuid);
-- 
1.7.10.4


^ permalink raw reply related

* [PATCHv5 1/3] android: Create debug hal-utils helpers
From: Andrei Emeltchenko @ 2013-11-08 13:15 UTC (permalink / raw)
  To: linux-bluetooth

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

Create hal-utils helpers which helps to decode packets Android
sends through HAL interface.
---
 android/Android.mk        |    2 ++
 android/Makefile.am       |    3 ++-
 android/client/if-gatt.c  |    1 +
 android/client/textconv.c |   42 ++------------------------------
 android/client/textconv.h |    2 --
 android/hal-utils.c       |   58 +++++++++++++++++++++++++++++++++++++++++++++
 android/hal-utils.h       |   26 ++++++++++++++++++++
 7 files changed, 91 insertions(+), 43 deletions(-)
 create mode 100644 android/hal-utils.c
 create mode 100644 android/hal-utils.h

diff --git a/android/Android.mk b/android/Android.mk
index 51037a7..0bc0e82 100644
--- a/android/Android.mk
+++ b/android/Android.mk
@@ -88,6 +88,7 @@ LOCAL_SRC_FILES := \
 	hal-pan.c \
 	hal-a2dp.c \
 	client/textconv.c \
+	hal-utils.c \
 
 LOCAL_C_INCLUDES += \
 	$(call include-path-for, system-core) \
@@ -125,6 +126,7 @@ LOCAL_SRC_FILES := \
 	client/if-hh.c \
 	client/if-pan.c \
 	client/if-sock.c \
+	hal-utils.c \
 
 ANDROID_4_3_OR_ABOVE := $(shell echo 0 | awk -v v=$(PLATFORM_SDK_VERSION) 'END {print (v > 17) ? 1 : 0}')
 
diff --git a/android/Makefile.am b/android/Makefile.am
index 073edc8..debe7c1 100644
--- a/android/Makefile.am
+++ b/android/Makefile.am
@@ -68,7 +68,8 @@ android_haltest_SOURCES = android/client/haltest.c \
 				android/client/if-hh.c \
 				android/client/if-pan.c \
 				android/client/if-sock.c \
-				android/client/hwmodule.c
+				android/client/hwmodule.c \
+				android/hal-utils.h android/hal-utils.c
 
 android_haltest_LDADD = android/libhal-internal.la
 
diff --git a/android/client/if-gatt.c b/android/client/if-gatt.c
index b2b20cb..bb53952 100644
--- a/android/client/if-gatt.c
+++ b/android/client/if-gatt.c
@@ -17,6 +17,7 @@
 
 #include <hardware/bluetooth.h>
 
+#include "../hal-utils.h"
 #include "if-main.h"
 
 const btgatt_interface_t *if_gatt = NULL;
diff --git a/android/client/textconv.c b/android/client/textconv.c
index 4def3da..469b2c3 100644
--- a/android/client/textconv.c
+++ b/android/client/textconv.c
@@ -19,6 +19,8 @@
 #include <stdio.h>
 #include <hardware/bluetooth.h>
 
+#include "../hal-utils.h"
+
 #include "textconv.h"
 
 /*
@@ -154,39 +156,6 @@ void str2bt_bdaddr_t(const char *str, bt_bdaddr_t *bd_addr)
 				&p[0], &p[1], &p[2], &p[3], &p[4], &p[5]);
 }
 
-static const char BT_BASE_UUID[] = {
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00,
-	0x80, 0x00, 0x00, 0x80, 0x5f, 0x9b, 0x34, 0xfb
-};
-
-/*
- * converts uuid to string
- * buf should be at least 39 bytes
- *
- * returns string representation of uuid
- */
-char *bt_uuid_t2str(const bt_uuid_t *uuid, char *buf)
-{
-	int shift = 0;
-	int i;
-	int is_bt;
-
-	is_bt = !memcmp(&uuid->uu[4], &BT_BASE_UUID[4], sizeof(bt_uuid_t) - 4);
-
-	for (i = 0; i < (int) sizeof(bt_uuid_t); i++) {
-		if (i == 4 && is_bt)
-			break;
-
-		if (i == 4 || i == 6 || i == 8 || i == 10) {
-			buf[i * 2 + shift] = '-';
-			shift++;
-		}
-		sprintf(buf + i * 2 + shift, "%02x", uuid->uu[i]);
-	}
-
-	return buf;
-}
-
 /* converts string to uuid */
 void str2bt_uuid_t(const char *str, bt_uuid_t *uuid)
 {
@@ -234,13 +203,6 @@ char *bdaddr2str(const bt_bdaddr_t *bd_addr)
 	return bt_bdaddr_t2str(bd_addr, buf);
 }
 
-static char *btuuid2str(const bt_uuid_t *uuid)
-{
-	static char buf[MAX_UUID_STR_LEN];
-
-	return bt_uuid_t2str(uuid, buf);
-}
-
 char *btproperty2str(const bt_property_t *property)
 {
 	static char buf[4096];
diff --git a/android/client/textconv.h b/android/client/textconv.h
index 1c848ef..837eb4e 100644
--- a/android/client/textconv.h
+++ b/android/client/textconv.h
@@ -103,8 +103,6 @@ static struct int2str __##type##2str[] = {
 char *bt_bdaddr_t2str(const bt_bdaddr_t *bd_addr, char *buf);
 void str2bt_bdaddr_t(const char *str, bt_bdaddr_t *bd_addr);
 
-#define MAX_UUID_STR_LEN 37
-char *bt_uuid_t2str(const bt_uuid_t *uuid, char *buf);
 void str2bt_uuid_t(const char *str, bt_uuid_t *uuid);
 
 char *btproperty2str(const bt_property_t *property);
diff --git a/android/hal-utils.c b/android/hal-utils.c
new file mode 100644
index 0000000..84cfad1
--- /dev/null
+++ b/android/hal-utils.c
@@ -0,0 +1,58 @@
+/*
+ * 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 <string.h>
+
+#include <hardware/bluetooth.h>
+
+#include "hal-utils.h"
+
+/*
+ * converts uuid to string
+ * buf should be at least 39 bytes
+ *
+ * returns string representation of uuid
+ */
+char *bt_uuid_t2str(const bt_uuid_t *uuid, char *buf)
+{
+	int shift = 0;
+	int i;
+	int is_bt;
+
+	is_bt = !memcmp(&uuid->uu[4], &BT_BASE_UUID[4], sizeof(bt_uuid_t) - 4);
+
+	for (i = 0; i < (int) sizeof(bt_uuid_t); i++) {
+		if (i == 4 && is_bt)
+			break;
+
+		if (i == 4 || i == 6 || i == 8 || i == 10) {
+			buf[i * 2 + shift] = '-';
+			shift++;
+		}
+		sprintf(buf + i * 2 + shift, "%02x", uuid->uu[i]);
+	}
+
+	return buf;
+}
+
+char *btuuid2str(const bt_uuid_t *uuid)
+{
+	static char buf[MAX_UUID_STR_LEN];
+
+	return bt_uuid_t2str(uuid, buf);
+}
diff --git a/android/hal-utils.h b/android/hal-utils.h
new file mode 100644
index 0000000..d40b430
--- /dev/null
+++ b/android/hal-utils.h
@@ -0,0 +1,26 @@
+/*
+ * 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.
+ *
+ */
+
+#define MAX_UUID_STR_LEN 37
+
+static const char BT_BASE_UUID[] = {
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00,
+	0x80, 0x00, 0x00, 0x80, 0x5f, 0x9b, 0x34, 0xfb
+};
+
+char *btuuid2str(const bt_uuid_t *uuid);
+char *bt_uuid_t2str(const bt_uuid_t *uuid, char *buf);
-- 
1.7.10.4


^ permalink raw reply related

* [PATCH 8/8] android/client: Add ssp key confirmation helper
From: Jerzy Kasenberg @ 2013-11-08 12:48 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Jerzy Kasenberg
In-Reply-To: <1383914910-2304-1-git-send-email-jerzy.kasenberg@tieto.com>

This patch adds handling of ssp_request_cb that prints prompt
asking user if pass key matches. User does not need to type:
bluetooth ssp_reply address BT_SSP_VARIANT_PASSKEY_CONFIRMATION 1 key
---
 android/client/if-bt.c |   26 ++++++++++++++++++++++++++
 1 file changed, 26 insertions(+)

diff --git a/android/client/if-bt.c b/android/client/if-bt.c
index 0a580e1..10ae125 100644
--- a/android/client/if-bt.c
+++ b/android/client/if-bt.c
@@ -239,10 +239,26 @@ static void pin_request_cb(bt_bdaddr_t *remote_bd_addr, bt_bdname_t *bd_name,
 	terminal_prompt_for("Enter pin: ", pin_request_answer);
 }
 
+/* Variables to store information from ssp_request_cb used for ssp_reply */
+static bt_bdaddr_t ssp_request_addr;
+static bt_ssp_variant_t ssp_request_variant;
+static uint32_t ssp_request_pask_key;
+
+/* Called when user hit enter on prompt for confirmation */
+static void ssp_request_yes_no_answer(char *reply)
+{
+	int accept = *reply == 0 || *reply == 'y' || *reply == 'Y';
+
+	if_bluetooth->ssp_reply(&ssp_request_addr, ssp_request_variant, accept,
+							ssp_request_pask_key);
+}
+
 static void ssp_request_cb(bt_bdaddr_t *remote_bd_addr, bt_bdname_t *bd_name,
 				uint32_t cod, bt_ssp_variant_t pairing_variant,
 				uint32_t pass_key)
 {
+	static char prompt[50];
+
 	/* Store for command completion */
 	bt_bdaddr_t2str(remote_bd_addr, last_remote_addr);
 	last_ssp_variant = pairing_variant;
@@ -250,6 +266,16 @@ static void ssp_request_cb(bt_bdaddr_t *remote_bd_addr, bt_bdname_t *bd_name,
 	haltest_info("%s: remote_bd_addr=%s bd_name=%s cod=%06x pairing_variant=%s pass_key=%d\n",
 			__func__, last_remote_addr, bd_name->name, cod,
 			bt_ssp_variant_t2str(pairing_variant), pass_key);
+
+	if (pairing_variant == BT_SSP_VARIANT_PASSKEY_CONFIRMATION) {
+		sprintf(prompt, "Does other device show %d [Y/n] ?", pass_key);
+
+		ssp_request_addr = *remote_bd_addr;
+		ssp_request_variant = pairing_variant;
+		ssp_request_pask_key = pass_key;
+
+		terminal_prompt_for(prompt, ssp_request_yes_no_answer);
+	}
 }
 
 static void bond_state_changed_cb(bt_status_t status,
-- 
1.7.9.5


^ permalink raw reply related

* [PATCH 7/8] android/client: Add pin handling for bind
From: Jerzy Kasenberg @ 2013-11-08 12:48 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Jerzy Kasenberg
In-Reply-To: <1383914910-2304-1-git-send-email-jerzy.kasenberg@tieto.com>

This patch ask user for ping in pin_request_cb, which does
what otherwise would be required to manually type
bluetooth pin_reply address pin.
---
 android/client/if-bt.c |   20 ++++++++++++++++++++
 1 file changed, 20 insertions(+)

diff --git a/android/client/if-bt.c b/android/client/if-bt.c
index 4c501a5..0a580e1 100644
--- a/android/client/if-bt.c
+++ b/android/client/if-bt.c
@@ -16,6 +16,7 @@
  */
 
 #include "if-main.h"
+#include "terminal.h"
 
 const bt_interface_t *if_bluetooth;
 
@@ -209,14 +210,33 @@ static void discovery_state_changed_cb(bt_discovery_state_t state)
 static char last_remote_addr[MAX_ADDR_STR_LEN];
 static bt_ssp_variant_t last_ssp_variant = (bt_ssp_variant_t) -1;
 
+static bt_bdaddr_t pin_request_addr;
+static void pin_request_answer(char *reply)
+{
+	bt_pin_code_t pin;
+	int accept = 0;
+	int pin_len = strlen(reply);
+
+	if (pin_len > 0) {
+		accept = 1;
+		if (pin_len > 16)
+			pin_len = 16;
+		memcpy(&pin.pin, reply, pin_len);
+	}
+
+	EXEC(if_bluetooth->pin_reply, &pin_request_addr, accept, pin_len, &pin);
+}
+
 static void pin_request_cb(bt_bdaddr_t *remote_bd_addr, bt_bdname_t *bd_name,
 								uint32_t cod)
 {
 	/* Store for command completion */
 	bt_bdaddr_t2str(remote_bd_addr, last_remote_addr);
+	pin_request_addr = *remote_bd_addr;
 
 	haltest_info("%s: remote_bd_addr=%s bd_name=%s cod=%06x\n", __func__,
 					last_remote_addr, bd_name->name, cod);
+	terminal_prompt_for("Enter pin: ", pin_request_answer);
 }
 
 static void ssp_request_cb(bt_bdaddr_t *remote_bd_addr, bt_bdname_t *bd_name,
-- 
1.7.9.5


^ permalink raw reply related

* [PATCH 6/8] android/client: Add prompting for answer
From: Jerzy Kasenberg @ 2013-11-08 12:48 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Jerzy Kasenberg
In-Reply-To: <1383914910-2304-1-git-send-email-jerzy.kasenberg@tieto.com>

This patch allows to switch to prompt mode where user will be asked
to supply some information.
---
 android/client/terminal.c |   67 +++++++++++++++++++++++++++++++++++++++++++++
 android/client/terminal.h |    1 +
 2 files changed, 68 insertions(+)

diff --git a/android/client/terminal.c b/android/client/terminal.c
index 3674f89..f7b56de 100644
--- a/android/client/terminal.c
+++ b/android/client/terminal.c
@@ -684,6 +684,9 @@ TERMINAL_ACTION(terminal_action_default)
 		terminal_insert_into_command_line(str);
 }
 
+/* Callback to call when user hit enter during prompt for */
+static line_callback prompt_callback;
+
 static KeyAction normal_actions[] = {
 	{ 0, terminal_action_default },
 	{ KEY_LEFT, terminal_action_left },
@@ -709,6 +712,59 @@ static KeyAction normal_actions[] = {
 	{ 0, NULL },
 };
 
+TERMINAL_ACTION(terminal_action_answer)
+{
+	putchar(c);
+
+	terminal_set_actions(normal_actions);
+	/* Restore default prompt */
+	current_prompt = prompt_buf;
+
+	/* No prompt for prints */
+	prompt = noprompt;
+	line_buf_ix = 0;
+	line_len = 0;
+	/* Call user function with what was typed */
+	prompt_callback(line_buf);
+
+	line_buf[0] = 0;
+	/* promot_callback could change current_prompt */
+	prompt = current_prompt;
+
+	printf("%s", prompt);
+}
+
+TERMINAL_ACTION(terminal_action_prompt_ctrl_c)
+{
+	printf("^C\n");
+	line_buf_ix = 0;
+	line_len = 0;
+	line_buf[0] = 0;
+
+	current_prompt = prompt_buf;
+	prompt = current_prompt;
+	terminal_set_actions(normal_actions);
+
+	printf("%s", prompt);
+}
+
+static KeyAction prompt_actions[] = {
+	{ 0, terminal_action_default },
+	{ KEY_LEFT, terminal_action_left },
+	{ KEY_RIGHT, terminal_action_right },
+	{ KEY_HOME, terminal_action_home },
+	{ KEY_END, terminal_action_end },
+	{ KEY_DELETE, terminal_action_del },
+	{ KEY_CLEFT, terminal_action_word_left },
+	{ KEY_CRIGHT, terminal_action_word_right },
+	{ KEY_BACKSPACE, terminal_action_backspace },
+	{ KEY_C_C, terminal_action_prompt_ctrl_c },
+	{ KEY_C_D, terminal_action_ctrl_d },
+	{ '\r', terminal_action_answer },
+	{ '\n', terminal_action_answer },
+	{ 0, NULL },
+};
+
 void terminal_process_char(int c, line_callback process_line)
 {
 	KeyAction *a;
@@ -726,6 +782,17 @@ void terminal_process_char(int c, line_callback process_line)
 	fflush(stdout);
 }
 
+void terminal_prompt_for(const char *s, line_callback process_line)
+{
+	current_prompt = s;
+	if (prompt != noprompt) {
+		prompt = s;
+		terminal_clear_line();
+	}
+	prompt_callback = process_line;
+	terminal_set_actions(prompt_actions);
+}
+
 static struct termios origianl_tios;
 
 static void terminal_cleanup(void)
diff --git a/android/client/terminal.h b/android/client/terminal.h
index b5e402d..0e63936 100644
--- a/android/client/terminal.h
+++ b/android/client/terminal.h
@@ -57,5 +57,6 @@ int terminal_vprint(const char *format, va_list args);
 void terminal_process_char(int c, line_callback process_line);
 void terminal_insert_into_command_line(const char *p);
 void terminal_draw_command_line(void);
+void terminal_prompt_for(const char *s, line_callback process_line);
 
 void process_tab(const char *line, int len);
-- 
1.7.9.5


^ permalink raw reply related

* [PATCH 5/8] android/client: Split terminal_process_char
From: Jerzy Kasenberg @ 2013-11-08 12:48 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Jerzy Kasenberg
In-Reply-To: <1383914910-2304-1-git-send-email-jerzy.kasenberg@tieto.com>

This patch changes the way input characters are handled in function
terminal_process_char from big switch statement to smaller functions.
No functionality is changed in this patch.
Splitting to smaller functions will make easier to change behaviour
of terminal for prompt handling when user will be asked for something
and history substitution or auto completion will not be used.
---
 android/client/terminal.c |  538 +++++++++++++++++++++++++++++----------------
 android/client/terminal.h |    4 +-
 2 files changed, 347 insertions(+), 195 deletions(-)

diff --git a/android/client/terminal.c b/android/client/terminal.c
index b152bf3..3674f89 100644
--- a/android/client/terminal.c
+++ b/android/client/terminal.c
@@ -118,6 +118,8 @@ static int line_len = 0;
 static int line_index = 0;
 
 static char prompt_buf[10] = "> ";
+static const char *const noprompt = "";
+static const char *current_prompt = prompt_buf;
 static const char *prompt = prompt_buf;
 /*
  * Moves cursor to right or left
@@ -232,6 +234,7 @@ static void terminal_line_replaced(void)
 	/* set up indexes to new line */
 	line_len = strlen(line_buf);
 	line_buf_ix = line_len;
+	fflush(stdout);
 }
 
 static void terminal_clear_line(void)
@@ -365,217 +368,361 @@ static int terminal_convert_sequence(int c)
 	return c;
 }
 
-void terminal_process_char(int c, void (*process_line)(char *line))
+typedef void (*terminal_action)(int c, line_callback process_line);
+
+#define TERMINAL_ACTION(n) \
+	static void n(int c, void (*process_line)(char *line))
+
+TERMINAL_ACTION(terminal_action_null)
 {
-	int refresh_from = -1;
-	int old_pos;
+}
 
-	c = terminal_convert_sequence(c);
+/* Mapping between keys and function */
+typedef struct {
+	int key;
+	terminal_action func;
+} KeyAction;
+
+int action_keys[] = {
+	KEY_SEQUNCE_NOT_FINISHED,
+	KEY_LEFT,
+	KEY_RIGHT,
+	KEY_HOME,
+	KEY_END,
+	KEY_DELETE,
+	KEY_CLEFT,
+	KEY_CRIGHT,
+	KEY_SUP,
+	KEY_SDOWN,
+	KEY_UP,
+	KEY_DOWN,
+	KEY_BACKSPACE,
+	KEY_INSERT,
+	KEY_PGUP,
+	KEY_PGDOWN,
+	KEY_CUP,
+	KEY_CDOWN,
+	KEY_SLEFT,
+	KEY_SRIGHT,
+	KEY_MLEFT,
+	KEY_MRIGHT,
+	KEY_MUP,
+	KEY_MDOWN,
+	KEY_STAB,
+	KEY_M_n,
+	KEY_M_p,
+	KEY_C_C,
+	KEY_C_D,
+	KEY_C_L,
+	'\t',
+	'\r',
+	'\n',
+};
 
-	switch (c) {
-	case KEY_SEQUNCE_NOT_FINISHED:
-		break;
-	case KEY_LEFT:
-		/* if not at the beginning move to previous character */
-		if (line_buf_ix <= 0)
-			break;
-		line_buf_ix--;
-		terminal_move_cursor(-1);
-		break;
-	case KEY_RIGHT:
-		/*
-		 * If not at the end, just print current character
-		 * and modify position
-		 */
-		if (line_buf_ix < line_len)
-			putchar(line_buf[line_buf_ix++]);
-		break;
-	case KEY_HOME:
-		/* move to beginning of line and update position */
-		printf("\r%s", prompt);
-		line_buf_ix = 0;
-		break;
-	case KEY_END:
-		/* if not at the end of line */
-		if (line_buf_ix < line_len) {
-			/* print everything from cursor */
-			printf("%s", line_buf + line_buf_ix);
-			/* just modify current position */
-			line_buf_ix = line_len;
-		}
-		break;
-	case KEY_DELETE:
-		terminal_delete_char();
-		break;
-	case KEY_CLEFT:
+#define NELEM(x) ((int) (sizeof(x) / sizeof((x)[0])))
+
+/*
+ * current_actions holds all recognizable kes and actions for them
+ * additional element (index 0) is used for default action
+ */
+static KeyAction current_actions[NELEM(action_keys) + 1];
+
+/* KeyAction comparator by key, for qsort and bsearch */
+static int KeyActionKeyCompare(const void *a, const void *b)
+{
+	return ((const KeyAction *) a)->key - ((const KeyAction *) b)->key;
+}
+
+/* Find action by key, NULL if no action for this key */
+static KeyAction *terminal_get_action(int key)
+{
+	KeyAction a = { .key = key };
+
+	return bsearch(&a, current_actions + 1, NELEM(action_keys), sizeof(a),
+							KeyActionKeyCompare);
+}
+
+/* Sets new set of actions to use */
+static void terminal_set_actions(const KeyAction *actions)
+{
+	int i;
+
+	/* Make map with empty function for every key */
+	for (i = 0; i < NELEM(action_keys); ++i) {
 		/*
-		 * Move by word left
-		 *
-		 * Are we at the beginning of line?
+		 * + 1 due to 0 index reserved for default action that is
+		 * called for non mapped key
 		 */
-		if (line_buf_ix <= 0)
-			break;
+		current_actions[i + 1].key = action_keys[i];
+		current_actions[i + 1].func = terminal_action_null;
+	}
+
+	/* Sort action from 1 (index 0 - default action) */
+	qsort(current_actions + 1, NELEM(action_keys), sizeof(KeyAction),
+							KeyActionKeyCompare);
+	/* Set default action (first in array) */
+	current_actions[0] = *actions++;
+
+	/* Copy rest of actions into their places */
+	for (; actions->key; ++actions) {
+		KeyAction *place = terminal_get_action(actions->key);
+
+		if (place)
+			place->func = actions->func;
+	}
+}
+
+TERMINAL_ACTION(terminal_action_left)
+{
+	/* if not at the beginning move to previous character */
+	if (line_buf_ix <= 0)
+		return;
+	line_buf_ix--;
+	terminal_move_cursor(-1);
+}
+
+TERMINAL_ACTION(terminal_action_right)
+{
+	/*
+	 * If not at the end, just print current character
+	 * and modify position
+	 */
+	if (line_buf_ix < line_len)
+		putchar(line_buf[line_buf_ix++]);
+}
+
+TERMINAL_ACTION(terminal_action_home)
+{
+	/* move to beginning of line and update position */
+	printf("\r%s", prompt);
+	line_buf_ix = 0;
+}
+
+TERMINAL_ACTION(terminal_action_end)
+{
+	/* if not at the end of line */
+	if (line_buf_ix < line_len) {
+		/* print everything from cursor */
+		printf("%s", line_buf + line_buf_ix);
+		/* just modify current position */
+		line_buf_ix = line_len;
+	}
+}
+
+TERMINAL_ACTION(terminal_action_del)
+{
+	terminal_delete_char();
+}
+
+TERMINAL_ACTION(terminal_action_word_left)
+{
+	int old_pos;
+	/*
+	 * Move by word left
+	 *
+	 * Are we at the beginning of line?
+	 */
+	if (line_buf_ix <= 0)
+		return;
 
-		old_pos = line_buf_ix;
+	old_pos = line_buf_ix;
+	line_buf_ix--;
+	/* skip spaces left */
+	while (line_buf_ix && isspace(line_buf[line_buf_ix]))
 		line_buf_ix--;
-		/* skip spaces left */
-		while (line_buf_ix && isspace(line_buf[line_buf_ix]))
-			line_buf_ix--;
-		/* skip all non spaces to the left */
-		while (line_buf_ix > 0 &&
+
+	/* skip all non spaces to the left */
+	while (line_buf_ix > 0 &&
 			!isspace(line_buf[line_buf_ix - 1]))
-			line_buf_ix--;
-		/* move cursor to new position */
-		terminal_move_cursor(line_buf_ix - old_pos);
-		break;
-	case KEY_CRIGHT:
-		/*
-		 * Move by word right
-		 *
-		 * are we at the end of line?
-		 */
-		if (line_buf_ix >= line_len)
-			break;
+		line_buf_ix--;
 
-		old_pos = line_buf_ix;
-		/* skip all spaces */
-		while (line_buf_ix < line_len &&
-			isspace(line_buf[line_buf_ix]))
-			line_buf_ix++;
-		/* skip all non spaces */
-		while (line_buf_ix < line_len &&
-			!isspace(line_buf[line_buf_ix]))
-			line_buf_ix++;
-		/*
-		 * Move cursor to right by printing text
-		 * between old cursor and new
-		 */
-		if (line_buf_ix > old_pos)
-			printf("%.*s", (int) (line_buf_ix - old_pos),
+	/* move cursor to new position */
+	terminal_move_cursor(line_buf_ix - old_pos);
+}
+
+TERMINAL_ACTION(terminal_action_word_right)
+{
+	int old_pos;
+	/*
+	 * Move by word right
+	 *
+	 * are we at the end of line?
+	 */
+	if (line_buf_ix >= line_len)
+		return;
+
+	old_pos = line_buf_ix;
+	/* skip all spaces */
+	while (line_buf_ix < line_len && isspace(line_buf[line_buf_ix]))
+		line_buf_ix++;
+
+	/* skip all non spaces */
+	while (line_buf_ix < line_len && !isspace(line_buf[line_buf_ix]))
+		line_buf_ix++;
+	/*
+	 * Move cursor to right by printing text
+	 * between old cursor and new
+	 */
+	if (line_buf_ix > old_pos)
+		printf("%.*s", (int) (line_buf_ix - old_pos),
 							line_buf + old_pos);
-		break;
-	case KEY_SUP:
-		terminal_get_line_from_history(-1);
-		break;
-	case KEY_SDOWN:
-		if (line_index > 0)
-			terminal_get_line_from_history(0);
-		break;
-	case KEY_UP:
-		terminal_get_line_from_history(line_index + 1);
-		break;
-	case KEY_DOWN:
-		if (line_index > 0)
-			terminal_get_line_from_history(line_index - 1);
-		break;
-	case '\n':
-	case '\r':
-		/*
-		 * On new line add line to history
-		 * forget history position
-		 */
-		history_add_line(line_buf);
-		line_len = 0;
-		line_buf_ix = 0;
-		line_index = -1;
-		/* print new line */
-		putchar(c);
-		prompt = "";
-		process_line(line_buf);
-		/* clear current line */
-		line_buf[0] = '\0';
-		prompt = prompt_buf;
-		printf("%s", prompt);
-		break;
-	case '\t':
-		/* tab processing */
-		process_tab(line_buf, line_buf_ix);
-		break;
-	case KEY_BACKSPACE:
-		if (line_buf_ix <= 0)
-			break;
+}
 
-		if (line_buf_ix == line_len) {
-			printf("\b \b");
-			line_len = --line_buf_ix;
-			line_buf[line_len] = 0;
-		} else {
-			putchar('\b');
-			refresh_from = --line_buf_ix;
-			line_len--;
-			memmove(line_buf + line_buf_ix,
+TERMINAL_ACTION(terminal_action_history_begin)
+{
+	terminal_get_line_from_history(-1);
+}
+
+TERMINAL_ACTION(terminal_action_history_end)
+{
+	if (line_index > 0)
+		terminal_get_line_from_history(0);
+}
+
+TERMINAL_ACTION(terminal_action_history_up)
+{
+	terminal_get_line_from_history(line_index + 1);
+}
+
+TERMINAL_ACTION(terminal_action_history_down)
+{
+	if (line_index > 0)
+		terminal_get_line_from_history(line_index - 1);
+}
+
+TERMINAL_ACTION(terminal_action_tab)
+{
+	/* tab processing */
+	process_tab(line_buf, line_buf_ix);
+}
+
+
+TERMINAL_ACTION(terminal_action_backspace)
+{
+	if (line_buf_ix <= 0)
+		return;
+
+	if (line_buf_ix == line_len) {
+		printf("\b \b");
+		line_len = --line_buf_ix;
+		line_buf[line_len] = 0;
+	} else {
+		putchar('\b');
+		line_buf_ix--;
+		line_len--;
+		memmove(line_buf + line_buf_ix,
 				line_buf + line_buf_ix + 1,
 				line_len - line_buf_ix + 1);
-		}
-		break;
-	case KEY_INSERT:
-	case KEY_PGUP:
-	case KEY_PGDOWN:
-	case KEY_CUP:
-	case KEY_CDOWN:
-	case KEY_SLEFT:
-	case KEY_SRIGHT:
-	case KEY_MLEFT:
-	case KEY_MRIGHT:
-	case KEY_MUP:
-	case KEY_MDOWN:
-	case KEY_STAB:
-	case KEY_M_n:
-		/* Search history forward */
-		terminal_match_hitory(false);
-		break;
-	case KEY_M_p:
-		/* Search history backward */
-		terminal_match_hitory(true);
-		break;
-	case KEY_C_C:
-		terminal_clear_line();
-		break;
-	case KEY_C_D:
-		if (line_len > 0) {
-			terminal_delete_char();
-		} else  {
-			puts("");
-			exit(0);
-		}
-		break;
-	case KEY_C_L:
-		terminal_clear_screen();
-		break;
-	default:
-		if (!isprint(c)) {
-			/*
-			 * TODO: remove this print once all meaningful sequences
-			 * are identified
-			 */
-			printf("char-0x%02x\n", c);
-			break;
-		}
-
-		if (line_buf_ix < LINE_BUF_MAX - 1) {
-			if (line_len == line_buf_ix) {
-				putchar(c);
-				line_buf[line_buf_ix++] = (char) c;
-				line_len++;
-				line_buf[line_len] = '\0';
-			} else {
-				memmove(line_buf + line_buf_ix + 1,
-					line_buf + line_buf_ix,
-					line_len - line_buf_ix + 1);
-				line_buf[line_buf_ix] = c;
-				refresh_from = line_buf_ix++;
-				line_len++;
-			}
-		}
-		break;
+		printf("%s \b", line_buf + line_buf_ix);
+		terminal_move_cursor(line_buf_ix - line_len);
 	}
+}
 
-	if (refresh_from >= 0) {
-		printf("%s \b", line_buf + refresh_from);
-		terminal_move_cursor(line_buf_ix - line_len);
+TERMINAL_ACTION(terminal_action_find_history_forward)
+{
+	/* Search history forward */
+	terminal_match_hitory(false);
+}
+
+TERMINAL_ACTION(terminal_action_find_history_backward)
+{
+	/* Search history forward */
+	terminal_match_hitory(true);
+}
+
+TERMINAL_ACTION(terminal_action_ctrl_c)
+{
+	terminal_clear_line();
+}
+
+TERMINAL_ACTION(terminal_action_ctrl_d)
+{
+	if (line_len > 0) {
+		terminal_delete_char();
+	} else  {
+		puts("");
+		exit(0);
 	}
+}
+
+TERMINAL_ACTION(terminal_action_clear_screen)
+{
+	terminal_clear_screen();
+}
+
+TERMINAL_ACTION(terminal_action_enter)
+{
+	/*
+	 * On new line add line to history
+	 * forget history position
+	 */
+	history_add_line(line_buf);
+	line_len = 0;
+	line_buf_ix = 0;
+	line_index = -1;
+	/* print new line */
+	putchar(c);
+	prompt = noprompt;
+	process_line(line_buf);
+	/* clear current line */
+	line_buf[0] = '\0';
+	prompt = current_prompt;
+	printf("%s", prompt);
+}
+
+TERMINAL_ACTION(terminal_action_default)
+{
+	char str[2] = { c, 0 };
+
+	if (!isprint(c))
+		/*
+		 * TODO: remove this print once all meaningful sequences
+		 * are identified
+		 */
+		printf("char-0x%02x\n", c);
+	else if (line_buf_ix < LINE_BUF_MAX - 1)
+		terminal_insert_into_command_line(str);
+}
 
-	/* Flush output after all user input */
+static KeyAction normal_actions[] = {
+	{ 0, terminal_action_default },
+	{ KEY_LEFT, terminal_action_left },
+	{ KEY_RIGHT, terminal_action_right },
+	{ KEY_HOME, terminal_action_home },
+	{ KEY_END, terminal_action_end },
+	{ KEY_DELETE, terminal_action_del },
+	{ KEY_CLEFT, terminal_action_word_left },
+	{ KEY_CRIGHT, terminal_action_word_right },
+	{ KEY_SUP, terminal_action_history_begin },
+	{ KEY_SDOWN, terminal_action_history_end },
+	{ KEY_UP, terminal_action_history_up },
+	{ KEY_DOWN, terminal_action_history_down },
+	{ '\t', terminal_action_tab },
+	{ KEY_BACKSPACE, terminal_action_backspace },
+	{ KEY_M_n, terminal_action_find_history_forward },
+	{ KEY_M_p, terminal_action_find_history_backward },
+	{ KEY_C_C, terminal_action_ctrl_c },
+	{ KEY_C_D, terminal_action_ctrl_d },
+	{ KEY_C_L, terminal_action_clear_screen },
+	{ '\r', terminal_action_enter },
+	{ '\n', terminal_action_enter },
+	{ 0, NULL },
+};
+
+void terminal_process_char(int c, line_callback process_line)
+{
+	KeyAction *a;
+
+	c = terminal_convert_sequence(c);
+
+	/* Get action for this key */
+	a = terminal_get_action(c);
+
+	/* No action found, get default one */
+	if (a == NULL)
+		a = &current_actions[0];
+
+	a->func(c, process_line);
 	fflush(stdout);
 }
 
@@ -589,6 +736,9 @@ static void terminal_cleanup(void)
 void terminal_setup(void)
 {
 	struct termios tios;
+
+	terminal_set_actions(normal_actions);
+
 	tcgetattr(0, &origianl_tios);
 	tios = origianl_tios;
 
diff --git a/android/client/terminal.h b/android/client/terminal.h
index e53750f..b5e402d 100644
--- a/android/client/terminal.h
+++ b/android/client/terminal.h
@@ -49,10 +49,12 @@ enum key_codes {
 	KEY_M_n
 };
 
+typedef void (*line_callback)(char *);
+
 void terminal_setup(void);
 int terminal_print(const char *format, ...);
 int terminal_vprint(const char *format, va_list args);
-void terminal_process_char(int c, void (*process_line)(char *line));
+void terminal_process_char(int c, line_callback process_line);
 void terminal_insert_into_command_line(const char *p);
 void terminal_draw_command_line(void);
 
-- 
1.7.9.5


^ 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