|
|
@@ -0,0 +1,297 @@
|
|
|
+/*
|
|
|
+ This example code is in the Public Domain (or CC0 licensed, at your option.)
|
|
|
+
|
|
|
+ Unless required by applicable law or agreed to in writing, this
|
|
|
+ software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
|
|
|
+ CONDITIONS OF ANY KIND, either express or implied.
|
|
|
+*/
|
|
|
+
|
|
|
+#include <stdint.h>
|
|
|
+#include <stdbool.h>
|
|
|
+#include <stdlib.h>
|
|
|
+#include <string.h>
|
|
|
+#include "esp_log.h"
|
|
|
+#include "esp_bt_main.h"
|
|
|
+#include "esp_bt_device.h"
|
|
|
+#include "esp_gap_bt_api.h"
|
|
|
+#include "esp_hf_ag_api.h"
|
|
|
+#include "freertos/FreeRTOS.h"
|
|
|
+#include "freertos/task.h"
|
|
|
+#include "freertos/queue.h"
|
|
|
+#include "freertos/semphr.h"
|
|
|
+#include "time.h"
|
|
|
+#include "sys/time.h"
|
|
|
+#include "sdkconfig.h"
|
|
|
+#include "bt_app_core.h"
|
|
|
+#include "bt_app_hf.h"
|
|
|
+
|
|
|
+const char *c_hf_evt_str[] = {
|
|
|
+ "CONNECTION_STATE_EVT", /*!< SERVICE LEVEL CONNECTION STATE CONTROL */
|
|
|
+ "AUDIO_STATE_EVT", /*!< AUDIO CONNECTION STATE CONTROL */
|
|
|
+ "VR_STATE_CHANGE_EVT", /*!< VOICE RECOGNITION CHANGE */
|
|
|
+ "VOLUME_CONTROL_EVT", /*!< AUDIO VOLUME CONTROL */
|
|
|
+ "UNKNOW_AT_CMD", /*!< UNKNOW AT COMMAND RECIEVED */
|
|
|
+ "CIND_RESPONSE_EVT", /*!< CALL & DEVICE INDICATION */
|
|
|
+ "COPS_RESPONSE_EVT", /*!< CURRENT OPERATOR EVENT */
|
|
|
+ "CLCC_RESPONSE_EVT", /*!< LIST OF CURRENT CALL EVENT */
|
|
|
+ "CNUM_RESPONSE_EVT", /*!< SUBSCRIBER INFORTMATION OF CALL EVENT */
|
|
|
+ "DTMF_RESPONSE_EVT", /*!< DTMF TRANSFER EVT */
|
|
|
+ "NREC_RESPONSE_EVT", /*!< NREC RESPONSE EVT */
|
|
|
+ "ANSWER_INCOMING_EVT", /*!< ANSWER INCOMING EVT */
|
|
|
+ "REJECT_INCOMING_EVT", /*!< AREJECT INCOMING EVT */
|
|
|
+ "DIAL_EVT", /*!< DIAL INCOMING EVT */
|
|
|
+ "BAC_EVT", /*!< CODEC NEGO EVT */
|
|
|
+ "BCS_EVT", /*!< CODEC NEGO EVT */
|
|
|
+};
|
|
|
+
|
|
|
+//esp_hf_connection_state_t
|
|
|
+const char *c_connection_state_str[] = {
|
|
|
+ "DISCONNECTED",
|
|
|
+ "CONNECTING",
|
|
|
+ "CONNECTED",
|
|
|
+ "SLC_CONNECTED",
|
|
|
+ "DISCONNECTING",
|
|
|
+};
|
|
|
+
|
|
|
+// esp_hf_audio_state_t
|
|
|
+const char *c_audio_state_str[] = {
|
|
|
+ "disconnected",
|
|
|
+ "connecting",
|
|
|
+ "connected",
|
|
|
+ "connected_msbc",
|
|
|
+};
|
|
|
+
|
|
|
+/// esp_hf_vr_state_t
|
|
|
+const char *c_vr_state_str[] = {
|
|
|
+ "Disabled",
|
|
|
+ "Enabled",
|
|
|
+};
|
|
|
+
|
|
|
+// esp_hf_nrec_t
|
|
|
+const char *c_nrec_status_str[] = {
|
|
|
+ "NREC DISABLE",
|
|
|
+ "NREC ABLE",
|
|
|
+};
|
|
|
+
|
|
|
+// esp_hf_control_target_t
|
|
|
+const char *c_volume_control_target_str[] = {
|
|
|
+ "SPEAKER",
|
|
|
+ "MICROPHONE",
|
|
|
+};
|
|
|
+
|
|
|
+// esp_hf_subscriber_service_type_t
|
|
|
+char *c_operator_name_str[] = {
|
|
|
+ "中国移动",
|
|
|
+ "中国联通",
|
|
|
+ "中国电信",
|
|
|
+};
|
|
|
+
|
|
|
+// esp_hf_subscriber_service_type_t
|
|
|
+char *c_subscriber_service_type_str[] = {
|
|
|
+ "UNKNOWN",
|
|
|
+ "VOICE",
|
|
|
+ "FAX",
|
|
|
+};
|
|
|
+
|
|
|
+// esp_hf_nego_codec_status_t
|
|
|
+const char *c_codec_mode_str[] = {
|
|
|
+ "CVSD Only",
|
|
|
+ "Use CVSD",
|
|
|
+ "Use MSBC",
|
|
|
+};
|
|
|
+
|
|
|
+#if CONFIG_BTDM_CTRL_BR_EDR_SCO_DATA_PATH_HCI
|
|
|
+// Produce a sine audio
|
|
|
+static const int16_t sine_int16[] = {
|
|
|
+ 0, 2057, 4107, 6140, 8149, 10126, 12062, 13952, 15786, 17557,
|
|
|
+ 19260, 20886, 22431, 23886, 25247, 26509, 27666, 28714, 29648, 30466,
|
|
|
+ 31163, 31738, 32187, 32509, 32702, 32767, 32702, 32509, 32187, 31738,
|
|
|
+ 31163, 30466, 29648, 28714, 27666, 26509, 25247, 23886, 22431, 20886,
|
|
|
+ 19260, 17557, 15786, 13952, 12062, 10126, 8149, 6140, 4107, 2057,
|
|
|
+ 0, -2057, -4107, -6140, -8149, -10126, -12062, -13952, -15786, -17557,
|
|
|
+-19260, -20886, -22431, -23886, -25247, -26509, -27666, -28714, -29648, -30466,
|
|
|
+-31163, -31738, -32187, -32509, -32702, -32767, -32702, -32509, -32187, -31738,
|
|
|
+-31163, -30466, -29648, -28714, -27666, -26509, -25247, -23886, -22431, -20886,
|
|
|
+-19260, -17557, -15786, -13952, -12062, -10126, -8149, -6140, -4107, -2057,
|
|
|
+};
|
|
|
+
|
|
|
+#define TABLE_SIZE_CVSD 100
|
|
|
+static uint32_t bt_app_hf_outgoing_cb(uint8_t *p_buf, uint32_t sz)
|
|
|
+{
|
|
|
+ int sine_phase = esp_random();
|
|
|
+
|
|
|
+ for (int i = 0; i < TABLE_SIZE_CVSD; i++) {
|
|
|
+ p_buf[i * 2] = sine_int16[sine_phase];
|
|
|
+ p_buf[i * 2 + 1] = sine_int16[sine_phase];
|
|
|
+ ++sine_phase;
|
|
|
+ if (sine_phase >= TABLE_SIZE_CVSD) {
|
|
|
+ sine_phase -= TABLE_SIZE_CVSD;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return sz;
|
|
|
+}
|
|
|
+
|
|
|
+static void bt_app_hf_incoming_cb(const uint8_t *buf, uint32_t sz)
|
|
|
+{
|
|
|
+ // direct to i2s
|
|
|
+ esp_hf_outgoing_data_ready();
|
|
|
+}
|
|
|
+#endif /* #if CONFIG_BTDM_CTRL_BR_EDR_SCO_DATA_PATH_HCI */
|
|
|
+
|
|
|
+void bt_app_hf_cb(esp_hf_cb_event_t event, esp_hf_cb_param_t *param)
|
|
|
+{
|
|
|
+ if (event <= ESP_HF_BCS_RESPONSE_EVT) {
|
|
|
+ ESP_LOGI(BT_HF_TAG, "APP HFP event: %s", c_hf_evt_str[event]);
|
|
|
+ } else {
|
|
|
+ ESP_LOGE(BT_HF_TAG, "APP HFP invalid event %d", event);
|
|
|
+ }
|
|
|
+
|
|
|
+ switch (event) {
|
|
|
+ case ESP_HF_CONNECTION_STATE_EVT:
|
|
|
+ {
|
|
|
+ ESP_LOGI(BT_HF_TAG, "--connection state %s, peer feats 0x%x, chld_feats 0x%x",
|
|
|
+ c_connection_state_str[param->conn_stat.state],
|
|
|
+ param->conn_stat.peer_feat,
|
|
|
+ param->conn_stat.chld_feat);
|
|
|
+ memcpy(hf_peer_addr, param->conn_stat.remote_bda, ESP_BD_ADDR_LEN);
|
|
|
+ if (param->conn_stat.state == ESP_HF_CONNECTION_STATE_CONNECTING) {
|
|
|
+ esp_bt_hf_connect(hf_peer_addr);
|
|
|
+ } else if (param->conn_stat.state == ESP_HF_CONNECTION_STATE_DISCONNECTING) {
|
|
|
+ esp_bt_hf_disconnect(hf_peer_addr);
|
|
|
+ }
|
|
|
+ break;
|
|
|
+ }
|
|
|
+
|
|
|
+ case ESP_HF_AUDIO_STATE_EVT:
|
|
|
+ {
|
|
|
+ ESP_LOGI(BT_HF_TAG, "--Audio State %s", c_audio_state_str[param->audio_stat.state]);
|
|
|
+#if CONFIG_BTDM_CTRL_BR_EDR_SCO_DATA_PATH_HCI
|
|
|
+ if (param->audio_stat.state == ESP_HF_AUDIO_STATE_CONNECTED ||
|
|
|
+ param->audio_stat.state == ESP_HF_AUDIO_STATE_CONNECTED_MSBC) {
|
|
|
+ esp_bt_hf_register_data_callback(bt_app_hf_incoming_cb, bt_app_hf_outgoing_cb);
|
|
|
+ } else if (param->audio_stat.state == ESP_HF_AUDIO_STATE_DISCONNECTED) {
|
|
|
+ ESP_LOGI(BT_HF_TAG, "--ESP AG Audio Connection Disconnected.");
|
|
|
+ }
|
|
|
+#endif /* #if CONFIG_BTDM_CTRL_BR_EDR_SCO_DATA_PATH_HCI */
|
|
|
+ break;
|
|
|
+ }
|
|
|
+
|
|
|
+ case ESP_HF_BVRA_EVT:
|
|
|
+ {
|
|
|
+ ESP_LOGI(BT_HF_TAG, "--Voice Recognition is %s", c_vr_state_str[param->vra_rep.value]);
|
|
|
+ break;
|
|
|
+ }
|
|
|
+
|
|
|
+ case ESP_HF_VOLUME_CONTROL_EVT:
|
|
|
+ {
|
|
|
+ ESP_LOGI(BT_HF_TAG, "--Volume Target: %s, Volume %d", c_volume_control_target_str[param->volume_control.type], param->volume_control.volume);
|
|
|
+ break;
|
|
|
+ }
|
|
|
+
|
|
|
+ case ESP_HF_UNAT_RESPONSE_EVT:
|
|
|
+ {
|
|
|
+ ESP_LOGI(BT_HF_TAG, "--UNKOW AT CMD: %s", param->unat_rep.unat);
|
|
|
+ esp_hf_unat_response(hf_peer_addr, param->unat_rep.unat);
|
|
|
+ break;
|
|
|
+ }
|
|
|
+
|
|
|
+ case ESP_HF_CIND_RESPONSE_EVT:
|
|
|
+ {
|
|
|
+ ESP_LOGI(BT_HF_TAG, "--CIND Start.");
|
|
|
+ esp_hf_call_status_t call_status = 0;
|
|
|
+ esp_hf_call_setup_status_t call_setup_status = 0;
|
|
|
+ esp_hf_network_state_t ntk_state = 1;
|
|
|
+ int signal = 4;
|
|
|
+ esp_hf_roaming_status_t roam = 0;
|
|
|
+ int batt_lev = 3;
|
|
|
+ esp_hf_call_held_status_t call_held_status = 0;
|
|
|
+ esp_bt_hf_cind_response(hf_peer_addr,call_status,call_setup_status,ntk_state,signal,roam,batt_lev,call_held_status);
|
|
|
+ break;
|
|
|
+ }
|
|
|
+
|
|
|
+ case ESP_HF_COPS_RESPONSE_EVT:
|
|
|
+ {
|
|
|
+ const int svc_type = 1;
|
|
|
+ esp_bt_hf_cops_response(hf_peer_addr, c_operator_name_str[svc_type]);
|
|
|
+ break;
|
|
|
+ }
|
|
|
+
|
|
|
+ case ESP_HF_CLCC_RESPONSE_EVT:
|
|
|
+ {
|
|
|
+ int index = 1;
|
|
|
+ //mandatory
|
|
|
+ esp_hf_current_call_direction_t dir = 1;
|
|
|
+ esp_hf_current_call_status_t current_call_status = 0;
|
|
|
+ esp_hf_current_call_mode_t mode = 0;
|
|
|
+ esp_hf_current_call_mpty_type_t mpty = 0;
|
|
|
+ //option
|
|
|
+ char *number = {"186xxxx5549"};
|
|
|
+ esp_hf_call_addr_type_t type = ESP_HF_CALL_ADDR_TYPE_UNKNOWN;
|
|
|
+
|
|
|
+ ESP_LOGI(BT_HF_TAG, "--Calling Line Identification.");
|
|
|
+ esp_bt_hf_clcc_response(hf_peer_addr, index, dir, current_call_status, mode, mpty, number, type);
|
|
|
+ break;
|
|
|
+ }
|
|
|
+
|
|
|
+ case ESP_HF_CNUM_RESPONSE_EVT:
|
|
|
+ {
|
|
|
+ char *number = {"186xxxx5549"};
|
|
|
+ esp_hf_subscriber_service_type_t type = 1;
|
|
|
+ ESP_LOGI(BT_HF_TAG, "--Current Number is %s ,Type is %s.", number, c_subscriber_service_type_str[type]);
|
|
|
+ esp_bt_hf_cnum_response(hf_peer_addr, number,type);
|
|
|
+ break;
|
|
|
+ }
|
|
|
+
|
|
|
+ case ESP_HF_VTS_RESPONSE_EVT:
|
|
|
+ {
|
|
|
+ ESP_LOGI(BT_HF_TAG, "--DTMF code is: %s.", param->vts_rep.code);
|
|
|
+ break;
|
|
|
+ }
|
|
|
+
|
|
|
+ case ESP_HF_NREC_RESPONSE_EVT:
|
|
|
+ {
|
|
|
+ ESP_LOGI(BT_HF_TAG, "--NREC status is: %s.", c_nrec_status_str[param->nrec.state]);
|
|
|
+ break;
|
|
|
+ }
|
|
|
+
|
|
|
+ case ESP_HF_ATA_RESPONSE_EVT:
|
|
|
+ {
|
|
|
+ ESP_LOGI(BT_HF_TAG, "--Asnwer Incoming Call.");
|
|
|
+ char *number = {"186xxxx5549"};
|
|
|
+ esp_bt_hf_answer_call(hf_peer_addr,1,0,1,0,number,0);
|
|
|
+ break;
|
|
|
+ }
|
|
|
+
|
|
|
+ case ESP_HF_CHUP_RESPONSE_EVT:
|
|
|
+ {
|
|
|
+ ESP_LOGI(BT_HF_TAG, "--Reject Incoming Call.");
|
|
|
+ char *number = {"186xxxx5549"};
|
|
|
+ esp_bt_hf_reject_call(hf_peer_addr,0,0,0,0,number,0);
|
|
|
+ break;
|
|
|
+ }
|
|
|
+
|
|
|
+ case ESP_HF_DIAL_EVT:
|
|
|
+ {
|
|
|
+ if (param->out_call.num_or_loc) {
|
|
|
+ //dia_num_or_mem
|
|
|
+ ESP_LOGI(BT_HF_TAG, "--Dial \"%s\".", param->out_call.num_or_loc);
|
|
|
+ esp_bt_hf_out_call(hf_peer_addr,1,0,1,0,param->out_call.num_or_loc,0);
|
|
|
+ } else {
|
|
|
+ //dia_last
|
|
|
+ ESP_LOGI(BT_HF_TAG, "--Dial last number.");
|
|
|
+ }
|
|
|
+ break;
|
|
|
+ }
|
|
|
+
|
|
|
+ // case ESP_HF_BAC_RESPONSE_EVT:
|
|
|
+ case ESP_HF_BCS_RESPONSE_EVT:
|
|
|
+ {
|
|
|
+ ESP_LOGI(BT_HF_TAG, "--AG choose codec mode: %s",c_codec_mode_str[param->codec.mode]);
|
|
|
+ break;
|
|
|
+ }
|
|
|
+
|
|
|
+ default:
|
|
|
+ ESP_LOGI(BT_HF_TAG, "Unsupported HF_AG EVT: %d.", event);
|
|
|
+ break;
|
|
|
+ }
|
|
|
+}
|