Linux bluetooth development
 help / color / mirror / Atom feed
* [PATCH v2 6/6] Add parsing for ATT Execute Write command
From: Andre Dieb Martins @ 2011-03-30 14:01 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: andre.dieb
In-Reply-To: <1301493694-10957-1-git-send-email-andre.dieb@signove.com>

BT's Core V4.0 document is buggy regarding Execute Write Response, so we'll
leave it out until a proper description is given.
---
 parser/att.c |   16 ++++++++++++++++
 1 files changed, 16 insertions(+), 0 deletions(-)

diff --git a/parser/att.c b/parser/att.c
index 7046357..a6f42df 100644
--- a/parser/att.c
+++ b/parser/att.c
@@ -523,6 +523,19 @@ static void att_prep_write_dump(int level, struct frame *frm)
 	printf("\n");
 }
 
+static void att_exec_write_req_dump(int level, struct frame *frm)
+{
+	uint8_t flags = get_u8(frm);
+
+	p_indent(level, frm);
+	if (flags == 0x00)
+		printf("cancel all prepared writes ");
+	else
+		printf("immediatelly write all pending prepared values ");
+
+	printf("(0x%2.2x)\n", flags);
+}
+
 static void att_handle_notify_dump(int level, struct frame *frm)
 {
 	uint16_t handle = btohs(htons(get_u16(frm)));
@@ -607,6 +620,9 @@ void att_dump(int level, struct frame *frm)
 		case ATT_OP_PREP_WRITE_RESP:
 			att_prep_write_dump(level + 1, frm);
 			break;
+		case ATT_OP_EXEC_WRITE_REQ:
+			att_exec_write_req_dump(level + 1, frm);
+			break;
 		case ATT_OP_HANDLE_NOTIFY:
 			att_handle_notify_dump(level + 1, frm);
 			break;
-- 
1.7.1


^ permalink raw reply related

* [PATCH v2 5/6] Add parsing for ATT Prepare Write
From: Andre Dieb Martins @ 2011-03-30 14:01 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: andre.dieb
In-Reply-To: <1301493694-10957-1-git-send-email-andre.dieb@signove.com>

---
 parser/att.c |   20 ++++++++++++++++++++
 1 files changed, 20 insertions(+), 0 deletions(-)

diff --git a/parser/att.c b/parser/att.c
index a1cd9af..7046357 100644
--- a/parser/att.c
+++ b/parser/att.c
@@ -507,6 +507,22 @@ static void att_signed_write_dump(int level, struct frame *frm)
 	printf("\n");
 }
 
+static void att_prep_write_dump(int level, struct frame *frm)
+{
+	uint16_t handle = btohs(htons(get_u16(frm)));
+	uint16_t val_offset = btohs(htons(get_u16(frm)));
+
+	p_indent(level, frm);
+	printf("attr handle 0x%4.4x, value offset 0x%4.4x\n", handle,
+								val_offset);
+
+	p_indent(level, frm);
+	printf("part attr value ");
+	while (frm->len > 0)
+		printf(" 0x%2.2x", get_u8(frm));
+	printf("\n");
+}
+
 static void att_handle_notify_dump(int level, struct frame *frm)
 {
 	uint16_t handle = btohs(htons(get_u16(frm)));
@@ -587,6 +603,10 @@ void att_dump(int level, struct frame *frm)
 		case ATT_OP_SIGNED_WRITE_CMD:
 			att_signed_write_dump(level + 1, frm);
 			break;
+		case ATT_OP_PREP_WRITE_REQ:
+		case ATT_OP_PREP_WRITE_RESP:
+			att_prep_write_dump(level + 1, frm);
+			break;
 		case ATT_OP_HANDLE_NOTIFY:
 			att_handle_notify_dump(level + 1, frm);
 			break;
-- 
1.7.1


^ permalink raw reply related

* [PATCH v2 4/6] Fix handle formatting for ATT Handle Notify
From: Andre Dieb Martins @ 2011-03-30 14:01 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: andre.dieb
In-Reply-To: <1301493694-10957-1-git-send-email-andre.dieb@signove.com>

---
 parser/att.c |    2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)

diff --git a/parser/att.c b/parser/att.c
index 5bff925..a1cd9af 100644
--- a/parser/att.c
+++ b/parser/att.c
@@ -512,7 +512,7 @@ static void att_handle_notify_dump(int level, struct frame *frm)
 	uint16_t handle = btohs(htons(get_u16(frm)));
 
 	p_indent(level, frm);
-	printf("handle 0x%2.2x\n", handle);
+	printf("handle 0x%4.4x\n", handle);
 
 	p_indent(level, frm);
 	printf("value ");
-- 
1.7.1


^ permalink raw reply related

* [PATCH v2 3/6] Add parsing for ATT Signed Write
From: Andre Dieb Martins @ 2011-03-30 14:01 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: andre.dieb
In-Reply-To: <1301493694-10957-1-git-send-email-andre.dieb@signove.com>

---
 parser/att.c |   22 ++++++++++++++++++++++
 1 files changed, 22 insertions(+), 0 deletions(-)

diff --git a/parser/att.c b/parser/att.c
index 595c984..5bff925 100644
--- a/parser/att.c
+++ b/parser/att.c
@@ -488,6 +488,25 @@ static void att_write_req_dump(int level, struct frame *frm)
 	printf("\n");
 }
 
+static void att_signed_write_dump(int level, struct frame *frm)
+{
+	uint16_t handle = btohs(htons(get_u16(frm)));
+	int value_len = frm->len - 12; /* handle:2 already accounted, sig: 12 */
+
+	p_indent(level, frm);
+	printf("handle 0x%4.4x value ", handle);
+
+	while (value_len--)
+		printf(" 0x%2.2x", get_u8(frm));
+	printf("\n");
+
+	p_indent(level, frm);
+	printf("auth signature ");
+	while (frm->len > 0)
+		printf(" 0x%2.2x", get_u8(frm));
+	printf("\n");
+}
+
 static void att_handle_notify_dump(int level, struct frame *frm)
 {
 	uint16_t handle = btohs(htons(get_u16(frm)));
@@ -565,6 +584,9 @@ void att_dump(int level, struct frame *frm)
 		case ATT_OP_WRITE_CMD:
 			att_write_req_dump(level + 1, frm);
 			break;
+		case ATT_OP_SIGNED_WRITE_CMD:
+			att_signed_write_dump(level + 1, frm);
+			break;
 		case ATT_OP_HANDLE_NOTIFY:
 			att_handle_notify_dump(level + 1, frm);
 			break;
-- 
1.7.1


^ permalink raw reply related

* [PATCH v2 2/6] Add parsing for ATT Write Command
From: Andre Dieb Martins @ 2011-03-30 14:01 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: andre.dieb
In-Reply-To: <1301493694-10957-1-git-send-email-andre.dieb@signove.com>

---
 parser/att.c |    1 +
 1 files changed, 1 insertions(+), 0 deletions(-)

diff --git a/parser/att.c b/parser/att.c
index 3804206..595c984 100644
--- a/parser/att.c
+++ b/parser/att.c
@@ -562,6 +562,7 @@ void att_dump(int level, struct frame *frm)
 			att_read_by_group_resp_dump(level + 1, frm);
 			break;
 		case ATT_OP_WRITE_REQ:
+		case ATT_OP_WRITE_CMD:
 			att_write_req_dump(level + 1, frm);
 			break;
 		case ATT_OP_HANDLE_NOTIFY:
-- 
1.7.1


^ permalink raw reply related

* [PATCH v2 1/6] Add parsing for ATT Write Request
From: Andre Dieb Martins @ 2011-03-30 14:01 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: andre.dieb

Note we do not need extra parsing for ATT Write Response as it only has one
field (opcode).
---
 parser/att.c |   15 +++++++++++++++
 1 files changed, 15 insertions(+), 0 deletions(-)

diff --git a/parser/att.c b/parser/att.c
index 7b8b83c..3804206 100644
--- a/parser/att.c
+++ b/parser/att.c
@@ -476,6 +476,18 @@ static void att_read_by_group_resp_dump(int level, struct frame *frm)
 	}
 }
 
+static void att_write_req_dump(int level, struct frame *frm)
+{
+	uint16_t handle = btohs(htons(get_u16(frm)));
+
+	p_indent(level, frm);
+	printf("handle 0x%4.4x value ", handle);
+
+	while (frm->len > 0)
+		printf(" 0x%2.2x", get_u8(frm));
+	printf("\n");
+}
+
 static void att_handle_notify_dump(int level, struct frame *frm)
 {
 	uint16_t handle = btohs(htons(get_u16(frm)));
@@ -549,6 +561,9 @@ void att_dump(int level, struct frame *frm)
 		case ATT_OP_READ_BY_GROUP_RESP:
 			att_read_by_group_resp_dump(level + 1, frm);
 			break;
+		case ATT_OP_WRITE_REQ:
+			att_write_req_dump(level + 1, frm);
+			break;
 		case ATT_OP_HANDLE_NOTIFY:
 			att_handle_notify_dump(level + 1, frm);
 			break;
-- 
1.7.1


^ permalink raw reply related

* Re: [PATCH 2/2] Bluetooth: Add mgmt_remote_name event
From: Johan Hedberg @ 2011-03-30 14:00 UTC (permalink / raw)
  To: Anderson Lizardo; +Cc: linux-bluetooth
In-Reply-To: <AANLkTi=BZhjKvCBon7qhS0tCPkABmv7to39UhoaQE1a8@mail.gmail.com>

Hi,

On Wed, Mar 30, 2011, Anderson Lizardo wrote:
> > This patch adds a new remote_name event to the Management interface
> > which is sent every time the name of a remote device is resolved (over
> > BR/EDR).
> 
> Just wondering if we could ever reuse this for LE. For LE (and GATT
> over BR/EDR ?), I believe the "remote device name resolution" is done
> by looking at the GAP "Device Name" characteristic after a service
> discovery (see spec page 1739).
> 
> The advertising data may contain the "full" device name as well, but
> it is not mandatory to include it. GAP Device Name OTOH is mandatory.

I suppose it can't be reused for LE. Btw, this event will *not* be sent
for advertising data or extended inquiry response data containing a
remote name. User space is expected to do that extraction from the data
(which comes in the mgmt_device_found event).

Johan

^ permalink raw reply

* Re: [PATCH 2/2] Bluetooth: Add mgmt_remote_name event
From: Anderson Lizardo @ 2011-03-30 13:51 UTC (permalink / raw)
  To: johan.hedberg; +Cc: linux-bluetooth
In-Reply-To: <1301480292-25370-2-git-send-email-johan.hedberg@gmail.com>

Hi Johan,

On Wed, Mar 30, 2011 at 6:18 AM,  <johan.hedberg@gmail.com> wrote:
> From: Johan Hedberg <johan.hedberg@nokia.com>
>
> This patch adds a new remote_name event to the Management interface
> which is sent every time the name of a remote device is resolved (over
> BR/EDR).

Just wondering if we could ever reuse this for LE. For LE (and GATT
over BR/EDR ?), I believe the "remote device name resolution" is done
by looking at the GAP "Device Name" characteristic after a service
discovery (see spec page 1739).

The advertising data may contain the "full" device name as well, but
it is not mandatory to include it. GAP Device Name OTOH is mandatory.

Regards,
-- 
Anderson Lizardo
Instituto Nokia de Tecnologia - INdT
Manaus - Brazil

^ permalink raw reply

* [PATCH] Fix crash when acquiring a2dp stream
From: Luiz Augusto von Dentz @ 2011-03-30 12:32 UTC (permalink / raw)
  To: linux-bluetooth

From: Luiz Augusto von Dentz <luiz.dentz-von@nokia.com>

Disconnecting l2cap before getting a response for avdtp start cause a
crash while we try to abort it:

avdtp_sep_set_state (session=0x9c210, sep=0x9ada0, state=AVDTP_STATE_IDLE)
0x000256dc in connection_lost (session=0x9c210, err=-5)
0x00025d44 in cancel_request (session=0x9c210, err=-5)
0x00026a98 in avdtp_abort (session=0x9c210, stream=0x9bee8)
0x00020e74 in a2dp_cancel (dev=<value optimized out>, id=<value optimized out>)
0x0002d5b4 in acquire_request_free (req=0x9b1a0)
0x0002d638 in media_owner_remove (owner=0x9a4a0)
0x0002da94 in media_transport_free (data=<value optimized out>)
0x000115a0 in remove_interface (data=0xa1f88, name=<value optimized out>)
0x0002e2a0 in media_transport_remove (transport=0x8fad8)
0x0002c624 in media_endpoint_clear_configuration (endpoint=0x9b098)
0x000260c8 in avdtp_sep_set_state (session=0x9c210, sep=0x9ada0, state=AVDTP_STATE_IDLE)

To fix this callbacks are called after handling the state change, so
any pending request are properly removed before state is set to idle.
---
 audio/avdtp.c     |   14 ++++++++------
 audio/transport.c |   12 +-----------
 2 files changed, 9 insertions(+), 17 deletions(-)

diff --git a/audio/avdtp.c b/audio/avdtp.c
index 83b1aa2..23281ac 100644
--- a/audio/avdtp.c
+++ b/audio/avdtp.c
@@ -1050,11 +1050,6 @@ static void avdtp_sep_set_state(struct avdtp *session,
 	old_state = sep->state;
 	sep->state = state;
 
-	for (l = stream->callbacks; l != NULL; l = g_slist_next(l)) {
-		struct stream_callback *cb = l->data;
-		cb->cb(stream, old_state, state, err_ptr, cb->user_data);
-	}
-
 	switch (state) {
 	case AVDTP_STATE_CONFIGURED:
 		if (sep->info.type == AVDTP_SEP_TYPE_SINK)
@@ -1086,11 +1081,18 @@ static void avdtp_sep_set_state(struct avdtp *session,
 			handle_unanswered_req(session, stream);
 		/* Remove pending commands for this stream from the queue */
 		cleanup_queue(session, stream);
-		stream_free(stream);
 		break;
 	default:
 		break;
 	}
+
+	for (l = stream->callbacks; l != NULL; l = g_slist_next(l)) {
+		struct stream_callback *cb = l->data;
+		cb->cb(stream, old_state, state, err_ptr, cb->user_data);
+	}
+
+	if (state == AVDTP_STATE_IDLE)
+		stream_free(stream);
 }
 
 static void finalize_discovery(struct avdtp *session, int err)
diff --git a/audio/transport.c b/audio/transport.c
index 8ff6c85..aa3308d 100644
--- a/audio/transport.c
+++ b/audio/transport.c
@@ -224,15 +224,6 @@ static gboolean media_transport_set_fd(struct media_transport *transport,
 	return TRUE;
 }
 
-static gboolean remove_owner(gpointer data)
-{
-	struct media_owner *owner = data;
-
-	media_transport_remove(owner->transport, owner);
-
-	return FALSE;
-}
-
 static void a2dp_resume_complete(struct avdtp *session,
 				struct avdtp_error *err, void *user_data)
 {
@@ -279,8 +270,7 @@ static void a2dp_resume_complete(struct avdtp *session,
 	return;
 
 fail:
-	/* Let the stream state change before removing the owner */
-	g_idle_add(remove_owner, owner);
+	media_transport_remove(transport, owner);
 }
 
 static guint resume_a2dp(struct media_transport *transport,
-- 
1.7.1


^ permalink raw reply related

* Re: [PATCH 1/2] Bluetooth: Add mgmt_device_found event
From: Anderson Lizardo @ 2011-03-30 12:30 UTC (permalink / raw)
  To: johan.hedberg; +Cc: linux-bluetooth
In-Reply-To: <1301480292-25370-1-git-send-email-johan.hedberg@gmail.com>

Hi Johan,

On Wed, Mar 30, 2011 at 6:18 AM,  <johan.hedberg@gmail.com> wrote:
> +int mgmt_device_found(u16 index, bdaddr_t *bdaddr, u8 *dev_class, s8 rssi,
> +                                                               u8 *eir)
> +{
> +       struct mgmt_ev_device_found ev;
> +
> +       memset(&ev, 0, sizeof(ev));
> +
> +       bacpy(&ev.bdaddr, bdaddr);
> +       memcpy(ev.dev_class, dev_class, 3);

What about "sizeof(ev.dev_class)" instead of 3 ?

> +       ev.rssi = rssi;
> +
> +       if (eir)
> +               memcpy(ev.eir, eir, HCI_MAX_EIR_LENGTH);

This could be "sizeof(ev.eir)" as well, although it is already clear
by the #define.

> +
> +       return mgmt_event(MGMT_EV_DEVICE_FOUND, index, &ev, sizeof(ev), NULL);
> +}

Regards,
-- 
Anderson Lizardo
Instituto Nokia de Tecnologia - INdT
Manaus - Brazil

^ permalink raw reply

* [PATCH 2/2] Bluetooth: Add mgmt_remote_name event
From: johan.hedberg @ 2011-03-30 10:18 UTC (permalink / raw)
  To: linux-bluetooth
In-Reply-To: <1301480292-25370-1-git-send-email-johan.hedberg@gmail.com>

From: Johan Hedberg <johan.hedberg@nokia.com>

This patch adds a new remote_name event to the Management interface
which is sent every time the name of a remote device is resolved (over
BR/EDR).

Signed-off-by: Johan Hedberg <johan.hedberg@nokia.com>
---
 include/net/bluetooth/hci_core.h |    1 +
 include/net/bluetooth/mgmt.h     |    6 ++++++
 net/bluetooth/hci_event.c        |    3 +++
 net/bluetooth/mgmt.c             |   12 ++++++++++++
 4 files changed, 22 insertions(+), 0 deletions(-)

diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h
index 2a88fc8..4093133 100644
--- a/include/net/bluetooth/hci_core.h
+++ b/include/net/bluetooth/hci_core.h
@@ -789,6 +789,7 @@ int mgmt_read_local_oob_data_reply_complete(u16 index, u8 *hash, u8 *randomizer,
 								u8 status);
 int mgmt_device_found(u16 index, bdaddr_t *bdaddr, u8 *dev_class, s8 rssi,
 								u8 *eir);
+int mgmt_remote_name(u16 index, bdaddr_t *bdaddr, u8 *name);
 
 /* HCI info for socket */
 #define hci_pi(sk) ((struct hci_pinfo *) sk)
diff --git a/include/net/bluetooth/mgmt.h b/include/net/bluetooth/mgmt.h
index 864d0cb..6b6ff92 100644
--- a/include/net/bluetooth/mgmt.h
+++ b/include/net/bluetooth/mgmt.h
@@ -275,3 +275,9 @@ struct mgmt_ev_device_found {
 	__s8 rssi;
 	__u8 eir[HCI_MAX_EIR_LENGTH];
 } __packed;
+
+#define MGMT_EV_REMOTE_NAME		0x0013
+struct mgmt_ev_remote_name {
+	bdaddr_t bdaddr;
+	__u8 name[MGMT_MAX_NAME_LENGTH];
+} __packed;
diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c
index fb78c27..8187846 100644
--- a/net/bluetooth/hci_event.c
+++ b/net/bluetooth/hci_event.c
@@ -1495,6 +1495,9 @@ static inline void hci_remote_name_evt(struct hci_dev *hdev, struct sk_buff *skb
 
 	hci_dev_lock(hdev);
 
+	if (ev->status == 0 && test_bit(HCI_MGMT, &hdev->flags))
+		mgmt_remote_name(hdev->id, &ev->bdaddr, ev->name);
+
 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
 	if (conn && hci_outgoing_auth_needed(hdev, conn)) {
 		struct hci_cp_auth_requested cp;
diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c
index 066a7f1..203b2f5 100644
--- a/net/bluetooth/mgmt.c
+++ b/net/bluetooth/mgmt.c
@@ -2061,3 +2061,15 @@ int mgmt_device_found(u16 index, bdaddr_t *bdaddr, u8 *dev_class, s8 rssi,
 
 	return mgmt_event(MGMT_EV_DEVICE_FOUND, index, &ev, sizeof(ev), NULL);
 }
+
+int mgmt_remote_name(u16 index, bdaddr_t *bdaddr, u8 *name)
+{
+	struct mgmt_ev_remote_name ev;
+
+	memset(&ev, 0, sizeof(ev));
+
+	bacpy(&ev.bdaddr, bdaddr);
+	memcpy(ev.name, name, HCI_MAX_NAME_LENGTH);
+
+	return mgmt_event(MGMT_EV_REMOTE_NAME, index, &ev, sizeof(ev), NULL);
+}
-- 
1.7.4.1


^ permalink raw reply related

* [PATCH 1/2] Bluetooth: Add mgmt_device_found event
From: johan.hedberg @ 2011-03-30 10:18 UTC (permalink / raw)
  To: linux-bluetooth

From: Johan Hedberg <johan.hedberg@nokia.com>

This patch adds a device_found event to the Management interface. For
now the event only maps to BR/EDR inquiry result HCI events, but in the
future the plan is to also use it for the LE device discovery process.

Signed-off-by: Johan Hedberg <johan.hedberg@nokia.com>
---
 include/net/bluetooth/hci_core.h |    2 ++
 include/net/bluetooth/mgmt.h     |    8 ++++++++
 net/bluetooth/hci_event.c        |   22 ++++++++++++++--------
 net/bluetooth/mgmt.c             |   17 +++++++++++++++++
 4 files changed, 41 insertions(+), 8 deletions(-)

diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h
index 3b2f09d..2a88fc8 100644
--- a/include/net/bluetooth/hci_core.h
+++ b/include/net/bluetooth/hci_core.h
@@ -787,6 +787,8 @@ int mgmt_auth_failed(u16 index, bdaddr_t *bdaddr, u8 status);
 int mgmt_set_local_name_complete(u16 index, u8 *name, u8 status);
 int mgmt_read_local_oob_data_reply_complete(u16 index, u8 *hash, u8 *randomizer,
 								u8 status);
+int mgmt_device_found(u16 index, bdaddr_t *bdaddr, u8 *dev_class, s8 rssi,
+								u8 *eir);
 
 /* HCI info for socket */
 #define hci_pi(sk) ((struct hci_pinfo *) sk)
diff --git a/include/net/bluetooth/mgmt.h b/include/net/bluetooth/mgmt.h
index 1a6283f..864d0cb 100644
--- a/include/net/bluetooth/mgmt.h
+++ b/include/net/bluetooth/mgmt.h
@@ -267,3 +267,11 @@ struct mgmt_ev_auth_failed {
 struct mgmt_ev_local_name_changed {
 	__u8 name[MGMT_MAX_NAME_LENGTH];
 } __packed;
+
+#define MGMT_EV_DEVICE_FOUND		0x0012
+struct mgmt_ev_device_found {
+	bdaddr_t bdaddr;
+	__u8 dev_class[3];
+	__s8 rssi;
+	__u8 eir[HCI_MAX_EIR_LENGTH];
+} __packed;
diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c
index da4c662..fb78c27 100644
--- a/net/bluetooth/hci_event.c
+++ b/net/bluetooth/hci_event.c
@@ -1226,7 +1226,7 @@ static inline void hci_inquiry_result_evt(struct hci_dev *hdev, struct sk_buff *
 
 	hci_dev_lock(hdev);
 
-	for (; num_rsp; num_rsp--) {
+	for (; num_rsp; num_rsp--, info++) {
 		bacpy(&data.bdaddr, &info->bdaddr);
 		data.pscan_rep_mode	= info->pscan_rep_mode;
 		data.pscan_period_mode	= info->pscan_period_mode;
@@ -1235,8 +1235,9 @@ static inline void hci_inquiry_result_evt(struct hci_dev *hdev, struct sk_buff *
 		data.clock_offset	= info->clock_offset;
 		data.rssi		= 0x00;
 		data.ssp_mode		= 0x00;
-		info++;
 		hci_inquiry_cache_update(hdev, &data);
+		mgmt_device_found(hdev->id, &info->bdaddr, info->dev_class, 0,
+									NULL);
 	}
 
 	hci_dev_unlock(hdev);
@@ -2156,7 +2157,7 @@ static inline void hci_inquiry_result_with_rssi_evt(struct hci_dev *hdev, struct
 		struct inquiry_info_with_rssi_and_pscan_mode *info;
 		info = (void *) (skb->data + 1);
 
-		for (; num_rsp; num_rsp--) {
+		for (; num_rsp; num_rsp--, info++) {
 			bacpy(&data.bdaddr, &info->bdaddr);
 			data.pscan_rep_mode	= info->pscan_rep_mode;
 			data.pscan_period_mode	= info->pscan_period_mode;
@@ -2165,13 +2166,15 @@ static inline void hci_inquiry_result_with_rssi_evt(struct hci_dev *hdev, struct
 			data.clock_offset	= info->clock_offset;
 			data.rssi		= info->rssi;
 			data.ssp_mode		= 0x00;
-			info++;
 			hci_inquiry_cache_update(hdev, &data);
+			mgmt_device_found(hdev->id, &info->bdaddr,
+						info->dev_class, info->rssi,
+						NULL);
 		}
 	} else {
 		struct inquiry_info_with_rssi *info = (void *) (skb->data + 1);
 
-		for (; num_rsp; num_rsp--) {
+		for (; num_rsp; num_rsp--, info++) {
 			bacpy(&data.bdaddr, &info->bdaddr);
 			data.pscan_rep_mode	= info->pscan_rep_mode;
 			data.pscan_period_mode	= info->pscan_period_mode;
@@ -2180,8 +2183,10 @@ static inline void hci_inquiry_result_with_rssi_evt(struct hci_dev *hdev, struct
 			data.clock_offset	= info->clock_offset;
 			data.rssi		= info->rssi;
 			data.ssp_mode		= 0x00;
-			info++;
 			hci_inquiry_cache_update(hdev, &data);
+			mgmt_device_found(hdev->id, &info->bdaddr,
+						info->dev_class, info->rssi,
+						NULL);
 		}
 	}
 
@@ -2312,7 +2317,7 @@ static inline void hci_extended_inquiry_result_evt(struct hci_dev *hdev, struct
 
 	hci_dev_lock(hdev);
 
-	for (; num_rsp; num_rsp--) {
+	for (; num_rsp; num_rsp--, info++) {
 		bacpy(&data.bdaddr, &info->bdaddr);
 		data.pscan_rep_mode	= info->pscan_rep_mode;
 		data.pscan_period_mode	= info->pscan_period_mode;
@@ -2321,8 +2326,9 @@ static inline void hci_extended_inquiry_result_evt(struct hci_dev *hdev, struct
 		data.clock_offset	= info->clock_offset;
 		data.rssi		= info->rssi;
 		data.ssp_mode		= 0x01;
-		info++;
 		hci_inquiry_cache_update(hdev, &data);
+		mgmt_device_found(hdev->id, &info->bdaddr, info->dev_class,
+						info->rssi, info->data);
 	}
 
 	hci_dev_unlock(hdev);
diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c
index 62055c9..066a7f1 100644
--- a/net/bluetooth/mgmt.c
+++ b/net/bluetooth/mgmt.c
@@ -2044,3 +2044,20 @@ int mgmt_read_local_oob_data_reply_complete(u16 index, u8 *hash, u8 *randomizer,
 
 	return err;
 }
+
+int mgmt_device_found(u16 index, bdaddr_t *bdaddr, u8 *dev_class, s8 rssi,
+								u8 *eir)
+{
+	struct mgmt_ev_device_found ev;
+
+	memset(&ev, 0, sizeof(ev));
+
+	bacpy(&ev.bdaddr, bdaddr);
+	memcpy(ev.dev_class, dev_class, 3);
+	ev.rssi = rssi;
+
+	if (eir)
+		memcpy(ev.eir, eir, HCI_MAX_EIR_LENGTH);
+
+	return mgmt_event(MGMT_EV_DEVICE_FOUND, index, &ev, sizeof(ev), NULL);
+}
-- 
1.7.4.1


^ permalink raw reply related

* Re: [PATCH v2] Bluetooth: Add local Extended Inquiry Response (EIR) support
From: Gustavo F. Padovan @ 2011-03-29 20:17 UTC (permalink / raw)
  To: johan.hedberg; +Cc: linux-bluetooth
In-Reply-To: <1301310443-13197-1-git-send-email-johan.hedberg@gmail.com>

Hi Johan,

* johan.hedberg@gmail.com <johan.hedberg@gmail.com> [2011-03-28 14:07:23 +0300]:

> From: Johan Hedberg <johan.hedberg@nokia.com>
> 
> This patch adds automated creation of the local EIR data based on what
> 16-bit UUIDs are registered and what the device name is. This should
> cover the majority use cases, however things like 32/128-bit UUIDs, TX
> power and Device ID will need to be added later to be on par with what
> bluetoothd is capable of doing (without the Management interface).
> 
> Signed-off-by: Johan Hedberg <johan.hedberg@nokia.com>
> ---
> v2: Updated to assume that the UUIDs are in little endian byte order
> like like all other data types in the management interface.
> 
>  include/net/bluetooth/hci.h      |    8 ++
>  include/net/bluetooth/hci_core.h |    1 +
>  net/bluetooth/mgmt.c             |  163 ++++++++++++++++++++++++++++++++++++++
>  3 files changed, 172 insertions(+), 0 deletions(-)

Patch has been applied. Thanks.

-- 
Gustavo F. Padovan
http://profusion.mobi

^ permalink raw reply

* [PATCH 2/2] Add constant for interleaved discovery window
From: Claudio Takahasi @ 2011-03-29 19:26 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Claudio Takahasi
In-Reply-To: <1301426790-3762-1-git-send-email-claudio.takahasi@openbossa.org>

---
 src/adapter.c |   10 +++++++---
 1 files changed, 7 insertions(+), 3 deletions(-)

diff --git a/src/adapter.c b/src/adapter.c
index 69fd5be..32ec71d 100644
--- a/src/adapter.c
+++ b/src/adapter.c
@@ -59,6 +59,9 @@
 #include "attrib-server.h"
 #include "att.h"
 
+/* Interleaved discovery window: 5.12 sec */
+#define GAP_INTER_DISCOV_WIN		5120
+
 /* Flags Descriptions */
 #define EIR_LIM_DISC                0x01 /* LE Limited Discoverable Mode */
 #define EIR_GEN_DISC                0x02 /* LE General Discoverable Mode */
@@ -2831,11 +2834,12 @@ void adapter_set_state(struct btd_adapter *adapter, int state)
 		if (!adapter->disc_sessions)
 			break;
 
-		/* Scanning enabled */
-		adapter->stop_discov_id = g_timeout_add(5120, stop_scanning,
+		/* Stop scanning after TGAP(100)/2 */
+		adapter->stop_discov_id = g_timeout_add(GAP_INTER_DISCOV_WIN,
+							stop_scanning,
 							adapter);
 
-		/* For dual mode: don't send "Discovering = TRUE"  */
+		/* For dual mode: don't send "Discovering = TRUE" (twice) */
 		if (bredr_capable(adapter) == TRUE)
 			return;
 
-- 
1.7.4.1


^ permalink raw reply related

* [PATCH 1/2] Improve the logic when emitting Discovering signal
From: Claudio Takahasi @ 2011-03-29 19:26 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Claudio Takahasi

---
 src/adapter.c |   21 ++++++++++-----------
 1 files changed, 10 insertions(+), 11 deletions(-)

diff --git a/src/adapter.c b/src/adapter.c
index 031e141..69fd5be 100644
--- a/src/adapter.c
+++ b/src/adapter.c
@@ -2826,19 +2826,18 @@ void adapter_set_state(struct btd_adapter *adapter, int state)
 			return;
 		break;
 	case STATE_LE_SCAN:
-		/* Scanning enabled */
-		if (adapter->disc_sessions) {
-			adapter->stop_discov_id = g_timeout_add(5120,
-								stop_scanning,
-								adapter);
+		discov_active = TRUE;
 
-			/* For dual mode: don't send "Discovering = TRUE"  */
-			if (bredr_capable(adapter) == TRUE)
-				return;
-		}
+		if (!adapter->disc_sessions)
+			break;
 
-		/* LE only */
-		discov_active = TRUE;
+		/* Scanning enabled */
+		adapter->stop_discov_id = g_timeout_add(5120, stop_scanning,
+							adapter);
+
+		/* For dual mode: don't send "Discovering = TRUE"  */
+		if (bredr_capable(adapter) == TRUE)
+			return;
 
 		break;
 	case STATE_IDLE:
-- 
1.7.4.1


^ permalink raw reply related

* [PATCH] Remove "authen" and "autho" short versions for ATT constants
From: Claudio Takahasi @ 2011-03-29 19:08 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Claudio Takahasi

---
 attrib/att.c        |    4 ++--
 attrib/att.h        |    4 ++--
 src/attrib-server.c |    4 ++--
 3 files changed, 6 insertions(+), 6 deletions(-)

diff --git a/attrib/att.c b/attrib/att.c
index 08000e0..972f8bf 100644
--- a/attrib/att.c
+++ b/attrib/att.c
@@ -44,13 +44,13 @@ const char *att_ecode2str(uint8_t status)
 		return "Attribute can't be written";
 	case ATT_ECODE_INVALID_PDU:
 		return "Attribute PDU was invalid";
-	case ATT_ECODE_INSUFF_AUTHEN:
+	case ATT_ECODE_AUTHENTICATION:
 		return "Attribute requires authentication before read/write";
 	case ATT_ECODE_REQ_NOT_SUPP:
 		return "Server doesn't support the request received";
 	case ATT_ECODE_INVALID_OFFSET:
 		return "Offset past the end of the attribute";
-	case ATT_ECODE_INSUFF_AUTHO:
+	case ATT_ECODE_AUTHORIZATION:
 		return "Attribute requires authorization before read/write";
 	case ATT_ECODE_PREP_QUEUE_FULL:
 		return "Too many prepare writes have been queued";
diff --git a/attrib/att.h b/attrib/att.h
index 7a83bfa..93b58dc 100644
--- a/attrib/att.h
+++ b/attrib/att.h
@@ -79,10 +79,10 @@
 #define ATT_ECODE_READ_NOT_PERM			0x02
 #define ATT_ECODE_WRITE_NOT_PERM		0x03
 #define ATT_ECODE_INVALID_PDU			0x04
-#define ATT_ECODE_INSUFF_AUTHEN			0x05
+#define ATT_ECODE_AUTHENTICATION		0x05
 #define ATT_ECODE_REQ_NOT_SUPP			0x06
 #define ATT_ECODE_INVALID_OFFSET		0x07
-#define ATT_ECODE_INSUFF_AUTHO			0x08
+#define ATT_ECODE_AUTHORIZATION			0x08
 #define ATT_ECODE_PREP_QUEUE_FULL		0x09
 #define ATT_ECODE_ATTR_NOT_FOUND		0x0A
 #define ATT_ECODE_ATTR_NOT_LONG			0x0B
diff --git a/src/attrib-server.c b/src/attrib-server.c
index c96351a..03c3501 100644
--- a/src/attrib-server.c
+++ b/src/attrib-server.c
@@ -172,9 +172,9 @@ static uint8_t att_check_reqs(struct gatt_channel *channel, uint8_t opcode,
 	if (!channel->encrypted)
 		channel->encrypted = g_attrib_is_encrypted(channel->attrib);
 	if (reqs == ATT_AUTHENTICATION && !channel->encrypted)
-		return ATT_ECODE_INSUFF_AUTHEN;
+		return ATT_ECODE_AUTHENTICATION;
 	else if (reqs == ATT_AUTHORIZATION)
-		return ATT_ECODE_INSUFF_AUTHO;
+		return ATT_ECODE_AUTHORIZATION;
 
 	switch (opcode) {
 	case ATT_OP_READ_BY_GROUP_REQ:
-- 
1.7.4.1


^ permalink raw reply related

* Re: [PATCH] Bluetooth: check L2CAP info_rsp ident and state
From: Gustavo F. Padovan @ 2011-03-29 19:06 UTC (permalink / raw)
  To: Emeltchenko Andrei; +Cc: linux-bluetooth
In-Reply-To: <1301045501-3346-1-git-send-email-Andrei.Emeltchenko.news@gmail.com>

Hi Andrei,

* Emeltchenko Andrei <Andrei.Emeltchenko.news@gmail.com> [2011-03-25 11:31:41 +0200]:

> From: Andrei Emeltchenko <andrei.emeltchenko@nokia.com>
> 
> Information requests/responses are unbound to L2CAP channel. Patch
> fixes issue arising when two devices connects at the same time to
> each other. This way we do not process out of the context messages.
> We are safe dropping info_rsp since info_timer is left running.
> 
> Signed-off-by: Andrei Emeltchenko <andrei.emeltchenko@nokia.com>

Patch has been applied. Thanks.

-- 
Gustavo F. Padovan
http://profusion.mobi

^ permalink raw reply

* BlueZ on Google Summer of Code: List of Ideas
From: Gustavo F. Padovan @ 2011-03-29 18:44 UTC (permalink / raw)
  To: linux-bluetooth

Hi Everyone,

As many of you may already know Google announced the accepted
organizations for Google Summer of Code and BlueZ[0] was accepted
again! If you a student and know nothing about it go to the Google
Summer of Code page[1] and learn about it.

We are already accepting projects proposal, check our ideas list[2] or
propose some new good idea you want to implement in BlueZ. Discuss
them with the BlueZ mentors and submit your project proposal. Our
freenode irc channel for GSoC is #bluez-gsoc.

We will be very glad to accept the best students proposals to take
part of GSoC 2011 with BlueZ.

Regards,


[0] http://www.bluez.org
[1] http://code.google.com/soc/
[2] http://www.bluez.org/development/gsoc/gsoc-ideas-list/

-- 
Gustavo F. Padovan
http://padovan.org

^ permalink raw reply

* Re: [PATCH] Remove unused variable in mgmtops plugin
From: Claudio Takahasi @ 2011-03-29 16:47 UTC (permalink / raw)
  To: Claudio Takahasi, linux-bluetooth; +Cc: Johan Hedberg
In-Reply-To: <20110329145049.GA12595@jh-x301>

Hi Johan,

On Tue, Mar 29, 2011 at 2:50 PM, Johan Hedberg <johan.hedberg@gmail.com> wrote:
> Hi Claudio,
>
> On Tue, Mar 29, 2011, Claudio Takahasi wrote:
>> ---
>>  plugins/mgmtops.c |    1 -
>>  1 files changed, 0 insertions(+), 1 deletions(-)
>>
>> diff --git a/plugins/mgmtops.c b/plugins/mgmtops.c
>> index 65b32e6..3f96017 100644
>> --- a/plugins/mgmtops.c
>> +++ b/plugins/mgmtops.c
>> @@ -1410,7 +1410,6 @@ static void mgmt_cleanup(void)
>>  {
>>       g_free(controllers);
>>       controllers = NULL;
>> -     max_index = -1;
>>
>>       if (mgmt_sock >= 0) {
>>               close(mgmt_sock);
>
> I don't understand the purpose of this patch. You're neither removing a
> variable (just removing an assignment) nor is the variable you're
> touching unused.
>
> Johan
>

No comment!
I am not working drunk! Maybe blind! ;-)

Claudio.

^ permalink raw reply

* [PATCH 3/3] Remove hard-coded handles from example GATT plugin
From: Anderson Lizardo @ 2011-03-29 16:15 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Anderson Lizardo
In-Reply-To: <1301415328-14257-1-git-send-email-anderson.lizardo@openbossa.org>

Instead of having static handles, use attrib_db_find_avail() to find
available handle ranges.

Also split the big register_attributes() into one function per service.
---
 plugins/gatt-example.c |  350 ++++++++++++++++++++++++++++++++++--------------
 1 files changed, 250 insertions(+), 100 deletions(-)

diff --git a/plugins/gatt-example.c b/plugins/gatt-example.c
index f1dfd5b..f86e76d 100644
--- a/plugins/gatt-example.c
+++ b/plugins/gatt-example.c
@@ -56,89 +56,116 @@
 
 static GSList *sdp_handles = NULL;
 
-static int register_attributes(void)
+static void register_battery_service(void)
 {
-	const char *desc_out_temp = "Outside Temperature";
-	const char *desc_out_hum = "Outside Relative Humidity";
-	const char *desc_weight = "Rucksack Weight";
-	const char *manufacturer_name1 = "ACME Temperature Sensor";
-	const char *manufacturer_name2 = "ACME Weighing Scales";
-	const char *serial1 = "237495-3282-A";
-	const char *serial2 = "11267-2327A00239";
-
-	const uint128_t char_weight_uuid_btorder = {
-		.data = { 0x80, 0x88, 0xF2, 0x18, 0x90, 0x2C, 0x45, 0x0B,
-			  0xB6, 0xC4, 0x62, 0x89, 0x1E, 0x8C, 0x25, 0xE9 } };
-	const uint128_t prim_weight_uuid_btorder = {
-		.data = { 0x4F, 0x0A, 0xC0, 0x96, 0x35, 0xD4, 0x49, 0x11,
-			  0x96, 0x31, 0xDE, 0xA8, 0xDC, 0x74, 0xEE, 0xFE } };
-
-	uint128_t char_weight_uuid;
+	uint16_t start_handle, h;
+	const int svc_size = 4;
+	uint32_t sdp_handle;
 	uint8_t atval[256];
-	uint32_t handle;
 	bt_uuid_t uuid;
-	int len;
 
-	btoh128(&char_weight_uuid_btorder, &char_weight_uuid);
+	start_handle = attrib_db_find_avail(svc_size);
+	if (start_handle == 0) {
+		error("Not enough free handles to register service");
+		return;
+	}
+
+	DBG("start_handle=0x%04x", start_handle);
+
+	h = start_handle;
 
 	/* Battery state service: primary service definition */
 	bt_uuid16_create(&uuid, GATT_PRIM_SVC_UUID);
 	att_put_u16(BATTERY_STATE_SVC_UUID, &atval[0]);
-	attrib_db_add(0x0100, &uuid, ATT_NONE, ATT_NOT_PERMITTED, atval, 2);
+	attrib_db_add(h++, &uuid, ATT_NONE, ATT_NOT_PERMITTED, atval, 2);
 
 	/* Battery: battery state characteristic */
 	bt_uuid16_create(&uuid, GATT_CHARAC_UUID);
 	atval[0] = ATT_CHAR_PROPER_READ;
-	att_put_u16(0x0110, &atval[1]);
+	att_put_u16(h + 1, &atval[1]);
 	att_put_u16(BATTERY_STATE_UUID, &atval[3]);
-	attrib_db_add(0x0106, &uuid, ATT_NONE, ATT_NOT_PERMITTED, atval, 5);
+	attrib_db_add(h++, &uuid, ATT_NONE, ATT_NOT_PERMITTED, atval, 5);
 
 	/* Battery: battery state attribute */
 	bt_uuid16_create(&uuid, BATTERY_STATE_UUID);
 	atval[0] = 0x04;
-	attrib_db_add(0x0110, &uuid, ATT_NONE, ATT_NOT_PERMITTED, atval, 1);
+	attrib_db_add(h++, &uuid, ATT_NONE, ATT_NOT_PERMITTED, atval, 1);
 
 	/* Battery: Client Characteristic Configuration */
 	bt_uuid16_create(&uuid, GATT_CLIENT_CHARAC_CFG_UUID);
 	atval[0] = 0x00;
 	atval[1] = 0x00;
-	attrib_db_add(0x0111, &uuid, ATT_NONE, ATT_AUTHENTICATION, atval, 2);
+	attrib_db_add(h++, &uuid, ATT_NONE, ATT_AUTHENTICATION, atval, 2);
+
+	g_assert(h - start_handle == svc_size);
 
 	/* Add an SDP record for the above service */
-	handle = attrib_create_sdp(0x0100, "Battery State Service");
-	if (handle)
-		sdp_handles = g_slist_prepend(sdp_handles, GUINT_TO_POINTER(handle));
+	sdp_handle = attrib_create_sdp(start_handle, "Battery State Service");
+	if (sdp_handle)
+		sdp_handles = g_slist_prepend(sdp_handles,
+						GUINT_TO_POINTER(sdp_handle));
+}
+
+static void register_termometer_service(const uint16_t manuf1[2],
+						const uint16_t manuf2[2])
+{
+	const char *desc_out_temp = "Outside Temperature";
+	const char *desc_out_hum = "Outside Relative Humidity";
+	uint16_t start_handle, h;
+	const int svc_size = 11;
+	uint32_t sdp_handle;
+	uint8_t atval[256];
+	bt_uuid_t uuid;
+	int len;
+
+	start_handle = attrib_db_find_avail(svc_size);
+	if (start_handle == 0) {
+		error("Not enough free handles to register service");
+		return;
+	}
+
+	DBG("start_handle=0x%04x manuf1=0x%04x-0x%04x, manuf2=0x%04x-0x%04x",
+		start_handle, manuf1[0], manuf1[1], manuf2[0], manuf2[1]);
+
+	h = start_handle;
 
 	/* Thermometer: primary service definition */
 	bt_uuid16_create(&uuid, GATT_PRIM_SVC_UUID);
 	att_put_u16(THERM_HUMIDITY_SVC_UUID, &atval[0]);
-	attrib_db_add(0x0200, &uuid, ATT_NONE, ATT_NOT_PERMITTED, atval, 2);
+	attrib_db_add(h++, &uuid, ATT_NONE, ATT_NOT_PERMITTED, atval, 2);
 
-	/* Thermometer: Include */
 	bt_uuid16_create(&uuid, GATT_INCLUDE_UUID);
-	att_put_u16(0x0500, &atval[0]);
-	att_put_u16(0x0504, &atval[2]);
-	att_put_u16(MANUFACTURER_SVC_UUID, &atval[4]);
-	attrib_db_add(0x0201, &uuid, ATT_NONE, ATT_NOT_PERMITTED, atval, 6);
 
 	/* Thermometer: Include */
-	att_put_u16(0x0550, &atval[0]);
-	att_put_u16(0x0568, &atval[2]);
-	att_put_u16(VENDOR_SPECIFIC_SVC_UUID, &atval[4]);
-	attrib_db_add(0x0202, &uuid, ATT_NONE, ATT_NOT_PERMITTED, atval, 6);
+	if (manuf1[0] && manuf1[1]) {
+		att_put_u16(manuf1[0], &atval[0]);
+		att_put_u16(manuf1[1], &atval[2]);
+		att_put_u16(MANUFACTURER_SVC_UUID, &atval[4]);
+		attrib_db_add(h++, &uuid, ATT_NONE, ATT_NOT_PERMITTED, atval,
+									6);
+	}
+
+	/* Thermometer: Include */
+	if (manuf2[0] && manuf2[1]) {
+		att_put_u16(manuf2[0], &atval[0]);
+		att_put_u16(manuf2[1], &atval[2]);
+		att_put_u16(VENDOR_SPECIFIC_SVC_UUID, &atval[4]);
+		attrib_db_add(h++, &uuid, ATT_NONE, ATT_NOT_PERMITTED, atval,
+									6);
+	}
 
 	/* Thermometer: temperature characteristic */
 	bt_uuid16_create(&uuid, GATT_CHARAC_UUID);
 	atval[0] = ATT_CHAR_PROPER_READ;
-	att_put_u16(0x0204, &atval[1]);
+	att_put_u16(h + 1, &atval[1]);
 	att_put_u16(TEMPERATURE_UUID, &atval[3]);
-	attrib_db_add(0x0203, &uuid, ATT_NONE, ATT_NOT_PERMITTED, atval, 5);
+	attrib_db_add(h++, &uuid, ATT_NONE, ATT_NOT_PERMITTED, atval, 5);
 
 	/* Thermometer: temperature characteristic value */
 	bt_uuid16_create(&uuid, TEMPERATURE_UUID);
 	atval[0] = 0x8A;
 	atval[1] = 0x02;
-	attrib_db_add(0x0204, &uuid, ATT_NONE, ATT_NOT_PERMITTED, atval, 2);
+	attrib_db_add(h++, &uuid, ATT_NONE, ATT_NOT_PERMITTED, atval, 2);
 
 	/* Thermometer: temperature characteristic format */
 	bt_uuid16_create(&uuid, GATT_CHARAC_FMT_UUID);
@@ -147,25 +174,25 @@ static int register_attributes(void)
 	att_put_u16(FMT_CELSIUS_UUID, &atval[2]);
 	atval[4] = 0x01;
 	att_put_u16(FMT_OUTSIDE_UUID, &atval[5]);
-	attrib_db_add(0x0205, &uuid, ATT_NONE, ATT_NOT_PERMITTED, atval, 7);
+	attrib_db_add(h++, &uuid, ATT_NONE, ATT_NOT_PERMITTED, atval, 7);
 
 	/* Thermometer: characteristic user description */
 	bt_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, ATT_NONE, ATT_NOT_PERMITTED, atval, len);
+	attrib_db_add(h++, &uuid, ATT_NONE, ATT_NOT_PERMITTED, atval, len);
 
 	/* Thermometer: relative humidity characteristic */
 	bt_uuid16_create(&uuid, GATT_CHARAC_UUID);
 	atval[0] = ATT_CHAR_PROPER_READ;
-	att_put_u16(0x0212, &atval[1]);
+	att_put_u16(h + 1, &atval[1]);
 	att_put_u16(RELATIVE_HUMIDITY_UUID, &atval[3]);
-	attrib_db_add(0x0210, &uuid, ATT_NONE, ATT_NOT_PERMITTED, atval, 5);
+	attrib_db_add(h++, &uuid, ATT_NONE, ATT_NOT_PERMITTED, atval, 5);
 
 	/* Thermometer: relative humidity value */
 	bt_uuid16_create(&uuid, RELATIVE_HUMIDITY_UUID);
 	atval[0] = 0x27;
-	attrib_db_add(0x0212, &uuid, ATT_NONE, ATT_NOT_PERMITTED, atval, 1);
+	attrib_db_add(h++, &uuid, ATT_NONE, ATT_NOT_PERMITTED, atval, 1);
 
 	/* Thermometer: relative humidity characteristic format */
 	bt_uuid16_create(&uuid, GATT_CHARAC_FMT_UUID);
@@ -174,73 +201,165 @@ static int register_attributes(void)
 	att_put_u16(FMT_PERCENT_UUID, &atval[2]);
 	att_put_u16(BLUETOOTH_SIG_UUID, &atval[4]);
 	att_put_u16(FMT_OUTSIDE_UUID, &atval[6]);
-	attrib_db_add(0x0213, &uuid, ATT_NONE, ATT_NOT_PERMITTED, atval, 8);
+	attrib_db_add(h++, &uuid, ATT_NONE, ATT_NOT_PERMITTED, atval, 8);
 
 	/* Thermometer: characteristic user description */
 	bt_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, ATT_NONE, ATT_NOT_PERMITTED, atval, len);
+	attrib_db_add(h++, &uuid, ATT_NONE, ATT_NOT_PERMITTED, atval, len);
+
+	g_assert(h - start_handle == svc_size);
 
 	/* Add an SDP record for the above service */
-	handle = attrib_create_sdp(0x0200, "Thermometer");
-	if (handle)
-		sdp_handles = g_slist_prepend(sdp_handles, GUINT_TO_POINTER(handle));
+	sdp_handle = attrib_create_sdp(start_handle, "Thermometer");
+	if (sdp_handle)
+		sdp_handles = g_slist_prepend(sdp_handles,
+						GUINT_TO_POINTER(sdp_handle));
+}
+
+static void register_manuf1_service(uint16_t range[2])
+{
+	const char *manufacturer_name1 = "ACME Temperature Sensor";
+	const char *serial1 = "237495-3282-A";
+	uint16_t start_handle, h;
+	const int svc_size = 5;
+	uint8_t atval[256];
+	bt_uuid_t uuid;
+	int len;
+
+	start_handle = attrib_db_find_avail(svc_size);
+	if (start_handle == 0) {
+		error("Not enough free handles to register service");
+		return;
+	}
+
+	DBG("start_handle=0x%04x", start_handle);
+
+	h = start_handle;
 
 	/* Secondary Service: Manufacturer Service */
 	bt_uuid16_create(&uuid, GATT_SND_SVC_UUID);
 	att_put_u16(MANUFACTURER_SVC_UUID, &atval[0]);
-	attrib_db_add(0x0500, &uuid, ATT_NONE, ATT_NOT_PERMITTED, atval, 2);
+	attrib_db_add(h++, &uuid, ATT_NONE, ATT_NOT_PERMITTED, atval, 2);
 
 	/* Manufacturer name characteristic definition */
 	bt_uuid16_create(&uuid, GATT_CHARAC_UUID);
 	atval[0] = ATT_CHAR_PROPER_READ;
-	att_put_u16(0x0502, &atval[1]);
+	att_put_u16(h + 1, &atval[1]);
 	att_put_u16(MANUFACTURER_NAME_UUID, &atval[3]);
-	attrib_db_add(0x0501, &uuid, ATT_NONE, ATT_NOT_PERMITTED, atval, 5);
+	attrib_db_add(h++, &uuid, ATT_NONE, ATT_NOT_PERMITTED, atval, 5);
 
 	/* Manufacturer name characteristic value */
 	bt_uuid16_create(&uuid, MANUFACTURER_NAME_UUID);
 	len = strlen(manufacturer_name1);
 	strncpy((char *) atval, manufacturer_name1, len);
-	attrib_db_add(0x0502, &uuid, ATT_NONE, ATT_NOT_PERMITTED, atval, len);
+	attrib_db_add(h++, &uuid, ATT_NONE, ATT_NOT_PERMITTED, atval, len);
 
 	/* Manufacturer serial number characteristic */
 	bt_uuid16_create(&uuid, GATT_CHARAC_UUID);
 	atval[0] = ATT_CHAR_PROPER_READ;
-	att_put_u16(0x0504, &atval[1]);
+	att_put_u16(h + 1, &atval[1]);
 	att_put_u16(MANUFACTURER_SERIAL_UUID, &atval[3]);
-	attrib_db_add(0x0503, &uuid, ATT_NONE, ATT_NOT_PERMITTED, atval, 5);
+	attrib_db_add(h++, &uuid, ATT_NONE, ATT_NOT_PERMITTED, atval, 5);
 
 	/* Manufacturer serial number characteristic value */
 	bt_uuid16_create(&uuid, MANUFACTURER_SERIAL_UUID);
 	len = strlen(serial1);
 	strncpy((char *) atval, serial1, len);
-	attrib_db_add(0x0504, &uuid, ATT_NONE, ATT_NOT_PERMITTED, atval, len);
+	attrib_db_add(h++, &uuid, ATT_NONE, ATT_NOT_PERMITTED, atval, len);
+
+	g_assert(h - start_handle == svc_size);
+
+	range[0] = start_handle;
+	range[1] = start_handle + svc_size - 1;
+}
+
+static void register_manuf2_service(uint16_t range[2])
+{
+	const char *manufacturer_name2 = "ACME Weighing Scales";
+	const char *serial2 = "11267-2327A00239";
+	uint16_t start_handle, h;
+	const int svc_size = 5;
+	uint8_t atval[256];
+	bt_uuid_t uuid;
+	int len;
+
+	start_handle = attrib_db_find_avail(svc_size);
+	if (start_handle == 0) {
+		error("Not enough free handles to register service");
+		return;
+	}
+
+	DBG("start_handle=0x%04x", start_handle);
+
+	h = start_handle;
 
 	/* Secondary Service: Manufacturer Service */
 	bt_uuid16_create(&uuid, GATT_SND_SVC_UUID);
 	att_put_u16(MANUFACTURER_SVC_UUID, &atval[0]);
-	attrib_db_add(0x0505, &uuid, ATT_NONE, ATT_NOT_PERMITTED, atval, 2);
+	attrib_db_add(h++, &uuid, ATT_NONE, ATT_NOT_PERMITTED, atval, 2);
 
 	/* Manufacturer name characteristic definition */
 	bt_uuid16_create(&uuid, GATT_CHARAC_UUID);
 	atval[0] = ATT_CHAR_PROPER_READ;
-	att_put_u16(0x0507, &atval[1]);
+	att_put_u16(h + 1, &atval[1]);
 	att_put_u16(MANUFACTURER_NAME_UUID, &atval[3]);
-	attrib_db_add(0x0506, &uuid, ATT_NONE, ATT_NOT_PERMITTED, atval, 5);
+	attrib_db_add(h++, &uuid, ATT_NONE, ATT_NOT_PERMITTED, atval, 5);
+
+	/* Manufacturer name attribute */
+	bt_uuid16_create(&uuid, MANUFACTURER_NAME_UUID);
+	len = strlen(manufacturer_name2);
+	strncpy((char *) atval, manufacturer_name2, len);
+	attrib_db_add(h++, &uuid, ATT_NONE, ATT_NOT_PERMITTED, atval, len);
+
+	/* Characteristic: serial number */
+	bt_uuid16_create(&uuid, GATT_CHARAC_UUID);
+	atval[0] = ATT_CHAR_PROPER_READ;
+	att_put_u16(h + 1, &atval[1]);
+	att_put_u16(MANUFACTURER_SERIAL_UUID, &atval[3]);
+	attrib_db_add(h++, &uuid, ATT_NONE, ATT_NOT_PERMITTED, atval, 5);
+
+	/* Serial number characteristic value */
+	bt_uuid16_create(&uuid, MANUFACTURER_SERIAL_UUID);
+	len = strlen(serial2);
+	strncpy((char *) atval, serial2, len);
+	attrib_db_add(h++, &uuid, ATT_NONE, ATT_NOT_PERMITTED, atval, len);
+
+	g_assert(h - start_handle == svc_size);
+
+	range[0] = start_handle;
+	range[1] = start_handle + svc_size - 1;
+}
+
+static void register_vendor_service(uint16_t range[2])
+{
+	uint16_t start_handle, h;
+	const int svc_size = 3;
+	uint8_t atval[256];
+	bt_uuid_t uuid;
+
+	start_handle = attrib_db_find_avail(svc_size);
+	if (start_handle == 0) {
+		error("Not enough free handles to register service");
+		return;
+	}
+
+	DBG("start_handle=0x%04x", start_handle);
+
+	h = start_handle;
 
 	/* Secondary Service: Vendor Specific Service */
 	bt_uuid16_create(&uuid, GATT_SND_SVC_UUID);
 	att_put_u16(VENDOR_SPECIFIC_SVC_UUID, &atval[0]);
-	attrib_db_add(0x0550, &uuid, ATT_NONE, ATT_NOT_PERMITTED, atval, 2);
+	attrib_db_add(h++, &uuid, ATT_NONE, ATT_NOT_PERMITTED, atval, 2);
 
 	/* Vendor Specific Type characteristic definition */
 	bt_uuid16_create(&uuid, GATT_CHARAC_UUID);
 	atval[0] = ATT_CHAR_PROPER_READ;
-	att_put_u16(0x0568, &atval[1]);
+	att_put_u16(h + 1, &atval[1]);
 	att_put_u16(VENDOR_SPECIFIC_TYPE_UUID, &atval[3]);
-	attrib_db_add(0x0560, &uuid, ATT_NONE, ATT_NOT_PERMITTED, atval, 5);
+	attrib_db_add(h++, &uuid, ATT_NONE, ATT_NOT_PERMITTED, atval, 5);
 
 	/* Vendor Specific Type characteristic value */
 	bt_uuid16_create(&uuid, VENDOR_SPECIFIC_TYPE_UUID);
@@ -250,45 +369,65 @@ static int register_attributes(void)
 	atval[3] = 0x64;
 	atval[4] = 0x6F;
 	atval[5] = 0x72;
-	attrib_db_add(0x0568, &uuid, ATT_NONE, ATT_NOT_PERMITTED, atval, 6);
+	attrib_db_add(h++, &uuid, ATT_NONE, ATT_NOT_PERMITTED, atval, 6);
 
-	/* Manufacturer name attribute */
-	bt_uuid16_create(&uuid, MANUFACTURER_NAME_UUID);
-	len = strlen(manufacturer_name2);
-	strncpy((char *) atval, manufacturer_name2, len);
-	attrib_db_add(0x0507, &uuid, ATT_NONE, ATT_NOT_PERMITTED, atval, len);
+	g_assert(h - start_handle == svc_size);
 
-	/* Characteristic: serial number */
-	bt_uuid16_create(&uuid, GATT_CHARAC_UUID);
-	atval[0] = ATT_CHAR_PROPER_READ;
-	att_put_u16(0x0509, &atval[1]);
-	att_put_u16(MANUFACTURER_SERIAL_UUID, &atval[3]);
-	attrib_db_add(0x0508, &uuid, ATT_NONE, ATT_NOT_PERMITTED, atval, 5);
+	range[0] = start_handle;
+	range[1] = start_handle + svc_size - 1;
+}
 
-	/* Serial number characteristic value */
-	bt_uuid16_create(&uuid, MANUFACTURER_SERIAL_UUID);
-	len = strlen(serial2);
-	strncpy((char *) atval, serial2, len);
-	attrib_db_add(0x0509, &uuid, ATT_NONE, ATT_NOT_PERMITTED, atval, len);
+static void register_weight_service(const uint16_t vendor[2])
+{
+	const char *desc_weight = "Rucksack Weight";
+	const uint128_t char_weight_uuid_btorder = {
+		.data = { 0x80, 0x88, 0xF2, 0x18, 0x90, 0x2C, 0x45, 0x0B,
+			  0xB6, 0xC4, 0x62, 0x89, 0x1E, 0x8C, 0x25, 0xE9 } };
+	const uint128_t prim_weight_uuid_btorder = {
+		.data = { 0x4F, 0x0A, 0xC0, 0x96, 0x35, 0xD4, 0x49, 0x11,
+			  0x96, 0x31, 0xDE, 0xA8, 0xDC, 0x74, 0xEE, 0xFE } };
+	uint128_t char_weight_uuid;
+	uint16_t start_handle, h;
+	const int svc_size = 6;
+	uint32_t sdp_handle;
+	uint8_t atval[256];
+	bt_uuid_t uuid;
+	int len;
+
+	btoh128(&char_weight_uuid_btorder, &char_weight_uuid);
+
+	start_handle = attrib_db_find_avail(svc_size);
+	if (start_handle == 0) {
+		error("Not enough free handles to register service");
+		return;
+	}
+
+	DBG("start_handle=0x%04x, vendor=0x%04x-0x%04x", start_handle,
+							vendor[0], vendor[1]);
+
+	h = start_handle;
 
 	/* Weight service: primary service definition */
 	bt_uuid16_create(&uuid, GATT_PRIM_SVC_UUID);
 	memcpy(atval, &prim_weight_uuid_btorder, 16);
-	attrib_db_add(0x0680, &uuid, ATT_NONE, ATT_NOT_PERMITTED, atval, 16);
-
-	/* Weight: include */
-	bt_uuid16_create(&uuid, GATT_INCLUDE_UUID);
-	att_put_u16(0x0505, &atval[0]);
-	att_put_u16(0x0509, &atval[2]);
-	att_put_u16(MANUFACTURER_SVC_UUID, &atval[4]);
-	attrib_db_add(0x0681, &uuid, ATT_NONE, ATT_NOT_PERMITTED, atval, 6);
+	attrib_db_add(h++, &uuid, ATT_NONE, ATT_NOT_PERMITTED, atval, 16);
+
+	if (vendor[0] && vendor[1]) {
+		/* Weight: include */
+		bt_uuid16_create(&uuid, GATT_INCLUDE_UUID);
+		att_put_u16(vendor[0], &atval[0]);
+		att_put_u16(vendor[1], &atval[2]);
+		att_put_u16(MANUFACTURER_SVC_UUID, &atval[4]);
+		attrib_db_add(h++, &uuid, ATT_NONE, ATT_NOT_PERMITTED, atval,
+									6);
+	}
 
 	/* Weight: characteristic */
 	bt_uuid16_create(&uuid, GATT_CHARAC_UUID);
 	atval[0] = ATT_CHAR_PROPER_READ;
-	att_put_u16(0x0683, &atval[1]);
+	att_put_u16(h + 1, &atval[1]);
 	memcpy(&atval[3], &char_weight_uuid_btorder, 16);
-	attrib_db_add(0x0682, &uuid, ATT_NONE, ATT_NOT_PERMITTED, atval, 19);
+	attrib_db_add(h++, &uuid, ATT_NONE, ATT_NOT_PERMITTED, atval, 19);
 
 	/* Weight: characteristic value */
 	bt_uuid128_create(&uuid, char_weight_uuid);
@@ -296,7 +435,7 @@ static int register_attributes(void)
 	atval[1] = 0x55;
 	atval[2] = 0x00;
 	atval[3] = 0x00;
-	attrib_db_add(0x0683, &uuid, ATT_NONE, ATT_NOT_PERMITTED, atval, 4);
+	attrib_db_add(h++, &uuid, ATT_NONE, ATT_NOT_PERMITTED, atval, 4);
 
 	/* Weight: characteristic format */
 	bt_uuid16_create(&uuid, GATT_CHARAC_FMT_UUID);
@@ -305,30 +444,41 @@ static int register_attributes(void)
 	att_put_u16(FMT_KILOGRAM_UUID, &atval[2]);
 	att_put_u16(BLUETOOTH_SIG_UUID, &atval[4]);
 	att_put_u16(FMT_HANGING_UUID, &atval[6]);
-	attrib_db_add(0x0684, &uuid, ATT_NONE, ATT_NOT_PERMITTED, atval, 8);
+	attrib_db_add(h++, &uuid, ATT_NONE, ATT_NOT_PERMITTED, atval, 8);
 
 	/* Weight: characteristic user description */
 	bt_uuid16_create(&uuid, GATT_CHARAC_USER_DESC_UUID);
 	len = strlen(desc_weight);
 	strncpy((char *) atval, desc_weight, len);
-	attrib_db_add(0x0685, &uuid, ATT_NONE, ATT_NOT_PERMITTED, atval, len);
+	attrib_db_add(h++, &uuid, ATT_NONE, ATT_NOT_PERMITTED, atval, len);
 
-	/* Add an SDP record for the above service */
-	handle = attrib_create_sdp(0x0680, "Weight Service");
-	if (handle)
-		sdp_handles = g_slist_prepend(sdp_handles, GUINT_TO_POINTER(handle));
+	g_assert(h - start_handle == svc_size);
 
-	return 0;
+	/* Add an SDP record for the above service */
+	sdp_handle = attrib_create_sdp(start_handle, "Weight Service");
+	if (sdp_handle)
+		sdp_handles = g_slist_prepend(sdp_handles,
+						GUINT_TO_POINTER(sdp_handle));
 }
 
 static int gatt_example_init(void)
 {
+	uint16_t manuf1_range[2] = {0, 0}, manuf2_range[2] = {0, 0};
+	uint16_t vendor_range[2] = {0, 0};
+
 	if (!main_opts.attrib_server) {
 		DBG("Attribute server is disabled");
 		return -1;
 	}
 
-	return register_attributes();
+	register_battery_service();
+	register_manuf1_service(manuf1_range);
+	register_manuf2_service(manuf2_range);
+	register_termometer_service(manuf1_range, manuf2_range);
+	register_vendor_service(vendor_range);
+	register_weight_service(vendor_range);
+
+	return 0;
 }
 
 static void gatt_example_exit(void)
-- 
1.7.0.4


^ permalink raw reply related

* [PATCH 2/3] Add attrib_db_find_avail() function to attribute server
From: Anderson Lizardo @ 2011-03-29 16:15 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Anderson Lizardo
In-Reply-To: <1301415328-14257-1-git-send-email-anderson.lizardo@openbossa.org>

This new function searches for a range of at least "nitems" available
(unused) attribute handles. It then returns either zero (if no available
range was found) or the start handle of the available range.
---
 src/attrib-server.c |   28 ++++++++++++++++++++++++++++
 src/attrib-server.h |    1 +
 2 files changed, 29 insertions(+), 0 deletions(-)

diff --git a/src/attrib-server.c b/src/attrib-server.c
index 98bd6b1..f4bf4b8 100644
--- a/src/attrib-server.c
+++ b/src/attrib-server.c
@@ -1215,6 +1215,34 @@ void attrib_free_sdp(uint32_t sdp_handle)
 	remove_record_from_server(sdp_handle);
 }
 
+uint16_t attrib_db_find_avail(uint16_t nitems)
+{
+	uint16_t handle;
+	GSList *l;
+
+	g_assert(nitems > 0);
+
+	for (l = database, handle = 0; l; l = l->next) {
+		struct attribute *a = l->data;
+
+		if (handle && (bt_uuid_cmp(&a->uuid, &prim_uuid) == 0 ||
+				bt_uuid_cmp(&a->uuid, &snd_uuid) == 0) &&
+				a->handle - handle >= nitems)
+			/* Note: the range above excludes the current handle */
+			return handle;
+
+		if (a->handle == 0xffff)
+			return 0;
+
+		handle = a->handle + 1;
+	}
+
+	if (0xffff - handle + 1 >= nitems)
+		return handle;
+
+	return 0;
+}
+
 struct attribute *attrib_db_add(uint16_t handle, bt_uuid_t *uuid, int read_reqs,
 				int write_reqs, const uint8_t *value, int len)
 {
diff --git a/src/attrib-server.h b/src/attrib-server.h
index 38a1f05..83484fc 100644
--- a/src/attrib-server.h
+++ b/src/attrib-server.h
@@ -25,6 +25,7 @@
 int attrib_server_init(void);
 void attrib_server_exit(void);
 
+uint16_t attrib_db_find_avail(uint16_t nitems);
 struct attribute *attrib_db_add(uint16_t handle, bt_uuid_t *uuid, int read_reqs,
 				int write_reqs, const uint8_t *value, int len);
 int attrib_db_update(uint16_t handle, bt_uuid_t *uuid, const uint8_t *value,
-- 
1.7.0.4


^ permalink raw reply related

* [PATCH 1/3] Move GATT example server to a standalone plugin
From: Anderson Lizardo @ 2011-03-29 16:15 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Anderson Lizardo
In-Reply-To: <1301415328-14257-1-git-send-email-anderson.lizardo@openbossa.org>

The GATT example server was in the same plugin as the GATT client.
Moving it to a separate plugin will allow to easily disable it.
---
 Makefile.am            |    8 +-
 acinclude.m4           |    6 +
 attrib/example.c       |  341 -----------------------------------------------
 attrib/example.h       |   26 ----
 attrib/manager.c       |    6 -
 bootstrap-configure    |    1 +
 plugins/gatt-example.c |  348 ++++++++++++++++++++++++++++++++++++++++++++++++
 7 files changed, 361 insertions(+), 375 deletions(-)

diff --git a/Makefile.am b/Makefile.am
index 77b9b7d..9b74970 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -204,8 +204,12 @@ endif
 
 builtin_modules += attrib
 builtin_sources += attrib/main.c \
-		attrib/manager.h attrib/manager.c \
-		attrib/example.h attrib/example.c
+		attrib/manager.h attrib/manager.c
+endif
+
+if GATT_EXAMPLE_PLUGIN
+builtin_modules += gatt_example
+builtin_sources += plugins/gatt-example.c
 endif
 
 if HEALTHPLUGIN
diff --git a/acinclude.m4 b/acinclude.m4
index 69e0740..81b366e 100644
--- a/acinclude.m4
+++ b/acinclude.m4
@@ -190,6 +190,7 @@ AC_DEFUN([AC_ARG_BLUEZ], [
 	health_enable=no
 	pnat_enable=no
 	attrib_enable=no
+	gatt_example_enable=no
 	tracer_enable=no
 	tools_enable=yes
 	hidd_enable=no
@@ -261,6 +262,10 @@ AC_DEFUN([AC_ARG_BLUEZ], [
 		attrib_enable=${enableval}
 	])
 
+	AC_ARG_ENABLE(gatt-example, AC_HELP_STRING([--enable-gatt-example], [enable GATT example plugin]), [
+		gatt_example_enable=${enableval}
+	])
+
 	AC_ARG_ENABLE(gstreamer, AC_HELP_STRING([--enable-gstreamer], [enable GStreamer support]), [
 		gstreamer_enable=${enableval}
 	])
@@ -385,6 +390,7 @@ AC_DEFUN([AC_ARG_BLUEZ], [
 	AM_CONDITIONAL(HAL, test "${hal_enable}" = "yes")
 	AM_CONDITIONAL(READLINE, test "${readline_found}" = "yes")
 	AM_CONDITIONAL(ATTRIBPLUGIN, test "${attrib_enable}" = "yes")
+	AM_CONDITIONAL(GATT_EXAMPLE_PLUGIN, test "${gatt_example_enable}" = "yes")
 	AM_CONDITIONAL(ECHOPLUGIN, test "no" = "yes")
 	AM_CONDITIONAL(PNATPLUGIN, test "${pnat_enable}" = "yes")
 	AM_CONDITIONAL(TRACER, test "${tracer_enable}" = "yes")
diff --git a/attrib/example.c b/attrib/example.c
deleted file mode 100644
index fae288c..0000000
--- a/attrib/example.c
+++ /dev/null
@@ -1,341 +0,0 @@
-/*
- *
- *  BlueZ - Bluetooth protocol stack for Linux
- *
- *  Copyright (C) 2010  Nokia Corporation
- *  Copyright (C) 2010  Marcel Holtmann <marcel@holtmann.org>
- *
- *
- *  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 <arpa/inet.h>
-
-#include <bluetooth/uuid.h>
-
-#include <glib.h>
-
-#include "log.h"
-#include "attrib-server.h"
-
-#include "att.h"
-#include "example.h"
-
-/* FIXME: Not defined by SIG? UUID128? */
-#define OPCODES_SUPPORTED_UUID          0xA001
-#define BATTERY_STATE_SVC_UUID		0xA002
-#define BATTERY_STATE_UUID		0xA003
-#define THERM_HUMIDITY_SVC_UUID		0xA004
-#define MANUFACTURER_SVC_UUID		0xA005
-#define TEMPERATURE_UUID		0xA006
-#define FMT_CELSIUS_UUID		0xA007
-#define FMT_OUTSIDE_UUID		0xA008
-#define RELATIVE_HUMIDITY_UUID		0xA009
-#define FMT_PERCENT_UUID		0xA00A
-#define BLUETOOTH_SIG_UUID		0xA00B
-#define MANUFACTURER_NAME_UUID		0xA00C
-#define MANUFACTURER_SERIAL_UUID	0xA00D
-#define VENDOR_SPECIFIC_SVC_UUID	0xA00E
-#define VENDOR_SPECIFIC_TYPE_UUID	0xA00F
-#define FMT_KILOGRAM_UUID		0xA010
-#define FMT_HANGING_UUID		0xA011
-
-static GSList *sdp_handles = NULL;
-
-static int register_attributes(void)
-{
-	const char *desc_out_temp = "Outside Temperature";
-	const char *desc_out_hum = "Outside Relative Humidity";
-	const char *desc_weight = "Rucksack Weight";
-	const char *manufacturer_name1 = "ACME Temperature Sensor";
-	const char *manufacturer_name2 = "ACME Weighing Scales";
-	const char *serial1 = "237495-3282-A";
-	const char *serial2 = "11267-2327A00239";
-
-	const uint128_t char_weight_uuid_btorder = {
-		.data = { 0x80, 0x88, 0xF2, 0x18, 0x90, 0x2C, 0x45, 0x0B,
-			  0xB6, 0xC4, 0x62, 0x89, 0x1E, 0x8C, 0x25, 0xE9 } };
-	const uint128_t prim_weight_uuid_btorder = {
-		.data = { 0x4F, 0x0A, 0xC0, 0x96, 0x35, 0xD4, 0x49, 0x11,
-			  0x96, 0x31, 0xDE, 0xA8, 0xDC, 0x74, 0xEE, 0xFE } };
-
-	uint128_t char_weight_uuid;
-	uint8_t atval[256];
-	uint32_t handle;
-	bt_uuid_t uuid;
-	int len;
-
-	btoh128(&char_weight_uuid_btorder, &char_weight_uuid);
-
-	/* Battery state service: primary service definition */
-	bt_uuid16_create(&uuid, GATT_PRIM_SVC_UUID);
-	att_put_u16(BATTERY_STATE_SVC_UUID, &atval[0]);
-	attrib_db_add(0x0100, &uuid, ATT_NONE, ATT_NOT_PERMITTED, atval, 2);
-
-	/* Battery: battery state characteristic */
-	bt_uuid16_create(&uuid, GATT_CHARAC_UUID);
-	atval[0] = ATT_CHAR_PROPER_READ;
-	att_put_u16(0x0110, &atval[1]);
-	att_put_u16(BATTERY_STATE_UUID, &atval[3]);
-	attrib_db_add(0x0106, &uuid, ATT_NONE, ATT_NOT_PERMITTED, atval, 5);
-
-	/* Battery: battery state attribute */
-	bt_uuid16_create(&uuid, BATTERY_STATE_UUID);
-	atval[0] = 0x04;
-	attrib_db_add(0x0110, &uuid, ATT_NONE, ATT_NOT_PERMITTED, atval, 1);
-
-	/* Battery: Client Characteristic Configuration */
-	bt_uuid16_create(&uuid, GATT_CLIENT_CHARAC_CFG_UUID);
-	atval[0] = 0x00;
-	atval[1] = 0x00;
-	attrib_db_add(0x0111, &uuid, ATT_NONE, ATT_AUTHENTICATION, atval, 2);
-
-	/* Add an SDP record for the above service */
-	handle = attrib_create_sdp(0x0100, "Battery State Service");
-	if (handle)
-		sdp_handles = g_slist_prepend(sdp_handles, GUINT_TO_POINTER(handle));
-
-	/* Thermometer: primary service definition */
-	bt_uuid16_create(&uuid, GATT_PRIM_SVC_UUID);
-	att_put_u16(THERM_HUMIDITY_SVC_UUID, &atval[0]);
-	attrib_db_add(0x0200, &uuid, ATT_NONE, ATT_NOT_PERMITTED, atval, 2);
-
-	/* Thermometer: Include */
-	bt_uuid16_create(&uuid, GATT_INCLUDE_UUID);
-	att_put_u16(0x0500, &atval[0]);
-	att_put_u16(0x0504, &atval[2]);
-	att_put_u16(MANUFACTURER_SVC_UUID, &atval[4]);
-	attrib_db_add(0x0201, &uuid, ATT_NONE, ATT_NOT_PERMITTED, atval, 6);
-
-	/* Thermometer: Include */
-	att_put_u16(0x0550, &atval[0]);
-	att_put_u16(0x0568, &atval[2]);
-	att_put_u16(VENDOR_SPECIFIC_SVC_UUID, &atval[4]);
-	attrib_db_add(0x0202, &uuid, ATT_NONE, ATT_NOT_PERMITTED, atval, 6);
-
-	/* Thermometer: temperature characteristic */
-	bt_uuid16_create(&uuid, GATT_CHARAC_UUID);
-	atval[0] = ATT_CHAR_PROPER_READ;
-	att_put_u16(0x0204, &atval[1]);
-	att_put_u16(TEMPERATURE_UUID, &atval[3]);
-	attrib_db_add(0x0203, &uuid, ATT_NONE, ATT_NOT_PERMITTED, atval, 5);
-
-	/* Thermometer: temperature characteristic value */
-	bt_uuid16_create(&uuid, TEMPERATURE_UUID);
-	atval[0] = 0x8A;
-	atval[1] = 0x02;
-	attrib_db_add(0x0204, &uuid, ATT_NONE, ATT_NOT_PERMITTED, atval, 2);
-
-	/* Thermometer: temperature characteristic format */
-	bt_uuid16_create(&uuid, GATT_CHARAC_FMT_UUID);
-	atval[0] = 0x0E;
-	atval[1] = 0xFE;
-	att_put_u16(FMT_CELSIUS_UUID, &atval[2]);
-	atval[4] = 0x01;
-	att_put_u16(FMT_OUTSIDE_UUID, &atval[5]);
-	attrib_db_add(0x0205, &uuid, ATT_NONE, ATT_NOT_PERMITTED, atval, 7);
-
-	/* Thermometer: characteristic user description */
-	bt_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, ATT_NONE, ATT_NOT_PERMITTED, atval, len);
-
-	/* Thermometer: relative humidity characteristic */
-	bt_uuid16_create(&uuid, GATT_CHARAC_UUID);
-	atval[0] = ATT_CHAR_PROPER_READ;
-	att_put_u16(0x0212, &atval[1]);
-	att_put_u16(RELATIVE_HUMIDITY_UUID, &atval[3]);
-	attrib_db_add(0x0210, &uuid, ATT_NONE, ATT_NOT_PERMITTED, atval, 5);
-
-	/* Thermometer: relative humidity value */
-	bt_uuid16_create(&uuid, RELATIVE_HUMIDITY_UUID);
-	atval[0] = 0x27;
-	attrib_db_add(0x0212, &uuid, ATT_NONE, ATT_NOT_PERMITTED, atval, 1);
-
-	/* Thermometer: relative humidity characteristic format */
-	bt_uuid16_create(&uuid, GATT_CHARAC_FMT_UUID);
-	atval[0] = 0x04;
-	atval[1] = 0x00;
-	att_put_u16(FMT_PERCENT_UUID, &atval[2]);
-	att_put_u16(BLUETOOTH_SIG_UUID, &atval[4]);
-	att_put_u16(FMT_OUTSIDE_UUID, &atval[6]);
-	attrib_db_add(0x0213, &uuid, ATT_NONE, ATT_NOT_PERMITTED, atval, 8);
-
-	/* Thermometer: characteristic user description */
-	bt_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, ATT_NONE, ATT_NOT_PERMITTED, atval, len);
-
-	/* Add an SDP record for the above service */
-	handle = attrib_create_sdp(0x0200, "Thermometer");
-	if (handle)
-		sdp_handles = g_slist_prepend(sdp_handles, GUINT_TO_POINTER(handle));
-
-	/* Secondary Service: Manufacturer Service */
-	bt_uuid16_create(&uuid, GATT_SND_SVC_UUID);
-	att_put_u16(MANUFACTURER_SVC_UUID, &atval[0]);
-	attrib_db_add(0x0500, &uuid, ATT_NONE, ATT_NOT_PERMITTED, atval, 2);
-
-	/* Manufacturer name characteristic definition */
-	bt_uuid16_create(&uuid, GATT_CHARAC_UUID);
-	atval[0] = ATT_CHAR_PROPER_READ;
-	att_put_u16(0x0502, &atval[1]);
-	att_put_u16(MANUFACTURER_NAME_UUID, &atval[3]);
-	attrib_db_add(0x0501, &uuid, ATT_NONE, ATT_NOT_PERMITTED, atval, 5);
-
-	/* Manufacturer name characteristic value */
-	bt_uuid16_create(&uuid, MANUFACTURER_NAME_UUID);
-	len = strlen(manufacturer_name1);
-	strncpy((char *) atval, manufacturer_name1, len);
-	attrib_db_add(0x0502, &uuid, ATT_NONE, ATT_NOT_PERMITTED, atval, len);
-
-	/* Manufacturer serial number characteristic */
-	bt_uuid16_create(&uuid, GATT_CHARAC_UUID);
-	atval[0] = ATT_CHAR_PROPER_READ;
-	att_put_u16(0x0504, &atval[1]);
-	att_put_u16(MANUFACTURER_SERIAL_UUID, &atval[3]);
-	attrib_db_add(0x0503, &uuid, ATT_NONE, ATT_NOT_PERMITTED, atval, 5);
-
-	/* Manufacturer serial number characteristic value */
-	bt_uuid16_create(&uuid, MANUFACTURER_SERIAL_UUID);
-	len = strlen(serial1);
-	strncpy((char *) atval, serial1, len);
-	attrib_db_add(0x0504, &uuid, ATT_NONE, ATT_NOT_PERMITTED, atval, len);
-
-	/* Secondary Service: Manufacturer Service */
-	bt_uuid16_create(&uuid, GATT_SND_SVC_UUID);
-	att_put_u16(MANUFACTURER_SVC_UUID, &atval[0]);
-	attrib_db_add(0x0505, &uuid, ATT_NONE, ATT_NOT_PERMITTED, atval, 2);
-
-	/* Manufacturer name characteristic definition */
-	bt_uuid16_create(&uuid, GATT_CHARAC_UUID);
-	atval[0] = ATT_CHAR_PROPER_READ;
-	att_put_u16(0x0507, &atval[1]);
-	att_put_u16(MANUFACTURER_NAME_UUID, &atval[3]);
-	attrib_db_add(0x0506, &uuid, ATT_NONE, ATT_NOT_PERMITTED, atval, 5);
-
-	/* Secondary Service: Vendor Specific Service */
-	bt_uuid16_create(&uuid, GATT_SND_SVC_UUID);
-	att_put_u16(VENDOR_SPECIFIC_SVC_UUID, &atval[0]);
-	attrib_db_add(0x0550, &uuid, ATT_NONE, ATT_NOT_PERMITTED, atval, 2);
-
-	/* Vendor Specific Type characteristic definition */
-	bt_uuid16_create(&uuid, GATT_CHARAC_UUID);
-	atval[0] = ATT_CHAR_PROPER_READ;
-	att_put_u16(0x0568, &atval[1]);
-	att_put_u16(VENDOR_SPECIFIC_TYPE_UUID, &atval[3]);
-	attrib_db_add(0x0560, &uuid, ATT_NONE, ATT_NOT_PERMITTED, atval, 5);
-
-	/* Vendor Specific Type characteristic value */
-	bt_uuid16_create(&uuid, VENDOR_SPECIFIC_TYPE_UUID);
-	atval[0] = 0x56;
-	atval[1] = 0x65;
-	atval[2] = 0x6E;
-	atval[3] = 0x64;
-	atval[4] = 0x6F;
-	atval[5] = 0x72;
-	attrib_db_add(0x0568, &uuid, ATT_NONE, ATT_NOT_PERMITTED, atval, 6);
-
-	/* Manufacturer name attribute */
-	bt_uuid16_create(&uuid, MANUFACTURER_NAME_UUID);
-	len = strlen(manufacturer_name2);
-	strncpy((char *) atval, manufacturer_name2, len);
-	attrib_db_add(0x0507, &uuid, ATT_NONE, ATT_NOT_PERMITTED, atval, len);
-
-	/* Characteristic: serial number */
-	bt_uuid16_create(&uuid, GATT_CHARAC_UUID);
-	atval[0] = ATT_CHAR_PROPER_READ;
-	att_put_u16(0x0509, &atval[1]);
-	att_put_u16(MANUFACTURER_SERIAL_UUID, &atval[3]);
-	attrib_db_add(0x0508, &uuid, ATT_NONE, ATT_NOT_PERMITTED, atval, 5);
-
-	/* Serial number characteristic value */
-	bt_uuid16_create(&uuid, MANUFACTURER_SERIAL_UUID);
-	len = strlen(serial2);
-	strncpy((char *) atval, serial2, len);
-	attrib_db_add(0x0509, &uuid, ATT_NONE, ATT_NOT_PERMITTED, atval, len);
-
-	/* Weight service: primary service definition */
-	bt_uuid16_create(&uuid, GATT_PRIM_SVC_UUID);
-	memcpy(atval, &prim_weight_uuid_btorder, 16);
-	attrib_db_add(0x0680, &uuid, ATT_NONE, ATT_NOT_PERMITTED, atval, 16);
-
-	/* Weight: include */
-	bt_uuid16_create(&uuid, GATT_INCLUDE_UUID);
-	att_put_u16(0x0505, &atval[0]);
-	att_put_u16(0x0509, &atval[2]);
-	att_put_u16(MANUFACTURER_SVC_UUID, &atval[4]);
-	attrib_db_add(0x0681, &uuid, ATT_NONE, ATT_NOT_PERMITTED, atval, 6);
-
-	/* Weight: characteristic */
-	bt_uuid16_create(&uuid, GATT_CHARAC_UUID);
-	atval[0] = ATT_CHAR_PROPER_READ;
-	att_put_u16(0x0683, &atval[1]);
-	memcpy(&atval[3], &char_weight_uuid_btorder, 16);
-	attrib_db_add(0x0682, &uuid, ATT_NONE, ATT_NOT_PERMITTED, atval, 19);
-
-	/* Weight: characteristic value */
-	bt_uuid128_create(&uuid, char_weight_uuid);
-	atval[0] = 0x82;
-	atval[1] = 0x55;
-	atval[2] = 0x00;
-	atval[3] = 0x00;
-	attrib_db_add(0x0683, &uuid, ATT_NONE, ATT_NOT_PERMITTED, atval, 4);
-
-	/* Weight: characteristic format */
-	bt_uuid16_create(&uuid, GATT_CHARAC_FMT_UUID);
-	atval[0] = 0x08;
-	atval[1] = 0xFD;
-	att_put_u16(FMT_KILOGRAM_UUID, &atval[2]);
-	att_put_u16(BLUETOOTH_SIG_UUID, &atval[4]);
-	att_put_u16(FMT_HANGING_UUID, &atval[6]);
-	attrib_db_add(0x0684, &uuid, ATT_NONE, ATT_NOT_PERMITTED, atval, 8);
-
-	/* Weight: characteristic user description */
-	bt_uuid16_create(&uuid, GATT_CHARAC_USER_DESC_UUID);
-	len = strlen(desc_weight);
-	strncpy((char *) atval, desc_weight, len);
-	attrib_db_add(0x0685, &uuid, ATT_NONE, ATT_NOT_PERMITTED, atval, len);
-
-	/* Add an SDP record for the above service */
-	handle = attrib_create_sdp(0x0680, "Weight Service");
-	if (handle)
-		sdp_handles = g_slist_prepend(sdp_handles, GUINT_TO_POINTER(handle));
-
-	return 0;
-}
-
-int server_example_init(void)
-{
-	return register_attributes();
-}
-
-void server_example_exit(void)
-{
-	while (sdp_handles) {
-		uint32_t handle = GPOINTER_TO_UINT(sdp_handles->data);
-
-		attrib_free_sdp(handle);
-		sdp_handles = g_slist_remove(sdp_handles, sdp_handles->data);
-	}
-}
diff --git a/attrib/example.h b/attrib/example.h
deleted file mode 100644
index a2b07fe..0000000
--- a/attrib/example.h
+++ /dev/null
@@ -1,26 +0,0 @@
-/*
- *
- *  BlueZ - Bluetooth protocol stack for Linux
- *
- *  Copyright (C) 2010  Nokia Corporation
- *  Copyright (C) 2010  Marcel Holtmann <marcel@holtmann.org>
- *
- *
- *  This program is free software; you can redistribute it and/or modify
- *  it under the terms of the GNU General Public License as published by
- *  the Free Software Foundation; either version 2 of the License, or
- *  (at your option) any later version.
- *
- *  This program is distributed in the hope that it will be useful,
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *  GNU General Public License for more details.
- *
- *  You should have received a copy of the GNU General Public License
- *  along with this program; if not, write to the Free Software
- *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
- *
- */
-
-int server_example_init(void);
-void server_example_exit(void);
diff --git a/attrib/manager.c b/attrib/manager.c
index 7c05720..6a2b80a 100644
--- a/attrib/manager.c
+++ b/attrib/manager.c
@@ -32,18 +32,12 @@
 #include "hcid.h"
 
 #include "manager.h"
-#include "example.h"
 
 int attrib_manager_init(void)
 {
-	if (main_opts.attrib_server)
-		return server_example_init();
-
 	return 0;
 }
 
 void attrib_manager_exit(void)
 {
-	if (main_opts.attrib_server)
-		server_example_exit();
 }
diff --git a/bootstrap-configure b/bootstrap-configure
index 69a102f..364998f 100755
--- a/bootstrap-configure
+++ b/bootstrap-configure
@@ -18,6 +18,7 @@ fi
 		--libexecdir=/lib \
 		--enable-capng \
 		--enable-attrib \
+		--enable-gatt-example \
 		--enable-health \
 		--enable-tracer \
 		--enable-tools \
diff --git a/plugins/gatt-example.c b/plugins/gatt-example.c
new file mode 100644
index 0000000..f1dfd5b
--- /dev/null
+++ b/plugins/gatt-example.c
@@ -0,0 +1,348 @@
+/*
+ *
+ *  BlueZ - Bluetooth protocol stack for Linux
+ *
+ *  Copyright (C) 2010  Nokia Corporation
+ *  Copyright (C) 2010  Marcel Holtmann <marcel@holtmann.org>
+ *
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <glib.h>
+#include <bluetooth/uuid.h>
+
+#include "plugin.h"
+#include "hcid.h"
+#include "log.h"
+#include "attrib-server.h"
+#include "att.h"
+
+/* FIXME: Not defined by SIG? UUID128? */
+#define OPCODES_SUPPORTED_UUID          0xA001
+#define BATTERY_STATE_SVC_UUID		0xA002
+#define BATTERY_STATE_UUID		0xA003
+#define THERM_HUMIDITY_SVC_UUID		0xA004
+#define MANUFACTURER_SVC_UUID		0xA005
+#define TEMPERATURE_UUID		0xA006
+#define FMT_CELSIUS_UUID		0xA007
+#define FMT_OUTSIDE_UUID		0xA008
+#define RELATIVE_HUMIDITY_UUID		0xA009
+#define FMT_PERCENT_UUID		0xA00A
+#define BLUETOOTH_SIG_UUID		0xA00B
+#define MANUFACTURER_NAME_UUID		0xA00C
+#define MANUFACTURER_SERIAL_UUID	0xA00D
+#define VENDOR_SPECIFIC_SVC_UUID	0xA00E
+#define VENDOR_SPECIFIC_TYPE_UUID	0xA00F
+#define FMT_KILOGRAM_UUID		0xA010
+#define FMT_HANGING_UUID		0xA011
+
+static GSList *sdp_handles = NULL;
+
+static int register_attributes(void)
+{
+	const char *desc_out_temp = "Outside Temperature";
+	const char *desc_out_hum = "Outside Relative Humidity";
+	const char *desc_weight = "Rucksack Weight";
+	const char *manufacturer_name1 = "ACME Temperature Sensor";
+	const char *manufacturer_name2 = "ACME Weighing Scales";
+	const char *serial1 = "237495-3282-A";
+	const char *serial2 = "11267-2327A00239";
+
+	const uint128_t char_weight_uuid_btorder = {
+		.data = { 0x80, 0x88, 0xF2, 0x18, 0x90, 0x2C, 0x45, 0x0B,
+			  0xB6, 0xC4, 0x62, 0x89, 0x1E, 0x8C, 0x25, 0xE9 } };
+	const uint128_t prim_weight_uuid_btorder = {
+		.data = { 0x4F, 0x0A, 0xC0, 0x96, 0x35, 0xD4, 0x49, 0x11,
+			  0x96, 0x31, 0xDE, 0xA8, 0xDC, 0x74, 0xEE, 0xFE } };
+
+	uint128_t char_weight_uuid;
+	uint8_t atval[256];
+	uint32_t handle;
+	bt_uuid_t uuid;
+	int len;
+
+	btoh128(&char_weight_uuid_btorder, &char_weight_uuid);
+
+	/* Battery state service: primary service definition */
+	bt_uuid16_create(&uuid, GATT_PRIM_SVC_UUID);
+	att_put_u16(BATTERY_STATE_SVC_UUID, &atval[0]);
+	attrib_db_add(0x0100, &uuid, ATT_NONE, ATT_NOT_PERMITTED, atval, 2);
+
+	/* Battery: battery state characteristic */
+	bt_uuid16_create(&uuid, GATT_CHARAC_UUID);
+	atval[0] = ATT_CHAR_PROPER_READ;
+	att_put_u16(0x0110, &atval[1]);
+	att_put_u16(BATTERY_STATE_UUID, &atval[3]);
+	attrib_db_add(0x0106, &uuid, ATT_NONE, ATT_NOT_PERMITTED, atval, 5);
+
+	/* Battery: battery state attribute */
+	bt_uuid16_create(&uuid, BATTERY_STATE_UUID);
+	atval[0] = 0x04;
+	attrib_db_add(0x0110, &uuid, ATT_NONE, ATT_NOT_PERMITTED, atval, 1);
+
+	/* Battery: Client Characteristic Configuration */
+	bt_uuid16_create(&uuid, GATT_CLIENT_CHARAC_CFG_UUID);
+	atval[0] = 0x00;
+	atval[1] = 0x00;
+	attrib_db_add(0x0111, &uuid, ATT_NONE, ATT_AUTHENTICATION, atval, 2);
+
+	/* Add an SDP record for the above service */
+	handle = attrib_create_sdp(0x0100, "Battery State Service");
+	if (handle)
+		sdp_handles = g_slist_prepend(sdp_handles, GUINT_TO_POINTER(handle));
+
+	/* Thermometer: primary service definition */
+	bt_uuid16_create(&uuid, GATT_PRIM_SVC_UUID);
+	att_put_u16(THERM_HUMIDITY_SVC_UUID, &atval[0]);
+	attrib_db_add(0x0200, &uuid, ATT_NONE, ATT_NOT_PERMITTED, atval, 2);
+
+	/* Thermometer: Include */
+	bt_uuid16_create(&uuid, GATT_INCLUDE_UUID);
+	att_put_u16(0x0500, &atval[0]);
+	att_put_u16(0x0504, &atval[2]);
+	att_put_u16(MANUFACTURER_SVC_UUID, &atval[4]);
+	attrib_db_add(0x0201, &uuid, ATT_NONE, ATT_NOT_PERMITTED, atval, 6);
+
+	/* Thermometer: Include */
+	att_put_u16(0x0550, &atval[0]);
+	att_put_u16(0x0568, &atval[2]);
+	att_put_u16(VENDOR_SPECIFIC_SVC_UUID, &atval[4]);
+	attrib_db_add(0x0202, &uuid, ATT_NONE, ATT_NOT_PERMITTED, atval, 6);
+
+	/* Thermometer: temperature characteristic */
+	bt_uuid16_create(&uuid, GATT_CHARAC_UUID);
+	atval[0] = ATT_CHAR_PROPER_READ;
+	att_put_u16(0x0204, &atval[1]);
+	att_put_u16(TEMPERATURE_UUID, &atval[3]);
+	attrib_db_add(0x0203, &uuid, ATT_NONE, ATT_NOT_PERMITTED, atval, 5);
+
+	/* Thermometer: temperature characteristic value */
+	bt_uuid16_create(&uuid, TEMPERATURE_UUID);
+	atval[0] = 0x8A;
+	atval[1] = 0x02;
+	attrib_db_add(0x0204, &uuid, ATT_NONE, ATT_NOT_PERMITTED, atval, 2);
+
+	/* Thermometer: temperature characteristic format */
+	bt_uuid16_create(&uuid, GATT_CHARAC_FMT_UUID);
+	atval[0] = 0x0E;
+	atval[1] = 0xFE;
+	att_put_u16(FMT_CELSIUS_UUID, &atval[2]);
+	atval[4] = 0x01;
+	att_put_u16(FMT_OUTSIDE_UUID, &atval[5]);
+	attrib_db_add(0x0205, &uuid, ATT_NONE, ATT_NOT_PERMITTED, atval, 7);
+
+	/* Thermometer: characteristic user description */
+	bt_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, ATT_NONE, ATT_NOT_PERMITTED, atval, len);
+
+	/* Thermometer: relative humidity characteristic */
+	bt_uuid16_create(&uuid, GATT_CHARAC_UUID);
+	atval[0] = ATT_CHAR_PROPER_READ;
+	att_put_u16(0x0212, &atval[1]);
+	att_put_u16(RELATIVE_HUMIDITY_UUID, &atval[3]);
+	attrib_db_add(0x0210, &uuid, ATT_NONE, ATT_NOT_PERMITTED, atval, 5);
+
+	/* Thermometer: relative humidity value */
+	bt_uuid16_create(&uuid, RELATIVE_HUMIDITY_UUID);
+	atval[0] = 0x27;
+	attrib_db_add(0x0212, &uuid, ATT_NONE, ATT_NOT_PERMITTED, atval, 1);
+
+	/* Thermometer: relative humidity characteristic format */
+	bt_uuid16_create(&uuid, GATT_CHARAC_FMT_UUID);
+	atval[0] = 0x04;
+	atval[1] = 0x00;
+	att_put_u16(FMT_PERCENT_UUID, &atval[2]);
+	att_put_u16(BLUETOOTH_SIG_UUID, &atval[4]);
+	att_put_u16(FMT_OUTSIDE_UUID, &atval[6]);
+	attrib_db_add(0x0213, &uuid, ATT_NONE, ATT_NOT_PERMITTED, atval, 8);
+
+	/* Thermometer: characteristic user description */
+	bt_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, ATT_NONE, ATT_NOT_PERMITTED, atval, len);
+
+	/* Add an SDP record for the above service */
+	handle = attrib_create_sdp(0x0200, "Thermometer");
+	if (handle)
+		sdp_handles = g_slist_prepend(sdp_handles, GUINT_TO_POINTER(handle));
+
+	/* Secondary Service: Manufacturer Service */
+	bt_uuid16_create(&uuid, GATT_SND_SVC_UUID);
+	att_put_u16(MANUFACTURER_SVC_UUID, &atval[0]);
+	attrib_db_add(0x0500, &uuid, ATT_NONE, ATT_NOT_PERMITTED, atval, 2);
+
+	/* Manufacturer name characteristic definition */
+	bt_uuid16_create(&uuid, GATT_CHARAC_UUID);
+	atval[0] = ATT_CHAR_PROPER_READ;
+	att_put_u16(0x0502, &atval[1]);
+	att_put_u16(MANUFACTURER_NAME_UUID, &atval[3]);
+	attrib_db_add(0x0501, &uuid, ATT_NONE, ATT_NOT_PERMITTED, atval, 5);
+
+	/* Manufacturer name characteristic value */
+	bt_uuid16_create(&uuid, MANUFACTURER_NAME_UUID);
+	len = strlen(manufacturer_name1);
+	strncpy((char *) atval, manufacturer_name1, len);
+	attrib_db_add(0x0502, &uuid, ATT_NONE, ATT_NOT_PERMITTED, atval, len);
+
+	/* Manufacturer serial number characteristic */
+	bt_uuid16_create(&uuid, GATT_CHARAC_UUID);
+	atval[0] = ATT_CHAR_PROPER_READ;
+	att_put_u16(0x0504, &atval[1]);
+	att_put_u16(MANUFACTURER_SERIAL_UUID, &atval[3]);
+	attrib_db_add(0x0503, &uuid, ATT_NONE, ATT_NOT_PERMITTED, atval, 5);
+
+	/* Manufacturer serial number characteristic value */
+	bt_uuid16_create(&uuid, MANUFACTURER_SERIAL_UUID);
+	len = strlen(serial1);
+	strncpy((char *) atval, serial1, len);
+	attrib_db_add(0x0504, &uuid, ATT_NONE, ATT_NOT_PERMITTED, atval, len);
+
+	/* Secondary Service: Manufacturer Service */
+	bt_uuid16_create(&uuid, GATT_SND_SVC_UUID);
+	att_put_u16(MANUFACTURER_SVC_UUID, &atval[0]);
+	attrib_db_add(0x0505, &uuid, ATT_NONE, ATT_NOT_PERMITTED, atval, 2);
+
+	/* Manufacturer name characteristic definition */
+	bt_uuid16_create(&uuid, GATT_CHARAC_UUID);
+	atval[0] = ATT_CHAR_PROPER_READ;
+	att_put_u16(0x0507, &atval[1]);
+	att_put_u16(MANUFACTURER_NAME_UUID, &atval[3]);
+	attrib_db_add(0x0506, &uuid, ATT_NONE, ATT_NOT_PERMITTED, atval, 5);
+
+	/* Secondary Service: Vendor Specific Service */
+	bt_uuid16_create(&uuid, GATT_SND_SVC_UUID);
+	att_put_u16(VENDOR_SPECIFIC_SVC_UUID, &atval[0]);
+	attrib_db_add(0x0550, &uuid, ATT_NONE, ATT_NOT_PERMITTED, atval, 2);
+
+	/* Vendor Specific Type characteristic definition */
+	bt_uuid16_create(&uuid, GATT_CHARAC_UUID);
+	atval[0] = ATT_CHAR_PROPER_READ;
+	att_put_u16(0x0568, &atval[1]);
+	att_put_u16(VENDOR_SPECIFIC_TYPE_UUID, &atval[3]);
+	attrib_db_add(0x0560, &uuid, ATT_NONE, ATT_NOT_PERMITTED, atval, 5);
+
+	/* Vendor Specific Type characteristic value */
+	bt_uuid16_create(&uuid, VENDOR_SPECIFIC_TYPE_UUID);
+	atval[0] = 0x56;
+	atval[1] = 0x65;
+	atval[2] = 0x6E;
+	atval[3] = 0x64;
+	atval[4] = 0x6F;
+	atval[5] = 0x72;
+	attrib_db_add(0x0568, &uuid, ATT_NONE, ATT_NOT_PERMITTED, atval, 6);
+
+	/* Manufacturer name attribute */
+	bt_uuid16_create(&uuid, MANUFACTURER_NAME_UUID);
+	len = strlen(manufacturer_name2);
+	strncpy((char *) atval, manufacturer_name2, len);
+	attrib_db_add(0x0507, &uuid, ATT_NONE, ATT_NOT_PERMITTED, atval, len);
+
+	/* Characteristic: serial number */
+	bt_uuid16_create(&uuid, GATT_CHARAC_UUID);
+	atval[0] = ATT_CHAR_PROPER_READ;
+	att_put_u16(0x0509, &atval[1]);
+	att_put_u16(MANUFACTURER_SERIAL_UUID, &atval[3]);
+	attrib_db_add(0x0508, &uuid, ATT_NONE, ATT_NOT_PERMITTED, atval, 5);
+
+	/* Serial number characteristic value */
+	bt_uuid16_create(&uuid, MANUFACTURER_SERIAL_UUID);
+	len = strlen(serial2);
+	strncpy((char *) atval, serial2, len);
+	attrib_db_add(0x0509, &uuid, ATT_NONE, ATT_NOT_PERMITTED, atval, len);
+
+	/* Weight service: primary service definition */
+	bt_uuid16_create(&uuid, GATT_PRIM_SVC_UUID);
+	memcpy(atval, &prim_weight_uuid_btorder, 16);
+	attrib_db_add(0x0680, &uuid, ATT_NONE, ATT_NOT_PERMITTED, atval, 16);
+
+	/* Weight: include */
+	bt_uuid16_create(&uuid, GATT_INCLUDE_UUID);
+	att_put_u16(0x0505, &atval[0]);
+	att_put_u16(0x0509, &atval[2]);
+	att_put_u16(MANUFACTURER_SVC_UUID, &atval[4]);
+	attrib_db_add(0x0681, &uuid, ATT_NONE, ATT_NOT_PERMITTED, atval, 6);
+
+	/* Weight: characteristic */
+	bt_uuid16_create(&uuid, GATT_CHARAC_UUID);
+	atval[0] = ATT_CHAR_PROPER_READ;
+	att_put_u16(0x0683, &atval[1]);
+	memcpy(&atval[3], &char_weight_uuid_btorder, 16);
+	attrib_db_add(0x0682, &uuid, ATT_NONE, ATT_NOT_PERMITTED, atval, 19);
+
+	/* Weight: characteristic value */
+	bt_uuid128_create(&uuid, char_weight_uuid);
+	atval[0] = 0x82;
+	atval[1] = 0x55;
+	atval[2] = 0x00;
+	atval[3] = 0x00;
+	attrib_db_add(0x0683, &uuid, ATT_NONE, ATT_NOT_PERMITTED, atval, 4);
+
+	/* Weight: characteristic format */
+	bt_uuid16_create(&uuid, GATT_CHARAC_FMT_UUID);
+	atval[0] = 0x08;
+	atval[1] = 0xFD;
+	att_put_u16(FMT_KILOGRAM_UUID, &atval[2]);
+	att_put_u16(BLUETOOTH_SIG_UUID, &atval[4]);
+	att_put_u16(FMT_HANGING_UUID, &atval[6]);
+	attrib_db_add(0x0684, &uuid, ATT_NONE, ATT_NOT_PERMITTED, atval, 8);
+
+	/* Weight: characteristic user description */
+	bt_uuid16_create(&uuid, GATT_CHARAC_USER_DESC_UUID);
+	len = strlen(desc_weight);
+	strncpy((char *) atval, desc_weight, len);
+	attrib_db_add(0x0685, &uuid, ATT_NONE, ATT_NOT_PERMITTED, atval, len);
+
+	/* Add an SDP record for the above service */
+	handle = attrib_create_sdp(0x0680, "Weight Service");
+	if (handle)
+		sdp_handles = g_slist_prepend(sdp_handles, GUINT_TO_POINTER(handle));
+
+	return 0;
+}
+
+static int gatt_example_init(void)
+{
+	if (!main_opts.attrib_server) {
+		DBG("Attribute server is disabled");
+		return -1;
+	}
+
+	return register_attributes();
+}
+
+static void gatt_example_exit(void)
+{
+	if (!main_opts.attrib_server)
+		return;
+
+	while (sdp_handles) {
+		uint32_t handle = GPOINTER_TO_UINT(sdp_handles->data);
+
+		attrib_free_sdp(handle);
+		sdp_handles = g_slist_remove(sdp_handles, sdp_handles->data);
+	}
+}
+
+BLUETOOTH_PLUGIN_DEFINE(gatt_example, VERSION, BLUETOOTH_PLUGIN_PRIORITY_LOW,
+					gatt_example_init, gatt_example_exit)
-- 
1.7.0.4


^ permalink raw reply related

* [PATCH 0/3] Make GATT example server a separate plugin
From: Anderson Lizardo @ 2011-03-29 16:15 UTC (permalink / raw)
  To: linux-bluetooth

These patches move the example server into a separate plugin. Currently, it is
inside the "Attribute plugin" and was always enabled when GATT support was
enabled. Making a separate plugin allows to disable it on production systems.

The last two patches remove hard-coded attribute handles from the plugin, which
will avoid handle conflicts between multiple profile plugins. The
attrib_db_find_avail() function was borrowed from my previous RFC series.

Note that these patches should be applied after Vinicius' "Attrib client move"
series.


^ permalink raw reply

* Re: [PATCH 1/2] Don't disable LE scan when started by external tools
From: Johan Hedberg @ 2011-03-29 15:10 UTC (permalink / raw)
  To: Claudio Takahasi; +Cc: linux-bluetooth
In-Reply-To: <1301409581-16057-1-git-send-email-claudio.takahasi@openbossa.org>

Hi Claudio,

On Tue, Mar 29, 2011, Claudio Takahasi wrote:
> This patch removes the automatic LE scan disabling when it is not
> triggered through the StartDiscovery() method.
> ---
>  src/adapter.c |    6 ++++--
>  1 files changed, 4 insertions(+), 2 deletions(-)

Both of these patches have been pushed upstream. Thanks.

Could you next send a patch to create a proper define for this
hard-coded value 5120? That should never have made it to the upstream
tree to begin with.

Johan

^ permalink raw reply

* Re: [PATCH 3/3 v2] Fix uninitialized variables warnings
From: Johan Hedberg @ 2011-03-29 15:08 UTC (permalink / raw)
  To: luiz.dentz; +Cc: linux-bluetooth
In-Reply-To: <1301406464-3404-2-git-send-email-luiz.dentz@gmail.com>

Hi Luiz,

On Tue, Mar 29, 2011, luiz.dentz@gmail.com wrote:
> src/attrib-server.c: In function ‘channel_handler’:
> src/attrib-server.c:297:21: error: ‘cur’ may be used uninitialized in this function
> src/attrib-server.c:502:10: error: ‘format’ may be used uninitialized in this function
> src/attrib-server.c:503:11: error: ‘length’ may be used uninitialized in this function
> make[1]: *** [src/attrib-server.o] Error 1
> ---
>  src/attrib-server.c |    5 ++++-
>  1 files changed, 4 insertions(+), 1 deletions(-)

All three patches (v2 of 2/3 & 3/3) have been pushed upstream. Thanks.

Johan

^ 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