123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658 |
- /*
- * Copyright (c) 2017 Actions Semi Co., Ltd.
- *
- * SPDX-License-Identifier: Apache-2.0
- */
- /**
- * @file
- * @brief btsrvice sco
- */
- #define SYS_LOG_DOMAIN "btsrv_sco"
- #include "btsrv_os_common.h"
- #include "btsrv_inner.h"
- /* WAIT TODO: Not ready work with two sco link as the same time */
- //#define DECODE_PLAYBACK_MCU 1
- #define BTSPEECH_SCO_PACKET_SIZE (60) /* bytes */
- #define SCO_EXCEPT_CACHE_SIZE (60)
- #define SCO_CHECK_DROP_MUTE_FRAME_CNT (50) /* Check drop mute frame number */
- static btsrv_sco_callback sco_user_callback;
- struct btsrv_sco_context_info {
- struct bt_conn *sco_conn;
- uint8_t last_seq_no : 3;
- uint8_t first_frame : 1;
- uint8_t mute_frame : 1;
- uint8_t check_mute_finish : 1;
- uint8_t drop_flag : 1;
- uint8_t sco_rx_last_pkg_status_flag;
- uint16_t sco_rx_pkt_cache_len;
- uint8_t *sco_rx_cache;
- uint16_t frame_cnt;
- uint16_t frame_cached_len;
- uint16_t drop_frame;
- uint16_t sco_except_cache_len;
- uint8_t *sco_except_cache;
- };
- static struct btsrv_sco_context_info sco_context_info;
- static struct btsrv_sco_context_info *sco_context;
- static void _btsrv_sco_connected_cb(struct bt_conn *conn, uint8_t err)
- {
- if (hostif_bt_conn_get_type(conn) != BT_CONN_TYPE_SCO)
- return;
- /* ref for bt servcie process MSG_BTSRV_SCO_CONNECTED,
- * need unref conn after process MSG_BTSRV_SCO_CONNECTED.
- */
- hostif_bt_conn_ref(conn);
- btsrv_event_notify_ext(MSG_BTSRV_SCO, MSG_BTSRV_SCO_CONNECTED, conn, err);
- }
- static void _btsrv_sco_disconnected_cb(struct bt_conn *conn, uint8_t reason)
- {
- if (hostif_bt_conn_get_type(conn) != BT_CONN_TYPE_SCO)
- return;
- /* ref for bt servcie process MSG_BTSRV_SCO_DISCONNECTED,
- * need unref conn after process MSG_BTSRV_SCO_DISCONNECTED.
- */
- hostif_bt_conn_ref(conn);
- btsrv_event_notify_ext(MSG_BTSRV_SCO, MSG_BTSRV_SCO_DISCONNECTED, conn, reason);
- }
- static void _btsrv_sco_security_changed_cb(struct bt_conn *conn, bt_security_t level, enum bt_security_err err)
- {
- if (hostif_bt_conn_get_type(conn) != BT_CONN_TYPE_SCO)
- return;
- }
- static int _btsrv_sco_mscb_seq_convert(uint8_t seq)
- {
- const uint8_t msbc_head_flag[4] = {0x08, 0x38, 0xc8, 0xf8};
- int i;
- for (i = 0; i < ARRAY_SIZE(msbc_head_flag); i++) {
- if (seq == msbc_head_flag[i]) {
- return i;
- }
- }
- return -1;
- }
- #ifdef DECODE_PLAYBACK_MCU
- static int _btsrv_sco_insert_package(uint8_t *data, uint8_t len, int num)
- {
- SYS_LOG_INF("lost %d packages\n", num);
- while (num > 0) {
- data[0] = 0;
- data[1] = 1;
- sco_user_callback(BTSRV_SCO_DATA_INDICATED, data, BTSPEECH_SCO_PACKET_SIZE);
- sco_context->last_seq_no = (sco_context->last_seq_no & 0x03) + 1;
- num--;
- }
- return 0;
- }
- #endif
- static int _btsrv_find_really_msbc_pkt(uint8_t *data_buf, uint16_t pkt_length)
- {
- uint8_t i;
- uint8_t valid_len;
- uint8_t remain_len;
- for(i=3; i < (pkt_length - 2); i++)
- {
- if((data_buf[i] == 0xad) && (data_buf[i+1] == 0x00) && (data_buf[i+2] == 0x00))
- {
- remain_len = i - 2;
- valid_len = pkt_length - i + 2;
- memcpy(sco_context->sco_except_cache + sco_context->sco_except_cache_len, (uint8_t *)&data_buf[i-2], valid_len);
- sco_context->sco_except_cache_len += valid_len;
- //printk("get flag:%d_%d\n", remain_len, valid_len);
- return 0;
- }
- }
- return -1;
- }
- static int _btsrv_read_msbc_pkt(uint8_t *data, uint16_t pkt_length)
- {
- int ret = -1;
- if((data[2] == 0xad) && (data[3] == 0x00) && (data[4] == 0x00))
- {
- sco_context->sco_except_cache_len = 0;
- ret = 0;
- goto exit;
- }
- //printk("wrong head:%d_%d\n", pkt_length, sco_context->sco_except_cache_len);
- if (sco_context->sco_except_cache_len > 0) {
- uint8_t remain_len;
- uint8_t start_len;
- uint8_t temp_buf[120];
- memset(temp_buf, 0, 120);
- start_len = sco_context->sco_except_cache_len;
- remain_len = pkt_length - sco_context->sco_except_cache_len;
- memcpy(temp_buf, sco_context->sco_except_cache, sco_context->sco_except_cache_len);
- sco_context->sco_except_cache_len = 0;
- memcpy(&temp_buf[start_len], data, remain_len);
- //printf("get pkt:%d_%d\n", remain_len, start_len);
- _btsrv_find_really_msbc_pkt(data, pkt_length);
- memcpy(data, temp_buf, pkt_length);
- ret = 0;
- goto exit;
- }
- if (_btsrv_find_really_msbc_pkt(data, pkt_length) < 0) {
- //printk("wrong pkt:%d\n", pkt_length);
- memset(data, 0, pkt_length);
- ret = 0;
- }
- exit:
- return ret;
- }
- static void _btsrv_sco_convert_data_to_media(uint8_t *data, uint8_t len, uint8_t pkg_flag, uint8_t codec_id)
- {
- uint16_t seq_no = 0;
- if (len != BTSPEECH_SCO_PACKET_SIZE) {
- SYS_LOG_ERR("len error %d codec_id %d\n", len, codec_id);
- return;
- }
- if (codec_id == BT_CODEC_ID_MSBC) {
- if (pkg_flag) {
- seq_no = (sco_context->last_seq_no & 0x03) + 1;
- } else if (data[1] == 0) {
- pkg_flag = 1;
- } else {
- seq_no = _btsrv_sco_mscb_seq_convert(data[1]) + 1;
- }
- } else {
- seq_no = (sco_context->last_seq_no & 0x03) + 1;
- }
- #ifdef DECODE_PLAYBACK_MCU
- if (codec_id == BT_CODEC_ID_MSBC) {
- if (system_check_low_latencey_mode()) {
- if (sco_context->first_frame) {
- _btsrv_sco_insert_package(data, len, 2);
- sco_context->first_frame = 0;
- sco_context->drop_frame = 2;
- } else if(sco_context->drop_frame != 0){
- if(sco_context->drop_flag) {
- sco_context->drop_frame--;
- sco_context->drop_flag = 0;
- return;
- } else {
- sco_context->drop_flag = 1;
- }
- }
- }
- data[0] = 0;
- data[1] = pkg_flag;
- /* print_buffer((void *)data, 1, BTSPEECH_SCO_PACKET_SIZE, 16, -1); */
- sco_user_callback(BTSRV_SCO_DATA_INDICATED, data, BTSPEECH_SCO_PACKET_SIZE);
- } else {
- uint8_t send_data[62];
- send_data[0] = 0;
- send_data[1] = pkg_flag;
- memcpy(&send_data[2], data, BTSPEECH_SCO_PACKET_SIZE);
- /* print_buffer((void *)send_data, 1, BTSPEECH_SCO_PACKET_SIZE + 2, 16, -1); */
- sco_user_callback(BTSRV_SCO_DATA_INDICATED, send_data, BTSPEECH_SCO_PACKET_SIZE + 2);
- }
- #else
- if (codec_id == BT_CODEC_ID_MSBC) {
- uint8_t send_data[68];
- uint16_t offset = 0;
- *(uint16_t *)&send_data[offset] = pkg_flag;
- offset += 2;
- *(uint16_t *)&send_data[offset] = sco_context->frame_cnt;
- offset += 2;
- *(uint16_t *)&send_data[offset]= len - 2;
- offset += 2;
- *(uint16_t *)&send_data[offset]= 2;
- offset += 2;
- memcpy(&send_data[offset], &data[2], len - 2);
- /* print_buffer((void *)data, 1, BTSPEECH_SCO_PACKET_SIZE, 16, -1); */
- sco_user_callback(BTSRV_SCO_DATA_INDICATED, send_data, sizeof(send_data));
- } else {
- uint8_t send_data[68];
- uint16_t offset = 0;
- *(uint16_t *)&send_data[offset] = pkg_flag;
- offset += 2;
- *(uint16_t *)&send_data[offset] = sco_context->frame_cnt;
- offset += 2;
- *(uint16_t *)&send_data[offset]= len;
- offset += 2;
- *(uint16_t *)&send_data[offset]= 0;
- offset += 2;
- memcpy(&send_data[offset], data, len);
- //print_buffer((void *)send_data, 1, sizeof(send_data), 16, -1);
- sco_user_callback(BTSRV_SCO_DATA_INDICATED, send_data, sizeof(send_data));
- }
- #endif
- sco_context->last_seq_no = seq_no;
- }
- static void _btsrv_sco_save_data_to_cache(uint8_t *data, uint8_t len, uint8_t pkg_status_flag, uint8_t codec_id)
- {
- if (!sco_context->sco_rx_cache) {
- SYS_LOG_ERR("Drop sco data");
- return;
- }
- #if 0
- if (codec_id == BT_CODEC_ID_MSBC) {
- if (sco_context->sco_rx_pkt_cache_len != 0 && _btsrv_sco_mscb_seq_convert(data[1]) >= 0) {
- sco_context->sco_rx_pkt_cache_len = 0;
- } else if (sco_context->sco_rx_pkt_cache_len == 0 && _btsrv_sco_mscb_seq_convert(data[1]) < 0) {
- return;
- }
- }
- #endif
- if (sco_context->sco_rx_pkt_cache_len != 0) {
- if (pkg_status_flag == 0 && sco_context->sco_rx_last_pkg_status_flag == 0) {
- memcpy(sco_context->sco_rx_cache + sco_context->sco_rx_pkt_cache_len, data, len);
- sco_context->sco_rx_last_pkg_status_flag = pkg_status_flag;
- } else {
- if (sco_context->sco_rx_last_pkg_status_flag == 0) {
- memset(sco_context->sco_rx_cache, 0, sco_context->sco_rx_pkt_cache_len);
- }
- memset(sco_context->sco_rx_cache + sco_context->sco_rx_pkt_cache_len, 0, len);
- sco_context->sco_rx_last_pkg_status_flag = pkg_status_flag;
- pkg_status_flag = 1;
- }
- } else {
- if (pkg_status_flag == 0) {
- memcpy(sco_context->sco_rx_cache + sco_context->sco_rx_pkt_cache_len, data, len);
- } else {
- memset(sco_context->sco_rx_cache, 0, len);
- }
- sco_context->sco_rx_last_pkg_status_flag = pkg_status_flag;
- }
- sco_context->sco_rx_pkt_cache_len += len;
- while (sco_context->sco_rx_pkt_cache_len >= BTSPEECH_SCO_PACKET_SIZE) {
- int ret = 0;
- if (codec_id == BT_CODEC_ID_MSBC) {
- ret = _btsrv_read_msbc_pkt(sco_context->sco_rx_cache, BTSPEECH_SCO_PACKET_SIZE);
- if (ret) {
- memset(sco_context->sco_rx_cache, 0, BTSPEECH_SCO_PACKET_SIZE);
- pkg_status_flag = 1;
- ret = 0;
- }
- }
- if (ret == 0) {
- _btsrv_sco_convert_data_to_media(sco_context->sco_rx_cache, BTSPEECH_SCO_PACKET_SIZE, pkg_status_flag, codec_id);
- }
- sco_context->sco_rx_pkt_cache_len -= BTSPEECH_SCO_PACKET_SIZE;
- memcpy(sco_context->sco_rx_cache, sco_context->sco_rx_cache + BTSPEECH_SCO_PACKET_SIZE, sco_context->sco_rx_pkt_cache_len);
- }
- }
- #ifdef CONFIG_DEBUG_DATA_RATE
- static uint32_t start_time_stamp;
- static inline void _btsrv_sco_debug_reset(void)
- {
- start_time_stamp = 0;
- }
- static inline void _btsrv_sco_debug_data_rate(uint8_t len, uint8_t pkg_flag, uint8_t fill_zero)
- {
- static int received_data;
- static int frame_cnt;
- static int err_frame_cnt;
- if (!start_time_stamp) {
- frame_cnt = 0;
- err_frame_cnt = 0;
- received_data = 0;
- start_time_stamp = k_cycle_get_32();
- }
- received_data += len;
- frame_cnt++;
- if (pkg_flag && (fill_zero == 0)) {
- err_frame_cnt++;
- }
- if ((k_cycle_get_32() - start_time_stamp) > 5 * sys_clock_hw_cycles_per_sec()) {
- if (start_time_stamp != 0) {
- SYS_LOG_INF("sco data rate: %d b/s frame cnt (%d / %d) error rate %d %%\n",
- received_data / 5, err_frame_cnt, frame_cnt, err_frame_cnt * 100 / frame_cnt);
- }
- frame_cnt = 0;
- err_frame_cnt = 0;
- received_data = 0;
- start_time_stamp = k_cycle_get_32();
- }
- }
- #endif
- static bool _btsrv_sco_check_mute_frame(uint8_t *data, uint8_t len)
- {
- if (data[6] == 0 && data[7] == 0 && data[8] == 0 && data[9] == 0) {
- return true;
- }
- return false;
- }
- static void _btsrv_sco_data_avaliable_cb(struct bt_conn *conn, uint8_t *data, uint8_t len, uint8_t pkg_flag)
- {
- uint8_t codec_id = 0, sample_rate = 0, fill_zero = 0;
- struct bt_conn *base_conn = btsrv_rdm_get_base_conn_by_sco(conn);
- if ((btsrv_rdm_hfp_get_actived_sco() != conn && base_conn != btsrv_rdm_get_tws_by_role(BTSRV_TWS_MASTER)
- && base_conn != btsrv_rdm_get_tws_by_role(BTSRV_TWS_SLAVE)) || !base_conn) {
- return;
- }
- if(base_conn == btsrv_rdm_get_tws_by_role(BTSRV_TWS_MASTER) && sco_context->sco_conn){
- btsrv_event_notify_malloc(MSG_BTSRV_TWS, MSG_BTSRV_TWS_SCO_DATA, data, len,len);
- return;
- }
- btsrv_rdm_hfp_get_codec_info(base_conn, &codec_id, &sample_rate);
- if (codec_id != BT_CODEC_ID_MSBC && codec_id != BT_CODEC_ID_CVSD) {
- SYS_LOG_ERR("error codec id %d\n", codec_id);
- return;
- }
- if (conn == btsrv_rdm_hfp_get_actived_sco()) {
- sco_context->frame_cached_len += len;
- if (sco_context->frame_cached_len >= BTSPEECH_SCO_PACKET_SIZE) {
- sco_context->frame_cnt++;
- sco_context->frame_cached_len -= BTSPEECH_SCO_PACKET_SIZE;
- }
- if (sco_context->frame_cnt < SCO_CHECK_DROP_MUTE_FRAME_CNT && !sco_context->check_mute_finish) {
- if (!sco_context->mute_frame) {
- if (_btsrv_sco_check_mute_frame(data, len)) {
- sco_context->mute_frame = 1;
- } else {
- SYS_LOG_DBG("drop frame %d", sco_context->frame_cnt);
- return;
- }
- } else {
- if (!_btsrv_sco_check_mute_frame(data, len)) {
- pkg_flag = 1;
- fill_zero = 1;
- SYS_LOG_INF("fill zero %d", sco_context->frame_cnt);
- }
- }
- } else {
- sco_context->check_mute_finish = 1;
- }
- }
- #ifdef CONFIG_DEBUG_DATA_RATE
- _btsrv_sco_debug_data_rate(len, pkg_flag, fill_zero);
- #endif
- if (len == BTSPEECH_SCO_PACKET_SIZE) {
- int ret = 0;
- if (codec_id == BT_CODEC_ID_MSBC) {
- ret = _btsrv_read_msbc_pkt(data, len);
- if (ret) {
- memset(data, 0, len);
- pkg_flag = 1;
- ret = 0;
- }
- }
- if (ret == 0) {
- _btsrv_sco_convert_data_to_media(data, len, pkg_flag, codec_id);
- }
- } else {
- _btsrv_sco_save_data_to_cache(data, len, pkg_flag, codec_id);
- }
- }
- static struct bt_conn_cb sco_conn_callbacks = {
- .connected = _btsrv_sco_connected_cb,
- .disconnected = _btsrv_sco_disconnected_cb,
- .security_changed = _btsrv_sco_security_changed_cb,
- .rx_sco_data = _btsrv_sco_data_avaliable_cb,
- };
- static void btsrv_sco_disconnect_timer_handler(struct thread_timer *ttimer, void *expiry_fn_arg)
- {
- struct bt_conn *sco_conn = (struct bt_conn *)expiry_fn_arg;
- struct bt_conn *br_conn = hostif_bt_conn_get_acl_conn_by_sco(sco_conn);
- struct bt_conn *second_br_conn = btsrv_rdm_hfp_get_second_dev();
- int other_state = btsrv_rdm_hfp_get_state(second_br_conn);
- if(br_conn && (br_conn != btsrv_rdm_hfp_get_actived() ||
- second_br_conn == NULL || other_state > BTSRV_HFP_STATE_LINKED)){
- hostif_bt_conn_ref(sco_conn);
- int err = hostif_bt_conn_disconnect(sco_conn, BT_HCI_ERR_REMOTE_USER_TERM_CONN);
- if (err) {
- SYS_LOG_INF("Disconnection failed (err %d)\n", err);
- }else
- btsrv_rdm_hfp_set_sco_state(br_conn,BTSRV_SCO_STATE_DISCONNECT);
- hostif_bt_conn_unref(sco_conn);
- SYS_LOG_INF("");
- }
- }
- void btsrv_sco_disconnect(struct bt_conn *sco_conn){
- uint32_t creat_time = -1,diff;
- struct thread_timer *sco_disconnect_timer = NULL;
- struct bt_conn *br_conn = hostif_bt_conn_get_acl_conn_by_sco(sco_conn);
- if(br_conn){
- btsrv_rdm_get_sco_creat_time(br_conn, &creat_time);
- diff = os_uptime_get_32() - creat_time;
- sco_disconnect_timer = btsrv_rdm_get_sco_disconnect_timer(br_conn);
- if (creat_time > 0 && diff > 500){
- if(sco_disconnect_timer && thread_timer_is_running(sco_disconnect_timer))
- thread_timer_stop(sco_disconnect_timer);
- hostif_bt_conn_ref(sco_conn);
- int err = hostif_bt_conn_disconnect(sco_conn, BT_HCI_ERR_REMOTE_USER_TERM_CONN);
- if (err) {
- SYS_LOG_INF("Disconnection failed (err %d)\n", err);
- }else
- btsrv_rdm_hfp_set_sco_state(br_conn,BTSRV_SCO_STATE_DISCONNECT);
- hostif_bt_conn_unref(sco_conn);
- SYS_LOG_INF("");
- }else if(sco_disconnect_timer){
- if(!thread_timer_is_running(sco_disconnect_timer)){
- thread_timer_init(sco_disconnect_timer, btsrv_sco_disconnect_timer_handler
- , (void *)sco_conn);
- thread_timer_start(sco_disconnect_timer, 500-diff, 0);
- }
- }
- }
- }
- static void _btsrv_sco_connected(struct bt_conn *conn)
- {
- struct bt_conn *br_conn;
- int hfp_state;
- if (sco_context) {
- br_conn = hostif_bt_conn_get_acl_conn_by_sco(conn);
- if ((br_conn == NULL) || (btsrv_rdm_sco_connected(br_conn, conn) < 0)) {
- return;
- }
- hfp_state = btsrv_rdm_hfp_get_state(br_conn);
- SYS_LOG_INF("other_state %d\n", hfp_state);
- SYS_LOG_INF("allow %d\n", btsrv_allow_sco_connect());
- if (!btsrv_allow_sco_connect()/* || (hfp_state == BTSRV_HFP_STATE_CALL_INCOMING)*/) {
- /* disconnect sco if upper application(ota) not allow */
- hostif_bt_conn_ref(conn);
- btsrv_sco_disconnect(conn);
- btsrv_hfp_rejected(conn);
- btsrv_rdm_set_sco_connected_reject(br_conn, 1);
- return;
- } else {
- btsrv_rdm_set_sco_connected_reject(br_conn, 0);
- }
- if(btsrv_rdm_get_hfp_role(br_conn) == BTSRV_HFP_ROLE_HF)
- btsrv_hfp_set_status(br_conn, BTSRV_HFP_STATE_SCO_ESTABLISHED);
- else
- btsrv_hfp_ag_set_status(br_conn, BTSRV_HFP_STATE_SCO_ESTABLISHED);
- if (br_conn == btsrv_rdm_hfp_get_actived()
- || br_conn == btsrv_rdm_get_tws_by_role(BTSRV_TWS_SLAVE)) {
- if (!sco_context->sco_conn) {
- hostif_bt_conn_ref(conn);
- sco_context->sco_conn = conn;
- } else {
- btsrv_sco_disconnect(sco_context->sco_conn);
- sco_context->sco_conn = conn;
- hostif_bt_conn_ref(conn);
- }
- sco_context->sco_rx_last_pkg_status_flag = 0;
- sco_context->sco_rx_pkt_cache_len = 0;
- sco_context->first_frame = 1;
- sco_context->drop_flag = 0;
- sco_context->mute_frame = 0;
- sco_context->check_mute_finish = 0;
- sco_context->frame_cnt = 0;
- sco_context->frame_cached_len = 0;
- sco_context->last_seq_no = 0;
- sco_context->sco_except_cache_len = 0;
- #ifdef CONFIG_DEBUG_DATA_RATE
- _btsrv_sco_debug_reset();
- #endif
- } else {
- /* disconnect sco for deactive dev */
- if (br_conn != btsrv_rdm_get_tws_by_role(BTSRV_TWS_MASTER)) {
- hostif_bt_conn_ref(conn);
- btsrv_sco_disconnect(conn);
- } else {
- //just ref conn,this conn will be send to tws and save in tws_manager->tws_session->sco_conn
- hostif_bt_conn_ref(conn);
- btsrv_event_notify(MSG_BTSRV_TWS, MSG_BTSRV_SCO_CONNECTED, conn);
- }
- }
- }
- }
- static void _btsrv_sco_disconnected(struct bt_conn *conn)
- {
- struct bt_conn *br_conn = btsrv_rdm_get_base_conn_by_sco(conn);
- if (br_conn == NULL) {
- SYS_LOG_WRN("conn not recorded\n");
- return;
- }
- struct thread_timer *sco_disconnect_timer = btsrv_rdm_get_sco_disconnect_timer(br_conn);
- if(sco_disconnect_timer && thread_timer_is_running(sco_disconnect_timer))
- thread_timer_stop(sco_disconnect_timer);
- if (!btsrv_rdm_is_sco_connected_reject(br_conn)) {
- if(btsrv_rdm_get_hfp_role(br_conn) == BTSRV_HFP_ROLE_HF)
- btsrv_hfp_set_status(br_conn, BTSRV_HFP_STATE_SCO_RELEASED);
- else
- btsrv_hfp_ag_set_status(br_conn, BTSRV_HFP_STATE_SCO_RELEASED);
- if(br_conn == btsrv_rdm_get_tws_by_role(BTSRV_TWS_MASTER)){
- btsrv_event_notify(MSG_BTSRV_TWS, MSG_BTSRV_SCO_DISCONNECTED, conn);
- }
- }
- btsrv_rdm_set_sco_connected_reject(br_conn, 0);
- btsrv_rdm_sco_disconnected(conn);
- hostif_bt_conn_unref(conn);
- if (sco_context && sco_context->sco_conn == conn) {
- sco_context->sco_conn = NULL;
- }
- }
- static int _btsrv_sco_init(btsrv_sco_callback cb)
- {
- sco_context = &sco_context_info;
- #if CONFIG_MEDIA
- sco_context->sco_rx_cache = media_mem_get_cache_pool(RX_SCO, AUDIO_STREAM_VOICE);
- sco_context->sco_except_cache = bt_mem_malloc(SCO_EXCEPT_CACHE_SIZE);
- if (!sco_context->sco_except_cache) {
- return -1;
- }
- #endif
- hostif_bt_conn_cb_register((struct bt_conn_cb *)&sco_conn_callbacks);
- sco_user_callback = cb;
- return 0;
- }
- static int _btsrv_sco_deinit(void)
- {
- if (sco_context->sco_except_cache) {
- bt_mem_free(sco_context->sco_except_cache);
- }
- sco_context = NULL;
- sco_user_callback = NULL;
- return 0;
- }
- int btsrv_sco_process(struct app_msg *msg)
- {
- switch (_btsrv_get_msg_param_cmd(msg)) {
- case MSG_BTSRV_SCO_START:
- SYS_LOG_INF("MSG_BTSRV_SCO_START\n");
- _btsrv_sco_init(msg->ptr);
- break;
- case MSG_BTSRV_SCO_STOP:
- SYS_LOG_INF("MSG_BTSRV_SCO_STOP\n");
- _btsrv_sco_deinit();
- break;
- case MSG_BTSRV_SCO_CONNECTED:
- SYS_LOG_INF("MSG_BTSRV_SCO_CONNECTED\n");
- _btsrv_sco_connected(msg->ptr);
- hostif_bt_conn_unref(msg->ptr); /* unref conn for ref in _btsrv_sco_connected_cb */
- break;
- case MSG_BTSRV_SCO_DISCONNECTED:
- SYS_LOG_INF("MSG_BTSRV_SCO_DISCONNECTED\n");
- _btsrv_sco_disconnected(msg->ptr);
- hostif_bt_conn_unref(msg->ptr); /* unref conn for ref in _btsrv_sco_disconnected_cb */
- break;
- }
- return 0;
- }
- struct bt_conn *btsrv_sco_get_conn(void)
- {
- if (sco_context)
- return sco_context->sco_conn;
- return NULL;
- }
|