feat(nimble): Added BLE CS Service

This commit is contained in:
Abhinav Kudnar
2025-10-14 12:08:12 +05:30
committed by Rahul Tank
parent 5b55424c20
commit 2d69e13657
17 changed files with 959 additions and 324 deletions
+4 -8
View File
@@ -22,18 +22,14 @@
#ifndef H_BLE_CS_
#define H_BLE_CS_
#include "syscfg/syscfg.h"
#include "host/ble_hs.h"
#include "nimble/hci_common.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
@@ -56,7 +52,7 @@ struct ble_cs_event {
uint8_t abort_reason;
uint8_t num_antenna_paths;
uint8_t num_steps_reported;
struct cs_step_data steps[];
const struct cs_steps_data *steps;
}subev_result;
struct
{
@@ -67,7 +63,7 @@ struct ble_cs_event {
uint8_t abort_reason;
uint8_t num_antenna_paths;
uint8_t num_steps_reported;
struct cs_step_data steps[];
const struct cs_steps_data *steps;
}subev_result_continue;
};
+13 -6
View File
@@ -221,10 +221,6 @@ 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 */
@@ -4087,9 +4083,20 @@ 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);
#if MYNEWT_VAL(BLE_CHANNEL_SOUNDING)
/**
* Set or clear a bit controlled by the host in the link layer featureSet
* stored in the Controller
*
* @param bit_num Bit position in the FeatureSet
*
* @param The Host feature is disabled or enabled (0 & 1)
*
* return 0 on success; nonzero on failure
*/
int ble_gap_set_host_feat(uint8_t bit_num,uint8_t bit_val);
#endif
#ifdef __cplusplus
}
#endif
@@ -21,8 +21,11 @@
#ifndef H_BLE_SVC_RAS_
#define H_BLE_SVC_RAS_
#include <stdint.h>
#include "host/ble_hs.h"
#include "host/ble_cs.h"
#define BLE_SVC_RAS_CHR_RANGING_SERVICE_VAL (0x185B)
#define BLE_SVC_RAS_RANGING_SERVICE_VAL (0x185B)
/** @brief UUID of the RAS Features Characteristic. **/
#define BLE_SVC_RAS_CHR_UUID_FEATURES_VAL (0x2C14)
@@ -57,83 +60,169 @@
(BLE_RAS_MAX_STEPS_PER_PROCEDURE * BLE_RAS_STEP_MODE_LEN) + \
(BLE_RAS_MAX_STEPS_PER_PROCEDURE * BLE_RAS_MAX_STEP_DATA_LEN))
#define REAL_TIME_RANGING_DATA_BIT (1<<0)
#define RETRIEVE_LST_SEG_BIT (1<<1)
#define ABORT_OP_BIT (1<<2)
#define FLTR_RANGING_DATA_BIT (1<<3)
#define RASCP_CMD_OPCODE_LEN 1
#define RASCP_CMD_OPCODE_OFFSET 0
#define RASCP_CMD_PARAMS_OFFSET RASCP_CMD_OPCODE_LEN
#define RASCP_CMD_PARAMS_MAX_LEN 4
#define RASCP_WRITE_MAX_LEN (RASCP_CMD_OPCODE_LEN + RASCP_CMD_PARAMS_MAX_LEN)
#define RASCP_ACK_DATA_TIMEOUT K_SECONDS(5)
/** @brief RAS Control Point opcodes as defined in RAS Specification, Table 3.10. */
enum rascp_opcode {
RASCP_OPCODE_GET_RD = 0x00,
RASCP_OPCODE_ACK_RD = 0x01,
RASCP_OPCODE_RETRIEVE_LOST_RD_SEGMENTS = 0x02,
RASCP_OPCODE_ABORT_OP = 0x03,
RASCP_OPCODE_SET_FILTER = 0x04,
};
/** @brief RAS Control Point Response opcodes as defined in RAS Specification, Table 3.11. */
enum rascp_rsp_opcode {
RASCP_RSP_OPCODE_COMPLETE_RD_RSP = 0x00,
RASCP_RSP_OPCODE_COMPLETE_LOST_RD_SEG_RSP = 0x01,
RASCP_RSP_OPCODE_RSP_CODE = 0x02,
};
#define RASCP_RSP_OPCODE_COMPLETE_RD_RSP_LEN 1
#define RASCP_RSP_OPCODE_COMPLETE_LOST_RD_SEG_RSP_LEN 4
#define RASCP_RSP_OPCODE_RSP_CODE_LEN 1
struct ranging_header {
/** Lower 12 bits used as the ranging session counter. */
uint16_t ranging_counter : 12;
/** Configuration identifier (4-bit value, range 03). */
uint8_t config_id : 4;
/** Transmit power used during the ranging session, in dBm (range: -127 to 20). */
int8_t selected_tx_power;
/** Bitmask indicating which antenna paths are active.
* Bit 0: Path 1
* Bit 1: Path 2
* Bit 2: Path 3
* Bit 3: Path 4
* Bits 47: Reserved
*/
uint8_t antenna_paths_mask;
} __attribute__((packed));
struct subevent_header {
/** Starting ACL connection event counter for the reported results. */
uint16_t start_acl_conn_event;
/** Frequency compensation value in 0.01 ppm units (15-bit signed integer).
* May be a reserved or unavailable value depending on the device role or support.
*/
uint16_t freq_compensation;
/** Status indicating completion of the overall ranging process.
* 0x0: Complete
* 0x1: Partial, more results to come
* 0xF: Procedure aborted
* Other values: Reserved
*/
uint8_t ranging_done_status : 4;
/** Status for the subevent portion of the ranging process.
* 0x0: Complete
* 0xF: Aborted
* Other values: Reserved
*/
uint8_t subevent_done_status : 4;
/** Reason code for aborting the entire procedure.
* 0x0: No abort
* 0x1: Abort due to local/remote request
* 0x2: Insufficient valid channels
* 0x3: Instant missed
* 0xF: Unspecified reason
* Other values: Reserved
*/
uint8_t ranging_abort_reason : 4;
/** Reason code for subevent-level aborts.
* 0x0: No abort
* 0x1: Abort due to local/remote request
* 0x2: No sync packet received
* 0x3: Scheduling/resource issue
* 0xF: Unspecified reason
* Other values: Reserved
*/
uint8_t subevent_abort_reason : 4;
/** Reference transmit power used during the subevent (in dBm). */
int8_t ref_power_level;
/** Number of steps included in the report. May be zero if aborted. */
uint8_t num_steps_reported;
} __attribute__((packed));
struct ranging_buffer {
/** Pointer to the associated Bluetooth connection. */
int conn;
/** Counter used for identifying the current ranging session. */
uint16_t ranging_counter;
/** Index for tracking the current write position in subevent data. */
uint16_t subevent_cursor;
/** Reference count to ensure safe access and prevent premature reuse. */
uint8_t refcount;
/** Indicates whether the buffer is completely filled and ready to transmit. */
uint8_t isready;
/** Flag showing that the buffer is currently in use for writing data. */
uint8_t isbusy;
/** Set when the remote side has acknowledged this buffer. */
uint8_t isacked;
/** Holds the entire data payload for a ranging operation. */
union {
uint8_t buf[BLE_RAS_PROCEDURE_MEM];
struct {
struct ranging_header ranging_header;
uint8_t subevents[0];
} __attribute__((packed));
} ranging_data;
};
struct segment_header {
/** Indicates if this is the first segment in a series. */
bool first_seg : 1;
/** Indicates if this is the last segment in a series. */
bool last_seg : 1;
/** Sequence number for this segment (6-bit counter). */
uint8_t seg_counter : 6;
} __attribute__((packed));
/** @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;
/** Generic format for a data segment containing a header and payload. */
struct segment {
struct segment_header header;
/** Payload data of variable length. */
uint8_t data[];
} __attribute__((packed));
void ble_gatts_indicate_ranging_data_ready(uint16_t ranging_counter);
void ble_gatts_store_ranging_data(struct ble_cs_event ranging_subevent);
void ble_gatts_indicate_control_point_response(uint16_t attr_handle , uint16_t ranging_counter);
struct ranging_buffer *ranging_buffer_alloc(uint16_t conn_handle , uint16_t ranging_counter);
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
#endif
+3 -3
View File
@@ -17,8 +17,8 @@
# under the License.
#
pkg.name: nimble/host/services/bas
pkg.description: Battery Service
pkg.name: nimble/host/services/ras
pkg.description: Ranging Service
pkg.author: "Apache Mynewt <[email protected]>"
pkg.homepage: "http://mynewt.apache.org/"
pkg.keywords:
@@ -31,4 +31,4 @@ pkg.deps:
- nimble/host
pkg.init:
ble_svc_hid_init: 'MYNEWT_VAL(BLE_SVC_HID_SYSINIT_STAGE)'
ble_svc_ras_init: 'MYNEWT_VAL(BLE_SVC_RAS_SYSINIT_STAGE)'
+494
View File
@@ -0,0 +1,494 @@
/*
* 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 <assert.h>
#include <stdio.h>
#include <string.h>
#include "host/ble_hs.h"
#include "host/ble_uuid.h"
#include "services/ras/ble_svc_ras.h"
#include "sysinit/sysinit.h"
#include "host/ble_cs.h"
#include "nimble/hci_common.h"
#include "esp_nimble_mem.h"
#define MIN(a, b) ((a) < (b) ? (a) : (b))
static uint16_t ble_svc_ras_feat_val_handle;
static uint32_t ble_svc_ras_feat_val;
static uint16_t ble_svc_ras_rd_val_handle;
static uint16_t ble_svc_ras_rd_val;
static uint16_t ble_svc_ras_rd_ov_val_handle;
static uint16_t ble_svc_ras_rd_ov_val;
static uint16_t ble_svc_ras_cp_val_handle;
static uint8_t ble_svc_ras_cp_val[RASCP_CMD_OPCODE_LEN + sizeof(uint16_t)] ;
static uint16_t ble_svc_ras_od_rd_val_handle;
static struct segment *ble_svc_ras_od_rd_val;
static uint16_t ble_svc_ras_rt_rd_val_handle;
static uint16_t ble_svc_ras_rt_rd_val;
static struct ranging_buffer ranging_buffers[BLE_RAS_MAX_SUBEVENTS_PER_PROCEDURE];
void ble_gatts_indicate_ranging_data_ready(uint16_t ranging_counter)
{
MODLOG_DFLT(INFO, "Indicate ranging data ready for counter %d\n", ranging_counter);
/* Indicate that the ranging data is ready for the client */
ble_svc_ras_rd_val = ranging_counter;
ble_gatts_chr_updated(ble_svc_ras_rd_val_handle);
}
void ble_gatts_indicate_control_point_response(uint16_t attr_handle , uint16_t ranging_counter)
{
/* Indication control point reponse only when all the idication for on_demad_rd is sent for all segments;*/
if (attr_handle == ble_svc_ras_od_rd_val_handle) {
MODLOG_DFLT(INFO, "Indicate control point response\n");
ble_svc_ras_cp_val[0] = RASCP_RSP_OPCODE_COMPLETE_RD_RSP;
memcpy(&ble_svc_ras_cp_val[RASCP_RSP_OPCODE_COMPLETE_RD_RSP_LEN], &ranging_counter, sizeof(uint16_t));
ble_gatts_chr_updated(ble_svc_ras_cp_val_handle);
} else {
return ;
}
}
static void ranging_buffer_init(uint16_t conn_handle, struct ranging_buffer *buf, uint16_t ranging_counter)
{
buf->conn = conn_handle;
buf->ranging_counter = ranging_counter;
buf->isready = false;
buf->isbusy = true;
buf->isacked = false;
buf->subevent_cursor = 0;
}
static void reset_ranging_buffer(void)
{
/* reset whole array of ranging buffers */
for (int i = 0; i < BLE_RAS_MAX_SUBEVENTS_PER_PROCEDURE; i++) {
ranging_buffers[i].conn = -1; //No connection
ranging_buffers[i].ranging_counter = 0;
ranging_buffers[i].isready = false;
ranging_buffers[i].isbusy = false;
ranging_buffers[i].isacked = false;
ranging_buffers[i].subevent_cursor = 0;
}
}
struct ranging_buffer *ranging_buffer_alloc(uint16_t conn_handle , uint16_t ranging_counter)
{
uint16_t conn_buffer_count = 0;
for (uint8_t i = 0; i < sizeof(ranging_buffers)/sizeof(ranging_buffers[0]) ; i++) {
if (ranging_buffers[i].conn == -1) {
conn_buffer_count++;
ranging_buffer_init(conn_handle, &ranging_buffers[i] , ranging_counter);
return &ranging_buffers[i];
}
}
/* No buffer available */
return NULL;
}
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_SVC_RAS_RANGING_SERVICE_VAL),
.characteristics = (struct ble_gatt_chr_def[]) {
{
/* Characteristic: Feature Value */
.uuid = BLE_UUID16_DECLARE(BLE_SVC_RAS_CHR_UUID_FEATURES_VAL),
.access_cb = gatt_svr_chr_access_ras_val,
.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_SVC_RAS_CHR_UUID_ONDEMAND_RD_VAL),
.access_cb = gatt_svr_chr_access_ras_val,
.val_handle = &ble_svc_ras_od_rd_val_handle,
.flags = BLE_GATT_CHR_F_NOTIFY | BLE_GATT_CHR_F_INDICATE ,
},
{
/* Characteristic: On realtime ranging data */
.uuid = BLE_UUID16_DECLARE(BLE_SVC_RAS_CHR_UUID_REALTIME_RD_VAL),
.access_cb = gatt_svr_chr_access_ras_val,
.val_handle = &ble_svc_ras_rt_rd_val_handle,
.flags = BLE_GATT_CHR_F_NOTIFY | BLE_GATT_CHR_F_INDICATE ,
},
{
/* Characteristic: RAS Control Point */
.uuid = BLE_UUID16_DECLARE(BLE_SVC_RAS_CHR_UUID_CP_VAL),
.access_cb = gatt_svr_chr_access_ras_val,
.val_handle = &ble_svc_ras_cp_val_handle,
.flags = BLE_GATT_CHR_F_WRITE_NO_RSP | BLE_GATT_CHR_F_INDICATE,
},
{
/* Characteristic: RAS Ranging Data Ready */
.uuid = BLE_UUID16_DECLARE(BLE_SVC_RAS_CHR_UUID_RD_READY_VAL),
.access_cb = gatt_svr_chr_access_ras_val,
.val_handle = &ble_svc_ras_rd_val_handle,
.flags = BLE_GATT_CHR_F_INDICATE | BLE_GATT_CHR_F_READ_ENC | BLE_GATT_CHR_F_READ ,
},
{
/* Characteristic: RAS Ranging data overwritten */
.uuid = BLE_UUID16_DECLARE(BLE_SVC_RAS_CHR_UUID_RD_OVERWRITTEN_VAL),
.access_cb = gatt_svr_chr_access_ras_val,
.val_handle = &ble_svc_ras_rd_ov_val_handle,
.flags = BLE_GATT_CHR_F_INDICATE | BLE_GATT_CHR_F_READ_ENC | BLE_GATT_CHR_F_READ,
},
{
0, /* No more characteristics in this service */
},
},
},
{
0, /* No more services */
},
};
static int
gatt_svr_write(struct os_mbuf *om, uint16_t min_len, uint16_t max_len,
void *dst, uint16_t *len)
{
uint16_t om_len;
int rc;
om_len = OS_MBUF_PKTLEN(om);
if (om_len < min_len || om_len > max_len) {
MODLOG_DFLT(INFO, "Invalid attr len");
return BLE_ATT_ERR_INVALID_ATTR_VALUE_LEN;
}
rc = ble_hs_mbuf_to_flat(om, dst, max_len, len);
if (rc != 0) {
return BLE_ATT_ERR_UNLIKELY;
}
return 0;
}
static int gatt_svr_chr_access_ras_val(uint16_t conn_handle, uint16_t attr_handle,
struct ble_gatt_access_ctxt *ctxt, void *arg)
{
uint16_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 = ble_uuid_u16(ctxt->chr->uuid);
if (uuid == BLE_SVC_RAS_CHR_UUID_FEATURES_VAL) {
ble_svc_ras_feat_val |= RETRIEVE_LST_SEG_BIT | ABORT_OP_BIT | FLTR_RANGING_DATA_BIT;
MODLOG_DFLT(INFO, "ble_svc_ras_feat_val = %02x\n",ble_svc_ras_feat_val);
if (attr_handle == ble_svc_ras_feat_val_handle) {
rc = os_mbuf_append(ctxt->om,
&ble_svc_ras_feat_val,
sizeof(ble_svc_ras_feat_val));
return rc == 0 ? 0 : BLE_ATT_ERR_INSUFFICIENT_RES;
}
} else if (uuid == BLE_SVC_RAS_CHR_UUID_RD_READY_VAL) {
MODLOG_DFLT(INFO, "ble_svc_ras_rd_val = %d\n", ble_svc_ras_rd_val);
if (attr_handle == ble_svc_ras_rd_val_handle) {
rc = os_mbuf_append(ctxt->om,
&ble_svc_ras_rd_val,
sizeof(ble_svc_ras_rd_val));
return rc == 0 ? 0 : BLE_ATT_ERR_INSUFFICIENT_RES;
}
}
else if (uuid == BLE_SVC_RAS_CHR_UUID_ONDEMAND_RD_VAL) {
// print the segament data
MODLOG_DFLT(INFO,"ble_svc_ras_od_rd_val\n");
MODLOG_DFLT(INFO, "ble_svc_ras_od_rd_val.data = %2x %02x %02x \n",ble_svc_ras_od_rd_val->header.first_seg,ble_svc_ras_od_rd_val->header.last_seg,ble_svc_ras_od_rd_val->header.seg_counter);
if (attr_handle == ble_svc_ras_od_rd_val_handle) {
rc = os_mbuf_append(ctxt->om,
ble_svc_ras_od_rd_val,
sizeof(struct segment )+100);
return rc == 0 ? 0 : BLE_ATT_ERR_INSUFFICIENT_RES;
}
} else if (uuid == BLE_SVC_RAS_CHR_UUID_REALTIME_RD_VAL) {
MODLOG_DFLT(INFO, "ble_svc_ras_rt_rd_val = %d\n", ble_svc_ras_rt_rd_val);
if (attr_handle == ble_svc_ras_rt_rd_val_handle) {
rc = os_mbuf_append(ctxt->om,
&ble_svc_ras_rt_rd_val,
sizeof(ble_svc_ras_rt_rd_val));
return rc == 0 ? 0 : BLE_ATT_ERR_INSUFFICIENT_RES;
}
} else if (uuid == BLE_SVC_RAS_CHR_UUID_CP_VAL) {
MODLOG_DFLT(INFO,"ble_svc_ras_cp_val read = %02x %02x %02x \n",ble_svc_ras_cp_val[0],ble_svc_ras_cp_val[1],ble_svc_ras_cp_val[2]);
rc = os_mbuf_append(ctxt->om,
&ble_svc_ras_cp_val,
sizeof(ble_svc_ras_cp_val));
return rc == 0 ? 0 : BLE_ATT_ERR_INSUFFICIENT_RES;
}
else if (uuid == BLE_SVC_RAS_CHR_UUID_RD_OVERWRITTEN_VAL) {
MODLOG_DFLT(INFO, "ble_svc_ras_rd_ov_val = %d\n", ble_svc_ras_rd_ov_val);
if (attr_handle == ble_svc_ras_rd_ov_val_handle) {
rc = os_mbuf_append(ctxt->om,
&ble_svc_ras_rd_ov_val,
sizeof(ble_svc_ras_rd_ov_val));
return rc == 0 ? 0 : BLE_ATT_ERR_INSUFFICIENT_RES;
}
}
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);
}
if (attr_handle == ble_svc_ras_rt_rd_val_handle) {
rc = gatt_svr_write(ctxt->om,
sizeof(ble_svc_ras_rt_rd_val),
sizeof(ble_svc_ras_rt_rd_val),
&ble_svc_ras_rt_rd_val, NULL);
ble_gatts_chr_updated(attr_handle);
MODLOG_DFLT(INFO, "Notification/Indication scheduled for "
"all subscribed peers.\n");
return rc;
} else if (attr_handle == ble_svc_ras_od_rd_val_handle) {
rc = gatt_svr_write(ctxt->om,
sizeof(ble_svc_ras_od_rd_val),
sizeof(ble_svc_ras_od_rd_val),
ble_svc_ras_od_rd_val, NULL);
ble_gatts_chr_updated(attr_handle);
MODLOG_DFLT(INFO, "Notification/Indication scheduled for "
"all subscribed peers.\n");
return rc;
} else if (attr_handle == ble_svc_ras_cp_val_handle) {
MODLOG_DFLT(INFO, "write for control point val ");
rc = gatt_svr_write(ctxt->om,
sizeof(ble_svc_ras_cp_val),
sizeof(ble_svc_ras_cp_val),
&ble_svc_ras_cp_val, NULL);
MODLOG_DFLT(INFO, "ble_svc_gap_cp_val = %02x %02x %02x \n",ble_svc_ras_cp_val[0],ble_svc_ras_cp_val[1],ble_svc_ras_cp_val[2]);
if (ble_svc_ras_cp_val[0] == RASCP_OPCODE_GET_RD) {
// n = size of (rangeing_buffer[i]) / mut -4);
/* Run a loop to send n segmet . for now sending only 1 segment*/
ble_gatts_chr_updated(ble_svc_ras_od_rd_val_handle);
} else if (ble_svc_ras_cp_val[0] == RASCP_OPCODE_ACK_RD) {
MODLOG_DFLT(INFO, "ack revied\n");
/* Reset the ranging buffers */
ble_svc_ras_cp_val[0]= 0x02;
/*Table 3.12. Response Code Values associated with Op Code 0x02*/
ble_svc_ras_cp_val[1]=0x01; // Success
ble_gatts_chr_updated(ble_svc_ras_cp_val_handle);
MODLOG_DFLT(INFO, "Sucssefully completed the Ranging procedure\n");
// vTaskDelay(4000 / portTICK_PERIOD_MS);
//extern void bt_hci_log_hci_data_show(void);
//bt_hci_log_hci_data_show();
}
MODLOG_DFLT(INFO, "Notification/Indication scheduled for "
"all subscribed peers.\n");
return rc;
} else if (attr_handle == ble_svc_ras_rd_val_handle) {
rc = gatt_svr_write(ctxt->om,
sizeof(ble_svc_ras_rd_val),
sizeof(ble_svc_ras_rd_val),
&ble_svc_ras_rd_val, NULL);
ble_gatts_chr_updated(attr_handle);
MODLOG_DFLT(INFO, "Notification/Indication scheduled for "
"all subscribed peers.\n");
return rc;
} else if (attr_handle == ble_svc_ras_rd_ov_val_handle) {
rc = gatt_svr_write(ctxt->om,
sizeof(ble_svc_ras_rd_ov_val),
sizeof(ble_svc_ras_rd_ov_val),
&ble_svc_ras_rd_ov_val, NULL);
ble_gatts_chr_updated(attr_handle);
MODLOG_DFLT(INFO, "Notification/Indication scheduled for "
"all subscribed peers.\n");
return rc;
}
return 0;
default:
goto unknown;
}
unknown:
/* Unknown characteristic/descriptor;
* The NimBLE host should not have called this function;
*/
// assert(0);
return BLE_ATT_ERR_UNLIKELY;
}
void ble_gatts_store_ranging_data(struct ble_cs_event ranging_subevent) {
struct ranging_buffer *buf = NULL;
/* Check if the subevent is already stored */
for (int i = 0; i < BLE_RAS_MAX_SUBEVENTS_PER_PROCEDURE; i++) {
if (ranging_buffers[i].conn == ranging_subevent.subev_result.conn_handle &&
ranging_buffers[i].ranging_counter == ranging_subevent.subev_result.procedure_counter) {
buf = &ranging_buffers[i];
break;
}
}
if (buf == NULL) {
/* Allocate a new buffer if not found */
buf = ranging_buffer_alloc(ranging_subevent.subev_result.conn_handle, ranging_subevent.subev_result.procedure_counter);
if (buf == NULL) {
MODLOG_DFLT(ERROR,"No available buffer for storing ranging data\n");
return;
}
}
buf->ranging_data.ranging_header.config_id = ranging_subevent.subev_result.config_id;
buf->ranging_data.ranging_header.ranging_counter = ranging_subevent.subev_result.procedure_counter;
// buf->ranging_data.ranging_header.selected_tx_power = ranging_subevent.subev_result.selected_tx_power;
/* convert antena path mask using bitmask*/
buf->ranging_data.ranging_header.antenna_paths_mask = ranging_subevent.subev_result.num_antenna_paths;
struct subevent_header *subevent_hdr = (struct subevent_header *)(buf->ranging_data.subevents + buf->subevent_cursor);
buf->subevent_cursor += sizeof(struct subevent_header);
subevent_hdr->start_acl_conn_event = ranging_subevent.subev_result.start_acl_conn_event_counter;
subevent_hdr->freq_compensation = ranging_subevent.subev_result.frequency_compensation;;
subevent_hdr->ranging_done_status = ranging_subevent.subev_result_continue.procedure_done_status;
subevent_hdr->subevent_done_status = ranging_subevent.subev_result_continue.subevent_done_status;
subevent_hdr->ranging_abort_reason = ranging_subevent.subev_result.abort_reason;
subevent_hdr->subevent_abort_reason = ranging_subevent.subev_result.abort_reason;
subevent_hdr->ref_power_level = ranging_subevent.subev_result.reference_power_level;
subevent_hdr->num_steps_reported = ranging_subevent.subev_result.num_steps_reported + ranging_subevent.subev_result_continue.num_steps_reported;
/* Add step data to buf*/
for (int i = 0; i < ranging_subevent.subev_result.num_steps_reported; i++) {
const struct cs_steps_data *step=&ranging_subevent.subev_result.steps[i];
buf->ranging_data.subevents[buf->subevent_cursor] = step->mode;
buf->subevent_cursor += BLE_RAS_STEP_MODE_LEN;
memcpy(&buf->ranging_data.subevents[buf->subevent_cursor], step->data, step->data_len);
buf->subevent_cursor += step->data_len;
}
/* Create RAS segment*/
struct segment *ras_segment;
uint16_t max_data_len = ble_att_mtu(ranging_subevent.subev_result.conn_handle) - sizeof(struct segment_header) - 4;
MODLOG_DFLT(INFO, "Max data len : %d\n", max_data_len);
ras_segment= nimble_platform_mem_malloc(sizeof(struct segment)+ max_data_len);
if (ras_segment == NULL) {
MODLOG_DFLT(INFO, "Failed to allocate memory for RAS segment\n");
return;
}
ras_segment->header.first_seg = true;
ras_segment->header.last_seg = true;
ras_segment->header.seg_counter = 0; // First segment
uint16_t buf_len = sizeof(struct ranging_header) + buf->subevent_cursor;
uint16_t remaining = buf_len - 0;
uint16_t pull_bytes = MIN(max_data_len, remaining);
if (max_data_len < remaining) {
// More segments to come
pull_bytes = max_data_len;
}else {
pull_bytes = remaining;
}
memcpy( ras_segment->data, &buf->ranging_data.buf[0], pull_bytes);
ble_svc_ras_od_rd_val= ras_segment; // Store the segment in the global variable
// ble_gatts_chr_updated(ble_svc_ras_od_rd_val_handle);
// 4 bytes for header and CRC
// now max data len is att mtu -4
// count number of egment required based on actudal rd_buffer len
// noe set buf to data [] of segment ensuring only one segment is created
// if more than one segment is required then set first_seg and last_seg accordingly
// and set seg_counter to 0 for first segment and increment it for each segment
// and set the data len to actual data len
// now once cp control point command is recived we will append the segment to os_mbuf buffer and indicate it to the client
}
void custom_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;
}
}
void
ble_svc_ras_init(void) {
int rc;
/* Ensure this function only gets called by sysinit. */
SYSINIT_ASSERT_ACTIVE();
rc = ble_gatts_count_cfg(gatt_svr_svcs);
SYSINIT_PANIC_ASSERT(rc == 0);
rc = ble_gatts_add_svcs(gatt_svr_svcs);
SYSINIT_PANIC_ASSERT(rc == 0);
reset_ranging_buffer();
}
@@ -31,5 +31,3 @@ enum ble_ras_rreq_cp_state {
/** @brief UUID of the Ranging Data Overwritten Characteristic. **/
#define BLE_UUID_RAS_RD_OVERWRITTEN_VAL (0x2C19)
@@ -23,8 +23,6 @@
#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;
@@ -36,111 +34,109 @@ 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
,
},{
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,
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;
{
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){
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;
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;
}
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;
@@ -150,57 +146,56 @@ unknown:
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;
}
void
custom_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;
}
+141 -78
View File
@@ -35,11 +35,6 @@
((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));
@@ -88,6 +83,7 @@ struct ble_cs_rd_rem_fae_cp {
uint16_t conn_handle;
} __attribute__((packed));
#if 0
struct ble_cs_wr_cached_rem_fae_cp {
uint16_t conn_handle;
uint8_t remote_fae_table[72];
@@ -96,6 +92,7 @@ struct ble_cs_wr_cached_rem_fae_rp {
uint16_t conn_handle;
} __attribute__((packed));
#endif
struct ble_cs_create_config_cp {
uint16_t conn_handle;
uint8_t config_id;
@@ -127,6 +124,7 @@ struct ble_cs_create_config_cp {
uint8_t companion_signal_enable;
} __attribute__((packed));
#if 0
struct ble_cs_remove_config_cp {
uint16_t conn_handle;
uint8_t config_id;
@@ -136,6 +134,7 @@ struct ble_cs_set_chan_class_cp {
uint8_t channel_classification[10];
} __attribute__((packed));
#endif
struct ble_cs_set_proc_params_cp {
uint16_t conn_handle;
uint8_t config_id;
@@ -200,6 +199,7 @@ ble_cs_call_event_cb(struct ble_cs_event *event)
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);
@@ -213,7 +213,9 @@ 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;
@@ -226,7 +228,8 @@ ble_cs_call_result_cb(const struct ble_hci_ev_le_subev_cs_subevent_result *ev)
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);
event.subev_result.steps=ev->steps;
//memcpy(event.subev_result.steps, ev->steps, 5);
ble_cs_call_event_cb(&event);
}
@@ -242,10 +245,12 @@ static void ble_cs_call_result_continue_cb(const struct ble_hci_ev_le_subev_cs_s
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);
MODLOG_DFLT(INFO, "event.subev_result_continue.num_steps_reported= %d\n",ev->num_steps_reported);
event.subev_result_continue.steps = ev->steps;
// memcpy(event.subev_result_continue.steps, ev->steps, ev->num_steps_reported * sizeof(event.subev_result_continue.steps[0]));
ble_cs_call_event_cb(&event);
}
#if 0
static int
ble_cs_rd_loc_supp_cap(void)
{
@@ -268,6 +273,7 @@ ble_cs_rd_loc_supp_cap(void)
return rc;
}
#endif
static int
ble_cs_rd_rem_supp_cap(const struct ble_cs_rd_rem_supp_cap_cp *cmd)
@@ -281,6 +287,7 @@ ble_cs_rd_rem_supp_cap(const struct ble_cs_rd_rem_supp_cap_cp *cmd)
&cp, sizeof(cp), NULL, 0);
}
#if 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)
@@ -318,6 +325,7 @@ ble_cs_wr_cached_rem_supp_cap(const struct ble_cs_wr_cached_rem_supp_cap_cp *cmd
return rc;
}
#endif
static int
ble_cs_sec_enable(const struct ble_cs_sec_enable_cp *cmd)
@@ -365,6 +373,7 @@ ble_cs_rd_rem_fae(const struct ble_cs_rd_rem_fae_cp *cmd)
&cp, sizeof(cp), NULL, 0);
}
#if 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)
@@ -384,13 +393,14 @@ ble_cs_wr_cached_rem_fae(const struct ble_cs_wr_cached_rem_fae_cp *cmd,
return rc;
}
#endif
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;
@@ -407,13 +417,13 @@ ble_cs_create_config(const struct ble_cs_create_config_cp *cmd)
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);
}
#if 0
static int
ble_cs_remove_config(const struct ble_cs_remove_config_cp *cmd)
{
@@ -442,6 +452,7 @@ ble_cs_set_chan_class(const struct ble_cs_set_chan_class_cp *cmd)
return rc;
}
#endif
static int
ble_cs_set_proc_params(const struct ble_cs_set_proc_params_cp *cmd,
struct ble_cs_set_proc_params_rp *rsp)
@@ -492,19 +503,16 @@ 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;
struct ble_gap_conn_desc desc;
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;
}
@@ -514,12 +522,14 @@ ble_hs_hci_evt_le_cs_rd_rem_supp_cap_complete(uint8_t subevent, const void *data
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;
set_cmd.role_enable = 0x00;
rc = ble_gap_conn_find(ev->conn_handle, &desc);
if (desc.role == BLE_GAP_ROLE_MASTER) {
set_cmd.role_enable |= 1;
} else{
set_cmd.role_enable |= 2;
}
/* Use antenna with ID 0x01 */
set_cmd.cs_sync_antenna_selection = 0xFE;
@@ -535,12 +545,13 @@ ble_hs_hci_evt_le_cs_rd_rem_supp_cap_complete(uint8_t subevent, const void *data
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");
}
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;
}
@@ -549,32 +560,32 @@ 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");
struct ble_gap_conn_desc desc;
const struct ble_hci_ev_le_subev_cs_rd_rem_fae_complete *ev = data;
struct ble_cs_create_config_cp cmd;
int rc;
memset(&cmd,0,sizeof cmd);
int rc=0;
print_ev_sz(len,sizeof(*ev),ev->status);
if (len != sizeof(*ev) || ev->status) {
printf("BLE_HS_ECONTROLLER fae \n");
// return BLE_HS_ECONTROLLER;
//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;
cmd.create_context = 0x01;
/* Measure phase rotations in main mode */
cmd.main_mode_type = 0x01;
/* Do not use sub mode for now. */
cmd.sub_mode_type = 0x00;
cmd.main_mode_type = 0x02;
/* Use sub mode 0xFF for now, meaning no sub mode */
cmd.sub_mode_type = 0x01;
/* 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;
cmd.min_main_mode_steps = 10;
cmd.max_main_mode_steps = 20;
/* 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.
@@ -585,34 +596,40 @@ ble_hs_hci_evt_le_cs_rd_rem_fae_complete(uint8_t subevent, const void *data,
*/
cmd.mode_0_steps = 0x03;
/* Take the Initiator role */
cmd.role = 0x01;
ble_gap_conn_find(ev->conn_handle, &desc);
cmd.role= 0x00;
if (desc.role == BLE_GAP_ROLE_MASTER) {
cmd.role = 0x00;
} else {
cmd.role = 0x01;
}
/* Use RTT type 0x00 for now */
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);
memcpy(cmd.channel_map, (uint8_t[10]) {0x08, 0xfa, 0x4f, 0xac, 0xfa, 0xc0}, 10);
cmd.channel_map_repetition = 0x03;
cmd.channel_map_repetition = 5;
/* 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");
}
if (desc.role == BLE_GAP_ROLE_MASTER) {
rc = ble_cs_create_config(&cmd);
if (rc) {
BLE_HS_LOG(INFO, "Failed to create CS config");
}
}
return rc;
}
@@ -620,12 +637,13 @@ 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;
struct ble_gap_conn_desc desc;
if (len != sizeof(*ev)) {
BLE_HS_LOG(INFO, "Failed to enable CS security BLE_HS_ECNOTEROLLER");
@@ -638,22 +656,22 @@ ble_hs_hci_evt_le_cs_sec_enable_complete(uint8_t subevent, const void *data,
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;
cmd.max_procedure_len = 100;
/* The maximum number of consecutive CS procedures to be scheduled
* as part of this measurement
*/
cmd.max_procedure_count = 0x0001;
cmd.max_procedure_count = 1;
/* 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;
cmd.min_procedure_interval = 10;
cmd.max_procedure_interval = 10;
/* 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.min_subevent_len = 60000;
cmd.max_subevent_len = 60000;
/* Use ACI 0 as we have only one CS setup phase completedantenna on each side */
cmd.tone_antenna_config_selection = 0x00;
/* Use LE 1M PHY for CS procedures */
cmd.phy = 0x01;
@@ -670,41 +688,54 @@ ble_hs_hci_evt_le_cs_sec_enable_complete(uint8_t subevent, const void *data,
rc = ble_cs_set_proc_params(&cmd, &rsp);
if (rc) {
BLE_HS_LOG(INFO, "Failed to set CS procedure parameters");
}else{
BLE_HS_LOG(INFO, "CS procedure parameters set");
}
enable_cmd.conn_handle = le16toh(ev->conn_handle);
enable_cmd.config_id = 0x00;
enable_cmd.enable = 0x01;
ble_gap_conn_find(ev->conn_handle, &desc);
if (desc.role == BLE_GAP_ROLE_MASTER) {
rc = ble_cs_proc_enable(&enable_cmd);
if (rc) {
BLE_HS_LOG(INFO, "Failed to enable CS procedure");
}else{
BLE_HS_LOG(INFO, "CS procedure enabled");
}
return rc;
}
return 0;
}
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;
struct ble_gap_conn_desc desc;
const struct ble_hci_ev_le_subev_cs_config_complete *ev = data;
struct ble_cs_sec_enable_cp cmd;
// struct ble_hs_conn *conn;
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);
rc = ble_gap_conn_find(ev->conn_handle, &desc);
if (desc.role == BLE_GAP_ROLE_MASTER) {
rc = ble_cs_sec_enable(&cmd);
if (rc) {
BLE_HS_LOG(DEBUG, "Failed to enable CS security");
ble_cs_call_procedure_complete_cb(le16toh(ev->conn_handle), ev->status);
}
}
return 0;
@@ -717,10 +748,10 @@ ble_hs_hci_evt_le_cs_proc_enable_complete(uint8_t subevent, const void *data,
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;
}
@@ -728,13 +759,29 @@ 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;
const struct ble_hci_ev_le_subev_cs_subevent_result *event = data;
int expected_len = 0;
void *step_ptr = NULL;
int steps_remaining = 0;
int step_size = 0;
if (len != sizeof(*ev)) {
expected_len += sizeof(*event);
steps_remaining = event->num_steps_reported;
step_ptr = (void *)event->steps;
while (steps_remaining) {
step_size = sizeof(struct cs_steps_data) + ((struct cs_steps_data *)step_ptr)->data_len;
expected_len += step_size;
step_ptr += step_size;
steps_remaining--;
}
if (len != expected_len) {
MODLOG_DFLT(INFO, "ble_hs_hci_evt_le_cs_subevent_result\n len :%d expected_len : %d\n", len, expected_len);
return BLE_HS_ECONTROLLER;
}
ble_cs_call_result_cb(ev);
ble_cs_call_result_cb(event);
return 0;
}
@@ -742,12 +789,28 @@ 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;
const struct ble_hci_ev_le_subev_cs_subevent_result_continue *event = data;
int expected_len = 0;
int steps_remaining = 0;
void *step_ptr = NULL;
int step_size = 0;
if (len != sizeof(*ev)) {
expected_len = sizeof(*event);
steps_remaining = event->num_steps_reported;
step_ptr = (void *)event->steps;
while (steps_remaining) {
step_size = sizeof(struct cs_steps_data) + ((struct cs_steps_data *)step_ptr)->data_len;
step_ptr += step_size;
expected_len += step_size;
steps_remaining--;
}
if (len != expected_len) {
MODLOG_DFLT(INFO, "ble_hs_hci_evt_le_cs_subevent_result_continue len: %d expected_len: %d\n", len, expected_len);
return BLE_HS_ECONTROLLER;
}
ble_cs_call_result_continue_cb(ev);
ble_cs_call_result_continue_cb(event);
return 0;
}
@@ -768,7 +831,7 @@ ble_hs_hci_evt_le_cs_test_end_complete(uint8_t subevent, const void *data,
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;
@@ -789,7 +852,7 @@ ble_cs_initiator_procedure_start(const struct ble_cs_initiator_procedure_start_p
BLE_HS_LOG(DEBUG, "Failed to read local supported CS capabilities,"
"err %dt", rc);
}
printf("cmd sent succfully\n");
return rc;
}
+2 -8
View File
@@ -104,9 +104,6 @@
#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).
@@ -1213,7 +1210,6 @@ 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.
@@ -1222,8 +1218,6 @@ 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);
@@ -2961,7 +2955,6 @@ 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;
@@ -2969,7 +2962,6 @@ 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;
@@ -10046,6 +10038,7 @@ ble_gap_host_check_status(void)
return status;
}
#if MYNEWT_VAL(BLE_CHANNEL_SOUNDING)
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;
@@ -10053,3 +10046,4 @@ int ble_gap_set_host_feat(uint8_t bit_num,uint8_t 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);
}
#endif
+1 -1
View File
@@ -4386,7 +4386,7 @@ ble_gattc_signed_write(uint16_t conn_handle, uint16_t attr_handle,
goto err;
}
if (desc.sec_state.encrypted == 1) {
rc = BLE_HS_EENCRYPT;
rc = BLE_HS_EENCRYPT;
goto err;
}
+3 -3
View File
@@ -723,7 +723,7 @@ ble_hs_rx_data(struct os_mbuf *om, void *arg)
{
int rc;
#if ((BT_HCI_LOG_INCLUDED == TRUE) && SOC_ESP_NIMBLE_CONTROLLER && CONFIG_BT_CONTROLLER_ENABLED)
#if ((BT_HCI_LOG_INCLUDED == TRUE))
uint16_t len = OS_MBUF_PKTHDR(om)->omp_len + 1;
uint8_t *data = (uint8_t *)nimble_platform_mem_malloc(len);
assert(data != NULL);
@@ -759,8 +759,8 @@ ble_hs_rx_data(struct os_mbuf *om, void *arg)
int
ble_hs_tx_data(struct os_mbuf *om)
{
#if ((BT_HCI_LOG_INCLUDED == TRUE) && SOC_ESP_NIMBLE_CONTROLLER && CONFIG_BT_CONTROLLER_ENABLED)
uint16_t len = 0;
#if ((BT_HCI_LOG_INCLUDED == TRUE))
uint16_t len = 0;
uint8_t data[MYNEWT_VAL(BLE_TRANSPORT_ACL_SIZE) + 1];
data[0] = 0x02;
len++;
+1 -1
View File
@@ -648,7 +648,7 @@ ble_hs_hci_rx_evt(uint8_t *hci_ev, void *arg)
BLE_HS_DBG_ASSERT(hci_ev != NULL);
#if ((BT_HCI_LOG_INCLUDED == TRUE) && SOC_ESP_NIMBLE_CONTROLLER && CONFIG_BT_CONTROLLER_ENABLED)
#if ((BT_HCI_LOG_INCLUDED == TRUE))
uint16_t len = hci_ev[1] + 3;
if (host_recv_adv_packet(hci_ev)) {
bt_hci_log_record_hci_adv(HCI_LOG_DATA_TYPE_ADV, &hci_ev[1], len - 2);
+1 -1
View File
@@ -91,7 +91,7 @@ ble_hs_hci_cmd_send(uint16_t opcode, uint8_t len, const void *cmddata)
buf--;
#endif
#if ((BT_HCI_LOG_INCLUDED == TRUE) && SOC_ESP_NIMBLE_CONTROLLER && CONFIG_BT_CONTROLLER_ENABLED)
#if ((BT_HCI_LOG_INCLUDED == TRUE))
uint8_t *data;
#if !(SOC_ESP_NIMBLE_CONTROLLER) && CONFIG_BT_CONTROLLER_ENABLED
data = (uint8_t *)buf + 1;
+1 -1
View File
@@ -221,6 +221,7 @@ 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:
@@ -313,7 +314,6 @@ 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;
}
-2
View File
@@ -238,7 +238,6 @@ ble_hs_startup_read_bd_addr(void)
}
ble_hs_id_set_pub(rsp.addr);
return 0;
}
@@ -385,7 +384,6 @@ ble_hs_startup_le_set_evmask_tx(void)
}
#endif
<<<<<<< HEAD
#if MYNEWT_VAL(BLE_ISO)
if (version >= BLE_HCI_VER_BCS_5_2) {
/**
+2 -1
View File
@@ -1472,7 +1472,7 @@ struct ble_hci_le_cs_create_config_cp {
uint8_t channel_selection_type;
uint8_t ch3c_shape;
uint8_t ch3c_jump;
uint8_t companion_signal_enable;
// uint8_t companion_signal_enable;
} __attribute__((packed));
#define BLE_HCI_OCF_LE_CS_REMOVE_CONFIG (0x0091)
@@ -2637,6 +2637,7 @@ struct ble_hci_ev_le_subev_cs_proc_enable_complete {
uint16_t event_interval;
uint16_t procedure_interval;
uint16_t procedure_count;
uint16_t max_procedure_len;
} __attribute__((packed));
#define BLE_HCI_LE_SUBEV_CS_SUBEVENT_RESULT (0x31)