Linux bluetooth development
 help / color / mirror / Atom feed
* RE: LE Kernel (bluetooth-le-2.6) and LE Security Manager
From: Brian Gix @ 2010-12-04  0:40 UTC (permalink / raw)
  To: 'Vinicius Costa Gomes', 'Gustavo F. Padovan',
	'Ville Tervo'
  Cc: linux-bluetooth
In-Reply-To: <20101203220534.GA16709@eris>



Hi Vinicius & Gustavo,


-----Original Message-----
From: Vinicius Costa Gomes [mailto:vinicius.gomes@openbossa.org] 
Sent: 03 December, 2010 2:06 PM
To: Brian Gix
Cc: linux-bluetooth@vger.kernel.org
Subject: Re: LE Kernel (bluetooth-le-2.6) and LE Security Manager

Hi Brian,

On 11:11 Fri 03 Dec, Brian Gix wrote:
> 
> Hi Claudio, Johan & All,
> 
> Is this LE capable kernel that Ville is working on, the development stream
> for the LE Security Manager?  And if so, is it in a partial fleshed out
> state?

There is a simple implementation of SMP here[1] on my "devel" branch. I am 
cleaning it up for sending it for review.

If you want to help, have any comments or just want to tell us what you are
working on, please drop by #bluez on freenode, or send an email.

[Gix] Unfortunately, I can't access git.infradead.org.  Gustavo, would it be
possible for you to pull Vinicius' devel branch from
git://git.infradead.org/users/vcgomes/linux-2.6.git to an le-devel branch on
your bluetooth-testing repository?

[Gix] I am trying to integrate Qualcomm's latest LE capable (BR/EDR/LE)
chipset with bluez.  Additionally, I do have a working non-open-source
[Gix]  host which has had it's LE Security Manager UPF tested, which I hope
to be able to use to help test/solidify the bluez version.


> 
> >
git://git.kernel.org/pub/scm/linux/kernel/git/vtervo/bluetooth-le-2.6.git
> 
> 
> Brian Gix
> bgix@codeaurora.org
> Employee of Qualcomm Innovation Center, Inc.
> Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum
> 
> 
> --
> To unsubscribe from this list: send the line "unsubscribe linux-bluetooth"
in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html


Cheers,
-- 
Vinicius

[1] git://git.infradead.org/users/vcgomes/linux-2.6.git 


^ permalink raw reply

* Re: LE Kernel (bluetooth-le-2.6) and LE Security Manager
From: Vinicius Costa Gomes @ 2010-12-03 22:05 UTC (permalink / raw)
  To: Brian Gix; +Cc: linux-bluetooth
In-Reply-To: <001c01cb931d$dc4cb3a0$94e61ae0$@org>

Hi Brian,

On 11:11 Fri 03 Dec, Brian Gix wrote:
> 
> Hi Claudio, Johan & All,
> 
> Is this LE capable kernel that Ville is working on, the development stream
> for the LE Security Manager?  And if so, is it in a partial fleshed out
> state?

There is a simple implementation of SMP here[1] on my "devel" branch. I am 
cleaning it up for sending it for review.

If you want to help, have any comments or just want to tell us what you are
working on, please drop by #bluez on freenode, or send an email.

> 
> > git://git.kernel.org/pub/scm/linux/kernel/git/vtervo/bluetooth-le-2.6.git
> 
> 
> Brian Gix
> bgix@codeaurora.org
> Employee of Qualcomm Innovation Center, Inc.
> Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum
> 
> 
> --
> To unsubscribe from this list: send the line "unsubscribe linux-bluetooth" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html


Cheers,
-- 
Vinicius

[1] git://git.infradead.org/users/vcgomes/linux-2.6.git 

^ permalink raw reply

* LE Kernel (bluetooth-le-2.6) and LE Security Manager
From: Brian Gix @ 2010-12-03 19:11 UTC (permalink / raw)
  To: linux-bluetooth


Hi Claudio, Johan & All,

Is this LE capable kernel that Ville is working on, the development stream
for the LE Security Manager?  And if so, is it in a partial fleshed out
state?

> git://git.kernel.org/pub/scm/linux/kernel/git/vtervo/bluetooth-le-2.6.git


Brian Gix
bgix@codeaurora.org
Employee of Qualcomm Innovation Center, Inc.
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum



^ permalink raw reply

* Re: Are LE connections possible yet?
From: Anderson Lizardo @ 2010-12-03 19:09 UTC (permalink / raw)
  To: Brian Gix; +Cc: Claudio Takahasi, Mike Tsai, linux-bluetooth
In-Reply-To: <000301cb931c$74e56870$5eb03950$@org>

On Fri, Dec 3, 2010 at 3:01 PM, Brian Gix <bgix@codeaurora.org> wrote:
> [Gix] And how do I get gatttool to build? This may be academic until I get fixed channel 4 access via the new kernel.

gatttool is built along with bluez. Just be sure to use latest code
from GIT, and pass "--enable-attrib" to ./configure (or use
./bootstrap-configure)

Regards,
-- 
Anderson Lizardo
OpenBossa Labs - INdT
Manaus - Brazil

^ permalink raw reply

* RE: Are LE connections possible yet?
From: Brian Gix @ 2010-12-03 19:01 UTC (permalink / raw)
  To: 'Claudio Takahasi', 'Mike Tsai'; +Cc: linux-bluetooth
In-Reply-To: <AANLkTi=gWTQXcfisupHXs9qVpHbUbYZ1yxxqKf2Mm9EU@mail.gmail.com>

Hi Claudio & Mike

-----Original Message-----
From: Claudio Takahasi [mailto:claudio.takahasi@openbossa.org] 
Sent: 03 December, 2010 10:07 AM
To: Mike Tsai
Cc: Brian Gix; linux-bluetooth@vger.kernel.org
Subject: Re: Are LE connections possible yet?

Hi All,

On Thu, Dec 2, 2010 at 10:21 PM, Mike Tsai <Mike.Tsai@atheros.com> wrote:
> Hi Brian,
>
> -----Original Message-----
> From: linux-bluetooth-owner@vger.kernel.org [mailto:linux-bluetooth-owner@vger.kernel.org] On Behalf Of Brian Gix
> Sent: Thursday, December 02, 2010 3:46 PM
> To: linux-bluetooth@vger.kernel.org
> Subject: Are LE connections possible yet?
>
> Hi All,
>
> I am bringing up an LE capable (BR/EDR/LE) baseband, and attempting to use
> it to establish a
> GATT/ATT connection over an LE link.  However when executing the command:
>
> % ./tools/hcitool lecc 00:14:BB:55:66:77
>
> I get a very rapid failure of:
>
> "Could not create connection: Operation not permitted"
>
> The correct HCI command does not appear to be making it to the BR/EDR/LE
> baseband.
>
> It appears to be a socket issue of some sort.  I can cause this error, when
> attached to the baseband, and:
> "Could not create connection: File descriptor in bad state"
>
> if I have not yet run hciattach.
>
> Other (BR/EDR) hcitool commands work as expected, such as "hcitool scan" and
> "hcitool inq"
> [MTsai]which kernel driver you are using? It seems the kernel does not know the LE create connection OpCode?
>
>
> Brian Gix
> bgix@codeaurora.org
> Employee of Qualcomm Innovation Center, Inc.
> Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum
>
>
>
> --
> To unsubscribe from this list: send the line "unsubscribe linux-bluetooth" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
> --
> To unsubscribe from this list: send the line "unsubscribe linux-bluetooth" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
>

For hcitool lecc it is not necessary a LE "capable" kernel, hcitool
sends the HCI commands from the userspace.
Try sudo hcitool lecc ... and don't forget putting the remote on
advertising mode: $hciconfig hcix leadv

If you want to test the connections managed by the kernel use Ville's kernel:
git://git.kernel.org/pub/scm/linux/kernel/git/vtervo/bluetooth-le-2.6.git

l2test support LE connections, use -J option to pass the fixed channel 4

[Gix] So I am cloning Ville's kernel as I type.  I did get the LE connection up and running (raw LE ACL connections, "sudo" was the key) but I will need it to be talking on Fixed channel 4, because it is a non-bluez server that I am connecting to, which does use Fixed-4.  This will probably take me the rest of the day.

[Gix] My next question is: How long until Ville's kernel is part of the tip? 

[Gix] And how do I get gatttool to build? This may be academic until I get fixed channel 4 access via the new kernel.


Regards,
Claudio


^ permalink raw reply

* Re: [PATCH 1/5] Add device type to identify LE, BR/EDR or dual mode devices
From: Anderson Lizardo @ 2010-12-03 18:42 UTC (permalink / raw)
  To: Claudio Takahasi; +Cc: linux-bluetooth
In-Reply-To: <1291386532-4985-1-git-send-email-claudio.takahasi@openbossa.org>

Hi Claudio,

