* Re: BLE - multiple connections
From: Ajay KV @ 2012-08-22 16:07 UTC (permalink / raw)
To: Anderson Lizardo, linux-bluetooth
In-Reply-To: <CAJdJm_OBh4OzKJejongsaWm1mSx2GN5Yki3B4nYc6C2DbVS=nw@mail.gmail.com>
On 08/17/2012 12:27 PM, Anderson Lizardo wrote:
> Hi Ajay
>
> [your emails to BlueZ mailing list may be getting blocked because you
> are using HTML. Please fix that on your mail client. Also remember to
> not top-post]
>
> On Fri, Aug 17, 2012 at 7:34 PM, Ajay KV<ajay.kv@globaledgesoft.com> wrote:
>
>> Thanks for your reply. i have 2 dongles of different made (iogear and
>> chirago) . "Hciconfig hci0 lestates" gives this following result
>>
>> Supported link layer states:
>> [...]
>>
>> Here my issue is to know whether (connected mode + advertising
>> mode) is possible at a time . Once A is connected to B (initiator), i
>> could not able to enable advertise in A (getting command disallowed ) , so
>> that device C is not getting the connectable advertising packets on
>> scanning.
>>
> I could not see any reason to get "command disallowed" when enabling
> LE adv. Did you try changing dongle combinations to make sure it is
> not some hardware issue?
>
> Regards,
>
Hi,
i could not able to figure it out yet , why its showing this
error " command disallowed" . Here im using fedora 13 with kernel 2.6.39
. i tried with both dongles , iogear and cirago . But the result is
same. i dont think that its something wrong with kernel version, as
we uses hci commands (hciconfig hci0 leadv ) that directly talks with
controller . please clear this issue..
^ permalink raw reply
* [PATCH obexd 1/4] build: BlueZ version 4.100 or later is required
From: Syam Sidhardhan @ 2012-08-22 16:10 UTC (permalink / raw)
To: linux-bluetooth
If we use the BlueZ version less than 4.100, then the following
compilation error happens.
Error:
-----
btio/btio.c: In function ‘l2cap_connect’:
btio/btio.c:301:6: error: ‘struct sockaddr_l2’ has no member named
‘l2_bdaddr_type’
btio/btio.c: In function ‘parse_set_opts’:
btio/btio.c:707:19: error: ‘BDADDR_BREDR’ undeclared (first use in
this function)
btio/btio.c:707:19: note: each undeclared identifier is reported only
once for each function it appears in
make[1]: *** [btio/btio.o] Error 1
make: *** [all] Error 2
---
configure.ac | 4 ++--
1 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/configure.ac b/configure.ac
index 69d71b2..c8e61ac 100644
--- a/configure.ac
+++ b/configure.ac
@@ -79,8 +79,8 @@ PKG_CHECK_MODULES(DBUS, dbus-1 >= 1.4, dummy=yes,
AC_SUBST(DBUS_CFLAGS)
AC_SUBST(DBUS_LIBS)
-PKG_CHECK_MODULES(BLUEZ, bluez >= 4.99, dummy=yes,
- AC_MSG_ERROR(BlueZ >= 4.99 is required))
+PKG_CHECK_MODULES(BLUEZ, bluez >= 4.100, dummy=yes,
+ AC_MSG_ERROR(BlueZ >= 4.100 is required))
AC_SUBST(BLUEZ_CFLAGS)
AC_SUBST(BLUEZ_LIBS)
--
1.7.4.1
^ permalink raw reply related
* [PATCH obexd 2/4] build: Require GLib 2.32 or later
From: Syam Sidhardhan @ 2012-08-22 16:10 UTC (permalink / raw)
To: linux-bluetooth
In-Reply-To: <1345651858-23031-1-git-send-email-s.syam@samsung.com>
If we use GLib version less than 2.32 (more precisely < 2.31.2) then
the following build error may occure in a 32 bit.
cc1: warnings being treated as errors
gobex/gobex-apparam.c: In function ‘g_obex_apparam_set_bytes’:
gobex/gobex-apparam.c:176:38: error: cast to pointer from integer of
different size
gobex/gobex-apparam.c: In function ‘g_obex_apparam_get_uint8’:
gobex/gobex-apparam.c:243:43: error: cast to pointer from integer of
different size
gobex/gobex-apparam.c: In function ‘g_obex_apparam_get_uint16’:
gobex/gobex-apparam.c:261:43: error: cast to pointer from integer of
different size
gobex/gobex-apparam.c: In function ‘g_obex_apparam_get_uint32’:
gobex/gobex-apparam.c:282:43: error: cast to pointer from integer of
different size
gobex/gobex-apparam.c: In function ‘g_obex_apparam_get_uint64’:
gobex/gobex-apparam.c:303:43: error: cast to pointer from integer of
different size
gobex/gobex-apparam.c: In function ‘g_obex_apparam_get_string’:
gobex/gobex-apparam.c:324:43: error: cast to pointer from integer of
different size
gobex/gobex-apparam.c: In function ‘g_obex_apparam_get_bytes’:
gobex/gobex-apparam.c:342:43: error: cast to pointer from integer of
different size
make[1]: *** [gobex/gobex-apparam.o] Error 1
make: *** [all] Error 2
---
Reference:
GLib tree: Commit: 16292dd753cb63f8ccb2267644aefbd2632dd52c
Author: Lucas De Marchi <lucas.demarchi@profusion.mobi>
Date: Thu Oct 6 11:18:03 2011 -0300
Fix G*_TO_POINTER casts on 32 bits
If we don't do the cast to the proper size in 32 bits, things like below
doesn't work:
uint8_t u = 20;
void *p;
p = GUINT_TO_POINTER(u);
Signed-off-by: Colin Walters <walters@verbum.org>
Thanks Luiz for giving this reference.
Btb I'm not very sure, is this the best way to solve this problem.
configure.ac | 4 ++--
1 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/configure.ac b/configure.ac
index c8e61ac..78da420 100644
--- a/configure.ac
+++ b/configure.ac
@@ -69,8 +69,8 @@ fi
AC_CHECK_LIB(dl, dlopen, dummy=yes,
AC_MSG_ERROR(dynamic linking loader is required))
-PKG_CHECK_MODULES(GLIB, glib-2.0 >= 2.28, dummy=yes,
- AC_MSG_ERROR(GLib >= 2.28 is required))
+PKG_CHECK_MODULES(GLIB, glib-2.0 >= 2.32, dummy=yes,
+ AC_MSG_ERROR(GLib >= 2.32 is required))
AC_SUBST(GLIB_CFLAGS)
AC_SUBST(GLIB_LIBS)
--
1.7.4.1
^ permalink raw reply related
* [PATCH obexd 3/4] plugins: Remove redundant incude sys/stat.h
From: Syam Sidhardhan @ 2012-08-22 16:10 UTC (permalink / raw)
To: linux-bluetooth
In-Reply-To: <1345651858-23031-1-git-send-email-s.syam@samsung.com>
---
plugins/filesystem.c | 1 -
1 files changed, 0 insertions(+), 1 deletions(-)
diff --git a/plugins/filesystem.c b/plugins/filesystem.c
index e664fc5..1132a34 100644
--- a/plugins/filesystem.c
+++ b/plugins/filesystem.c
@@ -32,7 +32,6 @@
#include <string.h>
#include <unistd.h>
#include <dirent.h>
-#include <sys/stat.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/statvfs.h>
--
1.7.4.1
^ permalink raw reply related
* [PATCH obexd 4/4] core: Remove redundant incude errno.h
From: Syam Sidhardhan @ 2012-08-22 16:10 UTC (permalink / raw)
To: linux-bluetooth
In-Reply-To: <1345651858-23031-1-git-send-email-s.syam@samsung.com>
---
src/server.c | 1 -
1 files changed, 0 insertions(+), 1 deletions(-)
diff --git a/src/server.c b/src/server.c
index 52f7f1e..16be849 100644
--- a/src/server.c
+++ b/src/server.c
@@ -31,7 +31,6 @@
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
-#include <errno.h>
#include <string.h>
#include <inttypes.h>
--
1.7.4.1
^ permalink raw reply related
* Re: [PATCH obexd 3/4] plugins: Remove redundant incude sys/stat.h
From: Syam Sidhardhan @ 2012-08-22 16:17 UTC (permalink / raw)
To: linux-bluetooth
In-Reply-To: <1345651858-23031-3-git-send-email-s.syam@samsung.com>
Hi,
----- Original Message -----
From: "Syam Sidhardhan" <s.syam@samsung.com>
To: <linux-bluetooth@vger.kernel.org>
Sent: Wednesday, August 22, 2012 9:40 PM
Subject: [PATCH obexd 3/4] plugins: Remove redundant incude sys/stat.h
> ---
> plugins/filesystem.c | 1 -
> 1 files changed, 0 insertions(+), 1 deletions(-)
>
> diff --git a/plugins/filesystem.c b/plugins/filesystem.c
> index e664fc5..1132a34 100644
> --- a/plugins/filesystem.c
> +++ b/plugins/filesystem.c
> @@ -32,7 +32,6 @@
> #include <string.h>
> #include <unistd.h>
> #include <dirent.h>
> -#include <sys/stat.h>
> #include <sys/types.h>
> #include <sys/stat.h>
> #include <sys/statvfs.h>
> --
%s/incude/include/g in commit message of 3/4 & 4/4.
Will send another version.
Regards,
Syam
^ permalink raw reply
* Re: [PATCH obexd v0] client-doc: Guarantee prefix in transfer paths
From: Patrick Ohly @ 2012-08-22 16:19 UTC (permalink / raw)
To: Luiz Augusto von Dentz; +Cc: Mikel Astiz, linux-bluetooth, Mikel Astiz
In-Reply-To: <CABBYNZLmM4DNUr031d_2MrDczN+K6-przkUFzWNkR7UTrxWf9w@mail.gmail.com>
On Wed, 2012-08-22 at 15:52 +0300, Luiz Augusto von Dentz wrote:
> Hi Patrick,
>
> On Wed, Aug 22, 2012 at 3:04 PM, Patrick Ohly <patrick.ohly@intel.com> wrote:
> > On Wed, 2012-08-22 at 14:39 +0300, Luiz Augusto von Dentz wrote:
> >> Hi Patrick,
> >>
> >> On Tue, Aug 21, 2012 at 11:31 AM, Patrick Ohly <patrick.ohly@intel.com> wrote:
> >> > It would be even better to explicitly mention that the "[variable
> >> > prefix]" here is the same as the "[variable prefix]" in the Session.
> >> >
> >> > Or perhaps change it like this?
> >> >
> >> > -Object path [variable prefix]/{transfer0,transfer1,...}
> >> > +Object path [session prefix]/{transfer0,...}
> >>
> >> Hmm, I prefer the original proposal since that imo looks more clear
> >> how the path is formatted, anyway the point here is that the transfers
> >> are tied to sessions.
> >
> > But as Marcel said, "variable prefix" means "no guarantee made about its
> > content, none whatsoever". Without knowing Bluez conventions, that was
> > also my understand when reading the API description. Assigning some
> > other meaning to "variable prefix" would break with developer
> > expectations.
>
> But we are not changing that, that why we return the object path to
> you, you will never have to guess it.
Knowing the path in advance is relevant for the client so that it can
set up an efficient signal watch before starting the transfer. That in
turn is needed to avoid race conditions. At the time that the client is
told the final path, it may already be too late to do anything with the
path.
> > Unless the meaning of "variable prefix" gets redefined, "[variable
> > prefix]/{session0,session1,...}" still doesn't allow the developer to do
> > path_namespace filtering.
>
> Im not sure why this is important? Prefix or variable prefix it does
> not matter, you will not be able to hardcode nor you should be
> constructing a path based on the session prefix, so if you are
> planning to do prefix matching I would strongly advise not to.
The prefix would not be hard-coded. The steps would be:
- create a session
- register for Transfer signals with a path prefix filter for the
session path as returned by obexd
- start a transfer
- process the signals
Currently this is not correct behavior, because the API makes no
guarantee about the "[variable prefix]" of Transfer objects. Therefore
clients have to receive and process *all* Transfer signals to avoid the
race condition described in the "obexd client API" mail.
I thought the purpose of the patch was to add that guarantee to the API
description.
> > I can imagine three ways to address race conditions:
> > 1. Clients subscribe to signals in advance, before any are sent.
>
> Can be done already, but it means you have to listen to every transfer
> which can cause you application to wakeup a little too much.
Exactly.
> > 2. Clients subscribe to signals later *and* check the current state.
> > 3. Clients provide a callback object with methods which get invoked by
> > obexd.
> >
> > The second option increases traffic and depends on being able to check
> > the current state. Currently this approach is not possible for Transfer
> > objects because they can get removed before the client checked their
> > state.
>
> I don't thing this is true, we do return the properties of the
> transfer so you don't need to check the current state just listen for
> changes,
Listen for changes *in advance* (given the current API). The returned
properties might already be out-dated. The path information is useful,
the completion state not so much. If it says "not complete yet", the
client needs a way to check for completion or failure reliably.
> btw if you mean a method call for checking the current state
> it does happen to have the same race conditions.
Right. To make it work, the life cycle of Transfer objects would have to
be changed.
> > The third option has the drawback that there's no standard way of
> > letting the client declare which of these methods it wants to have
> > called (in contrast to D-Bus signals). The advantage is that it becomes
> > possible to clean up temp files after completion of the transfer: add an
> > explicit "here's your result" callback method and when that fails,
> > delete the temporary file.
>
> We normally used the term agent for this type of object that is
> registered to act as callback mechanism, in fact this was used before
> and was just replaced with the current design recently as it was
> considered more complicated to the client application to implement and
> did not allow any other application like a download manager to listen
> for transfer progress.
Valid points. I included the option primarily for the sake of
completeness.
--
Best Regards, Patrick Ohly
The content of this message is my personal opinion only and although
I am an employee of Intel, the statements I make here in no way
represent Intel's position on the issue, nor am I authorized to speak
on behalf of Intel on this matter.
^ permalink raw reply
* [PATCH obexd v1 1/4] build: BlueZ version 4.100 or later is required
From: Syam Sidhardhan @ 2012-08-22 16:35 UTC (permalink / raw)
To: linux-bluetooth
If we use the BlueZ version less than 4.100, then the following
compilation error happens.
Error:
======
btio/btio.c: In function ‘l2cap_connect’:
btio/btio.c:301:6: error: ‘struct sockaddr_l2’ has no member named
‘l2_bdaddr_type’
btio/btio.c: In function ‘parse_set_opts’:
btio/btio.c:707:19: error: ‘BDADDR_BREDR’ undeclared (first use in
this function)
btio/btio.c:707:19: note: each undeclared identifier is reported only
once for each function it appears in
make[1]: *** [btio/btio.o] Error 1
make: *** [all] Error 2
---
configure.ac | 4 ++--
1 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/configure.ac b/configure.ac
index 69d71b2..c8e61ac 100644
--- a/configure.ac
+++ b/configure.ac
@@ -79,8 +79,8 @@ PKG_CHECK_MODULES(DBUS, dbus-1 >= 1.4, dummy=yes,
AC_SUBST(DBUS_CFLAGS)
AC_SUBST(DBUS_LIBS)
-PKG_CHECK_MODULES(BLUEZ, bluez >= 4.99, dummy=yes,
- AC_MSG_ERROR(BlueZ >= 4.99 is required))
+PKG_CHECK_MODULES(BLUEZ, bluez >= 4.100, dummy=yes,
+ AC_MSG_ERROR(BlueZ >= 4.100 is required))
AC_SUBST(BLUEZ_CFLAGS)
AC_SUBST(BLUEZ_LIBS)
--
1.7.4.1
^ permalink raw reply related
* [PATCH obexd v1 2/4] build: Require GLib 2.32 or later
From: Syam Sidhardhan @ 2012-08-22 16:35 UTC (permalink / raw)
To: linux-bluetooth
In-Reply-To: <1345653354-23720-1-git-send-email-s.syam@samsung.com>
If we use GLib version less than 2.32 (more precisely < 2.31.2) then
the following build error may occure in a 32 bit.
cc1: warnings being treated as errors
gobex/gobex-apparam.c: In function ‘g_obex_apparam_set_bytes’:
gobex/gobex-apparam.c:176:38: error: cast to pointer from integer of
different size
gobex/gobex-apparam.c: In function ‘g_obex_apparam_get_uint8’:
gobex/gobex-apparam.c:243:43: error: cast to pointer from integer of
different size
gobex/gobex-apparam.c: In function ‘g_obex_apparam_get_uint16’:
gobex/gobex-apparam.c:261:43: error: cast to pointer from integer of
different size
gobex/gobex-apparam.c: In function ‘g_obex_apparam_get_uint32’:
gobex/gobex-apparam.c:282:43: error: cast to pointer from integer of
different size
gobex/gobex-apparam.c: In function ‘g_obex_apparam_get_uint64’:
gobex/gobex-apparam.c:303:43: error: cast to pointer from integer of
different size
gobex/gobex-apparam.c: In function ‘g_obex_apparam_get_string’:
gobex/gobex-apparam.c:324:43: error: cast to pointer from integer of
different size
gobex/gobex-apparam.c: In function ‘g_obex_apparam_get_bytes’:
gobex/gobex-apparam.c:342:43: error: cast to pointer from integer of
different size
make[1]: *** [gobex/gobex-apparam.o] Error 1
make: *** [all] Error 2
---
Reference:
GLib tree: Commit: 16292dd753cb63f8ccb2267644aefbd2632dd52c
Author: Lucas De Marchi <lucas.demarchi@profusion.mobi>
Date: Thu Oct 6 11:18:03 2011 -0300
Fix G*_TO_POINTER casts on 32 bits
If we don't do the cast to the proper size in 32 bits, things like below
doesn't work:
uint8_t u = 20;
void *p;
p = GUINT_TO_POINTER(u);
Signed-off-by: Colin Walters <walters@verbum.org>
Thanks Luiz for giving this reference.
Btb I'm not very sure, is this the best way to solve this problem.
configure.ac | 4 ++--
1 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/configure.ac b/configure.ac
index c8e61ac..78da420 100644
--- a/configure.ac
+++ b/configure.ac
@@ -69,8 +69,8 @@ fi
AC_CHECK_LIB(dl, dlopen, dummy=yes,
AC_MSG_ERROR(dynamic linking loader is required))
-PKG_CHECK_MODULES(GLIB, glib-2.0 >= 2.28, dummy=yes,
- AC_MSG_ERROR(GLib >= 2.28 is required))
+PKG_CHECK_MODULES(GLIB, glib-2.0 >= 2.32, dummy=yes,
+ AC_MSG_ERROR(GLib >= 2.32 is required))
AC_SUBST(GLIB_CFLAGS)
AC_SUBST(GLIB_LIBS)
--
1.7.4.1
^ permalink raw reply related
* [PATCH obexd v1 3/4] plugins: Remove redundant include sys/stat.h
From: Syam Sidhardhan @ 2012-08-22 16:35 UTC (permalink / raw)
To: linux-bluetooth
In-Reply-To: <1345653354-23720-1-git-send-email-s.syam@samsung.com>
---
v1 => Corrected commit message typo
plugins/filesystem.c | 1 -
1 files changed, 0 insertions(+), 1 deletions(-)
diff --git a/plugins/filesystem.c b/plugins/filesystem.c
index e664fc5..1132a34 100644
--- a/plugins/filesystem.c
+++ b/plugins/filesystem.c
@@ -32,7 +32,6 @@
#include <string.h>
#include <unistd.h>
#include <dirent.h>
-#include <sys/stat.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/statvfs.h>
--
1.7.4.1
^ permalink raw reply related
* [PATCH obexd v1 4/4] core: Remove redundant include errno.h
From: Syam Sidhardhan @ 2012-08-22 16:35 UTC (permalink / raw)
To: linux-bluetooth
In-Reply-To: <1345653354-23720-1-git-send-email-s.syam@samsung.com>
---
v1 => Corrected commit message typo
src/server.c | 1 -
1 files changed, 0 insertions(+), 1 deletions(-)
diff --git a/src/server.c b/src/server.c
index 52f7f1e..16be849 100644
--- a/src/server.c
+++ b/src/server.c
@@ -31,7 +31,6 @@
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
-#include <errno.h>
#include <string.h>
#include <inttypes.h>
--
1.7.4.1
^ permalink raw reply related
* [PATCH BlueZ 1/4] gatt: Add support for find included services
From: Vinicius Costa Gomes @ 2012-08-22 19:31 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Jefferson Delfes
From: Jefferson Delfes <jefferson.delfes@openbossa.org>
Some services like HID over LE can reference another service using
included services.
See Vol 3, Part G, section 2.6.3 of Core specification for more
details.
---
attrib/gatt.c | 182 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
attrib/gatt.h | 9 +++
2 files changed, 191 insertions(+)
diff --git a/attrib/gatt.c b/attrib/gatt.c
index 6880e2d..2f80b7e 100644
--- a/attrib/gatt.c
+++ b/attrib/gatt.c
@@ -45,6 +45,21 @@ struct discover_primary {
void *user_data;
};
+struct find_included {
+ GAttrib *attrib;
+ uint16_t end_handle;
+ GSList *includes;
+ int resolving; /* number of UUID128 resolves pending */
+ gboolean finished;
+ gatt_cb_t cb;
+ void *user_data;
+};
+
+struct included_uuid_resolve {
+ struct find_included *fi;
+ struct gatt_included *included;
+};
+
struct discover_char {
GAttrib *attrib;
bt_uuid_t *uuid;
@@ -61,6 +76,13 @@ static void discover_primary_free(struct discover_primary *dp)
g_free(dp);
}
+static void find_included_free(struct find_included *fi)
+{
+ g_slist_free_full(fi->includes, g_free);
+ g_attrib_unref(fi->attrib);
+ g_free(fi);
+}
+
static void discover_char_free(struct discover_char *dc)
{
g_slist_free_full(dc->characteristics, g_free);
@@ -248,6 +270,166 @@ guint gatt_discover_primary(GAttrib *attrib, bt_uuid_t *uuid, gatt_cb_t func,
return g_attrib_send(attrib, 0, buf[0], buf, plen, cb, dp, NULL);
}
+static void resolve_included_uuid_cb(uint8_t status, const uint8_t *pdu,
+ uint16_t len, gpointer user_data)
+{
+ struct included_uuid_resolve *resolve = user_data;
+ struct find_included *fi = resolve->fi;
+ struct gatt_included *incl = resolve->included;
+ bt_uuid_t uuid;
+ unsigned int err = status;
+ size_t buflen;
+ uint8_t *buf;
+
+ if (err)
+ goto done;
+
+ buf = g_attrib_get_buffer(fi->attrib, &buflen);
+ if (dec_read_resp(pdu, len, buf, buflen) != 16) {
+ err = ATT_ECODE_IO;
+ goto done;
+ }
+
+ uuid = att_get_uuid128(buf);
+ bt_uuid_to_string(&uuid, incl->uuid, sizeof(incl->uuid));
+ fi->includes = g_slist_append(fi->includes, incl);
+ fi->resolving--;
+
+done:
+ if ((fi->finished && fi->resolving == 0) || err) {
+ fi->cb(fi->includes, err, fi->user_data);
+ find_included_free(fi);
+ }
+
+ if (err)
+ g_free(incl);
+
+ g_free(resolve);
+}
+
+static guint resolve_included_uuid(struct find_included *fi,
+ struct gatt_included *incl)
+{
+ size_t buflen;
+ uint8_t *buf = g_attrib_get_buffer(fi->attrib, &buflen);
+ guint16 oplen = enc_read_req(incl->range.start, buf, buflen);
+ struct included_uuid_resolve *resolve;
+
+ resolve = g_new0(struct included_uuid_resolve, 1);
+ resolve->fi = fi;
+ resolve->included = incl;
+
+ return g_attrib_send(fi->attrib, 0, buf[0], buf, oplen,
+ resolve_included_uuid_cb, resolve, NULL);
+}
+
+static struct gatt_included *included_from_buf(const uint8_t *buf, gsize buflen)
+{
+ struct gatt_included *incl = g_new0(struct gatt_included, 1);
+
+ incl->handle = att_get_u16(&buf[0]);
+ incl->range.start = att_get_u16(&buf[2]);
+ incl->range.end = att_get_u16(&buf[4]);
+
+ if (buflen == 8) {
+ bt_uuid_t uuid128;
+ bt_uuid_t uuid16 = att_get_uuid16(&buf[6]);
+
+ bt_uuid_to_uuid128(&uuid16, &uuid128);
+ bt_uuid_to_string(&uuid128, incl->uuid, sizeof(incl->uuid));
+ }
+
+ return incl;
+}
+
+static void find_included_cb(uint8_t status, const uint8_t *pdu, uint16_t len,
+ gpointer user_data);
+
+static guint call_find_included(struct find_included *fi, uint16_t start)
+{
+ bt_uuid_t uuid;
+ size_t buflen;
+ uint8_t *buf = g_attrib_get_buffer(fi->attrib, &buflen);
+ guint16 oplen;
+
+ bt_uuid16_create(&uuid, GATT_INCLUDE_UUID);
+ oplen = enc_read_by_type_req(start, fi->end_handle, &uuid,
+ buf, buflen);
+
+ return g_attrib_send(fi->attrib, 0, buf[0], buf, oplen,
+ find_included_cb, fi, NULL);
+}
+
+static void find_included_cb(uint8_t status, const uint8_t *pdu, uint16_t len,
+ gpointer user_data)
+{
+ struct find_included *fi = user_data;
+ uint16_t last_handle = fi->end_handle;
+ unsigned int err = status;
+ struct att_data_list *list;
+ int i;
+
+ if (err == ATT_ECODE_ATTR_NOT_FOUND)
+ err = 0;
+
+ if (status)
+ goto done;
+
+ list = dec_read_by_type_resp(pdu, len);
+ if (list == NULL) {
+ err = ATT_ECODE_IO;
+ goto done;
+ }
+
+ if (list->len != 6 || list->len != 8) {
+ att_data_list_free(list);
+ goto done;
+ }
+
+ for (i = 0; i < list->num; i++) {
+ struct gatt_included *incl;
+
+ incl = included_from_buf(list->data[i], list->len);
+ /* 128 bit UUID, needs resolving */
+ if (list->len == 6) {
+ fi->resolving++;
+ resolve_included_uuid(fi, incl);
+ continue;
+ }
+
+ fi->includes = g_slist_append(fi->includes, incl);
+ }
+
+ att_data_list_free(list);
+
+ if (last_handle != fi->end_handle) {
+ call_find_included(fi, last_handle + 1);
+ return;
+ }
+
+ fi->finished = TRUE;
+
+done:
+ if (fi->resolving == 0 || err) {
+ fi->cb(fi->includes, err, fi->user_data);
+ find_included_free(fi);
+ }
+}
+
+unsigned int gatt_find_included(GAttrib *attrib, uint16_t start, uint16_t end,
+ gatt_cb_t func, gpointer user_data)
+{
+ struct find_included *fi;
+
+ fi = g_new0(struct find_included, 1);
+ fi->attrib = g_attrib_ref(attrib);
+ fi->end_handle = end;
+ fi->cb = func;
+ fi->user_data = user_data;
+
+ return call_find_included(fi, start);
+}
+
static void char_discovered_cb(guint8 status, const guint8 *ipdu, guint16 iplen,
gpointer user_data)
{
diff --git a/attrib/gatt.h b/attrib/gatt.h
index a15e92f..dbec67f 100644
--- a/attrib/gatt.h
+++ b/attrib/gatt.h
@@ -61,6 +61,12 @@ struct gatt_primary {
struct att_range range;
};
+struct gatt_included {
+ char uuid[MAX_LEN_UUID_STR + 1];
+ uint16_t handle;
+ struct att_range range;
+};
+
struct gatt_char {
char uuid[MAX_LEN_UUID_STR + 1];
uint16_t handle;
@@ -71,6 +77,9 @@ struct gatt_char {
guint gatt_discover_primary(GAttrib *attrib, bt_uuid_t *uuid, gatt_cb_t func,
gpointer user_data);
+unsigned int gatt_find_included(GAttrib *attrib, uint16_t start, uint16_t end,
+ gatt_cb_t func, gpointer user_data);
+
guint gatt_discover_char(GAttrib *attrib, uint16_t start, uint16_t end,
bt_uuid_t *uuid, gatt_cb_t func,
gpointer user_data);
--
1.7.11.4
^ permalink raw reply related
* [PATCH BlueZ 2/4] gatttool: Add "included" command
From: Vinicius Costa Gomes @ 2012-08-22 19:31 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Jefferson Delfes
In-Reply-To: <1345663916-29989-1-git-send-email-vinicius.gomes@openbossa.org>
From: Jefferson Delfes <jefferson.delfes@openbossa.org>
New command to find included services in interactive mode.
---
attrib/interactive.c | 60 ++++++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 60 insertions(+)
diff --git a/attrib/interactive.c b/attrib/interactive.c
index 3e8a0d9..01201ef 100644
--- a/attrib/interactive.c
+++ b/attrib/interactive.c
@@ -209,6 +209,34 @@ static void primary_by_uuid_cb(GSList *ranges, guint8 status,
rl_forced_update_display();
}
+static void included_cb(GSList *includes, guint8 status, gpointer user_data)
+{
+ GSList *l;
+
+ if (status) {
+ printf("Find included services failed: %s\n",
+ att_ecode2str(status));
+ goto done;
+ }
+
+ if (includes == NULL) {
+ printf("No included services found for this range\n");
+ goto done;
+ }
+
+ printf("\n");
+ for (l = includes; l; l = l->next) {
+ struct gatt_included *incl = l->data;
+ printf("handle: 0x%04x, start handle: 0x%04x, "
+ "end handle: 0x%04x uuid: %s\n",
+ incl->handle, incl->range.start,
+ incl->range.end, incl->uuid);
+ }
+
+done:
+ rl_forced_update_display();
+}
+
static void char_cb(GSList *characteristics, guint8 status, gpointer user_data)
{
GSList *l;
@@ -426,6 +454,36 @@ static int strtohandle(const char *src)
return dst;
}
+static void cmd_included(int argcp, char **argvp)
+{
+ int start = 0x0001;
+ int end = 0xffff;
+
+ if (conn_state != STATE_CONNECTED) {
+ printf("Command failed: disconnected\n");
+ return;
+ }
+
+ if (argcp > 1) {
+ start = strtohandle(argvp[1]);
+ if (start < 0) {
+ printf("Invalid start handle: %s\n", argvp[1]);
+ return;
+ }
+ end = start;
+ }
+
+ if (argcp > 2) {
+ end = strtohandle(argvp[2]);
+ if (end < 0) {
+ printf("Invalid end handle: %s\n", argvp[2]);
+ return;
+ }
+ }
+
+ gatt_find_included(attrib, start, end, included_cb, NULL);
+}
+
static void cmd_char(int argcp, char **argvp)
{
int start = 0x0001;
@@ -752,6 +810,8 @@ static struct {
"Disconnect from a remote device" },
{ "primary", cmd_primary, "[UUID]",
"Primary Service Discovery" },
+ { "included", cmd_included, "[start hnd [end hnd]]",
+ "Find Included Services" },
{ "characteristics", cmd_char, "[start hnd [end hnd [UUID]]]",
"Characteristics Discovery" },
{ "char-desc", cmd_char_desc, "[start hnd] [end hnd]",
--
1.7.11.4
^ permalink raw reply related
* [PATCH BlueZ 3/4] core: Add support for included services
From: Vinicius Costa Gomes @ 2012-08-22 19:31 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Vinicius Costa Gomes
In-Reply-To: <1345663916-29989-1-git-send-email-vinicius.gomes@openbossa.org>
Soon after the primary service discovery is complete, we do a included
services discovery for all found services and add each included service
to the 'services' list so they can be probe()'d as a normal profile.
This will also make these services to appear on the D-Bus object tree.
---
src/device.c | 109 ++++++++++++++++++++++++++++++++++++++++++++++++++++-------
1 file changed, 96 insertions(+), 13 deletions(-)
diff --git a/src/device.c b/src/device.c
index 7b44e27..360969c 100644
--- a/src/device.c
+++ b/src/device.c
@@ -106,6 +106,12 @@ struct browse_req {
guint listener_id;
};
+struct included_search {
+ struct browse_req *req;
+ GSList *services;
+ GSList *current;
+};
+
struct attio_data {
guint id;
attio_connect_cb cfunc;
@@ -1877,21 +1883,10 @@ static void device_unregister_services(struct btd_device *device)
device->services = NULL;
}
-static void primary_cb(GSList *services, guint8 status, gpointer user_data)
+static void register_all_services(struct browse_req *req, GSList *services)
{
- struct browse_req *req = user_data;
struct btd_device *device = req->device;
- if (status) {
- if (req->msg) {
- DBusMessage *reply;
- reply = btd_error_failed(req->msg,
- att_ecode2str(status));
- g_dbus_send_message(req->conn, reply);
- }
- goto done;
- }
-
device_set_temporary(device, FALSE);
if (device->services)
@@ -1916,11 +1911,99 @@ static void primary_cb(GSList *services, guint8 status, gpointer user_data)
store_services(device);
-done:
device->browse = NULL;
browse_request_free(req);
}
+static int service_by_range_cmp(gconstpointer a, gconstpointer b)
+{
+ const struct gatt_primary *prim = a;
+ const struct att_range *range = b;
+
+ return memcmp(&prim->range, range, sizeof(*range));
+}
+
+static void find_included_cb(GSList *includes, uint8_t status,
+ gpointer user_data)
+{
+ struct included_search *search = user_data;
+ struct btd_device *device = search->req->device;
+ struct gatt_primary *prim;
+ GSList *l;
+
+ if (includes == NULL)
+ goto done;
+
+ for (l = includes; l; l = l->next) {
+ struct gatt_included *incl = l->data;
+
+ if (g_slist_find_custom(search->services, &incl->range,
+ service_by_range_cmp))
+ continue;
+
+ prim = g_new0(struct gatt_primary, 1);
+ memcpy(prim->uuid, incl->uuid, sizeof(prim->uuid));
+ memcpy(&prim->range, &incl->range, sizeof(prim->range));
+
+ search->services = g_slist_append(search->services, prim);
+ }
+
+done:
+ search->current = search->current->next;
+ if (search->current == NULL) {
+ register_all_services(search->req, search->services);
+ g_slist_free(search->services);
+ g_free(search);
+ return;
+ }
+
+ prim = search->current->data;
+ gatt_find_included(device->attrib, prim->range.start, prim->range.end,
+ find_included_cb, search);
+}
+
+static void find_included_services(struct browse_req *req, GSList *services)
+{
+ struct btd_device *device = req->device;
+ struct included_search *search;
+ struct gatt_primary *prim;
+
+ if (services == NULL)
+ return;
+
+ search = g_new0(struct included_search, 1);
+ search->req = req;
+ search->services = g_slist_copy(services);
+ search->current = search->services;
+
+ prim = search->current->data;
+ gatt_find_included(device->attrib, prim->range.start, prim->range.end,
+ find_included_cb, search);
+
+}
+
+static void primary_cb(GSList *services, guint8 status, gpointer user_data)
+{
+ struct browse_req *req = user_data;
+
+ if (status) {
+ struct btd_device *device = req->device;
+
+ if (req->msg) {
+ DBusMessage *reply;
+ reply = btd_error_failed(req->msg,
+ att_ecode2str(status));
+ g_dbus_send_message(req->conn, reply);
+ }
+
+ device->browse = NULL;
+ browse_request_free(req);
+ return;
+ }
+
+ find_included_services(req, services);
+}
+
static void att_connect_cb(GIOChannel *io, GError *gerr, gpointer user_data)
{
struct att_callbacks *attcb = user_data;
--
1.7.11.4
^ permalink raw reply related
* [PATCH BlueZ 4/4] attrib: Remove opcode parameter from g_attrib_send()
From: Vinicius Costa Gomes @ 2012-08-22 19:31 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Vinicius Costa Gomes
In-Reply-To: <1345663916-29989-1-git-send-email-vinicius.gomes@openbossa.org>
In all uses of g_attrib_send() the opcode of the command/event is
already clear because of the att.h functions used to build the ATT
PDU.
---
attrib/client.c | 3 +-
attrib/gatt.c | 56 ++++++++++++++++----------------------
attrib/gattrib.c | 9 ++++--
attrib/gattrib.h | 6 ++--
attrib/gatttool.c | 2 +-
attrib/interactive.c | 2 +-
profiles/gatt/gas.c | 2 +-
profiles/thermometer/thermometer.c | 3 +-
src/attrib-server.c | 3 +-
9 files changed, 39 insertions(+), 47 deletions(-)
diff --git a/attrib/client.c b/attrib/client.c
index c438d7c..48b88e6 100644
--- a/attrib/client.c
+++ b/attrib/client.c
@@ -298,8 +298,7 @@ static void events_handler(const uint8_t *pdu, uint16_t len,
case ATT_OP_HANDLE_IND:
opdu = g_attrib_get_buffer(gatt->attrib, &plen);
olen = enc_confirmation(opdu, plen);
- g_attrib_send(gatt->attrib, 0, opdu[0], opdu, olen,
- NULL, NULL, NULL);
+ g_attrib_send(gatt->attrib, 0, opdu, olen, NULL, NULL, NULL);
case ATT_OP_HANDLE_NOTIFY:
if (characteristic_set_value(chr, &pdu[3], len - 3) < 0)
DBG("Can't change Characteristic 0x%02x", handle);
diff --git a/attrib/gatt.c b/attrib/gatt.c
index 2f80b7e..457e798 100644
--- a/attrib/gatt.c
+++ b/attrib/gatt.c
@@ -163,8 +163,7 @@ static void primary_by_uuid_cb(guint8 status, const guint8 *ipdu,
if (oplen == 0)
goto done;
- g_attrib_send(dp->attrib, 0, buf[0], buf, oplen, primary_by_uuid_cb,
- dp, NULL);
+ g_attrib_send(dp->attrib, 0, buf, oplen, primary_by_uuid_cb, dp, NULL);
return;
done:
@@ -229,7 +228,7 @@ static void primary_all_cb(guint8 status, const guint8 *ipdu, guint16 iplen,
guint16 oplen = encode_discover_primary(end + 1, 0xffff, NULL,
buf, buflen);
- g_attrib_send(dp->attrib, 0, buf[0], buf, oplen, primary_all_cb,
+ g_attrib_send(dp->attrib, 0, buf, oplen, primary_all_cb,
dp, NULL);
return;
@@ -267,7 +266,7 @@ guint gatt_discover_primary(GAttrib *attrib, bt_uuid_t *uuid, gatt_cb_t func,
} else
cb = primary_all_cb;
- return g_attrib_send(attrib, 0, buf[0], buf, plen, cb, dp, NULL);
+ return g_attrib_send(attrib, 0, buf, plen, cb, dp, NULL);
}
static void resolve_included_uuid_cb(uint8_t status, const uint8_t *pdu,
@@ -319,8 +318,8 @@ static guint resolve_included_uuid(struct find_included *fi,
resolve->fi = fi;
resolve->included = incl;
- return g_attrib_send(fi->attrib, 0, buf[0], buf, oplen,
- resolve_included_uuid_cb, resolve, NULL);
+ return g_attrib_send(fi->attrib, 0, buf, oplen,
+ resolve_included_uuid_cb, resolve, NULL);
}
static struct gatt_included *included_from_buf(const uint8_t *buf, gsize buflen)
@@ -356,8 +355,8 @@ static guint call_find_included(struct find_included *fi, uint16_t start)
oplen = enc_read_by_type_req(start, fi->end_handle, &uuid,
buf, buflen);
- return g_attrib_send(fi->attrib, 0, buf[0], buf, oplen,
- find_included_cb, fi, NULL);
+ return g_attrib_send(fi->attrib, 0, buf, oplen, find_included_cb,
+ fi, NULL);
}
static void find_included_cb(uint8_t status, const uint8_t *pdu, uint16_t len,
@@ -496,8 +495,8 @@ static void char_discovered_cb(guint8 status, const guint8 *ipdu, guint16 iplen,
if (oplen == 0)
return;
- g_attrib_send(dc->attrib, 0, buf[0], buf, oplen,
- char_discovered_cb, dc, NULL);
+ g_attrib_send(dc->attrib, 0, buf, oplen, char_discovered_cb,
+ dc, NULL);
return;
}
@@ -535,7 +534,7 @@ guint gatt_discover_char(GAttrib *attrib, uint16_t start, uint16_t end,
dc->end = end;
dc->uuid = g_memdup(uuid, sizeof(bt_uuid_t));
- return g_attrib_send(attrib, 0, buf[0], buf, plen, char_discovered_cb,
+ return g_attrib_send(attrib, 0, buf, plen, char_discovered_cb,
dc, NULL);
}
@@ -551,8 +550,7 @@ guint gatt_read_char_by_uuid(GAttrib *attrib, uint16_t start, uint16_t end,
if (plen == 0)
return 0;
- return g_attrib_send(attrib, 0, ATT_OP_READ_BY_TYPE_REQ,
- buf, plen, func, user_data, NULL);
+ return g_attrib_send(attrib, 0, buf, plen, func, user_data, NULL);
}
struct read_long_data {
@@ -611,8 +609,7 @@ static void read_blob_helper(guint8 status, const guint8 *rpdu, guint16 rlen,
plen = enc_read_blob_req(long_read->handle, long_read->size - 1,
buf, buflen);
- id = g_attrib_send(long_read->attrib, long_read->id,
- ATT_OP_READ_BLOB_REQ, buf, plen,
+ id = g_attrib_send(long_read->attrib, long_read->id, buf, plen,
read_blob_helper, long_read, read_long_destroy);
if (id != 0) {
@@ -648,9 +645,8 @@ static void read_char_helper(guint8 status, const guint8 *rpdu,
long_read->size = rlen;
plen = enc_read_blob_req(long_read->handle, rlen - 1, buf, buflen);
- id = g_attrib_send(long_read->attrib, long_read->id,
- ATT_OP_READ_BLOB_REQ, buf, plen, read_blob_helper,
- long_read, read_long_destroy);
+ id = g_attrib_send(long_read->attrib, long_read->id, buf, plen,
+ read_blob_helper, long_read, read_long_destroy);
if (id != 0) {
g_atomic_int_inc(&long_read->ref);
@@ -686,12 +682,12 @@ guint gatt_read_char(GAttrib *attrib, uint16_t handle, uint16_t offset,
if (offset > 0) {
plen = enc_read_blob_req(long_read->handle, offset, buf,
buflen);
- id = g_attrib_send(attrib, 0, ATT_OP_READ_BLOB_REQ, buf, plen,
- read_blob_helper, long_read, read_long_destroy);
+ id = g_attrib_send(attrib, 0, buf, plen, read_blob_helper,
+ long_read, read_long_destroy);
} else {
plen = enc_read_req(handle, buf, buflen);
- id = g_attrib_send(attrib, 0, ATT_OP_READ_REQ, buf, plen,
- read_char_helper, long_read, read_long_destroy);
+ id = g_attrib_send(attrib, 0, buf, plen, read_char_helper,
+ long_read, read_long_destroy);
}
if (id == 0)
@@ -726,8 +722,7 @@ static guint execute_write(GAttrib *attrib, uint8_t flags,
if (plen == 0)
return 0;
- return g_attrib_send(attrib, 0, buf[0], buf, plen, func, user_data,
- NULL);
+ return g_attrib_send(attrib, 0, buf, plen, func, user_data, NULL);
}
static guint prepare_write(GAttrib *attrib, uint16_t handle, uint16_t offset,
@@ -776,7 +771,7 @@ static guint prepare_write(GAttrib *attrib, uint16_t handle, uint16_t offset,
if (plen == 0)
return 0;
- return g_attrib_send(attrib, 0, buf[0], buf, plen, prepare_write_cb,
+ return g_attrib_send(attrib, 0, buf, plen, prepare_write_cb,
user_data, NULL);
}
@@ -800,7 +795,7 @@ guint gatt_write_char(GAttrib *attrib, uint16_t handle, uint8_t *value,
plen = enc_write_cmd(handle, value, vlen, buf,
buflen);
- return g_attrib_send(attrib, 0, buf[0], buf, plen, func,
+ return g_attrib_send(attrib, 0, buf, plen, func,
user_data, NULL);
}
@@ -829,8 +824,7 @@ guint gatt_exchange_mtu(GAttrib *attrib, uint16_t mtu, GAttribResultFunc func,
buf = g_attrib_get_buffer(attrib, &buflen);
plen = enc_mtu_req(mtu, buf, buflen);
- return g_attrib_send(attrib, 0, ATT_OP_MTU_REQ, buf, plen, func,
- user_data, NULL);
+ return g_attrib_send(attrib, 0, buf, plen, func, user_data, NULL);
}
guint gatt_find_info(GAttrib *attrib, uint16_t start, uint16_t end,
@@ -845,8 +839,7 @@ guint gatt_find_info(GAttrib *attrib, uint16_t start, uint16_t end,
if (plen == 0)
return 0;
- return g_attrib_send(attrib, 0, ATT_OP_FIND_INFO_REQ, buf, plen, func,
- user_data, NULL);
+ return g_attrib_send(attrib, 0, buf, plen, func, user_data, NULL);
}
guint gatt_write_cmd(GAttrib *attrib, uint16_t handle, uint8_t *value, int vlen,
@@ -858,8 +851,7 @@ guint gatt_write_cmd(GAttrib *attrib, uint16_t handle, uint8_t *value, int vlen,
buf = g_attrib_get_buffer(attrib, &buflen);
plen = enc_write_cmd(handle, value, vlen, buf, buflen);
- return g_attrib_send(attrib, 0, ATT_OP_WRITE_CMD, buf, plen, NULL,
- user_data, notify);
+ return g_attrib_send(attrib, 0, buf, plen, NULL, user_data, notify);
}
static sdp_data_t *proto_seq_find(sdp_list_t *proto_list)
diff --git a/attrib/gattrib.c b/attrib/gattrib.c
index c91f5e9..f9652b3 100644
--- a/attrib/gattrib.c
+++ b/attrib/gattrib.c
@@ -475,12 +475,13 @@ GAttrib *g_attrib_new(GIOChannel *io)
return g_attrib_ref(attrib);
}
-guint g_attrib_send(GAttrib *attrib, guint id, guint8 opcode,
- const guint8 *pdu, guint16 len, GAttribResultFunc func,
- gpointer user_data, GDestroyNotify notify)
+guint g_attrib_send(GAttrib *attrib, guint id, const guint8 *pdu, guint16 len,
+ GAttribResultFunc func, gpointer user_data,
+ GDestroyNotify notify)
{
struct command *c;
GQueue *queue;
+ uint8_t opcode;
if (attrib->stale)
return 0;
@@ -489,6 +490,8 @@ guint g_attrib_send(GAttrib *attrib, guint id, guint8 opcode,
if (c == NULL)
return 0;
+ opcode = pdu[0];
+
c->opcode = opcode;
c->expected = opcode2expected(opcode);
c->pdu = g_malloc(len);
diff --git a/attrib/gattrib.h b/attrib/gattrib.h
index bcff039..bca966f 100644
--- a/attrib/gattrib.h
+++ b/attrib/gattrib.h
@@ -50,9 +50,9 @@ GIOChannel *g_attrib_get_channel(GAttrib *attrib);
gboolean g_attrib_set_destroy_function(GAttrib *attrib,
GDestroyNotify destroy, gpointer user_data);
-guint g_attrib_send(GAttrib *attrib, guint id, guint8 opcode,
- const guint8 *pdu, guint16 len, GAttribResultFunc func,
- gpointer user_data, GDestroyNotify notify);
+guint g_attrib_send(GAttrib *attrib, guint id, const guint8 *pdu, guint16 len,
+ GAttribResultFunc func, gpointer user_data,
+ GDestroyNotify notify);
gboolean g_attrib_cancel(GAttrib *attrib, guint id);
gboolean g_attrib_cancel_all(GAttrib *attrib);
diff --git a/attrib/gatttool.c b/attrib/gatttool.c
index 416bb71..dea1fc4 100644
--- a/attrib/gatttool.c
+++ b/attrib/gatttool.c
@@ -105,7 +105,7 @@ static void events_handler(const uint8_t *pdu, uint16_t len, gpointer user_data)
olen = enc_confirmation(opdu, plen);
if (olen > 0)
- g_attrib_send(attrib, 0, opdu[0], opdu, olen, NULL, NULL, NULL);
+ g_attrib_send(attrib, 0, opdu, olen, NULL, NULL, NULL);
}
static gboolean listen_start(gpointer user_data)
diff --git a/attrib/interactive.c b/attrib/interactive.c
index 01201ef..34417e0 100644
--- a/attrib/interactive.c
+++ b/attrib/interactive.c
@@ -133,7 +133,7 @@ static void events_handler(const uint8_t *pdu, uint16_t len, gpointer user_data)
olen = enc_confirmation(opdu, plen);
if (olen > 0)
- g_attrib_send(attrib, 0, opdu[0], opdu, olen, NULL, NULL, NULL);
+ g_attrib_send(attrib, 0, opdu, olen, NULL, NULL, NULL);
}
static void connect_cb(GIOChannel *io, GError *err, gpointer user_data)
diff --git a/profiles/gatt/gas.c b/profiles/gatt/gas.c
index e82513b..7211898 100644
--- a/profiles/gatt/gas.c
+++ b/profiles/gatt/gas.c
@@ -148,7 +148,7 @@ static void indication_cb(const uint8_t *pdu, uint16_t len, gpointer user_data)
/* Confirming indication received */
opdu = g_attrib_get_buffer(gas->attrib, &plen);
olen = enc_confirmation(opdu, plen);
- g_attrib_send(gas->attrib, 0, opdu[0], opdu, olen, NULL, NULL, NULL);
+ g_attrib_send(gas->attrib, 0, opdu, olen, NULL, NULL, NULL);
if (gas->changed.start == start && gas->changed.end == end)
return;
diff --git a/profiles/thermometer/thermometer.c b/profiles/thermometer/thermometer.c
index 6652a41..696693a 100644
--- a/profiles/thermometer/thermometer.c
+++ b/profiles/thermometer/thermometer.c
@@ -1167,8 +1167,7 @@ static void ind_handler(const uint8_t *pdu, uint16_t len, gpointer user_data)
olen = enc_confirmation(opdu, plen);
if (olen > 0)
- g_attrib_send(t->attrib, 0, opdu[0], opdu, olen, NULL, NULL,
- NULL);
+ g_attrib_send(t->attrib, 0, opdu, olen, NULL, NULL, NULL);
}
static void notif_handler(const uint8_t *pdu, uint16_t len, gpointer user_data)
diff --git a/src/attrib-server.c b/src/attrib-server.c
index 145fada..541a430 100644
--- a/src/attrib-server.c
+++ b/src/attrib-server.c
@@ -1032,8 +1032,7 @@ done:
length = enc_error_resp(ipdu[0], 0x0000, status, opdu,
channel->mtu);
- g_attrib_send(channel->attrib, 0, opdu[0], opdu, length,
- NULL, NULL, NULL);
+ g_attrib_send(channel->attrib, 0, opdu, length, NULL, NULL, NULL);
}
guint attrib_channel_attach(GAttrib *attrib)
--
1.7.11.4
^ permalink raw reply related
* [PATCH 1/2] Bluetooth: mgmt: Fix sending events with uninitialized data
From: Vinicius Costa Gomes @ 2012-08-22 19:33 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Vinicius Costa Gomes
In response to the Read Index List command, it is possible that
uninitialized data is sent to userspace because the way the number
of adapters is counted. This way we only count adapters that will
be included in the response.
Signed-off-by: Vinicius Costa Gomes <vinicius.gomes@openbossa.org>
---
net/bluetooth/mgmt.c | 3 +++
1 file changed, 3 insertions(+)
diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c
index 05d4b83..6219a39 100644
--- a/net/bluetooth/mgmt.c
+++ b/net/bluetooth/mgmt.c
@@ -333,6 +333,9 @@ static int read_index_list(struct sock *sk, struct hci_dev *hdev, void *data,
count = 0;
list_for_each_entry(d, &hci_dev_list, list) {
+ if (test_bit(HCI_SETUP, &d->dev_flags))
+ continue;
+
if (!mgmt_valid_hdev(d))
continue;
--
1.7.11.4
^ permalink raw reply related
* [PATCH 2/2] Bluetooth: Power the device up after a rfkill unblock
From: Vinicius Costa Gomes @ 2012-08-22 19:33 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Vinicius Costa Gomes
In-Reply-To: <1345664010-30471-1-git-send-email-vinicius.gomes@openbossa.org>
With the HCI_SETUP patches, this is all that is needed to make the
case when a adapter is added with Bluetooth blocked in rfkill to work.
When rfkill is unblocked, the device will be powered on, and if not
needed it will be automatically powered off.
Signed-off-by: Vinicius Costa Gomes <vinicius.gomes@openbossa.org>
---
net/bluetooth/hci_core.c | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c
index fa974a1..395dcc6 100644
--- a/net/bluetooth/hci_core.c
+++ b/net/bluetooth/hci_core.c
@@ -1061,8 +1061,10 @@ static int hci_rfkill_set_block(void *data, bool blocked)
BT_DBG("%p name %s blocked %d", hdev, hdev->name, blocked);
- if (!blocked)
+ if (!blocked) {
+ schedule_work(&hdev->power_on);
return 0;
+ }
hci_dev_do_close(hdev);
--
1.7.11.4
^ permalink raw reply related
* [PATCH BlueZ] gatt: GAP and GATT services are mandatory
From: Claudio Takahasi @ 2012-08-22 19:38 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Claudio Takahasi
This patch fixes potential segmentation fault if the remote doesn't
support GAP and GATT services.
---
profiles/gatt/manager.c | 9 +++++++--
1 file changed, 7 insertions(+), 2 deletions(-)
diff --git a/profiles/gatt/manager.c b/profiles/gatt/manager.c
index a1fa756..0702d26 100644
--- a/profiles/gatt/manager.c
+++ b/profiles/gatt/manager.c
@@ -30,6 +30,7 @@
#include "gattrib.h"
#include "gatt.h"
#include "gas.h"
+#include "log.h"
#include "manager.h"
static gint primary_uuid_cmp(gconstpointer a, gconstpointer b)
@@ -55,8 +56,12 @@ static int gatt_driver_probe(struct btd_device *device, GSList *uuids)
if (l)
gatt = l->data;
- return gas_register(device, gap ? &gap->range : NULL,
- gatt ? &gatt->range : NULL);
+ if (gap == NULL || gatt == NULL) {
+ error("GAP and GATT are mandatory");
+ return -EINVAL;
+ }
+
+ return gas_register(device, &gap->range, &gatt->range);
}
static void gatt_driver_remove(struct btd_device *device)
--
1.7.12
^ permalink raw reply related
* [PATCH BlueZ v0 0/8] Scan Parameters Plugin
From: Claudio Takahasi @ 2012-08-22 19:45 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Claudio Takahasi
This patch series implements a new GATT based service/plugin for Scan
Parameters: Optional service for HID devices.
This service enables a GATT Client to store the LE scan parameters on
a GATT Server device, allowing the GATT Server to utilize the information
to adjust behavior to optimize power consumption and/or reconnection
latency.
Claudio Takahasi (8):
scan: Add plugin skeleton
scan: Register device driver
scan: Add ATTIO callbacks registration
scan: Add write scan interval window
scan: Enable Scan Refresh notification
scan: Register notification handler
scan: Write parameters when requested
scan: Avoid discover if scan handle is known
Makefile.am | 8 +-
profiles/scanparam/main.c | 55 +++++++++
profiles/scanparam/manager.c | 89 ++++++++++++++
profiles/scanparam/manager.h | 26 +++++
profiles/scanparam/scan.c | 272 +++++++++++++++++++++++++++++++++++++++++++
profiles/scanparam/scan.h | 26 +++++
6 files changed, 474 insertions(+), 2 deletions(-)
create mode 100644 profiles/scanparam/main.c
create mode 100644 profiles/scanparam/manager.c
create mode 100644 profiles/scanparam/manager.h
create mode 100644 profiles/scanparam/scan.c
create mode 100644 profiles/scanparam/scan.h
--
1.7.12
^ permalink raw reply
* [PATCH BlueZ v0 1/8] scan: Add plugin skeleton
From: Claudio Takahasi @ 2012-08-22 19:45 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Claudio Takahasi
In-Reply-To: <1345664723-30814-1-git-send-email-claudio.takahasi@openbossa.org>
This patch adds the Makefile changes and plugin declaration to support
Scan Parameters service. BlueZ will act as Scan Client writting to a Scan
Server the scanning parameters.
---
Makefile.am | 5 +++--
profiles/scanparam/main.c | 53 +++++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 56 insertions(+), 2 deletions(-)
create mode 100644 profiles/scanparam/main.c
diff --git a/Makefile.am b/Makefile.am
index 4977a05..161586e 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -212,7 +212,7 @@ endif
if GATTMODULES
builtin_modules += thermometer alert time gatt_example proximity deviceinfo \
- gatt
+ gatt scanparam
builtin_sources += profiles/thermometer/main.c \
profiles/thermometer/manager.h \
profiles/thermometer/manager.c \
@@ -241,7 +241,8 @@ builtin_sources += profiles/thermometer/main.c \
profiles/deviceinfo/deviceinfo.c \
profiles/gatt/main.c profiles/gatt/manager.h \
profiles/gatt/manager.c profiles/gatt/gas.h \
- profiles/gatt/gas.c
+ profiles/gatt/gas.c \
+ profiles/scanparam/main.c
endif
builtin_modules += formfactor
diff --git a/profiles/scanparam/main.c b/profiles/scanparam/main.c
new file mode 100644
index 0000000..6e90929
--- /dev/null
+++ b/profiles/scanparam/main.c
@@ -0,0 +1,53 @@
+/*
+ *
+ * BlueZ - Bluetooth protocol stack for Linux
+ *
+ * Copyright (C) 2012 Nordic Semiconductor Inc.
+ * Copyright (C) 2012 Instituto Nokia de Tecnologia - INdT
+ *
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <errno.h>
+#include <stdint.h>
+#include <glib.h>
+
+#include "log.h"
+#include "plugin.h"
+#include "hcid.h"
+
+static int scan_param_init(void)
+{
+ if (!main_opts.gatt_enabled) {
+ DBG("Scan Parameters: GATT is disabled");
+ return -ENOTSUP;
+ }
+
+ return 0;
+}
+
+static void scan_param_exit(void)
+{
+}
+
+BLUETOOTH_PLUGIN_DEFINE(scanparam, VERSION,
+ BLUETOOTH_PLUGIN_PRIORITY_DEFAULT,
+ scan_param_init, scan_param_exit)
--
1.7.12
^ permalink raw reply related
* [PATCH BlueZ v0 2/8] scan: Register device driver
From: Claudio Takahasi @ 2012-08-22 19:45 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Claudio Takahasi
In-Reply-To: <1345664723-30814-1-git-send-email-claudio.takahasi@openbossa.org>
This patch add the probe and remove callbacks for the GATT Scan
Parameters service.
---
Makefile.am | 4 ++-
profiles/scanparam/main.c | 4 ++-
profiles/scanparam/manager.c | 65 ++++++++++++++++++++++++++++++++++++++++++++
profiles/scanparam/manager.h | 26 ++++++++++++++++++
4 files changed, 97 insertions(+), 2 deletions(-)
create mode 100644 profiles/scanparam/manager.c
create mode 100644 profiles/scanparam/manager.h
diff --git a/Makefile.am b/Makefile.am
index 161586e..0bc97ae 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -242,7 +242,9 @@ builtin_sources += profiles/thermometer/main.c \
profiles/gatt/main.c profiles/gatt/manager.h \
profiles/gatt/manager.c profiles/gatt/gas.h \
profiles/gatt/gas.c \
- profiles/scanparam/main.c
+ profiles/scanparam/main.c \
+ profiles/scanparam/manager.h \
+ profiles/scanparam/manager.c
endif
builtin_modules += formfactor
diff --git a/profiles/scanparam/main.c b/profiles/scanparam/main.c
index 6e90929..ba4b2c0 100644
--- a/profiles/scanparam/main.c
+++ b/profiles/scanparam/main.c
@@ -33,6 +33,7 @@
#include "log.h"
#include "plugin.h"
#include "hcid.h"
+#include "manager.h"
static int scan_param_init(void)
{
@@ -41,11 +42,12 @@ static int scan_param_init(void)
return -ENOTSUP;
}
- return 0;
+ return scan_param_manager_init();
}
static void scan_param_exit(void)
{
+ scan_param_manager_exit();
}
BLUETOOTH_PLUGIN_DEFINE(scanparam, VERSION,
diff --git a/profiles/scanparam/manager.c b/profiles/scanparam/manager.c
new file mode 100644
index 0000000..365320a
--- /dev/null
+++ b/profiles/scanparam/manager.c
@@ -0,0 +1,65 @@
+/*
+ *
+ * BlueZ - Bluetooth protocol stack for Linux
+ *
+ * Copyright (C) 2012 Nordic Semiconductor Inc.
+ * Copyright (C) 2012 Instituto Nokia de Tecnologia - INdT
+ *
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <glib.h>
+
+#include "log.h"
+#include "adapter.h"
+#include "device.h"
+#include "manager.h"
+
+#define SCAN_PARAMETERS_UUID "00001813-0000-1000-8000-00805f9b34fb"
+
+static int scan_param_probe(struct btd_device *device, GSList *uuids)
+{
+ DBG("Probing Scan Parameters");
+
+ return 0;
+}
+
+static void scan_param_remove(struct btd_device *device)
+{
+}
+
+static struct btd_device_driver scan_driver = {
+ .name = "Scan Parameters Client Driver",
+ .uuids = BTD_UUIDS(SCAN_PARAMETERS_UUID),
+ .probe = scan_param_probe,
+ .remove = scan_param_remove,
+};
+
+int scan_param_manager_init(void)
+{
+ return btd_register_device_driver(&scan_driver);
+
+}
+
+void scan_param_manager_exit(void)
+{
+ btd_unregister_device_driver(&scan_driver);
+}
diff --git a/profiles/scanparam/manager.h b/profiles/scanparam/manager.h
new file mode 100644
index 0000000..1cf2e5e
--- /dev/null
+++ b/profiles/scanparam/manager.h
@@ -0,0 +1,26 @@
+/*
+ *
+ * BlueZ - Bluetooth protocol stack for Linux
+ *
+ * Copyright (C) 2012 Nordic Semiconductor Inc.
+ * Copyright (C) 2012 Instituto Nokia de Tecnologia - INdT
+ *
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+int scan_param_manager_init(void);
+void scan_param_manager_exit(void);
--
1.7.12
^ permalink raw reply related
* [PATCH BlueZ v0 3/8] scan: Add ATTIO callbacks registration
From: Claudio Takahasi @ 2012-08-22 19:45 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Claudio Takahasi
In-Reply-To: <1345664723-30814-1-git-send-email-claudio.takahasi@openbossa.org>
This patch add the functions to manage ATTIO callbacks. The current
registration mechanism is not suitable for this service since it needs
to be passive. Scan Parameters should not actively request connections,
it needs to be notified if the connections has been established
requested by other services.
---
Makefile.am | 3 +-
profiles/scanparam/manager.c | 26 ++++++++++-
profiles/scanparam/scan.c | 103 +++++++++++++++++++++++++++++++++++++++++++
profiles/scanparam/scan.h | 26 +++++++++++
4 files changed, 156 insertions(+), 2 deletions(-)
create mode 100644 profiles/scanparam/scan.c
create mode 100644 profiles/scanparam/scan.h
diff --git a/Makefile.am b/Makefile.am
index 0bc97ae..955c78f 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -244,7 +244,8 @@ builtin_sources += profiles/thermometer/main.c \
profiles/gatt/gas.c \
profiles/scanparam/main.c \
profiles/scanparam/manager.h \
- profiles/scanparam/manager.c
+ profiles/scanparam/manager.c \
+ profiles/scanparam/scan.h profiles/scanparam/scan.c
endif
builtin_modules += formfactor
diff --git a/profiles/scanparam/manager.c b/profiles/scanparam/manager.c
index 365320a..2d33f4b 100644
--- a/profiles/scanparam/manager.c
+++ b/profiles/scanparam/manager.c
@@ -26,24 +26,48 @@
#include <config.h>
#endif
+#include <errno.h>
#include <glib.h>
+#include <bluetooth/uuid.h>
#include "log.h"
#include "adapter.h"
#include "device.h"
+#include "att.h"
+#include "gattrib.h"
+#include "gatt.h"
#include "manager.h"
+#include "scan.h"
#define SCAN_PARAMETERS_UUID "00001813-0000-1000-8000-00805f9b34fb"
+static gint primary_uuid_cmp(gconstpointer a, gconstpointer b)
+{
+ const struct gatt_primary *prim = a;
+ const char *uuid = b;
+
+ return g_strcmp0(prim->uuid, uuid);
+}
+
static int scan_param_probe(struct btd_device *device, GSList *uuids)
{
+ GSList *primaries, *l;
+
DBG("Probing Scan Parameters");
- return 0;
+ primaries = btd_device_get_primaries(device);
+
+ l = g_slist_find_custom(primaries, SCAN_PARAMETERS_UUID,
+ primary_uuid_cmp);
+ if (!l)
+ return -EINVAL;
+
+ return scan_register(device, l->data);
}
static void scan_param_remove(struct btd_device *device)
{
+ scan_unregister(device);
}
static struct btd_device_driver scan_driver = {
diff --git a/profiles/scanparam/scan.c b/profiles/scanparam/scan.c
new file mode 100644
index 0000000..5af1e57
--- /dev/null
+++ b/profiles/scanparam/scan.c
@@ -0,0 +1,103 @@
+/*
+ *
+ * BlueZ - Bluetooth protocol stack for Linux
+ *
+ * Copyright (C) 2012 Nordic Semiconductor Inc.
+ * Copyright (C) 2012 Instituto Nokia de Tecnologia - INdT
+ *
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <bluetooth/bluetooth.h>
+#include <bluetooth/uuid.h>
+
+#include "adapter.h"
+#include "device.h"
+#include "att.h"
+#include "gattrib.h"
+#include "gatt.h"
+#include "attio.h"
+#include "scan.h"
+
+struct scan {
+ struct btd_device *device;
+ GAttrib *attrib;
+ guint attioid;
+};
+
+GSList *servers = NULL;
+
+static gint scan_device_cmp(gconstpointer a, gconstpointer b)
+{
+ const struct scan *scan = a;
+ const struct btd_device *device = b;
+
+ return (device == scan->device ? 0 : -1);
+}
+
+static void attio_connected_cb(GAttrib *attrib, gpointer user_data)
+{
+ struct scan *scan = user_data;
+
+ scan->attrib = g_attrib_ref(attrib);
+}
+
+static void attio_disconnected_cb(gpointer user_data)
+{
+ struct scan *scan = user_data;
+
+ g_attrib_unref(scan->attrib);
+ scan->attrib = NULL;
+}
+
+int scan_register(struct btd_device *device, struct gatt_primary *prim)
+{
+ struct scan *scan;
+
+ scan = g_new0(struct scan, 1);
+ scan->device = btd_device_ref(device);
+ scan->attioid = btd_device_add_attio_callback(device,
+ attio_connected_cb,
+ attio_disconnected_cb,
+ scan);
+
+ servers = g_slist_prepend(servers, scan);
+
+ return 0;
+}
+
+void scan_unregister(struct btd_device *device)
+{
+ struct scan *scan;
+ GSList *l;
+
+ l = g_slist_find_custom(servers, device, scan_device_cmp);
+ if (l == NULL)
+ return;
+
+ scan = l->data;
+ servers = g_slist_remove(servers, scan);
+
+ btd_device_remove_attio_callback(scan->device, scan->attioid);
+ btd_device_unref(scan->device);
+ g_attrib_unref(scan->attrib);
+ g_free(scan);
+}
diff --git a/profiles/scanparam/scan.h b/profiles/scanparam/scan.h
new file mode 100644
index 0000000..93f7edd
--- /dev/null
+++ b/profiles/scanparam/scan.h
@@ -0,0 +1,26 @@
+/*
+ *
+ * BlueZ - Bluetooth protocol stack for Linux
+ *
+ * Copyright (C) 2012 Nordic Semiconductor Inc.
+ * Copyright (C) 2012 Instituto Nokia de Tecnologia - INdT
+ *
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+int scan_register(struct btd_device *device, struct gatt_primary *prim);
+void scan_unregister(struct btd_device *device);
--
1.7.12
^ permalink raw reply related
* [PATCH BlueZ v0 4/8] scan: Add write scan interval window
From: Claudio Takahasi @ 2012-08-22 19:45 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Claudio Takahasi
In-Reply-To: <1345664723-30814-1-git-send-email-claudio.takahasi@openbossa.org>
This patch adds the handle discovery of the Scan Interval Window
Characteristic and writes the default value (hard-coded in the kernel)
of the scan interval, and scan window in the remote's characteristic.
---
profiles/scanparam/scan.c | 41 +++++++++++++++++++++++++++++++++++++++++
1 file changed, 41 insertions(+)
diff --git a/profiles/scanparam/scan.c b/profiles/scanparam/scan.c
index 5af1e57..86bdcb7 100644
--- a/profiles/scanparam/scan.c
+++ b/profiles/scanparam/scan.c
@@ -29,6 +29,7 @@
#include <bluetooth/bluetooth.h>
#include <bluetooth/uuid.h>
+#include "log.h"
#include "adapter.h"
#include "device.h"
#include "att.h"
@@ -37,10 +38,18 @@
#include "attio.h"
#include "scan.h"
+#define SCAN_INTERVAL_WIN_UUID 0x2A4F
+
+#define SCAN_INTERVAL 0x0060
+#define SCAN_WINDOW 0x0030
+
struct scan {
struct btd_device *device;
GAttrib *attrib;
+ struct att_range range;
guint attioid;
+ uint16_t interval;
+ uint16_t window;
};
GSList *servers = NULL;
@@ -53,11 +62,42 @@ static gint scan_device_cmp(gconstpointer a, gconstpointer b)
return (device == scan->device ? 0 : -1);
}
+static void iwin_discovered_cb(GSList *chars, guint8 status,
+ gpointer user_data)
+{
+ struct scan *scan = user_data;
+ struct gatt_char *chr;
+ uint8_t value[4];
+
+ if (status) {
+ error("Discover Scan Interval Window: %s",
+ att_ecode2str(status));
+ return;
+ }
+
+ chr = chars->data;
+
+ DBG("Scan Interval Window handle: 0x%04x",
+ chr->value_handle);
+
+ att_put_u16(SCAN_INTERVAL, &value[0]);
+ att_put_u16(SCAN_WINDOW, &value[2]);
+
+ gatt_write_char(scan->attrib, chr->value_handle, value,
+ sizeof(value), NULL, NULL);
+}
+
static void attio_connected_cb(GAttrib *attrib, gpointer user_data)
{
struct scan *scan = user_data;
+ bt_uuid_t iwin_uuid;
+
+ bt_uuid16_create(&iwin_uuid, SCAN_INTERVAL_WIN_UUID);
scan->attrib = g_attrib_ref(attrib);
+
+ gatt_discover_char(scan->attrib, scan->range.start, scan->range.end,
+ &iwin_uuid, iwin_discovered_cb, scan);
}
static void attio_disconnected_cb(gpointer user_data)
@@ -74,6 +114,7 @@ int scan_register(struct btd_device *device, struct gatt_primary *prim)
scan = g_new0(struct scan, 1);
scan->device = btd_device_ref(device);
+ scan->range = prim->range;
scan->attioid = btd_device_add_attio_callback(device,
attio_connected_cb,
attio_disconnected_cb,
--
1.7.12
^ permalink raw reply related
* [PATCH BlueZ v0 5/8] scan: Enable Scan Refresh notification
From: Claudio Takahasi @ 2012-08-22 19:45 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Claudio Takahasi
In-Reply-To: <1345664723-30814-1-git-send-email-claudio.takahasi@openbossa.org>
This patch discovers the Scan Refresh Characteristic handle and sets
it's Client Characteristic Configuration bit to enable notifications.
---
profiles/scanparam/scan.c | 81 ++++++++++++++++++++++++++++++++++++++++++++++-
1 file changed, 80 insertions(+), 1 deletion(-)
diff --git a/profiles/scanparam/scan.c b/profiles/scanparam/scan.c
index 86bdcb7..59ff336 100644
--- a/profiles/scanparam/scan.c
+++ b/profiles/scanparam/scan.c
@@ -39,6 +39,7 @@
#include "scan.h"
#define SCAN_INTERVAL_WIN_UUID 0x2A4F
+#define SCAN_REFRESH_UUID 0x2A31
#define SCAN_INTERVAL 0x0060
#define SCAN_WINDOW 0x0030
@@ -62,6 +63,80 @@ static gint scan_device_cmp(gconstpointer a, gconstpointer b)
return (device == scan->device ? 0 : -1);
}
+static void ccc_written_cb(guint8 status, const guint8 *pdu,
+ guint16 plen, gpointer user_data)
+{
+ if (status != 0) {
+ error("Write Scan Refresh CCC failed: %s",
+ att_ecode2str(status));
+ return;
+ }
+
+ DBG("Scan Refresh: notification enabled");
+}
+
+static void discover_descriptor_cb(guint8 status, const guint8 *pdu,
+ guint16 len, gpointer user_data)
+{
+ struct scan *scan = user_data;
+ struct att_data_list *list;
+ uint8_t *ptr;
+ uint16_t uuid16, handle;
+ uint8_t value[2];
+ uint8_t format;
+
+ list = dec_find_info_resp(pdu, len, &format);
+ if (list == NULL)
+ return;
+
+ if (format != ATT_FIND_INFO_RESP_FMT_16BIT)
+ goto done;
+
+ ptr = list->data[0];
+ handle = att_get_u16(ptr);
+ uuid16 = att_get_u16(&ptr[2]);
+
+ if (uuid16 != GATT_CLIENT_CHARAC_CFG_UUID)
+ goto done;
+
+ att_put_u16(GATT_CLIENT_CHARAC_CFG_NOTIF_BIT, value);
+ gatt_write_char(scan->attrib, handle, value, sizeof(value),
+ ccc_written_cb, NULL);
+done:
+ att_data_list_free(list);
+}
+
+static void refresh_discovered_cb(GSList *chars, guint8 status,
+ gpointer user_data)
+{
+ struct scan *scan = user_data;
+ struct gatt_char *chr;
+ uint16_t start, end;
+
+ if (status) {
+ error("Scan Refresh %s", att_ecode2str(status));
+ return;
+ }
+
+ if (!chars) {
+ DBG("Scan Refresh not supported");
+ return;
+ }
+
+ chr = chars->data;
+
+ DBG("Scan Refresh handle: 0x%04x", chr->value_handle);
+
+ start = chr->value_handle + 1;
+ end = scan->range.end;
+
+ if (start >= end)
+ return;
+
+ gatt_find_info(scan->attrib, start, end,
+ discover_descriptor_cb, user_data);
+}
+
static void iwin_discovered_cb(GSList *chars, guint8 status,
gpointer user_data)
{
@@ -90,14 +165,18 @@ static void iwin_discovered_cb(GSList *chars, guint8 status,
static void attio_connected_cb(GAttrib *attrib, gpointer user_data)
{
struct scan *scan = user_data;
- bt_uuid_t iwin_uuid;
+ bt_uuid_t iwin_uuid, refresh_uuid;
bt_uuid16_create(&iwin_uuid, SCAN_INTERVAL_WIN_UUID);
+ bt_uuid16_create(&refresh_uuid, SCAN_REFRESH_UUID);
scan->attrib = g_attrib_ref(attrib);
gatt_discover_char(scan->attrib, scan->range.start, scan->range.end,
&iwin_uuid, iwin_discovered_cb, scan);
+
+ gatt_discover_char(scan->attrib, scan->range.start, scan->range.end,
+ &refresh_uuid, refresh_discovered_cb, scan);
}
static void attio_disconnected_cb(gpointer user_data)
--
1.7.12
^ permalink raw reply related
* [PATCH BlueZ v0 6/8] scan: Register notification handler
From: Claudio Takahasi @ 2012-08-22 19:45 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Claudio Takahasi
In-Reply-To: <1345664723-30814-1-git-send-email-claudio.takahasi@openbossa.org>
This patch registers the GAttrib notification handler for Refresh
Characteristic notification.
---
profiles/scanparam/scan.c | 36 +++++++++++++++++++++++++++++++++++-
1 file changed, 35 insertions(+), 1 deletion(-)
diff --git a/profiles/scanparam/scan.c b/profiles/scanparam/scan.c
index 59ff336..36e21f3 100644
--- a/profiles/scanparam/scan.c
+++ b/profiles/scanparam/scan.c
@@ -51,6 +51,8 @@ struct scan {
guint attioid;
uint16_t interval;
uint16_t window;
+ uint16_t refresh_handle;
+ uint16_t refresh_cb_id;
};
GSList *servers = NULL;
@@ -63,9 +65,30 @@ static gint scan_device_cmp(gconstpointer a, gconstpointer b)
return (device == scan->device ? 0 : -1);
}
+static void refresh_value_cb(const uint8_t *pdu, uint16_t len,
+ gpointer user_data)
+{
+ struct scan *scan = user_data;
+ uint16_t handle;
+
+ if (len < 4) { /* 1-byte opcode + 2-byte handle + refresh */
+ error("Malformed ATT notification");
+ return;
+ }
+
+ handle = att_get_u16(&pdu[1]);
+
+ if (handle != scan->refresh_handle)
+ return;
+
+ DBG("Server requires refresh: %d", pdu[3]);
+}
+
static void ccc_written_cb(guint8 status, const guint8 *pdu,
guint16 plen, gpointer user_data)
{
+ struct scan *scan = user_data;
+
if (status != 0) {
error("Write Scan Refresh CCC failed: %s",
att_ecode2str(status));
@@ -73,6 +96,10 @@ static void ccc_written_cb(guint8 status, const guint8 *pdu,
}
DBG("Scan Refresh: notification enabled");
+
+ scan->refresh_cb_id = g_attrib_register(scan->attrib,
+ ATT_OP_HANDLE_NOTIFY, refresh_value_cb,
+ user_data, NULL);
}
static void discover_descriptor_cb(guint8 status, const guint8 *pdu,
@@ -101,7 +128,7 @@ static void discover_descriptor_cb(guint8 status, const guint8 *pdu,
att_put_u16(GATT_CLIENT_CHARAC_CFG_NOTIF_BIT, value);
gatt_write_char(scan->attrib, handle, value, sizeof(value),
- ccc_written_cb, NULL);
+ ccc_written_cb, user_data);
done:
att_data_list_free(list);
}
@@ -133,6 +160,8 @@ static void refresh_discovered_cb(GSList *chars, guint8 status,
if (start >= end)
return;
+ scan->refresh_handle = chr->value_handle;
+
gatt_find_info(scan->attrib, start, end,
discover_descriptor_cb, user_data);
}
@@ -216,6 +245,11 @@ void scan_unregister(struct btd_device *device)
scan = l->data;
servers = g_slist_remove(servers, scan);
+ if (scan->refresh_cb_id) {
+ g_attrib_unregister(scan->attrib, scan->refresh_cb_id);
+ scan->refresh_cb_id = 0;
+ }
+
btd_device_remove_attio_callback(scan->device, scan->attioid);
btd_device_unref(scan->device);
g_attrib_unref(scan->attrib);
--
1.7.12
^ permalink raw reply related
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox