Linux bluetooth development
 help / color / mirror / Atom feed
* Re: [PATCH SBC v3 1/2] sbc: Add sbc_init_a2dp
From: Marcel Holtmann @ 2014-01-20 22:07 UTC (permalink / raw)
  To: Luiz Augusto von Dentz; +Cc: linux-bluetooth@vger.kernel.org development
In-Reply-To: <1390246452-29103-1-git-send-email-luiz.dentz@gmail.com>

Hi Luiz,

> 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

please use (1 << 0) here.

> +
> +#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);

Lets get const void *conf and size_t conf_len both on the second line. It feels looks wise a little bit easier on eyes. 

And then the same for the actual implementation of course. Otherwise, this looks good.

Regards

Marcel


^ permalink raw reply

* Re: [PATCH] obexd/irmc: Fix folder for LUID requests
From: Harald Schmitt @ 2014-01-20 20:55 UTC (permalink / raw)
  To: Luiz Augusto von Dentz; +Cc: linux-bluetooth@vger.kernel.org
In-Reply-To: <CABBYNZLDtvMzbZN8Ju+VpAnFwQc2vVnqkgAeyM73XC8af3XeGw@mail.gmail.com>

Hi Luiz,

Am 20.01.2014 20:29, schrieb Luiz Augusto von Dentz:
> 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.
> 
That's fine with me. I just thought it would be more descriptive.


^ permalink raw reply

* Re: linux-firmware: pull-request Marvell mwifiex-firmware 2014-01-09
From: Ben Hutchings @ 2014-01-20 20:32 UTC (permalink / raw)
  To: Bing Zhao
  Cc: linux-wireless@vger.kernel.org, linux-bluetooth@vger.kernel.org,
	Frank Huang
In-Reply-To: <477F20668A386D41ADCC57781B1F70430F53691FC8@SC-VEXCH1.marvell.com>

On Mon, Jan 20, 2014 at 12:26:47PM -0800, Bing Zhao wrote:
> Hi Ben,
> 
> > > > >  File: mrvl/usb8797_uapsta.bin
> > > > > -Version: 14.69.11.p179
> > > > > +Version: 14.68.29.p26
> > > > [...]
> > > >
> > > > Why are these updates rolling the version number backward?  Did the
> > > > later versions cause regressions?
> > >
> > > These images are newer firmware versions actually.
> > >
> > > The 2nd (69 or 68) and 3rd (11 or 29) numbers in the version string do
> > > not necessarily mean the version increasing or decreasing. Only when
> > > first 3 numbers are fixed, a smaller 4th number will mean that the
> > > version is rolling backward. For examples,
> > 
> > So what do you they mean and why are they in the version number?
> 
> The first 3 numbers altogether identifies the firmware branch/features. The 4th number is the firmware revision.

This is a uniquely confusing way of generating version numbers.  If
only the current 4th part (what you call firmware revision) follows
the usual version ordering, then I think that should be used as the
(public) version number.

Ben.

-- 
Ben Hutchings
Gates has joked that everything goes on and off unexepectedly in the house,
which is run by a high-end PC network built on Windows NT. - Seattle Times

^ permalink raw reply

* RE: linux-firmware: pull-request Marvell mwifiex-firmware 2014-01-09
From: Bing Zhao @ 2014-01-20 20:26 UTC (permalink / raw)
  To: Ben Hutchings
  Cc: linux-wireless@vger.kernel.org, linux-bluetooth@vger.kernel.org,
	Frank Huang
In-Reply-To: <1390186665.3651.27.camel@deadeye.wl.decadent.org.uk>

