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