Linux bluetooth development
 help / color / mirror / Atom feed
* [PATCH v3 bluetooth-next 4/4] ieee802154: 6lowpan: rename process_data and lowpan_process_data
From: Martin Townsend @ 2014-10-23 13:12 UTC (permalink / raw)
  To: linux-bluetooth, linux-wpan
  Cc: marcel, alex.aring, jukka.rissanen, Martin Townsend
In-Reply-To: <1414069948-29731-1-git-send-email-martin.townsend@xsilon.com>

From: Martin Townsend <mtownsend1973@gmail.com>

As we have decouple decompression from data delivery we can now rename all
occurences of process_data in receive path.

Signed-off-by: Martin Townsend <mtownsend1973@gmail.com>
---
 include/net/6lowpan.h         | 10 ++++++----
 net/6lowpan/iphc.c            | 12 +++++++-----
 net/bluetooth/6lowpan.c       | 15 ++++++++-------
 net/ieee802154/6lowpan_rtnl.c | 15 ++++++++-------
 4 files changed, 29 insertions(+), 23 deletions(-)

diff --git a/include/net/6lowpan.h b/include/net/6lowpan.h
index abfa359..dc03d77 100644
--- a/include/net/6lowpan.h
+++ b/include/net/6lowpan.h
@@ -372,10 +372,12 @@ lowpan_uncompress_size(const struct sk_buff *skb, u16 *dgram_offset)
 	return skb->len + uncomp_header - ret;
 }
 
-int lowpan_process_data(struct sk_buff *skb, struct net_device *dev,
-		const u8 *saddr, const u8 saddr_type, const u8 saddr_len,
-		const u8 *daddr, const u8 daddr_type, const u8 daddr_len,
-		u8 iphc0, u8 iphc1);
+int
+lowpan_header_decompress(struct sk_buff *skb, struct net_device *dev,
+			 const u8 *saddr, const u8 saddr_type,
+			 const u8 saddr_len, const u8 *daddr,
+			 const u8 daddr_type, const u8 daddr_len,
+			 u8 iphc0, u8 iphc1);
 int lowpan_header_compress(struct sk_buff *skb, struct net_device *dev,
 			unsigned short type, const void *_daddr,
 			const void *_saddr, unsigned int len);
diff --git a/net/6lowpan/iphc.c b/net/6lowpan/iphc.c
index 45714fe..73a7065 100644
--- a/net/6lowpan/iphc.c
+++ b/net/6lowpan/iphc.c
@@ -301,10 +301,12 @@ err:
 /* TTL uncompression values */
 static const u8 lowpan_ttl_values[] = { 0, 1, 64, 255 };
 
-int lowpan_process_data(struct sk_buff *skb, struct net_device *dev,
-			const u8 *saddr, const u8 saddr_type, const u8 saddr_len,
-			const u8 *daddr, const u8 daddr_type, const u8 daddr_len,
-			u8 iphc0, u8 iphc1)
+int
+lowpan_header_decompress(struct sk_buff *skb, struct net_device *dev,
+			 const u8 *saddr, const u8 saddr_type,
+			 const u8 saddr_len, const u8 *daddr,
+			 const u8 daddr_type, const u8 daddr_len,
+			 u8 iphc0, u8 iphc1)
 {
 	struct ipv6hdr hdr = {};
 	u8 tmp, num_context = 0;
@@ -480,7 +482,7 @@ drop:
 	kfree_skb(skb);
 	return -EINVAL;
 }
-EXPORT_SYMBOL_GPL(lowpan_process_data);
+EXPORT_SYMBOL_GPL(lowpan_header_decompress);
 
 static u8 lowpan_compress_addr_64(u8 **hc_ptr, u8 shift,
 				  const struct in6_addr *ipaddr,
diff --git a/net/bluetooth/6lowpan.c b/net/bluetooth/6lowpan.c
index 40e2cec..aa6ebbf 100644
--- a/net/bluetooth/6lowpan.c
+++ b/net/bluetooth/6lowpan.c
@@ -257,8 +257,8 @@ static int give_skb_to_upper(struct sk_buff *skb, struct net_device *dev)
 	return netif_rx(skb_cp);
 }
 
