feat(ble): ISO minor support for NimBLE Host

This commit is contained in:
Liu Linyan
2025-07-01 12:00:19 +08:00
parent b04e3d1e96
commit 550ce6a646
16 changed files with 2420 additions and 10 deletions
+456 -1
View File
@@ -172,6 +172,16 @@ struct hci_conn_update;
#define BLE_GAP_EVENT_PER_SUBEV_RESP 41
#define BLE_GAP_EVENT_PERIODIC_TRANSFER_V2 42
/* ISO events */
#define BLE_GAP_EVENT_CIS_ESTAB 43
#define BLE_GAP_EVENT_CIS_REQUEST 44
#define BLE_GAP_EVENT_CREATE_BIG_COMP 45
#define BLE_GAP_EVENT_TERM_BIG_COMP 46
#define BLE_GAP_EVENT_BIG_SYNC_ESTAB 47
#define BLE_GAP_EVENT_BIG_SYNC_LOST 48
#define BLE_GAP_EVENT_BIGINFO_ADV_RPT 49
#define BLE_GAP_EVENT_CIS_ESTAB_V2 50
/* DTM events */
#define BLE_GAP_DTM_TX_START_EVT 0
#define BLE_GAP_DTM_RX_START_EVT 1
@@ -1207,7 +1217,7 @@ struct ble_gap_event {
} periodic_transfer;
#endif
#if MYNEWT_VAL(BLE_PERIODIC_ADV_SYNC_BIGINFO_REPORTS)
#if MYNEWT_VAL(BLE_PERIODIC_ADV_SYNC_BIGINFO_REPORTS) && !MYNEWT_VAL(BLE_ISO)
/**
* Represents a periodic advertising sync transfer received. Valid for
* the following event types:
@@ -1653,6 +1663,293 @@ struct ble_gap_event {
} cte_req_fail;
#endif
#if MYNEWT_VAL(BLE_ISO)
struct {
/** BLE_ERR_SUCCESS on success or error code on failure */
uint8_t status;
/** Connection handle of the CIS */
uint16_t cis_handle;
/** The maximum time, in microseconds, for transmission of PDUs
* of all CISes in a CIG event.
*/
uint32_t cig_sync_delay;
/** The maximum time, in microseconds, for transmission of PDUs
* of the specified CIS in a CIG event.
*/
uint32_t cis_sync_delay;
/** The actual transport latency, in microseconds, from Central to Peripheral */
uint32_t transport_latency_c_to_p;
/** The actual transport latency, in microseconds, from Peripheral to Central */
uint32_t transport_latency_p_to_c;
/** TX PHY (Central to Peripheral) */
uint8_t phy_c_to_p;
/** TX PHY (Peripheral to Central) */
uint8_t phy_p_to_c;
/** Maximum number of subevents in each CIS event */
uint8_t nse;
/** The burst number for Central to Peripheral transmission */
uint8_t bn_c_to_p;
/** The burst number for Peripheral to Central transmission */
uint8_t bn_p_to_c;
/** The flush timeout, in multiple of the ISO_Interval for the CIS,
* for each payload sent from Central to Peripheral.
*/
uint8_t ft_c_to_p;
/** The flush timeout, in multiple of the ISO_Interval for the CIS,
* for each payload sent from Peripheral to Central.
*/
uint8_t ft_p_to_c;
/** Maximum size, in octets, of the payload from Central to Peripheral */
uint16_t max_pdu_c_to_p;
/** Maximum size, in octets, of the payload from Peripheral to Central */
uint16_t max_pdu_p_to_c;
/** The time between two consecutive CIS anchor points (unit 1.25ms) */
uint16_t iso_interval;
} cis_estab;
struct {
/** Connection handle of the ACL */
uint16_t conn_handle;
/** Connection handle of the CIS */
uint16_t cis_handle;
/** Identifier of the CIG */
uint8_t cig_id;
/** Identifier of the CIS */
uint8_t cis_id;
} cis_request;
struct {
/** BLE_ERR_SUCCESS on success or error code on failure */
uint8_t status;
/** Identifier of the BIG */
uint8_t big_handle;
/** The maximum time, in microseconds, for transmission of PDUs
* of all BISes in a BIG event.
*/
uint32_t big_sync_delay;
/** The actual transport latency, in microseconds */
uint32_t transport_latency;
/** PHY used to create the BIG */
uint8_t phy;
/** The number of subevents in each BIS event in the BIG */
uint8_t nse;
/** The number of new payloads in each BIS event */
uint8_t bn;
/** Offset used for pre-transmissions */
uint8_t pto;
/** The number of times a payload is transmitted in a BIS event */
uint8_t irc;
/** Maximum size, in octets, of the payload */
uint16_t max_pdu;
/** The time between two consecutive BIG anchor points (unit 1.25ms) */
uint16_t iso_interval;
/** Total number of BISes in the BIG */
uint8_t bis_cnt;
/** Connection handles of the BISes */
uint16_t bis_handle[MYNEWT_VAL(BLE_ISO_BIS_PER_BIG)];
} create_big_comp;
struct {
/** Identifier of the BIG */
uint8_t big_handle;
/** Reason for termination */
uint8_t reason;
} term_big_comp;
struct {
/** BLE_ERR_SUCCESS on success or error code on failure */
uint8_t status;
/** Identifier of the BIG */
uint8_t big_handle;
/** The actual transport latency, in microseconds */
uint32_t transport_latency;
/** The number of subevents in each BIS event in the BIG */
uint8_t nse;
/** The number of new payloads in each BIS event */
uint8_t bn;
/** Offset used for pre-transmissions */
uint8_t pto;
/** The number of times a payload is transmitted in a BIS event */
uint8_t irc;
/** Maximum size, in octets, of the payload */
uint16_t max_pdu;
/** The time between two consecutive BIG anchor points (unit 1.25ms) */
uint16_t iso_interval;
/** Total number of BISes in the BIG */
uint8_t bis_cnt;
/** Connection handles of the BISes */
uint16_t bis_handle[MYNEWT_VAL(BLE_ISO_BIS_PER_BIG)];
} big_sync_estab;
struct {
/** Identifier of the BIG */
uint8_t big_handle;
/** Reason for termination */
uint8_t reason;
} big_sync_lost;
struct {
/** Sync_Handle identifying the periodic advertising train */
uint16_t sync_handle;
/** Total number of BISes in the BIG */
uint8_t bis_cnt;
/** The number of subevents in each BIS event in the BIG */
uint8_t nse;
/** The time between two consecutive BIG anchor points (unit 1.25ms) */
uint16_t iso_interval;
/** The number of new payloads in each BIS event */
uint8_t bn;
/** Offset used for pre-transmissions */
uint8_t pto;
/** The number of times a payload is transmitted in a BIS event */
uint8_t irc;
/** Maximum size, in octets, of the payload */
uint16_t max_pdu;
/** Time, in microseconds, between the start of consecutive SDUs */
uint32_t sdu_interval;
/** Maximum size of an SDU, in octets */
uint16_t max_sdu;
/** PHY used by the BIG */
uint8_t phy;
/** Unframed or framed PDUs */
uint8_t framing;
/** BIG encryption */
uint8_t encryption;
} biginfo_report;
#if MYNEWT_VAL(BLE_ISO_CIS_ESTAB_V2)
struct {
/** BLE_ERR_SUCCESS on success or error code on failure */
uint8_t status;
/** Connection handle of the CIS */
uint16_t cis_handle;
/** The maximum time, in microseconds, for transmission of PDUs
* of all CISes in a CIG event.
*/
uint32_t cig_sync_delay;
/** The maximum time, in microseconds, for transmission of PDUs
* of the specified CIS in a CIG event.
*/
uint32_t cis_sync_delay;
/** The actual transport latency, in microseconds, from Central to Peripheral */
uint32_t transport_latency_c_to_p;
/** The actual transport latency, in microseconds, from Peripheral to Central */
uint32_t transport_latency_p_to_c;
/** TX PHY (Central to Peripheral) */
uint8_t phy_c_to_p;
/** TX PHY (Peripheral to Central) */
uint8_t phy_p_to_c;
/** Maximum number of subevents in each CIS event */
uint8_t nse;
/** The burst number for Central to Peripheral transmission */
uint8_t bn_c_to_p;
/** The burst number for Peripheral to Central transmission */
uint8_t bn_p_to_c;
/** The flush timeout, in multiple of the ISO_Interval for the CIS,
* for each payload sent from Central to Peripheral.
*/
uint8_t ft_c_to_p;
/** The flush timeout, in multiple of the ISO_Interval for the CIS,
* for each payload sent from Peripheral to Central.
*/
uint8_t ft_p_to_c;
/** Maximum size, in octets, of the payload from Central to Peripheral */
uint16_t max_pdu_c_to_p;
/** Maximum size, in octets, of the payload from Peripheral to Central */
uint16_t max_pdu_p_to_c;
/** The time between two consecutive CIS anchor points (unit 1.25ms) */
uint16_t iso_interval;
/** Time, in microseconds, between the start of consecutive subevents in a CIS event */
uint32_t sub_interval;
/** Maximum size, in octets, of the payload from Central's Host */
uint16_t max_sdu_c_to_p;
/** Maximum size, in octets, of the payload from Peripheral's Host */
uint16_t max_sdu_p_to_c;
/** Time, in microseconds, between the start of consecutive SDUs sent by Central */
uint32_t sdu_interval_c_to_p;
/** Time, in microseconds, between the start of consecutive SDUs sent by Peripheral */
uint32_t sdu_interval_p_to_c;
/** Unframed or framed PDUs */
uint8_t framing;
} cis_estab_v2;
#endif /* MYNEWT_VAL(BLE_ISO_CIS_ESTAB_V2) */
#endif /* MYNEWT_VAL(BLE_ISO) */
};
};
@@ -3372,6 +3669,164 @@ ble_gap_subrate_req(uint16_t conn_handle, uint16_t subrate_min, uint16_t subrate
uint16_t max_latency, uint16_t cont_num,
uint16_t supervision_timeout);
#endif
#if MYNEWT_VAL(BLE_ISO)
/**
* Create CIS by Central.
*
* @param cis_cnt The number of CISes to create.
* @param params The parameters used to create CISes.
* @param cb The callback to associate with the CIS creation procedure.
* When the CIS creation procedure completes, the result is
* reported through this callback.
* @param cb_arg The optional argument to pass to the callback function.
*
* @return 0 on success, error code on failure.
*/
int ble_gap_create_cis(uint8_t cis_cnt, const struct ble_hci_le_create_cis_params *params,
ble_gap_event_fn *cb, void *cb_arg);
/**
* Accept CIS request by Peripheral.
*
* @param cis_handle Connection handle of the CIS.
* @param cb The callback to associate with the CIS creation procedure.
* When the CIS creation procedure completes, the result is
* reported through this callback.
* @param cb_arg The optional argument to pass to the callback function.
*
* @return 0 on success, error code on failure.
*/
int ble_gap_accept_cis_request(uint16_t cis_handle, ble_gap_event_fn *cb, void *cb_arg);
/**
* Reject CIS request by Peripheral.
*
* @param cis_handle Connection handle of the CIS.
* @param reason Reason the CIS request was rejected.
*
* @return 0 on success, error code on failure.
*/
int ble_gap_reject_cis_request(uint16_t cis_handle, uint8_t reason);
/**
* Disconnect CIS.
*
* @param cis_handle Connection handle of the CIS.
* @param reason Reason the CIS was disconnected.
*
* @return 0 on success, error code on failure.
*/
int ble_gap_iso_disconnect(uint16_t cis_handle, uint8_t reason);
/**
* Create BIG Broadcaster.
*
* @param big_handle Identifier of the BIG.
* @param adv_handle Associated periodic advertising train.
* @param num_bis Total number of BISes in the BIG.
* @param sdu_interval The interval, in microseconds, of SDUs.
* @param max_sdu Maximum size, in octets, of an SDU.
* @param max_transport_latency Maximum transport latency, in milliseconds.
* @param rtn The number of times that every BIS PDU should be retransmitted.
* @param phy Transmitter PHY.
* @param packing Sequential or Interleaved.
* @param framing Unframed or framed.
* @param encryption Unencrypted or encrypted.
* @param broadcast_code The code used to derive the BIG session key.
* @param cb The callback to associate with the BIG creation procedure.
* When the BIG creation procedure completes, the result is
* reported through this callback.
* @param cb_arg The optional argument to pass to the callback function.
*
* @return 0 on success, error code on failure.
*/
int ble_gap_create_big(uint8_t big_handle, uint8_t adv_handle, uint8_t num_bis,
uint32_t sdu_interval, uint16_t max_sdu,
uint16_t max_transport_latency, uint8_t rtn,
uint8_t phy, uint8_t packing, uint8_t framing,
uint8_t encryption, uint8_t broadcast_code[16],
ble_gap_event_fn *cb, void *cb_arg);
#if MYNEWT_VAL(BLE_ISO_TEST)
/**
* Create BIG Broadcaster with test command.
*
* @param big_handle Identifier of the BIG.
* @param adv_handle Associated periodic advertising train.
* @param num_bis Total number of BISes in the BIG.
* @param sdu_interval The interval, in microseconds, of ISO SDUs.
* @param iso_interval The time between consecutive BIG anchor points (unit 1.25ms).
* @param nse The total number of subevents in each interval of each BIS in the BIG.
* @param max_sdu Maximum size, in octets, of an SDU.
* @param max_pdu Maximum size, in octets, of payload.
* @param phy Transmitter PHY.
* @param packing Sequential or Interleaved.
* @param framing Unframed or framed.
* @param bn The number of new payloads in each interval for each BIS.
* @param irc The number of times the payloads are transmitted in a given event.
* @param pto Offset used for pre-transmissions.
* @param encryption Unencrypted or encrypted.
* @param broadcast_code The code used to derive the BIG session key.
* @param cb The callback to associate with the BIG creation procedure.
* When the BIG creation procedure completes, the result is
* reported through this callback.
* @param cb_arg The optional argument to pass to the callback function.
*
* @return 0 on success, error code on failure.
*/
int ble_gap_create_big_test(uint8_t big_handle, uint8_t adv_handle, uint8_t num_bis,
uint32_t sdu_interval, uint16_t iso_interval, uint8_t nse,
uint16_t max_sdu, uint16_t max_pdu, uint8_t phy,
uint8_t packing, uint8_t framing, uint8_t bn, uint8_t irc,
uint8_t pto, uint8_t encryption, uint8_t broadcast_code[16],
ble_gap_event_fn *cb, void *cb_arg);
#endif /* MYNEWT_VAL(BLE_ISO_TEST) */
/**
* Terminate BIG Broadcaster.
*
* @param big_handle Identifier of the BIG.
* @param reason Reason the BIG is terminated.
*
* @return 0 on success, error code on failure.
*/
int ble_gap_terminate_big(uint8_t big_handle, uint8_t reason);
/**
* Create BIG Synchronized Receiver.
*
* @param big_handle Identifier of the BIG.
* @param sync_handle Associated periodic advertising train.
* @param encryption Unencrypted or encrypted.
* @param broadcast_code The code used to derive the BIG session key.
* @param mse Maximum number of subevents that should be used to receive in each BIS event.
* @param sync_timeout Synchronization timeout for the BIG (unit 10ms).
* @param num_bis Total number of BISes in the BIG.
* @param bis_index Indexes of the BISes.
* @param cb The callback to associate with the BIG creation procedure.
* When the BIG creation procedure completes, the result is
* reported through this callback.
* @param cb_arg The optional argument to pass to the callback function.
*
* @return 0 on success, error code on failure.
*/
int ble_gap_big_create_sync(uint8_t big_handle, uint16_t sync_handle,
uint8_t encryption, uint8_t broadcast_code[16],
uint8_t mse, uint16_t sync_timeout,
uint8_t num_bis, uint8_t *bis_index,
ble_gap_event_fn *cb, void *cb_arg);
/**
* Terminate BIG Synchronized Receiver.
*
* @param big_handle Identifier of the BIG.
*
* @return 0 on success, error code on failure.
*/
int ble_gap_big_terminate_sync(uint8_t big_handle);
#endif /* MYNEWT_VAL(BLE_ISO) */
/**
* Event listener structure
*
+10
View File
@@ -120,6 +120,16 @@ int ble_hs_hci_send_vs_cmd(uint16_t ocf, const void *cmdbuf, uint8_t cmdlen,
void *rspbuf, uint8_t rsplen);
#endif
/**
* Instructs the controller to 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 bit_val 0: The Host feature is disabled; 1: The Host feature is enabled.
* @return 0 on success, error code on failure
*/
int ble_hs_hci_set_host_feature(uint8_t bit_num, uint8_t bit_val);
#ifdef __cplusplus
}
#endif
+36
View File
@@ -0,0 +1,36 @@
/*
* SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Unlicense OR CC0-1.0
*/
#ifndef H_BLE_HS_ISO_
#define H_BLE_HS_ISO_
#include <stdint.h>
#include "os/os.h"
#include "mem/mem.h"
#include "syscfg/syscfg.h"
#ifdef __cplusplus
extern "C" {
#endif
int ble_hs_hci_set_iso_buf_sz(uint16_t pktlen, uint16_t max_pkts);
void ble_hs_hci_add_iso_avail_pkts(uint16_t conn_handle, uint16_t delta);
int ble_hs_hci_iso_tx(uint16_t conn_handle, const uint8_t *sdu, uint16_t sdu_len,
bool ts_flag, uint32_t time_stamp, uint16_t pkt_seq_num);
typedef int (*ble_hs_iso_pkt_rx_fn)(const uint8_t *data, uint16_t len, void *arg);
int ble_hs_iso_pkt_rx_cb_set(void *cb);
int ble_hs_rx_iso_data(const uint8_t *data, uint16_t len, void *arg);
#ifdef __cplusplus
}
#endif
#endif /* H_BLE_HS_ISO_ */
+120
View File
@@ -0,0 +1,120 @@
/*
* SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Unlicense OR CC0-1.0
*/
#ifndef H_BLE_HS_ISO_HCI_
#define H_BLE_HS_ISO_HCI_
#include <stdint.h>
#include "os/os.h"
#include "mem/mem.h"
#include "syscfg/syscfg.h"
#include "nimble/hci_common.h"
#ifdef __cplusplus
extern "C" {
#endif
#if MYNEWT_VAL(BLE_ISO)
int ble_hs_hci_iso_disconnect(uint16_t cis_handle, uint8_t reason);
int ble_hs_hci_read_local_supp_codec(uint8_t *rsp_buf, uint8_t rsp_len);
int ble_hs_hci_read_local_supp_codec_caps(uint8_t coding_fmt, uint16_t company_id,
uint16_t vs_codec_id, uint8_t logical_transport_type,
uint8_t direction, uint8_t *rsp_buf, uint8_t rsp_len);
int ble_hs_hci_read_local_supp_controller_delay(uint8_t coding_fmt, uint16_t company_id,
uint16_t vs_codec_id, uint8_t logical_transport_type,
uint8_t direction,
uint8_t codec_cfg_len, uint8_t *codec_cfg,
uint32_t *min_controller_delay,
uint32_t *max_controller_delay);
int ble_hs_hci_cfg_data_path(uint8_t data_path_direction, uint8_t data_path_id,
uint8_t vs_cfg_len, uint8_t *vs_cfg);
int ble_hs_hci_read_buf_sz_v2(uint16_t *data_len, uint8_t *data_packets,
uint16_t *iso_data_len, uint8_t *iso_data_packets);
int ble_hs_hci_read_iso_tx_sync(uint16_t conn_handle, uint16_t *packet_seq_num,
uint32_t *timestamp, uint32_t *timeoffset);
int ble_hs_hci_set_cig_params(uint8_t cig_id, uint32_t sdu_interval_c_to_p, uint32_t sdu_interval_p_to_c,
uint8_t slaves_clock_accuracy, uint8_t packing, uint8_t framing,
uint16_t max_transport_latency_c_to_p, uint16_t max_transport_latency_p_to_c,
uint8_t cis_cnt, struct ble_hci_le_cis_params *cis_params,
uint8_t *rsp_buf, uint8_t rsp_len);
#if MYNEWT_VAL(BLE_ISO_TEST)
int ble_hs_hci_set_cig_params_test(uint8_t cig_id, uint32_t sdu_interval_c_to_p, uint32_t sdu_interval_p_to_c,
uint8_t ft_c_to_p, uint8_t ft_p_to_c, uint16_t iso_interval,
uint8_t slaves_clock_accuracy, uint8_t packing, uint8_t framing,
uint8_t cis_cnt, struct ble_hci_le_cis_params_test *cis_params,
uint8_t *rsp_buf, uint8_t rsp_len);
#endif /* MYNEWT_VAL(BLE_ISO_TEST) */
int ble_hs_hci_create_cis(uint8_t cis_cnt, const struct ble_hci_le_create_cis_params *params);
int ble_hs_hci_remove_cig(uint8_t cig_id);
int ble_hs_hci_accept_cis_request(uint16_t cis_handle);
int ble_hs_hci_reject_cis_request(uint16_t cis_handle, uint8_t reason);
int ble_hs_hci_create_big(uint8_t big_handle, uint8_t adv_handle, uint8_t num_bis,
uint32_t sdu_interval, uint16_t max_sdu,
uint16_t max_transport_latency, uint8_t rtn, uint8_t phy,
uint8_t packing, uint8_t framing, uint8_t encryption,
uint8_t broadcast_code[16]);
#if MYNEWT_VAL(BLE_ISO_TEST)
int ble_hs_hci_create_big_test(uint8_t big_handle, uint8_t adv_handle, uint8_t num_bis,
uint32_t sdu_interval, uint16_t iso_interval, uint8_t nse,
uint16_t max_sdu, uint16_t max_pdu, uint8_t phy,
uint8_t packing, uint8_t framing, uint8_t bn, uint8_t irc,
uint8_t pto, uint8_t encryption, uint8_t broadcast_code[16]);
#endif /* MYNEWT_VAL(BLE_ISO_TEST) */
int ble_hs_hci_terminate_big(uint8_t big_handle, uint8_t reason);
int ble_hs_hci_big_create_sync(uint8_t big_handle, uint16_t sync_handle,
uint8_t encryption, uint8_t broadcast_code[16],
uint8_t mse, uint16_t sync_timeout,
uint8_t num_bis, uint8_t *bis_index);
int ble_hs_hci_big_terminate_sync(uint8_t big_handle);
int ble_hs_hci_setup_iso_data_path(uint16_t conn_handle, uint8_t data_path_direction,
uint8_t data_path_id, uint8_t coding_fmt,
uint16_t company_id, uint16_t vs_codec_id,
uint32_t controller_delay, uint8_t codec_cfg_len,
uint8_t *codec_cfg);
int ble_hs_hci_remove_iso_data_path(uint16_t conn_handle, uint8_t data_path_direction);
#if MYNEWT_VAL(BLE_ISO_TEST)
int ble_hs_hci_iso_transmit_test(uint16_t conn_handle, uint8_t payload_type);
int ble_hs_hci_iso_receive_test(uint16_t conn_handle, uint8_t payload_type);
int ble_hs_hci_iso_read_test_counters(uint16_t conn_handle, uint32_t *received_sdu_count,
uint32_t *missed_sdu_count, uint32_t *failed_sdu_count);
int ble_hs_hci_iso_test_end(uint16_t conn_handle, uint32_t *received_sdu_count,
uint32_t *missed_sdu_count, uint32_t *failed_sdu_count);
#endif /* MYNEWT_VAL(BLE_ISO_TEST) */
int ble_hs_hci_read_iso_link_quality(uint16_t conn_handle, uint32_t *tx_unacked_pkts,
uint32_t *tx_flushed_pkts, uint32_t *tx_last_subev_pkts,
uint32_t *retransmitted_pkts, uint32_t *crc_error_pkts,
uint32_t *rx_unreceived_pkts, uint32_t *duplicate_pkts);
#endif /* MYNEWT_VAL(BLE_ISO) */
#ifdef __cplusplus
}
#endif
#endif /* H_BLE_HS_ISO_HCI_ */
+457 -1
View File
@@ -34,6 +34,10 @@
#include "host/ble_hs_pvcy.h"
#include "host/util/util.h"
#if MYNEWT_VAL(BLE_ISO)
#include "host/ble_hs_iso_hci.h"
#endif /* MYNEWT_VAL(BLE_ISO) */
#ifndef min
#define min(a, b) ((a) < (b) ? (a) : (b))
#endif
@@ -256,6 +260,29 @@ struct ble_gap_slave_state {
static bssnz_t struct ble_gap_slave_state ble_gap_slave[BLE_ADV_INSTANCES];
#if MYNEWT_VAL(BLE_ISO)
struct ble_gap_cis_state {
ble_gap_event_fn *cb;
void *cb_arg;
};
static bssnz_t struct ble_gap_cis_state ble_gap_cis;
struct ble_gap_big_brd_state {
ble_gap_event_fn *cb;
void *cb_arg;
};
static bssnz_t struct ble_gap_big_brd_state ble_gap_big_brd;
struct ble_gap_big_snc_state {
ble_gap_event_fn *cb;
void *cb_arg;
};
static bssnz_t struct ble_gap_big_snc_state ble_gap_big_snc;
#endif /* MYNEWT_VAL(BLE_ISO) */
struct ble_gap_update_entry {
SLIST_ENTRY(ble_gap_update_entry) next;
struct ble_gap_upd_params params;
@@ -1934,6 +1961,248 @@ ble_gap_rx_adv_report_sanity_check(const uint8_t *adv_data, uint8_t adv_data_len
}
#endif
#if MYNEWT_VAL(BLE_ISO)
void
ble_gap_rx_cis_disconn(const struct ble_hci_ev_disconn_cmp *ev)
{
struct ble_gap_event event;
memset(&event, 0, sizeof(event));
event.type = BLE_GAP_EVENT_DISCONNECT;
event.disconnect.reason = ev->reason;
event.disconnect.conn.conn_handle = ev->conn_handle;
ble_gap_event_listener_call(&event);
if (ble_gap_cis.cb) {
ble_gap_cis.cb(&event, ble_gap_cis.cb_arg);
}
}
void
ble_gap_rx_cis_estab(const struct ble_hci_ev_le_subev_cis_established *ev)
{
struct ble_gap_event event;
memset(&event, 0, sizeof(event));
event.type = BLE_GAP_EVENT_CIS_ESTAB;
event.cis_estab.status = ev->status;
event.cis_estab.cis_handle = ev->conn_handle;
event.cis_estab.cig_sync_delay = get_le24(ev->cig_sync_delay);
event.cis_estab.cis_sync_delay = get_le24(ev->cis_sync_delay);
event.cis_estab.transport_latency_c_to_p = get_le24(ev->transport_latency_c_to_p);
event.cis_estab.transport_latency_p_to_c = get_le24(ev->transport_latency_p_to_c);
event.cis_estab.phy_c_to_p = ev->phy_c_to_p;
event.cis_estab.phy_p_to_c = ev->phy_p_to_c;
event.cis_estab.nse = ev->nse;
event.cis_estab.bn_c_to_p = ev->bn_c_to_p;
event.cis_estab.bn_p_to_c = ev->bn_p_to_c;
event.cis_estab.ft_c_to_p = ev->ft_c_to_p;
event.cis_estab.ft_p_to_c = ev->ft_p_to_c;
event.cis_estab.max_pdu_c_to_p = ev->max_pdu_c_to_p;
event.cis_estab.max_pdu_p_to_c = ev->max_pdu_p_to_c;
event.cis_estab.iso_interval = ev->iso_interval;
ble_gap_event_listener_call(&event);
if (ble_gap_cis.cb) {
ble_gap_cis.cb(&event, ble_gap_cis.cb_arg);
}
}
void
ble_gap_rx_cis_request(const struct ble_hci_ev_le_subev_cis_request *ev)
{
struct ble_gap_event event;
ble_gap_event_fn *cb;
void *cb_arg;
memset(&event, 0, sizeof(event));
event.type = BLE_GAP_EVENT_CIS_REQUEST;
event.cis_request.conn_handle = ev->acl_conn_handle;
event.cis_request.cis_handle = ev->cis_conn_handle;
event.cis_request.cig_id = ev->cig_id;
event.cis_request.cis_id = ev->cis_id;
ble_gap_event_listener_call(&event);
ble_gap_slave_extract_cb(0, &cb, &cb_arg);
if (cb) {
cb(&event, cb_arg);
}
}
void
ble_gap_rx_create_big_comp(const struct ble_hci_ev_le_subev_create_big_complete *ev)
{
struct ble_gap_event event;
memset(&event, 0, sizeof(event));
event.type = BLE_GAP_EVENT_CREATE_BIG_COMP;
event.create_big_comp.status = ev->status;
event.create_big_comp.big_handle = ev->big_handle;
event.create_big_comp.big_sync_delay = get_le24(ev->big_sync_delay);
event.create_big_comp.transport_latency = get_le24(ev->transport_latency_big);
event.create_big_comp.phy = ev->phy;
event.create_big_comp.nse = ev->nse;
event.create_big_comp.bn = ev->bn;
event.create_big_comp.pto = ev->pto;
event.create_big_comp.irc = ev->irc;
event.create_big_comp.max_pdu = ev->max_pdu;
event.create_big_comp.iso_interval = ev->iso_interval;
event.create_big_comp.bis_cnt = ev->num_bis;
memcpy(event.create_big_comp.bis_handle, ev->conn_handle, ev->num_bis * 2);
ble_gap_event_listener_call(&event);
if (ble_gap_big_brd.cb) {
ble_gap_big_brd.cb(&event, ble_gap_big_brd.cb_arg);
}
}
void
ble_gap_rx_term_big_comp(const struct ble_hci_ev_le_subev_terminate_big_complete *ev)
{
struct ble_gap_event event;
memset(&event, 0, sizeof(event));
event.type = BLE_GAP_EVENT_TERM_BIG_COMP;
event.term_big_comp.big_handle = ev->big_handle;
event.term_big_comp.reason = ev->reason;
ble_gap_event_listener_call(&event);
if (ble_gap_big_brd.cb) {
ble_gap_big_brd.cb(&event, ble_gap_big_brd.cb_arg);
}
}
void
ble_gap_rx_big_sync_estab(const struct ble_hci_ev_le_subev_big_sync_established *ev)
{
struct ble_gap_event event;
memset(&event, 0, sizeof(event));
event.type = BLE_GAP_EVENT_BIG_SYNC_ESTAB;
event.big_sync_estab.status = ev->status;
event.big_sync_estab.big_handle = ev->big_handle;
event.big_sync_estab.transport_latency = get_le24(ev->transport_latency_big);
event.big_sync_estab.nse = ev->nse;
event.big_sync_estab.bn = ev->bn;
event.big_sync_estab.pto = ev->pto;
event.big_sync_estab.irc = ev->irc;
event.big_sync_estab.max_pdu = ev->max_pdu;
event.big_sync_estab.iso_interval = ev->iso_interval;
event.big_sync_estab.bis_cnt = ev->num_bis;
for(size_t i = 0; i < ev->num_bis; i++){
event.big_sync_estab.bis_handle[i] = ev->conn_handle[i];
}
ble_gap_event_listener_call(&event);
if (ble_gap_big_snc.cb) {
ble_gap_big_snc.cb(&event, ble_gap_big_snc.cb_arg);
}
}
void
ble_gap_rx_big_sync_lost(const struct ble_hci_ev_le_subev_big_sync_lost *ev)
{
struct ble_gap_event event;
memset(&event, 0, sizeof(event));
event.type = BLE_GAP_EVENT_BIG_SYNC_LOST;
event.big_sync_lost.big_handle = ev->big_handle;
event.big_sync_lost.reason = ev->reason;
ble_gap_event_listener_call(&event);
if (ble_gap_big_snc.cb) {
ble_gap_big_snc.cb(&event, ble_gap_big_snc.cb_arg);
}
}
void
ble_gap_rx_biginfo_adv_rpt(const struct ble_hci_ev_le_subev_biginfo_adv_report *ev)
{
struct ble_gap_master_state state;
struct ble_gap_event event;
memset(&event, 0, sizeof(event));
event.type = BLE_GAP_EVENT_BIGINFO_ADV_RPT;
event.biginfo_report.sync_handle = ev->sync_handle;
event.biginfo_report.bis_cnt = ev->bis_cnt;
event.biginfo_report.nse = ev->nse;
event.biginfo_report.iso_interval = ev->iso_interval;
event.biginfo_report.bn = ev->bn;
event.biginfo_report.pto = ev->pto;
event.biginfo_report.irc = ev->irc;
event.biginfo_report.max_pdu = ev->max_pdu;
event.biginfo_report.sdu_interval = get_le24(ev->sdu_interval);
event.biginfo_report.max_sdu = ev->max_sdu;
event.biginfo_report.phy = ev->phy;
event.biginfo_report.framing = ev->framing;
event.biginfo_report.encryption = ev->encryption;
ble_gap_master_extract_state(&state, 0);
if (ble_gap_has_client(&state)) {
state.cb(&event, state.cb_arg);
}
ble_gap_event_listener_call(&event);
}
#if MYNEWT_VAL(BLE_ISO_CIS_ESTAB_V2)
void
ble_gap_rx_cis_estab_v2(const struct ble_hci_ev_le_subev_cis_established_v2 *ev)
{
struct ble_gap_event event;
memset(&event, 0, sizeof(event));
event.type = BLE_GAP_EVENT_CIS_ESTAB_V2;
event.cis_estab_v2.status = ev->status;
event.cis_estab_v2.cis_handle = ev->conn_handle;
event.cis_estab_v2.cig_sync_delay = get_le24(ev->cig_sync_delay);
event.cis_estab_v2.cis_sync_delay = get_le24(ev->cis_sync_delay);
event.cis_estab_v2.transport_latency_c_to_p = get_le24(ev->transport_latency_c_to_p);
event.cis_estab_v2.transport_latency_p_to_c = get_le24(ev->transport_latency_p_to_c);
event.cis_estab_v2.phy_c_to_p = ev->phy_c_to_p;
event.cis_estab_v2.phy_p_to_c = ev->phy_p_to_c;
event.cis_estab_v2.nse = ev->nse;
event.cis_estab_v2.bn_c_to_p = ev->bn_c_to_p;
event.cis_estab_v2.bn_p_to_c = ev->bn_p_to_c;
event.cis_estab_v2.ft_c_to_p = ev->ft_c_to_p;
event.cis_estab_v2.ft_p_to_c = ev->ft_p_to_c;
event.cis_estab_v2.max_pdu_c_to_p = ev->max_pdu_c_to_p;
event.cis_estab_v2.max_pdu_p_to_c = ev->max_pdu_p_to_c;
event.cis_estab_v2.iso_interval = ev->iso_interval;
event.cis_estab_v2.sub_interval = get_le24(ev->sub_interval);
event.cis_estab_v2.max_sdu_c_to_p = ev->max_sdu_c_to_p;
event.cis_estab_v2.max_sdu_p_to_c = ev->max_sdu_p_to_c;
event.cis_estab_v2.sdu_interval_c_to_p = get_le24(ev->sdu_interval_c_to_p);
event.cis_estab_v2.sdu_interval_p_to_c = get_le24(ev->sdu_interval_p_to_c);
event.cis_estab_v2.framing = ev->framing;
ble_gap_event_listener_call(&event);
if (ble_gap_cis.cb) {
ble_gap_cis.cb(&event, ble_gap_cis.cb_arg);
}
}
#endif /* MYNEWT_VAL(BLE_ISO_CIS_ESTAB_V2) */
#endif /* MYNEWT_VAL(BLE_ISO) */
void
ble_gap_rx_adv_report(struct ble_gap_disc_desc *desc)
{
@@ -2433,7 +2702,7 @@ ble_gap_rx_periodic_adv_sync_transfer(const struct ble_hci_ev_le_subev_periodic_
}
#endif
#if MYNEWT_VAL(BLE_PERIODIC_ADV_SYNC_BIGINFO_REPORTS)
#if MYNEWT_VAL(BLE_PERIODIC_ADV_SYNC_BIGINFO_REPORTS) && !MYNEWT_VAL(BLE_ISO)
void
ble_gap_rx_biginfo_adv_rpt(const struct ble_hci_ev_le_subev_biginfo_adv_report *ev)
{
@@ -9083,6 +9352,187 @@ ble_gap_event_listener_call(struct ble_gap_event *event)
return 0;
}
#if MYNEWT_VAL(BLE_ISO)
int
ble_gap_create_cis(uint8_t cis_cnt, const struct ble_hci_le_create_cis_params *params,
ble_gap_event_fn *cb, void *cb_arg)
{
int rc;
ble_hs_lock();
rc = ble_hs_hci_create_cis(cis_cnt, params);
if (!rc) {
ble_gap_cis.cb = cb;
ble_gap_cis.cb_arg = cb_arg;
}
ble_hs_unlock();
return rc;
}
int
ble_gap_accept_cis_request(uint16_t cis_handle, ble_gap_event_fn *cb, void *cb_arg)
{
int rc;
ble_hs_lock();
rc = ble_hs_hci_accept_cis_request(cis_handle);
if (!rc) {
ble_gap_cis.cb = cb;
ble_gap_cis.cb_arg = cb_arg;
}
ble_hs_unlock();
return rc;
}
int
ble_gap_reject_cis_request(uint16_t cis_handle, uint8_t reason)
{
int rc;
ble_hs_lock();
rc = ble_hs_hci_reject_cis_request(cis_handle, reason);
ble_hs_unlock();
return rc;
}
int
ble_gap_iso_disconnect(uint16_t cis_handle, uint8_t reason)
{
struct ble_hci_lc_disconnect_cp cmd;
int rc;
ble_hs_lock();
cmd.conn_handle = cis_handle;
cmd.reason = reason;
rc = ble_hs_hci_cmd_tx(BLE_HCI_OP(BLE_HCI_OGF_LINK_CTRL,
BLE_HCI_OCF_DISCONNECT_CMD),
&cmd, sizeof(cmd), NULL, 0);
ble_hs_unlock();
return rc;
}
int
ble_gap_create_big(uint8_t big_handle, uint8_t adv_handle, uint8_t num_bis,
uint32_t sdu_interval, uint16_t max_sdu, uint16_t max_transport_latency,
uint8_t rtn, uint8_t phy, uint8_t packing, uint8_t framing,
uint8_t encryption, uint8_t broadcast_code[16],
ble_gap_event_fn *cb, void *cb_arg)
{
int rc;
ble_hs_lock();
rc = ble_hs_hci_create_big(big_handle, adv_handle, num_bis, sdu_interval,
max_sdu, max_transport_latency, rtn, phy,
packing, framing, encryption, broadcast_code);
if (!rc) {
ble_gap_big_brd.cb = cb;
ble_gap_big_brd.cb_arg = cb_arg;
}
ble_hs_unlock();
return rc;
}
#if MYNEWT_VAL(BLE_ISO_TEST)
int
ble_gap_create_big_test(uint8_t big_handle, uint8_t adv_handle, uint8_t num_bis,
uint32_t sdu_interval, uint16_t iso_interval, uint8_t nse,
uint16_t max_sdu, uint16_t max_pdu, uint8_t phy,
uint8_t packing, uint8_t framing, uint8_t bn, uint8_t irc,
uint8_t pto, uint8_t encryption, uint8_t broadcast_code[16],
ble_gap_event_fn *cb, void *cb_arg)
{
int rc;
ble_hs_lock();
rc = ble_hs_hci_create_big_test(big_handle, adv_handle, num_bis, sdu_interval,
iso_interval, nse, max_sdu, max_pdu, phy,
packing, framing, bn, irc, pto, encryption,
broadcast_code);
if (!rc) {
ble_gap_big_brd.cb = cb;
ble_gap_big_brd.cb_arg = cb_arg;
}
ble_hs_unlock();
return rc;
}
#endif /* MYNEWT_VAL(BLE_ISO_TEST) */
int
ble_gap_terminate_big(uint8_t big_handle, uint8_t reason)
{
int rc;
ble_hs_lock();
rc = ble_hs_hci_terminate_big(big_handle, reason);
ble_hs_unlock();
return rc;
}
int
ble_gap_big_create_sync(uint8_t big_handle, uint16_t sync_handle,
uint8_t encryption, uint8_t broadcast_code[16],
uint8_t mse, uint16_t sync_timeout,
uint8_t num_bis, uint8_t *bis_index,
ble_gap_event_fn *cb, void *cb_arg)
{
int rc;
ble_hs_lock();
rc = ble_hs_hci_big_create_sync(big_handle, sync_handle, encryption,
broadcast_code, mse, sync_timeout,
num_bis, bis_index);
if (!rc) {
ble_gap_big_snc.cb = cb;
ble_gap_big_snc.cb_arg = cb_arg;
}
ble_hs_unlock();
return rc;
}
int
ble_gap_big_terminate_sync(uint8_t big_handle)
{
int rc;
ble_hs_lock();
rc = ble_hs_hci_big_terminate_sync(big_handle);
if (!rc) {
ble_gap_big_snc.cb = NULL;
ble_gap_big_snc.cb_arg = NULL;
}
ble_hs_unlock();
return rc;
}
#endif /* MYNEWT_VAL(BLE_ISO) */
/*****************************************************************************
* $init *
*****************************************************************************/
@@ -9103,6 +9553,12 @@ ble_gap_init(void)
memset(&ble_gap_sync, 0, sizeof(ble_gap_sync));
#endif
#if MYNEWT_VAL(BLE_ISO)
memset(&ble_gap_cis, 0, sizeof(ble_gap_cis));
memset(&ble_gap_big_brd, 0, sizeof(ble_gap_big_brd));
memset(&ble_gap_big_snc, 0, sizeof(ble_gap_big_snc));
#endif /* MYNEWT_VAL(BLE_ISO) */
rc = ble_npl_mutex_init(&preempt_done_mutex);
if (rc) {
+15 -1
View File
@@ -88,7 +88,7 @@ void ble_gap_rx_periodic_adv_rpt(const struct ble_hci_ev_le_subev_periodic_adv_r
void ble_gap_rx_periodic_adv_sync_lost(const struct ble_hci_ev_le_subev_periodic_adv_sync_lost *ev);
void ble_gap_rx_periodic_adv_sync_transfer(const struct ble_hci_ev_le_subev_periodic_adv_sync_transfer *ev);
#endif
#if MYNEWT_VAL(BLE_PERIODIC_ADV_SYNC_BIGINFO_REPORTS)
#if MYNEWT_VAL(BLE_PERIODIC_ADV_SYNC_BIGINFO_REPORTS) && !MYNEWT_VAL(BLE_ISO)
void ble_gap_rx_biginfo_adv_rpt(const struct ble_hci_ev_le_subev_biginfo_adv_report *ev);
#endif
void ble_gap_rx_scan_req_rcvd(const struct ble_hci_ev_le_subev_scan_req_rcvd *ev);
@@ -110,6 +110,20 @@ void ble_gap_rx_conn_iq_report(const struct ble_hci_ev_le_subev_conn_iq_rpt *ev)
void ble_gap_rx_cte_req_failed(const struct ble_hci_ev_le_subev_cte_req_failed *ev);
#endif
#if MYNEWT_VAL(BLE_ISO)
void ble_gap_rx_cis_disconn(const struct ble_hci_ev_disconn_cmp *ev);
void ble_gap_rx_cis_estab(const struct ble_hci_ev_le_subev_cis_established *ev);
void ble_gap_rx_cis_request(const struct ble_hci_ev_le_subev_cis_request *ev);
void ble_gap_rx_create_big_comp(const struct ble_hci_ev_le_subev_create_big_complete *ev);
void ble_gap_rx_term_big_comp(const struct ble_hci_ev_le_subev_terminate_big_complete *ev);
void ble_gap_rx_big_sync_estab(const struct ble_hci_ev_le_subev_big_sync_established *ev);
void ble_gap_rx_big_sync_lost(const struct ble_hci_ev_le_subev_big_sync_lost *ev);
void ble_gap_rx_biginfo_adv_rpt(const struct ble_hci_ev_le_subev_biginfo_adv_report *ev);
#if MYNEWT_VAL(BLE_ISO_CIS_ESTAB_V2)
void ble_gap_rx_cis_estab_v2(const struct ble_hci_ev_le_subev_cis_established_v2 *ev);
#endif /* MYNEWT_VAL(BLE_ISO_CIS_ESTAB_V2) */
#endif /* MYNEWT_VAL(BLE_ISO) */
struct ble_gap_conn_complete
{
uint8_t status;
+12
View File
@@ -36,6 +36,10 @@
#include "hci_log/bt_hci_log.h"
#endif // (BT_HCI_LOG_INCLUDED == TRUE)
#if MYNEWT_VAL(BLE_ISO)
#include "host/ble_hs_iso.h"
#endif /* MYNEWT_VAL(BLE_ISO) */
#define BLE_HS_HCI_EVT_COUNT (MYNEWT_VAL(BLE_TRANSPORT_EVT_COUNT) + \
MYNEWT_VAL(BLE_TRANSPORT_EVT_DISCARDABLE_COUNT))
@@ -901,6 +905,14 @@ ble_transport_to_hs_iso_impl(struct os_mbuf *om)
return 0;
}
#if MYNEWT_VAL(BLE_ISO)
int
ble_transport_to_hs_iso_impl_v2(const uint8_t *data, uint16_t len)
{
return ble_hs_rx_iso_data(data, len, NULL);
}
#endif /* MYNEWT_VAL(BLE_ISO) */
void
ble_transport_hs_init(void)
{
+230 -3
View File
@@ -26,6 +26,9 @@
#include "ble_hs_priv.h"
#include "ble_hs_resolv_priv.h"
#include "esp_nimble_mem.h"
#if MYNEWT_VAL(BLE_ISO)
#include "host/ble_hs_iso.h"
#endif /* MYNEWT_VAL(BLE_ISO) */
#if MYNEWT_VAL(BLE_ENABLE_CONN_REATTEMPT)
struct ble_gap_reattempt_ctxt {
@@ -89,7 +92,7 @@ static ble_hs_hci_evt_le_fn ble_hs_hci_evt_le_periodic_adv_rpt;
static ble_hs_hci_evt_le_fn ble_hs_hci_evt_le_periodic_adv_sync_lost;
static ble_hs_hci_evt_le_fn ble_hs_hci_evt_le_scan_req_rcvd;
static ble_hs_hci_evt_le_fn ble_hs_hci_evt_le_periodic_adv_sync_transfer;
#if MYNEWT_VAL(BLE_PERIODIC_ADV_SYNC_BIGINFO_REPORTS)
#if MYNEWT_VAL(BLE_PERIODIC_ADV_SYNC_BIGINFO_REPORTS) && !MYNEWT_VAL(BLE_ISO)
static ble_hs_hci_evt_le_fn ble_hs_hci_evt_le_biginfo_adv_report;
#endif
#if MYNEWT_VAL(BLE_POWER_CONTROL)
@@ -109,6 +112,19 @@ static ble_hs_hci_evt_le_fn ble_hs_hci_evt_le_periodic_adv_subev_data_req;
static ble_hs_hci_evt_le_fn ble_hs_hci_evt_le_periodic_adv_subev_resp_rep;
#endif
#if MYNEWT_VAL(BLE_ISO)
static ble_hs_hci_evt_le_fn ble_hs_hci_evt_le_cis_estab;
static ble_hs_hci_evt_le_fn ble_hs_hci_evt_le_cis_request;
static ble_hs_hci_evt_le_fn ble_hs_hci_evt_le_create_big_comp;
static ble_hs_hci_evt_le_fn ble_hs_hci_evt_le_term_big_comp;
static ble_hs_hci_evt_le_fn ble_hs_hci_evt_le_big_sync_estab;
static ble_hs_hci_evt_le_fn ble_hs_hci_evt_le_big_sync_lost;
static ble_hs_hci_evt_le_fn ble_hs_hci_evt_le_biginfo_adv_rpt;
#if MYNEWT_VAL(BLE_ISO_CIS_ESTAB_V2)
static ble_hs_hci_evt_le_fn ble_hs_hci_evt_le_cis_estab_v2;
#endif /* MYNEWT_VAL(BLE_ISO_CIS_ESTAB_V2) */
#endif /* MYNEWT_VAL(BLE_ISO) */
/* Statistics */
struct host_hci_stats {
uint32_t events_rxd;
@@ -173,7 +189,7 @@ static ble_hs_hci_evt_le_fn * const ble_hs_hci_evt_le_dispatch[] = {
[BLE_HCI_LE_SUBEV_ADV_SET_TERMINATED] = ble_hs_hci_evt_le_adv_set_terminated,
[BLE_HCI_LE_SUBEV_SCAN_REQ_RCVD] = ble_hs_hci_evt_le_scan_req_rcvd,
[BLE_HCI_LE_SUBEV_PERIODIC_ADV_SYNC_TRANSFER] = ble_hs_hci_evt_le_periodic_adv_sync_transfer,
#if MYNEWT_VAL(BLE_PERIODIC_ADV_SYNC_BIGINFO_REPORTS)
#if MYNEWT_VAL(BLE_PERIODIC_ADV_SYNC_BIGINFO_REPORTS) && !MYNEWT_VAL(BLE_ISO)
[BLE_HCI_LE_SUBEV_BIGINFO_ADV_REPORT] = ble_hs_hci_evt_le_biginfo_adv_report,
#endif
#if MYNEWT_VAL(BLE_POWER_CONTROL)
@@ -196,6 +212,18 @@ static ble_hs_hci_evt_le_fn * const ble_hs_hci_evt_le_dispatch[] = {
[BLE_HCI_LE_SUBEV_PERIODIC_ADV_RESP_REPORT] = ble_hs_hci_evt_le_periodic_adv_subev_resp_rep,
[BLE_HCI_LE_SUBEV_ENH_CONN_COMPLETE_V2] = ble_hs_hci_evt_le_enh_conn_complete,
#endif
#if MYNEWT_VAL(BLE_ISO)
[BLE_HCI_LE_SUBEV_CIS_ESTABLISHED] = ble_hs_hci_evt_le_cis_estab,
[BLE_HCI_LE_SUBEV_CIS_REQUEST] = ble_hs_hci_evt_le_cis_request,
[BLE_HCI_LE_SUBEV_CREATE_BIG_COMPLETE] = ble_hs_hci_evt_le_create_big_comp,
[BLE_HCI_LE_SUBEV_TERMINATE_BIG_COMPLETE] = ble_hs_hci_evt_le_term_big_comp,
[BLE_HCI_LE_SUBEV_BIG_SYNC_ESTABLISHED] = ble_hs_hci_evt_le_big_sync_estab,
[BLE_HCI_LE_SUBEV_BIG_SYNC_LOST] = ble_hs_hci_evt_le_big_sync_lost,
[BLE_HCI_LE_SUBEV_BIGINFO_ADV_REPORT] = ble_hs_hci_evt_le_biginfo_adv_rpt,
#if MYNEWT_VAL(BLE_ISO_CIS_ESTAB_V2)
[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) */
};
#define BLE_HS_HCI_EVT_LE_DISPATCH_SZ \
@@ -228,6 +256,10 @@ ble_hs_hci_evt_le_dispatch_find(uint8_t event_code)
return ble_hs_hci_evt_le_dispatch[event_code];
}
#if MYNEWT_VAL(BLE_ISO)
static int ble_hs_hci_evt_le_cis_disconn(const struct ble_hci_ev_disconn_cmp *ev);
#endif /* MYNEWT_VAL(BLE_ISO) */
#if NIMBLE_BLE_CONNECT
static int
ble_hs_hci_evt_disconn_complete(uint8_t event_code, const void *data,
@@ -317,7 +349,15 @@ ble_hs_hci_evt_disconn_complete(uint8_t event_code, const void *data,
}
#endif
#if MYNEWT_VAL(BLE_ISO)
if (conn) {
ble_gap_rx_disconn_complete(ev);
} else {
ble_hs_hci_evt_le_cis_disconn(ev);
}
#else /* MYNEWT_VAL(BLE_ISO) */
ble_gap_rx_disconn_complete(ev);
#endif /* MYNEWT_VAL(BLE_ISO) */
/* The connection termination may have freed up some capacity in the
* controller for additional ACL data packets. Wake up any stalled
@@ -405,6 +445,10 @@ ble_hs_hci_evt_num_completed_pkts(uint8_t event_code, const void *data,
}
ble_hs_hci_add_avail_pkts(num_pkts);
#if MYNEWT_VAL(BLE_ISO_STD_FLOW_CTRL)
} else {
ble_hs_hci_add_iso_avail_pkts(le16toh(ev->completed[i].handle), num_pkts);
#endif /* MYNEWT_VAL(BLE_ISO_STD_FLOW_CTRL) */
}
ble_hs_unlock();
}
@@ -791,6 +835,189 @@ ble_hs_hci_decode_legacy_type(uint16_t evt_type)
}
}
#if MYNEWT_VAL(BLE_ISO)
typedef void (*ble_hs_hci_evt_iso_fn)(uint8_t event, const void *data,
unsigned int len, bool le_meta);
static ble_hs_hci_evt_iso_fn iso_evt_cb;
int
ble_hs_iso_evt_rx_cb_set(void *cb)
{
if (cb == NULL) {
return -BLE_HS_EINVAL;
}
if (iso_evt_cb) {
return -BLE_HS_EALREADY;
}
iso_evt_cb = cb;
return 0;
}
static int
ble_hs_hci_evt_le_cis_disconn(const struct ble_hci_ev_disconn_cmp *ev)
{
if (iso_evt_cb) {
iso_evt_cb(BLE_HCI_EVCODE_DISCONN_CMP, (const void *)ev, sizeof(*ev), false);
} else {
ble_gap_rx_cis_disconn(ev);
}
return 0;
}
static int
ble_hs_hci_evt_le_cis_estab(uint8_t subevent, const void *data, unsigned int len)
{
const struct ble_hci_ev_le_subev_cis_established *ev = data;
if (len != sizeof(*ev)) {
return BLE_HS_ECONTROLLER;
}
if (iso_evt_cb) {
iso_evt_cb(BLE_HCI_LE_SUBEV_CIS_ESTABLISHED, data, len, true);
} else {
ble_gap_rx_cis_estab(ev);
}
return 0;
}
static int
ble_hs_hci_evt_le_cis_request(uint8_t subevent, const void *data, unsigned int len)
{
const struct ble_hci_ev_le_subev_cis_request *ev = data;
if (len != sizeof(*ev)) {
return BLE_HS_ECONTROLLER;
}
if (iso_evt_cb) {
iso_evt_cb(BLE_HCI_LE_SUBEV_CIS_REQUEST, data, len, true);
} else {
ble_gap_rx_cis_request(ev);
}
return 0;
}
static int
ble_hs_hci_evt_le_create_big_comp(uint8_t subevent, const void *data, unsigned int len)
{
const struct ble_hci_ev_le_subev_create_big_complete *ev = data;
if ((len != sizeof(*ev) + ev->num_bis * 2) ||
(ev->num_bis > MYNEWT_VAL(BLE_ISO_BIS_PER_BIG))) {
return BLE_HS_ECONTROLLER;
}
if (iso_evt_cb) {
iso_evt_cb(BLE_HCI_LE_SUBEV_CREATE_BIG_COMPLETE, data, len, true);
} else {
ble_gap_rx_create_big_comp(ev);
}
return 0;
}
static int
ble_hs_hci_evt_le_term_big_comp(uint8_t subevent, const void *data, unsigned int len)
{
const struct ble_hci_ev_le_subev_terminate_big_complete *ev = data;
if (len != sizeof(*ev)) {
return BLE_HS_ECONTROLLER;
}
if (iso_evt_cb) {
iso_evt_cb(BLE_HCI_LE_SUBEV_TERMINATE_BIG_COMPLETE, data, len, true);
} else {
ble_gap_rx_term_big_comp(ev);
}
return 0;
}
static int
ble_hs_hci_evt_le_big_sync_estab(uint8_t subevent, const void *data, unsigned int len)
{
const struct ble_hci_ev_le_subev_big_sync_established *ev = data;
if ((len != sizeof(*ev) + ev->num_bis * 2) ||
(ev->num_bis > MYNEWT_VAL(BLE_ISO_BIS_PER_BIG))) {
return BLE_HS_ECONTROLLER;
}
if (iso_evt_cb) {
iso_evt_cb(BLE_HCI_LE_SUBEV_BIG_SYNC_ESTABLISHED, data, len, true);
} else {
ble_gap_rx_big_sync_estab(ev);
}
return 0;
}
static int
ble_hs_hci_evt_le_big_sync_lost(uint8_t subevent, const void *data, unsigned int len)
{
const struct ble_hci_ev_le_subev_big_sync_lost *ev = data;
if (len != sizeof(*ev)) {
return BLE_HS_ECONTROLLER;
}
if (iso_evt_cb) {
iso_evt_cb(BLE_HCI_LE_SUBEV_BIG_SYNC_LOST, data, len, true);
} else {
ble_gap_rx_big_sync_lost(ev);
}
return 0;
}
static int
ble_hs_hci_evt_le_biginfo_adv_rpt(uint8_t subevent, const void *data, unsigned int len)
{
const struct ble_hci_ev_le_subev_biginfo_adv_report *ev = data;
if (len != sizeof(*ev)) {
return BLE_HS_ECONTROLLER;
}
if (iso_evt_cb) {
iso_evt_cb(BLE_HCI_LE_SUBEV_BIGINFO_ADV_REPORT, data, len, true);
} else {
ble_gap_rx_biginfo_adv_rpt(ev);
}
return 0;
}
#if MYNEWT_VAL(BLE_ISO_CIS_ESTAB_V2)
static int
ble_hs_hci_evt_le_cis_estab_v2(uint8_t subevent, const void *data, unsigned int len)
{
const struct ble_hci_ev_le_subev_cis_established_v2 *ev = data;
if (len != sizeof(*ev)) {
return BLE_HS_ECONTROLLER;
}
if (iso_evt_cb) {
iso_evt_cb(BLE_HCI_LE_SUBEV_CIS_ESTABLISHED_V2, data, len, true);
} else {
ble_gap_rx_cis_estab_v2(ev);
}
return 0;
}
#endif /* MYNEWT_VAL(BLE_ISO_CIS_ESTAB_V2) */
#endif /* MYNEWT_VAL(BLE_ISO) */
static int
ble_hs_hci_evt_le_ext_adv_rpt_first_pass(const void *data, unsigned int len)
{
@@ -998,7 +1225,7 @@ ble_hs_hci_evt_le_periodic_adv_sync_transfer(uint8_t subevent, const void *data,
return 0;
}
#if MYNEWT_VAL(BLE_PERIODIC_ADV_SYNC_BIGINFO_REPORTS)
#if MYNEWT_VAL(BLE_PERIODIC_ADV_SYNC_BIGINFO_REPORTS) && !MYNEWT_VAL(BLE_ISO)
static int
ble_hs_hci_evt_le_biginfo_adv_report(uint8_t subevent, const void *data,
unsigned int len)
+17
View File
@@ -360,3 +360,20 @@ ble_hs_hci_dtm_enh_rx_start(const uint8_t rx_chan, const uint8_t index,
return ble_hs_hci_cmd_tx_no_rsp(opcode, &cmd, sizeof(cmd));
}
int
ble_hs_hci_set_host_feature(uint8_t bit_num, uint8_t bit_val)
{
struct ble_hci_le_set_host_feature_cp cmd;
if (bit_val > 0x01) {
return BLE_HS_EINVAL;
}
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);
}
+252
View File
@@ -0,0 +1,252 @@
/*
* SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Unlicense OR CC0-1.0
*/
#include <string.h>
#include <assert.h>
#include "os/os.h"
#include "mem/mem.h"
#include "nimble/hci_common.h"
#include "host/ble_hs_hci.h"
#include "ble_hs_priv.h"
#include "bt_osi_mem.h"
#include "host/ble_hs_iso.h"
#if MYNEWT_VAL(BLE_ISO)
_Static_assert((MYNEWT_VAL(BLE_ISO_STD_FLOW_CTRL) &&
MYNEWT_VAL(BLE_ISO_NON_STD_FLOW_CTRL)) == 0,
"Only one of standard or non-standard can be enabled");
#define BLE_HCI_ISO_PB_FIRST_FRAG 0
#define BLE_HCI_ISO_PB_CONT_FRAG 1
#define BLE_HCI_ISO_PB_COMP_SDU 2
#define BLE_HCI_ISO_PB_LAST_FRAG 3
#define BLE_HCI_ISO_DATA_HDR_SZ 4
#define BLE_HCI_ISO_DATA_LOAD_TS_SZ 4
#define BLE_HCI_ISO_DATA_LOAD_HDR_SZ 4
#ifndef min
#define min(a, b) ((a) < (b) ? (a) : (b))
#endif
static uint16_t ble_hs_iso_buf_sz;
static uint8_t ble_hs_iso_max_pkts;
#if MYNEWT_VAL(BLE_ISO_STD_FLOW_CTRL)
/* Number of available ISO transmit buffers on the controller.
* It must only be accessed while the host mutex is locked.
*/
static uint16_t ble_hs_iso_avail_pkts;
#endif /* MYNEWT_VAL(BLE_ISO_STD_FLOW_CTRL) */
int
ble_hs_hci_set_iso_buf_sz(uint16_t pktlen, uint16_t max_pkts)
{
if (pktlen == 0 || max_pkts == 0) {
return BLE_HS_EINVAL;
}
ble_hs_iso_buf_sz = pktlen;
ble_hs_iso_max_pkts = max_pkts;
#if MYNEWT_VAL(BLE_ISO_STD_FLOW_CTRL)
ble_hs_iso_avail_pkts = max_pkts;
#endif /* MYNEWT_VAL(BLE_ISO_STD_FLOW_CTRL) */
BLE_HS_LOG(INFO, "ISO Flow Control:");
BLE_HS_LOG(INFO, " Length: %u", pktlen);
BLE_HS_LOG(INFO, " Count: %u", max_pkts);
BLE_HS_LOG(INFO, " Status: ");
if (MYNEWT_VAL(BLE_ISO_STD_FLOW_CTRL)) {
BLE_HS_LOG(INFO, "%s", "Standard");
} else if (MYNEWT_VAL(BLE_ISO_NON_STD_FLOW_CTRL)) {
BLE_HS_LOG(INFO, "%s", "Non-standard");
} else {
BLE_HS_LOG(INFO, "%s", "Not support");
}
return 0;
}
#if MYNEWT_VAL(BLE_ISO_STD_FLOW_CTRL)
void
ble_hs_hci_add_iso_avail_pkts(uint16_t conn_handle, uint16_t delta)
{
BLE_HS_DBG_ASSERT(ble_hs_locked_by_cur_task());
if (ble_hs_iso_avail_pkts + delta > ble_hs_iso_max_pkts) {
BLE_HS_LOG(ERROR, "ISO_HS_RESET %u %u %u", ble_hs_iso_avail_pkts, delta, ble_hs_iso_max_pkts);
ble_hs_sched_reset(BLE_HS_ECONTROLLER);
} else {
ble_hs_iso_avail_pkts += delta;
}
}
#endif /* MYNEWT_VAL(BLE_ISO_STD_FLOW_CTRL) */
#if MYNEWT_VAL(BLE_ISO_STD_FLOW_CTRL)
static uint8_t
ble_hs_hci_iso_buf_needed(uint16_t sdu_len, bool ts_flag)
{
uint16_t sdu_offset;
uint16_t dl_len;
uint8_t dlh_len;
uint8_t count;
dlh_len = (ts_flag ? BLE_HCI_ISO_DATA_LOAD_TS_SZ : 0) + BLE_HCI_ISO_DATA_LOAD_HDR_SZ;
sdu_offset = 0;
count = 1; /* 1 extra since framed pdu may be used */
while (1) {
dl_len = min(dlh_len + sdu_len - sdu_offset, ble_hs_iso_buf_sz);
count += 1;
sdu_offset += dl_len - dlh_len;
assert(sdu_offset <= sdu_len);
if (sdu_offset == sdu_len) {
break;
}
/* No data load header for continuation/last segment */
dlh_len = 0;
}
return count;
}
#endif /* MYNEWT_VAL(BLE_ISO_STD_FLOW_CTRL) */
static void
ble_hs_hci_iso_hdr_append(uint16_t conn_handle, uint16_t sdu_len,
bool ts_flag, uint32_t time_stamp,
uint16_t pkt_seq_num, uint8_t *frag,
uint8_t pb_flag, uint16_t dl_len)
{
uint32_t pkt_hdr;
uint32_t dl_hdr;
pkt_hdr = ((pb_flag << 12) | conn_handle);
if (pb_flag == BLE_HCI_ISO_PB_FIRST_FRAG ||
pb_flag == BLE_HCI_ISO_PB_COMP_SDU) {
pkt_hdr |= (ts_flag << 14);
}
pkt_hdr |= (dl_len << 16);
memcpy(frag, &pkt_hdr, BLE_HCI_ISO_DATA_HDR_SZ);
/* No data load header for continuation/last segment */
if (pb_flag == BLE_HCI_ISO_PB_CONT_FRAG ||
pb_flag == BLE_HCI_ISO_PB_LAST_FRAG) {
return;
}
if (ts_flag) {
memcpy(frag + BLE_HCI_ISO_DATA_HDR_SZ, &time_stamp, BLE_HCI_ISO_DATA_LOAD_TS_SZ);
}
dl_hdr = (sdu_len << 16) | pkt_seq_num;
memcpy(frag + BLE_HCI_ISO_DATA_HDR_SZ + (ts_flag ? BLE_HCI_ISO_DATA_LOAD_TS_SZ : 0),
&dl_hdr, BLE_HCI_ISO_DATA_LOAD_HDR_SZ);
}
static int
ble_hs_hci_iso_tx_now(uint16_t conn_handle, const uint8_t *sdu, uint16_t sdu_len,
bool ts_flag, uint32_t time_stamp, uint16_t pkt_seq_num)
{
uint8_t dlh_len;
uint8_t *frag;
int rc;
#if MYNEWT_VAL(BLE_ISO_STD_FLOW_CTRL)
/* Get the Controller ISO buffer needed for the SDU */
uint8_t count = ble_hs_hci_iso_buf_needed(sdu_len, ts_flag);
/* Make sure the Controller ISO buffer can accommodate the SDU completely */
if (count > ble_hs_iso_avail_pkts) {
BLE_HS_LOG(WARN, "ISO flow control(%u/%u)!", count, ble_hs_iso_avail_pkts);
return BLE_HS_EAGAIN;
}
#elif MYNEWT_VAL(BLE_ISO_NON_STD_FLOW_CTRL)
extern uint16_t ble_ll_iso_free_buf_num_get(uint16_t conn_handle);
if (ble_ll_iso_free_buf_num_get(conn_handle) == 0) {
BLE_HS_LOG(WARN, "ISO flow control!");
return BLE_HS_EAGAIN;
}
#endif
dlh_len = (ts_flag ? BLE_HCI_ISO_DATA_LOAD_TS_SZ : 0) + BLE_HCI_ISO_DATA_LOAD_HDR_SZ;
frag = malloc(BLE_HCI_ISO_DATA_HDR_SZ + dlh_len + sdu_len);
if (frag == NULL) {
return BLE_HS_ENOMEM;
}
ble_hs_hci_iso_hdr_append(conn_handle, sdu_len, ts_flag, time_stamp, pkt_seq_num,
frag, BLE_HCI_ISO_PB_COMP_SDU, dlh_len + sdu_len);
memcpy(frag + BLE_HCI_ISO_DATA_HDR_SZ + dlh_len, sdu, sdu_len);
extern int ble_hci_trans_hs_iso_tx(const uint8_t *data, uint16_t length, void *arg);
rc = ble_hci_trans_hs_iso_tx(frag, BLE_HCI_ISO_DATA_HDR_SZ + dlh_len + sdu_len, NULL);
if (rc) {
return BLE_HS_EDONE;
}
#if MYNEWT_VAL(BLE_ISO_STD_FLOW_CTRL)
/* If an ISO SDU is fragmented into fragments, flow control is not supported.
*
* Currently even if an SDU is larger than the ISO buffer size, fragmentation
* will not happen here, the SDU will be posted to Controller completely.
*/
ble_hs_iso_avail_pkts -= 1;
#endif /* MYNEWT_VAL(BLE_ISO_STD_FLOW_CTRL) */
return 0;
}
int
ble_hs_hci_iso_tx(uint16_t conn_handle, const uint8_t *sdu, uint16_t sdu_len,
bool ts_flag, uint32_t time_stamp, uint16_t pkt_seq_num)
{
BLE_HS_DBG_ASSERT(ble_hs_locked_by_cur_task());
return ble_hs_hci_iso_tx_now(conn_handle, sdu, sdu_len, ts_flag, time_stamp, pkt_seq_num);
}
static ble_hs_iso_pkt_rx_fn ble_hs_iso_pkt_rx_cb;
int
ble_hs_iso_pkt_rx_cb_set(void *cb)
{
if (cb == NULL) {
return -BLE_HS_EINVAL;
}
if (ble_hs_iso_pkt_rx_cb) {
return -BLE_HS_EALREADY;
}
ble_hs_iso_pkt_rx_cb = cb;
return 0;
}
int
ble_hs_rx_iso_data(const uint8_t *data, uint16_t len, void *arg)
{
if (ble_hs_iso_pkt_rx_cb) {
ble_hs_iso_pkt_rx_cb(data, len, arg);
}
/* The `data` is dynamically allocated by Controller, free it here */
bt_osi_mem_free((void *)data);
return 0;
}
#endif /* MYNEWT_VAL(BLE_ISO) */
+639
View File
@@ -0,0 +1,639 @@
/*
* SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Unlicense OR CC0-1.0
*/
#include <string.h>
#include "os/os.h"
#include "mem/mem.h"
#include "nimble/hci_common.h"
#include "host/ble_hs_hci.h"
#include "ble_hs_priv.h"
#if MYNEWT_VAL(BLE_ISO)
int
ble_hs_hci_iso_disconnect(uint16_t cis_handle, uint8_t reason)
{
struct ble_hci_lc_disconnect_cp cmd;
cmd.conn_handle = htole16(cis_handle);
cmd.reason = reason;
return ble_hs_hci_cmd_tx(BLE_HCI_OP(BLE_HCI_OGF_LINK_CTRL,
BLE_HCI_OCF_DISCONNECT_CMD),
&cmd, sizeof(cmd), NULL, 0);
}
int
ble_hs_hci_read_local_supp_codec(uint8_t *rsp_buf, uint8_t rsp_len)
{
if (rsp_buf == NULL || rsp_len < 2) {
return BLE_ERR_INV_HCI_CMD_PARMS;
}
return ble_hs_hci_cmd_tx(BLE_HCI_OP(BLE_HCI_OGF_INFO_PARAMS,
BLE_HCI_OCF_IP_RD_LOCAL_SUPP_CODEC),
NULL, 0, rsp_buf, rsp_len);
}
int
ble_hs_hci_read_local_supp_codec_caps(uint8_t coding_fmt, uint16_t company_id,
uint16_t vs_codec_id, uint8_t logical_transport_type,
uint8_t direction, uint8_t *rsp_buf, uint8_t rsp_len)
{
struct ble_hci_ip_rd_local_supp_codec_caps_cp cmd;
if (rsp_buf == NULL || rsp_len == 0) {
return BLE_ERR_INV_HCI_CMD_PARMS;
}
cmd.coding_fmt = coding_fmt;
cmd.company_id = company_id;
cmd.vs_codec_id = vs_codec_id;
cmd.logical_tpt_type = logical_transport_type;
cmd.direction = direction;
return ble_hs_hci_cmd_tx(BLE_HCI_OP(BLE_HCI_OGF_INFO_PARAMS,
BLE_HCI_OCF_IP_RD_LOCAL_SUPP_CODEC_CAPS),
&cmd, sizeof(cmd), rsp_buf, rsp_len);
}
int
ble_hs_hci_read_local_supp_controller_delay(uint8_t coding_fmt, uint16_t company_id,
uint16_t vs_codec_id, uint8_t logical_transport_type,
uint8_t direction,
uint8_t codec_cfg_len, uint8_t *codec_cfg,
uint32_t *min_controller_delay,
uint32_t *max_controller_delay)
{
struct ble_hci_ip_rd_local_supp_controller_delay_cp cmd;
struct ble_hci_ip_rd_local_supp_controller_delay_rp rsp;
int rc;
if ((codec_cfg_len && codec_cfg == NULL) ||
min_controller_delay == NULL ||
max_controller_delay == NULL) {
return BLE_ERR_INV_HCI_CMD_PARMS;
}
cmd.coding_fmt = coding_fmt;
cmd.company_id = company_id;
cmd.vs_codec_id = vs_codec_id;
cmd.logical_tpt_type = logical_transport_type;
cmd.direction = direction;
cmd.codec_cfg_len = codec_cfg_len;
/* TODO: Use Codec Configuration */
rc = ble_hs_hci_cmd_tx(BLE_HCI_OP(BLE_HCI_OGF_INFO_PARAMS,
BLE_HCI_OCF_IP_RD_LOCAL_SUPP_CONTROLLER_DELAY),
&cmd, sizeof(cmd), &rsp, sizeof(rsp));
if (rc) {
return rc;
}
memcpy(min_controller_delay, rsp.min_controller_delay, sizeof(rsp.min_controller_delay));
memcpy(max_controller_delay, rsp.max_controller_delay, sizeof(rsp.max_controller_delay));
return 0;
}
int
ble_hs_hci_cfg_data_path(uint8_t data_path_direction, uint8_t data_path_id,
uint8_t vs_cfg_len, uint8_t *vs_cfg)
{
struct ble_hci_cb_cfg_data_path_cp cmd;
if (vs_cfg_len && vs_cfg == NULL) {
return BLE_ERR_INV_HCI_CMD_PARMS;
}
cmd.data_path_dir = data_path_direction;
cmd.data_path_id = data_path_id;
cmd.vs_cfg_len = vs_cfg_len;
/* TODO: Use Vendor-Specific Configuration */
return ble_hs_hci_cmd_tx(BLE_HCI_OP(BLE_HCI_OGF_CTLR_BASEBAND,
BLE_HCI_OCF_CB_CFG_DATA_PATH),
&cmd, sizeof(cmd), NULL, 0);
}
int
ble_hs_hci_read_buf_sz_v2(uint16_t *data_len, uint8_t *data_packets,
uint16_t *iso_data_len, uint8_t *iso_data_packets)
{
struct ble_hci_le_rd_buf_size_v2_rp rsp;
int rc;
if (data_len == NULL || data_packets == NULL ||
iso_data_len == NULL || iso_data_packets == NULL) {
return BLE_ERR_INV_HCI_CMD_PARMS;
}
rc = ble_hs_hci_cmd_tx(BLE_HCI_OP(BLE_HCI_OGF_LE,
BLE_HCI_OCF_LE_RD_BUF_SIZE_V2),
NULL, 0, &rsp, sizeof(rsp));
if (rc) {
return rc;
}
*data_len = rsp.data_len;
*data_packets = rsp.data_packets;
*iso_data_len = rsp.iso_data_len;
*iso_data_packets = rsp.iso_data_packets;
return 0;
}
int
ble_hs_hci_read_iso_tx_sync(uint16_t conn_handle, uint16_t *packet_seq_num,
uint32_t *timestamp, uint32_t *timeoffset)
{
struct ble_hci_le_read_iso_tx_sync_cp cmd;
struct ble_hci_le_read_iso_tx_sync_rp rsp;
int rc;
if (packet_seq_num == NULL || timestamp == NULL || timeoffset == NULL) {
return BLE_ERR_INV_HCI_CMD_PARMS;
}
cmd.conn_handle = htole16(conn_handle);
rc = ble_hs_hci_cmd_tx(BLE_HCI_OP(BLE_HCI_OGF_LE,
BLE_HCI_OCF_LE_READ_ISO_TX_SYNC),
&cmd, sizeof(cmd), &rsp, sizeof(rsp));
if (rc) {
return rc;
}
if (le16toh(rsp.conn_handle) != conn_handle) {
return BLE_HS_ECONTROLLER;
}
*packet_seq_num = rsp.packet_seq_num;
*timestamp = rsp.tx_timestamp;
memcpy(timeoffset, rsp.time_offset, sizeof(rsp.time_offset));
return 0;
}
int
ble_hs_hci_set_cig_params(uint8_t cig_id, uint32_t sdu_interval_c_to_p, uint32_t sdu_interval_p_to_c,
uint8_t slaves_clock_accuracy, uint8_t packing, uint8_t framing,
uint16_t max_transport_latency_c_to_p, uint16_t max_transport_latency_p_to_c,
uint8_t cis_cnt, struct ble_hci_le_cis_params *cis_params,
uint8_t *rsp_buf, uint8_t rsp_len)
{
struct ble_hci_le_set_cig_params_cp *cmd;
struct ble_hci_le_cis_params *cis_param;
uint8_t cmd_buf[sizeof(*cmd) + cis_cnt * sizeof(*cis_params)];
uint8_t cmd_len = sizeof(*cmd);
if (cis_cnt == 0 || cis_params == NULL) {
return BLE_ERR_INV_HCI_CMD_PARMS;
}
if (rsp_buf == NULL ||
rsp_len < sizeof(struct ble_hci_le_set_cig_params_rp) + cis_cnt * 2) {
return BLE_ERR_INV_HCI_CMD_PARMS;
}
cmd = (void *)cmd_buf;
cis_param = cmd->cis;
cmd->cig_id = cig_id;
memcpy(cmd->sdu_interval_c_to_p, &sdu_interval_c_to_p, sizeof(cmd->sdu_interval_c_to_p));
memcpy(cmd->sdu_interval_p_to_c, &sdu_interval_p_to_c, sizeof(cmd->sdu_interval_p_to_c));
cmd->worst_sca = slaves_clock_accuracy;
cmd->packing = packing;
cmd->framing = framing;
cmd->max_latency_c_to_p = max_transport_latency_c_to_p;
cmd->max_latency_p_to_c = max_transport_latency_p_to_c;
cmd->cis_count = cis_cnt;
for (size_t i = 0; i < cis_cnt; i++) {
cis_param->cis_id = cis_params[i].cis_id;
cis_param->max_sdu_c_to_p = cis_params[i].max_sdu_c_to_p;
cis_param->max_sdu_p_to_c = cis_params[i].max_sdu_p_to_c;
cis_param->phy_c_to_p = cis_params[i].phy_c_to_p;
cis_param->phy_p_to_c = cis_params[i].phy_p_to_c;
cis_param->rtn_c_to_p = cis_params[i].rtn_c_to_p;
cis_param->rtn_p_to_c = cis_params[i].rtn_p_to_c;
cmd_len += sizeof(*cis_param);
cis_param++;
}
return ble_hs_hci_cmd_tx(BLE_HCI_OP(BLE_HCI_OGF_LE,
BLE_HCI_OCF_LE_SET_CIG_PARAMS),
cmd, cmd_len, rsp_buf, rsp_len);
}
#if MYNEWT_VAL(BLE_ISO_TEST)
int
ble_hs_hci_set_cig_params_test(uint8_t cig_id, uint32_t sdu_interval_c_to_p, uint32_t sdu_interval_p_to_c,
uint8_t ft_c_to_p, uint8_t ft_p_to_c, uint16_t iso_interval,
uint8_t slaves_clock_accuracy, uint8_t packing, uint8_t framing,
uint8_t cis_cnt, struct ble_hci_le_cis_params_test *cis_params,
uint8_t *rsp_buf, uint8_t rsp_len)
{
struct ble_hci_le_set_cig_params_test_cp *cmd;
struct ble_hci_le_cis_params_test *cis_param;
uint8_t cmd_buf[sizeof(*cmd) + cis_cnt * sizeof(*cis_params)];
uint8_t cmd_len = sizeof(*cmd);
if (cis_cnt == 0 || cis_params == NULL) {
return BLE_ERR_INV_HCI_CMD_PARMS;
}
if (rsp_buf == NULL||
rsp_len < sizeof(struct ble_hci_le_set_cig_params_rp) + cis_cnt * 2) {
return BLE_ERR_INV_HCI_CMD_PARMS;
}
cmd = (void *)cmd_buf;
cis_param = cmd->cis;
cmd->cig_id = cig_id;
memcpy(cmd->sdu_interval_c_to_p, &sdu_interval_c_to_p, sizeof(cmd->sdu_interval_c_to_p));
memcpy(cmd->sdu_interval_p_to_c, &sdu_interval_p_to_c, sizeof(cmd->sdu_interval_p_to_c));
cmd->ft_c_to_p = ft_c_to_p;
cmd->ft_p_to_c = ft_p_to_c;
cmd->iso_interval = iso_interval;
cmd->worst_sca = slaves_clock_accuracy;
cmd->packing = packing;
cmd->framing = framing;
cmd->cis_count = cis_cnt;
for (size_t i = 0; i < cis_cnt; i++) {
cis_param->cis_id = cis_params[i].cis_id;
cis_param->nse = cis_params[i].nse;
cis_param->max_sdu_c_to_p = cis_params[i].max_sdu_c_to_p;
cis_param->max_sdu_p_to_c = cis_params[i].max_sdu_p_to_c;
cis_param->max_pdu_c_to_p = cis_params[i].max_pdu_c_to_p;
cis_param->max_pdu_p_to_c = cis_params[i].max_pdu_p_to_c;
cis_param->phy_c_to_p = cis_params[i].phy_c_to_p;
cis_param->phy_p_to_c = cis_params[i].phy_p_to_c;
cis_param->bn_c_to_p = cis_params[i].bn_c_to_p;
cis_param->bn_p_to_c = cis_params[i].bn_p_to_c;
cmd_len += sizeof(*cis_param);
cis_param++;
}
return ble_hs_hci_cmd_tx(BLE_HCI_OP(BLE_HCI_OGF_LE,
BLE_HCI_OCF_LE_SET_CIG_PARAMS_TEST),
cmd_buf, cmd_len, rsp_buf, rsp_len);
}
#endif /* MYNEWT_VAL(BLE_ISO_TEST) */
int
ble_hs_hci_create_cis(uint8_t cis_cnt, const struct ble_hci_le_create_cis_params *params)
{
struct ble_hci_le_create_cis_cp *cmd;
struct ble_hci_le_create_cis_params *param;
uint8_t cmd_buf[sizeof(*cmd) + cis_cnt * sizeof(*params)];
uint8_t cmd_len = sizeof(*cmd);
if (cis_cnt == 0 || params == NULL) {
return BLE_ERR_INV_HCI_CMD_PARMS;
}
cmd = (void *)cmd_buf;
param = cmd->cis;
cmd->cis_count = cis_cnt;
for (size_t i = 0; i < cis_cnt; i++) {
param->cis_handle = params[i].cis_handle;
param->conn_handle = params[i].conn_handle;
cmd_len += sizeof(*param);
param++;
}
return ble_hs_hci_cmd_tx(BLE_HCI_OP(BLE_HCI_OGF_LE,
BLE_HCI_OCF_LE_CREATE_CIS),
cmd_buf, cmd_len, NULL, 0);
}
int
ble_hs_hci_remove_cig(uint8_t cig_id)
{
struct ble_hci_le_remove_cig_cp cmd;
struct ble_hci_le_remove_cig_rp rsp;
cmd.cig_id = cig_id;
return ble_hs_hci_cmd_tx(BLE_HCI_OP(BLE_HCI_OGF_LE,
BLE_HCI_OCF_LE_REMOVE_CIG),
&cmd, sizeof(cmd), &rsp, sizeof(rsp));
}
int
ble_hs_hci_accept_cis_request(uint16_t cis_handle)
{
struct ble_hci_le_accept_cis_request_cp cmd;
cmd.conn_handle = cis_handle;
return ble_hs_hci_cmd_tx(BLE_HCI_OP(BLE_HCI_OGF_LE,
BLE_HCI_OCF_LE_ACCEPT_CIS_REQ),
&cmd, sizeof(cmd), NULL, 0);
}
int
ble_hs_hci_reject_cis_request(uint16_t cis_handle, uint8_t reason)
{
struct ble_hci_le_reject_cis_request_cp cmd;
cmd.conn_handle = cis_handle;
cmd.reason = reason;
return ble_hs_hci_cmd_tx(BLE_HCI_OP(BLE_HCI_OGF_LE,
BLE_HCI_OCF_LE_REJECT_CIS_REQ),
&cmd, sizeof(cmd), NULL, 0);
}
int
ble_hs_hci_create_big(uint8_t big_handle, uint8_t adv_handle, uint8_t num_bis,
uint32_t sdu_interval, uint16_t max_sdu,
uint16_t max_transport_latency, uint8_t rtn, uint8_t phy,
uint8_t packing, uint8_t framing, uint8_t encryption,
uint8_t broadcast_code[16])
{
struct ble_hci_le_create_big_cp cmd;
if (num_bis == 0 || (encryption && broadcast_code == NULL)) {
return BLE_ERR_INV_HCI_CMD_PARMS;
}
cmd.big_handle = big_handle;
cmd.adv_handle = adv_handle;
cmd.num_bis = num_bis;
memcpy(cmd.sdu_interval, &sdu_interval, sizeof(cmd.sdu_interval));
cmd.max_sdu = max_sdu;
cmd.max_transport_latency = max_transport_latency;
cmd.rtn = rtn;
cmd.phy = phy;
cmd.packing = packing;
cmd.framing = framing;
cmd.encryption = encryption;
if (encryption) {
memcpy(cmd.broadcast_code, broadcast_code, sizeof(cmd.broadcast_code));
}
return ble_hs_hci_cmd_tx(BLE_HCI_OP(BLE_HCI_OGF_LE,
BLE_HCI_OCF_LE_CREATE_BIG),
&cmd, sizeof(cmd), NULL, 0);
}
#if MYNEWT_VAL(BLE_ISO_TEST)
int
ble_hs_hci_create_big_test(uint8_t big_handle, uint8_t adv_handle, uint8_t num_bis,
uint32_t sdu_interval, uint16_t iso_interval, uint8_t nse,
uint16_t max_sdu, uint16_t max_pdu, uint8_t phy,
uint8_t packing, uint8_t framing, uint8_t bn, uint8_t irc,
uint8_t pto, uint8_t encryption, uint8_t broadcast_code[16])
{
struct ble_hci_le_create_big_test_cp cmd;
if (num_bis == 0 || (encryption && broadcast_code == NULL)) {
return BLE_ERR_INV_HCI_CMD_PARMS;
}
cmd.big_handle = big_handle;
cmd.adv_handle = adv_handle;
cmd.num_bis = num_bis;
memcpy(cmd.sdu_interval, &sdu_interval, sizeof(cmd.sdu_interval));
cmd.iso_interval = iso_interval;
cmd.nse = nse;
cmd.max_sdu = max_sdu;
cmd.max_pdu = max_pdu;
cmd.phy = phy;
cmd.packing = packing;
cmd.framing = framing;
cmd.bn = bn;
cmd.irc = irc;
cmd.pto = pto;
cmd.encryption = encryption;
if (encryption) {
memcpy(cmd.broadcast_code, broadcast_code, sizeof(cmd.broadcast_code));
}
return ble_hs_hci_cmd_tx(BLE_HCI_OP(BLE_HCI_OGF_LE,
BLE_HCI_OCF_LE_CREATE_BIG_TEST),
&cmd, sizeof(cmd), NULL, 0);
}
#endif /* MYNEWT_VAL(BLE_ISO_TEST) */
int
ble_hs_hci_terminate_big(uint8_t big_handle, uint8_t reason)
{
struct ble_hci_le_terminate_big_cp cmd;
cmd.big_handle = big_handle;
cmd.reason = reason;
return ble_hs_hci_cmd_tx(BLE_HCI_OP(BLE_HCI_OGF_LE,
BLE_HCI_OCF_LE_TERMINATE_BIG),
&cmd, sizeof(cmd), NULL, 0);
}
int
ble_hs_hci_big_create_sync(uint8_t big_handle, uint16_t sync_handle,
uint8_t encryption, uint8_t broadcast_code[16],
uint8_t mse, uint16_t sync_timeout,
uint8_t num_bis, uint8_t *bis_index)
{
struct ble_hci_le_big_create_sync_cp *cmd;
uint8_t cmd_buf[sizeof(*cmd) + MYNEWT_VAL(BLE_ISO_BIS_PER_BIG)];
if ((encryption && broadcast_code == NULL) || num_bis == 0 || bis_index == NULL) {
return BLE_ERR_INV_HCI_CMD_PARMS;
}
cmd = (void *)cmd_buf;
cmd->big_handle = big_handle;
cmd->sync_handle = sync_handle;
cmd->encryption = encryption;
if (encryption) {
memcpy(cmd->broadcast_code, broadcast_code, 16);
}
cmd->mse = mse;
cmd->sync_timeout = sync_timeout;
cmd->num_bis = num_bis;
memcpy(cmd->bis, bis_index, num_bis);
return ble_hs_hci_cmd_tx(BLE_HCI_OP(BLE_HCI_OGF_LE,
BLE_HCI_OCF_LE_BIG_CREATE_SYNC),
cmd, sizeof(*cmd) + num_bis, NULL, 0);
}
int
ble_hs_hci_big_terminate_sync(uint8_t big_handle)
{
struct ble_hci_le_big_terminate_sync_cp cmd;
cmd.big_handle = big_handle;
return ble_hs_hci_cmd_tx(BLE_HCI_OP(BLE_HCI_OGF_LE,
BLE_HCI_OCF_LE_BIG_TERMINATE_SYNC),
&cmd, sizeof(cmd), NULL, 0);
}
int
ble_hs_hci_setup_iso_data_path(uint16_t conn_handle, uint8_t data_path_direction,
uint8_t data_path_id, uint8_t coding_fmt,
uint16_t company_id, uint16_t vs_codec_id,
uint32_t controller_delay, uint8_t codec_cfg_len,
uint8_t *codec_cfg)
{
struct ble_hci_le_setup_iso_data_path_cp cmd;
if (codec_cfg_len && codec_cfg == NULL) {
return BLE_ERR_INV_HCI_CMD_PARMS;
}
cmd.conn_handle = conn_handle;
cmd.data_path_dir = data_path_direction;
cmd.data_path_id = data_path_id;
cmd.codec_id[0] = coding_fmt;
put_le16(cmd.codec_id + 1, company_id);
put_le16(cmd.codec_id + 3, vs_codec_id);
memcpy(cmd.controller_delay, &controller_delay, sizeof(cmd.controller_delay));
cmd.codec_config_len = codec_cfg_len;
/* TODO: Codec Configuration */
return ble_hs_hci_cmd_tx(BLE_HCI_OP(BLE_HCI_OGF_LE,
BLE_HCI_OCF_LE_SETUP_ISO_DATA_PATH),
&cmd, sizeof(cmd), NULL, 0);
}
int
ble_hs_hci_remove_iso_data_path(uint16_t conn_handle, uint8_t data_path_direction)
{
struct ble_hci_le_remove_iso_data_path_cp cmd;
cmd.conn_handle = conn_handle;
cmd.data_path_dir = data_path_direction;
return ble_hs_hci_cmd_tx(BLE_HCI_OP(BLE_HCI_OGF_LE,
BLE_HCI_OCF_LE_REMOVE_ISO_DATA_PATH),
&cmd, sizeof(cmd), NULL, 0);
}
#if MYNEWT_VAL(BLE_ISO_TEST)
int
ble_hs_hci_iso_transmit_test(uint16_t conn_handle, uint8_t payload_type)
{
struct ble_hci_le_iso_transmit_test_cp cmd;
cmd.conn_handle = conn_handle;
cmd.payload_type = payload_type;
return ble_hs_hci_cmd_tx(BLE_HCI_OP(BLE_HCI_OGF_LE,
BLE_HCI_OCF_LE_ISO_TRANSMIT_TEST),
&cmd, sizeof(cmd), NULL, 0);
}
int
ble_hs_hci_iso_receive_test(uint16_t conn_handle, uint8_t payload_type)
{
struct ble_hci_le_iso_receive_test_cp cmd;
cmd.conn_handle = conn_handle;
cmd.payload_type = payload_type;
return ble_hs_hci_cmd_tx(BLE_HCI_OP(BLE_HCI_OGF_LE,
BLE_HCI_OCF_LE_ISO_RECEIVE_TEST),
&cmd, sizeof(cmd), NULL, 0);
}
int
ble_hs_hci_iso_read_test_counters(uint16_t conn_handle, uint32_t *received_sdu_count,
uint32_t *missed_sdu_count, uint32_t *failed_sdu_count)
{
struct ble_hci_le_iso_read_test_counters_cp cmd;
struct ble_hci_le_iso_read_test_counters_rp rsp;
int rc;
cmd.conn_handle = conn_handle;
rc = ble_hs_hci_cmd_tx(BLE_HCI_OP(BLE_HCI_OGF_LE,
BLE_HCI_OCF_LE_ISO_READ_TEST_COUNTERS),
&cmd, sizeof(cmd), &rsp, sizeof(rsp));
if (rc) {
return rc;
}
*received_sdu_count = rsp.received_sdu_count;
*missed_sdu_count = rsp.missed_sdu_count;
*failed_sdu_count = rsp.failed_sdu_count;
return 0;
}
int
ble_hs_hci_iso_test_end(uint16_t conn_handle, uint32_t *received_sdu_count,
uint32_t *missed_sdu_count, uint32_t *failed_sdu_count)
{
struct ble_hci_le_iso_test_end_cp cmd;
struct ble_hci_le_iso_test_end_rp rsp;
int rc;
cmd.conn_handle = conn_handle;
rc = ble_hs_hci_cmd_tx(BLE_HCI_OP(BLE_HCI_OGF_LE,
BLE_HCI_OCF_LE_ISO_TEST_END),
&cmd, sizeof(cmd), &rsp, sizeof(rsp));
if (rc) {
return rc;
}
*received_sdu_count = rsp.received_sdu_count;
*missed_sdu_count = rsp.missed_sdu_count;
*failed_sdu_count = rsp.failed_sdu_count;
return 0;
}
#endif /* MYNEWT_VAL(BLE_ISO_TEST) */
int
ble_hs_hci_read_iso_link_quality(uint16_t conn_handle, uint32_t *tx_unacked_pkts,
uint32_t *tx_flushed_pkts, uint32_t *tx_last_subev_pkts,
uint32_t *retransmitted_pkts, uint32_t *crc_error_pkts,
uint32_t *rx_unreceived_pkts, uint32_t *duplicate_pkts)
{
struct ble_hci_le_read_iso_link_quality_cp cmd;
struct ble_hci_le_read_iso_link_quality_rp rsp;
int rc;
if (!tx_unacked_pkts || !tx_flushed_pkts ||
!tx_last_subev_pkts || !retransmitted_pkts ||
!crc_error_pkts || !rx_unreceived_pkts ||
!duplicate_pkts) {
return BLE_ERR_INV_HCI_CMD_PARMS;
}
cmd.conn_handle = conn_handle;
rc = ble_hs_hci_cmd_tx(BLE_HCI_OP(BLE_HCI_OGF_LE,
BLE_HCI_OCF_LE_READ_ISO_LINK_QUALITY),
&cmd, sizeof(cmd), &rsp, sizeof(rsp));
if (rc) {
return rc;
}
*tx_unacked_pkts = rsp.tx_unacked_pkts;
*tx_flushed_pkts = rsp.tx_flushed_pkts;
*tx_last_subev_pkts = rsp.tx_last_subevent_pkts;
*retransmitted_pkts = rsp.retransmitted_pkts;
*crc_error_pkts = rsp.crc_error_pkts;
*rx_unreceived_pkts = rsp.rx_unreceived_pkts;
*duplicate_pkts = rsp.duplicate_pkts;
return 0;
}
#endif /* MYNEWT_VAL(BLE_ISO) */
+67 -1
View File
@@ -22,6 +22,9 @@
#include "host/ble_hs.h"
#include "host/ble_hs_hci.h"
#include "ble_hs_priv.h"
#if MYNEWT_VAL(BLE_ISO)
#include "host/ble_hs_iso.h"
#endif /* MYNEWT_VAL(BLE_ISO) */
#if !MYNEWT_VAL(BLE_CONTROLLER)
static int
@@ -107,6 +110,33 @@ ble_hs_startup_le_read_sup_f_tx(void)
}
#if MYNEWT_VAL(BLE_ROLE_CENTRAL) || MYNEWT_VAL(BLE_ROLE_PERIPHERAL)
#if MYNEWT_VAL(BLE_ISO)
static int
ble_hs_startup_le_read_buf_sz_v2_tx(uint16_t *out_acl_pktlen, uint8_t *out_max_acl_pkts,
uint16_t *out_iso_pktlen, uint8_t *out_max_iso_pkts)
{
struct ble_hci_le_rd_buf_size_v2_rp rsp;
int rc;
rc = ble_hs_hci_cmd_tx(BLE_HCI_OP(BLE_HCI_OGF_LE,
BLE_HCI_OCF_LE_RD_BUF_SIZE_V2), NULL, 0,
&rsp, sizeof(rsp));
if (rc != 0) {
return rc;
}
*out_acl_pktlen = le16toh(rsp.data_len);
*out_max_acl_pkts = rsp.data_packets;
*out_iso_pktlen = le16toh(rsp.iso_data_len);
*out_max_iso_pkts = rsp.iso_data_packets;
BLE_HS_LOG(INFO, "LE Read Buffer Size v2: %u %u %u %u",
*out_acl_pktlen, *out_max_acl_pkts,
*out_iso_pktlen, *out_max_iso_pkts);
return 0;
}
#else /* MYNEWT_VAL(BLE_ISO) */
static int
ble_hs_startup_le_read_buf_sz_tx(uint16_t *out_pktlen, uint8_t *out_max_pkts)
{
@@ -125,6 +155,7 @@ ble_hs_startup_le_read_buf_sz_tx(uint16_t *out_pktlen, uint8_t *out_max_pkts)
return 0;
}
#endif /* MYNEWT_VAL(BLE_ISO) */
static int
ble_hs_startup_read_buf_sz_tx(uint16_t *out_pktlen, uint16_t *out_max_pkts)
@@ -152,9 +183,17 @@ ble_hs_startup_read_buf_sz(void)
uint16_t max_pkts = 0;
uint16_t pktlen = 0;
uint8_t le_max_pkts = 0;
#if MYNEWT_VAL(BLE_ISO)
uint16_t iso_pktlen = 0;
uint8_t iso_max_pkts = 0;
#endif /* MYNEWT_VAL(BLE_ISO) */
int rc;
#if MYNEWT_VAL(BLE_ISO)
rc = ble_hs_startup_le_read_buf_sz_v2_tx(&le_pktlen, &le_max_pkts, &iso_pktlen, &iso_max_pkts);
#else /* MYNEWT_VAL(BLE_ISO) */
rc = ble_hs_startup_le_read_buf_sz_tx(&le_pktlen, &le_max_pkts);
#endif /* MYNEWT_VAL(BLE_ISO) */
if (rc != 0) {
return rc;
}
@@ -174,6 +213,13 @@ ble_hs_startup_read_buf_sz(void)
return rc;
}
#if MYNEWT_VAL(BLE_ISO)
rc = ble_hs_hci_set_iso_buf_sz(iso_pktlen, iso_max_pkts);
if (rc != 0) {
return rc;
}
#endif /* MYNEWT_VAL(BLE_ISO) */
return 0;
}
#endif
@@ -292,7 +338,7 @@ ble_hs_startup_le_set_evmask_tx(void)
}
#endif
#if MYNEWT_VAL(BLE_PERIODIC_ADV_SYNC_BIGINFO_REPORTS)
#if MYNEWT_VAL(BLE_PERIODIC_ADV_SYNC_BIGINFO_REPORTS) && !MYNEWT_VAL(BLE_ISO)
if (version >= BLE_HCI_VER_BCS_5_2) {
/**
* Enable the following LE events:
@@ -338,6 +384,26 @@ ble_hs_startup_le_set_evmask_tx(void)
}
#endif
#if MYNEWT_VAL(BLE_ISO)
if (version >= BLE_HCI_VER_BCS_5_2) {
/**
* Enable the following LE events:
* 0x0000000001000000 LE CIS Established event [v1]
* 0x0000000002000000 LE CIS Request event
* 0x0000000004000000 LE Create BIG Complete event
* 0x0000000008000000 LE Terminate BIG Complete event
* 0x0000000010000000 LE BIG Sync Established event
* 0x0000000020000000 LE BIG Sync Lost event
* 0x0000000200000000 LE BIGInfo Advertising Report event
* 0x0000020000000000 LE CIS Established event [v2]
*/
mask |= 0x000000023f000000;
#if MYNEWT_VAL(BLE_ISO_CIS_ESTAB_V2)
mask |= 0x0000020000000000;
#endif /* MYNEWT_VAL(BLE_ISO_CIS_ESTAB_V2) */
}
#endif /* MYNEWT_VAL(BLE_ISO) */
cmd.event_mask = htole64(mask);
rc = ble_hs_hci_cmd_tx(BLE_HCI_OP(BLE_HCI_OGF_LE,
+91 -2
View File
@@ -154,6 +154,14 @@ struct ble_hci_cb_wr_auth_pyld_tmo_rp {
uint16_t conn_handle;
} __attribute__((packed));
#define BLE_HCI_OCF_CB_CFG_DATA_PATH (0x0083)
struct ble_hci_cb_cfg_data_path_cp {
uint8_t data_path_dir;
uint8_t data_path_id;
uint8_t vs_cfg_len;
uint8_t vs_cfg[0];
} __attribute__((packed));
/* List of OCF for Info Param commands (OGF=0x04) */
#define BLE_HCI_OCF_IP_RD_LOCAL_VER (0x0001)
struct ble_hci_ip_rd_local_ver_rp {
@@ -187,6 +195,60 @@ struct ble_hci_ip_rd_bd_addr_rp {
uint8_t addr[6];
} __attribute__((packed));
#define BLE_HCI_OCF_IP_RD_LOCAL_SUPP_CODEC (0x000D)
struct ble_hci_ip_rd_local_supp_std_codec {
uint8_t coding_fmt;
uint8_t transport;
} __attribute__((packed));
struct ble_hci_ip_rd_local_supp_vs_codec {
uint16_t company_id;
uint16_t vs_codec_id;
uint8_t transport;
} __attribute__((packed));
struct ble_hci_ip_rd_local_supp_codec_rp {
uint8_t num_std_codec;
struct ble_hci_ip_rd_local_supp_std_codec std;
uint8_t num_vs_codec;
struct ble_hci_ip_rd_local_supp_vs_codec vs;
} __attribute__((packed));
#define BLE_HCI_OCF_IP_RD_LOCAL_SUPP_CODEC_CAPS (0x000E)
struct ble_hci_ip_rd_local_supp_codec_caps_cp {
uint8_t coding_fmt;
uint16_t company_id;
uint16_t vs_codec_id;
uint8_t logical_tpt_type;
uint8_t direction;
} __attribute__((packed));
struct ble_hci_ip_rd_local_supp_codec_caps {
uint8_t codec_cap_len;
uint8_t codec_cap[0];
} __attribute__((packed));
struct ble_hci_ip_rd_local_supp_codec_caps_rp {
uint8_t num_codec_caps;
struct ble_hci_ip_rd_local_supp_codec_caps codec_caps;
} __attribute__((packed));
#define BLE_HCI_OCF_IP_RD_LOCAL_SUPP_CONTROLLER_DELAY (0x000F)
struct ble_hci_ip_rd_local_supp_controller_delay_cp {
uint8_t coding_fmt;
uint16_t company_id;
uint16_t vs_codec_id;
uint8_t logical_tpt_type;
uint8_t direction;
uint8_t codec_cfg_len;
uint8_t codec_cfg[0];
} __attribute__((packed));
struct ble_hci_ip_rd_local_supp_controller_delay_rp {
uint8_t min_controller_delay[3];
uint8_t max_controller_delay[3];
} __attribute__((packed));
/* List of OCF for Status parameters commands (OGF = 0x05) */
#define BLE_HCI_OCF_RD_RSSI (0x0005)
struct ble_hci_rd_rssi_cp {
@@ -947,8 +1009,8 @@ struct ble_hci_le_cis_params {
uint16_t max_sdu_p_to_c;
uint8_t phy_c_to_p;
uint8_t phy_p_to_c;
uint8_t rnt_c_to_p;
uint8_t rnt_p_to_c;
uint8_t rtn_c_to_p;
uint8_t rtn_p_to_c;
} __attribute__((packed));
struct ble_hci_le_set_cig_params_cp {
uint8_t cig_id;
@@ -2284,6 +2346,33 @@ struct ble_hci_ev_le_subev_periodic_adv_resp_rep {
struct periodic_adv_response responses[0];
} __attribute__((packed));
#define BLE_HCI_LE_SUBEV_CIS_ESTABLISHED_V2 (0x2A)
struct ble_hci_ev_le_subev_cis_established_v2 {
uint8_t subev_code;
uint8_t status;
uint16_t conn_handle;
uint8_t cig_sync_delay[3];
uint8_t cis_sync_delay[3];
uint8_t transport_latency_c_to_p[3];
uint8_t transport_latency_p_to_c[3];
uint8_t phy_c_to_p;
uint8_t phy_p_to_c;
uint8_t nse;
uint8_t bn_c_to_p;
uint8_t bn_p_to_c;
uint8_t ft_c_to_p;
uint8_t ft_p_to_c;
uint16_t max_pdu_c_to_p;
uint16_t max_pdu_p_to_c;
uint16_t iso_interval;
uint8_t sub_interval[3];
uint16_t max_sdu_c_to_p;
uint16_t max_sdu_p_to_c;
uint8_t sdu_interval_c_to_p[3];
uint8_t sdu_interval_p_to_c[3];
uint8_t framing;
} __attribute__((packed));
#if (BLE_ADV_REPORT_FLOW_CONTROL == TRUE)
// LE vendor hci event
#define BLE_HCI_LE_SUBEV_DISCARD_REPORT_EVT 0XF0
+7 -1
View File
@@ -28,7 +28,13 @@ ble_transport_host_recv_cb(hci_trans_pkt_ind_t type, uint8_t *data, uint16_t len
if (type == HCI_ACL_IND) {
rc = ble_transport_to_hs_acl((struct os_mbuf *)data);
} else {
}
#if MYNEWT_VAL(BLE_ISO)
else if (type == HCI_ISO_IND) {
rc = ble_transport_to_hs_iso_v2(data, len);
}
#endif /* MYNEWT_VAL(BLE_ISO) */
else {
rc = ble_transport_to_hs_evt(data);
}
return rc;
@@ -82,6 +82,14 @@ ble_transport_to_hs_iso(struct os_mbuf *om)
{
return ble_transport_to_hs_iso_impl(om);
}
#if MYNEWT_VAL(BLE_ISO)
static inline int
ble_transport_to_hs_iso_v2(const uint8_t *data, uint16_t len)
{
return ble_transport_to_hs_iso_impl_v2(data, len);
}
#endif /* MYNEWT_VAL(BLE_ISO) */
#endif /* BLE_MONITOR */
#ifdef __cplusplus
@@ -40,6 +40,9 @@ extern int ble_transport_to_ll_iso_impl(struct os_mbuf *om);
extern int ble_transport_to_hs_evt_impl(void *buf);
extern int ble_transport_to_hs_acl_impl(struct os_mbuf *om);
extern int ble_transport_to_hs_iso_impl(struct os_mbuf *om);
#if MYNEWT_VAL(BLE_ISO)
extern int ble_transport_to_hs_iso_impl_v2(const uint8_t *data, uint16_t len);
#endif /* MYNEWT_VAL(BLE_ISO) */
#ifdef __cplusplus
}