diff --git a/nimble/host/src/ble_hs_hci_priv.h b/nimble/host/src/ble_hs_hci_priv.h index 24ced0a36..a152dde1e 100644 --- a/nimble/host/src/ble_hs_hci_priv.h +++ b/nimble/host/src/ble_hs_hci_priv.h @@ -96,9 +96,8 @@ int ble_hs_hci_util_set_data_len(uint16_t conn_handle, uint16_t tx_octets, uint16_t tx_time); int ble_hs_hci_util_data_hdr_strip(struct os_mbuf *om, struct hci_data_hdr *out_hdr); - int ble_hs_hci_evt_process(uint8_t *data); -uint16_t ble_hs_hci_util_opcode_join(uint8_t ogf, uint16_t ocf); + void ble_hs_hci_cmd_write_hdr(uint8_t ogf, uint16_t ocf, uint8_t len, void *buf); int ble_hs_hci_cmd_send_buf(uint16_t opcode, void *buf, uint8_t buf_len); diff --git a/nimble/host/src/ble_hs_hci_util.c b/nimble/host/src/ble_hs_hci_util.c index f210ee7ba..fabf65f1a 100644 --- a/nimble/host/src/ble_hs_hci_util.c +++ b/nimble/host/src/ble_hs_hci_util.c @@ -22,12 +22,6 @@ #include "host/ble_hs_hci.h" #include "ble_hs_priv.h" -uint16_t -ble_hs_hci_util_opcode_join(uint8_t ogf, uint16_t ocf) -{ - return (ogf << 10) | ocf; -} - uint16_t ble_hs_hci_util_handle_pb_bc_join(uint16_t handle, uint8_t pb, uint8_t bc) { diff --git a/nimble/host/src/ble_hs_startup.c b/nimble/host/src/ble_hs_startup.c index 4ad6694dd..63428a0fb 100644 --- a/nimble/host/src/ble_hs_startup.c +++ b/nimble/host/src/ble_hs_startup.c @@ -23,8 +23,40 @@ #include "host/ble_hs_hci.h" #include "ble_hs_priv.h" +#if !MYNEWT_VAL(BLE_DEVICE) static int -ble_hs_startup_le_read_local_ver_tx(void) +ble_hs_startup_read_sup_f_tx(void) +{ + uint8_t ack_params[BLE_HCI_RD_LOC_SUPP_FEAT_RSPLEN]; + uint8_t ack_params_len; + int rc; + + rc = ble_hs_hci_cmd_tx(BLE_HCI_OP(BLE_HCI_OGF_INFO_PARAMS, + BLE_HCI_OCF_IP_RD_LOC_SUPP_FEAT), + NULL,0, ack_params, sizeof ack_params, + &ack_params_len); + if (rc != 0) { + return rc; + } + + if (ack_params_len != BLE_HCI_RD_LOC_SUPP_FEAT_RSPLEN) { + return BLE_HS_ECONTROLLER; + } + + /* for now we don't use it outside of init sequence so check this here + * LE Supported (Controller) byte 4, bit 6 + */ + if (!(ack_params[4] & 0x60)) { + BLE_HS_LOG(ERROR, "Controller doesn't support LE\n"); + return BLE_HS_ECONTROLLER; + } + + return 0; +} +#endif + +static int +ble_hs_startup_read_local_ver_tx(void) { uint8_t ack_params[BLE_HCI_RD_LOC_VER_INFO_RSPLEN]; uint8_t ack_params_len; @@ -53,7 +85,7 @@ ble_hs_startup_le_read_local_ver_tx(void) static int ble_hs_startup_le_read_sup_f_tx(void) { - uint8_t ack_params[BLE_HCI_RD_LOC_SUPP_FEAT_RSPLEN]; + uint8_t ack_params[BLE_HCI_RD_LE_LOC_SUPP_FEAT_RSPLEN]; uint8_t ack_params_len; uint32_t feat; int rc; @@ -66,7 +98,7 @@ ble_hs_startup_le_read_sup_f_tx(void) return rc; } - if (ack_params_len != BLE_HCI_RD_LOC_SUPP_FEAT_RSPLEN) { + if (ack_params_len != BLE_HCI_RD_LE_LOC_SUPP_FEAT_RSPLEN) { return BLE_HS_ECONTROLLER; } @@ -184,8 +216,14 @@ static int ble_hs_startup_le_set_evmask_tx(void) { uint8_t buf[BLE_HCI_SET_LE_EVENT_MASK_LEN]; + uint8_t version; + uint64_t mask; int rc; + version = ble_hs_hci_get_hci_version(); + + /* TODO should we also check for supported commands when setting this? */ + /** * Enable the following LE events: * 0x0000000000000001 LE Connection Complete Event @@ -193,18 +231,40 @@ ble_hs_startup_le_set_evmask_tx(void) * 0x0000000000000004 LE Connection Update Complete Event * 0x0000000000000008 LE Read Remote Used Features Complete Event * 0x0000000000000010 LE Long Term Key Request Event - * 0x0000000000000020 LE Remote Connection Parameter Request Event - * 0x0000000000000040 LE Data Length Change Event - * 0x0000000000000200 LE Enhanced Connection Complete Event - * 0x0000000000000400 LE Directed Advertising Report Event - * 0x0000000000000800 LE PHY Update Complete Event - * 0x0000000000001000 LE Extended Advertising Report Event - * 0x0000000000010000 LE Extended Scan Timeout Event - * 0x0000000000020000 LE Extended Advertising Set Terminated Event - * 0x0000000000040000 LE Scan Request Received Event - * 0x0000000000080000 LE Channel Selection Algorithm Event */ - ble_hs_hci_cmd_build_le_set_event_mask(0x00000000000F1A7F, buf, sizeof buf); + mask = 0x000000000000001f; + + if (version >= BLE_HCI_VER_BCS_4_1) { + /** + * Enable the following LE events: + * 0x0000000000000020 LE Remote Connection Parameter Request Event */ + mask |= 0x0000000000000020; + } + + if (version >= BLE_HCI_VER_BCS_4_2) { + /** + * Enable the following LE events: + * 0x0000000000000040 LE Data Length Change Event + * 0x0000000000000200 LE Enhanced Connection Complete Event + * 0x0000000000000400 LE Directed Advertising Report Event + */ + mask |= 0x0000000000000640; + } + + if (version >= BLE_HCI_VER_BCS_5_0) { + /** + * Enable the following LE events: + * 0x0000000000000800 LE PHY Update Complete Event + * 0x0000000000001000 LE Extended Advertising Report Event + * 0x0000000000010000 LE Extended Scan Timeout Event + * 0x0000000000020000 LE Extended Advertising Set Terminated Event + * 0x0000000000040000 LE Scan Request Received Event + * 0x0000000000080000 LE Channel Selection Algorithm Event + */ + mask |= 0x00000000000f1800; + } + + ble_hs_hci_cmd_build_le_set_event_mask(mask, buf, sizeof buf); rc = ble_hs_hci_cmd_tx_empty_ack(BLE_HCI_OP(BLE_HCI_OGF_LE, BLE_HCI_OCF_LE_SET_EVENT_MASK), buf, sizeof(buf)); @@ -247,7 +307,7 @@ ble_hs_startup_set_evmask_tx(void) BLE_HCI_OCF_CB_SET_EVENT_MASK2), buf, sizeof(buf)); if (rc != 0) { - BLE_HS_LOG(WARN, "ble_hs_startup_set_evmask_tx() failed\n"); + return rc; } return 0; @@ -278,13 +338,25 @@ ble_hs_startup_go(void) return rc; } - rc = ble_hs_startup_le_read_local_ver_tx(); + rc = ble_hs_startup_read_local_ver_tx(); if (rc != 0) { return rc; } /* XXX: Read local supported commands. */ - /* XXX: Read local supported features. */ + + /* we need to check this only if using external controller */ +#if !MYNEWT_VAL(BLE_DEVICE) + if (ble_hs_hci_get_hci_version() < BLE_HCI_VER_BCS_4_0) { + BLE_HS_LOG(ERROR, "Required controller version is 4.0 (6)\n"); + return BLE_HS_ECONTROLLER; + } + + rc = ble_hs_startup_read_sup_f_tx(); + if (rc != 0) { + return rc; + } +#endif rc = ble_hs_startup_set_evmask_tx(); if (rc != 0) { diff --git a/nimble/host/test/src/ble_hs_pvcy_test.c b/nimble/host/test/src/ble_hs_pvcy_test.c index 27e95fded..f048efd90 100644 --- a/nimble/host/test/src/ble_hs_pvcy_test.c +++ b/nimble/host/test/src/ble_hs_pvcy_test.c @@ -125,7 +125,7 @@ ble_hs_pvcy_test_util_start_host(int num_expected_irks) TEST_ASSERT_FATAL(rc == 0); /* Discard startup HCI commands. */ - ble_hs_test_util_hci_out_adj(13); + ble_hs_test_util_hci_out_adj(ble_hs_test_util_hci_startup_seq_cnt()); } static void diff --git a/nimble/host/test/src/ble_hs_test_util_hci.c b/nimble/host/test/src/ble_hs_test_util_hci.c index 8eb5c9479..af32d5e18 100644 --- a/nimble/host/test/src/ble_hs_test_util_hci.c +++ b/nimble/host/test/src/ble_hs_test_util_hci.c @@ -226,8 +226,81 @@ ble_hs_test_util_hci_ack_append(uint16_t opcode, uint8_t status) ble_hs_test_util_hci_ack_append_params(opcode, status, NULL, 0); } +static const struct ble_hs_test_util_hci_ack hci_startup_seq[] = { + { + .opcode = ble_hs_hci_util_opcode_join(BLE_HCI_OGF_CTLR_BASEBAND, + BLE_HCI_OCF_CB_RESET), + }, + { + .opcode = ble_hs_hci_util_opcode_join( + BLE_HCI_OGF_INFO_PARAMS, BLE_HCI_OCF_IP_RD_LOCAL_VER), + .evt_params = { 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, + .evt_params_len = 8, + }, + { + .opcode = ble_hs_hci_util_opcode_join( + BLE_HCI_OGF_INFO_PARAMS, BLE_HCI_OCF_IP_RD_LOC_SUPP_FEAT), + .evt_params = { 0x00, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00}, + .evt_params_len = 8, + }, + { + .opcode = ble_hs_hci_util_opcode_join( + BLE_HCI_OGF_CTLR_BASEBAND, BLE_HCI_OCF_CB_SET_EVENT_MASK), + }, + { + .opcode = ble_hs_hci_util_opcode_join( + BLE_HCI_OGF_CTLR_BASEBAND, BLE_HCI_OCF_CB_SET_EVENT_MASK2), + }, + { + .opcode = ble_hs_hci_util_opcode_join( + BLE_HCI_OGF_LE, BLE_HCI_OCF_LE_SET_EVENT_MASK), + }, + { + .opcode = ble_hs_hci_util_opcode_join( + BLE_HCI_OGF_LE, BLE_HCI_OCF_LE_RD_BUF_SIZE), + /* Use a very low buffer size (20) to test fragmentation. + * Use a large num-pkts (200) to prevent controller buf exhaustion. + */ + .evt_params = { 0x14, 0x00, 200 }, + .evt_params_len = 3, + }, + { + .opcode = ble_hs_hci_util_opcode_join( + BLE_HCI_OGF_LE, BLE_HCI_OCF_LE_RD_LOC_SUPP_FEAT), + .evt_params = { 0 }, + .evt_params_len = 8, + }, + { + .opcode = ble_hs_hci_util_opcode_join( + BLE_HCI_OGF_INFO_PARAMS, BLE_HCI_OCF_IP_RD_BD_ADDR), + .evt_params = BLE_HS_TEST_UTIL_PUB_ADDR_VAL, + .evt_params_len = 6, + }, + { + .opcode = ble_hs_hci_util_opcode_join( + BLE_HCI_OGF_LE, BLE_HCI_OCF_LE_SET_ADDR_RES_EN), + }, + { + .opcode = ble_hs_hci_util_opcode_join( + BLE_HCI_OGF_LE, BLE_HCI_OCF_LE_CLR_RESOLV_LIST), + }, + { + .opcode = ble_hs_hci_util_opcode_join( + BLE_HCI_OGF_LE, BLE_HCI_OCF_LE_SET_ADDR_RES_EN), + }, + { + .opcode = ble_hs_hci_util_opcode_join( + BLE_HCI_OGF_LE, BLE_HCI_OCF_LE_ADD_RESOLV_LIST), + }, + { + .opcode = ble_hs_hci_util_opcode_join( + BLE_HCI_OGF_LE, BLE_HCI_OCF_LE_SET_PRIVACY_MODE), + }, + { 0 } +}; + void -ble_hs_test_util_hci_ack_set_seq(struct ble_hs_test_util_hci_ack *acks) +ble_hs_test_util_hci_ack_set_seq(const struct ble_hs_test_util_hci_ack *acks) { int i; @@ -239,78 +312,20 @@ ble_hs_test_util_hci_ack_set_seq(struct ble_hs_test_util_hci_ack *acks) ble_hs_hci_set_phony_ack_cb(ble_hs_test_util_hci_ack_cb); } +int +ble_hs_test_util_hci_startup_seq_cnt(void) +{ + /* last element is terminator, don't count it*/ + return sizeof(hci_startup_seq)/sizeof(hci_startup_seq[0]) - 1; +} + void ble_hs_test_util_hci_ack_set_startup(void) { /* Receive acknowledgements for the startup sequence. We sent the * corresponding requests when the host task was started. */ - ble_hs_test_util_hci_ack_set_seq(((struct ble_hs_test_util_hci_ack[]) { - { - .opcode = ble_hs_hci_util_opcode_join(BLE_HCI_OGF_CTLR_BASEBAND, - BLE_HCI_OCF_CB_RESET), - }, - { - .opcode = ble_hs_hci_util_opcode_join( - BLE_HCI_OGF_INFO_PARAMS, BLE_HCI_OCF_IP_RD_LOCAL_VER), - .evt_params = { 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, - .evt_params_len = 8, - }, - { - .opcode = ble_hs_hci_util_opcode_join( - BLE_HCI_OGF_CTLR_BASEBAND, BLE_HCI_OCF_CB_SET_EVENT_MASK), - }, - { - .opcode = ble_hs_hci_util_opcode_join( - BLE_HCI_OGF_CTLR_BASEBAND, BLE_HCI_OCF_CB_SET_EVENT_MASK2), - }, - { - .opcode = ble_hs_hci_util_opcode_join( - BLE_HCI_OGF_LE, BLE_HCI_OCF_LE_SET_EVENT_MASK), - }, - { - .opcode = ble_hs_hci_util_opcode_join( - BLE_HCI_OGF_LE, BLE_HCI_OCF_LE_RD_BUF_SIZE), - /* Use a very low buffer size (20) to test fragmentation. - * Use a large num-pkts (200) to prevent controller buf exhaustion. - */ - .evt_params = { 0x14, 0x00, 200 }, - .evt_params_len = 3, - }, - { - .opcode = ble_hs_hci_util_opcode_join( - BLE_HCI_OGF_LE, BLE_HCI_OCF_LE_RD_LOC_SUPP_FEAT), - .evt_params = { 0 }, - .evt_params_len = 8, - }, - { - .opcode = ble_hs_hci_util_opcode_join( - BLE_HCI_OGF_INFO_PARAMS, BLE_HCI_OCF_IP_RD_BD_ADDR), - .evt_params = BLE_HS_TEST_UTIL_PUB_ADDR_VAL, - .evt_params_len = 6, - }, - { - .opcode = ble_hs_hci_util_opcode_join( - BLE_HCI_OGF_LE, BLE_HCI_OCF_LE_SET_ADDR_RES_EN), - }, - { - .opcode = ble_hs_hci_util_opcode_join( - BLE_HCI_OGF_LE, BLE_HCI_OCF_LE_CLR_RESOLV_LIST), - }, - { - .opcode = ble_hs_hci_util_opcode_join( - BLE_HCI_OGF_LE, BLE_HCI_OCF_LE_SET_ADDR_RES_EN), - }, - { - .opcode = ble_hs_hci_util_opcode_join( - BLE_HCI_OGF_LE, BLE_HCI_OCF_LE_ADD_RESOLV_LIST), - }, - { - .opcode = ble_hs_hci_util_opcode_join( - BLE_HCI_OGF_LE, BLE_HCI_OCF_LE_SET_PRIVACY_MODE), - }, - { 0 } - })); + ble_hs_test_util_hci_ack_set_seq(hci_startup_seq); } void diff --git a/nimble/host/test/src/ble_hs_test_util_hci.h b/nimble/host/test/src/ble_hs_test_util_hci.h index 82df67e46..500f8ed68 100644 --- a/nimble/host/test/src/ble_hs_test_util_hci.h +++ b/nimble/host/test/src/ble_hs_test_util_hci.h @@ -24,6 +24,9 @@ extern "C" { #endif +/* leave this as macro so it may be used for static const initialization */ +#define ble_hs_hci_util_opcode_join(ogf, ocf) (((ogf) << 10) | (ocf)) + #define BLE_HS_TEST_UTIL_PHONY_ACK_MAX 64 struct ble_hs_test_util_hci_ack { uint16_t opcode; @@ -60,12 +63,14 @@ void ble_hs_test_util_hci_ack_set(uint16_t opcode, uint8_t status); void ble_hs_test_util_hci_ack_append_params(uint16_t opcode, uint8_t status, void *params, uint8_t params_len); void ble_hs_test_util_hci_ack_append(uint16_t opcode, uint8_t status); -void ble_hs_test_util_hci_ack_set_seq(struct ble_hs_test_util_hci_ack *acks); +void ble_hs_test_util_hci_ack_set_seq(const struct ble_hs_test_util_hci_ack *acks); void ble_hs_test_util_hci_ack_set_startup(void); void ble_hs_test_util_hci_ack_set_disc(uint8_t own_addr_type, int fail_idx, uint8_t fail_status); void ble_hs_test_util_hci_ack_set_disconnect(uint8_t hci_status); +int ble_hs_test_util_hci_startup_seq_cnt(void); + /* $verify tx */ void ble_hs_test_util_hci_verify_tx_add_irk(uint8_t addr_type, const uint8_t *addr, diff --git a/nimble/include/nimble/hci_common.h b/nimble/include/nimble/hci_common.h index 52a676e0c..443c563e7 100644 --- a/nimble/include/nimble/hci_common.h +++ b/nimble/include/nimble/hci_common.h @@ -203,9 +203,13 @@ extern "C" { #define BLE_HCI_WR_AUTH_PYLD_TMO_LEN (2) /* --- Read local version information (OGF 0x04, OCF 0x0001) --- */ -/* NOTE: does not include status field in command complete event! */ -#define BLE_HCI_RD_LOC_VER_INFO_RSPLEN (8) -#define BLE_HCI_RD_LOC_SUPP_CMD_RSPLEN (64) +#define BLE_HCI_RD_LOC_VER_INFO_RSPLEN (8) /* No status byte. */ + +/* --- Read local supported command (OGF 0x04, OCF 0x0002) --- */ +#define BLE_HCI_RD_LOC_SUPP_CMD_RSPLEN (64) /* No status byte. */ + +/* --- Read local supported features (OGF 0x04, OCF 0x0003) --- */ +#define BLE_HCI_RD_LOC_SUPP_FEAT_RSPLEN (8) /* No status byte. */ /* --- Read RSSI (OGF 0x05, OCF 0x0005) --- */ #define BLE_HCI_READ_RSSI_LEN (2) @@ -219,7 +223,7 @@ extern "C" { #define BLE_HCI_RD_BUF_SIZE_RSPLEN (3) /* No status byte. */ /* --- LE read local supported features (OCF 0x0003) --- */ -#define BLE_HCI_RD_LOC_SUPP_FEAT_RSPLEN (8) +#define BLE_HCI_RD_LE_LOC_SUPP_FEAT_RSPLEN (8) /* No status byte. */ /* --- LE set random address (OCF 0x0005) */ #define BLE_HCI_SET_RAND_ADDR_LEN (6)