-static int process_data(struct sk_buff *skb, struct net_device *netdev,
-			struct l2cap_chan *chan)
+static int iphc_decompress(struct sk_buff *skb, struct net_device *netdev,
+			   struct l2cap_chan *chan)
 {
 	const u8 *saddr, *daddr;
 	u8 iphc0, iphc1;
@@ -287,10 +287,11 @@ static int process_data(struct sk_buff *skb, struct net_device *netdev,
 	if (lowpan_fetch_skb_u8(skb, &iphc1))
 		goto drop;
 
-	return lowpan_process_data(skb, netdev,
-				   saddr, IEEE802154_ADDR_LONG, EUI64_ADDR_LEN,
-				   daddr, IEEE802154_ADDR_LONG, EUI64_ADDR_LEN,
-				   iphc0, iphc1);
+	return lowpan_header_decompress(skb, netdev,
+					saddr, IEEE802154_ADDR_LONG,
+					EUI64_ADDR_LEN, daddr,
+					IEEE802154_ADDR_LONG, EUI64_ADDR_LEN,
+					iphc0, iphc1);
 
 drop:
 	kfree_skb(skb);
@@ -346,7 +347,7 @@ static int recv_pkt(struct sk_buff *skb, struct net_device *dev,
 			if (!local_skb)
 				goto drop;
 
-			ret = process_data(local_skb, dev, chan);
+			ret = iphc_decompress(local_skb, dev, chan);
 			if (ret < 0)
 				goto drop;
 
diff --git a/net/ieee802154/6lowpan_rtnl.c b/net/ieee802154/6lowpan_rtnl.c
index 05a0a84..64ec0cd 100644
--- a/net/ieee802154/6lowpan_rtnl.c
+++ b/net/ieee802154/6lowpan_rtnl.c
@@ -166,7 +166,8 @@ static int lowpan_give_skb_to_devices(struct sk_buff *skb,
 	return stat;
 }
 
-static int process_data(struct sk_buff *skb, const struct ieee802154_hdr *hdr)
+static int
+iphc_decompress(struct sk_buff *skb, const struct ieee802154_hdr *hdr)
 {
 	u8 iphc0, iphc1;
 	struct ieee802154_addr_sa sa, da;
@@ -196,9 +197,9 @@ static int process_data(struct sk_buff *skb, const struct ieee802154_hdr *hdr)
 	else
 		dap = &da.hwaddr;
 
-	return lowpan_process_data(skb, skb->dev, sap, sa.addr_type,
-				   IEEE802154_ADDR_LEN, dap, da.addr_type,
-				   IEEE802154_ADDR_LEN, iphc0, iphc1);
+	return lowpan_header_decompress(skb, skb->dev, sap, sa.addr_type,
+					IEEE802154_ADDR_LEN, dap, da.addr_type,
+					IEEE802154_ADDR_LEN, iphc0, iphc1);
 
 drop:
 	kfree_skb(skb);
@@ -541,7 +542,7 @@ static int lowpan_rcv(struct sk_buff *skb, struct net_device *dev,
 	} else {
 		switch (skb->data[0] & 0xe0) {
 		case LOWPAN_DISPATCH_IPHC:	/* ipv6 datagram */
-			ret = process_data(skb, &hdr);
+			ret = iphc_decompress(skb, &hdr);
 			if (ret < 0)
 				goto drop;
 
@@ -549,7 +550,7 @@ static int lowpan_rcv(struct sk_buff *skb, struct net_device *dev,
 		case LOWPAN_DISPATCH_FRAG1:	/* first fragment header */
 			ret = lowpan_frag_rcv(skb, LOWPAN_DISPATCH_FRAG1);
 			if (ret == 1) {
-				ret = process_data(skb, &hdr);
+				ret = iphc_decompress(skb, &hdr);
 				if (ret < 0)
 					goto drop;
 
@@ -563,7 +564,7 @@ static int lowpan_rcv(struct sk_buff *skb, struct net_device *dev,
 		case LOWPAN_DISPATCH_FRAGN:	/* next fragments headers */
 			ret = lowpan_frag_rcv(skb, LOWPAN_DISPATCH_FRAGN);
 			if (ret == 1) {
-				ret = process_data(skb, &hdr);
+				ret = iphc_decompress(skb, &hdr);
 				if (ret < 0)
 					goto drop;
 
-- 
1.9.1

^ permalink raw reply related

* [PATCH v3 bluetooth-next 3/4] bluetooth:6lowpan: use consume_skb when packet processed successfully
From: Martin Townsend @ 2014-10-23 13:12 UTC (permalink / raw)
  To: linux-bluetooth, linux-wpan
  Cc: marcel, alex.aring, jukka.rissanen, Martin Townsend
In-Reply-To: <1414069948-29731-1-git-send-email-martin.townsend@xsilon.com>

From: Martin Townsend <mtownsend1973@gmail.com>

Signed-off-by: Martin Townsend <mtownsend1973@gmail.com>
---
 net/bluetooth/6lowpan.c | 7 ++++---
 1 file changed, 4 insertions(+), 3 deletions(-)

diff --git a/net/bluetooth/6lowpan.c b/net/bluetooth/6lowpan.c
index 94bbb66..40e2cec 100644
--- a/net/bluetooth/6lowpan.c
+++ b/net/bluetooth/6lowpan.c
@@ -337,8 +337,8 @@ static int recv_pkt(struct sk_buff *skb, struct net_device *dev,
 		dev->stats.rx_bytes += skb->len;
 		dev->stats.rx_packets++;
 
-		kfree_skb(local_skb);
-		kfree_skb(skb);
+		consume_skb(local_skb);
+		consume_skb(skb);
 	} else {
 		switch (skb->data[0] & 0xe0) {
 		case LOWPAN_DISPATCH_IPHC:	/* ipv6 datagram */
@@ -363,7 +363,8 @@ static int recv_pkt(struct sk_buff *skb, struct net_device *dev,
 			dev->stats.rx_bytes += skb->len;
 			dev->stats.rx_packets++;
 
-			kfree_skb(skb);
+			consume_skb(local_skb);
+			consume_skb(skb);
 			break;
 		default:
 			break;
-- 
1.9.1

^ permalink raw reply related

* [PATCH v3 bluetooth-next 2/4] 6lowpan: fix process_data return values
From: Martin Townsend @ 2014-10-23 13:12 UTC (permalink / raw)
  To: linux-bluetooth, linux-wpan
  Cc: marcel, alex.aring, jukka.rissanen, Martin Townsend,
	Martin Townsend
In-Reply-To: <1414069948-29731-1-git-send-email-martin.townsend@xsilon.com>

As process_data now returns just error codes fix up the calls to this
function to only drop the skb if an error code is returned.

Signed-off-by: Martin Townsend <mtownsend1973@gmail.com>
---
 net/bluetooth/6lowpan.c       | 2 +-
 net/ieee802154/6lowpan_rtnl.c | 6 +++---
 2 files changed, 4 insertions(+), 4 deletions(-)

diff --git a/net/bluetooth/6lowpan.c b/net/bluetooth/6lowpan.c
index 45d9a9f..94bbb66 100644
--- a/net/bluetooth/6lowpan.c
+++ b/net/bluetooth/6lowpan.c
@@ -347,7 +347,7 @@ static int recv_pkt(struct sk_buff *skb, struct net_device *dev,
 				goto drop;
 
 			ret = process_data(local_skb, dev, chan);
-			if (ret != NET_RX_SUCCESS)
+			if (ret < 0)
 				goto drop;
 
 			local_skb->protocol = htons(ETH_P_IPV6);
diff --git a/net/ieee802154/6lowpan_rtnl.c b/net/ieee802154/6lowpan_rtnl.c
index 473aaa3..05a0a84 100644
--- a/net/ieee802154/6lowpan_rtnl.c
+++ b/net/ieee802154/6lowpan_rtnl.c
@@ -542,7 +542,7 @@ static int lowpan_rcv(struct sk_buff *skb, struct net_device *dev,
 		switch (skb->data[0] & 0xe0) {
 		case LOWPAN_DISPATCH_IPHC:	/* ipv6 datagram */
 			ret = process_data(skb, &hdr);
-			if (ret == NET_RX_DROP)
+			if (ret < 0)
 				goto drop;
 
 			return lowpan_give_skb_to_devices(skb, NULL);
@@ -550,7 +550,7 @@ static int lowpan_rcv(struct sk_buff *skb, struct net_device *dev,
 			ret = lowpan_frag_rcv(skb, LOWPAN_DISPATCH_FRAG1);
 			if (ret == 1) {
 				ret = process_data(skb, &hdr);
-				if (ret == NET_RX_DROP)
+				if (ret < 0)
 					goto drop;
 
 				return lowpan_give_skb_to_devices(skb, NULL);
@@ -564,7 +564,7 @@ static int lowpan_rcv(struct sk_buff *skb, struct net_device *dev,
 			ret = lowpan_frag_rcv(skb, LOWPAN_DISPATCH_FRAGN);
 			if (ret == 1) {
 				ret = process_data(skb, &hdr);
-				if (ret == NET_RX_DROP)
+				if (ret < 0)
 					goto drop;
 
 				return lowpan_give_skb_to_devices(skb, NULL);
-- 
1.9.1

^ permalink raw reply related

* [PATCH v3 bluetooth-next 1/4] 6lowpan: remove skb_deliver from IPHC
From: Martin Townsend @ 2014-10-23 13:12 UTC (permalink / raw)
  To: linux-bluetooth, linux-wpan
  Cc: marcel, alex.aring, jukka.rissanen, Martin Townsend,
	Martin Townsend
In-Reply-To: <1414069948-29731-1-git-send-email-martin.townsend@xsilon.com>

Separating skb delivery from decompression ensures that we can support further
decompression schemes and removes the mixed return value of error codes with
NET_RX_FOO.

Signed-off-by: Martin Townsend <mtownsend1973@gmail.com>
---
 include/net/6lowpan.h         |  4 +---
 net/6lowpan/iphc.c            | 32 ++++++--------------------------
 net/bluetooth/6lowpan.c       | 14 ++++++++++++--
 net/ieee802154/6lowpan_rtnl.c | 39 ++++++++++++++++++++++++++-------------
 4 files changed, 45 insertions(+), 44 deletions(-)

diff --git a/include/net/6lowpan.h b/include/net/6lowpan.h
index d184df1..abfa359 100644
--- a/include/net/6lowpan.h
+++ b/include/net/6lowpan.h
@@ -372,12 +372,10 @@ lowpan_uncompress_size(const struct sk_buff *skb, u16 *dgram_offset)
 	return skb->len + uncomp_header - ret;
 }
 
-typedef int (*skb_delivery_cb)(struct sk_buff *skb, struct net_device *dev);
-
 int lowpan_process_data(struct sk_buff *skb, struct net_device *dev,
 		const u8 *saddr, const u8 saddr_type, const u8 saddr_len,
 		const u8 *daddr, const u8 daddr_type, const u8 daddr_len,
-		u8 iphc0, u8 iphc1, skb_delivery_cb skb_deliver);
+		u8 iphc0, u8 iphc1);
 int lowpan_header_compress(struct sk_buff *skb, struct net_device *dev,
 			unsigned short type, const void *_daddr,
 			const void *_saddr, unsigned int len);
diff --git a/net/6lowpan/iphc.c b/net/6lowpan/iphc.c
index 747b3cc..45714fe 100644
--- a/net/6lowpan/iphc.c
+++ b/net/6lowpan/iphc.c
@@ -171,29 +171,6 @@ static int uncompress_context_based_src_addr(struct sk_buff *skb,
 	return 0;
 }
 
-static int skb_deliver(struct sk_buff *skb, struct ipv6hdr *hdr,
-		       struct net_device *dev, skb_delivery_cb deliver_skb)
-{
-	int stat;
-
-	skb_push(skb, sizeof(struct ipv6hdr));
-	skb_reset_network_header(skb);
-	skb_copy_to_linear_data(skb, hdr, sizeof(struct ipv6hdr));
-
-	skb->protocol = htons(ETH_P_IPV6);
-	skb->pkt_type = PACKET_HOST;
-	skb->dev = dev;
-
-	raw_dump_table(__func__, "raw skb data dump before receiving",
-		       skb->data, skb->len);
-
-	stat = deliver_skb(skb, dev);
-
-	consume_skb(skb);
-
-	return stat;
-}
-
 /* Uncompress function for multicast destination address,
  * when M bit is set.
  */
@@ -327,7 +304,7 @@ static const u8 lowpan_ttl_values[] = { 0, 1, 64, 255 };
 int lowpan_process_data(struct sk_buff *skb, struct net_device *dev,
 			const u8 *saddr, const u8 saddr_type, const u8 saddr_len,
 			const u8 *daddr, const u8 daddr_type, const u8 daddr_len,
-			u8 iphc0, u8 iphc1, skb_delivery_cb deliver_skb)
+			u8 iphc0, u8 iphc1)
 {
 	struct ipv6hdr hdr = {};
 	u8 tmp, num_context = 0;
@@ -492,10 +469,13 @@ int lowpan_process_data(struct sk_buff *skb, struct net_device *dev,
 		hdr.version, ntohs(hdr.payload_len), hdr.nexthdr,
 		hdr.hop_limit, &hdr.daddr);
 
-	raw_dump_table(__func__, "raw header dump", (u8 *)&hdr, sizeof(hdr));
+	skb_push(skb, sizeof(hdr));
+	skb_reset_network_header(skb);
+	skb_copy_to_linear_data(skb, &hdr, sizeof(hdr));
 
-	return skb_deliver(skb, &hdr, dev, deliver_skb);
+	raw_dump_table(__func__, "raw header dump", (u8 *)&hdr, sizeof(hdr));
 
+	return 0;
 drop:
 	kfree_skb(skb);
 	return -EINVAL;
diff --git a/net/bluetooth/6lowpan.c b/net/bluetooth/6lowpan.c
index 6c5c2ef..45d9a9f 100644
--- a/net/bluetooth/6lowpan.c
+++ b/net/bluetooth/6lowpan.c
@@ -252,7 +252,7 @@ static int give_skb_to_upper(struct sk_buff *skb, struct net_device *dev)
 
 	skb_cp = skb_copy(skb, GFP_ATOMIC);
 	if (!skb_cp)
-		return -ENOMEM;
+		return NET_RX_DROP;
 
 	return netif_rx(skb_cp);
 }
@@ -290,7 +290,7 @@ static int process_data(struct sk_buff *skb, struct net_device *netdev,
 	return lowpan_process_data(skb, netdev,
 				   saddr, IEEE802154_ADDR_LONG, EUI64_ADDR_LEN,
 				   daddr, IEEE802154_ADDR_LONG, EUI64_ADDR_LEN,
-				   iphc0, iphc1, give_skb_to_upper);
+				   iphc0, iphc1);
 
 drop:
 	kfree_skb(skb);
@@ -350,6 +350,16 @@ static int recv_pkt(struct sk_buff *skb, struct net_device *dev,
 			if (ret != NET_RX_SUCCESS)
 				goto drop;
 
+			local_skb->protocol = htons(ETH_P_IPV6);
+			local_skb->pkt_type = PACKET_HOST;
+			local_skb->dev = dev;
+
+			if (give_skb_to_upper(local_skb, dev)
+					!= NET_RX_SUCCESS) {
+				kfree_skb(local_skb);
+				goto drop;
+			}
+
 			dev->stats.rx_bytes += skb->len;
 			dev->stats.rx_packets++;
 
diff --git a/net/ieee802154/6lowpan_rtnl.c b/net/ieee802154/6lowpan_rtnl.c
index 0c1a49b..473aaa3 100644
--- a/net/ieee802154/6lowpan_rtnl.c
+++ b/net/ieee802154/6lowpan_rtnl.c
@@ -141,20 +141,28 @@ static int lowpan_give_skb_to_devices(struct sk_buff *skb,
 	struct sk_buff *skb_cp;
 	int stat = NET_RX_SUCCESS;
 
+	skb->protocol = htons(ETH_P_IPV6);
+	skb->pkt_type = PACKET_HOST;
+
 	rcu_read_lock();
 	list_for_each_entry_rcu(entry, &lowpan_devices, list)
 		if (lowpan_dev_info(entry->ldev)->real_dev == skb->dev) {
 			skb_cp = skb_copy(skb, GFP_ATOMIC);
 			if (!skb_cp) {
-				stat = -ENOMEM;
-				break;
+				kfree_skb(skb);
+				rcu_read_unlock();
+				return NET_RX_DROP;
 			}
 
 			skb_cp->dev = entry->ldev;
 			stat = netif_rx(skb_cp);
+			if (stat == NET_RX_DROP)
+				break;
 		}
 	rcu_read_unlock();
 
+	consume_skb(skb);
+
 	return stat;
 }
 
@@ -190,8 +198,7 @@ static int process_data(struct sk_buff *skb, const struct ieee802154_hdr *hdr)
 
 	return lowpan_process_data(skb, skb->dev, sap, sa.addr_type,
 				   IEEE802154_ADDR_LEN, dap, da.addr_type,
-				   IEEE802154_ADDR_LEN, iphc0, iphc1,
-				   lowpan_give_skb_to_devices);
+				   IEEE802154_ADDR_LEN, iphc0, iphc1);
 
 drop:
 	kfree_skb(skb);
@@ -528,28 +535,29 @@ static int lowpan_rcv(struct sk_buff *skb, struct net_device *dev,
 
 	/* check that it's our buffer */
 	if (skb->data[0] == LOWPAN_DISPATCH_IPV6) {
-		skb->protocol = htons(ETH_P_IPV6);
-		skb->pkt_type = PACKET_HOST;
-
 		/* Pull off the 1-byte of 6lowpan header. */
 		skb_pull(skb, 1);
-
-		ret = lowpan_give_skb_to_devices(skb, NULL);
-		if (ret == NET_RX_DROP)
-			goto drop;
+		return lowpan_give_skb_to_devices(skb, NULL);
 	} else {
 		switch (skb->data[0] & 0xe0) {
 		case LOWPAN_DISPATCH_IPHC:	/* ipv6 datagram */
 			ret = process_data(skb, &hdr);
 			if (ret == NET_RX_DROP)
 				goto drop;
-			break;
+
+			return lowpan_give_skb_to_devices(skb, NULL);
 		case LOWPAN_DISPATCH_FRAG1:	/* first fragment header */
 			ret = lowpan_frag_rcv(skb, LOWPAN_DISPATCH_FRAG1);
 			if (ret == 1) {
 				ret = process_data(skb, &hdr);
 				if (ret == NET_RX_DROP)
 					goto drop;
+
+				return lowpan_give_skb_to_devices(skb, NULL);
+			} else if (ret == -1) {
+				return NET_RX_DROP;
+			} else {
+				return NET_RX_SUCCESS;
 			}
 			break;
 		case LOWPAN_DISPATCH_FRAGN:	/* next fragments headers */
@@ -558,6 +566,12 @@ static int lowpan_rcv(struct sk_buff *skb, struct net_device *dev,
 				ret = process_data(skb, &hdr);
 				if (ret == NET_RX_DROP)
 					goto drop;
+
+				return lowpan_give_skb_to_devices(skb, NULL);
+			} else if (ret == -1) {
+				return NET_RX_DROP;
+			} else {
+				return NET_RX_SUCCESS;
 			}
 			break;
 		default:
@@ -565,7 +579,6 @@ static int lowpan_rcv(struct sk_buff *skb, struct net_device *dev,
 		}
 	}
 
-	return NET_RX_SUCCESS;
 drop_skb:
 	kfree_skb(skb);
 drop:
-- 
1.9.1

^ permalink raw reply related

* [PATCH v3 bluetooth-next 0/4] 6lowpan: Move skb delivery out of IPHC
From: Martin Townsend @ 2014-10-23 13:12 UTC (permalink / raw)
  To: linux-bluetooth, linux-wpan
  Cc: marcel, alex.aring, jukka.rissanen, Martin Townsend

This series moves skb delivery out of IPHC and into the receive routines of
both bluetooth and 802.15.4.  The reason is that we need to support more
(de)compression schemes in the future.  It also means that calling 
lowpan_process_data now only returns error codes or 0 for success so 
this has been cleaned up.  The final patch then renames occurences of
lowpan_process_data and process_data to something more meaningful.

v1 -> v2

* Handle freeing of skb in lowpan_give_skb_to_devices for 802.15.14
* Added another skb_consume in bluetooth code for uncompressed IPv6 headers
* Added missing skb_consume for local_skb for bluetooth in compreesed IPv6 header
  path
* Combine patch 4 into 1.

v2 -> v3

* Ensure error codes aren't returned in the bluetooth skb delivery function.
* In lowpan_give_skb_to_devices return NET_RX_DROP when the first call to
  netif_rx fails.

v3 -> v4

* Fixed incorrect frag return handling due to refactoring skb_deliver.

Martin Townsend (4):
  6lowpan: remove skb_deliver from IPHC
  6lowpan: fix process_data return values
  bluetooth:6lowpan: use consume_skb when packet processed successfully
  ieee802154: 6lowpan: rename process_data and lowpan_process_data

 include/net/6lowpan.h         | 12 ++++-----
 net/6lowpan/iphc.c            | 42 +++++++++----------------------
 net/bluetooth/6lowpan.c       | 36 ++++++++++++++++++---------
 net/ieee802154/6lowpan_rtnl.c | 58 +++++++++++++++++++++++++++----------------
 4 files changed, 78 insertions(+), 70 deletions(-)

-- 
1.9.1

^ permalink raw reply

* Re: [PATCHv6 00/14] Included service discovery
From: Szymon Janc @ 2014-10-23 12:59 UTC (permalink / raw)
  To: Marcin Kraglak; +Cc: linux-bluetooth
In-Reply-To: <1414059337-12040-1-git-send-email-marcin.kraglak@tieto.com>

Hi Marcin,

On Thursday 23 of October 2014 12:15:23 Marcin Kraglak wrote:
> v3:
> In this version after primary service discovery,
> secondary services are discovered. Next included
> services are resolved. With this approach we
> don't have recursively search for included service,
> like it was TODO in previous proposal.
> There is also small coding style fix suggested by Arman.
> 
> v4:
> If no secondary services found, continue include services search (fixed
> in gatt-client.c).
> Fixed wrong debug logs (primary->secondary).
> Fixed searching descriptors
> 
> v5:
> Ignore Unsupported Group Type Error in response to secondary service
> discovery and continue included services discovery.
> 
> v6
> * Added comments to specific calculations and numbers.
> * Fixed goto labels as suggested by Szymon
> * Changed printing type of service.
> * Typo fixes pointed by Szymon
> 
> Marcin Kraglak (14):
>   shared/gatt: Add discover_secondary_services()
>   shared/gatt: Add initial implementation of discover_included_services
>   shared/gatt: Discover included services 128 bit UUIDS
>   shared/gatt: Add extra check in characteristic iterator
>   shared/gatt: Add included service iterator
>   shared/gatt: Add function bt_gatt_result_included_count()
>   shared/gatt: Remove not needed function parameter
>   shared/gatt: Distinguish Primary from Secondary services
>   tools/btgatt-client: Print type of service
>   shared/gatt: Discover secondary services
>   shared/gatt: Discover included services
>   shared/gatt: Add gatt-client include service iterator
>   tools/btgatt-client: Print found include services
>   shared/gatt: Fix searching descriptors
> 
>  src/shared/gatt-client.c  | 252 +++++++++++++++++++++++--
>  src/shared/gatt-client.h  |  18 ++
>  src/shared/gatt-helpers.c | 462 ++++++++++++++++++++++++++++++++++++++++++++--
>  src/shared/gatt-helpers.h |  10 +-
>  tools/btgatt-client.c     |  20 +-
>  5 files changed, 725 insertions(+), 37 deletions(-)
> 

All patches in this set have been applied. Thanks a lot.

-- 
Best regards, 
Szymon Janc

^ permalink raw reply

* [PATCHv6 10/14] shared/gatt: Discover secondary services
From: Marcin Kraglak @ 2014-10-23 12:36 UTC (permalink / raw)
  To: linux-bluetooth
In-Reply-To: <1414059337-12040-11-git-send-email-marcin.kraglak@tieto.com>

Add searching of secondary services in gatt-client.
---
 src/shared/gatt-client.c | 113 +++++++++++++++++++++++++++++++++++++++++------
 1 file changed, 100 insertions(+), 13 deletions(-)

diff --git a/src/shared/gatt-client.c b/src/shared/gatt-client.c
index 724fde2..acc0cb9 100644
--- a/src/shared/gatt-client.c
+++ b/src/shared/gatt-client.c
@@ -200,23 +200,36 @@ static void mark_notify_data_invalid_if_in_range(void *data, void *user_data)
 		notify_data->invalid = true;
 }
 
-static bool service_list_add_service(struct service_list **head,
-						struct service_list **tail,
-						bool primary, uint16_t start,
-						uint16_t end,
+static struct service_list *new_service_list(uint16_t start, uint16_t end,
+						bool primary,
 						uint8_t uuid[BT_GATT_UUID_SIZE])
 {
 	struct service_list *list;
 
 	list = new0(struct service_list, 1);
 	if (!list)
-		return false;
+		return NULL;
 
 	list->service.primary = primary;
 	list->service.start_handle = start;
 	list->service.end_handle = end;
 	memcpy(list->service.uuid, uuid, UUID_BYTES);
 
+	return list;
+}
+
+static bool service_list_add_service(struct service_list **head,
+						struct service_list **tail,
+						bool primary, uint16_t start,
+						uint16_t end,
+						uint8_t uuid[BT_GATT_UUID_SIZE])
+{
+	struct service_list *list;
+
+	list = new_service_list(start, end, primary, uuid);
+	if (!list)
+		return false;
+
 	if (!(*head))
 		*head = *tail = list;
 	else {
@@ -364,6 +377,8 @@ struct discovery_op {
 	struct bt_gatt_client *client;
 	struct service_list *result_head, *result_tail, *cur_service;
 	struct chrc_data *cur_chrc;
+	uint16_t start;
+	uint16_t end;
 	int cur_chrc_index;
 	int ref_count;
 	void (*complete_func)(struct discovery_op *op, bool success,
@@ -634,6 +649,75 @@ done:
 	op->complete_func(op, success, att_ecode);
 }
 
+static void discover_secondary_cb(bool success, uint8_t att_ecode,
+						struct bt_gatt_result *result,
+						void *user_data)
+{
+	struct discovery_op *op = user_data;
+	struct bt_gatt_client *client = op->client;
+	struct bt_gatt_iter iter;
+	uint16_t start, end;
+	uint8_t uuid[BT_GATT_UUID_SIZE];
+	char uuid_str[MAX_LEN_UUID_STR];
+	struct service_list *service;
+
+	if (!success) {
+		util_debug(client->debug_callback, client->debug_data,
+					"Secondary service discovery failed."
+					" ATT ECODE: 0x%02x", att_ecode);
+		switch (att_ecode) {
+		case BT_ATT_ERROR_ATTRIBUTE_NOT_FOUND:
+		case BT_ATT_ERROR_UNSUPPORTED_GROUP_TYPE:
+			goto next;
+		default:
+			goto done;
+		}
+	}
+
+	if (!result || !bt_gatt_iter_init(&iter, result))
+		goto done;
+
+	util_debug(client->debug_callback, client->debug_data,
+					"Secondary services found: %u",
+					bt_gatt_result_service_count(result));
+
+	while (bt_gatt_iter_next_service(&iter, &start, &end, uuid)) {
+		uuid_to_string(uuid, uuid_str);
+		util_debug(client->debug_callback, client->debug_data,
+				"start: 0x%04x, end: 0x%04x, uuid: %s",
+				start, end, uuid_str);
+
+		/* Store the service */
+		service = new_service_list(start, end, false, uuid);
+		if (!service) {
+			util_debug(client->debug_callback, client->debug_data,
+						"Failed to create service");
+			goto done;
+		}
+
+		service_list_insert_services(&op->result_head, &op->result_tail,
+							service, service);
+	}
+
+next:
+	/* Sequentially discover the characteristics of all services */
+	op->cur_service = op->result_head;
+	if (bt_gatt_discover_characteristics(client->att,
+					op->cur_service->service.start_handle,
+					op->cur_service->service.end_handle,
+					discover_chrcs_cb,
+					discovery_op_ref(op),
+					discovery_op_unref))
+		return;
+
+	util_debug(client->debug_callback, client->debug_data,
+				"Failed to start characteristic discovery");
+	discovery_op_unref(op);
+
+done:
+	op->complete_func(op, false, att_ecode);
+}
+
 static void discover_primary_cb(bool success, uint8_t att_ecode,
 						struct bt_gatt_result *result,
 						void *user_data)
@@ -686,18 +770,17 @@ static void discover_primary_cb(bool success, uint8_t att_ecode,
 	if (!op->result_head)
 		goto done;
 
-	/* Sequentially discover the characteristics of all services */
+	/* Discover secondary services */
 	op->cur_service = op->result_head;
-	if (bt_gatt_discover_characteristics(client->att,
-					op->cur_service->service.start_handle,
-					op->cur_service->service.end_handle,
-					discover_chrcs_cb,
-					discovery_op_ref(op),
-					discovery_op_unref))
+	if (bt_gatt_discover_secondary_services(client->att, NULL,
+							op->start, op->end,
+							discover_secondary_cb,
+							discovery_op_ref(op),
+							discovery_op_unref))
 		return;
 
 	util_debug(client->debug_callback, client->debug_data,
-				"Failed to start characteristic discovery");
+				"Failed to start secondary service discovery");
 	discovery_op_unref(op);
 	success = false;
 
@@ -870,6 +953,8 @@ static void process_service_changed(struct bt_gatt_client *client,
 
 	op->client = client;
 	op->complete_func = service_changed_complete;
+	op->start = start_handle;
+	op->end = end_handle;
 
 	if (!bt_gatt_discover_primary_services(client->att, NULL,
 						start_handle, end_handle,
@@ -1002,6 +1087,8 @@ static bool gatt_client_init(struct bt_gatt_client *client, uint16_t mtu)
 
 	op->client = client;
 	op->complete_func = init_complete;
+	op->start = 0x0001;
+	op->end = 0xffff;
 
 	/* Configure the MTU */
 	if (!bt_gatt_exchange_mtu(client->att, MAX(BT_ATT_DEFAULT_LE_MTU, mtu),
-- 
1.9.3


^ permalink raw reply related

* [PATCHv6 10/14] shared/gatt: Discover secondary services
From: Marcin Kraglak @ 2014-10-23 12:35 UTC (permalink / raw)
  To: linux-bluetooth
In-Reply-To: <1414059337-12040-11-git-send-email-marcin.kraglak@tieto.com>

Add searching of secondary services in gatt-client.
---
 src/shared/gatt-client.c | 113 +++++++++++++++++++++++++++++++++++++++++------
 1 file changed, 100 insertions(+), 13 deletions(-)

diff --git a/src/shared/gatt-client.c b/src/shared/gatt-client.c
index 724fde2..acc0cb9 100644
--- a/src/shared/gatt-client.c
+++ b/src/shared/gatt-client.c
@@ -200,23 +200,36 @@ static void mark_notify_data_invalid_if_in_range(void *data, void *user_data)
 		notify_data->invalid = true;
 }
 
-static bool service_list_add_service(struct service_list **head,
-						struct service_list **tail,
-						bool primary, uint16_t start,
-						uint16_t end,
+static struct service_list *new_service_list(uint16_t start, uint16_t end,
+						bool primary,
 						uint8_t uuid[BT_GATT_UUID_SIZE])
 {
 	struct service_list *list;
 
 	list = new0(struct service_list, 1);
 	if (!list)
-		return false;
+		return NULL;
 
 	list->service.primary = primary;
 	list->service.start_handle = start;
 	list->service.end_handle = end;
 	memcpy(list->service.uuid, uuid, UUID_BYTES);
 
+	return list;
+}
+
+static bool service_list_add_service(struct service_list **head,
+						struct service_list **tail,
+						bool primary, uint16_t start,
+						uint16_t end,
+						uint8_t uuid[BT_GATT_UUID_SIZE])
+{
+	struct service_list *list;
+
+	list = new_service_list(start, end, primary, uuid);
+	if (!list)
+		return false;
+
 	if (!(*head))
 		*head = *tail = list;
 	else {
@@ -364,6 +377,8 @@ struct discovery_op {
 	struct bt_gatt_client *client;
 	struct service_list *result_head, *result_tail, *cur_service;
 	struct chrc_data *cur_chrc;
+	uint16_t start;
+	uint16_t end;
 	int cur_chrc_index;
 	int ref_count;
 	void (*complete_func)(struct discovery_op *op, bool success,
@@ -634,6 +649,75 @@ done:
 	op->complete_func(op, success, att_ecode);
 }
 
+static void discover_secondary_cb(bool success, uint8_t att_ecode,
+						struct bt_gatt_result *result,
+						void *user_data)
+{
+	struct discovery_op *op = user_data;
+	struct bt_gatt_client *client = op->client;
+	struct bt_gatt_iter iter;
+	uint16_t start, end;
+	uint8_t uuid[BT_GATT_UUID_SIZE];
+	char uuid_str[MAX_LEN_UUID_STR];
+	struct service_list *service;
+
+	if (!success) {
+		util_debug(client->debug_callback, client->debug_data,
+					"Secondary service discovery failed."
+					" ATT ECODE: 0x%02x", att_ecode);
+		switch (att_ecode) {
+		case BT_ATT_ERROR_ATTRIBUTE_NOT_FOUND:
+		case BT_ATT_ERROR_UNSUPPORTED_GROUP_TYPE:
+			goto next;
+		default:
+			goto done;
+		}
+	}
+
+	if (!result || !bt_gatt_iter_init(&iter, result))
+		goto done;
+
+	util_debug(client->debug_callback, client->debug_data,
+					"Secondary services found: %u",
+					bt_gatt_result_service_count(result));
+
+	while (bt_gatt_iter_next_service(&iter, &start, &end, uuid)) {
+		uuid_to_string(uuid, uuid_str);
+		util_debug(client->debug_callback, client->debug_data,
+				"start: 0x%04x, end: 0x%04x, uuid: %s",
+				start, end, uuid_str);
+
+		/* Store the service */
+		service = new_service_list(start, end, false, uuid);
+		if (!service) {
+			util_debug(client->debug_callback, client->debug_data,
+						"Failed to create service");
+			goto done;
+		}
+
+		service_list_insert_services(&op->result_head, &op->result_tail,
+							service, service);
+	}
+
+next:
+	/* Sequentially discover the characteristics of all services */
+	op->cur_service = op->result_head;
+	if (bt_gatt_discover_characteristics(client->att,
+					op->cur_service->service.start_handle,
+					op->cur_service->service.end_handle,
+					discover_chrcs_cb,
+					discovery_op_ref(op),
+					discovery_op_unref))
+		return;
+
+	util_debug(client->debug_callback, client->debug_data,
+				"Failed to start characteristic discovery");
+	discovery_op_unref(op);
+
+done:
+	op->complete_func(op, false, att_ecode);
+}
+
 static void discover_primary_cb(bool success, uint8_t att_ecode,
 						struct bt_gatt_result *result,
 						void *user_data)
@@ -686,18 +770,17 @@ static void discover_primary_cb(bool success, uint8_t att_ecode,
 	if (!op->result_head)
 		goto done;
 
-	/* Sequentially discover the characteristics of all services */
+	/* Discover secondary services */
 	op->cur_service = op->result_head;
-	if (bt_gatt_discover_characteristics(client->att,
-					op->cur_service->service.start_handle,
-					op->cur_service->service.end_handle,
-					discover_chrcs_cb,
-					discovery_op_ref(op),
-					discovery_op_unref))
+	if (bt_gatt_discover_secondary_services(client->att, NULL,
+							op->start, op->end,
+							discover_secondary_cb,
+							discovery_op_ref(op),
+							discovery_op_unref))
 		return;
 
 	util_debug(client->debug_callback, client->debug_data,
-				"Failed to start characteristic discovery");
+				"Failed to start secondary service discovery");
 	discovery_op_unref(op);
 	success = false;
 
@@ -870,6 +953,8 @@ static void process_service_changed(struct bt_gatt_client *client,
 
 	op->client = client;
 	op->complete_func = service_changed_complete;
+	op->start = start_handle;
+	op->end = end_handle;
 
 	if (!bt_gatt_discover_primary_services(client->att, NULL,
 						start_handle, end_handle,
@@ -1002,6 +1087,8 @@ static bool gatt_client_init(struct bt_gatt_client *client, uint16_t mtu)
 
 	op->client = client;
 	op->complete_func = init_complete;
+	op->start = 0x0001;
+	op->end = 0xffff;
 
 	/* Configure the MTU */
 	if (!bt_gatt_exchange_mtu(client->att, MAX(BT_ATT_DEFAULT_LE_MTU, mtu),
-- 
1.9.3


^ permalink raw reply related

* Re: [bluetooth]  btusb issues
From: Andrei Emeltchenko @ 2014-10-23 12:29 UTC (permalink / raw)
  To: Patrick Shirkey; +Cc: linux-bluetooth
In-Reply-To: <49444.86.105.94.79.1414061963.squirrel@boosthardware.com>

Hi Patrick,

On Thu, Oct 23, 2014 at 09:59:23PM +1100, Patrick Shirkey wrote:
> 
> On Thu, October 23, 2014 7:59 pm, Patrick Shirkey wrote:
> > Hi,
> >
> > I have now got backports to run with bluez instead of bluedroid and the
> > btusb driver instead of rtk_btusb.
> >
> > However the android bluetooth system does not want to run for me.

So what is not working? Do you have logcat with "BlueZ" and "bluetothd" logs?

Best regards 
Andrei Emeltchenko 

> >
> 
> For reference purposes I have got bluez running on an 8723au chipset with
> the btusb driver from the "new" branch of the btusb git repo.
> 
> Here's an overview of the steps required:
> 
> - Patch the 3.4 kernel with the patch files from the aosp-bluez "misc" repo
> - Completely replace bluedroid in the android tree with bluez including
> the modifed bionic tree from the aosp-bluez repo
> - Cross compile the backports drivers replacing btusb.c with the version
> from the "new" branch in the git repo.
> - Copy the modules from the backports tree to the linux tree before
> building the firmware image. (overwrite the .ko files generated by the
> kernel build)
> - Include the firmware binary images from the git repo "new" branch in the
> android build so they are copied to the /system/etc/firmware/ folder in
> the firmware image
> - Modify the init.rc script to include the init.bluetooth.rc file
> - Modify the <platform>.mk file (in this case
> /device/softwinner/wing-k70/wing-k70.mk) to load the following modules on
> boot:
>     /system/vendor/modules/compat.ko
>     /system/vendor/modules/bluetooth.ko
>     /system/vendor/modules/btusb.ko
> 
> enable debug logging with :
> 
> setprop persist.sys.bluetooth.debug 1
> 
> 
> 
> # btmgmt info
> hci0:	addr CC:D2:9C:73:CB:45 version 6 manufacturer 93 class 0x000000
> 	supported settings: powered connectable fast-connectable discoverable
> bondable link-security ssp br/edr hs le advertising debug-keys privacy
> 	current settings: bondable ssp br/edr le
> 	name BlueZ for Android
> 	short name
> 
> 
> # haltest
> audio_hw_device_open returned -98
> hw_get_module_by_class returned -2
> thread_evt_cb: evt=ASSOCIATE_JVM
> if_bluetooth->init: BT_STATUS_SUCCESS
> get_profile_interface(handsfree) : 0xb6e58134
> get_profile_interface(a2dp) : 0xb6e580ec
> get_profile_interface(avrcp) : 0xb6e58100
> get_profile_interface(health) : 0xb6e583d0
> get_profile_interface(hidhost) : 0xb6e580a0
> get_profile_interface(pan) : 0xb6e580d0
> get_profile_interface(gatt) : 0xb6e581ac
> get_profile_interface(socket) : 0xb6e58094
> if_bluetooth->init: BT_STATUS_DONE
> if_av->init: BT_STATUS_SUCCESS
> if_rc->init: BT_STATUS_SUCCESS
> if_gatt->init: BT_STATUS_FAIL
> adapter_properties_cb: status=BT_STATUS_SUCCESS num_properties=1
> prop: type=BT_PROPERTY_UUIDS len=80 val={0000110e, 0000110c, 0000110a,
> 0000113b, 00001200}
> adapter_properties_cb: status=BT_STATUS_SUCCESS num_properties=1
> prop: type=BT_PROPERTY_UUIDS len=80 val={0000110e, 0000110c, 0000110a,
> 0000113b, 00001200}
> adapter_properties_cb: status=BT_STATUS_SUCCESS num_properties=1
> prop: type=BT_PROPERTY_UUIDS len=80 val={0000110e, 0000110c, 0000110a,
> 0000113b, 00001200}
> if_hf->init: BT_STATUS_FAIL
> if_hh->init: BT_STATUS_SUCCESS
> if_pan->init: BT_STATUS_FAIL
> adapter_properties_cb: status=BT_STATUS_SUCCESS num_properties=1
> prop: type=BT_PROPERTY_UUIDS len=80 val={0000110e, 0000110c, 0000110a,
> 0000113b, 00001200}
> adapter_properties_cb: status=BT_STATUS_SUCCESS num_properties=1
> prop: type=BT_PROPERTY_UUIDS len=80 val={0000110e, 0000110c, 0000110a,
> 0000113b, 00001200}
> if_hl->init: BT_STATUS_SUCCESS
> >
> 
> 
> # btmgmt le on
> hci0 Set Low Energy complete, settings: bondable ssp br/edr le
> # btmgmt find
> Unable to start discovery. status 0x0f (Not Powered)
> # btmgmt power on
> hci0 Set Powered complete, settings: powered bondable ssp br/edr le
> # btmgmt find
> Discovery started
> hci0 dev_found: BC:6A:29:AB:2C:AA type LE Public rssi -44 flags 0x0000 AD
> flags 0x06 eir_len 25
> 
> 
> 
> 
> 
> --
> Patrick Shirkey
> Boost Hardware Ltd
> --
> To unsubscribe from this list: send the line "unsubscribe linux-bluetooth" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply

* Re: [bluetooth]  btusb issues
From: Patrick Shirkey @ 2014-10-23 10:59 UTC (permalink / raw)
  To: linux-bluetooth
In-Reply-To: <65245.86.105.94.79.1414054796.squirrel@boosthardware.com>


On Thu, October 23, 2014 7:59 pm, Patrick Shirkey wrote:
> Hi,
>
> I have now got backports to run with bluez instead of bluedroid and the
> btusb driver instead of rtk_btusb.
>
> However the android bluetooth system does not want to run for me.
>

For reference purposes I have got bluez running on an 8723au chipset with
the btusb driver from the "new" branch of the btusb git repo.

Here's an overview of the steps required:

- Patch the 3.4 kernel with the patch files from the aosp-bluez "misc" repo
- Completely replace bluedroid in the android tree with bluez including
the modifed bionic tree from the aosp-bluez repo
- Cross compile the backports drivers replacing btusb.c with the version
from the "new" branch in the git repo.
- Copy the modules from the backports tree to the linux tree before
building the firmware image. (overwrite the .ko files generated by the
kernel build)
- Include the firmware binary images from the git repo "new" branch in the
android build so they are copied to the /system/etc/firmware/ folder in
the firmware image
- Modify the init.rc script to include the init.bluetooth.rc file
- Modify the <platform>.mk file (in this case
/device/softwinner/wing-k70/wing-k70.mk) to load the following modules on
boot:
    /system/vendor/modules/compat.ko
    /system/vendor/modules/bluetooth.ko
    /system/vendor/modules/btusb.ko

enable debug logging with :

setprop persist.sys.bluetooth.debug 1



# btmgmt info
hci0:	addr CC:D2:9C:73:CB:45 version 6 manufacturer 93 class 0x000000
	supported settings: powered connectable fast-connectable discoverable
bondable link-security ssp br/edr hs le advertising debug-keys privacy
	current settings: bondable ssp br/edr le
	name BlueZ for Android
	short name


# haltest
audio_hw_device_open returned -98
hw_get_module_by_class returned -2
thread_evt_cb: evt=ASSOCIATE_JVM
if_bluetooth->init: BT_STATUS_SUCCESS
get_profile_interface(handsfree) : 0xb6e58134
get_profile_interface(a2dp) : 0xb6e580ec
get_profile_interface(avrcp) : 0xb6e58100
get_profile_interface(health) : 0xb6e583d0
get_profile_interface(hidhost) : 0xb6e580a0
get_profile_interface(pan) : 0xb6e580d0
get_profile_interface(gatt) : 0xb6e581ac
get_profile_interface(socket) : 0xb6e58094
if_bluetooth->init: BT_STATUS_DONE
if_av->init: BT_STATUS_SUCCESS
if_rc->init: BT_STATUS_SUCCESS
if_gatt->init: BT_STATUS_FAIL
adapter_properties_cb: status=BT_STATUS_SUCCESS num_properties=1
prop: type=BT_PROPERTY_UUIDS len=80 val={0000110e, 0000110c, 0000110a,
0000113b, 00001200}
adapter_properties_cb: status=BT_STATUS_SUCCESS num_properties=1
prop: type=BT_PROPERTY_UUIDS len=80 val={0000110e, 0000110c, 0000110a,
0000113b, 00001200}
adapter_properties_cb: status=BT_STATUS_SUCCESS num_properties=1
prop: type=BT_PROPERTY_UUIDS len=80 val={0000110e, 0000110c, 0000110a,
0000113b, 00001200}
if_hf->init: BT_STATUS_FAIL
if_hh->init: BT_STATUS_SUCCESS
if_pan->init: BT_STATUS_FAIL
adapter_properties_cb: status=BT_STATUS_SUCCESS num_properties=1
prop: type=BT_PROPERTY_UUIDS len=80 val={0000110e, 0000110c, 0000110a,
0000113b, 00001200}
adapter_properties_cb: status=BT_STATUS_SUCCESS num_properties=1
prop: type=BT_PROPERTY_UUIDS len=80 val={0000110e, 0000110c, 0000110a,
0000113b, 00001200}
if_hl->init: BT_STATUS_SUCCESS
>


# btmgmt le on
hci0 Set Low Energy complete, settings: bondable ssp br/edr le
# btmgmt find
Unable to start discovery. status 0x0f (Not Powered)
# btmgmt power on
hci0 Set Powered complete, settings: powered bondable ssp br/edr le
# btmgmt find
Discovery started
hci0 dev_found: BC:6A:29:AB:2C:AA type LE Public rssi -44 flags 0x0000 AD
flags 0x06 eir_len 25





--
Patrick Shirkey
Boost Hardware Ltd

^ permalink raw reply

* Re: [PATCH v3 bluetooth-next 0/4] 6lowpan: Move skb delivery out of IPHC
From: Alexander Aring @ 2014-10-23 10:30 UTC (permalink / raw)
  To: Martin Townsend
  Cc: Martin Townsend, linux-bluetooth, linux-wpan, marcel,
	jukka.rissanen
In-Reply-To: <5448CFA8.3020604@xsilon.com>

Hi Martin,

On Thu, Oct 23, 2014 at 10:51:36AM +0100, Martin Townsend wrote:
> Hi Alex,
> 
> Looks like the SKB is now non-linear which causes the skb_put to assert.  Maybe skb_linearlize will help[0]
> 
> I'll also take a look.

yes, I did also take a fast look at:

"kernel BUG at net/core/skbuff.c:1275!"

But why occurs this now? I think you didn't change anything in this
behaviour in the sequence of skb_put, etc...



I know now why this happens, maybe I can't test it currently fast.

In file net/ieee802154/6lowpan_rtnl.c at function "lowpan_rcv"

case LOWPAN_DISPATCH_FRAG1:     /* first fragment header */
	ret = lowpan_frag_rcv(skb, LOWPAN_DISPATCH_FRAG1);
	if (ret == 1) {
		ret = iphc_decompress(skb, &hdr);
		if (ret < 0) 
			goto drop;
	}
	break;
case LOWPAN_DISPATCH_FRAGN:     /* next fragments headers */
	ret = lowpan_frag_rcv(skb, LOWPAN_DISPATCH_FRAGN);
	if (ret == 1) {
		ret = iphc_decompress(skb, &hdr);
		if (ret < 0) 
			goto drop;
	}
	break;

later you do _ALWAYS_ a "lowpan_give_skb_to_devices". But you changed
now the behaviour, because in case of LOWPAN_DISPATCH_FRAG1 or
LOWPAN_DISPATCH_FRAGN should lowpan_give_skb_to_devices only called when
lowpan_frag_rcv returns 1 and after iphc_decompress.

I think that's your problem. Always call lowpan_give_skb_to_devices
seems to be 100% wrong.

- Alex

^ permalink raw reply

* Re: [PATCHv2 1/3] bnep: Add error print and return errno instead of -1
From: Luiz Augusto von Dentz @ 2014-10-23 10:23 UTC (permalink / raw)
  To: Andrei Emeltchenko; +Cc: linux-bluetooth@vger.kernel.org
In-Reply-To: <1413984870-24023-1-git-send-email-Andrei.Emeltchenko.news@gmail.com>

Hi Andrei,

On Wed, Oct 22, 2014 at 4:34 PM, Andrei Emeltchenko
<Andrei.Emeltchenko.news@gmail.com> wrote:
> From: Andrei Emeltchenko <andrei.emeltchenko@intel.com>
>
> ---
>  profiles/network/bnep.c | 15 +++++++--------
>  1 file changed, 7 insertions(+), 8 deletions(-)
>
> diff --git a/profiles/network/bnep.c b/profiles/network/bnep.c
> index 927367c..f8fcd1f 100644
> --- a/profiles/network/bnep.c
> +++ b/profiles/network/bnep.c
> @@ -219,7 +219,7 @@ static int bnep_if_up(const char *devname)
>  static int bnep_if_down(const char *devname)
>  {
>         struct ifreq ifr;
> -       int sk, err;
> +       int sk, err = 0;
>
>         sk = socket(AF_INET, SOCK_DGRAM, 0);
>
> @@ -229,16 +229,15 @@ static int bnep_if_down(const char *devname)
>         ifr.ifr_flags &= ~IFF_UP;
>
>         /* Bring down the interface */
> -       err = ioctl(sk, SIOCSIFFLAGS, (void *) &ifr);
> +       if (ioctl(sk, SIOCSIFFLAGS, (void *) &ifr) < 0) {
> +               err = -errno;
> +               error("bnep: Could not bring down %s: %s(%d)",
> +                                               devname, strerror(-err), -err);
> +       }
>
>         close(sk);
>
> -       if (err < 0) {
> -               error("bnep: Could not bring down %s", devname);
> -               return err;
> -       }
> -
> -       return 0;
> +       return err;
>  }
>
>  static gboolean bnep_watchdog_cb(GIOChannel *chan, GIOCondition cond,
> --
> 1.9.1

Applied, thanks.

-- 
Luiz Augusto von Dentz

^ permalink raw reply

* [PATCHv6 14/14] shared/gatt: Fix searching descriptors
From: Marcin Kraglak @ 2014-10-23 10:15 UTC (permalink / raw)
  To: linux-bluetooth
In-Reply-To: <1414059337-12040-1-git-send-email-marcin.kraglak@tieto.com>

Descriptor discovery range started from characteristic value handle + 1
and end with characteristic end handle. If characteristic value handle
is 0xffff, then discovery range was set to 0x0000-0xffff.
Found during PTS test case TC_GAD_CL_BV_03_C.
---
 src/shared/gatt-client.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/src/shared/gatt-client.c b/src/shared/gatt-client.c
index 1c50d82..f884365 100644
--- a/src/shared/gatt-client.c
+++ b/src/shared/gatt-client.c
@@ -706,8 +706,8 @@ static void discover_chrcs_cb(bool success, uint8_t att_ecode,
 	for (i = 0; i < chrc_count; i++) {
 		op->cur_chrc_index = i;
 		op->cur_chrc = chrcs + i;
-		desc_start = chrcs[i].chrc_external.value_handle + 1;
-		if (desc_start > chrcs[i].chrc_external.end_handle)
+		desc_start = chrcs[i].chrc_external.value_handle;
+		if (desc_start++ == chrcs[i].chrc_external.end_handle)
 			continue;
 
 		if (bt_gatt_discover_descriptors(client->att, desc_start,
-- 
1.9.3


^ permalink raw reply related

* [PATCHv6 13/14] tools/btgatt-client: Print found include services
From: Marcin Kraglak @ 2014-10-23 10:15 UTC (permalink / raw)
  To: linux-bluetooth
In-Reply-To: <1414059337-12040-1-git-send-email-marcin.kraglak@tieto.com>

---
 tools/btgatt-client.c | 15 +++++++++++++++
 1 file changed, 15 insertions(+)

diff --git a/tools/btgatt-client.c b/tools/btgatt-client.c
index d21bc34..b7bfa24 100644
--- a/tools/btgatt-client.c
+++ b/tools/btgatt-client.c
@@ -174,7 +174,9 @@ static void print_uuid(const uint8_t uuid[16])
 static void print_service(const bt_gatt_service_t *service)
 {
 	struct bt_gatt_characteristic_iter iter;
+	struct bt_gatt_incl_service_iter include_iter;
 	const bt_gatt_characteristic_t *chrc;
+	const bt_gatt_included_service_t *incl;
 	size_t i;
 
 	if (!bt_gatt_characteristic_iter_init(&iter, service)) {
@@ -182,12 +184,25 @@ static void print_service(const bt_gatt_service_t *service)
 		return;
 	}
 
+	if (!bt_gatt_include_service_iter_init(&include_iter, service)) {
+		PRLOG("Failed to initialize include service iterator\n");
+		return;
+	}
+
 	printf(COLOR_RED "service" COLOR_OFF " - start: 0x%04x, "
 				"end: 0x%04x, type: %s, uuid: ",
 				service->start_handle, service->end_handle,
 				service->primary ? "primary" : "secondary");
 	print_uuid(service->uuid);
 
+	while (bt_gatt_include_service_iter_next(&include_iter, &incl)) {
+		printf("\t  " COLOR_GREEN "include" COLOR_OFF " - handle: "
+					"0x%04x, - start: 0x%04x, end: 0x%04x,"
+					"uuid: ", incl->handle,
+					incl->start_handle, incl->end_handle);
+		print_uuid(incl->uuid);
+	}
+
 	while (bt_gatt_characteristic_iter_next(&iter, &chrc)) {
 		printf("\t  " COLOR_YELLOW "charac" COLOR_OFF
 				" - start: 0x%04x, end: 0x%04x, "
-- 
1.9.3


^ permalink raw reply related

* [PATCHv6 12/14] shared/gatt: Add gatt-client include service iterator
From: Marcin Kraglak @ 2014-10-23 10:15 UTC (permalink / raw)
  To: linux-bluetooth
In-Reply-To: <1414059337-12040-1-git-send-email-marcin.kraglak@tieto.com>

It will allow user to take value, handle, start and end handle
of included service.
---
 src/shared/gatt-client.c | 30 ++++++++++++++++++++++++++++++
 src/shared/gatt-client.h | 10 ++++++++++
 2 files changed, 40 insertions(+)

diff --git a/src/shared/gatt-client.c b/src/shared/gatt-client.c
index b2c33e3..1c50d82 100644
--- a/src/shared/gatt-client.c
+++ b/src/shared/gatt-client.c
@@ -1666,6 +1666,36 @@ bool bt_gatt_characteristic_iter_next(struct bt_gatt_characteristic_iter *iter,
 	return true;
 }
 
+bool bt_gatt_include_service_iter_init(struct bt_gatt_incl_service_iter *iter,
+					const bt_gatt_service_t *service)
+{
+	if (!iter || !service)
+		return false;
+
+	memset(iter, 0, sizeof(*iter));
+	iter->service = (struct service_list *) service;
+
+	return true;
+}
+
+bool bt_gatt_include_service_iter_next(struct bt_gatt_incl_service_iter *iter,
+					const bt_gatt_included_service_t **incl)
+{
+	struct service_list *service;
+
+	if (!iter || !incl)
+		return false;
+
+	service = iter->service;
+
+	if (iter->pos >= service->num_includes)
+		return false;
+
+	*incl = &service->includes[iter->pos++];
+
+	return true;
+}
+
 struct read_op {
 	bt_gatt_client_read_callback_t callback;
 	void *user_data;
diff --git a/src/shared/gatt-client.h b/src/shared/gatt-client.h
index 05b4838..bf4e7bb 100644
--- a/src/shared/gatt-client.h
+++ b/src/shared/gatt-client.h
@@ -113,6 +113,11 @@ struct bt_gatt_characteristic_iter {
 	size_t pos;
 };
 
+struct bt_gatt_incl_service_iter {
+	void *service;
+	size_t pos;
+};
+
 bool bt_gatt_service_iter_init(struct bt_gatt_service_iter *iter,
 						struct bt_gatt_client *client);
 bool bt_gatt_service_iter_next(struct bt_gatt_service_iter *iter,
@@ -129,6 +134,11 @@ bool bt_gatt_characteristic_iter_init(struct bt_gatt_characteristic_iter *iter,
 bool bt_gatt_characteristic_iter_next(struct bt_gatt_characteristic_iter *iter,
 					const bt_gatt_characteristic_t **chrc);
 
+bool bt_gatt_include_service_iter_init(struct bt_gatt_incl_service_iter *iter,
+					const bt_gatt_service_t *service);
+bool bt_gatt_include_service_iter_next(struct bt_gatt_incl_service_iter *iter,
+					const bt_gatt_included_service_t **inc);
+
 typedef void (*bt_gatt_client_read_callback_t)(bool success, uint8_t att_ecode,
 					const uint8_t *value, uint16_t length,
 					void *user_data);
-- 
1.9.3


^ permalink raw reply related

* [PATCHv6 11/14] shared/gatt: Discover included services
From: Marcin Kraglak @ 2014-10-23 10:15 UTC (permalink / raw)
  To: linux-bluetooth
In-Reply-To: <1414059337-12040-1-git-send-email-marcin.kraglak@tieto.com>

---
 src/shared/gatt-client.c | 106 +++++++++++++++++++++++++++++++++++++++++++++--
 src/shared/gatt-client.h |   7 ++++
 2 files changed, 109 insertions(+), 4 deletions(-)

diff --git a/src/shared/gatt-client.c b/src/shared/gatt-client.c
index e04724c..b2c33e3 100644
--- a/src/shared/gatt-client.c
+++ b/src/shared/gatt-client.c
@@ -69,6 +69,8 @@ struct service_list {
 	bt_gatt_service_t service;
 	struct chrc_data *chrcs;
 	size_t num_chrcs;
+	bt_gatt_included_service_t *includes;
+	size_t num_includes;
 	struct service_list *next;
 };
 
@@ -253,6 +255,14 @@ static void service_destroy_characteristics(struct service_list *service)
 	free(service->chrcs);
 }
 
+static void service_destroy_includes(struct service_list *service)
+{
+	free(service->includes);
+
+	service->includes = NULL;
+	service->num_includes = 0;
+}
+
 static void service_list_clear(struct service_list **head,
 						struct service_list **tail)
 {
@@ -265,6 +275,7 @@ static void service_list_clear(struct service_list **head,
 
 	while (l) {
 		service_destroy_characteristics(l);
+		service_destroy_includes(l);
 		tmp = l;
 		l = tmp->next;
 		free(tmp);
@@ -293,6 +304,7 @@ static void service_list_clear_range(struct service_list **head,
 		}
 
 		service_destroy_characteristics(cur);
+		service_destroy_includes(cur);
 
 		if (!prev)
 			*head = cur->next;
@@ -428,6 +440,91 @@ static int uuid_cmp(const uint8_t uuid128[16], uint16_t uuid16)
 	return memcmp(uuid128, rhs_uuid, sizeof(rhs_uuid));
 }
 
+static void discover_incl_cb(bool success, uint8_t att_ecode,
+				struct bt_gatt_result *result, void *user_data)
+{
+	struct discovery_op *op = user_data;
+	struct bt_gatt_client *client = op->client;
+	struct bt_gatt_iter iter;
+	char uuid_str[MAX_LEN_UUID_STR];
+	bt_gatt_included_service_t *includes;
+	unsigned int includes_count, i;
+
+	if (!success) {
+		if (att_ecode == BT_ATT_ERROR_ATTRIBUTE_NOT_FOUND)
+			goto next;
+
+		goto failed;
+	}
+
+	if (!result || !bt_gatt_iter_init(&iter, result))
+		goto failed;
+
+	includes_count = bt_gatt_result_included_count(result);
+	if (includes_count == 0)
+		goto failed;
+
+	includes = new0(bt_gatt_included_service_t, includes_count);
+	if (!includes)
+		goto failed;
+
+	util_debug(client->debug_callback, client->debug_data,
+						"Included services found: %u",
+						includes_count);
+
+	for (i = 0; i < includes_count; i++) {
+		if (!bt_gatt_iter_next_included_service(&iter,
+						&includes[i].handle,
+						&includes[i].start_handle,
+						&includes[i].end_handle,
+						includes[i].uuid))
+			break;
+
+		uuid_to_string(includes[i].uuid, uuid_str);
+		util_debug(client->debug_callback, client->debug_data,
+				"handle: 0x%04x, start: 0x%04x, end: 0x%04x,"
+				"uuid: %s", includes[i].handle,
+				includes[i].start_handle,
+				includes[i].end_handle, uuid_str);
+	}
+
+	op->cur_service->includes = includes;
+	op->cur_service->num_includes = includes_count;
+
+next:
+	if (!op->cur_service->next) {
+		op->cur_service = op->result_head;
+		if (bt_gatt_discover_characteristics(client->att,
+					op->cur_service->service.start_handle,
+					op->cur_service->service.end_handle,
+					discover_chrcs_cb,
+					discovery_op_ref(op),
+					discovery_op_unref))
+			return;
+
+		util_debug(client->debug_callback, client->debug_data,
+				"Failed to start characteristic discovery");
+		discovery_op_unref(op);
+		goto failed;
+	}
+
+	op->cur_service = op->cur_service->next;
+	if (bt_gatt_discover_included_services(client->att,
+				op->cur_service->service.start_handle,
+				op->cur_service->service.end_handle,
+				discover_incl_cb,
+				discovery_op_ref(op),
+				discovery_op_unref))
+		return;
+
+	util_debug(client->debug_callback, client->debug_data,
+					"Failed to start included discovery");
+	discovery_op_unref(op);
+
+failed:
+	op->complete_func(op, false, att_ecode);
+}
+
 static void discover_descs_cb(bool success, uint8_t att_ecode,
 						struct bt_gatt_result *result,
 						void *user_data)
@@ -532,6 +629,7 @@ done:
 	op->complete_func(op, success, att_ecode);
 }
 
+
 static void discover_chrcs_cb(bool success, uint8_t att_ecode,
 						struct bt_gatt_result *result,
 						void *user_data)
@@ -703,18 +801,18 @@ static void discover_secondary_cb(bool success, uint8_t att_ecode,
 	}
 
 next:
-	/* Sequentially discover the characteristics of all services */
+	/* Sequentially discover included services */
 	op->cur_service = op->result_head;
-	if (bt_gatt_discover_characteristics(client->att,
+	if (bt_gatt_discover_included_services(client->att,
 					op->cur_service->service.start_handle,
 					op->cur_service->service.end_handle,
-					discover_chrcs_cb,
+					discover_incl_cb,
 					discovery_op_ref(op),
 					discovery_op_unref))
 		return;
 
 	util_debug(client->debug_callback, client->debug_data,
-				"Failed to start characteristic discovery");
+				"Failed to start included services discovery");
 	discovery_op_unref(op);
 	success = false;
 
diff --git a/src/shared/gatt-client.h b/src/shared/gatt-client.h
index 22d4dc0..05b4838 100644
--- a/src/shared/gatt-client.h
+++ b/src/shared/gatt-client.h
@@ -96,6 +96,13 @@ typedef struct {
 	size_t num_descs;
 } bt_gatt_characteristic_t;
 
+typedef struct {
+	uint16_t handle;
+	uint16_t start_handle;
+	uint16_t end_handle;
+	uint8_t uuid[BT_GATT_UUID_SIZE];
+} bt_gatt_included_service_t;
+
 struct bt_gatt_service_iter {
 	struct bt_gatt_client *client;
 	void *ptr;
-- 
1.9.3


^ permalink raw reply related

* [PATCHv6 10/14] shared/gatt: Discover secondary services
From: Marcin Kraglak @ 2014-10-23 10:15 UTC (permalink / raw)
  To: linux-bluetooth
In-Reply-To: <1414059337-12040-1-git-send-email-marcin.kraglak@tieto.com>

Add searching of secondary services in gatt-client.
---
 src/shared/gatt-client.c | 117 +++++++++++++++++++++++++++++++++++++++++------
 1 file changed, 104 insertions(+), 13 deletions(-)

diff --git a/src/shared/gatt-client.c b/src/shared/gatt-client.c
index 724fde2..e04724c 100644
--- a/src/shared/gatt-client.c
+++ b/src/shared/gatt-client.c
@@ -200,23 +200,36 @@ static void mark_notify_data_invalid_if_in_range(void *data, void *user_data)
 		notify_data->invalid = true;
 }
 
-static bool service_list_add_service(struct service_list **head,
-						struct service_list **tail,
-						bool primary, uint16_t start,
-						uint16_t end,
+static struct service_list *new_service_list(uint16_t start, uint16_t end,
+						bool primary,
 						uint8_t uuid[BT_GATT_UUID_SIZE])
 {
 	struct service_list *list;
 
 	list = new0(struct service_list, 1);
 	if (!list)
-		return false;
+		return NULL;
 
 	list->service.primary = primary;
 	list->service.start_handle = start;
 	list->service.end_handle = end;
 	memcpy(list->service.uuid, uuid, UUID_BYTES);
 
+	return list;
+}
+
+static bool service_list_add_service(struct service_list **head,
+						struct service_list **tail,
+						bool primary, uint16_t start,
+						uint16_t end,
+						uint8_t uuid[BT_GATT_UUID_SIZE])
+{
+	struct service_list *list;
+
+	list = new_service_list(start, end, primary, uuid);
+	if (!list)
+		return false;
+
 	if (!(*head))
 		*head = *tail = list;
 	else {
@@ -364,6 +377,8 @@ struct discovery_op {
 	struct bt_gatt_client *client;
 	struct service_list *result_head, *result_tail, *cur_service;
 	struct chrc_data *cur_chrc;
+	uint16_t start;
+	uint16_t end;
 	int cur_chrc_index;
 	int ref_count;
 	void (*complete_func)(struct discovery_op *op, bool success,
@@ -634,6 +649,79 @@ done:
 	op->complete_func(op, success, att_ecode);
 }
 
+static void discover_secondary_cb(bool success, uint8_t att_ecode,
+						struct bt_gatt_result *result,
+						void *user_data)
+{
+	struct discovery_op *op = user_data;
+	struct bt_gatt_client *client = op->client;
+	struct bt_gatt_iter iter;
+	uint16_t start, end;
+	uint8_t uuid[BT_GATT_UUID_SIZE];
+	char uuid_str[MAX_LEN_UUID_STR];
+	struct service_list *service;
+
+	if (!success) {
+		util_debug(client->debug_callback, client->debug_data,
+					"Secondary service discovery failed."
+					" ATT ECODE: 0x%02x", att_ecode);
+		switch (att_ecode) {
+		case BT_ATT_ERROR_ATTRIBUTE_NOT_FOUND:
+		case BT_ATT_ERROR_UNSUPPORTED_GROUP_TYPE:
+			goto next;
+		default:
+			goto done;
+		}
+	}
+
+	if (!result || !bt_gatt_iter_init(&iter, result)) {
+		success = false;
+		goto done;
+	}
+
+	util_debug(client->debug_callback, client->debug_data,
+					"Secondary services found: %u",
+					bt_gatt_result_service_count(result));
+
+	while (bt_gatt_iter_next_service(&iter, &start, &end, uuid)) {
+		uuid_to_string(uuid, uuid_str);
+		util_debug(client->debug_callback, client->debug_data,
+				"start: 0x%04x, end: 0x%04x, uuid: %s",
+				start, end, uuid_str);
+
+		/* Store the service */
+		service = new_service_list(start, end, false, uuid);
+		if (!service) {
+			util_debug(client->debug_callback, client->debug_data,
+						"Failed to create service");
+			success = false;
+			goto done;
+		}
+
+		service_list_insert_services(&op->result_head, &op->result_tail,
+							service, service);
+	}
+
+next:
+	/* Sequentially discover the characteristics of all services */
+	op->cur_service = op->result_head;
+	if (bt_gatt_discover_characteristics(client->att,
+					op->cur_service->service.start_handle,
+					op->cur_service->service.end_handle,
+					discover_chrcs_cb,
+					discovery_op_ref(op),
+					discovery_op_unref))
+		return;
+
+	util_debug(client->debug_callback, client->debug_data,
+				"Failed to start characteristic discovery");
+	discovery_op_unref(op);
+	success = false;
+
+done:
+	op->complete_func(op, success, att_ecode);
+}
+
 static void discover_primary_cb(bool success, uint8_t att_ecode,
 						struct bt_gatt_result *result,
 						void *user_data)
@@ -686,18 +774,17 @@ static void discover_primary_cb(bool success, uint8_t att_ecode,
 	if (!op->result_head)
 		goto done;
 
-	/* Sequentially discover the characteristics of all services */
+	/* Discover secondary services */
 	op->cur_service = op->result_head;
-	if (bt_gatt_discover_characteristics(client->att,
-					op->cur_service->service.start_handle,
-					op->cur_service->service.end_handle,
-					discover_chrcs_cb,
-					discovery_op_ref(op),
-					discovery_op_unref))
+	if (bt_gatt_discover_secondary_services(client->att, NULL,
+							op->start, op->end,
+							discover_secondary_cb,
+							discovery_op_ref(op),
+							discovery_op_unref))
 		return;
 
 	util_debug(client->debug_callback, client->debug_data,
-				"Failed to start characteristic discovery");
+				"Failed to start secondary service discovery");
 	discovery_op_unref(op);
 	success = false;
 
@@ -870,6 +957,8 @@ static void process_service_changed(struct bt_gatt_client *client,
 
 	op->client = client;
 	op->complete_func = service_changed_complete;
+	op->start = start_handle;
+	op->end = end_handle;
 
 	if (!bt_gatt_discover_primary_services(client->att, NULL,
 						start_handle, end_handle,
@@ -1002,6 +1091,8 @@ static bool gatt_client_init(struct bt_gatt_client *client, uint16_t mtu)
 
 	op->client = client;
 	op->complete_func = init_complete;
+	op->start = 0x0001;
+	op->end = 0xffff;
 
 	/* Configure the MTU */
 	if (!bt_gatt_exchange_mtu(client->att, MAX(BT_ATT_DEFAULT_LE_MTU, mtu),
-- 
1.9.3


^ permalink raw reply related

* [PATCHv6 09/14] tools/btgatt-client: Print type of service
From: Marcin Kraglak @ 2014-10-23 10:15 UTC (permalink / raw)
  To: linux-bluetooth
In-Reply-To: <1414059337-12040-1-git-send-email-marcin.kraglak@tieto.com>

---
 tools/btgatt-client.c | 5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)

diff --git a/tools/btgatt-client.c b/tools/btgatt-client.c
index d900e08..d21bc34 100644
--- a/tools/btgatt-client.c
+++ b/tools/btgatt-client.c
@@ -183,8 +183,9 @@ static void print_service(const bt_gatt_service_t *service)
 	}
 
 	printf(COLOR_RED "service" COLOR_OFF " - start: 0x%04x, "
-				"end: 0x%04x, uuid: ",
-				service->start_handle, service->end_handle);
+				"end: 0x%04x, type: %s, uuid: ",
+				service->start_handle, service->end_handle,
+				service->primary ? "primary" : "secondary");
 	print_uuid(service->uuid);
 
 	while (bt_gatt_characteristic_iter_next(&iter, &chrc)) {
-- 
1.9.3


^ permalink raw reply related

* [PATCHv6 08/14] shared/gatt: Distinguish Primary from Secondary services
From: Marcin Kraglak @ 2014-10-23 10:15 UTC (permalink / raw)
  To: linux-bluetooth
In-Reply-To: <1414059337-12040-1-git-send-email-marcin.kraglak@tieto.com>

Add flag primary to distinguish service as primary or secondary.
---
 src/shared/gatt-client.c | 7 +++++--
 src/shared/gatt-client.h | 1 +
 2 files changed, 6 insertions(+), 2 deletions(-)

diff --git a/src/shared/gatt-client.c b/src/shared/gatt-client.c
index 03d722f..724fde2 100644
--- a/src/shared/gatt-client.c
+++ b/src/shared/gatt-client.c
@@ -202,7 +202,8 @@ static void mark_notify_data_invalid_if_in_range(void *data, void *user_data)
 
 static bool service_list_add_service(struct service_list **head,
 						struct service_list **tail,
-						uint16_t start, uint16_t end,
+						bool primary, uint16_t start,
+						uint16_t end,
 						uint8_t uuid[BT_GATT_UUID_SIZE])
 {
 	struct service_list *list;
@@ -211,6 +212,7 @@ static bool service_list_add_service(struct service_list **head,
 	if (!list)
 		return false;
 
+	list->service.primary = primary;
 	list->service.start_handle = start;
 	list->service.end_handle = end;
 	memcpy(list->service.uuid, uuid, UUID_BYTES);
@@ -668,7 +670,8 @@ static void discover_primary_cb(bool success, uint8_t att_ecode,
 
 		/* Store the service */
 		if (!service_list_add_service(&op->result_head,
-					&op->result_tail, start, end, uuid)) {
+					&op->result_tail, true, start, end,
+					uuid)) {
 			util_debug(client->debug_callback, client->debug_data,
 						"Failed to store service");
 			success = false;
diff --git a/src/shared/gatt-client.h b/src/shared/gatt-client.h
index 6807f6b..22d4dc0 100644
--- a/src/shared/gatt-client.h
+++ b/src/shared/gatt-client.h
@@ -75,6 +75,7 @@ bool bt_gatt_client_set_debug(struct bt_gatt_client *client,
 					bt_gatt_client_destroy_func_t destroy);
 
 typedef struct {
+	bool primary;
 	uint16_t start_handle;
 	uint16_t end_handle;
 	uint8_t uuid[BT_GATT_UUID_SIZE];
-- 
1.9.3


^ permalink raw reply related

* [PATCHv6 07/14] shared/gatt: Remove not needed function parameter
From: Marcin Kraglak @ 2014-10-23 10:15 UTC (permalink / raw)
  To: linux-bluetooth
In-Reply-To: <1414059337-12040-1-git-send-email-marcin.kraglak@tieto.com>

According to SPEC 4.1 4.5.1 "Find Included Services" there is no need
to pass UUID to discover_included_services() function.
---
 src/shared/gatt-helpers.c | 1 -
 src/shared/gatt-helpers.h | 1 -
 2 files changed, 2 deletions(-)

diff --git a/src/shared/gatt-helpers.c b/src/shared/gatt-helpers.c
index f993243..d751d5a 100644
--- a/src/shared/gatt-helpers.c
+++ b/src/shared/gatt-helpers.c
@@ -1067,7 +1067,6 @@ failed:
 
 bool bt_gatt_discover_included_services(struct bt_att *att,
 					uint16_t start, uint16_t end,
-					bt_uuid_t *uuid,
 					bt_gatt_discovery_callback_t callback,
 					void *user_data,
 					bt_gatt_destroy_func_t destroy)
diff --git a/src/shared/gatt-helpers.h b/src/shared/gatt-helpers.h
index df003ac..07c145d 100644
--- a/src/shared/gatt-helpers.h
+++ b/src/shared/gatt-helpers.h
@@ -83,7 +83,6 @@ bool bt_gatt_discover_secondary_services(struct bt_att *att, bt_uuid_t *uuid,
 					bt_gatt_destroy_func_t destroy);
 bool bt_gatt_discover_included_services(struct bt_att *att,
 					uint16_t start, uint16_t end,
-					bt_uuid_t *uuid,
 					bt_gatt_discovery_callback_t callback,
 					void *user_data,
 					bt_gatt_destroy_func_t destroy);
-- 
1.9.3


^ permalink raw reply related

* [PATCHv6 06/14] shared/gatt: Add function bt_gatt_result_included_count()
From: Marcin Kraglak @ 2014-10-23 10:15 UTC (permalink / raw)
  To: linux-bluetooth
In-Reply-To: <1414059337-12040-1-git-send-email-marcin.kraglak@tieto.com>

It will return number of included services in result.
---
 src/shared/gatt-helpers.c | 28 ++++++++++++++++++++++++++++
 src/shared/gatt-helpers.h |  1 +
 2 files changed, 29 insertions(+)

diff --git a/src/shared/gatt-helpers.c b/src/shared/gatt-helpers.c
index 1516e79..f993243 100644
--- a/src/shared/gatt-helpers.c
+++ b/src/shared/gatt-helpers.c
@@ -147,6 +147,34 @@ unsigned int bt_gatt_result_descriptor_count(struct bt_gatt_result *result)
 	return result_element_count(result);
 }
 
+unsigned int bt_gatt_result_included_count(struct bt_gatt_result *result)
+{
+	struct bt_gatt_result *cur;
+	unsigned int count = 0;
+
+	if (!result)
+		return 0;
+
+	if (result->opcode != BT_ATT_OP_READ_BY_TYPE_RSP)
+		return 0;
+
+	/*
+	 * Data length can be of length 6 or 8 octets:
+	 * 2 octets - include service handle
+	 * 2 octets - start handle of included service
+	 * 2 octets - end handle of included service
+	 * 2 octets (optionally) - 16 bit Bluetooth UUID
+	 */
+	if (result->data_len != 6 && result->data_len != 8)
+		return 0;
+
+	for (cur = result; cur; cur = cur->next)
+		if (cur->opcode == BT_ATT_OP_READ_BY_TYPE_RSP)
+			count += cur->pdu_len / cur->data_len;
+
+	return count;
+}
+
 bool bt_gatt_iter_init(struct bt_gatt_iter *iter, struct bt_gatt_result *result)
 {
 	if (!iter || !result)
diff --git a/src/shared/gatt-helpers.h b/src/shared/gatt-helpers.h
index 8c434c1..df003ac 100644
--- a/src/shared/gatt-helpers.h
+++ b/src/shared/gatt-helpers.h
@@ -38,6 +38,7 @@ struct bt_gatt_iter {
 unsigned int bt_gatt_result_service_count(struct bt_gatt_result *result);
 unsigned int bt_gatt_result_characteristic_count(struct bt_gatt_result *result);
 unsigned int bt_gatt_result_descriptor_count(struct bt_gatt_result *result);
+unsigned int bt_gatt_result_included_count(struct bt_gatt_result *result);
 
 bool bt_gatt_iter_init(struct bt_gatt_iter *iter, struct bt_gatt_result *result);
 bool bt_gatt_iter_next_service(struct bt_gatt_iter *iter,
-- 
1.9.3


^ permalink raw reply related

* [PATCHv6 05/14] shared/gatt: Add included service iterator
From: Marcin Kraglak @ 2014-10-23 10:15 UTC (permalink / raw)
  To: linux-bluetooth
In-Reply-To: <1414059337-12040-1-git-send-email-marcin.kraglak@tieto.com>

It will fetch included services from result.
---
 src/shared/gatt-helpers.c | 74 +++++++++++++++++++++++++++++++++++++++++++++++
 src/shared/gatt-helpers.h |  3 ++
 2 files changed, 77 insertions(+)

diff --git a/src/shared/gatt-helpers.c b/src/shared/gatt-helpers.c
index 0dbd999..1516e79 100644
--- a/src/shared/gatt-helpers.c
+++ b/src/shared/gatt-helpers.c
@@ -193,6 +193,80 @@ struct discovery_op {
 	bt_gatt_destroy_func_t destroy;
 };
 
+bool bt_gatt_iter_next_included_service(struct bt_gatt_iter *iter,
+				uint16_t *handle, uint16_t *start_handle,
+				uint16_t *end_handle, uint8_t uuid[16])
+{
+	struct bt_gatt_result *read_result;
+	const void *pdu_ptr;
+	int i = 0;
+
+	if (!iter || !iter->result || !handle || !start_handle || !end_handle
+								|| !uuid)
+		return false;
+
+	if (iter->result->opcode != BT_ATT_OP_READ_BY_TYPE_RSP)
+		return false;
+
+	/*
+	 * iter->result points to READ_BY_TYPE_RSP with data length containing:
+	 * 2 octets - include service handle
+	 * 2 octets - start handle of included service
+	 * 2 octets - end handle of included service
+	 * optional 2  octets - Bluetooth UUID
+	 */
+	if (iter->result->data_len != 8 && iter->result->data_len != 6)
+		return false;
+
+	pdu_ptr = iter->result->pdu + iter->pos;
+
+	/* This result contains 16 bit UUID */
+	if (iter->result->data_len == 8) {
+		*handle = get_le16(pdu_ptr);
+		*start_handle = get_le16(pdu_ptr + 2);
+		*end_handle = get_le16(pdu_ptr + 4);
+		convert_uuid_le(pdu_ptr + 6, 2, uuid);
+
+		iter->pos += iter->result->data_len;
+
+		if (iter->pos == iter->result->pdu_len) {
+			iter->result = iter->result->next;
+			iter->pos = 0;
+		}
+
+		return true;
+	}
+
+	*handle = get_le16(pdu_ptr);
+	*start_handle = get_le16(pdu_ptr + 2);
+	*end_handle = get_le16(pdu_ptr + 4);
+	read_result = iter->result;
+
+	/*
+	 * Find READ_RSP with include service UUID.
+	 * If number of current data set in READ_BY_TYPE_RSP is n, then we must
+	 * go to n'th PDU next to current item->result
+	 */
+	for (read_result = read_result->next; read_result; i++) {
+		if (i >= (iter->pos / iter->result->data_len))
+			break;
+
+		read_result = read_result->next;
+	}
+
+	if (!read_result)
+		return false;
+
+	convert_uuid_le(read_result->pdu, read_result->data_len, uuid);
+	iter->pos += iter->result->data_len;
+	if (iter->pos == iter->result->pdu_len) {
+		iter->result = read_result->next;
+		iter->pos = 0;
+	}
+
+	return true;
+}
+
 bool bt_gatt_iter_next_service(struct bt_gatt_iter *iter,
 				uint16_t *start_handle, uint16_t *end_handle,
 				uint8_t uuid[16])
diff --git a/src/shared/gatt-helpers.h b/src/shared/gatt-helpers.h
index 8a25dea..8c434c1 100644
--- a/src/shared/gatt-helpers.h
+++ b/src/shared/gatt-helpers.h
@@ -49,6 +49,9 @@ bool bt_gatt_iter_next_characteristic(struct bt_gatt_iter *iter,
 				uint8_t uuid[16]);
 bool bt_gatt_iter_next_descriptor(struct bt_gatt_iter *iter, uint16_t *handle,
 							uint8_t uuid[16]);
+bool bt_gatt_iter_next_included_service(struct bt_gatt_iter *iter,
+				uint16_t *handle, uint16_t *start_handle,
+				uint16_t *end_handle, uint8_t uuid[16]);
 
 typedef void (*bt_gatt_destroy_func_t)(void *user_data);
 
-- 
1.9.3


^ permalink raw reply related

* [PATCHv6 04/14] shared/gatt: Add extra check in characteristic iterator
From: Marcin Kraglak @ 2014-10-23 10:15 UTC (permalink / raw)
  To: linux-bluetooth
In-Reply-To: <1414059337-12040-1-git-send-email-marcin.kraglak@tieto.com>

Avoid incorrect reading of included service discovery results.
---
 src/shared/gatt-helpers.c | 20 ++++++++++++++++++++
 1 file changed, 20 insertions(+)

diff --git a/src/shared/gatt-helpers.c b/src/shared/gatt-helpers.c
index d689c56..0dbd999 100644
--- a/src/shared/gatt-helpers.c
+++ b/src/shared/gatt-helpers.c
@@ -123,6 +123,16 @@ unsigned int bt_gatt_result_characteristic_count(struct bt_gatt_result *result)
 	if (result->opcode != BT_ATT_OP_READ_BY_TYPE_RSP)
 		return 0;
 
+	/*
+	 * Data length contains 7 or 21 octets:
+	 * 2 octets: Attribute handle
+	 * 1 octet: Characteristic properties
+	 * 2 octets: Characteristic value handle
+	 * 2 or 16 octets: characteristic UUID
+	 */
+	if (result->data_len != 21 && result->data_len != 7)
+		return 0;
+
 	return result_element_count(result);
 }
 
@@ -239,6 +249,16 @@ bool bt_gatt_iter_next_characteristic(struct bt_gatt_iter *iter,
 	if (iter->result->opcode != BT_ATT_OP_READ_BY_TYPE_RSP)
 		return false;
 
+	/*
+	 * Data length contains 7 or 21 octets:
+	 * 2 octets: Attribute handle
+	 * 1 octet: Characteristic properties
+	 * 2 octets: Characteristic value handle
+	 * 2 or 16 octets: characteristic UUID
+	 */
+	if (iter->result->data_len != 21 && iter->result->data_len != 7)
+		return false;
+
 	op = iter->result->op;
 	pdu_ptr = iter->result->pdu + iter->pos;
 
-- 
1.9.3


^ permalink raw reply related

* [PATCHv6 03/14] shared/gatt: Discover included services 128 bit UUIDS
From: Marcin Kraglak @ 2014-10-23 10:15 UTC (permalink / raw)
  To: linux-bluetooth
In-Reply-To: <1414059337-12040-1-git-send-email-marcin.kraglak@tieto.com>

If included services has 128 bit UUID, it won't be returned in
READ_BY_TYPE_RSP. To get UUID READ_REQUEST is used.
This procedure is described in CORE SPEC 4.5.1 "Find Included Services".
---
 src/shared/gatt-helpers.c | 167 +++++++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 166 insertions(+), 1 deletion(-)

diff --git a/src/shared/gatt-helpers.c b/src/shared/gatt-helpers.c
index 4cc483a..d689c56 100644
--- a/src/shared/gatt-helpers.c
+++ b/src/shared/gatt-helpers.c
@@ -692,6 +692,157 @@ bool bt_gatt_discover_secondary_services(struct bt_att *att, bt_uuid_t *uuid,
 								destroy, false);
 }
 
+struct read_incl_data {
+	struct discovery_op *op;
+	struct bt_gatt_result *result;
+	int pos;
+	int ref_count;
+};
+
+static struct read_incl_data *new_read_included(struct bt_gatt_result *res)
+{
+	struct read_incl_data *data;
+
+	data = new0(struct read_incl_data, 1);
+	if (!data)
+		return NULL;
+
+	data->op = discovery_op_ref(res->op);
+	data->result = res;
+
+	return data;
+};
+
+static struct read_incl_data *read_included_ref(struct read_incl_data *data)
+{
+	__sync_fetch_and_add(&data->ref_count, 1);
+
+	return data;
+}
+
+static void read_included_unref(void *data)
+{
+	struct read_incl_data *read_data = data;
+
+	if (__sync_sub_and_fetch(&read_data->ref_count, 1))
+		return;
+
+	discovery_op_unref(read_data->op);
+
+	free(read_data);
+}
+
+static void discover_included_cb(uint8_t opcode, const void *pdu,
+					uint16_t length, void *user_data);
+
+static void read_included_cb(uint8_t opcode, const void *pdu,
+					uint16_t length, void *user_data)
+{
+	struct read_incl_data *data = user_data;
+	struct bt_gatt_result *final_result = NULL;
+	struct discovery_op *op = data->op;
+	struct bt_gatt_result *cur_result;
+	uint8_t att_ecode = 0;
+	uint8_t read_pdu[2];
+	bool success;
+
+	if (opcode == BT_ATT_OP_ERROR_RSP) {
+		success = false;
+		att_ecode = process_error(pdu, length);
+		goto done;
+	}
+
+	if (opcode != BT_ATT_OP_READ_RSP || (!pdu && length)) {
+		success = false;
+		goto done;
+	}
+
+	/*
+	 * UUID should be in 128 bit format, as it couldn't be read in
+	 * READ_BY_TYPE request
+	 */
+	if (length != 16) {
+		success = false;
+		goto done;
+	}
+
+	cur_result = result_create(opcode, pdu, length, length, op);
+	if (!cur_result) {
+		success = false;
+		goto done;
+	}
+
+	if (!op->result_head) {
+		op->result_head = op->result_tail = cur_result;
+	} else {
+		op->result_tail->next = cur_result;
+		op->result_tail = cur_result;
+	}
+
+	if (data->pos == data->result->pdu_len) {
+		uint16_t last_handle;
+		uint8_t pdu[6];
+
+		last_handle = get_le16(data->result->pdu + data->pos -
+							data->result->data_len);
+		if (last_handle == op->end_handle) {
+			final_result = op->result_head;
+			success = true;
+			goto done;
+		}
+
+		put_le16(last_handle + 1, pdu);
+		put_le16(op->end_handle, pdu + 2);
+		put_le16(GATT_INCLUDE_UUID, pdu + 4);
+
+		if (bt_att_send(op->att, BT_ATT_OP_READ_BY_TYPE_REQ,
+				pdu, sizeof(pdu), discover_included_cb,
+				discovery_op_ref(op), discovery_op_unref))
+			return;
+
+		discovery_op_unref(op);
+		success = false;
+		goto done;
+	}
+
+	memcpy(read_pdu, data->result->pdu + data->pos + 2, sizeof(uint16_t));
+
+	data->pos += data->result->data_len;
+
+	if (bt_att_send(op->att, BT_ATT_OP_READ_REQ, read_pdu, sizeof(read_pdu),
+				read_included_cb, read_included_ref(data),
+				read_included_unref))
+		return;
+
+	read_included_unref(data);
+	success = false;
+
+done:
+	if (op->callback)
+		op->callback(success, att_ecode, final_result, op->user_data);
+}
+
+static void read_included(struct read_incl_data *data)
+{
+	struct discovery_op *op = data->op;
+	uint8_t pdu[2];
+
+	memcpy(pdu, data->result->pdu + 2, sizeof(uint16_t));
+
+	data->pos += data->result->data_len;
+
+	if (bt_att_send(op->att, BT_ATT_OP_READ_REQ, pdu, sizeof(pdu),
+							read_included_cb,
+							read_included_ref(data),
+							read_included_unref))
+		return;
+
+	read_included_unref(data);
+
+	if (op->callback)
+		op->callback(false, 0, NULL, data->op->user_data);
+}
+
 static void discover_included_cb(uint8_t opcode, const void *pdu,
 					uint16_t length, void *user_data)
 {
@@ -730,7 +881,8 @@ static void discover_included_cb(uint8_t opcode, const void *pdu,
 	 * 2 octets - end handle of included service
 	 * optional 2 octets - Bluetooth UUID of included service
 	 */
-	if (data_length != 8 || (length - 1) % data_length) {
+	if ((data_length != 8 && data_length != 6) ||
+						(length - 1) % data_length) {
 		success = false;
 		goto failed;
 	}
@@ -749,6 +901,19 @@ static void discover_included_cb(uint8_t opcode, const void *pdu,
 		op->result_tail = cur_result;
 	}
 
+	if (data_length == 6) {
+		struct read_incl_data *data;
+
+		data = new_read_included(cur_result);
+		if (!data) {
+			success = false;
+			goto done;
+		}
+
+		read_included(data);
+		return;
+	}
+
 	last_handle = get_le16(pdu + length - data_length);
 	if (last_handle != op->end_handle) {
 		uint8_t pdu[6];
-- 
1.9.3


^ permalink raw reply related

* [PATCHv6 02/14] shared/gatt: Add initial implementation of discover_included_services
From: Marcin Kraglak @ 2014-10-23 10:15 UTC (permalink / raw)
  To: linux-bluetooth
In-Reply-To: <1414059337-12040-1-git-send-email-marcin.kraglak@tieto.com>

Current implementation allow to discover included services with
16 bit UUID only.
---
 src/shared/gatt-helpers.c | 118 +++++++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 116 insertions(+), 2 deletions(-)

diff --git a/src/shared/gatt-helpers.c b/src/shared/gatt-helpers.c
index 4dc787f..4cc483a 100644
--- a/src/shared/gatt-helpers.c
+++ b/src/shared/gatt-helpers.c
@@ -692,6 +692,92 @@ bool bt_gatt_discover_secondary_services(struct bt_att *att, bt_uuid_t *uuid,
 								destroy, false);
 }
 
+static void discover_included_cb(uint8_t opcode, const void *pdu,
+					uint16_t length, void *user_data)
+{
+	struct bt_gatt_result *final_result = NULL;
+	struct discovery_op *op = user_data;
+	struct bt_gatt_result *cur_result;
+	uint8_t att_ecode = 0;
+	uint16_t last_handle;
+	size_t data_length;
+	bool success;
+
+	if (opcode == BT_ATT_OP_ERROR_RSP) {
+		att_ecode = process_error(pdu, length);
+
+		if (att_ecode == BT_ATT_ERROR_ATTRIBUTE_NOT_FOUND &&
+							op->result_head)
+			goto done;
+
+		success = false;
+		goto failed;
+	}
+
+	if (opcode != BT_ATT_OP_READ_BY_TYPE_RSP || !pdu || length < 6) {
+		success = false;
+		goto failed;
+	}
+
+	data_length = ((const uint8_t *) pdu)[0];
+
+	/*
+	 * Check if PDU contains data sets with length declared in the beginning
+	 * of frame and if this length is correct.
+	 * Data set length may be 6 or 8 octets:
+	 * 2 octets - include service handle
+	 * 2 octets - start handle of included service
+	 * 2 octets - end handle of included service
+	 * optional 2 octets - Bluetooth UUID of included service
+	 */
+	if (data_length != 8 || (length - 1) % data_length) {
+		success = false;
+		goto failed;
+	}
+
+	cur_result = result_create(opcode, pdu + 1, length - 1,
+							data_length, op);
+	if (!cur_result) {
+		success = false;
+		goto failed;
+	}
+
+	if (!op->result_head) {
+		op->result_head = op->result_tail = cur_result;
+	} else {
+		op->result_tail->next = cur_result;
+		op->result_tail = cur_result;
+	}
+
+	last_handle = get_le16(pdu + length - data_length);
+	if (last_handle != op->end_handle) {
+		uint8_t pdu[6];
+
+		put_le16(last_handle + 1, pdu);
+		put_le16(op->end_handle, pdu + 2);
+		put_le16(GATT_INCLUDE_UUID, pdu + 4);
+
+		if (bt_att_send(op->att, BT_ATT_OP_READ_BY_TYPE_REQ,
+							pdu, sizeof(pdu),
+							discover_included_cb,
+							discovery_op_ref(op),
+							discovery_op_unref))
+			return;
+
+		discovery_op_unref(op);
+		success = false;
+		goto failed;
+	}
+
+done:
+	success = true;
+	final_result = op->result_head;
+
+failed:
+	if (op->callback)
+		op->callback(success, att_ecode, final_result, op->user_data);
+}
+
 bool bt_gatt_discover_included_services(struct bt_att *att,
 					uint16_t start, uint16_t end,
 					bt_uuid_t *uuid,
@@ -699,8 +785,36 @@ bool bt_gatt_discover_included_services(struct bt_att *att,
 					void *user_data,
 					bt_gatt_destroy_func_t destroy)
 {
-	/* TODO */
-	return false;
+	struct discovery_op *op;
+	uint8_t pdu[6];
+
+	if (!att)
+		return false;
+
+	op = new0(struct discovery_op, 1);
+	if (!op)
+		return false;
+
+	op->att = att;
+	op->callback = callback;
+	op->user_data = user_data;
+	op->destroy = destroy;
+	op->end_handle = end;
+
+	put_le16(start, pdu);
+	put_le16(end, pdu + 2);
+	put_le16(GATT_INCLUDE_UUID, pdu + 4);
+
+	if (!bt_att_send(att, BT_ATT_OP_READ_BY_TYPE_REQ,
+					pdu, sizeof(pdu),
+					discover_included_cb,
+					discovery_op_ref(op),
+					discovery_op_unref)) {
+		free(op);
+		return false;
+	}
+
+	return true;
 }
 
 static void discover_chrcs_cb(uint8_t opcode, const void *pdu,
-- 
1.9.3


^ 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