SGkgQmVuLA0KDQo+ID4gPiA+ICBGaWxlOiBtcnZsL3VzYjg3OTdfdWFwc3RhLmJpbg0KPiA+ID4g
PiAtVmVyc2lvbjogMTQuNjkuMTEucDE3OQ0KPiA+ID4gPiArVmVyc2lvbjogMTQuNjguMjkucDI2
DQo+ID4gPiBbLi4uXQ0KPiA+ID4NCj4gPiA+IFdoeSBhcmUgdGhlc2UgdXBkYXRlcyByb2xsaW5n
IHRoZSB2ZXJzaW9uIG51bWJlciBiYWNrd2FyZD8gIERpZCB0aGUNCj4gPiA+IGxhdGVyIHZlcnNp
b25zIGNhdXNlIHJlZ3Jlc3Npb25zPw0KPiA+DQo+ID4gVGhlc2UgaW1hZ2VzIGFyZSBuZXdlciBm
aXJtd2FyZSB2ZXJzaW9ucyBhY3R1YWxseS4NCj4gPg0KPiA+IFRoZSAybmQgKDY5IG9yIDY4KSBh
bmQgM3JkICgxMSBvciAyOSkgbnVtYmVycyBpbiB0aGUgdmVyc2lvbiBzdHJpbmcgZG8NCj4gPiBu
b3QgbmVjZXNzYXJpbHkgbWVhbiB0aGUgdmVyc2lvbiBpbmNyZWFzaW5nIG9yIGRlY3JlYXNpbmcu
IE9ubHkgd2hlbg0KPiA+IGZpcnN0IDMgbnVtYmVycyBhcmUgZml4ZWQsIGEgc21hbGxlciA0dGgg
bnVtYmVyIHdpbGwgbWVhbiB0aGF0IHRoZQ0KPiA+IHZlcnNpb24gaXMgcm9sbGluZyBiYWNrd2Fy
ZC4gRm9yIGV4YW1wbGVzLA0KPiANCj4gU28gd2hhdCBkbyB5b3UgdGhleSBtZWFuIGFuZCB3aHkg
YXJlIHRoZXkgaW4gdGhlIHZlcnNpb24gbnVtYmVyPw0KDQpUaGUgZmlyc3QgMyBudW1iZXJzIGFs
dG9nZXRoZXIgaWRlbnRpZmllcyB0aGUgZmlybXdhcmUgYnJhbmNoL2ZlYXR1cmVzLiBUaGUgNHRo
IG51bWJlciBpcyB0aGUgZmlybXdhcmUgcmV2aXNpb24uDQoNClRoYW5rcywNCkJpbmcNCg0K

^ permalink raw reply

* RE: linux-firmware: pull-request Marvell mwifiex-firmware 2014-01-09
From: Bing Zhao @ 2014-01-20 20:25 UTC (permalink / raw)
  To: quozl@laptop.org
  Cc: Ben Hutchings, linux-wireless@vger.kernel.org,
	linux-bluetooth@vger.kernel.org, Frank Huang
In-Reply-To: <20140120022223.GI17658@us.netrek.org>

Hi James,

> On Sun, Jan 19, 2014 at 06:10:03PM -0800, Bing Zhao wrote:
> > The 2nd (69 or 68) and 3rd (11 or 29) numbers in the version string
> > do not necessarily mean the version increasing or decreasing. Only
> > when first 3 numbers are fixed, a smaller 4th number will mean that
> > the version is rolling backward.
> 
> Ah, light dawns.  I've been dealing with these version numbers for
> years now, for 8388, 8686 and 8787, and I didn't know that.  Is this
> documented anywhere else?  Have the 2nd and 3rd numbers any meaning or
> are they random?

They're not random. They represent firmware branch and features built in.

Thanks,
Bing

^ permalink raw reply

* Re: [PATCH 1/5] lib: Add flag to double L2CAP IMTU size used for SDP connection
From: Szymon Janc @ 2014-01-20 20:00 UTC (permalink / raw)
  To: simon; +Cc: linux-bluetooth
In-Reply-To: <649bfd2b8da26f5cf4b19f59d40d26fc.squirrel@mungewell.org>

Hi Simon,

On Monday 20 January 2014 12:31:14 simon@mungewell.org wrote:

<snip>

> I also noticed a weird log at one point, although only saw this once and
> don't know what triggered it.
> --
> [bluetooth]#
> [CHG] Device 1C:66:6D:07:C3:E0 Class: 0x200404
> [CHG] Device 1C:66:6D:07:C3:E0 Icon: audio-card <--------!!
> [CHG] Device 1C:66:6D:07:C3:E0 Class: 0x002508
> [CHG] Device 1C:66:6D:07:C3:E0 Icon: input-gaming
> --

Yes, I've seen this as well. I suspect that DS4 has some extra features 
related to audio (it has jack for headphones) and it enables that for PS4 
only, possibly switching to 'gamepad mode' if not connected to PS4. Maybe 
related to connecting USB first or sth...

But this is just my suspicion... 

-- 
Szymon K. Janc
szymon.janc@gmail.com

^ permalink raw reply

* [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


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