• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2021 Chipsea Technologies (Shenzhen) Corp., Ltd. All rights reserved.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 /*chipsea_ohos proguard begin*/
16 #include "cs_proguard.h"
17 /*chipsea_ohos proguard end*/
18 #include "cs_target_config.h"
19 #if APP_SUPPORT_A2DP_SBC == 1 || APP_SUPPORT_A2DP_AAC ==1 ||APP_SUPPORT_A2DP_SOURCE == 1
20 #include "al_rtos.h"
21 #include "app_bt.h"
22 #include "app_a2dp.h"
23 #if APP_SUPPORT_A2DP_SOURCE == 1
24 #include "app_a2dp_source.h"
25 #endif
26 #if APP_SUPPORT_TWS == 1
27 #include "app_tws.h"
28 #endif
29 #include "cs_adp_api.h"
30 
31 
32 app_a2dp_state_t t_a2dp_state = A2DP_IDLE;
33 
34 
35 
app_get_a2dp_state(void)36 app_a2dp_state_t app_get_a2dp_state(void)
37 {
38     return t_a2dp_state;
39 }
40 
app_set_a2dp_state(app_a2dp_state_t state)41 void app_set_a2dp_state(app_a2dp_state_t state)
42 {
43     APP_BT_MGR *app_bt_manager_ptr = cs_adp_get_app_bt_mgr_ptr();
44 
45     if (t_a2dp_state == state){
46         return;
47     }
48 
49     if(state == A2DP_PLAY){
50 #if TWS_SLAVE_CONNECT_MASTER == 1
51         if(app_bt_manager_ptr->connect_index == 1){
52 #if APP_SUPPORT_TWS == 1
53             if(tws_app_get_role() == TWS_SLAVE){
54                 app_bt_set_scan_mode(BT_NOSCAN);
55             }else
56 #endif
57             {
58                 app_bt_set_scan_mode(BT_CONNECTABLE);
59             }
60         }else if(app_bt_manager_ptr->connect_index >= 2){
61             app_bt_set_scan_mode(BT_NOSCAN);
62         }
63 #else
64         app_bt_set_scan_mode(BT_NOSCAN);
65 #endif
66     }
67     else if(t_a2dp_state == A2DP_PLAY && state != A2DP_PLAY){
68         if(app_bt_manager_ptr->connect_index == 1){
69 #if APP_SUPPORT_TWS == 1
70             if(tws_app_get_role() == TWS_SLAVE){
71                 app_bt_set_scan_mode(BT_NOSCAN);
72             }else
73 #endif
74             {
75                 #if APP_SUPPORT_LINK_ONE_ONLY == 1
76                 app_bt_set_scan_mode(BT_NOSCAN);
77                 #else
78                 app_bt_set_scan_mode(BT_CONNECTABLE);
79                 #endif
80             }
81         }else if(app_bt_manager_ptr->connect_index >= 2){
82             app_bt_set_scan_mode(BT_NOSCAN);
83         }
84     }
85     TRACE("APP:set a2dp state = %d\n",state);
86     t_a2dp_state = state;
87 }
88 
89 
bt_parse_sbc_sample_rate(uint8_t samp_rate)90 AUD_SAMPRATE_T bt_parse_sbc_sample_rate(uint8_t samp_rate)
91 {
92     AUD_SAMPRATE_T sample_rate = AUD_SAMPRATE_44100;
93     samp_rate = samp_rate & A2DP_CSIE_SAMP_FREQ_MSK;
94 
95     switch (samp_rate)
96     {
97         case A2DP_CSIE_SAMP_FREQ_16:
98             sample_rate = AUD_SAMPRATE_16000;
99             break;
100         case A2DP_CSIE_SAMP_FREQ_32:
101             sample_rate = AUD_SAMPRATE_32000;
102             break;
103         case A2DP_CSIE_SAMP_FREQ_48:
104             sample_rate = AUD_SAMPRATE_48000;
105             break;
106         case A2DP_CSIE_SAMP_FREQ_44:
107             sample_rate = AUD_SAMPRATE_44100;
108             break;
109         default:
110             ASSERT_ERR(0);
111             break;
112     }
113     return sample_rate;
114 }
115 
app_a2dp_pause(void)116 void app_a2dp_pause(void)
117 {
118     TRACE("APP:app_a2dp_pause.\n");
119     if(app_get_a2dp_state() == A2DP_PLAY){
120         app_media_play(AUD_BT_A2DP ,MC_STOP,0,true);
121         app_set_a2dp_state(A2DP_CONNECTED);
122     }
123 }
124 
app_a2dp_play(BT_ADDR bdaddr)125 void app_a2dp_play(BT_ADDR bdaddr)
126 {
127     A2DP_AUDIO_CAP *audio_cap = NULL;
128     MediaCommonStruct audio_param;
129     memset((U8*)&audio_param, 0, sizeof(MediaCommonStruct));
130     audio_cap = cs_adp_a2dp_get_audio_cap_by_addr(bdaddr);
131     TRACE("APP:app_a2dp_play audio_cap = 0x%x\n",audio_cap);
132     if(audio_cap){
133         audio_param.p.aud_ctrl.a2dpcodec = audio_cap->codec_type;
134         audio_param.p.aud_ctrl.samplerate = bt_parse_sbc_sample_rate(audio_cap->sample_rate_bit);
135         //TODO add channel parsing
136         audio_param.p.aud_ctrl.channel = audio_cap->channel;
137         audio_param.p.aud_ctrl.numBlocks = audio_cap->numBlocks;
138         audio_param.p.aud_ctrl.numSubBands = audio_cap->numSubBands;
139         audio_param.p.aud_ctrl.dpll_mode = AUD_DPLL_NORMAL;
140 #if APP_SUPPORT_TWS == 1
141         if(tws_app_get_role() >= TWS_NOROLE){
142             app_media_play(AUD_BT_A2DP,MC_OPEN,&audio_param,true);
143         }else{
144             app_media_play(AUD_BT_A2DP ,MC_STOP,0,false);
145             app_media_play(AUD_BT_A2DP ,MC_OPEN,&audio_param,true);
146         }
147 #else
148 #if APP_SUPPORT_MULTIPLE_PHONE == 1
149         if(app_get_a2dp_state() == A2DP_PLAY)
150             app_media_play(AUD_BT_A2DP ,MC_STOP,0,true);
151 #endif
152         app_media_play(AUD_BT_A2DP,MC_OPEN,&audio_param,true);
153 #endif
154         app_set_a2dp_state(A2DP_PLAY);
155     }
156 }
157 
158 
app_handle_a2dp_connect_status(CS_EVENT * event)159 void app_handle_a2dp_connect_status(CS_EVENT *event)
160 {
161     CS_ADP_A2DP_EVENT *cs_a2dp_msg = (CS_ADP_A2DP_EVENT *)event->Param;
162     app_connect_manager * app_bt_con = NULL;
163 
164     app_bt_con = app_bt_get_con_ptr_by_addr(&cs_a2dp_msg->bdaddr);
165     if(!app_bt_con ){
166         app_bt_con = app_bt_get_unused_con_ptr();
167         if(!app_bt_con){
168             TRACE("APP:app a2dp get con ptr error\n");
169             ASSERT_ERR(0);
170         }
171         memcpy(app_bt_con->remotedev_addr.addr,cs_a2dp_msg->bdaddr.addr, BD_ADDR_SIZE);
172     }
173 
174     if(app_bt_con->reconnect.connect_timer_handle){
175 #if PLF_AON_SUPPORT
176         co_timer_stop(app_bt_con->reconnect.connect_timer_handle);
177 #else
178         rtos_timer_stop(app_bt_con->reconnect.connect_timer_handle,0);
179 #endif
180         app_bt_con->reconnect.connect_timer_cb = NULL;
181     }
182 
183     switch(event->EventId){
184         case CS_ADP_A2DP_STREAM_OPEN:
185             {
186                 btdev_info* dev_info = cs_adp_get_devinfo_by_addr(&cs_a2dp_msg->bdaddr);
187                 if(dev_info){
188                     A2DP_AUDIO_CAP *audio_cap = (A2DP_AUDIO_CAP *)cs_a2dp_msg->p.signalingP.audioCodecP;
189                     dev_info->a2dp_state = 1;
190                     dev_info->a2dp_codectype = audio_cap->codec_type;
191                     dev_info->a2dp_role = cs_a2dp_msg->role;
192                 }
193                 app_bt_con->profile.a2dp_connect = CONNECTED;
194                 memcpy(app_bt_con->remotedev_addr.addr, cs_a2dp_msg->bdaddr.addr, BD_ADDR_SIZE);
195                 app_bt_con->reconnect.connect_retry_cnt = 0;
196 
197                 switch(app_bt_con->reconnect.reconnect_mode){
198                     case RECONNECT_POWERON:
199                         if(app_bt_con->profile.hfp_connect != CONNECTED){
200                             app_bt_connect_hfp(&app_bt_con->remotedev_addr);
201                         }
202                         break;
203                     case RECONNECT_AFTER_DISC:
204                         if(app_bt_con->profile.hfp_connect != CONNECTED){
205                             app_bt_connect_hfp(&app_bt_con->remotedev_addr);
206                         }
207                         break;
208                     default:
209                         app_bt_con->reconnect.reconnect_mode = RECONNECT_IDLE;
210                         break;
211                 }
212             }
213             break;
214         case CS_ADP_A2DP_STREAM_CLOSED:
215             {
216                 app_bt_con->profile.a2dp_connect = DISCONNECTED;
217                 switch(app_bt_con->reconnect.reconnect_mode){
218                     case RECONNECT_POWERON:
219                         app_bt_con->reconnect.reconnect_mode = RECONNECT_IDLE;
220                         break;
221                     case RECONNECT_AFTER_DISC:
222                         if(app_bt_con->reconnect.connect_retry_cnt < APP_RECONNECT_NUM){
223 #if PLF_AON_SUPPORT
224                             app_bt_start_reconnect(&app_bt_con->reconnect.connect_timer_handle,app_bt_con->reconnect.cb_param
225                                                   ,APP_RECONNECT_INCREASE_TIME*app_bt_con->reconnect.connect_retry_cnt + APP_RECONNECT_TIME);
226 #else
227                             app_bt_start_reconnect(app_bt_con->reconnect.connect_timer_handle
228                                                   ,APP_RECONNECT_INCREASE_TIME*app_bt_con->reconnect.connect_retry_cnt + APP_RECONNECT_TIME);
229 #endif
230                             app_bt_con->reconnect.connect_retry_cnt++;
231                         }else{
232                             app_bt_con->reconnect.reconnect_mode = RECONNECT_IDLE;
233                             #if APP_SUPPORT_TWS == 1
234                             app_tws_power_down();
235                             #endif
236                         }
237                         break;
238                     default:
239                         if(cs_a2dp_msg->p.disc_reason == BT_CONNECTION_TIMEOUT){
240                             app_bt_con->reconnect.reconnect_mode = RECONNECT_AFTER_DISC;
241                             TRACE("APP:a2dp start reconnect\n");
242 #if PLF_AON_SUPPORT
243                             app_bt_start_reconnect(&app_bt_con->reconnect.connect_timer_handle, app_bt_con->reconnect.cb_param, APP_RECONNECT_TIME);
244 #else
245                             app_bt_start_reconnect(app_bt_con->reconnect.connect_timer_handle ,APP_RECONNECT_TIME);
246 #endif
247                         }else{
248                             app_bt_con->profile.a2dp_connect = CONNECT_IDLE;
249                         }
250                         break;
251                 }
252             }
253             break;
254         default:
255             break;
256     }
257     app_bt_report_connect_internal_audio(app_bt_con);
258 }
259 
app_a2dp_state_machine(CS_EVENT * event)260 void app_a2dp_state_machine(CS_EVENT *event)
261 {
262     //CS_ADP_A2DP_EVENT *cs_a2dp_msg = (CS_ADP_A2DP_EVENT *)event->Param;
263 
264     switch(event->EventId){
265         case CS_ADP_A2DP_STREAM_OPEN:
266             if(app_get_a2dp_state() == A2DP_IDLE){
267                 app_set_a2dp_state(A2DP_CONNECTED);
268             }
269             break;
270         case CS_ADP_A2DP_STREAM_CLOSED:
271             if(app_get_a2dp_state() != A2DP_PLAY)
272                 app_set_a2dp_state(A2DP_IDLE);
273             break;
274         default:
275             break;
276     }
277 }
278 
app_a2dp_msg_handle(CS_EVENT * event)279 void app_a2dp_msg_handle(CS_EVENT *event)
280 {
281     CS_ADP_A2DP_EVENT *cs_a2dp_msg = (CS_ADP_A2DP_EVENT *)event->Param;
282     app_a2dp_state_machine(event);
283 
284     switch(event->EventId) {
285         case CS_ADP_A2DP_STREAM_OPEN:
286             {
287                 if(cs_a2dp_msg->role == BT_A2DP_SOURCE){
288 #if APP_SUPPORT_A2DP_SOURCE == 1
289 #endif
290                 }
291                 app_handle_a2dp_connect_status(event);
292             }
293             break;
294         case CS_ADP_A2DP_STREAM_STARTED:
295             {
296                 A2DP_AUDIO_CAP *audio_cap = (A2DP_AUDIO_CAP *)cs_a2dp_msg->p.signalingP.audioCodecP;
297                 TRACE("APP:a2dp_stream_started role = %d, codec_type = %d , sample_rate_bit = %d\n",cs_a2dp_msg->role,audio_cap->codec_type, audio_cap->sample_rate_bit);
298                 if(cs_a2dp_msg->role == BT_A2DP_SOURCE){
299 #if APP_SUPPORT_A2DP_SOURCE == 1
300                     app_a2dp_source_sbc_data_send_timer_begin();
301 #endif
302                 }else{
303                     app_a2dp_play(cs_a2dp_msg->bdaddr);
304                 }
305             }
306             break;
307         case CS_ADP_A2DP_STREAM_SUSPENDED:
308             {
309                 TRACE("APP:a2dp_stream_suspended role = %d\n",cs_a2dp_msg->role);
310                 if(cs_a2dp_msg->role == BT_A2DP_SINK){
311                     app_a2dp_pause();
312                 }
313             }
314             break;
315         case CS_ADP_A2DP_STREAM_CLOSED:
316             {
317                 TRACE("APP:a2dp_stream_closed role = %d\n",cs_a2dp_msg->role);
318                 if(cs_a2dp_msg->role == BT_A2DP_SINK){
319                     app_a2dp_pause();
320                 }
321                 app_handle_a2dp_connect_status(event);
322             }
323             break;
324 
325         case CS_ADP_A2DP_STREAM_PACKET_SENT:
326             TRACE("APP:a2dp source data send succ!\n");
327             if(cs_a2dp_msg->role == BT_A2DP_SOURCE){
328 #if APP_SUPPORT_A2DP_SOURCE == 1
329                 app_a2dp_source_sbc_data_send_timer_begin();
330 #endif
331             }
332             break;
333         case CS_ADP_A2DP_STREAM_DATA_IND:
334             {
335                 A2DP_AUDIO_CAP *audio_cap = (A2DP_AUDIO_CAP *)cs_a2dp_msg->p.mediaP.audioCodecP;
336                 A2DP_AUDIO_DATA *audio_data = (A2DP_AUDIO_DATA *)cs_a2dp_msg->p.mediaP.audioDataP;
337 
338                 if(app_get_a2dp_state() == A2DP_PLAY){
339                     AppReceive_A2dpData(((unsigned char *)audio_data->data)+ audio_data->headerlen ,
340                                                           audio_data->datalen - audio_data->headerlen,
341                                                           audio_cap->sbc_frame_number ,
342                                                           bt_parse_sbc_sample_rate(audio_cap->sample_rate_bit));
343                 }else{
344                     TRACE("APP:free a2dp stream data\n");
345                 }
346             }
347             break;
348         default:
349             break;
350     }
351 
352 }
353 
354 #endif
355 
356 
357