From 0351e3011e4116eab7becf0cd96abccec6305c50 Mon Sep 17 00:00:00 2001 From: Szymon Janc Date: Tue, 21 Nov 2017 15:36:12 +0100 Subject: [PATCH] nimble/host: Add support for setting extended adv_data and scan_rsp Data from application can come fragmented but host make sure all is sent using minimal number of HCI commands. X-Original-Commit: 6e7c6cc3892d1414531fe6e2712496086dc34b89 --- nimble/host/include/host/ble_hs_adv.h | 3 + nimble/host/src/ble_gap.c | 193 ++++++++++++++++++++- nimble/host/src/ble_hs_adv.c | 232 ++++++++++++++++++-------- nimble/host/src/ble_hs_hci_cmd.c | 23 +-- nimble/host/src/ble_hs_hci_priv.h | 12 +- nimble/include/nimble/hci_common.h | 6 + 6 files changed, 366 insertions(+), 103 deletions(-) diff --git a/nimble/host/include/host/ble_hs_adv.h b/nimble/host/include/host/ble_hs_adv.h index c0b46d27e..b0d85c02a 100644 --- a/nimble/host/include/host/ble_hs_adv.h +++ b/nimble/host/include/host/ble_hs_adv.h @@ -158,6 +158,9 @@ struct ble_hs_adv_fields { #define BLE_HS_ADV_SVC_DATA_UUID128_MIN_LEN 16 +int ble_hs_adv_set_fields_mbuf(const struct ble_hs_adv_fields *adv_fields, + struct os_mbuf *om); + 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); diff --git a/nimble/host/src/ble_gap.c b/nimble/host/src/ble_gap.c index 7d8152613..20db13317 100644 --- a/nimble/host/src/ble_gap.c +++ b/nimble/host/src/ble_gap.c @@ -2729,16 +2729,205 @@ ble_gap_ext_adv_stop(uint8_t instance) return rc; } + +static int +ble_gap_ext_adv_set_data_validate(uint8_t instance, struct os_mbuf *data) +{ + uint16_t len = OS_MBUF_PKTLEN(data); + + if (!ble_gap_slave[instance].configured) { + return BLE_HS_EINVAL; + } + + /* not allowed with directed advertising */ + if (ble_gap_slave[instance].directed) { + return BLE_HS_EINVAL; + } + + /* always allowed with legacy PDU but limited to legacy length */ + if (ble_gap_slave[instance].legacy_pdu) { + if (len > BLE_HS_ADV_MAX_SZ) { + return BLE_HS_EINVAL; + } + + return 0; + } + + /* if already advertising, data must fit in single HCI command */ + if (ble_gap_slave[instance].op == BLE_GAP_OP_S_ADV) { + if (len > min(MYNEWT_VAL(BLE_EXT_ADV_MAX_SIZE), 251)) { + return EINVAL; + } + } + + /* not allowed with scannable advertising */ + if (ble_gap_slave[instance].scannable) { + return BLE_HS_EINVAL; + } + + return 0; +} + +static int +ble_gap_ext_adv_set(uint8_t instance, uint16_t opcode, struct os_mbuf *data) +{ + /* in that case we always fit all data in single HCI command */ +#if MYNEWT_VAL(BLE_EXT_ADV_MAX_SIZE) <= BLE_HCI_MAX_EXT_ADV_DATA_LEN + static uint8_t buf[BLE_HCI_SET_EXT_ADV_DATA_HDR_LEN + \ + MYNEWT_VAL(BLE_EXT_ADV_MAX_SIZE)]; + uint16_t len = OS_MBUF_PKTLEN(data); + int rc; + + opcode = BLE_HCI_OP(BLE_HCI_OGF_LE, opcode); + + rc = ble_hs_hci_cmd_build_le_ext_adv_data(instance, + BLE_HCI_LE_SET_EXT_ADV_DATA_OPER_COMPLETE, + 0, data, len, buf, sizeof(buf)); + if (rc) { + return rc; + } + + return ble_hs_hci_cmd_tx_empty_ack(opcode, buf, + BLE_HCI_SET_EXT_ADV_DATA_HDR_LEN + len); +#else + static uint8_t buf[BLE_HCI_SET_EXT_ADV_DATA_HDR_LEN + \ + BLE_HCI_MAX_EXT_ADV_DATA_LEN]; + uint16_t len = OS_MBUF_PKTLEN(data); + uint16_t off = 0; + uint8_t op; + int rc; + + opcode = BLE_HCI_OP(BLE_HCI_OGF_LE, opcode); + + /* complete data */ + if (len <= BLE_HCI_MAX_EXT_ADV_DATA_LEN) { + rc = ble_hs_hci_cmd_build_le_ext_adv_data(instance, + BLE_HCI_LE_SET_EXT_ADV_DATA_OPER_COMPLETE, + 0, data, len, buf,sizeof(buf)); + if (rc) { + return rc; + } + + return ble_hs_hci_cmd_tx_empty_ack(opcode, buf, + BLE_HCI_SET_EXT_ADV_DATA_HDR_LEN + len); + } + + /* first fragment */ + op = BLE_HCI_LE_SET_EXT_ADV_DATA_OPER_FIRST; + + do { + rc = ble_hs_hci_cmd_build_le_ext_adv_data(instance, op, 0, data, + BLE_HCI_MAX_EXT_ADV_DATA_LEN, + buf, sizeof(buf)); + if (rc) { + return rc; + } + rc = ble_hs_hci_cmd_tx_empty_ack(opcode, buf, sizeof(buf)); + if (rc) { + return rc; + } + + len -= BLE_HCI_MAX_EXT_ADV_DATA_LEN; + off += BLE_HCI_MAX_EXT_ADV_DATA_LEN; + op = BLE_HCI_LE_SET_EXT_ADV_DATA_OPER_INT; + } while (len > BLE_HCI_MAX_EXT_ADV_DATA_LEN); + + /* last fragment */ + rc = ble_hs_hci_cmd_build_le_ext_adv_data(instance, + BLE_HCI_LE_SET_EXT_ADV_DATA_OPER_LAST, + 0, data, len, buf, sizeof(buf)); + if (rc) { + return rc; + } + + return ble_hs_hci_cmd_tx_empty_ack(opcode, buf, + BLE_HCI_SET_EXT_ADV_DATA_HDR_LEN + len); +#endif +} + int ble_gap_ext_adv_set_data(uint8_t instance, struct os_mbuf *data) { - return -1; + int rc; + + if (instance >= BLE_ADV_INSTANCES) { + return BLE_HS_EINVAL; + } + + ble_hs_lock(); + rc = ble_gap_ext_adv_set_data_validate(instance, data); + if (rc != 0) { + ble_hs_unlock(); + return rc; + } + + rc = ble_gap_ext_adv_set(instance, BLE_HCI_OCF_LE_SET_EXT_ADV_DATA, data); + + ble_hs_unlock(); + + return rc; +} + +static int +ble_gap_ext_adv_rsp_set_validate(uint8_t instance, struct os_mbuf *data) +{ + uint16_t len = OS_MBUF_PKTLEN(data); + + if (!ble_gap_slave[instance].configured) { + return BLE_HS_EINVAL; + } + + /* not allowed with directed advertising */ + if (ble_gap_slave[instance].directed) { + return BLE_HS_EINVAL; + } + + /* only allowed with scannable advertising */ + if (!ble_gap_slave[instance].scannable) { + return BLE_HS_EINVAL; + } + + /* with legacy PDU limited to legacy length */ + if (ble_gap_slave[instance].legacy_pdu) { + if (len > BLE_HS_ADV_MAX_SZ) { + return BLE_HS_EINVAL; + } + + return 0; + } + + /* if already advertising, data must fit in single HCI command */ + if (ble_gap_slave[instance].op == BLE_GAP_OP_S_ADV) { + if (len > min(MYNEWT_VAL(BLE_EXT_ADV_MAX_SIZE), 251)) { + return EINVAL; + } + } + + return 0; } int ble_gap_ext_adv_rsp_set_data(uint8_t instance, struct os_mbuf *data) { - return -1; + int rc; + + if (instance >= BLE_ADV_INSTANCES) { + return BLE_HS_EINVAL; + } + + ble_hs_lock(); + rc = ble_gap_ext_adv_rsp_set_validate(instance, data); + if (rc != 0) { + ble_hs_unlock(); + return rc; + } + + rc = ble_gap_ext_adv_set(instance, BLE_HCI_OCF_LE_SET_EXT_SCAN_RSP_DATA, + data); + + ble_hs_unlock(); + + return rc; } int diff --git a/nimble/host/src/ble_hs_adv.c b/nimble/host/src/ble_hs_adv.c index 026603bbb..7f1517c7c 100644 --- a/nimble/host/src/ble_hs_adv.c +++ b/nimble/host/src/ble_hs_adv.c @@ -34,8 +34,21 @@ static ble_uuid128_t ble_hs_adv_uuids128[BLE_HS_ADV_MAX_FIELD_SZ / 16]; static int ble_hs_adv_set_hdr(uint8_t type, uint8_t data_len, uint8_t max_len, - uint8_t *dst, uint8_t *dst_len) + uint8_t *dst, uint8_t *dst_len, struct os_mbuf *om) { + int rc; + + if (om ) { + data_len++; + rc = os_mbuf_append(om, &data_len, sizeof(data_len)); + if (rc) { + return rc; + } + + return os_mbuf_append(om, &type, sizeof(type)); + } + + if (*dst_len + 2 + data_len > max_len) { return BLE_HS_EMSGSIZE; } @@ -48,46 +61,67 @@ ble_hs_adv_set_hdr(uint8_t type, uint8_t data_len, uint8_t max_len, return 0; } -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) +static int +ble_hs_adv_set_flat_mbuf(uint8_t type, int data_len, const void *data, + uint8_t *dst, uint8_t *dst_len, uint8_t max_len, + struct os_mbuf *om) { -#if !NIMBLE_BLE_ADVERTISE - return BLE_HS_ENOTSUP; -#endif - int rc; BLE_HS_DBG_ASSERT(data_len > 0); - rc = ble_hs_adv_set_hdr(type, data_len, max_len, dst, dst_len); + rc = ble_hs_adv_set_hdr(type, data_len, max_len, dst, dst_len, om); if (rc != 0) { return rc; } + if (om) { + return os_mbuf_append(om, data, data_len); + } + memcpy(dst + *dst_len, data, data_len); *dst_len += data_len; return 0; } +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) +{ +#if !NIMBLE_BLE_ADVERTISE + return BLE_HS_ENOTSUP; +#endif + + return ble_hs_adv_set_flat_mbuf(type, data_len, data, dst, dst_len, max_len, + NULL); +} + static int ble_hs_adv_set_array_uuid16(uint8_t type, uint8_t num_elems, const ble_uuid16_t *elems, uint8_t *dst, - uint8_t *dst_len, uint8_t max_len) + uint8_t *dst_len, uint8_t max_len, + struct os_mbuf *om) { int rc; int i; rc = ble_hs_adv_set_hdr(type, num_elems * 2, max_len, dst, - dst_len); + dst_len, om); if (rc != 0) { return rc; } for (i = 0; i < num_elems; i++) { - ble_uuid_flat(&elems[i].u, dst + *dst_len); - *dst_len += 2; + if (om) { + rc = ble_uuid_to_mbuf(&elems[i].u, om); + if (rc) { + return rc; + } + } else { + ble_uuid_flat(&elems[i].u, dst + *dst_len); + *dst_len += 2; + } } return 0; @@ -96,13 +130,15 @@ ble_hs_adv_set_array_uuid16(uint8_t type, uint8_t num_elems, static int ble_hs_adv_set_array_uuid32(uint8_t type, uint8_t num_elems, const ble_uuid32_t *elems, uint8_t *dst, - uint8_t *dst_len, uint8_t max_len) + uint8_t *dst_len, uint8_t max_len, + struct os_mbuf *om) { + uint32_t uuid_le; int rc; int i; rc = ble_hs_adv_set_hdr(type, num_elems * 4, max_len, dst, - dst_len); + dst_len, om); if (rc != 0) { return rc; } @@ -112,8 +148,16 @@ ble_hs_adv_set_array_uuid32(uint8_t type, uint8_t num_elems, * 128-bit as ATT requires. In AD, 32-bit UUID shall be written as an * actual 32-bit value. */ - put_le32(dst + *dst_len, elems[i].value); - *dst_len += 4; + if (om) { + uuid_le = htole32(elems[i].value); + rc = os_mbuf_append(om, &uuid_le, sizeof(uuid_le)); + if (rc) { + return rc; + } + } else { + put_le32(dst + *dst_len, elems[i].value); + *dst_len += 4; + } } return 0; @@ -122,20 +166,28 @@ ble_hs_adv_set_array_uuid32(uint8_t type, uint8_t num_elems, static int ble_hs_adv_set_array_uuid128(uint8_t type, uint8_t num_elems, const ble_uuid128_t *elems, uint8_t *dst, - uint8_t *dst_len, uint8_t max_len) + uint8_t *dst_len, uint8_t max_len, + struct os_mbuf *om) { int rc; int i; rc = ble_hs_adv_set_hdr(type, num_elems * 16, max_len, dst, - dst_len); + dst_len, om); if (rc != 0) { return rc; } for (i = 0; i < num_elems; i++) { - ble_uuid_flat(&elems[i].u, dst + *dst_len); - *dst_len += 16; + if (om) { + rc = ble_uuid_to_mbuf(&elems[i].u, om); + if (rc) { + return rc; + } + } else { + ble_uuid_flat(&elems[i].u, dst + *dst_len); + *dst_len += 16; + } } return 0; @@ -143,33 +195,39 @@ ble_hs_adv_set_array_uuid128(uint8_t type, uint8_t num_elems, static int ble_hs_adv_set_array16(uint8_t type, uint8_t num_elems, const uint16_t *elems, - uint8_t *dst, uint8_t *dst_len, uint8_t max_len) + uint8_t *dst, uint8_t *dst_len, uint8_t max_len, + struct os_mbuf *om) { + uint16_t tmp; int rc; int i; rc = ble_hs_adv_set_hdr(type, num_elems * sizeof *elems, max_len, dst, - dst_len); + dst_len, om); if (rc != 0) { return rc; } for (i = 0; i < num_elems; i++) { - put_le16(dst + *dst_len, elems[i]); - *dst_len += sizeof elems[i]; + if (om) { + tmp = htole16(elems[i]); + rc = os_mbuf_append(om, &tmp, sizeof(tmp)); + if (rc) { + return rc; + } + } else { + put_le16(dst + *dst_len, elems[i]); + *dst_len += sizeof elems[i]; + } } return 0; } -/** - * Converts a high-level set of fields to a byte buffer. - * - * @return 0 on success; nonzero on failure. - */ -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) +static int +adv_set_fields(const struct ble_hs_adv_fields *adv_fields, + uint8_t *dst, uint8_t *dst_len, uint8_t max_len, + struct os_mbuf *om) { #if !NIMBLE_BLE_ADVERTISE return BLE_HS_ENOTSUP; @@ -179,7 +237,9 @@ ble_hs_adv_set_fields(const struct ble_hs_adv_fields *adv_fields, int8_t tx_pwr_lvl; int rc; - *dst_len = 0; + if (dst_len) { + *dst_len = 0; + } /*** 0x01 - Flags. */ /* The application has two options concerning the flags field: @@ -190,8 +250,9 @@ ble_hs_adv_set_fields(const struct ble_hs_adv_fields *adv_fields, * of specifying option 1 vs. 2 is sound. */ if (adv_fields->flags != 0) { - rc = ble_hs_adv_set_flat(BLE_HS_ADV_TYPE_FLAGS, 1, &adv_fields->flags, - dst, dst_len, max_len); + rc = ble_hs_adv_set_flat_mbuf(BLE_HS_ADV_TYPE_FLAGS, 1, + &adv_fields->flags, dst, dst_len, + max_len, om); if (rc != 0) { return rc; @@ -208,7 +269,7 @@ ble_hs_adv_set_fields(const struct ble_hs_adv_fields *adv_fields, rc = ble_hs_adv_set_array_uuid16(type, adv_fields->num_uuids16, adv_fields->uuids16, dst, dst_len, - max_len); + max_len, om); if (rc != 0) { return rc; } @@ -224,7 +285,7 @@ ble_hs_adv_set_fields(const struct ble_hs_adv_fields *adv_fields, rc = ble_hs_adv_set_array_uuid32(type, adv_fields->num_uuids32, adv_fields->uuids32, dst, dst_len, - max_len); + max_len, om); if (rc != 0) { return rc; } @@ -240,7 +301,7 @@ ble_hs_adv_set_fields(const struct ble_hs_adv_fields *adv_fields, rc = ble_hs_adv_set_array_uuid128(type, adv_fields->num_uuids128, adv_fields->uuids128, dst, dst_len, - max_len); + max_len, om); if (rc != 0) { return rc; } @@ -254,8 +315,9 @@ ble_hs_adv_set_fields(const struct ble_hs_adv_fields *adv_fields, type = BLE_HS_ADV_TYPE_INCOMP_NAME; } - rc = ble_hs_adv_set_flat(type, adv_fields->name_len, adv_fields->name, - dst, dst_len, max_len); + rc = ble_hs_adv_set_flat_mbuf(type, adv_fields->name_len, + adv_fields->name, dst, dst_len, max_len, + om); if (rc != 0) { return rc; } @@ -275,8 +337,8 @@ ble_hs_adv_set_fields(const struct ble_hs_adv_fields *adv_fields, tx_pwr_lvl = adv_fields->tx_pwr_lvl; } - rc = ble_hs_adv_set_flat(BLE_HS_ADV_TYPE_TX_PWR_LVL, 1, &tx_pwr_lvl, - dst, dst_len, max_len); + rc = ble_hs_adv_set_flat_mbuf(BLE_HS_ADV_TYPE_TX_PWR_LVL, 1, + &tx_pwr_lvl, dst, dst_len, max_len, om); if (rc != 0) { return rc; } @@ -284,10 +346,10 @@ ble_hs_adv_set_fields(const struct ble_hs_adv_fields *adv_fields, /*** 0x12 - Slave connection interval range. */ if (adv_fields->slave_itvl_range != NULL) { - rc = ble_hs_adv_set_flat(BLE_HS_ADV_TYPE_SLAVE_ITVL_RANGE, - BLE_HS_ADV_SLAVE_ITVL_RANGE_LEN, - adv_fields->slave_itvl_range, dst, dst_len, - max_len); + rc = ble_hs_adv_set_flat_mbuf(BLE_HS_ADV_TYPE_SLAVE_ITVL_RANGE, + BLE_HS_ADV_SLAVE_ITVL_RANGE_LEN, + adv_fields->slave_itvl_range, dst, + dst_len, max_len, om); if (rc != 0) { return rc; } @@ -295,10 +357,10 @@ ble_hs_adv_set_fields(const struct ble_hs_adv_fields *adv_fields, /*** 0x16 - Service data - 16-bit UUID. */ if (adv_fields->svc_data_uuid16 != NULL) { - rc = ble_hs_adv_set_flat(BLE_HS_ADV_TYPE_SVC_DATA_UUID16, - adv_fields->svc_data_uuid16_len, - adv_fields->svc_data_uuid16, dst, dst_len, - max_len); + rc = ble_hs_adv_set_flat_mbuf(BLE_HS_ADV_TYPE_SVC_DATA_UUID16, + adv_fields->svc_data_uuid16_len, + adv_fields->svc_data_uuid16, dst, dst_len, + max_len, om); if (rc != 0) { return rc; } @@ -308,11 +370,11 @@ ble_hs_adv_set_fields(const struct ble_hs_adv_fields *adv_fields, if (adv_fields->public_tgt_addr != NULL && adv_fields->num_public_tgt_addrs != 0) { - rc = ble_hs_adv_set_flat(BLE_HS_ADV_TYPE_PUBLIC_TGT_ADDR, + rc = ble_hs_adv_set_flat_mbuf(BLE_HS_ADV_TYPE_PUBLIC_TGT_ADDR, BLE_HS_ADV_PUBLIC_TGT_ADDR_ENTRY_LEN * adv_fields->num_public_tgt_addrs, adv_fields->public_tgt_addr, dst, dst_len, - max_len); + max_len, om); if (rc != 0) { return rc; } @@ -320,10 +382,10 @@ ble_hs_adv_set_fields(const struct ble_hs_adv_fields *adv_fields, /*** 0x19 - Appearance. */ if (adv_fields->appearance_is_present) { - rc = ble_hs_adv_set_flat(BLE_HS_ADV_TYPE_APPEARANCE, - BLE_HS_ADV_APPEARANCE_LEN, - &adv_fields->appearance, dst, dst_len, - max_len); + rc = ble_hs_adv_set_flat_mbuf(BLE_HS_ADV_TYPE_APPEARANCE, + BLE_HS_ADV_APPEARANCE_LEN, + &adv_fields->appearance, dst, dst_len, + max_len, om); if (rc != 0) { return rc; } @@ -333,7 +395,7 @@ ble_hs_adv_set_fields(const struct ble_hs_adv_fields *adv_fields, if (adv_fields->adv_itvl_is_present) { rc = ble_hs_adv_set_array16(BLE_HS_ADV_TYPE_ADV_ITVL, 1, &adv_fields->adv_itvl, dst, dst_len, - max_len); + max_len, om); if (rc != 0) { return rc; } @@ -341,10 +403,10 @@ ble_hs_adv_set_fields(const struct ble_hs_adv_fields *adv_fields, /*** 0x20 - Service data - 32-bit UUID. */ if (adv_fields->svc_data_uuid32 != NULL) { - rc = ble_hs_adv_set_flat(BLE_HS_ADV_TYPE_SVC_DATA_UUID32, - adv_fields->svc_data_uuid32_len, - adv_fields->svc_data_uuid32, dst, dst_len, - max_len); + rc = ble_hs_adv_set_flat_mbuf(BLE_HS_ADV_TYPE_SVC_DATA_UUID32, + adv_fields->svc_data_uuid32_len, + adv_fields->svc_data_uuid32, dst, dst_len, + max_len, om); if (rc != 0) { return rc; } @@ -352,10 +414,10 @@ ble_hs_adv_set_fields(const struct ble_hs_adv_fields *adv_fields, /*** 0x21 - Service data - 128-bit UUID. */ if (adv_fields->svc_data_uuid128 != NULL) { - rc = ble_hs_adv_set_flat(BLE_HS_ADV_TYPE_SVC_DATA_UUID128, - adv_fields->svc_data_uuid128_len, - adv_fields->svc_data_uuid128, dst, dst_len, - max_len); + rc = ble_hs_adv_set_flat_mbuf(BLE_HS_ADV_TYPE_SVC_DATA_UUID128, + adv_fields->svc_data_uuid128_len, + adv_fields->svc_data_uuid128, dst, + dst_len, max_len, om); if (rc != 0) { return rc; } @@ -363,8 +425,9 @@ ble_hs_adv_set_fields(const struct ble_hs_adv_fields *adv_fields, /*** 0x24 - URI. */ if (adv_fields->uri != NULL) { - rc = ble_hs_adv_set_flat(BLE_HS_ADV_TYPE_URI, adv_fields->uri_len, - adv_fields->uri, dst, dst_len, max_len); + rc = ble_hs_adv_set_flat_mbuf(BLE_HS_ADV_TYPE_URI, adv_fields->uri_len, + adv_fields->uri, dst, dst_len, max_len, + om); if (rc != 0) { return rc; } @@ -372,9 +435,10 @@ ble_hs_adv_set_fields(const struct ble_hs_adv_fields *adv_fields, /*** 0xff - Manufacturer specific data. */ if (adv_fields->mfg_data != NULL) { - rc = ble_hs_adv_set_flat(BLE_HS_ADV_TYPE_MFG_DATA, - adv_fields->mfg_data_len, - adv_fields->mfg_data, dst, dst_len, max_len); + rc = ble_hs_adv_set_flat_mbuf(BLE_HS_ADV_TYPE_MFG_DATA, + adv_fields->mfg_data_len, + adv_fields->mfg_data, + dst, dst_len, max_len, om); if (rc != 0) { return rc; } @@ -383,6 +447,32 @@ ble_hs_adv_set_fields(const struct ble_hs_adv_fields *adv_fields, return 0; } +/** + * Converts a high-level set of fields to a byte buffer. + * + * @return 0 on success; nonzero on failure. + */ +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) +{ +#if !NIMBLE_BLE_ADVERTISE + return BLE_HS_ENOTSUP; +#endif + + return adv_set_fields(adv_fields, dst, dst_len, max_len, NULL); +} + +int +ble_hs_adv_set_fields_mbuf(const struct ble_hs_adv_fields *adv_fields, + struct os_mbuf *om) +{ +#if !NIMBLE_BLE_ADVERTISE + return BLE_HS_ENOTSUP; +#endif + return adv_set_fields(adv_fields, NULL, NULL, 0, om); +} + static int ble_hs_adv_parse_uuids16(struct ble_hs_adv_fields *adv_fields, const uint8_t *data, uint8_t data_len) diff --git a/nimble/host/src/ble_hs_hci_cmd.c b/nimble/host/src/ble_hs_hci_cmd.c index 8c464c4d2..9cd732659 100644 --- a/nimble/host/src/ble_hs_hci_cmd.c +++ b/nimble/host/src/ble_hs_hci_cmd.c @@ -1471,8 +1471,8 @@ ble_hs_hci_cmd_build_le_ext_adv_set_random_addr(uint8_t handle, int ble_hs_hci_cmd_build_le_ext_adv_data(uint8_t handle, uint8_t operation, - uint8_t frag_pref, - const uint8_t *data, uint8_t data_len, + uint8_t frag_pref, struct os_mbuf *data, + uint8_t data_len, uint8_t *cmd, int cmd_len) { BLE_HS_DBG_ASSERT(cmd_len >= 4 + data_len); @@ -1481,24 +1481,7 @@ ble_hs_hci_cmd_build_le_ext_adv_data(uint8_t handle, uint8_t operation, cmd[1] = operation; cmd[2] = frag_pref; cmd[3] = data_len; - memcpy(cmd + 4, data, data_len); - - return 0; -} - -int -ble_hs_hci_cmd_build_le_ext_adv_scan_rsp(uint8_t handle, uint8_t operation, - uint8_t frag_pref, - const uint8_t *data, uint8_t data_len, - uint8_t *cmd, int cmd_len) -{ - BLE_HS_DBG_ASSERT(cmd_len >= 4 + data_len); - - cmd[0] = handle; - cmd[1] = operation; - cmd[2] = frag_pref; - cmd[3] = data_len; - memcpy(cmd + 4, data, data_len); + os_mbuf_copydata(data, 0, data_len, cmd + 4); return 0; } diff --git a/nimble/host/src/ble_hs_hci_priv.h b/nimble/host/src/ble_hs_hci_priv.h index 1c605d1f4..45f95ac54 100644 --- a/nimble/host/src/ble_hs_hci_priv.h +++ b/nimble/host/src/ble_hs_hci_priv.h @@ -212,20 +212,12 @@ ble_hs_hci_cmd_build_le_ext_adv_set_random_addr(uint8_t handle, const uint8_t *addr, uint8_t *cmd, int cmd_len); - - int ble_hs_hci_cmd_build_le_ext_adv_data(uint8_t handle, uint8_t operation, - uint8_t frag_pref, - const uint8_t *data, uint8_t data_len, + uint8_t frag_pref, struct os_mbuf *data, + uint8_t data_len, uint8_t *cmd, int cmd_len); -int -ble_hs_hci_cmd_build_le_ext_adv_scan_rsp(uint8_t handle, uint8_t operation, - uint8_t frag_pref, - const uint8_t *data, uint8_t data_len, - uint8_t *cmd, int cmd_len); - int ble_hs_hci_cmd_build_le_ext_adv_enable(uint8_t enable, uint8_t sets_num, const struct hci_ext_adv_set *sets, diff --git a/nimble/include/nimble/hci_common.h b/nimble/include/nimble/hci_common.h index f5323ad79..e14137d14 100644 --- a/nimble/include/nimble/hci_common.h +++ b/nimble/include/nimble/hci_common.h @@ -491,6 +491,9 @@ extern "C" { #define BLE_HCI_LE_SET_EXT_ADV_PROP_LEGACY_NONCONN (0x0010) /* --- LE set extended advertising data (OCF 0x0037) */ +#define BLE_HCI_MAX_EXT_ADV_DATA_LEN (251) +#define BLE_HCI_SET_EXT_ADV_DATA_HDR_LEN (4) + #define BLE_HCI_LE_SET_EXT_ADV_DATA_LEN BLE_HCI_VARIABLE_LEN #define BLE_HCI_LE_SET_EXT_ADV_DATA_OPER_INT (0) #define BLE_HCI_LE_SET_EXT_ADV_DATA_OPER_FIRST (1) @@ -499,6 +502,9 @@ extern "C" { #define BLE_HCI_LE_SET_EXT_ADV_DATA_OPER_UNCHANGED (4) /* --- LE set extended scan response data (OCF 0x0038) */ +#define BLE_HCI_MAX_EXT_SCAN_RSP_DATA_LEN (251) +#define BLE_HCI_SET_EXT_SCAN_RSP_DATA_HDR_LEN (4) + #define BLE_HCI_LE_SET_EXT_SCAN_RSP_DATA_LEN BLE_HCI_VARIABLE_LEN #define BLE_HCI_LE_SET_EXT_SCAN_RSP_DATA_OPER_INT (0) #define BLE_HCI_LE_SET_EXT_SCAN_RSP_DATA_OPER_FIRST (1)