feat(nimble): Add support to 6.2 BLE HCI Command Event(FSU, UTP over OTA)

This commit is contained in:
Sahil Yadav
2026-02-17 14:54:11 +05:30
committed by Rahul Tank
parent f40b4612ec
commit e52e061c49
5 changed files with 299 additions and 0 deletions
+68
View File
@@ -186,6 +186,8 @@ struct hci_conn_update;
#define BLE_GAP_EVENT_MONITOR_ADV_REPORT 52 #define BLE_GAP_EVENT_MONITOR_ADV_REPORT 52
#define BLE_GAP_EVENT_CACHE_ASSOC 53 #define BLE_GAP_EVENT_CACHE_ASSOC 53
#define BLE_GAP_EVENT_FRAME_SPACE_UPDATE 54
#define BLE_GAP_EVENT_UTP_RECEIVE 55
/* DTM events */ /* DTM events */
#define BLE_GAP_DTM_TX_START_EVT 0 #define BLE_GAP_DTM_TX_START_EVT 0
@@ -2038,6 +2040,54 @@ struct ble_gap_event {
} monitor_adv_report; } monitor_adv_report;
#endif #endif
#if MYNEWT_VAL(BLE_FRAME_SPACE_UPDATE)
/*
* Represents a change in the Inter-Frame Space (IFS).
*/
struct {
/* The status of the frame space update attempt (0 on success). */
int status;
/* The handle of the connection where the update occurred. */
uint16_t conn_handle;
/*
* Indicates whether the local Host initiated the update.
* 0: Controller initiated
* 1: Local Host initiated
*/
uint8_t initiator;
/* The new frame space value in microseconds. */
uint16_t frame_space;
/* Bitmask indicating the PHYs to which the frame space applies. */
uint8_t phys;
/* Bitmask indicating the spacing types. */
uint16_t spacing_types;
} frame_space_update;
#endif
#if MYNEWT_VAL(BLE_UTP_OTA)
/*
* Represents a received Unified Test Protocol (UTP) packet.
*/
struct {
/* The connection handle associated with the packet.
* Note: Currently set to BLE_HS_CONN_HANDLE_NONE as the
* controller event does not provide a handle.
*/
uint16_t conn_handle;
/* The length of the UTP data payload. */
uint8_t len;
/* Pointer to the UTP data payload. */
const uint8_t *data;
} utp_receive;
#endif
}; };
}; };
@@ -4175,6 +4225,24 @@ int ble_gap_read_local_irk(uint8_t * out_irk);
int ble_gap_set_host_feat(uint8_t bit_num,uint8_t bit_val); int ble_gap_set_host_feat(uint8_t bit_num,uint8_t bit_val);
#endif #endif
#if MYNEWT_VAL(BLE_FRAME_SPACE_UPDATE)
/* * Request a Frame Space Update.
* phys: Bitmask of PHYs (0=1M, 1=2M, 2=Coded)
* spacing_types: Bitmask of spacing types to update
*/
int ble_gap_frame_space_update(uint16_t conn_handle,
uint16_t frame_space_min,
uint16_t frame_space_max,
uint8_t phys,
uint16_t spacing_types);
#endif
#if MYNEWT_VAL(BLE_UTP_OTA)
int ble_gap_enable_utp_ota_mode(uint8_t enable);
int ble_gap_utp_send(uint8_t len, const uint8_t *data);
#endif
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif
+142
View File
@@ -2501,6 +2501,59 @@ ble_gap_rx_rd_monitor_adv_report(const struct ble_hci_ev_le_subev_monitor_adv_re
} }
#endif #endif
#if MYNEWT_VAL(BLE_FRAME_SPACE_UPDATE)
void
ble_gap_rx_frame_space_update_complete(const struct ble_hci_ev_le_subev_frame_space_update_complete *ev)
{
#if NIMBLE_BLE_CONNECT
struct ble_gap_event event;
uint16_t conn_handle;
conn_handle = le16toh(ev->conn_handle);
memset(&event, 0, sizeof(event));
event.type = BLE_GAP_EVENT_FRAME_SPACE_UPDATE;
event.frame_space_update.status = ev->status;
event.frame_space_update.conn_handle = conn_handle;
event.frame_space_update.initiator = ev->initiator;
event.frame_space_update.frame_space = le16toh(ev->frame_space);
event.frame_space_update.phys = ev->phys;
event.frame_space_update.spacing_types = le16toh(ev->spacing_types);
ble_gap_event_listener_call(&event);
ble_gap_call_conn_event_cb(&event, conn_handle);
#endif
}
#endif
#if MYNEWT_VAL(BLE_UTP_OTA)
void
ble_gap_rx_utp_receive(const struct ble_hci_ev_le_subev_utp_receive *ev, uint8_t len)
{
struct ble_gap_event event;
const uint8_t *data_ptr;
if (len < sizeof(*ev)) {
return;
}
if (len < (sizeof(*ev) + ev->len)) {
return;
}
data_ptr = (const uint8_t *)ev + sizeof(*ev);
memset(&event, 0, sizeof(event));
event.type = BLE_GAP_EVENT_UTP_RECEIVE;
event.utp_receive.conn_handle = BLE_HS_CONN_HANDLE_NONE;
event.utp_receive.len = ev->len;
event.utp_receive.data = data_ptr;
ble_gap_event_listener_call(&event);
}
#endif
void void
ble_gap_rx_adv_report(struct ble_gap_disc_desc *desc) ble_gap_rx_adv_report(struct ble_gap_disc_desc *desc)
{ {
@@ -10954,3 +11007,92 @@ bool ble_gap_rpa_resolve(uint8_t *rpa, uint8_t *ida, uint8_t *addr_type)
return false; /* No match */ return false; /* No match */
} }
#if MYNEWT_VAL(BLE_FRAME_SPACE_UPDATE)
int
ble_gap_frame_space_update(uint16_t conn_handle,
uint16_t frame_space_min,
uint16_t frame_space_max,
uint8_t phys,
uint16_t spacing_types)
{
#if NIMBLE_BLE_CONNECT
struct ble_hci_le_frame_space_update_cp cmd;
struct ble_hs_conn *conn;
ble_hs_lock();
conn = ble_hs_conn_find(conn_handle);
ble_hs_unlock();
if (conn == NULL) {
return BLE_HS_ENOTCONN;
}
if (frame_space_min > 10000 || frame_space_max > 10000) {
return BLE_HS_EINVAL;
}
if (frame_space_min > frame_space_max) {
return BLE_HS_EINVAL;
}
if ((phys & ~0x07) || (phys == 0)) {
return BLE_HS_EINVAL;
}
if ((spacing_types & ~0x1F) || (spacing_types == 0)) {
return BLE_HS_EINVAL;
}
cmd.conn_handle = htole16(conn_handle);
cmd.frame_space_min = htole16(frame_space_min);
cmd.frame_space_max = htole16(frame_space_max);
cmd.phys = phys;
cmd.spacing_types = htole16(spacing_types);
return ble_hs_hci_cmd_tx(BLE_HCI_OP(BLE_HCI_OGF_LE,
BLE_HCI_OCF_LE_FRAME_SPACE_UPDATE), &cmd, sizeof(cmd), NULL, 0);
#else
return BLE_HS_ENOTSUP;
#endif
}
#endif
#if MYNEWT_VAL(BLE_UTP_OTA)
int
ble_gap_enable_utp_ota_mode(uint8_t enable)
{
struct ble_hci_le_enable_utp_ota_mode_cp cmd;
if (enable > 1) {
return BLE_HS_EINVAL;
}
cmd.enable = enable;
return ble_hs_hci_cmd_tx(BLE_HCI_OP(BLE_HCI_OGF_LE,
BLE_HCI_OCF_LE_ENABLE_UTP_OTA_MODE), &cmd, sizeof(cmd), NULL, 0);
}
int
ble_gap_utp_send(uint8_t len, const uint8_t *data)
{
uint8_t buf[sizeof(struct ble_hci_le_utp_send_cp) + 254];
struct ble_hci_le_utp_send_cp *cmd = (void *)buf;
if (len == 0 || len > 254) {
return BLE_HS_EINVAL;
}
cmd->len = len;
if (data == NULL)
{
return BLE_HS_EINVAL;
}
memcpy(buf + sizeof(*cmd), data, len);
return ble_hs_hci_cmd_tx(BLE_HCI_OP(BLE_HCI_OGF_LE,
BLE_HCI_OCF_LE_UTP_SEND), cmd, sizeof(*cmd) + len, NULL, 0);
}
#endif
+8
View File
@@ -208,6 +208,14 @@ void ble_gap_rx_rd_all_remote_feat(const struct ble_hci_ev_le_subev_rd_all_rem_f
void ble_gap_rx_rd_monitor_adv_report(const struct ble_hci_ev_le_subev_monitor_adv_report *ev); void ble_gap_rx_rd_monitor_adv_report(const struct ble_hci_ev_le_subev_monitor_adv_report *ev);
#endif #endif
#if MYNEWT_VAL(BLE_FRAME_SPACE_UPDATE)
void ble_gap_rx_frame_space_update_complete(const struct ble_hci_ev_le_subev_frame_space_update_complete *ev);
#endif
#if MYNEWT_VAL(BLE_UTP_OTA)
void ble_gap_rx_utp_receive(const struct ble_hci_ev_le_subev_utp_receive *ev, uint8_t len);
#endif
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif
+45
View File
@@ -215,6 +215,12 @@ static ble_hs_hci_evt_le_fn ble_hs_hci_evt_le_cis_estab_v2;
#if NIMBLE_BLE_CONNECT #if NIMBLE_BLE_CONNECT
static ble_hs_hci_evt_le_fn ble_hs_hci_evt_le_rd_all_rem_feat; static ble_hs_hci_evt_le_fn ble_hs_hci_evt_le_rd_all_rem_feat;
#endif #endif
#if MYNEWT_VAL(BLE_FRAME_SPACE_UPDATE)
static ble_hs_hci_evt_le_fn ble_hs_hci_evt_le_frame_space_update;
#endif
#if MYNEWT_VAL(BLE_UTP_OTA)
static ble_hs_hci_evt_le_fn ble_hs_hci_evt_le_utp_receive;
#endif
#if MYNEWT_VAL(BLE_MONITOR_ADV) #if MYNEWT_VAL(BLE_MONITOR_ADV)
static ble_hs_hci_evt_le_fn ble_hci_ev_le_subev_monitor_adv_report; static ble_hs_hci_evt_le_fn ble_hci_ev_le_subev_monitor_adv_report;
#endif #endif
@@ -364,6 +370,12 @@ static ble_hs_hci_evt_le_fn * const ble_hs_hci_evt_le_dispatch[] = {
#if MYNEWT_VAL(BLE_MONITOR_ADV) #if MYNEWT_VAL(BLE_MONITOR_ADV)
[BLE_HCI_LE_SUBEV_MONITOR_ADV_REPORT] = ble_hci_ev_le_subev_monitor_adv_report, [BLE_HCI_LE_SUBEV_MONITOR_ADV_REPORT] = ble_hci_ev_le_subev_monitor_adv_report,
#endif #endif
#if MYNEWT_VAL(BLE_FRAME_SPACE_UPDATE)
[BLE_HCI_LE_SUBEV_FRAME_SPACE_UPDATE_COMPLETE] = ble_hs_hci_evt_le_frame_space_update,
#endif
#if MYNEWT_VAL(BLE_UTP_OTA)
[BLE_HCI_LE_SUBEV_UTP_RECEIVE] = ble_hs_hci_evt_le_utp_receive,
#endif
}; };
@@ -1858,6 +1870,39 @@ ble_hs_hci_evt_le_rd_all_rem_feat(uint8_t subevent, const void *data,
#endif #endif
#if MYNEWT_VAL(BLE_FRAME_SPACE_UPDATE)
static int
ble_hs_hci_evt_le_frame_space_update(uint8_t subevent, const void *data, unsigned int len)
{
/* FSU is strictly a connection-oriented feature.
* If connections are disabled, ignore the event or return error.
*/
#if NIMBLE_BLE_CONNECT
if (len != sizeof(struct ble_hci_ev_le_subev_frame_space_update_complete)) {
return BLE_HS_EBADDATA;
}
ble_gap_rx_frame_space_update_complete(data);
return 0;
#else
return BLE_HS_ENOTSUP;
#endif
}
#endif
#if MYNEWT_VAL(BLE_UTP_OTA)
static int
ble_hs_hci_evt_le_utp_receive(uint8_t subevent, const void *data, unsigned int len)
{
const struct ble_hci_ev_le_subev_utp_receive *ev = data;
if (len < sizeof(*ev) || len != (sizeof(*ev) + ev->len)) {
return BLE_HS_EBADDATA;
}
ble_gap_rx_utp_receive(data, (uint8_t)len);
return 0;
}
#endif
#if MYNEWT_VAL(BLE_MONITOR_ADV) #if MYNEWT_VAL(BLE_MONITOR_ADV)
static int static int
ble_hci_ev_le_subev_monitor_adv_report(uint8_t subevent, const void *data, ble_hci_ev_le_subev_monitor_adv_report(uint8_t subevent, const void *data,
+36
View File
@@ -1583,6 +1583,25 @@ struct ble_hci_le_enable_monitor_adv_cp {
uint8_t enable; uint8_t enable;
} __attribute__((packed)); } __attribute__((packed));
#define BLE_HCI_OCF_LE_FRAME_SPACE_UPDATE (0x009D)
struct ble_hci_le_frame_space_update_cp {
uint16_t conn_handle;
uint16_t frame_space_min;
uint16_t frame_space_max;
uint8_t phys;
uint16_t spacing_types;
} __attribute__((packed));
#define BLE_HCI_OCF_LE_ENABLE_UTP_OTA_MODE (0x009F)
struct ble_hci_le_enable_utp_ota_mode_cp {
uint8_t enable;
} __attribute__((packed));
#define BLE_HCI_OCF_LE_UTP_SEND (0x00A0)
struct ble_hci_le_utp_send_cp {
uint8_t len;
} __attribute__((packed));
/* --- Vendor specific commands (OGF 0x003F) */ /* --- Vendor specific commands (OGF 0x003F) */
/* Read Random Static Address */ /* Read Random Static Address */
#define BLE_HCI_OCF_VS_RD_STATIC_ADDR (MYNEWT_VAL(BLE_HCI_VS_OCF_OFFSET) + (0x0001)) #define BLE_HCI_OCF_VS_RD_STATIC_ADDR (MYNEWT_VAL(BLE_HCI_VS_OCF_OFFSET) + (0x0001))
@@ -2608,6 +2627,23 @@ struct ble_hci_ev_le_subev_monitor_adv_report {
uint8_t condition; uint8_t condition;
} __attribute__((packed)); } __attribute__((packed));
#define BLE_HCI_LE_SUBEV_FRAME_SPACE_UPDATE_COMPLETE (0x35)
struct ble_hci_ev_le_subev_frame_space_update_complete {
uint8_t subev_code;
uint8_t status;
uint16_t conn_handle;
uint8_t initiator;
uint16_t frame_space;
uint8_t phys;
uint16_t spacing_types;
} __attribute__((packed));
#define BLE_HCI_LE_SUBEV_UTP_RECEIVE (0x36)
struct ble_hci_ev_le_subev_utp_receive {
uint8_t subev_code;
uint8_t len;
} __attribute__((packed));
#if (BLE_ADV_REPORT_FLOW_CONTROL == TRUE) #if (BLE_ADV_REPORT_FLOW_CONTROL == TRUE)
// LE vendor hci event // LE vendor hci event
#define BLE_HCI_LE_SUBEV_DISCARD_REPORT_EVT 0XF0 #define BLE_HCI_LE_SUBEV_DISCARD_REPORT_EVT 0XF0