* [PATCH SBC v3 2/2] sbc: Add sbc_init_a2dp to sbc.sym
From: Luiz Augusto von Dentz @ 2014-01-20 19:34 UTC (permalink / raw)
To: linux-bluetooth
In-Reply-To: <1390246452-29103-1-git-send-email-luiz.dentz@gmail.com>
From: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
---
sbc/sbc.sym | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/sbc/sbc.sym b/sbc/sbc.sym
index 3a0c6bf..0c23a05 100644
--- a/sbc/sbc.sym
+++ b/sbc/sbc.sym
@@ -19,3 +19,7 @@ SBC_1.1 {
global:
sbc_init_msbc;
} SBC_1.0;
+SBC_1.2 {
+global:
+ sbc_init_a2dp;
+} SBC_1.1;
--
1.8.4.2
^ permalink raw reply related
* [PATCH SBC v3 1/2] sbc: Add sbc_init_a2dp
From: Luiz Augusto von Dentz @ 2014-01-20 19:34 UTC (permalink / raw)
To: linux-bluetooth
From: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
This adds sbc_init_a2dp that can be used to convert A2DP configuration to
the internal representation since they are not binary compatible.
---
sbc/sbc.c | 144 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
sbc/sbc.h | 2 +
2 files changed, 146 insertions(+)
diff --git a/sbc/sbc.c b/sbc/sbc.c
index c589217..9fd2311 100644
--- a/sbc/sbc.c
+++ b/sbc/sbc.c
@@ -57,6 +57,55 @@
#define MSBC_SYNCWORD 0xAD
#define MSBC_BLOCKS 15
+#define A2DP_SAMPLING_FREQ_16000 (1 << 3)
+#define A2DP_SAMPLING_FREQ_32000 (1 << 2)
+#define A2DP_SAMPLING_FREQ_44100 (1 << 1)
+#define A2DP_SAMPLING_FREQ_48000 1
+
+#define A2DP_CHANNEL_MODE_MONO (1 << 3)
+#define A2DP_CHANNEL_MODE_DUAL_CHANNEL (1 << 2)
+#define A2DP_CHANNEL_MODE_STEREO (1 << 1)
+#define A2DP_CHANNEL_MODE_JOINT_STEREO 1
+
+#define A2DP_BLOCK_LENGTH_4 (1 << 3)
+#define A2DP_BLOCK_LENGTH_8 (1 << 2)
+#define A2DP_BLOCK_LENGTH_12 (1 << 1)
+#define A2DP_BLOCK_LENGTH_16 1
+
+#define A2DP_SUBBANDS_4 (1 << 1)
+#define A2DP_SUBBANDS_8 1
+
+#define A2DP_ALLOCATION_SNR (1 << 1)
+#define A2DP_ALLOCATION_LOUDNESS 1
+
+#if __BYTE_ORDER == __LITTLE_ENDIAN
+
+struct a2dp_sbc {
+ uint8_t channel_mode:4;
+ uint8_t frequency:4;
+ uint8_t allocation_method:2;
+ uint8_t subbands:2;
+ uint8_t block_length:4;
+ uint8_t min_bitpool;
+ uint8_t max_bitpool;
+} __attribute__ ((packed));
+
+#elif __BYTE_ORDER == __BIG_ENDIAN
+
+struct a2dp_sbc {
+ uint8_t frequency:4;
+ uint8_t channel_mode:4;
+ uint8_t block_length:4;
+ uint8_t subbands:2;
+ uint8_t allocation_method:2;
+ uint8_t min_bitpool;
+ uint8_t max_bitpool;
+} __attribute__ ((packed));
+
+#else
+#error "Unknown byte order"
+#endif
+
/* This structure contains an unpacked SBC frame.
Yes, there is probably quite some unused space herein */
struct sbc_frame {
@@ -1046,6 +1095,101 @@ SBC_EXPORT int sbc_init_msbc(sbc_t *sbc, unsigned long flags)
return 0;
}
+SBC_EXPORT int sbc_init_a2dp(sbc_t *sbc, unsigned long flags, const void *conf,
+ size_t conf_len)
+{
+ const struct a2dp_sbc *a2dp;
+ int err;
+
+ if (conf_len != sizeof(*a2dp))
+ return -EINVAL;
+
+ err = sbc_init(sbc, flags);
+ if (err < 0)
+ return err;
+
+ a2dp = conf;
+
+ switch (a2dp->frequency) {
+ case A2DP_SAMPLING_FREQ_16000:
+ sbc->frequency = SBC_FREQ_16000;
+ break;
+ case A2DP_SAMPLING_FREQ_32000:
+ sbc->frequency = SBC_FREQ_32000;
+ break;
+ case A2DP_SAMPLING_FREQ_44100:
+ sbc->frequency = SBC_FREQ_44100;
+ break;
+ case A2DP_SAMPLING_FREQ_48000:
+ sbc->frequency = SBC_FREQ_48000;
+ break;
+ default:
+ goto failed;
+ }
+
+ switch (a2dp->channel_mode) {
+ case A2DP_CHANNEL_MODE_MONO:
+ sbc->mode = SBC_MODE_MONO;
+ break;
+ case A2DP_CHANNEL_MODE_DUAL_CHANNEL:
+ sbc->mode = SBC_MODE_DUAL_CHANNEL;
+ break;
+ case A2DP_CHANNEL_MODE_STEREO:
+ sbc->mode = SBC_MODE_STEREO;
+ break;
+ case A2DP_CHANNEL_MODE_JOINT_STEREO:
+ sbc->mode = SBC_MODE_JOINT_STEREO;
+ break;
+ default:
+ goto failed;
+ }
+
+ switch (a2dp->allocation_method) {
+ case A2DP_ALLOCATION_SNR:
+ sbc->allocation = SBC_AM_SNR;
+ break;
+ case A2DP_ALLOCATION_LOUDNESS:
+ sbc->allocation = SBC_AM_LOUDNESS;
+ break;
+ default:
+ goto failed;
+ }
+
+ switch (a2dp->subbands) {
+ case A2DP_SUBBANDS_4:
+ sbc->subbands = SBC_SB_4;
+ break;
+ case A2DP_SUBBANDS_8:
+ sbc->subbands = SBC_SB_8;
+ break;
+ default:
+ goto failed;
+ }
+
+ switch (a2dp->block_length) {
+ case A2DP_BLOCK_LENGTH_4:
+ sbc->blocks = SBC_BLK_4;
+ break;
+ case A2DP_BLOCK_LENGTH_8:
+ sbc->blocks = SBC_BLK_8;
+ break;
+ case A2DP_BLOCK_LENGTH_12:
+ sbc->blocks = SBC_BLK_12;
+ break;
+ case A2DP_BLOCK_LENGTH_16:
+ sbc->blocks = SBC_BLK_16;
+ break;
+ default:
+ goto failed;
+ }
+
+ return 0;
+
+failed:
+ sbc_finish(sbc);
+ return -EINVAL;
+}
+
SBC_EXPORT ssize_t sbc_parse(sbc_t *sbc, const void *input, size_t input_len)
{
return sbc_decode(sbc, input, input_len, NULL, 0, NULL);
diff --git a/sbc/sbc.h b/sbc/sbc.h
index 5f8a1fc..02ad9fe 100644
--- a/sbc/sbc.h
+++ b/sbc/sbc.h
@@ -84,6 +84,8 @@ typedef struct sbc_struct sbc_t;
int sbc_init(sbc_t *sbc, unsigned long flags);
int sbc_reinit(sbc_t *sbc, unsigned long flags);
int sbc_init_msbc(sbc_t *sbc, unsigned long flags);
+int sbc_init_a2dp(sbc_t *sbc, unsigned long flags, const void *conf,
+ size_t conf_len);
ssize_t sbc_parse(sbc_t *sbc, const void *input, size_t input_len);
--
1.8.4.2
^ permalink raw reply related
* Re: [PATCH] obexd/irmc: Fix folder for LUID requests
From: Luiz Augusto von Dentz @ 2014-01-20 19:29 UTC (permalink / raw)
To: Harald Schmitt; +Cc: linux-bluetooth@vger.kernel.org
In-Reply-To: <1390239558-6384-1-git-send-email-linux@hschmitt.de>
Hi Harald,
On Mon, Jan 20, 2014 at 7:39 PM, Harald Schmitt <linux@hschmitt.de> wrote:
> The old macro PB_LUID_FOLDER had the folder luid on the second level:
> /telecom/luid. But the luid folder occurs per IrMC spec on level three e.g.
> /telecom/pb/luid. On the second level the object store e.g. pb is specified.
> This bug was introduced with commit 62ebf8d0f345e7722334d852cf7a010b202647e7.
> ---
> obexd/plugins/irmc.c | 6 +++---
> obexd/plugins/phonebook.h | 2 +-
> 2 files changed, 4 insertions(+), 4 deletions(-)
>
> diff --git a/obexd/plugins/irmc.c b/obexd/plugins/irmc.c
> index d343977..d0e98b4 100644
> --- a/obexd/plugins/irmc.c
> +++ b/obexd/plugins/irmc.c
> @@ -326,7 +326,7 @@ static int irmc_open_nt(struct irmc_session *irmc)
> return 0;
> }
>
> -static int irmc_open_luid(struct irmc_session *irmc)
> +static int irmc_open_pb_luid(struct irmc_session *irmc)
> {
> if (irmc->buffer == NULL)
> irmc->buffer = g_string_new("");
> @@ -381,8 +381,8 @@ static void *irmc_open(const char *name, int oflag, mode_t mode, void *context,
> ret = irmc_open_cal(irmc);
> else if (g_str_has_prefix(path, PB_NOTES_FOLDER))
> ret = irmc_open_nt(irmc);
> - else if (g_str_has_prefix(path, PB_LUID_FOLDER))
> - ret = irmc_open_luid(irmc);
> + else if (g_str_has_prefix(path, PB_CONTACTS_LUID_FOLDER))
> + ret = irmc_open_pb_luid(irmc);
> else
> ret = -EBADR;
>
> diff --git a/obexd/plugins/phonebook.h b/obexd/plugins/phonebook.h
> index 441cff2..015c9a3 100644
> --- a/obexd/plugins/phonebook.h
> +++ b/obexd/plugins/phonebook.h
> @@ -37,7 +37,7 @@
> #define PB_CALLS_INCOMING_FOLDER "/telecom/ich"
> #define PB_CALLS_MISSED_FOLDER "/telecom/mch"
> #define PB_CALLS_OUTGOING_FOLDER "/telecom/och"
> -#define PB_LUID_FOLDER "/telecom/luid"
> +#define PB_CONTACTS_LUID_FOLDER "/telecom/pb/luid"
>
> #define PB_CONTACTS "/telecom/pb.vcf"
> #define PB_CALLS_COMBINED "/telecom/cch.vcf"
> --
> 1.8.3.2
I went ahead and pushed this one, but I preserve much of the define
and function names used before since I did not see any reason to
change those.
--
Luiz Augusto von Dentz
^ permalink raw reply
* [PATCH SBC v2 2/2] sbc: Add sbc_init_a2dp to sbc.sym
From: Luiz Augusto von Dentz @ 2014-01-20 18:51 UTC (permalink / raw)
To: linux-bluetooth
In-Reply-To: <1390243913-13962-1-git-send-email-luiz.dentz@gmail.com>
From: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
---
sbc/sbc.sym | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/sbc/sbc.sym b/sbc/sbc.sym
index 3a0c6bf..0c23a05 100644
--- a/sbc/sbc.sym
+++ b/sbc/sbc.sym
@@ -19,3 +19,7 @@ SBC_1.1 {
global:
sbc_init_msbc;
} SBC_1.0;
+SBC_1.2 {
+global:
+ sbc_init_a2dp;
+} SBC_1.1;
--
1.8.4.2
^ permalink raw reply related
* [PATCH SBC v2 1/2] sbc: Add sbc_init_a2dp
From: Luiz Augusto von Dentz @ 2014-01-20 18:51 UTC (permalink / raw)
To: linux-bluetooth
From: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
This adds sbc_init_a2dp that can be used to convert A2DP configuration to
the internal representation since they are not binary compatible.
---
sbc/sbc.c | 144 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
sbc/sbc.h | 2 +
2 files changed, 146 insertions(+)
diff --git a/sbc/sbc.c b/sbc/sbc.c
index c589217..9352446 100644
--- a/sbc/sbc.c
+++ b/sbc/sbc.c
@@ -57,6 +57,55 @@
#define MSBC_SYNCWORD 0xAD
#define MSBC_BLOCKS 15
+#define A2DP_SAMPLING_FREQ_16000 (1 << 3)
+#define A2DP_SAMPLING_FREQ_32000 (1 << 2)
+#define A2DP_SAMPLING_FREQ_44100 (1 << 1)
+#define A2DP_SAMPLING_FREQ_48000 1
+
+#define A2DP_CHANNEL_MODE_MONO (1 << 3)
+#define A2DP_CHANNEL_MODE_DUAL_CHANNEL (1 << 2)
+#define A2DP_CHANNEL_MODE_STEREO (1 << 1)
+#define A2DP_CHANNEL_MODE_JOINT_STEREO 1
+
+#define A2DP_BLOCK_LENGTH_4 (1 << 3)
+#define A2DP_BLOCK_LENGTH_8 (1 << 2)
+#define A2DP_BLOCK_LENGTH_12 (1 << 1)
+#define A2DP_BLOCK_LENGTH_16 1
+
+#define A2DP_SUBBANDS_4 (1 << 1)
+#define A2DP_SUBBANDS_8 1
+
+#define A2DP_ALLOCATION_SNR (1 << 1)
+#define A2DP_ALLOCATION_LOUDNESS 1
+
+#if __BYTE_ORDER == __LITTLE_ENDIAN
+
+struct a2dp_sbc {
+ uint8_t channel_mode:4;
+ uint8_t frequency:4;
+ uint8_t allocation_method:2;
+ uint8_t subbands:2;
+ uint8_t block_length:4;
+ uint8_t min_bitpool;
+ uint8_t max_bitpool;
+} __attribute__ ((packed));
+
+#elif __BYTE_ORDER == __BIG_ENDIAN
+
+struct a2dp_sbc {
+ uint8_t frequency:4;
+ uint8_t channel_mode:4;
+ uint8_t block_length:4;
+ uint8_t subbands:2;
+ uint8_t allocation_method:2;
+ uint8_t min_bitpool;
+ uint8_t max_bitpool;
+} __attribute__ ((packed));
+
+#else
+#error "Unknown byte order"
+#endif
+
/* This structure contains an unpacked SBC frame.
Yes, there is probably quite some unused space herein */
struct sbc_frame {
@@ -1046,6 +1095,101 @@ SBC_EXPORT int sbc_init_msbc(sbc_t *sbc, unsigned long flags)
return 0;
}
+SBC_EXPORT int sbc_init_a2dp(sbc_t *sbc, unsigned long flags,
+ const void *config, size_t len)
+{
+ const struct a2dp_sbc *a2dp;
+ int err;
+
+ if (len != sizeof(*a2dp))
+ return -EINVAL;
+
+ err = sbc_init(sbc, flags);
+ if (err < 0)
+ return err;
+
+ a2dp = config;
+
+ switch (a2dp->frequency) {
+ case A2DP_SAMPLING_FREQ_16000:
+ sbc->frequency = SBC_FREQ_16000;
+ break;
+ case A2DP_SAMPLING_FREQ_32000:
+ sbc->frequency = SBC_FREQ_32000;
+ break;
+ case A2DP_SAMPLING_FREQ_44100:
+ sbc->frequency = SBC_FREQ_44100;
+ break;
+ case A2DP_SAMPLING_FREQ_48000:
+ sbc->frequency = SBC_FREQ_48000;
+ break;
+ default:
+ goto failed;
+ }
+
+ switch (a2dp->channel_mode) {
+ case A2DP_CHANNEL_MODE_MONO:
+ sbc->mode = SBC_MODE_MONO;
+ break;
+ case A2DP_CHANNEL_MODE_DUAL_CHANNEL:
+ sbc->mode = SBC_MODE_DUAL_CHANNEL;
+ break;
+ case A2DP_CHANNEL_MODE_STEREO:
+ sbc->mode = SBC_MODE_STEREO;
+ break;
+ case A2DP_CHANNEL_MODE_JOINT_STEREO:
+ sbc->mode = SBC_MODE_JOINT_STEREO;
+ break;
+ default:
+ goto failed;
+ }
+
+ switch (a2dp->allocation_method) {
+ case A2DP_ALLOCATION_SNR:
+ sbc->allocation = SBC_AM_SNR;
+ break;
+ case A2DP_ALLOCATION_LOUDNESS:
+ sbc->allocation = SBC_AM_LOUDNESS;
+ break;
+ default:
+ goto failed;
+ }
+
+ switch (a2dp->subbands) {
+ case A2DP_SUBBANDS_4:
+ sbc->subbands = SBC_SB_4;
+ break;
+ case A2DP_SUBBANDS_8:
+ sbc->subbands = SBC_SB_8;
+ break;
+ default:
+ goto failed;
+ }
+
+ switch (a2dp->block_length) {
+ case A2DP_BLOCK_LENGTH_4:
+ sbc->blocks = SBC_BLK_4;
+ break;
+ case A2DP_BLOCK_LENGTH_8:
+ sbc->blocks = SBC_BLK_8;
+ break;
+ case A2DP_BLOCK_LENGTH_12:
+ sbc->blocks = SBC_BLK_12;
+ break;
+ case A2DP_BLOCK_LENGTH_16:
+ sbc->blocks = SBC_BLK_16;
+ break;
+ default:
+ goto failed;
+ }
+
+ return 0;
+
+failed:
+ sbc_finish(sbc);
+ return -EINVAL;
+}
+
SBC_EXPORT ssize_t sbc_parse(sbc_t *sbc, const void *input, size_t input_len)
{
return sbc_decode(sbc, input, input_len, NULL, 0, NULL);
diff --git a/sbc/sbc.h b/sbc/sbc.h
index 5f8a1fc..5791faa 100644
--- a/sbc/sbc.h
+++ b/sbc/sbc.h
@@ -84,6 +84,8 @@ typedef struct sbc_struct sbc_t;
int sbc_init(sbc_t *sbc, unsigned long flags);
int sbc_reinit(sbc_t *sbc, unsigned long flags);
int sbc_init_msbc(sbc_t *sbc, unsigned long flags);
+int sbc_init_a2dp(sbc_t *sbc, unsigned long flags, const void *config,
+ size_t len);
ssize_t sbc_parse(sbc_t *sbc, const void *input, size_t input_len);
--
1.8.4.2
^ permalink raw reply related
* Re: [PATCH v2 1/5] lib: Add flag to force large MTU size used for SDP connection
From: Szymon Janc @ 2014-01-20 18:48 UTC (permalink / raw)
To: simon; +Cc: Szymon Janc, linux-bluetooth
In-Reply-To: <cfdf976e52d86b180ee5e750c23fed8f.squirrel@mungewell.org>
Hi Simon,
On Monday 20 January 2014 13:28:57 simon@mungewell.org wrote:
> > From: Szymon Janc <szymon.janc@gmail.com>
> >
> > This will allow to workaround Dualshock4 not respecting L2CAP MTU
> > size while sending SDP response. Use same L2CAP MTU value base on
> > RFCOMM.
>
> I can confirm that the V2 series of patches work with my DS4 and crappy
> laptop. Still require particular 'connect' sequence...
Thanks for testing, and yes this sequence is about dedicated vs general
bonding mentioned in commit message.
>
> I note that I do not need the original '[PATCH 3/3] input: Add DualShock 4
> detection' patch. I am using just this sequence of 5 patches on top of
> 5.13.
This detection is used only when using SSP controller. And only in case when
dedicated bonding is used - when DS4 tries to connect immediately after
pairing is completed, but before bluetoothd was able to retrieve SDP.
--
Szymon K. Janc
szymon.janc@gmail.com
^ permalink raw reply
* Re: [PATCH v2 1/5] lib: Add flag to force large MTU size used for SDP connection
From: simon @ 2014-01-20 18:28 UTC (permalink / raw)
To: Szymon Janc; +Cc: linux-bluetooth, Szymon Janc
In-Reply-To: <1390216116-23670-1-git-send-email-szymon.janc@tieto.com>
> From: Szymon Janc <szymon.janc@gmail.com>
>
> This will allow to workaround Dualshock4 not respecting L2CAP MTU
> size while sending SDP response. Use same L2CAP MTU value base on
> RFCOMM.
I can confirm that the V2 series of patches work with my DS4 and crappy
laptop. Still require particular 'connect' sequence...
I note that I do not need the original '[PATCH 3/3] input: Add DualShock 4
detection' patch. I am using just this sequence of 5 patches on top of
5.13.
Simon
^ permalink raw reply
* Re: [PATCH 00/11] HIDHost E2E tests and fixes
From: Ravi kumar Veeramally @ 2014-01-20 18:08 UTC (permalink / raw)
To: Szymon Janc; +Cc: linux-bluetooth
In-Reply-To: <1991876.SYBil5rWd4@uw000953>
Hi Szymon,
On 01/20/2014 05:30 PM, Szymon Janc wrote:
> android/android-tester.c | 517 ++++++++++++++++++++++++++++++++++++++++++++++-
> android/hal-hidhost.c | 3 +-
> android/hidhost.c | 14 +-
> 3 files changed, 511 insertions(+), 23 deletions(-)
>
>
> I've applied all patches except 2 and 9, thanks.
> Please see comments for 02/11.
>
Ok, I will check what went wrong.
Thanks,
Ravi.
^ permalink raw reply
* [PATCH BlueZ v1 18/18] bluetooth.conf: Add ObjectManager interface
From: Claudio Takahasi @ 2014-01-20 18:05 UTC (permalink / raw)
To: linux-bluetooth; +Cc: claudio.takahasi
In-Reply-To: <1390241103-808-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 v1 17/18] gatttool: Add unix socket support for interactive mode
From: Claudio Takahasi @ 2014-01-20 18:05 UTC (permalink / raw)
To: linux-bluetooth; +Cc: claudio.takahasi
In-Reply-To: <1390241103-808-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 9826a4b..febebaa 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 v1 16/18] gatttool: Add unix socket connect
From: Claudio Takahasi @ 2014-01-20 18:05 UTC (permalink / raw)
To: linux-bluetooth; +Cc: claudio.takahasi
In-Reply-To: <1390241103-808-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 ebc8123..d701f7b 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 77bab27..de7b00a 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 v1 15/18] test: Add registering external service
From: Claudio Takahasi @ 2014-01-20 18:05 UTC (permalink / raw)
To: linux-bluetooth; +Cc: claudio.takahasi
In-Reply-To: <1390241103-808-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 | 66 +++++++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 66 insertions(+)
diff --git a/test/gatt-service.c b/test/gatt-service.c
index c076588..dc00f4c 100644
--- a/test/gatt-service.c
+++ b/test/gatt-service.c
@@ -114,6 +114,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))
+ fprintf(stderr, "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",
+ SERVICE_MGR_IFACE, "RegisterService");
+ if (msg == NULL) {
+ fprintf(stderr, "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 condition,
gpointer user_data)
{
@@ -159,6 +218,7 @@ static guint setup_signalfd(void)
int main(int argc, char *argv[])
{
+ GDBusClient *client;
DBusConnection *dbus_conn;
guint signal;
@@ -177,8 +237,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 v1 14/18] test: Add signal handling for gatt-service
From: Claudio Takahasi @ 2014-01-20 18:04 UTC (permalink / raw)
To: linux-bluetooth; +Cc: claudio.takahasi
In-Reply-To: <1390241103-808-1-git-send-email-claudio.takahasi@openbossa.org>
This patch implements signal handling to run cleanup tasks before
exiting.
---
test/gatt-service.c | 52 ++++++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 52 insertions(+)
diff --git a/test/gatt-service.c b/test/gatt-service.c
index 16e2cea..c076588 100644
--- a/test/gatt-service.c
+++ b/test/gatt-service.c
@@ -27,12 +27,14 @@
#include <errno.h>
#include <stdio.h>
+#include <sys/signalfd.h>
#include <glib.h>
#include <dbus/dbus.h>
#include <gdbus/gdbus.h>
#define SERVICE_IFACE "org.bluez.Service1"
+#define SERVICE_MGR_IFACE "org.bluez.ServiceManager1"
/* Immediate Alert Service UUID */
#define IAS_UUID "00001802-0000-1000-8000-00805f9b34fb"
@@ -112,9 +114,57 @@ static void create_services(DBusConnection *conn)
printf("Registered service: %s\n", service_path);
}
+static gboolean signal_handler(GIOChannel *channel, GIOCondition condition,
+ gpointer user_data)
+{
+ g_main_loop_quit(main_loop);
+
+ return FALSE;
+}
+
+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);
+
+ 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);
@@ -129,6 +179,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 v1 13/18] gitignore: Add test/gatt-service
From: Claudio Takahasi @ 2014-01-20 18:04 UTC (permalink / raw)
To: linux-bluetooth; +Cc: claudio.takahasi
In-Reply-To: <1390241103-808-1-git-send-email-claudio.takahasi@openbossa.org>
---
.gitignore | 1 +
1 file changed, 1 insertion(+)
diff --git a/.gitignore b/.gitignore
index 2c8e033..82f99ba 100644
--- a/.gitignore
+++ b/.gitignore
@@ -73,6 +73,7 @@ tools/3dsp
tools/obexctl
test/sap_client.pyc
test/bluezutils.pyc
+test/gatt-service
unit/test-eir
unit/test-uuid
unit/test-crc
--
1.8.3.1
^ permalink raw reply related
* [PATCH BlueZ v1 12/18] test: Add external service GATT skeleton
From: Claudio Takahasi @ 2014-01-20 18:04 UTC (permalink / raw)
To: linux-bluetooth; +Cc: claudio.takahasi
In-Reply-To: <1390241103-808-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 | 136 ++++++++++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 141 insertions(+)
create mode 100644 test/gatt-service.c
diff --git a/Makefile.tools b/Makefile.tools
index 7548dca..2a80962 100644
--- a/Makefile.tools
+++ b/Makefile.tools
@@ -367,3 +367,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..16e2cea
--- /dev/null
+++ b/test/gatt-service.c
@@ -0,0 +1,136 @@
+/*
+ *
+ * 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.Service1"
+
+/* 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 DBusMessage *service_release(DBusConnection *conn,
+ DBusMessage *msg, void *user_data)
+{
+ fprintf(stderr, "Terminating...\n");
+
+ g_main_loop_quit(main_loop);
+
+ return NULL;
+}
+
+static const GDBusMethodTable service_methods[] = {
+ { GDBUS_NOREPLY_METHOD("Release", NULL, NULL, service_release) },
+ { }
+};
+
+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,
+ service_methods, NULL, service_properties,
+ g_strdup(uuid), g_free) == FALSE) {
+ fprintf(stderr, "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 v1 11/18] gatt: Add Discover All Primary Services
From: Claudio Takahasi @ 2014-01-20 18:04 UTC (permalink / raw)
To: linux-bluetooth; +Cc: claudio.takahasi, Alvaro Silva
In-Reply-To: <1390241103-808-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 33c3b6a..b204f9c 100644
--- a/src/gatt.c
+++ b/src/gatt.c
@@ -112,6 +112,130 @@ static void send_error(GAttrib *attrib, uint8_t opcode, uint16_t handle,
g_attrib_send(attrib, 0, pdu, plen, NULL, NULL, NULL);
}
+static void read_by_group_resp(GAttrib *attrib, 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(attrib, ATT_OP_READ_BY_GROUP_REQ, start,
+ ATT_ECODE_ATTR_NOT_FOUND);
+ return;
+ }
+
+ if (group_end)
+ att_put_u16(last->handle, group_end);
+
+ g_attrib_send(attrib, 0, opdu, plen, NULL, NULL, NULL);
+}
+
+static void read_by_group(GAttrib *attrib, const uint8_t *ipdu, size_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(attrib, ipdu[0], 0x0000, ATT_ECODE_INVALID_PDU);
+ return;
+ }
+
+ if (start > end || start == 0x0000) {
+ send_error(attrib, 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(attrib, ipdu[0], start, ATT_ECODE_UNSUPP_GRP_TYPE);
+ return;
+ }
+
+ read_by_group_resp(attrib, start, end, &pattern);
+}
+
static void channel_handler_cb(const uint8_t *ipdu, uint16_t ilen,
gpointer user_data)
{
@@ -133,11 +257,14 @@ static void channel_handler_cb(const uint8_t *ipdu, uint16_t ilen,
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(attrib, ipdu[0], 0x0000, ATT_ECODE_REQ_NOT_SUPP);
break;
+ case ATT_OP_READ_BY_GROUP_REQ:
+ read_by_group(attrib, 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 v1 10/18] gatt: Register ATT command/event handler
From: Claudio Takahasi @ 2014-01-20 18:04 UTC (permalink / raw)
To: linux-bluetooth; +Cc: claudio.takahasi, Alvaro Silva
In-Reply-To: <1390241103-808-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 | 80 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 80 insertions(+)
diff --git a/src/gatt.c b/src/gatt.c
index 4806205..33c3b6a 100644
--- a/src/gatt.c
+++ b/src/gatt.c
@@ -38,6 +38,7 @@
#include "log.h"
#include "lib/uuid.h"
#include "attrib/att.h"
+#include "attrib/gattrib.h"
#include "gatt-dbus.h"
#include "gatt.h"
@@ -100,12 +101,83 @@ struct btd_attribute *btd_gatt_add_service(const bt_uuid_t *uuid)
return attr;
}
+static void send_error(GAttrib *attrib, 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));
+
+ g_attrib_send(attrib, 0, pdu, plen, NULL, NULL, NULL);
+}
+
+static void channel_handler_cb(const uint8_t *ipdu, uint16_t ilen,
+ gpointer user_data)
+{
+ GAttrib *attrib = user_data;
+
+ 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(attrib, 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;
+ }
+}
+
+static gboolean unix_hup_cb(GIOChannel *io, GIOCondition cond,
+ gpointer user_data)
+{
+ GAttrib *attrib = user_data;
+
+ g_attrib_unregister_all(attrib);
+ g_attrib_unref(attrib);
+
+ return FALSE;
+}
+
static gboolean unix_accept_cb(GIOChannel *io, GIOCondition cond,
gpointer user_data)
{
struct sockaddr_un uaddr;
socklen_t len = sizeof(uaddr);
GIOChannel *nio;
+ GAttrib *attrib;
int err, nsk, sk;
sk = g_io_channel_unix_get_fd(io);
@@ -120,6 +192,14 @@ static gboolean unix_accept_cb(GIOChannel *io, GIOCondition cond,
nio = g_io_channel_unix_new(nsk);
g_io_channel_set_close_on_unref(nio, TRUE);
DBG("ATT UNIX socket: %p new client", nio);
+
+ attrib = g_attrib_new(nio);
+
+ g_attrib_register(attrib, GATTRIB_ALL_EVENTS, GATTRIB_ALL_HANDLES,
+ channel_handler_cb, attrib, NULL);
+
+ g_io_add_watch(nio, G_IO_HUP, unix_hup_cb, attrib);
+
g_io_channel_unref(nio);
return TRUE;
--
1.8.3.1
^ permalink raw reply related
* [PATCH BlueZ v1 09/18] gattrib: Use default ATT LE MTU for non-standard sockets
From: Claudio Takahasi @ 2014-01-20 18:04 UTC (permalink / raw)
To: linux-bluetooth; +Cc: claudio.takahasi
In-Reply-To: <1390241103-808-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 609b908..fccb2bf 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 v1 08/18] gatt: Add server unix socket
From: Claudio Takahasi @ 2014-01-20 18:04 UTC (permalink / raw)
To: linux-bluetooth; +Cc: claudio.takahasi
In-Reply-To: <1390241103-808-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 | 67 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 67 insertions(+)
diff --git a/src/gatt.c b/src/gatt.c
index ee045b1..4806205 100644
--- a/src/gatt.c
+++ b/src/gatt.c
@@ -25,6 +25,11 @@
#include <config.h>
#endif
+#include <unistd.h>
+#include <errno.h>
+#include <sys/socket.h>
+#include <sys/un.h>
+
#include <glib.h>
#include "adapter.h"
@@ -50,6 +55,7 @@ struct btd_attribute {
static GList *local_attribute_db;
static uint16_t next_handle = 0x0001;
+static guint unix_watch;
static int local_database_add(uint16_t handle, struct btd_attribute *attr)
{
@@ -94,11 +100,71 @@ struct btd_attribute *btd_gatt_add_service(const bt_uuid_t *uuid)
return attr;
}
+static gboolean unix_accept_cb(GIOChannel *io, GIOCondition cond,
+ gpointer user_data)
+{
+ struct sockaddr_un uaddr;
+ socklen_t len = sizeof(uaddr);
+ GIOChannel *nio;
+ int err, nsk, sk;
+
+ sk = g_io_channel_unix_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;
+ }
+
+ nio = g_io_channel_unix_new(nsk);
+ g_io_channel_set_close_on_unref(nio, TRUE);
+ DBG("ATT UNIX socket: %p new client", nio);
+ g_io_channel_unref(nio);
+
+ return TRUE;
+}
+
void gatt_init(void)
{
+ struct sockaddr_un uaddr = {
+ .sun_family = AF_UNIX,
+ .sun_path = "\0/bluetooth/unix_att",
+ };
+ GIOChannel *io;
+ 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;
+ }
+
+ io = g_io_channel_unix_new(sk);
+ g_io_channel_set_close_on_unref(io, TRUE);
+ unix_watch = g_io_add_watch(io,
+ G_IO_IN | G_IO_ERR | G_IO_HUP | G_IO_NVAL,
+ unix_accept_cb, NULL);
+ g_io_channel_unref(io);
}
void gatt_cleanup(void)
@@ -106,4 +172,5 @@ void gatt_cleanup(void)
DBG("Stopping GATT server");
gatt_dbus_manager_unregister();
+ g_source_remove(unix_watch);
}
--
1.8.3.1
^ permalink raw reply related
* [PATCH BlueZ v1 07/18] gatt: Implement UnregisterService
From: Claudio Takahasi @ 2014-01-20 18:04 UTC (permalink / raw)
To: linux-bluetooth; +Cc: claudio.takahasi, Alvaro Silva
In-Reply-To: <1390241103-808-1-git-send-email-claudio.takahasi@openbossa.org>
From: Alvaro Silva <alvaro.silva@openbossa.org>
This patch implements UnregisterService method of ServiceManager1.
External applications may call this method to unregister a given
service without leaving the system bus.
---
src/gatt-dbus.c | 25 +++++++++++++++++++++++++
1 file changed, 25 insertions(+)
diff --git a/src/gatt-dbus.c b/src/gatt-dbus.c
index fc41d00..1f789b0 100644
--- a/src/gatt-dbus.c
+++ b/src/gatt-dbus.c
@@ -243,6 +243,31 @@ static DBusMessage *register_service(DBusConnection *conn,
static DBusMessage *unregister_service(DBusConnection *conn,
DBusMessage *msg, void *user_data)
{
+ struct external_app *eapp = user_data;
+ DBusMessageIter iter;
+ const char *path;
+ GSList *list;
+
+ DBG("Unregistering GATT Service");
+
+ 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);
+
+ list = g_slist_find_custom(external_apps, path, external_app_path_cmp);
+ if (list == NULL)
+ return btd_error_does_not_exist(msg);
+
+ eapp = list->data;
+ if (g_strcmp0(dbus_message_get_sender(msg), eapp->owner) != 0)
+ return btd_error_does_not_exist(msg);
+
+ g_dbus_remove_watch(conn, eapp->watch);
+
return dbus_message_new_method_return(msg);
}
--
1.8.3.1
^ permalink raw reply related
* [PATCH BlueZ v1 06/18] gatt: Add external services tracking
From: Claudio Takahasi @ 2014-01-20 18:04 UTC (permalink / raw)
To: linux-bluetooth; +Cc: claudio.takahasi, Alvaro Silva
In-Reply-To: <1390241103-808-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 fc41b78..fc41d00 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 SERVICE_IFACE "org.bluez.Service1"
#define SERVICE_MGR_IFACE "org.bluez.ServiceManager1"
+#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 v1 05/18] gatt: Add helper for creating GATT services
From: Claudio Takahasi @ 2014-01-20 18:04 UTC (permalink / raw)
To: linux-bluetooth; +Cc: claudio.takahasi, Andre Guedes
In-Reply-To: <1390241103-808-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 | 62 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
src/gatt.h | 10 ++++++++++
3 files changed, 77 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..ee045b1 100644
--- a/src/gatt.c
+++ b/src/gatt.c
@@ -27,11 +27,73 @@
#include <glib.h>
+#include "adapter.h"
+#include "device.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 v1 04/18] lib: Move GATT UUID to uuid.h
From: Claudio Takahasi @ 2014-01-20 18:04 UTC (permalink / raw)
To: linux-bluetooth; +Cc: claudio.takahasi
In-Reply-To: <1390241103-808-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 v1 03/18] gatt: Add registering external service
From: Claudio Takahasi @ 2014-01-20 18:04 UTC (permalink / raw)
To: linux-bluetooth; +Cc: claudio.takahasi, Alvaro Silva
In-Reply-To: <1390241103-808-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 90a321b..fc41b78 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 SERVICE_MGR_IFACE "org.bluez.ServiceManager1"
+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 v1 02/18] gatt: Register Manager D-Bus Interface
From: Claudio Takahasi @ 2014-01-20 18:04 UTC (permalink / raw)
To: linux-bluetooth; +Cc: claudio.takahasi, Alvaro Silva
In-Reply-To: <1390241103-808-1-git-send-email-claudio.takahasi@openbossa.org>
From: Alvaro Silva <alvaro.silva@openbossa.org>
This patch registers the 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 1444f0e..c395874 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..90a321b
--- /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 SERVICE_MGR_IFACE "org.bluez.ServiceManager1"
+
+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", SERVICE_MGR_IFACE,
+ methods, NULL, NULL, NULL, NULL);
+}
+
+void gatt_dbus_manager_unregister(void)
+{
+ g_dbus_unregister_interface(btd_get_dbus_connection(), "/org/bluez",
+ SERVICE_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