On Fri, Dec 3, 2010 at 10:28 AM, Claudio Takahasi
<claudio.takahasi@openbossa.org> wrote:
> +static uint8_t flags2type(uint8_t flags)
> +{
> +       /* Inferring the remote type based on the EIR Flags field */
> +
> +       if (flags & EIR_SIM_CONTROLLER && flags & EIR_SIM_HOST)
> +               return DUALMODE_TYPE;

Can the above be simplified to the following?

 if (flags & (EIR_SIM_CONTROLLER | EIR_SIM_HOST))

I know the semantics will change slightly, but I suppose that either
host or controller supports simultaneous LE and BR/EDR, it can be
considered dual mode. It would no be necessary to have *both* bits set
(my impression).

> @@ -3082,6 +3098,7 @@ void adapter_update_device_from_info(struct btd_adapter *adapter,
>        if (new_dev) {
>                dev->le = TRUE;
>                dev->evt_type = info->evt_type;
> +               dev->type = LE_TYPE;
>        } else if (dev->rssi == rssi)
>                return;
>

Can you remind me why both dev->le and dev->type are necessary in
struct remote_dev_info ?

> @@ -3124,6 +3142,7 @@ void adapter_update_found_devices(struct btd_adapter *adapter, bdaddr_t *bdaddr,
>                        dev->alias = g_strdup(alias);
>
>                dev->le = FALSE;
> +               dev->type = BREDR_TYPE;
>                dev->class = class;
>                dev->legacy = legacy;
>                dev->name_status = name_status;

Same question as above here too.

Regards,
-- 
Anderson Lizardo
OpenBossa Labs - INdT
Manaus - Brazil

^ permalink raw reply

* [PATCH] Fix writing to GAttrib socket without POLLOUT event
From: Vinicius Costa Gomes @ 2010-12-03 18:28 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Vinicius Costa Gomes

If the GIOChannel is in the buffered state (the default) the watch
function is called without receiving a POLLOUT from the socket. GLib
adds a G_IO_OUT condition just because there is space in the GIOChannel
internal buffer.

The solution is disabling the internal buffer, which in turn, makes the
call of g_io_channel_flush() useless.
---
 attrib/gattrib.c |    3 +--
 1 files changed, 1 insertions(+), 2 deletions(-)

diff --git a/attrib/gattrib.c b/attrib/gattrib.c
index ed18168..1083519 100644
--- a/attrib/gattrib.c
+++ b/attrib/gattrib.c
@@ -248,8 +248,6 @@ static gboolean can_write_data(GIOChannel *io, GIOCondition cond,
 	if (iostat != G_IO_STATUS_NORMAL)
 		return FALSE;
 
-	g_io_channel_flush(io, NULL);
-
 	if (cmd->expected == 0) {
 		g_queue_pop_head(attrib->queue);
 		command_destroy(cmd);
@@ -350,6 +348,7 @@ GAttrib *g_attrib_new(GIOChannel *io)
 	struct _GAttrib *attrib;
 
 	g_io_channel_set_encoding(io, NULL, NULL);
+	g_io_channel_set_buffered(io, FALSE);
 
 	attrib = g_try_new0(struct _GAttrib, 1);
 	if (attrib == NULL)
-- 
1.7.3.2


^ permalink raw reply related

* [PATCH 3/3] Check authentication permissions on attribute server
From: Anderson Lizardo @ 2010-12-03 18:26 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Anderson Lizardo
In-Reply-To: <1291400782-24736-1-git-send-email-anderson.lizardo@openbossa.org>

Attributes may require encryption for certain operations. This commit
adds checks to the attribute server which verify whether the current
connection is encrypted (by checking the security level) and the
attribute being accessed requires authentication. If encryption
requirements are not satisfied, the "Insufficient Encryption" error is
returned by the server.

Note that currently there is no actual distinction between
authentication and encryption. Currently, if an attribute requires
authentication, it is only checked whether the link is encrypted. Core
Specification, as of version 4.0, does not specify an explicit
"encryption" permission (see Vol.  3, Part F, 3.2.5 "Attribute
Permissions").
---
 src/attrib-server.c |   57 +++++++++++++++++++++++++++++++++++---------------
 1 files changed, 40 insertions(+), 17 deletions(-)

diff --git a/src/attrib-server.c b/src/attrib-server.c
index 2ba21e9..f2df853 100644
--- a/src/attrib-server.c
+++ b/src/attrib-server.c
@@ -57,6 +57,7 @@ struct gatt_channel {
 	GAttrib *attrib;
 	guint mtu;
 	guint id;
+	gboolean encrypted;
 };
 
 struct group_elem {
@@ -138,8 +139,15 @@ static sdp_record_t *server_record_new(void)
 	return record;
 }
 
-static uint8_t att_check_reqs(uint8_t opcode, int reqs)
+static uint8_t att_check_reqs(struct gatt_channel *channel, uint8_t opcode,
+								int reqs)
 {
+	/* FIXME: currently, it is assumed an encrypted link is enough for
+	 * authentication. This will allow to enable the SMP negotiation once
+	 * it is on upstream kernel. */
+	if (reqs == ATT_AUTHENTICATION && !channel->encrypted)
+		return ATT_ECODE_INSUFF_ENC;
+
 	switch (opcode) {
 	case ATT_OP_READ_BY_GROUP_REQ:
 	case ATT_OP_READ_BY_TYPE_REQ:
@@ -160,8 +168,9 @@ static uint8_t att_check_reqs(uint8_t opcode, int reqs)
 	return 0;
 }
 
-static uint16_t read_by_group(uint16_t start, uint16_t end, uuid_t *uuid,
-							uint8_t *pdu, int len)
+static uint16_t read_by_group(struct gatt_channel *channel, uint16_t start,
+						uint16_t end, uuid_t *uuid,
+						uint8_t *pdu, int len)
 {
 	struct att_data_list *adl;
 	struct attribute *a;
@@ -212,7 +221,8 @@ static uint16_t read_by_group(uint16_t start, uint16_t end, uuid_t *uuid,
 		if (last_size && (last_size != a->len))
 			break;
 
-		status = att_check_reqs(ATT_OP_READ_BY_GROUP_REQ, a->read_reqs);
+		status = att_check_reqs(channel, ATT_OP_READ_BY_GROUP_REQ,
+								a->read_reqs);
 		if (status) {
 			g_slist_foreach(groups, (GFunc) g_free, NULL);
 			g_slist_free(groups);
@@ -271,8 +281,9 @@ static uint16_t read_by_group(uint16_t start, uint16_t end, uuid_t *uuid,
 	return length;
 }
 
-static uint16_t read_by_type(uint16_t start, uint16_t end, uuid_t *uuid,
-							uint8_t *pdu, int len)
+static uint16_t read_by_type(struct gatt_channel *channel, uint16_t start,
+						uint16_t end, uuid_t *uuid,
+						uint8_t *pdu, int len)
 {
 	struct att_data_list *adl;
 	GSList *l, *types;
@@ -297,7 +308,8 @@ static uint16_t read_by_type(uint16_t start, uint16_t end, uuid_t *uuid,
 		if (sdp_uuid_cmp(&a->uuid, uuid)  != 0)
 			continue;
 
-		status = att_check_reqs(ATT_OP_READ_BY_TYPE_REQ, a->read_reqs);
+		status = att_check_reqs(channel, ATT_OP_READ_BY_TYPE_REQ,
+								a->read_reqs);
 		if (status) {
 			g_slist_free(types);
 			return enc_error_resp(ATT_OP_READ_BY_TYPE_REQ,
@@ -508,7 +520,8 @@ static int attribute_cmp(gconstpointer a1, gconstpointer a2)
 	return attrib1->handle - attrib2->handle;
 }
 
-static uint16_t read_value(uint16_t handle, uint8_t *pdu, int len)
+static uint16_t read_value(struct gatt_channel *channel, uint16_t handle,
+							uint8_t *pdu, int len)
 {
 	struct attribute *a;
 	uint8_t status;
@@ -522,7 +535,7 @@ static uint16_t read_value(uint16_t handle, uint8_t *pdu, int len)
 
 	a = l->data;
 
-	status = att_check_reqs(ATT_OP_READ_REQ, a->read_reqs);
+	status = att_check_reqs(channel, ATT_OP_READ_REQ, a->read_reqs);
 	if (status)
 		return enc_error_resp(ATT_OP_READ_REQ, handle, status, pdu,
 									len);
@@ -530,8 +543,9 @@ static uint16_t read_value(uint16_t handle, uint8_t *pdu, int len)
 	return enc_read_resp(a->data, a->len, pdu, len);
 }
 
-static uint16_t write_value(uint16_t handle, const uint8_t *value, int vlen,
-							uint8_t *pdu, int len)
+static uint16_t write_value(struct gatt_channel *channel, uint16_t handle,
+						const uint8_t *value, int vlen,
+						uint8_t *pdu, int len)
 {
 	struct attribute *a;
 	uint8_t status;
@@ -546,7 +560,7 @@ static uint16_t write_value(uint16_t handle, const uint8_t *value, int vlen,
 
 	a = l->data;
 
-	status = att_check_reqs(ATT_OP_WRITE_REQ, a->write_reqs);
+	status = att_check_reqs(channel, ATT_OP_WRITE_REQ, a->write_reqs);
 	if (status)
 		return enc_error_resp(ATT_OP_WRITE_REQ, handle, status, pdu,
 									len);
@@ -595,7 +609,8 @@ static void channel_handler(const uint8_t *ipdu, uint16_t len,
 			goto done;
 		}
 
-		length = read_by_group(start, end, &uuid, opdu, channel->mtu);
+		length = read_by_group(channel, start, end, &uuid, opdu,
+								channel->mtu);
 		break;
 	case ATT_OP_READ_BY_TYPE_REQ:
 		length = dec_read_by_type_req(ipdu, len, &start, &end, &uuid);
@@ -604,7 +619,8 @@ static void channel_handler(const uint8_t *ipdu, uint16_t len,
 			goto done;
 		}
 
-		length = read_by_type(start, end, &uuid, opdu, channel->mtu);
+		length = read_by_type(channel, start, end, &uuid, opdu,
+								channel->mtu);
 		break;
 	case ATT_OP_READ_REQ:
 		length = dec_read_req(ipdu, len, &start);
@@ -613,7 +629,7 @@ static void channel_handler(const uint8_t *ipdu, uint16_t len,
 			goto done;
 		}
 
-		length = read_value(start, opdu, channel->mtu);
+		length = read_value(channel, start, opdu, channel->mtu);
 		break;
 	case ATT_OP_MTU_REQ:
 		length = dec_mtu_req(ipdu, len, &mtu);
@@ -640,12 +656,14 @@ static void channel_handler(const uint8_t *ipdu, uint16_t len,
 			goto done;
 		}
 
-		length = write_value(start, value, vlen, opdu, channel->mtu);
+		length = write_value(channel, start, value, vlen, opdu,
+								channel->mtu);
 		break;
 	case ATT_OP_WRITE_CMD:
 		length = dec_write_cmd(ipdu, len, &start, value, &vlen);
 		if (length > 0)
-			write_value(start, value, vlen, opdu, channel->mtu);
+			write_value(channel, start, value, vlen, opdu,
+								channel->mtu);
 		return;
 	case ATT_OP_FIND_BY_TYPE_REQ:
 		length = dec_find_by_type_req(ipdu, len, &start, &end,
@@ -682,6 +700,7 @@ static void connect_event(GIOChannel *io, GError *err, void *user_data)
 {
 	struct gatt_channel *channel;
 	GError *gerr = NULL;
+	int sec_level;
 
 	if (err) {
 		error("%s", err->message);
@@ -693,6 +712,7 @@ static void connect_event(GIOChannel *io, GError *err, void *user_data)
 	bt_io_get(io, BT_IO_L2CAP, &gerr,
 			BT_IO_OPT_SOURCE_BDADDR, &channel->src,
 			BT_IO_OPT_DEST_BDADDR, &channel->dst,
+			BT_IO_OPT_SEC_LEVEL, &sec_level,
 			BT_IO_OPT_INVALID);
 	if (gerr) {
 		error("bt_io_get: %s", gerr->message);
@@ -705,6 +725,9 @@ static void connect_event(GIOChannel *io, GError *err, void *user_data)
 	channel->attrib = g_attrib_new(io);
 	channel->mtu = ATT_DEFAULT_MTU;
 
+	/* FIXME: the security level needs to checked on every request. */
+	channel->encrypted = sec_level > BT_IO_SEC_LOW;
+
 	channel->id = g_attrib_register(channel->attrib, GATTRIB_ALL_EVENTS,
 				channel_handler, channel, NULL);
 
-- 
1.7.0.4


^ permalink raw reply related

* [PATCH 2/3] Check attribute permissions in attribute server
From: Anderson Lizardo @ 2010-12-03 18:26 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Bruna Moreira
In-Reply-To: <1291400782-24736-1-git-send-email-anderson.lizardo@openbossa.org>

From: Bruna Moreira <bruna.moreira@openbossa.org>

The attribute server must verify if the operation (read/write) is
permitted before running the request, and send "Read Not Permitted" or
"Write Not Permitted" error response to client if appropriate.
---
 TODO                |    7 -----
 src/attrib-server.c |   68 ++++++++++++++++++++++++++++++++++++++++++++++----
 2 files changed, 62 insertions(+), 13 deletions(-)

diff --git a/TODO b/TODO
index 49a9e76..32d3a61 100644
--- a/TODO
+++ b/TODO
@@ -136,13 +136,6 @@ ATT/GATT
   Priority: Low
   Complexity: C2
 
-- Attribute server shall implement attribute permission verification,
-  returning an error code if necessary. See Volume 3, Part F, 3.2.5
-  for more information.
-
-  Priority: Low
-  Complexity: C2
-
 - Implement Client Characteristic Configuration support in the attribute
   server to manage indications and notications. This is a per client attribute
   to control how the client wants to receive reports of changes in a given
diff --git a/src/attrib-server.c b/src/attrib-server.c
index 410ac98..2ba21e9 100644
--- a/src/attrib-server.c
+++ b/src/attrib-server.c
@@ -138,6 +138,28 @@ static sdp_record_t *server_record_new(void)
 	return record;
 }
 
+static uint8_t att_check_reqs(uint8_t opcode, int reqs)
+{
+	switch (opcode) {
+	case ATT_OP_READ_BY_GROUP_REQ:
+	case ATT_OP_READ_BY_TYPE_REQ:
+	case ATT_OP_READ_REQ:
+	case ATT_OP_READ_BLOB_REQ:
+	case ATT_OP_READ_MULTI_REQ:
+		if (reqs == ATT_NOT_PERMITTED)
+			return ATT_ECODE_READ_NOT_PERM;
+		break;
+	case ATT_OP_PREP_WRITE_REQ:
+	case ATT_OP_WRITE_REQ:
+	case ATT_OP_WRITE_CMD:
+		if (reqs == ATT_NOT_PERMITTED)
+			return ATT_ECODE_WRITE_NOT_PERM;
+		break;
+	}
+
+	return 0;
+}
+
 static uint16_t read_by_group(uint16_t start, uint16_t end, uuid_t *uuid,
 							uint8_t *pdu, int len)
 {
@@ -146,6 +168,7 @@ static uint16_t read_by_group(uint16_t start, uint16_t end, uuid_t *uuid,
 	struct group_elem *cur, *old = NULL;
 	GSList *l, *groups;
 	uint16_t length, last_handle, last_size = 0;
+	uint8_t status;
 	int i;
 
 	if (start > end || start == 0x0000)
@@ -189,6 +212,14 @@ static uint16_t read_by_group(uint16_t start, uint16_t end, uuid_t *uuid,
 		if (last_size && (last_size != a->len))
 			break;
 
+		status = att_check_reqs(ATT_OP_READ_BY_GROUP_REQ, a->read_reqs);
+		if (status) {
+			g_slist_foreach(groups, (GFunc) g_free, NULL);
+			g_slist_free(groups);
+			return enc_error_resp(ATT_OP_READ_BY_GROUP_REQ,
+						a->handle, status, pdu, len);
+		}
+
 		cur = g_new0(struct group_elem, 1);
 		cur->handle = a->handle;
 		cur->data = a->data;
@@ -247,6 +278,7 @@ static uint16_t read_by_type(uint16_t start, uint16_t end, uuid_t *uuid,
 	GSList *l, *types;
 	struct attribute *a;
 	uint16_t num, length;
+	uint8_t status;
 	int i;
 
 	if (start > end || start == 0x0000)
@@ -265,6 +297,13 @@ static uint16_t read_by_type(uint16_t start, uint16_t end, uuid_t *uuid,
 		if (sdp_uuid_cmp(&a->uuid, uuid)  != 0)
 			continue;
 
+		status = att_check_reqs(ATT_OP_READ_BY_TYPE_REQ, a->read_reqs);
+		if (status) {
+			g_slist_free(types);
+			return enc_error_resp(ATT_OP_READ_BY_TYPE_REQ,
+						a->handle, status, pdu, len);
+		}
+
 		/* All elements must have the same length */
 		if (length == 0)
 			length = a->len;
@@ -472,6 +511,7 @@ static int attribute_cmp(gconstpointer a1, gconstpointer a2)
 static uint16_t read_value(uint16_t handle, uint8_t *pdu, int len)
 {
 	struct attribute *a;
+	uint8_t status;
 	GSList *l;
 	guint h = handle;
 
@@ -482,23 +522,41 @@ static uint16_t read_value(uint16_t handle, uint8_t *pdu, int len)
 
 	a = l->data;
 
+	status = att_check_reqs(ATT_OP_READ_REQ, a->read_reqs);
+	if (status)
+		return enc_error_resp(ATT_OP_READ_REQ, handle, status, pdu,
+									len);
+
 	return enc_read_resp(a->data, a->len, pdu, len);
 }
 
-static void write_value(uint16_t handle, const uint8_t *value, int vlen)
+static uint16_t write_value(uint16_t handle, const uint8_t *value, int vlen,
+							uint8_t *pdu, int len)
 {
 	struct attribute *a;
+	uint8_t status;
 	GSList *l;
 	guint h = handle;
 	uuid_t uuid;
 
 	l = g_slist_find_custom(database, GUINT_TO_POINTER(h), handle_cmp);
 	if (!l)
-		return;
+		return enc_error_resp(ATT_OP_WRITE_REQ, handle,
+				ATT_ECODE_INVALID_HANDLE, pdu, len);
 
 	a = l->data;
+
+	status = att_check_reqs(ATT_OP_WRITE_REQ, a->write_reqs);
+	if (status)
+		return enc_error_resp(ATT_OP_WRITE_REQ, handle, status, pdu,
+									len);
+
 	memcpy(&uuid, &a->uuid, sizeof(uuid_t));
 	attrib_db_update(handle, &uuid, value, vlen);
+
+	pdu[0] = ATT_OP_WRITE_RESP;
+
+	return sizeof(pdu[0]);
 }
 
 static uint16_t mtu_exchange(struct gatt_channel *channel, uint16_t mtu,
@@ -582,14 +640,12 @@ static void channel_handler(const uint8_t *ipdu, uint16_t len,
 			goto done;
 		}
 
-		write_value(start, value, vlen);
-		opdu[0] = ATT_OP_WRITE_RESP;
-		length = sizeof(opdu[0]);
+		length = write_value(start, value, vlen, opdu, channel->mtu);
 		break;
 	case ATT_OP_WRITE_CMD:
 		length = dec_write_cmd(ipdu, len, &start, value, &vlen);
 		if (length > 0)
-			write_value(start, value, vlen);
+			write_value(start, value, vlen, opdu, channel->mtu);
 		return;
 	case ATT_OP_FIND_BY_TYPE_REQ:
 		length = dec_find_by_type_req(ipdu, len, &start, &end,
-- 
1.7.0.4


^ permalink raw reply related

* [PATCH 1/3] Initial attribute permission implementation
From: Anderson Lizardo @ 2010-12-03 18:26 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Bruna Moreira
In-Reply-To: <1291400782-24736-1-git-send-email-anderson.lizardo@openbossa.org>

From: Bruna Moreira <bruna.moreira@openbossa.org>

Add enums for attribute read/write requirements, which may be "none",
"authentication required" or "authorization required". Additionally, a
"not permitted" requirement means that operation is not permitted,
allowing read-only or write-only attributes.

The attrib_db_add() API was changed to allow setting these requirements,
and the example server was changed to set requirements for its
attributes.
---
 attrib/att.h        |   10 ++++++
 attrib/example.c    |   80 +++++++++++++++++++++++++-------------------------
 src/attrib-server.c |    5 ++-
 src/attrib-server.h |    3 +-
 4 files changed, 56 insertions(+), 42 deletions(-)

diff --git a/attrib/att.h b/attrib/att.h
index 7c98b4a..2c8c724 100644
--- a/attrib/att.h
+++ b/attrib/att.h
@@ -109,9 +109,19 @@
 #define ATT_MAX_MTU				256
 #define ATT_DEFAULT_MTU				23
 
+/* Requirements for read/write operations */
+enum {
+	ATT_NONE,		/* No restrictions */
+	ATT_AUTHENTICATION,	/* Authentication required */
+	ATT_AUTHORIZATION,	/* Authorization required */
+	ATT_NOT_PERMITTED,	/* Operation not permitted */
+};
+
 struct attribute {
 	uint16_t handle;
 	uuid_t uuid;
+	int read_reqs;
+	int write_reqs;
 	int len;
 	uint8_t data[0];
 };
diff --git a/attrib/example.c b/attrib/example.c
index c29e1e4..4307804 100644
--- a/attrib/example.c
+++ b/attrib/example.c
@@ -101,7 +101,7 @@ static int register_attributes(void)
 	u16 = htons(GENERIC_ACCESS_PROFILE_ID);
 	atval[0] = u16 >> 8;
 	atval[1] = u16;
-	attrib_db_add(0x0001, &uuid, atval, 2);
+	attrib_db_add(0x0001, &uuid, ATT_NONE, ATT_NOT_PERMITTED, atval, 2);
 
 	/* GAP service: device name characteristic */
 	sdp_uuid16_create(&uuid, GATT_CHARAC_UUID);
@@ -111,20 +111,20 @@ static int register_attributes(void)
 	atval[2] = 0x00;
 	atval[3] = u16 >> 8;
 	atval[4] = u16;
-	attrib_db_add(0x0004, &uuid, atval, 5);
+	attrib_db_add(0x0004, &uuid, ATT_NONE, ATT_NOT_PERMITTED, atval, 5);
 
 	/* GAP service: device name attribute */
 	sdp_uuid16_create(&uuid, GATT_CHARAC_DEVICE_NAME);
 	len = strlen(devname);
 	strncpy((char *) atval, devname, len);
-	attrib_db_add(0x0006, &uuid, atval, len);
+	attrib_db_add(0x0006, &uuid, ATT_NONE, ATT_NOT_PERMITTED, atval, len);
 
 	/* GATT service: primary service definition */
 	sdp_uuid16_create(&uuid, GATT_PRIM_SVC_UUID);
 	u16 = htons(GENERIC_ATTRIB_PROFILE_ID);
 	atval[0] = u16 >> 8;
 	atval[1] = u16;
-	attrib_db_add(0x0010, &uuid, atval, 2);
+	attrib_db_add(0x0010, &uuid, ATT_NONE, ATT_NOT_PERMITTED, atval, 2);
 
 	/* GATT service: attributes opcodes characteristic */
 	sdp_uuid16_create(&uuid, GATT_CHARAC_UUID);
@@ -134,20 +134,20 @@ static int register_attributes(void)
 	atval[2] = 0x00;
 	atval[3] = u16 >> 8;
 	atval[4] = u16;
-	attrib_db_add(0x0011, &uuid, atval, 5);
+	attrib_db_add(0x0011, &uuid, ATT_NONE, ATT_NOT_PERMITTED, atval, 5);
 
 	/* GATT service: attribute opcodes supported */
 	sdp_uuid16_create(&uuid, OPCODES_SUPPORTED_UUID);
 	atval[0] = 0xFF;
 	atval[1] = 0x01;
-	attrib_db_add(0x0012, &uuid, atval, 2);
+	attrib_db_add(0x0012, &uuid, ATT_NONE, ATT_NOT_PERMITTED, atval, 2);
 
 	/* Battery state service: primary service definition */
 	sdp_uuid16_create(&uuid, GATT_PRIM_SVC_UUID);
 	u16 = htons(BATTERY_STATE_SVC_UUID);
 	atval[0] = u16 >> 8;
 	atval[1] = u16;
-	attrib_db_add(0x0100, &uuid, atval, 2);
+	attrib_db_add(0x0100, &uuid, ATT_NONE, ATT_NOT_PERMITTED, atval, 2);
 
 	/* Battery: battery state characteristic */
 	sdp_uuid16_create(&uuid, GATT_CHARAC_UUID);
@@ -157,18 +157,18 @@ static int register_attributes(void)
 	atval[2] = 0x01;
 	atval[3] = u16 >> 8;
 	atval[4] = u16;
-	attrib_db_add(0x0106, &uuid, atval, 5);
+	attrib_db_add(0x0106, &uuid, ATT_NONE, ATT_NOT_PERMITTED, atval, 5);
 
 	/* Battery: battery state attribute */
 	sdp_uuid16_create(&uuid, BATTERY_STATE_UUID);
 	atval[0] = 0x04;
-	attrib_db_add(0x0110, &uuid, atval, 1);
+	attrib_db_add(0x0110, &uuid, ATT_NONE, ATT_NOT_PERMITTED, atval, 1);
 
 	/* Battery: Client Characteristic Configuration */
 	sdp_uuid16_create(&uuid, GATT_CLIENT_CHARAC_CFG_UUID);
 	atval[0] = 0x00;
 	atval[1] = 0x00;
-	attrib_db_add(0x0111, &uuid, atval, 2);
+	attrib_db_add(0x0111, &uuid, ATT_NONE, ATT_AUTHENTICATION, atval, 2);
 
 	timeout_id = g_timeout_add_seconds(10, change_battery_state, NULL);
 
@@ -177,7 +177,7 @@ static int register_attributes(void)
 	u16 = htons(THERM_HUMIDITY_SVC_UUID);
 	atval[0] = u16 >> 8;
 	atval[1] = u16;
-	attrib_db_add(0x0200, &uuid, atval, 2);
+	attrib_db_add(0x0200, &uuid, ATT_NONE, ATT_NOT_PERMITTED, atval, 2);
 
 	/* Thermometer: Include */
 	sdp_uuid16_create(&uuid, GATT_INCLUDE_UUID);
@@ -188,14 +188,14 @@ static int register_attributes(void)
 	atval[3] = 0x05;
 	atval[4] = u16 >> 8;
 	atval[5] = u16;
-	attrib_db_add(0x0201, &uuid, atval, 6);
+	attrib_db_add(0x0201, &uuid, ATT_NONE, ATT_NOT_PERMITTED, atval, 6);
 
 	/* Thermometer: Include */
 	atval[0] = 0x50;
 	atval[1] = 0x05;
 	atval[2] = 0x68;
 	atval[3] = 0x05;
-	attrib_db_add(0x0202, &uuid, atval, 4);
+	attrib_db_add(0x0202, &uuid, ATT_NONE, ATT_NOT_PERMITTED, atval, 4);
 
 	/* Thermometer: temperature characteristic */
 	sdp_uuid16_create(&uuid, GATT_CHARAC_UUID);
@@ -205,13 +205,13 @@ static int register_attributes(void)
 	atval[2] = 0x02;
 	atval[3] = u16 >> 8;
 	atval[4] = u16;
-	attrib_db_add(0x0203, &uuid, atval, 5);
+	attrib_db_add(0x0203, &uuid, ATT_NONE, ATT_NOT_PERMITTED, atval, 5);
 
 	/* Thermometer: temperature characteristic value */
 	sdp_uuid16_create(&uuid, TEMPERATURE_UUID);
 	atval[0] = 0x8A;
 	atval[1] = 0x02;
-	attrib_db_add(0x0204, &uuid, atval, 2);
+	attrib_db_add(0x0204, &uuid, ATT_NONE, ATT_NOT_PERMITTED, atval, 2);
 
 	/* Thermometer: temperature characteristic format */
 	sdp_uuid16_create(&uuid, GATT_CHARAC_FMT_UUID);
@@ -224,13 +224,13 @@ static int register_attributes(void)
 	u16 = htons(FMT_OUTSIDE_UUID);
 	atval[5] = u16 >> 8;
 	atval[6] = u16;
-	attrib_db_add(0x0205, &uuid, atval, 7);
+	attrib_db_add(0x0205, &uuid, ATT_NONE, ATT_NOT_PERMITTED, atval, 7);
 
 	/* Thermometer: characteristic user description */
 	sdp_uuid16_create(&uuid, GATT_CHARAC_USER_DESC_UUID);
 	len = strlen(desc_out_temp);
 	strncpy((char *) atval, desc_out_temp, len);
-	attrib_db_add(0x0206, &uuid, atval, len);
+	attrib_db_add(0x0206, &uuid, ATT_NONE, ATT_NOT_PERMITTED, atval, len);
 
 	/* Thermometer: relative humidity characteristic */
 	sdp_uuid16_create(&uuid, GATT_CHARAC_UUID);
@@ -240,12 +240,12 @@ static int register_attributes(void)
 	atval[2] = 0x02;
 	atval[3] = u16 >> 8;
 	atval[4] = u16;
-	attrib_db_add(0x0210, &uuid, atval, 5);
+	attrib_db_add(0x0210, &uuid, ATT_NONE, ATT_NOT_PERMITTED, atval, 5);
 
 	/* Thermometer: relative humidity value */
 	sdp_uuid16_create(&uuid, RELATIVE_HUMIDITY_UUID);
 	atval[0] = 0x27;
-	attrib_db_add(0x0212, &uuid, atval, 1);
+	attrib_db_add(0x0212, &uuid, ATT_NONE, ATT_NOT_PERMITTED, atval, 1);
 
 	/* Thermometer: relative humidity characteristic format */
 	sdp_uuid16_create(&uuid, GATT_CHARAC_FMT_UUID);
@@ -260,20 +260,20 @@ static int register_attributes(void)
 	u16 = htons(FMT_OUTSIDE_UUID);
 	atval[6] = u16 >> 8;
 	atval[7] = u16;
-	attrib_db_add(0x0213, &uuid, atval, 8);
+	attrib_db_add(0x0213, &uuid, ATT_NONE, ATT_NOT_PERMITTED, atval, 8);
 
 	/* Thermometer: characteristic user description */
 	sdp_uuid16_create(&uuid, GATT_CHARAC_USER_DESC_UUID);
 	len = strlen(desc_out_hum);
 	strncpy((char *) atval, desc_out_hum, len);
-	attrib_db_add(0x0214, &uuid, atval, len);
+	attrib_db_add(0x0214, &uuid, ATT_NONE, ATT_NOT_PERMITTED, atval, len);
 
 	/* Secondary Service: Manufacturer Service */
 	sdp_uuid16_create(&uuid, GATT_SND_SVC_UUID);
 	u16 = htons(MANUFACTURER_SVC_UUID);
 	atval[0] = u16 >> 8;
 	atval[1] = u16;
-	attrib_db_add(0x0500, &uuid, atval, 2);
+	attrib_db_add(0x0500, &uuid, ATT_NONE, ATT_NOT_PERMITTED, atval, 2);
 
 	/* Manufacturer name characteristic definition */
 	sdp_uuid16_create(&uuid, GATT_CHARAC_UUID);
@@ -283,13 +283,13 @@ static int register_attributes(void)
 	atval[2] = 0x05;
 	atval[3] = u16 >> 8;
 	atval[4] = u16;
-	attrib_db_add(0x0501, &uuid, atval, 5);
+	attrib_db_add(0x0501, &uuid, ATT_NONE, ATT_NOT_PERMITTED, atval, 5);
 
 	/* Manufacturer name characteristic value */
 	sdp_uuid16_create(&uuid, MANUFACTURER_NAME_UUID);
 	len = strlen(manufacturer_name1);
 	strncpy((char *) atval, manufacturer_name1, len);
-	attrib_db_add(0x0502, &uuid, atval, len);
+	attrib_db_add(0x0502, &uuid, ATT_NONE, ATT_NOT_PERMITTED, atval, len);
 
 	/* Manufacturer serial number characteristic */
 	sdp_uuid16_create(&uuid, GATT_CHARAC_UUID);
@@ -299,20 +299,20 @@ static int register_attributes(void)
 	atval[2] = 0x05;
 	atval[3] = u16 >> 8;
 	atval[4] = u16;
-	attrib_db_add(0x0503, &uuid, atval, 5);
+	attrib_db_add(0x0503, &uuid, ATT_NONE, ATT_NOT_PERMITTED, atval, 5);
 
 	/* Manufacturer serial number characteristic value */
 	sdp_uuid16_create(&uuid, MANUFACTURER_SERIAL_UUID);
 	len = strlen(serial1);
 	strncpy((char *) atval, serial1, len);
-	attrib_db_add(0x0504, &uuid, atval, len);
+	attrib_db_add(0x0504, &uuid, ATT_NONE, ATT_NOT_PERMITTED, atval, len);
 
 	/* Secondary Service: Manufacturer Service */
 	sdp_uuid16_create(&uuid, GATT_SND_SVC_UUID);
 	u16 = htons(MANUFACTURER_SVC_UUID);
 	atval[0] = u16 >> 8;
 	atval[1] = u16;
-	attrib_db_add(0x0505, &uuid, atval, 2);
+	attrib_db_add(0x0505, &uuid, ATT_NONE, ATT_NOT_PERMITTED, atval, 2);
 
 	/* Manufacturer name characteristic definition */
 	sdp_uuid16_create(&uuid, GATT_CHARAC_UUID);
@@ -322,14 +322,14 @@ static int register_attributes(void)
 	atval[2] = 0x05;
 	atval[3] = u16 >> 8;
 	atval[4] = u16;
-	attrib_db_add(0x0506, &uuid, atval, 5);
+	attrib_db_add(0x0506, &uuid, ATT_NONE, ATT_NOT_PERMITTED, atval, 5);
 
 	/* Secondary Service: Vendor Specific Service */
 	sdp_uuid16_create(&uuid, GATT_SND_SVC_UUID);
 	u16 = htons(VENDOR_SPECIFIC_SVC_UUID);
 	atval[0] = u16 >> 8;
 	atval[1] = u16;
-	attrib_db_add(0x0550, &uuid, atval, 2);
+	attrib_db_add(0x0550, &uuid, ATT_NONE, ATT_NOT_PERMITTED, atval, 2);
 
 	/* Vendor Specific Type characteristic definition */
 	sdp_uuid16_create(&uuid, GATT_CHARAC_UUID);
@@ -339,7 +339,7 @@ static int register_attributes(void)
 	atval[2] = 0x05;
 	atval[3] = u16 >> 8;
 	atval[4] = u16;
-	attrib_db_add(0x0560, &uuid, atval, 5);
+	attrib_db_add(0x0560, &uuid, ATT_NONE, ATT_NOT_PERMITTED, atval, 5);
 
 	/* Vendor Specific Type characteristic value */
 	sdp_uuid16_create(&uuid, VENDOR_SPECIFIC_TYPE_UUID);
@@ -349,13 +349,13 @@ static int register_attributes(void)
 	atval[3] = 0x64;
 	atval[4] = 0x6F;
 	atval[5] = 0x72;
-	attrib_db_add(0x0568, &uuid, atval, 6);
+	attrib_db_add(0x0568, &uuid, ATT_NONE, ATT_NOT_PERMITTED, atval, 6);
 
 	/* Manufacturer name attribute */
 	sdp_uuid16_create(&uuid, MANUFACTURER_NAME_UUID);
 	len = strlen(manufacturer_name2);
 	strncpy((char *) atval, manufacturer_name2, len);
-	attrib_db_add(0x0507, &uuid, atval, len);
+	attrib_db_add(0x0507, &uuid, ATT_NONE, ATT_NOT_PERMITTED, atval, len);
 
 	/* Characteristic: serial number */
 	sdp_uuid16_create(&uuid, GATT_CHARAC_UUID);
@@ -365,18 +365,18 @@ static int register_attributes(void)
 	atval[2] = 0x05;
 	atval[3] = u16 >> 8;
 	atval[4] = u16;
-	attrib_db_add(0x0508, &uuid, atval, 5);
+	attrib_db_add(0x0508, &uuid, ATT_NONE, ATT_NOT_PERMITTED, atval, 5);
 
 	/* Serial number characteristic value */
 	sdp_uuid16_create(&uuid, MANUFACTURER_SERIAL_UUID);
 	len = strlen(serial2);
 	strncpy((char *) atval, serial2, len);
-	attrib_db_add(0x0509, &uuid, atval, len);
+	attrib_db_add(0x0509, &uuid, ATT_NONE, ATT_NOT_PERMITTED, atval, len);
 
 	/* Weight service: primary service definition */
 	sdp_uuid16_create(&uuid, GATT_PRIM_SVC_UUID);
 	memcpy(atval, prim_weight_uuid, 16);
-	attrib_db_add(0x0680, &uuid, atval, 16);
+	attrib_db_add(0x0680, &uuid, ATT_NONE, ATT_NOT_PERMITTED, atval, 16);
 
 	/* Weight: include */
 	sdp_uuid16_create(&uuid, GATT_INCLUDE_UUID);
@@ -387,7 +387,7 @@ static int register_attributes(void)
 	atval[3] = 0x05;
 	atval[4] = u16 >> 8;
 	atval[5] = u16;
-	attrib_db_add(0x0681, &uuid, atval, 6);
+	attrib_db_add(0x0681, &uuid, ATT_NONE, ATT_NOT_PERMITTED, atval, 6);
 
 	/* Weight: characteristic */
 	sdp_uuid16_create(&uuid, GATT_CHARAC_UUID);
@@ -395,7 +395,7 @@ static int register_attributes(void)
 	atval[1] = 0x83;
 	atval[2] = 0x06;
 	memcpy(atval + 3, char_weight_uuid, 16);
-	attrib_db_add(0x0682, &uuid, atval, 19);
+	attrib_db_add(0x0682, &uuid, ATT_NONE, ATT_NOT_PERMITTED, atval, 19);
 
 	/* Weight: characteristic value */
 	sdp_uuid128_create(&uuid, char_weight_uuid);
@@ -403,7 +403,7 @@ static int register_attributes(void)
 	atval[1] = 0x55;
 	atval[2] = 0x00;
 	atval[3] = 0x00;
-	attrib_db_add(0x0683, &uuid, atval, 4);
+	attrib_db_add(0x0683, &uuid, ATT_NONE, ATT_NOT_PERMITTED, atval, 4);
 
 	/* Weight: characteristic format */
 	sdp_uuid16_create(&uuid, GATT_CHARAC_FMT_UUID);
@@ -418,13 +418,13 @@ static int register_attributes(void)
 	u16 = htons(FMT_HANGING_UUID);
 	atval[6] = u16 >> 8;
 	atval[7] = u16;
-	attrib_db_add(0x0684, &uuid, atval, 8);
+	attrib_db_add(0x0684, &uuid, ATT_NONE, ATT_NOT_PERMITTED, atval, 8);
 
 	/* Weight: characteristic user description */
 	sdp_uuid16_create(&uuid, GATT_CHARAC_USER_DESC_UUID);
 	len = strlen(desc_weight);
 	strncpy((char *) atval, desc_weight, len);
-	attrib_db_add(0x0685, &uuid, atval, len);
+	attrib_db_add(0x0685, &uuid, ATT_NONE, ATT_NOT_PERMITTED, atval, len);
 
 	return 0;
 }
diff --git a/src/attrib-server.c b/src/attrib-server.c
index 41c0ffc..410ac98 100644
--- a/src/attrib-server.c
+++ b/src/attrib-server.c
@@ -760,7 +760,8 @@ void attrib_server_exit(void)
 		remove_record_from_server(sdp_handle);
 }
 
-int attrib_db_add(uint16_t handle, uuid_t *uuid, const uint8_t *value, int len)
+int attrib_db_add(uint16_t handle, uuid_t *uuid, int read_reqs, int write_reqs,
+						const uint8_t *value, int len)
 {
 	struct attribute *a;
 
@@ -769,6 +770,8 @@ int attrib_db_add(uint16_t handle, uuid_t *uuid, const uint8_t *value, int len)
 	a = g_malloc0(sizeof(struct attribute) + len);
 	a->handle = handle;
 	memcpy(&a->uuid, uuid, sizeof(uuid_t));
+	a->read_reqs = read_reqs;
+	a->write_reqs = write_reqs;
 	a->len = len;
 	memcpy(a->data, value, len);
 
diff --git a/src/attrib-server.h b/src/attrib-server.h
index 4a0afa6..ba90ff4 100644
--- a/src/attrib-server.h
+++ b/src/attrib-server.h
@@ -25,7 +25,8 @@
 int attrib_server_init(void);
 void attrib_server_exit(void);
 
-int attrib_db_add(uint16_t handle, uuid_t *uuid, const uint8_t *value, int len);
+int attrib_db_add(uint16_t handle, uuid_t *uuid, int read_reqs, int write_reqs,
+						const uint8_t *value, int len);
 int attrib_db_update(uint16_t handle, uuid_t *uuid, const uint8_t *value,
 								int len);
 int attrib_db_del(uint16_t handle);
-- 
1.7.0.4


^ permalink raw reply related

* [PATCH v2 0/3] Basic attribute permission support
From: Anderson Lizardo @ 2010-12-03 18:26 UTC (permalink / raw)
  To: linux-bluetooth

Hi,

Changes since V1:

* Simplified permission scheme according to discussion on IRC.
* Fixed incorrect error sent by server.

This patchset adds initial support for attribute permission checks. Currently,
only access and authentication permissions are checked. Authorization
permissions require integration with the BlueZ agent, which is not implemented
yet.

There are some pending issues necessary for a minimum complete attribute
permission support (all of them are being worked on):

* The attribute client, upon receiving the "Insufficient Encryption" error,
  shall increase the security level and resend the failed request.
* The attribute server shall verify the connection permissions on each ATT
  request, and not just once on connection callback.
* On kernel side, increasing the security level (using setsockopt()) shall
  trigger SMP negotiation for a LE connection, blocking next socket I/O until
  negotiation is finished.
* On BR/EDR, link encryption is mandatory for GATT (see Vol 3, Part G, 2.4
  "Profile Fundamentals").

Albeit the above issues, we believe these patches are ready for commit.

Regards,
--
Anderson Lizardo
OpenBossa Labs - INdT
Manaus - Brazil


^ permalink raw reply

* Re: Are LE connections possible yet?
From: Claudio Takahasi @ 2010-12-03 18:07 UTC (permalink / raw)
  To: Mike Tsai; +Cc: Brian Gix, linux-bluetooth@vger.kernel.org
In-Reply-To: <35B17FE5076C7040809188FBE7913F98406D794075@SC1EXMB-MBCL.global.atheros.com>

Hi All,

On Thu, Dec 2, 2010 at 10:21 PM, Mike Tsai <Mike.Tsai@atheros.com> wrote:
> Hi Brian,
>
> -----Original Message-----
> From: linux-bluetooth-owner@vger.kernel.org [mailto:linux-bluetooth-owner@vger.kernel.org] On Behalf Of Brian Gix
> Sent: Thursday, December 02, 2010 3:46 PM
> To: linux-bluetooth@vger.kernel.org
> Subject: Are LE connections possible yet?
>
> Hi All,
>
> I am bringing up an LE capable (BR/EDR/LE) baseband, and attempting to use
> it to establish a
> GATT/ATT connection over an LE link.  However when executing the command:
>
> % ./tools/hcitool lecc 00:14:BB:55:66:77
>
> I get a very rapid failure of:
>
> "Could not create connection: Operation not permitted"
>
> The correct HCI command does not appear to be making it to the BR/EDR/LE
> baseband.
>
> It appears to be a socket issue of some sort.  I can cause this error, when
> attached to the baseband, and:
> "Could not create connection: File descriptor in bad state"
>
> if I have not yet run hciattach.
>
> Other (BR/EDR) hcitool commands work as expected, such as "hcitool scan" and
> "hcitool inq"
> [MTsai]which kernel driver you are using? It seems the kernel does not know the LE create connection OpCode?
>
>
> Brian Gix
> bgix@codeaurora.org
> Employee of Qualcomm Innovation Center, Inc.
> Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum
>
>
>
> --
> To unsubscribe from this list: send the line "unsubscribe linux-bluetooth" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
> --
> To unsubscribe from this list: send the line "unsubscribe linux-bluetooth" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
>

For hcitool lecc it is not necessary a LE "capable" kernel, hcitool
sends the HCI commands from the userspace.
Try sudo hcitool lecc ... and don't forget putting the remote on
advertising mode: $hciconfig hcix leadv

If you want to test the connections managed by the kernel use Ville's kernel:
git://git.kernel.org/pub/scm/linux/kernel/git/vtervo/bluetooth-le-2.6.git

l2test support LE connections, use -J option to pass the fixed channel 4

Regards,
Claudio

^ permalink raw reply

* Re: [PATCH] Remove automatic battery state change on attribute example
From: Claudio Takahasi @ 2010-12-03 17:05 UTC (permalink / raw)
  To: Luiz Augusto von Dentz; +Cc: linux-bluetooth
In-Reply-To: <AANLkTik7Pn3_HE9wm21CRHM9sXuDRvwTrzo7DMd2QgXp@mail.gmail.com>

Hi Luiz,

On Fri, Dec 3, 2010 at 12:01 PM, Luiz Augusto von Dentz
<luiz.dentz@gmail.com> wrote:
> Hi,
>
> On Fri, Dec 3, 2010 at 4:56 PM, Claudio Takahasi
> <claudio.takahasi@openbossa.org> wrote:
>> On Fri, Dec 3, 2010 at 11:50 AM, Claudio Takahasi
>> <claudio.takahasi@openbossa.org> wrote:
>>> Hi Luiz,
>>>
>>> On Fri, Dec 3, 2010 at 11:37 AM, Luiz Augusto von Dentz
>>> <luiz.dentz@gmail.com> wrote:
>>>> Hi,
>>>>
>>>> On Fri, Dec 3, 2010 at 4:24 PM, Claudio Takahasi
>>>> <claudio.takahasi@openbossa.org> wrote:
>>>>> Legacy code implemented to test Indication and Notification
>>>>> ---
>>>>>  attrib/example.c |   19 -------------------
>>>>>  1 files changed, 0 insertions(+), 19 deletions(-)
>>>>>
>>>>> diff --git a/attrib/example.c b/attrib/example.c
>>>>> index c29e1e4..2d5b758 100644
>>>>> --- a/attrib/example.c
>>>>> +++ b/attrib/example.c
>>>>> @@ -59,22 +59,6 @@
>>>>>  #define FMT_KILOGRAM_UUID              0xA010
>>>>>  #define FMT_HANGING_UUID               0xA011
>>>>>
>>>>> -static guint timeout_id = 0;
>>>>> -
>>>>> -static gboolean change_battery_state(gpointer user_data)
>>>>> -{
>>>>> -       static uint8_t state =  0x05;
>>>>> -       uuid_t uuid;
>>>>> -       uint8_t atval[1];
>>>>> -
>>>>> -       /* Battery state is being increased every 10 seconds. */
>>>>> -       atval[0] = state++;
>>>>> -       sdp_uuid16_create(&uuid, BATTERY_STATE_UUID);
>>>>> -       attrib_db_update(0x0110, &uuid, atval, 1);
>>>>> -
>>>>> -       return TRUE;
>>>>> -}
>>>>> -
>>>>>  static int register_attributes(void)
>>>>>  {
>>>>>        const char *devname = "Example Device";
>>>>> @@ -170,8 +154,6 @@ static int register_attributes(void)
>>>>>        atval[1] = 0x00;
>>>>>        attrib_db_add(0x0111, &uuid, atval, 2);
>>>>>
>>>>> -       timeout_id = g_timeout_add_seconds(10, change_battery_state, NULL);
>>>>> -
>>>>>        /* Thermometer: primary service definition */
>>>>>        sdp_uuid16_create(&uuid, GATT_PRIM_SVC_UUID);
>>>>>        u16 = htons(THERM_HUMIDITY_SVC_UUID);
>>>>> @@ -436,5 +418,4 @@ int server_example_init(void)
>>>>>
>>>>>  void server_example_exit(void)
>>>>>  {
>>>>> -       g_source_remove(timeout_id);
>>>>>  }
>>>>> --
>>>>> 1.7.3.2
>>>>>
>>>>> --
>>>>> To unsubscribe from this list: send the line "unsubscribe linux-bluetooth" in
>>>>> the body of a message to majordomo@vger.kernel.org
>>>>> More majordomo info at  http://vger.kernel.org/majordomo-info.html
>>>>>
>>>>
>>>> I wonder what is the relation of this code with attrib-server.c, does
>>>> this work if we don't have the attrib server enabled?
>>>>
>>>> --
>>>> Luiz Augusto von Dentz
>>>> Computer Engineer
>>>>
>>>
>>> Currently, we don't have compile option to disable the gatt server(in
>>> the core), only configuration option: "EnableAttrib" in the main.conf.
>>> The gatt server example "belongs" to the attribute plugin,
>>> --disable-attrib disables the attrib client and the attribute server
>>> example.
>>>
>>> Claudio.
>>>
>>
>> The right main.conf option is:
>> AttributeServer = false
>
> Yep, but this still enables the server example code, even with
> attribute server not enabled, which IMO sounds weird, anyway this
> example code should probably be removed at some right? So why not do
> it now?
>
>
> --
> Luiz Augusto von Dentz
> Computer Engineer
>

It is true, the attribute server can be disabled, but using
--enable-attrib, the example will add the attributes in the "database"
even it is not available.

We decided to use only one configure option and add "AttributeServer"
in the main.conf to disable the server. Now, If everyone agrees, we
can split --enable-attrib allowing to disable/enable client and server
separately.

BTW, the patch still valid.This code will not be used anymore, the
plan is to implement <<Client Characteristic Configuration>>

It will take some time to remove the example.c, the GATT profiles that
are being proposed are not using all the features that we need to test
the client side.

Claudio

^ permalink raw reply

* Re: [PATCH] Remove automatic battery state change on attribute example
From: Luiz Augusto von Dentz @ 2010-12-03 15:01 UTC (permalink / raw)
  To: Claudio Takahasi; +Cc: linux-bluetooth
In-Reply-To: <AANLkTikLm_nJv9Gr4CFGoVdW-b5MW21WgqVv128EAw+5@mail.gmail.com>

Hi,

On Fri, Dec 3, 2010 at 4:56 PM, Claudio Takahasi
<claudio.takahasi@openbossa.org> wrote:
> On Fri, Dec 3, 2010 at 11:50 AM, Claudio Takahasi
> <claudio.takahasi@openbossa.org> wrote:
>> Hi Luiz,
>>
>> On Fri, Dec 3, 2010 at 11:37 AM, Luiz Augusto von Dentz
>> <luiz.dentz@gmail.com> wrote:
>>> Hi,
>>>
>>> On Fri, Dec 3, 2010 at 4:24 PM, Claudio Takahasi
>>> <claudio.takahasi@openbossa.org> wrote:
>>>> Legacy code implemented to test Indication and Notification
>>>> ---
>>>>  attrib/example.c |   19 -------------------
>>>>  1 files changed, 0 insertions(+), 19 deletions(-)
>>>>
>>>> diff --git a/attrib/example.c b/attrib/example.c
>>>> index c29e1e4..2d5b758 100644
>>>> --- a/attrib/example.c
>>>> +++ b/attrib/example.c
>>>> @@ -59,22 +59,6 @@
>>>>  #define FMT_KILOGRAM_UUID              0xA010
>>>>  #define FMT_HANGING_UUID               0xA011
>>>>
>>>> -static guint timeout_id = 0;
>>>> -
>>>> -static gboolean change_battery_state(gpointer user_data)
>>>> -{
>>>> -       static uint8_t state =  0x05;
>>>> -       uuid_t uuid;
>>>> -       uint8_t atval[1];
>>>> -
>>>> -       /* Battery state is being increased every 10 seconds. */
>>>> -       atval[0] = state++;
>>>> -       sdp_uuid16_create(&uuid, BATTERY_STATE_UUID);
>>>> -       attrib_db_update(0x0110, &uuid, atval, 1);
>>>> -
>>>> -       return TRUE;
>>>> -}
>>>> -
>>>>  static int register_attributes(void)
>>>>  {
>>>>        const char *devname = "Example Device";
>>>> @@ -170,8 +154,6 @@ static int register_attributes(void)
>>>>        atval[1] = 0x00;
>>>>        attrib_db_add(0x0111, &uuid, atval, 2);
>>>>
>>>> -       timeout_id = g_timeout_add_seconds(10, change_battery_state, NULL);
>>>> -
>>>>        /* Thermometer: primary service definition */
>>>>        sdp_uuid16_create(&uuid, GATT_PRIM_SVC_UUID);
>>>>        u16 = htons(THERM_HUMIDITY_SVC_UUID);
>>>> @@ -436,5 +418,4 @@ int server_example_init(void)
>>>>
>>>>  void server_example_exit(void)
>>>>  {
>>>> -       g_source_remove(timeout_id);
>>>>  }
>>>> --
>>>> 1.7.3.2
>>>>
>>>> --
>>>> To unsubscribe from this list: send the line "unsubscribe linux-bluetooth" in
>>>> the body of a message to majordomo@vger.kernel.org
>>>> More majordomo info at  http://vger.kernel.org/majordomo-info.html
>>>>
>>>
>>> I wonder what is the relation of this code with attrib-server.c, does
>>> this work if we don't have the attrib server enabled?
>>>
>>> --
>>> Luiz Augusto von Dentz
>>> Computer Engineer
>>>
>>
>> Currently, we don't have compile option to disable the gatt server(in
>> the core), only configuration option: "EnableAttrib" in the main.conf.
>> The gatt server example "belongs" to the attribute plugin,
>> --disable-attrib disables the attrib client and the attribute server
>> example.
>>
>> Claudio.
>>
>
> The right main.conf option is:
> AttributeServer = false

Yep, but this still enables the server example code, even with
attribute server not enabled, which IMO sounds weird, anyway this
example code should probably be removed at some right? So why not do
it now?


-- 
Luiz Augusto von Dentz
Computer Engineer

^ permalink raw reply

* Re: [PATCH] Remove automatic battery state change on attribute example
From: Claudio Takahasi @ 2010-12-03 14:56 UTC (permalink / raw)
  To: Luiz Augusto von Dentz; +Cc: linux-bluetooth
In-Reply-To: <AANLkTi=sAP2cHNKczaaTRGhantbxY_4h_-eQuJ6wfsih@mail.gmail.com>

On Fri, Dec 3, 2010 at 11:50 AM, Claudio Takahasi
<claudio.takahasi@openbossa.org> wrote:
> Hi Luiz,
>
> On Fri, Dec 3, 2010 at 11:37 AM, Luiz Augusto von Dentz
> <luiz.dentz@gmail.com> wrote:
>> Hi,
>>
>> On Fri, Dec 3, 2010 at 4:24 PM, Claudio Takahasi
>> <claudio.takahasi@openbossa.org> wrote:
>>> Legacy code implemented to test Indication and Notification
>>> ---
>>>  attrib/example.c |   19 -------------------
>>>  1 files changed, 0 insertions(+), 19 deletions(-)
>>>
>>> diff --git a/attrib/example.c b/attrib/example.c
>>> index c29e1e4..2d5b758 100644
>>> --- a/attrib/example.c
>>> +++ b/attrib/example.c
>>> @@ -59,22 +59,6 @@
>>>  #define FMT_KILOGRAM_UUID              0xA010
>>>  #define FMT_HANGING_UUID               0xA011
>>>
>>> -static guint timeout_id = 0;
>>> -
>>> -static gboolean change_battery_state(gpointer user_data)
>>> -{
>>> -       static uint8_t state =  0x05;
>>> -       uuid_t uuid;
>>> -       uint8_t atval[1];
>>> -
>>> -       /* Battery state is being increased every 10 seconds. */
>>> -       atval[0] = state++;
>>> -       sdp_uuid16_create(&uuid, BATTERY_STATE_UUID);
>>> -       attrib_db_update(0x0110, &uuid, atval, 1);
>>> -
>>> -       return TRUE;
>>> -}
>>> -
>>>  static int register_attributes(void)
>>>  {
>>>        const char *devname = "Example Device";
>>> @@ -170,8 +154,6 @@ static int register_attributes(void)
>>>        atval[1] = 0x00;
>>>        attrib_db_add(0x0111, &uuid, atval, 2);
>>>
>>> -       timeout_id = g_timeout_add_seconds(10, change_battery_state, NULL);
>>> -
>>>        /* Thermometer: primary service definition */
>>>        sdp_uuid16_create(&uuid, GATT_PRIM_SVC_UUID);
>>>        u16 = htons(THERM_HUMIDITY_SVC_UUID);
>>> @@ -436,5 +418,4 @@ int server_example_init(void)
>>>
>>>  void server_example_exit(void)
>>>  {
>>> -       g_source_remove(timeout_id);
>>>  }
>>> --
>>> 1.7.3.2
>>>
>>> --
>>> To unsubscribe from this list: send the line "unsubscribe linux-bluetooth" in
>>> the body of a message to majordomo@vger.kernel.org
>>> More majordomo info at  http://vger.kernel.org/majordomo-info.html
>>>
>>
>> I wonder what is the relation of this code with attrib-server.c, does
>> this work if we don't have the attrib server enabled?
>>
>> --
>> Luiz Augusto von Dentz
>> Computer Engineer
>>
>
> Currently, we don't have compile option to disable the gatt server(in
> the core), only configuration option: "EnableAttrib" in the main.conf.
> The gatt server example "belongs" to the attribute plugin,
> --disable-attrib disables the attrib client and the attribute server
> example.
>
> Claudio.
>

The right main.conf option is:
AttributeServer = false

Claudio

^ permalink raw reply

* Re: [PATCH] Remove automatic battery state change on attribute example
From: Claudio Takahasi @ 2010-12-03 14:50 UTC (permalink / raw)
  To: Luiz Augusto von Dentz; +Cc: linux-bluetooth
In-Reply-To: <AANLkTikrFvKHQ9zcxiK_hA7L1cr8ooBUJgu2GHa8yBEP@mail.gmail.com>

Hi Luiz,

On Fri, Dec 3, 2010 at 11:37 AM, Luiz Augusto von Dentz
<luiz.dentz@gmail.com> wrote:
> Hi,
>
> On Fri, Dec 3, 2010 at 4:24 PM, Claudio Takahasi
> <claudio.takahasi@openbossa.org> wrote:
>> Legacy code implemented to test Indication and Notification
>> ---
>>  attrib/example.c |   19 -------------------
>>  1 files changed, 0 insertions(+), 19 deletions(-)
>>
>> diff --git a/attrib/example.c b/attrib/example.c
>> index c29e1e4..2d5b758 100644
>> --- a/attrib/example.c
>> +++ b/attrib/example.c
>> @@ -59,22 +59,6 @@
>>  #define FMT_KILOGRAM_UUID              0xA010
>>  #define FMT_HANGING_UUID               0xA011
>>
>> -static guint timeout_id = 0;
>> -
>> -static gboolean change_battery_state(gpointer user_data)
>> -{
>> -       static uint8_t state =  0x05;
>> -       uuid_t uuid;
>> -       uint8_t atval[1];
>> -
>> -       /* Battery state is being increased every 10 seconds. */
>> -       atval[0] = state++;
>> -       sdp_uuid16_create(&uuid, BATTERY_STATE_UUID);
>> -       attrib_db_update(0x0110, &uuid, atval, 1);
>> -
>> -       return TRUE;
>> -}
>> -
>>  static int register_attributes(void)
>>  {
>>        const char *devname = "Example Device";
>> @@ -170,8 +154,6 @@ static int register_attributes(void)
>>        atval[1] = 0x00;
>>        attrib_db_add(0x0111, &uuid, atval, 2);
>>
>> -       timeout_id = g_timeout_add_seconds(10, change_battery_state, NULL);
>> -
>>        /* Thermometer: primary service definition */
>>        sdp_uuid16_create(&uuid, GATT_PRIM_SVC_UUID);
>>        u16 = htons(THERM_HUMIDITY_SVC_UUID);
>> @@ -436,5 +418,4 @@ int server_example_init(void)
>>
>>  void server_example_exit(void)
>>  {
>> -       g_source_remove(timeout_id);
>>  }
>> --
>> 1.7.3.2
>>
>> --
>> To unsubscribe from this list: send the line "unsubscribe linux-bluetooth" in
>> the body of a message to majordomo@vger.kernel.org
>> More majordomo info at  http://vger.kernel.org/majordomo-info.html
>>
>
> I wonder what is the relation of this code with attrib-server.c, does
> this work if we don't have the attrib server enabled?
>
> --
> Luiz Augusto von Dentz
> Computer Engineer
>

Currently, we don't have compile option to disable the gatt server(in
the core), only configuration option: "EnableAttrib" in the main.conf.
The gatt server example "belongs" to the attribute plugin,
--disable-attrib disables the attrib client and the attribute server
example.

Claudio.

^ permalink raw reply

* Re: [PATCH] Remove automatic battery state change on attribute example
From: Luiz Augusto von Dentz @ 2010-12-03 14:37 UTC (permalink / raw)
  To: Claudio Takahasi; +Cc: linux-bluetooth
In-Reply-To: <1291386290-2521-1-git-send-email-claudio.takahasi@openbossa.org>

Hi,

On Fri, Dec 3, 2010 at 4:24 PM, Claudio Takahasi
<claudio.takahasi@openbossa.org> wrote:
> Legacy code implemented to test Indication and Notification
> ---
>  attrib/example.c |   19 -------------------
>  1 files changed, 0 insertions(+), 19 deletions(-)
>
> diff --git a/attrib/example.c b/attrib/example.c
> index c29e1e4..2d5b758 100644
> --- a/attrib/example.c
> +++ b/attrib/example.c
> @@ -59,22 +59,6 @@
>  #define FMT_KILOGRAM_UUID              0xA010
>  #define FMT_HANGING_UUID               0xA011
>
> -static guint timeout_id = 0;
> -
> -static gboolean change_battery_state(gpointer user_data)
> -{
> -       static uint8_t state =  0x05;
> -       uuid_t uuid;
> -       uint8_t atval[1];
> -
> -       /* Battery state is being increased every 10 seconds. */
> -       atval[0] = state++;
> -       sdp_uuid16_create(&uuid, BATTERY_STATE_UUID);
> -       attrib_db_update(0x0110, &uuid, atval, 1);
> -
> -       return TRUE;
> -}
> -
>  static int register_attributes(void)
>  {
>        const char *devname = "Example Device";
> @@ -170,8 +154,6 @@ static int register_attributes(void)
>        atval[1] = 0x00;
>        attrib_db_add(0x0111, &uuid, atval, 2);
>
> -       timeout_id = g_timeout_add_seconds(10, change_battery_state, NULL);
> -
>        /* Thermometer: primary service definition */
>        sdp_uuid16_create(&uuid, GATT_PRIM_SVC_UUID);
>        u16 = htons(THERM_HUMIDITY_SVC_UUID);
> @@ -436,5 +418,4 @@ int server_example_init(void)
>
>  void server_example_exit(void)
>  {
> -       g_source_remove(timeout_id);
>  }
> --
> 1.7.3.2
>
> --
> To unsubscribe from this list: send the line "unsubscribe linux-bluetooth" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
>

I wonder what is the relation of this code with attrib-server.c, does
this work if we don't have the attrib server enabled?

-- 
Luiz Augusto von Dentz
Computer Engineer

^ permalink raw reply

* [PATCH 5/5] Make bt_name2class static on glib-helper
From: Claudio Takahasi @ 2010-12-03 14:28 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Claudio Takahasi
In-Reply-To: <1291386532-4985-1-git-send-email-claudio.takahasi@openbossa.org>

---
 src/glib-helper.c |    6 +++---
 src/glib-helper.h |    1 -
 2 files changed, 3 insertions(+), 4 deletions(-)

diff --git a/src/glib-helper.c b/src/glib-helper.c
index 2db307e..9871c5b 100644
--- a/src/glib-helper.c
+++ b/src/glib-helper.c
@@ -586,7 +586,7 @@ static struct {
 	{ }
 };
 
-uint16_t bt_name2class(const char *pattern)
+static uint16_t name2class(const char *pattern)
 {
 	int i;
 
@@ -636,7 +636,7 @@ char *bt_name2string(const char *pattern)
 		return g_strdup(pattern);
 
 	/* Friendly service name format */
-	uuid16 = bt_name2class(pattern);
+	uuid16 = name2class(pattern);
 	if (uuid16)
 		goto proceed;
 
@@ -683,7 +683,7 @@ int bt_string2uuid(uuid_t *uuid, const char *string)
 
 		return 0;
 	} else {
-		uint16_t class = bt_name2class(string);
+		uint16_t class = name2class(string);
 		if (class) {
 			sdp_uuid16_create(uuid, class);
 			return 0;
diff --git a/src/glib-helper.h b/src/glib-helper.h
index 018ff92..5bb20a6 100644
--- a/src/glib-helper.h
+++ b/src/glib-helper.h
@@ -38,7 +38,6 @@ int bt_discover_primary(const bdaddr_t *src, const bdaddr_t *dst, int psm,
 					bt_destroy_t destroy);
 
 gchar *bt_uuid2string(uuid_t *uuid);
-uint16_t bt_name2class(const char *string);
 char *bt_name2string(const char *string);
 int bt_string2uuid(uuid_t *uuid, const char *string);
 gchar *bt_list2string(GSList *list);
-- 
1.7.3.2


^ permalink raw reply related

* [PATCH 4/5] glib-helper: fix coding style issues
From: Claudio Takahasi @ 2010-12-03 14:28 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Claudio Takahasi
In-Reply-To: <1291386532-4985-1-git-send-email-claudio.takahasi@openbossa.org>

---
 src/glib-helper.c |   14 +++++++-------
 1 files changed, 7 insertions(+), 7 deletions(-)

diff --git a/src/glib-helper.c b/src/glib-helper.c
index e71841b..2db307e 100644
--- a/src/glib-helper.c
+++ b/src/glib-helper.c
@@ -115,7 +115,7 @@ static sdp_session_t *get_sdp_session(const bdaddr_t *src, const bdaddr_t *dst)
 }
 
 static void cache_sdp_session(bdaddr_t *src, bdaddr_t *dst,
-				sdp_session_t *session)
+						sdp_session_t *session)
 {
 	struct cached_sdp_session *cached;
 
@@ -210,8 +210,8 @@ done:
 	search_context_cleanup(ctxt);
 }
 
-static gboolean search_process_cb(GIOChannel *chan,
-			GIOCondition cond, void *user_data)
+static gboolean search_process_cb(GIOChannel *chan, GIOCondition cond,
+							gpointer user_data)
 {
 	struct search_context *ctxt = user_data;
 	int err = 0;
@@ -240,7 +240,8 @@ failed:
 	return FALSE;
 }
 
-static gboolean connect_watch(GIOChannel *chan, GIOCondition cond, gpointer user_data)
+static gboolean connect_watch(GIOChannel *chan, GIOCondition cond,
+							gpointer user_data)
 {
 	struct search_context *ctxt = user_data;
 	sdp_list_t *search, *attrids;
@@ -297,8 +298,7 @@ failed:
 }
 
 static int create_search_context(struct search_context **ctxt,
-				const bdaddr_t *src, const bdaddr_t *dst,
-				uuid_t *uuid)
+			const bdaddr_t *src, const bdaddr_t *dst, uuid_t *uuid)
 {
 	sdp_session_t *s;
 	GIOChannel *chan;
@@ -363,7 +363,7 @@ int bt_discover_services(const bdaddr_t *src, const bdaddr_t *dst,
 	return bt_search_service(src, dst, &uuid, cb, user_data, destroy);
 }
 
-static int find_by_bdaddr(const void *data, const void *user_data)
+static gint find_by_bdaddr(gconstpointer data, gconstpointer user_data)
 {
 	const struct search_context *ctxt = data, *search = user_data;
 
-- 
1.7.3.2


^ permalink raw reply related

* [PATCH 3/5] Make EIR type an optional argument for bt_extract_eir_name
From: Claudio Takahasi @ 2010-12-03 14:28 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Claudio Takahasi
In-Reply-To: <1291386532-4985-1-git-send-email-claudio.takahasi@openbossa.org>

---
 src/adapter.c     |    4 ++--
 src/glib-helper.c |    5 +++--
 2 files changed, 5 insertions(+), 4 deletions(-)

diff --git a/src/adapter.c b/src/adapter.c
index 04ffd2b..03ae1e9 100644
--- a/src/adapter.c
+++ b/src/adapter.c
@@ -3135,8 +3135,8 @@ void adapter_update_device_from_info(struct btd_adapter *adapter,
 						(GCompareFunc) dev_rssi_cmp);
 
 	if (info->length) {
-		uint8_t type, flags;
-		char *tmp_name = bt_extract_eir_name(info->data, &type);
+		uint8_t flags;
+		char *tmp_name = bt_extract_eir_name(info->data, NULL);
 		if (tmp_name) {
 			g_free(dev->name);
 			dev->name = tmp_name;
diff --git a/src/glib-helper.c b/src/glib-helper.c
index 927fb7c..e71841b 100644
--- a/src/glib-helper.c
+++ b/src/glib-helper.c
@@ -744,9 +744,10 @@ char *bt_extract_eir_name(uint8_t *data, uint8_t *type)
 	if (data[0] == 0)
 		return NULL;
 
-	*type = data[1];
+	if (type)
+		*type = data[1];
 
-	switch (*type) {
+	switch (data[1]) {
 	case EIR_NAME_SHORT:
 	case EIR_NAME_COMPLETE:
 		if (!g_utf8_validate((char *) (data + 2), data[0] - 1, NULL))
-- 
1.7.3.2


^ permalink raw reply related

* [PATCH 2/5] Check if the remote LE is connectable when creating a device
From: Claudio Takahasi @ 2010-12-03 14:28 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Claudio Takahasi
In-Reply-To: <1291386532-4985-1-git-send-email-claudio.takahasi@openbossa.org>

Before issue Discover All Primary Service the advertising event type
needs to be evaluated to avoid connection attempts to non-connectable
devices. For non-connectable devices CreateDevice the remote object
instance is created however no Services/UUIDs will be exposed.
---
 src/adapter.c |   29 ++++++++++++++++++++++++++++-
 src/adapter.h |    2 +-
 2 files changed, 29 insertions(+), 2 deletions(-)

diff --git a/src/adapter.c b/src/adapter.c
index 4d21d95..04ffd2b 100644
--- a/src/adapter.c
+++ b/src/adapter.c
@@ -56,6 +56,9 @@
 #include "agent.h"
 #include "storage.h"
 
+#define ADV_TYPE_IND		0x00
+#define ADV_TYPE_DIRECT_IND	0x01
+
 #define IO_CAPABILITY_DISPLAYONLY	0x00
 #define IO_CAPABILITY_DISPLAYYESNO	0x01
 #define IO_CAPABILITY_KEYBOARDONLY	0x02
@@ -1734,6 +1737,19 @@ static DBusMessage *create_device(DBusConnection *conn,
 	if (!device)
 		return NULL;
 
+	if (type == LE_TYPE && !dev->connectable) {
+		/* Device is not connectable */
+		const char *path = device_get_path(device);
+		DBusMessage *reply;
+
+		reply = dbus_message_new_method_return(msg);
+
+		dbus_message_append_args(reply, DBUS_TYPE_OBJECT_PATH, &path,
+					DBUS_TYPE_INVALID);
+
+		return reply;
+	}
+
 	err = device_browse(device, conn, msg, NULL, FALSE);
 	if (err < 0)
 		return failed_strerror(msg, -err);
@@ -3082,6 +3098,17 @@ static gboolean extract_eir_flags(uint8_t *flags, uint8_t *eir_data)
 	return TRUE;
 }
 
+static gboolean connectable_event(uint8_t type)
+{
+	switch (type) {
+	case ADV_TYPE_IND:
+	case ADV_TYPE_DIRECT_IND:
+		return TRUE;
+	default:
+		return FALSE;
+	}
+}
+
 void adapter_update_device_from_info(struct btd_adapter *adapter,
 						le_advertising_info *info)
 {
@@ -3097,8 +3124,8 @@ void adapter_update_device_from_info(struct btd_adapter *adapter,
 
 	if (new_dev) {
 		dev->le = TRUE;
-		dev->evt_type = info->evt_type;
 		dev->type = LE_TYPE;
+		dev->connectable = connectable_event(info->evt_type);
 	} else if (dev->rssi == rssi)
 		return;
 
diff --git a/src/adapter.h b/src/adapter.h
index feeb9c9..2c09546 100644
--- a/src/adapter.h
+++ b/src/adapter.h
@@ -74,7 +74,7 @@ struct remote_dev_info {
 	char **uuids;
 	size_t uuid_count;
 	GSList *services;
-	uint8_t evt_type;
+	gboolean connectable;
 	uint8_t bdaddr_type;
 };
 
-- 
1.7.3.2


^ permalink raw reply related

* [PATCH 1/5] Add device type to identify LE, BR/EDR or dual mode devices
From: Claudio Takahasi @ 2010-12-03 14:28 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Claudio Takahasi

If EIR Flags field is sent in the advertising data, it can be used
to detect the operation mode. If the remote device is dual mode,
GAP operation mode defines that it shall follow the connectable
mode for BR/EDR and non-connectable mode for LE. This patch forces
service discovery protocol prior to Discover All Primary Services.
---
 src/adapter.c |   41 ++++++++++++++++++++++++++++++-----------
 src/adapter.h |    4 ++--
 src/device.c  |   10 +++++-----
 src/device.h  |    8 +++++++-
 4 files changed, 44 insertions(+), 19 deletions(-)

diff --git a/src/adapter.c b/src/adapter.c
index 62afc0c..4d21d95 100644
--- a/src/adapter.c
+++ b/src/adapter.c
@@ -1198,14 +1198,14 @@ sdp_list_t *adapter_get_services(struct btd_adapter *adapter)
 
 struct btd_device *adapter_create_device(DBusConnection *conn,
 					struct btd_adapter *adapter,
-					const char *address, gboolean le)
+					const char *address, uint8_t type)
 {
 	struct btd_device *device;
 	const char *path;
 
 	DBG("%s", address);
 
-	device = device_create(conn, adapter, address, le);
+	device = device_create(conn, adapter, address, type);
 	if (!device)
 		return NULL;
 
@@ -1686,6 +1686,19 @@ static DBusMessage *cancel_device_creation(DBusConnection *conn,
 	return dbus_message_new_method_return(msg);
 }
 
+static uint8_t flags2type(uint8_t flags)
+{
+	/* Inferring the remote type based on the EIR Flags field */
+
+	if (flags & EIR_SIM_CONTROLLER && flags & EIR_SIM_HOST)
+		return DUALMODE_TYPE;
+
+	if (flags & (EIR_BREDR_UNSUP | EIR_LIM_DISC | EIR_GEN_DISC))
+		return LE_TYPE;
+
+	return UNKNOWN_TYPE;
+}
+
 static DBusMessage *create_device(DBusConnection *conn,
 					DBusMessage *msg, void *data)
 {
@@ -1693,8 +1706,8 @@ static DBusMessage *create_device(DBusConnection *conn,
 	struct btd_device *device;
 	struct remote_dev_info *dev, match;
 	const gchar *address;
-	gboolean le;
 	int err;
+	uint8_t type;
 
 	if (dbus_message_get_args(msg, NULL, DBUS_TYPE_STRING, &address,
 						DBUS_TYPE_INVALID) == FALSE)
@@ -1715,9 +1728,9 @@ static DBusMessage *create_device(DBusConnection *conn,
 	match.name_status = NAME_ANY;
 
 	dev = adapter_search_found_devices(adapter, &match);
-	le  = dev ? dev->le : FALSE;
+	type = dev ? dev->type : BREDR_TYPE;
 
-	device = adapter_create_device(conn, adapter, address, le);
+	device = adapter_create_device(conn, adapter, address, type);
 	if (!device)
 		return NULL;
 
@@ -3054,16 +3067,19 @@ static struct remote_dev_info *get_found_dev(struct btd_adapter *adapter,
 	return dev;
 }
 
-static uint8_t extract_eir_flags(uint8_t *eir_data)
+static gboolean extract_eir_flags(uint8_t *flags, uint8_t *eir_data)
 {
 	if (eir_data[0] == 0)
-		return 0;
+		return FALSE;
 
 	if (eir_data[1] != EIR_FLAGS)
-		return 0;
+		return FALSE;
 
 	/* For now, only one octet is used for flags */
-	return eir_data[2];
+	if (flags)
+		*flags = eir_data[2];
+
+	return TRUE;
 }
 
 void adapter_update_device_from_info(struct btd_adapter *adapter,
@@ -3082,6 +3098,7 @@ void adapter_update_device_from_info(struct btd_adapter *adapter,
 	if (new_dev) {
 		dev->le = TRUE;
 		dev->evt_type = info->evt_type;
+		dev->type = LE_TYPE;
 	} else if (dev->rssi == rssi)
 		return;
 
@@ -3091,14 +3108,15 @@ void adapter_update_device_from_info(struct btd_adapter *adapter,
 						(GCompareFunc) dev_rssi_cmp);
 
 	if (info->length) {
-		uint8_t type;
+		uint8_t type, flags;
 		char *tmp_name = bt_extract_eir_name(info->data, &type);
 		if (tmp_name) {
 			g_free(dev->name);
 			dev->name = tmp_name;
 		}
 
-		dev->flags = extract_eir_flags(info->data);
+		if (extract_eir_flags(info->data, &flags))
+			dev->type = flags2type(flags);
 	}
 
 	/* FIXME: check if other information was changed before emitting the
@@ -3124,6 +3142,7 @@ void adapter_update_found_devices(struct btd_adapter *adapter, bdaddr_t *bdaddr,
 			dev->alias = g_strdup(alias);
 
 		dev->le = FALSE;
+		dev->type = BREDR_TYPE;
 		dev->class = class;
 		dev->legacy = legacy;
 		dev->name_status = name_status;
diff --git a/src/adapter.h b/src/adapter.h
index b189b27..feeb9c9 100644
--- a/src/adapter.h
+++ b/src/adapter.h
@@ -70,12 +70,12 @@ struct remote_dev_info {
 	dbus_bool_t legacy;
 	name_status_t name_status;
 	gboolean le;
+	uint8_t type;
 	char **uuids;
 	size_t uuid_count;
 	GSList *services;
 	uint8_t evt_type;
 	uint8_t bdaddr_type;
-	uint8_t flags;
 };
 
 struct hci_dev {
@@ -110,7 +110,7 @@ void adapter_remove_device(DBusConnection *conn, struct btd_adapter *adapter,
 						gboolean remove_storage);
 struct btd_device *adapter_create_device(DBusConnection *conn,
 					struct btd_adapter *adapter,
-					const char *address, gboolean le);
+					const char *address, uint8_t type);
 
 int adapter_resolve_names(struct btd_adapter *adapter);
 
diff --git a/src/device.c b/src/device.c
index 5326e3f..6f80635 100644
--- a/src/device.c
+++ b/src/device.c
@@ -107,7 +107,7 @@ struct browse_req {
 
 struct btd_device {
 	bdaddr_t	bdaddr;
-	gboolean	le;
+	uint8_t		type;
 	gchar		*path;
 	char		name[MAX_NAME_LENGTH + 1];
 	char		*alias;
@@ -212,7 +212,7 @@ static void browse_request_cancel(struct browse_req *req)
 
 	adapter_get_address(adapter, &src);
 
-	if (device->le == FALSE)
+	if (device->type != LE_TYPE)
 		bt_cancel_discovery(&src, &device->bdaddr);
 
 	device->browse = NULL;
@@ -965,7 +965,7 @@ void device_set_secmode3_conn(struct btd_device *device, gboolean enable)
 
 struct btd_device *device_create(DBusConnection *conn,
 					struct btd_adapter *adapter,
-					const gchar *address, gboolean le)
+					const gchar *address, uint8_t type)
 {
 	gchar *address_up;
 	struct btd_device *device;
@@ -993,7 +993,7 @@ struct btd_device *device_create(DBusConnection *conn,
 
 	str2ba(address, &device->bdaddr);
 	device->adapter = adapter;
-	device->le = le;
+	device->type = type;
 	adapter_get_address(adapter, &src);
 	ba2str(&src, srcaddr);
 	read_device_name(srcaddr, address, device->name);
@@ -1656,7 +1656,7 @@ int device_browse(struct btd_device *device, DBusConnection *conn,
 	if (device->browse)
 		return -EBUSY;
 
-	if (device->le)
+	if (device->type == LE_TYPE)
 		req = browse_primary(device, &err);
 	else
 		req = browse_sdp(device, search, reverse, &err);
diff --git a/src/device.h b/src/device.h
index a5b6273..cfb82bd 100644
--- a/src/device.h
+++ b/src/device.h
@@ -34,9 +34,15 @@ typedef enum {
 	AUTH_TYPE_AUTO,
 } auth_type_t;
 
+/* Operation modes for BR/EDR/LE */
+#define UNKNOWN_TYPE		0x00
+#define BREDR_TYPE		0x01
+#define LE_TYPE			0x02
+#define DUALMODE_TYPE		0x03
+
 struct btd_device *device_create(DBusConnection *conn,
 					struct btd_adapter *adapter,
-					const gchar *address, gboolean le);
+					const gchar *address, uint8_t type);
 void device_set_name(struct btd_device *device, const char *name);
 void device_get_name(struct btd_device *device, char *name, size_t len);
 void device_remove(struct btd_device *device, gboolean remove_stored);
-- 
1.7.3.2


^ permalink raw reply related

* [PATCH] Remove automatic battery state change on attribute example
From: Claudio Takahasi @ 2010-12-03 14:24 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Claudio Takahasi

Legacy code implemented to test Indication and Notification
---
 attrib/example.c |   19 -------------------
 1 files changed, 0 insertions(+), 19 deletions(-)

diff --git a/attrib/example.c b/attrib/example.c
index c29e1e4..2d5b758 100644
--- a/attrib/example.c
+++ b/attrib/example.c
@@ -59,22 +59,6 @@
 #define FMT_KILOGRAM_UUID		0xA010
 #define FMT_HANGING_UUID		0xA011
 
-static guint timeout_id = 0;
-
-static gboolean change_battery_state(gpointer user_data)
-{
-	static uint8_t state =  0x05;
-	uuid_t uuid;
-	uint8_t atval[1];
-
-	/* Battery state is being increased every 10 seconds. */
-	atval[0] = state++;
-	sdp_uuid16_create(&uuid, BATTERY_STATE_UUID);
-	attrib_db_update(0x0110, &uuid, atval, 1);
-
-	return TRUE;
-}
-
 static int register_attributes(void)
 {
 	const char *devname = "Example Device";
@@ -170,8 +154,6 @@ static int register_attributes(void)
 	atval[1] = 0x00;
 	attrib_db_add(0x0111, &uuid, atval, 2);
 
-	timeout_id = g_timeout_add_seconds(10, change_battery_state, NULL);
-
 	/* Thermometer: primary service definition */
 	sdp_uuid16_create(&uuid, GATT_PRIM_SVC_UUID);
 	u16 = htons(THERM_HUMIDITY_SVC_UUID);
@@ -436,5 +418,4 @@ int server_example_init(void)
 
 void server_example_exit(void)
 {
-	g_source_remove(timeout_id);
 }
-- 
1.7.3.2


^ permalink raw reply related

* Re: [PATCH 5/9] mfd: Add UART support for the ST-Ericsson CG2900.
From: Vitaly Wool @ 2010-12-03 11:42 UTC (permalink / raw)
  To: Par-Gunnar Hjalmdahl
  Cc: Alan Cox, linus.walleij, linux-bluetooth, linux-kernel,
	Arnd Bergmann, Marcel Holtmann
In-Reply-To: <AANLkTimiyxiKzT=9pKXLFACkc6C=nTD2dtBR7PcgjhOL@mail.gmail.com>

Hi Par,

On Fri, Dec 3, 2010 at 10:16 AM, Par-Gunnar Hjalmdahl
<pghatwork@gmail.com> wrote:
> 2010/10/29 Alan Cox <alan@lxorguk.ukuu.org.uk>:

> By the way, I will soon release a new patch set for CG2900 (hopefully
> next week), which contains major rework. It's hard to explain
> everything here and now but changes include:
> =A0- Reuse of existing HCI line discipline under /drivers/bluetooth/.
> Line discipline has been modified so it is selectable from protocol if
> line discipline should register to Bluetooth stack or not.

So is it true that if there's the other chip with similar
functionality I have to implement support for, I'll have to pretty
much duplicate your line discipline driver?

Isn't it better to have a new line discipline that the standard
drivers (H4, LL, ...) will be applicable to?

~Vitaly

^ permalink raw reply

* Re: [PATCH] ath3k: reduce memory usage
From: Bala Shanmugam @ 2010-12-03 10:51 UTC (permalink / raw)
  To: Alexander Holler
  Cc: Gustavo F. Padovan, SongXing Xu, Luis Rodriguez, Vikram Kandukuri,
	linux-bluetooth@vger.kernel.org
In-Reply-To: <4CF4BAE6.1080502@ahsoftware.de>

On 11/30/2010 2:20 PM, Alexander Holler wrote:
> Hello,
>
> Am 30.11.2010 02:52, schrieb Gustavo F. Padovan:
>>> -	if ((usb_control_msg(data->udev, pipe,
>>> +	send_buf = kmalloc(BULK_SIZE, GFP_ATOMIC);
>>> +	if (!send_buf) {
>>> +		BT_ERR("Can't allocate memory chunk for firmware");
>>> +		return -ENOMEM;
>>> +	}
>>> +
>>> +	memcpy(send_buf, firmware->data, 20);
>>> +	if ((err = usb_control_msg(udev, pipe,
>>>    				USB_REQ_DFU_DNLOAD,
>>>    				USB_TYPE_VENDOR, 0, 0,
>>> -				firmware, 20, USB_CTRL_SET_TIMEOUT))<   0) {
>>> +				send_buf, 20, USB_CTRL_SET_TIMEOUT))<   0) {
>>>    		BT_ERR("Can't change to loading configuration err");
>>> -		return -EBUSY;
>>> +		goto error;
>>>    	}
>>>    	sent += 20;
>>>    	count -= 20;
>> Patch looks good to me,  but I have a question here: what's 20 here? I
>> didn't figured out.
> I don't know. I assume it's a stub which has to be send before the real
> firmware. It already was there and I haven't touched that.
>
> Regards,
>
> Alexander
> --
> To unsubscribe from this list: send the line "unsubscribe linux-bluetooth" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
The first 20 bytes contain information about the binary like binary 
length, crc,
jump address etc.,

I manually made these changes and its not working.
I am unable to apply Alex patch taken from my office id.
Alex can you send the patch to btlinuxmail@gmail.com.

Regards,
BAla.

^ permalink raw reply


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