mirror of
https://github.com/espressif/esp-nimble.git
synced 2026-06-06 05:14:45 +00:00
feat(ble): ISO minor support for NimBLE Host
This commit is contained in:
@@ -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
|
||||
*
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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_ */
|
||||
@@ -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
@@ -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) {
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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)
|
||||
{
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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) */
|
||||
@@ -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) */
|
||||
@@ -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,
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user