Linux bluetooth development
 help / color / mirror / Atom feed
* Fwd: help needed for bluez debugging. - suspend-resume
From: John Miller @ 2014-10-16  0:11 UTC (permalink / raw)
  To: linux-bluetooth
In-Reply-To: <CAPJhuYJ9hTkoavCcg5O5jXJOONUQpns2S2iXgHQCza7v9u=zig@mail.gmail.com>

Hello,

I ran into a problem in which after resuming form suspend my bluetooth
headset does not autoconnect.

i have bluez-5.19 in my system with chromium OS on kernel 3.14

btmon says that when my HCI host tries to connect after resuming,
"authentication failure" error pops up.

How can i further debug this issue?

What could be the reason for failure?

Please help.

^ permalink raw reply

* Re: [PATCH] Bluetooth: Incorrect locking when sending data in softirq
From: Peter Hurley @ 2014-10-16  1:20 UTC (permalink / raw)
  To: Alexander Aring; +Cc: Jukka Rissanen, linux-bluetooth
In-Reply-To: <20141015222333.GC17138@omega>

On 10/15/2014 06:23 PM, Alexander Aring wrote:
> Hi Peter,
> 
> On Wed, Oct 15, 2014 at 05:58:40PM -0400, Peter Hurley wrote:
>> On 10/15/2014 05:53 PM, Alexander Aring wrote:
>>> Hi Peter,
>>>
>>> On Wed, Oct 15, 2014 at 04:46:24PM -0400, Peter Hurley wrote:
>>> ...
>>>>
>>>> That's happening because 6lowpan.c:send_mcast_pkt() is disabling
>>>> interrupts with the read_lock_irqsave() before calling send_pkt().
>>>>
>>>> It's unclear browsing through the lowpan driver why the
>>>> irqflags save/restore read_lock flavors are being used; is there a
>>>> place where the bluetooth core is calling the driver in atomic
>>>> context (ie., where interrupts are disabled)?
>>>>
>>>
>>> In my opinion bt_xmit is called in atomic context. Make the stacktrace
>>> sense now?
>>
>> I don't think so.
>>
>> The network layer is very careful about keeping interrupts enabled
>> and calling network drivers from softirq, so that spin_lock_bh() is
>> typically all that's required.
>>
>>> It's the callback 'ndo_start_xmit' of 'struct net_device_ops' [0].
>>
>> The send_mcast_pkt() isn't showing in the stack trace because it's
>> being inlined; and send_mcast_pkt() is definitely disabling interrupts
>> and calling send_pkt().
>>
> 
> Thanks for explanation, now I know a little more about different context
> and handling of them. I need to say I am not an expert into this. :-)
> 
> 
> Nevertheless, I found something in "Documentation/networking/netdevices.txt"
> about context information for 'ndo_start_xmit':
> 
> <qoute>
> ...
> Context: Process with BHs disabled or BH (timer),
>          will be called with interrupts disabled by netconsole.
> ...
> </qoute>
> 
> Now I am not sure if this helps us and what exactly this means. But "...
> interrupts disabled..." is this atomic now?

Local interrupts disabled is only atomic for the same cpu. Which would mean
that spin_lock_bh() wouldn't be appropriate in the ndo_start_xmit() handler.
However, this driver doesn't support netconsole because it doesn't support
the netpoll api, so it won't be called from that context.

Regards,
Peter Hurley


^ permalink raw reply

* [PATCH] Bluetooth: 6lowpan: remove unnecessary codes in give_skb_to_upper
From: roy.qing.li @ 2014-10-16  2:21 UTC (permalink / raw)
  To: linux-bluetooth, marcel, gustavo, johan.hedberg

From: Li RongQing <roy.qing.li@gmail.com>

netif_rx() only returns NET_RX_DROP and NET_RX_SUCCESS, not returns
negative value

Signed-off-by: Li RongQing <roy.qing.li@gmail.com>
---
 net/bluetooth/6lowpan.c |    9 +--------
 1 file changed, 1 insertion(+), 8 deletions(-)

