1 /*
2 This example code is in the Public Domain (or CC0 licensed, at your option.)
3
4 Unless required by applicable law or agreed to in writing, this
5 software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
6 CONDITIONS OF ANY KIND, either express or implied.
7 */
8
9 #include <stdint.h>
10 #include <stdbool.h>
11 #include <stdlib.h>
12 #include <string.h>
13 #include "esp_log.h"
14 #include "esp_bt_main.h"
15 #include "esp_bt_device.h"
16 #include "esp_gap_bt_api.h"
17 #include "esp_hf_ag_api.h"
18 #include "esp_timer.h"
19 #include "freertos/FreeRTOS.h"
20 #include "freertos/task.h"
21 #include "freertos/queue.h"
22 #include "freertos/semphr.h"
23 #include "freertos/ringbuf.h"
24 #include "time.h"
25 #include "sys/time.h"
26 #include "sdkconfig.h"
27 #include "bt_app_core.h"
28 #include "bt_app_hf.h"
29 #include "osi/allocator.h"
30
31 const char *c_hf_evt_str[] = {
32 "CONNECTION_STATE_EVT", /*!< SERVICE LEVEL CONNECTION STATE CONTROL */
33 "AUDIO_STATE_EVT", /*!< AUDIO CONNECTION STATE CONTROL */
34 "VR_STATE_CHANGE_EVT", /*!< VOICE RECOGNITION CHANGE */
35 "VOLUME_CONTROL_EVT", /*!< AUDIO VOLUME CONTROL */
36 "UNKNOW_AT_CMD", /*!< UNKNOW AT COMMAND RECIEVED */
37 "IND_UPDATE", /*!< INDICATION UPDATE */
38 "CIND_RESPONSE_EVT", /*!< CALL & DEVICE INDICATION */
39 "COPS_RESPONSE_EVT", /*!< CURRENT OPERATOR EVENT */
40 "CLCC_RESPONSE_EVT", /*!< LIST OF CURRENT CALL EVENT */
41 "CNUM_RESPONSE_EVT", /*!< SUBSCRIBER INFORTMATION OF CALL EVENT */
42 "DTMF_RESPONSE_EVT", /*!< DTMF TRANSFER EVT */
43 "NREC_RESPONSE_EVT", /*!< NREC RESPONSE EVT */
44 "ANSWER_INCOMING_EVT", /*!< ANSWER INCOMING EVT */
45 "REJECT_INCOMING_EVT", /*!< AREJECT INCOMING EVT */
46 "DIAL_EVT", /*!< DIAL INCOMING EVT */
47 "WBS_EVT", /*!< CURRENT CODEC EVT */
48 "BCS_EVT", /*!< CODEC NEGO EVT */
49 };
50
51 //esp_hf_connection_state_t
52 const char *c_connection_state_str[] = {
53 "DISCONNECTED",
54 "CONNECTING",
55 "CONNECTED",
56 "SLC_CONNECTED",
57 "DISCONNECTING",
58 };
59
60 // esp_hf_audio_state_t
61 const char *c_audio_state_str[] = {
62 "disconnected",
63 "connecting",
64 "connected",
65 "connected_msbc",
66 };
67
68 /// esp_hf_vr_state_t
69 const char *c_vr_state_str[] = {
70 "Disabled",
71 "Enabled",
72 };
73
74 // esp_hf_nrec_t
75 const char *c_nrec_status_str[] = {
76 "NREC DISABLE",
77 "NREC ABLE",
78 };
79
80 // esp_hf_control_target_t
81 const char *c_volume_control_target_str[] = {
82 "SPEAKER",
83 "MICROPHONE",
84 };
85
86 // esp_hf_subscriber_service_type_t
87 char *c_operator_name_str[] = {
88 "中国移动",
89 "中国联通",
90 "中国电信",
91 };
92
93 // esp_hf_subscriber_service_type_t
94 char *c_subscriber_service_type_str[] = {
95 "UNKNOWN",
96 "VOICE",
97 "FAX",
98 };
99
100 // esp_hf_nego_codec_status_t
101 const char *c_codec_mode_str[] = {
102 "CVSD Only",
103 "Use CVSD",
104 "Use MSBC",
105 };
106
107 #if CONFIG_BT_HFP_AUDIO_DATA_PATH_HCI
108 #define TABLE_SIZE 100
109 #define TABLE_SIZE_BYTE 200
110 // Produce a sine audio
111 static const int16_t sine_int16[TABLE_SIZE] = {
112 0, 2057, 4107, 6140, 8149, 10126, 12062, 13952, 15786, 17557,
113 19260, 20886, 22431, 23886, 25247, 26509, 27666, 28714, 29648, 30466,
114 31163, 31738, 32187, 32509, 32702, 32767, 32702, 32509, 32187, 31738,
115 31163, 30466, 29648, 28714, 27666, 26509, 25247, 23886, 22431, 20886,
116 19260, 17557, 15786, 13952, 12062, 10126, 8149, 6140, 4107, 2057,
117 0, -2057, -4107, -6140, -8149, -10126, -12062, -13952, -15786, -17557,
118 -19260, -20886, -22431, -23886, -25247, -26509, -27666, -28714, -29648, -30466,
119 -31163, -31738, -32187, -32509, -32702, -32767, -32702, -32509, -32187, -31738,
120 -31163, -30466, -29648, -28714, -27666, -26509, -25247, -23886, -22431, -20886,
121 -19260, -17557, -15786, -13952, -12062, -10126, -8149, -6140, -4107, -2057,
122 };
123
124 #define ESP_HFP_RINGBUF_SIZE 3600
125
126 // 7500 microseconds(=12 slots) is aligned to 1 msbc frame duration, and is multiple of common Tesco for eSCO link with EV3 or 2-EV3 packet type
127 #define PCM_BLOCK_DURATION_US (7500)
128
129 #define WBS_PCM_SAMPLING_RATE_KHZ (16)
130 #define PCM_SAMPLING_RATE_KHZ (8)
131
132 #define BYTES_PER_SAMPLE (2)
133
134 // input can refer to Enhanced Setup Synchronous Connection Command in core spec4.2 Vol2, Part E
135 #define WBS_PCM_INPUT_DATA_SIZE (WBS_PCM_SAMPLING_RATE_KHZ * PCM_BLOCK_DURATION_US / 1000 * BYTES_PER_SAMPLE) //240
136 #define PCM_INPUT_DATA_SIZE (PCM_SAMPLING_RATE_KHZ * PCM_BLOCK_DURATION_US / 1000 * BYTES_PER_SAMPLE) //120
137
138 #define PCM_GENERATOR_TICK_US (4000)
139
140 static long s_data_num = 0;
141 static RingbufHandle_t s_m_rb = NULL;
142 static uint64_t s_time_new, s_time_old;
143 static esp_timer_handle_t s_periodic_timer;
144 static uint64_t s_last_enter_time, s_now_enter_time;
145 static uint64_t s_us_duration;
146 static xSemaphoreHandle s_send_data_Semaphore = NULL;
147 static xTaskHandle s_bt_app_send_data_task_handler = NULL;
148 static esp_hf_audio_state_t s_audio_code;
149
150 static void print_speed(void);
151
bt_app_hf_outgoing_cb(uint8_t * p_buf,uint32_t sz)152 static uint32_t bt_app_hf_outgoing_cb(uint8_t *p_buf, uint32_t sz)
153 {
154 size_t item_size = 0;
155 uint8_t *data;
156 if (!s_m_rb) {
157 return 0;
158 }
159 vRingbufferGetInfo(s_m_rb, NULL, NULL, NULL, NULL, &item_size);
160 if (item_size >= sz) {
161 data = xRingbufferReceiveUpTo(s_m_rb, &item_size, 0, sz);
162 memcpy(p_buf, data, item_size);
163 vRingbufferReturnItem(s_m_rb, data);
164 return sz;
165 } else {
166 // data not enough, do not read\n
167 return 0;
168 }
169 return 0;
170 }
171
bt_app_hf_incoming_cb(const uint8_t * buf,uint32_t sz)172 static void bt_app_hf_incoming_cb(const uint8_t *buf, uint32_t sz)
173 {
174 s_time_new = esp_timer_get_time();
175 s_data_num += sz;
176 if ((s_time_new - s_time_old) >= 3000000) {
177 print_speed();
178 }
179 }
180
bt_app_hf_create_audio_data(uint8_t * p_buf,uint32_t sz)181 static uint32_t bt_app_hf_create_audio_data(uint8_t *p_buf, uint32_t sz)
182 {
183 static int index = 0;
184 uint8_t *data = (uint8_t *)sine_int16;
185
186 for (uint32_t i = 0; i < sz; i++) {
187 p_buf[i] = data[index++];
188 if (index >= TABLE_SIZE_BYTE) {
189 index -= TABLE_SIZE_BYTE;
190 }
191 }
192 return sz;
193 }
194
print_speed(void)195 static void print_speed(void)
196 {
197 float tick_s = (s_time_new - s_time_old) / 1000000.0;
198 float speed = s_data_num * 8 / tick_s / 1000.0;
199 ESP_LOGI(BT_HF_TAG, "speed(%fs ~ %fs): %f kbit/s" , s_time_old / 1000000.0, s_time_new / 1000000.0, speed);
200 s_data_num = 0;
201 s_time_old = s_time_new;
202 }
203
bt_app_send_data_timer_cb(void * arg)204 static void bt_app_send_data_timer_cb(void *arg)
205 {
206 if (!xSemaphoreGive(s_send_data_Semaphore)) {
207 ESP_LOGE(BT_HF_TAG, "%s xSemaphoreGive failed", __func__);
208 return;
209 }
210 return;
211 }
212
bt_app_send_data_task(void * arg)213 static void bt_app_send_data_task(void *arg)
214 {
215 uint64_t frame_data_num;
216 uint32_t item_size = 0;
217 uint8_t *buf = NULL;
218 for (;;) {
219 if (xSemaphoreTake(s_send_data_Semaphore, (portTickType)portMAX_DELAY)) {
220 s_now_enter_time = esp_timer_get_time();
221 s_us_duration = s_now_enter_time - s_last_enter_time;
222 if(s_audio_code == ESP_HF_AUDIO_STATE_CONNECTED_MSBC) {
223 // time of a frame is 7.5ms, sample is 120, data is 2 (byte/sample), so a frame is 240 byte (HF_SBC_ENC_RAW_DATA_SIZE)
224 frame_data_num = s_us_duration / (PCM_BLOCK_DURATION_US / WBS_PCM_INPUT_DATA_SIZE);
225 s_last_enter_time += frame_data_num * (PCM_BLOCK_DURATION_US / WBS_PCM_INPUT_DATA_SIZE);
226 } else {
227 frame_data_num = s_us_duration / (PCM_BLOCK_DURATION_US / PCM_INPUT_DATA_SIZE);
228 s_last_enter_time += frame_data_num * (PCM_BLOCK_DURATION_US / PCM_INPUT_DATA_SIZE);
229 }
230 buf = osi_malloc(frame_data_num);
231 if (!buf) {
232 ESP_LOGE(BT_HF_TAG, "%s, no mem", __FUNCTION__);
233 continue;
234 }
235 bt_app_hf_create_audio_data(buf, frame_data_num);
236 BaseType_t done = xRingbufferSend(s_m_rb, buf, frame_data_num, 0);
237 if (!done) {
238 ESP_LOGE(BT_HF_TAG, "rb send fail\n");
239 }
240 osi_free(buf);
241 vRingbufferGetInfo(s_m_rb, NULL, NULL, NULL, NULL, &item_size);
242
243 if(s_audio_code == ESP_HF_AUDIO_STATE_CONNECTED_MSBC) {
244 if(item_size >= WBS_PCM_INPUT_DATA_SIZE) {
245 esp_hf_outgoing_data_ready();
246 }
247 } else {
248 if(item_size >= PCM_INPUT_DATA_SIZE) {
249 esp_hf_outgoing_data_ready();
250 }
251 }
252 }
253 }
254 }
bt_app_send_data(void)255 void bt_app_send_data(void)
256 {
257 s_send_data_Semaphore = xSemaphoreCreateBinary();
258 xTaskCreate(bt_app_send_data_task, "BtAppSendDataTask", 2048, NULL, configMAX_PRIORITIES - 3, &s_bt_app_send_data_task_handler);
259 s_m_rb = xRingbufferCreate(ESP_HFP_RINGBUF_SIZE, RINGBUF_TYPE_BYTEBUF);
260 const esp_timer_create_args_t c_periodic_timer_args = {
261 .callback = &bt_app_send_data_timer_cb,
262 .name = "periodic"
263 };
264 ESP_ERROR_CHECK(esp_timer_create(&c_periodic_timer_args, &s_periodic_timer));
265 ESP_ERROR_CHECK(esp_timer_start_periodic(s_periodic_timer, PCM_GENERATOR_TICK_US));
266 s_last_enter_time = esp_timer_get_time();
267 return;
268 }
269
bt_app_send_data_shut_down(void)270 void bt_app_send_data_shut_down(void)
271 {
272 if (s_bt_app_send_data_task_handler) {
273 vTaskDelete(s_bt_app_send_data_task_handler);
274 s_bt_app_send_data_task_handler = NULL;
275 }
276 if (s_send_data_Semaphore) {
277 vSemaphoreDelete(s_send_data_Semaphore);
278 s_send_data_Semaphore = NULL;
279 }
280 if(s_periodic_timer) {
281 ESP_ERROR_CHECK(esp_timer_stop(s_periodic_timer));
282 ESP_ERROR_CHECK(esp_timer_delete(s_periodic_timer));
283 }
284 if (s_m_rb) {
285 vRingbufferDelete(s_m_rb);
286 }
287 return;
288 }
289 #endif /* #if CONFIG_BT_HFP_AUDIO_DATA_PATH_HCI */
290
bt_app_hf_cb(esp_hf_cb_event_t event,esp_hf_cb_param_t * param)291 void bt_app_hf_cb(esp_hf_cb_event_t event, esp_hf_cb_param_t *param)
292 {
293 if (event <= ESP_HF_BCS_RESPONSE_EVT) {
294 ESP_LOGI(BT_HF_TAG, "APP HFP event: %s", c_hf_evt_str[event]);
295 } else {
296 ESP_LOGE(BT_HF_TAG, "APP HFP invalid event %d", event);
297 }
298
299 switch (event) {
300 case ESP_HF_CONNECTION_STATE_EVT:
301 {
302 ESP_LOGI(BT_HF_TAG, "--connection state %s, peer feats 0x%x, chld_feats 0x%x",
303 c_connection_state_str[param->conn_stat.state],
304 param->conn_stat.peer_feat,
305 param->conn_stat.chld_feat);
306 memcpy(hf_peer_addr, param->conn_stat.remote_bda, ESP_BD_ADDR_LEN);
307 break;
308 }
309
310 case ESP_HF_AUDIO_STATE_EVT:
311 {
312 ESP_LOGI(BT_HF_TAG, "--Audio State %s", c_audio_state_str[param->audio_stat.state]);
313 #if CONFIG_BT_HFP_AUDIO_DATA_PATH_HCI
314 if (param->audio_stat.state == ESP_HF_AUDIO_STATE_CONNECTED ||
315 param->audio_stat.state == ESP_HF_AUDIO_STATE_CONNECTED_MSBC)
316 {
317 if(param->audio_stat.state == ESP_HF_AUDIO_STATE_CONNECTED) {
318 s_audio_code = ESP_HF_AUDIO_STATE_CONNECTED;
319 } else {
320 s_audio_code = ESP_HF_AUDIO_STATE_CONNECTED_MSBC;
321 }
322 s_time_old = esp_timer_get_time();
323 esp_bt_hf_register_data_callback(bt_app_hf_incoming_cb, bt_app_hf_outgoing_cb);
324 /* Begin send esco data task */
325 bt_app_send_data();
326 } else if (param->audio_stat.state == ESP_HF_AUDIO_STATE_DISCONNECTED) {
327 ESP_LOGI(BT_HF_TAG, "--ESP AG Audio Connection Disconnected.");
328 bt_app_send_data_shut_down();
329 }
330 #endif /* #if CONFIG_BT_HFP_AUDIO_DATA_PATH_HCI */
331 break;
332 }
333
334 case ESP_HF_BVRA_RESPONSE_EVT:
335 {
336 ESP_LOGI(BT_HF_TAG, "--Voice Recognition is %s", c_vr_state_str[param->vra_rep.value]);
337 break;
338 }
339
340 case ESP_HF_VOLUME_CONTROL_EVT:
341 {
342 ESP_LOGI(BT_HF_TAG, "--Volume Target: %s, Volume %d", c_volume_control_target_str[param->volume_control.type], param->volume_control.volume);
343 break;
344 }
345
346 case ESP_HF_UNAT_RESPONSE_EVT:
347 {
348 ESP_LOGI(BT_HF_TAG, "--UNKOW AT CMD: %s", param->unat_rep.unat);
349 esp_hf_unat_response(hf_peer_addr, NULL);
350 break;
351 }
352
353 case ESP_HF_IND_UPDATE_EVT:
354 {
355 ESP_LOGI(BT_HF_TAG, "--UPDATE INDCATOR!");
356 esp_hf_call_status_t call_state = 1;
357 esp_hf_call_setup_status_t call_setup_state = 2;
358 esp_hf_network_state_t ntk_state = 1;
359 int signal = 2;
360 esp_bt_hf_indchange_notification(hf_peer_addr,call_state,call_setup_state,ntk_state,signal);
361 break;
362 }
363
364 case ESP_HF_CIND_RESPONSE_EVT:
365 {
366 ESP_LOGI(BT_HF_TAG, "--CIND Start.");
367 esp_hf_call_status_t call_status = 0;
368 esp_hf_call_setup_status_t call_setup_status = 0;
369 esp_hf_network_state_t ntk_state = 1;
370 int signal = 4;
371 esp_hf_roaming_status_t roam = 0;
372 int batt_lev = 3;
373 esp_hf_call_held_status_t call_held_status = 0;
374 esp_bt_hf_cind_response(hf_peer_addr,call_status,call_setup_status,ntk_state,signal,roam,batt_lev,call_held_status);
375 break;
376 }
377
378 case ESP_HF_COPS_RESPONSE_EVT:
379 {
380 const int svc_type = 1;
381 esp_bt_hf_cops_response(hf_peer_addr, c_operator_name_str[svc_type]);
382 break;
383 }
384
385 case ESP_HF_CLCC_RESPONSE_EVT:
386 {
387 int index = 1;
388 //mandatory
389 esp_hf_current_call_direction_t dir = 1;
390 esp_hf_current_call_status_t current_call_status = 0;
391 esp_hf_current_call_mode_t mode = 0;
392 esp_hf_current_call_mpty_type_t mpty = 0;
393 //option
394 char *number = {"123456"};
395 esp_hf_call_addr_type_t type = ESP_HF_CALL_ADDR_TYPE_UNKNOWN;
396
397 ESP_LOGI(BT_HF_TAG, "--Calling Line Identification.");
398 esp_bt_hf_clcc_response(hf_peer_addr, index, dir, current_call_status, mode, mpty, number, type);
399 break;
400 }
401
402 case ESP_HF_CNUM_RESPONSE_EVT:
403 {
404 char *number = {"123456"};
405 esp_hf_subscriber_service_type_t type = 1;
406 ESP_LOGI(BT_HF_TAG, "--Current Number is %s ,Type is %s.", number, c_subscriber_service_type_str[type]);
407 esp_bt_hf_cnum_response(hf_peer_addr, number,type);
408 break;
409 }
410
411 case ESP_HF_VTS_RESPONSE_EVT:
412 {
413 ESP_LOGI(BT_HF_TAG, "--DTMF code is: %s.", param->vts_rep.code);
414 break;
415 }
416
417 case ESP_HF_NREC_RESPONSE_EVT:
418 {
419 ESP_LOGI(BT_HF_TAG, "--NREC status is: %s.", c_nrec_status_str[param->nrec.state]);
420 break;
421 }
422
423 case ESP_HF_ATA_RESPONSE_EVT:
424 {
425 ESP_LOGI(BT_HF_TAG, "--Asnwer Incoming Call.");
426 char *number = {"123456"};
427 esp_bt_hf_answer_call(hf_peer_addr,1,0,1,0,number,0);
428 break;
429 }
430
431 case ESP_HF_CHUP_RESPONSE_EVT:
432 {
433 ESP_LOGI(BT_HF_TAG, "--Reject Incoming Call.");
434 char *number = {"123456"};
435 esp_bt_hf_reject_call(hf_peer_addr,0,0,0,0,number,0);
436 break;
437 }
438
439 case ESP_HF_DIAL_EVT:
440 {
441 if (param->out_call.num_or_loc) {
442 //dia_num_or_mem
443 ESP_LOGI(BT_HF_TAG, "--Dial \"%s\".", param->out_call.num_or_loc);
444 esp_bt_hf_out_call(hf_peer_addr,1,0,1,0,param->out_call.num_or_loc,0);
445 } else {
446 //dia_last
447 ESP_LOGI(BT_HF_TAG, "--Dial last number.");
448 }
449 break;
450 }
451 #if (CONFIG_BT_HFP_WBS_ENABLE)
452 case ESP_HF_WBS_RESPONSE_EVT:
453 {
454 ESP_LOGI(BT_HF_TAG, "--Current codec: %s",c_codec_mode_str[param->wbs_rep.codec]);
455 break;
456 }
457 #endif
458 case ESP_HF_BCS_RESPONSE_EVT:
459 {
460 ESP_LOGI(BT_HF_TAG, "--Consequence of codec negotiation: %s",c_codec_mode_str[param->bcs_rep.mode]);
461 break;
462 }
463
464 default:
465 ESP_LOGI(BT_HF_TAG, "Unsupported HF_AG EVT: %d.", event);
466 break;
467
468 }
469 }
470