mirror of
https://github.com/espressif/esp-idf.git
synced 2026-10-02 11:10:54 +03:00
feat(ble_audio): Support BLE ISO & BLE Audio deinitialization
This commit is contained in:
@@ -54,6 +54,12 @@ esp_err_t esp_ble_audio_bap_unicast_server_unregister(void)
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
#if BLE_AUDIO_SVC_DEFERRED_ADD
|
||||
if (bt_le_ascs_deinit()) {
|
||||
return ESP_FAIL;
|
||||
}
|
||||
#endif /* BLE_AUDIO_SVC_DEFERRED_ADD */
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
@@ -772,6 +778,12 @@ esp_err_t esp_ble_audio_bap_scan_delegator_unregister(void)
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
#if BLE_AUDIO_SVC_DEFERRED_ADD
|
||||
if (bt_le_bass_deinit()) {
|
||||
return ESP_FAIL;
|
||||
}
|
||||
#endif /* BLE_AUDIO_SVC_DEFERRED_ADD */
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
|
||||
@@ -11,8 +11,12 @@
|
||||
#include <stdbool.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include <zephyr/logging/log.h>
|
||||
|
||||
#include "esp_ble_audio_common_api.h"
|
||||
|
||||
LOG_MODULE_REGISTER(LEA_API, CONFIG_BT_ISO_LOG_LEVEL);
|
||||
|
||||
esp_err_t esp_ble_audio_data_parse(const uint8_t ltv[], size_t size,
|
||||
bool (*func)(uint8_t type,
|
||||
const uint8_t *data,
|
||||
@@ -127,6 +131,52 @@ unregister_gap:
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
esp_err_t esp_ble_audio_common_deinit(const esp_ble_iso_deinit_info_t *info)
|
||||
{
|
||||
bool reset_ext_adv = true;
|
||||
bool reset_pa_sync = true;
|
||||
int err;
|
||||
|
||||
if (info) {
|
||||
if (!info->reset_acl_conn) {
|
||||
LOG_WRN("ConnKeepUnsupported");
|
||||
return ESP_ERR_NOT_SUPPORTED;
|
||||
}
|
||||
|
||||
reset_ext_adv = info->reset_ext_adv;
|
||||
reset_pa_sync = info->reset_pa_sync;
|
||||
}
|
||||
|
||||
if (bt_le_host_check_idle()) {
|
||||
return ESP_ERR_INVALID_STATE;
|
||||
}
|
||||
|
||||
err = bt_le_iso_task_deinit();
|
||||
if (err) {
|
||||
return ESP_ERR_TIMEOUT;
|
||||
}
|
||||
|
||||
bt_le_audio_deinit();
|
||||
|
||||
err = bt_le_host_deinit();
|
||||
if (err) {
|
||||
return ESP_ERR_TIMEOUT;
|
||||
}
|
||||
|
||||
if (reset_ext_adv) {
|
||||
bt_le_ext_adv_state_reset();
|
||||
}
|
||||
|
||||
if (reset_pa_sync) {
|
||||
bt_le_per_adv_sync_state_reset();
|
||||
}
|
||||
|
||||
bt_le_gatt_app_cb_unregister();
|
||||
bt_le_gap_app_cb_unregister();
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t esp_ble_audio_common_start(esp_ble_audio_start_info_t *info)
|
||||
{
|
||||
int err;
|
||||
|
||||
@@ -59,6 +59,10 @@ esp_err_t esp_ble_audio_csip_set_member_unregister(esp_ble_audio_csip_set_member
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
|
||||
if (bt_le_csis_deinit(svc_inst)) {
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
err = bt_csip_set_member_unregister_safe(svc_inst);
|
||||
if (err) {
|
||||
return ESP_FAIL;
|
||||
|
||||
@@ -34,6 +34,10 @@ esp_err_t esp_ble_audio_pacs_unregister(void)
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
if (bt_le_pacs_deinit()) {
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
|
||||
@@ -376,6 +376,16 @@ esp_err_t esp_ble_audio_tbs_unregister_bearer(uint8_t bearer_index)
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
#if BLE_AUDIO_SVC_DEFERRED_ADD
|
||||
if (bearer_index == ESP_BLE_AUDIO_TBS_GTBS_INDEX) {
|
||||
if (bt_le_gtbs_deinit()) {
|
||||
return ESP_FAIL;
|
||||
}
|
||||
} else if (bt_le_tbs_deinit(bearer_index)) {
|
||||
return ESP_FAIL;
|
||||
}
|
||||
#endif /* BLE_AUDIO_SVC_DEFERRED_ADD */
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
#endif /* CONFIG_BT_TBS */
|
||||
|
||||
@@ -121,10 +121,30 @@ typedef struct {
|
||||
/**
|
||||
* @brief Post an application-layer GAP event for audio internal usage.
|
||||
*
|
||||
* @note This function is only needed while using NimBLE Host.
|
||||
* @note NimBLE-only: NimBLE has no global GAP callback, so the layers below
|
||||
* see only what the application forwards here. An event left out is
|
||||
* dropped silently. Bluedroid's adapter hooks the stack directly.
|
||||
*
|
||||
* @param type Event type.
|
||||
* @param param Event parameters.
|
||||
* @note Forward every event below that the application's flows can produce.
|
||||
* Forwarding an unused one is harmless; omitting one leaves the
|
||||
* matching state uncreated and fails later and elsewhere:
|
||||
* - BLE_GAP_EVENT_EXT_DISC extended advertising report
|
||||
* - BLE_GAP_EVENT_CONNECT ACL established or failed
|
||||
* - BLE_GAP_EVENT_DISCONNECT ACL closed
|
||||
* - BLE_GAP_EVENT_ENC_CHANGE encryption changed
|
||||
* - BLE_GAP_EVENT_PERIODIC_SYNC PA sync established
|
||||
* - BLE_GAP_EVENT_PERIODIC_SYNC_LOST PA sync lost
|
||||
* - BLE_GAP_EVENT_PERIODIC_REPORT periodic advertising report
|
||||
* - BLE_GAP_EVENT_PERIODIC_TRANSFER PA sync received over PAST
|
||||
* - BLE_GAP_EVENT_PERIODIC_TRANSFER_V2 as above, PAwR
|
||||
*
|
||||
* GATT events go to esp_ble_audio_gatt_app_post_event() instead.
|
||||
*
|
||||
* @note Shares a sink with esp_ble_iso_gap_app_post_event(): forward a given
|
||||
* event through exactly one of them or it is delivered twice.
|
||||
*
|
||||
* @param type Event type, i.e. ble_gap_event::type.
|
||||
* @param param Event parameters, i.e. the struct ble_gap_event pointer.
|
||||
*/
|
||||
void esp_ble_audio_gap_app_post_event(uint16_t type, void *param);
|
||||
|
||||
@@ -132,13 +152,20 @@ void esp_ble_audio_gap_app_post_event(uint16_t type, void *param);
|
||||
/**
|
||||
* @brief Post an application-layer GATT event for audio internal usage.
|
||||
*
|
||||
* @note NimBLE-only. Bluedroid dispatches GATT events directly inside the
|
||||
* adapter (BTA callbacks), so no app-level post is needed. This
|
||||
* declaration is hidden from Bluedroid builds to make misuse a
|
||||
* compile-time error.
|
||||
* @note NimBLE-only: Bluedroid dispatches GATT events inside the adapter, so
|
||||
* no app-level post is needed. Hidden from Bluedroid builds to make
|
||||
* misuse a compile-time error.
|
||||
*
|
||||
* @param type Event type.
|
||||
* @param param Event parameters.
|
||||
* @note Forward all four below here rather than through
|
||||
* esp_ble_audio_gap_app_post_event() - GATT has no ISO counterpart.
|
||||
* Omitting one is silent; ASCS and PACS simply never react.
|
||||
* - BLE_GAP_EVENT_MTU ATT MTU exchanged
|
||||
* - BLE_GAP_EVENT_SUBSCRIBE peer wrote a CCC descriptor
|
||||
* - BLE_GAP_EVENT_NOTIFY_RX notification or indication received
|
||||
* - BLE_GAP_EVENT_NOTIFY_TX notification or indication sent
|
||||
*
|
||||
* @param type Event type, i.e. ble_gap_event::type.
|
||||
* @param param Event parameters, i.e. the struct ble_gap_event pointer.
|
||||
*/
|
||||
void esp_ble_audio_gatt_app_post_event(uint8_t type, void *param);
|
||||
#endif /* !CONFIG_BT_BLUEDROID_ENABLED */
|
||||
@@ -163,6 +190,30 @@ typedef struct {
|
||||
uint8_t dummy; /*!< Dummy field to avoid empty struct */
|
||||
} esp_ble_audio_start_info_t;
|
||||
|
||||
/**
|
||||
* @brief Deinitialize BLE Audio.
|
||||
*
|
||||
* The only precondition is that the application has stopped its streams: a live
|
||||
* stream always has a CIS under it, so one still up makes this return
|
||||
* ESP_ERR_INVALID_STATE with each offending item logged at ERROR level.
|
||||
*
|
||||
* @note Registered profiles need no prior unregister - this releases them
|
||||
* itself, while the host lock and GATT application are still alive.
|
||||
* The per-profile esp_ble_audio_*_unregister() calls are for dropping
|
||||
* one profile while audio stays up.
|
||||
*
|
||||
* @note Also releases the ISO layer, so esp_ble_iso_common_deinit() must not
|
||||
* be called as well. @p info has the same meaning as there.
|
||||
*
|
||||
* @param info Which ISO-layer records to clear, or NULL to clear all.
|
||||
*
|
||||
* @return ESP_OK on success,
|
||||
* ESP_ERR_INVALID_STATE if something is still active,
|
||||
* ESP_ERR_TIMEOUT if the ISO task could not be stopped.
|
||||
* Nothing is released unless ESP_OK is returned.
|
||||
*/
|
||||
esp_err_t esp_ble_audio_common_deinit(const esp_ble_iso_deinit_info_t *info);
|
||||
|
||||
/**
|
||||
* @brief Start BLE Audio services.
|
||||
*
|
||||
|
||||
@@ -29,6 +29,8 @@ extern "C" {
|
||||
|
||||
int bt_le_bluedroid_audio_init(void);
|
||||
|
||||
void bt_le_bluedroid_audio_deinit(void);
|
||||
|
||||
int bt_le_bluedroid_media_proxy_pl_init(void);
|
||||
|
||||
int bt_le_bluedroid_vcp_vol_rend_init(void);
|
||||
|
||||
@@ -16,6 +16,8 @@ extern "C" {
|
||||
|
||||
int bt_le_bluedroid_ascs_init(void);
|
||||
|
||||
int bt_le_bluedroid_ascs_deinit(void);
|
||||
|
||||
int bt_le_bluedroid_ascs_start(void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
||||
@@ -16,6 +16,8 @@ extern "C" {
|
||||
|
||||
int bt_le_bluedroid_bass_init(void);
|
||||
|
||||
int bt_le_bluedroid_bass_deinit(void);
|
||||
|
||||
int bt_le_bluedroid_bass_start(void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
||||
@@ -14,8 +14,12 @@
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
void bt_le_bluedroid_csis_state_reset(void);
|
||||
|
||||
int bt_le_bluedroid_csis_init(void *csis_svc, uint8_t count);
|
||||
|
||||
int bt_le_bluedroid_csis_deinit(void *csis_svc);
|
||||
|
||||
int bt_le_bluedroid_csis_start(void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
||||
@@ -14,6 +14,8 @@
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
void bt_le_bluedroid_mcs_state_reset(void);
|
||||
|
||||
int bt_le_bluedroid_gmcs_init(void);
|
||||
|
||||
int bt_le_bluedroid_gmcs_start(void);
|
||||
|
||||
@@ -14,6 +14,8 @@
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
void bt_le_bluedroid_mics_state_reset(void);
|
||||
|
||||
int bt_le_bluedroid_mics_init(void *micp_inc);
|
||||
|
||||
int bt_le_bluedroid_mics_start(void);
|
||||
|
||||
@@ -16,6 +16,8 @@ extern "C" {
|
||||
|
||||
int bt_le_bluedroid_pacs_init(void);
|
||||
|
||||
int bt_le_bluedroid_pacs_deinit(void);
|
||||
|
||||
int bt_le_bluedroid_pacs_start(void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
||||
@@ -16,10 +16,14 @@ extern "C" {
|
||||
|
||||
int bt_le_bluedroid_gtbs_init(void);
|
||||
|
||||
int bt_le_bluedroid_gtbs_deinit(void);
|
||||
|
||||
int bt_le_bluedroid_gtbs_start(void);
|
||||
|
||||
int bt_le_bluedroid_tbs_init(void);
|
||||
|
||||
int bt_le_bluedroid_tbs_deinit(uint8_t bearer_index);
|
||||
|
||||
int bt_le_bluedroid_tbs_start(void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
||||
@@ -14,6 +14,8 @@
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
void bt_le_bluedroid_vcs_state_reset(void);
|
||||
|
||||
int bt_le_bluedroid_vcs_init(void *vcp_inc);
|
||||
|
||||
int bt_le_bluedroid_vcs_start(void);
|
||||
|
||||
@@ -162,10 +162,14 @@ enum {
|
||||
|
||||
void bt_le_bluedroid_audio_gatts_init(void);
|
||||
|
||||
void bt_le_bluedroid_audio_gatts_deinit(void);
|
||||
|
||||
int bt_le_bluedroid_set_svc_in_progress(uint8_t value);
|
||||
|
||||
int bt_le_bluedroid_svc_init(struct bt_gatt_service *svc);
|
||||
|
||||
int bt_le_bluedroid_svc_deinit(struct bt_gatt_service *svc);
|
||||
|
||||
int bt_le_bluedroid_svc_start(struct bt_gatt_service *svc);
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
||||
@@ -71,6 +71,19 @@ int bt_le_bluedroid_audio_init(void)
|
||||
|
||||
bt_le_bluedroid_audio_gatts_init();
|
||||
|
||||
#if CONFIG_BT_CSIP_SET_MEMBER
|
||||
bt_le_bluedroid_csis_state_reset();
|
||||
#endif /* CONFIG_BT_CSIP_SET_MEMBER */
|
||||
#if CONFIG_BT_VCP_VOL_REND
|
||||
bt_le_bluedroid_vcs_state_reset();
|
||||
#endif /* CONFIG_BT_VCP_VOL_REND */
|
||||
#if CONFIG_BT_MICP_MIC_DEV
|
||||
bt_le_bluedroid_mics_state_reset();
|
||||
#endif /* CONFIG_BT_MICP_MIC_DEV */
|
||||
#if CONFIG_BT_MCS
|
||||
bt_le_bluedroid_mcs_state_reset();
|
||||
#endif /* CONFIG_BT_MCS */
|
||||
|
||||
#if CONFIG_BT_PACS
|
||||
err = bt_le_bluedroid_pacs_init();
|
||||
if (err) {
|
||||
@@ -123,6 +136,16 @@ int bt_le_bluedroid_audio_init(void)
|
||||
return err;
|
||||
}
|
||||
|
||||
void bt_le_bluedroid_audio_deinit(void)
|
||||
{
|
||||
LOG_DBG("[B]AudioDeinit");
|
||||
|
||||
/* The services are removed by the BTA_GATTS_AppDeregister() in the ISO
|
||||
* layer's gatt deinit - GATT_Deregister() stops every service the app
|
||||
* owns - so only this layer's own hook is dropped here. */
|
||||
bt_le_bluedroid_audio_gatts_deinit();
|
||||
}
|
||||
|
||||
#if CONFIG_BT_CSIP_SET_MEMBER
|
||||
static int bluedroid_gatt_csis_init(struct bt_le_audio_start_info *info,
|
||||
struct bt_gatt_service **inc_csis_svc)
|
||||
|
||||
@@ -38,6 +38,21 @@ int bt_le_bluedroid_ascs_init(void)
|
||||
return bt_le_bluedroid_svc_init(ascs_svc);
|
||||
}
|
||||
|
||||
int bt_le_bluedroid_ascs_deinit(void)
|
||||
{
|
||||
struct bt_gatt_service *ascs_svc;
|
||||
|
||||
LOG_DBG("[B]AscsDeinit");
|
||||
|
||||
ascs_svc = lib_ascs_svc_get();
|
||||
if (!ascs_svc) {
|
||||
LOG_ERR("[B]AscsSvcGetFail");
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
return bt_le_bluedroid_svc_deinit(ascs_svc);
|
||||
}
|
||||
|
||||
int bt_le_bluedroid_ascs_start(void)
|
||||
{
|
||||
struct bt_gatt_service *ascs_svc;
|
||||
|
||||
@@ -38,6 +38,21 @@ int bt_le_bluedroid_bass_init(void)
|
||||
return bt_le_bluedroid_svc_init(bass_svc);
|
||||
}
|
||||
|
||||
int bt_le_bluedroid_bass_deinit(void)
|
||||
{
|
||||
struct bt_gatt_service *bass_svc;
|
||||
|
||||
LOG_DBG("[B]BassDeinit");
|
||||
|
||||
bass_svc = lib_bap_bass_svc_get();
|
||||
if (!bass_svc) {
|
||||
LOG_ERR("[B]BassSvcGetFail");
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
return bt_le_bluedroid_svc_deinit(bass_svc);
|
||||
}
|
||||
|
||||
int bt_le_bluedroid_bass_start(void)
|
||||
{
|
||||
struct bt_gatt_service *bass_svc;
|
||||
|
||||
@@ -30,6 +30,11 @@ static BT_AUDIO_EXT_RAM_BSS_ATTR struct csis_inst {
|
||||
|
||||
static BT_AUDIO_EXT_RAM_BSS_ATTR uint8_t csis_svc_count;
|
||||
|
||||
void bt_le_bluedroid_csis_state_reset(void)
|
||||
{
|
||||
csis_svc_count = 0;
|
||||
}
|
||||
|
||||
int bt_le_bluedroid_csis_init(void *svc, uint8_t count)
|
||||
{
|
||||
int err;
|
||||
@@ -58,6 +63,18 @@ int bt_le_bluedroid_csis_init(void *svc, uint8_t count)
|
||||
return 0;
|
||||
}
|
||||
|
||||
int bt_le_bluedroid_csis_deinit(void *csis_svc)
|
||||
{
|
||||
LOG_DBG("[B]CsisDeinit");
|
||||
|
||||
if (csis_svc == NULL) {
|
||||
LOG_ERR("[B]CsisSvcNull");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
return bt_le_bluedroid_svc_deinit(csis_svc);
|
||||
}
|
||||
|
||||
int bt_le_bluedroid_csis_start(void)
|
||||
{
|
||||
int err;
|
||||
|
||||
@@ -62,12 +62,28 @@ static int bluedroid_gmcs_ots_init(void)
|
||||
|
||||
static int bluedroid_gmcs_ots_start(void)
|
||||
{
|
||||
/* svc_p comes from bluedroid_gmcs_ots_init(), which only runs once the app
|
||||
* calls media_proxy_pl_init(); NULL means MCS was never registered. The
|
||||
* count-guarded loops in vcs.c / mics.c / csis.c skip for the same reason. */
|
||||
if (inc_ots_inst.svc_p == NULL) {
|
||||
LOG_DBG("[B]GmcsOtsNotReg");
|
||||
return 0;
|
||||
}
|
||||
|
||||
bt_le_bluedroid_set_svc_in_progress(OTS_IN_PROGRESS);
|
||||
|
||||
return bt_le_bluedroid_svc_start(inc_ots_inst.svc_p);
|
||||
}
|
||||
#endif /* CONFIG_BT_OTS */
|
||||
|
||||
void bt_le_bluedroid_mcs_state_reset(void)
|
||||
{
|
||||
#if CONFIG_BT_OTS
|
||||
inc_ots_inst.svc_p = NULL;
|
||||
inc_ots_inst.included = false;
|
||||
#endif /* CONFIG_BT_OTS */
|
||||
}
|
||||
|
||||
int bt_le_bluedroid_gmcs_init(void)
|
||||
{
|
||||
struct bt_gatt_service *gmcs_svc;
|
||||
@@ -151,6 +167,7 @@ int bt_le_bluedroid_mcs_init(void)
|
||||
* (created during gmcs_init). Reset the flag so it re-resolves per instance. */
|
||||
inc_ots_inst.included = false;
|
||||
#endif /* CONFIG_BT_OTS */
|
||||
|
||||
err = bt_le_bluedroid_svc_init(&list[i]);
|
||||
if (err) {
|
||||
return err;
|
||||
|
||||
@@ -41,6 +41,11 @@ struct inc_svc_inst *mics_not_included_inst(void)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void bt_le_bluedroid_mics_state_reset(void)
|
||||
{
|
||||
inc_aics_svc_count = 0;
|
||||
}
|
||||
|
||||
int bt_le_bluedroid_mics_init(void *micp_inc)
|
||||
{
|
||||
struct bt_micp_included *micp_included;
|
||||
|
||||
@@ -38,6 +38,21 @@ int bt_le_bluedroid_pacs_init(void)
|
||||
return bt_le_bluedroid_svc_init(pacs_svc);
|
||||
}
|
||||
|
||||
int bt_le_bluedroid_pacs_deinit(void)
|
||||
{
|
||||
struct bt_gatt_service *pacs_svc;
|
||||
|
||||
LOG_DBG("[B]PacsDeinit");
|
||||
|
||||
pacs_svc = lib_pacs_svc_get();
|
||||
if (!pacs_svc) {
|
||||
LOG_ERR("[B]PacsSvcGetFail");
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
return bt_le_bluedroid_svc_deinit(pacs_svc);
|
||||
}
|
||||
|
||||
int bt_le_bluedroid_pacs_start(void)
|
||||
{
|
||||
struct bt_gatt_service *pacs_svc;
|
||||
|
||||
@@ -36,6 +36,21 @@ int bt_le_bluedroid_gtbs_init(void)
|
||||
return bt_le_bluedroid_svc_init(gtbs_svc);
|
||||
}
|
||||
|
||||
int bt_le_bluedroid_gtbs_deinit(void)
|
||||
{
|
||||
struct bt_gatt_service *gtbs_svc;
|
||||
|
||||
LOG_DBG("[B]GtbsDeinit");
|
||||
|
||||
gtbs_svc = lib_gtbs_svc_get();
|
||||
if (!gtbs_svc) {
|
||||
LOG_ERR("[B]GtbsSvcGetFail");
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
return bt_le_bluedroid_svc_deinit(gtbs_svc);
|
||||
}
|
||||
|
||||
int bt_le_bluedroid_gtbs_start(void)
|
||||
{
|
||||
struct bt_gatt_service *gtbs_svc;
|
||||
@@ -83,6 +98,29 @@ int bt_le_bluedroid_tbs_init(void)
|
||||
return 0;
|
||||
}
|
||||
|
||||
int bt_le_bluedroid_tbs_deinit(uint8_t bearer_index)
|
||||
{
|
||||
#if CONFIG_BT_TBS_BEARER_COUNT > 0
|
||||
struct bt_gatt_service *tbs_list;
|
||||
#endif /* CONFIG_BT_TBS_BEARER_COUNT > 0 */
|
||||
|
||||
LOG_DBG("[B]TbsDeinit[%u]", bearer_index);
|
||||
|
||||
#if CONFIG_BT_TBS_BEARER_COUNT > 0
|
||||
if (bearer_index < CONFIG_BT_TBS_BEARER_COUNT) {
|
||||
tbs_list = lib_tbs_server_list_get();
|
||||
if (!tbs_list) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return bt_le_bluedroid_svc_deinit(&tbs_list[bearer_index]);
|
||||
}
|
||||
#endif /* CONFIG_BT_TBS_BEARER_COUNT > 0 */
|
||||
|
||||
LOG_ERR("[B]TbsInvBearerIdx[%u]", bearer_index);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
int bt_le_bluedroid_tbs_start(void)
|
||||
{
|
||||
struct bt_gatt_service *tbs_list;
|
||||
|
||||
@@ -49,6 +49,12 @@ struct inc_svc_inst *vcs_not_included_inst(void)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void bt_le_bluedroid_vcs_state_reset(void)
|
||||
{
|
||||
inc_vocs_svc_count = 0;
|
||||
inc_aics_svc_count = 0;
|
||||
}
|
||||
|
||||
int bt_le_bluedroid_vcs_init(void *vcp_inc)
|
||||
{
|
||||
struct bt_vcp_included *vcp_included;
|
||||
|
||||
@@ -33,6 +33,39 @@ static BT_AUDIO_EXT_RAM_BSS_ATTR uint16_t inc_svc_handle;
|
||||
static BT_AUDIO_EXT_RAM_BSS_ATTR uint16_t svc_handle;
|
||||
static BT_AUDIO_EXT_RAM_BSS_ATTR uint16_t chrc_handle;
|
||||
|
||||
static BT_AUDIO_EXT_RAM_BSS_ATTR uint8_t aics_count;
|
||||
static BT_AUDIO_EXT_RAM_BSS_ATTR uint8_t csis_count;
|
||||
static BT_AUDIO_EXT_RAM_BSS_ATTR uint8_t vocs_count;
|
||||
static BT_AUDIO_EXT_RAM_BSS_ATTR uint8_t mcs_count;
|
||||
static BT_AUDIO_EXT_RAM_BSS_ATTR uint8_t ots_count;
|
||||
static BT_AUDIO_EXT_RAM_BSS_ATTR uint8_t tbs_count;
|
||||
|
||||
/* Every service svc_init() created, so the deinit can delete each one:
|
||||
* BTA_GATTS_AppDeregister() clears BTA's srvc_cb[] but leaves gatt_cb.sr_reg[],
|
||||
* which is the table GATTS_StartService() checks on the next init. */
|
||||
static BT_AUDIO_EXT_RAM_BSS_ATTR struct bt_gatt_service *created_svcs[CONFIG_BT_GATT_MAX_SR_PROFILES];
|
||||
static BT_AUDIO_EXT_RAM_BSS_ATTR uint8_t created_svc_count;
|
||||
|
||||
static void svc_created_record(struct bt_gatt_service *svc)
|
||||
{
|
||||
for (uint8_t i = 0; i < created_svc_count; i++) {
|
||||
if (created_svcs[i] == svc) {
|
||||
/* Re-created in place: gtbs_init has no "already added" guard, and
|
||||
* the tbs/mcs loops re-enter for each newly registered instance. */
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (created_svc_count == ARRAY_SIZE(created_svcs)) {
|
||||
/* Same ceiling as the stack's, so reaching it means the static_assert on
|
||||
* TOTAL_SERVICE_COUNT is out of date rather than that we over-created. */
|
||||
LOG_ERR("[B]SvcRecordFull[%u]", svc_in_progress);
|
||||
return;
|
||||
}
|
||||
|
||||
created_svcs[created_svc_count++] = svc;
|
||||
}
|
||||
|
||||
static bool is_primary_svc(void)
|
||||
{
|
||||
if (svc_in_progress == ASCS_IN_PROGRESS ||
|
||||
@@ -237,9 +270,61 @@ static struct gatts_svc_cb svc_cb = {
|
||||
|
||||
void bt_le_bluedroid_audio_gatts_init(void)
|
||||
{
|
||||
svc_in_progress = 0;
|
||||
inc_svc_handle = 0;
|
||||
svc_handle = 0;
|
||||
chrc_handle = 0;
|
||||
|
||||
created_svc_count = 0;
|
||||
|
||||
aics_count = 0;
|
||||
csis_count = 0;
|
||||
vocs_count = 0;
|
||||
mcs_count = 0;
|
||||
ots_count = 0;
|
||||
tbs_count = 0;
|
||||
|
||||
bt_le_bluedroid_gatts_svc_cb_register(&svc_cb);
|
||||
}
|
||||
|
||||
int bt_le_bluedroid_svc_deinit(struct bt_gatt_service *svc)
|
||||
{
|
||||
if (svc == NULL || svc->attrs == NULL) {
|
||||
LOG_ERR("[B]SvcDeinitNoSvc");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (svc->attrs[0].handle == 0) {
|
||||
LOG_DBG("[B]SvcDeinitNotCreated");
|
||||
return 0;
|
||||
}
|
||||
|
||||
LOG_DBG("[B]SvcDeinit[0x%04x]", svc->attrs[0].handle);
|
||||
|
||||
BTA_GATTS_DeleteService(svc->attrs[0].handle);
|
||||
svc->attrs[0].handle = 0;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void bt_le_bluedroid_audio_gatts_deinit(void)
|
||||
{
|
||||
/* Reverse creation order, so an included secondary outlives the primary that
|
||||
* includes it. Each delete logs upstream's "Active Service Found" at ERROR;
|
||||
* that is its successful lookup, not a failure. */
|
||||
|
||||
while (created_svc_count > 0) {
|
||||
struct bt_gatt_service *svc = created_svcs[--created_svc_count];
|
||||
|
||||
created_svcs[created_svc_count] = NULL;
|
||||
|
||||
/* Already-unregistered entries fall out as a no-op inside. */
|
||||
(void)bt_le_bluedroid_svc_deinit(svc);
|
||||
}
|
||||
|
||||
bt_le_bluedroid_gatts_svc_cb_register(NULL);
|
||||
}
|
||||
|
||||
int bt_le_bluedroid_set_svc_in_progress(uint8_t value)
|
||||
{
|
||||
if (value >= MAX_IN_PROGRESS) {
|
||||
@@ -414,17 +499,6 @@ static struct inc_svc_inst *get_not_included_inst(void)
|
||||
|
||||
static uint8_t get_svc_inst_id(uint16_t svc_uuid)
|
||||
{
|
||||
/* Note:
|
||||
* For LE Audio, some service could have multiple instances.
|
||||
*/
|
||||
|
||||
static BT_AUDIO_EXT_RAM_BSS_ATTR uint8_t aics_count;
|
||||
static BT_AUDIO_EXT_RAM_BSS_ATTR uint8_t csis_count;
|
||||
static BT_AUDIO_EXT_RAM_BSS_ATTR uint8_t vocs_count;
|
||||
static BT_AUDIO_EXT_RAM_BSS_ATTR uint8_t mcs_count;
|
||||
static BT_AUDIO_EXT_RAM_BSS_ATTR uint8_t ots_count;
|
||||
static BT_AUDIO_EXT_RAM_BSS_ATTR uint8_t tbs_count;
|
||||
|
||||
switch (svc_uuid) {
|
||||
case BT_UUID_AICS_VAL:
|
||||
return aics_count++;
|
||||
@@ -611,6 +685,12 @@ int bt_le_bluedroid_svc_init(struct bt_gatt_service *svc)
|
||||
}
|
||||
}
|
||||
|
||||
/* Created, so the deinit has to delete it. attr_count 0 is a service the
|
||||
* application never registered; svc_init walked nothing. */
|
||||
if (svc->attr_count > 0 && svc->attrs[0].handle != 0) {
|
||||
svc_created_record(svc);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -618,11 +698,16 @@ int bt_le_bluedroid_svc_start(struct bt_gatt_service *svc)
|
||||
{
|
||||
BT_LE_ASSERT(svc);
|
||||
|
||||
/* App may not register this svc; skip rather than fail audio_start.
|
||||
* Unused CAP Acceptor capabilities stop at handle 0, GMAS at NULL
|
||||
* attrs - only bt_gmap_register() allocates them. */
|
||||
if (svc->attrs == NULL) {
|
||||
LOG_DBG("[B]SvcNotReg[%u]", svc_in_progress);
|
||||
return 0;
|
||||
}
|
||||
|
||||
svc_handle = svc->attrs[0].handle;
|
||||
|
||||
/* App may not register this svc (e.g. CAP Acceptor single mode keeps
|
||||
* unused capability built). Skip rather than fail audio_start.
|
||||
*/
|
||||
if (svc_handle == 0) {
|
||||
LOG_DBG("[B]SvcNotInit[%u]", svc_in_progress);
|
||||
return 0;
|
||||
@@ -632,7 +717,9 @@ int bt_le_bluedroid_svc_start(struct bt_gatt_service *svc)
|
||||
BTA_GATTS_StartService(svc_handle, BTA_GATT_TRANSPORT_LE);
|
||||
|
||||
if (bt_le_bluedroid_gatts_sem_take()) {
|
||||
LOG_ERR("[B]SvcStartFail");
|
||||
/* Which service and which handle: BTA only says "already started" or
|
||||
* "not created", neither of which names the caller. */
|
||||
LOG_ERR("[B]SvcStartFail[%u][0x%04x]", svc_in_progress, svc_handle);
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
@@ -28,6 +28,8 @@ extern "C" {
|
||||
|
||||
int bt_le_nimble_audio_init(void);
|
||||
|
||||
void bt_le_nimble_audio_deinit(void);
|
||||
|
||||
int bt_le_nimble_media_proxy_pl_init(void);
|
||||
|
||||
int bt_le_nimble_vcp_vol_rend_init(void);
|
||||
|
||||
@@ -18,6 +18,8 @@ int bt_le_nimble_ascs_attr_handle_set(void);
|
||||
|
||||
int bt_le_nimble_ascs_init(void);
|
||||
|
||||
int bt_le_nimble_ascs_deinit(void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -18,6 +18,8 @@ int bt_le_nimble_bass_attr_handle_set(void);
|
||||
|
||||
int bt_le_nimble_bass_init(void);
|
||||
|
||||
int bt_le_nimble_bass_deinit(void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -19,8 +19,12 @@ extern "C" {
|
||||
|
||||
int bt_le_nimble_csis_attr_handle_set(void);
|
||||
|
||||
void bt_le_nimble_csis_state_reset(void);
|
||||
|
||||
int bt_le_nimble_csis_init(void *csis_svc, uint8_t count);
|
||||
|
||||
int bt_le_nimble_csis_deinit(void *csis_svc);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -19,6 +19,8 @@ extern "C" {
|
||||
|
||||
int bt_le_nimble_gmcs_attr_handle_set(void);
|
||||
|
||||
void bt_le_nimble_mcs_state_reset(void);
|
||||
|
||||
int bt_le_nimble_gmcs_init(bool ots_included);
|
||||
|
||||
int bt_le_nimble_mcs_attr_handle_set(void);
|
||||
|
||||
@@ -19,6 +19,8 @@ extern "C" {
|
||||
|
||||
int bt_le_nimble_mics_attr_handle_set(void);
|
||||
|
||||
void bt_le_nimble_mics_state_reset(void);
|
||||
|
||||
int bt_le_nimble_mics_init(void *micp_inc);
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
||||
@@ -21,6 +21,8 @@ int bt_le_nimble_pacs_attr_handle_set(void);
|
||||
|
||||
int bt_le_nimble_pacs_init(void);
|
||||
|
||||
int bt_le_nimble_pacs_deinit(void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -18,10 +18,14 @@ int bt_le_nimble_gtbs_attr_handle_set(void);
|
||||
|
||||
int bt_le_nimble_gtbs_init(void);
|
||||
|
||||
int bt_le_nimble_gtbs_deinit(void);
|
||||
|
||||
int bt_le_nimble_tbs_attr_handle_set(void);
|
||||
|
||||
int bt_le_nimble_tbs_init(void);
|
||||
|
||||
int bt_le_nimble_tbs_deinit(uint8_t bearer_index);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -16,6 +16,8 @@ extern "C" {
|
||||
|
||||
int bt_le_nimble_vcs_attr_handle_set(void);
|
||||
|
||||
void bt_le_nimble_vcs_state_reset(void);
|
||||
|
||||
int bt_le_nimble_vcs_init(void *vcp_inc);
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
||||
@@ -20,6 +20,7 @@
|
||||
|
||||
#include "nimble/init.h"
|
||||
#include "common/init.h"
|
||||
#include "common/audio_attr.h"
|
||||
|
||||
#include "../../../lib/include/audio.h"
|
||||
|
||||
@@ -159,6 +160,9 @@ LOG_MODULE_REGISTER(LEA_NINIT, CONFIG_BT_ISO_LOG_LEVEL);
|
||||
|
||||
_Static_assert(TOTAL_CCCDS_COUNT <= CONFIG_BT_NIMBLE_MAX_CCCDS, "Too small BT_NIMBLE_MAX_CCCDS");
|
||||
|
||||
static BT_AUDIO_EXT_RAM_BSS_ATTR bool nimble_svcs_registered;
|
||||
static BT_AUDIO_EXT_RAM_BSS_ATTR bool nimble_gatts_started;
|
||||
|
||||
int bt_le_nimble_audio_init(void)
|
||||
{
|
||||
int err = 0;
|
||||
@@ -169,6 +173,23 @@ int bt_le_nimble_audio_init(void)
|
||||
return err;
|
||||
}
|
||||
|
||||
#if CONFIG_BT_CSIP_SET_MEMBER
|
||||
bt_le_nimble_csis_state_reset();
|
||||
#endif /* CONFIG_BT_CSIP_SET_MEMBER */
|
||||
#if CONFIG_BT_VCP_VOL_REND
|
||||
bt_le_nimble_vcs_state_reset();
|
||||
#endif /* CONFIG_BT_VCP_VOL_REND */
|
||||
#if CONFIG_BT_MICP_MIC_DEV
|
||||
bt_le_nimble_mics_state_reset();
|
||||
#endif /* CONFIG_BT_MICP_MIC_DEV */
|
||||
#if CONFIG_BT_MCS
|
||||
bt_le_nimble_mcs_state_reset();
|
||||
#endif /* CONFIG_BT_MCS */
|
||||
|
||||
if (nimble_svcs_registered) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
ble_svc_gap_init();
|
||||
|
||||
ble_svc_gatt_init();
|
||||
@@ -222,6 +243,8 @@ int bt_le_nimble_audio_init(void)
|
||||
#endif /* CONFIG_BT_HAS */
|
||||
#endif /* (BLE_AUDIO_SVC_DEFERRED_ADD == 0) */
|
||||
|
||||
nimble_svcs_registered = true;
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
@@ -442,6 +465,14 @@ int bt_le_nimble_micp_mic_dev_init(void)
|
||||
}
|
||||
#endif /* CONFIG_BT_MICP_MIC_DEV */
|
||||
|
||||
void bt_le_nimble_audio_deinit(void)
|
||||
{
|
||||
LOG_DBG("[N]AudioDeinit");
|
||||
|
||||
/* Nothing to release: the services added here are boot-scoped and the defs
|
||||
* NimBLE holds reference no lib memory, so resources_deinit() is safe. */
|
||||
}
|
||||
|
||||
int bt_le_nimble_audio_start(void *info)
|
||||
{
|
||||
struct bt_gatt_service *inc_csis_svc = NULL;
|
||||
@@ -499,10 +530,17 @@ int bt_le_nimble_audio_start(void *info)
|
||||
}
|
||||
#endif /* CONFIG_BT_GMAP */
|
||||
|
||||
err = ble_gatts_start();
|
||||
if (err) {
|
||||
LOG_ERR("[N]GattsStartFail[%d]", err);
|
||||
return err;
|
||||
/* Once per boot: ble_gatts_start() resets the whole ATT database and only
|
||||
* re-registers defs added since the last start, so calling it again drops
|
||||
* other owners' services. attr_handle_set() still runs every cycle. */
|
||||
if (!nimble_gatts_started) {
|
||||
err = ble_gatts_start();
|
||||
if (err) {
|
||||
LOG_ERR("[N]GattsStartFail[%d]", err);
|
||||
return err;
|
||||
}
|
||||
|
||||
nimble_gatts_started = true;
|
||||
}
|
||||
|
||||
err = nimble_gatt_attr_handle_set();
|
||||
|
||||
@@ -254,3 +254,9 @@ free:
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
|
||||
int bt_le_nimble_ascs_deinit(void)
|
||||
{
|
||||
LOG_DBG("[N]AscsDeinit");
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -218,3 +218,9 @@ free:
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
|
||||
int bt_le_nimble_bass_deinit(void)
|
||||
{
|
||||
LOG_DBG("[N]BassDeinit");
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -87,6 +87,9 @@ static BT_AUDIO_EXT_RAM_BSS_ATTR struct csis_inst {
|
||||
|
||||
static BT_AUDIO_EXT_RAM_BSS_ATTR uint8_t csis_svc_count;
|
||||
|
||||
static BT_AUDIO_EXT_RAM_BSS_ATTR uint8_t csis_reg_count;
|
||||
static BT_AUDIO_EXT_RAM_BSS_ATTR bool csis_registered;
|
||||
|
||||
/* Extra one for terminating the CSIS service array */
|
||||
static BT_AUDIO_EXT_RAM_BSS_ATTR struct ble_gatt_svc_def gatt_svc_csis[CSIS_SVC_COUNT + 1];
|
||||
|
||||
@@ -162,7 +165,14 @@ int bt_le_nimble_csis_attr_handle_set(void)
|
||||
struct bt_gatt_service *zsvc = csis_insts[i].svc_p;
|
||||
|
||||
BT_LE_ASSERT(zsvc);
|
||||
BT_LE_ASSERT(csis_insts[i].sirk_handle >= 2);
|
||||
|
||||
/* Zero means no registration round ever covered this instance, so it is
|
||||
* absent from the ATT database and there is no range to anchor. Happens
|
||||
* when CSIS is first registered after the boot's ble_gatts_start(). */
|
||||
if (csis_insts[i].sirk_handle < 2) {
|
||||
LOG_ERR("[N]CsisNoAttrHdl[%u]", i);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* SIRK is always the first characteristic, so its value handle anchors the range. */
|
||||
start_handle = csis_insts[i].sirk_handle - 2; /* server attr handle & char def handle */
|
||||
@@ -295,6 +305,11 @@ static void csis_svc_init(struct csis_inst *inst,
|
||||
BT_LE_ASSERT(chr_cnt < CSIS_CHR_COUNT);
|
||||
}
|
||||
|
||||
void bt_le_nimble_csis_state_reset(void)
|
||||
{
|
||||
csis_svc_count = 0;
|
||||
}
|
||||
|
||||
int bt_le_nimble_csis_init(void *svc, uint8_t count)
|
||||
{
|
||||
bool csis_added = false;
|
||||
@@ -307,11 +322,27 @@ int bt_le_nimble_csis_init(void *svc, uint8_t count)
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* The attribute table is built by the boot's single ble_gatts_start(), so a
|
||||
* different instance count now needs a table this boot cannot produce. Fail
|
||||
* here, not later on a handle NimBLE never assigned. */
|
||||
if (csis_registered && count != csis_reg_count) {
|
||||
LOG_ERR("[N]CsisCountChanged[%u][%u]", csis_reg_count, count);
|
||||
return -1;
|
||||
}
|
||||
|
||||
csis_svc_count = count;
|
||||
|
||||
/* Refreshed every cycle: the lib frees and reallocates its service objects,
|
||||
* while the NimBLE defs below are built once and stay in the database. */
|
||||
for (size_t i = 0; i < csis_svc_count; i++) {
|
||||
csis_insts[i].svc_p = ((struct bt_gatt_service **)svc)[i];
|
||||
}
|
||||
|
||||
if (csis_registered) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < csis_svc_count; i++) {
|
||||
csis_svc_init(&csis_insts[i], &gatt_svc_csis[i], csis_insts[i].svc_p);
|
||||
}
|
||||
|
||||
@@ -333,6 +364,9 @@ int bt_le_nimble_csis_init(void *svc, uint8_t count)
|
||||
goto free;
|
||||
}
|
||||
|
||||
csis_reg_count = count;
|
||||
csis_registered = true;
|
||||
|
||||
return 0;
|
||||
|
||||
free:
|
||||
@@ -348,3 +382,11 @@ free:
|
||||
csis_svc_count = 0;
|
||||
return rc;
|
||||
}
|
||||
|
||||
int bt_le_nimble_csis_deinit(void *csis_svc)
|
||||
{
|
||||
ARG_UNUSED(csis_svc);
|
||||
|
||||
LOG_DBG("[N]CsisDeinit");
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -630,6 +630,13 @@ static int inc_ots_svc_init(void)
|
||||
}
|
||||
#endif /* CONFIG_BT_OTS */
|
||||
|
||||
void bt_le_nimble_mcs_state_reset(void)
|
||||
{
|
||||
#if CONFIG_BT_OTS
|
||||
inc_ots_svc_count = 0;
|
||||
#endif /* CONFIG_BT_OTS */
|
||||
}
|
||||
|
||||
int bt_le_nimble_gmcs_init(bool ots_included)
|
||||
{
|
||||
#if CONFIG_BT_OTS
|
||||
|
||||
@@ -346,6 +346,11 @@ static void inc_aics_svc_init(struct inc_aics_inst *inst,
|
||||
INC_AICS_CHR_FLAGS_DESCRIPTION);
|
||||
}
|
||||
|
||||
void bt_le_nimble_mics_state_reset(void)
|
||||
{
|
||||
inc_aics_svc_count = 0;
|
||||
}
|
||||
|
||||
int bt_le_nimble_mics_init(void *micp_inc)
|
||||
{
|
||||
struct bt_micp_included *micp_included;
|
||||
|
||||
@@ -275,3 +275,9 @@ int bt_le_nimble_pacs_init(void)
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int bt_le_nimble_pacs_deinit(void)
|
||||
{
|
||||
LOG_DBG("[N]PacsDeinit");
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -372,3 +372,15 @@ int bt_le_nimble_tbs_init(void)
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int bt_le_nimble_gtbs_deinit(void)
|
||||
{
|
||||
LOG_DBG("[N]GtbsDeinit");
|
||||
return 0;
|
||||
}
|
||||
|
||||
int bt_le_nimble_tbs_deinit(uint8_t bearer_index)
|
||||
{
|
||||
LOG_DBG("[N]TbsDeinit[%u]", bearer_index);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -542,6 +542,12 @@ static void inc_aics_svc_init(struct inc_aics_inst *inst,
|
||||
INC_AICS_CHR_FLAGS_DESCRIPTION);
|
||||
}
|
||||
|
||||
void bt_le_nimble_vcs_state_reset(void)
|
||||
{
|
||||
inc_vocs_svc_count = 0;
|
||||
inc_aics_svc_count = 0;
|
||||
}
|
||||
|
||||
int bt_le_nimble_vcs_init(void *vcp_inc)
|
||||
{
|
||||
struct bt_vcp_included *vcp_included;
|
||||
|
||||
@@ -49,14 +49,26 @@ void bt_le_audio_deinit(void);
|
||||
|
||||
int bt_le_ascs_init(void);
|
||||
|
||||
int bt_le_ascs_deinit(void);
|
||||
|
||||
int bt_le_pacs_deinit(void);
|
||||
|
||||
int bt_le_csis_deinit(const void *svc_inst);
|
||||
|
||||
int bt_le_bass_init(void);
|
||||
|
||||
int bt_le_bass_deinit(void);
|
||||
|
||||
int bt_le_tmas_init(void);
|
||||
|
||||
int bt_le_gtbs_init(void);
|
||||
|
||||
int bt_le_gtbs_deinit(void);
|
||||
|
||||
int bt_le_tbs_init(void);
|
||||
|
||||
int bt_le_tbs_deinit(uint8_t bearer_index);
|
||||
|
||||
int bt_le_has_init(void);
|
||||
|
||||
int bt_le_media_proxy_pl_init(void);
|
||||
|
||||
@@ -185,7 +185,7 @@ static const uint16_t ext_structs[] = {
|
||||
sizeof(struct bt_bond_info),
|
||||
};
|
||||
|
||||
#define LEA_VERSION (0x20260820)
|
||||
#define LEA_VERSION (0x20260824)
|
||||
|
||||
struct lib_ext_cfgs {
|
||||
/* BLE */
|
||||
@@ -1085,16 +1085,20 @@ struct lib_ext_funcs {
|
||||
|
||||
/* Scan */
|
||||
int (*_scan_cb_register)(struct bt_le_scan_cb *cb);
|
||||
void (*_scan_cb_unregister)(struct bt_le_scan_cb *cb);
|
||||
int (*_scan_start)(const struct bt_le_scan_param *param, void *cb);
|
||||
int (*_scan_stop)(void);
|
||||
int (*_pa_sync_cb_register)(struct bt_le_per_adv_sync_cb *cb);
|
||||
int (*_pa_sync_cb_unregister)(struct bt_le_per_adv_sync_cb *cb);
|
||||
int (*_pa_sync_get_info)(struct bt_le_per_adv_sync *per_adv_sync,
|
||||
struct bt_le_per_adv_sync_info *info);
|
||||
struct bt_le_per_adv_sync *(*_pa_sync_lookup_addr)(const bt_addr_le_t *adv_addr, uint8_t sid);
|
||||
|
||||
/* Connection */
|
||||
int (*_conn_cb_register)(struct bt_conn_cb *cb);
|
||||
int (*_conn_cb_unregister)(struct bt_conn_cb *cb);
|
||||
int (*_conn_auth_info_cb_register)(struct bt_conn_auth_info_cb *cb);
|
||||
int (*_conn_auth_info_cb_unregister)(struct bt_conn_auth_info_cb *cb);
|
||||
void (*_conn_foreach)(enum bt_conn_type type,
|
||||
void (*func)(struct bt_conn *conn, void *data),
|
||||
void *data);
|
||||
@@ -1295,14 +1299,18 @@ static const struct lib_ext_funcs ext_funcs = {
|
||||
._bt_foreach_bond = (void *)bt_foreach_bond,
|
||||
|
||||
._scan_cb_register = (void *)bt_le_scan_cb_register,
|
||||
._scan_cb_unregister = (void *)bt_le_scan_cb_unregister,
|
||||
._scan_start = (void *)bt_le_scan_start,
|
||||
._scan_stop = (void *)bt_le_scan_stop,
|
||||
._pa_sync_cb_register = (void *)bt_le_per_adv_sync_cb_register,
|
||||
._pa_sync_cb_unregister = (void *)bt_le_per_adv_sync_cb_unregister,
|
||||
._pa_sync_get_info = (void *)bt_le_per_adv_sync_get_info,
|
||||
._pa_sync_lookup_addr = (void *)bt_le_per_adv_sync_lookup_addr,
|
||||
|
||||
._conn_cb_register = (void *)bt_conn_cb_register,
|
||||
._conn_cb_unregister = (void *)bt_conn_cb_unregister,
|
||||
._conn_auth_info_cb_register = (void *)bt_conn_auth_info_cb_register,
|
||||
._conn_auth_info_cb_unregister = (void *)bt_conn_auth_info_cb_unregister,
|
||||
._conn_foreach = (void *)bt_conn_foreach,
|
||||
._conn_get_info = (void *)bt_conn_get_info,
|
||||
._conn_index = (void *)bt_conn_index,
|
||||
@@ -2075,6 +2083,260 @@ static int lib_audio_resources_init(void)
|
||||
return err;
|
||||
}
|
||||
|
||||
/* Reverse order of lib_audio_resources_init(): a module may reference an earlier
|
||||
* one. Failures log and continue - stopping half way leaves more behind. Keep
|
||||
* every lib_*_init() listed here; a missing counterpart leaks silently. */
|
||||
static void lib_audio_resources_deinit(void)
|
||||
{
|
||||
#if CONFIG_BT_GMAP
|
||||
/* No init counterpart above: bt_gmap_register() allocates GMAS on demand,
|
||||
* so only the deinit side is listed. */
|
||||
if (lib_gmap_server_deinit()) {
|
||||
LOG_ERR("LibGmapSrvDeinitFail");
|
||||
}
|
||||
|
||||
if (lib_gmap_client_deinit()) {
|
||||
LOG_ERR("LibGmapCliDeinitFail");
|
||||
}
|
||||
#endif /* CONFIG_BT_GMAP */
|
||||
|
||||
#if CONFIG_BT_HAS_CLIENT
|
||||
if (lib_has_client_deinit()) {
|
||||
LOG_ERR("LibHasCliDeinitFail");
|
||||
}
|
||||
#endif /* CONFIG_BT_HAS_CLIENT */
|
||||
|
||||
#if CONFIG_BT_HAS
|
||||
if (lib_has_deinit()) {
|
||||
LOG_ERR("LibHasDeinitFail");
|
||||
}
|
||||
#endif /* CONFIG_BT_HAS */
|
||||
|
||||
#if CONFIG_BT_VOCS_CLIENT
|
||||
if (lib_vocs_client_deinit()) {
|
||||
LOG_ERR("LibVocsClientDeinitFail");
|
||||
}
|
||||
#endif /* CONFIG_BT_VOCS_CLIENT */
|
||||
|
||||
#if CONFIG_BT_VOCS || CONFIG_BT_VOCS_CLIENT
|
||||
if (lib_vocs_deinit()) {
|
||||
LOG_ERR("LibVocsDeinitFail");
|
||||
}
|
||||
#endif /* CONFIG_BT_VOCS || CONFIG_BT_VOCS_CLIENT */
|
||||
|
||||
#if CONFIG_BT_VCP_VOL_REND
|
||||
if (lib_vcp_vol_rend_deinit()) {
|
||||
LOG_ERR("LibVcpVolRendDeinitFail");
|
||||
}
|
||||
#endif /* CONFIG_BT_VCP_VOL_REND */
|
||||
|
||||
#if CONFIG_BT_VCP_VOL_CTLR
|
||||
if (lib_vcp_vol_ctlr_deinit()) {
|
||||
LOG_ERR("LibVcpVolCtlrDeinitFail");
|
||||
}
|
||||
#endif /* CONFIG_BT_VCP_VOL_CTLR */
|
||||
|
||||
#if CONFIG_BT_TMAP
|
||||
if (lib_tmap_deinit()) {
|
||||
LOG_ERR("LibTmapDeinitFail");
|
||||
}
|
||||
#endif /* CONFIG_BT_TMAP */
|
||||
|
||||
#if CONFIG_BT_TBS
|
||||
if (lib_tbs_deinit()) {
|
||||
LOG_ERR("LibTbsDeinitFail");
|
||||
}
|
||||
#endif /* CONFIG_BT_TBS */
|
||||
|
||||
#if CONFIG_BT_TBS_CLIENT
|
||||
if (lib_tbs_client_deinit()) {
|
||||
LOG_ERR("LibTbsCliDeinitFail");
|
||||
}
|
||||
#endif /* CONFIG_BT_TBS_CLIENT */
|
||||
|
||||
#if CONFIG_BT_PBP
|
||||
if (lib_pbp_deinit()) {
|
||||
LOG_ERR("LibPbpDeinitFail");
|
||||
}
|
||||
#endif /* CONFIG_BT_PBP */
|
||||
|
||||
#if CONFIG_BT_MPL
|
||||
if (lib_mpl_deinit()) {
|
||||
LOG_ERR("LibMplDeinitFail");
|
||||
}
|
||||
#endif /* CONFIG_BT_MPL */
|
||||
|
||||
#if CONFIG_BT_MICP_MIC_DEV
|
||||
if (lib_micp_mic_dev_deinit()) {
|
||||
LOG_ERR("LibMicpMicDevDeinitFail");
|
||||
}
|
||||
#endif /* CONFIG_BT_MICP_MIC_DEV */
|
||||
|
||||
#if CONFIG_BT_MICP_MIC_CTLR
|
||||
if (lib_micp_mic_ctlr_deinit()) {
|
||||
LOG_ERR("LibMicpMicCtlrDeinitFail");
|
||||
}
|
||||
#endif /* CONFIG_BT_MICP_MIC_CTLR */
|
||||
|
||||
#if CONFIG_BT_MCTL
|
||||
if (lib_media_proxy_deinit()) {
|
||||
LOG_ERR("LibMediaProxyDeinitFail");
|
||||
}
|
||||
#endif /* CONFIG_BT_MCTL */
|
||||
|
||||
#if CONFIG_BT_MCS
|
||||
if (lib_mcs_deinit()) {
|
||||
LOG_ERR("LibMcsDeinitFail");
|
||||
}
|
||||
#endif /* CONFIG_BT_MCS */
|
||||
|
||||
#if CONFIG_BT_MCC
|
||||
if (lib_mcc_deinit()) {
|
||||
LOG_ERR("LibMccDeinitFail");
|
||||
}
|
||||
#endif /* CONFIG_BT_MCC */
|
||||
|
||||
#if CONFIG_BT_CSIP_SET_COORDINATOR
|
||||
if (lib_csip_set_coordinator_deinit()) {
|
||||
LOG_ERR("LibCsipSetCoordinatorDeinitFail");
|
||||
}
|
||||
#endif /* CONFIG_BT_CSIP_SET_COORDINATOR */
|
||||
|
||||
#if CONFIG_BT_CSIP_SET_MEMBER
|
||||
if (lib_csip_set_member_deinit()) {
|
||||
LOG_ERR("LibCsipSetMemberDeinitFail");
|
||||
}
|
||||
#endif /* CONFIG_BT_CSIP_SET_MEMBER */
|
||||
|
||||
#if CONFIG_BT_BAP_STREAM
|
||||
if (lib_codec_deinit()) {
|
||||
LOG_ERR("LibCodecDeinitFail");
|
||||
}
|
||||
#endif /* CONFIG_BT_BAP_STREAM */
|
||||
|
||||
#if CONFIG_BT_CCP_CALL_CONTROL_SERVER
|
||||
if (lib_ccp_call_control_server_deinit()) {
|
||||
LOG_ERR("LibCcpCallControlServerDeinitFail");
|
||||
}
|
||||
#endif /* CONFIG_BT_CCP_CALL_CONTROL_SERVER */
|
||||
|
||||
#if CONFIG_BT_CCP_CALL_CONTROL_CLIENT
|
||||
if (lib_ccp_call_control_client_deinit()) {
|
||||
LOG_ERR("LibCcpCallControlClientDeinitFail");
|
||||
}
|
||||
#endif /* CONFIG_BT_CCP_CALL_CONTROL_CLIENT */
|
||||
|
||||
if (lib_ccid_deinit()) {
|
||||
LOG_ERR("LibCcidDeinitFail");
|
||||
}
|
||||
|
||||
#if CONFIG_BT_CAP_COMMANDER
|
||||
if (lib_cap_commander_deinit()) {
|
||||
LOG_ERR("LibCapComDeinitFail");
|
||||
}
|
||||
#endif /* CONFIG_BT_CAP_COMMANDER */
|
||||
|
||||
#if CONFIG_BT_CAP_ACCEPTOR
|
||||
if (lib_cap_acceptor_deinit()) {
|
||||
LOG_ERR("LibCapAccDeinitFail");
|
||||
}
|
||||
#endif /* CONFIG_BT_CAP_ACCEPTOR */
|
||||
|
||||
#if CONFIG_BT_CAP_INITIATOR
|
||||
if (lib_cap_initiator_deinit()) {
|
||||
LOG_ERR("LibCapIniDeinitFail");
|
||||
}
|
||||
#endif /* CONFIG_BT_CAP_INITIATOR */
|
||||
|
||||
#if CONFIG_BT_CAP
|
||||
if (lib_cap_stream_deinit()) {
|
||||
LOG_ERR("LibCapStreamDeinitFail");
|
||||
}
|
||||
#endif /* CONFIG_BT_CAP */
|
||||
|
||||
#if CONFIG_BT_CAP_INITIATOR_UNICAST || CONFIG_BT_CAP_COMMANDER
|
||||
if (lib_cap_common_deinit()) {
|
||||
LOG_ERR("LibCapCommonDeinitFail");
|
||||
}
|
||||
#endif /* CONFIG_BT_CAP_INITIATOR_UNICAST || CONFIG_BT_CAP_COMMANDER */
|
||||
|
||||
#if CONFIG_BT_BAP_UNICAST_SERVER
|
||||
if (lib_bap_unicast_server_deinit()) {
|
||||
LOG_ERR("LibBapUniSrvDeinitFail");
|
||||
}
|
||||
#endif /* CONFIG_BT_BAP_UNICAST_SERVER */
|
||||
|
||||
#if CONFIG_BT_BAP_UNICAST_CLIENT
|
||||
if (lib_bap_unicast_client_deinit()) {
|
||||
LOG_ERR("LibBapUniCliDeinitFail");
|
||||
}
|
||||
#endif /* CONFIG_BT_BAP_UNICAST_CLIENT */
|
||||
|
||||
#if CONFIG_BT_BAP_BROADCAST_ASSISTANT
|
||||
if (lib_bap_broadcast_assistant_deinit()) {
|
||||
LOG_ERR("LibBapBaDeinitFail");
|
||||
}
|
||||
#endif /* CONFIG_BT_BAP_BROADCAST_ASSISTANT */
|
||||
|
||||
#if CONFIG_BT_BAP_SCAN_DELEGATOR
|
||||
if (lib_bap_scan_delegator_deinit()) {
|
||||
LOG_ERR("LibBapSdeDeinitFail");
|
||||
}
|
||||
#endif /* CONFIG_BT_BAP_SCAN_DELEGATOR */
|
||||
|
||||
#if CONFIG_BT_BAP_BROADCAST_SOURCE
|
||||
if (lib_bap_broadcast_source_deinit()) {
|
||||
LOG_ERR("LibBapBsrcDeinitFail");
|
||||
}
|
||||
#endif /* CONFIG_BT_BAP_BROADCAST_SOURCE */
|
||||
|
||||
#if CONFIG_BT_BAP_BROADCAST_SINK
|
||||
if (lib_bap_broadcast_sink_deinit()) {
|
||||
LOG_ERR("LibBapBsnkDeinitFail");
|
||||
}
|
||||
#endif /* CONFIG_BT_BAP_BROADCAST_SINK */
|
||||
|
||||
#if CONFIG_BT_PACS
|
||||
if (lib_pacs_deinit()) {
|
||||
LOG_ERR("LibPacsDeinitFail");
|
||||
}
|
||||
#endif /* CONFIG_BT_PACS */
|
||||
|
||||
#if CONFIG_BT_ASCS
|
||||
if (lib_ascs_deinit()) {
|
||||
LOG_ERR("LibAscsDeinitFail");
|
||||
}
|
||||
#endif /* CONFIG_BT_ASCS */
|
||||
|
||||
#if CONFIG_BT_BAP_STREAM
|
||||
if (lib_bap_stream_deinit()) {
|
||||
LOG_ERR("LibBapStreamDeinitFail");
|
||||
}
|
||||
|
||||
if (lib_bap_iso_deinit()) {
|
||||
LOG_ERR("LibBapIsoDeinitFail");
|
||||
}
|
||||
#endif /* CONFIG_BT_BAP_STREAM */
|
||||
|
||||
#if CONFIG_BT_BAP_BASE
|
||||
if (lib_bap_base_deinit()) {
|
||||
LOG_ERR("LibBapBaseDeinitFail");
|
||||
}
|
||||
#endif /* CONFIG_BT_BAP_BASE */
|
||||
|
||||
#if CONFIG_BT_AICS_CLIENT
|
||||
if (lib_aics_client_deinit()) {
|
||||
LOG_ERR("LibAicsClientDeinitFail");
|
||||
}
|
||||
#endif /* CONFIG_BT_AICS_CLIENT */
|
||||
|
||||
#if CONFIG_BT_AICS || CONFIG_BT_AICS_CLIENT
|
||||
if (lib_aics_deinit()) {
|
||||
LOG_ERR("LibAicsDeinitFail");
|
||||
}
|
||||
#endif /* CONFIG_BT_AICS || CONFIG_BT_AICS_CLIENT */
|
||||
}
|
||||
|
||||
int bt_le_audio_init(void)
|
||||
{
|
||||
int err;
|
||||
@@ -2112,13 +2374,13 @@ int bt_le_audio_init(void)
|
||||
|
||||
err = lib_audio_resources_init();
|
||||
if (err) {
|
||||
return err;
|
||||
goto deinit_lib;
|
||||
}
|
||||
|
||||
#if CONFIG_BT_OTS || CONFIG_BT_OTS_CLIENT
|
||||
err = bt_le_l2cap_ots_init();
|
||||
if (err) {
|
||||
return err;
|
||||
goto deinit_lib;
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -2128,20 +2390,33 @@ int bt_le_audio_init(void)
|
||||
err = bt_le_nimble_audio_init();
|
||||
#endif
|
||||
if (err) {
|
||||
#if CONFIG_BT_OTS || CONFIG_BT_OTS_CLIENT
|
||||
bt_le_l2cap_ots_deinit();
|
||||
#endif
|
||||
return err;
|
||||
goto deinit_ots;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
deinit_ots:
|
||||
#if CONFIG_BT_OTS || CONFIG_BT_OTS_CLIENT
|
||||
bt_le_l2cap_ots_deinit();
|
||||
#endif
|
||||
deinit_lib:
|
||||
lib_audio_resources_deinit();
|
||||
return err;
|
||||
}
|
||||
|
||||
void bt_le_audio_deinit(void)
|
||||
{
|
||||
#if CONFIG_BT_BLUEDROID_ENABLED
|
||||
bt_le_bluedroid_audio_deinit();
|
||||
#else
|
||||
bt_le_nimble_audio_deinit();
|
||||
#endif
|
||||
|
||||
#if CONFIG_BT_OTS || CONFIG_BT_OTS_CLIENT
|
||||
bt_le_l2cap_ots_deinit();
|
||||
#endif
|
||||
|
||||
lib_audio_resources_deinit();
|
||||
}
|
||||
|
||||
#if BLE_AUDIO_SVC_DEFERRED_ADD
|
||||
@@ -2156,6 +2431,17 @@ int bt_le_ascs_init(void)
|
||||
return bt_le_nimble_ascs_init();
|
||||
#endif
|
||||
}
|
||||
|
||||
int bt_le_ascs_deinit(void)
|
||||
{
|
||||
LOG_DBG("AscsDeinit");
|
||||
|
||||
#if CONFIG_BT_BLUEDROID_ENABLED
|
||||
return bt_le_bluedroid_ascs_deinit();
|
||||
#else
|
||||
return bt_le_nimble_ascs_deinit();
|
||||
#endif
|
||||
}
|
||||
#endif /* CONFIG_BT_ASCS */
|
||||
|
||||
#if CONFIG_BT_BAP_SCAN_DELEGATOR
|
||||
@@ -2169,6 +2455,17 @@ int bt_le_bass_init(void)
|
||||
return bt_le_nimble_bass_init();
|
||||
#endif
|
||||
}
|
||||
|
||||
int bt_le_bass_deinit(void)
|
||||
{
|
||||
LOG_DBG("BassDeinit");
|
||||
|
||||
#if CONFIG_BT_BLUEDROID_ENABLED
|
||||
return bt_le_bluedroid_bass_deinit();
|
||||
#else
|
||||
return bt_le_nimble_bass_deinit();
|
||||
#endif
|
||||
}
|
||||
#endif /* CONFIG_BT_BAP_SCAN_DELEGATOR */
|
||||
|
||||
#if CONFIG_BT_TMAP
|
||||
@@ -2196,6 +2493,17 @@ int bt_le_gtbs_init(void)
|
||||
#endif
|
||||
}
|
||||
|
||||
int bt_le_gtbs_deinit(void)
|
||||
{
|
||||
LOG_DBG("GtbsDeinit");
|
||||
|
||||
#if CONFIG_BT_BLUEDROID_ENABLED
|
||||
return bt_le_bluedroid_gtbs_deinit();
|
||||
#else
|
||||
return bt_le_nimble_gtbs_deinit();
|
||||
#endif
|
||||
}
|
||||
|
||||
int bt_le_tbs_init(void)
|
||||
{
|
||||
LOG_DBG("TbsInit");
|
||||
@@ -2206,6 +2514,17 @@ int bt_le_tbs_init(void)
|
||||
return bt_le_nimble_tbs_init();
|
||||
#endif
|
||||
}
|
||||
|
||||
int bt_le_tbs_deinit(uint8_t bearer_index)
|
||||
{
|
||||
LOG_DBG("TbsDeinit[%u]", bearer_index);
|
||||
|
||||
#if CONFIG_BT_BLUEDROID_ENABLED
|
||||
return bt_le_bluedroid_tbs_deinit(bearer_index);
|
||||
#else
|
||||
return bt_le_nimble_tbs_deinit(bearer_index);
|
||||
#endif
|
||||
}
|
||||
#endif /* CONFIG_BT_TBS */
|
||||
|
||||
#if CONFIG_BT_HAS
|
||||
@@ -2261,6 +2580,40 @@ int bt_le_micp_mic_dev_init(void)
|
||||
#endif /* CONFIG_BT_MICP_MIC_DEV */
|
||||
#endif /* BLE_AUDIO_SVC_DEFERRED_ADD */
|
||||
|
||||
#if CONFIG_BT_PACS
|
||||
int bt_le_pacs_deinit(void)
|
||||
{
|
||||
LOG_DBG("PacsDeinit");
|
||||
|
||||
#if CONFIG_BT_BLUEDROID_ENABLED
|
||||
return bt_le_bluedroid_pacs_deinit();
|
||||
#else
|
||||
return bt_le_nimble_pacs_deinit();
|
||||
#endif
|
||||
}
|
||||
#endif /* CONFIG_BT_PACS */
|
||||
|
||||
#if CONFIG_BT_CSIP_SET_MEMBER
|
||||
int bt_le_csis_deinit(const void *svc_inst)
|
||||
{
|
||||
struct bt_gatt_service *csis_svc;
|
||||
|
||||
LOG_DBG("CsisDeinit");
|
||||
|
||||
csis_svc = lib_csip_set_member_svc_get(svc_inst);
|
||||
if (!csis_svc) {
|
||||
LOG_ERR("CsisSvcGetFail");
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
#if CONFIG_BT_BLUEDROID_ENABLED
|
||||
return bt_le_bluedroid_csis_deinit(csis_svc);
|
||||
#else
|
||||
return bt_le_nimble_csis_deinit(csis_svc);
|
||||
#endif
|
||||
}
|
||||
#endif /* CONFIG_BT_CSIP_SET_MEMBER */
|
||||
|
||||
int bt_le_audio_start(void *info)
|
||||
{
|
||||
LOG_DBG("AudioStart");
|
||||
|
||||
@@ -44,10 +44,12 @@ static BT_AUDIO_EXT_RAM_BSS_ATTR sys_slist_t l2cap_servers;
|
||||
extern int bt_gatt_ots_conn_cb_register(void);
|
||||
extern void bt_gatt_ots_conn_cb_unregister(void);
|
||||
extern int bt_gatt_ots_instances_prepare(void);
|
||||
extern void bt_ots_instances_rewind(void);
|
||||
#endif /* CONFIG_BT_OTS */
|
||||
#if CONFIG_BT_OTS_CLIENT
|
||||
extern int bt_gatt_ots_client_conn_cb_register(void);
|
||||
extern void bt_gatt_ots_client_conn_cb_unregister(void);
|
||||
extern void bt_ots_client_unregister_all(void);
|
||||
#endif /* CONFIG_BT_OTS_CLIENT */
|
||||
extern int bt_gatt_ots_l2cap_init(void);
|
||||
|
||||
@@ -361,17 +363,31 @@ static void l2cap_sent(uint16_t conn_handle, uint16_t psm)
|
||||
}
|
||||
}
|
||||
|
||||
_IDF_ONLY
|
||||
void bt_le_l2cap_event_free(void *data)
|
||||
{
|
||||
struct bt_le_l2cap_event *qev = data;
|
||||
|
||||
if (qev == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
/* Only RECEIVED carries a buffer of its own; the rest are header-only. */
|
||||
if (qev->type == BT_LE_L2CAP_EVENT_RECEIVED) {
|
||||
free(qev->received.data);
|
||||
}
|
||||
|
||||
free(qev);
|
||||
}
|
||||
|
||||
static int l2cap_post_event(struct bt_le_l2cap_event *qev)
|
||||
{
|
||||
int err;
|
||||
|
||||
err = bt_le_iso_task_post(ISO_QUEUE_ITEM_TYPE_L2CAP_EVENT, qev, sizeof(*qev));
|
||||
if (err) {
|
||||
LOG_ERR("L2capPostFail[%d][%u]", err, qev->type);
|
||||
if (qev->type == BT_LE_L2CAP_EVENT_RECEIVED) {
|
||||
free(qev->received.data);
|
||||
}
|
||||
free(qev);
|
||||
ISO_POST_FAIL_LOG(err, "L2capPostFail[%d][%u]", err, qev->type);
|
||||
bt_le_l2cap_event_free(qev);
|
||||
}
|
||||
|
||||
return err;
|
||||
@@ -811,14 +827,20 @@ void bt_le_l2cap_ots_deinit(void)
|
||||
{
|
||||
LOG_DBG("L2capOtsDeinit");
|
||||
|
||||
/* TODO(deinit): unassign OTS obj managers / clear instance->obj_manager. */
|
||||
|
||||
/* Symmetric with the registers in _init: conn_cbs is never reset elsewhere. */
|
||||
#if CONFIG_BT_OTS
|
||||
bt_gatt_ots_conn_cb_unregister();
|
||||
|
||||
/* Give the instances handed out by bt_ots_free_instance_get() back to the
|
||||
* pool; the profiles that took them are released right after this. */
|
||||
bt_ots_instances_rewind();
|
||||
#endif /* CONFIG_BT_OTS */
|
||||
#if CONFIG_BT_OTS_CLIENT
|
||||
bt_gatt_ots_client_conn_cb_unregister();
|
||||
|
||||
/* Before lib_audio_resources_deinit() frees the bt_ots_client instances
|
||||
* the table points at - this runs first in bt_le_audio_deinit(). */
|
||||
bt_ots_client_unregister_all();
|
||||
#endif /* CONFIG_BT_OTS_CLIENT */
|
||||
|
||||
#if CONFIG_BT_BLUEDROID_ENABLED
|
||||
|
||||
@@ -106,6 +106,8 @@ int bt_le_l2cap_post_sent(uint16_t conn_handle, uint16_t psm);
|
||||
|
||||
void bt_le_l2cap_handle_event(void *data, size_t data_len);
|
||||
|
||||
void bt_le_l2cap_event_free(void *data);
|
||||
|
||||
int bt_le_l2cap_ots_init(void);
|
||||
|
||||
void bt_le_l2cap_ots_deinit(void);
|
||||
|
||||
@@ -563,6 +563,9 @@ int bt_ots_init(struct bt_ots *ots,
|
||||
|
||||
/* Check OACP supported features against Kconfig. */
|
||||
if (ots_init->features.oacp & (~((uint32_t) OACP_FEAT))) {
|
||||
/* cb is what bt_ots_instances_rewind() reads to decide there is an init
|
||||
* to reverse, so every bail after the assignment above has to undo it. */
|
||||
ots->cb = NULL;
|
||||
return -ENOTSUP;
|
||||
}
|
||||
|
||||
@@ -575,6 +578,7 @@ int bt_ots_init(struct bt_ots *ots,
|
||||
|
||||
/* Check OLCP supported features against Kconfig. */
|
||||
if (ots_init->features.olcp & (~((uint32_t) OLCP_FEAT))) {
|
||||
ots->cb = NULL;
|
||||
return -ENOTSUP;
|
||||
}
|
||||
ots->features.olcp = ots_init->features.olcp;
|
||||
@@ -583,6 +587,7 @@ int bt_ots_init(struct bt_ots *ots,
|
||||
/* Register L2CAP context. */
|
||||
err = bt_gatt_ots_l2cap_register(&ots->l2cap);
|
||||
if (err) {
|
||||
ots->cb = NULL;
|
||||
return err;
|
||||
}
|
||||
|
||||
@@ -594,6 +599,7 @@ int bt_ots_init(struct bt_ots *ots,
|
||||
LOG_ERR("OtsL2capUnregFail[%d]", unreg_err);
|
||||
}
|
||||
|
||||
ots->cb = NULL;
|
||||
return err;
|
||||
}
|
||||
|
||||
@@ -768,6 +774,38 @@ struct bt_ots *bt_ots_free_instance_get(void)
|
||||
return &BT_GATT_OTS_INSTANCE_LIST_START[instance_cnt++];
|
||||
}
|
||||
|
||||
/* Both pools only count up, so without this a second init finds them exhausted
|
||||
* (McsNoFreeOtsInst / OtsObjMgrInstUnavail). Safe here: the profile that took an
|
||||
* instance has dropped its reference by now. */
|
||||
void bt_ots_instances_rewind(void)
|
||||
{
|
||||
for (struct bt_ots *instance = BT_GATT_OTS_INSTANCE_LIST_START;
|
||||
instance != BT_GATT_OTS_INSTANCE_LIST_END; instance++) {
|
||||
/* cb is the marker for "bt_ots_init() ran here": it is set on entry and
|
||||
* cleared again on every failure path, so it is exactly the set of
|
||||
* instances with something to reverse. Reverse order of that function. */
|
||||
if (instance->cb != NULL) {
|
||||
k_work_deinit_delayable(&instance->olcp_ind.work);
|
||||
k_work_deinit_delayable(&instance->oacp_ind.work);
|
||||
|
||||
if (IS_ENABLED(CONFIG_BT_OTS_DIR_LIST_OBJ)) {
|
||||
bt_ots_dir_list_deinit(&instance->dir_list);
|
||||
}
|
||||
|
||||
(void)bt_gatt_service_unregister(instance->service);
|
||||
(void)bt_gatt_ots_l2cap_unregister(&instance->l2cap);
|
||||
instance->cb = NULL;
|
||||
}
|
||||
|
||||
if (instance->obj_manager != NULL) {
|
||||
bt_gatt_ots_obj_manager_release(instance->obj_manager);
|
||||
instance->obj_manager = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
instance_cnt = 0;
|
||||
}
|
||||
|
||||
int bt_gatt_ots_instances_prepare(void)
|
||||
{
|
||||
uint32_t index;
|
||||
|
||||
@@ -637,6 +637,15 @@ int bt_ots_client_unregister(uint8_t index)
|
||||
return 0;
|
||||
}
|
||||
|
||||
void bt_ots_client_unregister_all(void)
|
||||
{
|
||||
for (uint8_t i = 0; i < ARRAY_SIZE(otc_insts); i++) {
|
||||
if (otc_insts[i].otc_inst != NULL) {
|
||||
(void)bt_ots_client_unregister(i);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
__attribute__((unused))
|
||||
int bt_ots_client_read_feature(struct bt_ots_client *otc_inst,
|
||||
struct bt_conn *conn)
|
||||
|
||||
@@ -320,6 +320,16 @@ void bt_ots_dir_list_init(struct bt_ots_dir_list **dir_list, void *obj_manager)
|
||||
dir_list_update_size(*dir_list, obj_manager);
|
||||
}
|
||||
|
||||
void bt_ots_dir_list_deinit(struct bt_ots_dir_list **dir_list)
|
||||
{
|
||||
if (*dir_list == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
memset(*dir_list, 0, sizeof(**dir_list));
|
||||
*dir_list = NULL;
|
||||
}
|
||||
|
||||
ssize_t bt_ots_dir_list_content_get(struct bt_ots_dir_list *dir_list, void *obj_manager,
|
||||
void **data, size_t len, off_t offset)
|
||||
{
|
||||
|
||||
@@ -161,6 +161,7 @@ void bt_ots_dir_list_selected(struct bt_ots_dir_list *dir_list, void *obj_manage
|
||||
struct bt_gatt_ots_object *cur_obj);
|
||||
void bt_ots_dir_list_content_changed(struct bt_ots_dir_list *dir_list, void *obj_manager);
|
||||
void bt_ots_dir_list_init(struct bt_ots_dir_list **dir_list, void *obj_manager);
|
||||
void bt_ots_dir_list_deinit(struct bt_ots_dir_list **dir_list);
|
||||
ssize_t bt_ots_dir_list_content_get(struct bt_ots_dir_list *dir_list, void *obj_manager,
|
||||
void **data, size_t len, off_t offset);
|
||||
bool bt_ots_dir_list_is_idle(const struct bt_ots_dir_list *dir_list);
|
||||
|
||||
@@ -256,3 +256,19 @@ void *bt_gatt_ots_obj_manager_assign(void)
|
||||
|
||||
return cur_manager;
|
||||
}
|
||||
|
||||
void bt_gatt_ots_obj_manager_release(void *obj_manager)
|
||||
{
|
||||
struct bt_gatt_ots_obj_manager *manager = obj_manager;
|
||||
|
||||
if (manager == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < CONFIG_BT_OTS_MAX_OBJ_CNT; i++) {
|
||||
manager->pool[i].is_allocated = false;
|
||||
}
|
||||
|
||||
sys_dlist_init(&manager->list);
|
||||
manager->is_assigned = false;
|
||||
}
|
||||
|
||||
@@ -43,6 +43,8 @@ bool bt_gatt_ots_obj_manager_obj_contains(void *obj_manager, struct bt_gatt_ots_
|
||||
|
||||
void *bt_gatt_ots_obj_manager_assign(void);
|
||||
|
||||
void bt_gatt_ots_obj_manager_release(void *obj_manager);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -32,86 +32,128 @@ struct bt_gatt_service;
|
||||
extern struct bt_aics *lib_aics_insts_get(void);
|
||||
extern void *lib_aics_svc_get(struct bt_aics *aics);
|
||||
extern int lib_aics_init(void);
|
||||
extern int lib_aics_deinit(void);
|
||||
extern int lib_aics_client_init(void);
|
||||
extern int lib_aics_client_deinit(void);
|
||||
|
||||
extern int lib_bap_base_init(void);
|
||||
extern int lib_bap_base_deinit(void);
|
||||
extern int lib_bap_iso_init(void);
|
||||
extern int lib_bap_iso_deinit(void);
|
||||
extern int lib_bap_stream_init(void);
|
||||
extern int lib_bap_stream_deinit(void);
|
||||
|
||||
extern struct bt_gatt_service *lib_ascs_svc_get(void);
|
||||
extern int lib_ascs_init(void);
|
||||
extern int lib_ascs_deinit(void);
|
||||
|
||||
extern struct bt_gatt_service *lib_bap_bass_svc_get(void);
|
||||
extern int lib_bap_broadcast_assistant_init(void);
|
||||
extern int lib_bap_broadcast_assistant_deinit(void);
|
||||
extern int lib_bap_broadcast_sink_init(void);
|
||||
extern int lib_bap_broadcast_sink_deinit(void);
|
||||
extern int lib_bap_broadcast_source_init(void);
|
||||
extern int lib_bap_broadcast_source_deinit(void);
|
||||
extern int lib_bap_scan_delegator_init(void);
|
||||
extern int lib_bap_scan_delegator_deinit(void);
|
||||
extern int lib_bap_unicast_client_init(void);
|
||||
extern int lib_bap_unicast_client_deinit(void);
|
||||
extern int lib_bap_unicast_server_init(void);
|
||||
extern int lib_bap_unicast_server_deinit(void);
|
||||
|
||||
extern struct bt_gatt_service *lib_pacs_svc_get(void);
|
||||
extern int lib_pacs_init(void);
|
||||
extern int lib_pacs_deinit(void);
|
||||
|
||||
extern struct bt_gatt_service *lib_cas_svc_get(void);
|
||||
|
||||
extern int lib_cap_common_init(void);
|
||||
extern int lib_cap_common_deinit(void);
|
||||
extern int lib_cap_stream_init(void);
|
||||
extern int lib_cap_stream_deinit(void);
|
||||
extern int lib_cap_initiator_init(void);
|
||||
extern int lib_cap_initiator_deinit(void);
|
||||
extern int lib_cap_acceptor_init(void);
|
||||
extern int lib_cap_acceptor_deinit(void);
|
||||
extern int lib_cap_commander_init(void);
|
||||
extern int lib_cap_commander_deinit(void);
|
||||
|
||||
extern int lib_ccid_init(void);
|
||||
extern int lib_ccid_deinit(void);
|
||||
|
||||
extern int lib_ccp_call_control_client_init(void);
|
||||
extern int lib_ccp_call_control_client_deinit(void);
|
||||
extern int lib_ccp_call_control_server_init(void);
|
||||
extern int lib_ccp_call_control_server_deinit(void);
|
||||
|
||||
extern int lib_codec_init(void);
|
||||
extern int lib_codec_deinit(void);
|
||||
|
||||
extern int lib_csip_set_coordinator_init(void);
|
||||
extern int lib_csip_set_coordinator_deinit(void);
|
||||
extern void *lib_csip_set_member_svc_get(const void *svc_inst);
|
||||
extern int lib_csip_set_member_init(void);
|
||||
extern int lib_csip_set_member_deinit(void);
|
||||
|
||||
extern int lib_gmap_client_init(void);
|
||||
extern int lib_gmap_client_deinit(void);
|
||||
extern struct bt_gatt_service *lib_gmas_svc_get(void);
|
||||
extern int lib_gmap_server_deinit(void);
|
||||
|
||||
extern struct bt_gatt_service *lib_has_svc_get(void);
|
||||
extern int lib_has_init(void);
|
||||
extern int lib_has_deinit(void);
|
||||
extern int lib_has_client_init(void);
|
||||
extern int lib_has_client_deinit(void);
|
||||
|
||||
extern int lib_mcc_init(void);
|
||||
extern int lib_mcc_deinit(void);
|
||||
extern struct bt_gatt_service *lib_gmcs_svc_get(void);
|
||||
extern struct bt_gatt_service *lib_mcs_server_list_get(void);
|
||||
extern int lib_mcs_init(void);
|
||||
extern int lib_mcs_deinit(void);
|
||||
|
||||
extern int lib_media_proxy_init(void);
|
||||
extern int lib_media_proxy_deinit(void);
|
||||
|
||||
extern int lib_micp_mic_ctlr_init(void);
|
||||
extern int lib_micp_mic_ctlr_deinit(void);
|
||||
extern struct bt_gatt_service *lib_mics_svc_get(void);
|
||||
extern int lib_micp_mic_dev_init(void);
|
||||
extern int lib_micp_mic_dev_deinit(void);
|
||||
|
||||
extern int lib_mpl_init(void);
|
||||
extern int lib_mpl_deinit(void);
|
||||
|
||||
extern int lib_pbp_init(void);
|
||||
extern int lib_pbp_deinit(void);
|
||||
|
||||
extern int lib_tbs_client_init(void);
|
||||
extern int lib_tbs_client_deinit(void);
|
||||
extern struct bt_gatt_service *lib_gtbs_svc_get(void);
|
||||
extern struct bt_gatt_service *lib_tbs_server_list_get(void);
|
||||
extern int lib_tbs_init(void);
|
||||
extern int lib_tbs_deinit(void);
|
||||
|
||||
extern struct bt_gatt_service *lib_tmas_svc_get(void);
|
||||
extern int lib_tmap_init(void);
|
||||
extern int lib_tmap_deinit(void);
|
||||
|
||||
extern int lib_vcp_vol_ctlr_init(void);
|
||||
extern int lib_vcp_vol_ctlr_deinit(void);
|
||||
extern struct bt_gatt_service *lib_vcs_svc_get(void);
|
||||
extern int lib_vcp_vol_rend_init(void);
|
||||
extern int lib_vcp_vol_rend_deinit(void);
|
||||
|
||||
struct bt_vocs;
|
||||
struct bt_vocs_server;
|
||||
|
||||
extern int lib_vocs_client_init(void);
|
||||
extern int lib_vocs_client_deinit(void);
|
||||
extern struct bt_vocs_server *lib_vocs_insts_get(void);
|
||||
extern void *lib_vocs_svc_get(struct bt_vocs *vocs);
|
||||
extern int lib_vocs_init(void);
|
||||
extern int lib_vocs_deinit(void);
|
||||
|
||||
struct bt_conn;
|
||||
struct bt_gatt_attr;
|
||||
|
||||
Submodule components/bt/esp_ble_audio/lib/lib updated: 7c6b2930f2...3ada1f9e75
Reference in New Issue
Block a user