* Re: [PATCH 3/3] Bluetooth: Fix disconnecting L2CAP when a credits overflow occurs
From: Marcel Holtmann @ 2014-01-27 23:36 UTC (permalink / raw)
To: Johan Hedberg; +Cc: BlueZ development
In-Reply-To: <1390864295-4259-3-git-send-email-johan.hedberg@gmail.com>
Hi Johan,
> The L2CAP specification requires us to disconnect an L2CAP channel if
> the remote side gives us credits beyond 65535. This patch makes sure we
> disconnect the channel in such a situation.
>
> Signed-off-by: Johan Hedberg <johan.hedberg@intel.com>
> ---
> net/bluetooth/l2cap_core.c | 15 ++++++++++++++-
> 1 file changed, 14 insertions(+), 1 deletion(-)
patch has been applied to bluetooth-next tree.
Regards
Marcel
^ permalink raw reply
* Re: [PATCH 2/3] Bluetooth: Fix disconnecting L2CAP channel for credits violation
From: Marcel Holtmann @ 2014-01-27 23:32 UTC (permalink / raw)
To: Johan Hedberg; +Cc: BlueZ development
In-Reply-To: <1390864295-4259-2-git-send-email-johan.hedberg@gmail.com>
Hi Johan,
> The L2CAP specification requires us to disconnect a channel if the
> remote device sends us data when it doesn't have any credits to do so.
> This patch makes sure that we send the appropriate L2CAP Disconnect
> request in this situation.
>
> Signed-off-by: Johan Hedberg <johan.hedberg@intel.com>
> ---
> net/bluetooth/l2cap_core.c | 1 +
> 1 file changed, 1 insertion(+)
patch has been applied to bluetooth-next tree.
Regards
Marcel
^ permalink raw reply
* Re: [PATCH 1/3] Bluetooth: Fix respecting le_default_mps value
From: Marcel Holtmann @ 2014-01-27 23:30 UTC (permalink / raw)
To: Johan Hedberg; +Cc: BlueZ development
In-Reply-To: <1390864295-4259-1-git-send-email-johan.hedberg@gmail.com>
Hi Johan,
> There's a le_default_mps variable that can be modified through debugfs
> but it was never actually used for determining our MPS value. This patch
> fixes the MPS initialization to use the variable instead of a fixed
> value.
>
> Signed-off-by: Johan Hedberg <johan.hedberg@intel.com>
> ---
> net/bluetooth/l2cap_core.c | 2 +-
> 1 file changed, 1 insertion(+), 1 deletion(-)
patch has been applied to bluetooth-next tree.
Regards
Marcel
^ permalink raw reply
* [PATCH 3/3] Bluetooth: Fix disconnecting L2CAP when a credits overflow occurs
From: johan.hedberg @ 2014-01-27 23:11 UTC (permalink / raw)
To: linux-bluetooth
In-Reply-To: <1390864295-4259-1-git-send-email-johan.hedberg@gmail.com>
From: Johan Hedberg <johan.hedberg@intel.com>
The L2CAP specification requires us to disconnect an L2CAP channel if
the remote side gives us credits beyond 65535. This patch makes sure we
disconnect the channel in such a situation.
Signed-off-by: Johan Hedberg <johan.hedberg@intel.com>
---
net/bluetooth/l2cap_core.c | 15 ++++++++++++++-
1 file changed, 14 insertions(+), 1 deletion(-)
diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c
index fbc9709abccf..d2ef49b54aa2 100644
--- a/net/bluetooth/l2cap_core.c
+++ b/net/bluetooth/l2cap_core.c
@@ -42,6 +42,8 @@
#include "amp.h"
#include "6lowpan.h"
+#define LE_FLOWCTL_MAX_CREDITS 65535
+
bool disable_ertm;
static u32 l2cap_feat_mask = L2CAP_FEAT_FIXED_CHAN | L2CAP_FEAT_UCD;
@@ -5473,7 +5475,7 @@ static inline int l2cap_le_credits(struct l2cap_conn *conn,
{
struct l2cap_le_credits *pkt;
struct l2cap_chan *chan;
- u16 cid, credits;
+ u16 cid, credits, max_credits;
if (cmd_len != sizeof(*pkt))
return -EPROTO;
@@ -5488,6 +5490,17 @@ static inline int l2cap_le_credits(struct l2cap_conn *conn,
if (!chan)
return -EBADSLT;
+ max_credits = LE_FLOWCTL_MAX_CREDITS - chan->tx_credits;
+ if (credits > max_credits) {
+ BT_ERR("LE credits overflow");
+ l2cap_send_disconn_req(chan, ECONNRESET);
+
+ /* Return 0 so that we don't trigger an unnecessary
+ * command reject packet.
+ */
+ return 0;
+ }
+
chan->tx_credits += credits;
while (chan->tx_credits && !skb_queue_empty(&chan->tx_q)) {
--
1.8.5.3
^ permalink raw reply related
* [PATCH 2/3] Bluetooth: Fix disconnecting L2CAP channel for credits violation
From: johan.hedberg @ 2014-01-27 23:11 UTC (permalink / raw)
To: linux-bluetooth
In-Reply-To: <1390864295-4259-1-git-send-email-johan.hedberg@gmail.com>
From: Johan Hedberg <johan.hedberg@intel.com>
The L2CAP specification requires us to disconnect a channel if the
remote device sends us data when it doesn't have any credits to do so.
This patch makes sure that we send the appropriate L2CAP Disconnect
request in this situation.
Signed-off-by: Johan Hedberg <johan.hedberg@intel.com>
---
net/bluetooth/l2cap_core.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c
index 5a30fc72f4ba..fbc9709abccf 100644
--- a/net/bluetooth/l2cap_core.c
+++ b/net/bluetooth/l2cap_core.c
@@ -6635,6 +6635,7 @@ static int l2cap_le_data_rcv(struct l2cap_chan *chan, struct sk_buff *skb)
if (!chan->rx_credits) {
BT_ERR("No credits to receive LE L2CAP data");
+ l2cap_send_disconn_req(chan, ECONNRESET);
return -ENOBUFS;
}
--
1.8.5.3
^ permalink raw reply related
* [PATCH 1/3] Bluetooth: Fix respecting le_default_mps value
From: johan.hedberg @ 2014-01-27 23:11 UTC (permalink / raw)
To: linux-bluetooth
From: Johan Hedberg <johan.hedberg@intel.com>
There's a le_default_mps variable that can be modified through debugfs
but it was never actually used for determining our MPS value. This patch
fixes the MPS initialization to use the variable instead of a fixed
value.
Signed-off-by: Johan Hedberg <johan.hedberg@intel.com>
---
net/bluetooth/l2cap_core.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c
index cc340700573e..5a30fc72f4ba 100644
--- a/net/bluetooth/l2cap_core.c
+++ b/net/bluetooth/l2cap_core.c
@@ -482,7 +482,7 @@ static void l2cap_le_flowctl_init(struct l2cap_chan *chan)
chan->sdu_len = 0;
chan->tx_credits = 0;
chan->rx_credits = le_max_credits;
- chan->mps = min_t(u16, chan->imtu, L2CAP_LE_DEFAULT_MPS);
+ chan->mps = min_t(u16, chan->imtu, le_default_mps);
skb_queue_head_init(&chan->tx_q);
}
--
1.8.5.3
^ permalink raw reply related
* Re: [PATCH BlueZ 4/4] emulator: Fix crash if socket(AF_ALG) is not supported by the kernel
From: Szymon Janc @ 2014-01-27 20:52 UTC (permalink / raw)
To: Anderson Lizardo; +Cc: BlueZ development
In-Reply-To: <CAJdJm_MHvakZpy_j_X3ACOS9EegKyO8WKL45w5u4t_h2LOBXww@mail.gmail.com>
Hi,
On Monday 27 of January 2014 16:03:59 Anderson Lizardo wrote:
> Hi Johan,
>
> On Mon, Jan 27, 2014 at 1:59 PM, Johan Hedberg <johan.hedberg@gmail.com>
wrote:
> > This patch has been applied. Thanks.
>
> Any comments on the other patches that touch android/* files?
Applied as well, thanks.
--
BR
Szymon Janc
^ permalink raw reply
* Re: [RFC BlueZ] android/AVDTP: Make signalling channel high priority
From: Luiz Augusto von Dentz @ 2014-01-27 20:44 UTC (permalink / raw)
To: Marcel Holtmann; +Cc: BlueZ development
In-Reply-To: <7AF5DE79-4CEA-453C-895C-EF03DE9205B8@holtmann.org>
Hi Marcel,
On Mon, Jan 27, 2014 at 12:40 PM, Marcel Holtmann <marcel@holtmann.org> wrote:
> Hi Luiz,
>
>> This makes signalling high priority (6) so it can push commands before
>> the stream channel, without this the stream channel may be schedule
>> first and cause the signalling commands to timeout while waiting a slot.
>> ---
>> android/avdtp.c | 9 +++++++++
>> 1 file changed, 9 insertions(+)
>>
>> diff --git a/android/avdtp.c b/android/avdtp.c
>> index 4abcd75..4cfffc8 100644
>> --- a/android/avdtp.c
>> +++ b/android/avdtp.c
>> @@ -2057,6 +2057,7 @@ struct avdtp *avdtp_new(int fd, size_t imtu, size_t omtu, uint16_t version)
>> struct avdtp *session;
>> GIOCondition cond = G_IO_IN | G_IO_ERR | G_IO_HUP | G_IO_NVAL;
>> int new_fd;
>> + int priority;
>>
>> new_fd = dup(fd);
>> if (new_fd < 0) {
>> @@ -2064,6 +2065,14 @@ struct avdtp *avdtp_new(int fd, size_t imtu, size_t omtu, uint16_t version)
>> return NULL;
>> }
>>
>> + priority = 6;
>> + if (setsockopt(new_fd, SOL_SOCKET, SO_PRIORITY,
>> + (const void *) &priority, sizeof(priority)) < 0) {
>> + error("setsockopt(SO_PRIORITY): %s (%d)", strerror(errno),
>> + errno);
>> + return NULL;
>> + }
>> +
>
> I think we should make it one higher than the media channel. If we are currently using priority 6 on the media channel than this should be 7. If 7 is not possible, then we might degrade the media channel to 5.
Setting anything bigger than 6 requires CAP_NET_ADMIN so it would
requires unit tests to run with it, perhaps we can do some logic that
checks if we can over 6 or not depending on what capabilities we have.
--
Luiz Augusto von Dentz
^ permalink raw reply
* Re: [RFC BlueZ] android/AVDTP: Make signalling channel high priority
From: Marcel Holtmann @ 2014-01-27 20:40 UTC (permalink / raw)
To: Luiz Augusto von Dentz; +Cc: BlueZ development
In-Reply-To: <1390854261-5325-1-git-send-email-luiz.dentz@gmail.com>
Hi Luiz,
> This makes signalling high priority (6) so it can push commands before
> the stream channel, without this the stream channel may be schedule
> first and cause the signalling commands to timeout while waiting a slot.
> ---
> android/avdtp.c | 9 +++++++++
> 1 file changed, 9 insertions(+)
>
> diff --git a/android/avdtp.c b/android/avdtp.c
> index 4abcd75..4cfffc8 100644
> --- a/android/avdtp.c
> +++ b/android/avdtp.c
> @@ -2057,6 +2057,7 @@ struct avdtp *avdtp_new(int fd, size_t imtu, size_t omtu, uint16_t version)
> struct avdtp *session;
> GIOCondition cond = G_IO_IN | G_IO_ERR | G_IO_HUP | G_IO_NVAL;
> int new_fd;
> + int priority;
>
> new_fd = dup(fd);
> if (new_fd < 0) {
> @@ -2064,6 +2065,14 @@ struct avdtp *avdtp_new(int fd, size_t imtu, size_t omtu, uint16_t version)
> return NULL;
> }
>
> + priority = 6;
> + if (setsockopt(new_fd, SOL_SOCKET, SO_PRIORITY,
> + (const void *) &priority, sizeof(priority)) < 0) {
> + error("setsockopt(SO_PRIORITY): %s (%d)", strerror(errno),
> + errno);
> + return NULL;
> + }
> +
I think we should make it one higher than the media channel. If we are currently using priority 6 on the media channel than this should be 7. If 7 is not possible, then we might degrade the media channel to 5.
Regards
Marcel
^ permalink raw reply
* [PATCH BlueZ v5 18/18] bluetooth.conf: Add ObjectManager interface
From: Claudio Takahasi @ 2014-01-27 20:35 UTC (permalink / raw)
To: linux-bluetooth; +Cc: claudio.takahasi
In-Reply-To: <1390854924-31904-1-git-send-email-claudio.takahasi@openbossa.org>
---
src/bluetooth.conf | 1 +
1 file changed, 1 insertion(+)
diff --git a/src/bluetooth.conf b/src/bluetooth.conf
index 0495200..ad8891a 100644
--- a/src/bluetooth.conf
+++ b/src/bluetooth.conf
@@ -18,6 +18,7 @@
<allow send_interface="org.bluez.Profile1"/>
<allow send_interface="org.bluez.HeartRateWatcher1"/>
<allow send_interface="org.bluez.CyclingSpeedWatcher1"/>
+ <allow send_interface="org.freedesktop.DBus.ObjectManager"/>
</policy>
<policy at_console="true">
--
1.8.3.1
^ permalink raw reply related
* [PATCH BlueZ v5 17/18] gatttool: Add unix socket support for interactive mode
From: Claudio Takahasi @ 2014-01-27 20:35 UTC (permalink / raw)
To: linux-bluetooth; +Cc: claudio.takahasi
In-Reply-To: <1390854924-31904-1-git-send-email-claudio.takahasi@openbossa.org>
This patch allows running GATT operations over unix socket on
interactive mode.
---
attrib/interactive.c | 19 +++++++++++--------
1 file changed, 11 insertions(+), 8 deletions(-)
diff --git a/attrib/interactive.c b/attrib/interactive.c
index 70c091c..67e060e 100644
--- a/attrib/interactive.c
+++ b/attrib/interactive.c
@@ -84,7 +84,7 @@ static char *get_prompt(void)
if (opt_dst)
g_string_append_printf(prompt, "[%17s]", opt_dst);
else
- g_string_append_printf(prompt, "[%17s]", "");
+ g_string_append_printf(prompt, "[LOCAL]");
if (conn_state == STATE_CONNECTED)
g_string_append(prompt, COLOR_OFF);
@@ -405,15 +405,18 @@ static void cmd_connect(int argcp, char **argvp)
opt_dst_type = g_strdup("public");
}
- if (opt_dst == NULL) {
- error("Remote Bluetooth address required\n");
- return;
+ if (opt_dst) {
+
+ rl_printf("Attempting to connect to %s\n", opt_dst);
+ set_state(STATE_CONNECTING);
+ iochannel = gatt_connect(opt_src, opt_dst, opt_dst_type,
+ opt_sec_level, opt_psm, opt_mtu,
+ connect_cb, &gerr);
+ } else {
+ rl_printf("Local connection\n");
+ iochannel = unix_connect(connect_cb, &gerr);
}
- rl_printf("Attempting to connect to %s\n", opt_dst);
- set_state(STATE_CONNECTING);
- iochannel = gatt_connect(opt_src, opt_dst, opt_dst_type, opt_sec_level,
- opt_psm, opt_mtu, connect_cb, &gerr);
if (iochannel == NULL) {
set_state(STATE_DISCONNECTED);
error("%s\n", gerr->message);
--
1.8.3.1
^ permalink raw reply related
* [PATCH BlueZ v5 16/18] gatttool: Add unix socket connect
From: Claudio Takahasi @ 2014-01-27 20:35 UTC (permalink / raw)
To: linux-bluetooth; +Cc: claudio.takahasi
In-Reply-To: <1390854924-31904-1-git-send-email-claudio.takahasi@openbossa.org>
This patch adds the initial support for GATT procedures over unix
socket transport on command line mode (one-shot command). Temporary
solution to allow local GATT procedures testing.
---
attrib/gatttool.c | 27 ++++++++++++++++++++-------
attrib/gatttool.h | 1 +
attrib/utils.c | 54 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
3 files changed, 75 insertions(+), 7 deletions(-)
diff --git a/attrib/gatttool.c b/attrib/gatttool.c
index 9f2ead9..cf106de 100644
--- a/attrib/gatttool.c
+++ b/attrib/gatttool.c
@@ -29,7 +29,6 @@
#include <errno.h>
#include <glib.h>
#include <stdlib.h>
-#include <unistd.h>
#include <bluetooth/bluetooth.h>
#include <bluetooth/hci.h>
@@ -53,6 +52,7 @@ static int opt_end = 0xffff;
static int opt_handle = -1;
static int opt_mtu = 0;
static int opt_psm = 0;
+static gboolean opt_local = FALSE;
static gboolean opt_primary = FALSE;
static gboolean opt_characteristics = FALSE;
static gboolean opt_char_read = FALSE;
@@ -511,6 +511,8 @@ static GOptionEntry options[] = {
"Specify local adapter interface", "hciX" },
{ "device", 'b', 0, G_OPTION_ARG_STRING, &opt_dst,
"Specify remote Bluetooth address", "MAC" },
+ { "local", 'L', 0, G_OPTION_ARG_NONE, &opt_local,
+ "Use unix socket transport (local communication)", NULL },
{ "addr-type", 't', 0, G_OPTION_ARG_STRING, &opt_dst_type,
"Set LE address type. Default: public", "[public | random]"},
{ "mtu", 'm', 0, G_OPTION_ARG_INT, &opt_mtu,
@@ -563,6 +565,11 @@ int main(int argc, char *argv[])
g_clear_error(&gerr);
}
+ if (opt_local) {
+ opt_src = NULL;
+ opt_dst = NULL;
+ }
+
if (opt_interactive) {
interactive(opt_src, opt_dst, opt_dst_type, opt_psm);
goto done;
@@ -588,14 +595,20 @@ int main(int argc, char *argv[])
goto done;
}
- if (opt_dst == NULL) {
- g_print("Remote Bluetooth address required\n");
- got_error = TRUE;
- goto done;
+ if (opt_local)
+ chan = unix_connect(connect_cb, &gerr);
+ else {
+ if (opt_dst == NULL) {
+ g_print("Remote Bluetooth address required\n");
+ got_error = TRUE;
+ goto done;
+ }
+
+ chan = gatt_connect(opt_src, opt_dst, opt_dst_type,
+ opt_sec_level, opt_psm, opt_mtu,
+ connect_cb, &gerr);
}
- chan = gatt_connect(opt_src, opt_dst, opt_dst_type, opt_sec_level,
- opt_psm, opt_mtu, connect_cb, &gerr);
if (chan == NULL) {
g_printerr("%s\n", gerr->message);
g_clear_error(&gerr);
diff --git a/attrib/gatttool.h b/attrib/gatttool.h
index 8f0913c..be8e236 100644
--- a/attrib/gatttool.h
+++ b/attrib/gatttool.h
@@ -27,4 +27,5 @@ GIOChannel *gatt_connect(const char *src, const char *dst,
const char *dst_type, const char *sec_level,
int psm, int mtu, BtIOConnect connect_cb,
GError **gerr);
+GIOChannel *unix_connect(BtIOConnect connect_cb, GError **gerr);
size_t gatt_attr_data_from_string(const char *str, uint8_t **data);
diff --git a/attrib/utils.c b/attrib/utils.c
index 17f02be..7d2966f 100644
--- a/attrib/utils.c
+++ b/attrib/utils.c
@@ -25,7 +25,12 @@
#include "config.h"
#endif
+#include <errno.h>
#include <stdlib.h>
+#include <unistd.h>
+#include <sys/socket.h>
+#include <sys/un.h>
+
#include <glib.h>
#include <bluetooth/bluetooth.h>
@@ -101,6 +106,55 @@ GIOChannel *gatt_connect(const char *src, const char *dst,
return chan;
}
+static gboolean unix_connect_cb(GIOChannel *io, GIOCondition cond,
+ gpointer user_data)
+{
+ BtIOConnect connect_cb = user_data;
+ GError *gerr;
+
+ if (cond & (G_IO_HUP | G_IO_ERR | G_IO_NVAL)) {
+ gerr = g_error_new_literal(G_IO_CHANNEL_ERROR,
+ G_IO_CHANNEL_ERROR_FAILED,
+ "connection attempt failed");
+ connect_cb(io, gerr, user_data);
+ g_clear_error(&gerr);
+ } else {
+ connect_cb(io, NULL, user_data);
+ }
+
+ return FALSE;
+}
+
+GIOChannel *unix_connect(BtIOConnect connect_cb, GError **gerr)
+{
+ GIOChannel *io;
+ struct sockaddr_un uaddr = {
+ .sun_family = AF_UNIX,
+ .sun_path = "\0/bluetooth/unix_att",
+ };
+ int sk;
+
+ sk = socket(AF_UNIX, SOCK_SEQPACKET | SOCK_CLOEXEC , 0);
+ if (sk < 0) {
+ g_set_error_literal(gerr, G_IO_CHANNEL_ERROR,
+ G_IO_CHANNEL_ERROR_FAILED, strerror(errno));
+ return NULL;
+ }
+
+ if (connect(sk, (struct sockaddr *) &uaddr, sizeof(uaddr)) < 0) {
+ g_set_error_literal(gerr, G_IO_CHANNEL_ERROR,
+ G_IO_CHANNEL_ERROR_FAILED, strerror(errno));
+ close(sk);
+ return NULL;
+ }
+
+ io = g_io_channel_unix_new(sk);
+ g_io_add_watch(io, G_IO_OUT | G_IO_ERR | G_IO_HUP | G_IO_NVAL,
+ unix_connect_cb, connect_cb);
+
+ return io;
+}
+
size_t gatt_attr_data_from_string(const char *str, uint8_t **data)
{
char tmp[3];
--
1.8.3.1
^ permalink raw reply related
* [PATCH BlueZ v5 15/18] test: Add registering external service
From: Claudio Takahasi @ 2014-01-27 20:35 UTC (permalink / raw)
To: linux-bluetooth; +Cc: claudio.takahasi
In-Reply-To: <1390854924-31904-1-git-send-email-claudio.takahasi@openbossa.org>
This patch extends gatt-service to call RegisterService() when org.bluez
service gets connected to the system bus.
---
test/gatt-service.c | 67 +++++++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 67 insertions(+)
diff --git a/test/gatt-service.c b/test/gatt-service.c
index 4059336..b656ef3 100644
--- a/test/gatt-service.c
+++ b/test/gatt-service.c
@@ -35,6 +35,7 @@
#include <dbus/dbus.h>
#include <gdbus/gdbus.h>
+#define GATT_MGR_IFACE "org.bluez.GattManager1"
#define SERVICE_IFACE "org.bluez.GattService1"
/* Immediate Alert Service UUID */
@@ -100,6 +101,65 @@ static void create_services(DBusConnection *conn)
printf("Registered service: %s\n", service_path);
}
+static void register_external_service_reply(DBusPendingCall *call,
+ void *user_data)
+{
+ DBusMessage *reply = dbus_pending_call_steal_reply(call);
+ DBusError derr;
+
+ dbus_error_init(&derr);
+ dbus_set_error_from_message(&derr, reply);
+
+ if (dbus_error_is_set(&derr))
+ printf("RegisterService: %s\n", derr.message);
+ else
+ printf("RegisterService: OK\n");
+
+ dbus_message_unref(reply);
+ dbus_error_free(&derr);
+}
+
+static void register_external_service(gpointer a, gpointer b)
+{
+ DBusConnection *conn = b;
+ const char *path = a;
+ DBusMessage *msg;
+ DBusPendingCall *call;
+ DBusMessageIter iter, dict;
+
+ msg = dbus_message_new_method_call("org.bluez", "/org/bluez",
+ GATT_MGR_IFACE, "RegisterService");
+ if (msg == NULL) {
+ printf("Couldn't allocate D-Bus message\n");
+ return;
+ }
+
+ dbus_message_iter_init_append(msg, &iter);
+
+ dbus_message_iter_append_basic(&iter, DBUS_TYPE_OBJECT_PATH, &path);
+
+ dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, "{sv}", &dict);
+
+ /* TODO: Add options dictionary */
+
+ dbus_message_iter_close_container(&iter, &dict);
+
+ if (g_dbus_send_message_with_reply(conn, msg, &call, -1) == FALSE) {
+ dbus_message_unref(msg);
+ return;
+ }
+
+ dbus_pending_call_set_notify(call, register_external_service_reply,
+ NULL, NULL);
+
+ dbus_pending_call_unref(call);
+}
+
+static void connect_handler(DBusConnection *conn, void *user_data)
+{
+ g_slist_foreach(services, register_external_service, conn);
+}
+
static gboolean signal_handler(GIOChannel *channel, GIOCondition cond,
gpointer user_data)
{
@@ -171,6 +231,7 @@ static guint setup_signalfd(void)
int main(int argc, char *argv[])
{
+ GDBusClient *client;
DBusConnection *dbus_conn;
guint signal;
@@ -189,8 +250,14 @@ int main(int argc, char *argv[])
create_services(dbus_conn);
+ client = g_dbus_client_new(dbus_conn, "org.bluez", "/org/bluez");
+
+ g_dbus_client_set_connect_watch(client, connect_handler, NULL);
+
g_main_loop_run(main_loop);
+ g_dbus_client_unref(client);
+
g_source_remove(signal);
g_slist_free_full(services, g_free);
--
1.8.3.1
^ permalink raw reply related
* [PATCH BlueZ v5 14/18] test: Add signal handling for gatt-service
From: Claudio Takahasi @ 2014-01-27 20:35 UTC (permalink / raw)
To: linux-bluetooth; +Cc: claudio.takahasi
In-Reply-To: <1390854924-31904-1-git-send-email-claudio.takahasi@openbossa.org>
This patch implements signal handling to run cleanup tasks before
exiting.
---
test/gatt-service.c | 79 +++++++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 79 insertions(+)
diff --git a/test/gatt-service.c b/test/gatt-service.c
index 769fd37..4059336 100644
--- a/test/gatt-service.c
+++ b/test/gatt-service.c
@@ -27,6 +27,9 @@
#include <errno.h>
#include <stdio.h>
+#include <stdbool.h>
+#include <unistd.h>
+#include <sys/signalfd.h>
#include <glib.h>
#include <dbus/dbus.h>
@@ -97,9 +100,83 @@ static void create_services(DBusConnection *conn)
printf("Registered service: %s\n", service_path);
}
+static gboolean signal_handler(GIOChannel *channel, GIOCondition cond,
+ gpointer user_data)
+{
+ static bool __terminated = false;
+ struct signalfd_siginfo si;
+ ssize_t result;
+ int fd;
+
+ if (cond & (G_IO_NVAL | G_IO_ERR | G_IO_HUP))
+ return FALSE;
+
+ fd = g_io_channel_unix_get_fd(channel);
+
+ result = read(fd, &si, sizeof(si));
+ if (result != sizeof(si))
+ return FALSE;
+
+ switch (si.ssi_signo) {
+ case SIGINT:
+ case SIGTERM:
+ if (!__terminated) {
+ printf("Terminating\n");
+ g_main_loop_quit(main_loop);
+ }
+
+ __terminated = true;
+ break;
+ }
+
+ return TRUE;
+}
+
+static guint setup_signalfd(void)
+{
+ GIOChannel *channel;
+ guint source;
+ sigset_t mask;
+ int fd;
+
+ sigemptyset(&mask);
+ sigaddset(&mask, SIGINT);
+ sigaddset(&mask, SIGTERM);
+
+ if (sigprocmask(SIG_BLOCK, &mask, NULL) < 0) {
+ perror("Failed to set signal mask");
+ return 0;
+ }
+
+ fd = signalfd(-1, &mask, 0);
+ if (fd < 0) {
+ perror("Failed to create signal descriptor");
+ return 0;
+ }
+
+ channel = g_io_channel_unix_new(fd);
+
+ g_io_channel_set_close_on_unref(channel, TRUE);
+ g_io_channel_set_encoding(channel, NULL, NULL);
+ g_io_channel_set_buffered(channel, FALSE);
+
+ source = g_io_add_watch(channel,
+ G_IO_IN | G_IO_HUP | G_IO_ERR | G_IO_NVAL,
+ signal_handler, NULL);
+
+ g_io_channel_unref(channel);
+
+ return source;
+}
+
int main(int argc, char *argv[])
{
DBusConnection *dbus_conn;
+ guint signal;
+
+ signal = setup_signalfd();
+ if (signal == 0)
+ return -errno;
dbus_conn = g_dbus_setup_bus(DBUS_BUS_SYSTEM, NULL, NULL);
@@ -114,6 +191,8 @@ int main(int argc, char *argv[])
g_main_loop_run(main_loop);
+ g_source_remove(signal);
+
g_slist_free_full(services, g_free);
dbus_connection_unref(dbus_conn);
--
1.8.3.1
^ permalink raw reply related
* [PATCH BlueZ v5 13/18] gitignore: Add test/gatt-service
From: Claudio Takahasi @ 2014-01-27 20:35 UTC (permalink / raw)
To: linux-bluetooth; +Cc: claudio.takahasi
In-Reply-To: <1390854924-31904-1-git-send-email-claudio.takahasi@openbossa.org>
---
.gitignore | 1 +
1 file changed, 1 insertion(+)
diff --git a/.gitignore b/.gitignore
index e2b23fc..5e5880f 100644
--- a/.gitignore
+++ b/.gitignore
@@ -75,6 +75,7 @@ test/sap_client.pyc
test/bluezutils.pyc
unit/test-ringbuf
unit/test-queue
+test/gatt-service
unit/test-eir
unit/test-uuid
unit/test-crc
--
1.8.3.1
^ permalink raw reply related
* [PATCH BlueZ v5 12/18] test: Add external service GATT skeleton
From: Claudio Takahasi @ 2014-01-27 20:35 UTC (permalink / raw)
To: linux-bluetooth; +Cc: claudio.takahasi
In-Reply-To: <1390854924-31904-1-git-send-email-claudio.takahasi@openbossa.org>
This patch adds the initial code for an external GATT service example.
It implements the API defined at doc/gatt-api.txt
---
Makefile.tools | 5 +++
test/gatt-service.c | 121 ++++++++++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 126 insertions(+)
create mode 100644 test/gatt-service.c
diff --git a/Makefile.tools b/Makefile.tools
index 9199222..a468272 100644
--- a/Makefile.tools
+++ b/Makefile.tools
@@ -374,3 +374,8 @@ test_scripts += test/sap_client.py test/bluezutils.py \
test/test-heartrate test/test-alert test/test-hfp \
test/test-cyclingspeed test/opp-client test/ftp-client \
test/pbap-client test/map-client
+
+noinst_PROGRAMS += test/gatt-service
+
+test_gatt_service_SOURCES = test/gatt-service.c
+test_gatt_service_LDADD = @GLIB_LIBS@ @DBUS_LIBS@ gdbus/libgdbus-internal.la
diff --git a/test/gatt-service.c b/test/gatt-service.c
new file mode 100644
index 0000000..769fd37
--- /dev/null
+++ b/test/gatt-service.c
@@ -0,0 +1,121 @@
+/*
+ *
+ * BlueZ - Bluetooth protocol stack for Linux
+ *
+ * Copyright (C) 2013 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 <stdio.h>
+
+#include <glib.h>
+#include <dbus/dbus.h>
+#include <gdbus/gdbus.h>
+
+#define SERVICE_IFACE "org.bluez.GattService1"
+
+/* Immediate Alert Service UUID */
+#define IAS_UUID "00001802-0000-1000-8000-00805f9b34fb"
+
+static GMainLoop *main_loop;
+static GSList *services;
+
+static gboolean service_get_uuid(const GDBusPropertyTable *property,
+ DBusMessageIter *iter, void *user_data)
+{
+ const char *uuid = user_data;
+
+ dbus_message_iter_append_basic(iter, DBUS_TYPE_STRING, &uuid);
+
+ return TRUE;
+}
+
+static gboolean service_get_includes(const GDBusPropertyTable *property,
+ DBusMessageIter *iter, void *user_data)
+{
+ return TRUE;
+}
+
+static gboolean service_exist_includes(const GDBusPropertyTable *property,
+ void *user_data)
+{
+ return FALSE;
+}
+
+static const GDBusPropertyTable service_properties[] = {
+ { "UUID", "s", service_get_uuid },
+ { "Includes", "ao", service_get_includes, NULL,
+ service_exist_includes },
+ { }
+};
+
+static char *register_service(DBusConnection *conn, const char *uuid)
+{
+ static int id = 1;
+ char *path;
+
+ path = g_strdup_printf("/service%d", id++);
+ if (g_dbus_register_interface(conn, path, SERVICE_IFACE,
+ NULL, NULL, service_properties,
+ g_strdup(uuid), g_free) == FALSE) {
+ printf("Couldn't register service interface\n");
+ g_free(path);
+ return NULL;
+ }
+
+ return path;
+}
+
+static void create_services(DBusConnection *conn)
+{
+ char *service_path;
+
+ service_path = register_service(conn, IAS_UUID);
+
+ services = g_slist_prepend(services, service_path);
+
+ printf("Registered service: %s\n", service_path);
+}
+
+int main(int argc, char *argv[])
+{
+ DBusConnection *dbus_conn;
+
+ dbus_conn = g_dbus_setup_bus(DBUS_BUS_SYSTEM, NULL, NULL);
+
+ main_loop = g_main_loop_new(NULL, FALSE);
+
+ g_dbus_attach_object_manager(dbus_conn);
+
+ printf("gatt-service unique name: %s\n",
+ dbus_bus_get_unique_name(dbus_conn));
+
+ create_services(dbus_conn);
+
+ g_main_loop_run(main_loop);
+
+ g_slist_free_full(services, g_free);
+ dbus_connection_unref(dbus_conn);
+
+ return 0;
+}
--
1.8.3.1
^ permalink raw reply related
* [PATCH BlueZ v5 11/18] gatt: Add Discover All Primary Services
From: Claudio Takahasi @ 2014-01-27 20:35 UTC (permalink / raw)
To: linux-bluetooth; +Cc: claudio.takahasi, Alvaro Silva
In-Reply-To: <1390854924-31904-1-git-send-email-claudio.takahasi@openbossa.org>
From: Alvaro Silva <alvaro.silva@openbossa.org>
This patch adds ATT Read By Group request handling to the attribute
server. It is the primitive to implement Discover All Primary Services
procedure.
---
src/gatt.c | 129 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-
1 file changed, 128 insertions(+), 1 deletion(-)
diff --git a/src/gatt.c b/src/gatt.c
index f5c1df7..dce5c02 100644
--- a/src/gatt.c
+++ b/src/gatt.c
@@ -107,6 +107,130 @@ static int send_error(int sk, uint8_t opcode, uint16_t handle, uint8_t ecode)
return write(sk, pdu, plen);
}
+static void read_by_group_resp(int sk, uint16_t start,
+ uint16_t end, bt_uuid_t *pattern)
+{
+ uint8_t opdu[ATT_DEFAULT_LE_MTU];
+ GList *list;
+ struct btd_attribute *last = NULL;
+ uint8_t *group_start, *group_end = NULL, *group_uuid;
+ unsigned int uuid_type = BT_UUID_UNSPEC;
+ size_t group_len = 0, plen = 0;
+
+ /*
+ * Read By Group Type Response format:
+ * Attribute Opcode: 1 byte
+ * Length: 1 byte (size of each group)
+ * Group: start | end | <<UUID>>
+ */
+
+ opdu[0] = ATT_OP_READ_BY_GROUP_RESP;
+ group_start = &opdu[2];
+ group_uuid = &opdu[6];
+
+ for (list = local_attribute_db; list;
+ last = list->data, list = g_list_next(list)) {
+ struct btd_attribute *attr = list->data;
+
+ if (attr->handle < start)
+ continue;
+
+ if (attr->handle > end)
+ break;
+
+ if (bt_uuid_cmp(&attr->type, pattern) != 0)
+ continue;
+
+ if (uuid_type != BT_UUID_UNSPEC &&
+ uuid_type != attr->type.type) {
+ /*
+ * Groups should contain the same length: UUID16 and
+ * UUID128 should be sent on different ATT PDUs
+ */
+ break;
+ }
+
+ /*
+ * MTU checking should not be shifted up, otherwise the
+ * handle of last end group will not be set properly.
+ */
+ if ((plen + group_len) >= ATT_DEFAULT_LE_MTU)
+ break;
+
+ /* Start Grouping handle */
+ att_put_u16(attr->handle, group_start);
+
+ /* Grouping <<UUID>>: Value is little endian */
+ memcpy(group_uuid, attr->value, attr->value_len);
+
+ if (last && group_end) {
+ att_put_u16(last->handle, group_end);
+ group_end += group_len;
+ plen += group_len;
+ }
+
+ /* Grouping initial settings: First grouping */
+ if (uuid_type == BT_UUID_UNSPEC) {
+ uuid_type = attr->type.type;
+
+ /* start(0xXXXX) | end(0xXXXX) | <<UUID>> */
+ group_len = 2 + 2 + bt_uuid_len(&attr->type);
+
+ /* 2: ATT Opcode and Length */
+ plen = 2 + group_len;
+
+ /* Size of each Attribute Data */
+ opdu[1] = group_len;
+
+ group_end = &opdu[4];
+ }
+
+ group_start += group_len;
+ group_uuid += group_len;
+ }
+
+ if (plen == 0) {
+ send_error(sk, ATT_OP_READ_BY_GROUP_REQ, start,
+ ATT_ECODE_ATTR_NOT_FOUND);
+ return;
+ }
+
+ if (group_end)
+ att_put_u16(last->handle, group_end);
+
+ write(sk, opdu, plen);
+}
+
+static void read_by_group(int sk, const uint8_t *ipdu, ssize_t ilen)
+{
+ uint16_t decoded, start, end;
+ bt_uuid_t pattern;
+
+ decoded = dec_read_by_grp_req(ipdu, ilen, &start, &end, &pattern);
+ if (decoded == 0) {
+ send_error(sk, ipdu[0], 0x0000, ATT_ECODE_INVALID_PDU);
+ return;
+ }
+
+ if (start > end || start == 0x0000) {
+ send_error(sk, ipdu[0], start, ATT_ECODE_INVALID_HANDLE);
+ return;
+ }
+
+ /*
+ * Restricting Read By Group Type to <<Primary>>.
+ * Removing the checking below requires changes to support
+ * dynamic values(defined in the upper layer) and additional
+ * security verification.
+ */
+ if (bt_uuid_cmp(&pattern, &primary_uuid) != 0) {
+ send_error(sk, ipdu[0], start, ATT_ECODE_UNSUPP_GRP_TYPE);
+ return;
+ }
+
+ read_by_group_resp(sk, start, end, &pattern);
+}
+
static bool channel_handler_cb(struct io *io, void *user_data)
{
uint8_t ipdu[ATT_DEFAULT_LE_MTU];
@@ -136,11 +260,14 @@ static bool channel_handler_cb(struct io *io, void *user_data)
case ATT_OP_READ_MULTI_REQ:
case ATT_OP_PREP_WRITE_REQ:
case ATT_OP_EXEC_WRITE_REQ:
- case ATT_OP_READ_BY_GROUP_REQ:
case ATT_OP_SIGNED_WRITE_CMD:
send_error(sk, ipdu[0], 0x0000, ATT_ECODE_REQ_NOT_SUPP);
break;
+ case ATT_OP_READ_BY_GROUP_REQ:
+ read_by_group(sk, ipdu, ilen);
+ break;
+
/* Responses */
case ATT_OP_MTU_RESP:
case ATT_OP_FIND_INFO_RESP:
--
1.8.3.1
^ permalink raw reply related
* [PATCH BlueZ v5 10/18] gatt: Register ATT command/event handler
From: Claudio Takahasi @ 2014-01-27 20:35 UTC (permalink / raw)
To: linux-bluetooth; +Cc: claudio.takahasi, Alvaro Silva
In-Reply-To: <1390854924-31904-1-git-send-email-claudio.takahasi@openbossa.org>
From: Alvaro Silva <alvaro.silva@openbossa.org>
This patch registers the ATT channel handler to manage incoming ATT
commands and events.
---
src/gatt.c | 84 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++--
1 file changed, 82 insertions(+), 2 deletions(-)
diff --git a/src/gatt.c b/src/gatt.c
index 7a595c6..f5c1df7 100644
--- a/src/gatt.c
+++ b/src/gatt.c
@@ -98,10 +98,85 @@ struct btd_attribute *btd_gatt_add_service(const bt_uuid_t *uuid)
return attr;
}
+static int send_error(int sk, uint8_t opcode, uint16_t handle, uint8_t ecode)
+{
+ uint8_t pdu[ATT_DEFAULT_LE_MTU];
+ size_t plen;
+
+ plen = enc_error_resp(opcode, handle, ecode, pdu, sizeof(pdu));
+ return write(sk, pdu, plen);
+}
+
+static bool channel_handler_cb(struct io *io, void *user_data)
+{
+ uint8_t ipdu[ATT_DEFAULT_LE_MTU];
+ ssize_t ilen;
+ int sk = io_get_fd(io);
+
+ ilen = read(sk, ipdu, sizeof(ipdu));
+ if (ilen < 0) {
+ int err = errno;
+ DBG("ATT channel read: %s(%d)", strerror(err), err);
+ return false;
+ }
+
+ switch (ipdu[0]) {
+ case ATT_OP_ERROR:
+ break;
+
+ /* Requests */
+ case ATT_OP_WRITE_CMD:
+ case ATT_OP_WRITE_REQ:
+ case ATT_OP_READ_REQ:
+ case ATT_OP_READ_BY_TYPE_REQ:
+ case ATT_OP_MTU_REQ:
+ case ATT_OP_FIND_INFO_REQ:
+ case ATT_OP_FIND_BY_TYPE_REQ:
+ case ATT_OP_READ_BLOB_REQ:
+ case ATT_OP_READ_MULTI_REQ:
+ case ATT_OP_PREP_WRITE_REQ:
+ case ATT_OP_EXEC_WRITE_REQ:
+ case ATT_OP_READ_BY_GROUP_REQ:
+ case ATT_OP_SIGNED_WRITE_CMD:
+ send_error(sk, ipdu[0], 0x0000, ATT_ECODE_REQ_NOT_SUPP);
+ break;
+
+ /* Responses */
+ case ATT_OP_MTU_RESP:
+ case ATT_OP_FIND_INFO_RESP:
+ case ATT_OP_FIND_BY_TYPE_RESP:
+ case ATT_OP_READ_BY_TYPE_RESP:
+ case ATT_OP_READ_RESP:
+ case ATT_OP_READ_BLOB_RESP:
+ case ATT_OP_READ_MULTI_RESP:
+ case ATT_OP_READ_BY_GROUP_RESP:
+ case ATT_OP_WRITE_RESP:
+ case ATT_OP_PREP_WRITE_RESP:
+ case ATT_OP_EXEC_WRITE_RESP:
+ case ATT_OP_HANDLE_CNF:
+ break;
+
+ /* Notification & Indication */
+ case ATT_OP_HANDLE_NOTIFY:
+ case ATT_OP_HANDLE_IND:
+ break;
+ }
+
+ return true;
+}
+
+static void channel_watch_destroy(void *user_data)
+{
+ struct io *io = user_data;
+
+ io_destroy(io);
+}
+
static bool unix_accept_cb(struct io *io, void *user_data)
{
struct sockaddr_un uaddr;
socklen_t len = sizeof(uaddr);
+ struct io *nio;
int err, nsk, sk;
sk = io_get_fd(io);
@@ -110,12 +185,17 @@ static bool unix_accept_cb(struct io *io, void *user_data)
if (nsk < 0) {
err = errno;
error("ATT UNIX socket accept: %s(%d)", strerror(err), err);
- return TRUE;
+ return true;
}
DBG("ATT UNIX socket: %d", nsk);
+ nio = io_new(nsk);
+
+ io_set_close_on_destroy(nio, true);
+ io_set_read_handler(nio, channel_handler_cb, nio,
+ channel_watch_destroy);
- return TRUE;
+ return true;
}
void gatt_init(void)
--
1.8.3.1
^ permalink raw reply related
* [PATCH BlueZ v5 09/18] gattrib: Use default ATT LE MTU for non-standard sockets
From: Claudio Takahasi @ 2014-01-27 20:35 UTC (permalink / raw)
To: linux-bluetooth; +Cc: claudio.takahasi
In-Reply-To: <1390854924-31904-1-git-send-email-claudio.takahasi@openbossa.org>
This patch forces the MTU to 23 (default ATT MTU) if the transport
is not Bluetooth. This is a development purpose change to allow
testing GATT procedures over non-Bluetooth sockets.
---
attrib/gattrib.c | 16 ++++++++--------
1 file changed, 8 insertions(+), 8 deletions(-)
diff --git a/attrib/gattrib.c b/attrib/gattrib.c
index daf6312..b5b8529 100644
--- a/attrib/gattrib.c
+++ b/attrib/gattrib.c
@@ -468,18 +468,18 @@ GAttrib *g_attrib_new(GIOChannel *io)
struct _GAttrib *attrib;
uint16_t imtu;
uint16_t att_mtu;
- uint16_t cid;
- GError *gerr = NULL;
+ uint16_t cid = 0;
g_io_channel_set_encoding(io, NULL, NULL);
g_io_channel_set_buffered(io, FALSE);
- bt_io_get(io, &gerr, BT_IO_OPT_IMTU, &imtu,
- BT_IO_OPT_CID, &cid, BT_IO_OPT_INVALID);
- if (gerr) {
- error("%s", gerr->message);
- g_error_free(gerr);
- return NULL;
+ if (bt_io_get(io, NULL, BT_IO_OPT_IMTU, &imtu, BT_IO_OPT_CID, &cid,
+ BT_IO_OPT_INVALID) == FALSE) {
+ /*
+ * Use default ATT LE MTU for non-standard transports. Used
+ * for testing purpose only. eg: Unix sockets
+ */
+ imtu = ATT_DEFAULT_LE_MTU;
}
attrib = g_try_new0(struct _GAttrib, 1);
--
1.8.3.1
^ permalink raw reply related
* [PATCH BlueZ v5 08/18] gatt: Add server unix socket
From: Claudio Takahasi @ 2014-01-27 20:35 UTC (permalink / raw)
To: linux-bluetooth; +Cc: claudio.takahasi
In-Reply-To: <1390854924-31904-1-git-send-email-claudio.takahasi@openbossa.org>
This patch adds a server unix socket to handle local ATT traffic. This
is a development purpose feature used to allow local testing without
breaking the current attribute server.
---
src/gatt.c | 59 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 59 insertions(+)
diff --git a/src/gatt.c b/src/gatt.c
index f7b74d6..7a595c6 100644
--- a/src/gatt.c
+++ b/src/gatt.c
@@ -25,11 +25,17 @@
#include <config.h>
#endif
+#include <unistd.h>
+#include <errno.h>
+#include <sys/socket.h>
+#include <sys/un.h>
+
#include <glib.h>
#include "log.h"
#include "lib/uuid.h"
#include "attrib/att.h"
+#include "src/shared/io.h"
#include "gatt-dbus.h"
#include "gatt.h"
@@ -45,6 +51,7 @@ struct btd_attribute {
uint8_t value[0];
};
+static struct io *server_io;
static GList *local_attribute_db;
static uint16_t next_handle = 0x0001;
@@ -91,11 +98,62 @@ struct btd_attribute *btd_gatt_add_service(const bt_uuid_t *uuid)
return attr;
}
+static bool unix_accept_cb(struct io *io, void *user_data)
+{
+ struct sockaddr_un uaddr;
+ socklen_t len = sizeof(uaddr);
+ int err, nsk, sk;
+
+ sk = io_get_fd(io);
+
+ nsk = accept(sk, (struct sockaddr *) &uaddr, &len);
+ if (nsk < 0) {
+ err = errno;
+ error("ATT UNIX socket accept: %s(%d)", strerror(err), err);
+ return TRUE;
+ }
+
+ DBG("ATT UNIX socket: %d", nsk);
+
+ return TRUE;
+}
+
void gatt_init(void)
{
+ struct sockaddr_un uaddr = {
+ .sun_family = AF_UNIX,
+ .sun_path = "\0/bluetooth/unix_att",
+ };
+ int sk, err;
+
DBG("Starting GATT server");
gatt_dbus_manager_register();
+
+ sk = socket(AF_UNIX, SOCK_SEQPACKET | SOCK_NONBLOCK | SOCK_CLOEXEC , 0);
+ if (sk < 0) {
+ err = errno;
+ error("ATT UNIX socket: %s(%d)", strerror(err), err);
+ return;
+ }
+
+ if (bind(sk, (struct sockaddr *) &uaddr, sizeof(uaddr)) < 0) {
+ err = errno;
+ error("binding ATT UNIX socket: %s(%d)", strerror(err), err);
+ close(sk);
+ return;
+ }
+
+ if (listen(sk, 5) < 0) {
+ err = errno;
+ error("listen ATT UNIX socket: %s(%d)", strerror(err), err);
+ close(sk);
+ return;
+ }
+
+ server_io = io_new(sk);
+ io_set_close_on_destroy(server_io, true);
+ io_set_read_handler(server_io, unix_accept_cb, NULL, NULL);
}
void gatt_cleanup(void)
@@ -103,4 +161,5 @@ void gatt_cleanup(void)
DBG("Stopping GATT server");
gatt_dbus_manager_unregister();
+ io_destroy(server_io);
}
--
1.8.3.1
^ permalink raw reply related
* [PATCH BlueZ v5 07/18] gatt: Add external services tracking
From: Claudio Takahasi @ 2014-01-27 20:35 UTC (permalink / raw)
To: linux-bluetooth; +Cc: claudio.takahasi, Alvaro Silva
In-Reply-To: <1390854924-31904-1-git-send-email-claudio.takahasi@openbossa.org>
From: Alvaro Silva <alvaro.silva@openbossa.org>
All primary services declarations provided by an external application
will be automatically inserted in the attribute database.
---
src/gatt-dbus.c | 109 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 109 insertions(+)
diff --git a/src/gatt-dbus.c b/src/gatt-dbus.c
index fd614f9..000d7ae 100644
--- a/src/gatt-dbus.c
+++ b/src/gatt-dbus.c
@@ -39,15 +39,21 @@
#include "log.h"
#include "error.h"
+#include "gatt.h"
#include "gatt-dbus.h"
#define GATT_MGR_IFACE "org.bluez.GattManager1"
+#define SERVICE_IFACE "org.bluez.GattService1"
+
+#define REGISTER_TIMER 1
struct external_app {
char *owner;
char *path;
GDBusClient *client;
+ GSList *proxies;
unsigned int watch;
+ guint register_timer;
};
static GSList *external_apps;
@@ -60,6 +66,36 @@ static int external_app_path_cmp(gconstpointer a, gconstpointer b)
return g_strcmp0(eapp->path, path);
}
+static void proxy_added(GDBusProxy *proxy, void *user_data)
+{
+ struct external_app *eapp = user_data;
+ const char *interface, *path;
+
+ interface = g_dbus_proxy_get_interface(proxy);
+ path = g_dbus_proxy_get_path(proxy);
+
+ DBG("path %s iface %s", path, interface);
+
+ if (g_strcmp0(interface, SERVICE_IFACE) != 0)
+ return;
+
+ eapp->proxies = g_slist_append(eapp->proxies, proxy);
+}
+
+static void proxy_removed(GDBusProxy *proxy, void *user_data)
+{
+ struct external_app *eapp = user_data;
+ const char *interface, *path;
+
+ interface = g_dbus_proxy_get_interface(proxy);
+ path = g_dbus_proxy_get_path(proxy);
+
+ DBG("path %s iface %s", path, interface);
+
+ eapp->proxies = g_slist_remove(eapp->proxies, proxy);
+}
+
+
static void external_app_watch_destroy(gpointer user_data)
{
struct external_app *eapp = user_data;
@@ -70,6 +106,9 @@ static void external_app_watch_destroy(gpointer user_data)
g_dbus_client_unref(eapp->client);
+ if (eapp->register_timer)
+ g_source_remove(eapp->register_timer);
+
g_free(eapp->owner);
g_free(eapp->path);
g_free(eapp);
@@ -99,9 +138,75 @@ static struct external_app *new_external_app(DBusConnection *conn,
eapp->client = client;
eapp->path = g_strdup(path);
+ g_dbus_client_set_proxy_handlers(client, proxy_added, proxy_removed,
+ NULL, eapp);
+
return eapp;
}
+static int register_external_service(GDBusProxy *proxy)
+{
+ DBusMessageIter iter;
+ const char *uuid;
+ bt_uuid_t btuuid;
+
+ if (!g_dbus_proxy_get_property(proxy, "UUID", &iter))
+ return -EINVAL;
+
+ if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_STRING)
+ return -EINVAL;
+
+ dbus_message_iter_get_basic(&iter, &uuid);
+
+ if (bt_string_to_uuid(&btuuid, uuid) < 0)
+ return -EINVAL;
+
+ if (btd_gatt_add_service(&btuuid) == NULL)
+ return -EINVAL;
+
+ return 0;
+}
+
+static gboolean finish_register(gpointer user_data)
+{
+ struct external_app *eapp = user_data;
+ GSList *list;
+
+ /*
+ * It is not possible to detect when the last proxy object
+ * was reported. "Proxy added" handler reports objects
+ * added on demand or returned by GetManagedObjects().
+ * This timer helps to register all the GATT declarations
+ * (services, characteristics and descriptors) after fetching
+ * all the D-Bus objects.
+ */
+
+ eapp->register_timer = 0;
+
+ for (list = eapp->proxies; list; list = g_slist_next(list)) {
+ const char *interface, *path;
+ GDBusProxy *proxy = list->data;
+
+ interface = g_dbus_proxy_get_interface(proxy);
+ path = g_dbus_proxy_get_path(proxy);
+
+ if (g_strcmp0(SERVICE_IFACE, interface) != 0)
+ continue;
+
+ if (g_strcmp0(path, eapp->path) != 0)
+ continue;
+
+ if (register_external_service(proxy) < 0) {
+ DBG("Inconsistent external service: %s", path);
+ continue;
+ }
+
+ DBG("External service: %s", path);
+ }
+
+ return FALSE;
+}
+
static DBusMessage *register_service(DBusConnection *conn,
DBusMessage *msg, void *user_data)
{
@@ -109,6 +214,8 @@ static DBusMessage *register_service(DBusConnection *conn,
DBusMessageIter iter;
const char *path;
+ DBG("Registering GATT Service");
+
if (!dbus_message_iter_init(msg, &iter))
return btd_error_invalid_args(msg);
@@ -127,6 +234,8 @@ static DBusMessage *register_service(DBusConnection *conn,
external_apps = g_slist_prepend(external_apps, eapp);
DBG("New app %p: %s", eapp, path);
+ eapp->register_timer = g_timeout_add_seconds(REGISTER_TIMER,
+ finish_register, eapp);
return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
}
--
1.8.3.1
^ permalink raw reply related
* [PATCH BlueZ v5 06/18] gatt: Add helper for creating GATT services
From: Claudio Takahasi @ 2014-01-27 20:35 UTC (permalink / raw)
To: linux-bluetooth; +Cc: claudio.takahasi, Andre Guedes
In-Reply-To: <1390854924-31904-1-git-send-email-claudio.takahasi@openbossa.org>
From: Andre Guedes <andre.guedes@openbossa.org>
This patch adds the btd_gatt_add_service() helper which adds a
GATT Service declaration to the local attribute database.
---
lib/uuid.h | 5 +++++
src/gatt.c | 59 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
src/gatt.h | 10 ++++++++++
3 files changed, 74 insertions(+)
diff --git a/lib/uuid.h b/lib/uuid.h
index c24cee5..237145b 100644
--- a/lib/uuid.h
+++ b/lib/uuid.h
@@ -158,6 +158,11 @@ void bt_uuid_to_uuid128(const bt_uuid_t *src, bt_uuid_t *dst);
int bt_uuid_to_string(const bt_uuid_t *uuid, char *str, size_t n);
int bt_string_to_uuid(bt_uuid_t *uuid, const char *string);
+static inline int bt_uuid_len(const bt_uuid_t *uuid)
+{
+ return uuid->type / 8;
+}
+
#ifdef __cplusplus
}
#endif
diff --git a/src/gatt.c b/src/gatt.c
index e8b691a..f7b74d6 100644
--- a/src/gatt.c
+++ b/src/gatt.c
@@ -28,10 +28,69 @@
#include <glib.h>
#include "log.h"
+#include "lib/uuid.h"
+#include "attrib/att.h"
#include "gatt-dbus.h"
#include "gatt.h"
+/* Common GATT UUIDs */
+static const bt_uuid_t primary_uuid = { .type = BT_UUID16,
+ .value.u16 = GATT_PRIM_SVC_UUID };
+
+struct btd_attribute {
+ uint16_t handle;
+ bt_uuid_t type;
+ uint16_t value_len;
+ uint8_t value[0];
+};
+
+static GList *local_attribute_db;
+static uint16_t next_handle = 0x0001;
+
+static int local_database_add(uint16_t handle, struct btd_attribute *attr)
+{
+ attr->handle = handle;
+
+ local_attribute_db = g_list_append(local_attribute_db, attr);
+
+ return 0;
+}
+
+struct btd_attribute *btd_gatt_add_service(const bt_uuid_t *uuid)
+{
+ uint16_t len = bt_uuid_len(uuid);
+ struct btd_attribute *attr = g_malloc0(sizeof(struct btd_attribute) +
+ len);
+
+ /*
+ * Service DECLARATION
+ *
+ * TYPE ATTRIBUTE VALUE
+ * +-------+---------------------------------+
+ * |0x2800 | 0xYYYY... |
+ * | (1) | (2) |
+ * +------+----------------------------------+
+ * (1) - 2 octets: Primary/Secondary Service UUID
+ * (2) - 2 or 16 octets: Service UUID
+ */
+
+ attr->type = primary_uuid;
+
+ att_put_uuid(*uuid, attr->value);
+ attr->value_len = len;
+
+ if (local_database_add(next_handle, attr) < 0) {
+ g_free(attr);
+ return NULL;
+ }
+
+ /* TODO: missing overflow checking */
+ next_handle = next_handle + 1;
+
+ return attr;
+}
+
void gatt_init(void)
{
DBG("Starting GATT server");
diff --git a/src/gatt.h b/src/gatt.h
index 3a320b4..8dd1312 100644
--- a/src/gatt.h
+++ b/src/gatt.h
@@ -21,6 +21,16 @@
*
*/
+struct btd_attribute;
+
void gatt_init(void);
void gatt_cleanup(void);
+
+/* btd_gatt_add_service - Add a service declaration to local attribute database.
+ * @uuid: Service UUID.
+ *
+ * Returns a reference to service declaration attribute. In case of error,
+ * NULL is returned.
+ */
+struct btd_attribute *btd_gatt_add_service(const bt_uuid_t *uuid);
--
1.8.3.1
^ permalink raw reply related
* [PATCH BlueZ v5 05/18] lib: Move GATT UUID to uuid.h
From: Claudio Takahasi @ 2014-01-27 20:35 UTC (permalink / raw)
To: linux-bluetooth; +Cc: claudio.takahasi
In-Reply-To: <1390854924-31904-1-git-send-email-claudio.takahasi@openbossa.org>
This patch moves GATT UUIDs definitions to a common header. uuid.h contains
helper functions to manipulate Bluetooth UUIDs and some common BR/EDR services
UUIDs.
---
attrib/gatt.h | 25 -------------------------
lib/uuid.h | 25 +++++++++++++++++++++++++
2 files changed, 25 insertions(+), 25 deletions(-)
diff --git a/attrib/gatt.h b/attrib/gatt.h
index 0f113e7..4fea3eb 100644
--- a/attrib/gatt.h
+++ b/attrib/gatt.h
@@ -24,31 +24,6 @@
#include <bluetooth/sdp.h>
-/* GATT Profile Attribute types */
-#define GATT_PRIM_SVC_UUID 0x2800
-#define GATT_SND_SVC_UUID 0x2801
-#define GATT_INCLUDE_UUID 0x2802
-#define GATT_CHARAC_UUID 0x2803
-
-/* GATT Characteristic Types */
-#define GATT_CHARAC_DEVICE_NAME 0x2A00
-#define GATT_CHARAC_APPEARANCE 0x2A01
-#define GATT_CHARAC_PERIPHERAL_PRIV_FLAG 0x2A02
-#define GATT_CHARAC_RECONNECTION_ADDRESS 0x2A03
-#define GATT_CHARAC_PERIPHERAL_PREF_CONN 0x2A04
-#define GATT_CHARAC_SERVICE_CHANGED 0x2A05
-
-/* GATT Characteristic Descriptors */
-#define GATT_CHARAC_EXT_PROPER_UUID 0x2900
-#define GATT_CHARAC_USER_DESC_UUID 0x2901
-#define GATT_CLIENT_CHARAC_CFG_UUID 0x2902
-#define GATT_SERVER_CHARAC_CFG_UUID 0x2903
-#define GATT_CHARAC_FMT_UUID 0x2904
-#define GATT_CHARAC_AGREG_FMT_UUID 0x2905
-#define GATT_CHARAC_VALID_RANGE_UUID 0x2906
-#define GATT_EXTERNAL_REPORT_REFERENCE 0x2907
-#define GATT_REPORT_REFERENCE 0x2908
-
/* Client Characteristic Configuration bit field */
#define GATT_CLIENT_CHARAC_CFG_NOTIF_BIT 0x0001
#define GATT_CLIENT_CHARAC_CFG_IND_BIT 0x0002
diff --git a/lib/uuid.h b/lib/uuid.h
index 95e5a9a..c24cee5 100644
--- a/lib/uuid.h
+++ b/lib/uuid.h
@@ -105,6 +105,31 @@ extern "C" {
#define OBEX_MNS_UUID "00001133-0000-1000-8000-00805f9b34fb"
#define OBEX_MAP_UUID "00001134-0000-1000-8000-00805f9b34fb"
+/* GATT UUIDs section */
+#define GATT_PRIM_SVC_UUID 0x2800
+#define GATT_SND_SVC_UUID 0x2801
+#define GATT_INCLUDE_UUID 0x2802
+#define GATT_CHARAC_UUID 0x2803
+
+/* GATT Characteristic Types */
+#define GATT_CHARAC_DEVICE_NAME 0x2A00
+#define GATT_CHARAC_APPEARANCE 0x2A01
+#define GATT_CHARAC_PERIPHERAL_PRIV_FLAG 0x2A02
+#define GATT_CHARAC_RECONNECTION_ADDRESS 0x2A03
+#define GATT_CHARAC_PERIPHERAL_PREF_CONN 0x2A04
+#define GATT_CHARAC_SERVICE_CHANGED 0x2A05
+
+/* GATT Characteristic Descriptors */
+#define GATT_CHARAC_EXT_PROPER_UUID 0x2900
+#define GATT_CHARAC_USER_DESC_UUID 0x2901
+#define GATT_CLIENT_CHARAC_CFG_UUID 0x2902
+#define GATT_SERVER_CHARAC_CFG_UUID 0x2903
+#define GATT_CHARAC_FMT_UUID 0x2904
+#define GATT_CHARAC_AGREG_FMT_UUID 0x2905
+#define GATT_CHARAC_VALID_RANGE_UUID 0x2906
+#define GATT_EXTERNAL_REPORT_REFERENCE 0x2907
+#define GATT_REPORT_REFERENCE 0x2908
+
typedef struct {
enum {
BT_UUID_UNSPEC = 0,
--
1.8.3.1
^ permalink raw reply related
* [PATCH BlueZ v5 04/18] gatt: Add registering external service
From: Claudio Takahasi @ 2014-01-27 20:35 UTC (permalink / raw)
To: linux-bluetooth; +Cc: claudio.takahasi, Alvaro Silva
In-Reply-To: <1390854924-31904-1-git-send-email-claudio.takahasi@openbossa.org>
From: Alvaro Silva <alvaro.silva@openbossa.org>
This patch allows external applications register a given service on
Bluez. Applications must provide an object path and a dictionary of
options. Options dictionary will be used later to provide additional
service information.
---
src/gatt-dbus.c | 89 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++-
1 file changed, 88 insertions(+), 1 deletion(-)
diff --git a/src/gatt-dbus.c b/src/gatt-dbus.c
index 183c611..fd614f9 100644
--- a/src/gatt-dbus.c
+++ b/src/gatt-dbus.c
@@ -26,22 +26,109 @@
#endif
#include <stdint.h>
+#include <errno.h>
#include <glib.h>
#include <dbus/dbus.h>
#include <gdbus/gdbus.h>
+#include "adapter.h"
+#include "device.h"
+#include "lib/uuid.h"
#include "dbus-common.h"
#include "log.h"
+#include "error.h"
#include "gatt-dbus.h"
#define GATT_MGR_IFACE "org.bluez.GattManager1"
+struct external_app {
+ char *owner;
+ char *path;
+ GDBusClient *client;
+ unsigned int watch;
+};
+
+static GSList *external_apps;
+
+static int external_app_path_cmp(gconstpointer a, gconstpointer b)
+{
+ const struct external_app *eapp = a;
+ const char *path = b;
+
+ return g_strcmp0(eapp->path, path);
+}
+
+static void external_app_watch_destroy(gpointer user_data)
+{
+ struct external_app *eapp = user_data;
+
+ /* TODO: Remove from the database */
+
+ external_apps = g_slist_remove(external_apps, eapp);
+
+ g_dbus_client_unref(eapp->client);
+
+ g_free(eapp->owner);
+ g_free(eapp->path);
+ g_free(eapp);
+}
+
+static struct external_app *new_external_app(DBusConnection *conn,
+ const char *sender, const char *path)
+{
+ struct external_app *eapp;
+ GDBusClient *client;
+
+ client = g_dbus_client_new(conn, sender, "/");
+ if (client == NULL)
+ return NULL;
+
+ eapp = g_new0(struct external_app, 1);
+
+ eapp->watch = g_dbus_add_disconnect_watch(btd_get_dbus_connection(),
+ sender, NULL, eapp, external_app_watch_destroy);
+ if (eapp->watch == 0) {
+ g_dbus_client_unref(client);
+ g_free(eapp);
+ return NULL;
+ }
+
+ eapp->owner = g_strdup(sender);
+ eapp->client = client;
+ eapp->path = g_strdup(path);
+
+ return eapp;
+}
+
static DBusMessage *register_service(DBusConnection *conn,
DBusMessage *msg, void *user_data)
{
- return dbus_message_new_method_return(msg);
+ struct external_app *eapp;
+ DBusMessageIter iter;
+ const char *path;
+
+ if (!dbus_message_iter_init(msg, &iter))
+ return btd_error_invalid_args(msg);
+
+ if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_OBJECT_PATH)
+ return btd_error_invalid_args(msg);
+
+ dbus_message_iter_get_basic(&iter, &path);
+
+ if (g_slist_find_custom(external_apps, path, external_app_path_cmp))
+ return btd_error_already_exists(msg);
+
+ eapp = new_external_app(conn, dbus_message_get_sender(msg), path);
+ if (eapp == NULL)
+ return btd_error_failed(msg, "Not enough resources");
+
+ external_apps = g_slist_prepend(external_apps, eapp);
+
+ DBG("New app %p: %s", eapp, path);
+
+ return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
}
static DBusMessage *unregister_service(DBusConnection *conn,
--
1.8.3.1
^ permalink raw reply related
* [PATCH BlueZ v5 03/18] gatt: Register Manager D-Bus Interface
From: Claudio Takahasi @ 2014-01-27 20:35 UTC (permalink / raw)
To: linux-bluetooth; +Cc: claudio.takahasi, Alvaro Silva
In-Reply-To: <1390854924-31904-1-git-send-email-claudio.takahasi@openbossa.org>
From: Alvaro Silva <alvaro.silva@openbossa.org>
This patch registers GATT Service Manager D-Bus Interface. This
interface implements the methods to allow external application register
and unregister GATT Services.
---
Makefile.am | 1 +
src/gatt-dbus.c | 75 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++
src/gatt-dbus.h | 25 +++++++++++++++++++
src/gatt.c | 9 +++++++
4 files changed, 110 insertions(+)
create mode 100644 src/gatt-dbus.c
create mode 100644 src/gatt-dbus.h
diff --git a/Makefile.am b/Makefile.am
index 101d5de..fbae2c8 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -146,6 +146,7 @@ src_bluetoothd_SOURCES = $(builtin_sources) \
src/adapter.h src/adapter.c \
src/profile.h src/profile.c \
src/service.h src/service.c \
+ src/gatt-dbus.h src/gatt-dbus.c \
src/gatt.h src/gatt.c \
src/device.h src/device.c src/attio.h \
src/dbus-common.c src/dbus-common.h \
diff --git a/src/gatt-dbus.c b/src/gatt-dbus.c
new file mode 100644
index 0000000..183c611
--- /dev/null
+++ b/src/gatt-dbus.c
@@ -0,0 +1,75 @@
+/*
+ *
+ * BlueZ - Bluetooth protocol stack for Linux
+ *
+ * Copyright (C) 2014 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 <stdint.h>
+
+#include <glib.h>
+#include <dbus/dbus.h>
+#include <gdbus/gdbus.h>
+
+#include "dbus-common.h"
+#include "log.h"
+
+#include "gatt-dbus.h"
+
+#define GATT_MGR_IFACE "org.bluez.GattManager1"
+
+static DBusMessage *register_service(DBusConnection *conn,
+ DBusMessage *msg, void *user_data)
+{
+ return dbus_message_new_method_return(msg);
+}
+
+static DBusMessage *unregister_service(DBusConnection *conn,
+ DBusMessage *msg, void *user_data)
+{
+ return dbus_message_new_method_return(msg);
+}
+
+static const GDBusMethodTable methods[] = {
+ { GDBUS_EXPERIMENTAL_METHOD("RegisterService",
+ GDBUS_ARGS({ "service", "o"},
+ { "options", "a{sv}"}),
+ NULL, register_service) },
+ { GDBUS_EXPERIMENTAL_METHOD("UnregisterService",
+ GDBUS_ARGS({"service", "o"}),
+ NULL, unregister_service) },
+ { }
+};
+
+gboolean gatt_dbus_manager_register(void)
+{
+ return g_dbus_register_interface(btd_get_dbus_connection(),
+ "/org/bluez", GATT_MGR_IFACE,
+ methods, NULL, NULL, NULL, NULL);
+}
+
+void gatt_dbus_manager_unregister(void)
+{
+ g_dbus_unregister_interface(btd_get_dbus_connection(), "/org/bluez",
+ GATT_MGR_IFACE);
+}
diff --git a/src/gatt-dbus.h b/src/gatt-dbus.h
new file mode 100644
index 0000000..310cfa9
--- /dev/null
+++ b/src/gatt-dbus.h
@@ -0,0 +1,25 @@
+/*
+ *
+ * BlueZ - Bluetooth protocol stack for Linux
+ *
+ * Copyright (C) 2014 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
+ *
+ */
+
+gboolean gatt_dbus_manager_register(void);
+void gatt_dbus_manager_unregister(void);
diff --git a/src/gatt.c b/src/gatt.c
index 06619f0..e8b691a 100644
--- a/src/gatt.c
+++ b/src/gatt.c
@@ -25,14 +25,23 @@
#include <config.h>
#endif
+#include <glib.h>
+
+#include "log.h"
+
+#include "gatt-dbus.h"
#include "gatt.h"
void gatt_init(void)
{
+ DBG("Starting GATT server");
+ gatt_dbus_manager_register();
}
void gatt_cleanup(void)
{
+ DBG("Stopping GATT server");
+ gatt_dbus_manager_unregister();
}
--
1.8.3.1
^ 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