From 5b55424c20d27e6fa50428c8cdca47a2ba75d56a Mon Sep 17 00:00:00 2001 From: Magdalena Kasenberg Date: Mon, 5 Feb 2024 16:49:27 +0100 Subject: [PATCH] nimble/host: Add initial support for Channel Sounding HCI commands and events --- nimble/host/include/host/ble_cs.h | 93 ++ nimble/host/include/host/ble_gap.h | 7 + .../ras/include/services/ras/ble_svc_ras.h | 139 +++ nimble/host/services/ras/pkg.yml | 34 + .../services/ras/src/rreq/ble_svc_ras_rreq.c | 35 + .../ras/src/rrsp/ble_svc_ras_rd_buffer.c | 0 .../services/ras/src/rrsp/ble_svc_ras_rrsp.c | 206 +++++ nimble/host/src/ble_cs.c | 810 ++++++++++++++++++ nimble/host/src/ble_cs_priv.h | 31 + nimble/host/src/ble_gap.c | 16 + nimble/host/src/ble_hs_hci_evt.c | 15 + nimble/host/src/ble_hs_id.c | 2 +- nimble/host/src/ble_hs_startup.c | 19 + nimble/include/nimble/hci_common.h | 303 +++++++ nimble/syscfg.yml | 5 + nimble/transport/syscfg.yml | 4 + 16 files changed, 1718 insertions(+), 1 deletion(-) create mode 100644 nimble/host/include/host/ble_cs.h create mode 100644 nimble/host/services/ras/include/services/ras/ble_svc_ras.h create mode 100644 nimble/host/services/ras/pkg.yml create mode 100644 nimble/host/services/ras/src/rreq/ble_svc_ras_rreq.c create mode 100644 nimble/host/services/ras/src/rrsp/ble_svc_ras_rd_buffer.c create mode 100644 nimble/host/services/ras/src/rrsp/ble_svc_ras_rrsp.c create mode 100644 nimble/host/src/ble_cs.c create mode 100644 nimble/host/src/ble_cs_priv.h diff --git a/nimble/host/include/host/ble_cs.h b/nimble/host/include/host/ble_cs.h new file mode 100644 index 000000000..802cf7b69 --- /dev/null +++ b/nimble/host/include/host/ble_cs.h @@ -0,0 +1,93 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +/* All Channel Sounding APIs are experimental and subject to change at any time */ + +#ifndef H_BLE_CS_ +#define H_BLE_CS_ +#include "syscfg/syscfg.h" + +#define BLE_CS_EVENT_CS_PROCEDURE_COMPLETE (0) +#define BLE_CS_EVENT_CS_PROCEDURE_ENABLE_COMPLETE (1) +#define BLE_CS_EVENT_SUBEVET_RESULT (2) +#define BLE_CS_EVENT_SUBEVET_RESULT_CONTINUE (3) + +struct cs_step_data { + uint8_t mode; + uint8_t channel; + uint8_t data_len; + uint8_t data[]; +} __attribute__((packed)); +struct ble_cs_event { + uint8_t type; + union + { + struct + { + uint16_t conn_handle; + uint8_t status; + } procedure_complete; + struct + { + uint16_t conn_handle; + uint8_t config_id; + uint16_t start_acl_conn_event_counter; + uint16_t procedure_counter; + uint16_t frequency_compensation; + uint8_t reference_power_level; + uint8_t procedure_done_status; + uint8_t subevent_done_status; + uint8_t abort_reason; + uint8_t num_antenna_paths; + uint8_t num_steps_reported; + struct cs_step_data steps[]; + }subev_result; + struct + { + uint16_t conn_handle; + uint8_t config_id; + uint8_t procedure_done_status; + uint8_t subevent_done_status; + uint8_t abort_reason; + uint8_t num_antenna_paths; + uint8_t num_steps_reported; + struct cs_step_data steps[]; + }subev_result_continue; + + }; +}; + +typedef int ble_cs_event_fn(struct ble_cs_event *event, void *arg); + +struct ble_cs_initiator_procedure_start_params { + uint16_t conn_handle; + ble_cs_event_fn *cb; + void *cb_arg; +}; + +struct ble_cs_reflector_setup_params { + ble_cs_event_fn *cb; + void *cb_arg; +}; + + +int ble_cs_initiator_procedure_start(const struct ble_cs_initiator_procedure_start_params *params); +int ble_cs_initiator_procedure_terminate(uint16_t conn_handle); +int ble_cs_reflector_setup(struct ble_cs_reflector_setup_params *params); +#endif diff --git a/nimble/host/include/host/ble_gap.h b/nimble/host/include/host/ble_gap.h index e48ea82bd..14d82a032 100644 --- a/nimble/host/include/host/ble_gap.h +++ b/nimble/host/include/host/ble_gap.h @@ -221,6 +221,10 @@ struct hci_conn_update; #define BLE_GAP_AUTHORIZE_ACCEPT 1 #define BLE_GAP_AUTHORIZE_REJECT 2 + + +extern int ble_global_status; + /** Connection security state */ struct ble_gap_sec_state { /** If connection is encrypted */ @@ -4083,6 +4087,9 @@ int ble_gap_read_rem_ver_info(uint16_t conn_handle, uint8_t *version, uint16_t * int ble_gap_rd_local_resolv_addr(uint8_t peer_addr_type, const ble_addr_t *peer_addr, uint8_t *out_addr); + + +int ble_gap_set_host_feat(uint8_t bit_num,uint8_t bit_val); #ifdef __cplusplus } #endif diff --git a/nimble/host/services/ras/include/services/ras/ble_svc_ras.h b/nimble/host/services/ras/include/services/ras/ble_svc_ras.h new file mode 100644 index 000000000..244b7d46e --- /dev/null +++ b/nimble/host/services/ras/include/services/ras/ble_svc_ras.h @@ -0,0 +1,139 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + + +#ifndef H_BLE_SVC_RAS_ +#define H_BLE_SVC_RAS_ + + +#define BLE_SVC_RAS_CHR_RANGING_SERVICE_VAL (0x185B) + +/** @brief UUID of the RAS Features Characteristic. **/ +#define BLE_SVC_RAS_CHR_UUID_FEATURES_VAL (0x2C14) + +/** @brief UUID of the Real-time Ranging Data Characteristic. **/ +#define BLE_SVC_RAS_CHR_UUID_REALTIME_RD_VAL (0x2C15) + +/** @brief UUID of the On-demand Ranging Data Characteristic. **/ +#define BLE_SVC_RAS_CHR_UUID_ONDEMAND_RD_VAL (0x2C16) + +/** @brief UUID of the RAS Control Point Characteristic. **/ +#define BLE_SVC_RAS_CHR_UUID_CP_VAL (0x2C17) + +/** @brief UUID of the Ranging Data Ready Characteristic. **/ +#define BLE_SVC_RAS_CHR_UUID_RD_READY_VAL (0x2C18) + +/** @brief UUID of the Ranging Data Overwritten Characteristic. **/ +#define BLE_SVC_RAS_CHR_UUID_RD_OVERWRITTEN_VAL (0x2C19) + + +#define BLE_RAS_RANGING_HEADER_LEN 4 +#define BLE_RAS_SUBEVENT_HEADER_LEN 8 +#define BLE_RAS_STEP_MODE_LEN 1 + +#define BLE_RAS_MAX_SUBEVENTS_PER_PROCEDURE 32 +#define BLE_RAS_MAX_STEPS_PER_PROCEDURE 256 + +#define BLE_RAS_MAX_STEP_DATA_LEN 32 +#define BLE_RAS_PROCEDURE_MEM \ + (BLE_RAS_RANGING_HEADER_LEN + \ + (BLE_RAS_MAX_SUBEVENTS_PER_PROCEDURE * BLE_RAS_SUBEVENT_HEADER_LEN) + \ + (BLE_RAS_MAX_STEPS_PER_PROCEDURE * BLE_RAS_STEP_MODE_LEN) + \ + (BLE_RAS_MAX_STEPS_PER_PROCEDURE * BLE_RAS_MAX_STEP_DATA_LEN)) + + + + +/** @brief Ranging Header structure as defined in RAS Specification, Table 3.7. */ +struct ras_ranging_header { + /** Ranging Counter is lower 12-bits of CS Procedure_Counter provided by the Core Controller + * (Core Specification, Volume 4, Part E, Section 7.7.65.44). + */ + uint16_t ranging_counter : 12; + /** CS configuration identifier. Range: 0 to 3. */ + uint8_t config_id : 4; + /** Transmit power level used for the CS Procedure. Range: -127 to 20. Units: dBm. */ + int8_t selected_tx_power; + /** Antenna paths that are reported: + * Bit0: 1 if Antenna Path_1 included; 0 if not. + * Bit1: 1 if Antenna Path_2 included; 0 if not. + * Bit2: 1 if Antenna Path_3 included; 0 if not. + * Bit3: 1 if Antenna Path_4 included; 0 if not. + * Bits 4-7: RFU + */ + uint8_t antenna_paths_mask; +} __packed; +void ble_svc_ras_init(void); + + +/** @brief Subevent Header structure as defined in RAS Specification, Table 3.8. */ +struct ras_subevent_header { + /** Starting ACL connection event count for the results reported in the event */ + uint16_t start_acl_conn_event; + /** Frequency compensation value in units of 0.01 ppm (15-bit signed integer). + * Note this value can be BT_HCI_LE_CS_SUBEVENT_RESULT_FREQ_COMPENSATION_NOT_AVAILABLE + * if the role is not the initiator, or the frequency compensation value is unavailable. + */ + uint16_t freq_compensation; + /** Ranging Done Status: + * 0x0: All results complete for the CS Procedure + * 0x1: Partial results with more to follow for the CS procedure + * 0xF: All subsequent CS Procedures aborted + * All other values: RFU + */ + uint8_t ranging_done_status : 4; + /** Subevent Done Status: + * 0x0: All results complete for the CS Subevent + * 0xF: Current CS Subevent aborted. + * All other values: RFU + */ + uint8_t subevent_done_status : 4; + /** Indicates the abort reason when Procedure_Done Status received from the Core Controller + * (Core Specification, Volume 4, Part 4, Section 7.7.65.44) is set to 0xF, + * otherwise the value is set to zero. + * 0x0: Report with no abort + * 0x1: Abort because of local Host or remote request + * 0x2: Abort because filtered channel map has less than 15 channels + * 0x3: Abort because the channel map update instant has passed + * 0xF: Abort because of unspecified reasons + * All other values: RFU + */ + uint8_t ranging_abort_reason : 4; + /** Indicates the abort reason when Subevent_Done_Status received from the Core Controller + * (Core Specification, Volume 4, Part 4, Section 7.7.65.44) is set to 0xF, + * otherwise the default value is set to zero. + * 0x0: Report with no abort + * 0x1: Abort because of local Host or remote request + * 0x2: Abort because no CS_SYNC (mode 0) received + * 0x3: Abort because of scheduling conflicts or limited resources + * 0xF: Abort because of unspecified reasons + * All other values: RFU + */ + uint8_t subevent_abort_reason : 4; + /** Reference power level. Range: -127 to 20. Units: dBm */ + int8_t ref_power_level; + /** Number of steps in the CS Subevent for which results are reported. + * If the Subevent is aborted, then the Number Of Steps Reported can be set to zero + */ + uint8_t num_steps_reported; +} __packed; + + + +#endif \ No newline at end of file diff --git a/nimble/host/services/ras/pkg.yml b/nimble/host/services/ras/pkg.yml new file mode 100644 index 000000000..cd0c6bdde --- /dev/null +++ b/nimble/host/services/ras/pkg.yml @@ -0,0 +1,34 @@ +# +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. +# + +pkg.name: nimble/host/services/bas +pkg.description: Battery Service +pkg.author: "Apache Mynewt " +pkg.homepage: "http://mynewt.apache.org/" +pkg.keywords: + - ble + - bluetooth + - hid + - nimble + +pkg.deps: + - nimble/host + +pkg.init: + ble_svc_hid_init: 'MYNEWT_VAL(BLE_SVC_HID_SYSINIT_STAGE)' diff --git a/nimble/host/services/ras/src/rreq/ble_svc_ras_rreq.c b/nimble/host/services/ras/src/rreq/ble_svc_ras_rreq.c new file mode 100644 index 000000000..7c1582884 --- /dev/null +++ b/nimble/host/services/ras/src/rreq/ble_svc_ras_rreq.c @@ -0,0 +1,35 @@ +#include +#include +#include +#include "host/ble_hs.h" +#include "host/ble_uuid.h" +#include "services/ras/ble_svc_ras.h" + +/*RAS control point state */ +enum ble_ras_rreq_cp_state { + BLE_RAS_RREQ_CP_STATE_NONE, + BLE_RAS_RREQ_CP_STATE_GET_RD_WRITTEN, + BLE_RAS_RREQ_CP_STATE_ACK_RD_WRITTEN, +}; + +#define BLE_UUID_RANGING_SERVICE_VAL (0x185B) + +/** @brief UUID of the RAS Features Characteristic. **/ +#define BLE_UUID_RAS_FEATURES_VAL (0x2C14) + +/** @brief UUID of the Real-time Ranging Data Characteristic. **/ +#define BLE_UUID_RAS_REALTIME_RD_VAL (0x2C15) + +/** @brief UUID of the On-demand Ranging Data Characteristic. **/ +#define BLE_UUID_RAS_ONDEMAND_RD_VAL (0x2C16) + +/** @brief UUID of the RAS Control Point Characteristic. **/ +#define BLE_UUID_RAS_CP_VAL (0x2C17) + +/** @brief UUID of the Ranging Data Ready Characteristic. **/ +#define BLE_UUID_RAS_RD_READY_VAL (0x2C18) + +/** @brief UUID of the Ranging Data Overwritten Characteristic. **/ +#define BLE_UUID_RAS_RD_OVERWRITTEN_VAL (0x2C19) + + diff --git a/nimble/host/services/ras/src/rrsp/ble_svc_ras_rd_buffer.c b/nimble/host/services/ras/src/rrsp/ble_svc_ras_rd_buffer.c new file mode 100644 index 000000000..e69de29bb diff --git a/nimble/host/services/ras/src/rrsp/ble_svc_ras_rrsp.c b/nimble/host/services/ras/src/rrsp/ble_svc_ras_rrsp.c new file mode 100644 index 000000000..885c2fcf1 --- /dev/null +++ b/nimble/host/services/ras/src/rrsp/ble_svc_ras_rrsp.c @@ -0,0 +1,206 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + + #include + #include + #include + #include "host/ble_hs.h" + #include "host/ble_uuid.h" + #include "services/ras/ble_svc_ras.h" + + + + /* Char values */ +static int32_t ble_svc_ras_feat_val; +static uint16_t ble_svc_ras_rd_val; +static uint16_t ble_svc_ras_rd_ov_val; +static uint16_t ble_svc_ras_cp_val + +static uint16_t ble_svc_ras_feat_val_handle; +static uint16_t ble_svc_ras_rd_val_handle; +static uint16_t ble_svc_ras_rd_ov_val_handle; +static uint16_t ble_svc_ras_cp_val_handle; +static u_int16_t ble_svc_ras_od_val_handle; + + static int + gatt_svr_chr_access_ras_val(uint16_t conn_handle, uint16_t attr_handle, + struct ble_gatt_access_ctxt *ctxt, void *arg); + + static const struct ble_gatt_svc_def gatt_svr_svcs[] = { + { + /* Service: Ranging Data Service */ + .type = BLE_GATT_SVC_TYPE_PRIMARY, + .uuid = BLE_UUID16_DECLARE(BLE_UUID_RANGING_SERVICE_VAL), + .characteristics = (struct ble_gatt_chr_def[]) + { { + /* Characteristic: Feature Value */ + .uuid = BLE_UUID16_DECLARE(BLE_UUID_RAS_FEATURES_VAL), + .access_cb = gatt_svr_chr_access_ras_feature, + .val_handle = &ble_svc_ras_feat_val_handle, + .flags = BLE_GATT_CHR_F_READ|BLE_GATT_CHR_F_READ_ENC, + }, { + /* Characteristic: On demand ranging data */ + .uuid = BLE_UUID16_DECLARE(BLE_UUID_RAS_ONDEMAND_RD_VAL), + .access_cb = gatt_svr_chr_access_ras_feature, + .val_handle = ble_svc_ras_od_val_handle, + .flags = BLE_GATT_CHR_F_NOTIFY | BLE_GATT_CHR_F_INDICATE |BLE_GATT_CHR_F_READ_ENC + , + },{ + /* Characteristic: RAS Control Point */ + .uuid = BLE_UUID16_DECLARE(BLE_UUID_RAS_CP_VAL), + .access_cb = gatt_svr_chr_access_ras_feature, + .val_handle = ble_svc_ras_cp_val_handle, + .flags = BLE_GATT_CHR_F_WRITE_NO_RSP | BLE_GATT_CHR_F_INDICATE |BLE_GATT_CHR_F_READ_ENC , + },{ + /* Characteristic: RAS Data Ready */ + .uuid = BLE_UUID16_DECLARE(BLE_UUID_RAS_RD_READY_VAL), + .access_cb = gatt_svr_chr_access_ras_feature, + .val_handle = ble_svc_ras_rd_val_handle, + .flags = BLE_GATT_CHR_F_INDICATE | BLE_GATT_CHR_F_READ_ENC, + },{ + /* Characteristic: RAS data overwritten */ + .uuid = BLE_UUID16_DECLARE(BLE_UUID_RAS_RD_OVERWRITTEN_VAL), + .access_cb = gatt_svr_chr_access_ras_feature, + .val_handle=ble_svc_ras_rd_ov_val_handle, + .flags = BLE_GATT_CHR_F_INDICATE | BLE_GATT_CHR_F_READ_ENC, + }, { + 0, /* No more characteristics in this service */ + }, + } + }, + { + 0, /* No more services */ + }, + }; + + + static int + gatt_svr_chr_access_ras_val(uint16_t conn_handle, uint16_t attr_handle, + struct ble_gatt_access_ctxt *ctxt, void *arg) + { + const ble_uuid_t *uuid; + int rc; + + switch (ctxt->op) { + case BLE_GATT_ACCESS_OP_READ_CHR: + if (conn_handle != BLE_HS_CONN_HANDLE_NONE) { + MODLOG_DFLT(INFO, "Characteristic read; conn_handle=%d attr_handle=%d\n", + conn_handle, attr_handle); + } else { + MODLOG_DFLT(INFO, "Characteristic read by NimBLE stack; attr_handle=%d\n", + attr_handle); + } + uuid = ctxt->chr->uuid; + if(uuid == BLE_UUID_RAS_FEATURES_VAL){ + + if (attr_handle == ras_feat_val_handle) { + rc = os_mbuf_append(ctxt->om, + &ras_feat_val, + sizeof(ras_feat_val)); + return rc == 0 ? 0 : BLE_ATT_ERR_INSUFFICIENT_RES; + } + } + goto unknown; + + case BLE_GATT_ACCESS_OP_WRITE_CHR: + if (conn_handle != BLE_HS_CONN_HANDLE_NONE) { + MODLOG_DFLT(INFO, "Characteristic write; conn_handle=%d attr_handle=%d", + conn_handle, attr_handle); + } else { + MODLOG_DFLT(INFO, "Characteristic write by NimBLE stack; attr_handle=%d", + attr_handle); + } + uuid = ctxt->chr->uuid; + if (attr_handle == ras_feat_val_handle) { + rc = gatt_svr_write(ctxt->om, + sizeof(ras_feat_val), + sizeof(ras_feat_val), + &ras_feat_val, NULL); + ble_gatts_chr_updated(attr_handle); + MODLOG_DFLT(INFO, "Notification/Indication scheduled for " + "all subscribed peers.\n"); + return rc; + } + goto unknown; + default: + goto unknown; + } + +unknown: + /* Unknown characteristic/descriptor; + * The NimBLE host should not have called this function; + */ + assert(0); + return BLE_ATT_ERR_UNLIKELY; + + } + + void + gatt_svr_register_cb(struct ble_gatt_register_ctxt *ctxt, void *arg) + { + char buf[BLE_UUID_STR_LEN]; + + switch (ctxt->op) { + case BLE_GATT_REGISTER_OP_SVC: + MODLOG_DFLT(DEBUG, "registered service %s with handle=%d\n", + ble_uuid_to_str(ctxt->svc.svc_def->uuid, buf), + ctxt->svc.handle); + break; + + case BLE_GATT_REGISTER_OP_CHR: + MODLOG_DFLT(DEBUG, "registering characteristic %s with " + "def_handle=%d val_handle=%d\n", + ble_uuid_to_str(ctxt->chr.chr_def->uuid, buf), + ctxt->chr.def_handle, + ctxt->chr.val_handle); + break; + + case BLE_GATT_REGISTER_OP_DSC: + MODLOG_DFLT(DEBUG, "registering descriptor %s with handle=%d\n", + ble_uuid_to_str(ctxt->dsc.dsc_def->uuid, buf), + ctxt->dsc.handle); + break; + + default: + assert(0); + break; + } + } + + int + gatt_svr_init(void) + { + int rc; + + ble_svc_gap_init(); + ble_svc_gatt_init(); + + rc = ble_gatts_count_cfg(gatt_svr_svcs); + if (rc != 0) { + return rc; + } + + rc = ble_gatts_add_svcs(gatt_svr_svcs); + if (rc != 0) { + return rc; + } + + return 0; + } + \ No newline at end of file diff --git a/nimble/host/src/ble_cs.c b/nimble/host/src/ble_cs.c new file mode 100644 index 000000000..13902dc2b --- /dev/null +++ b/nimble/host/src/ble_cs.c @@ -0,0 +1,810 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#include +#include "syscfg/syscfg.h" +#include "ble_hs_mbuf_priv.h" + +#if MYNEWT_VAL(BLE_CHANNEL_SOUNDING) + +#include "os/os_mbuf.h" +#include "host/ble_hs_log.h" +#include "host/ble_hs.h" +#include "host/ble_cs.h" +#include "nimble/hci_common.h" +#include "sys/queue.h" +#include "ble_hs_hci_priv.h" + +#define BT_LE_CS_CHANNEL_BIT_SET_VAL(chmap, bit, val) \ +((chmap)[(bit) / 8] = ((chmap)[(bit) / 8] & ~BIT((bit) % 8)) | ((val) << ((bit) % 8))) + + +static void print_ev_sz(int len ,int sz,int status){ + printf("len= %d\n",len); + printf("size = %d\n",sz); + printf("status %d\n",status); +} +struct ble_cs_rd_rem_supp_cap_cp { + uint16_t conn_handle; +} __attribute__((packed)); + +struct ble_cs_wr_cached_rem_supp_cap_cp { + uint16_t conn_handle; + uint8_t num_config_supported; + uint16_t max_consecutive_procedures_supported; + uint8_t num_antennas_supported; + uint8_t max_antenna_paths_supported; + uint8_t roles_supported; + uint8_t optional_modes_supported; + uint8_t rtt_capability; + uint8_t rtt_aa_only_n; + uint8_t rtt_sounding_n; + uint8_t rtt_random_payload_n; + uint16_t optional_nadm_sounding_capability; + uint16_t optional_nadm_random_capability; + uint8_t optional_cs_sync_phys_supported; + uint16_t optional_subfeatures_supported; + uint16_t optional_t_ip1_times_supported; + uint16_t optional_t_ip2_times_supported; + uint16_t optional_t_fcs_times_supported; + uint16_t optional_t_pm_times_supported; + uint8_t t_sw_time_supported; +} __attribute__((packed)); +struct ble_cs_wr_cached_rem_supp_cap_rp { + uint16_t conn_handle; +} __attribute__((packed)); + +struct ble_cs_sec_enable_cp { + uint16_t conn_handle; +} __attribute__((packed)); + +struct ble_cs_set_def_settings_cp { + uint16_t conn_handle; + uint8_t role_enable; + uint8_t cs_sync_antenna_selection; + uint8_t max_tx_power; +} __attribute__((packed)); +struct ble_cs_set_def_settings_rp { + uint16_t conn_handle; +} __attribute__((packed)); + +struct ble_cs_rd_rem_fae_cp { + uint16_t conn_handle; +} __attribute__((packed)); + +struct ble_cs_wr_cached_rem_fae_cp { + uint16_t conn_handle; + uint8_t remote_fae_table[72]; +} __attribute__((packed)); +struct ble_cs_wr_cached_rem_fae_rp { + uint16_t conn_handle; +} __attribute__((packed)); + +struct ble_cs_create_config_cp { + uint16_t conn_handle; + uint8_t config_id; + /* If the config should be created on the remote controller too */ + uint8_t create_context; + /* The main mode to be used in the CS procedures */ + uint8_t main_mode_type; + /* The sub mode to be used in the CS procedures */ + uint8_t sub_mode_type; + /* Minimum/maximum number of CS main mode steps to be executed before + * a submode step. + */ + uint8_t min_main_mode_steps; + uint8_t max_main_mode_steps; + /* The number of main mode steps taken from the end of the last + * CS subevent to be repeated at the beginning of the current CS subevent + * directly after the last mode 0 step of that event + */ + uint8_t main_mode_repetition; + uint8_t mode_0_steps; + uint8_t role; + uint8_t rtt_type; + uint8_t cs_sync_phy; + uint8_t channel_map[10]; + uint8_t channel_map_repetition; + uint8_t channel_selection_type; + uint8_t ch3c_shape; + uint8_t ch3c_jump; + uint8_t companion_signal_enable; +} __attribute__((packed)); + +struct ble_cs_remove_config_cp { + uint16_t conn_handle; + uint8_t config_id; +} __attribute__((packed)); + +struct ble_cs_set_chan_class_cp { + uint8_t channel_classification[10]; +} __attribute__((packed)); + +struct ble_cs_set_proc_params_cp { + uint16_t conn_handle; + uint8_t config_id; + /* The maximum duration of each CS procedure (time = N × 0.625 ms) */ + uint16_t max_procedure_len; + /* The minimum and maximum number of connection events between + * consecutive CS procedures. Ignored if only one CS procedure. */ + uint16_t min_procedure_interval; + uint16_t max_procedure_interval; + /* The maximum number of consecutive CS procedures to be scheduled */ + uint16_t max_procedure_count; + /* Minimum/maximum suggested durations for each CS subevent in microseconds. + * Only 3 bytes meaningful. */ + uint32_t min_subevent_len; + uint32_t max_subevent_len; + /* Antenna Configuration Index (ACI) for swithing during phase measuement */ + uint8_t tone_antenna_config_selection; + /* The remote device’s Tx PHY. A 4 bits bitmap. */ + uint8_t phy; + /* How many more or fewer of transmit power levels should the remote device’s + * Tx PHY use during the CS tones and RTT transmission */ + uint8_t tx_power_delta; + /* Preferred peer-ordered antenna elements to be used by the peer for + * the selected antenna configuration (ACI). A 4 bits bitmap. */ + uint8_t preferred_peer_antenna; + /* SNR Output Index (SOI) for SNR control adjustment. */ + uint8_t snr_control_initiator; + uint8_t snr_control_reflector; +} __attribute__((packed)); +struct ble_cs_set_proc_params_rp { + uint16_t conn_handle; +} __attribute__((packed)); + +struct ble_cs_proc_enable_cp { + uint16_t conn_handle; + uint8_t config_id; + uint8_t enable; +} __attribute__((packed)); + +struct ble_cs_state { + uint8_t op; + ble_cs_event_fn *cb; + void *cb_arg; +}; + +static struct ble_cs_state cs_state; + +static int +ble_cs_call_event_cb(struct ble_cs_event *event) +{ + int rc; + + if (cs_state.cb != NULL) { + rc = cs_state.cb(event, cs_state.cb_arg); + } else { + rc = 0; + } + + return rc; +} + +static void +ble_cs_call_procedure_complete_cb(uint16_t conn_handle, uint8_t status) +{ + struct ble_cs_event event; + + memset(&event, 0, sizeof event); + event.type = BLE_CS_EVENT_CS_PROCEDURE_COMPLETE; + event.procedure_complete.conn_handle = conn_handle; + event.procedure_complete.status = status; + ble_cs_call_event_cb(&event); +} + +static void +ble_cs_call_result_cb(const struct ble_hci_ev_le_subev_cs_subevent_result *ev) +{ + struct ble_cs_event event; + memset(&event,0,sizeof event); + event.type = BLE_CS_EVENT_SUBEVET_RESULT; + event.subev_result.conn_handle = le16toh(ev->conn_handle); + event.subev_result.config_id = ev->config_id; + event.subev_result.start_acl_conn_event_counter=ev->start_acl_conn_event_counter; + event.subev_result.procedure_counter=ev->procedure_counter; + event.subev_result.frequency_compensation=ev->frequency_compensation; + event.subev_result.reference_power_level=ev->reference_power_level; + event.subev_result.procedure_done_status=ev->procedure_done_status; + event.subev_result.subevent_done_status=ev->subevent_done_status; + event.subev_result.abort_reason=ev->abort_reason; + event.subev_result.num_antenna_paths=ev->num_antenna_paths; + event.subev_result.num_steps_reported=ev->num_steps_reported; + memcpy(event.subev_result.steps,ev->steps,ev->num_steps_reported); + + ble_cs_call_event_cb(&event); +} + +static void ble_cs_call_result_continue_cb(const struct ble_hci_ev_le_subev_cs_subevent_result_continue *ev){ + struct ble_cs_event event; + memset(&event,0,sizeof event); + event.type = BLE_CS_EVENT_SUBEVET_RESULT_CONTINUE; + event.subev_result_continue.conn_handle=le16toh(ev->conn_handle); + event.subev_result_continue.config_id=ev->config_id; + event.subev_result_continue.procedure_done_status=ev->procedure_done_status; + event.subev_result_continue.subevent_done_status=ev->procedure_done_status; + event.subev_result_continue.abort_reason=ev->abort_reason; + event.subev_result_continue.num_antenna_paths=ev->num_antenna_paths; + event.subev_result_continue.num_steps_reported=ev->num_steps_reported; + memcpy(event.subev_result_continue.steps,ev->steps,ev->num_steps_reported); + + ble_cs_call_event_cb(&event); +} +static int +ble_cs_rd_loc_supp_cap(void) +{ + int rc; + struct ble_hci_le_cs_rd_loc_supp_cap_rp rp; + + rc = ble_hs_hci_cmd_tx(BLE_HCI_OP(BLE_HCI_OGF_LE, + BLE_HCI_OCF_LE_CS_RD_LOC_SUPP_CAP), + NULL, 0, &rp, sizeof(rp)); + + rp.max_consecutive_procedures_supported = le16toh(rp.max_consecutive_procedures_supported); + rp.optional_nadm_sounding_capability = le16toh(rp.optional_nadm_sounding_capability); + rp.optional_nadm_random_capability = le16toh(rp.optional_nadm_random_capability); + rp.optional_subfeatures_supported = le16toh(rp.optional_subfeatures_supported); + rp.optional_t_ip1_times_supported = le16toh(rp.optional_t_ip1_times_supported); + rp.optional_t_ip2_times_supported = le16toh(rp.optional_t_ip2_times_supported); + rp.optional_t_fcs_times_supported = le16toh(rp.optional_t_fcs_times_supported); + rp.optional_t_pm_times_supported = le16toh(rp.optional_t_pm_times_supported); + (void) rp; + + return rc; +} + +static int +ble_cs_rd_rem_supp_cap(const struct ble_cs_rd_rem_supp_cap_cp *cmd) +{ + struct ble_hci_le_cs_rd_rem_supp_cap_cp cp; + + cp.conn_handle = htole16(cmd->conn_handle); + + return ble_hs_hci_cmd_tx(BLE_HCI_OP(BLE_HCI_OGF_LE, + BLE_HCI_OCF_LE_CS_RD_REM_SUPP_CAP), + &cp, sizeof(cp), NULL, 0); +} + +static int +ble_cs_wr_cached_rem_supp_cap(const struct ble_cs_wr_cached_rem_supp_cap_cp *cmd, + struct ble_cs_wr_cached_rem_supp_cap_rp *rsp) +{ + struct ble_hci_le_cs_wr_cached_rem_supp_cap_cp cp; + struct ble_hci_le_cs_wr_cached_rem_supp_cap_rp rp; + int rc; + + cp.conn_handle = htole16(cmd->conn_handle); + cp.num_config_supported = cmd->num_config_supported; + cp.max_consecutive_procedures_supported = htole16(cmd->max_consecutive_procedures_supported); + cp.num_antennas_supported = cmd->num_antennas_supported; + cp.max_antenna_paths_supported = cmd->max_antenna_paths_supported; + cp.roles_supported = cmd->roles_supported; + cp.optional_modes_supported = cmd->optional_modes_supported; + cp.rtt_capability = cmd->rtt_capability; + cp.rtt_aa_only_n = cmd->rtt_aa_only_n; + cp.rtt_sounding_n = cmd->rtt_sounding_n; + cp.rtt_random_payload_n = cmd->rtt_random_payload_n; + cp.optional_nadm_sounding_capability = htole16(cmd->optional_nadm_sounding_capability); + cp.optional_nadm_random_capability = htole16(cmd->optional_nadm_random_capability); + cp.optional_cs_sync_phys_supported = cmd->optional_cs_sync_phys_supported; + cp.optional_subfeatures_supported = htole16(cmd->optional_subfeatures_supported); + cp.optional_t_ip1_times_supported = htole16(cmd->optional_t_ip1_times_supported); + cp.optional_t_ip2_times_supported = htole16(cmd->optional_t_ip2_times_supported); + cp.optional_t_fcs_times_supported = htole16(cmd->optional_t_fcs_times_supported); + cp.optional_t_pm_times_supported = htole16(cmd->optional_t_pm_times_supported); + cp.t_sw_time_supported = cmd->t_sw_time_supported; + + rc = ble_hs_hci_cmd_tx(BLE_HCI_OP(BLE_HCI_OGF_LE, + BLE_HCI_OCF_LE_CS_WR_CACHED_REM_SUPP_CAP), + &cp, sizeof(cp), &rp, sizeof(rp)); + + rsp->conn_handle = le16toh(rp.conn_handle); + + return rc; +} + +static int +ble_cs_sec_enable(const struct ble_cs_sec_enable_cp *cmd) +{ + struct ble_hci_le_cs_sec_enable_cp cp; + + cp.conn_handle = htole16(cmd->conn_handle); + + return ble_hs_hci_cmd_tx(BLE_HCI_OP(BLE_HCI_OGF_LE, + BLE_HCI_OCF_LE_CS_SEC_ENABLE), + &cp, sizeof(cp), NULL, 0); +} + +static int +ble_cs_set_def_settings(const struct ble_cs_set_def_settings_cp *cmd, + struct ble_cs_set_def_settings_rp *rsp) +{ + struct ble_hci_le_cs_set_def_settings_cp cp; + struct ble_hci_le_cs_set_def_settings_rp rp; + int rc; + + cp.conn_handle = htole16(cmd->conn_handle); + cp.role_enable = cmd->role_enable; + cp.cs_sync_antenna_selection = cmd->cs_sync_antenna_selection; + cp.max_tx_power = cmd->max_tx_power; + + rc = ble_hs_hci_cmd_tx(BLE_HCI_OP(BLE_HCI_OGF_LE, + BLE_HCI_OCF_LE_CS_SET_DEF_SETTINGS), + &cp, sizeof(cp), &rp, sizeof(rp)); + + rsp->conn_handle = le16toh(rp.conn_handle); + + return rc; +} + +static int +ble_cs_rd_rem_fae(const struct ble_cs_rd_rem_fae_cp *cmd) +{ + struct ble_hci_le_cs_rd_rem_fae_cp cp; + + cp.conn_handle = htole16(cmd->conn_handle); + + return ble_hs_hci_cmd_tx(BLE_HCI_OP(BLE_HCI_OGF_LE, + BLE_HCI_OCF_LE_CS_RD_REM_FAE), + &cp, sizeof(cp), NULL, 0); +} + +static int +ble_cs_wr_cached_rem_fae(const struct ble_cs_wr_cached_rem_fae_cp *cmd, + struct ble_cs_wr_cached_rem_fae_rp *rsp) +{ + struct ble_hci_le_cs_wr_cached_rem_fae_cp cp; + struct ble_hci_le_cs_wr_cached_rem_fae_rp rp; + int rc; + + cp.conn_handle = htole16(cmd->conn_handle); + memcpy(cp.remote_fae_table, cmd->remote_fae_table, 72); + + rc = ble_hs_hci_cmd_tx(BLE_HCI_OP(BLE_HCI_OGF_LE, + BLE_HCI_OCF_LE_CS_WR_CACHED_REM_FAE), + &cp, sizeof(cp), &rp, sizeof(rp)); + + rsp->conn_handle = le16toh(rp.conn_handle); + + return rc; +} + +static int +ble_cs_create_config(const struct ble_cs_create_config_cp *cmd) +{ + struct ble_hci_le_cs_create_config_cp cp; + + cp.conn_handle = htole16(cmd->conn_handle); + cp.config_id = cmd->config_id; + cp.create_context = cmd->create_context; + cp.main_mode_type = cmd->main_mode_type; + cp.sub_mode_type = cmd->sub_mode_type; + cp.min_main_mode_steps = cmd->min_main_mode_steps; + cp.max_main_mode_steps = cmd->max_main_mode_steps; + cp.main_mode_repetition = cmd->main_mode_repetition; + cp.mode_0_steps = cmd->mode_0_steps; + cp.role = cmd->role; + cp.rtt_type = cmd->rtt_type; + cp.cs_sync_phy = cmd->cs_sync_phy; + memcpy(cp.channel_map, cmd->channel_map, 10); + cp.channel_map_repetition = cmd->channel_map_repetition; + cp.channel_selection_type = cmd->channel_selection_type; + cp.ch3c_shape = cmd->ch3c_shape; + cp.ch3c_jump = cmd->ch3c_jump; + cp.companion_signal_enable = cmd->companion_signal_enable; + + return ble_hs_hci_cmd_tx(BLE_HCI_OP(BLE_HCI_OGF_LE, + BLE_HCI_OCF_LE_CS_CREATE_CONFIG), + &cp, sizeof(cp), NULL, 0); +} + +static int +ble_cs_remove_config(const struct ble_cs_remove_config_cp *cmd) +{ + struct ble_hci_le_cs_remove_config_cp cp; + + cp.conn_handle = htole16(cmd->conn_handle); + cp.config_id = cmd->config_id; + + return ble_hs_hci_cmd_tx(BLE_HCI_OP(BLE_HCI_OGF_LE, + BLE_HCI_OCF_LE_CS_REMOVE_CONFIG), + &cp, sizeof(cp), NULL, 0); +} + +static int +ble_cs_set_chan_class(const struct ble_cs_set_chan_class_cp *cmd) +{ + struct ble_hci_le_cs_set_chan_class_cp cp; + int rc; + + memcpy(cp.channel_classification, cmd->channel_classification, 10); + + rc = ble_hs_hci_cmd_tx(BLE_HCI_OP(BLE_HCI_OGF_LE, + BLE_HCI_OCF_LE_CS_SET_CHAN_CLASS), + &cp, sizeof(cp), NULL, 0); + + return rc; +} + +static int +ble_cs_set_proc_params(const struct ble_cs_set_proc_params_cp *cmd, + struct ble_cs_set_proc_params_rp *rsp) +{ + struct ble_hci_le_cs_set_proc_params_cp cp; + struct ble_hci_le_cs_set_proc_params_rp rp; + int rc; + + cp.conn_handle = htole16(cmd->conn_handle); + cp.config_id = cmd->config_id; + cp.max_procedure_len = htole16(cmd->max_procedure_len); + cp.min_procedure_interval = htole16(cmd->min_procedure_interval); + cp.max_procedure_interval = htole16(cmd->max_procedure_interval); + cp.max_procedure_count = htole16(cmd->max_procedure_count); + put_le24(cp.min_subevent_len, cmd->min_subevent_len); + put_le24(cp.max_subevent_len, cmd->max_subevent_len); + cp.tone_antenna_config_selection = cmd->tone_antenna_config_selection; + cp.phy = cmd->phy; + cp.tx_power_delta = cmd->tx_power_delta; + cp.preferred_peer_antenna = cmd->preferred_peer_antenna; + cp.snr_control_initiator = cmd->snr_control_initiator; + cp.snr_control_reflector = cmd->snr_control_reflector; + + rc = ble_hs_hci_cmd_tx(BLE_HCI_OP(BLE_HCI_OGF_LE, + BLE_HCI_OCF_LE_CS_SET_PROC_PARAMS), + &cp, sizeof(cp), &rp, sizeof(rp)); + + rsp->conn_handle = le16toh(rp.conn_handle); + + return rc; +} + +static int +ble_cs_proc_enable(const struct ble_cs_proc_enable_cp *cmd) +{ + struct ble_hci_le_cs_proc_enable_cp cp; + + cp.conn_handle = htole16(cmd->conn_handle); + cp.config_id = cmd->config_id; + cp.enable = cmd->enable; + + return ble_hs_hci_cmd_tx(BLE_HCI_OP(BLE_HCI_OGF_LE, + BLE_HCI_OCF_LE_CS_PROC_ENABLE), + &cp, sizeof(cp), NULL, 0); +} + +int +ble_hs_hci_evt_le_cs_rd_rem_supp_cap_complete(uint8_t subevent, const void *data, + unsigned int len) +{ + printf("ble_hs_hci_evt_le_cs_rd_rem_supp_cap_complete\n"); + int rc; + const struct ble_hci_ev_le_subev_cs_rd_rem_supp_cap_complete *ev = data; + struct ble_cs_set_def_settings_cp set_cmd; + struct ble_cs_set_def_settings_rp set_rsp; + struct ble_cs_rd_rem_fae_cp fae_cmd; + + + printf("ev->startus = %d\n", ev->status); + printf("sizeof(*ev)= %d\n",sizeof(*ev)); + printf("len= %d\n",len); + if (len != sizeof(*ev) || ev->status) { + printf("\n BLE_HS_ECONTROLLER\n"); + return BLE_HS_ECONTROLLER; + } + + BLE_HS_LOG(INFO, "CS capabilities exchanged"); + + /* TODO: Save the remote capabilities somewhere */ + + set_cmd.conn_handle = le16toh(ev->conn_handle); + /* Only initiator role is enabled */ + printf("ble_global_status %d\n",ble_global_status); + if(ble_global_status==0){ + set_cmd.role_enable = 0x01; + } + else{ + set_cmd.role_enable = 0x02; + } + /* Use antenna with ID 0x01 */ + set_cmd.cs_sync_antenna_selection = 0xFE; + /* Set max TX power to the max supported */ + set_cmd.max_tx_power = 20; + + rc = ble_cs_set_def_settings(&set_cmd, &set_rsp); + if (rc) { + BLE_HS_LOG(INFO, "Failed to set the default CS settings, err %dt", rc); + + return rc; + } + BLE_HS_LOG(INFO, "Set default CS settings "); + + + /* Read the mode 0 Frequency Actuation Error table */ + fae_cmd.conn_handle = le16toh(ev->conn_handle); + rc = ble_cs_rd_rem_fae(&fae_cmd); + if (rc) { + BLE_HS_LOG(INFO, "Failed to read FAE table"); + } + + return rc; +} + +int +ble_hs_hci_evt_le_cs_rd_rem_fae_complete(uint8_t subevent, const void *data, + unsigned int len) +{ + printf("ble_hs_hci_evt_le_cs_rd_rem_fae_complete\n"); + const struct ble_hci_ev_le_subev_cs_rd_rem_fae_complete *ev = data; + struct ble_cs_create_config_cp cmd; + int rc; + + + print_ev_sz(len,sizeof(*ev),ev->status); + if (len != sizeof(*ev) || ev->status) { + printf("BLE_HS_ECONTROLLER fae \n"); + // return BLE_HS_ECONTROLLER; + } + + cmd.conn_handle = le16toh(ev->conn_handle); + /* The config will use ID 0x00 */ + cmd.config_id = 0x00; + /* Create the config on the remote controller too */ + cmd.create_context = 0x00; + /* Measure phase rotations in main mode */ + cmd.main_mode_type = 0x01; + /* Do not use sub mode for now. */ + cmd.sub_mode_type = 0x00; + /* Range from which the number of CS main mode steps to execute + * will be randomly selected. + */ + cmd.min_main_mode_steps = 0x02; + cmd.max_main_mode_steps = 0x05; + /* The number of main mode steps to be repeated at the beginning of + * the current CS, irrespectively if there are some overlapping main + * mode steps from previous CS subevent or not. + */ + cmd.main_mode_repetition = 0x00; + /* Number of CS mode 0 steps to be included at the beginning of + * each CS subevent + */ + cmd.mode_0_steps = 0x03; + /* Take the Initiator role */ + cmd.role = 0x01; + cmd.rtt_type = 0x00; + cmd.cs_sync_phy = 0x01; + // memcpy(cmd.channel_map, (uint8_t[10]) {0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, 10); + BT_LE_CS_CHANNEL_BIT_SET_VAL(cmd.channel_map, 0, 0); +BT_LE_CS_CHANNEL_BIT_SET_VAL(cmd.channel_map, 1, 0); +BT_LE_CS_CHANNEL_BIT_SET_VAL(cmd.channel_map, 23, 0); +BT_LE_CS_CHANNEL_BIT_SET_VAL(cmd.channel_map, 24, 0); +BT_LE_CS_CHANNEL_BIT_SET_VAL(cmd.channel_map, 25, 0); +BT_LE_CS_CHANNEL_BIT_SET_VAL(cmd.channel_map, 77, 0); +BT_LE_CS_CHANNEL_BIT_SET_VAL(cmd.channel_map, 78, 0); +BT_LE_CS_CHANNEL_BIT_SET_VAL(cmd.channel_map, 79, 0); + + cmd.channel_map_repetition = 0x03; + /* Use Channel Selection Algorithm #3b */ + cmd.channel_selection_type = 0x00; + /* Ignore these as used only with #3c algorithm */ + cmd.ch3c_shape = 0x00; + cmd.ch3c_jump = 0x02; + /* EDLC/ECLD attack protection not supported */ + // cmd.companion_signal_enable = 0x00; + + /* Create CS config */ + rc = ble_cs_create_config(&cmd); + if (rc) { + BLE_HS_LOG(INFO, "Failed to create CS config"); + } + + return rc; +} + +int +ble_hs_hci_evt_le_cs_sec_enable_complete(uint8_t subevent, const void *data, + unsigned int len) +{ + printf("ble_hs_hci_evt_le_cs_sec_enable_complete\n"); + int rc; + struct ble_cs_set_proc_params_cp cmd; + struct ble_cs_set_proc_params_rp rsp; + struct ble_cs_proc_enable_cp enable_cmd; + const struct ble_hci_ev_le_subev_cs_sec_enable_complete *ev = data; + + if (len != sizeof(*ev)) { + BLE_HS_LOG(INFO, "Failed to enable CS security BLE_HS_ECNOTEROLLER"); + + return BLE_HS_ECONTROLLER; + } + + BLE_HS_LOG(INFO, "CS setup phase completed"); + + cmd.conn_handle = le16toh(ev->conn_handle); + cmd.config_id = 0x00; + /* The maximum duration of each CS procedure (time = N × 0.625 ms) */ + cmd.max_procedure_len = 8; + /* The maximum number of consecutive CS procedures to be scheduled + * as part of this measurement + */ + cmd.max_procedure_count = 0x0001; + /* The minimum and maximum number of connection events between + * consecutive CS procedures. Ignored if only one CS procedure. + */ + cmd.min_procedure_interval = 0x0000; + cmd.max_procedure_interval = 0x0000; + /* Minimum/maximum suggested durations for each CS subevent in microseconds. + * 1250us and 5000us selected. + */ + cmd.min_subevent_len = 1250; + cmd.max_subevent_len = 5000; + /* Use ACI 0 as we have only one antenna on each side */ + cmd.tone_antenna_config_selection = 0x00; + /* Use LE 1M PHY for CS procedures */ + cmd.phy = 0x01; + /* Transmit power delta set to 0x80 means Host does not have a recommendation. */ + cmd.tx_power_delta = 0x80; + /* Preferred antenna array elements to use. We have only a single antenna here. */ + cmd.preferred_peer_antenna = 0x01; + /* SNR Output Index (SOI) for SNR control adjustment. 0xFF means SNR control + * is not to be applied. + */ + cmd.snr_control_initiator = 0xff; + cmd.snr_control_reflector = 0xff; + + rc = ble_cs_set_proc_params(&cmd, &rsp); + if (rc) { + BLE_HS_LOG(INFO, "Failed to set CS procedure parameters"); + } + + enable_cmd.conn_handle = le16toh(ev->conn_handle); + enable_cmd.config_id = 0x00; + enable_cmd.enable = 0x01; + + rc = ble_cs_proc_enable(&enable_cmd); + if (rc) { + BLE_HS_LOG(INFO, "Failed to enable CS procedure"); + } + + return rc; +} + +int +ble_hs_hci_evt_le_cs_config_complete(uint8_t subevent, const void *data, + unsigned int len) +{ + printf("ble_hs_hci_evt_le_cs_config_complete\n"); + int rc; + const struct ble_hci_ev_le_subev_cs_config_complete *ev = data; + struct ble_cs_sec_enable_cp cmd; + + if (len != sizeof(*ev) || ev->status) { + printf("_cs_config_complete BLE_HS_ECONTROLLER\n"); + return BLE_HS_ECONTROLLER; + } + + cmd.conn_handle = le16toh(ev->conn_handle); + + /* Exchange CS security keys */ + rc = ble_cs_sec_enable(&cmd); + if (rc) { + BLE_HS_LOG(INFO, "Failed to enable CS security"); + ble_cs_call_procedure_complete_cb(le16toh(ev->conn_handle), ev->status); + } + + return 0; +} + +int +ble_hs_hci_evt_le_cs_proc_enable_complete(uint8_t subevent, const void *data, + unsigned int len) +{ + const struct ble_hci_ev_le_subev_cs_proc_enable_complete *ev = data; + + if (len != sizeof(*ev) || ev->status) { + return BLE_HS_ECONTROLLER; + } + + + return 0; +} + +int +ble_hs_hci_evt_le_cs_subevent_result(uint8_t subevent, const void *data, + unsigned int len) +{ + const struct ble_hci_ev_le_subev_cs_subevent_result *ev = data; + + if (len != sizeof(*ev)) { + return BLE_HS_ECONTROLLER; + } + + ble_cs_call_result_cb(ev); + return 0; +} + +int +ble_hs_hci_evt_le_cs_subevent_result_continue(uint8_t subevent, const void *data, + unsigned int len) +{ + const struct ble_hci_ev_le_subev_cs_subevent_result_continue *ev = data; + + if (len != sizeof(*ev)) { + return BLE_HS_ECONTROLLER; + } + ble_cs_call_result_continue_cb(ev); + return 0; +} + +int +ble_hs_hci_evt_le_cs_test_end_complete(uint8_t subevent, const void *data, + unsigned int len) +{ + const struct ble_hci_ev_le_subev_cs_test_end_complete *ev = data; + + if (len != sizeof(*ev)) { + return BLE_HS_ECONTROLLER; + } + + return 0; +} + + +int +ble_cs_initiator_procedure_start(const struct ble_cs_initiator_procedure_start_params *params) +{ + struct ble_hci_le_cs_rd_loc_supp_cap_rp rsp; + struct ble_cs_rd_rem_supp_cap_cp cmd; + int rc; + + /* Channel Sounding setup phase: + * 1. Set local default CS settings + * 2. Exchange CS capabilities with the remote + * 3. Read or write the mode 0 Frequency Actuation Error table + * 4. Create CS configurations + * 5. Start the CS Security Start procedure + */ + + cs_state.cb = params->cb; + cs_state.cb_arg = params->cb_arg; + + cmd.conn_handle = params->conn_handle; + rc = ble_cs_rd_rem_supp_cap(&cmd); + if (rc) { + BLE_HS_LOG(DEBUG, "Failed to read local supported CS capabilities," + "err %dt", rc); + } + printf("cmd sent succfully\n"); + return rc; +} + +int +ble_cs_initiator_procedure_terminate(uint16_t conn_handle) +{ + return 0; +} + +int +ble_cs_reflector_setup(struct ble_cs_reflector_setup_params *params) +{ + cs_state.cb = params->cb; + cs_state.cb_arg = params->cb_arg; + + return 0; +} +#endif diff --git a/nimble/host/src/ble_cs_priv.h b/nimble/host/src/ble_cs_priv.h new file mode 100644 index 000000000..f02565852 --- /dev/null +++ b/nimble/host/src/ble_cs_priv.h @@ -0,0 +1,31 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#ifndef H_BLE_CS_PRIV_ +#define H_BLE_CS_PRIV_ + +int ble_hs_hci_evt_le_cs_rd_rem_supp_cap_complete(uint8_t subevent, const void *data, unsigned int len); +int ble_hs_hci_evt_le_cs_rd_rem_fae_complete(uint8_t subevent, const void *data, unsigned int len); +int ble_hs_hci_evt_le_cs_sec_enable_complete(uint8_t subevent, const void *data, unsigned int len); +int ble_hs_hci_evt_le_cs_config_complete(uint8_t subevent, const void *data, unsigned int len); +int ble_hs_hci_evt_le_cs_proc_enable_complete(uint8_t subevent, const void *data, unsigned int len); +int ble_hs_hci_evt_le_cs_subevent_result(uint8_t subevent, const void *data, unsigned int len); +int ble_hs_hci_evt_le_cs_subevent_result_continue(uint8_t subevent, const void *data, unsigned int len); +int ble_hs_hci_evt_le_cs_test_end_complete(uint8_t subevent, const void *data, unsigned int len); +#endif diff --git a/nimble/host/src/ble_gap.c b/nimble/host/src/ble_gap.c index 928214537..2867f2e06 100644 --- a/nimble/host/src/ble_gap.c +++ b/nimble/host/src/ble_gap.c @@ -104,6 +104,9 @@ #define BLE_GAP_OP_S_PERIODIC_ADV 2 #define BLE_GAP_OP_SYNC 1 + +int ble_global_status = 0; + /** * If an attempt to cancel an active procedure fails, the attempt is retried * at this rate (ms). @@ -1210,6 +1213,7 @@ ble_gap_master_connect_reattempt(uint16_t conn_handle) return rc; } + ble_global_status=BLE_GAP_ROLE_SLAVE; if (conn.role == BLE_GAP_ROLE_MASTER) { /* If there was a connection update in progress, indicate to the * application that it did not complete. @@ -1218,6 +1222,8 @@ ble_gap_master_connect_reattempt(uint16_t conn_handle) entry = ble_gap_update_entry_remove(conn_handle); ble_hs_unlock(); + ble_global_status=BLE_GAP_ROLE_MASTER; + if (entry != NULL) { ble_gap_update_notify(conn_handle, BLE_ERR_CONN_ESTABLISHMENT); ble_gap_update_entry_free(entry); @@ -2955,6 +2961,7 @@ ble_gap_rx_conn_complete(struct ble_gap_conn_complete *evt, uint8_t instance) switch (evt->role) { case BLE_HCI_LE_CONN_COMPLETE_ROLE_MASTER: + ble_global_status=0; rc = ble_gap_accept_master_conn(); if (rc != 0) { return rc; @@ -2962,6 +2969,7 @@ ble_gap_rx_conn_complete(struct ble_gap_conn_complete *evt, uint8_t instance) break; case BLE_HCI_LE_CONN_COMPLETE_ROLE_SLAVE: + ble_global_status=1; rc = ble_gap_accept_slave_conn(instance); if (rc != 0) { return rc; @@ -10037,3 +10045,11 @@ ble_gap_host_check_status(void) return status; } + +int ble_gap_set_host_feat(uint8_t bit_num,uint8_t bit_val) { + struct ble_hci_le_set_host_feature_cp cmd; + cmd.bit_num=bit_num; + cmd.bit_val=bit_val; + return ble_hs_hci_cmd_tx(BLE_HCI_OP(BLE_HCI_OGF_LE, + BLE_HCI_OCF_LE_SET_HOST_FEATURE),&cmd, sizeof(cmd), NULL, 0); +} diff --git a/nimble/host/src/ble_hs_hci_evt.c b/nimble/host/src/ble_hs_hci_evt.c index 4712bcdc6..a6460988e 100644 --- a/nimble/host/src/ble_hs_hci_evt.c +++ b/nimble/host/src/ble_hs_hci_evt.c @@ -48,6 +48,10 @@ static uint16_t ble_adv_list_count; #define BLE_ADV_LIST_MAX_COUNT 200 #endif +#if MYNEWT_VAL(BLE_CHANNEL_SOUNDING) +#include "ble_cs_priv.h" +#endif + _Static_assert(sizeof (struct hci_data_hdr) == BLE_HCI_DATA_HDR_SZ, "struct hci_data_hdr must be 4 bytes"); @@ -224,6 +228,17 @@ static ble_hs_hci_evt_le_fn * const ble_hs_hci_evt_le_dispatch[] = { [BLE_HCI_LE_SUBEV_CIS_ESTABLISHED_V2] = ble_hs_hci_evt_le_cis_estab_v2, #endif /* MYNEWT_VAL(BLE_ISO_CIS_ESTAB_V2) */ #endif /* MYNEWT_VAL(BLE_ISO) */ + +#if MYNEWT_VAL(BLE_CHANNEL_SOUNDING) + [BLE_HCI_LE_SUBEV_CS_RD_REM_SUPP_CAP_COMPLETE] = ble_hs_hci_evt_le_cs_rd_rem_supp_cap_complete, + [BLE_HCI_LE_SUBEV_CS_RD_REM_FAE_COMPLETE] = ble_hs_hci_evt_le_cs_rd_rem_fae_complete, + [BLE_HCI_LE_SUBEV_CS_SEC_ENABLE_COMPLETE] = ble_hs_hci_evt_le_cs_sec_enable_complete, + [BLE_HCI_LE_SUBEV_CS_CONFIG_COMPLETE] = ble_hs_hci_evt_le_cs_config_complete, + [BLE_HCI_LE_SUBEV_CS_PROC_ENABLE_COMPLETE] = ble_hs_hci_evt_le_cs_proc_enable_complete, + [BLE_HCI_LE_SUBEV_CS_SUBEVENT_RESULT] = ble_hs_hci_evt_le_cs_subevent_result, + [BLE_HCI_LE_SUBEV_CS_SUBEVENT_RESULT_CONTINUE] = ble_hs_hci_evt_le_cs_subevent_result_continue, + [BLE_HCI_LE_SUBEV_CS_TEST_END_COMPLETE] = ble_hs_hci_evt_le_cs_test_end_complete, +#endif }; #define BLE_HS_HCI_EVT_LE_DISPATCH_SZ \ diff --git a/nimble/host/src/ble_hs_id.c b/nimble/host/src/ble_hs_id.c index ae423934c..197d0b981 100644 --- a/nimble/host/src/ble_hs_id.c +++ b/nimble/host/src/ble_hs_id.c @@ -221,7 +221,6 @@ ble_hs_id_addr(uint8_t id_addr_type, const uint8_t **out_id_addr, { const uint8_t *id_addr; int nrpa; - switch (id_addr_type) { case BLE_ADDR_PUBLIC: case BLE_ADDR_PUBLIC_ID: @@ -314,6 +313,7 @@ ble_hs_id_use_addr(uint8_t own_addr_type) rc = ble_hs_id_addr_type_usable(own_addr_type); if (rc != 0) { + printf("usable rc = %d\n",rc); return rc; } diff --git a/nimble/host/src/ble_hs_startup.c b/nimble/host/src/ble_hs_startup.c index 8960ac39e..f7a1776f7 100644 --- a/nimble/host/src/ble_hs_startup.c +++ b/nimble/host/src/ble_hs_startup.c @@ -238,6 +238,7 @@ ble_hs_startup_read_bd_addr(void) } ble_hs_id_set_pub(rsp.addr); + return 0; } @@ -384,6 +385,7 @@ ble_hs_startup_le_set_evmask_tx(void) } #endif +<<<<<<< HEAD #if MYNEWT_VAL(BLE_ISO) if (version >= BLE_HCI_VER_BCS_5_2) { /** @@ -404,6 +406,23 @@ ble_hs_startup_le_set_evmask_tx(void) } #endif /* MYNEWT_VAL(BLE_ISO) */ +#if MYNEWT_VAL(BLE_CHANNEL_SOUNDING) + if (version >= BLE_HCI_VER_BCS_5_4) { + /** + * Enable the following LE events: + * 0x0000080000000000 LE CS Read Remote Supported Capabilities Complete event + * 0x0000100000000000 LE CS Read Remote FAE Table Complete event + * 0x0000200000000000 LE CS Security Enable Complete event + * 0x0000400000000000 LE CS Config Complete event + * 0x0000800000000000 LE CS Procedure Enable Complete event + * 0x0001000000000000 LE CS Subevent Result event + * 0x0002000000000000 LE CS Subevent Result Continue event + * 0x0004000000000000 LE CS Test End Complete event + */ + mask |= 0x0007f80000000000; + } +#endif + cmd.event_mask = htole64(mask); rc = ble_hs_hci_cmd_tx(BLE_HCI_OP(BLE_HCI_OGF_LE, diff --git a/nimble/include/nimble/hci_common.h b/nimble/include/nimble/hci_common.h index 2997eafdc..bc904487b 100644 --- a/nimble/include/nimble/hci_common.h +++ b/nimble/include/nimble/hci_common.h @@ -1368,6 +1368,180 @@ struct ble_hci_le_set_periodic_adv_params_v2 { uint8_t num_response_slots; } __attribute__((packed)); +#define BLE_HCI_OCF_LE_CS_RD_LOC_SUPP_CAP (0x0089) +struct ble_hci_le_cs_rd_loc_supp_cap_rp { + uint8_t num_config_supported; + uint16_t max_consecutive_procedures_supported; + uint8_t num_antennas_supported; + uint8_t max_antenna_paths_supported; + uint8_t roles_supported; + uint8_t optional_modes_supported; + uint8_t rtt_capability; + uint8_t rtt_aa_only_n; + uint8_t rtt_sounding_n; + uint8_t rtt_random_payload_n; + uint16_t optional_nadm_sounding_capability; + uint16_t optional_nadm_random_capability; + uint8_t optional_cs_sync_phys_supported; + uint16_t optional_subfeatures_supported; + uint16_t optional_t_ip1_times_supported; + uint16_t optional_t_ip2_times_supported; + uint16_t optional_t_fcs_times_supported; + uint16_t optional_t_pm_times_supported; + uint8_t t_sw_time_supported; +} __attribute__((packed)); + +#define BLE_HCI_OCF_LE_CS_RD_REM_SUPP_CAP (0x008A) +struct ble_hci_le_cs_rd_rem_supp_cap_cp { + uint16_t conn_handle; +} __attribute__((packed)); + +#define BLE_HCI_OCF_LE_CS_WR_CACHED_REM_SUPP_CAP (0x008B) +struct ble_hci_le_cs_wr_cached_rem_supp_cap_cp { + uint16_t conn_handle; + uint8_t num_config_supported; + uint16_t max_consecutive_procedures_supported; + uint8_t num_antennas_supported; + uint8_t max_antenna_paths_supported; + uint8_t roles_supported; + uint8_t optional_modes_supported; + uint8_t rtt_capability; + uint8_t rtt_aa_only_n; + uint8_t rtt_sounding_n; + uint8_t rtt_random_payload_n; + uint16_t optional_nadm_sounding_capability; + uint16_t optional_nadm_random_capability; + uint8_t optional_cs_sync_phys_supported; + uint16_t optional_subfeatures_supported; + uint16_t optional_t_ip1_times_supported; + uint16_t optional_t_ip2_times_supported; + uint16_t optional_t_fcs_times_supported; + uint16_t optional_t_pm_times_supported; + uint8_t t_sw_time_supported; +} __attribute__((packed)); +struct ble_hci_le_cs_wr_cached_rem_supp_cap_rp { + uint16_t conn_handle; +} __attribute__((packed)); + +#define BLE_HCI_OCF_LE_CS_SEC_ENABLE (0x008C) +struct ble_hci_le_cs_sec_enable_cp { + uint16_t conn_handle; +} __attribute__((packed)); + +#define BLE_HCI_OCF_LE_CS_SET_DEF_SETTINGS (0x008D) +struct ble_hci_le_cs_set_def_settings_cp { + uint16_t conn_handle; + uint8_t role_enable; + uint8_t cs_sync_antenna_selection; + uint8_t max_tx_power; +} __attribute__((packed)); +struct ble_hci_le_cs_set_def_settings_rp { + uint16_t conn_handle; +} __attribute__((packed)); + +#define BLE_HCI_OCF_LE_CS_RD_REM_FAE (0x008E) +struct ble_hci_le_cs_rd_rem_fae_cp { + uint16_t conn_handle; +} __attribute__((packed)); + +#define BLE_HCI_OCF_LE_CS_WR_CACHED_REM_FAE (0x008F) +struct ble_hci_le_cs_wr_cached_rem_fae_cp { + uint16_t conn_handle; + uint8_t remote_fae_table[72]; +} __attribute__((packed)); +struct ble_hci_le_cs_wr_cached_rem_fae_rp { + uint16_t conn_handle; +} __attribute__((packed)); + +#define BLE_HCI_OCF_LE_CS_CREATE_CONFIG (0x0090) +struct ble_hci_le_cs_create_config_cp { + uint16_t conn_handle; + uint8_t config_id; + uint8_t create_context; + uint8_t main_mode_type; + uint8_t sub_mode_type; + uint8_t min_main_mode_steps; + uint8_t max_main_mode_steps; + uint8_t main_mode_repetition; + uint8_t mode_0_steps; + uint8_t role; + uint8_t rtt_type; + uint8_t cs_sync_phy; + uint8_t channel_map[10]; + uint8_t channel_map_repetition; + uint8_t channel_selection_type; + uint8_t ch3c_shape; + uint8_t ch3c_jump; + uint8_t companion_signal_enable; +} __attribute__((packed)); + +#define BLE_HCI_OCF_LE_CS_REMOVE_CONFIG (0x0091) +struct ble_hci_le_cs_remove_config_cp { + uint16_t conn_handle; + uint8_t config_id; +} __attribute__((packed)); + +#define BLE_HCI_OCF_LE_CS_SET_CHAN_CLASS (0x0092) +struct ble_hci_le_cs_set_chan_class_cp { + uint8_t channel_classification[10]; +} __attribute__((packed)); + +#define BLE_HCI_OCF_LE_CS_SET_PROC_PARAMS (0x0093) +struct ble_hci_le_cs_set_proc_params_cp { + uint16_t conn_handle; + uint8_t config_id; + uint16_t max_procedure_len; + uint16_t min_procedure_interval; + uint16_t max_procedure_interval; + uint16_t max_procedure_count; + uint8_t min_subevent_len[3]; + uint8_t max_subevent_len[3]; + uint8_t tone_antenna_config_selection; + uint8_t phy; + uint8_t tx_power_delta; + uint8_t preferred_peer_antenna; + uint8_t snr_control_initiator; + uint8_t snr_control_reflector; +} __attribute__((packed)); +struct ble_hci_le_cs_set_proc_params_rp { + uint16_t conn_handle; +} __attribute__((packed)); + +#define BLE_HCI_OCF_LE_CS_PROC_ENABLE (0x0094) +struct ble_hci_le_cs_proc_enable_cp { + uint16_t conn_handle; + uint8_t config_id; + uint8_t enable; +} __attribute__((packed)); + +#define BLE_HCI_OCF_LE_CS_TEST (0x0095) +struct ble_hci_le_cs_test_cp { + uint8_t main_mode_type; + uint8_t sub_mode_type; + uint8_t main_mode_repetition; + uint8_t mode_0_steps; + uint8_t role; + uint8_t rtt_type; + uint8_t cs_sync_phy; + uint8_t cs_sync_antenna_selection; + uint8_t subevent_len[3]; + uint16_t subevent_interval; + uint8_t transmit_power_level; + uint8_t t_ip1_time; + uint8_t t_ip2_time; + uint8_t t_fcs_time; + uint8_t t_pm_time; + uint8_t t_sw_time; + uint8_t tone_antenna_config_selection; + uint8_t companion_signal_enable; + uint16_t drbg_nonce; + uint16_t override_config; + uint8_t override_parameters_length; + uint8_t override_parameters_data[]; +} __attribute__((packed)); + +#define BLE_HCI_OCF_LE_CS_TEST_END (0x0096) + /* --- Vendor specific commands (OGF 0x003F) */ /* Read Random Static Address */ #define BLE_HCI_OCF_VS_RD_STATIC_ADDR (MYNEWT_VAL(BLE_HCI_VS_OCF_OFFSET) + (0x0001)) @@ -2378,6 +2552,135 @@ struct ble_hci_ev_le_subev_cis_established_v2 { #define BLE_HCI_LE_SUBEV_DISCARD_REPORT_EVT 0XF0 #endif // (BLE_ADV_REPORT_FLOW_CONTROL == TRUE) +#define BLE_HCI_LE_SUBEV_CS_RD_REM_SUPP_CAP_COMPLETE (0x2C) +struct ble_hci_ev_le_subev_cs_rd_rem_supp_cap_complete { + uint8_t subev_code; + uint8_t status; + uint16_t conn_handle; + uint8_t num_config_supported; + uint16_t max_consecutive_procedures_supported; + uint8_t num_antennas_supported; + uint8_t max_antenna_paths_supported; + uint8_t roles_supported; + uint8_t optional_modes_supported; + uint8_t rtt_capability; + uint8_t rtt_aa_only_n; + uint8_t rtt_sounding_n; + uint8_t rtt_random_payload_n; + uint16_t optional_nadm_sounding_capability; + uint16_t optional_nadm_random_capability; + uint8_t optional_cs_sync_phys_supported; + uint16_t optional_subfeatures_supported; + uint16_t optional_t_ip1_times_supported; + uint16_t optional_t_ip2_times_supported; + uint16_t optional_t_fcs_times_supported; + uint16_t optional_t_pm_times_supported; + uint8_t t_sw_time_supported; + uint8_t tx_snr_capability; +} __attribute__((packed)); + +#define BLE_HCI_LE_SUBEV_CS_RD_REM_FAE_COMPLETE (0x2D) +struct ble_hci_ev_le_subev_cs_rd_rem_fae_complete { + uint8_t subev_code; + uint8_t status; + uint16_t conn_handle; + uint8_t remote_fae_table[72]; +} __attribute__((packed)); + +#define BLE_HCI_LE_SUBEV_CS_SEC_ENABLE_COMPLETE (0x2E) +struct ble_hci_ev_le_subev_cs_sec_enable_complete { + uint8_t subev_code; + uint8_t status; + uint16_t conn_handle; +} __attribute__((packed)); + +#define BLE_HCI_LE_SUBEV_CS_CONFIG_COMPLETE (0x2F) +struct ble_hci_ev_le_subev_cs_config_complete { + uint8_t subev_code; + uint8_t status; + uint16_t conn_handle; + uint8_t config_id; + uint8_t action; + uint8_t main_mode_type; + uint8_t sub_mode_type; + uint8_t min_main_mode_steps; + uint8_t max_main_mode_steps; + uint8_t main_mode_repetition; + uint8_t mode_0_steps; + uint8_t role; + uint8_t rtt_type; + uint8_t cs_sync_phy; + uint8_t channel_map[10]; + uint8_t channel_map_repetition; + uint8_t channel_selection_type; + uint8_t ch3c_shape; + uint8_t ch3c_jump; + uint8_t companion_signal_enable; + uint8_t t_ip1_time; + uint8_t t_ip2_time; + uint8_t t_fcs_time; + uint8_t t_pm_time; +} __attribute__((packed)); + +#define BLE_HCI_LE_SUBEV_CS_PROC_ENABLE_COMPLETE (0x30) +struct ble_hci_ev_le_subev_cs_proc_enable_complete { + uint8_t subev_code; + uint8_t status; + uint16_t conn_handle; + uint8_t config_id; + uint8_t state; + uint8_t tone_antenna_config_selection; + uint8_t selected_tx_power; + uint8_t subevent_len[3]; + uint8_t subevents_per_event; + uint16_t subevent_interval; + uint16_t event_interval; + uint16_t procedure_interval; + uint16_t procedure_count; +} __attribute__((packed)); + +#define BLE_HCI_LE_SUBEV_CS_SUBEVENT_RESULT (0x31) +struct cs_steps_data { + uint8_t mode; + uint8_t channel; + uint8_t data_len; + uint8_t data[]; +} __attribute__((packed)); +struct ble_hci_ev_le_subev_cs_subevent_result { + uint8_t subev_code; + uint16_t conn_handle; + uint8_t config_id; + uint16_t start_acl_conn_event_counter; + uint16_t procedure_counter; + uint16_t frequency_compensation; + uint8_t reference_power_level; + uint8_t procedure_done_status; + uint8_t subevent_done_status; + uint8_t abort_reason; + uint8_t num_antenna_paths; + uint8_t num_steps_reported; + struct cs_steps_data steps[]; +} __attribute__((packed)); + +#define BLE_HCI_LE_SUBEV_CS_SUBEVENT_RESULT_CONTINUE (0x32) +struct ble_hci_ev_le_subev_cs_subevent_result_continue { + uint8_t subev_code; + uint16_t conn_handle; + uint8_t config_id; + uint8_t procedure_done_status; + uint8_t subevent_done_status; + uint8_t abort_reason; + uint8_t num_antenna_paths; + uint8_t num_steps_reported; + struct cs_steps_data steps[]; +} __attribute__((packed)); + +#define BLE_HCI_LE_SUBEV_CS_TEST_END_COMPLETE (0x33) +struct ble_hci_ev_le_subev_cs_test_end_complete { + uint8_t subev_code; + uint8_t status; +} __attribute__((packed)); + /* Data buffer overflow event */ #define BLE_HCI_EVENT_ACL_BUF_OVERFLOW (0x01) diff --git a/nimble/syscfg.yml b/nimble/syscfg.yml index 040171d35..e3277aed8 100644 --- a/nimble/syscfg.yml +++ b/nimble/syscfg.yml @@ -103,6 +103,11 @@ syscfg.defs: restrictions: - 'BLE_ISO if 1' + BLE_CHANNEL_SOUNDING: + description: > + This enables Channel Sounding feature + value: 0 + BLE_HCI_VS: description: > Enables support for NimBLE specific vendor HCI commands diff --git a/nimble/transport/syscfg.yml b/nimble/transport/syscfg.yml index febe09d40..7e8ea9357 100644 --- a/nimble/transport/syscfg.yml +++ b/nimble/transport/syscfg.yml @@ -117,3 +117,7 @@ $import: syscfg.vals.'BLE_EXT_ADV || BLE_LL_CFG_FEAT_LL_EXT_ADV': BLE_TRANSPORT_EVT_SIZE: 257 + +syscfg.vals.'BLE_CHANNEL_SOUNDING && !(BLE_EXT_ADV || BLE_LL_CFG_FEAT_LL_EXT_ADV)': + # A larger buffer is needed to sent the FAE table. + BLE_TRANSPORT_EVT_SIZE: 78