diff --git a/net/bluetooth/6lowpan.c b/net/bluetooth/6lowpan.c
index c2e0d14..9b5c89b 100644
--- a/net/bluetooth/6lowpan.c
+++ b/net/bluetooth/6lowpan.c
@@ -249,19 +249,12 @@ static struct lowpan_dev *lookup_dev(struct l2cap_conn *conn)
 static int give_skb_to_upper(struct sk_buff *skb, struct net_device *dev)
 {
 	struct sk_buff *skb_cp;
-	int ret;
 
 	skb_cp = skb_copy(skb, GFP_ATOMIC);
 	if (!skb_cp)
 		return -ENOMEM;
 
-	ret = netif_rx(skb_cp);
-	if (ret < 0) {
-		BT_DBG("receive skb %d", ret);
-		return NET_RX_DROP;
-	}
-
-	return ret;
+	return netif_rx(skb_cp);
 }
 
 static int process_data(struct sk_buff *skb, struct net_device *netdev,
-- 
1.7.10.4

^ permalink raw reply related

* Re: help needed for bluez debugging. - suspend-resume
From: John Miller @ 2014-10-16  3:44 UTC (permalink / raw)
  To: linux-bluetooth
In-Reply-To: <CAPJhuYJS1wSDc9GssTLUAbuLRPW7ud6VyG4C8k3X2ok4LLmWNw@mail.gmail.com>

Somebody, please help


On Wed, Oct 15, 2014 at 5:11 PM, John Miller <jmiller5611@gmail.com> wrote:
> Hello,
>
> I ran into a problem in which after resuming form suspend my bluetooth
> headset does not autoconnect.
>
> i have bluez-5.19 in my system with chromium OS on kernel 3.14
>
> btmon says that when my HCI host tries to connect after resuming,
> "authentication failure" error pops up.
>
> How can i further debug this issue?
>
> What could be the reason for failure?
>
> Please help.

^ permalink raw reply

* Re: btusb_intr_complete returns -EPIPE
From: Naveen Kumar Parna @ 2014-10-16  7:13 UTC (permalink / raw)
  To: Alan Stern
  Cc: Oliver Neukum, linux-bluetooth@vger.kernel.org, linux-usb, acho
In-Reply-To: <Pine.LNX.4.44L0.1410151207020.1210-100000@iolanthe.rowland.org>

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

> It's entirely possible that the stall packets are created by the hub.
> When a full-speed device is connected to a USB-2 hub, and the device
> fails to respond to a packet sent by the host, the hub reports this
> failure as a stall.

Here I don’t think device fails to respond to a packet sent by the
host. I verified this by connecting Ellisys USB analyser in between
host and devices.

For example Look at the attached(Sample_HciEvt.png) HCI event captured
by Ellisys USB analyser. It is a valid HCI event from device to Host.
IN transaction 96 1 ACK FS 16 bytes (FF 2F C2 01 00 17 00 DF 00 01 10
00 00 A9 EE 0F)
IN transaction 96 1 ACK FS 16 bytes (00 00 00 5A 06 9D 39 00 00 66 00
00 00 00 00 00)
IN transaction 96 1 ACK FS 16 bytes (00 00 00 00 00 00 00 00 00 00 00
8E 05 28 00 01)
IN transaction 96 1 ACK FS 1 byte (00)

Due to spurious stall packets , sometimes btusb driver is not
receiving this full event , instead it got STALL packet instead of
first 16 bytes plus rest of other 33 bytes.



> When the device is connected to an OHCI controller, such failures would
> be reported in a different way, such as a -EPROTO or -EILSEQ status.
>

I did not observed -EPROTO or -EILSEQ status in OHCI controller scenario.

Thanks,
Naveen

[-- Attachment #2: Sample_HciEvt.png --]
[-- Type: image/png, Size: 7343 bytes --]

^ permalink raw reply

* Re: [PATCH v2 1/5] shared/att: Drop the connection if a request is received while one is pending.
From: Luiz Augusto von Dentz @ 2014-10-16  7:31 UTC (permalink / raw)
  To: Arman Uguray; +Cc: linux-bluetooth@vger.kernel.org
In-Reply-To: <CAHrH25S-W2gVkeJfsn74VCcD9h2wS86zWDcUVKX=-994pwV76A@mail.gmail.com>

Hi Arman,

On Wed, Oct 15, 2014 at 8:36 PM, Arman Uguray <armansito@chromium.org> wrote:
> Hi Luiz,
>
>
>>> +       case ATT_OP_TYPE_REQ:
>>> +               /* If a request is currently pending, then the sequential
>>> +                * protocol was violated. Disconnect the bearer and notify the
>>> +                * upper-layer.
>>> +                */
>>
>> It seems this code is not following our coding style regarding multi
>> line comments, check doc/coding-style.txt(M2: Multiple line comment)
>> the first line should be empty.
>>
>
> I didn't realize that was the comment style. I've seen both styles in
> daemon code and I think I went with this one because of that. I'd
> rather have the code be consistent (since shared/att uses this style
> elsewhere) and maybe do a style correction pass in another patch?

Sure, I can probably fix this myself just made the comment to let you
know that we do in fact have a coding style for it.

>
>>> +               if (att->in_req) {
>>> +                       util_debug(att->debug_callback, att->debug_data,
>>> +                                       "Received request while another is "
>>> +                                       "pending: 0x%02x", opcode);
>>> +                       disconnect_cb(att->io, att);
>>> +                       return false;
>>> +               }
>>> +
>>> +               att->in_req = true;
>>> +
>>> +               /* Fall through to the next case */
>>
>> This might cause a problem with our own code when connecting to each
>> other if bt_att_cancel is used, apparently bt_att_cancel does not send
>> anything to the remote side which seems to enable sending a new
>> request without waiting any response for the first one.
>>
>
> I'm confused. Do you mean if bt_att is being used in the client role,
> it can send multiple requests this way? That is correct, though I
> don't see how that's related to this patch? Currently bt_att_cancel
> can be used to cancel waiting for a pending request and send the next
> one, as you said. In that regard, it doesn't actually "cancel"
> anything if the PDU has been sent over the air already. I don't know
> how big of a problem this is, since the remote end should normally
> detect the error and terminate the connection anyway. If this becomes
> a problem we can always prevent canceling a request that has already
> left the queue and is pending. Though, again, this isn't really
> related to this patch unless I'm missing something.

Sorry for the confusion, this patch is actually fine what we really
need to fix is bt_att_cancel should not really remove the pending
request otherwise the remote may disconnect if we proceed with another
request.


-- 
Luiz Augusto von Dentz

^ permalink raw reply

* Re: [PBAP 1/2] obexd/client/pbap: Add support for spd,fav in PBAP
From: Luiz Augusto von Dentz @ 2014-10-16  7:45 UTC (permalink / raw)
  To: Gowtham Anandha Babu
  Cc: linux-bluetooth@vger.kernel.org, Dmitry Kasatkin, Bharat Panda,
	cpgs
In-Reply-To: <1413380382-3302-1-git-send-email-gowtham.ab@samsung.com>

Hi,

On Wed, Oct 15, 2014 at 4:39 PM, Gowtham Anandha Babu
<gowtham.ab@samsung.com> wrote:
> Add support for the speed-dial and favorite entries in PBAP.
> ---
>  doc/obex-api.txt          |  2 ++
>  obexd/client/pbap.c       | 10 +++++++---
>  obexd/plugins/phonebook.h |  4 ++++
>  3 files changed, 13 insertions(+), 3 deletions(-)
>
> diff --git a/doc/obex-api.txt b/doc/obex-api.txt
> index f80ef39..4439a41 100644
> --- a/doc/obex-api.txt
> +++ b/doc/obex-api.txt
> @@ -341,6 +341,8 @@ Methods             void Select(string location, string phonebook)
>                                 "och":  outgoing call history
>                                 "mch":  missing call history
>                                 "cch":  combination of ich och mch
> +                               "spd":  speed dials entry ( only for "internal" )
> +                               "fav":  favorites entry ( only for "internal" )
>
>                         Possible errors: org.bluez.obex.Error.InvalidArguments
>                                          org.bluez.obex.Error.Failed
> diff --git a/obexd/client/pbap.c b/obexd/client/pbap.c
> index 2089860..614616c 100644
> --- a/obexd/client/pbap.c
> +++ b/obexd/client/pbap.c
> @@ -183,11 +183,13 @@ static const GMarkupParser listing_parser = {
>  static char *build_phonebook_path(const char *location, const char *item)
>  {
>         char *path = NULL, *tmp, *tmp1;
> +       int int_telecom = 0;
>
>         if (!g_ascii_strcasecmp(location, "int") ||
> -                       !g_ascii_strcasecmp(location, "internal"))
> +                       !g_ascii_strcasecmp(location, "internal")) {
>                 path = g_strdup("/telecom");
> -       else if (!g_ascii_strncasecmp(location, "sim", 3)) {
> +               int_telecom = 1;
> +       } else if (!g_ascii_strncasecmp(location, "sim", 3)) {
>                 if (strlen(location) == 3)
>                         tmp = g_strdup("sim1");
>                 else
> @@ -202,7 +204,9 @@ static char *build_phonebook_path(const char *location, const char *item)
>                 !g_ascii_strcasecmp(item, "ich") ||
>                 !g_ascii_strcasecmp(item, "och") ||
>                 !g_ascii_strcasecmp(item, "mch") ||
> -               !g_ascii_strcasecmp(item, "cch")) {
> +               !g_ascii_strcasecmp(item, "cch") ||
> +               (int_telecom && !g_ascii_strcasecmp(item, "spd")) ||
> +               (int_telecom && !g_ascii_strcasecmp(item, "fav"))) {
>                 tmp = path;
>                 tmp1 = g_ascii_strdown(item, -1);
>                 path = g_build_filename(tmp, tmp1, NULL);
> diff --git a/obexd/plugins/phonebook.h b/obexd/plugins/phonebook.h
> index fff33c1..70a9cb7 100644
> --- a/obexd/plugins/phonebook.h
> +++ b/obexd/plugins/phonebook.h
> @@ -37,6 +37,8 @@
>  #define PB_CALLS_INCOMING_FOLDER "/telecom/ich"
>  #define PB_CALLS_MISSED_FOLDER "/telecom/mch"
>  #define PB_CALLS_OUTGOING_FOLDER "/telecom/och"
> +#define PB_CALLS_SPEEDDIAL_FOLDER "/telecom/spd"
> +#define PB_CALLS_FAVORITE_FOLDER "/telecom/fav"
>  #define PB_LUID_FOLDER "/telecom/pb/luid"
>
>  #define PB_CONTACTS "/telecom/pb.vcf"
> @@ -44,6 +46,8 @@
>  #define PB_CALLS_INCOMING "/telecom/ich.vcf"
>  #define PB_CALLS_MISSED "/telecom/mch.vcf"
>  #define PB_CALLS_OUTGOING "/telecom/och.vcf"
> +#define PB_CALLS_SPEEDDIAL "/telecom/spd.vcf"
> +#define PB_CALLS_FAVORITE "/telecom/fav.vcf"
>  #define PB_DEVINFO "/telecom/devinfo.txt"
>  #define PB_INFO_LOG "/telecom/pb/info.log"
>  #define PB_CC_LOG "/telecom/pb/luid/cc.log"
> --
> 1.9.1

Applied, please make sure you following the 50/72 format for commits,
it is documented in the HACKING document and I would like that we stay
consistent with it.


-- 
Luiz Augusto von Dentz

^ permalink raw reply

* Re: [PATCH] Bluetooth: Incorrect locking when sending data in softirq
From: Jukka Rissanen @ 2014-10-16  7:47 UTC (permalink / raw)
  To: Peter Hurley; +Cc: linux-bluetooth
In-Reply-To: <543EDD20.8050508@hurleysoftware.com>

Hi Peter,

On ke, 2014-10-15 at 16:46 -0400, Peter Hurley wrote:

> That's happening because 6lowpan.c:send_mcast_pkt() is disabling
> interrupts with the read_lock_irqsave() before calling send_pkt().
> 
> It's unclear browsing through the lowpan driver why the
> irqflags save/restore read_lock flavors are being used; is there a
> place where the bluetooth core is calling the driver in atomic
> context (ie., where interrupts are disabled)?
> 
> The devices_lock/bt_6lowpan_devices list looks ideal for
> converting to RCU.
> 
> Regards,
> Peter Hurley
> 
> PS - list_for_each_entry_safe() is only required when the reference
> to the list entry may become invalid _while_ still iterating the list.
> So not necessary in peer_lookup_conn(), lookup_peer(), lookup_dev(),
> peer_lookup_chan(), peer_lookup_ba(), send_mcast_pkt(), maybe others.
> 

Thanks for the explanations, these were very valuable. I will
investigate the RCU conversion and fixes to list handling.


Cheers,
Jukka



^ permalink raw reply

* Re: [PATCH 4/4] Fix enum coding-style
From: Luiz Augusto von Dentz @ 2014-10-16  7:59 UTC (permalink / raw)
  To: Gowtham Anandha Babu
  Cc: linux-bluetooth@vger.kernel.org, Dmitry Kasatkin, Bharat Panda,
	cpgs
In-Reply-To: <1413382102-4049-4-git-send-email-gowtham.ab@samsung.com>

Hi,

On Wed, Oct 15, 2014 at 5:08 PM, Gowtham Anandha Babu
<gowtham.ab@samsung.com> wrote:
> Fix the enum coding-style as per the new coding style doc.

I guess the tabs confused you a little bit, the coding style is more
about having the values in case they come from a specification, the
alignment of the values don't need to be exactly as in the example in
the coding style.

> ---
>  lib/uuid.h                    |  8 ++++----
>  profiles/cups/cups.h          | 16 ++++++++--------
>  profiles/health/hdp_types.h   |  4 ++--
>  profiles/proximity/reporter.h |  6 +++---
>  profiles/time/server.c        | 20 ++++++++++----------
>  5 files changed, 27 insertions(+), 27 deletions(-)
>
> diff --git a/lib/uuid.h b/lib/uuid.h
> index 8303772..f05888a 100644
> --- a/lib/uuid.h
> +++ b/lib/uuid.h
> @@ -142,10 +142,10 @@ extern "C" {
>
>  typedef struct {
>         enum {
> -               BT_UUID_UNSPEC = 0,
> -               BT_UUID16 = 16,
> -               BT_UUID32 = 32,
> -               BT_UUID128 = 128,
> +               BT_UUID_UNSPEC =        0,
> +               BT_UUID16 =             16,
> +               BT_UUID32 =             32,
> +               BT_UUID128 =            128,
>         } type;
>         union {
>                 uint16_t  u16;
> diff --git a/profiles/cups/cups.h b/profiles/cups/cups.h
> index f4e0c01..dbea1bf 100644
> --- a/profiles/cups/cups.h
> +++ b/profiles/cups/cups.h
> @@ -21,14 +21,14 @@
>   *
>   */
>
> -enum {                                 /**** Backend exit codes ****/
> -       CUPS_BACKEND_OK = 0,            /* Job completed successfully */
> -       CUPS_BACKEND_FAILED = 1,        /* Job failed, use error-policy */
> -       CUPS_BACKEND_AUTH_REQUIRED = 2, /* Job failed, authentication required */
> -       CUPS_BACKEND_HOLD = 3,          /* Job failed, hold job */
> -       CUPS_BACKEND_STOP = 4,          /* Job failed, stop queue */
> -       CUPS_BACKEND_CANCEL = 5,        /* Job failed, cancel job */
> -       CUPS_BACKEND_RETRY = 6,         /* Failure requires us to retry (BlueZ specific) */
> +enum {                                         /**** Backend exit codes ****/
> +       CUPS_BACKEND_OK =               0,      /* Job completed successfully */
> +       CUPS_BACKEND_FAILED =           1,      /* Job failed, use error-policy */
> +       CUPS_BACKEND_AUTH_REQUIRED =    2,      /* Job failed, authentication required */
> +       CUPS_BACKEND_HOLD =             3,      /* Job failed, hold job */
> +       CUPS_BACKEND_STOP =             4,      /* Job failed, stop queue */
> +       CUPS_BACKEND_CANCEL =           5,      /* Job failed, cancel job */
> +       CUPS_BACKEND_RETRY =            6,      /* Failure requires us to retry (BlueZ specific) */
>  };
>
>  int sdp_search_spp(sdp_session_t *sdp, uint8_t *channel);
> diff --git a/profiles/health/hdp_types.h b/profiles/health/hdp_types.h
> index b34b5e0..92f461a 100644
> --- a/profiles/health/hdp_types.h
> +++ b/profiles/health/hdp_types.h
> @@ -49,8 +49,8 @@
>  #define HDP_SOURCE_ROLE_AS_STRING      "source"
>
>  typedef enum {
> -       HDP_SOURCE = 0x00,
> -       HDP_SINK = 0x01
> +       HDP_SOURCE =    0x00,
> +       HDP_SINK =      0x01
>  } HdpRole;
>
>  typedef enum {
> diff --git a/profiles/proximity/reporter.h b/profiles/proximity/reporter.h
> index a8e1aac..243db26 100644
> --- a/profiles/proximity/reporter.h
> +++ b/profiles/proximity/reporter.h
> @@ -31,9 +31,9 @@
>  #define POWER_LEVEL_CHR_UUID           0x2A07
>
>  enum {
> -       NO_ALERT = 0x00,
> -       MILD_ALERT = 0x01,
> -       HIGH_ALERT = 0x02,
> +       NO_ALERT =      0x00,
> +       MILD_ALERT =    0x01,
> +       HIGH_ALERT =    0x02,
>  };
>
>  void reporter_device_remove(struct btd_service *service);
> diff --git a/profiles/time/server.c b/profiles/time/server.c
> index 1716a5e..0b6f70b 100644
> --- a/profiles/time/server.c
> +++ b/profiles/time/server.c
> @@ -55,22 +55,22 @@
>  #define CT_TIME_CHR_UUID               0x2A2B
>
>  enum {
> -       UPDATE_RESULT_SUCCESSFUL = 0,
> -       UPDATE_RESULT_CANCELED = 1,
> -       UPDATE_RESULT_NO_CONN = 2,
> -       UPDATE_RESULT_ERROR = 3,
> -       UPDATE_RESULT_TIMEOUT = 4,
> -       UPDATE_RESULT_NOT_ATTEMPTED = 5,
> +       UPDATE_RESULT_SUCCESSFUL =      0,
> +       UPDATE_RESULT_CANCELED =        1,
> +       UPDATE_RESULT_NO_CONN =         2,
> +       UPDATE_RESULT_ERROR =           3,
> +       UPDATE_RESULT_TIMEOUT =         4,
> +       UPDATE_RESULT_NOT_ATTEMPTED =   5,
>  };
>
>  enum {
> -       UPDATE_STATE_IDLE = 0,
> -       UPDATE_STATE_PENDING = 1,
> +       UPDATE_STATE_IDLE =     0,
> +       UPDATE_STATE_PENDING =  1,
>  };
>
>  enum {
> -       GET_REFERENCE_UPDATE = 1,
> -       CANCEL_REFERENCE_UPDATE = 2,
> +       GET_REFERENCE_UPDATE =          1,
> +       CANCEL_REFERENCE_UPDATE =       2,
>  };
>
>  static int encode_current_time(uint8_t value[10])
> --
> 1.9.1
>



-- 
Luiz Augusto von Dentz

^ permalink raw reply

* Re: [PATCH 1/4] tools/csr_usb : Fix Resource leak: file
From: Luiz Augusto von Dentz @ 2014-10-16  8:17 UTC (permalink / raw)
  To: Gowtham Anandha Babu
  Cc: linux-bluetooth@vger.kernel.org, Dmitry Kasatkin, Bharat Panda,
	cpgs
In-Reply-To: <1413382102-4049-1-git-send-email-gowtham.ab@samsung.com>

Hi,

On Wed, Oct 15, 2014 at 5:08 PM, Gowtham Anandha Babu
<gowtham.ab@samsung.com> wrote:
> Handles resource leak.
> ---
>  tools/csr_usb.c | 5 ++++-
>  1 file changed, 4 insertions(+), 1 deletion(-)
>
> diff --git a/tools/csr_usb.c b/tools/csr_usb.c
> index 5fb6bdc..a1d7324 100644
> --- a/tools/csr_usb.c
> +++ b/tools/csr_usb.c
> @@ -80,9 +80,12 @@ static int read_value(const char *name, const char *attr, const char *format)
>                 return -1;
>
>         n = fscanf(file, format, &value);
> -       if (n != 1)
> +       if (n != 1) {
> +               fclose(file);
>                 return -1;
> +       }
>
> +       fclose(file);
>         return value;
>  }
>
> --
> 1.9.1

Applied 1-3, but note that I did some changes in the commit message,
please be consistent and don't include things like space before ':'
etc, it is always a good practice got look how previous commit have
been formatted and follow the HACKING document.


-- 
Luiz Augusto von Dentz

^ permalink raw reply

* RE: [PATCH 1/4] tools/csr_usb : Fix Resource leak: file
From: Gowtham Anandha Babu @ 2014-10-16  8:57 UTC (permalink / raw)
  To: 'Luiz Augusto von Dentz'
  Cc: linux-bluetooth, 'Dmitry Kasatkin',
	'Bharat Panda', cpgs
In-Reply-To: <CABBYNZKe1=awjhj2XttF+7gyHaw8f5zWftL=p1wrf+HWMUefMQ@mail.gmail.com>

Hi Luiz,

> -----Original Message-----
> From: Luiz Augusto von Dentz [mailto:luiz.dentz@gmail.com]
> Sent: Thursday, October 16, 2014 1:48 PM
> To: Gowtham Anandha Babu
> Cc: linux-bluetooth@vger.kernel.org; Dmitry Kasatkin; Bharat Panda;
> cpgs@samsung.com
> Subject: Re: [PATCH 1/4] tools/csr_usb : Fix Resource leak: file
> 
> Hi,
> 
> On Wed, Oct 15, 2014 at 5:08 PM, Gowtham Anandha Babu
> <gowtham.ab@samsung.com> wrote:
> > Handles resource leak.
> > ---
> >  tools/csr_usb.c | 5 ++++-
> >  1 file changed, 4 insertions(+), 1 deletion(-)
> >
> > diff --git a/tools/csr_usb.c b/tools/csr_usb.c index 5fb6bdc..a1d7324
> > 100644
> > --- a/tools/csr_usb.c
> > +++ b/tools/csr_usb.c
> > @@ -80,9 +80,12 @@ static int read_value(const char *name, const char
> *attr, const char *format)
> >                 return -1;
> >
> >         n = fscanf(file, format, &value);
> > -       if (n != 1)
> > +       if (n != 1) {
> > +               fclose(file);
> >                 return -1;
> > +       }
> >
> > +       fclose(file);
> >         return value;
> >  }
> >
> > --
> > 1.9.1
> 
> Applied 1-3, but note that I did some changes in the commit message, please
> be consistent and don't include things like space before ':'
> etc, it is always a good practice got look how previous commit have been
> formatted and follow the HACKING document.
> 
> 
> --
> Luiz Augusto von Dentz

Sorry for the formatting errors and 50/72 format. I will follow the HACKING documents here after.
Thanks !

Regards, 
Gowtham Anandha Babu


^ permalink raw reply

* Re: btusb_intr_complete returns -EPIPE
From: Oliver Neukum @ 2014-10-16  9:15 UTC (permalink / raw)
  To: Alan Stern
  Cc: Naveen Kumar Parna, linux-bluetooth@vger.kernel.org, linux-usb,
	acho
In-Reply-To: <Pine.LNX.4.44L0.1410151207020.1210-100000@iolanthe.rowland.org>

On Wed, 2014-10-15 at 12:11 -0400, Alan Stern wrote:
> > If the hub is the problem… what will be the better solution? Is it
> > possible to change internal hub?
> 
> No, it is not possible.

Indeed. However, it is possible to use an additional in between your
devices and the internal hub.

	Regards
		Oliver



^ permalink raw reply

* [PATCH] src/profile: Add feature bits to MAS SDP record
From: Gowtham Anandha Babu @ 2014-10-16 10:01 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: d.kasatkin, bharat.panda, cpgs, Gowtham Anandha Babu

Add MAP supported features bits to MAS SDP record.
Fix the PTS 5.3 test-cases:
TC_MSE_MFB_BV_02_I
TC_MSE_MFB_BV_05_I
---
 src/profile.c | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/src/profile.c b/src/profile.c
index 7aca3be..bccb145 100644
--- a/src/profile.c
+++ b/src/profile.c
@@ -439,6 +439,9 @@
 		<attribute id=\"0x0316\">				\
 			<uint8 value=\"0x0F\"/>				\
 		</attribute>						\
+		<attribute id=\"0x0317\">				\
+			<uint32 value=\"0x0000007f\"/>			\
+		</attribute>						\
 	</record>"
 
 #define MNS_RECORD							\
-- 
1.9.1


^ permalink raw reply related

* [PATCHv5 00/14] Included service discovery
From: Marcin Kraglak @ 2014-10-16 10:17 UTC (permalink / raw)
  To: linux-bluetooth

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.

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: 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
  shared/gatt: Add function bt_gatt_result_included_count()

 src/shared/gatt-client.c  | 263 +++++++++++++++++++++++++++--
 src/shared/gatt-client.h  |  18 ++
 src/shared/gatt-helpers.c | 418 +++++++++++++++++++++++++++++++++++++++++++---
 src/shared/gatt-helpers.h |  10 +-
 tools/btgatt-client.c     |  17 +-
 5 files changed, 690 insertions(+), 36 deletions(-)

-- 
1.9.3


^ permalink raw reply

* [PATCHv5 01/14] shared/gatt: Add discover_secondary_services()
From: Marcin Kraglak @ 2014-10-16 10:17 UTC (permalink / raw)
  To: linux-bluetooth
In-Reply-To: <1413454646-23076-1-git-send-email-marcin.kraglak@tieto.com>

This pach implements searching Secondary Services in given range.
---
 src/shared/gatt-helpers.c | 56 +++++++++++++++++++++++++++++++++--------------
 src/shared/gatt-helpers.h |  5 +++++
 2 files changed, 45 insertions(+), 16 deletions(-)

diff --git a/src/shared/gatt-helpers.c b/src/shared/gatt-helpers.c
index 55e6992..4dc787f 100644
--- a/src/shared/gatt-helpers.c
+++ b/src/shared/gatt-helpers.c
@@ -175,6 +175,7 @@ struct discovery_op {
 	uint16_t end_handle;
 	int ref_count;
 	bt_uuid_t uuid;
+	uint16_t service_type;
 	struct bt_gatt_result *result_head;
 	struct bt_gatt_result *result_tail;
 	bt_gatt_discovery_callback_t callback;
@@ -487,7 +488,7 @@ static void read_by_grp_type_cb(uint8_t opcode, const void *pdu,
 
 		put_le16(last_end + 1, pdu);
 		put_le16(op->end_handle, pdu + 2);
-		put_le16(GATT_PRIM_SVC_UUID, pdu + 4);
+		put_le16(op->service_type, pdu + 4);
 
 		if (bt_att_send(op->att, BT_ATT_OP_READ_BY_GRP_TYPE_REQ,
 							pdu, sizeof(pdu),
@@ -569,7 +570,7 @@ static void find_by_type_val_cb(uint8_t opcode, const void *pdu,
 
 		put_le16(last_end + 1, pdu);
 		put_le16(op->end_handle, pdu + 2);
-		put_le16(GATT_PRIM_SVC_UUID, pdu + 4);
+		put_le16(op->service_type, pdu + 4);
 		put_uuid_le(&op->uuid, pdu + 6);
 
 		if (bt_att_send(op->att, BT_ATT_OP_FIND_BY_TYPE_VAL_REQ,
@@ -594,21 +595,12 @@ done:
 		op->callback(success, att_ecode, final_result, op->user_data);
 }
 
-bool bt_gatt_discover_all_primary_services(struct bt_att *att, bt_uuid_t *uuid,
-					bt_gatt_discovery_callback_t callback,
-					void *user_data,
-					bt_gatt_destroy_func_t destroy)
-{
-	return bt_gatt_discover_primary_services(att, uuid, 0x0001, 0xffff,
-							callback, user_data,
-							destroy);
-}
-
-bool bt_gatt_discover_primary_services(struct bt_att *att, bt_uuid_t *uuid,
+static bool discover_services(struct bt_att *att, bt_uuid_t *uuid,
 					uint16_t start, uint16_t end,
 					bt_gatt_discovery_callback_t callback,
 					void *user_data,
-					bt_gatt_destroy_func_t destroy)
+					bt_gatt_destroy_func_t destroy,
+					bool primary)
 {
 	struct discovery_op *op;
 	bool result;
@@ -625,6 +617,8 @@ bool bt_gatt_discover_primary_services(struct bt_att *att, bt_uuid_t *uuid,
 	op->callback = callback;
 	op->user_data = user_data;
 	op->destroy = destroy;
+	/* set service uuid to primary or secondary */
+	op->service_type = primary ? GATT_PRIM_SVC_UUID : GATT_SND_SVC_UUID;
 
 	/* If UUID is NULL, then discover all primary services */
 	if (!uuid) {
@@ -632,7 +626,7 @@ bool bt_gatt_discover_primary_services(struct bt_att *att, bt_uuid_t *uuid,
 
 		put_le16(start, pdu);
 		put_le16(end, pdu + 2);
-		put_le16(GATT_PRIM_SVC_UUID, pdu + 4);
+		put_le16(op->service_type, pdu + 4);
 
 		result = bt_att_send(att, BT_ATT_OP_READ_BY_GRP_TYPE_REQ,
 							pdu, sizeof(pdu),
@@ -652,7 +646,7 @@ bool bt_gatt_discover_primary_services(struct bt_att *att, bt_uuid_t *uuid,
 
 		put_le16(start, pdu);
 		put_le16(end, pdu + 2);
-		put_le16(GATT_PRIM_SVC_UUID, pdu + 4);
+		put_le16(op->service_type, pdu + 4);
 		put_uuid_le(&op->uuid, pdu + 6);
 
 		result = bt_att_send(att, BT_ATT_OP_FIND_BY_TYPE_VAL_REQ,
@@ -668,6 +662,36 @@ bool bt_gatt_discover_primary_services(struct bt_att *att, bt_uuid_t *uuid,
 	return result;
 }
 
+bool bt_gatt_discover_all_primary_services(struct bt_att *att, bt_uuid_t *uuid,
+					bt_gatt_discovery_callback_t callback,
+					void *user_data,
+					bt_gatt_destroy_func_t destroy)
+{
+	return bt_gatt_discover_primary_services(att, uuid, 0x0001, 0xffff,
+							callback, user_data,
+							destroy);
+}
+
+bool bt_gatt_discover_primary_services(struct bt_att *att, bt_uuid_t *uuid,
+					uint16_t start, uint16_t end,
+					bt_gatt_discovery_callback_t callback,
+					void *user_data,
+					bt_gatt_destroy_func_t destroy)
+{
+	return discover_services(att, uuid, start, end, callback, user_data,
+								destroy, true);
+}
+
+bool bt_gatt_discover_secondary_services(struct bt_att *att, bt_uuid_t *uuid,
+					uint16_t start, uint16_t end,
+					bt_gatt_discovery_callback_t callback,
+					void *user_data,
+					bt_gatt_destroy_func_t destroy)
+{
+	return discover_services(att, uuid, start, end, callback, user_data,
+								destroy, false);
+}
+
 bool bt_gatt_discover_included_services(struct bt_att *att,
 					uint16_t start, uint16_t end,
 					bt_uuid_t *uuid,
diff --git a/src/shared/gatt-helpers.h b/src/shared/gatt-helpers.h
index f6f4b62..8a25dea 100644
--- a/src/shared/gatt-helpers.h
+++ b/src/shared/gatt-helpers.h
@@ -72,6 +72,11 @@ bool bt_gatt_discover_primary_services(struct bt_att *att, bt_uuid_t *uuid,
 					bt_gatt_discovery_callback_t callback,
 					void *user_data,
 					bt_gatt_destroy_func_t destroy);
+bool bt_gatt_discover_secondary_services(struct bt_att *att, bt_uuid_t *uuid,
+					uint16_t start, uint16_t end,
+					bt_gatt_discovery_callback_t callback,
+					void *user_data,
+					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,
-- 
1.9.3


^ permalink raw reply related

* [PATCHv5 02/14] shared/gatt: Add initial implementation of discover_included_services
From: Marcin Kraglak @ 2014-10-16 10:17 UTC (permalink / raw)
  To: linux-bluetooth
In-Reply-To: <1413454646-23076-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 | 108 +++++++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 106 insertions(+), 2 deletions(-)

diff --git a/src/shared/gatt-helpers.c b/src/shared/gatt-helpers.c
index 4dc787f..dcb2a2f 100644
--- a/src/shared/gatt-helpers.c
+++ b/src/shared/gatt-helpers.c
@@ -692,6 +692,82 @@ 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) {
+		success = false;
+		att_ecode = process_error(pdu, length);
+
+		if (att_ecode == BT_ATT_ERROR_ATTRIBUTE_NOT_FOUND &&
+							op->result_head)
+			goto success;
+
+		goto done;
+	}
+
+	if (opcode != BT_ATT_OP_READ_BY_TYPE_RSP || !pdu || length < 6) {
+		success = false;
+		goto done;
+	}
+
+	data_length = ((uint8_t *) pdu)[0];
+
+	if ((length - 1) % data_length || data_length != 8) {
+		success = false;
+		goto done;
+	}
+
+	cur_result = result_create(opcode, pdu + 1, length - 1,
+							data_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;
+	}
+
+	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;
+	}
+
+success:
+	success = true;
+	final_result = op->result_head;
+
+done:
+	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 +775,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

* [PATCHv5 03/14] shared/gatt: Discover included services 128 bit UUIDS
From: Marcin Kraglak @ 2014-10-16 10:17 UTC (permalink / raw)
  To: linux-bluetooth
In-Reply-To: <1413454646-23076-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 | 170 +++++++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 169 insertions(+), 1 deletion(-)

diff --git a/src/shared/gatt-helpers.c b/src/shared/gatt-helpers.c
index dcb2a2f..c18f738 100644
--- a/src/shared/gatt-helpers.c
+++ b/src/shared/gatt-helpers.c
@@ -692,6 +692,160 @@ 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;
+	uint16_t handle;
+	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;
+	}
+
+	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, data_len;
+		uint8_t pdu[6];
+
+		data_len = data->result->data_len;
+		last_handle = get_le16(data->result->pdu + data->pos -
+								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;
+	}
+
+	handle = get_le16(data->result->pdu + data->pos + 2);
+	put_le16(handle, read_pdu);
+
+	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;
+	uint16_t handle;
+	uint8_t pdu[2];
+
+	handle = get_le16(data->result->pdu + 2);
+	put_le16(handle, pdu);
+
+	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)
 {
@@ -721,7 +875,8 @@ static void discover_included_cb(uint8_t opcode, const void *pdu,
 
 	data_length = ((uint8_t *) pdu)[0];
 
-	if ((length - 1) % data_length || data_length != 8) {
+	if (((length - 1) % data_length) ||
+				(data_length != 8 && data_length != 6)) {
 		success = false;
 		goto done;
 	}
@@ -740,6 +895,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

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

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

diff --git a/src/shared/gatt-helpers.c b/src/shared/gatt-helpers.c
index c18f738..58104d9 100644
--- a/src/shared/gatt-helpers.c
+++ b/src/shared/gatt-helpers.c
@@ -123,6 +123,9 @@ unsigned int bt_gatt_result_characteristic_count(struct bt_gatt_result *result)
 	if (result->opcode != BT_ATT_OP_READ_BY_TYPE_RSP)
 		return 0;
 
+	if (result->data_len != 21 && result->data_len != 7)
+		return 0;
+
 	return result_element_count(result);
 }
 
@@ -239,6 +242,9 @@ bool bt_gatt_iter_next_characteristic(struct bt_gatt_iter *iter,
 	if (iter->result->opcode != BT_ATT_OP_READ_BY_TYPE_RSP)
 		return false;
 
+	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

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

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

diff --git a/src/shared/gatt-helpers.c b/src/shared/gatt-helpers.c
index 58104d9..fd8d06c 100644
--- a/src/shared/gatt-helpers.c
+++ b/src/shared/gatt-helpers.c
@@ -186,6 +186,64 @@ 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;
+
+	if (iter->result->data_len != 8 && iter->result->data_len != 6)
+		return false;
+
+	pdu_ptr = iter->result->pdu + iter->pos;
+
+	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;
+
+	do {
+		read_result = read_result->next;
+	} while (read_result && i++ < (iter->pos / iter->result->data_len));
+
+	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

* [PATCHv5 06/14] shared/gatt: Remove not needed function parameter
From: Marcin Kraglak @ 2014-10-16 10:17 UTC (permalink / raw)
  To: linux-bluetooth
In-Reply-To: <1413454646-23076-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 fd8d06c..48e7379 100644
--- a/src/shared/gatt-helpers.c
+++ b/src/shared/gatt-helpers.c
@@ -1002,7 +1002,6 @@ done:
 
 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 8c434c1..f2c7ec5 100644
--- a/src/shared/gatt-helpers.h
+++ b/src/shared/gatt-helpers.h
@@ -82,7 +82,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

* [PATCHv5 07/14] shared/gatt: Distinguish Primary from Secondary services
From: Marcin Kraglak @ 2014-10-16 10:17 UTC (permalink / raw)
  To: linux-bluetooth
In-Reply-To: <1413454646-23076-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

* [PATCHv5 08/14] tools/btgatt-client: Print type of service
From: Marcin Kraglak @ 2014-10-16 10:17 UTC (permalink / raw)
  To: linux-bluetooth
In-Reply-To: <1413454646-23076-1-git-send-email-marcin.kraglak@tieto.com>

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

diff --git a/tools/btgatt-client.c b/tools/btgatt-client.c
index d900e08..5c692ff 100644
--- a/tools/btgatt-client.c
+++ b/tools/btgatt-client.c
@@ -182,8 +182,9 @@ static void print_service(const bt_gatt_service_t *service)
 		return;
 	}
 
-	printf(COLOR_RED "service" COLOR_OFF " - start: 0x%04x, "
+	printf(COLOR_RED "service %s" COLOR_OFF " - start: 0x%04x, "
 				"end: 0x%04x, uuid: ",
+				service->primary ? "primary" : "second.",
 				service->start_handle, service->end_handle);
 	print_uuid(service->uuid);
 
-- 
1.9.3


^ permalink raw reply related

* [PATCHv5 09/14] shared/gatt: Discover secondary services
From: Marcin Kraglak @ 2014-10-16 10:17 UTC (permalink / raw)
  To: linux-bluetooth
In-Reply-To: <1413454646-23076-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

* [PATCHv5 10/14] shared/gatt: Discover included services
From: Marcin Kraglak @ 2014-10-16 10:17 UTC (permalink / raw)
  To: linux-bluetooth
In-Reply-To: <1413454646-23076-1-git-send-email-marcin.kraglak@tieto.com>

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

diff --git a/src/shared/gatt-client.c b/src/shared/gatt-client.c
index e04724c..971788c 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,99 @@ 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) {
+			success = true;
+			goto next;
+		}
+
+		goto done;
+	}
+
+	if (!result || !bt_gatt_iter_init(&iter, result)) {
+		success = false;
+		goto done;
+	}
+
+	includes_count = bt_gatt_result_included_count(result);
+	if (includes_count == 0) {
+		success = false;
+		goto done;
+	}
+
+	includes = new0(bt_gatt_included_service_t, includes_count);
+	if (!includes) {
+		success = false;
+		goto done;
+	}
+
+	util_debug(client->debug_callback, client->debug_data,
+						"Included services found: %u",
+						includes_count);
+
+	i = 0;
+	while (bt_gatt_iter_next_included_service(&iter, &includes[i].handle,
+						&includes[i].start_handle,
+						&includes[i].end_handle,
+						includes[i].uuid)) {
+		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);
+		i++;
+	}
+
+	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);
+		success = false;
+		goto done;
+	}
+
+	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);
+	success = false;
+
+done:
+	op->complete_func(op, success, att_ecode);
+}
+
 static void discover_descs_cb(bool success, uint8_t att_ecode,
 						struct bt_gatt_result *result,
 						void *user_data)
@@ -532,6 +637,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 +809,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

* [PATCHv5 11/14] shared/gatt: Add gatt-client include service iterator
From: Marcin Kraglak @ 2014-10-16 10:17 UTC (permalink / raw)
  To: linux-bluetooth
In-Reply-To: <1413454646-23076-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 971788c..28865da 100644
--- a/src/shared/gatt-client.c
+++ b/src/shared/gatt-client.c
@@ -1674,6 +1674,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


This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox