* [PATCH 4/4] HCI command to clear LE White List
From: Arun Kumar SINGH @ 2011-02-23 7:20 UTC (permalink / raw)
To: linux-bluetooth@vger.kernel.org
>From 1142406b33f6f279ee6913e0327e922c93c32e16 Mon Sep 17 00:00:00 2001
From: ArunKumarSingh <arunkr.singh@stericsson.com>
Date: Wed, 23 Feb 2011 12:26:39 +0530
Subject: [PATCH] HCI command to clear LE White list
Signed-off-by: ArunKumarSingh <arunkr.singh@stericsson.com>
---
lib/hci.c | 22 ++++++++++++++++++++++
lib/hci_lib.h | 1 +
tools/hcitool.c | 42 ++++++++++++++++++++++++++++++++++++++++++
3 files changed, 65 insertions(+), 0 deletions(-)
diff --git a/lib/hci.c b/lib/hci.c
index 2f36448..43f596f 100755
--- a/lib/hci.c
+++ b/lib/hci.c
@@ -1377,6 +1377,28 @@ int hci_le_read_white_list_size(int dd, int *size)
return 0;
}
+int hci_le_clear_white_list(int dd)
+{
+ struct hci_request rq;
+ uint8_t status;
+
+ memset(&rq, 0, sizeof(rq));
+ rq.ogf = OGF_LE_CTL;
+ rq.ocf = OCF_LE_CLEAR_WHITE_LIST;
+ rq.rparam = &status;
+ rq.rlen = 1;
+
+ if (hci_send_req(dd, &rq, 1000) < 0)
+ return -1;
+
+ if (status) {
+ errno = EIO;
+ return -1;
+ }
+
+ return 0;
+}
+
int hci_read_local_name(int dd, int len, char *name, int to)
{
read_local_name_rp rp;
diff --git a/lib/hci_lib.h b/lib/hci_lib.h
index d5f07f6..c86b0de 100755
--- a/lib/hci_lib.h
+++ b/lib/hci_lib.h
@@ -130,6 +130,7 @@ int hci_le_create_conn(int dd, uint16_t interval, uint16_t window,
int hci_le_add_to_white_list(int dd, const bdaddr_t *bdaddr, uint8_t type);
int hci_le_remove_from_white_list(int dd, const bdaddr_t *bdaddr, uint8_t type);
int hci_le_read_white_list_size(int dd, int *size);
+int hci_le_clear_white_list(int dd);
int hci_for_each_dev(int flag, int(*func)(int dd, int dev_id, long arg), long arg);
int hci_get_route(bdaddr_t *bdaddr);
diff --git a/tools/hcitool.c b/tools/hcitool.c
index fa65c4e..8ec4c20 100755
--- a/tools/hcitool.c
+++ b/tools/hcitool.c
@@ -2620,6 +2620,47 @@ static void cmd_lerdwlsz(int dev_id, int argc, char **argv)
}
}
+static struct option leclrwl_options[] = {
+ { "help", 0, 0, 'h' },
+ { 0, 0, 0, 0 }
+};
+
+static const char *leclrwl_help =
+ "Usage:\n"
+ "\tleclrwl\n";
+
+static void cmd_leclrwl(int dev_id, int argc, char **argv)
+{
+ int err, dd, opt;
+
+ for_each_opt(opt, leclrwl_options, NULL) {
+ switch (opt) {
+ default:
+ printf("%s", leclrwl_help);
+ return;
+ }
+ }
+
+ helper_arg(0, 0, &argc, &argv, leclrwl_help);
+
+ if (dev_id < 0)
+ dev_id = hci_get_route(NULL);
+
+ dd = hci_open_dev(dev_id);
+ if (dd < 0) {
+ perror("Could not open device");
+ exit(1);
+ }
+
+ err = hci_le_clear_white_list(dd);
+ hci_close_dev(dd);
+
+ if (err < 0) {
+ perror("Cant clear white list");
+ exit(1);
+ }
+}
+
static struct option ledc_options[] = {
{ "help", 0, 0, 'h' },
{ 0, 0, 0, 0 }
@@ -2699,6 +2740,7 @@ static struct {
{ "leaddwl", cmd_leaddwl, "Add this device to white list" },
{ "lermwl", cmd_lermwl, "Remove this device from white list" },
{ "lerdwlsz", cmd_lerdwlsz, "Read white list size" },
+ { "leclrwl", cmd_leclrwl, "Clear white list" },
{ "lecc", cmd_lecc, "Create a LE Connection", },
{ "ledc", cmd_ledc, "Disconnect a LE Connection", },
{ NULL, NULL, 0 }
--
1.7.0.4
^ permalink raw reply related
* [PATCH 3/4] HCI command to read size of LE White List
From: Arun Kumar SINGH @ 2011-02-23 7:11 UTC (permalink / raw)
To: linux-bluetooth@vger.kernel.org
>From 33f99e9cf42b4986e969488923d1710d8d7b2025 Mon Sep 17 00:00:00 2001
From: ArunKumarSingh <arunkr.singh@stericsson.com>
Date: Wed, 23 Feb 2011 12:23:13 +0530
Subject: [PATCH] HCI command to read size of White-List
Signed-off-by: ArunKumarSingh <arunkr.singh@stericsson.com>
---
lib/hci.c | 28 ++++++++++++++++++++++++++++
lib/hci_lib.h | 1 +
tools/hcitool.c | 42 ++++++++++++++++++++++++++++++++++++++++++
3 files changed, 71 insertions(+), 0 deletions(-)
diff --git a/lib/hci.c b/lib/hci.c
index 1ae2dc6..2f36448 100755
--- a/lib/hci.c
+++ b/lib/hci.c
@@ -1349,6 +1349,34 @@ int hci_le_remove_from_white_list(int dd, const bdaddr_t *bdaddr, uint8_t type)
return 0;
}
+int hci_le_read_white_list_size(int dd, int *size)
+{
+ struct hci_request rq;
+ le_read_white_list_size_rp rp;
+
+ memset(&rp, 0, sizeof(rp));
+ rp.size = 0;
+
+ memset(&rq, 0, sizeof(rq));
+ rq.ogf = OGF_LE_CTL;
+ rq.ocf = OCF_LE_READ_WHITE_LIST_SIZE;
+ rq.rparam = &rp;
+ rq.rlen = LE_READ_WHITE_LIST_SIZE_RP_SIZE;
+
+ if (hci_send_req(dd, &rq, 1000) < 0)
+ return -1;
+
+ if (rp.status) {
+ errno = EIO;
+ return -1;
+ }
+
+ if (size)
+ *size = rp.size;
+
+ return 0;
+}
+
int hci_read_local_name(int dd, int len, char *name, int to)
{
read_local_name_rp rp;
diff --git a/lib/hci_lib.h b/lib/hci_lib.h
index b42a91b..d5f07f6 100755
--- a/lib/hci_lib.h
+++ b/lib/hci_lib.h
@@ -129,6 +129,7 @@ int hci_le_create_conn(int dd, uint16_t interval, uint16_t window,
uint16_t *handle, int to);
int hci_le_add_to_white_list(int dd, const bdaddr_t *bdaddr, uint8_t type);
int hci_le_remove_from_white_list(int dd, const bdaddr_t *bdaddr, uint8_t type);
+int hci_le_read_white_list_size(int dd, int *size);
int hci_for_each_dev(int flag, int(*func)(int dd, int dev_id, long arg), long arg);
int hci_get_route(bdaddr_t *bdaddr);
diff --git a/tools/hcitool.c b/tools/hcitool.c
index 1118b07..fa65c4e 100755
--- a/tools/hcitool.c
+++ b/tools/hcitool.c
@@ -2579,6 +2579,47 @@ static void cmd_lermwl(int dev_id, int argc, char **argv)
}
}
+static struct option lerdwlsz_options[] = {
+ { "help", 0, 0, 'h' },
+ { 0, 0, 0, 0 }
+};
+
+static const char *lerdwlsz_help =
+ "Usage:\n"
+ "\tlerdwlsz\n";
+
+static void cmd_lerdwlsz(int dev_id, int argc, char **argv)
+{
+ int err, dd, opt, size;
+
+ for_each_opt(opt, lerdwlsz_options, NULL) {
+ switch (opt) {
+ default:
+ printf("%s", lerdwlsz_help);
+ return;
+ }
+ }
+
+ helper_arg(0, 0, &argc, &argv, lerdwlsz_help);
+
+ if (dev_id < 0)
+ dev_id = hci_get_route(NULL);
+
+ dd = hci_open_dev(dev_id);
+ if (dd < 0) {
+ perror("Could not open device");
+ exit(1);
+ }
+
+ err = hci_le_read_white_list_size(dd, &size);
+ hci_close_dev(dd);
+
+ if (err < 0) {
+ perror("Cant read white list size");
+ exit(1);
+ }
+}
+
static struct option ledc_options[] = {
{ "help", 0, 0, 'h' },
{ 0, 0, 0, 0 }
@@ -2657,6 +2698,7 @@ static struct {
{ "lescan", cmd_lescan, "Start LE scan" },
{ "leaddwl", cmd_leaddwl, "Add this device to white list" },
{ "lermwl", cmd_lermwl, "Remove this device from white list" },
+ { "lerdwlsz", cmd_lerdwlsz, "Read white list size" },
{ "lecc", cmd_lecc, "Create a LE Connection", },
{ "ledc", cmd_ledc, "Disconnect a LE Connection", },
{ NULL, NULL, 0 }
--
1.7.0.4
^ permalink raw reply related
* [PATCH 2/4] HCI command to remove device from LE White List
From: Arun Kumar SINGH @ 2011-02-23 7:09 UTC (permalink / raw)
To: linux-bluetooth@vger.kernel.org
>From 2c5038477842b3b73eea161d9610b2bd4100f338 Mon Sep 17 00:00:00 2001
From: ArunKumarSingh <arunkr.singh@stericsson.com>
Date: Wed, 23 Feb 2011 12:03:36 +0530
Subject: [PATCH] Command to remove device from Whitelist
Signed-off-by: ArunKumarSingh <arunkr.singh@stericsson.com>
---
lib/hci.c | 29 +++++++++++++++++++++++++++++
lib/hci_lib.h | 1 +
tools/hcitool.c | 47 +++++++++++++++++++++++++++++++++++++++++++++++
3 files changed, 77 insertions(+), 0 deletions(-)
diff --git a/lib/hci.c b/lib/hci.c
index a85f193..1ae2dc6 100755
--- a/lib/hci.c
+++ b/lib/hci.c
@@ -1320,6 +1320,35 @@ int hci_le_add_to_white_list(int dd, const bdaddr_t *bdaddr, uint8_t type)
return 0;
}
+int hci_le_remove_from_white_list(int dd, const bdaddr_t *bdaddr, uint8_t type)
+{
+ struct hci_request rq;
+ le_remove_device_from_white_list_cp cp;
+ uint8_t status;
+
+ memset(&cp, 0, sizeof(cp));
+ cp.bdaddr_type = type;
+ bacpy(&cp.bdaddr, bdaddr);
+
+ memset(&rq, 0, sizeof(rq));
+ rq.ogf = OGF_LE_CTL;
+ rq.ocf = OCF_LE_REMOVE_DEVICE_FROM_WHITE_LIST;
+ rq.cparam = &cp;
+ rq.clen = LE_REMOVE_DEVICE_FROM_WHITE_LIST_CP_SIZE;
+ rq.rparam = &status;
+ rq.rlen = 1;
+
+ if (hci_send_req(dd, &rq, 1000) < 0)
+ return -1;
+
+ if (status) {
+ errno = EIO;
+ return -1;
+ }
+
+ return 0;
+}
+
int hci_read_local_name(int dd, int len, char *name, int to)
{
read_local_name_rp rp;
diff --git a/lib/hci_lib.h b/lib/hci_lib.h
index 7127d70..b42a91b 100755
--- a/lib/hci_lib.h
+++ b/lib/hci_lib.h
@@ -128,6 +128,7 @@ int hci_le_create_conn(int dd, uint16_t interval, uint16_t window,
uint16_t min_ce_length, uint16_t max_ce_length,
uint16_t *handle, int to);
int hci_le_add_to_white_list(int dd, const bdaddr_t *bdaddr, uint8_t type);
+int hci_le_remove_from_white_list(int dd, const bdaddr_t *bdaddr, uint8_t type);
int hci_for_each_dev(int flag, int(*func)(int dd, int dev_id, long arg), long arg);
int hci_get_route(bdaddr_t *bdaddr);
diff --git a/tools/hcitool.c b/tools/hcitool.c
index b5109b8..1118b07 100755
--- a/tools/hcitool.c
+++ b/tools/hcitool.c
@@ -2533,6 +2533,52 @@ static void cmd_leaddwl(int dev_id, int argc, char **argv)
}
}
+static struct option lermwl_options[] = {
+ { "help", 0, 0, 'h' },
+ { 0, 0, 0, 0 }
+};
+
+static const char *lermwl_help =
+ "Usage:\n"
+ "\tlermwl <bdaddr>\n";
+
+static void cmd_lermwl(int dev_id, int argc, char **argv)
+{
+ int err, opt, dd;
+ bdaddr_t bdaddr;
+ le_device_addr_type bdaddr_type;
+
+ for_each_opt(opt, lermwl_options, NULL) {
+ switch (opt) {
+ default:
+ printf("%s", lermwl_help);
+ return;
+ }
+ }
+
+ helper_arg(1, 1, &argc, &argv, lermwl_help);
+
+ if (dev_id < 0)
+ dev_id = hci_get_route(NULL);
+
+ dd = hci_open_dev(dev_id);
+ if (dd < 0) {
+ perror("Could not open device");
+ exit(1);
+ }
+
+ str2ba(argv[0], &bdaddr);
+ bdaddr_type = LE_PUBLIC_DEVICE_ADDR;
+
+ err = hci_le_remove_from_white_list(dd, &bdaddr, bdaddr_type);
+ hci_close_dev(dd);
+
+ if (err < 0) {
+ perror("Cant remove from white list");
+ exit(1);
+ }
+}
+
static struct option ledc_options[] = {
{ "help", 0, 0, 'h' },
{ 0, 0, 0, 0 }
@@ -2610,6 +2656,7 @@ static struct {
{ "clock", cmd_clock, "Read local or remote clock" },
{ "lescan", cmd_lescan, "Start LE scan" },
{ "leaddwl", cmd_leaddwl, "Add this device to white list" },
+ { "lermwl", cmd_lermwl, "Remove this device from white list" },
{ "lecc", cmd_lecc, "Create a LE Connection", },
{ "ledc", cmd_ledc, "Disconnect a LE Connection", },
{ NULL, NULL, 0 }
--
1.7.0.4
^ permalink raw reply related
* [PATCH 1/4] HCI command to add device in LE White List
From: Arun Kumar SINGH @ 2011-02-23 7:07 UTC (permalink / raw)
To: linux-bluetooth@vger.kernel.org
>From fd4e7d6f3b9b33c7b75f7da5600c6fc0fb947b06 Mon Sep 17 00:00:00 2001
From: ArunKumarSingh <arunkr.singh@stericsson.com>
Date: Wed, 23 Feb 2011 11:24:58 +0530
Subject: [PATCH] Commands to add device to White-list
---
lib/hci.c | 29 +++++++++++++++++++++++++++++
lib/hci.h | 5 +++++
lib/hci_lib.h | 1 +
tools/hcitool.c | 47 +++++++++++++++++++++++++++++++++++++++++++++++
4 files changed, 82 insertions(+), 0 deletions(-)
mode change 100644 => 100755 lib/hci.c
mode change 100644 => 100755 lib/hci.h
mode change 100644 => 100755 lib/hci_lib.h
mode change 100644 => 100755 tools/hcitool.c
diff --git a/lib/hci.c b/lib/hci.c
old mode 100644
new mode 100755
index 048fda4..a85f193
--- a/lib/hci.c
+++ b/lib/hci.c
@@ -1291,6 +1291,35 @@ int hci_disconnect(int dd, uint16_t handle, uint8_t reason, int to)
return 0;
}
+int hci_le_add_to_white_list(int dd, const bdaddr_t *bdaddr, uint8_t type)
+{
+ struct hci_request rq;
+ le_add_device_to_white_list_cp cp;
+ uint8_t status;
+
+ memset(&cp, 0, sizeof(cp));
+ cp.bdaddr_type = type;
+ bacpy(&cp.bdaddr, bdaddr);
+
+ memset(&rq, 0, sizeof(rq));
+ rq.ogf = OGF_LE_CTL;
+ rq.ocf = OCF_LE_ADD_DEVICE_TO_WHITE_LIST;
+ rq.cparam = &cp;
+ rq.clen = LE_ADD_DEVICE_TO_WHITE_LIST_CP_SIZE;
+ rq.rparam = &status;
+ rq.rlen = 1;
+
+ if (hci_send_req(dd, &rq, 1000) < 0)
+ return -1;
+
+ if (status) {
+ errno = EIO;
+ return -1;
+ }
+
+ return 0;
+}
+
int hci_read_local_name(int dd, int len, char *name, int to)
{
read_local_name_rp rp;
diff --git a/lib/hci.h b/lib/hci.h
old mode 100644
new mode 100755
index 9b5388b..06d0b35
--- a/lib/hci.h
+++ b/lib/hci.h
@@ -1523,6 +1523,11 @@ typedef struct {
#define OCF_LE_CREATE_CONN_CANCEL 0x000E
+typedef enum {
+ LE_PUBLIC_DEVICE_ADDR = 0x00,
+ LE_RANDOM_DEVICE_ADDR = 0x01,
+}le_device_addr_type;
+
#define OCF_LE_READ_WHITE_LIST_SIZE 0x000F
typedef struct {
uint8_t status;
diff --git a/lib/hci_lib.h b/lib/hci_lib.h
old mode 100644
new mode 100755
index b63a2a4..7127d70
--- a/lib/hci_lib.h
+++ b/lib/hci_lib.h
@@ -127,6 +127,7 @@ int hci_le_create_conn(int dd, uint16_t interval, uint16_t window,
uint16_t latency, uint16_t supervision_timeout,
uint16_t min_ce_length, uint16_t max_ce_length,
uint16_t *handle, int to);
+int hci_le_add_to_white_list(int dd, const bdaddr_t *bdaddr, uint8_t type);
int hci_for_each_dev(int flag, int(*func)(int dd, int dev_id, long arg), long arg);
int hci_get_route(bdaddr_t *bdaddr);
diff --git a/tools/hcitool.c b/tools/hcitool.c
old mode 100644
new mode 100755
index d7a82cc..b5109b8
--- a/tools/hcitool.c
+++ b/tools/hcitool.c
@@ -2487,6 +2487,52 @@ static void cmd_lecc(int dev_id, int argc, char **argv)
hci_close_dev(dd);
}
+static struct option leaddwl_options[] = {
+ { "help", 0, 0, 'h' },
+ { 0, 0, 0, 0 }
+};
+
+static const char *leaddwl_help =
+ "Usage:\n"
+ "\tleaddwl\n";
+
+static void cmd_leaddwl(int dev_id, int argc, char **argv)
+{
+ int err, opt, dd;
+ bdaddr_t bdaddr;
+ le_device_addr_type bdaddr_type;
+
+ for_each_opt(opt, leaddwl_options, NULL) {
+ switch (opt) {
+ default:
+ printf("%s", leaddwl_help);
+ return;
+ }
+ }
+
+ helper_arg(1, 1, &argc, &argv, leaddwl_help);
+
+ if (dev_id < 0)
+ dev_id = hci_get_route(NULL);
+
+ dd = hci_open_dev(dev_id);
+ if (dd < 0) {
+ perror("Could not open device");
+ exit(1);
+ }
+
+ str2ba(argv[0], &bdaddr);
+ bdaddr_type = LE_PUBLIC_DEVICE_ADDR;
+
+ err = hci_le_add_to_white_list(dd, &bdaddr, bdaddr_type);
+ hci_close_dev(dd);
+
+ if (err < 0) {
+ perror("Cant add to white list");
+ exit(1);
+ }
+}
+
static struct option ledc_options[] = {
{ "help", 0, 0, 'h' },
{ 0, 0, 0, 0 }
@@ -2563,6 +2609,7 @@ static struct {
{ "clkoff", cmd_clkoff, "Read clock offset" },
{ "clock", cmd_clock, "Read local or remote clock" },
{ "lescan", cmd_lescan, "Start LE scan" },
+ { "leaddwl", cmd_leaddwl, "Add this device to white list" },
{ "lecc", cmd_lecc, "Create a LE Connection", },
{ "ledc", cmd_ledc, "Disconnect a LE Connection", },
{ NULL, NULL, 0 }
--
1.7.0.4
^ permalink raw reply related
* Re: [PATCH 3/3] Add hcitool command to change the parameters of a given LE connection
From: Johan Hedberg @ 2011-02-23 3:29 UTC (permalink / raw)
To: Claudio Takahasi; +Cc: linux-bluetooth
In-Reply-To: <1298410927-9165-3-git-send-email-claudio.takahasi@openbossa.org>
Hi Claudio,
On Tue, Feb 22, 2011, Claudio Takahasi wrote:
> Allows the LE master to start the Connection Parameter Update Procedure.
> Parameters values consistency are not verified on purpose allowing
> invalid values to test fail scenarios.
> ---
> tools/hcitool.c | 86 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
All three patches have been pushed upstream. Thanks.
Johan
^ permalink raw reply
* Re: [PATCHv2 2/5] Initial Client Characteristic Configuration implementation
From: Johan Hedberg @ 2011-02-23 3:26 UTC (permalink / raw)
To: Anderson Lizardo; +Cc: linux-bluetooth
In-Reply-To: <1298408491-11154-2-git-send-email-anderson.lizardo@openbossa.org>
Hi Lizardo,
On Tue, Feb 22, 2011, Anderson Lizardo wrote:
> +static uint8_t client_set_notifications(struct attribute *attr,
> + gpointer user_data)
> +{
> + struct gatt_channel *channel = user_data;
> + struct attribute *a, *last_chr_val = NULL;
> + uint16_t handle, cfg_val;
> + uuid_t uuid;
> + GSList *l;
> +
> + cfg_val = att_get_u16(attr->data);
> +
> + sdp_uuid16_create(&uuid, GATT_CHARAC_UUID);
> + for (l = database, handle = 0; l != NULL; l = l->next) {
> + a = l->data;
The variable "a" is only used inside the for-loop so it should be
declared inside it as well. I think you can move handle inside the loop
as well as long as you declare it static (so it only gets initialized to
0 on the first iteration).
Johan
^ permalink raw reply
* Re: [PATCHv2 1/5] Add read/write callbacks to attribute server
From: Johan Hedberg @ 2011-02-23 3:21 UTC (permalink / raw)
To: Anderson Lizardo; +Cc: linux-bluetooth
In-Reply-To: <1298408491-11154-1-git-send-email-anderson.lizardo@openbossa.org>
Hi Anderson,
On Tue, Feb 22, 2011, Anderson Lizardo wrote:
> +struct attribute;
> +
> +typedef uint8_t (*att_cb_t)(struct attribute *a, gpointer user_data);
> +
> struct attribute {
> uint16_t handle;
> uuid_t uuid;
> int read_reqs;
> int write_reqs;
> + att_cb_t read_cb;
> + att_cb_t write_cb;
> + gpointer cb_user_data;
> int len;
> uint8_t data[0];
> };
I'm not really a fan of the needed forward declaration here. I can't
find you using "att_cb_t" anywhere else in your patches, so how about
just having the full type of the callbacks inside the struct definition
and skip the typedef completely?
Johan
^ permalink raw reply
* Re: [PATCH 7/7] TODO: Add item to support characteristic authorization in the agent
From: Johan Hedberg @ 2011-02-23 3:10 UTC (permalink / raw)
To: Claudio Takahasi; +Cc: linux-bluetooth
In-Reply-To: <1298407391-19260-7-git-send-email-claudio.takahasi@openbossa.org>
Hi Claudio,
On Tue, Feb 22, 2011, Claudio Takahasi wrote:
> ---
> TODO | 6 ++++++
> 1 files changed, 6 insertions(+), 0 deletions(-)
All seven TODO patches have been pushed upstream. Thanks.
Johan
^ permalink raw reply
* Re: [PATCH v2 3/7] Create helper functions to deal with handles on interactive gatttool
From: Johan Hedberg @ 2011-02-23 3:09 UTC (permalink / raw)
To: Sheldon Demario; +Cc: linux-bluetooth
In-Reply-To: <1298401924-20094-3-git-send-email-sheldon.demario@openbossa.org>
Hi Sheldon,
On Tue, Feb 22, 2011, Sheldon Demario wrote:
> + *dst = strtoll(src, &e, 16);
> + if (errno != 0 || *e != '\0') {
> + return -1;
> }
Firstly, you've got a coding style issue here: no {} for one-line
scopes. Secondly, are you sure that this is the right way to check for
strtoll failure? If there was some earlier libc function that failed
errno might be set to != 0 even if strtoll succeeds, right? Or are all
errno using libc functions guaranteed to set errno to 0 on success?
Reading the man-page of strtoll it seems you should be checking for
LLONG_MIN and LLONG_MAX return values.
I've pushed the first two patches since they were fine, but I'll stop
here until we get some clarification on this matter.
Johan
^ permalink raw reply
* Re: [PATCH] Fix potential bug in le_advertising_report()
From: Johan Hedberg @ 2011-02-23 3:00 UTC (permalink / raw)
To: Andre Guedes; +Cc: linux-bluetooth
In-Reply-To: <1298396669-5530-1-git-send-email-andre.guedes@openbossa.org>
Hi André,
On Tue, Feb 22, 2011, Andre Guedes wrote:
> In the current implementation of le_advertising_report(), the variable
> 'info' has an invalid memory address after the 'for' loop. If 'info'
> is dereferenced it will access invalid memory.
>
> This patch fixes this potential bug and improves the code's readability.
> ---
> plugins/hciops.c | 15 ++++++++++-----
> 1 files changed, 10 insertions(+), 5 deletions(-)
The patch has been pushed upstream. Thanks.
Johan
^ permalink raw reply
* [PATCH 3/3] Add hcitool command to change the parameters of a given LE connection
From: Claudio Takahasi @ 2011-02-22 21:42 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Claudio Takahasi
In-Reply-To: <1298410927-9165-1-git-send-email-claudio.takahasi@openbossa.org>
Allows the LE master to start the Connection Parameter Update Procedure.
Parameters values consistency are not verified on purpose allowing
invalid values to test fail scenarios.
---
tools/hcitool.c | 86 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
1 files changed, 86 insertions(+), 0 deletions(-)
diff --git a/tools/hcitool.c b/tools/hcitool.c
index 875e25e..8c147bf 100644
--- a/tools/hcitool.c
+++ b/tools/hcitool.c
@@ -2533,6 +2533,91 @@ static void cmd_ledc(int dev_id, int argc, char **argv)
hci_close_dev(dd);
}
+static struct option lecup_options[] = {
+ { "help", 0, 0, 'h' },
+ { "handle", 1, 0, 'H' },
+ { "min", 1, 0, 'm' },
+ { "max", 1, 0, 'M' },
+ { "latency", 1, 0, 'l' },
+ { "timeout", 1, 0, 't' },
+ { 0, 0, 0, 0 }
+};
+
+static const char *lecup_help =
+ "Usage:\n"
+ "\tlecup <handle> <min> <max> <latency> <timeout>\n"
+ "\tOptions:\n"
+ "\t -H, --handle <0xXXXX> LE connection handle\n"
+ "\t -m, --min <interval> Range: 0x0006 to 0x0C80\n"
+ "\t -M, --max <interval> Range: 0x0006 to 0x0C80\n"
+ "\t -l, --latency <range> Slave latency. Range: 0x0000 to 0x03E8\n"
+ "\t -t, --timeout <time> N * 10ms. Range: 0x000A to 0x0C80\n"
+ "\n\t min/max range: 7.5ms to 4s. Multiply factor: 1.25ms"
+ "\n\t timeout range: 100ms to 32.0s. Larger than max interval\n";
+
+static void cmd_lecup(int dev_id, int argc, char **argv)
+{
+ uint16_t handle = 0, min, max, latency, timeout;
+ int opt, dd, base;
+
+ /* Aleatory valid values */
+ min = 0x0C8;
+ max = 0x0960;
+ latency = 0x0007;
+ timeout = 0x0C80;
+
+ for_each_opt(opt, lecup_options, NULL) {
+ if (optarg && strncasecmp("0x", optarg, 2) == 0)
+ base = 16;
+ else
+ base = 10;
+
+ switch (opt) {
+ case 'H':
+ handle = strtoul(optarg, NULL, base);
+ break;
+ case 'm':
+ min = strtoul(optarg, NULL, base);
+ break;
+ case 'M':
+ max = strtoul(optarg, NULL, base);
+ break;
+ case 'l':
+ latency = strtoul(optarg, NULL, base);
+ break;
+ case 't':
+ timeout = strtoul(optarg, NULL, base);
+ break;
+ default:
+ printf("%s", lecup_help);
+ return;
+ }
+ }
+
+ if (handle == 0) {
+ printf("%s", lecup_help);
+ return;
+ }
+
+ if (dev_id < 0)
+ dev_id = hci_get_route(NULL);
+
+ dd = hci_open_dev(dev_id);
+ if (dd < 0) {
+ fprintf(stderr, "HCI device open failed\n");
+ exit(1);
+ }
+
+ if (hci_le_conn_update(dd, htobs(handle), htobs(min), htobs(max),
+ htobs(latency), htobs(timeout), 5000) < 0) {
+ int err = errno;
+ fprintf(stderr, "Could not change connection params: %s(%d)\n",
+ strerror(err), err);
+ }
+
+ hci_close_dev(dd);
+}
+
static struct {
char *cmd;
void (*func)(int dev_id, int argc, char **argv);
@@ -2565,6 +2650,7 @@ static struct {
{ "lescan", cmd_lescan, "Start LE scan" },
{ "lecc", cmd_lecc, "Create a LE Connection" },
{ "ledc", cmd_ledc, "Disconnect a LE Connection" },
+ { "lecup", cmd_lecup, "LE Connection Update" },
{ NULL, NULL, 0 }
};
--
1.7.4.1
^ permalink raw reply related
* [PATCH 2/3] Add hci utility function to change LE connection parameters
From: Claudio Takahasi @ 2011-02-22 21:42 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Claudio Takahasi
In-Reply-To: <1298410927-9165-1-git-send-email-claudio.takahasi@openbossa.org>
---
lib/hci.c | 37 +++++++++++++++++++++++++++++++++++++
lib/hci_lib.h | 4 ++++
2 files changed, 41 insertions(+), 0 deletions(-)
diff --git a/lib/hci.c b/lib/hci.c
index 048fda4..688b0b4 100644
--- a/lib/hci.c
+++ b/lib/hci.c
@@ -2767,3 +2767,40 @@ int hci_le_create_conn(int dd, uint16_t interval, uint16_t window,
return 0;
}
+
+int hci_le_conn_update(int dd, uint16_t handle, uint16_t min_interval,
+ uint16_t max_interval, uint16_t latency,
+ uint16_t supervision_timeout, int to)
+{
+ evt_le_connection_update_complete evt;
+ le_connection_update_cp cp;
+ struct hci_request rq;
+
+ memset(&cp, 0, sizeof(cp));
+ cp.handle = handle;
+ cp.min_interval = min_interval;
+ cp.max_interval = max_interval;
+ cp.latency = latency;
+ cp.supervision_timeout = supervision_timeout;
+ cp.min_ce_length = htobs(0x0001);
+ cp.max_ce_length = htobs(0x0001);
+
+ memset(&rq, 0, sizeof(rq));
+ rq.ogf = OGF_LE_CTL;
+ rq.ocf = OCF_LE_CONN_UPDATE;
+ rq.cparam = &cp;
+ rq.clen = LE_CONN_UPDATE_CP_SIZE;
+ rq.event = EVT_LE_CONN_UPDATE_COMPLETE;
+ rq.rparam = &evt;
+ rq.rlen = sizeof(evt);
+
+ if (hci_send_req(dd, &rq, to) < 0)
+ return -1;
+
+ if (evt.status) {
+ errno = EIO;
+ return -1;
+ }
+
+ return 0;
+}
diff --git a/lib/hci_lib.h b/lib/hci_lib.h
index b63a2a4..5be8d50 100644
--- a/lib/hci_lib.h
+++ b/lib/hci_lib.h
@@ -128,6 +128,10 @@ int hci_le_create_conn(int dd, uint16_t interval, uint16_t window,
uint16_t min_ce_length, uint16_t max_ce_length,
uint16_t *handle, int to);
+int hci_le_conn_update(int dd, uint16_t handle, uint16_t min_interval,
+ uint16_t max_interval, uint16_t latency,
+ uint16_t supervision_timeout, int to);
+
int hci_for_each_dev(int flag, int(*func)(int dd, int dev_id, long arg), long arg);
int hci_get_route(bdaddr_t *bdaddr);
--
1.7.4.1
^ permalink raw reply related
* [PATCH 1/3] Remove unneeded comma in the hcitool commands declaration
From: Claudio Takahasi @ 2011-02-22 21:42 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Claudio Takahasi
---
tools/hcitool.c | 4 ++--
1 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/tools/hcitool.c b/tools/hcitool.c
index d7a82cc..875e25e 100644
--- a/tools/hcitool.c
+++ b/tools/hcitool.c
@@ -2563,8 +2563,8 @@ static struct {
{ "clkoff", cmd_clkoff, "Read clock offset" },
{ "clock", cmd_clock, "Read local or remote clock" },
{ "lescan", cmd_lescan, "Start LE scan" },
- { "lecc", cmd_lecc, "Create a LE Connection", },
- { "ledc", cmd_ledc, "Disconnect a LE Connection", },
+ { "lecc", cmd_lecc, "Create a LE Connection" },
+ { "ledc", cmd_ledc, "Disconnect a LE Connection" },
{ NULL, NULL, 0 }
};
--
1.7.4.1
^ permalink raw reply related
* [PATCHv2 5/5] Implement ATT handle indication
From: Anderson Lizardo @ 2011-02-22 21:01 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Elvis Pfützenreuter
In-Reply-To: <1298323843-31106-1-git-send-email-anderson.lizardo@openbossa.org>
From: Elvis Pfützenreuter <epx@signove.com>
---
src/attrib-server.c | 40 ++++++++++++++++++++++++++++++++++++++++
1 files changed, 40 insertions(+), 0 deletions(-)
diff --git a/src/attrib-server.c b/src/attrib-server.c
index 8fcfa89..dc4d864 100644
--- a/src/attrib-server.c
+++ b/src/attrib-server.c
@@ -61,6 +61,8 @@ struct gatt_channel {
guint mtu;
guint id;
gboolean encrypted;
+ guint outstanding_indications;
+ time_t oldest_indication;
};
struct group_elem {
@@ -888,6 +890,10 @@ static void channel_handler(const uint8_t *ipdu, uint16_t len,
length = find_by_type(start, end, &uuid, value, vlen,
opdu, channel->mtu);
break;
+ case ATT_OP_HANDLE_CNF:
+ if (channel->outstanding_indications)
+ channel->outstanding_indications -= 1;
+ return;
case ATT_OP_READ_MULTI_REQ:
case ATT_OP_PREP_WRITE_REQ:
case ATT_OP_EXEC_WRITE_REQ:
@@ -967,8 +973,11 @@ static void confirm_event(GIOChannel *io, void *user_data)
static void attrib_notify_clients(struct attribute *attr)
{
guint handle = attr->handle;
+ time_t now;
GSList *l;
+ time(&now);
+
for (l = clients; l; l = l->next) {
struct gatt_channel *channel = l->data;
@@ -985,6 +994,37 @@ static void attrib_notify_clients(struct attribute *attr)
g_attrib_send(channel->attrib, 0, pdu[0], pdu, len,
NULL, NULL, NULL);
}
+
+ /* The outstanding_indications variable counts how many
+ * unconfirmed indications have been sent. The oldest_indication
+ * variable gives a small time frame to accomodate
+ * almost-concomitant indications, sending both without forcing
+ * a serialization.
+ *
+ * Indications are withheld once oldest_indication is older than
+ * at least 1 second and there are pending confirmations. */
+
+ if (channel->outstanding_indications &&
+ (now - channel->oldest_indication) > 1)
+ continue;
+
+ /* Indication */
+ if (g_slist_find_custom(channel->indicate,
+ GUINT_TO_POINTER(handle), handle_cmp) != NULL) {
+ uint8_t pdu[ATT_MAX_MTU];
+ uint16_t len;
+
+ len = enc_indication(attr, pdu, channel->mtu);
+ if (len == 0)
+ continue;
+
+ g_attrib_send(channel->attrib, 0, pdu[0], pdu, len,
+ NULL, NULL, NULL);
+
+ channel->outstanding_indications += 1;
+ if (channel->outstanding_indications == 1)
+ channel->oldest_indication = now;
+ }
}
}
--
1.7.0.4
^ permalink raw reply related
* [PATCHv2 4/5] Implement server-side ATT handle notification
From: Anderson Lizardo @ 2011-02-22 21:01 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Andre Dieb Martins
In-Reply-To: <1298323843-31106-1-git-send-email-anderson.lizardo@openbossa.org>
From: Andre Dieb Martins <andre.dieb@signove.com>
Adds an initial version of ATT handle notification. Notifications are sent to
interested clients (based on the Client Characteristic Configuration) always
when the attribute is updated.
This enables services to call db_attrib_update() and send notifications on their
own terms.
---
src/attrib-server.c | 26 ++++++++++++++++++++++++++
1 files changed, 26 insertions(+), 0 deletions(-)
diff --git a/src/attrib-server.c b/src/attrib-server.c
index aa24985..8fcfa89 100644
--- a/src/attrib-server.c
+++ b/src/attrib-server.c
@@ -964,6 +964,30 @@ static void confirm_event(GIOChannel *io, void *user_data)
return;
}
+static void attrib_notify_clients(struct attribute *attr)
+{
+ guint handle = attr->handle;
+ GSList *l;
+
+ for (l = clients; l; l = l->next) {
+ struct gatt_channel *channel = l->data;
+
+ /* Notification */
+ if (g_slist_find_custom(channel->notify,
+ GUINT_TO_POINTER(handle), handle_cmp)) {
+ uint8_t pdu[ATT_MAX_MTU];
+ uint16_t len;
+
+ len = enc_notification(attr, pdu, channel->mtu);
+ if (len == 0)
+ continue;
+
+ g_attrib_send(channel->attrib, 0, pdu[0], pdu, len,
+ NULL, NULL, NULL);
+ }
+ }
+}
+
static gboolean register_core_services(void)
{
uint8_t atval[256];
@@ -1208,6 +1232,8 @@ int attrib_db_update(uint16_t handle, uuid_t *uuid, const uint8_t *value,
a->len = len;
memcpy(a->data, value, len);
+ attrib_notify_clients(a);
+
return 0;
}
--
1.7.0.4
^ permalink raw reply related
* [PATCHv2 3/5] Check permissions before setting client configs
From: Anderson Lizardo @ 2011-02-22 21:01 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Andre Dieb Martins
In-Reply-To: <1298323843-31106-1-git-send-email-anderson.lizardo@openbossa.org>
From: Andre Dieb Martins <andre.dieb@signove.com>
Only enable notification/indication if the descriptor allows it.
---
src/attrib-server.c | 11 ++++++++---
1 files changed, 8 insertions(+), 3 deletions(-)
diff --git a/src/attrib-server.c b/src/attrib-server.c
index 8c74a5b..aa24985 100644
--- a/src/attrib-server.c
+++ b/src/attrib-server.c
@@ -199,19 +199,21 @@ static uint8_t client_set_notifications(struct attribute *attr,
struct gatt_channel *channel = user_data;
struct attribute *a, *last_chr_val = NULL;
uint16_t handle, cfg_val;
+ uint8_t perm;
uuid_t uuid;
GSList *l;
cfg_val = att_get_u16(attr->data);
sdp_uuid16_create(&uuid, GATT_CHARAC_UUID);
- for (l = database, handle = 0; l != NULL; l = l->next) {
+ for (l = database, handle = 0, perm = 0; l != NULL; l = l->next) {
a = l->data;
if (a->handle >= attr->handle)
break;
if (sdp_uuid_cmp(&a->uuid, &uuid) == 0) {
+ perm = att_get_u8(&a->data[0]);
handle = att_get_u16(&a->data[1]);
continue;
}
@@ -223,8 +225,11 @@ static uint8_t client_set_notifications(struct attribute *attr,
if (last_chr_val == NULL)
return 0;
- /* FIXME: Characteristic properties shall be checked for
- * Notification/Indication permissions. */
+ if ((cfg_val & 0x0001) && !(perm & ATT_CHAR_PROPER_NOTIFY))
+ return ATT_ECODE_WRITE_NOT_PERM;
+
+ if ((cfg_val & 0x0002) && !(perm & ATT_CHAR_PROPER_INDICATE))
+ return ATT_ECODE_WRITE_NOT_PERM;
if (cfg_val & 0x0001)
channel->notify = g_slist_append(channel->notify, last_chr_val);
--
1.7.0.4
^ permalink raw reply related
* [PATCHv2 2/5] Initial Client Characteristic Configuration implementation
From: Anderson Lizardo @ 2011-02-22 21:01 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Anderson Lizardo
In-Reply-To: <1298323843-31106-1-git-send-email-anderson.lizardo@openbossa.org>
This initial version creates a private copy of the Client Configuration
attribute for each client on the first write to that attribute. Further
reads/writes should use the client's private copy.
Two list of attributes are created: one for values to be indicated and
another for values to be notified. The actual notification/indication
sending is implemented in a separate commit.
This initial version also does not check for the characteristic
properties, which is implemented in a separate commit as well.
---
src/attrib-server.c | 180 ++++++++++++++++++++++++++++++++++++++++++---------
1 files changed, 149 insertions(+), 31 deletions(-)
diff --git a/src/attrib-server.c b/src/attrib-server.c
index 28649f1..8c74a5b 100644
--- a/src/attrib-server.c
+++ b/src/attrib-server.c
@@ -54,6 +54,9 @@ static GSList *database = NULL;
struct gatt_channel {
bdaddr_t src;
bdaddr_t dst;
+ GSList *configs;
+ GSList *notify;
+ GSList *indicate;
GAttrib *attrib;
guint mtu;
guint id;
@@ -143,6 +146,22 @@ static sdp_record_t *server_record_new(uuid_t *uuid, uint16_t start, uint16_t en
return record;
}
+static int handle_cmp(gconstpointer a, gconstpointer b)
+{
+ const struct attribute *attrib = a;
+ uint16_t handle = GPOINTER_TO_UINT(b);
+
+ return attrib->handle - handle;
+}
+
+static int attribute_cmp(gconstpointer a1, gconstpointer a2)
+{
+ const struct attribute *attrib1 = a1;
+ const struct attribute *attrib2 = a2;
+
+ return attrib1->handle - attrib2->handle;
+}
+
static uint8_t att_check_reqs(struct gatt_channel *channel, uint8_t opcode,
int reqs)
{
@@ -174,6 +193,92 @@ static uint8_t att_check_reqs(struct gatt_channel *channel, uint8_t opcode,
return 0;
}
+static uint8_t client_set_notifications(struct attribute *attr,
+ gpointer user_data)
+{
+ struct gatt_channel *channel = user_data;
+ struct attribute *a, *last_chr_val = NULL;
+ uint16_t handle, cfg_val;
+ uuid_t uuid;
+ GSList *l;
+
+ cfg_val = att_get_u16(attr->data);
+
+ sdp_uuid16_create(&uuid, GATT_CHARAC_UUID);
+ for (l = database, handle = 0; l != NULL; l = l->next) {
+ a = l->data;
+
+ if (a->handle >= attr->handle)
+ break;
+
+ if (sdp_uuid_cmp(&a->uuid, &uuid) == 0) {
+ handle = att_get_u16(&a->data[1]);
+ continue;
+ }
+
+ if (handle && a->handle == handle)
+ last_chr_val = a;
+ }
+
+ if (last_chr_val == NULL)
+ return 0;
+
+ /* FIXME: Characteristic properties shall be checked for
+ * Notification/Indication permissions. */
+
+ if (cfg_val & 0x0001)
+ channel->notify = g_slist_append(channel->notify, last_chr_val);
+ else
+ channel->notify = g_slist_remove(channel->notify, last_chr_val);
+
+ if (cfg_val & 0x0002)
+ channel->indicate = g_slist_append(channel->indicate,
+ last_chr_val);
+ else
+ channel->indicate = g_slist_remove(channel->indicate,
+ last_chr_val);
+
+ return 0;
+}
+
+static struct attribute *client_cfg_attribute(struct gatt_channel *channel,
+ struct attribute *orig_attr,
+ const uint8_t *value, int vlen)
+{
+ uuid_t uuid;
+ GSList *l;
+ guint handle = orig_attr->handle;
+
+ sdp_uuid16_create(&uuid, GATT_CLIENT_CHARAC_CFG_UUID);
+ if (sdp_uuid_cmp(&orig_attr->uuid, &uuid) != 0)
+ return NULL;
+
+ /* Value is unchanged, not need to create a private copy yet */
+ if (vlen == orig_attr->len && memcmp(orig_attr->data, value, vlen) == 0)
+ return orig_attr;
+
+ l = g_slist_find_custom(channel->configs, GUINT_TO_POINTER(handle),
+ handle_cmp);
+ if (!l) {
+ struct attribute *a;
+
+ /* Create a private copy of the Client Characteristic
+ * Configuration attribute */
+ a = g_malloc0(sizeof(*a) + vlen);
+ memcpy(a, orig_attr, sizeof(*a));
+ memcpy(a->data, value, vlen);
+ a->write_cb = client_set_notifications;
+ a->cb_user_data = channel;
+
+ channel->configs = g_slist_insert_sorted(channel->configs, a,
+ attribute_cmp);
+
+ return a;
+ }
+
+ return l->data;
+}
+
static uint16_t read_by_group(struct gatt_channel *channel, uint16_t start,
uint16_t end, uuid_t *uuid,
uint8_t *pdu, int len)
@@ -202,6 +307,8 @@ static uint16_t read_by_group(struct gatt_channel *channel, uint16_t start,
last_handle = end;
for (l = database, groups = NULL; l; l = l->next) {
+ struct attribute *client_attr;
+
a = l->data;
if (a->handle < start)
@@ -230,6 +337,10 @@ static uint16_t read_by_group(struct gatt_channel *channel, uint16_t start,
status = att_check_reqs(channel, ATT_OP_READ_BY_GROUP_REQ,
a->read_reqs);
+ client_attr = client_cfg_attribute(channel, a, a->data, a->len);
+ if (client_attr)
+ a = client_attr;
+
if (status == 0x00 && a->read_cb)
status = a->read_cb(a, a->cb_user_data);
@@ -308,6 +419,8 @@ static uint16_t read_by_type(struct gatt_channel *channel, uint16_t start,
ATT_ECODE_INVALID_HANDLE, pdu, len);
for (l = database, length = 0, types = NULL; l; l = l->next) {
+ struct attribute *client_attr;
+
a = l->data;
if (a->handle < start)
@@ -322,6 +435,10 @@ static uint16_t read_by_type(struct gatt_channel *channel, uint16_t start,
status = att_check_reqs(channel, ATT_OP_READ_BY_TYPE_REQ,
a->read_reqs);
+ client_attr = client_cfg_attribute(channel, a, a->data, a->len);
+ if (client_attr)
+ a = client_attr;
+
if (status == 0x00 && a->read_cb)
status = a->read_cb(a, a->cb_user_data);
@@ -506,22 +623,6 @@ static int find_by_type(uint16_t start, uint16_t end, uuid_t *uuid,
return len;
}
-static int handle_cmp(gconstpointer a, gconstpointer b)
-{
- const struct attribute *attrib = a;
- uint16_t handle = GPOINTER_TO_UINT(b);
-
- return attrib->handle - handle;
-}
-
-static int attribute_cmp(gconstpointer a1, gconstpointer a2)
-{
- const struct attribute *attrib1 = a1;
- const struct attribute *attrib2 = a2;
-
- return attrib1->handle - attrib2->handle;
-}
-
static struct attribute *find_primary_range(uint16_t start, uint16_t *end)
{
struct attribute *attrib;
@@ -559,7 +660,7 @@ static struct attribute *find_primary_range(uint16_t start, uint16_t *end)
static uint16_t read_value(struct gatt_channel *channel, uint16_t handle,
uint8_t *pdu, int len)
{
- struct attribute *a;
+ struct attribute *a, *client_attr;
uint8_t status;
GSList *l;
guint h = handle;
@@ -573,6 +674,10 @@ static uint16_t read_value(struct gatt_channel *channel, uint16_t handle,
status = att_check_reqs(channel, ATT_OP_READ_REQ, a->read_reqs);
+ client_attr = client_cfg_attribute(channel, a, a->data, a->len);
+ if (client_attr)
+ a = client_attr;
+
if (status == 0x00 && a->read_cb)
status = a->read_cb(a, a->cb_user_data);
@@ -586,7 +691,7 @@ static uint16_t read_value(struct gatt_channel *channel, uint16_t handle,
static uint16_t read_blob(struct gatt_channel *channel, uint16_t handle,
uint16_t offset, uint8_t *pdu, int len)
{
- struct attribute *a;
+ struct attribute *a, *client_attr;
uint8_t status;
GSList *l;
guint h = handle;
@@ -604,6 +709,10 @@ static uint16_t read_blob(struct gatt_channel *channel, uint16_t handle,
status = att_check_reqs(channel, ATT_OP_READ_BLOB_REQ, a->read_reqs);
+ client_attr = client_cfg_attribute(channel, a, a->data, a->len);
+ if (client_attr)
+ a = client_attr;
+
if (status == 0x00 && a->read_cb)
status = a->read_cb(a, a->cb_user_data);
@@ -618,11 +727,10 @@ 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;
+ struct attribute *a, *client_attr;
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)
@@ -636,8 +744,11 @@ static uint16_t write_value(struct gatt_channel *channel, uint16_t handle,
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);
+ client_attr = client_cfg_attribute(channel, a, value, vlen);
+ if (client_attr)
+ a = client_attr;
+ else
+ attrib_db_update(a->handle, &a->uuid, value, vlen);
if (a->write_cb) {
status = a->write_cb(a, a->cb_user_data);
@@ -646,6 +757,10 @@ static uint16_t write_value(struct gatt_channel *channel, uint16_t handle,
pdu, len);
}
+ DBG("Notifications: %d, indications: %d",
+ g_slist_length(channel->notify),
+ g_slist_length(channel->indicate));
+
return enc_write_resp(pdu, len);
}
@@ -664,6 +779,11 @@ static void channel_disconnect(void *user_data)
g_attrib_unref(channel->attrib);
clients = g_slist_remove(clients, channel);
+ g_slist_free(channel->notify);
+ g_slist_free(channel->indicate);
+ g_slist_foreach(channel->configs, (GFunc) g_free, NULL);
+ g_slist_free(channel->configs);
+
g_free(channel);
}
@@ -976,6 +1096,11 @@ void attrib_server_exit(void)
for (l = clients; l; l = l->next) {
struct gatt_channel *channel = l->data;
+ g_slist_free(channel->notify);
+ g_slist_free(channel->indicate);
+ g_slist_foreach(channel->configs, (GFunc) g_free, NULL);
+ g_slist_free(channel->configs);
+
g_attrib_unref(channel->attrib);
g_free(channel);
}
@@ -1073,18 +1198,11 @@ int attrib_db_update(uint16_t handle, uuid_t *uuid, const uint8_t *value,
l->data = a;
a->handle = handle;
- memcpy(&a->uuid, uuid, sizeof(uuid_t));
+ if (uuid != &a->uuid)
+ memcpy(&a->uuid, uuid, sizeof(uuid_t));
a->len = len;
memcpy(a->data, value, len);
- /*
- * <<Client/Server Characteristic Configuration>> descriptors are
- * not supported yet. If a given attribute changes, the attribute
- * server shall report the new values using the mechanism selected
- * by the client. Notification/Indication shall not be automatically
- * sent if the client didn't request them.
- */
-
return 0;
}
--
1.7.0.4
^ permalink raw reply related
* [PATCHv2 1/5] Add read/write callbacks to attribute server
From: Anderson Lizardo @ 2011-02-22 21:01 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Anderson Lizardo
In-Reply-To: <1298323843-31106-1-git-send-email-anderson.lizardo@openbossa.org>
These callbacks will allow profiles to act before an attribute is read
and after it is written, to e.g. update the attribute value to/from an
external source.
Note that by the time the callback is called, the necessary security
checks (attribute permissions, authentication and encryption) were
already performed by the core attribute server.
The callback can optionally return an ATT status code, which will be
sent to the client using an Error Response PDU.
---
attrib/att.h | 7 +++++++
src/attrib-server.c | 29 ++++++++++++++++++++++++++---
src/attrib-server.h | 4 ++--
3 files changed, 35 insertions(+), 5 deletions(-)
diff --git a/attrib/att.h b/attrib/att.h
index 7d9afeb..397898f 100644
--- a/attrib/att.h
+++ b/attrib/att.h
@@ -118,11 +118,18 @@ enum {
ATT_NOT_PERMITTED, /* Operation not permitted */
};
+struct attribute;
+
+typedef uint8_t (*att_cb_t)(struct attribute *a, gpointer user_data);
+
struct attribute {
uint16_t handle;
uuid_t uuid;
int read_reqs;
int write_reqs;
+ att_cb_t read_cb;
+ att_cb_t write_cb;
+ gpointer cb_user_data;
int len;
uint8_t data[0];
};
diff --git a/src/attrib-server.c b/src/attrib-server.c
index 7ec0f56..28649f1 100644
--- a/src/attrib-server.c
+++ b/src/attrib-server.c
@@ -229,6 +229,10 @@ static uint16_t read_by_group(struct gatt_channel *channel, uint16_t start,
status = att_check_reqs(channel, ATT_OP_READ_BY_GROUP_REQ,
a->read_reqs);
+
+ if (status == 0x00 && a->read_cb)
+ status = a->read_cb(a, a->cb_user_data);
+
if (status) {
g_slist_foreach(groups, (GFunc) g_free, NULL);
g_slist_free(groups);
@@ -317,6 +321,10 @@ static uint16_t read_by_type(struct gatt_channel *channel, uint16_t start,
status = att_check_reqs(channel, ATT_OP_READ_BY_TYPE_REQ,
a->read_reqs);
+
+ if (status == 0x00 && a->read_cb)
+ status = a->read_cb(a, a->cb_user_data);
+
if (status) {
g_slist_free(types);
return enc_error_resp(ATT_OP_READ_BY_TYPE_REQ,
@@ -564,6 +572,10 @@ static uint16_t read_value(struct gatt_channel *channel, uint16_t handle,
a = l->data;
status = att_check_reqs(channel, ATT_OP_READ_REQ, a->read_reqs);
+
+ if (status == 0x00 && a->read_cb)
+ status = a->read_cb(a, a->cb_user_data);
+
if (status)
return enc_error_resp(ATT_OP_READ_REQ, handle, status, pdu,
len);
@@ -591,6 +603,10 @@ static uint16_t read_blob(struct gatt_channel *channel, uint16_t handle,
ATT_ECODE_INVALID_OFFSET, pdu, len);
status = att_check_reqs(channel, ATT_OP_READ_BLOB_REQ, a->read_reqs);
+
+ if (status == 0x00 && a->read_cb)
+ status = a->read_cb(a, a->cb_user_data);
+
if (status)
return enc_error_resp(ATT_OP_READ_BLOB_REQ, handle, status,
pdu, len);
@@ -623,6 +639,13 @@ static uint16_t write_value(struct gatt_channel *channel, uint16_t handle,
memcpy(&uuid, &a->uuid, sizeof(uuid_t));
attrib_db_update(handle, &uuid, value, vlen);
+ if (a->write_cb) {
+ status = a->write_cb(a, a->cb_user_data);
+ if (status)
+ return enc_error_resp(ATT_OP_WRITE_REQ, handle, status,
+ pdu, len);
+ }
+
return enc_write_resp(pdu, len);
}
@@ -1013,8 +1036,8 @@ void attrib_free_sdp(uint32_t sdp_handle)
remove_record_from_server(sdp_handle);
}
-int attrib_db_add(uint16_t handle, uuid_t *uuid, int read_reqs, int write_reqs,
- const uint8_t *value, int len)
+struct attribute *attrib_db_add(uint16_t handle, uuid_t *uuid, int read_reqs,
+ int write_reqs, const uint8_t *value, int len)
{
struct attribute *a;
@@ -1030,7 +1053,7 @@ int attrib_db_add(uint16_t handle, uuid_t *uuid, int read_reqs, int write_reqs,
database = g_slist_insert_sorted(database, a, attribute_cmp);
- return 0;
+ return a;
}
int attrib_db_update(uint16_t handle, uuid_t *uuid, const uint8_t *value,
diff --git a/src/attrib-server.h b/src/attrib-server.h
index ecd695c..85f3bdb 100644
--- a/src/attrib-server.h
+++ b/src/attrib-server.h
@@ -25,8 +25,8 @@
int attrib_server_init(void);
void attrib_server_exit(void);
-int attrib_db_add(uint16_t handle, uuid_t *uuid, int read_reqs, int write_reqs,
- const uint8_t *value, int len);
+struct attribute *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 7/7] TODO: Add item to support characteristic authorization in the agent
From: Claudio Takahasi @ 2011-02-22 20:43 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Claudio Takahasi
In-Reply-To: <1298407391-19260-1-git-send-email-claudio.takahasi@openbossa.org>
---
TODO | 6 ++++++
1 files changed, 6 insertions(+), 0 deletions(-)
diff --git a/TODO b/TODO
index c53339b..c69e7bb 100644
--- a/TODO
+++ b/TODO
@@ -119,6 +119,12 @@ ATT/GATT
Priority: Medium
Complexity: C2
+- Agent for characteristics: Agent interface should be extended to support
+ authorization per characteristic if the remote is not in the trusted list.
+
+ Priority: Low
+ Complexity: C1
+
- gatttool should have the ability to wait for req responses before
quitting (some servers require a small sleep even with cmd's). Maybe a
--delay-exit or --timeout command line switch.
--
1.7.4.1
^ permalink raw reply related
* [PATCH 6/7] TODO: Add item for reconnection address
From: Claudio Takahasi @ 2011-02-22 20:43 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Claudio Takahasi
In-Reply-To: <1298407391-19260-1-git-send-email-claudio.takahasi@openbossa.org>
---
TODO | 8 ++++++++
1 files changed, 8 insertions(+), 0 deletions(-)
diff --git a/TODO b/TODO
index b5e4d09..c53339b 100644
--- a/TODO
+++ b/TODO
@@ -78,6 +78,14 @@ Low Energy
Priority: Low
Complexity: C1
+- Reconnection address: Reconnection address is a non resolvable private
+ address that the central writes in the peripheral. BlueZ will support
+ multiple profiles, it is not clear how it needs to be implemented.
+ Further discussion is necessary.
+
+ Priority: Low
+ Complexity: C2
+
- Device Name Characteristic is a GAP characteristic for Low Energy. This
characteristic shall be integrated/used in the discovery procedure. The
ideia is to report the value of this characteristic using DeviceFound signals.
--
1.7.4.1
^ permalink raw reply related
* [PATCH 5/7] TODO: Add item for static random address
From: Claudio Takahasi @ 2011-02-22 20:43 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Claudio Takahasi
In-Reply-To: <1298407391-19260-1-git-send-email-claudio.takahasi@openbossa.org>
---
TODO | 6 ++++++
1 files changed, 6 insertions(+), 0 deletions(-)
diff --git a/TODO b/TODO
index 4c5cd55..b5e4d09 100644
--- a/TODO
+++ b/TODO
@@ -72,6 +72,12 @@ Low Energy
Priority: Medium
Complexity: C1
+- Static random address setup and storage. Once this address is written
+ in the a given remote, the address can not be changed anymore.
+
+ Priority: Low
+ Complexity: C1
+
- Device Name Characteristic is a GAP characteristic for Low Energy. This
characteristic shall be integrated/used in the discovery procedure. The
ideia is to report the value of this characteristic using DeviceFound signals.
--
1.7.4.1
^ permalink raw reply related
* [PATCH 4/7] TODO: Change item related to read/write long characteristic
From: Claudio Takahasi @ 2011-02-22 20:43 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Claudio Takahasi
In-Reply-To: <1298407391-19260-1-git-send-email-claudio.takahasi@openbossa.org>
---
TODO | 3 ++-
1 files changed, 2 insertions(+), 1 deletions(-)
diff --git a/TODO b/TODO
index 8cb205a..4c5cd55 100644
--- a/TODO
+++ b/TODO
@@ -155,7 +155,8 @@ ATT/GATT
Priority: Low
Complexity: C1
-- Long reads/writes don't work (consisting of multiple request packets)
+- Long write is not implemented. Attribute server, client and command line
+ tool shall be changed to support this feature.
Priority: Low
Complexity: C2
--
1.7.4.1
^ permalink raw reply related
* [PATCH 3/7] TODO: Remove interactive gatttool item
From: Claudio Takahasi @ 2011-02-22 20:43 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Claudio Takahasi
In-Reply-To: <1298407391-19260-1-git-send-email-claudio.takahasi@openbossa.org>
---
TODO | 8 --------
1 files changed, 0 insertions(+), 8 deletions(-)
diff --git a/TODO b/TODO
index 5ee892c..8cb205a 100644
--- a/TODO
+++ b/TODO
@@ -105,14 +105,6 @@ ATT/GATT
Priority: Medium
Complexity: C2
-- gatttool: add an interactive command prompt mode. Many LE devices
- expect the connection to stay up a long time and disable advertising
- after a disconnection so it's inconvenient to use gatttool in the
- current "single operation at a time" mode.
-
- Priority: Medium
- Complexity: C2
-
- gatttool should have the ability to wait for req responses before
quitting (some servers require a small sleep even with cmd's). Maybe a
--delay-exit or --timeout command line switch.
--
1.7.4.1
^ permalink raw reply related
* [PATCH 2/7] TODO: Add item for privacy feature in the central
From: Claudio Takahasi @ 2011-02-22 20:43 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Claudio Takahasi
In-Reply-To: <1298407391-19260-1-git-send-email-claudio.takahasi@openbossa.org>
---
TODO | 7 +++++++
1 files changed, 7 insertions(+), 0 deletions(-)
diff --git a/TODO b/TODO
index 3617777..5ee892c 100644
--- a/TODO
+++ b/TODO
@@ -65,6 +65,13 @@ Low Energy
Priority: Medium
Complexity: C2
+- Privacy: When privacy is enabled in the adapter, LE scanning/connection
+ should use a private address. StartDiscovery method shall be changed and
+ new adapter property shall be added.
+
+ Priority: Medium
+ Complexity: C1
+
- Device Name Characteristic is a GAP characteristic for Low Energy. This
characteristic shall be integrated/used in the discovery procedure. The
ideia is to report the value of this characteristic using DeviceFound signals.
--
1.7.4.1
^ permalink raw reply related
* [PATCH 1/7] TODO: Changed item related to ATT parsing for hcidump
From: Claudio Takahasi @ 2011-02-22 20:43 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Claudio Takahasi
---
TODO | 3 ++-
1 files changed, 2 insertions(+), 1 deletions(-)
diff --git a/TODO b/TODO
index 1357db9..3617777 100644
--- a/TODO
+++ b/TODO
@@ -87,7 +87,8 @@ ATT/GATT
Priority: Medium
Complexity: C1
-- Add ATT/GATT parsing to hcidump
+- ATT/GATT parsing to hcidump. Partially implemented, missing to fix
+ multiple advertises in the same event and RSSI.
Priority: Medium
Complexity: C2
--
1.7.4.1
^ permalink raw reply related
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox