123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790 |
- /*
- * Copyright (c) 2017 Actions Semi Co., Ltd.
- *
- * SPDX-License-Identifier: Apache-2.0
- */
- /**
- * @file
- * @brief btsrvice a2dp
- */
- #define SYS_LOG_DOMAIN "btsrv_a2dp"
- #include "btsrv_os_common.h"
- #include "btsrv_inner.h"
- struct btsrv_a2dp_codec_cb {
- struct bt_conn *conn;
- struct bt_a2dp_media_codec codec;
- uint8_t cp_type;
- };
- static btsrv_a2dp_hdl_callback a2dp_user_callback;
- static struct bt_a2dp_endpoint a2dp_sbc_endpoint[CONFIG_MAX_A2DP_ENDPOINT];
- static struct bt_a2dp_endpoint a2dp_aac_endpoint[CONFIG_MAX_A2DP_ENDPOINT];
- static uint8_t a2dp_register_aac_num;
- static struct bt_conn *trs_conn = NULL;
- #if 0
- static const uint8_t a2dp_sbc_codec[] = {
- BT_A2DP_AUDIO << 4,
- BT_A2DP_SBC,
- 0xFF, /* (SNK mandatory)44100, 48000, mono, dual channel, stereo, join stereo */
- /* (SNK optional) 16000, 32000 */
- 0xFF, /* (SNK mandatory) Block length: 4/8/12/16, subbands:4/8, Allocation Method: SNR, Londness */
- 0x02, /* min bitpool */
- 0x35 /* max bitpool */
- };
- static const uint8_t a2dp_aac_codec[] = {
- BT_A2DP_AUDIO << 4,
- BT_A2DP_MPEG2,
- 0xF0, /* MPEG2 AAC LC, MPEG4 AAC LC, MPEG AAC LTP, MPEG4 AAC Scalable */
- 0x01, /* Sampling Frequecy 44100 */
- 0x8F, /* Sampling Frequecy 48000, channels 1, channels 2 */
- 0xFF, /* VBR, bit rate */
- 0xFF, /* bit rate */
- 0xFF /* bit rate */
- };
- #endif
- #define A2DP_AAC_FREQ_NUM 12
- const static uint8_t a2dp_aac_freq_table[A2DP_AAC_FREQ_NUM] = {96, 88, 64, 48, 44, 32, 24, 22, 16, 12, 11, 8};
- static void btsrv_a2dp_hdl_cb_user(struct bt_conn *conn, btsrv_a2dp_event_e event, void *packet, int size)
- {
- if (a2dp_user_callback) {
- a2dp_user_callback(hostif_bt_conn_get_handle(conn), event, packet, size);
- }
- }
- static uint8_t btsrv_convert_sample_rate(struct bt_a2dp_media_codec *codec)
- {
- uint8_t sample_rate = 44, i;
- uint16_t freq;
- if (codec->head.codec_type == BT_A2DP_SBC) {
- switch (codec->sbc.freq) {
- case BT_A2DP_SBC_48000:
- sample_rate = 48;
- break;
- case BT_A2DP_SBC_44100:
- sample_rate = 44;
- break;
- case BT_A2DP_SBC_32000:
- sample_rate = 32;
- break;
- case BT_A2DP_SBC_16000:
- sample_rate = 16;
- break;
- }
- } else if (codec->head.codec_type == BT_A2DP_MPEG2) {
- freq = (codec->aac.freq0 << 4) | codec->aac.freq1;
- for (i = 0; i < A2DP_AAC_FREQ_NUM; i++) {
- if (freq & (BT_A2DP_AAC_96000 << i)) {
- sample_rate = a2dp_aac_freq_table[i];
- break;
- }
- }
- }
- return sample_rate;
- }
- static uint8_t btsrv_parse_bitpool(struct bt_a2dp_media_codec *codec)
- {
- if (codec->head.codec_type == BT_A2DP_SBC) {
- return codec->sbc.max_bitpool;
- } else {
- return 0;
- }
- }
- static void _btsrv_a2dp_connect_cb(struct bt_conn *conn)
- {
- btsrv_event_notify(MSG_BTSRV_CONNECT, MSG_BTSRV_A2DP_CONNECTED, conn);
- }
- static void _btsrv_a2dp_disconnected_cb(struct bt_conn *conn)
- {
- /* TODO: Disconnected process order: btsrv_tws->btsrv_a2dp->btsrv_connect */
- btsrv_event_notify(MSG_BTSRV_A2DP, MSG_BTSRV_A2DP_DISCONNECTED, conn);
- }
- #ifdef CONFIG_DEBUG_DATA_RATE
- #define TEST_RECORD_NUM 10
- static uint32_t pre_rx_time;
- static uint8_t test_index;
- static uint16_t test_rx_record[TEST_RECORD_NUM][2];
- static inline void _btsrv_a2dp_debug_date_rate(uint16_t len)
- {
- static int start_time_stamp;
- static int received_data;
- uint32_t curr_time;
- if (!start_time_stamp) {
- received_data = 0;
- start_time_stamp = k_cycle_get_32();
- }
- received_data += len;
- if ((k_cycle_get_32() - start_time_stamp) > 5 * sys_clock_hw_cycles_per_sec()) {
- if (start_time_stamp != 0) {
- SYS_LOG_INF("a2dp data rate: %d bytes/s\n", received_data / 5);
- }
- received_data = 0;
- start_time_stamp = k_cycle_get_32();
- }
- curr_time = os_uptime_get_32();
- test_rx_record[test_index][0] = curr_time - pre_rx_time;
- test_rx_record[test_index][1] = len;
- test_index++;
- if (test_index >= TEST_RECORD_NUM) {
- test_index = 0;
- }
- pre_rx_time = curr_time;
- }
- void debug_dump_media_rx_state(void)
- {
- static uint32_t pre_dump_time;
- uint32_t curr_time;
- uint16_t time_cnt = 0, len_cnt = 0;
- int flag, i;
- curr_time = os_uptime_get_32();
- if ((curr_time - pre_dump_time) < 500) {
- return;
- }
- pre_dump_time = curr_time;
- flag = btsrv_set_negative_prio();
- printk("diff_time data_len\n");
- for (i = test_index; i < TEST_RECORD_NUM; i++) {
- time_cnt += test_rx_record[i][0];
- len_cnt += test_rx_record[i][1];
- printk("%d(%d)\t %d(%d)\n", test_rx_record[i][0], time_cnt, test_rx_record[i][1], len_cnt);
- }
- for (i = 0; i < test_index; i++) {
- time_cnt += test_rx_record[i][0];
- len_cnt += test_rx_record[i][1];
- printk("%d(%d)\t %d(%d)\n", test_rx_record[i][0], time_cnt, test_rx_record[i][1], len_cnt);
- }
- printk("%d(%d)\n", curr_time - pre_rx_time, time_cnt + (curr_time - pre_rx_time));
- btsrv_revert_prio(flag);
- }
- #else
- void debug_dump_media_rx_state(void)
- {
- }
- #endif
- struct avdtp_data_header_t
- {
- uint16_t frame_cnt;
- uint16_t seq_no;
- uint16_t frame_len; //stream len
- uint16_t padding_len;
- } __packed;
- static uint8_t btsrv_a2dp_pack_date_header(struct bt_conn *conn, uint8_t *data, uint16_t media_len, uint8_t head_len, uint8_t format, uint8_t *padding_len)
- {
- struct avdtp_data_header_t header;
- uint8_t pack_header_size = sizeof(struct avdtp_data_header_t);
- uint8_t start_pos;
- /* data start from RTTP */
- if (format == BT_A2DP_SBC) {
- header.frame_cnt = (uint16_t)(data[head_len - 1]&0x0F);
- } else {
- header.frame_cnt = 1;
- }
- header.seq_no = data[3] | ((uint16_t)(data[2]) << 8);
- header.frame_len = media_len;
- header.padding_len = media_len % 2;
- *padding_len = header.padding_len;
- start_pos = head_len - pack_header_size;
- memcpy(&data[start_pos], (uint8_t*)&header, pack_header_size);
- #if 1
- static struct bt_conn *rec_seq_conn;
- static uint16_t rec_seq_no;
- static uint32_t rec_time;
- uint32_t curr_time;
- curr_time = os_uptime_get_32();
- if (rec_seq_conn != conn || ((curr_time - rec_time) > 300)) {
- rec_seq_conn = conn;
- rec_seq_no = header.seq_no;
- } else {
- rec_seq_no += 1;
- if (rec_seq_no != header.seq_no) {
- SYS_LOG_ERR("pkt miss %d %d\n", header.seq_no, (rec_seq_no - 1));
- }
- rec_seq_no = header.seq_no;
- }
- rec_time = curr_time;
- #endif
- return start_pos;
- }
- /** this callback dircty call to app, will in bt stack context */
- static void _btsrv_a2dp_media_handler_cb(struct bt_conn *conn, uint8_t *data, uint16_t len)
- {
- uint8_t head_len, format, sample_rate, cp_type, padding_len;
- if (btsrv_rdm_get_a2dp_pending_ahead_start(conn)) {
- btsrv_a2dp_media_state_change(conn, BT_A2DP_MEDIA_STATE_START);
- }
- #ifdef CONFIG_SUPPORT_TWS
- if (btsrv_tws_protocol_data_cb(conn, data, len)) {
- return;
- }
- #endif
- /* Must get info after btsrv_tws_protocol_data_cb,
- * tws slave update format in btsrv_tws_protocol_data_cb
- */
- btsrv_rdm_a2dp_get_codec_info(conn, &format, &sample_rate, &cp_type);
- switch (format) {
- case BT_A2DP_SBC:
- case BT_A2DP_MPEG2:
- if (!(btsrv_rdm_a2dp_get_actived() == conn ||
- btsrv_rdm_get_dev_role() == BTSRV_TWS_SLAVE)) {
- SYS_LOG_DBG("return for master role %d\n", btsrv_rdm_get_dev_role());
- break;
- }
- if (format == BT_A2DP_SBC) {
- head_len = AVDTP_SBC_HEADER_LEN;
- } else {
- head_len = AVDTP_AAC_HEADER_LEN;
- }
- if (cp_type == BT_AVDTP_AV_CP_TYPE_SCMS_T) {
- head_len++;
- }
- #ifdef CONFIG_DEBUG_DATA_RATE
- _btsrv_a2dp_debug_date_rate(len - head_len);
- #endif
- head_len = btsrv_a2dp_pack_date_header(conn, data, (len - head_len), head_len, format, &padding_len);
- btsrv_a2dp_hdl_cb_user(conn, BTSRV_A2DP_DATA_INDICATED, data + head_len, (len - head_len + padding_len));
- break;
- default:
- SYS_LOG_INF("A2dp not support type: 0x%x, 0x%x, %d\n", data[0], data[1], format);
- break;
- }
- }
- static int _btsrv_a2dp_media_state_req_cb(struct bt_conn *conn, uint8_t state)
- {
- btsrv_event_notify_ext(MSG_BTSRV_A2DP, MSG_BTSRV_A2DP_MEDIA_STATE_CB, conn, state);
- return 0;
- }
- static int btsrv_a2dp_media_state_req_proc(struct bt_conn *conn, uint8_t state)
- {
- int cmd = -1;
- uint8_t send_notify = 0;
- uint16_t delay_report;
- #ifdef CONFIG_BT_A2DP_TRS
- if(btsrv_trs_a2dp_media_state_req_cb(conn, state) == true) {
- SYS_LOG_INF("trs a2dp media state req %d", state);
- if (state == BT_A2DP_MEDIA_STATE_START) {
- btsrv_rdm_trs_a2dp_stream_open(conn, true);
- } else if (state == BT_A2DP_MEDIA_STATE_CLOSE ||
- state == BT_A2DP_MEDIA_STATE_SUSPEND) {
- btsrv_rdm_trs_a2dp_stream_open(conn, false);
- }
- return 0;
- }
- #endif
- SYS_LOG_INF("a2dp media state req %d", state);
- switch (state) {
- case BT_A2DP_MEDIA_STATE_OPEN:
- cmd = MSG_BTSRV_A2DP_MEDIA_STATE_OPEN;
- delay_report = 0;
- btsrv_a2dp_hdl_cb_user(conn, BTSRV_A2DP_GET_INIT_DELAY_REPORT, &delay_report, sizeof(delay_report));
- if (delay_report) {
- hostif_bt_a2dp_send_delay_report(conn, delay_report);
- }
- break;
- case BT_A2DP_MEDIA_STATE_START:
- cmd = MSG_BTSRV_A2DP_MEDIA_STATE_START;
- btsrv_rdm_a2dp_actived(conn, 1);
- btsrv_rdm_set_a2dp_pending_ahead_start(conn, 0);
- break;
- case BT_A2DP_MEDIA_STATE_CLOSE:
- cmd = MSG_BTSRV_A2DP_MEDIA_STATE_CLOSE;
- btsrv_rdm_a2dp_actived(conn, 0);
- btsrv_rdm_set_a2dp_pending_ahead_start(conn, 0);
- break;
- case BT_A2DP_MEDIA_STATE_SUSPEND:
- cmd = MSG_BTSRV_A2DP_MEDIA_STATE_SUSPEND;
- btsrv_rdm_a2dp_actived(conn, 0);
- btsrv_rdm_set_a2dp_pending_ahead_start(conn, 0);
- break;
- case BT_A2DP_MEDIA_STATE_PENDING_AHEAD_START:
- btsrv_rdm_set_a2dp_pending_ahead_start(conn, 1);
- break;
- }
- if (cmd > 0) {
- if (btsrv_rdm_a2dp_get_actived() == conn) {
- /* Phone state req */
- send_notify = 1;
- } else if (btsrv_rdm_a2dp_get_actived() &&
- (btsrv_rdm_get_dev_role() == BTSRV_TWS_MASTER)) {
- /* Tws source_restart state req,
- * only notify when have a2dp active device.
- */
- send_notify = 1;
- } else if (btsrv_rdm_get_dev_role() == BTSRV_TWS_SLAVE) {
- /* Tws mater send to slave state req */
- send_notify = 1;
- }
- if ((btsrv_rdm_a2dp_get_actived() == conn || btsrv_rdm_get_dev_role() == BTSRV_TWS_SLAVE) &&
- (cmd == MSG_BTSRV_A2DP_MEDIA_STATE_START)) {
- uint8_t format, sample_rate;
- uint8_t codec_info[3];
- btsrv_rdm_a2dp_get_codec_info(conn, &format, &sample_rate, NULL);
- codec_info[0] = format;
- codec_info[1] = sample_rate;
- codec_info[2] = btsrv_rdm_a2dp_get_bitpool(conn);
- btsrv_a2dp_hdl_cb_user(conn, BTSRV_A2DP_CODEC_INFO, codec_info, sizeof(codec_info));
- }
- if (send_notify) {
- btsrv_event_notify(MSG_BTSRV_A2DP, cmd, conn);
- }
- }
- return 0;
- }
- static void _btsrv_a2dp_seted_codec_cb(struct bt_conn *conn, struct bt_a2dp_media_codec *codec, uint8_t cp_type)
- {
- struct btsrv_a2dp_codec_cb param;
- memset(¶m, 0, sizeof(param));
- param.conn = conn;
- memcpy(¶m.codec, codec, sizeof(struct bt_a2dp_media_codec));
- param.cp_type = cp_type;
- btsrv_event_notify_malloc(MSG_BTSRV_A2DP, MSG_BTSRV_A2DP_SET_CODEC_CB, (uint8_t *)¶m, sizeof(param), 0);
- }
- static void btsrv_a2dp_seted_codec_proc(void *in_parm)
- {
- struct btsrv_a2dp_codec_cb *param = in_parm;
- uint8_t codec_info[3];
- codec_info[0] = param->codec.head.codec_type;
- codec_info[1] = btsrv_convert_sample_rate(¶m->codec);
- codec_info[2] = btsrv_parse_bitpool(¶m->codec);
- SYS_LOG_INF("media %d, codec %d, freq %d, cp %d\n", param->codec.head.media_type, codec_info[0], codec_info[1], param->cp_type);
- btsrv_rdm_a2dp_set_codec_info(param->conn, codec_info[0], codec_info[1], param->cp_type);
- btsrv_rdm_a2dp_set_bitpool(param->conn, codec_info[2]);
- #ifdef CONFIG_BT_A2DP_TRS
- /* Wait TODO: Not ready support a2dp device and TRS concurrently */
- btsrv_a2dp_hdl_cb_user(param->conn, BTSRV_A2DP_CODEC_INFO, codec_info, sizeof(codec_info));
- btsrv_trs_a2dp_seted_codec_cb(param->conn, ¶m->codec);
- #endif
- }
- static const struct bt_a2dp_app_cb btsrv_a2dp_cb = {
- .connected = _btsrv_a2dp_connect_cb,
- .disconnected = _btsrv_a2dp_disconnected_cb,
- .media_handler = _btsrv_a2dp_media_handler_cb,
- .media_state_req = _btsrv_a2dp_media_state_req_cb,
- .seted_codec = _btsrv_a2dp_seted_codec_cb,
- };
- int btsrv_a2dp_media_state_change(struct bt_conn *conn, uint8_t state)
- {
- return _btsrv_a2dp_media_state_req_cb(conn, state);
- }
- static void _btsrv_a2dp_connected(struct bt_conn *conn)
- {
- char addr_str[BT_ADDR_STR_LEN];
- bd_address_t *addr = GET_CONN_BT_ADDR(conn);
- hostif_bt_addr_to_str((const bt_addr_t *)addr, addr_str, BT_ADDR_STR_LEN);
- SYS_LOG_INF("A2dp connected:%p addr %s\n", conn, addr_str);
- btsrv_a2dp_hdl_cb_user(conn, BTSRV_A2DP_CONNECTED, NULL, 0);
- }
- static void _btsrv_a2dp_disconnected(struct bt_conn *conn)
- {
- char addr_str[BT_ADDR_STR_LEN];
- bd_address_t *addr = GET_CONN_BT_ADDR(conn);
- hostif_bt_addr_to_str((const bt_addr_t *)addr, addr_str, BT_ADDR_STR_LEN);
- SYS_LOG_INF("A2dp disconnected:%p addr %s\n", conn, addr_str);
- btsrv_a2dp_hdl_cb_user(conn, BTSRV_A2DP_DISCONNECTED, NULL, 0);
- }
- static void _btsrv_a2dp_actived_dev_changed(struct bt_conn *conn)
- {
- uint8_t format, sample_rate;
- uint8_t codec_info[3];
- struct bt_conn *second_conn = btsrv_rdm_a2dp_get_second_dev();
- btsrv_a2dp_hdl_cb_user(second_conn, BTSRV_A2DP_STREAM_SUSPEND, NULL, 0);
- btsrv_rdm_a2dp_get_codec_info(conn, &format, &sample_rate, NULL);
- codec_info[0] = format;
- codec_info[1] = sample_rate;
- codec_info[2] = btsrv_rdm_a2dp_get_bitpool(conn);
- btsrv_a2dp_hdl_cb_user(conn, BTSRV_A2DP_CODEC_INFO, codec_info, sizeof(codec_info));
- btsrv_a2dp_hdl_cb_user(conn, BTSRV_A2DP_STREAM_STARED, NULL, 0);
- }
- static void _btsrv_a2dp_check_state(void)
- {
- struct bt_conn *conn = btsrv_rdm_a2dp_get_actived();
- struct bt_conn *second_conn = btsrv_rdm_a2dp_get_second_dev();
- if (btsrv_rdm_is_actived_a2dp_stream_open()) {
- SYS_LOG_INF("a2dp trigger start\n");
- uint8_t format, sample_rate;
- uint8_t codec_info[3];
- btsrv_rdm_a2dp_get_codec_info(conn, &format, &sample_rate, NULL);
- codec_info[0] = format;
- codec_info[1] = sample_rate;
- codec_info[2] = btsrv_rdm_a2dp_get_bitpool(conn);
- btsrv_a2dp_hdl_cb_user(conn, BTSRV_A2DP_CODEC_INFO, codec_info, sizeof(codec_info));
- btsrv_a2dp_hdl_cb_user(conn, BTSRV_A2DP_STREAM_STARED, NULL, 0);
- } else if (second_conn && btsrv_rdm_is_a2dp_stream_open(second_conn)) {
- /* active dev may not update during call,so after call exit,
- * we should change active dev if current active dev is not
- * stream opened.
- */
- btsrv_rdm_a2dp_actived(second_conn, 1);
- SYS_LOG_INF("change active dev to another\n");
- }
- }
- static void pts_send_delay_report(struct bt_conn *base_conn, uint8_t tws_dev, void *cb_param)
- {
- uint32_t delay_time = (uint32_t)cb_param;
- hostif_bt_a2dp_send_delay_report(base_conn, (uint16_t)delay_time);
- }
- static void btsrv_a2dp_send_delay_report(uint16_t delay_time)
- {
- struct bt_conn *conn = btsrv_rdm_a2dp_get_actived();
- uint32_t cb_param = delay_time;
- if (btsrv_is_pts_test() && conn == NULL) {
- btsrv_rdm_get_connected_dev(pts_send_delay_report, (void *)cb_param);
- return;
- }
- if (conn) {
- hostif_bt_a2dp_send_delay_report(conn, delay_time);
- }
- }
- int btsrv_a2dp_init(struct btsrv_a2dp_start_param *param)
- {
- int ret = 0;
- int i = 0, max_register;
- max_register = MIN(CONFIG_MAX_A2DP_ENDPOINT, param->sbc_endpoint_num);
- max_register = (max_register == 1) ? 2 : max_register; /* Register two endpoint for 1 phone */
- for (i = 0; i < max_register; i++) {
- a2dp_sbc_endpoint[i].info.codec = (struct bt_a2dp_media_codec *)param->sbc_codec;
- a2dp_sbc_endpoint[i].info.a2dp_cp_scms_t = param->a2dp_cp_scms_t;
- a2dp_sbc_endpoint[i].info.a2dp_delay_report = param->a2dp_delay_report;
- #ifdef CONFIG_BT_A2DP_SINK
- ret |= hostif_bt_a2dp_register_endpoint(&a2dp_sbc_endpoint[i], BT_A2DP_AUDIO, BT_A2DP_EP_SINK);
- #endif
- }
- max_register = MIN(CONFIG_MAX_A2DP_ENDPOINT, param->aac_endpoint_num);
- max_register = (max_register == 1) ? 2 : max_register; /* Register two endpoint for 1 phone */
- a2dp_register_aac_num = max_register;
- for (i = 0; i < max_register; i++) {
- a2dp_aac_endpoint[i].info.codec = (struct bt_a2dp_media_codec *)param->aac_codec;
- a2dp_aac_endpoint[i].info.a2dp_cp_scms_t = param->a2dp_cp_scms_t;
- a2dp_aac_endpoint[i].info.a2dp_delay_report = param->a2dp_delay_report;
- #ifdef CONFIG_BT_A2DP_SINK
- ret |= hostif_bt_a2dp_register_endpoint(&a2dp_aac_endpoint[i], BT_A2DP_AUDIO, BT_A2DP_EP_SINK);
- #endif
- }
- if (ret) {
- SYS_LOG_ERR("bt br-a2dp-register failed\n");
- goto err;
- }
- a2dp_user_callback = param->cb;
- #ifdef CONFIG_BT_A2DP_TRS
- btsrv_trs_a2dp_init(param);
- #endif
- hostif_bt_a2dp_register_cb((struct bt_a2dp_app_cb *)&btsrv_a2dp_cb);
- return 0;
- err:
- return -1;
- }
- int btsrv_a2dp_deinit(void)
- {
- hostif_bt_a2dp_register_cb(NULL);
- a2dp_user_callback = NULL;
- #ifdef CONFIG_BT_A2DP_TRS
- btsrv_trs_a2dp_deinit();
- #endif
- return 0;
- }
- static int btsrv_a2dp_disable(void)
- {
- struct bt_conn *conn;
- /** step 1: unregister sdp list*****************************/
- #ifdef CONFIG_BT_AVDTP
- #ifdef CONFIG_BT_A2DP_SINK
- bt_unregister_a2dp_sink_sdp();
- #endif
- #if defined(CONFIG_TWS) || defined(CONFIG_BT_A2DP_TRS)
- bt_unregister_a2dp_source_sdp();
- #endif
- #endif
- #ifdef CONFIG_BT_AVRCP
- bt_unregister_avrcp_ct_sdp();
- bt_unregister_avrcp_tg_sdp();
- #endif
- /*** step 2: unregister avdtp psm, disable a2dp/avrcp********/
- hostif_bt_a2dp_disable(0);
- hostif_bt_avrcp_disable(0);
- /*** step 3: disconnect a2dp/avrcp***************************/
- conn = btsrv_rdm_a2dp_get_connected_dev();
- if (conn) {
- btsrv_a2dp_disconnect(conn);
- }
- conn = btsrv_rdm_avrcp_get_connected_dev();
- if (conn) {
- btsrv_avrcp_disconnect(conn);
- }
- #ifdef CONFIG_BT_A2DP_TRS
- conn = btsrv_rdm_trs_a2dp_get_actived();
- if (conn) {
- btsrv_a2dp_disconnect(conn);
- }
- conn = btsrv_rdm_trs_avrcp_get_actived();
- if (conn) {
- btsrv_avrcp_disconnect(conn);
- }
- #endif
- return 0;
- }
- static int btsrv_a2dp_enable(void)
- {
- struct bt_conn *conn;
- /** step 1: register sdp list*********************************/
- #ifdef CONFIG_BT_AVDTP
- #ifdef CONFIG_BT_A2DP_SINK
- bt_register_a2dp_sink_sdp();
- #endif
- #if defined(CONFIG_TWS) || defined(CONFIG_BT_A2DP_TRS)
- bt_register_a2dp_source_sdp();
- #endif
- #endif
- #ifdef CONFIG_BT_AVRCP
- bt_register_avrcp_ct_sdp();
- bt_register_avrcp_tg_sdp();
- #endif
- /*** step 2: register avdtp psm, enable a2dp/avrcp***********/
- hostif_bt_a2dp_enable(0);
- hostif_bt_avrcp_enable(0);
- /*** step 3: connect a2dp/avrcp******************************/
- conn = btsrv_rdm_acl_get_connected_dev();
- if (conn) {
- if (!btsrv_rdm_is_a2dp_connected(conn)) {
- btsrv_a2dp_connect(conn, BT_A2DP_CH_SINK);
- }
- if (!btsrv_rdm_is_avrcp_connected(conn)) {
- btsrv_avrcp_connect(conn);
- }
- }
- return 0;
- }
- int btsrv_a2dp_disconnect(struct bt_conn *conn)
- {
- if (!conn) {
- SYS_LOG_ERR("conn is NULL\n");
- return -EINVAL;
- }
- hostif_bt_a2dp_disconnect(conn);
- SYS_LOG_INF("a2dp_disconnect\n");
- return 0;
- }
- int btsrv_a2dp_connect(struct bt_conn *conn, uint8_t role)
- {
- #ifndef CONFIG_BT_A2DP_SINK
- if (role == BT_A2DP_CH_SINK) {
- SYS_LOG_INF("Not config A2DP SINK");
- return 0;
- }
- #endif
- if (!hostif_bt_a2dp_connect(conn, role)) {
- SYS_LOG_INF("Connect a2dp\n");
- } else {
- SYS_LOG_ERR("Connect a2dp failed\n");
- }
- return 0;
- }
- void btsrv_a2dp_halt_aac_endpoint(bool halt)
- {
- int ret, i;
- for (i = 0; i < a2dp_register_aac_num; i++) {
- ret = hostif_bt_a2dp_halt_endpoint(&a2dp_aac_endpoint[i], halt);
- SYS_LOG_INF("%s AAC endpoint %d\n", (halt ? "Halt" : "Resume"), ret);
- }
- }
- int btsrv_a2dp_process(struct app_msg *msg)
- {
- struct bt_conn *conn;
- #ifdef CONFIG_BT_A2DP_TRS
- if (btsrv_trs_a2dp_process(msg) == true) {
- if (MSG_BTSRV_A2DP_CONNECTED == _btsrv_get_msg_param_cmd(msg)) {
- trs_conn = (struct bt_conn *)(msg->ptr);
- } else if (MSG_BTSRV_A2DP_DISCONNECTED == _btsrv_get_msg_param_cmd(msg)) {
- trs_conn = NULL;
- }
- SYS_LOG_INF("trs proc offset %d", (_btsrv_get_msg_param_cmd(msg) - MSG_BTSRV_A2DP_START));
- return 0;
- }
- #endif
- switch (_btsrv_get_msg_param_cmd(msg)) {
- case MSG_BTSRV_A2DP_START:
- SYS_LOG_INF("btsrv a2dp start");
- btsrv_a2dp_init(msg->ptr);
- break;
- case MSG_BTSRV_A2DP_STOP:
- SYS_LOG_INF("btsrv a2dp stop");
- btsrv_a2dp_deinit();
- break;
- case MSG_BTSRV_A2DP_DISABLE:
- SYS_LOG_INF("btsrv a2dp disable");
- btsrv_a2dp_disable();
- break;
- case MSG_BTSRV_A2DP_ENABLE:
- SYS_LOG_INF("btsrv a2dp enable");
- btsrv_a2dp_enable();
- break;
- case MSG_BTSRV_A2DP_CONNECT_TO:
- SYS_LOG_INF("btsrv a2dp connect");
- conn = btsrv_rdm_find_conn_by_addr(msg->ptr);
- if (conn) {
- btsrv_a2dp_connect(conn, (_btsrv_get_msg_param_reserve(msg) ? BT_A2DP_CH_SOURCE : BT_A2DP_CH_SINK));
- }
- break;
- case MSG_BTSRV_A2DP_DISCONNECT:
- SYS_LOG_INF("btsrv a2dp disconnect");
- conn = btsrv_rdm_find_conn_by_addr(msg->ptr);
- if (conn) {
- btsrv_a2dp_disconnect(conn);
- }
- break;
- case MSG_BTSRV_A2DP_CONNECTED:
- SYS_LOG_INF("btsrv a2dp connected");
- _btsrv_a2dp_connected(msg->ptr);
- break;
- case MSG_BTSRV_A2DP_DISCONNECTED:
- SYS_LOG_INF("btsrv a2dp disconnected");
- if (btsrv_rdm_a2dp_get_actived() == (struct bt_conn *)(msg->ptr) ||
- btsrv_rdm_get_conn_role(msg->ptr) == BTSRV_TWS_SLAVE) {
- /* Device with media start, without media suspend/close buf direct
- * a2dp disconnect, need send media close to upper layer to stop music play.
- */
- btsrv_a2dp_hdl_cb_user(msg->ptr, BTSRV_A2DP_STREAM_CLOSED, NULL, 0);
- }
- _btsrv_a2dp_disconnected(msg->ptr);
- btsrv_event_notify(MSG_BTSRV_CONNECT, _btsrv_get_msg_param_cmd(msg), msg->ptr);
- break;
- case MSG_BTSRV_A2DP_MEDIA_STATE_CB:
- btsrv_a2dp_media_state_req_proc(msg->ptr, _btsrv_get_msg_param_reserve(msg));
- break;
- case MSG_BTSRV_A2DP_SET_CODEC_CB:
- btsrv_a2dp_seted_codec_proc(msg->ptr);
- break;
- case MSG_BTSRV_A2DP_MEDIA_STATE_OPEN:
- btsrv_a2dp_hdl_cb_user(msg->ptr, BTSRV_A2DP_STREAM_OPENED, NULL, 0);
- break;
- case MSG_BTSRV_A2DP_MEDIA_STATE_START:
- btsrv_a2dp_hdl_cb_user(msg->ptr, BTSRV_A2DP_STREAM_STARED, NULL, 0);
- break;
- case MSG_BTSRV_A2DP_MEDIA_STATE_CLOSE:
- btsrv_a2dp_hdl_cb_user(msg->ptr, BTSRV_A2DP_STREAM_CLOSED, NULL, 0);
- break;
- case MSG_BTSRV_A2DP_MEDIA_STATE_SUSPEND:
- btsrv_a2dp_hdl_cb_user(msg->ptr, BTSRV_A2DP_STREAM_SUSPEND, NULL, 0);
- break;
- case MSG_BTSRV_A2DP_ACTIVED_DEV_CHANGED:
- _btsrv_a2dp_actived_dev_changed(msg->ptr);
- break;
- case MSG_BTSRV_A2DP_CHECK_STATE:
- _btsrv_a2dp_check_state();
- break;
- case MSG_BTSRV_A2DP_SEND_DELAY_REPORT:
- btsrv_a2dp_send_delay_report((uint16_t)_btsrv_get_msg_param_value(msg));
- break;
- default:
- break;
- }
- return 0;
- }
- int btsrv_a2dp_trs_conn_get(void)
- {
- return (int)trs_conn;
- }
|