nimble/gap: Use raw data only in ble_gap_disc_desc struct The main API to set adv data now accepts raw buffers with helper func to create data from ble_hs_adv_fields.
This patch does the same for the data that host sends as an even to application, i.e. ble_gap_disc_desc contains only raw buffer and there are helpers to parse them into ble_hs_adv_fields struct or iterate using a callback. Project: http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/repo Commit: http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/commit/1fe117a6 Tree: http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/tree/1fe117a6 Diff: http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/diff/1fe117a6 Branch: refs/heads/develop Commit: 1fe117a67d65cb8e827f39048ce549d2e983776c Parents: c5b5588 Author: Andrzej Kaczmarek <[email protected]> Authored: Thu Jan 26 17:19:11 2017 +0100 Committer: Andrzej Kaczmarek <[email protected]> Committed: Fri Jan 27 16:51:41 2017 +0100 ---------------------------------------------------------------------- apps/blecent/src/main.c | 20 ++++++-- apps/bletiny/src/main.c | 5 +- net/nimble/host/include/host/ble_gap.h | 4 +- net/nimble/host/include/host/ble_hs_adv.h | 15 ++++++ net/nimble/host/src/ble_gap.c | 20 +++----- net/nimble/host/src/ble_hs_adv.c | 67 ++++++++++++++++++++++++++ net/nimble/host/src/ble_hs_adv_priv.h | 4 +- net/nimble/host/src/ble_hs_hci_evt.c | 1 - net/nimble/host/test/src/ble_gap_test.c | 2 +- 9 files changed, 115 insertions(+), 23 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/1fe117a6/apps/blecent/src/main.c ---------------------------------------------------------------------- diff --git a/apps/blecent/src/main.c b/apps/blecent/src/main.c index f6de476..64279a9 100755 --- a/apps/blecent/src/main.c +++ b/apps/blecent/src/main.c @@ -259,6 +259,8 @@ blecent_scan(void) static int blecent_should_connect(const struct ble_gap_disc_desc *disc) { + struct ble_hs_adv_fields fields; + int rc; int i; /* The device has to be advertising connectability. */ @@ -268,11 +270,16 @@ blecent_should_connect(const struct ble_gap_disc_desc *disc) return 0; } + rc = ble_hs_adv_parse_fields(&fields, disc->data, disc->length_data); + if (rc != 0) { + return rc; + } + /* The device has to advertise support for the Alert Notification * service (0x1811). */ - for (i = 0; i < disc->fields->num_uuids16; i++) { - if (disc->fields->uuids16[i] == BLECENT_SVC_ALERT_UUID) { + for (i = 0; i < fields.num_uuids16; i++) { + if (fields.uuids16[i] == BLECENT_SVC_ALERT_UUID) { return 1; } } @@ -332,12 +339,19 @@ static int blecent_gap_event(struct ble_gap_event *event, void *arg) { struct ble_gap_conn_desc desc; + struct ble_hs_adv_fields fields; int rc; switch (event->type) { case BLE_GAP_EVENT_DISC: + rc = ble_hs_adv_parse_fields(&fields, event->disc.data, + event->disc.length_data); + if (rc != 0) { + return 0; + } + /* An advertisment report was received during GAP discovery. */ - print_adv_fields(event->disc.fields); + print_adv_fields(&fields); /* Try to connect to the advertiser if it looks interesting. */ blecent_connect_if_interesting(&event->disc); http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/1fe117a6/apps/bletiny/src/main.c ---------------------------------------------------------------------- diff --git a/apps/bletiny/src/main.c b/apps/bletiny/src/main.c index 5aa2f44..63b0535 100755 --- a/apps/bletiny/src/main.c +++ b/apps/bletiny/src/main.c @@ -879,6 +879,7 @@ static int bletiny_gap_event(struct ble_gap_event *event, void *arg) { struct ble_gap_conn_desc desc; + struct ble_hs_adv_fields fields; int conn_idx; int rc; @@ -926,7 +927,9 @@ bletiny_gap_event(struct ble_gap_event *event, void *arg) event->disc.length_data); print_bytes(event->disc.data, event->disc.length_data); console_printf(" fields:\n"); - bletiny_print_adv_fields(event->disc.fields); + ble_hs_adv_parse_fields(&fields, event->disc.data, + event->disc.length_data); + bletiny_print_adv_fields(&fields); console_printf("\n"); return 0; http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/1fe117a6/net/nimble/host/include/host/ble_gap.h ---------------------------------------------------------------------- diff --git a/net/nimble/host/include/host/ble_gap.h b/net/nimble/host/include/host/ble_gap.h index f24c4e0..fa84d3b 100644 --- a/net/nimble/host/include/host/ble_gap.h +++ b/net/nimble/host/include/host/ble_gap.h @@ -22,6 +22,7 @@ #include <inttypes.h> #include "host/ble_hs.h" +#include "host/ble_hs_adv.h" #ifdef __cplusplus extern "C" { #endif @@ -222,10 +223,7 @@ struct ble_gap_disc_desc { uint8_t length_data; int8_t rssi; uint8_t addr[6]; - - /*** LE advertising report fields; both null if no data present. */ uint8_t *data; - struct ble_hs_adv_fields *fields; /*** * LE direct advertising report fields; direct_addr_type is http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/1fe117a6/net/nimble/host/include/host/ble_hs_adv.h ---------------------------------------------------------------------- diff --git a/net/nimble/host/include/host/ble_hs_adv.h b/net/nimble/host/include/host/ble_hs_adv.h index d15c8ee..538fc7d 100644 --- a/net/nimble/host/include/host/ble_hs_adv.h +++ b/net/nimble/host/include/host/ble_hs_adv.h @@ -31,6 +31,15 @@ extern "C" { /** Max field payload size (account for 2-byte header). */ #define BLE_HS_ADV_MAX_FIELD_SZ (BLE_HS_ADV_MAX_SZ - 2) +struct ble_hs_adv_field { + uint8_t length; + uint8_t type; + uint8_t value[]; +}; + +typedef int (* ble_hs_adv_parse_func_t) (const struct ble_hs_adv_field *, + void *); + struct ble_hs_adv_fields { /*** 0x01 - Flags. */ uint8_t flags; @@ -148,6 +157,12 @@ struct ble_hs_adv_fields { int ble_hs_adv_set_fields(const struct ble_hs_adv_fields *adv_fields, uint8_t *dst, uint8_t *dst_len, uint8_t max_len); +int ble_hs_adv_parse_fields(struct ble_hs_adv_fields *adv_fields, uint8_t *src, + uint8_t src_len); + +int ble_hs_adv_parse(const uint8_t *data, uint8_t length, + ble_hs_adv_parse_func_t func, void *user_data); + #ifdef __cplusplus } #endif http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/1fe117a6/net/nimble/host/src/ble_gap.c ---------------------------------------------------------------------- diff --git a/net/nimble/host/src/ble_gap.c b/net/nimble/host/src/ble_gap.c index 8d46aa4..3b9892c 100644 --- a/net/nimble/host/src/ble_gap.c +++ b/net/nimble/host/src/ble_gap.c @@ -1056,7 +1056,7 @@ ble_gap_rx_adv_report(struct ble_gap_disc_desc *desc) return; #endif - struct ble_hs_adv_fields fields; + const struct ble_hs_adv_field *flags; int rc; STATS_INC(ble_gap_stats, rx_adv_report); @@ -1065,22 +1065,18 @@ ble_gap_rx_adv_report(struct ble_gap_disc_desc *desc) return; } - rc = ble_hs_adv_parse_fields(&fields, desc->data, desc->length_data); - if (rc != 0) { - /* XXX: Increment stat. */ - return; - } - /* If a limited discovery procedure is active, discard non-limited * advertisements. */ - if (ble_gap_master.disc.limited && - !(fields.flags & BLE_HS_ADV_F_DISC_LTD)) { - - return; + if (ble_gap_master.disc.limited) { + rc = ble_hs_adv_find_field(BLE_HS_ADV_TYPE_FLAGS, desc->data, + desc->length_data, &flags); + if ((rc == 0) && (flags->length == 2) && + !(flags->value[0] & BLE_HS_ADV_F_DISC_LTD)) { + return; + } } - desc->fields = &fields; ble_gap_disc_report(desc); } http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/1fe117a6/net/nimble/host/src/ble_hs_adv.c ---------------------------------------------------------------------- diff --git a/net/nimble/host/src/ble_hs_adv.c b/net/nimble/host/src/ble_hs_adv.c index 1d65817..37236c8 100644 --- a/net/nimble/host/src/ble_hs_adv.c +++ b/net/nimble/host/src/ble_hs_adv.c @@ -23,6 +23,11 @@ #include "host/ble_hs_adv.h" #include "ble_hs_priv.h" +struct find_field_data { + uint8_t type; + const struct ble_hs_adv_field *field; +}; + static uint16_t ble_hs_adv_uuids16[BLE_HS_ADV_MAX_FIELD_SZ / 2]; static uint32_t ble_hs_adv_uuids32[BLE_HS_ADV_MAX_FIELD_SZ / 4]; @@ -561,3 +566,65 @@ ble_hs_adv_parse_fields(struct ble_hs_adv_fields *adv_fields, uint8_t *src, return 0; } + +int +ble_hs_adv_parse(const uint8_t *data, uint8_t length, + ble_hs_adv_parse_func_t func, void *user_data) +{ + const struct ble_hs_adv_field *field; + + while (length > 1) { + field = (const void *) data; + + if (field->length >= length) { + return BLE_HS_EBADDATA; + } + + if (func(field, user_data) == 0) { + return 0; + } + + length -= 1 + field->length; + length += 1 + field->length; + } + + return 0; +} + +static int +find_field_func(const struct ble_hs_adv_field *field, void *user_data) +{ + struct find_field_data *ffd = user_data; + + if (field->type != ffd->type) { + return BLE_HS_EAGAIN; + } + + ffd->field = field; + + return 0; +} + +int +ble_hs_adv_find_field(uint8_t type, const uint8_t *data, uint8_t length, + const struct ble_hs_adv_field **out) +{ + int rc; + struct find_field_data ffd = { + .type = type, + .field = NULL, + }; + + rc = ble_hs_adv_parse(data, length, find_field_func, &ffd); + if (rc != 0) { + return rc; + } + + if (!ffd.field) { + return BLE_HS_ENOENT; + } + + *out = ffd.field; + + return 0; +} http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/1fe117a6/net/nimble/host/src/ble_hs_adv_priv.h ---------------------------------------------------------------------- diff --git a/net/nimble/host/src/ble_hs_adv_priv.h b/net/nimble/host/src/ble_hs_adv_priv.h index f913b09..5c8a6ec 100644 --- a/net/nimble/host/src/ble_hs_adv_priv.h +++ b/net/nimble/host/src/ble_hs_adv_priv.h @@ -26,8 +26,8 @@ extern "C" { int ble_hs_adv_set_flat(uint8_t type, int data_len, const void *data, uint8_t *dst, uint8_t *dst_len, uint8_t max_len); -int ble_hs_adv_parse_fields(struct ble_hs_adv_fields *adv_fields, uint8_t *src, - uint8_t src_len); +int ble_hs_adv_find_field(uint8_t type, const uint8_t *data, uint8_t length, + const struct ble_hs_adv_field **out); #ifdef __cplusplus } http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/1fe117a6/net/nimble/host/src/ble_hs_hci_evt.c ---------------------------------------------------------------------- diff --git a/net/nimble/host/src/ble_hs_hci_evt.c b/net/nimble/host/src/ble_hs_hci_evt.c index 546e38b..4305124 100644 --- a/net/nimble/host/src/ble_hs_hci_evt.c +++ b/net/nimble/host/src/ble_hs_hci_evt.c @@ -434,7 +434,6 @@ ble_hs_hci_evt_le_dir_adv_rpt(uint8_t subevent, uint8_t *data, int len) /* Data fields not present in a direct advertising report. */ desc.data = NULL; - desc.fields = NULL; for (i = 0; i < num_reports; i++) { suboff = 0; http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/1fe117a6/net/nimble/host/test/src/ble_gap_test.c ---------------------------------------------------------------------- diff --git a/net/nimble/host/test/src/ble_gap_test.c b/net/nimble/host/test/src/ble_gap_test.c index 7aaebee..a13640e 100644 --- a/net/nimble/host/test/src/ble_gap_test.c +++ b/net/nimble/host/test/src/ble_gap_test.c @@ -630,7 +630,7 @@ TEST_CASE(ble_gap_test_case_disc_ltd_mismatch) struct ble_gap_disc_desc desc = { .event_type = BLE_HCI_ADV_TYPE_ADV_IND, .addr_type = BLE_ADDR_TYPE_PUBLIC, - .length_data = 0, + .length_data = 3, .rssi = 0, .addr = { 1, 2, 3, 4, 5, 6 }, .data = (uint8_t[BLE_HS_ADV_MAX_SZ]){
