Merge branch 'feature/btdm_hfp_hf' into 'master'

component/bt: implement HFP Hands Free Unit Role

See merge request idf/esp-idf!2306
This commit is contained in:
Jiang Jiang Jian 2018-05-21 13:56:52 +08:00
commit adcad91c55
60 changed files with 9191 additions and 611 deletions

View file

@ -189,6 +189,33 @@ config BT_SPP_ENABLED
help
This enables the Serial Port Profile
config HFP_ENABLE
bool "Hands Free/Handset Profile"
depends on CLASSIC_BT_ENABLED
default n
choice HFP_ROLE
prompt "Hands-free Profile Role configuration"
depends on HFP_ENABLE
config HFP_CLIENT_ENABLE
bool "Hands Free Unit"
endchoice
choice HFP_AUDIO_DATA_PATH
prompt "audio(SCO) data path"
depends on HFP_ENABLE
config HFP_AUDIO_DATA_PATH_PCM
bool "PCM"
help
This enables the Serial Port Profile
config HFP_AUDIO_DATA_PATH_HCI
bool "HCI"
help
This enables the Serial Port Profile
endchoice
config GATTS_ENABLE
bool "Include GATT server module(GATTS)"
depends on BLUEDROID_ENABLED

View file

@ -0,0 +1,476 @@
// Copyright 2018 Espressif Systems (Shanghai) PTE LTD
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#include "common/bt_target.h"
#include <string.h>
#include "esp_err.h"
#include "esp_hf_client_api.h"
#include "esp_bt_main.h"
#include "btc/btc_manage.h"
#include "btc_hf_client.h"
#include "bta/bta_api.h"
#include "bta/bta_hf_client_api.h"
#if BTC_HF_CLIENT_INCLUDED
esp_err_t esp_hf_client_register_callback(esp_hf_client_cb_t callback)
{
if (esp_bluedroid_get_status() != ESP_BLUEDROID_STATUS_ENABLED) {
return ESP_ERR_INVALID_STATE;
}
if (callback == NULL) {
return ESP_FAIL;
}
btc_profile_cb_set(BTC_PID_HF_CLIENT, callback);
return ESP_OK;
}
esp_err_t esp_hf_client_init(void)
{
if (esp_bluedroid_get_status() != ESP_BLUEDROID_STATUS_ENABLED) {
return ESP_ERR_INVALID_STATE;
}
btc_msg_t msg;
msg.sig = BTC_SIG_API_CALL;
msg.pid = BTC_PID_HF_CLIENT;
msg.act = BTC_HF_CLIENT_INIT_EVT;
/* Switch to BTC context */
bt_status_t stat = btc_transfer_context(&msg, NULL, 0, NULL);
return (stat == BT_STATUS_SUCCESS) ? ESP_OK : ESP_FAIL;
}
esp_err_t esp_hf_client_deinit(void)
{
if (esp_bluedroid_get_status() != ESP_BLUEDROID_STATUS_ENABLED) {
return ESP_ERR_INVALID_STATE;
}
btc_msg_t msg;
msg.sig = BTC_SIG_API_CALL;
msg.pid = BTC_PID_HF_CLIENT;
msg.act = BTC_HF_CLIENT_DEINIT_EVT;
/* Switch to BTC context */
bt_status_t stat = btc_transfer_context(&msg, NULL, 0, NULL);
return (stat == BT_STATUS_SUCCESS) ? ESP_OK : ESP_FAIL;
}
esp_err_t esp_hf_client_connect(esp_bd_addr_t remote_bda)
{
if (esp_bluedroid_get_status() != ESP_BLUEDROID_STATUS_ENABLED) {
return ESP_ERR_INVALID_STATE;
}
bt_status_t stat;
btc_hf_client_args_t arg;
btc_msg_t msg;
msg.sig = BTC_SIG_API_CALL;
msg.pid = BTC_PID_HF_CLIENT;
msg.act = BTC_HF_CLIENT_CONNECT_EVT;
memset(&arg, 0, sizeof(btc_hf_client_args_t));
/* Switch to BTC context */
memcpy(&(arg.connect), remote_bda, sizeof(bt_bdaddr_t));
stat = btc_transfer_context(&msg, &arg, sizeof(btc_hf_client_args_t), NULL);
return (stat == BT_STATUS_SUCCESS) ? ESP_OK : ESP_FAIL;
}
esp_err_t esp_hf_client_disconnect(esp_bd_addr_t remote_bda)
{
if (esp_bluedroid_get_status() != ESP_BLUEDROID_STATUS_ENABLED) {
return ESP_ERR_INVALID_STATE;
}
bt_status_t stat;
btc_hf_client_args_t arg;
btc_msg_t msg;
msg.sig = BTC_SIG_API_CALL;
msg.pid = BTC_PID_HF_CLIENT;
msg.act = BTC_HF_CLIENT_DISCONNECT_EVT;
memset(&arg, 0, sizeof(btc_hf_client_args_t));
/* Switch to BTC context */
memcpy(&(arg.disconnect), remote_bda, sizeof(bt_bdaddr_t));
stat = btc_transfer_context(&msg, &arg, sizeof(btc_hf_client_args_t), NULL);
return (stat == BT_STATUS_SUCCESS) ? ESP_OK : ESP_FAIL;
}
esp_err_t esp_hf_client_connect_audio(esp_bd_addr_t remote_bda)
{
if (esp_bluedroid_get_status() != ESP_BLUEDROID_STATUS_ENABLED) {
return ESP_ERR_INVALID_STATE;
}
bt_status_t stat;
btc_hf_client_args_t arg;
btc_msg_t msg;
msg.sig = BTC_SIG_API_CALL;
msg.pid = BTC_PID_HF_CLIENT;
msg.act = BTC_HF_CLIENT_CONNECT_AUDIO_EVT;
memset(&arg, 0, sizeof(btc_hf_client_args_t));
/* Switch to BTC context */
memcpy(&(arg.connect_audio), remote_bda, sizeof(bt_bdaddr_t));
stat = btc_transfer_context(&msg, &arg, sizeof(btc_hf_client_args_t), NULL);
return (stat == BT_STATUS_SUCCESS) ? ESP_OK : ESP_FAIL;
}
esp_err_t esp_hf_client_disconnect_audio(esp_bd_addr_t remote_bda)
{
if (esp_bluedroid_get_status() != ESP_BLUEDROID_STATUS_ENABLED) {
return ESP_ERR_INVALID_STATE;
}
bt_status_t stat;
btc_hf_client_args_t arg;
btc_msg_t msg;
msg.sig = BTC_SIG_API_CALL;
msg.pid = BTC_PID_HF_CLIENT;
msg.act = BTC_HF_CLIENT_DISCONNECT_AUDIO_EVT;
memset(&arg, 0, sizeof(btc_hf_client_args_t));
/* Switch to BTC context */
memcpy(&(arg.disconnect_audio), remote_bda, sizeof(bt_bdaddr_t));
stat = btc_transfer_context(&msg, &arg, sizeof(btc_hf_client_args_t), NULL);
return (stat == BT_STATUS_SUCCESS) ? ESP_OK : ESP_FAIL;
}
esp_err_t esp_hf_client_start_voice_recognition(void)
{
if (esp_bluedroid_get_status() != ESP_BLUEDROID_STATUS_ENABLED) {
return ESP_ERR_INVALID_STATE;
}
btc_msg_t msg;
msg.sig = BTC_SIG_API_CALL;
msg.pid = BTC_PID_HF_CLIENT;
msg.act = BTC_HF_CLIENT_START_VOICE_RECOGNITION_EVT;
/* Switch to BTC context */
bt_status_t stat = btc_transfer_context(&msg, NULL, 0, NULL);
return (stat == BT_STATUS_SUCCESS) ? ESP_OK : ESP_FAIL;
}
esp_err_t esp_hf_client_stop_voice_recognition(void)
{
if (esp_bluedroid_get_status() != ESP_BLUEDROID_STATUS_ENABLED) {
return ESP_ERR_INVALID_STATE;
}
btc_msg_t msg;
msg.sig = BTC_SIG_API_CALL;
msg.pid = BTC_PID_HF_CLIENT;
msg.act = BTC_HF_CLIENT_STOP_VOICE_RECOGNITION_EVT;
/* Switch to BTC context */
bt_status_t stat = btc_transfer_context(&msg, NULL, 0, NULL);
return (stat == BT_STATUS_SUCCESS) ? ESP_OK : ESP_FAIL;
}
esp_err_t esp_hf_client_volume_update(esp_hf_volume_control_target_t type, int volume)
{
if (esp_bluedroid_get_status() != ESP_BLUEDROID_STATUS_ENABLED) {
return ESP_ERR_INVALID_STATE;
}
btc_msg_t msg;
btc_hf_client_args_t arg;
msg.sig = BTC_SIG_API_CALL;
msg.pid = BTC_PID_HF_CLIENT;
msg.act = BTC_HF_CLIENT_VOLUME_UPDATE_EVT;
memset(&arg, 0, sizeof(btc_hf_client_args_t));
arg.volume_update.type = type;
arg.volume_update.volume = volume;
/* Switch to BTC context */
bt_status_t stat = btc_transfer_context(&msg, &arg, sizeof(btc_hf_client_args_t), NULL);
return (stat == BT_STATUS_SUCCESS) ? ESP_OK : ESP_FAIL;
}
esp_err_t esp_hf_client_dial(const char *number)
{
if (esp_bluedroid_get_status() != ESP_BLUEDROID_STATUS_ENABLED) {
return ESP_ERR_INVALID_STATE;
}
btc_msg_t msg;
btc_hf_client_args_t arg;
if (number != NULL && strlen(number) > ESP_BT_HF_CLIENT_NUMBER_LEN) {
return ESP_ERR_INVALID_ARG;
}
msg.sig = BTC_SIG_API_CALL;
msg.pid = BTC_PID_HF_CLIENT;
msg.act = BTC_HF_CLIENT_DIAL_EVT;
memset(&arg, 0, sizeof(btc_hf_client_args_t));
if (number != NULL) {
strcpy(arg.dial.number, number);
} else {
arg.dial.number[0] = '\0';
}
/* Switch to BTC context */
bt_status_t stat = btc_transfer_context(&msg, &arg, sizeof(btc_hf_client_args_t), NULL);
return (stat == BT_STATUS_SUCCESS) ? ESP_OK : ESP_FAIL;
}
esp_err_t esp_hf_client_dial_memory(int location)
{
if (esp_bluedroid_get_status() != ESP_BLUEDROID_STATUS_ENABLED) {
return ESP_ERR_INVALID_STATE;
}
btc_msg_t msg;
btc_hf_client_args_t arg;
msg.sig = BTC_SIG_API_CALL;
msg.pid = BTC_PID_HF_CLIENT;
msg.act = BTC_HF_CLIENT_DIAL_MEMORY_EVT;
memset(&arg, 0, sizeof(btc_hf_client_args_t));
arg.dial_memory.location = location;
/* Switch to BTC context */
bt_status_t stat = btc_transfer_context(&msg, &arg, sizeof(btc_hf_client_args_t), NULL);
return (stat == BT_STATUS_SUCCESS) ? ESP_OK : ESP_FAIL;
}
esp_err_t esp_hf_client_send_chld_cmd(esp_hf_chld_type_t chld, int idx)
{
if (esp_bluedroid_get_status() != ESP_BLUEDROID_STATUS_ENABLED) {
return ESP_ERR_INVALID_STATE;
}
btc_msg_t msg;
btc_hf_client_args_t arg;
msg.sig = BTC_SIG_API_CALL;
msg.pid = BTC_PID_HF_CLIENT;
msg.act = BTC_HF_CLIENT_SEND_CHLD_CMD_EVT;
memset(&arg, 0, sizeof(btc_hf_client_args_t));
arg.chld.type = chld;
arg.chld.idx = idx;
/* Switch to BTC context */
bt_status_t stat = btc_transfer_context(&msg, &arg, sizeof(btc_hf_client_args_t), NULL);
return (stat == BT_STATUS_SUCCESS) ? ESP_OK : ESP_FAIL;
}
esp_err_t esp_hf_client_send_btrh_cmd(esp_hf_btrh_cmd_t btrh)
{
if (esp_bluedroid_get_status() != ESP_BLUEDROID_STATUS_ENABLED) {
return ESP_ERR_INVALID_STATE;
}
btc_msg_t msg;
btc_hf_client_args_t arg;
msg.sig = BTC_SIG_API_CALL;
msg.pid = BTC_PID_HF_CLIENT;
msg.act = BTC_HF_CLIENT_SEND_BTRH_CMD_EVT;
memset(&arg, 0, sizeof(btc_hf_client_args_t));
arg.btrh.cmd = btrh;
/* Switch to BTC context */
bt_status_t stat = btc_transfer_context(&msg, &arg, sizeof(btc_hf_client_args_t), NULL);
return (stat == BT_STATUS_SUCCESS) ? ESP_OK : ESP_FAIL;
}
esp_err_t esp_hf_client_answer_call(void)
{
if (esp_bluedroid_get_status() != ESP_BLUEDROID_STATUS_ENABLED) {
return ESP_ERR_INVALID_STATE;
}
btc_msg_t msg;
msg.sig = BTC_SIG_API_CALL;
msg.pid = BTC_PID_HF_CLIENT;
msg.act = BTC_HF_CLIENT_ANSWER_CALL_EVT;
/* Switch to BTC context */
bt_status_t stat = btc_transfer_context(&msg, NULL, 0, NULL);
return (stat == BT_STATUS_SUCCESS) ? ESP_OK : ESP_FAIL;
}
esp_err_t esp_hf_client_reject_call(void)
{
if (esp_bluedroid_get_status() != ESP_BLUEDROID_STATUS_ENABLED) {
return ESP_ERR_INVALID_STATE;
}
btc_msg_t msg;
msg.sig = BTC_SIG_API_CALL;
msg.pid = BTC_PID_HF_CLIENT;
msg.act = BTC_HF_CLIENT_REJECT_CALL_EVT;
/* Switch to BTC context */
bt_status_t stat = btc_transfer_context(&msg, NULL, 0, NULL);
return (stat == BT_STATUS_SUCCESS) ? ESP_OK : ESP_FAIL;
}
esp_err_t esp_hf_client_query_current_calls(void)
{
if (esp_bluedroid_get_status() != ESP_BLUEDROID_STATUS_ENABLED) {
return ESP_ERR_INVALID_STATE;
}
btc_msg_t msg;
msg.sig = BTC_SIG_API_CALL;
msg.pid = BTC_PID_HF_CLIENT;
msg.act = BTC_HF_CLIENT_QUERY_CURRENT_CALLS_EVT;
/* Switch to BTC context */
bt_status_t stat = btc_transfer_context(&msg, NULL, 0, NULL);
return (stat == BT_STATUS_SUCCESS) ? ESP_OK : ESP_FAIL;
}
esp_err_t esp_hf_client_query_current_operator_name(void)
{
if (esp_bluedroid_get_status() != ESP_BLUEDROID_STATUS_ENABLED) {
return ESP_ERR_INVALID_STATE;
}
btc_msg_t msg;
msg.sig = BTC_SIG_API_CALL;
msg.pid = BTC_PID_HF_CLIENT;
msg.act = BTC_HF_CLIENT_QUERY_CURRENT_OPERATOR_NAME_EVT;
/* Switch to BTC context */
bt_status_t stat = btc_transfer_context(&msg, NULL, 0, NULL);
return (stat == BT_STATUS_SUCCESS) ? ESP_OK : ESP_FAIL;
}
esp_err_t esp_hf_client_retrieve_subscriber_info(void)
{
if (esp_bluedroid_get_status() != ESP_BLUEDROID_STATUS_ENABLED) {
return ESP_ERR_INVALID_STATE;
}
btc_msg_t msg;
msg.sig = BTC_SIG_API_CALL;
msg.pid = BTC_PID_HF_CLIENT;
msg.act = BTC_HF_CLIENT_RETRIEVE_SUBSCRIBER_INFO_EVT;
/* Switch to BTC context */
bt_status_t stat = btc_transfer_context(&msg, NULL, 0, NULL);
return (stat == BT_STATUS_SUCCESS) ? ESP_OK : ESP_FAIL;
}
esp_err_t esp_hf_client_send_dtmf(char code)
{
if (esp_bluedroid_get_status() != ESP_BLUEDROID_STATUS_ENABLED) {
return ESP_ERR_INVALID_STATE;
}
btc_msg_t msg;
btc_hf_client_args_t arg;
msg.sig = BTC_SIG_API_CALL;
msg.pid = BTC_PID_HF_CLIENT;
msg.act = BTC_HF_CLIENT_SEND_DTMF_EVT;
memset(&arg, 0, sizeof(btc_hf_client_args_t));
arg.send_dtmf.code = code;
/* Switch to BTC context */
bt_status_t stat = btc_transfer_context(&msg, &arg, sizeof(btc_hf_client_args_t), NULL);
return (stat == BT_STATUS_SUCCESS) ? ESP_OK : ESP_FAIL;
}
esp_err_t esp_hf_client_request_last_voice_tag_number(void)
{
if (esp_bluedroid_get_status() != ESP_BLUEDROID_STATUS_ENABLED) {
return ESP_ERR_INVALID_STATE;
}
btc_msg_t msg;
msg.sig = BTC_SIG_API_CALL;
msg.pid = BTC_PID_HF_CLIENT;
msg.act = BTC_HF_CLIENT_REQUEST_LAST_VOICE_TAG_NUMBER_EVT;
/* Switch to BTC context */
bt_status_t stat = btc_transfer_context(&msg, NULL, 0, NULL);
return (stat == BT_STATUS_SUCCESS) ? ESP_OK : ESP_FAIL;
}
esp_err_t esp_hf_client_register_data_callback(esp_hf_client_incoming_data_cb_t recv,
esp_hf_client_outgoing_data_cb_t send)
{
if (esp_bluedroid_get_status() != ESP_BLUEDROID_STATUS_ENABLED) {
return ESP_ERR_INVALID_STATE;
}
btc_msg_t msg;
msg.sig = BTC_SIG_API_CALL;
msg.pid = BTC_PID_HF_CLIENT;
msg.act = BTC_HF_CLIENT_REGISTER_DATA_CALLBACK_EVT;
btc_hf_client_args_t arg;
memset(&arg, 0, sizeof(btc_hf_client_args_t));
arg.reg_data_cb.recv = recv;
arg.reg_data_cb.send = send;
/* Switch to BTC context */
bt_status_t stat = btc_transfer_context(&msg, &arg, sizeof(btc_hf_client_args_t), NULL);
return (stat == BT_STATUS_SUCCESS) ? ESP_OK : ESP_FAIL;
}
#if (BTM_SCO_HCI_INCLUDED == TRUE )
void esp_hf_client_outgoing_data_ready(void)
{
BTA_HfClientCiData();
}
void esp_hf_client_pcm_resample_init(uint32_t src_sps, uint32_t bits, uint32_t channels)
{
BTA_DmPcmInitSamples(src_sps, bits, channels);
}
int32_t esp_hf_client_pcm_resample(void *src, uint32_t in_bytes, void *dst)
{
return BTA_DmPcmResample(src, in_bytes, dst);
}
#endif /* #if (BTM_SCO_HCI_INCLUDED == TRUE ) */
#endif /* BTC_HF_CLIENT_INCLUDED */

View file

@ -0,0 +1,635 @@
// Copyright 2018 Espressif Systems (Shanghai) PTE LTD
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef __ESP_HF_CLIENT_API_H__
#define __ESP_HF_CLIENT_API_H__
#include "esp_err.h"
#include "esp_bt_defs.h"
#include "esp_hf_defs.h"
#ifdef __cplusplus
extern "C" {
#endif
#define ESP_BT_HF_CLIENT_NUMBER_LEN (32)
#define ESP_BT_HF_CLIENT_OPERATOR_NAME_LEN (16)
/// Bluetooth HFP RFCOMM connection and service level connection status
typedef enum {
ESP_HF_CLIENT_CONNECTION_STATE_DISCONNECTED = 0, /*!< RFCOMM data link channel released */
ESP_HF_CLIENT_CONNECTION_STATE_CONNECTING, /*!< connecting remote device on the RFCOMM data link*/
ESP_HF_CLIENT_CONNECTION_STATE_CONNECTED, /*!< RFCOMM connection established */
ESP_HF_CLIENT_CONNECTION_STATE_SLC_CONNECTED, /*!< service level connection established */
ESP_HF_CLIENT_CONNECTION_STATE_DISCONNECTING, /*!< disconnecting with remote device on the RFCOMM dat link*/
} esp_hf_client_connection_state_t;
/// Bluetooth HFP audio connection status
typedef enum {
ESP_HF_CLIENT_AUDIO_STATE_DISCONNECTED = 0, /*!< audio connection released */
ESP_HF_CLIENT_AUDIO_STATE_CONNECTING, /*!< audio connection has been initiated */
ESP_HF_CLIENT_AUDIO_STATE_CONNECTED, /*!< audio connection is established */
ESP_HF_CLIENT_AUDIO_STATE_CONNECTED_MSBC, /*!< mSBC audio connection is estalibshed */
} esp_hf_client_audio_state_t;
/// in-band ring tone state
typedef enum {
ESP_HF_CLIENT_IN_BAND_RINGTONE_NOT_PROVIDED = 0,
ESP_HF_CLIENT_IN_BAND_RINGTONE_PROVIDED,
} esp_hf_client_in_band_ring_state_t;
/* features masks of AG */
#define ESP_HF_CLIENT_PEER_FEAT_3WAY 0x01 /* Three-way calling */
#define ESP_HF_CLIENT_PEER_FEAT_ECNR 0x02 /* Echo cancellation and/or noise reduction */
#define ESP_HF_CLIENT_PEER_FEAT_VREC 0x04 /* Voice recognition */
#define ESP_HF_CLIENT_PEER_FEAT_INBAND 0x08 /* In-band ring tone */
#define ESP_HF_CLIENT_PEER_FEAT_VTAG 0x10 /* Attach a phone number to a voice tag */
#define ESP_HF_CLIENT_PEER_FEAT_REJECT 0x20 /* Ability to reject incoming call */
#define ESP_HF_CLIENT_PEER_FEAT_ECS 0x40 /* Enhanced Call Status */
#define ESP_HF_CLIENT_PEER_FEAT_ECC 0x80 /* Enhanced Call Control */
#define ESP_HF_CLIENT_PEER_FEAT_EXTERR 0x100 /* Extended error codes */
#define ESP_HF_CLIENT_PEER_FEAT_CODEC 0x200 /* Codec Negotiation */
/* CHLD feature masks of AG */
#define ESP_HF_CLIENT_CHLD_FEAT_REL 0x01 /* 0 Release waiting call or held calls */
#define ESP_HF_CLIENT_CHLD_FEAT_REL_ACC 0x02 /* 1 Release active calls and accept other waiting or held call */
#define ESP_HF_CLIENT_CHLD_FEAT_REL_X 0x04 /* 1x Release specified active call only */
#define ESP_HF_CLIENT_CHLD_FEAT_HOLD_ACC 0x08 /* 2 Active calls on hold and accept other waiting or held call */
#define ESP_HF_CLIENT_CHLD_FEAT_PRIV_X 0x10 /* 2x Request private mode with specified call(put the rest on hold */
#define ESP_HF_CLIENT_CHLD_FEAT_MERGE 0x20 /* 3 Add held call to multiparty */
#define ESP_HF_CLIENT_CHLD_FEAT_MERGE_DETACH 0x40 /* 4 Connect two calls and leave(disconnct from multiparty */
/// HF CLIENT callback events
typedef enum {
ESP_HF_CLIENT_CONNECTION_STATE_EVT = 0, /*!< connection state changed event */
ESP_HF_CLIENT_AUDIO_STATE_EVT, /*!< audio connection state change event */
ESP_HF_CLIENT_BVRA_EVT, /*!< voice recognition state change event */
ESP_HF_CLIENT_CIND_CALL_EVT, /*!< call indication */
ESP_HF_CLIENT_CIND_CALL_SETUP_EVT, /*!< call setup indication */
ESP_HF_CLIENT_CIND_CALL_HELD_EVT, /*!< call held indication */
ESP_HF_CLIENT_CIND_SERVICE_AVAILABILITY_EVT, /*!< network service availability indication */
ESP_HF_CLIENT_CIND_SIGNAL_STRENGTH_EVT, /*!< signal strength indication */
ESP_HF_CLIENT_CIND_ROAMING_STATUS_EVT, /*!< roaming status indication */
ESP_HF_CLIENT_CIND_BATTERY_LEVEL_EVT, /*!< battery level indication */
ESP_HF_CLIENT_COPS_CURRENT_OPERATOR_EVT, /*!< current operator information */
ESP_HF_CLIENT_BTRH_EVT, /*!< call response and hold event */
ESP_HF_CLIENT_CLIP_EVT, /*!< Calling Line Identification notification */
ESP_HF_CLIENT_CCWA_EVT, /*!< call waiting notification */
ESP_HF_CLIENT_CLCC_EVT, /*!< list of current calls notification */
ESP_HF_CLIENT_VOLUME_CONTROL_EVT, /*!< audio volume control command from AG, provided by +VGM or +VGS message */
ESP_HF_CLIENT_AT_RESPONSE_EVT, /*!< AT command response event */
ESP_HF_CLIENT_CNUM_EVT, /*!< subscriber information response from AG */
ESP_HF_CLIENT_BSIR_EVT, /*!< setting of in-band ring tone */
ESP_HF_CLIENT_BINP_EVT, /*!< requested number of last voice tag from AG */
ESP_HF_CLIENT_RING_IND_EVT, /*!< ring indication event */
} esp_hf_client_cb_event_t;
/// HFP client callback parameters
typedef union {
/**
* @brief ESP_HF_CLIENT_CONNECTION_STATE_EVT
*/
struct hf_client_conn_stat_param {
esp_hf_client_connection_state_t state; /*!< HF connection state */
uint32_t peer_feat; /*!< AG supported features */
uint32_t chld_feat; /*!< AG supported features on call hold and multiparty services */
esp_bd_addr_t remote_bda; /*!< remote bluetooth device address */
} conn_stat; /*!< HF callback param of ESP_HF_CLIENT_CONNECTION_STATE_EVT */
/**
* @brief ESP_HF_CLIENT_AUDIO_STATE_EVT
*/
struct hf_client_audio_stat_param {
esp_hf_client_audio_state_t state; /*!< audio connection state */
esp_bd_addr_t remote_bda; /*!< remote bluetooth device address */
} audio_stat; /*!< HF callback param of ESP_HF_CLIENT_AUDIO_STATE_EVT */
/**
* @brief ESP_HF_CLIENT_BVRA_EVT
*/
struct hf_client_bvra_param {
esp_hf_vr_state_t value; /*!< voice recognition state */
} bvra; /*!< HF callback param of ESP_HF_CLIENT_BVRA_EVT */
/**
* @brief ESP_HF_CLIENT_CIND_SERVICE_AVAILABILITY_EVT
*/
struct hf_client_service_availability_param {
esp_hf_service_availability_status_t status; /*!< service availability status */
} service_availability; /*!< HF callback param of ESP_HF_CLIENT_CIND_SERVICE_AVAILABILITY_EVT */
/**
* @brief ESP_HF_CLIENT_CIND_ROAMING_STATUS_EVT
*/
struct hf_client_network_roaming_param {
esp_hf_roaming_status_t status; /*!< roaming status */
} roaming; /*!< HF callback param of ESP_HF_CLIENT_CIND_ROAMING_STATUS_EVT */
/**
* @brief ESP_HF_CLIENT_CIND_SIGNAL_STRENGTH_EVT
*/
struct hf_client_signal_strength_ind_param {
int value; /*!< singal strength value, ranges from 0 to 5 */
} signal_strength; /*!< HF callback param of ESP_HF_CLIENT_CIND_SIGNAL_STRENGTH_EVT */
/**
* @brief ESP_HF_CLIENT_CIND_BATTERY_LEVEL_EVT
*/
struct hf_client_battery_level_ind_param {
int value; /*!< battery charge value, ranges from 0 to 5 */
} battery_level; /*!< HF callback param of ESP_HF_CLIENT_CIND_BATTERY_LEVEL_EVT */
/**
* @brief ESP_HF_CLIENT_COPS_CURRENT_OPERATOR_EVT
*/
struct hf_client_current_operator_param {
const char *name; /*!< name of the network operator */
} cops; /*!< HF callback param of ESP_HF_CLIENT_COPS_CURRENT_OPERATOR_EVT */
/**
* @brief ESP_HF_CLIENT_CIND_CALL_EVT
*/
struct hf_client_call_ind_param {
esp_hf_call_status_t status; /*!< call status indicator */
} call; /*!< HF callback param of ESP_HF_CLIENT_CIND_CALL_EVT */
/**
* @brief ESP_HF_CLIENT_CIND_CALL_SETUP_EVT
*/
struct hf_client_call_setup_ind_param {
esp_hf_call_setup_status_t status; /*!< call setup status indicator */
} call_setup; /*!< HF callback param of ESP_HF_CLIENT_BVRA_EVT */
/**
* @brief ESP_HF_CLIENT_CIND_CALL_HELD_EVT
*/
struct hf_client_call_held_ind_param {
esp_hf_call_held_status_t status; /*!< bluetooth proprietary call hold status indocator */
} call_held; /*!< HF callback param of ESP_HF_CLIENT_CIND_CALL_HELD_EVT */
/**
* @brief ESP_HF_CLIENT_BTRH_EVT
*/
struct hf_client_btrh_param {
esp_hf_btrh_status_t status; /*!< call hold and response status result code */
} btrh; /*!< HF callback param of ESP_HF_CLIENT_BRTH_EVT */
/**
* @brief ESP_HF_CLIENT_CLIP_EVT
*/
struct hf_client_clip_param {
const char *number; /*!< phone number string of call */
} clip; /*!< HF callback param of ESP_HF_CLIENT_CLIP_EVT */
/**
* @brief ESP_HF_CLIENT_CCWA_EVT
*/
struct hf_client_ccwa_param {
const char *number; /*!< phone number string of waiting call */
} ccwa; /*!< HF callback param of ESP_HF_CLIENT_BVRA_EVT */
/**
* @brief ESP_HF_CLIENT_CLCC_EVT
*/
struct hf_client_clcc_param {
int idx; /*!< numbering(starting with 1) of the call */
esp_hf_current_call_direction_t dir; /*!< direction of the call */
esp_hf_current_call_status_t status; /*!< status of the call */
esp_hf_current_call_mpty_type_t mpty; /*!< multi-party flag */
char *number; /*!< phone number(optional) */
} clcc; /*!< HF callback param of ESP_HF_CLIENT_CLCC_EVT */
/**
* @brief ESP_HF_CLIENT_VOLUME_CONTROL_EVT
*/
struct hf_client_volume_control_param {
esp_hf_volume_control_target_t type; /*!< volume control target, speaker or microphone */
int volume; /*!< gain, ranges from 0 to 15 */
} volume_control; /*!< HF callback param of ESP_HF_CLIENT_VOLUME_CONTROL_EVT */
/**
* @brief ESP_HF_CLIENT_AT_RESPONSE_EVT
*/
struct hf_client_at_response_param {
esp_hf_at_response_code_t code; /*!< AT response code */
esp_hf_cme_err_t cme; /*!< Extended Audio Gateway Error Result Code */
} at_response; /*!< HF callback param of ESP_HF_CLIENT_AT_RESPONSE_EVT */
/**
* @brief ESP_HF_CLIENT_CNUM_EVT
*/
struct hf_client_cnum_param {
const char *number; /*!< phone number string */
esp_hf_subscriber_service_type_t type; /*!< service type that the phone number relates to */
} cnum; /*!< HF callback param of ESP_HF_CLIENT_CNUM_EVT */
/**
* @brief ESP_HF_CLIENT_BSIR_EVT
*/
struct hf_client_bsirparam {
esp_hf_client_in_band_ring_state_t state; /*!< setting state of in-band ring tone */
} bsir; /*!< HF callback param of ESP_HF_CLIENT_BSIR_EVT */
/**
* @brief ESP_HF_CLIENT_BINP_EVT
*/
struct hf_client_binp_param {
const char *number; /*!< phone number corresponding to the last voice tag in the HF */
} binp; /*!< HF callback param of ESP_HF_CLIENT_BINP_EVT */
} esp_hf_client_cb_param_t;
/**
* @brief HFP client incoming data callback function, the callback is useful in case of
* Voice Over HCI.
* @param[in] buf : pointer to incoming data(payload of HCI synchronous data packet), the
* buffer is allocated inside bluetooth protocol stack and will be released after
* invoke of the callback is finished.
* @param[in] len : size(in bytes) in buf
*/
typedef void (* esp_hf_client_incoming_data_cb_t)(const uint8_t *buf, uint32_t len);
/**
* @brief HFP client outgoing data callback function, the callback is useful in case of
* Voice Over HCI. Once audio connection is set up and the application layer has
* prepared data to send, the lower layer will call this function to read data
* and then send. This callback is supposed to be implemented as non-blocking,
* and if data is not enough, return value 0 is supposed.
*
* @param[in] buf : pointer to incoming data(payload of HCI synchronous data packet), the
* buffer is allocated inside bluetooth protocol stack and will be released after
* invoke of the callback is finished.
* @param[in] len : size(in bytes) in buf
* @param[out] length of data successfully read
*/
typedef uint32_t (* esp_hf_client_outgoing_data_cb_t)(uint8_t *buf, uint32_t len);
/**
* @brief HFP client callback function type
*
* @param event : Event type
*
* @param param : Pointer to callback parameter
*/
typedef void (* esp_hf_client_cb_t)(esp_hf_client_cb_event_t event, esp_hf_client_cb_param_t *param);
/**
* @brief Register application callback function to HFP client module. This function should be called
* only after esp_bluedroid_enable() completes successfully, used by HFP client
*
* @param[in] callback: HFP client event callback function
*
* @return
* - ESP_OK: success
* - ESP_INVALID_STATE: if bluetooth stack is not yet enabled
* - ESP_FAIL: if callback is a NULL function pointer
*
*/
esp_err_t esp_hf_client_register_callback(esp_hf_client_cb_t callback);
/**
*
* @brief Initialize the bluetooth HFP client module. This function should be called
* after esp_bluedroid_enable() completes successfully
*
* @return
* - ESP_OK: if the initialization request is sent successfully
* - ESP_INVALID_STATE: if bluetooth stack is not yet enabled
* - ESP_FAIL: others
*
*/
esp_err_t esp_hf_client_init(void);
/**
*
* @brief De-initialize for HFP client module. This function
* should be called only after esp_bluedroid_enable() completes successfully
*
* @return
* - ESP_OK: success
* - ESP_INVALID_STATE: if bluetooth stack is not yet enabled
* - ESP_FAIL: others
*
*/
esp_err_t esp_hf_client_deinit(void);
/**
*
* @brief Connect to remote bluetooth HFP audio gateway(AG) device, must after esp_a2d_hf_client_init()
*
* @param[in] remote_bda: remote bluetooth device address
*
* @return
* - ESP_OK: connect request is sent to lower layer
* - ESP_INVALID_STATE: if bluetooth stack is not yet enabled
* - ESP_FAIL: others
*
*/
esp_err_t esp_hf_client_connect(esp_bd_addr_t remote_bda);
/**
*
* @brief Disconnect from the remote HFP audio gateway
*
* @param[in] remote_bda: remote bluetooth device address
* @return
* - ESP_OK: disconnect request is sent to lower layer
* - ESP_INVALID_STATE: if bluetooth stack is not yet enabled
* - ESP_FAIL: others
*
*/
esp_err_t esp_hf_client_disconnect(esp_bd_addr_t remote_bda);
/**
*
* @brief Create audio connection with remote HFP AG. As a precondition to use this API,
* Service Level Connection shall exist with AG
*
* @param[in] remote_bda: remote bluetooth device address
* @return
* - ESP_OK: disconnect request is sent to lower layer
* - ESP_INVALID_STATE: if bluetooth stack is not yet enabled
* - ESP_FAIL: others
*
*/
esp_err_t esp_hf_client_connect_audio(esp_bd_addr_t remote_bda);
/**
*
* @brief Release the established audio connection with remote HFP AG.
*
* @param[in] remote_bda: remote bluetooth device address
* @return
* - ESP_OK: disconnect request is sent to lower layer
* - ESP_INVALID_STATE: if bluetooth stack is not yet enabled
* - ESP_FAIL: others
*
*/
esp_err_t esp_hf_client_disconnect_audio(esp_bd_addr_t remote_bda);
/**
*
* @brief Enable voice recognition in the AG. As a precondition to use this API,
* Service Level Connection shall exist with AG
*
* @return
* - ESP_OK: disconnect request is sent to lower layer
* - ESP_INVALID_STATE: if bluetooth stack is not yet enabled
* - ESP_FAIL: others
*
*/
esp_err_t esp_hf_client_start_voice_recognition(void);
/**
*
* @brief Disable voice recognition in the AG. As a precondition to use this API,
* Service Level Connection shall exist with AG
*
* @return
* - ESP_OK: disconnect request is sent to lower layer
* - ESP_INVALID_STATE: if bluetooth stack is not yet enabled
* - ESP_FAIL: others
*
*/
esp_err_t esp_hf_client_stop_voice_recognition(void);
/**
*
* @brief Volume synchronization with AG. As a precondition to use this API,
* Service Level Connection shall exist with AG
*
* @param[in] type: volume control target, speaker or microphone
* @param[in] volume: gain of the speaker of microphone, ranges 0 to 15
*
* @return
* - ESP_OK: disconnect request is sent to lower layer
* - ESP_INVALID_STATE: if bluetooth stack is not yet enabled
* - ESP_FAIL: others
*
*/
esp_err_t esp_hf_client_volume_update(esp_hf_volume_control_target_t type, int volume);
/**
*
* @brief Place a call with a specified number, if number is NULL, last called number is
* called. As a precondition to use this API, Service Level Connection shall
* exist with AG
*
* @param[in] number: number string of the call. If NULL, the last number is called(aka re-dial)
*
* @return
* - ESP_OK: disconnect request is sent to lower layer
* - ESP_INVALID_STATE: if bluetooth stack is not yet enabled
* - ESP_FAIL: others
*
*/
esp_err_t esp_hf_client_dial(const char *number);
/**
*
* @brief Place a call with number specified by location(speed dial). As a precondition,
* to use this API, Service Level Connection shall exist with AG
*
* @param[in] location: location of the number in the memory
*
* @return
* - ESP_OK: disconnect request is sent to lower layer
* - ESP_INVALID_STATE: if bluetooth stack is not yet enabled
* - ESP_FAIL: others
*
*/
esp_err_t esp_hf_client_dial_memory(int location);
/**
*
* @brief Send call hold and multiparty commands, or enhanced call control commands(Use AT+CHLD).
* As a precondition to use this API, Service Level Connection shall exist with AG
*
* @param[in] chld: AT+CHLD call hold and multiparty handling AT command.
* @param[in] idx: used in Enhanced Call Control Mechanisms, used if chld is
* ESP_HF_CHLD_TYPE_REL_X or ESP_HF_CHLD_TYPE_PRIV_X
*
* @return
* - ESP_OK: disconnect request is sent to lower layer
* - ESP_INVALID_STATE: if bluetooth stack is not yet enabled
* - ESP_FAIL: others
*
*/
esp_err_t esp_hf_client_send_chld_cmd(esp_hf_chld_type_t chld, int idx);
/**
*
* @brief Send response and hold action command(Send AT+BTRH command)
* As a precondition to use this API, Service Level Connection shall exist with AG
*
* @param[in] btrh: response and hold action to send
*
* @return
* - ESP_OK: disconnect request is sent to lower layer
* - ESP_INVALID_STATE: if bluetooth stack is not yet enabled
* - ESP_FAIL: others
*
*/
esp_err_t esp_hf_client_send_btrh_cmd(esp_hf_btrh_cmd_t btrh);
/**
*
* @brief Answer an incoming call(send ATA command). As a precondition to use this API,
* Service Level Connection shall exist with AG
*
* @return
* - ESP_OK: disconnect request is sent to lower layer
* - ESP_INVALID_STATE: if bluetooth stack is not yet enabled
* - ESP_FAIL: others
*
*/
esp_err_t esp_hf_client_answer_call(void);
/**
*
* @brief Reject an incoming call(send AT+CHUP command), As a precondition to use this API,
* Service Level Connection shall exist with AG
*
* @return
* - ESP_OK: disconnect request is sent to lower layer
* - ESP_INVALID_STATE: if bluetooth stack is not yet enabled
* - ESP_FAIL: others
*
*/
esp_err_t esp_hf_client_reject_call(void);
/**
*
* @brief Query list of current calls in AG(send AT+CLCC command), As a precondition to use this API,
* Service Level Connection shall exist with AG
*
* @return
* - ESP_OK: disconnect request is sent to lower layer
* - ESP_INVALID_STATE: if bluetooth stack is not yet enabled
* - ESP_FAIL: others
*
*/
esp_err_t esp_hf_client_query_current_calls(void);
/**
*
* @brief Query the name of currently selected network operator in AG(use AT+COPS commands)
* As a precondition to use this API, Service Level Connection shall exist with AG
*
* @return
* - ESP_OK: disconnect request is sent to lower layer
* - ESP_INVALID_STATE: if bluetooth stack is not yet enabled
* - ESP_FAIL: others
*
*/
esp_err_t esp_hf_client_query_current_operator_name(void);
/**
*
* @brief Get subscriber information number from AG(send AT+CNUM command)
* As a precondition to use this API, Service Level Connection shall exist with AG
*
* @return
* - ESP_OK: disconnect request is sent to lower layer
* - ESP_INVALID_STATE: if bluetooth stack is not yet enabled
* - ESP_FAIL: others
*
*/
esp_err_t esp_hf_client_retrieve_subscriber_info(void);
/**
*
* @brief Transmit DTMF codes during an ongoing call(use AT+VTS commands)
* As a precondition to use this API, Service Level Connection shall exist with AG
*
* @param[in] code: dtmf code, single ascii character in the set 0-9, #, *, A-D
*
* @return
* - ESP_OK: disconnect request is sent to lower layer
* - ESP_INVALID_STATE: if bluetooth stack is not yet enabled
* - ESP_FAIL: others
*
*/
esp_err_t esp_hf_client_send_dtmf(char code);
/**
*
* @brief Request a phone number from AG corresponding to last voice tag recorded
* (send AT+BINP command). As a precondition to use this API, Service Level
* Connection shall exist with AG
*
* @return
* - ESP_OK: disconnect request is sent to lower layer
* - ESP_INVALID_STATE: if bluetooth stack is not yet enabled
* - ESP_FAIL: others
*
*/
esp_err_t esp_hf_client_request_last_voice_tag_number(void);
/**
* @brief Register HFP client data output function; the callback is only used in
* the case that Voice Over HCI is enabled.
*
* @param[in] recv: HFP client incoming data callback function
* @param[in] send: HFP client outgoing data callback function
*
* @return
* - ESP_OK: success
* - ESP_INVALID_STATE: if bluetooth stack is not yet enabled
* - ESP_FAIL: if callback is a NULL function pointer
*
*/
esp_err_t esp_hf_client_register_data_callback(esp_hf_client_incoming_data_cb_t recv,
esp_hf_client_outgoing_data_cb_t send);
/**
* @brief Trigger the lower-layer to fetch and send audio data. This function is only
* only used in the case that Voice Over HCI is enabled. Precondition is that
* the HFP audio connection is connected. After this function is called, lower
* layer will invoke esp_hf_client_outgoing_data_cb_t to fetch data
*
*/
void esp_hf_client_outgoing_data_ready(void);
/**
* @brief Initialize the down sampling converter. This is a utility function that can
* only be used in the case that Voice Over HCI is enabled.
*
* @param[in] src_sps: original samples per second(source audio data, i.e. 48000, 32000,
* 16000, 44100, 22050, 11025)
* @param[in] bits: number of bits per pcm sample (16)
* @param[in] channels: number of channels (i.e. mono(1), stereo(2)...)
*/
void esp_hf_client_pcm_resample_init(uint32_t src_sps, uint32_t bits, uint32_t channels);
/**
* @brief Down sampling utility to convert high sampling rate into 8K/16bits 1-channel mode PCM
* samples. This can only be used in the case that Voice Over HCI is enabled.
*
* @param[in] src: pointer to the buffer where the original smapling PCM are stored
* @param[in] in_bytes: length of the input PCM sample buffer in byte
* @param[in] dst: pointer to the buffer which is to be used to store the converted PCM samples
*
* @return number of samples converted
*/
int32_t esp_hf_client_pcm_resample(void *src, uint32_t in_bytes, void *dst);
#ifdef __cplusplus
}
#endif
#endif /* __ESP_HF_CLIENT_API_H__ */

View file

@ -0,0 +1,181 @@
// Copyright 2018 Espressif Systems (Shanghai) PTE LTD
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef __ESP_HF_DEFS_H__
#define __ESP_HF_DEFS_H__
#include "esp_bt_defs.h"
#ifdef __cplusplus
extern "C" {
#endif
/// Bluetooth HFP audio volume control target
typedef enum {
ESP_HF_VOLUME_CONTROL_TARGET_SPK = 0, /*!< speaker */
ESP_HF_VOLUME_CONTROL_TARGET_MIC, /*!< microphone */
} esp_hf_volume_control_target_t;
/// +CIND roaming status indicator values
typedef enum {
ESP_HF_ROAMING_STATUS_INACTIVE = 0, /*!< roaming is not active */
ESP_HF_ROAMING_STATUS_ACTIVE, /*!< a roaming is active */
} esp_hf_roaming_status_t;
/// +CIND call status indicator values
typedef enum {
ESP_HF_CALL_STATUS_NO_CALLS = 0, /*!< no call in progress */
ESP_HF_CALL_STATUS_CALL_IN_PROGRESS = 1, /*!< call is present(active or held) */
} esp_hf_call_status_t;
/// +CIND call setup status indicator values
typedef enum {
ESP_HF_CALL_SETUP_STATUS_NONE = 0, /*!< no call setup in progress */
ESP_HF_CALL_SETUP_STATUS_INCOMING = 1, /*!< incoming call setup in progress */
ESP_HF_CALL_SETUP_STATUS_OUTGOING_DIALING = 2, /*!< outgoing call setup in dialing state */
ESP_HF_CALL_SETUP_STATUS_OUTGOING_ALERTING = 3, /*!< outgoing call setup in alerting state */
} esp_hf_call_setup_status_t;
/// +CIND call held indicator values
typedef enum {
ESP_HF_CALL_HELD_STATUS_NONE = 0, /*!< no calls held */
ESP_HF_CALL_HELD_STATUS_HELD_AND_ACTIVE = 1, /*!< both active and held call */
ESP_HF_CALL_HELD_STATUS_HELD = 2, /*!< call on hold, no active call*/
} esp_hf_call_held_status_t;
/// +CIND network service availability status
typedef enum {
ESP_HF_SERVICE_AVAILABILITY_STATUS_UNAVAILABLE = 0, /*!< service not available */
ESP_HF_SERVICE_AVAILABILITY_STATUS_AVAILABLE, /*!< service available */
} esp_hf_service_availability_status_t;
/// +CLCC status of the call
typedef enum {
ESP_HF_CURRENT_CALL_STATUS_ACTIVE = 0, /*!< active */
ESP_HF_CURRENT_CALL_STATUS_HELD = 1, /*!< held */
ESP_HF_CURRENT_CALL_STATUS_DIALING = 2, /*!< dialing (outgoing calls only) */
ESP_HF_CURRENT_CALL_STATUS_ALERTING = 3, /*!< alerting (outgoing calls only) */
ESP_HF_CURRENT_CALL_STATUS_INCOMING = 4, /*!< incoming (incoming calls only) */
ESP_HF_CURRENT_CALL_STATUS_WAITING = 5, /*!< waiting (incoming calls only) */
ESP_HF_CURRENT_CALL_STATUS_HELD_BY_RESP_HOLD = 6, /*!< call held by response and hold */
} esp_hf_current_call_status_t;
/// +CLCC direction of the call
typedef enum {
ESP_HF_CURRENT_CALL_DIRECTION_OUTGOING = 0, /*!< outgoing */
ESP_HF_CURRENT_CALL_DIRECTION_INCOMING = 1, /*!< incoming */
} esp_hf_current_call_direction_t;
/// +CLCC multi-party call flag
typedef enum {
ESP_HF_CURRENT_CALL_MPTY_TYPE_SINGLE = 0, /*!< not a member of a multi-party call */
ESP_HF_CURRENT_CALL_MPTY_TYPE_MULTI = 1, /*!< member of a multi-party call */
} esp_hf_current_call_mpty_type_t;
/// +CLCC call mode
typedef enum {
ESP_HF_CURRENT_CALL_MODE_VOICE = 0,
ESP_HF_CURRENT_CALL_MODE_DATA = 1,
ESP_HF_CURRENT_CALL_MODE_FAX = 2,
} esp_hf_current_call_mode_t;
/// +CLCC address type
typedef enum {
ESP_HF_CALL_ADDR_TYPE_UNKNOWN = 0x81, /*!< unkown address type */
ESP_HF_CALL_ADDR_TYPE_INTERNATIONAL = 0x91, /*!< international address */
} esp_hf_call_addr_type_t;
/// +CNUM service type of the phone number
typedef enum {
ESP_HF_SUBSCRIBER_SERVICE_TYPE_UNKNOWN = 0, /*!< unknown */
ESP_HF_SUBSCRIBER_SERVICE_TYPE_VOICE, /*!< voice service */
ESP_HF_SUBSCRIBER_SERVICE_TYPE_FAX, /*!< fax service */
} esp_hf_subscriber_service_type_t;
/// +BTRH response and hold result code
typedef enum {
ESP_HF_BTRH_STATUS_HELD = 0, /*!< incoming call is put on held in AG */
ESP_HF_BTRH_STATUS_ACCEPTED, /*!< held incoming call is accepted in AG */
ESP_HF_BTRH_STATUS_REJECTED, /*!< held incoming call is rejected in AG */
} esp_hf_btrh_status_t;
/// AT+BTRH response and hold action code
typedef enum {
ESP_HF_BTRH_CMD_HOLD = 0, /*!< put the incoming call on hold */
ESP_HF_BTRH_CMD_ACCEPT = 1, /*!< accept a held incoming call */
ESP_HF_BTRH_CMD_REJECT = 2, /*!< reject a held incoming call */
} esp_hf_btrh_cmd_t;
/// response indication codes for AT commands
typedef enum {
ESP_HF_AT_RESPONSE_CODE_OK = 0, /*!< acknoweledges execution of a command line */
ESP_HF_AT_RESPONSE_CODE_ERR, /*!< command not accepted */
ESP_HF_AT_RESPONSE_CODE_NO_CARRIER, /*!< connection terminated */
ESP_HF_AT_RESPONSE_CODE_BUSY, /*!< busy signal detected */
ESP_HF_AT_RESPONSE_CODE_NO_ANSWER, /*!< connection completion timeout */
ESP_HF_AT_RESPONSE_CODE_DELAYED, /*!< delayed */
ESP_HF_AT_RESPONSE_CODE_BLACKLISTED, /*!< blacklisted */
ESP_HF_AT_RESPONSE_CODE_CME, /*!< CME error */
} esp_hf_at_response_code_t;
/// voice recognition state
typedef enum {
ESP_HF_VR_STATE_DISABLED = 0, /*!< voice recognition disabled */
ESP_HF_VR_STATE_ENABLED, /*!< voice recognition enabled */
} esp_hf_vr_state_t;
/// AT+CHLD command values
typedef enum {
ESP_HF_CHLD_TYPE_REL = 0, /*!< <0>, Terminate all held or set UDUB("busy") to a waiting call */
ESP_HF_CHLD_TYPE_REL_ACC, /*!< <1>, Terminate all active calls and accepts a waiting/held call */
ESP_HF_CHLD_TYPE_HOLD_ACC, /*!< <2>, Hold all active calls and accepts a waiting/held call */
ESP_HF_CHLD_TYPE_MERGE, /*!< <3>, Add all held calls to a conference */
ESP_HF_CHLD_TYPE_MERGE_DETACH, /*!< <4>, connect the two calls and disconnects the subscriber from both calls */
ESP_HF_CHLD_TYPE_REL_X, /*!< <1x>, releases specified calls only */
ESP_HF_CHLD_TYPE_PRIV_X, /*!< <2x>, request private consultation mode with specified call */
} esp_hf_chld_type_t;
/// Extended Audio Gateway Error Result Code Response
typedef enum {
ESP_HF_CME_AG_FAILURE = 0, /*!< ag failure */
ESP_HF_CME_NO_CONNECTION_TO_PHONE = 1, /*!< no connection to phone */
ESP_HF_CME_OPERATION_NOT_ALLOWED = 3, /*!< operation not allowed */
ESP_HF_CME_OPERATION_NOT_SUPPORTED = 4, /*!< operation not supported */
ESP_HF_CME_PH_SIM_PIN_REQUIRED = 5, /*!< PH-SIM PIN Required */
ESP_HF_CME_SIM_NOT_INSERTED = 10, /*!< SIM not inserted */
ESP_HF_CME_SIM_PIN_REQUIRED = 11, /*!< SIM PIN required */
ESP_HF_CME_SIM_PUK_REQUIRED = 12, /*!< SIM PUK required */
ESP_HF_CME_SIM_FAILURE = 13, /*!< SIM failure */
ESP_HF_CME_SIM_BUSY = 14, /*!< SIM busy */
ESP_HF_CME_INCORRECT_PASSWORD = 16, /*!< incorrect password */
ESP_HF_CME_SIM_PIN2_REQUIRED = 17, /*!< SIM PIN2 required */
ESP_HF_CME_SIM_PUK2_REQUIRED = 18, /*!< SIM PUK2 required */
ESP_HF_CME_MEMEORY_FULL = 20, /*!< memory full */
ESP_HF_CME_INVALID_INDEX = 21, /*!< invalid index */
ESP_HF_CME_MEMEORY_FAILURE = 23, /*!< memory failure */
ESP_HF_CME_TEXT_STRING_TOO_LONG = 24, /*!< test string too long */
ESP_HF_CME_INVALID_CHARACTERS_IN_TEXT_STRING = 25, /*!< invalid characters in text string */
ESP_HF_CME_DIAL_STRING_TOO_LONG = 26, /*!< dial string too long*/
ESP_HF_CME_INVALID_CHARACTERS_IN_DIAL_STRING = 27, /*!< invalid characters in dial string */
ESP_HF_CME_NO_NETWORK_SERVICE = 30, /*!< no network service */
ESP_HF_CME_NETWORK_TIMEOUT = 31, /*!< network timeout */
ESP_HF_CME_NETWORK_NOT_ALLOWED = 32, /*!< network not allowed --emergency calls only */
} esp_hf_cme_err_t;
#ifdef __cplusplus
}
#endif
#endif /* __ESP_HF_DEFS_H__ */

View file

@ -396,9 +396,7 @@ static void bta_dm_sys_hw_cback( tBTA_SYS_HW_EVT status )
#endif
/* hw is ready, go on with BTA DM initialization */
memset(&bta_dm_search_cb, 0x00, sizeof(bta_dm_search_cb));
#if (BTM_SSR_INCLUDED == TRUE)
memset(&bta_dm_conn_srvcs, 0x00, sizeof(bta_dm_conn_srvcs));
#endif ///BTM_SSR_INCLUDED == TRUE
memset(&bta_dm_di_cb, 0, sizeof(tBTA_DM_DI_CB));
memcpy(dev_class, p_bta_dm_cfg->dev_class, sizeof(dev_class));
@ -443,10 +441,12 @@ static void bta_dm_sys_hw_cback( tBTA_SYS_HW_EVT status )
BTM_ReadLocalDeviceNameFromController((tBTM_CMPL_CB *)bta_dm_local_name_cback);
bta_sys_rm_register((tBTA_SYS_CONN_CBACK *)bta_dm_rm_cback);
#if (BTM_SSR_INCLUDED == TRUE)
#if (BTA_DM_PM_INCLUDED == TRUE)
/* initialize bluetooth low power manager */
bta_dm_init_pm();
#endif ///BTM_SSR_INCLUDED == TRUE
#endif /* #if (BTA_DM_PM_INCLUDED == TRUE) */
bta_sys_policy_register((tBTA_SYS_CONN_CBACK *)bta_dm_policy_cback);
#if (BLE_INCLUDED == TRUE && BTA_GATT_INCLUDED == TRUE && SDP_INCLUDED == TRUE) && (GATTC_INCLUDED == TRUE)
@ -483,9 +483,11 @@ void bta_dm_disable (tBTA_DM_MSG *p_data)
BTM_SetDiscoverability(BTM_NON_DISCOVERABLE, 0, 0);
BTM_SetConnectability(BTM_NON_CONNECTABLE, 0, 0);
#if (BTM_SSR_INCLUDED == TRUE)
#if (BTA_DM_PM_INCLUDED == TRUE)
bta_dm_disable_pm();
#endif ///BTM_SSR_INCLUDED == TRUE
#endif /* #if (BTA_DM_PM_INCLUDED == TRUE) */
bta_dm_disable_search_and_disc();
bta_dm_cb.disabling = TRUE;
@ -1070,12 +1072,12 @@ static void bta_dm_policy_cback(tBTA_SYS_CONN_STATUS status, UINT8 id, UINT8 app
p_dev->link_policy &= (~policy);
BTM_SetLinkPolicy(p_dev->peer_bdaddr, &(p_dev->link_policy));
#if (BTA_DM_PM_INCLUDED == TRUE)
if (policy & (HCI_ENABLE_SNIFF_MODE | HCI_ENABLE_PARK_MODE)) {
/* if clearing sniff/park, wake the link */
#if (BTM_SSR_INCLUDED == TRUE)
bta_dm_pm_active(p_dev->peer_bdaddr);
#endif ///BTM_SSR_INCLUDED == TRUE
}
#endif /* #if (BTA_DM_PM_INCLUDED == TRUE) */
break;
case BTA_SYS_PLCY_DEF_SET:
@ -3365,10 +3367,12 @@ static void bta_dm_disable_conn_down_timer_cback (TIMER_LIST_ENT *p_tle)
{
UNUSED(p_tle);
tBTA_SYS_HW_MSG *sys_enable_event;
#if (BTM_SSR_INCLUDED == TRUE)
#if (BTA_DM_PM_INCLUDED == TRUE)
/* disable the power managment module */
bta_dm_disable_pm();
#endif ///BTM_SSR_INCLUDED == TRUE
#endif /* #if (BTA_DM_PM_INCLUDED == TRUE) */
/* register our callback to SYS HW manager */
bta_sys_hw_register( BTA_SYS_HW_BLUETOOTH, bta_dm_sys_hw_cback );
@ -3431,9 +3435,7 @@ static void bta_dm_rm_cback(tBTA_SYS_CONN_STATUS status, UINT8 id, UINT8 app_id,
}
/* AV calls bta_sys_conn_open with the A2DP stream count as app_id */
if (BTA_ID_AV == id) {
#if (BTM_SSR_INCLUDED == TRUE)
bta_dm_cb.cur_av_count = bta_dm_get_av_count();
#endif ///BTM_SSR_INCLUDED == TRUE
}
} else if ( status == BTA_SYS_CONN_IDLE) {
if (p_dev) {
@ -3442,9 +3444,7 @@ static void bta_dm_rm_cback(tBTA_SYS_CONN_STATUS status, UINT8 id, UINT8 app_id,
/* get cur_av_count from connected services */
if (BTA_ID_AV == id) {
#if (BTM_SSR_INCLUDED == TRUE)
bta_dm_cb.cur_av_count = bta_dm_get_av_count();
#endif ///BTM_SSR_INCLUDED == TRUE
}
}
APPL_TRACE_EVENT("bta_dm_rm_cback:%d, status:%d", bta_dm_cb.cur_av_count, status);

View file

@ -116,39 +116,24 @@ tBTA_DM_CFG *p_bta_dm_cfg = (tBTA_DM_CFG *) &bta_dm_cfg;
tBTA_DM_RM *p_bta_dm_rm_cfg = (tBTA_DM_RM *) &bta_dm_rm_cfg;
#if BLE_INCLUDED == TRUE
# define BTA_DM_NUM_PM_ENTRY 21 /* number of entries in bta_dm_pm_cfg except the first */
# define BTA_DM_NUM_PM_SPEC 15 /* number of entries in bta_dm_pm_spec */
# define BTA_DM_NUM_PM_ENTRY 6 /* number of entries in bta_dm_pm_cfg except the first */
# define BTA_DM_NUM_PM_SPEC 6 /* number of entries in bta_dm_pm_spec */
#else
# define BTA_DM_NUM_PM_ENTRY 19 /* number of entries in bta_dm_pm_cfg except the first */
# define BTA_DM_NUM_PM_SPEC 13 /* number of entries in bta_dm_pm_spec */
# define BTA_DM_NUM_PM_ENTRY 4 /* number of entries in bta_dm_pm_cfg except the first */
# define BTA_DM_NUM_PM_SPEC 4 /* number of entries in bta_dm_pm_spec */
#endif
#if (BTA_DM_PM_INCLUDED == TRUE)
tBTA_DM_PM_TYPE_QUALIFIER tBTA_DM_PM_CFG bta_dm_pm_cfg[BTA_DM_NUM_PM_ENTRY + 1] = {
{BTA_ID_SYS, BTA_DM_NUM_PM_ENTRY, 0}, /* reserved: specifies length of this table. */
{BTA_ID_AG, BTA_ALL_APP_ID, 0}, /* ag uses first spec table for app id 0 */
{BTA_ID_CT, 1, 1}, /* ct (BTA_ID_CT,APP ID=1) spec table */
{BTA_ID_CG, BTA_ALL_APP_ID, 1}, /* cg resue ct spec table */
{BTA_ID_DG, BTA_ALL_APP_ID, 2}, /* dg spec table */
{BTA_ID_AV, BTA_ALL_APP_ID, 4}, /* av spec table */
{BTA_ID_AVK, BTA_ALL_APP_ID, 12}, /* avk spec table */
{BTA_ID_FTC, BTA_ALL_APP_ID, 6}, /* ftc spec table */
{BTA_ID_FTS, BTA_ALL_APP_ID, 7}, /* fts spec table */
{BTA_ID_HD, BTA_ALL_APP_ID, 3}, /* hd spec table */
{BTA_ID_HH, BTA_ALL_APP_ID, 5}, /* hh spec table */
{BTA_ID_PBC, BTA_ALL_APP_ID, 2}, /* reuse dg spec table */
{BTA_ID_PBS, BTA_ALL_APP_ID, 7}, /* reuse fts spec table */
{BTA_ID_OPC, BTA_ALL_APP_ID, 6}, /* reuse ftc spec table */
{BTA_ID_OPS, BTA_ALL_APP_ID, 7}, /* reuse fts spec table */
{BTA_ID_MSE, BTA_ALL_APP_ID, 7}, /* reuse fts spec table */
// {BTA_ID_JV, BTA_JV_PM_ID_1, 6}, /* app BTA_JV_PM_ID_1, reuse ftc spec table */
// {BTA_ID_JV, BTA_ALL_APP_ID, 7}, /* reuse fts spec table */
{BTA_ID_HL, BTA_ALL_APP_ID, 8}, /* reuse fts spec table */
{BTA_ID_PAN, BTUI_PAN_ID_PANU, 9}, /* PANU spec table */
{BTA_ID_PAN, BTUI_PAN_ID_NAP, 10}, /* NAP spec table */
{BTA_ID_HS, BTA_ALL_APP_ID, 11} /* HS spec table */
{BTA_ID_AV, BTA_ALL_APP_ID, 1}, /* av spec table */
{BTA_ID_HS, BTA_ALL_APP_ID, 2}, /* HS spec table */
{BTA_ID_AVK, BTA_ALL_APP_ID, 3} /* avk spec table */
#if BLE_INCLUDED == TRUE
, {BTA_ID_GATTC, BTA_ALL_APP_ID, 13} /* gattc spec table */
, {BTA_ID_GATTS, BTA_ALL_APP_ID, 14} /* gatts spec table */
, {BTA_ID_GATTC, BTA_ALL_APP_ID, 4} /* gattc spec table */
, {BTA_ID_GATTS, BTA_ALL_APP_ID, 5} /* gatts spec table */
#endif
};
@ -173,64 +158,7 @@ tBTA_DM_PM_TYPE_QUALIFIER tBTA_DM_PM_SPEC bta_dm_pm_spec[BTA_DM_NUM_PM_SPEC] = {
}
},
/* CT, CG : 1 */
{
(BTA_DM_PM_SNIFF | BTA_DM_PM_PARK), /* allow park & sniff */
#if (BTM_SSR_INCLUDED == TRUE)
(BTA_DM_PM_SSR2), /* the SSR entry */
#endif
{
{{BTA_DM_PM_PARK, 5000 + BTA_DM_PM_SPEC_TO_OFFSET}, {BTA_DM_PM_NO_ACTION, 0}}, /* conn open park */
{{BTA_DM_PM_NO_PREF, 0}, {BTA_DM_PM_NO_ACTION, 0}}, /* conn close */
{{BTA_DM_PM_NO_ACTION, 0}, {BTA_DM_PM_NO_ACTION, 0}}, /* app open */
{{BTA_DM_PM_NO_ACTION, 0}, {BTA_DM_PM_NO_ACTION, 0}}, /* app close */
{{BTA_DM_PM_SNIFF_A2DP_IDX, 5000 + BTA_DM_PM_SPEC_TO_OFFSET}, {BTA_DM_PM_NO_ACTION, 0}}, /* sco open sniff */
{{BTA_DM_PM_PARK, 5000 + BTA_DM_PM_SPEC_TO_OFFSET}, {BTA_DM_PM_NO_ACTION, 0}}, /* sco close park */
{{BTA_DM_PM_NO_ACTION, 0}, {BTA_DM_PM_NO_ACTION, 0}}, /* idle */
{{BTA_DM_PM_NO_ACTION, 0}, {BTA_DM_PM_NO_ACTION, 0}}, /* busy */
{{BTA_DM_PM_RETRY, 5000 + BTA_DM_PM_SPEC_TO_OFFSET}, {BTA_DM_PM_NO_ACTION, 0}} /* mode change retry */
}
},
/* DG, PBC : 2 */
{
(BTA_DM_PM_ACTIVE), /* no power saving mode allowed */
#if (BTM_SSR_INCLUDED == TRUE)
(BTA_DM_PM_SSR2), /* the SSR entry */
#endif
{
{{BTA_DM_PM_SNIFF, 5000 + BTA_DM_PM_SPEC_TO_OFFSET}, {BTA_DM_PM_NO_ACTION, 0}}, /* conn open active */
{{BTA_DM_PM_NO_PREF, 0}, {BTA_DM_PM_NO_ACTION, 0}}, /* conn close */
{{BTA_DM_PM_ACTIVE, 0}, {BTA_DM_PM_NO_ACTION, 0}}, /* app open */
{{BTA_DM_PM_NO_ACTION, 0}, {BTA_DM_PM_NO_ACTION, 0}}, /* app close */
{{BTA_DM_PM_NO_ACTION, 0}, {BTA_DM_PM_NO_ACTION, 0}}, /* sco open */
{{BTA_DM_PM_NO_ACTION, 0}, {BTA_DM_PM_NO_ACTION, 0}}, /* sco close */
{{BTA_DM_PM_SNIFF, 1000 + BTA_DM_PM_SPEC_TO_OFFSET}, {BTA_DM_PM_NO_ACTION, 0}}, /* idle */
{{BTA_DM_PM_ACTIVE, 0}, {BTA_DM_PM_NO_ACTION, 0}}, /* busy */
{{BTA_DM_PM_NO_ACTION, 0}, {BTA_DM_PM_NO_ACTION, 0}} /* mode change retry */
}
},
/* HD : 3 */
{
(BTA_DM_PM_SNIFF | BTA_DM_PM_PARK), /* allow park & sniff */
#if (BTM_SSR_INCLUDED == TRUE)
(BTA_DM_PM_SSR3), /* the SSR entry */
#endif
{
{{BTA_DM_PM_SNIFF_HD_ACTIVE_IDX, 5000 + BTA_DM_PM_SPEC_TO_OFFSET}, {BTA_DM_PM_NO_ACTION, 0}}, /* conn open sniff */
{{BTA_DM_PM_NO_PREF, 0}, {BTA_DM_PM_NO_ACTION, 0}}, /* conn close */
{{BTA_DM_PM_NO_ACTION, 0}, {BTA_DM_PM_NO_ACTION, 0}}, /* app open */
{{BTA_DM_PM_NO_ACTION, 0}, {BTA_DM_PM_NO_ACTION, 0}}, /* app close */
{{BTA_DM_PM_NO_ACTION, 0}, {BTA_DM_PM_NO_ACTION, 0}}, /* sco open */
{{BTA_DM_PM_NO_ACTION, 0}, {BTA_DM_PM_NO_ACTION, 0}}, /* sco close */
{{BTA_DM_PM_SNIFF_HD_IDLE_IDX, 5000 + BTA_DM_PM_SPEC_TO_OFFSET}, {BTA_DM_PM_NO_ACTION, 0}}, /* idle */
{{BTA_DM_PM_SNIFF_HD_ACTIVE_IDX, 0}, {BTA_DM_PM_NO_ACTION, 0}}, /* busy */
{{BTA_DM_PM_NO_ACTION, 0}, {BTA_DM_PM_NO_ACTION, 0}} /* mode change retry */
}
},
/* AV : 4 */
/* AV : 1 */
{
(BTA_DM_PM_SNIFF), /* allow sniff */
#if (BTM_SSR_INCLUDED == TRUE)
@ -249,122 +177,7 @@ tBTA_DM_PM_TYPE_QUALIFIER tBTA_DM_PM_SPEC bta_dm_pm_spec[BTA_DM_NUM_PM_SPEC] = {
}
},
/* HH : 5 */
{
(BTA_DM_PM_SNIFF | BTA_DM_PM_PARK), /* allow park & sniff */
#if (BTM_SSR_INCLUDED == TRUE)
(BTA_DM_PM_SSR1), /* the SSR entry */
#endif
{
{{BTA_DM_PM_SNIFF_HH_OPEN_IDX, BTA_DM_PM_HH_OPEN_DELAY + BTA_DM_PM_SPEC_TO_OFFSET}, {BTA_DM_PM_NO_ACTION, 0}}, /* conn open sniff */
{{BTA_DM_PM_NO_PREF, 0}, {BTA_DM_PM_NO_ACTION, 0}}, /* conn close */
{{BTA_DM_PM_NO_ACTION, 0}, {BTA_DM_PM_NO_ACTION, 0}}, /* app open */
{{BTA_DM_PM_NO_ACTION, 0}, {BTA_DM_PM_NO_ACTION, 0}}, /* app close */
{{BTA_DM_PM_NO_ACTION, 0}, {BTA_DM_PM_NO_ACTION, 0}}, /* sco open */
{{BTA_DM_PM_NO_ACTION, 0}, {BTA_DM_PM_NO_ACTION, 0}}, /* sco close, used for HH suspend */
{{BTA_DM_PM_SNIFF_HH_IDLE_IDX, BTA_DM_PM_HH_IDLE_DELAY + BTA_DM_PM_SPEC_TO_OFFSET}, {BTA_DM_PM_NO_ACTION, 0}}, /* idle */
{{BTA_DM_PM_SNIFF_HH_ACTIVE_IDX, BTA_DM_PM_HH_ACTIVE_DELAY + BTA_DM_PM_SPEC_TO_OFFSET}, {BTA_DM_PM_NO_ACTION, 0}}, /* busy */
{{BTA_DM_PM_NO_ACTION, 0}, {BTA_DM_PM_NO_ACTION, 0}} /* mode change retry */
}
},
/* FTC, OPC, JV : 6 */
{
(BTA_DM_PM_SNIFF), /* allow sniff */
#if (BTM_SSR_INCLUDED == TRUE)
(BTA_DM_PM_SSR2), /* the SSR entry */
#endif
{
{{BTA_DM_PM_ACTIVE, 0}, {BTA_DM_PM_NO_ACTION, 0}}, /* conn open active */
{{BTA_DM_PM_NO_PREF, 0}, {BTA_DM_PM_NO_ACTION, 0}}, /* conn close */
{{BTA_DM_PM_ACTIVE, 0}, {BTA_DM_PM_NO_ACTION, 0}}, /* app open */
{{BTA_DM_PM_NO_ACTION, 0}, {BTA_DM_PM_NO_ACTION, 0}}, /* app close */
{{BTA_DM_PM_NO_ACTION, 0}, {BTA_DM_PM_NO_ACTION, 0}}, /* sco open */
{{BTA_DM_PM_NO_ACTION, 0}, {BTA_DM_PM_NO_ACTION, 0}}, /* sco close */
{{BTA_DM_PM_SNIFF_A2DP_IDX, 5000 + BTA_DM_PM_SPEC_TO_OFFSET}, {BTA_DM_PM_NO_ACTION, 0}}, /* idle */
{{BTA_DM_PM_ACTIVE, 0}, {BTA_DM_PM_NO_ACTION, 0}}, /* busy */
{{BTA_DM_PM_NO_ACTION, 0}, {BTA_DM_PM_NO_ACTION, 0}} /* mode change retry */
}
},
/* FTS, PBS, OPS, MSE, BTA_JV_PM_ID_1 : 7 */
{
(BTA_DM_PM_SNIFF), /* allow sniff */
#if (BTM_SSR_INCLUDED == TRUE)
(BTA_DM_PM_SSR2), /* the SSR entry */
#endif
{
{{BTA_DM_PM_ACTIVE, 0}, {BTA_DM_PM_NO_ACTION, 0}}, /* conn open active */
{{BTA_DM_PM_NO_PREF, 0}, {BTA_DM_PM_NO_ACTION, 0}}, /* conn close */
{{BTA_DM_PM_ACTIVE, 0}, {BTA_DM_PM_NO_ACTION, 0}}, /* app open */
{{BTA_DM_PM_NO_ACTION, 0}, {BTA_DM_PM_NO_ACTION, 0}}, /* app close */
{{BTA_DM_PM_NO_ACTION, 0}, {BTA_DM_PM_NO_ACTION, 0}}, /* sco open */
{{BTA_DM_PM_NO_ACTION, 0}, {BTA_DM_PM_NO_ACTION, 0}}, /* sco close */
{{BTA_DM_PM_SNIFF_A2DP_IDX, BTA_FTS_OPS_IDLE_TO_SNIFF_DELAY_MS + BTA_DM_PM_SPEC_TO_OFFSET}, {BTA_DM_PM_NO_ACTION, 0}}, /* idle */
{{BTA_DM_PM_ACTIVE, 0}, {BTA_DM_PM_NO_ACTION, 0}}, /* busy */
{{BTA_DM_PM_NO_ACTION, 0}, {BTA_DM_PM_NO_ACTION, 0}} /* mode change retry */
}
},
/* HL : 8 */
{
(BTA_DM_PM_SNIFF), /* allow sniff */
#if (BTM_SSR_INCLUDED == TRUE)
(BTA_DM_PM_SSR2), /* the SSR entry */
#endif
{
{{BTA_DM_PM_SNIFF_A2DP_IDX, 5000 + BTA_DM_PM_SPEC_TO_OFFSET}, {BTA_DM_PM_NO_ACTION, 0}}, /* conn open sniff */
{{BTA_DM_PM_NO_PREF, 0}, {BTA_DM_PM_NO_ACTION, 0}}, /* conn close */
{{BTA_DM_PM_NO_ACTION, 0}, {BTA_DM_PM_NO_ACTION, 0}}, /* app open */
{{BTA_DM_PM_NO_ACTION, 0}, {BTA_DM_PM_NO_ACTION, 0}}, /* app close */
{{BTA_DM_PM_NO_ACTION, 0}, {BTA_DM_PM_NO_ACTION, 0}}, /* sco open, active */
{{BTA_DM_PM_NO_ACTION, 0}, {BTA_DM_PM_NO_ACTION, 0}}, /* sco close sniff */
{{BTA_DM_PM_NO_ACTION, 0}, {BTA_DM_PM_NO_ACTION, 0}}, /* idle */
{{BTA_DM_PM_ACTIVE, 0}, {BTA_DM_PM_NO_ACTION, 0}}, /* busy */
{{BTA_DM_PM_NO_ACTION, 0}, {BTA_DM_PM_NO_ACTION, 0}} /* mode change retry */
}
},
/* PANU : 9 */
{
(BTA_DM_PM_SNIFF), /* allow sniff */
#if (BTM_SSR_INCLUDED == TRUE)
(BTA_DM_PM_SSR2), /* the SSR entry */
#endif
{
{{BTA_DM_PM_ACTIVE, 0}, {BTA_DM_PM_NO_ACTION, 0}}, /* conn open active */
{{BTA_DM_PM_NO_PREF, 0}, {BTA_DM_PM_NO_ACTION, 0}}, /* conn close */
{{BTA_DM_PM_ACTIVE, 0}, {BTA_DM_PM_NO_ACTION, 0}}, /* app open */
{{BTA_DM_PM_NO_ACTION, 0}, {BTA_DM_PM_NO_ACTION, 0}}, /* app close */
{{BTA_DM_PM_NO_ACTION, 0}, {BTA_DM_PM_NO_ACTION, 0}}, /* sco open */
{{BTA_DM_PM_NO_ACTION, 0}, {BTA_DM_PM_NO_ACTION, 0}}, /* sco close */
{{BTA_DM_PM_SNIFF_A2DP_IDX, 5000 + BTA_DM_PM_SPEC_TO_OFFSET}, {BTA_DM_PM_NO_ACTION, 0}}, /* idle */
{{BTA_DM_PM_ACTIVE, 0}, {BTA_DM_PM_NO_ACTION, 0}}, /* busy */
{{BTA_DM_PM_NO_ACTION, 0}, {BTA_DM_PM_NO_ACTION, 0}} /* mode change retry */
}
},
/* NAP : 10 */
{
(BTA_DM_PM_SNIFF), /* allow sniff */
#if (BTM_SSR_INCLUDED == TRUE)
(BTA_DM_PM_SSR2), /* the SSR entry */
#endif
{
{{BTA_DM_PM_ACTIVE, 0}, {BTA_DM_PM_NO_ACTION, 0}}, /* conn open active */
{{BTA_DM_PM_NO_PREF, 0}, {BTA_DM_PM_NO_ACTION, 0}}, /* conn close */
{{BTA_DM_PM_ACTIVE, 0}, {BTA_DM_PM_NO_ACTION, 0}}, /* app open */
{{BTA_DM_PM_NO_ACTION, 0}, {BTA_DM_PM_NO_ACTION, 0}}, /* app close */
{{BTA_DM_PM_NO_ACTION, 0}, {BTA_DM_PM_NO_ACTION, 0}}, /* sco open */
{{BTA_DM_PM_NO_ACTION, 0}, {BTA_DM_PM_NO_ACTION, 0}}, /* sco close */
{{BTA_DM_PM_SNIFF_A2DP_IDX, 5000 + BTA_DM_PM_SPEC_TO_OFFSET}, {BTA_DM_PM_NO_ACTION, 0}}, /* idle */
{{BTA_DM_PM_ACTIVE, 0}, {BTA_DM_PM_NO_ACTION, 0}}, /* busy */
{{BTA_DM_PM_NO_ACTION, 0}, {BTA_DM_PM_NO_ACTION, 0}} /* mode change retry */
}
},
/* HS : 11 */
/* HS : 2 */
{
(BTA_DM_PM_SNIFF | BTA_DM_PM_PARK), /* allow park & sniff */
#if (BTM_SSR_INCLUDED == TRUE)
@ -383,7 +196,7 @@ tBTA_DM_PM_TYPE_QUALIFIER tBTA_DM_PM_SPEC bta_dm_pm_spec[BTA_DM_NUM_PM_SPEC] = {
}
},
/* AVK : 12 */
/* AVK : 3 */
{
(BTA_DM_PM_SNIFF), /* allow sniff */
#if (BTM_SSR_INCLUDED == TRUE)
@ -403,7 +216,7 @@ tBTA_DM_PM_TYPE_QUALIFIER tBTA_DM_PM_SPEC bta_dm_pm_spec[BTA_DM_NUM_PM_SPEC] = {
}
#if BLE_INCLUDED == TRUE
/* GATTC : 13 */
/* GATTC : 4 */
, {
(BTA_DM_PM_SNIFF | BTA_DM_PM_PARK), /* allow park & sniff */
#if (BTM_SSR_INCLUDED == TRUE)
@ -424,7 +237,7 @@ tBTA_DM_PM_TYPE_QUALIFIER tBTA_DM_PM_SPEC bta_dm_pm_spec[BTA_DM_NUM_PM_SPEC] = {
{{BTA_DM_PM_RETRY, 5000 + BTA_DM_PM_SPEC_TO_OFFSET}, {BTA_DM_PM_NO_ACTION, 0}} /* mode change retry */
}
}
/* GATTS : 14 */
/* GATTS : 5 */
, {
(BTA_DM_PM_SNIFF | BTA_DM_PM_PARK), /* allow park & sniff */
#if (BTM_SSR_INCLUDED == TRUE)
@ -528,6 +341,8 @@ tBTA_DM_PM_CFG *p_bta_dm_pm_cfg = (tBTA_DM_PM_CFG *) &bta_dm_pm_cfg;
tBTA_DM_PM_SPEC *p_bta_dm_pm_spec = (tBTA_DM_PM_SPEC *) &bta_dm_pm_spec;
tBTM_PM_PWR_MD *p_bta_dm_pm_md = (tBTM_PM_PWR_MD *) &bta_dm_pm_md;
#endif /* #if (BTA_DM_PM_INCLUDED == TRUE) */
/* The performance impact of EIR packet size
**
** When BTM_EIR_DEFAULT_FEC_REQUIRED is TRUE,

View file

@ -83,32 +83,3 @@ void bta_dm_ci_rmt_oob(BOOLEAN accept, BD_ADDR bd_addr, BT_OCTET16 c, BT_OCTET16
}
}
#endif /* BTM_OOB_INCLUDED */
#if (BTM_SCO_HCI_INCLUDED == TRUE)
/*******************************************************************************
**
** Function bta_dm_sco_ci_data_ready
**
** Description This function sends an event to indicating that the phone
** has SCO data ready.
**
** Parameters event: is obtained from bta_dm_sco_co_open() function, which
** is the BTA event we want to send back to BTA module
** when there is encoded data ready.
** sco_handle: is the BTA sco handle which indicate a specific
** SCO connection.
** Returns void
**
*******************************************************************************/
void bta_dm_sco_ci_data_ready(UINT16 event, UINT16 sco_handle)
{
BT_HDR *p_buf;
if ((p_buf = (BT_HDR *) osi_malloc(sizeof(BT_HDR))) != NULL) {
p_buf->event = event;
p_buf->layer_specific = sco_handle;
bta_sys_sendmsg(p_buf);
}
}
#endif

View file

@ -205,149 +205,6 @@ void bta_dm_co_rmt_oob(BD_ADDR bd_addr)
// REMOVE FOR BLUEDROID ?
#if (BTM_SCO_HCI_INCLUDED == TRUE ) && (BTM_SCO_INCLUDED == TRUE)
#if (defined(BTIF_INCLUDED) && BTIF_INCLUDED == TRUE)
/*******************************************************************************
**
** Function btui_sco_codec_callback
**
** Description Callback for btui codec.
**
**
** Returns void
**
*******************************************************************************/
static void btui_sco_codec_callback(UINT16 event, UINT16 sco_handle)
{
bta_dm_sco_ci_data_ready(event, sco_handle);
}
/*******************************************************************************
**
** Function bta_dm_sco_co_init
**
** Description This function can be used by the phone to initialize audio
** codec or for other initialization purposes before SCO connection
** is opened.
**
**
** Returns tBTA_DM_SCO_ROUTE_TYPE: SCO routing configuration type.
**
*******************************************************************************/
tBTA_DM_SCO_ROUTE_TYPE bta_dm_sco_co_init(UINT32 rx_bw, UINT32 tx_bw,
tBTA_CODEC_INFO *p_codec_type, UINT8 app_id)
{
tBTM_SCO_ROUTE_TYPE route = BTA_DM_SCO_ROUTE_PCM;
BTIF_TRACE_DEBUG("bta_dm_sco_co_init");
/* set up SCO routing configuration if SCO over HCI app ID is used and run time
configuration is set to SCO over HCI */
/* HS invoke this call-out */
if (
#if (BTA_HS_INCLUDED == TRUE ) && (BTA_HS_INCLUDED == TRUE)
(app_id == BTUI_DM_SCO_4_HS_APP_ID && btui_cfg.hs_sco_over_hci) ||
#endif
/* AG invoke this call-out */
(app_id != BTUI_DM_SCO_4_HS_APP_ID && btui_cfg.ag_sco_over_hci )) {
route = btui_cb.sco_hci = BTA_DM_SCO_ROUTE_HCI;
}
/* no codec is is used for the SCO data */
if (p_codec_type->codec_type == BTA_SCO_CODEC_PCM && route == BTA_DM_SCO_ROUTE_HCI) {
/* initialize SCO codec */
if (!btui_sco_codec_init(rx_bw, tx_bw)) {
BTIF_TRACE_ERROR("codec initialization exception!");
}
}
return route;
}
/*******************************************************************************
**
** Function bta_dm_sco_co_open
**
** Description This function is executed when a SCO connection is open.
**
**
** Returns void
**
*******************************************************************************/
void bta_dm_sco_co_open(UINT16 handle, UINT8 pkt_size, UINT16 event)
{
tBTUI_SCO_CODEC_CFG cfg;
if (btui_cb.sco_hci) {
BTIF_TRACE_DEBUG("bta_dm_sco_co_open handle:%d pkt_size:%d", handle, pkt_size);
/* use dedicated SCO buffer pool for SCO TX data */
cfg.pool_id = HCI_SCO_POOL_ID;
cfg.p_cback = btui_sco_codec_callback;
cfg.pkt_size = pkt_size;
cfg.cb_event = event;
/* open and start the codec */
btui_sco_codec_open(&cfg);
btui_sco_codec_start(handle);
}
}
/*******************************************************************************
**
** Function bta_dm_sco_co_close
**
** Description This function is called when a SCO connection is closed
**
**
** Returns void
**
*******************************************************************************/
void bta_dm_sco_co_close(void)
{
if (btui_cb.sco_hci) {
BTIF_TRACE_DEBUG("bta_dm_sco_co_close close codec");
/* close sco codec */
btui_sco_codec_close();
btui_cb.sco_hci = FALSE;
}
}
/*******************************************************************************
**
** Function bta_dm_sco_co_in_data
**
** Description This function is called to send incoming SCO data to application.
**
** Returns void
**
*******************************************************************************/
void bta_dm_sco_co_in_data(BT_HDR *p_buf)
{
if (btui_cfg.sco_use_mic) {
btui_sco_codec_inqdata (p_buf);
} else {
osi_free(p_buf);
}
}
/*******************************************************************************
**
** Function bta_dm_sco_co_out_data
**
** Description This function is called to send SCO data over HCI.
**
** Returns void
**
*******************************************************************************/
void bta_dm_sco_co_out_data(BT_HDR **p_buf)
{
btui_sco_codec_readbuf(p_buf);
}
#endif /* #if (defined(BTIF_INCLUDED) && BTIF_INCLUDED == TRUE) */
#endif /* #if (BTM_SCO_HCI_INCLUDED == TRUE ) && (BTM_SCO_INCLUDED == TRUE)*/
#if (defined BLE_INCLUDED && BLE_INCLUDED == TRUE)
/*******************************************************************************
**

View file

@ -66,11 +66,11 @@ const tBTA_DM_ACTION bta_dm_action[BTA_DM_MAX_EVT] = {
bta_dm_bond_cancel, /* 12 BTA_DM_API_BOND_CANCEL_EVT */
bta_dm_pin_reply, /* 13 BTA_DM_API_PIN_REPLY_EVT */
#endif ///SMP_INCLUDED == TRUE
#if (BTM_SSR_INCLUDED == TRUE)
#if (BTA_DM_PM_INCLUDED == TRUE)
/* power manger events */
bta_dm_pm_btm_status, /* 16 BTA_DM_PM_BTM_STATUS_EVT */
bta_dm_pm_timer, /* 17 BTA_DM_PM_TIMER_EVT*/
#endif ///BTM_SSR_INCLUDED == TRUE
#endif /* #if (BTA_DM_PM_INCLUDED == TRUE) */
/* simple pairing events */
#if (SMP_INCLUDED == TRUE)
bta_dm_confirm, /* 18 BTA_DM_API_CONFIRM_EVT */

View file

@ -30,9 +30,11 @@
#include "bta/bta_api.h"
#include "bta_dm_int.h"
#include "stack/btm_api.h"
#include "osi/allocator.h"
#if (BTM_SSR_INCLUDED == TRUE)
tBTA_DM_CONNECTED_SRVCS bta_dm_conn_srvcs;
#if (BTA_DM_PM_INCLUDED == TRUE)
static void bta_dm_pm_cback(tBTA_SYS_CONN_STATUS status, UINT8 id, UINT8 app_id, BD_ADDR peer_addr);
static void bta_dm_pm_set_mode(BD_ADDR peer_addr, tBTA_DM_PM_ACTION pm_mode,
tBTA_DM_PM_REQ pm_req);
@ -45,18 +47,15 @@ static void bta_dm_pm_hid_check(BOOLEAN bScoActive);
static void bta_dm_pm_set_sniff_policy(tBTA_DM_PEER_DEVICE *p_dev, BOOLEAN bDisable);
static void bta_dm_pm_stop_timer_by_index(tBTA_PM_TIMER *p_timer,
UINT8 timer_idx);
#endif///BTM_SSR_INCLUDED == TRUE
#if (BTM_SSR_INCLUDED == TRUE)
#if (defined BTA_HH_INCLUDED && BTA_HH_INCLUDED == TRUE)
#include "../hh/bta_hh_int.h"
/* BTA_DM_PM_SSR1 will be dedicated for HH SSR setting entry, no other profile can use it */
#define BTA_DM_PM_SSR_HH BTA_DM_PM_SSR1
#endif
#endif /* (defined BTA_HH_INCLUDED && BTA_HH_INCLUDED == TRUE) */
static void bta_dm_pm_ssr(BD_ADDR peer_addr);
tBTA_DM_CONNECTED_SRVCS bta_dm_conn_srvcs;
#endif /* (BTM_SSR_INCLUDED == TRUE) */
/*******************************************************************************
**
@ -118,27 +117,6 @@ void bta_dm_disable_pm(void)
}
}
/*******************************************************************************
**
** Function bta_dm_get_av_count
**
** Description Get the number of connected AV
**
**
** Returns number of av connections
**
*******************************************************************************/
UINT8 bta_dm_get_av_count(void)
{
UINT8 count = 0;
for (int i = 0; i < bta_dm_conn_srvcs.count; i++) {
if (bta_dm_conn_srvcs.conn_srvc[i].id == BTA_ID_AV) {
++count;
}
}
return count;
}
/*******************************************************************************
**
** Function bta_dm_pm_stop_timer
@ -337,10 +315,10 @@ static void bta_dm_pm_cback(tBTA_SYS_CONN_STATUS status, UINT8 id, UINT8 app_id,
{
UINT8 i, j;
UINT8 *p = NULL;
tBTA_DM_PEER_DEVICE *p_dev;
#if (BTM_SSR_INCLUDED == TRUE)
UINT8 *p = NULL;
int index = BTA_DM_PM_SSR0;
#endif
@ -492,7 +470,6 @@ static void bta_dm_pm_cback(tBTA_SYS_CONN_STATUS status, UINT8 id, UINT8 app_id,
** Returns void
**
*******************************************************************************/
static void bta_dm_pm_set_mode(BD_ADDR peer_addr, tBTA_DM_PM_ACTION pm_request,
tBTA_DM_PM_REQ pm_req )
{
@ -702,8 +679,6 @@ static BOOLEAN bta_dm_pm_sniff(tBTA_DM_PEER_DEVICE *p_peer_dev, UINT8 index)
BTM_ReadPowerMode(p_peer_dev->peer_bdaddr, &mode);
#if (BTM_SSR_INCLUDED == TRUE)
p_rem_feat = BTM_ReadRemoteFeatures (p_peer_dev->peer_bdaddr);
#endif ///BTM_SSR_INCLUDED == TRUE
#if (BTM_SSR_INCLUDED == TRUE)
APPL_TRACE_DEBUG("bta_dm_pm_sniff cur:%d, idx:%d, info:x%x", mode, index, p_peer_dev->info);
if (mode != BTM_PM_MD_SNIFF ||
(HCI_SNIFF_SUB_RATE_SUPPORTED(BTM_ReadLocalFeatures ()) && p_rem_feat &&
@ -805,6 +780,7 @@ static void bta_dm_pm_ssr(BD_ADDR peer_addr)
}
}
#endif
/*******************************************************************************
**
** Function bta_dm_pm_active
@ -824,11 +800,8 @@ void bta_dm_pm_active(BD_ADDR peer_addr)
/* switch to active mode */
pm.mode = BTM_PM_MD_ACTIVE;
BTM_SetPowerMode (bta_dm_cb.pm_id, peer_addr, &pm);
}
/*******************************************************************************
**
** Function bta_dm_pm_btm_cback
@ -901,6 +874,7 @@ static void bta_dm_pm_timer_cback(void *p_tle)
}
}
/*******************************************************************************
**
** Function bta_dm_pm_btm_status
@ -995,11 +969,9 @@ void bta_dm_pm_btm_status(tBTA_DM_MSG *p_data)
default:
break;
}
}
/*******************************************************************************
**
** Function bta_dm_pm_timer
@ -1015,33 +987,7 @@ void bta_dm_pm_timer(tBTA_DM_MSG *p_data)
APPL_TRACE_EVENT("%s", __func__);
bta_dm_pm_set_mode(p_data->pm_timer.bd_addr, p_data->pm_timer.pm_request, BTA_DM_PM_EXECUTE);
}
#endif ///BTM_SSR_INCLUDED == TRUE
/*******************************************************************************
**
** Function bta_dm_find_peer_device
**
** Description Given an address, find the associated control block.
**
** Returns tBTA_DM_PEER_DEVICE
**
*******************************************************************************/
tBTA_DM_PEER_DEVICE *bta_dm_find_peer_device(BD_ADDR peer_addr)
{
tBTA_DM_PEER_DEVICE *p_dev = NULL;
for (int i = 0; i < bta_dm_cb.device_list.count; i++) {
if (!bdcmp( bta_dm_cb.device_list.peer_device[i].peer_bdaddr, peer_addr)) {
p_dev = &bta_dm_cb.device_list.peer_device[i];
break;
}
}
return p_dev;
}
#if (BTM_SSR_INCLUDED == TRUE)
/*******************************************************************************
**
** Function bta_dm_is_sco_active
@ -1138,7 +1084,52 @@ static void bta_dm_pm_set_sniff_policy(tBTA_DM_PEER_DEVICE *p_dev, BOOLEAN bDisa
BTM_SetLinkPolicy(p_dev->peer_bdaddr, &policy_setting);
}
#endif ///BTM_SSR_INCLUDED == TRUE
#endif /* #if (BTA_DM_PM_INCLUDED == TRUE) */
/*******************************************************************************
**
** Function bta_dm_get_av_count
**
** Description Get the number of connected AV
**
**
** Returns number of av connections
**
*******************************************************************************/
UINT8 bta_dm_get_av_count(void)
{
UINT8 count = 0;
for (int i = 0; i < bta_dm_conn_srvcs.count; i++) {
if (bta_dm_conn_srvcs.conn_srvc[i].id == BTA_ID_AV) {
++count;
}
}
return count;
}
/*******************************************************************************
**
** Function bta_dm_find_peer_device
**
** Description Given an address, find the associated control block.
**
** Returns tBTA_DM_PEER_DEVICE
**
*******************************************************************************/
tBTA_DM_PEER_DEVICE *bta_dm_find_peer_device(BD_ADDR peer_addr)
{
tBTA_DM_PEER_DEVICE *p_dev = NULL;
for (int i = 0; i < bta_dm_cb.device_list.count; i++) {
if (!bdcmp( bta_dm_cb.device_list.peer_device[i].peer_bdaddr, peer_addr)) {
p_dev = &bta_dm_cb.device_list.peer_device[i];
break;
}
}
return p_dev;
}
#if ((defined BLE_INCLUDED) && (BLE_INCLUDED == TRUE) && SDP_INCLUDED == TRUE)
/*******************************************************************************
@ -1161,5 +1152,6 @@ tBTA_DM_CONTRL_STATE bta_dm_pm_obtain_controller_state(void)
APPL_TRACE_DEBUG("bta_dm_pm_obtain_controller_state: %d", cur_state);
return cur_state;
}
#endif

View file

@ -650,6 +650,6 @@ INT32 BTA_DmPcmResample (void *p_src, UINT32 in_bytes, void *p_dst)
APPL_TRACE_DEBUG("bta_pcm_resample : outsamples %d", out_sample);
#endif
return (out_sample * bta_dm_pcm_cb.sample_size);
return (out_sample);
}
#endif

View file

@ -63,11 +63,11 @@ enum {
BTA_DM_API_BOND_CANCEL_EVT,
BTA_DM_API_PIN_REPLY_EVT,
#endif ///SMP_INCLUDED == TRUE
#if (BTM_SSR_INCLUDED == TRUE)
#if (BTA_DM_PM_INCLUDED == TRUE)
/* power manger events */
BTA_DM_PM_BTM_STATUS_EVT,
BTA_DM_PM_TIMER_EVT,
#endif ///BTM_SSR_INCLUDED == TRUE
#endif /* #if (BTA_DM_PM_INCLUDED == TRUE) */
#if (SMP_INCLUDED == TRUE)
/* simple pairing events */
BTA_DM_API_CONFIRM_EVT,
@ -350,6 +350,7 @@ typedef struct {
#endif
} tBTA_DM_ACL_CHANGE;
#if (BTA_DM_PM_INCLUDED == TRUE)
/* data type for BTA_DM_PM_BTM_STATUS_EVT */
typedef struct {
@ -367,7 +368,7 @@ typedef struct {
BD_ADDR bd_addr;
tBTA_DM_PM_ACTION pm_request;
} tBTA_DM_PM_TIMER;
#endif /* #if (BTA_DM_PM_INCLUDED == TRUE) */
/* data type for BTA_DM_API_ADD_DEVICE_EVT */
typedef struct {
@ -757,9 +758,11 @@ typedef union {
tBTA_DM_ACL_CHANGE acl_change;
#if (BTA_DM_PM_INCLUDED == TRUE)
tBTA_DM_PM_BTM_STATUS pm_status;
tBTA_DM_PM_TIMER pm_timer;
#endif /* #if (BTA_DM_PM_INCLUDED == TRUE) */
tBTA_DM_API_DI_DISC di_disc;
@ -889,6 +892,10 @@ typedef struct {
} tBTA_DM_CONNECTED_SRVCS;
extern tBTA_DM_CONNECTED_SRVCS bta_dm_conn_srvcs;
#if (BTA_DM_PM_INCLUDED == TRUE)
typedef struct {
#define BTA_DM_PM_SNIFF_TIMER_IDX 0
#define BTA_DM_PM_PARK_TIMER_IDX 1
@ -908,9 +915,8 @@ typedef struct {
BOOLEAN in_use;
} tBTA_PM_TIMER;
extern tBTA_DM_CONNECTED_SRVCS bta_dm_conn_srvcs;
#define BTA_DM_NUM_PM_TIMER 7
#endif /* #if (BTA_DM_PM_INCLUDED == TRUE) */
/* DM control block */
typedef struct {
@ -931,10 +937,10 @@ typedef struct {
UINT32 wbt_sdp_handle; /* WIDCOMM Extensions SDP record handle */
UINT8 wbt_scn; /* WIDCOMM Extensions SCN */
UINT8 num_master_only;
#if BTM_SSR_INCLUDED == TRUE
#if (BTA_DM_PM_INCLUDED == TRUE)
UINT8 pm_id;
tBTA_PM_TIMER pm_timer[BTA_DM_NUM_PM_TIMER];
#endif ///BTM_SSR_INCLUDED == TRUE
#endif /* #if (BTA_DM_PM_INCLUDED == TRUE) */
UINT32 role_policy_mask; /* the bits set indicates the modules that wants to remove role switch from the default link policy */
UINT16 cur_policy; /* current default link policy */
UINT16 rs_event; /* the event waiting for role switch */
@ -1101,12 +1107,14 @@ typedef struct {
UINT8 lmp_version;
} tBTA_DM_LMP_VER_INFO;
#if (BTA_DM_PM_INCLUDED == TRUE)
extern tBTA_DM_PM_CFG *p_bta_dm_pm_cfg;
extern tBTA_DM_PM_SPEC *p_bta_dm_pm_spec;
extern tBTM_PM_PWR_MD *p_bta_dm_pm_md;
#if (BTM_SSR_INCLUDED == TRUE)
extern tBTA_DM_SSR_SPEC *p_bta_dm_ssr_spec;
#endif
#endif /* #if (BTA_DM_PM_INCLUDED == TRUE) */
/* update dynamic BRCM Aware EIR data */
extern const tBTA_DM_EIR_CONF bta_dm_eir_cfg;
@ -1161,9 +1169,6 @@ extern void bta_dm_add_device (tBTA_DM_MSG *p_data);
extern void bta_dm_remove_device (tBTA_DM_MSG *p_data);
extern void bta_dm_close_acl(tBTA_DM_MSG *p_data);
extern void bta_dm_pm_btm_status(tBTA_DM_MSG *p_data);
extern void bta_dm_pm_timer(tBTA_DM_MSG *p_data);
extern void bta_dm_add_ampkey (tBTA_DM_MSG *p_data);
#if BLE_INCLUDED == TRUE
@ -1223,8 +1228,13 @@ extern void bta_dm_ci_io_req_act(tBTA_DM_MSG *p_data);
extern void bta_dm_ci_rmt_oob_act(tBTA_DM_MSG *p_data);
#endif /* BTM_OOB_INCLUDED */
#if (BTA_DM_PM_INCLUDED == TRUE)
extern void bta_dm_init_pm(void);
extern void bta_dm_disable_pm(void);
extern void bta_dm_pm_active(BD_ADDR peer_addr);
extern void bta_dm_pm_btm_status(tBTA_DM_MSG *p_data);
extern void bta_dm_pm_timer(tBTA_DM_MSG *p_data);
#endif /* #if (BTA_DM_PM_INCLUDED == TRUE) */
extern UINT8 bta_dm_get_av_count(void);
extern void bta_dm_search_start (tBTA_DM_MSG *p_data);
@ -1251,9 +1261,6 @@ extern void bta_dm_search_cancel_notify (tBTA_DM_MSG *p_data);
extern void bta_dm_search_cancel_transac_cmpl(tBTA_DM_MSG *p_data);
extern void bta_dm_disc_rmt_name (tBTA_DM_MSG *p_data);
extern tBTA_DM_PEER_DEVICE *bta_dm_find_peer_device(BD_ADDR peer_addr);
extern void bta_dm_pm_active(BD_ADDR peer_addr);
void bta_dm_eir_update_uuid(UINT16 uuid16, BOOLEAN adding);
extern void bta_dm_enable_test_mode(tBTA_DM_MSG *p_data);

View file

@ -0,0 +1,772 @@
/******************************************************************************
*
* Copyright (c) 2014 The Android Open Source Project
* Copyright (C) 2003-2012 Broadcom Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at:
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
******************************************************************************/
/******************************************************************************
*
* This file contains action functions for the handsfree client.
*
******************************************************************************/
#include "bta/bta_api.h"
#include "bta/bta_hf_client_api.h"
#include "bta_hf_client_int.h"
#include "bta_dm_int.h"
#include "stack/l2c_api.h"
#include "stack/port_api.h"
#include "bta/bta_sys.h"
#include "bta/utl.h"
#include "common/bt_defs.h"
#include <string.h>
#include "osi/allocator.h"
#if (BTA_HF_INCLUDED == TRUE)
/*****************************************************************************
** Constants
*****************************************************************************/
/* maximum length of data to read from RFCOMM */
#define BTA_HF_CLIENT_RFC_READ_MAX 512
/*******************************************************************************
**
** Function bta_hf_client_register
**
** Description This function initializes values of the scb and sets up
** the SDP record for the services.
**
**
** Returns void
**
*******************************************************************************/
void bta_hf_client_register(tBTA_HF_CLIENT_DATA *p_data)
{
tBTA_HF_CLIENT_REGISTER evt;
tBTA_UTL_COD cod;
memset(&evt, 0, sizeof(evt));
/* initialize control block */
bta_hf_client_scb_init();
bta_hf_client_cb.scb.serv_sec_mask = p_data->api_register.sec_mask;
bta_hf_client_cb.scb.features = p_data->api_register.features;
/* initialize AT control block */
bta_hf_client_at_init();
/* create SDP records */
bta_hf_client_create_record(p_data);
/* Set the Audio service class bit */
cod.service = BTM_COD_SERVICE_AUDIO;
utl_set_device_class(&cod, BTA_UTL_SET_COD_SERVICE_CLASS);
/* start RFCOMM server */
bta_hf_client_start_server();
/* call app callback with register event */
evt.status = BTA_HF_CLIENT_SUCCESS;
(*bta_hf_client_cb.p_cback)(BTA_HF_CLIENT_REGISTER_EVT, &evt);
}
/*******************************************************************************
**
** Function bta_hf_client_deregister
**
** Description This function removes the sdp records, closes the RFCOMM
** servers, and deallocates the service control block.
**
**
** Returns void
**
*******************************************************************************/
void bta_hf_client_deregister(tBTA_HF_CLIENT_DATA *p_data)
{
bta_hf_client_cb.scb.deregister = TRUE;
/* remove sdp record */
bta_hf_client_del_record(p_data);
/* remove rfcomm server */
bta_hf_client_close_server();
/* disable */
bta_hf_client_scb_disable();
}
/*******************************************************************************
**
** Function bta_hf_client_start_dereg
**
** Description Start a deregister event.
**
**
** Returns void
**
*******************************************************************************/
void bta_hf_client_start_dereg(tBTA_HF_CLIENT_DATA *p_data)
{
bta_hf_client_cb.scb.deregister = TRUE;
/* remove sdp record */
bta_hf_client_del_record(p_data);
}
/*******************************************************************************
**
** Function bta_hf_client_start_close
**
** Description Start the process of closing SCO and RFCOMM connection.
**
**
** Returns void
**
*******************************************************************************/
void bta_hf_client_start_close(tBTA_HF_CLIENT_DATA *p_data)
{
/* Take the link out of sniff and set L2C idle time to 0 */
#if (BTA_DM_PM_INCLUDED == TRUE)
bta_dm_pm_active(bta_hf_client_cb.scb.peer_addr);
#endif /* (BTA_DM_PM_INCLUDED == TRUE) */
L2CA_SetIdleTimeoutByBdAddr(bta_hf_client_cb.scb.peer_addr, 0, BT_TRANSPORT_BR_EDR);
/* if SCO is open close SCO and wait on RFCOMM close */
if (bta_hf_client_cb.scb.sco_state == BTA_HF_CLIENT_SCO_OPEN_ST) {
bta_hf_client_cb.scb.sco_close_rfc = TRUE;
} else {
bta_hf_client_rfc_do_close(p_data);
}
/* always do SCO shutdown to handle all SCO corner cases */
bta_hf_client_sco_shutdown(NULL);
}
/*******************************************************************************
**
** Function bta_hf_client_start_open
**
** Description This starts an HF Client open.
**
**
** Returns void
**
*******************************************************************************/
void bta_hf_client_start_open(tBTA_HF_CLIENT_DATA *p_data)
{
BD_ADDR pending_bd_addr;
/* store parameters */
if (p_data) {
bdcpy(bta_hf_client_cb.scb.peer_addr, p_data->api_open.bd_addr);
bta_hf_client_cb.scb.cli_sec_mask = p_data->api_open.sec_mask;
}
/* Check if RFCOMM has any incoming connection to avoid collision. */
if (PORT_IsOpening (pending_bd_addr)) {
/* Let the incoming connection goes through. */
/* Issue collision for now. */
/* We will decide what to do when we find incoming connection later.*/
bta_hf_client_collision_cback (0, BTA_ID_HS, 0, bta_hf_client_cb.scb.peer_addr);
return;
}
/* close server */
bta_hf_client_close_server();
/* set role */
bta_hf_client_cb.scb.role = BTA_HF_CLIENT_INT;
/* do service search */
bta_hf_client_do_disc();
}
/*******************************************************************************
**
** Function bta_hf_client_cback_open
**
** Description Send open callback event to application.
**
**
** Returns void
**
*******************************************************************************/
static void bta_hf_client_cback_open(tBTA_HF_CLIENT_DATA *p_data, tBTA_HF_CLIENT_STATUS status)
{
tBTA_HF_CLIENT_OPEN evt;
memset(&evt, 0, sizeof(evt));
/* call app callback with open event */
evt.status = status;
if (p_data) {
/* if p_data is provided then we need to pick the bd address from the open api structure */
bdcpy(evt.bd_addr, p_data->api_open.bd_addr);
} else {
bdcpy(evt.bd_addr, bta_hf_client_cb.scb.peer_addr);
}
(*bta_hf_client_cb.p_cback)(BTA_HF_CLIENT_OPEN_EVT, &evt);
}
/*******************************************************************************
**
** Function bta_hf_client_rfc_open
**
** Description Handle RFCOMM channel open.
**
**
** Returns void
**
*******************************************************************************/
void bta_hf_client_rfc_open(tBTA_HF_CLIENT_DATA *p_data)
{
UNUSED(p_data);
bta_sys_conn_open(BTA_ID_HS, 1, bta_hf_client_cb.scb.peer_addr);
bta_hf_client_cback_open(NULL, BTA_HF_CLIENT_SUCCESS);
/* start SLC procedure */
bta_hf_client_slc_seq(FALSE);
}
/*******************************************************************************
**
** Function bta_hf_client_rfc_acp_open
**
** Description Handle RFCOMM channel open when accepting connection.
**
**
** Returns void
**
*******************************************************************************/
void bta_hf_client_rfc_acp_open(tBTA_HF_CLIENT_DATA *p_data)
{
UINT16 lcid;
BD_ADDR dev_addr;
int status;
/* set role */
bta_hf_client_cb.scb.role = BTA_HF_CLIENT_ACP;
APPL_TRACE_DEBUG ("bta_hf_client_rfc_acp_open: serv_handle = %d rfc.port_handle = %d",
bta_hf_client_cb.scb.serv_handle, p_data->rfc.port_handle);
/* get bd addr of peer */
if (PORT_SUCCESS != (status = PORT_CheckConnection(p_data->rfc.port_handle, dev_addr, &lcid))) {
APPL_TRACE_DEBUG ("bta_hf_client_rfc_acp_open error PORT_CheckConnection returned status %d", status);
}
/* Collision Handling */
if (bta_hf_client_cb.scb.colli_tmr_on) {
/* stop collision timer */
bta_hf_client_cb.scb.colli_tmr_on = FALSE;
bta_sys_free_timer (&bta_hf_client_cb.scb.colli_timer);
if (bdcmp (dev_addr, bta_hf_client_cb.scb.peer_addr) == 0) {
/* If incoming and outgoing device are same, nothing more to do. */
/* Outgoing conn will be aborted because we have successful incoming conn. */
} else {
/* Resume outgoing connection. */
bta_hf_client_resume_open ();
}
}
bdcpy (bta_hf_client_cb.scb.peer_addr, dev_addr);
bta_hf_client_cb.scb.conn_handle = p_data->rfc.port_handle;
/* do service discovery to get features */
bta_hf_client_do_disc();
/* continue with open processing */
bta_hf_client_rfc_open(p_data);
}
/*******************************************************************************
**
** Function bta_hf_client_rfc_fail
**
** Description RFCOMM connection failed.
**
**
** Returns void
**
*******************************************************************************/
void bta_hf_client_rfc_fail(tBTA_HF_CLIENT_DATA *p_data)
{
UNUSED(p_data);
/* reinitialize stuff */
bta_hf_client_cb.scb.conn_handle = 0;
bta_hf_client_cb.scb.peer_features = 0;
bta_hf_client_cb.scb.chld_features = 0;
bta_hf_client_cb.scb.role = BTA_HF_CLIENT_ACP;
bta_hf_client_cb.scb.svc_conn = FALSE;
bta_hf_client_cb.scb.send_at_reply = FALSE;
bta_hf_client_cb.scb.negotiated_codec = BTM_SCO_CODEC_CVSD;
bta_hf_client_at_reset();
/* reopen server */
bta_hf_client_start_server();
/* call open cback w. failure */
bta_hf_client_cback_open(NULL, BTA_HF_CLIENT_FAIL_RFCOMM);
}
/*******************************************************************************
**
** Function bta_hf_client_disc_fail
**
** Description This function handles a discovery failure.
**
**
** Returns void
**
*******************************************************************************/
void bta_hf_client_disc_fail(tBTA_HF_CLIENT_DATA *p_data)
{
UNUSED(p_data);
/* reopen server */
bta_hf_client_start_server();
/* reinitialize stuff */
/* call open cback w. failure */
bta_hf_client_cback_open(NULL, BTA_HF_CLIENT_FAIL_SDP);
}
/*******************************************************************************
**
** Function bta_hf_client_open_fail
**
** Description open connection failed.
**
**
** Returns void
**
*******************************************************************************/
void bta_hf_client_open_fail(tBTA_HF_CLIENT_DATA *p_data)
{
/* call open cback w. failure */
bta_hf_client_cback_open(p_data, BTA_HF_CLIENT_FAIL_RESOURCES);
}
/*******************************************************************************
**
** Function bta_hf_client_rfc_close
**
** Description RFCOMM connection closed.
**
**
** Returns void
**
*******************************************************************************/
void bta_hf_client_rfc_close(tBTA_HF_CLIENT_DATA *p_data)
{
UNUSED(p_data);
/* reinitialize stuff */
bta_hf_client_cb.scb.peer_features = 0;
bta_hf_client_cb.scb.chld_features = 0;
bta_hf_client_cb.scb.role = BTA_HF_CLIENT_ACP;
bta_hf_client_cb.scb.svc_conn = FALSE;
bta_hf_client_cb.scb.send_at_reply = FALSE;
bta_hf_client_cb.scb.negotiated_codec = BTM_SCO_CODEC_CVSD;
bta_hf_client_at_reset();
bta_sys_conn_close(BTA_ID_HS, 1, bta_hf_client_cb.scb.peer_addr);
/* call close cback */
(*bta_hf_client_cb.p_cback)(BTA_HF_CLIENT_CLOSE_EVT, NULL);
/* if not deregistering reopen server */
if (bta_hf_client_cb.scb.deregister == FALSE) {
/* Clear peer bd_addr so instance can be reused */
bdcpy(bta_hf_client_cb.scb.peer_addr, bd_addr_null);
/* start server as it might got closed on open*/
bta_hf_client_start_server();
bta_hf_client_cb.scb.conn_handle = 0;
/* Make sure SCO is shutdown */
bta_hf_client_sco_shutdown(NULL);
bta_sys_sco_unuse(BTA_ID_HS, 1, bta_hf_client_cb.scb.peer_addr);
}
/* else close port and deallocate scb */
else {
bta_hf_client_close_server();
bta_hf_client_scb_disable();
}
}
/*******************************************************************************
**
** Function bta_hf_client_disc_int_res
**
** Description This function handles a discovery result when initiator.
**
**
** Returns void
**
*******************************************************************************/
void bta_hf_client_disc_int_res(tBTA_HF_CLIENT_DATA *p_data)
{
UINT16 event = BTA_HF_CLIENT_DISC_FAIL_EVT;
APPL_TRACE_DEBUG ("bta_hf_client_disc_int_res: Status: %d", p_data->disc_result.status);
/* if found service */
if (p_data->disc_result.status == SDP_SUCCESS ||
p_data->disc_result.status == SDP_DB_FULL) {
/* get attributes */
if (bta_hf_client_sdp_find_attr()) {
event = BTA_HF_CLIENT_DISC_OK_EVT;
}
}
/* free discovery db */
bta_hf_client_free_db(p_data);
/* send ourselves sdp ok/fail event */
bta_hf_client_sm_execute(event, p_data);
}
/*******************************************************************************
**
** Function bta_hf_client_disc_acp_res
**
** Description This function handles a discovery result when acceptor.
**
**
** Returns void
**
*******************************************************************************/
void bta_hf_client_disc_acp_res(tBTA_HF_CLIENT_DATA *p_data)
{
/* if found service */
if (p_data->disc_result.status == SDP_SUCCESS ||
p_data->disc_result.status == SDP_DB_FULL) {
/* get attributes */
bta_hf_client_sdp_find_attr();
}
/* free discovery db */
bta_hf_client_free_db(p_data);
}
/*******************************************************************************
**
** Function bta_hf_client_rfc_data
**
** Description Read and process data from RFCOMM.
**
**
** Returns void
**
*******************************************************************************/
void bta_hf_client_rfc_data(tBTA_HF_CLIENT_DATA *p_data)
{
UINT16 len;
char *buf = osi_calloc(BTA_HF_CLIENT_RFC_READ_MAX);
if (buf == NULL) {
APPL_TRACE_ERROR("No mem %s", __FUNCTION__);
return;
}
UNUSED(p_data);
/* read data from rfcomm; if bad status, we're done */
while (PORT_ReadData(bta_hf_client_cb.scb.conn_handle, buf, BTA_HF_CLIENT_RFC_READ_MAX, &len) == PORT_SUCCESS) {
/* if no data, we're done */
if (len == 0) {
break;
}
bta_hf_client_at_parse(buf, len);
/* no more data to read, we're done */
if (len < BTA_HF_CLIENT_RFC_READ_MAX) {
break;
}
}
osi_free(buf);
}
/*******************************************************************************
**
** Function bta_hf_client_svc_conn_open
**
** Description Service level connection opened
**
**
** Returns void
**
*******************************************************************************/
void bta_hf_client_svc_conn_open(tBTA_HF_CLIENT_DATA *p_data)
{
tBTA_HF_CLIENT_CONN evt;
UNUSED(p_data);
memset(&evt, 0, sizeof(evt));
if (!bta_hf_client_cb.scb.svc_conn) {
/* set state variable */
bta_hf_client_cb.scb.svc_conn = TRUE;
/* call callback */
evt.peer_feat = bta_hf_client_cb.scb.peer_features;
evt.chld_feat = bta_hf_client_cb.scb.chld_features;
(*bta_hf_client_cb.p_cback)(BTA_HF_CLIENT_CONN_EVT, &evt);
}
}
/*******************************************************************************
**
** Function bta_hf_client_cback_ind
**
** Description Send indicator callback event to application.
**
** Returns void
**
*******************************************************************************/
void bta_hf_client_ind(tBTA_HF_CLIENT_IND_TYPE type, UINT16 value)
{
tBTA_HF_CLIENT_IND evt;
memset(&evt, 0, sizeof(evt));
evt.type = type;
evt.value = value;
(*bta_hf_client_cb.p_cback)(BTA_HF_CLIENT_IND_EVT, &evt);
}
/*******************************************************************************
**
** Function bta_hf_client_evt_val
**
** Description Send event to application.
** This is a generic helper for events with common data.
**
**
** Returns void
**
*******************************************************************************/
void bta_hf_client_evt_val(tBTA_HF_CLIENT_EVT type, UINT16 value)
{
tBTA_HF_CLIENT_VAL evt;
memset(&evt, 0, sizeof(evt));
evt.value = value;
(*bta_hf_client_cb.p_cback)(type, &evt);
}
/*******************************************************************************
**
** Function bta_hf_client_operator_name
**
** Description Send operator name event to application.
**
**
** Returns void
**
*******************************************************************************/
void bta_hf_client_operator_name(char *name)
{
tBTA_HF_CLIENT_OPERATOR_NAME *evt;
if ((evt = osi_calloc(sizeof(tBTA_HF_CLIENT_OPERATOR_NAME))) != NULL) {
strlcpy(evt->name, name, BTA_HF_CLIENT_OPERATOR_NAME_LEN + 1);
evt->name[BTA_HF_CLIENT_OPERATOR_NAME_LEN] = '\0';
(*bta_hf_client_cb.p_cback)(BTA_HF_CLIENT_OPERATOR_NAME_EVT, evt);
osi_free(evt);
} else {
APPL_TRACE_ERROR("No mem: %s", __func__);
}
}
/*******************************************************************************
**
** Function bta_hf_client_clip
**
** Description Send CLIP event to application.
**
**
** Returns void
**
*******************************************************************************/
void bta_hf_client_clip(char *number)
{
tBTA_HF_CLIENT_NUMBER *evt;
if ((evt = osi_calloc(sizeof(tBTA_HF_CLIENT_NUMBER))) != NULL) {
strlcpy(evt->number, number, BTA_HF_CLIENT_NUMBER_LEN + 1);
evt->number[BTA_HF_CLIENT_NUMBER_LEN] = '\0';
(*bta_hf_client_cb.p_cback)(BTA_HF_CLIENT_CLIP_EVT, evt);
osi_free(evt);
} else {
APPL_TRACE_ERROR("No mem: %s", __func__);
}
}
/*******************************************************************************
**
** Function bta_hf_client_ccwa
**
** Description Send CLIP event to application.
**
**
** Returns void
**
*******************************************************************************/
void bta_hf_client_ccwa(char *number)
{
tBTA_HF_CLIENT_NUMBER *evt;
if ((evt = osi_calloc(sizeof(tBTA_HF_CLIENT_NUMBER))) != NULL) {
strlcpy(evt->number, number, BTA_HF_CLIENT_NUMBER_LEN + 1);
evt->number[BTA_HF_CLIENT_NUMBER_LEN] = '\0';
(*bta_hf_client_cb.p_cback)(BTA_HF_CLIENT_CCWA_EVT, evt);
osi_free(evt);
} else {
APPL_TRACE_ERROR("No mem: %s", __func__);
}
}
/*******************************************************************************
**
** Function bta_hf_client_at_result
**
** Description Send AT result event to application.
**
**
** Returns void
**
*******************************************************************************/
void bta_hf_client_at_result(tBTA_HF_CLIENT_AT_RESULT_TYPE type, UINT16 cme)
{
tBTA_HF_CLIENT_AT_RESULT evt;
memset(&evt, 0, sizeof(evt));
evt.type = type;
evt.cme = cme;
(*bta_hf_client_cb.p_cback)(BTA_HF_CLIENT_AT_RESULT_EVT, &evt);
}
/*******************************************************************************
**
** Function bta_hf_client_clcc
**
** Description Send clcc event to application.
**
**
** Returns void
**
*******************************************************************************/
void bta_hf_client_clcc(UINT32 idx, BOOLEAN incoming, UINT8 status, BOOLEAN mpty, char *number)
{
tBTA_HF_CLIENT_CLCC *evt;
if ((evt = osi_calloc(sizeof(tBTA_HF_CLIENT_CLCC))) != NULL) {
evt->idx = idx;
evt->inc = incoming;
evt->status = status;
evt->mpty = mpty;
if (number) {
evt->number_present = TRUE;
strlcpy(evt->number, number, BTA_HF_CLIENT_NUMBER_LEN + 1);
evt->number[BTA_HF_CLIENT_NUMBER_LEN] = '\0';
}
(*bta_hf_client_cb.p_cback)(BTA_HF_CLIENT_CLCC_EVT, evt);
osi_free(evt);
} else {
APPL_TRACE_ERROR("No mem, %s\n", __func__);
}
}
/*******************************************************************************
**
** Function bta_hf_client_cnum
**
** Description Send cnum event to application.
**
**
** Returns void
**
*******************************************************************************/
void bta_hf_client_cnum(char *number, UINT16 service)
{
tBTA_HF_CLIENT_CNUM *evt;
if ((evt = osi_calloc(sizeof(tBTA_HF_CLIENT_CNUM))) != NULL) {
evt->service = service;
strlcpy(evt->number, number, BTA_HF_CLIENT_NUMBER_LEN + 1);
evt->number[BTA_HF_CLIENT_NUMBER_LEN] = '\0';
(*bta_hf_client_cb.p_cback)(BTA_HF_CLIENT_CNUM_EVT, evt);
osi_free(evt);
} else {
APPL_TRACE_ERROR("No mem, %s", __func__);
}
}
/*******************************************************************************
**
** Function bta_hf_client_binp
**
** Description Send BINP event to application.
**
**
** Returns void
**
*******************************************************************************/
void bta_hf_client_binp(char *number)
{
tBTA_HF_CLIENT_NUMBER *evt;
if ((evt = osi_calloc(sizeof(tBTA_HF_CLIENT_NUMBER))) != NULL) {
strlcpy(evt->number, number, BTA_HF_CLIENT_NUMBER_LEN + 1);
evt->number[BTA_HF_CLIENT_NUMBER_LEN] = '\0';
(*bta_hf_client_cb.p_cback)(BTA_HF_CLIENT_BINP_EVT, evt);
osi_free(evt);
} else {
APPL_TRACE_ERROR("No mem: %s", __func__);
}
}
#endif /* #if (BTA_HF_INCLUDED == TRUE) */

View file

@ -0,0 +1,312 @@
/******************************************************************************
*
* Copyright (c) 2014 The Android Open Source Project
* Copyright (C) 2003-2012 Broadcom Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at:
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
******************************************************************************/
/******************************************************************************
*
* This is the implementation of the API for the handsfree (HF role)
* subsystem of BTA
*
******************************************************************************/
#include <string.h>
#include "bta/bta_hf_client_api.h"
#include "bta_hf_client_int.h"
#include "osi/allocator.h"
#if (BTA_HF_INCLUDED == TRUE)
/*****************************************************************************
** Constants and data types
*****************************************************************************/
static const tBTA_SYS_REG bta_hf_client_reg = {
bta_hf_client_hdl_event,
BTA_HfClientDisable
};
static const uint8_t bta_hf_client_cb_data_size[] = {
0, // #define BTA_HF_CLIENT_ENABLE_EVT 0
sizeof(tBTA_HF_CLIENT_REGISTER), // #define BTA_HF_CLIENT_REGISTER_EVT 1
sizeof(tBTA_HF_CLIENT_OPEN), // #define BTA_HF_CLIENT_OPEN_EVT 2
0, // #define BTA_HF_CLIENT_CLOSE_EVT 3
sizeof(tBTA_HF_CLIENT_CONN), // #define BTA_HF_CLIENT_CONN_EVT 4
sizeof(tBTA_HF_CLIENT_HDR), // #define BTA_HF_CLIENT_AUDIO_OPEN_EVT 5
sizeof(tBTA_HF_CLIENT_HDR), //#define BTA_HF_CLIENT_AUDIO_MSBC_OPEN_EVT 6
sizeof(tBTA_HF_CLIENT_HDR), // #define BTA_HF_CLIENT_AUDIO_CLOSE_EVT 7
sizeof(tBTA_HF_CLIENT_VAL), // #define BTA_HF_CLIENT_SPK_EVT 8
sizeof(tBTA_HF_CLIENT_VAL), // #define BTA_HF_CLIENT_MIC_EVT 9
sizeof(tBTA_HF_CLIENT_IND), //#define BTA_HF_CLIENT_IND_EVT 10
sizeof(tBTA_HF_CLIENT_VAL), // #define BTA_HF_CLIENT_VOICE_REC_EVT 11
sizeof(tBTA_HF_CLIENT_OPERATOR_NAME), // #define BTA_HF_CLIENT_OPERATOR_NAME_EVT 12
sizeof(tBTA_HF_CLIENT_NUMBER), // #define BTA_HF_CLIENT_CLIP_EVT 13
sizeof(tBTA_HF_CLIENT_NUMBER), // #define BTA_HF_CLIENT_CCWA_EVT 14
sizeof(tBTA_HF_CLIENT_AT_RESULT), // #define BTA_HF_CLIENT_AT_RESULT_EVT 15
sizeof(tBTA_HF_CLIENT_CLCC), // #define BTA_HF_CLIENT_CLCC_EVT 16
sizeof(tBTA_HF_CLIENT_CNUM), //#define BTA_HF_CLIENT_CNUM_EVT 17
sizeof(tBTA_HF_CLIENT_VAL), // #define BTA_HF_CLIENT_BTRH_EVT 18
sizeof(tBTA_HF_CLIENT_VAL), // #define BTA_HF_CLIENT_BSIR_EVT 19
sizeof(tBTA_HF_CLIENT_NUMBER), // #define BTA_HF_CLIENT_BINP_EVT 20
sizeof(tBTA_HF_CLIENT_VAL), // #define BTA_HF_CLIENT_RING_INDICATION 21
0, // #define BTA_HF_CLIENT_DISABLE_EVT 30
};
/*****************************************************************************
** External Function Declarations
*****************************************************************************/
/*******************************************************************************
**
** Function BTA_HfClientEnable
**
** Description Enable the HF CLient service. When the enable
** operation is complete the callback function will be
** called with a BTA_HF_CLIENT_ENABLE_EVT. This function must
** be called before other function in the HF CLient API are
** called.
**
** Returns BTA_SUCCESS if OK, BTA_FAILURE otherwise.
**
*******************************************************************************/
tBTA_STATUS BTA_HfClientEnable(tBTA_HF_CLIENT_CBACK *p_cback)
{
tBTA_HF_CLIENT_API_ENABLE *p_buf;
if (bta_sys_is_register (BTA_ID_HS)) {
APPL_TRACE_ERROR("BTA HF Client is already enabled, ignoring ...");
return BTA_FAILURE;
}
/* register with BTA system manager */
bta_sys_register(BTA_ID_HS, &bta_hf_client_reg);
if ((p_buf = (tBTA_HF_CLIENT_API_ENABLE *) osi_malloc(sizeof(tBTA_HF_CLIENT_API_ENABLE))) != NULL) {
p_buf->hdr.event = BTA_HF_CLIENT_API_ENABLE_EVT;
p_buf->p_cback = p_cback;
bta_sys_sendmsg(p_buf);
}
return BTA_SUCCESS;
}
/*******************************************************************************
**
** Function BTA_HfClientDisable
**
** Description Disable the HF Client service
**
**
** Returns void
**
*******************************************************************************/
void BTA_HfClientDisable(void)
{
BT_HDR *p_buf;
if ((p_buf = (BT_HDR *) osi_malloc(sizeof(BT_HDR))) != NULL) {
p_buf->event = BTA_HF_CLIENT_API_DISABLE_EVT;
bta_sys_sendmsg(p_buf);
}
}
/*******************************************************************************
**
** Function BTA_HfClientRegister
**
** Description Register an HF Client service.
**
**
** Returns void
**
*******************************************************************************/
void BTA_HfClientRegister(tBTA_SEC sec_mask, tBTA_HF_CLIENT_FEAT features,
char *p_service_name)
{
tBTA_HF_CLIENT_API_REGISTER *p_buf;
if ((p_buf = (tBTA_HF_CLIENT_API_REGISTER *) osi_malloc(sizeof(tBTA_HF_CLIENT_API_REGISTER))) != NULL) {
p_buf->hdr.event = BTA_HF_CLIENT_API_REGISTER_EVT;
p_buf->features = features;
p_buf->sec_mask = sec_mask;
if (p_service_name) {
BCM_STRNCPY_S(p_buf->name, BTA_SERVICE_NAME_LEN + 1, p_service_name, BTA_SERVICE_NAME_LEN);
p_buf->name[BTA_SERVICE_NAME_LEN] = 0;
} else {
p_buf->name[0] = '\0';
}
bta_sys_sendmsg(p_buf);
}
}
/*******************************************************************************
**
** Function BTA_HfClientDeregister
**
** Description Deregister an HF Client service.
**
**
** Returns void
**
*******************************************************************************/
void BTA_HfClientDeregister(UINT16 handle)
{
BT_HDR *p_buf;
if ((p_buf = (BT_HDR *) osi_malloc(sizeof(BT_HDR))) != NULL) {
p_buf->event = BTA_HF_CLIENT_API_DEREGISTER_EVT;
p_buf->layer_specific = handle;
bta_sys_sendmsg(p_buf);
}
}
/*******************************************************************************
**
** Function BTA_HfClientOpen
**
** Description Opens a connection to an audio gateway.
** When connection is open callback function is called
** with a BTA_AG_OPEN_EVT. Only the data connection is
** opened. The audio connection is not opened.
**
**
** Returns void
**
*******************************************************************************/
void BTA_HfClientOpen(UINT16 handle, BD_ADDR bd_addr, tBTA_SEC sec_mask)
{
tBTA_HF_CLIENT_API_OPEN *p_buf;
if ((p_buf = (tBTA_HF_CLIENT_API_OPEN *) osi_malloc(sizeof(tBTA_HF_CLIENT_API_OPEN))) != NULL) {
p_buf->hdr.event = BTA_HF_CLIENT_API_OPEN_EVT;
p_buf->hdr.layer_specific = handle;
bdcpy(p_buf->bd_addr, bd_addr);
p_buf->sec_mask = sec_mask;
bta_sys_sendmsg(p_buf);
}
}
/*******************************************************************************
**
** Function BTA_HfClientClose
**
** Description Close the current connection to an audio gateway.
** Any current audio connection will also be closed
**
**
** Returns void
**
*******************************************************************************/
void BTA_HfClientClose(UINT16 handle)
{
BT_HDR *p_buf;
if ((p_buf = (BT_HDR *) osi_malloc(sizeof(BT_HDR))) != NULL) {
p_buf->event = BTA_HF_CLIENT_API_CLOSE_EVT;
p_buf->layer_specific = handle;
bta_sys_sendmsg(p_buf);
}
}
/*******************************************************************************
**
** Function BTA_HfCllientAudioOpen
**
** Description Opens an audio connection to the currently connected
** audio gateway
**
**
** Returns void
**
*******************************************************************************/
void BTA_HfClientAudioOpen(UINT16 handle)
{
BT_HDR *p_buf;
if ((p_buf = (BT_HDR *) osi_malloc(sizeof(BT_HDR))) != NULL) {
p_buf->event = BTA_HF_CLIENT_API_AUDIO_OPEN_EVT;
p_buf->layer_specific = handle;
bta_sys_sendmsg(p_buf);
}
}
/*******************************************************************************
**
** Function BTA_HfClientAudioClose
**
** Description Close the currently active audio connection to an audio
** gateway. The data connection remains open
**
**
** Returns void
**
*******************************************************************************/
void BTA_HfClientAudioClose(UINT16 handle)
{
BT_HDR *p_buf;
if ((p_buf = (BT_HDR *) osi_malloc(sizeof(BT_HDR))) != NULL) {
p_buf->event = BTA_HF_CLIENT_API_AUDIO_CLOSE_EVT;
p_buf->layer_specific = handle;
bta_sys_sendmsg(p_buf);
}
}
/*******************************************************************************
**
** Function BTA_HfClientSendAT
**
** Description send AT command
**
**
** Returns void
**
*******************************************************************************/
void BTA_HfClientSendAT(UINT16 handle, tBTA_HF_CLIENT_AT_CMD_TYPE at, UINT32 val1, UINT32 val2, const char *str)
{
tBTA_HF_CLIENT_DATA_VAL *p_buf;
if ((p_buf = (tBTA_HF_CLIENT_DATA_VAL *) osi_malloc(sizeof(tBTA_HF_CLIENT_DATA_VAL))) != NULL) {
p_buf->hdr.event = BTA_HF_CLIENT_SEND_AT_CMD_EVT;
p_buf->uint8_val = at;
p_buf->uint32_val1 = val1;
p_buf->uint32_val2 = val2;
if (str) {
strlcpy(p_buf->str, str, BTA_HF_CLIENT_NUMBER_LEN + 1);
p_buf->str[BTA_HF_CLIENT_NUMBER_LEN] = '\0';
} else {
p_buf->str[0] = '\0';
}
p_buf->hdr.layer_specific = handle;
bta_sys_sendmsg(p_buf);
}
}
#if (BTM_SCO_HCI_INCLUDED == TRUE )
void BTA_HfClientCiData(void)
{
BT_HDR *p_buf;
if ((p_buf = (BT_HDR *) osi_malloc(sizeof(BT_HDR))) != NULL) {
p_buf->event = BTA_HF_CLIENT_CI_SCO_DATA_EVT;
bta_sys_sendmsg(p_buf);
}
}
#endif /* #if (BTM_SCO_HCI_INCLUDED == TRUE ) */
int BTA_HfClientGetCbDataSize(tBTA_HF_CLIENT_EVT event)
{
return bta_hf_client_cb_data_size[event];
}
#endif /* #if (BTA_HF_INCLUDED == TRUE) */

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,85 @@
/******************************************************************************
*
* Copyright (c) 2014 The Android Open Source Project
* Copyright (C) 2003-2012 Broadcom Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at:
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
******************************************************************************/
#include "bta_hf_client_int.h"
#include "stdio.h"
#include "common/bt_target.h"
#if (BTA_HF_INCLUDED == TRUE)
void bta_hf_client_send_at_cmd(tBTA_HF_CLIENT_DATA *p_data)
{
tBTA_HF_CLIENT_DATA_VAL *p_val = (tBTA_HF_CLIENT_DATA_VAL *)p_data;
switch (p_val->uint8_val) {
case BTA_HF_CLIENT_AT_CMD_VTS:
bta_hf_client_send_at_vts((char)p_val->uint32_val1);
break;
case BTA_HF_CLIENT_AT_CMD_BTRH:
bta_hf_client_send_at_btrh(FALSE, p_val->uint32_val1);
break;
case BTA_HF_CLIENT_AT_CMD_CHUP:
bta_hf_client_send_at_chup();
break;
case BTA_HF_CLIENT_AT_CMD_CHLD:
/* expects ascii code for command */
bta_hf_client_send_at_chld('0' + p_val->uint32_val1, p_val->uint32_val2);
break;
case BTA_HF_CLIENT_AT_CMD_BCC:
bta_hf_client_send_at_bcc();
break;
case BTA_HF_CLIENT_AT_CMD_CNUM:
bta_hf_client_send_at_cnum();
break;
case BTA_HF_CLIENT_AT_CMD_ATA:
bta_hf_client_send_at_ata();
break;
case BTA_HF_CLIENT_AT_CMD_COPS:
bta_hf_client_send_at_cops(TRUE);
break;
case BTA_HF_CLIENT_AT_CMD_ATD:
bta_hf_client_send_at_atd(p_val->str, p_val->uint32_val1);
break;
case BTA_HF_CLIENT_AT_CMD_VGM:
bta_hf_client_send_at_vgm(p_val->uint32_val1);
break;
case BTA_HF_CLIENT_AT_CMD_VGS:
bta_hf_client_send_at_vgs(p_val->uint32_val1);
break;
case BTA_HF_CLIENT_AT_CMD_BVRA:
bta_hf_client_send_at_bvra(p_val->uint32_val1 == 0 ? FALSE : TRUE);
break;
case BTA_HF_CLIENT_AT_CMD_CLCC:
bta_hf_client_send_at_clcc();
break;
case BTA_HF_CLIENT_AT_CMD_BINP:
bta_hf_client_send_at_binp(p_val->uint32_val1);
break;
case BTA_HF_CLIENT_AT_CMD_BLDN:
bta_hf_client_send_at_bldn();
break;
case BTA_HF_CLIENT_AT_CMD_NREC:
bta_hf_client_send_at_nrec();
break;
default:
APPL_TRACE_ERROR("Default case, %s", __FUNCTION__);
break;
}
}
#endif /* #if (BTA_HF_INCLUDED == TRUE) */

View file

@ -0,0 +1,662 @@
/******************************************************************************
*
* Copyright (c) 2014 The Android Open Source Project
* Copyright (C) 2003-2012 Broadcom Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at:
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
******************************************************************************/
#include <string.h>
#include <stdlib.h>
#include "common/bt_defs.h"
#include "bta/bta_api.h"
#include "bta/bta_sys.h"
#include "bta/bta_hf_client_api.h"
#include "bta_hf_client_int.h"
#if (BTA_HF_INCLUDED == TRUE)
/* uncomment to enable extra debug */
/* #define BTA_HF_CLIENT_DEBUG TRUE */
#ifndef BTA_HF_CLIENT_DEBUG
#define BTA_HF_CLIENT_DEBUG FALSE
#endif
#if BTA_HF_CLIENT_DEBUG == TRUE
static char *bta_hf_client_evt_str(UINT16 event);
static char *bta_hf_client_state_str(UINT8 state);
#endif
/* state machine states */
enum {
BTA_HF_CLIENT_INIT_ST,
BTA_HF_CLIENT_OPENING_ST,
BTA_HF_CLIENT_OPEN_ST,
BTA_HF_CLIENT_CLOSING_ST
};
/* state machine action enumeration list */
enum {
BTA_HF_CLIENT_REGISTER,
BTA_HF_CLIENT_DEREGISTER,
BTA_HF_CLIENT_START_DEREG,
BTA_HF_CLIENT_RFC_DO_CLOSE,
BTA_HF_CLIENT_START_CLOSE,
BTA_HF_CLIENT_START_OPEN,
BTA_HF_CLIENT_RFC_ACP_OPEN,
BTA_HF_CLIENT_SCO_LISTEN,
BTA_HF_CLIENT_SCO_CONN_OPEN,
BTA_HF_CLIENT_SCO_CONN_CLOSE,
BTA_HF_CLIENT_SCO_OPEN,
BTA_HF_CLIENT_SCO_CLOSE,
BTA_HF_CLIENT_SCO_SHUTDOWN,
BTA_HF_CLIENT_FREE_DB,
BTA_HF_CLIENT_OPEN_FAIL,
BTA_HF_CLIENT_RFC_OPEN,
BTA_HF_CLIENT_RFC_FAIL,
BTA_HF_CLIENT_DISC_INT_RES,
BTA_HF_CLIENT_RFC_DO_OPEN,
BTA_HF_CLIENT_DISC_FAIL,
BTA_HF_CLIENT_RFC_CLOSE,
BTA_HF_CLIENT_RFC_DATA,
BTA_HF_CLIENT_DISC_ACP_RES,
BTA_HF_CLIENT_SVC_CONN_OPEN,
BTA_HF_CLIENT_SEND_AT_CMD,
#if (BTM_SCO_HCI_INCLUDED == TRUE)
BTA_HF_CLIENT_CI_SCO_DATA,
#endif
BTA_HF_CLIENT_NUM_ACTIONS,
};
#define BTA_HF_CLIENT_IGNORE BTA_HF_CLIENT_NUM_ACTIONS
/* type for action functions */
typedef void (*tBTA_HF_CLIENT_ACTION)(tBTA_HF_CLIENT_DATA *p_data);
/* action functions table, indexed with action enum */
const tBTA_HF_CLIENT_ACTION bta_hf_client_action[] = {
/* BTA_HF_CLIENT_REGISTER */ bta_hf_client_register,
/* BTA_HF_CLIENT_DEREGISTER */ bta_hf_client_deregister,
/* BTA_HF_CLIENT_START_DEREG */ bta_hf_client_start_dereg,
/* BTA_HF_CLIENT_RFC_DO_CLOSE */ bta_hf_client_rfc_do_close,
/* BTA_HF_CLIENT_START_CLOSE */ bta_hf_client_start_close,
/* BTA_HF_CLIENT_START_OPEN */ bta_hf_client_start_open,
/* BTA_HF_CLIENT_RFC_ACP_OPEN */ bta_hf_client_rfc_acp_open,
/* BTA_HF_CLIENT_SCO_LISTEN */ bta_hf_client_sco_listen,
/* BTA_HF_CLIENT_SCO_CONN_OPEN */ bta_hf_client_sco_conn_open,
/* BTA_HF_CLIENT_SCO_CONN_CLOSE*/ bta_hf_client_sco_conn_close,
/* BTA_HF_CLIENT_SCO_OPEN */ bta_hf_client_sco_open,
/* BTA_HF_CLIENT_SCO_CLOSE */ bta_hf_client_sco_close,
/* BTA_HF_CLIENT_SCO_SHUTDOWN */ bta_hf_client_sco_shutdown,
/* BTA_HF_CLIENT_FREE_DB */ bta_hf_client_free_db,
/* BTA_HF_CLIENT_OPEN_FAIL */ bta_hf_client_open_fail,
/* BTA_HF_CLIENT_RFC_OPEN */ bta_hf_client_rfc_open,
/* BTA_HF_CLIENT_RFC_FAIL */ bta_hf_client_rfc_fail,
/* BTA_HF_CLIENT_DISC_INT_RES */ bta_hf_client_disc_int_res,
/* BTA_HF_CLIENT_RFC_DO_OPEN */ bta_hf_client_rfc_do_open,
/* BTA_HF_CLIENT_DISC_FAIL */ bta_hf_client_disc_fail,
/* BTA_HF_CLIENT_RFC_CLOSE */ bta_hf_client_rfc_close,
/* BTA_HF_CLIENT_RFC_DATA */ bta_hf_client_rfc_data,
/* BTA_HF_CLIENT_DISC_ACP_RES */ bta_hf_client_disc_acp_res,
/* BTA_HF_CLIENT_SVC_CONN_OPEN */ bta_hf_client_svc_conn_open,
/* BTA_HF_CLIENT_SEND_AT_CMD */ bta_hf_client_send_at_cmd,
#if (BTM_SCO_HCI_INCLUDED == TRUE )
/* BTA_HF_CLIENT_CI_SCO_DATA */ bta_hf_client_ci_sco_data,
#endif /* (BTM_SCO_HCI_INCLUDED == TRUE ) */
};
/* state table information */
#define BTA_HF_CLIENT_ACTIONS 2 /* number of actions */
#define BTA_HF_CLIENT_NEXT_STATE 2 /* position of next state */
#define BTA_HF_CLIENT_NUM_COLS 3 /* number of columns in state tables */
/* state table for init state */
const UINT8 bta_hf_client_st_init[][BTA_HF_CLIENT_NUM_COLS] = {
/* Event Action 1 Action 2 Next state */
/* API_REGISTER_EVT */ {BTA_HF_CLIENT_REGISTER, BTA_HF_CLIENT_IGNORE, BTA_HF_CLIENT_INIT_ST},
/* API_DEREGISTER_EVT */ {BTA_HF_CLIENT_DEREGISTER, BTA_HF_CLIENT_IGNORE, BTA_HF_CLIENT_INIT_ST},
/* API_OPEN_EVT */ {BTA_HF_CLIENT_START_OPEN, BTA_HF_CLIENT_IGNORE, BTA_HF_CLIENT_OPENING_ST},
/* API_CLOSE_EVT */ {BTA_HF_CLIENT_IGNORE, BTA_HF_CLIENT_IGNORE, BTA_HF_CLIENT_INIT_ST},
/* API_AUDIO_OPEN_EVT */ {BTA_HF_CLIENT_IGNORE, BTA_HF_CLIENT_IGNORE, BTA_HF_CLIENT_INIT_ST},
/* API_AUDIO_CLOSE_EVT */ {BTA_HF_CLIENT_IGNORE, BTA_HF_CLIENT_IGNORE, BTA_HF_CLIENT_INIT_ST},
/* RFC_OPEN_EVT */ {BTA_HF_CLIENT_RFC_ACP_OPEN, BTA_HF_CLIENT_SCO_LISTEN, BTA_HF_CLIENT_OPEN_ST},
/* RFC_CLOSE_EVT */ {BTA_HF_CLIENT_IGNORE, BTA_HF_CLIENT_IGNORE, BTA_HF_CLIENT_INIT_ST},
/* RFC_SRV_CLOSE_EVT */ {BTA_HF_CLIENT_IGNORE, BTA_HF_CLIENT_IGNORE, BTA_HF_CLIENT_INIT_ST},
/* RFC_DATA_EVT */ {BTA_HF_CLIENT_IGNORE, BTA_HF_CLIENT_IGNORE, BTA_HF_CLIENT_INIT_ST},
/* DISC_ACP_RES_EVT */ {BTA_HF_CLIENT_FREE_DB, BTA_HF_CLIENT_IGNORE, BTA_HF_CLIENT_INIT_ST},
/* DISC_INT_RES_EVT */ {BTA_HF_CLIENT_IGNORE, BTA_HF_CLIENT_IGNORE, BTA_HF_CLIENT_INIT_ST},
/* DISC_OK_EVT */ {BTA_HF_CLIENT_IGNORE, BTA_HF_CLIENT_IGNORE, BTA_HF_CLIENT_INIT_ST},
/* DISC_FAIL_EVT */ {BTA_HF_CLIENT_IGNORE, BTA_HF_CLIENT_IGNORE, BTA_HF_CLIENT_INIT_ST},
/* SCO_OPEN_EVT */ {BTA_HF_CLIENT_IGNORE, BTA_HF_CLIENT_IGNORE, BTA_HF_CLIENT_INIT_ST},
/* SCO_CLOSE_EVT */ {BTA_HF_CLIENT_IGNORE, BTA_HF_CLIENT_IGNORE, BTA_HF_CLIENT_INIT_ST},
/* SEND_AT_CMD_EVT */ {BTA_HF_CLIENT_IGNORE, BTA_HF_CLIENT_IGNORE, BTA_HF_CLIENT_INIT_ST},
#if (BTM_SCO_HCI_INCLUDED == TRUE )
/* CI_SCO_DATA_EVT */ {BTA_HF_CLIENT_IGNORE, BTA_HF_CLIENT_IGNORE, BTA_HF_CLIENT_INIT_ST},
#endif /* (BTM_SCO_HCI_INCLUDED == TRUE ) */
};
/* state table for opening state */
const UINT8 bta_hf_client_st_opening[][BTA_HF_CLIENT_NUM_COLS] = {
/* Event Action 1 Action 2 Next state */
/* API_REGISTER_EVT */ {BTA_HF_CLIENT_IGNORE, BTA_HF_CLIENT_IGNORE, BTA_HF_CLIENT_OPENING_ST},
/* API_DEREGISTER_EVT */ {BTA_HF_CLIENT_RFC_DO_CLOSE, BTA_HF_CLIENT_START_DEREG, BTA_HF_CLIENT_CLOSING_ST},
/* API_OPEN_EVT */ {BTA_HF_CLIENT_OPEN_FAIL, BTA_HF_CLIENT_IGNORE, BTA_HF_CLIENT_OPENING_ST},
/* API_CLOSE_EVT */ {BTA_HF_CLIENT_RFC_DO_CLOSE, BTA_HF_CLIENT_IGNORE, BTA_HF_CLIENT_CLOSING_ST},
/* API_AUDIO_OPEN_EVT */ {BTA_HF_CLIENT_IGNORE, BTA_HF_CLIENT_IGNORE, BTA_HF_CLIENT_OPENING_ST},
/* API_AUDIO_CLOSE_EVT */ {BTA_HF_CLIENT_IGNORE, BTA_HF_CLIENT_IGNORE, BTA_HF_CLIENT_OPENING_ST},
/* RFC_OPEN_EVT */ {BTA_HF_CLIENT_RFC_OPEN, BTA_HF_CLIENT_SCO_LISTEN, BTA_HF_CLIENT_OPEN_ST},
/* RFC_CLOSE_EVT */ {BTA_HF_CLIENT_RFC_FAIL, BTA_HF_CLIENT_IGNORE, BTA_HF_CLIENT_INIT_ST},
/* RFC_SRV_CLOSE_EVT */ {BTA_HF_CLIENT_IGNORE, BTA_HF_CLIENT_IGNORE, BTA_HF_CLIENT_OPENING_ST},
/* RFC_DATA_EVT */ {BTA_HF_CLIENT_IGNORE, BTA_HF_CLIENT_IGNORE, BTA_HF_CLIENT_OPENING_ST},
/* DISC_ACP_RES_EVT */ {BTA_HF_CLIENT_IGNORE, BTA_HF_CLIENT_IGNORE, BTA_HF_CLIENT_OPENING_ST},
/* DISC_INT_RES_EVT */ {BTA_HF_CLIENT_DISC_INT_RES, BTA_HF_CLIENT_IGNORE, BTA_HF_CLIENT_OPENING_ST},
/* DISC_OK_EVT */ {BTA_HF_CLIENT_RFC_DO_OPEN, BTA_HF_CLIENT_IGNORE, BTA_HF_CLIENT_OPENING_ST},
/* DISC_FAIL_EVT */ {BTA_HF_CLIENT_DISC_FAIL, BTA_HF_CLIENT_IGNORE, BTA_HF_CLIENT_INIT_ST},
/* SCO_OPEN_EVT */ {BTA_HF_CLIENT_IGNORE, BTA_HF_CLIENT_IGNORE, BTA_HF_CLIENT_OPENING_ST},
/* SCO_CLOSE_EVT */ {BTA_HF_CLIENT_IGNORE, BTA_HF_CLIENT_IGNORE, BTA_HF_CLIENT_OPENING_ST},
/* SEND_AT_CMD_EVT */ {BTA_HF_CLIENT_IGNORE, BTA_HF_CLIENT_IGNORE, BTA_HF_CLIENT_OPENING_ST},
#if (BTM_SCO_HCI_INCLUDED == TRUE )
/* CI_SCO_DATA_EVT */ {BTA_HF_CLIENT_IGNORE, BTA_HF_CLIENT_IGNORE, BTA_HF_CLIENT_OPENING_ST},
#endif /* (BTM_SCO_HCI_INCLUDED == TRUE ) */
};
/* state table for open state */
const UINT8 bta_hf_client_st_open[][BTA_HF_CLIENT_NUM_COLS] = {
/* Event Action 1 Action 2 Next state */
/* API_REGISTER_EVT */ {BTA_HF_CLIENT_IGNORE, BTA_HF_CLIENT_IGNORE, BTA_HF_CLIENT_OPEN_ST},
/* API_DEREGISTER_EVT */ {BTA_HF_CLIENT_START_CLOSE, BTA_HF_CLIENT_START_DEREG, BTA_HF_CLIENT_CLOSING_ST},
/* API_OPEN_EVT */ {BTA_HF_CLIENT_OPEN_FAIL, BTA_HF_CLIENT_IGNORE, BTA_HF_CLIENT_OPEN_ST},
/* API_CLOSE_EVT */ {BTA_HF_CLIENT_START_CLOSE, BTA_HF_CLIENT_IGNORE, BTA_HF_CLIENT_CLOSING_ST},
/* API_AUDIO_OPEN_EVT */ {BTA_HF_CLIENT_SCO_OPEN, BTA_HF_CLIENT_IGNORE, BTA_HF_CLIENT_OPEN_ST},
/* API_AUDIO_CLOSE_EVT */ {BTA_HF_CLIENT_SCO_CLOSE, BTA_HF_CLIENT_IGNORE, BTA_HF_CLIENT_OPEN_ST},
/* RFC_OPEN_EVT */ {BTA_HF_CLIENT_IGNORE, BTA_HF_CLIENT_IGNORE, BTA_HF_CLIENT_OPEN_ST},
/* RFC_CLOSE_EVT */ {BTA_HF_CLIENT_RFC_CLOSE, BTA_HF_CLIENT_IGNORE, BTA_HF_CLIENT_INIT_ST},
/* RFC_SRV_CLOSE_EVT */ {BTA_HF_CLIENT_IGNORE, BTA_HF_CLIENT_IGNORE, BTA_HF_CLIENT_OPEN_ST},
/* RFC_DATA_EVT */ {BTA_HF_CLIENT_RFC_DATA, BTA_HF_CLIENT_IGNORE, BTA_HF_CLIENT_OPEN_ST},
/* DISC_ACP_RES_EVT */ {BTA_HF_CLIENT_DISC_ACP_RES, BTA_HF_CLIENT_IGNORE, BTA_HF_CLIENT_OPEN_ST},
/* DISC_INT_RES_EVT */ {BTA_HF_CLIENT_IGNORE, BTA_HF_CLIENT_IGNORE, BTA_HF_CLIENT_OPEN_ST},
/* DISC_OK_EVT */ {BTA_HF_CLIENT_IGNORE, BTA_HF_CLIENT_IGNORE, BTA_HF_CLIENT_OPEN_ST},
/* DISC_FAIL_EVT */ {BTA_HF_CLIENT_IGNORE, BTA_HF_CLIENT_IGNORE, BTA_HF_CLIENT_OPEN_ST},
/* SCO_OPEN_EVT */ {BTA_HF_CLIENT_SCO_CONN_OPEN, BTA_HF_CLIENT_IGNORE, BTA_HF_CLIENT_OPEN_ST},
/* SCO_CLOSE_EVT */ {BTA_HF_CLIENT_SCO_CONN_CLOSE, BTA_HF_CLIENT_IGNORE, BTA_HF_CLIENT_OPEN_ST},
/* SEND_AT_CMD_EVT */ {BTA_HF_CLIENT_SEND_AT_CMD, BTA_HF_CLIENT_IGNORE, BTA_HF_CLIENT_OPEN_ST},
#if (BTM_SCO_HCI_INCLUDED == TRUE )
/* CI_SCO_DATA_EVT */ {BTA_HF_CLIENT_CI_SCO_DATA, BTA_HF_CLIENT_IGNORE, BTA_HF_CLIENT_OPEN_ST},
#endif /* (BTM_SCO_HCI_INCLUDED == TRUE ) */
};
/* state table for closing state */
const UINT8 bta_hf_client_st_closing[][BTA_HF_CLIENT_NUM_COLS] = {
/* Event Action 1 Action 2 Next state */
/* API_REGISTER_EVT */ {BTA_HF_CLIENT_IGNORE, BTA_HF_CLIENT_IGNORE, BTA_HF_CLIENT_CLOSING_ST},
/* API_DEREGISTER_EVT */ {BTA_HF_CLIENT_START_DEREG, BTA_HF_CLIENT_IGNORE, BTA_HF_CLIENT_CLOSING_ST},
/* API_OPEN_EVT */ {BTA_HF_CLIENT_OPEN_FAIL, BTA_HF_CLIENT_IGNORE, BTA_HF_CLIENT_CLOSING_ST},
/* API_CLOSE_EVT */ {BTA_HF_CLIENT_IGNORE, BTA_HF_CLIENT_IGNORE, BTA_HF_CLIENT_CLOSING_ST},
/* API_AUDIO_OPEN_EVT */ {BTA_HF_CLIENT_IGNORE, BTA_HF_CLIENT_IGNORE, BTA_HF_CLIENT_CLOSING_ST},
/* API_AUDIO_CLOSE_EVT */ {BTA_HF_CLIENT_IGNORE, BTA_HF_CLIENT_IGNORE, BTA_HF_CLIENT_CLOSING_ST},
/* RFC_OPEN_EVT */ {BTA_HF_CLIENT_IGNORE, BTA_HF_CLIENT_IGNORE, BTA_HF_CLIENT_CLOSING_ST},
/* RFC_CLOSE_EVT */ {BTA_HF_CLIENT_RFC_CLOSE, BTA_HF_CLIENT_IGNORE, BTA_HF_CLIENT_INIT_ST},
/* RFC_SRV_CLOSE_EVT */ {BTA_HF_CLIENT_IGNORE, BTA_HF_CLIENT_IGNORE, BTA_HF_CLIENT_CLOSING_ST},
/* RFC_DATA_EVT */ {BTA_HF_CLIENT_IGNORE, BTA_HF_CLIENT_IGNORE, BTA_HF_CLIENT_CLOSING_ST},
/* DISC_ACP_RES_EVT */ {BTA_HF_CLIENT_FREE_DB, BTA_HF_CLIENT_IGNORE, BTA_HF_CLIENT_CLOSING_ST},
/* DISC_INT_RES_EVT */ {BTA_HF_CLIENT_FREE_DB, BTA_HF_CLIENT_IGNORE, BTA_HF_CLIENT_INIT_ST},
/* DISC_OK_EVT */ {BTA_HF_CLIENT_IGNORE, BTA_HF_CLIENT_IGNORE, BTA_HF_CLIENT_CLOSING_ST},
/* DISC_FAIL_EVT */ {BTA_HF_CLIENT_IGNORE, BTA_HF_CLIENT_IGNORE, BTA_HF_CLIENT_CLOSING_ST},
/* SCO_OPEN_EVT */ {BTA_HF_CLIENT_IGNORE, BTA_HF_CLIENT_IGNORE, BTA_HF_CLIENT_CLOSING_ST},
/* SCO_CLOSE_EVT */ {BTA_HF_CLIENT_IGNORE, BTA_HF_CLIENT_IGNORE, BTA_HF_CLIENT_CLOSING_ST},
/* SEND_AT_CMD_EVT */ {BTA_HF_CLIENT_IGNORE, BTA_HF_CLIENT_IGNORE, BTA_HF_CLIENT_CLOSING_ST},
#if (BTM_SCO_HCI_INCLUDED == TRUE )
/* CI_SCO_DATA_EVT */ {BTA_HF_CLIENT_IGNORE, BTA_HF_CLIENT_IGNORE, BTA_HF_CLIENT_CLOSING_ST},
#endif /* (BTM_SCO_HCI_INCLUDED == TRUE ) */
};
/* type for state table */
typedef const UINT8 (*tBTA_HF_CLIENT_ST_TBL)[BTA_HF_CLIENT_NUM_COLS];
/* state table */
const tBTA_HF_CLIENT_ST_TBL bta_hf_client_st_tbl[] = {
bta_hf_client_st_init,
bta_hf_client_st_opening,
bta_hf_client_st_open,
bta_hf_client_st_closing
};
/* HF Client control block */
#if BTA_DYNAMIC_MEMORY == FALSE
tBTA_HF_CLIENT_CB bta_hf_client_cb;
#else
tBTA_HF_CLIENT_CB *bta_hf_client_cb_ptr;
#endif
/*******************************************************************************
**
** Function bta_hf_client_scb_init
**
** Description Initialize an HF_Client service control block.
**
**
** Returns void
**
*******************************************************************************/
void bta_hf_client_scb_init(void)
{
APPL_TRACE_DEBUG("%s", __FUNCTION__);
memset(&bta_hf_client_cb.scb, 0, sizeof(tBTA_HF_CLIENT_SCB));
bta_hf_client_cb.scb.sco_idx = BTM_INVALID_SCO_INDEX;
bta_hf_client_cb.scb.negotiated_codec = BTM_SCO_CODEC_CVSD;
}
/*******************************************************************************
**
** Function bta_hf_client_scb_disable
**
** Description Disable a service control block.
**
**
** Returns void
**
*******************************************************************************/
void bta_hf_client_scb_disable(void)
{
APPL_TRACE_DEBUG("%s", __FUNCTION__);
bta_hf_client_scb_init();
(*bta_hf_client_cb.p_cback)(BTA_HF_CLIENT_DISABLE_EVT, NULL);
}
/*******************************************************************************
**
** Function bta_hf_client_resume_open
**
** Description Resume opening process.
**
**
** Returns void
**
*******************************************************************************/
void bta_hf_client_resume_open (void)
{
APPL_TRACE_DEBUG ("%s", __FUNCTION__);
/* resume opening process. */
if (bta_hf_client_cb.scb.state == BTA_HF_CLIENT_INIT_ST) {
bta_hf_client_cb.scb.state = BTA_HF_CLIENT_OPENING_ST;
bta_hf_client_start_open (NULL);
}
}
/*******************************************************************************
**
** Function bta_hf_client_colli_timer_cback
**
** Description HF Client connection collision timer callback
**
**
** Returns void
**
*******************************************************************************/
static void bta_hf_client_colli_timer_cback (TIMER_LIST_ENT *p_tle)
{
APPL_TRACE_DEBUG("%s", __FUNCTION__);
if (p_tle) {
bta_hf_client_cb.scb.colli_tmr_on = FALSE;
/* If the peer haven't opened connection, restart opening process */
bta_hf_client_resume_open ();
}
}
/*******************************************************************************
**
** Function bta_hf_client_collision_cback
**
** Description Get notified about collision.
**
**
** Returns void
**
*******************************************************************************/
void bta_hf_client_collision_cback (tBTA_SYS_CONN_STATUS status, UINT8 id,
UINT8 app_id, BD_ADDR peer_addr)
{
UNUSED(status);
UNUSED(app_id);
UNUSED(peer_addr);
if (bta_hf_client_cb.scb.state == BTA_HF_CLIENT_OPENING_ST) {
if (id == BTA_ID_SYS) { /* ACL collision */
APPL_TRACE_WARNING ("HF Client found collision (ACL) ...");
} else if (id == BTA_ID_HS) { /* RFCOMM collision */
APPL_TRACE_WARNING ("HF Client found collision (RFCOMM) ...");
} else {
APPL_TRACE_WARNING ("HF Client found collision (\?\?\?) ...");
}
bta_hf_client_cb.scb.state = BTA_HF_CLIENT_INIT_ST;
/* Cancel SDP if it had been started. */
if (bta_hf_client_cb.scb.p_disc_db) {
(void)SDP_CancelServiceSearch (bta_hf_client_cb.scb.p_disc_db);
bta_hf_client_free_db(NULL);
}
/* reopen registered server */
/* Collision may be detected before or after we close servers. */
bta_hf_client_start_server();
/* Start timer to handle connection opening restart */
bta_hf_client_cb.scb.colli_timer.p_cback = (TIMER_CBACK *)&bta_hf_client_colli_timer_cback;
bta_sys_start_timer(&bta_hf_client_cb.scb.colli_timer, 0, BTA_HF_CLIENT_COLLISION_TIMER);
bta_hf_client_cb.scb.colli_tmr_on = TRUE;
}
}
/*******************************************************************************
**
** Function bta_hf_client_api_enable
**
** Description Handle an API enable event.
**
**
** Returns void
**
*******************************************************************************/
static void bta_hf_client_api_enable(tBTA_HF_CLIENT_DATA *p_data)
{
/* initialize control block */
memset(&bta_hf_client_cb, 0, sizeof(tBTA_HF_CLIENT_CB));
/* store callback function */
bta_hf_client_cb.p_cback = p_data->api_enable.p_cback;
/* check if mSBC support enabled */
#if 0 // todo
char value[PROPERTY_VALUE_MAX];
property_get("ro.bluetooth.hfp.ver", value, "0");
if (strcmp(value, "1.6") == 0) {
bta_hf_client_cb.msbc_enabled = TRUE;
}
#else
bta_hf_client_cb.msbc_enabled = FALSE;
#endif
bta_hf_client_cb.scb.negotiated_codec = BTM_SCO_CODEC_CVSD;
/* set same setting as AG does */
BTM_WriteVoiceSettings(AG_VOICE_SETTINGS);
bta_sys_collision_register (BTA_ID_HS, bta_hf_client_collision_cback);
/* call callback with enable event */
(*bta_hf_client_cb.p_cback)(BTA_HF_CLIENT_ENABLE_EVT, NULL);
}
/*******************************************************************************
**
** Function bta_hf_client_api_disable
**
** Description Handle an API disable event.
**
**
** Returns void
**
*******************************************************************************/
static void bta_hf_client_api_disable(tBTA_HF_CLIENT_DATA *p_data)
{
if (!bta_sys_is_register (BTA_ID_HS)) {
APPL_TRACE_ERROR("BTA HF Client is already disabled, ignoring ...");
return;
}
/* De-register with BTA system manager */
bta_sys_deregister(BTA_ID_HS);
bta_hf_client_sm_execute(BTA_HF_CLIENT_API_DEREGISTER_EVT, p_data);
bta_sys_collision_register (BTA_ID_HS, NULL);
}
/*******************************************************************************
**
** Function bta_hf_client_hdl_event
**
** Description Data HF Client main event handling function.
**
**
** Returns BOOLEAN
**
*******************************************************************************/
BOOLEAN bta_hf_client_hdl_event(BT_HDR *p_msg)
{
#if BTA_HF_CLIENT_DEBUG == TRUE
APPL_TRACE_DEBUG("bta_hf_client_hdl_event %s (0x%x)", bta_hf_client_evt_str(p_msg->event), p_msg->event);
#endif
switch (p_msg->event) {
/* handle enable event */
case BTA_HF_CLIENT_API_ENABLE_EVT:
bta_hf_client_api_enable((tBTA_HF_CLIENT_DATA *) p_msg);
break;
/* handle disable event */
case BTA_HF_CLIENT_API_DISABLE_EVT:
bta_hf_client_api_disable((tBTA_HF_CLIENT_DATA *) p_msg);
break;
default:
bta_hf_client_sm_execute(p_msg->event, (tBTA_HF_CLIENT_DATA *) p_msg);
break;
}
return TRUE;
}
/*******************************************************************************
**
** Function bta_hf_client_sm_execute
**
** Description State machine event handling function for HF Client
**
**
** Returns void
**
*******************************************************************************/
void bta_hf_client_sm_execute(UINT16 event, tBTA_HF_CLIENT_DATA *p_data)
{
tBTA_HF_CLIENT_ST_TBL state_table;
UINT8 action;
int i;
#if BTA_HF_CLIENT_DEBUG == TRUE
UINT16 in_event = event;
UINT8 in_state = bta_hf_client_cb.scb.state;
/* Ignore displaying of AT results when not connected (Ignored in state machine) */
if (bta_hf_client_cb.scb.state == BTA_HF_CLIENT_OPEN_ST) {
APPL_TRACE_EVENT("HF Client evt : State %d (%s), Event 0x%04x (%s)",
bta_hf_client_cb.scb.state,
bta_hf_client_state_str(bta_hf_client_cb.scb.state),
event, bta_hf_client_evt_str(event));
}
#endif
event &= 0x00FF;
if (event >= (BTA_HF_CLIENT_MAX_EVT & 0x00FF)) {
APPL_TRACE_ERROR("HF Client evt out of range, ignoring...");
return;
}
/* look up the state table for the current state */
state_table = bta_hf_client_st_tbl[bta_hf_client_cb.scb.state];
/* set next state */
bta_hf_client_cb.scb.state = state_table[event][BTA_HF_CLIENT_NEXT_STATE];
/* execute action functions */
for (i = 0; i < BTA_HF_CLIENT_ACTIONS; i++) {
if ((action = state_table[event][i]) != BTA_HF_CLIENT_IGNORE) {
(*bta_hf_client_action[action])(p_data);
} else {
break;
}
}
#if BTA_HF_CLIENT_DEBUG == TRUE
if (bta_hf_client_cb.scb.state != in_state) {
APPL_TRACE_EVENT("BTA HF Client State Change: [%s] -> [%s] after Event [%s]",
bta_hf_client_state_str(in_state),
bta_hf_client_state_str(bta_hf_client_cb.scb.state),
bta_hf_client_evt_str(in_event));
}
#endif
}
static void send_post_slc_cmd(void)
{
bta_hf_client_cb.scb.at_cb.current_cmd = BTA_HF_CLIENT_AT_NONE;
bta_hf_client_send_at_bia();
bta_hf_client_send_at_ccwa(TRUE);
bta_hf_client_send_at_cmee(TRUE);
bta_hf_client_send_at_cops(FALSE);
bta_hf_client_send_at_btrh(TRUE, 0);
bta_hf_client_send_at_clip(TRUE);
}
/*******************************************************************************
**
** Function bta_hf_client_slc_seq
**
** Description Handles AT commands sequence required for SLC creation
**
**
** Returns void
**
*******************************************************************************/
void bta_hf_client_slc_seq(BOOLEAN error)
{
APPL_TRACE_DEBUG("bta_hf_client_slc_seq cmd: %u", bta_hf_client_cb.scb.at_cb.current_cmd);
if (error) {
/* SLC establishment error, sent close rfcomm event */
APPL_TRACE_ERROR("HFPClient: Failed to create SLC due to AT error, disconnecting (%u)",
bta_hf_client_cb.scb.at_cb.current_cmd);
bta_hf_client_sm_execute(BTA_HF_CLIENT_API_CLOSE_EVT, NULL);
return;
}
if (bta_hf_client_cb.scb.svc_conn) {
return;
}
switch (bta_hf_client_cb.scb.at_cb.current_cmd) {
case BTA_HF_CLIENT_AT_NONE:
bta_hf_client_send_at_brsf();
break;
case BTA_HF_CLIENT_AT_BRSF:
if (bta_hf_client_cb.scb.peer_features & BTA_HF_CLIENT_PEER_CODEC) {
bta_hf_client_send_at_bac();
break;
}
bta_hf_client_send_at_cind(FALSE);
break;
case BTA_HF_CLIENT_AT_BAC:
bta_hf_client_send_at_cind(FALSE);
break;
case BTA_HF_CLIENT_AT_CIND:
bta_hf_client_send_at_cind(TRUE);
break;
case BTA_HF_CLIENT_AT_CIND_STATUS:
bta_hf_client_send_at_cmer(TRUE);
break;
case BTA_HF_CLIENT_AT_CMER:
if (bta_hf_client_cb.scb.peer_features & BTA_HF_CLIENT_PEER_FEAT_3WAY) {
bta_hf_client_send_at_chld('?', 0);
} else {
bta_hf_client_svc_conn_open(NULL);
send_post_slc_cmd();
}
break;
case BTA_HF_CLIENT_AT_CHLD:
bta_hf_client_svc_conn_open(NULL);
send_post_slc_cmd();
break;
default:
/* If happen there is a bug in SLC creation procedure... */
APPL_TRACE_ERROR("HFPClient: Failed to create SLCdue to unexpected AT command, disconnecting (%u)",
bta_hf_client_cb.scb.at_cb.current_cmd);
bta_hf_client_sm_execute(BTA_HF_CLIENT_API_CLOSE_EVT, NULL);
break;
}
}
#if BTA_HF_CLIENT_DEBUG == TRUE
#ifndef CASE_RETURN_STR
#define CASE_RETURN_STR(const) case const: return #const;
#endif
static char *bta_hf_client_evt_str(UINT16 event)
{
switch (event) {
CASE_RETURN_STR(BTA_HF_CLIENT_API_REGISTER_EVT)
CASE_RETURN_STR(BTA_HF_CLIENT_API_DEREGISTER_EVT)
CASE_RETURN_STR(BTA_HF_CLIENT_API_OPEN_EVT)
CASE_RETURN_STR(BTA_HF_CLIENT_API_CLOSE_EVT)
CASE_RETURN_STR(BTA_HF_CLIENT_API_AUDIO_OPEN_EVT)
CASE_RETURN_STR(BTA_HF_CLIENT_API_AUDIO_CLOSE_EVT)
CASE_RETURN_STR(BTA_HF_CLIENT_RFC_OPEN_EVT)
CASE_RETURN_STR(BTA_HF_CLIENT_RFC_CLOSE_EVT)
CASE_RETURN_STR(BTA_HF_CLIENT_RFC_SRV_CLOSE_EVT)
CASE_RETURN_STR(BTA_HF_CLIENT_RFC_DATA_EVT)
CASE_RETURN_STR(BTA_HF_CLIENT_DISC_ACP_RES_EVT)
CASE_RETURN_STR(BTA_HF_CLIENT_DISC_INT_RES_EVT)
CASE_RETURN_STR(BTA_HF_CLIENT_DISC_OK_EVT)
CASE_RETURN_STR(BTA_HF_CLIENT_DISC_FAIL_EVT)
CASE_RETURN_STR(BTA_HF_CLIENT_API_ENABLE_EVT)
CASE_RETURN_STR(BTA_HF_CLIENT_API_DISABLE_EVT)
CASE_RETURN_STR(BTA_HF_CLIENT_SCO_OPEN_EVT)
CASE_RETURN_STR(BTA_HF_CLIENT_SCO_CLOSE_EVT)
CASE_RETURN_STR(BTA_HF_CLIENT_SEND_AT_CMD_EVT)
default:
return "Unknown HF Client Event";
}
}
static char *bta_hf_client_state_str(UINT8 state)
{
switch (state) {
CASE_RETURN_STR(BTA_HF_CLIENT_INIT_ST)
CASE_RETURN_STR(BTA_HF_CLIENT_OPENING_ST)
CASE_RETURN_STR(BTA_HF_CLIENT_OPEN_ST)
CASE_RETURN_STR(BTA_HF_CLIENT_CLOSING_ST)
default:
return "Unknown HF Client State";
}
}
#endif
#endif /* #if (BTA_HF_INCLUDED == TRUE) */

View file

@ -0,0 +1,246 @@
/******************************************************************************
*
* Copyright (c) 2014 The Android Open Source Project
* Copyright (C) 2004-2012 Broadcom Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at:
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
******************************************************************************/
/******************************************************************************
*
* This file contains the audio gateway functions controlling the RFCOMM
* connections.
*
******************************************************************************/
#include <string.h>
#include "common/bt_defs.h"
#include "bta/bta_api.h"
#include "bta_hf_client_int.h"
#include "stack/port_api.h"
#include "osi/allocator.h"
#if (BTA_HF_INCLUDED == TRUE)
/*******************************************************************************
**
** Function bta_hf_client_port_cback
**
** Description RFCOMM Port callback
**
**
** Returns void
**
*******************************************************************************/
static void bta_hf_client_port_cback(UINT32 code, UINT16 port_handle)
{
BT_HDR *p_buf;
UNUSED(code);
/* ignore port events for port handles other than connected handle */
if (port_handle != bta_hf_client_cb.scb.conn_handle) {
APPL_TRACE_DEBUG("bta_hf_client_port_cback ignoring handle:%d conn_handle = %d",
port_handle, bta_hf_client_cb.scb.conn_handle);
return;
}
if ((p_buf = (BT_HDR *) osi_malloc(sizeof(BT_HDR))) != NULL) {
p_buf->event = BTA_HF_CLIENT_RFC_DATA_EVT;
bta_sys_sendmsg(p_buf);
}
}
/*******************************************************************************
**
** Function bta_hf_client_mgmt_cback
**
** Description RFCOMM management callback
**
**
** Returns void
**
*******************************************************************************/
static void bta_hf_client_mgmt_cback(UINT32 code, UINT16 port_handle)
{
tBTA_HF_CLIENT_RFC *p_buf;
UINT16 event;
APPL_TRACE_DEBUG("bta_hf_client_mgmt_cback : code = %d, port_handle = %d, conn_handle = %d, serv_handle = %d",
code, port_handle, bta_hf_client_cb.scb.conn_handle, bta_hf_client_cb.scb.serv_handle);
/* ignore close event for port handles other than connected handle */
if ((code != PORT_SUCCESS) && (port_handle != bta_hf_client_cb.scb.conn_handle)) {
APPL_TRACE_DEBUG("bta_hf_client_mgmt_cback ignoring handle:%d", port_handle);
return;
}
if (code == PORT_SUCCESS) {
if ((bta_hf_client_cb.scb.conn_handle && (port_handle == bta_hf_client_cb.scb.conn_handle)) || /* outgoing connection */
(port_handle == bta_hf_client_cb.scb.serv_handle)) { /* incoming connection */
event = BTA_HF_CLIENT_RFC_OPEN_EVT;
} else {
APPL_TRACE_ERROR ("bta_hf_client_mgmt_cback: PORT_SUCCESS, ignoring handle = %d", port_handle);
return;
}
}
/* distinguish server close events */
else if (port_handle == bta_hf_client_cb.scb.conn_handle) {
event = BTA_HF_CLIENT_RFC_CLOSE_EVT;
} else {
event = BTA_HF_CLIENT_RFC_SRV_CLOSE_EVT;
}
if ((p_buf = (tBTA_HF_CLIENT_RFC *) osi_malloc(sizeof(tBTA_HF_CLIENT_RFC))) != NULL) {
p_buf->hdr.event = event;
p_buf->port_handle = port_handle;
bta_sys_sendmsg(p_buf);
}
}
/*******************************************************************************
**
** Function bta_hf_client_setup_port
**
** Description Setup RFCOMM port for use by HF Client.
**
**
** Returns void
**
*******************************************************************************/
void bta_hf_client_setup_port(UINT16 handle)
{
PORT_SetEventMask(handle, PORT_EV_RXCHAR);
PORT_SetEventCallback(handle, bta_hf_client_port_cback);
}
/*******************************************************************************
**
** Function bta_hf_client_start_server
**
** Description Setup RFCOMM server for use by HF Client.
**
**
** Returns void
**
*******************************************************************************/
void bta_hf_client_start_server(void)
{
int port_status;
if (bta_hf_client_cb.scb.serv_handle > 0) {
APPL_TRACE_DEBUG("%s already started, handle: %d", __FUNCTION__, bta_hf_client_cb.scb.serv_handle);
return;
}
BTM_SetSecurityLevel(FALSE, "", BTM_SEC_SERVICE_HF_HANDSFREE, bta_hf_client_cb.scb.serv_sec_mask,
BT_PSM_RFCOMM, BTM_SEC_PROTO_RFCOMM, bta_hf_client_cb.scn);
port_status = RFCOMM_CreateConnection(UUID_SERVCLASS_HF_HANDSFREE, bta_hf_client_cb.scn,
TRUE, BTA_HF_CLIENT_MTU, (UINT8 *) bd_addr_any, &(bta_hf_client_cb.scb.serv_handle),
bta_hf_client_mgmt_cback);
if (port_status == PORT_SUCCESS) {
bta_hf_client_setup_port(bta_hf_client_cb.scb.serv_handle);
} else {
/* TODO: can we handle this better? */
APPL_TRACE_DEBUG("bta_hf_client_start_server: RFCOMM_CreateConnection returned error:%d", port_status);
}
APPL_TRACE_DEBUG("bta_hf_client_start_server handle: %d", bta_hf_client_cb.scb.serv_handle);
}
/*******************************************************************************
**
** Function bta_hf_client_close_server
**
** Description Close RFCOMM server port for use by HF Client.
**
**
** Returns void
**
*******************************************************************************/
void bta_hf_client_close_server(void)
{
APPL_TRACE_DEBUG("%s %d", __FUNCTION__, bta_hf_client_cb.scb.serv_handle);
if (bta_hf_client_cb.scb.serv_handle == 0) {
APPL_TRACE_DEBUG("%s already stopped", __FUNCTION__);
return;
}
RFCOMM_RemoveServer(bta_hf_client_cb.scb.serv_handle);
bta_hf_client_cb.scb.serv_handle = 0;
}
/*******************************************************************************
**
** Function bta_hf_client_rfc_do_open
**
** Description Open an RFCOMM connection to the peer device.
**
**
** Returns void
**
*******************************************************************************/
void bta_hf_client_rfc_do_open(tBTA_HF_CLIENT_DATA *p_data)
{
BTM_SetSecurityLevel(TRUE, "", BTM_SEC_SERVICE_HF_HANDSFREE,
bta_hf_client_cb.scb.cli_sec_mask, BT_PSM_RFCOMM,
BTM_SEC_PROTO_RFCOMM, bta_hf_client_cb.scb.peer_scn);
if (RFCOMM_CreateConnection(UUID_SERVCLASS_HF_HANDSFREE, bta_hf_client_cb.scb.peer_scn,
FALSE, BTA_HF_CLIENT_MTU, bta_hf_client_cb.scb.peer_addr, &(bta_hf_client_cb.scb.conn_handle),
bta_hf_client_mgmt_cback) == PORT_SUCCESS) {
bta_hf_client_setup_port(bta_hf_client_cb.scb.conn_handle);
APPL_TRACE_DEBUG("bta_hf_client_rfc_do_open : conn_handle = %d", bta_hf_client_cb.scb.conn_handle);
}
/* RFCOMM create connection failed; send ourselves RFCOMM close event */
else {
bta_hf_client_sm_execute(BTA_HF_CLIENT_RFC_CLOSE_EVT, p_data);
}
}
/*******************************************************************************
**
** Function bta_hf_client_rfc_do_close
**
** Description Close RFCOMM connection.
**
**
** Returns void
**
*******************************************************************************/
void bta_hf_client_rfc_do_close(tBTA_HF_CLIENT_DATA *p_data)
{
tBTA_HF_CLIENT_RFC *p_buf;
UNUSED(p_data);
if (bta_hf_client_cb.scb.conn_handle) {
RFCOMM_RemoveConnection(bta_hf_client_cb.scb.conn_handle);
} else {
/* Close API was called while HF Client is in Opening state. */
/* Need to trigger the state machine to send callback to the app */
/* and move back to INIT state. */
if ((p_buf = (tBTA_HF_CLIENT_RFC *) osi_malloc(sizeof(tBTA_HF_CLIENT_RFC))) != NULL) {
p_buf->hdr.event = BTA_HF_CLIENT_RFC_CLOSE_EVT;
bta_sys_sendmsg(p_buf);
}
/* Cancel SDP if it had been started. */
if (bta_hf_client_cb.scb.p_disc_db) {
(void)SDP_CancelServiceSearch (bta_hf_client_cb.scb.p_disc_db);
bta_hf_client_free_db(NULL);
}
}
}
#endif /* #if (BTA_HF_INCLUDED == TRUE) */

View file

@ -0,0 +1,825 @@
/******************************************************************************
*
* Copyright (c) 2014 The Android Open Source Project
* Copyright (C) 2004-2012 Broadcom Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at:
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
******************************************************************************/
#include "bta_hf_client_int.h"
#include "common/bt_trace.h"
#include <string.h>
#include "common/bt_defs.h"
#include "common/bt_target.h"
#include "osi/allocator.h"
#if (BTM_SCO_HCI_INCLUDED == TRUE )
#include "bta/bta_hf_client_co.h"
#include "hci/hci_audio.h"
#endif
#if (BTA_HF_INCLUDED == TRUE)
#define BTA_HF_CLIENT_NO_EDR_ESCO (BTM_SCO_PKT_TYPES_MASK_NO_2_EV3 | \
BTM_SCO_PKT_TYPES_MASK_NO_3_EV3 | \
BTM_SCO_PKT_TYPES_MASK_NO_2_EV5 | \
BTM_SCO_PKT_TYPES_MASK_NO_3_EV5)
static const tBTM_ESCO_PARAMS bta_hf_client_esco_params[] = {
/* SCO CVSD */
{
.rx_bw = BTM_64KBITS_RATE,
.tx_bw = BTM_64KBITS_RATE,
.max_latency = 10,
.voice_contfmt = BTM_VOICE_SETTING_CVSD,
.packet_types = (BTM_SCO_LINK_ONLY_MASK |
BTM_SCO_PKT_TYPES_MASK_NO_2_EV3 |
BTM_SCO_PKT_TYPES_MASK_NO_3_EV3 |
BTM_SCO_PKT_TYPES_MASK_NO_2_EV5 |
BTM_SCO_PKT_TYPES_MASK_NO_3_EV5),
.retrans_effort = BTM_ESCO_RETRANS_POWER,
},
/* ESCO CVSD */
{
.rx_bw = BTM_64KBITS_RATE,
.tx_bw = BTM_64KBITS_RATE,
.max_latency = 10,
.voice_contfmt = BTM_VOICE_SETTING_CVSD,
/* Allow controller to use all types available except 5-slot EDR */
.packet_types = (BTM_SCO_LINK_ALL_PKT_MASK |
BTM_SCO_PKT_TYPES_MASK_NO_2_EV5 |
BTM_SCO_PKT_TYPES_MASK_NO_3_EV5),
.retrans_effort = BTM_ESCO_RETRANS_POWER,
},
/* ESCO mSBC */
{
.rx_bw = BTM_64KBITS_RATE,
.tx_bw = BTM_64KBITS_RATE,
.max_latency = 13,
.voice_contfmt = BTM_VOICE_SETTING_TRANS,
/* Packet Types : EV3 + 2-EV3 */
.packet_types = (BTM_SCO_PKT_TYPES_MASK_EV3 |
BTM_SCO_PKT_TYPES_MASK_NO_3_EV3 |
BTM_SCO_PKT_TYPES_MASK_NO_2_EV5 |
BTM_SCO_PKT_TYPES_MASK_NO_3_EV5),
.retrans_effort = BTM_ESCO_RETRANS_QUALITY,
}
};
enum {
BTA_HF_CLIENT_SCO_LISTEN_E,
BTA_HF_CLIENT_SCO_OPEN_E, /* open request */
BTA_HF_CLIENT_SCO_CLOSE_E, /* close request */
BTA_HF_CLIENT_SCO_SHUTDOWN_E, /* shutdown request */
BTA_HF_CLIENT_SCO_CONN_OPEN_E, /* sco opened */
BTA_HF_CLIENT_SCO_CONN_CLOSE_E, /* sco closed */
#if (BTM_SCO_HCI_INCLUDED == TRUE )
BTA_HF_CLIENT_SCO_CI_DATA_E, /* sco data ready */
#endif /* #if (BTM_SCO_HCI_INCLUDED == TRUE ) */
};
static void bta_hf_client_sco_event(UINT8 event);
/*******************************************************************************
**
** Function bta_hf_client_remove_sco
**
** Description Removes the specified SCO from the system.
** If only_active is TRUE, then SCO is only removed if connected
**
** Returns BOOLEAN - TRUE if Sco removal was started
**
*******************************************************************************/
static BOOLEAN bta_hf_client_sco_remove(BOOLEAN only_active)
{
BOOLEAN removed_started = FALSE;
tBTM_STATUS status;
APPL_TRACE_DEBUG("%s %d", __FUNCTION__, only_active);
if (bta_hf_client_cb.scb.sco_idx != BTM_INVALID_SCO_INDEX) {
status = BTM_RemoveSco(bta_hf_client_cb.scb.sco_idx);
APPL_TRACE_DEBUG("%s idx 0x%04x, status:0x%x", __FUNCTION__, bta_hf_client_cb.scb.sco_idx, status);
if (status == BTM_CMD_STARTED) {
removed_started = TRUE;
}
/* If no connection reset the sco handle */
else if ( (status == BTM_SUCCESS) || (status == BTM_UNKNOWN_ADDR) ) {
bta_hf_client_cb.scb.sco_idx = BTM_INVALID_SCO_INDEX;
}
}
return removed_started;
}
/*******************************************************************************
**
** Function bta_hf_client_cback_sco
**
** Description Call application callback function with SCO event.
**
**
** Returns void
**
*******************************************************************************/
void bta_hf_client_cback_sco(UINT8 event)
{
tBTA_HF_CLIENT_HDR evt;
memset(&evt, 0, sizeof(evt));
/* call app cback */
(*bta_hf_client_cb.p_cback)(event, (tBTA_HF_CLIENT_HDR *) &evt);
}
#if (BTM_SCO_HCI_INCLUDED == TRUE )
/*******************************************************************************
**
** Function bta_hf_client_sco_read_cback
**
** Description Callback function is the callback function for incoming
** SCO data over HCI.
**
** Returns void
**
*******************************************************************************/
static void bta_hf_client_sco_read_cback (UINT16 sco_idx, BT_HDR *p_data, tBTM_SCO_DATA_FLAG status)
{
if (status != BTM_SCO_DATA_CORRECT)
{
APPL_TRACE_DEBUG("%s: status(%d)", __FUNCTION__, status);
}
bta_hf_client_sco_co_in_data (p_data, status);
osi_free(p_data);
}
#endif /* BTM_SCO_HCI_INCLUDED */
/*******************************************************************************
**
** Function bta_hf_client_sco_conn_rsp
**
** Description Process the SCO connection request
**
**
** Returns void
**
*******************************************************************************/
static void bta_hf_client_sco_conn_rsp(tBTM_ESCO_CONN_REQ_EVT_DATA *p_data)
{
tBTM_ESCO_PARAMS resp;
UINT8 hci_status = HCI_SUCCESS;
#if (BTM_SCO_HCI_INCLUDED == TRUE )
tBTA_HFP_CODEC_INFO codec_info = {BTA_HFP_SCO_CODEC_PCM};
UINT32 pcm_sample_rate;
#endif
APPL_TRACE_DEBUG("%s", __FUNCTION__);
if (bta_hf_client_cb.scb.sco_state == BTA_HF_CLIENT_SCO_LISTEN_ST) {
if (p_data->link_type == BTM_LINK_TYPE_SCO) {
resp = bta_hf_client_esco_params[0];
} else {
resp = bta_hf_client_esco_params[bta_hf_client_cb.scb.negotiated_codec];
}
/* tell sys to stop av if any */
bta_sys_sco_use(BTA_ID_HS, 1, bta_hf_client_cb.scb.peer_addr);
#if (BTM_SCO_HCI_INCLUDED == TRUE )
bta_hf_client_co_audio_state(bta_hf_client_cb.scb.sco_idx, SCO_STATE_SETUP, 0);
pcm_sample_rate = BTA_HFP_SCO_SAMP_RATE_8K;
/* initialize SCO setup, no voice setting for AG, data rate <==> sample rate */
BTM_ConfigScoPath(bta_hf_client_sco_co_init(pcm_sample_rate, pcm_sample_rate, &codec_info, 0),
bta_hf_client_sco_read_cback, NULL, TRUE);
#endif
} else {
hci_status = HCI_ERR_HOST_REJECT_DEVICE;
}
BTM_EScoConnRsp(p_data->sco_inx, hci_status, &resp);
}
#if (BTM_SCO_HCI_INCLUDED == TRUE )
/*******************************************************************************
**
** Function bta_ag_ci_sco_data
**
** Description Process the SCO data ready callin event
**
**
** Returns void
**
*******************************************************************************/
void bta_hf_client_ci_sco_data(tBTA_HF_CLIENT_DATA *p_data)
{
UNUSED(p_data);
bta_hf_client_sco_event(BTA_HF_CLIENT_SCO_CI_DATA_E);
}
#endif
/*******************************************************************************
**
** Function bta_hf_client_sco_connreq_cback
**
** Description BTM eSCO connection requests and eSCO change requests
** Only the connection requests are processed by BTA.
**
** Returns void
**
*******************************************************************************/
static void bta_hf_client_esco_connreq_cback(tBTM_ESCO_EVT event, tBTM_ESCO_EVT_DATA *p_data)
{
APPL_TRACE_DEBUG("%s %d", __FUNCTION__, event);
if (event != BTM_ESCO_CONN_REQ_EVT) {
return;
}
/* TODO check remote bdaddr, should allow connect only from device with
* active SLC */
bta_hf_client_cb.scb.sco_idx = p_data->conn_evt.sco_inx;
bta_hf_client_sco_conn_rsp(&p_data->conn_evt);
bta_hf_client_cb.scb.sco_state = BTA_HF_CLIENT_SCO_OPENING_ST;
}
/*******************************************************************************
**
** Function bta_hf_client_sco_conn_cback
**
** Description BTM SCO connection callback.
**
**
** Returns void
**
*******************************************************************************/
static void bta_hf_client_sco_conn_cback(UINT16 sco_idx)
{
BT_HDR *p_buf;
UINT8 *rem_bd;
APPL_TRACE_DEBUG("%s %d", __FUNCTION__, sco_idx);
rem_bd = BTM_ReadScoBdAddr(sco_idx);
if (rem_bd && bdcmp(bta_hf_client_cb.scb.peer_addr, rem_bd) == 0 &&
bta_hf_client_cb.scb.svc_conn && bta_hf_client_cb.scb.sco_idx == sco_idx) {
if ((p_buf = (BT_HDR *) osi_malloc(sizeof(BT_HDR))) != NULL) {
p_buf->event = BTA_HF_CLIENT_SCO_OPEN_EVT;
p_buf->layer_specific = bta_hf_client_cb.scb.conn_handle;
bta_sys_sendmsg(p_buf);
}
}
/* no match found; disconnect sco, init sco variables */
else {
bta_hf_client_cb.scb.sco_state = BTA_HF_CLIENT_SCO_SHUTDOWN_ST;
BTM_RemoveSco(sco_idx);
}
}
/*******************************************************************************
**
** Function bta_hf_client_sco_disc_cback
**
** Description BTM SCO disconnection callback.
**
**
** Returns void
**
*******************************************************************************/
static void bta_hf_client_sco_disc_cback(UINT16 sco_idx)
{
BT_HDR *p_buf;
APPL_TRACE_DEBUG("%s %d", __FUNCTION__, sco_idx);
if (bta_hf_client_cb.scb.sco_idx == sco_idx) {
#if (BTM_SCO_HCI_INCLUDED == TRUE )
tBTM_STATUS status = BTM_ConfigScoPath(BTM_SCO_ROUTE_PCM, NULL, NULL, TRUE);
APPL_TRACE_DEBUG("%s close config status = %d", __FUNCTION__, status);
/* SCO clean up here */
bta_hf_client_sco_co_close();
#endif
if ((p_buf = (BT_HDR *) osi_malloc(sizeof(BT_HDR))) != NULL) {
p_buf->event = BTA_HF_CLIENT_SCO_CLOSE_EVT;
p_buf->layer_specific = bta_hf_client_cb.scb.conn_handle;;
bta_sys_sendmsg(p_buf);
}
}
}
/*******************************************************************************
**
** Function bta_hf_client_create_sco
**
** Description
**
**
** Returns void
**
*******************************************************************************/
static void bta_hf_client_sco_create(BOOLEAN is_orig)
{
tBTM_STATUS status;
UINT8 *p_bd_addr = NULL;
tBTM_ESCO_PARAMS params;
#if (BTM_SCO_HCI_INCLUDED == TRUE )
tBTM_SCO_ROUTE_TYPE sco_route;
tBTA_HFP_CODEC_INFO codec_info = {BTA_HFP_SCO_CODEC_PCM};
UINT32 pcm_sample_rate;
#endif
APPL_TRACE_DEBUG("%s %d", __FUNCTION__, is_orig);
/* Make sure this sco handle is not already in use */
if (bta_hf_client_cb.scb.sco_idx != BTM_INVALID_SCO_INDEX) {
APPL_TRACE_WARNING("%s: Index 0x%04x already in use", __FUNCTION__,
bta_hf_client_cb.scb.sco_idx);
return;
}
params = bta_hf_client_esco_params[1];
/* if initiating set current scb and peer bd addr */
if (is_orig) {
/* Attempt to use eSCO if remote host supports HFP >= 1.5 */
if (bta_hf_client_cb.scb.peer_version >= HFP_VERSION_1_5 && !bta_hf_client_cb.scb.retry_with_sco_only) {
BTM_SetEScoMode(BTM_LINK_TYPE_ESCO, &params);
/* If ESCO or EDR ESCO, retry with SCO only in case of failure */
if ((params.packet_types & BTM_ESCO_LINK_ONLY_MASK)
|| !((params.packet_types & ~(BTM_ESCO_LINK_ONLY_MASK | BTM_SCO_LINK_ONLY_MASK)) ^ BTA_HF_CLIENT_NO_EDR_ESCO)) {
bta_hf_client_cb.scb.retry_with_sco_only = TRUE;
APPL_TRACE_API("Setting retry_with_sco_only to TRUE");
}
} else {
if (bta_hf_client_cb.scb.retry_with_sco_only) {
APPL_TRACE_API("retrying with SCO only");
}
bta_hf_client_cb.scb.retry_with_sco_only = FALSE;
BTM_SetEScoMode(BTM_LINK_TYPE_SCO, &params);
}
/* tell sys to stop av if any */
bta_sys_sco_use(BTA_ID_HS, 1, bta_hf_client_cb.scb.peer_addr);
#if (BTM_SCO_HCI_INCLUDED == TRUE )
/* Allow any platform specific pre-SCO set up to take place */
bta_hf_client_co_audio_state(bta_hf_client_cb.scb.sco_idx, SCO_STATE_SETUP, 0);
pcm_sample_rate = BTA_HFP_SCO_SAMP_RATE_8K;
sco_route = bta_hf_client_sco_co_init(pcm_sample_rate, pcm_sample_rate, &codec_info, 0);
/* initialize SCO setup, no voice setting for AG, data rate <==> sample rate */
BTM_ConfigScoPath(sco_route, bta_hf_client_sco_read_cback, NULL, TRUE);
#endif
} else {
bta_hf_client_cb.scb.retry_with_sco_only = FALSE;
}
p_bd_addr = bta_hf_client_cb.scb.peer_addr;
status = BTM_CreateSco(p_bd_addr, is_orig, params.packet_types,
&bta_hf_client_cb.scb.sco_idx, bta_hf_client_sco_conn_cback,
bta_hf_client_sco_disc_cback);
if (status == BTM_CMD_STARTED && !is_orig) {
if (!BTM_RegForEScoEvts(bta_hf_client_cb.scb.sco_idx, bta_hf_client_esco_connreq_cback)) {
APPL_TRACE_DEBUG("%s SCO registration success", __FUNCTION__);
}
}
APPL_TRACE_API("%s: orig %d, inx 0x%04x, status 0x%x, pkt types 0x%04x",
__FUNCTION__, is_orig, bta_hf_client_cb.scb.sco_idx,
status, params.packet_types);
}
/*******************************************************************************
**
** Function bta_hf_client_sco_event
**
** Description Handle SCO events
**
**
** Returns void
**
*******************************************************************************/
static void bta_hf_client_sco_event(UINT8 event)
{
APPL_TRACE_DEBUG("%s state: %d event: %d", __FUNCTION__,
bta_hf_client_cb.scb.sco_state, event);
#if (BTM_SCO_HCI_INCLUDED == TRUE )
tBTA_HF_CLIENT_SCB *p_scb = &bta_hf_client_cb.scb;
BT_HDR *p_buf;
#endif
#if (BTM_SCO_HCI_INCLUDED == TRUE )
if (event == BTA_HF_CLIENT_SCO_CI_DATA_E) {
uint16_t pkt_offset = 1 + HCI_SCO_PREAMBLE_SIZE;
uint16_t len_to_send = 0;
uint8_t *p;
while (true)
{
p_buf = osi_malloc(sizeof(BT_HDR) + pkt_offset + BTM_SCO_DATA_SIZE_MAX);
if (!p_buf) {
APPL_TRACE_WARNING("%s, no mem", __FUNCTION__);
break;
}
p_buf->offset = pkt_offset;
len_to_send = bta_hf_client_sco_co_out_data(p_buf->data + pkt_offset, BTM_SCO_DATA_SIZE_MAX);
if (len_to_send) {
if (bta_hf_client_cb.scb.sco_state == BTA_HF_CLIENT_SCO_OPEN_ST) {
p = (UINT8 *)(p_buf->data + pkt_offset -1);
*p = len_to_send; // set SCO packet length;
tBTM_STATUS write_stat = BTM_WriteScoData(p_scb->sco_idx, p_buf);
if (write_stat != BTM_SUCCESS && write_stat != BTM_SCO_BAD_LENGTH) {
break;
}
} else {
osi_free(p_buf);
}
} else {
osi_free(p_buf);
break;
}
}
return;
}
#endif
switch (bta_hf_client_cb.scb.sco_state) {
case BTA_HF_CLIENT_SCO_SHUTDOWN_ST:
switch (event) {
case BTA_HF_CLIENT_SCO_LISTEN_E:
/* create sco listen connection */
bta_hf_client_sco_create(FALSE);
bta_hf_client_cb.scb.sco_state = BTA_HF_CLIENT_SCO_LISTEN_ST;
break;
default:
APPL_TRACE_WARNING("BTA_HF_CLIENT_SCO_SHUTDOWN_ST: Ignoring event %d", event);
break;
}
break;
case BTA_HF_CLIENT_SCO_LISTEN_ST:
switch (event) {
case BTA_HF_CLIENT_SCO_LISTEN_E:
/* create sco listen connection (Additional channel) */
bta_hf_client_sco_create(FALSE);
break;
case BTA_HF_CLIENT_SCO_OPEN_E:
/* remove listening connection */
bta_hf_client_sco_remove(FALSE);
/* create sco connection to peer */
bta_hf_client_sco_create(TRUE);
bta_hf_client_cb.scb.sco_state = BTA_HF_CLIENT_SCO_OPENING_ST;
break;
case BTA_HF_CLIENT_SCO_SHUTDOWN_E:
/* remove listening connection */
bta_hf_client_sco_remove(FALSE);
bta_hf_client_cb.scb.sco_state = BTA_HF_CLIENT_SCO_SHUTDOWN_ST;
break;
case BTA_HF_CLIENT_SCO_CLOSE_E:
/* remove listening connection */
/* Ignore the event. We need to keep listening SCO for the active SLC */
APPL_TRACE_WARNING("BTA_HF_CLIENT_SCO_LISTEN_ST: Ignoring event %d", event);
break;
case BTA_HF_CLIENT_SCO_CONN_CLOSE_E:
/* sco failed; create sco listen connection */
bta_hf_client_sco_create(FALSE);
bta_hf_client_cb.scb.sco_state = BTA_HF_CLIENT_SCO_LISTEN_ST;
break;
default:
APPL_TRACE_WARNING("BTA_HF_CLIENT_SCO_LISTEN_ST: Ignoring event %d", event);
break;
}
break;
case BTA_HF_CLIENT_SCO_OPENING_ST:
switch (event) {
case BTA_HF_CLIENT_SCO_CLOSE_E:
bta_hf_client_cb.scb.sco_state = BTA_HF_CLIENT_SCO_OPEN_CL_ST;
break;
case BTA_HF_CLIENT_SCO_SHUTDOWN_E:
bta_hf_client_cb.scb.sco_state = BTA_HF_CLIENT_SCO_SHUTTING_ST;
break;
case BTA_HF_CLIENT_SCO_CONN_OPEN_E:
bta_hf_client_cb.scb.sco_state = BTA_HF_CLIENT_SCO_OPEN_ST;
break;
case BTA_HF_CLIENT_SCO_CONN_CLOSE_E:
/* sco failed; create sco listen connection */
bta_hf_client_sco_create(FALSE);
bta_hf_client_cb.scb.sco_state = BTA_HF_CLIENT_SCO_LISTEN_ST;
break;
default:
APPL_TRACE_WARNING("BTA_HF_CLIENT_SCO_OPENING_ST: Ignoring event %d", event);
break;
}
break;
case BTA_HF_CLIENT_SCO_OPEN_CL_ST:
switch (event) {
case BTA_HF_CLIENT_SCO_OPEN_E:
bta_hf_client_cb.scb.sco_state = BTA_HF_CLIENT_SCO_OPENING_ST;
break;
case BTA_HF_CLIENT_SCO_SHUTDOWN_E:
bta_hf_client_cb.scb.sco_state = BTA_HF_CLIENT_SCO_SHUTTING_ST;
break;
case BTA_HF_CLIENT_SCO_CONN_OPEN_E:
/* close sco connection */
bta_hf_client_sco_remove(TRUE);
bta_hf_client_cb.scb.sco_state = BTA_HF_CLIENT_SCO_CLOSING_ST;
break;
case BTA_HF_CLIENT_SCO_CONN_CLOSE_E:
/* sco failed; create sco listen connection */
bta_hf_client_cb.scb.sco_state = BTA_HF_CLIENT_SCO_LISTEN_ST;
break;
default:
APPL_TRACE_WARNING("BTA_HF_CLIENT_SCO_OPEN_CL_ST: Ignoring event %d", event);
break;
}
break;
case BTA_HF_CLIENT_SCO_OPEN_ST:
switch (event) {
case BTA_HF_CLIENT_SCO_CLOSE_E:
/* close sco connection if active */
if (bta_hf_client_sco_remove(TRUE)) {
bta_hf_client_cb.scb.sco_state = BTA_HF_CLIENT_SCO_CLOSING_ST;
}
break;
case BTA_HF_CLIENT_SCO_SHUTDOWN_E:
/* remove all listening connections */
bta_hf_client_sco_remove(FALSE);
bta_hf_client_cb.scb.sco_state = BTA_HF_CLIENT_SCO_SHUTTING_ST;
break;
case BTA_HF_CLIENT_SCO_CONN_CLOSE_E:
/* peer closed sco; create sco listen connection */
bta_hf_client_sco_create(FALSE);
bta_hf_client_cb.scb.sco_state = BTA_HF_CLIENT_SCO_LISTEN_ST;
break;
default:
APPL_TRACE_WARNING("BTA_HF_CLIENT_SCO_OPEN_ST: Ignoring event %d", event);
break;
}
break;
case BTA_HF_CLIENT_SCO_CLOSING_ST:
switch (event) {
case BTA_HF_CLIENT_SCO_OPEN_E:
bta_hf_client_cb.scb.sco_state = BTA_HF_CLIENT_SCO_CLOSE_OP_ST;
break;
case BTA_HF_CLIENT_SCO_SHUTDOWN_E:
bta_hf_client_cb.scb.sco_state = BTA_HF_CLIENT_SCO_SHUTTING_ST;
break;
case BTA_HF_CLIENT_SCO_CONN_CLOSE_E:
/* peer closed sco; create sco listen connection */
bta_hf_client_sco_create(FALSE);
bta_hf_client_cb.scb.sco_state = BTA_HF_CLIENT_SCO_LISTEN_ST;
break;
default:
APPL_TRACE_WARNING("BTA_HF_CLIENT_SCO_CLOSING_ST: Ignoring event %d", event);
break;
}
break;
case BTA_HF_CLIENT_SCO_CLOSE_OP_ST:
switch (event) {
case BTA_HF_CLIENT_SCO_CLOSE_E:
bta_hf_client_cb.scb.sco_state = BTA_HF_CLIENT_SCO_CLOSING_ST;
break;
case BTA_HF_CLIENT_SCO_SHUTDOWN_E:
bta_hf_client_cb.scb.sco_state = BTA_HF_CLIENT_SCO_SHUTTING_ST;
break;
case BTA_HF_CLIENT_SCO_CONN_CLOSE_E:
/* open sco connection */
bta_hf_client_sco_create(TRUE);
bta_hf_client_cb.scb.sco_state = BTA_HF_CLIENT_SCO_OPENING_ST;
break;
default:
APPL_TRACE_WARNING("BTA_HF_CLIENT_SCO_CLOSE_OP_ST: Ignoring event %d", event);
break;
}
break;
case BTA_HF_CLIENT_SCO_SHUTTING_ST:
switch (event) {
case BTA_HF_CLIENT_SCO_CONN_OPEN_E:
/* close sco connection; wait for conn close event */
bta_hf_client_sco_remove(TRUE);
break;
case BTA_HF_CLIENT_SCO_CONN_CLOSE_E:
bta_hf_client_cb.scb.sco_state = BTA_HF_CLIENT_SCO_SHUTDOWN_ST;
break;
case BTA_HF_CLIENT_SCO_SHUTDOWN_E:
bta_hf_client_cb.scb.sco_state = BTA_HF_CLIENT_SCO_SHUTDOWN_ST;
break;
default:
APPL_TRACE_WARNING("BTA_HF_CLIENT_SCO_SHUTTING_ST: Ignoring event %d", event);
break;
}
break;
default:
break;
}
}
/*******************************************************************************
**
** Function bta_hf_client_sco_listen
**
** Description Initialize SCO listener
**
**
** Returns void
**
*******************************************************************************/
void bta_hf_client_sco_listen(tBTA_HF_CLIENT_DATA *p_data)
{
UNUSED(p_data);
APPL_TRACE_DEBUG("%s", __FUNCTION__);
bta_hf_client_sco_event(BTA_HF_CLIENT_SCO_LISTEN_E);
}
/*******************************************************************************
**
** Function bta_hf_client_sco_shutdown
**
** Description
**
**
** Returns void
**
*******************************************************************************/
void bta_hf_client_sco_shutdown(tBTA_HF_CLIENT_DATA *p_data)
{
UNUSED(p_data);
APPL_TRACE_DEBUG("%s", __FUNCTION__);
bta_hf_client_sco_event(BTA_HF_CLIENT_SCO_SHUTDOWN_E);
}
/*******************************************************************************
**
** Function bta_hf_client_sco_conn_open
**
** Description
**
**
** Returns void
**
*******************************************************************************/
void bta_hf_client_sco_conn_open(tBTA_HF_CLIENT_DATA *p_data)
{
UNUSED(p_data);
APPL_TRACE_DEBUG("%s", __FUNCTION__);
bta_hf_client_sco_event(BTA_HF_CLIENT_SCO_CONN_OPEN_E);
bta_sys_sco_open(BTA_ID_HS, 1, bta_hf_client_cb.scb.peer_addr);
#if (BTM_SCO_HCI_INCLUDED == TRUE)
bta_hf_client_co_audio_state(bta_hf_client_cb.scb.sco_idx, SCO_STATE_ON, 0);
/* open SCO codec if SCO is routed through transport */
bta_hf_client_sco_co_open(bta_hf_client_cb.scb.sco_idx, BTA_HFP_SCO_OUT_PKT_SIZE, BTA_HF_CLIENT_CI_SCO_DATA_EVT);
#endif
if (bta_hf_client_cb.scb.negotiated_codec == BTM_SCO_CODEC_MSBC) {
bta_hf_client_cback_sco(BTA_HF_CLIENT_AUDIO_MSBC_OPEN_EVT);
} else {
bta_hf_client_cback_sco(BTA_HF_CLIENT_AUDIO_OPEN_EVT);
}
bta_hf_client_cb.scb.retry_with_sco_only = FALSE;
}
/*******************************************************************************
**
** Function bta_hf_client_sco_conn_close
**
** Description
**
**
** Returns void
**
*******************************************************************************/
void bta_hf_client_sco_conn_close(tBTA_HF_CLIENT_DATA *p_data)
{
APPL_TRACE_DEBUG("%s", __FUNCTION__);
/* clear current scb */
bta_hf_client_cb.scb.sco_idx = BTM_INVALID_SCO_INDEX;
/* retry_with_sco_only, will be set only when initiator
** and HFClient is first trying to establish an eSCO connection */
if (bta_hf_client_cb.scb.retry_with_sco_only && bta_hf_client_cb.scb.svc_conn) {
bta_hf_client_sco_create(TRUE);
} else {
bta_hf_client_sco_event(BTA_HF_CLIENT_SCO_CONN_CLOSE_E);
bta_sys_sco_close(BTA_ID_HS, 1, bta_hf_client_cb.scb.peer_addr);
bta_sys_sco_unuse(BTA_ID_HS, 1, bta_hf_client_cb.scb.peer_addr);
/* call app callback */
bta_hf_client_cback_sco(BTA_HF_CLIENT_AUDIO_CLOSE_EVT);
if (bta_hf_client_cb.scb.sco_close_rfc == TRUE) {
bta_hf_client_cb.scb.sco_close_rfc = FALSE;
bta_hf_client_rfc_do_close(p_data);
}
}
bta_hf_client_cb.scb.retry_with_sco_only = FALSE;
}
/*******************************************************************************
**
** Function bta_hf_client_sco_open
**
** Description
**
**
** Returns void
**
*******************************************************************************/
void bta_hf_client_sco_open(tBTA_HF_CLIENT_DATA *p_data)
{
UNUSED(p_data);
APPL_TRACE_DEBUG("%s", __FUNCTION__);
bta_hf_client_sco_event(BTA_HF_CLIENT_SCO_OPEN_E);
}
/*******************************************************************************
**
** Function bta_hf_client_sco_close
**
** Description
**
**
** Returns void
**
*******************************************************************************/
void bta_hf_client_sco_close(tBTA_HF_CLIENT_DATA *p_data)
{
UNUSED(p_data);
APPL_TRACE_DEBUG("%s 0x%x", __FUNCTION__, bta_hf_client_cb.scb.sco_idx);
if (bta_hf_client_cb.scb.sco_idx != BTM_INVALID_SCO_INDEX) {
bta_hf_client_sco_event(BTA_HF_CLIENT_SCO_CLOSE_E);
}
}
#endif /* #if (BTA_HF_INCLUDED == TRUE) */

View file

@ -0,0 +1,367 @@
/******************************************************************************
*
* Copyright (c) 2014 The Android Open Source Project
* Copyright (C) 2003-2012 Broadcom Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at:
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
******************************************************************************/
/******************************************************************************
*
* This file contains the audio gateway functions performing SDP
* operations.
*
******************************************************************************/
#include <string.h>
#include "bta/bta_api.h"
#include "bta/bta_sys.h"
#include "common/bt_defs.h"
#include "bta/bta_hf_client_api.h"
#include "bta_hf_client_int.h"
#include "osi/allocator.h"
#if (BTA_HF_INCLUDED == TRUE)
/* Number of protocol elements in protocol element list. */
#define BTA_HF_CLIENT_NUM_PROTO_ELEMS 2
/* Number of elements in service class id list. */
#define BTA_HF_CLIENT_NUM_SVC_ELEMS 2
/*******************************************************************************
**
** Function bta_hf_client_sdp_cback
**
** Description SDP callback function.
**
**
** Returns void
**
*******************************************************************************/
static void bta_hf_client_sdp_cback(UINT16 status)
{
tBTA_HF_CLIENT_DISC_RESULT *p_buf;
UINT16 event;
APPL_TRACE_DEBUG("bta_hf_client_sdp_cback status:0x%x", status);
/* set event according to int/acp */
if (bta_hf_client_cb.scb.role == BTA_HF_CLIENT_ACP) {
event = BTA_HF_CLIENT_DISC_ACP_RES_EVT;
} else {
event = BTA_HF_CLIENT_DISC_INT_RES_EVT;
}
if ((p_buf = (tBTA_HF_CLIENT_DISC_RESULT *) osi_malloc(sizeof(tBTA_HF_CLIENT_DISC_RESULT))) != NULL) {
p_buf->hdr.event = event;
p_buf->status = status;
bta_sys_sendmsg(p_buf);
}
}
/******************************************************************************
**
** Function bta_hf_client_add_record
**
** Description This function is called by a server application to add
** HFP Client information to an SDP record. Prior to
** calling this function the application must call
** SDP_CreateRecord() to create an SDP record.
**
** Returns TRUE if function execution succeeded,
** FALSE if function execution failed.
**
******************************************************************************/
BOOLEAN bta_hf_client_add_record(char *p_service_name, UINT8 scn,
tBTA_HF_CLIENT_FEAT features, UINT32 sdp_handle)
{
tSDP_PROTOCOL_ELEM proto_elem_list[BTA_HF_CLIENT_NUM_PROTO_ELEMS];
UINT16 svc_class_id_list[BTA_HF_CLIENT_NUM_SVC_ELEMS];
UINT16 browse_list[] = {UUID_SERVCLASS_PUBLIC_BROWSE_GROUP};
UINT16 version;
UINT16 profile_uuid;
BOOLEAN result = TRUE;
UINT8 buf[2];
UINT16 sdp_features = 0;
APPL_TRACE_DEBUG("bta_hf_client_add_record");
memset( proto_elem_list, 0 , BTA_HF_CLIENT_NUM_PROTO_ELEMS * sizeof(tSDP_PROTOCOL_ELEM));
/* add the protocol element sequence */
proto_elem_list[0].protocol_uuid = UUID_PROTOCOL_L2CAP;
proto_elem_list[0].num_params = 0;
proto_elem_list[1].protocol_uuid = UUID_PROTOCOL_RFCOMM;
proto_elem_list[1].num_params = 1;
proto_elem_list[1].params[0] = scn;
result &= SDP_AddProtocolList(sdp_handle, BTA_HF_CLIENT_NUM_PROTO_ELEMS, proto_elem_list);
/* add service class id list */
svc_class_id_list[0] = UUID_SERVCLASS_HF_HANDSFREE;
svc_class_id_list[1] = UUID_SERVCLASS_GENERIC_AUDIO;
result &= SDP_AddServiceClassIdList(sdp_handle, BTA_HF_CLIENT_NUM_SVC_ELEMS, svc_class_id_list);
/* add profile descriptor list */
profile_uuid = UUID_SERVCLASS_HF_HANDSFREE;
version = HFP_VERSION_1_6;
result &= SDP_AddProfileDescriptorList(sdp_handle, profile_uuid, version);
/* add service name */
if (p_service_name != NULL && p_service_name[0] != 0) {
result &= SDP_AddAttribute(sdp_handle, ATTR_ID_SERVICE_NAME, TEXT_STR_DESC_TYPE,
(UINT32)(strlen(p_service_name) + 1), (UINT8 *) p_service_name);
}
/* add features */
if (features & BTA_HF_CLIENT_FEAT_ECNR) {
sdp_features |= BTA_HF_CLIENT_FEAT_ECNR;
}
if (features & BTA_HF_CLIENT_FEAT_3WAY) {
sdp_features |= BTA_HF_CLIENT_FEAT_3WAY;
}
if (features & BTA_HF_CLIENT_FEAT_CLI) {
sdp_features |= BTA_HF_CLIENT_FEAT_CLI;
}
if (features & BTA_HF_CLIENT_FEAT_VREC) {
sdp_features |= BTA_HF_CLIENT_FEAT_VREC;
}
if (features & BTA_HF_CLIENT_FEAT_VOL) {
sdp_features |= BTA_HF_CLIENT_FEAT_VOL;
}
/* Codec bit position is different in SDP (bit 5) and in BRSF (bit 7) */
if (features & BTA_HF_CLIENT_FEAT_CODEC) {
sdp_features |= 0x0020;
}
UINT16_TO_BE_FIELD(buf, sdp_features);
result &= SDP_AddAttribute(sdp_handle, ATTR_ID_SUPPORTED_FEATURES, UINT_DESC_TYPE, 2, buf);
/* add browse group list */
result &= SDP_AddUuidSequence(sdp_handle, ATTR_ID_BROWSE_GROUP_LIST, 1, browse_list);
return result;
}
/*******************************************************************************
**
** Function bta_hf_client_create_record
**
** Description Create SDP record for registered service.
**
**
** Returns void
**
*******************************************************************************/
void bta_hf_client_create_record(tBTA_HF_CLIENT_DATA *p_data)
{
/* add sdp record if not already registered */
if (bta_hf_client_cb.sdp_handle == 0) {
bta_hf_client_cb.sdp_handle = SDP_CreateRecord();
bta_hf_client_cb.scn = BTM_AllocateSCN();
bta_hf_client_add_record(p_data->api_register.name,
bta_hf_client_cb.scn,
p_data->api_register.features,
bta_hf_client_cb.sdp_handle);
bta_sys_add_uuid(UUID_SERVCLASS_HF_HANDSFREE);
}
}
/*******************************************************************************
**
** Function bta_hf_client_del_record
**
** Description Delete SDP record for registered service.
**
**
** Returns void
**
*******************************************************************************/
void bta_hf_client_del_record(tBTA_HF_CLIENT_DATA *p_data)
{
UNUSED(p_data);
APPL_TRACE_DEBUG("bta_hf_client_del_record");
if (bta_hf_client_cb.sdp_handle != 0) {
SDP_DeleteRecord(bta_hf_client_cb.sdp_handle);
bta_hf_client_cb.sdp_handle = 0;
BTM_FreeSCN(bta_hf_client_cb.scn);
BTM_SecClrService(BTM_SEC_SERVICE_HF_HANDSFREE);
bta_sys_remove_uuid(UUID_SERVCLASS_HF_HANDSFREE);
}
}
/*******************************************************************************
**
** Function bta_hf_client_sdp_find_attr
**
** Description Process SDP discovery results to find requested attribute
**
**
** Returns TRUE if results found, FALSE otherwise.
**
*******************************************************************************/
BOOLEAN bta_hf_client_sdp_find_attr(void)
{
tSDP_DISC_REC *p_rec = NULL;
tSDP_DISC_ATTR *p_attr;
tSDP_PROTOCOL_ELEM pe;
BOOLEAN result = FALSE;
bta_hf_client_cb.scb.peer_version = HFP_VERSION_1_1; /* Default version */
/* loop through all records we found */
while (TRUE) {
/* get next record; if none found, we're done */
if ((p_rec = SDP_FindServiceInDb(bta_hf_client_cb.scb.p_disc_db, UUID_SERVCLASS_AG_HANDSFREE, p_rec)) == NULL) {
break;
}
/* get scn from proto desc list if initiator */
if (bta_hf_client_cb.scb.role == BTA_HF_CLIENT_INT) {
if (SDP_FindProtocolListElemInRec(p_rec, UUID_PROTOCOL_RFCOMM, &pe)) {
bta_hf_client_cb.scb.peer_scn = (UINT8) pe.params[0];
} else {
continue;
}
}
/* get profile version (if failure, version parameter is not updated) */
SDP_FindProfileVersionInRec(p_rec, UUID_SERVCLASS_HF_HANDSFREE, &bta_hf_client_cb.scb.peer_version);
/* get features */
if ((p_attr = SDP_FindAttributeInRec(p_rec, ATTR_ID_SUPPORTED_FEATURES)) != NULL) {
/* Found attribute. Get value. */
/* There might be race condition between SDP and BRSF. */
/* Do not update if we already received BRSF. */
if (bta_hf_client_cb.scb.peer_features == 0) {
bta_hf_client_cb.scb.peer_features = p_attr->attr_value.v.u16;
/* SDP and BRSF WBS bit are different, correct it if set */
if (bta_hf_client_cb.scb.peer_features & 0x0020) {
bta_hf_client_cb.scb.peer_features &= ~0x0020;
bta_hf_client_cb.scb.peer_features |= BTA_HF_CLIENT_PEER_CODEC;
}
/* get network for ability to reject calls */
if ((p_attr = SDP_FindAttributeInRec(p_rec, ATTR_ID_NETWORK)) != NULL) {
if (p_attr->attr_value.v.u16 == 0x01) {
bta_hf_client_cb.scb.peer_features |= BTA_HF_CLIENT_PEER_REJECT;
}
}
}
}
/* found what we needed */
result = TRUE;
break;
}
APPL_TRACE_DEBUG("%s peer_version=0x%x peer_features=0x%x",
__FUNCTION__, bta_hf_client_cb.scb.peer_version,
bta_hf_client_cb.scb.peer_features);
return result;
}
/*******************************************************************************
**
** Function bta_hf_client_do_disc
**
** Description Do service discovery.
**
**
** Returns void
**
*******************************************************************************/
void bta_hf_client_do_disc(void)
{
tSDP_UUID uuid_list[2];
UINT16 num_uuid = 1;
UINT16 attr_list[4];
UINT8 num_attr;
BOOLEAN db_inited = FALSE;
/* initiator; get proto list and features */
if (bta_hf_client_cb.scb.role == BTA_HF_CLIENT_INT) {
attr_list[0] = ATTR_ID_SERVICE_CLASS_ID_LIST;
attr_list[1] = ATTR_ID_PROTOCOL_DESC_LIST;
attr_list[2] = ATTR_ID_BT_PROFILE_DESC_LIST;
attr_list[3] = ATTR_ID_SUPPORTED_FEATURES;
num_attr = 4;
uuid_list[0].uu.uuid16 = UUID_SERVCLASS_AG_HANDSFREE;
}
/* acceptor; get features */
else {
attr_list[0] = ATTR_ID_SERVICE_CLASS_ID_LIST;
attr_list[1] = ATTR_ID_BT_PROFILE_DESC_LIST;
attr_list[2] = ATTR_ID_SUPPORTED_FEATURES;
num_attr = 3;
uuid_list[0].uu.uuid16 = UUID_SERVCLASS_AG_HANDSFREE;
}
/* allocate buffer for sdp database */
bta_hf_client_cb.scb.p_disc_db = (tSDP_DISCOVERY_DB *) osi_malloc(BT_DEFAULT_BUFFER_SIZE);
if (bta_hf_client_cb.scb.p_disc_db) {
/* set up service discovery database; attr happens to be attr_list len */
uuid_list[0].len = LEN_UUID_16;
uuid_list[1].len = LEN_UUID_16;
db_inited = SDP_InitDiscoveryDb(bta_hf_client_cb.scb.p_disc_db, BT_DEFAULT_BUFFER_SIZE, num_uuid,
uuid_list, num_attr, attr_list);
}
if (db_inited) {
/*Service discovery not initiated */
db_inited = SDP_ServiceSearchAttributeRequest(bta_hf_client_cb.scb.peer_addr,
bta_hf_client_cb.scb.p_disc_db, bta_hf_client_sdp_cback);
}
if (!db_inited) {
/*free discover db */
bta_hf_client_free_db(NULL);
/* sent failed event */
bta_hf_client_sm_execute(BTA_HF_CLIENT_DISC_FAIL_EVT, NULL);
}
}
/*******************************************************************************
**
** Function bta_hf_client_free_db
**
** Description Free discovery database.
**
**
** Returns void
**
*******************************************************************************/
void bta_hf_client_free_db(tBTA_HF_CLIENT_DATA *p_data)
{
UNUSED(p_data);
if (bta_hf_client_cb.scb.p_disc_db != NULL) {
osi_free(bta_hf_client_cb.scb.p_disc_db);
bta_hf_client_cb.scb.p_disc_db = NULL;
}
}
#endif /* #if (BTA_HF_INCLUDED == TRUE) */

View file

@ -0,0 +1,117 @@
/******************************************************************************
*
* Copyright (c) 2014 The Android Open Source Project
* Copyright (C) 2003-2012 Broadcom Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at:
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
******************************************************************************/
/*****************************************************************************
** Data types
*****************************************************************************/
#include "common/bt_target.h"
#if (BTA_HF_INCLUDED == TRUE)
/* ASCII character string of arguments to the AT command */
#define BTA_HF_CLIENT_AT_MAX_LEN 512
/* AT command table element */
typedef struct {
const char *p_cmd; /* AT command string */
UINT8 arg_type; /* allowable argument type syntax */
UINT8 fmt; /* whether arg is int or string */
UINT8 min; /* minimum value for int arg */
INT16 max; /* maximum value for int arg */
} tBTA_AG_AT_CMD;
/* callback function executed when command is parsed */
typedef void (tBTA_AG_AT_CMD_CBACK)(void *p_user, UINT16 cmd, UINT8 arg_type,
char *p_arg, INT16 int_arg);
/* callback function executed to send "ERROR" result code */
typedef void (tBTA_AG_AT_ERR_CBACK)(void *p_user, BOOLEAN unknown, char *p_arg);
enum {
BTA_HF_CLIENT_AT_NONE,
BTA_HF_CLIENT_AT_BRSF,
BTA_HF_CLIENT_AT_BAC,
BTA_HF_CLIENT_AT_CIND,
BTA_HF_CLIENT_AT_CIND_STATUS,
BTA_HF_CLIENT_AT_CMER,
BTA_HF_CLIENT_AT_CHLD,
BTA_HF_CLIENT_AT_CMEE,
BTA_HF_CLIENT_AT_BIA,
BTA_HF_CLIENT_AT_CLIP,
BTA_HF_CLIENT_AT_CCWA,
BTA_HF_CLIENT_AT_COPS,
BTA_HF_CLIENT_AT_CLCC,
BTA_HF_CLIENT_AT_BVRA,
BTA_HF_CLIENT_AT_VGS,
BTA_HF_CLIENT_AT_VGM,
BTA_HF_CLIENT_AT_ATD,
BTA_HF_CLIENT_AT_BLDN,
BTA_HF_CLIENT_AT_ATA,
BTA_HF_CLIENT_AT_CHUP,
BTA_HF_CLIENT_AT_BTRH,
BTA_HF_CLIENT_AT_VTS,
BTA_HF_CLIENT_AT_BCC,
BTA_HF_CLIENT_AT_BCS,
BTA_HF_CLIENT_AT_CNUM,
BTA_HF_CLIENT_AT_NREC,
BTA_HF_CLIENT_AT_BINP,
};
typedef UINT8 tBTA_HF_CLIENT_AT_CMD;
/* Maximum combined buffer for received AT events string */
#define BTA_HF_CLIENT_AT_PARSER_MAX_LEN 4096
/* This structure holds prepared AT command queued for sending */
struct queued_at_cmd {
tBTA_HF_CLIENT_AT_CMD cmd;
char buf[BTA_HF_CLIENT_AT_MAX_LEN];
UINT16 buf_len;
struct queued_at_cmd *next;
};
typedef struct queued_at_cmd tBTA_HF_CLIENT_AT_QCMD;
/* Maximum number of indicators */
#define BTA_HF_CLIENT_AT_INDICATOR_COUNT 20
/* AT command parsing control block */
typedef struct {
char buf[BTA_HF_CLIENT_AT_PARSER_MAX_LEN + 1]; /* extra byte to always have \0 at the end */
unsigned int offset;
tBTA_HF_CLIENT_AT_CMD current_cmd;
tBTA_HF_CLIENT_AT_QCMD *queued_cmd;
TIMER_LIST_ENT resp_timer; /* AT response timer */
BOOLEAN resp_timer_on; /* TRUE if AT response timer is active */
TIMER_LIST_ENT hold_timer; /* AT hold timer */
BOOLEAN hold_timer_on; /* TRUE if AT hold timer is active */
/* CIND: lookup table to store the sequence of incoming indicators and their values
so when their values come later, we know which value in sequence match certain indicator */
int indicator_lookup[BTA_HF_CLIENT_AT_INDICATOR_COUNT];
} tBTA_HF_CLIENT_AT_CB;
/*****************************************************************************
** Functions
*****************************************************************************/
void bta_hf_client_at_init(void);
void bta_hf_client_at_reset(void);
#endif /* #if (BTA_HF_INCLUDED == TRUE) */

View file

@ -0,0 +1,296 @@
/******************************************************************************
*
* Copyright (c) 2014 The Android Open Source Project
* Copyright (C) 2003-2012 Broadcom Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at:
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
******************************************************************************/
#include "bta/bta_sys.h"
#include "bta/bta_api.h"
#include "bta/bta_hf_client_api.h"
#include "bta_hf_client_at.h"
#if (BTA_HF_INCLUDED == TRUE)
/*****************************************************************************
** Constants
*****************************************************************************/
#define HFP_VERSION_1_1 0x0101
#define HFP_VERSION_1_5 0x0105
#define HFP_VERSION_1_6 0x0106
/* RFCOMM MTU SIZE */
#define BTA_HF_CLIENT_MTU 256
/* profile role for connection */
#define BTA_HF_CLIENT_ACP 0 /* accepted connection */
#define BTA_HF_CLIENT_INT 1 /* initiating connection */
/* Timer to wait for retry in case of collision */
#ifndef BTA_HF_CLIENT_COLLISION_TIMER
#define BTA_HF_CLIENT_COLLISION_TIMER 2411
#endif
enum {
/* these events are handled by the state machine */
BTA_HF_CLIENT_API_REGISTER_EVT = BTA_SYS_EVT_START(BTA_ID_HS),
BTA_HF_CLIENT_API_DEREGISTER_EVT,
BTA_HF_CLIENT_API_OPEN_EVT,
BTA_HF_CLIENT_API_CLOSE_EVT,
BTA_HF_CLIENT_API_AUDIO_OPEN_EVT,
BTA_HF_CLIENT_API_AUDIO_CLOSE_EVT,
BTA_HF_CLIENT_RFC_OPEN_EVT,
BTA_HF_CLIENT_RFC_CLOSE_EVT,
BTA_HF_CLIENT_RFC_SRV_CLOSE_EVT,
BTA_HF_CLIENT_RFC_DATA_EVT,
BTA_HF_CLIENT_DISC_ACP_RES_EVT,
BTA_HF_CLIENT_DISC_INT_RES_EVT,
BTA_HF_CLIENT_DISC_OK_EVT,
BTA_HF_CLIENT_DISC_FAIL_EVT,
BTA_HF_CLIENT_SCO_OPEN_EVT,
BTA_HF_CLIENT_SCO_CLOSE_EVT,
BTA_HF_CLIENT_SEND_AT_CMD_EVT,
#if (BTM_SCO_HCI_INCLUDED == TRUE )
BTA_HF_CLIENT_CI_SCO_DATA_EVT,
#endif /* (BTM_SCO_HCI_INCLUDED == TRUE ) */
BTA_HF_CLIENT_MAX_EVT,
/* these events are handled outside of the state machine */
BTA_HF_CLIENT_API_ENABLE_EVT,
BTA_HF_CLIENT_API_DISABLE_EVT
};
/*****************************************************************************
** Data types
*****************************************************************************/
/* data type for BTA_HF_CLIENT_API_ENABLE_EVT */
typedef struct {
BT_HDR hdr;
tBTA_HF_CLIENT_CBACK *p_cback;
} tBTA_HF_CLIENT_API_ENABLE;
/* data type for BTA_HF_CLIENT_API_REGISTER_EVT */
typedef struct {
BT_HDR hdr;
tBTA_HF_CLIENT_CBACK *p_cback;
tBTA_SEC sec_mask;
tBTA_HF_CLIENT_FEAT features;
char name[BTA_SERVICE_NAME_LEN + 1];
} tBTA_HF_CLIENT_API_REGISTER;
/* data type for BTA_HF_CLIENT_API_OPEN_EVT */
typedef struct {
BT_HDR hdr;
BD_ADDR bd_addr;
tBTA_SEC sec_mask;
} tBTA_HF_CLIENT_API_OPEN;
/* data type for BTA_HF_CLIENT_DISC_RESULT_EVT */
typedef struct {
BT_HDR hdr;
UINT16 status;
} tBTA_HF_CLIENT_DISC_RESULT;
/* data type for RFCOMM events */
typedef struct {
BT_HDR hdr;
UINT16 port_handle;
} tBTA_HF_CLIENT_RFC;
/* generic purpose data type for other events */
typedef struct {
BT_HDR hdr;
BOOLEAN bool_val;
UINT8 uint8_val;
UINT32 uint32_val1;
UINT32 uint32_val2;
char str[BTA_HF_CLIENT_NUMBER_LEN + 1];
} tBTA_HF_CLIENT_DATA_VAL;
/* union of all event datatypes */
typedef union {
BT_HDR hdr;
tBTA_HF_CLIENT_API_ENABLE api_enable;
tBTA_HF_CLIENT_API_REGISTER api_register;
tBTA_HF_CLIENT_API_OPEN api_open;
tBTA_HF_CLIENT_DISC_RESULT disc_result;
tBTA_HF_CLIENT_RFC rfc;
tBTA_HF_CLIENT_DATA_VAL val;
} tBTA_HF_CLIENT_DATA;
/* type for each service control block */
typedef struct {
UINT16 serv_handle; /* RFCOMM server handle */
BD_ADDR peer_addr; /* peer bd address */
tSDP_DISCOVERY_DB *p_disc_db; /* pointer to discovery database */
UINT16 conn_handle; /* RFCOMM handle of connected service */
tBTA_SEC serv_sec_mask; /* server security mask */
tBTA_SEC cli_sec_mask; /* client security mask */
tBTA_HF_CLIENT_FEAT features; /* features registered by application */
tBTA_HF_CLIENT_PEER_FEAT peer_features; /* peer device features */
tBTA_HF_CLIENT_CHLD_FEAT chld_features; /* call handling features */
UINT16 peer_version; /* profile version of peer device */
UINT8 peer_scn; /* peer scn */
UINT8 role; /* initiator/acceptor role */
UINT16 sco_idx; /* SCO handle */
UINT8 sco_state; /* SCO state variable */
BOOLEAN sco_close_rfc; /* TRUE if also close RFCOMM after SCO */
BOOLEAN retry_with_sco_only;
BOOLEAN deregister; /* TRUE if service shutting down */
BOOLEAN svc_conn; /* set to TRUE when service level connection is up */
BOOLEAN send_at_reply; /* set to TRUE to notify framework about AT results */
tBTA_HF_CLIENT_AT_CB at_cb; /* AT Parser control block */
UINT8 state; /* state machine state */
tBTM_SCO_CODEC_TYPE negotiated_codec; /* negotiated codec */
TIMER_LIST_ENT colli_timer; /* Collision timer */
BOOLEAN colli_tmr_on; /* TRUE if collision timer is active */
} tBTA_HF_CLIENT_SCB;
/* sco states */
enum {
BTA_HF_CLIENT_SCO_SHUTDOWN_ST, /* no listening, no connection */
BTA_HF_CLIENT_SCO_LISTEN_ST, /* listening */
BTA_HF_CLIENT_SCO_OPENING_ST, /* connection opening */
BTA_HF_CLIENT_SCO_OPEN_CL_ST, /* opening connection being closed */
BTA_HF_CLIENT_SCO_OPEN_ST, /* open */
BTA_HF_CLIENT_SCO_CLOSING_ST, /* closing */
BTA_HF_CLIENT_SCO_CLOSE_OP_ST, /* closing sco being opened */
BTA_HF_CLIENT_SCO_SHUTTING_ST /* sco shutting down */
};
/* type for AG control block */
typedef struct {
tBTA_HF_CLIENT_SCB scb; /* service control block */
UINT32 sdp_handle;
UINT8 scn;
tBTA_HF_CLIENT_CBACK *p_cback; /* application callback */
BOOLEAN msbc_enabled;
} tBTA_HF_CLIENT_CB;
/*****************************************************************************
** Global data
*****************************************************************************/
/* control block declaration */
#if BTA_DYNAMIC_MEMORY == FALSE
extern tBTA_HF_CLIENT_CB bta_hf_client_cb;
#else
extern tBTA_HF_CLIENT_CB *bta_hf_client_cb_ptr;
#define bta_hf_client_cb (*bta_hf_client_cb_ptr)
#endif
/*****************************************************************************
** Function prototypes
*****************************************************************************/
/* main functions */
extern void bta_hf_client_scb_init(void);
extern void bta_hf_client_scb_disable(void);
extern BOOLEAN bta_hf_client_hdl_event(BT_HDR *p_msg);
extern void bta_hf_client_sm_execute(UINT16 event,
tBTA_HF_CLIENT_DATA *p_data);
extern void bta_hf_client_slc_seq(BOOLEAN error);
extern void bta_hf_client_collision_cback (tBTA_SYS_CONN_STATUS status, UINT8 id,
UINT8 app_id, BD_ADDR peer_addr);
extern void bta_hf_client_resume_open ();
/* SDP functions */
extern BOOLEAN bta_hf_client_add_record(char *p_service_name,
UINT8 scn, tBTA_HF_CLIENT_FEAT features,
UINT32 sdp_handle);
extern void bta_hf_client_create_record(tBTA_HF_CLIENT_DATA *p_data);
extern void bta_hf_client_del_record(tBTA_HF_CLIENT_DATA *p_data);
extern BOOLEAN bta_hf_client_sdp_find_attr(void);
extern void bta_hf_client_do_disc(void);
extern void bta_hf_client_free_db(tBTA_HF_CLIENT_DATA *p_data);
/* RFCOMM functions */
extern void bta_hf_client_setup_port(UINT16 handle);
extern void bta_hf_client_start_server(void);
extern void bta_hf_client_close_server(void);
extern void bta_hf_client_rfc_do_open(tBTA_HF_CLIENT_DATA *p_data);
extern void bta_hf_client_rfc_do_close(tBTA_HF_CLIENT_DATA *p_data);
/* SCO functions */
extern void bta_hf_client_sco_listen(tBTA_HF_CLIENT_DATA *p_data);
extern void bta_hf_client_sco_shutdown(tBTA_HF_CLIENT_DATA *p_data);
extern void bta_hf_client_sco_conn_open(tBTA_HF_CLIENT_DATA *p_data);
extern void bta_hf_client_sco_conn_close(tBTA_HF_CLIENT_DATA *p_data);
extern void bta_hf_client_sco_open(tBTA_HF_CLIENT_DATA *p_data);
extern void bta_hf_client_sco_close(tBTA_HF_CLIENT_DATA *p_data);
extern void bta_hf_client_cback_sco(UINT8 event);
/* AT command functions */
extern void bta_hf_client_at_parse(char *buf, unsigned int len);
extern void bta_hf_client_send_at_brsf(void);
extern void bta_hf_client_send_at_bac(void);
extern void bta_hf_client_send_at_cind(BOOLEAN status);
extern void bta_hf_client_send_at_cmer(BOOLEAN activate);
extern void bta_hf_client_send_at_chld(char cmd, UINT32 idx);
extern void bta_hf_client_send_at_clip(BOOLEAN activate);
extern void bta_hf_client_send_at_ccwa(BOOLEAN activate);
extern void bta_hf_client_send_at_cmee(BOOLEAN activate);
extern void bta_hf_client_send_at_cops(BOOLEAN query);
extern void bta_hf_client_send_at_clcc(void);
extern void bta_hf_client_send_at_bvra(BOOLEAN enable);
extern void bta_hf_client_send_at_vgs(UINT32 volume);
extern void bta_hf_client_send_at_vgm(UINT32 volume);
extern void bta_hf_client_send_at_atd(char *number, UINT32 memory);
extern void bta_hf_client_send_at_bldn(void);
extern void bta_hf_client_send_at_ata(void);
extern void bta_hf_client_send_at_chup(void);
extern void bta_hf_client_send_at_btrh(BOOLEAN query, UINT32 val);
extern void bta_hf_client_send_at_vts(char code);
extern void bta_hf_client_send_at_bcc(void);
extern void bta_hf_client_send_at_bcs(UINT32 codec);
extern void bta_hf_client_send_at_cnum(void);
extern void bta_hf_client_send_at_nrec(void);
extern void bta_hf_client_send_at_binp(UINT32 action);
extern void bta_hf_client_send_at_bia(void);
/* Action functions */
extern void bta_hf_client_register(tBTA_HF_CLIENT_DATA *p_data);
extern void bta_hf_client_deregister(tBTA_HF_CLIENT_DATA *p_data);
extern void bta_hf_client_start_dereg(tBTA_HF_CLIENT_DATA *p_data);
extern void bta_hf_client_start_close(tBTA_HF_CLIENT_DATA *p_data);
extern void bta_hf_client_start_open(tBTA_HF_CLIENT_DATA *p_data);
extern void bta_hf_client_rfc_acp_open(tBTA_HF_CLIENT_DATA *p_data);
extern void bta_hf_client_rfc_open(tBTA_HF_CLIENT_DATA *p_data);
extern void bta_hf_client_rfc_fail(tBTA_HF_CLIENT_DATA *p_data);
extern void bta_hf_client_disc_fail(tBTA_HF_CLIENT_DATA *p_data);
extern void bta_hf_client_open_fail(tBTA_HF_CLIENT_DATA *p_data);
extern void bta_hf_client_rfc_close(tBTA_HF_CLIENT_DATA *p_data);
extern void bta_hf_client_disc_acp_res(tBTA_HF_CLIENT_DATA *p_data);
extern void bta_hf_client_rfc_data(tBTA_HF_CLIENT_DATA *p_data);
extern void bta_hf_client_disc_int_res(tBTA_HF_CLIENT_DATA *p_data);
extern void bta_hf_client_svc_conn_open(tBTA_HF_CLIENT_DATA *p_data);
extern void bta_hf_client_ind(tBTA_HF_CLIENT_IND_TYPE type, UINT16 value);
extern void bta_hf_client_evt_val(tBTA_HF_CLIENT_EVT type, UINT16 value);
extern void bta_hf_client_operator_name(char *name);
extern void bta_hf_client_clip(char *number);
extern void bta_hf_client_ccwa(char *number);
extern void bta_hf_client_at_result(tBTA_HF_CLIENT_AT_RESULT_TYPE type, UINT16 cme);
extern void bta_hf_client_clcc(UINT32 idx, BOOLEAN incoming, UINT8 status, BOOLEAN mpty, char *number);
extern void bta_hf_client_cnum(char *number, UINT16 service);
extern void bta_hf_client_binp(char *number);
/* Commands handling functions */
extern void bta_hf_client_dial(tBTA_HF_CLIENT_DATA *p_data);
extern void bta_hf_client_send_at_cmd(tBTA_HF_CLIENT_DATA *p_data);
#if (BTM_SCO_HCI_INCLUDED == TRUE )
extern void bta_hf_client_ci_sco_data(tBTA_HF_CLIENT_DATA *p_data);
#endif /* (BTM_SCO_HCI_INCLUDED == TRUE ) */
#endif /* #if (BTA_HF_INCLUDED == TRUE) */

View file

@ -61,18 +61,6 @@ extern void bta_dm_ci_io_req(BD_ADDR bd_addr, tBTA_IO_CAP io_cap,
*******************************************************************************/
extern void bta_dm_ci_rmt_oob(BOOLEAN accept, BD_ADDR bd_addr,
BT_OCTET16 c, BT_OCTET16 r);
/*******************************************************************************
**
** Function bta_dm_sco_ci_data_ready
**
** Description This function sends an event to indicating that the phone
** has SCO data ready..
**
** Returns void
**
*******************************************************************************/
extern void bta_dm_sco_ci_data_ready(UINT16 event, UINT16 sco_handle);
#ifdef __cplusplus
}
#endif

View file

@ -26,29 +26,6 @@
#include "bta/bta_sys.h"
#ifndef BTA_SCO_OUT_PKT_SIZE
#define BTA_SCO_OUT_PKT_SIZE BTM_SCO_DATA_SIZE_MAX
#endif
#define BTA_SCO_CODEC_PCM 0 /* used for regular SCO */
#define BTA_SCO_CODEC_SBC 1 /* used for WBS */
typedef UINT8 tBTA_SCO_CODEC_TYPE;
#define BTA_DM_SCO_SAMP_RATE_8K 8000
#define BTA_DM_SCO_SAMP_RATE_16K 16000
/* SCO codec information */
typedef struct {
tBTA_SCO_CODEC_TYPE codec_type;
} tBTA_CODEC_INFO;
#define BTA_DM_SCO_ROUTE_PCM BTM_SCO_ROUTE_PCM
#define BTA_DM_SCO_ROUTE_HCI BTM_SCO_ROUTE_HCI
typedef tBTM_SCO_ROUTE_TYPE tBTA_DM_SCO_ROUTE_TYPE;
/*****************************************************************************
** Function Declarations
*****************************************************************************/
@ -135,72 +112,6 @@ extern void bta_dm_co_loc_oob(BOOLEAN valid, BT_OCTET16 c, BT_OCTET16 r);
*******************************************************************************/
extern void bta_dm_co_rmt_oob(BD_ADDR bd_addr);
/*****************************************************************************
** SCO over HCI Function Declarations
*****************************************************************************/
/*******************************************************************************
**
** Function bta_dm_sco_co_init
**
** Description This function can be used by the phone to initialize audio
** codec or for other initialization purposes before SCO connection
** is opened.
**
**
** Returns Void.
**
*******************************************************************************/
extern tBTA_DM_SCO_ROUTE_TYPE bta_dm_sco_co_init(UINT32 rx_bw, UINT32 tx_bw,
tBTA_CODEC_INFO *p_codec_info, UINT8 app_id);
/*******************************************************************************
**
** Function bta_dm_sco_co_open
**
** Description This function is executed when a SCO connection is open.
**
**
** Returns void
**
*******************************************************************************/
extern void bta_dm_sco_co_open(UINT16 handle, UINT8 pkt_size, UINT16 event);
/*******************************************************************************
**
** Function bta_dm_sco_co_close
**
** Description This function is called when a SCO connection is closed
**
**
** Returns void
**
*******************************************************************************/
extern void bta_dm_sco_co_close(void);
/*******************************************************************************
**
** Function bta_dm_sco_co_out_data
**
** Description This function is called to send SCO data over HCI.
**
** Returns void
**
*******************************************************************************/
extern void bta_dm_sco_co_out_data(BT_HDR **p_buf);
/*******************************************************************************
**
** Function bta_dm_sco_co_in_data
**
** Description This function is called to send incoming SCO data to application.
**
** Returns void
**
*******************************************************************************/
extern void bta_dm_sco_co_in_data(BT_HDR *p_buf, tBTM_SCO_DATA_FLAG status);
/*******************************************************************************
**

View file

@ -0,0 +1,378 @@
/******************************************************************************
*
* Copyright (c) 2014 The Android Open Source Project
* Copyright (C) 2003-2012 Broadcom Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at:
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
******************************************************************************/
/******************************************************************************
*
* This is the public interface file for the handsfree (HF role) subsystem
*
******************************************************************************/
#ifndef BTA_HF_CLIENT_API_H
#define BTA_HF_CLIENT_API_H
#include "bta_api.h"
#include "bta_hfp_defs.h"
#if (BTA_HF_INCLUDED == TRUE)
/*****************************************************************************
** Constants and data types
*****************************************************************************/
/* HFP peer (AG) features*/
#define BTA_HF_CLIENT_PEER_FEAT_3WAY 0x00000001 /* Three-way calling */
#define BTA_HF_CLIENT_PEER_FEAT_ECNR 0x00000002 /* Echo cancellation and/or noise reduction */
#define BTA_HF_CLIENT_PEER_FEAT_VREC 0x00000004 /* Voice recognition */
#define BTA_HF_CLIENT_PEER_INBAND 0x00000008 /* In-band ring tone */
#define BTA_HF_CLIENT_PEER_VTAG 0x00000010 /* Attach a phone number to a voice tag */
#define BTA_HF_CLIENT_PEER_REJECT 0x00000020 /* Ability to reject incoming call */
#define BTA_HF_CLIENT_PEER_ECS 0x00000040 /* Enhanced Call Status */
#define BTA_HF_CLIENT_PEER_ECC 0x00000080 /* Enhanced Call Control */
#define BTA_HF_CLIENT_PEER_EXTERR 0x00000100 /* Extended error codes */
#define BTA_HF_CLIENT_PEER_CODEC 0x00000200 /* Codec Negotiation */
typedef UINT16 tBTA_HF_CLIENT_PEER_FEAT;
/* HFP HF features */
#define BTA_HF_CLIENT_FEAT_ECNR 0x00000001 /* Echo cancellation and/or noise reduction */
#define BTA_HF_CLIENT_FEAT_3WAY 0x00000002 /* Call waiting and three-way calling */
#define BTA_HF_CLIENT_FEAT_CLI 0x00000004 /* Caller ID presentation capability */
#define BTA_HF_CLIENT_FEAT_VREC 0x00000008 /* Voice recognition activation */
#define BTA_HF_CLIENT_FEAT_VOL 0x00000010 /* Remote volume control */
#define BTA_HF_CLIENT_FEAT_ECS 0x00000020 /* Enhanced Call Status */
#define BTA_HF_CLIENT_FEAT_ECC 0x00000040 /* Enhanced Call Control */
#define BTA_HF_CLIENT_FEAT_CODEC 0x00000080 /* Codec Negotiation */
/* HFP HF extended call handling - masks not related to any spec */
#define BTA_HF_CLIENT_CHLD_REL 0x00000001 /* 0 Release waiting call or held calls */
#define BTA_HF_CLIENT_CHLD_REL_ACC 0x00000002 /* 1 Release active calls and accept other (waiting or held) cal */
#define BTA_HF_CLIENT_CHLD_REL_X 0x00000004 /* 1x Release x call*/
#define BTA_HF_CLIENT_CHLD_HOLD_ACC 0x00000008 /* 2 Active calls on hold and accept other call */
#define BTA_HF_CLIENT_CHLD_PRIV_X 0x00000010 /* 2x Active multiparty call on hold except call x */
#define BTA_HF_CLIENT_CHLD_MERGE 0x00000020 /* 3 Add held call to multiparty */
#define BTA_HF_CLIENT_CHLD_MERGE_DETACH 0x00000040 /* 4 Add held call to multiparty */
typedef UINT16 tBTA_HF_CLIENT_CHLD_FEAT;
/* HFP AG errors ot OK sent to HF Unit */
#define BTA_HF_CLIENT_AT_RESULT_OK 0
#define BTA_HF_CLIENT_AT_RESULT_ERROR 1
#define BTA_HF_CLIENT_AT_RESULT_NO_CARRIER 2
#define BTA_HF_CLIENT_AT_RESULT_BUSY 3
#define BTA_HF_CLIENT_AT_RESULT_NO_ANSWER 4
#define BTA_HF_CLIENT_AT_RESULT_DELAY 5
#define BTA_HF_CLIENT_AT_RESULT_BLACKLISTED 6
#define BTA_HF_CLIENT_AT_RESULT_CME 7
typedef UINT8 tBTA_HF_CLIENT_AT_RESULT_TYPE;
/* HF Client callback events */
#define BTA_HF_CLIENT_ENABLE_EVT 0 /* HF Client enabled */
#define BTA_HF_CLIENT_REGISTER_EVT 1 /* HF Client registered */
#define BTA_HF_CLIENT_OPEN_EVT 2 /* HF Client connection open */
#define BTA_HF_CLIENT_CLOSE_EVT 3 /* HF Client connection closed */
#define BTA_HF_CLIENT_CONN_EVT 4 /* Service level connection opened */
#define BTA_HF_CLIENT_AUDIO_OPEN_EVT 5 /* Audio connection open */
#define BTA_HF_CLIENT_AUDIO_MSBC_OPEN_EVT 6 /* Audio connection with mSBC codec open */
#define BTA_HF_CLIENT_AUDIO_CLOSE_EVT 7 /* Audio connection closed */
#define BTA_HF_CLIENT_SPK_EVT 8 /* Speaker volume changed */
#define BTA_HF_CLIENT_MIC_EVT 9 /* Microphone volume changed */
#define BTA_HF_CLIENT_IND_EVT 10 /* Indicator */
#define BTA_HF_CLIENT_VOICE_REC_EVT 11 /* AG changed voice recognition setting */
#define BTA_HF_CLIENT_OPERATOR_NAME_EVT 12 /* Operator name acquired */
#define BTA_HF_CLIENT_CLIP_EVT 13 /* Calling line identification event */
#define BTA_HF_CLIENT_CCWA_EVT 14 /* Call waiting notification */
#define BTA_HF_CLIENT_AT_RESULT_EVT 15 /* Call waiting notification */
#define BTA_HF_CLIENT_CLCC_EVT 16 /* current call event */
#define BTA_HF_CLIENT_CNUM_EVT 17 /* subscriber information event */
#define BTA_HF_CLIENT_BTRH_EVT 18 /* bluetooth response and hold event */
#define BTA_HF_CLIENT_BSIR_EVT 19 /* in-band ring tone setting changed event */
#define BTA_HF_CLIENT_BINP_EVT 20 /* binp number event */
#define BTA_HF_CLIENT_RING_INDICATION 21 /* HF Client ring indication */
#define BTA_HF_CLIENT_DISABLE_EVT 30 /* HF Client disabled */
typedef UINT8 tBTA_HF_CLIENT_EVT;
/* HF Client open status */
#define BTA_HF_CLIENT_SUCCESS 0 /* Connection successfully opened */
#define BTA_HF_CLIENT_FAIL_SDP 1 /* Open failed due to SDP */
#define BTA_HF_CLIENT_FAIL_RFCOMM 2 /* Open failed due to RFCOMM */
#define BTA_HF_CLIENT_FAIL_RESOURCES 3 /* out of resources failure */
typedef UINT8 tBTA_HF_CLIENT_STATUS;
/* indicator type */
#define BTA_HF_CLIENT_IND_BATTCH 0 /* Battery charge indicator */
#define BTA_HF_CLIENT_IND_SIGNAL 1 /* Signal Strength indicator */
#define BTA_HF_CLIENT_IND_SERVICE 2 /* Service availability indicator */
#define BTA_HF_CLIENT_IND_CALL 3 /* Standard call status indicator*/
#define BTA_HF_CLIENT_IND_ROAM 4 /* Roaming status indicator */
#define BTA_HF_CLIENT_IND_CALLSETUP 5 /* Call setup status indicator */
#define BTA_HF_CLIENT_IND_CALLHELD 6 /* Call hold status indicator */
typedef UINT8 tBTA_HF_CLIENT_IND_TYPE;
/* AT commands */
#define BTA_HF_CLIENT_AT_CMD_VTS 0
#define BTA_HF_CLIENT_AT_CMD_BTRH 1
#define BTA_HF_CLIENT_AT_CMD_CHUP 2
#define BTA_HF_CLIENT_AT_CMD_CHLD 3
#define BTA_HF_CLIENT_AT_CMD_BCC 4
#define BTA_HF_CLIENT_AT_CMD_CNUM 5
#define BTA_HF_CLIENT_AT_CMD_ATA 6
#define BTA_HF_CLIENT_AT_CMD_COPS 7
#define BTA_HF_CLIENT_AT_CMD_ATD 8
#define BTA_HF_CLIENT_AT_CMD_VGM 9
#define BTA_HF_CLIENT_AT_CMD_VGS 10
#define BTA_HF_CLIENT_AT_CMD_BVRA 11
#define BTA_HF_CLIENT_AT_CMD_CLCC 12
#define BTA_HF_CLIENT_AT_CMD_BINP 13
#define BTA_HF_CLIENT_AT_CMD_BLDN 14
#define BTA_HF_CLIENT_AT_CMD_NREC 15
typedef UINT8 tBTA_HF_CLIENT_AT_CMD_TYPE;
/* data associated with most non-AT events */
/* placeholder, if not needed should be removed*/
typedef struct {
} tBTA_HF_CLIENT_HDR;
/* data associated with BTA_HF_CLIENT_REGISTER_EVT */
typedef struct {
tBTA_HF_CLIENT_HDR hdr;
UINT16 handle;
tBTA_HF_CLIENT_STATUS status;
} tBTA_HF_CLIENT_REGISTER;
/* data associated with BTA_HF_CLIENT_OPEN_EVT */
typedef struct {
tBTA_HF_CLIENT_HDR hdr;
BD_ADDR bd_addr;
tBTA_HF_CLIENT_STATUS status;
} tBTA_HF_CLIENT_OPEN;
/* data associated with BTA_HF_CLIENT_CONN_EVT */
typedef struct {
tBTA_HF_CLIENT_HDR hdr;
tBTA_HF_CLIENT_PEER_FEAT peer_feat;
tBTA_HF_CLIENT_CHLD_FEAT chld_feat;
} tBTA_HF_CLIENT_CONN;
/* data associated with BTA_HF_CLIENT_IND_EVT event */
typedef struct {
tBTA_HF_CLIENT_HDR hdr;
tBTA_HF_CLIENT_IND_TYPE type;
UINT16 value;
} tBTA_HF_CLIENT_IND;
/* data associated with BTA_HF_CLIENT_OPERATOR_NAME_EVT */
#define BTA_HF_CLIENT_OPERATOR_NAME_LEN 16
typedef struct {
char name[BTA_HF_CLIENT_OPERATOR_NAME_LEN + 1];
} tBTA_HF_CLIENT_OPERATOR_NAME;
/* data associated with BTA_HF_CLIENT_CLIP_EVT and BTA_HF_CLIENT_CCWA_EVT*/
#define BTA_HF_CLIENT_NUMBER_LEN 32
typedef struct {
char number[BTA_HF_CLIENT_NUMBER_LEN + 1];
} tBTA_HF_CLIENT_NUMBER;
/* data associated with BTA_HF_CLIENT_AT_RESULT_EVT event */
typedef struct {
tBTA_HF_CLIENT_AT_RESULT_TYPE type;
UINT16 cme;
} tBTA_HF_CLIENT_AT_RESULT;
/* data associated with BTA_HF_CLIENT_CLCC_EVT event */
typedef struct {
UINT32 idx;
BOOLEAN inc;
UINT8 status;
BOOLEAN mpty;
BOOLEAN number_present;
char number[BTA_HF_CLIENT_NUMBER_LEN + 1];
} tBTA_HF_CLIENT_CLCC;
/* data associated with BTA_HF_CLIENT_CNUM_EVT event */
typedef struct {
UINT16 service;
char number[BTA_HF_CLIENT_NUMBER_LEN + 1];
} tBTA_HF_CLIENT_CNUM;
/* data associated with other events */
typedef struct {
UINT16 value;
} tBTA_HF_CLIENT_VAL;
/* union of data associated with AG callback */
typedef union {
tBTA_HF_CLIENT_HDR hdr;
tBTA_HF_CLIENT_REGISTER reg;
tBTA_HF_CLIENT_OPEN open;
tBTA_HF_CLIENT_CONN conn;
tBTA_HF_CLIENT_IND ind;
tBTA_HF_CLIENT_VAL val;
tBTA_HF_CLIENT_OPERATOR_NAME operator;
tBTA_HF_CLIENT_NUMBER number;
tBTA_HF_CLIENT_AT_RESULT result;
tBTA_HF_CLIENT_CLCC clcc;
tBTA_HF_CLIENT_CNUM cnum;
} tBTA_HF_CLIENT;
typedef UINT32 tBTA_HF_CLIENT_FEAT;
/* HF Client callback */
typedef void (tBTA_HF_CLIENT_CBACK)(tBTA_HF_CLIENT_EVT event, void *p_data);
#ifdef __cplusplus
extern "C"
{
#endif
/*****************************************************************************
** External Function Declarations
*****************************************************************************/
/*******************************************************************************
**
** Function BTA_HfClientEnable
**
** Description Enable the HF CLient service. When the enable
** operation is complete the callback function will be
** called with a BTA_HF_CLIENT_ENABLE_EVT. This function must
** be called before other function in the HF CLient API are
** called.
**
** Returns BTA_SUCCESS if OK, BTA_FAILURE otherwise.
**
*******************************************************************************/
tBTA_STATUS BTA_HfClientEnable(tBTA_HF_CLIENT_CBACK *p_cback);
/*******************************************************************************
**
** Function BTA_HfClientDisable
**
** Description Disable the HF Client service
**
**
** Returns void
**
*******************************************************************************/
void BTA_HfClientDisable(void);
/*******************************************************************************
**
** Function BTA_HfClientRegister
**
** Description Register an HF Client service.
**
**
** Returns void
**
*******************************************************************************/
void BTA_HfClientRegister(tBTA_SEC sec_mask, tBTA_HF_CLIENT_FEAT features,
char *p_service_name);
/*******************************************************************************
**
** Function BTA_HfClientDeregister
**
** Description Deregister an HF Client service.
**
**
** Returns void
**
*******************************************************************************/
void BTA_HfClientDeregister(UINT16 handle);
/*******************************************************************************
**
** Function BTA_HfClientOpen
**
** Description Opens a connection to an audio gateway.
** When connection is open callback function is called
** with a BTA_HF_CLIENT_OPEN_EVT. Only the data connection is
** opened. The audio connection is not opened.
**
**
** Returns void
**
*******************************************************************************/
void BTA_HfClientOpen(UINT16 handle, BD_ADDR bd_addr, tBTA_SEC sec_mask);
/*******************************************************************************
**
** Function BTA_HfClientClose
**
** Description Close the current connection to an audio gateway.
** Any current audio connection will also be closed
**
**
** Returns void
**
*******************************************************************************/
void BTA_HfClientClose(UINT16 handle);
/*******************************************************************************
**
** Function BTA_HfCllientAudioOpen
**
** Description Opens an audio connection to the currently connected
** audio gateway
**
**
** Returns void
**
*******************************************************************************/
void BTA_HfClientAudioOpen(UINT16 handle);
/*******************************************************************************
**
** Function BTA_HfClientAudioClose
**
** Description Close the currently active audio connection to an audio
** gateway. The data connection remains open
**
**
** Returns void
**
*******************************************************************************/
void BTA_HfClientAudioClose(UINT16 handle);
/*******************************************************************************
**
** Function BTA_HfClientSendAT
**
** Description send AT command
**
**
** Returns void
**
*******************************************************************************/
void BTA_HfClientSendAT(UINT16 handle, tBTA_HF_CLIENT_AT_CMD_TYPE at, UINT32 val1, UINT32 val2, const char *str);
#if (BTM_SCO_HCI_INCLUDED == TRUE )
void BTA_HfClientCiData(void);
#endif /*#if (BTM_SCO_HCI_INCLUDED == TRUE ) */
int BTA_HfClientGetCbDataSize(tBTA_HF_CLIENT_EVT event);
#ifdef __cplusplus
}
#endif
#endif /* #if (BTA_HF_INCLUDED == TRUE) */
#endif /* BTA_HF_CLIENT_API_H */

View file

@ -0,0 +1,115 @@
// Copyright 2018 Espressif Systems (Shanghai) PTE LTD
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
/******************************************************************************
*
* This is the interface file for hf client call-out functions.
*
******************************************************************************/
#ifndef BTA_HF_CLIENT_CO_H
#define BTA_HF_CLIENT_CO_H
#include "common/bt_target.h"
#include "bta/bta_hf_client_api.h"
#if (BTA_HF_INCLUDED == TRUE)
#if (BTM_SCO_HCI_INCLUDED == TRUE)
/*******************************************************************************
**
** Function bta_hf_client_co_audio_state
**
** Description This function is called by the HF CLIENT before the audio connection
** is brought up, after it comes up, and after it goes down.
**
** Parameters handle - handle of the AG instance
** state - Audio state
** codec - if WBS support is compiled in, codec to going to be used is provided
** and when in SCO_STATE_SETUP, BTM_I2SPCMConfig() must be called with
** the correct platform parameters.
** in the other states codec type should not be ignored
**
** Returns void
**
*******************************************************************************/
void bta_hf_client_co_audio_state(UINT16 handle, UINT8 state, tBTA_HFP_PEER_CODEC codec);
/*******************************************************************************
**
** Function bta_hf_client_sco_co_init
**
** Description This function can be used by the phone to initialize audio
** codec or for other initialization purposes before SCO connection
** is opened.
**
**
** Returns Void.
**
*******************************************************************************/
tBTA_HFP_SCO_ROUTE_TYPE bta_hf_client_sco_co_init(UINT32 rx_bw, UINT32 tx_bw,
tBTA_HFP_CODEC_INFO *p_codec_info, UINT8 app_id);
/*******************************************************************************
**
** Function bta_hf_client_sco_co_open
**
** Description This function is executed when a SCO connection is open.
**
**
** Returns void
**
*******************************************************************************/
void bta_hf_client_sco_co_open(UINT16 handle, UINT8 pkt_size, UINT16 event);
/*******************************************************************************
**
** Function bta_hf_client_sco_co_close
**
** Description This function is called when a SCO connection is closed
**
**
** Returns void
**
*******************************************************************************/
void bta_hf_client_sco_co_close(void);
/*******************************************************************************
**
** Function bta_hf_client_sco_co_out_data
**
** Description This function is called to send SCO data over HCI.
**
** Returns number of bytes got from application
**
*******************************************************************************/
uint32_t bta_hf_client_sco_co_out_data(uint8_t *p_buf, uint32_t sz);
/*******************************************************************************
**
** Function bta_hf_client_sco_co_in_data
**
** Description This function is called to send incoming SCO data to application.
**
** Returns void
**
*******************************************************************************/
extern void bta_hf_client_sco_co_in_data(BT_HDR *p_buf, tBTM_SCO_DATA_FLAG status);
#endif /* #if (BTM_SCO_HCI_INCLUDED == TRUE) */
#endif /* #if (BTA_HF_INCLUDED == TRUE) */
#endif /* BTA_HF_CLIENT_CO_H */

View file

@ -0,0 +1,47 @@
// Copyright 2018 Espressif Systems (Shanghai) PTE LTD
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef __BTA_HFP_DEFS_H__
#define __BTA_HFP_DEFS_H__
#include "stack/btm_api.h"
#define BTA_HFP_CODEC_NONE BTM_SCO_CODEC_NONE
#define BTA_HFP_CODEC_CVSD BTM_SCO_CODEC_CVSD /* CVSD */
#define BTA_HFP_CODEC_MSBC BTM_SCO_CODEC_MSBC /* mSBC */
typedef UINT16 tBTA_HFP_PEER_CODEC;
#ifndef BTA_HFP_SCO_OUT_PKT_SIZE
#define BTA_HFP_SCO_OUT_PKT_SIZE BTM_SCO_DATA_SIZE_MAX
#endif
#define BTA_HFP_SCO_CODEC_PCM 0 /* used for regular SCO */
#define BTA_HFP_SCO_CODEC_SBC 1 /* used for WBS */
typedef UINT8 tBTA_HFP_SCO_CODEC_TYPE;
#define BTA_HFP_SCO_SAMP_RATE_8K 8000
#define BTA_HFP_SCO_SAMP_RATE_16K 16000
/* SCO codec information */
typedef struct {
tBTA_HFP_SCO_CODEC_TYPE codec_type;
} tBTA_HFP_CODEC_INFO;
#define BTA_HFP_SCO_ROUTE_PCM BTM_SCO_ROUTE_PCM
#define BTA_HFP_SCO_ROUTE_HCI BTM_SCO_ROUTE_HCI
typedef tBTM_SCO_ROUTE_TYPE tBTA_HFP_SCO_ROUTE_TYPE;
#endif /* __BTA_HFP_DEFS_H__ */

View file

@ -57,6 +57,9 @@ static btc_dm_local_key_cb_t ble_local_key_cb;
extern bt_status_t btc_av_execute_service(BOOLEAN b_enable);
extern bt_status_t btc_av_sink_execute_service(BOOLEAN b_enable);
#endif
#if BTC_HF_CLIENT_INCLUDED
extern bt_status_t btc_hf_client_execute_service(BOOLEAN b_enable);
#endif
/******************************************************************************
** Functions
******************************************************************************/
@ -396,6 +399,11 @@ static bt_status_t btc_in_execute_service_request(tBTA_SERVICE_ID service_id,
btc_av_sink_execute_service(b_enable);
break;
#endif
#if BTC_HF_CLIENT_INCLUDED
case BTA_HFP_HS_SERVICE_ID:
btc_hf_client_execute_service(b_enable);
break;
#endif /* #if BTC_HF_CLIENT_INCLUDED */
default:
BTC_TRACE_ERROR("%s: Unknown service being enabled\n", __FUNCTION__);
return BT_STATUS_FAIL;

View file

@ -42,6 +42,9 @@
#if CONFIG_BT_SPP_ENABLED
#include "btc_spp.h"
#endif /* #if CONFIG_BT_SPP_ENABLED */
#if BTC_HF_CLIENT_INCLUDED
#include "btc_hf_client.h"
#endif /* #if BTC_HF_CLIENT_INCLUDED */
#endif /* #if CONFIG_CLASSIC_BT_ENABLED */
@ -80,6 +83,9 @@ static btc_func_t profile_tab[BTC_PID_NUM] = {
#if CONFIG_BT_SPP_ENABLED
[BTC_PID_SPP] = {btc_spp_call_handler, btc_spp_cb_handler },
#endif /* #if CONFIG_BT_SPP_ENABLED */
#if BTC_HF_CLIENT_INCLUDED
[BTC_PID_HF_CLIENT] = {btc_hf_client_call_handler, btc_hf_client_cb_handler},
#endif /* #if BTC_HF_CLIENT_INCLUDED */
#endif /* #if CONFIG_CLASSIC_BT_ENABLED */
};

View file

@ -54,6 +54,9 @@ typedef enum {
BTC_PID_A2DP,
BTC_PID_AVRC,
BTC_PID_SPP,
#if BTC_HF_CLIENT_INCLUDED
BTC_PID_HF_CLIENT,
#endif /* BTC_HF_CLIENT_INCLUDED */
#endif /* CONFIG_CLASSIC_BT_ENABLED */
BTC_PID_NUM,
} btc_pid_t; //btc profile id

View file

@ -0,0 +1,137 @@
// Copyright 2018 Espressif Systems (Shanghai) PTE LTD
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#include "bta/bta_hf_client_co.h"
#include "hci/hci_audio.h"
#include "btc_hf_client.h"
#if (BTA_HF_INCLUDED == TRUE)
#if (BTM_SCO_HCI_INCLUDED == TRUE)
/*******************************************************************************
**
** Function bta_hf_client_co_audio_state
**
** Description This function is called by the HF CLIENT before the audio connection
** is brought up, after it comes up, and after it goes down.
**
** Parameters handle - handle of the AG instance
** state - Audio state
** codec - if WBS support is compiled in, codec to going to be used is provided
** and when in SCO_STATE_SETUP, BTM_I2SPCMConfig() must be called with
** the correct platform parameters.
** in the other states codec type should not be ignored
**
** Returns void
**
*******************************************************************************/
void bta_hf_client_co_audio_state(UINT16 handle, UINT8 state, tBTA_HFP_PEER_CODEC codec)
{
switch (state)
{
case SCO_STATE_ON:
case SCO_STATE_OFF:
case SCO_STATE_OFF_TRANSFER:
case SCO_STATE_SETUP:
default:
break;
}
}
/*******************************************************************************
**
** Function bta_hf_client_sco_co_init
**
** Description This function can be used by the phone to initialize audio
** codec or for other initialization purposes before SCO connection
** is opened.
**
**
** Returns Void.
**
*******************************************************************************/
tBTA_HFP_SCO_ROUTE_TYPE bta_hf_client_sco_co_init(UINT32 rx_bw, UINT32 tx_bw,
tBTA_HFP_CODEC_INFO *p_codec_info, UINT8 app_id)
{
APPL_TRACE_EVENT("%s rx_bw %d, tx_bw %d, codec %d", __FUNCTION__, rx_bw, tx_bw,
p_codec_info->codec_type);
return BTA_HFP_SCO_ROUTE_HCI;
}
/*******************************************************************************
**
** Function bta_hf_client_sco_co_open
**
** Description This function is executed when a SCO connection is open.
**
**
** Returns void
**
*******************************************************************************/
void bta_hf_client_sco_co_open(UINT16 handle, UINT8 pkt_size, UINT16 event)
{
APPL_TRACE_EVENT("%s hdl %x, pkt_sz %u, event %u", __FUNCTION__, handle,
pkt_size, event);
}
/*******************************************************************************
**
** Function bta_hf_client_sco_co_close
**
** Description This function is called when a SCO connection is closed
**
**
** Returns void
**
*******************************************************************************/
void bta_hf_client_sco_co_close(void)
{
APPL_TRACE_EVENT("%s", __FUNCTION__);
}
/*******************************************************************************
**
** Function bta_hf_client_sco_co_out_data
**
** Description This function is called to send SCO data over HCI.
**
** Returns number of bytes got from application
**
*******************************************************************************/
uint32_t bta_hf_client_sco_co_out_data(uint8_t *p_buf, uint32_t sz)
{
return btc_hf_client_outgoing_data_cb_to_app(p_buf, sz);
}
/*******************************************************************************
**
** Function bta_hf_client_sco_co_in_data
**
** Description This function is called to send incoming SCO data to application.
**
** Returns void
**
*******************************************************************************/
void bta_hf_client_sco_co_in_data(BT_HDR *p_buf, tBTM_SCO_DATA_FLAG status)
{
UINT8 *p = (UINT8 *)(p_buf + 1) + p_buf->offset;
UINT8 pkt_size = 0;
STREAM_SKIP_UINT16(p);
STREAM_TO_UINT8 (pkt_size, p);
btc_hf_client_incoming_data_cb_to_app(p, pkt_size);
}
#endif /* #if (BTM_SCO_HCI_INCLUDED == TRUE) */
#endif /* #if (BTA_HF_INCLUDED == TRUE) */

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,128 @@
// Copyright 2018 Espressif Systems (Shanghai) PTE LTD
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
/*******************************************************************************
*
* Filename: btc_hf_client.h
*
* Description: Main API header file for all BTC HF client functions accessed
* from internal stack.
*
*******************************************************************************/
#ifndef __BTC_HF_CLIENT_H__
#define __BTC_HF_CLIENT_H__
#include "common/bt_target.h"
#include "esp_hf_client_api.h"
#include "btc/btc_task.h"
#include "btc/btc_common.h"
#include "bta/bta_hf_client_api.h"
#if (BTC_HF_CLIENT_INCLUDED == TRUE)
/*******************************************************************************
** Type definitions for callback functions
********************************************************************************/
typedef enum {
BTC_HF_CLIENT_INIT_EVT,
BTC_HF_CLIENT_DEINIT_EVT,
BTC_HF_CLIENT_CONNECT_EVT,
BTC_HF_CLIENT_DISCONNECT_EVT,
BTC_HF_CLIENT_CONNECT_AUDIO_EVT,
BTC_HF_CLIENT_DISCONNECT_AUDIO_EVT,
BTC_HF_CLIENT_START_VOICE_RECOGNITION_EVT,
BTC_HF_CLIENT_STOP_VOICE_RECOGNITION_EVT,
BTC_HF_CLIENT_VOLUME_UPDATE_EVT,
BTC_HF_CLIENT_DIAL_EVT,
BTC_HF_CLIENT_DIAL_MEMORY_EVT,
BTC_HF_CLIENT_SEND_CHLD_CMD_EVT,
BTC_HF_CLIENT_SEND_BTRH_CMD_EVT,
BTC_HF_CLIENT_ANSWER_CALL_EVT,
BTC_HF_CLIENT_REJECT_CALL_EVT,
BTC_HF_CLIENT_QUERY_CURRENT_CALLS_EVT,
BTC_HF_CLIENT_QUERY_CURRENT_OPERATOR_NAME_EVT,
BTC_HF_CLIENT_RETRIEVE_SUBSCRIBER_INFO_EVT,
BTC_HF_CLIENT_SEND_DTMF_EVT,
BTC_HF_CLIENT_REQUEST_LAST_VOICE_TAG_NUMBER_EVT,
BTC_HF_CLIENT_REGISTER_DATA_CALLBACK_EVT,
} btc_hf_client_act_t;
/* btc_hf_client_args_t */
typedef union {
// BTC_HF_CLIENT_CONNECT_EVT
bt_bdaddr_t connect;
// BTC_HF_CLIENT_DISCONNECT_EVT
bt_bdaddr_t disconnect;
// BTC_HF_CLIENT_CONNECT_AUDIO_EVT
bt_bdaddr_t connect_audio;
// BTC_HF_CLIENT_DISCONNECT_AUDIO_EVT
bt_bdaddr_t disconnect_audio;
// BTC_HF_CLIENT_VOLUME_UPDATE_EVT,
struct volume_update_args {
esp_hf_volume_control_target_t type;
int volume;
} volume_update;
// BTC_HF_CLIENT_DIAL_EVT
struct dial_args {
char number[ESP_BT_HF_CLIENT_NUMBER_LEN + 1];
} dial;
// BTC_HF_CLIENT_DIAL_MEMORY_EVT
struct dial_memory_args {
int location;
} dial_memory;
// BTC_HF_CLIENT_SEND_CHLD_CMD_EVT
struct send_chld_cmd_args {
esp_hf_chld_type_t type;
int idx;
} chld;
// BTC_HF_CLIENT_SEND_BTRH_CMD_EVT
struct send_btrh_cmd_args {
esp_hf_btrh_cmd_t cmd;
} btrh;
// BTC_HF_CLIENT_SEND_DTMF_EVT
struct send_dtmf {
char code;
} send_dtmf;
// BTC_HF_CLIENT_REGISTER_DATA_CALLBACK_EVT
struct reg_data_callback {
esp_hf_client_incoming_data_cb_t recv;
esp_hf_client_outgoing_data_cb_t send;
} reg_data_cb;
} btc_hf_client_args_t;
/*******************************************************************************
** BTC HF AG API
********************************************************************************/
void btc_hf_client_call_handler(btc_msg_t *msg);
void btc_hf_client_cb_handler(btc_msg_t *msg);
void btc_hf_client_incoming_data_cb_to_app(const uint8_t *data, uint32_t len);
uint32_t btc_hf_client_outgoing_data_cb_to_app(uint8_t *data, uint32_t len);
#endif ///BTC_HF_CLIENT_INCLUDED == TRUE
#endif /* __BTC_HF_CLIENT_H__ */

View file

@ -50,6 +50,7 @@
#define BTC_PRF_QUEUE_INCLUDED TRUE
#define BTC_GAP_BT_INCLUDED TRUE
#define BTA_SDP_INCLUDED TRUE
#define BTA_DM_PM_INCLUDED TRUE
#define SDP_INCLUDED TRUE
#if CONFIG_A2DP_ENABLE
@ -79,6 +80,20 @@
#define BTC_SPP_INCLUDED TRUE
#endif /* CONFIG_BT_SPP_ENABLED */
#if CONFIG_HFP_CLIENT_ENABLE
#define BTC_HF_CLIENT_INCLUDED TRUE
#define BTA_HF_INCLUDED TRUE
#ifndef RFCOMM_INCLUDED
#define RFCOMM_INCLUDED TRUE
#endif
#ifndef BTM_SCO_INCLUDED
#define BTM_SCO_INCLUDED TRUE
#endif
#ifndef BTM_MAX_SCO_LINKS
#define BTM_MAX_SCO_LINKS (1)
#endif
#endif /* CONFIG_HFP_HF_ENABLE */
#endif /* #if CONFIG_CLASSIC_BT_ENABLED */
#ifndef CLASSIC_BT_INCLUDED
@ -190,6 +205,10 @@
#define BTA_INCLUDED TRUE
#endif
#ifndef BTA_DM_PM_INCLUDED
#define BTA_DM_PM_INCLUDED FALSE
#endif
#ifndef BTA_PAN_INCLUDED
#define BTA_PAN_INCLUDED FALSE
#endif
@ -491,12 +510,16 @@
/* Includes SCO if TRUE */
#ifndef BTM_SCO_INCLUDED
#define BTM_SCO_INCLUDED FALSE //TRUE /* TRUE includes SCO code */
#define BTM_SCO_INCLUDED FALSE /* TRUE includes SCO code */
#endif
/* Includes SCO if TRUE */
#ifndef BTM_SCO_HCI_INCLUDED
#define BTM_SCO_HCI_INCLUDED FALSE /* TRUE includes SCO over HCI code */
#if CONFIG_HFP_AUDIO_DATA_PATH_HCI
#define BTM_SCO_HCI_INCLUDED TRUE /* TRUE includes SCO over HCI code */
#else
#define BTM_SCO_HCI_INCLUDED FALSE
#endif /* CONFIG_HFP_AUDIO_DATA_PATH_HCI */
#endif
/* Includes WBS if TRUE */
@ -516,7 +539,7 @@
*************************/
/* max TX SCO data packet size */
#ifndef BTM_SCO_DATA_SIZE_MAX
#define BTM_SCO_DATA_SIZE_MAX 240
#define BTM_SCO_DATA_SIZE_MAX 120 //240
#endif
/* The size in bytes of the BTM inquiry database. 5 As Default */
@ -580,11 +603,7 @@
/* The number of SCO links. */
#ifndef BTM_MAX_SCO_LINKS
#if (CLASSIC_BT_INCLUDED == TRUE)
#define BTM_MAX_SCO_LINKS 1 //3
#else ///CLASSIC_BT_INCLUDED == TRUE
#define BTM_MAX_SCO_LINKS 0
#endif ///CLASSIC_BT_INCLUDED == TRUE
#define BTM_MAX_SCO_LINKS 0 //3
#endif
/* The preferred type of SCO links (2-eSCO, 0-SCO). */
@ -656,7 +675,7 @@
/* This is set to TRUE if link is to be unparked due to BTM_CreateSCO API. */
#ifndef BTM_SCO_WAKE_PARKED_LINK
#define BTM_SCO_WAKE_PARKED_LINK TRUE
#define BTM_SCO_WAKE_PARKED_LINK FALSE
#endif
/* If the user does not respond to security process requests within this many seconds,
@ -710,9 +729,11 @@
#endif
/* TRUE to include Sniff Subrating */
#if (BTA_DM_PM_INCLUDED == TRUE)
#ifndef BTM_SSR_INCLUDED
#define BTM_SSR_INCLUDED FALSE
#endif
#endif /* BTA_DM_PM_INCLUDED */
/*************************
** End of Lisbon Features

View file

@ -16,6 +16,7 @@
*
******************************************************************************/
#include <stdbool.h>
#include "common/bt_target.h"
#include "common/bt_trace.h"
#include "device/bdaddr.h"
#include "stack/bt_types.h"
@ -61,6 +62,9 @@ static uint16_t acl_data_size_ble;
static uint16_t acl_buffer_count_classic;
static uint8_t acl_buffer_count_ble;
static uint8_t sco_data_size;
static uint16_t sco_buffer_count;
static uint8_t ble_white_list_size;
static uint8_t ble_resolving_list_max_size;
static uint8_t ble_supported_states[BLE_SUPPORTED_STATES_SIZE];
@ -88,7 +92,8 @@ static void start_up(void)
// Request the classic buffer size next
response = AWAIT_COMMAND(packet_factory->make_read_buffer_size());
packet_parser->parse_read_buffer_size_response(
response, &acl_data_size_classic, &acl_buffer_count_classic);
response, &acl_data_size_classic, &acl_buffer_count_classic,
&sco_data_size, &sco_buffer_count);
// Tell the controller about our buffer sizes and buffer counts next
// TODO(zachoverflow): factor this out. eww l2cap contamination. And why just a hardcoded 10?
@ -244,6 +249,10 @@ static void start_up(void)
packet_parser->parse_generic_command_complete(response);
}
#if (BTM_SCO_HCI_INCLUDED == TRUE)
response = AWAIT_COMMAND(packet_factory->make_write_sync_flow_control_enable(1));
packet_parser->parse_generic_command_complete(response);
#endif
readable = true;
// return future_new_immediate(FUTURE_SUCCESS);
return;
@ -447,6 +456,20 @@ static void set_ble_resolving_list_max_size(int resolving_list_max_size)
ble_resolving_list_max_size = resolving_list_max_size;
}
#if (BTM_SCO_HCI_INCLUDED == TRUE)
static uint8_t get_sco_data_size(void)
{
assert(readable);
return sco_data_size;
}
static uint8_t get_sco_buffer_count(void)
{
assert(readable);
return sco_buffer_count;
}
#endif /* (BTM_SCO_HCI_INCLUDED == TRUE) */
static const controller_t interface = {
start_up,
shut_down,
@ -489,7 +512,11 @@ static const controller_t interface = {
get_ble_white_list_size,
get_ble_resolving_list_max_size,
set_ble_resolving_list_max_size
set_ble_resolving_list_max_size,
#if (BTM_SCO_HCI_INCLUDED == TRUE)
get_sco_data_size,
get_sco_buffer_count,
#endif /* (BTM_SCO_HCI_INCLUDED == TRUE) */
};
const controller_t *controller_get_interface()

View file

@ -79,6 +79,11 @@ typedef struct controller_t {
uint8_t (*get_ble_resolving_list_max_size)(void);
void (*set_ble_resolving_list_max_size)(int resolving_list_max_size);
#if (BTM_SCO_HCI_INCLUDED == TRUE)
// Get the number of sco packets the controller can buffer
uint8_t (*get_sco_data_size)(void);
uint8_t (*get_sco_buffer_count)(void);
#endif /* #if (BTM_SCO_HCI_INCLUDED == TRUE) */
} controller_t;
const controller_t *controller_get_interface();

View file

@ -0,0 +1,7 @@
#include "hci/hci_audio.h"
void set_audio_state(uint16_t handle, sco_codec_t codec, sco_state_t state)
{
//todo
return;
}

View file

@ -175,6 +175,15 @@ static BT_HDR *make_ble_set_event_mask(const bt_event_mask_t *event_mask)
return packet;
}
static BT_HDR *make_write_sync_flow_control_enable(uint8_t enable)
{
uint8_t *stream;
const uint8_t parameter_size = 1;
BT_HDR *packet = make_command(HCI_WRITE_SCO_FLOW_CTRL_ENABLE, parameter_size, &stream);
UINT8_TO_STREAM(stream, enable);
return packet;
}
// Internal functions
static BT_HDR *make_command_no_params(uint16_t opcode)
@ -227,7 +236,8 @@ static const hci_packet_factory_t interface = {
make_ble_read_resolving_list_size,
make_ble_read_suggested_default_data_length,
make_ble_write_suggested_default_data_length,
make_ble_set_event_mask
make_ble_set_event_mask,
make_write_sync_flow_control_enable
};
const hci_packet_factory_t *hci_packet_factory_get_interface()

View file

@ -42,16 +42,18 @@ static void parse_generic_command_complete(BT_HDR *response)
static void parse_read_buffer_size_response(
BT_HDR *response,
uint16_t *data_size_ptr,
uint16_t *acl_buffer_count_ptr)
uint16_t *acl_data_size_ptr,
uint16_t *acl_buffer_count_ptr,
uint8_t *sco_data_size_ptr,
uint16_t *sco_buffer_count_ptr)
{
uint8_t *stream = read_command_complete_header(response, HCI_READ_BUFFER_SIZE, 5 /* bytes after */);
uint8_t *stream = read_command_complete_header(response, HCI_READ_BUFFER_SIZE, 7 /* bytes after */);
assert(stream != NULL);
STREAM_TO_UINT16(*data_size_ptr, stream);
STREAM_SKIP_UINT8(stream); // skip the sco packet length
STREAM_TO_UINT16(*acl_data_size_ptr, stream);
STREAM_TO_UINT8(*sco_data_size_ptr, stream);
STREAM_TO_UINT16(*acl_buffer_count_ptr, stream);
STREAM_TO_UINT16(*sco_buffer_count_ptr, stream);
buffer_allocator->free(response);
}

View file

@ -0,0 +1,42 @@
/******************************************************************************
*
* Copyright (C) 2015 Google, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at:
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
******************************************************************************/
#ifndef _HCI_AUDIO_H_
#define _HCI_AUDIO_H_
#include <stdint.h>
// Audio state definitions.
typedef enum {
SCO_STATE_OFF = 0, // Audio is off.
SCO_STATE_OFF_TRANSFER, // Closed pending final transfer of audio.
SCO_STATE_ON, // Audio is on.
SCO_STATE_SETUP, // Open pending completion of audio setup.
} sco_state_t;
// Codec type definitions.
typedef enum {
SCO_CODEC_NONE = 0x0000,
SCO_CODEC_CVSD = 0x0001,
SCO_CODEC_MSBC = 0x0002,
} sco_codec_t;
// Set the audio state on the controller for SCO (PCM, WBS, ...) using the
// vendor library.
void set_audio_state(uint16_t handle, sco_codec_t codec, sco_state_t state);
#endif /* _HCI_AUDIO_H_ */

View file

@ -42,6 +42,7 @@ typedef struct {
BT_HDR *(*make_ble_read_suggested_default_data_length)(void);
BT_HDR *(*make_ble_write_suggested_default_data_length)(uint16_t SuggestedMaxTxOctets, uint16_t SuggestedMaxTxTime);
BT_HDR *(*make_ble_set_event_mask)(const bt_event_mask_t *event_mask);
BT_HDR *(*make_write_sync_flow_control_enable)(uint8_t enable);
} hci_packet_factory_t;
const hci_packet_factory_t *hci_packet_factory_get_interface();

View file

@ -33,8 +33,10 @@ typedef struct {
void (*parse_read_buffer_size_response)(
BT_HDR *response,
uint16_t *data_size_ptr,
uint16_t *acl_buffer_count_ptr
uint16_t *acl_data_size_ptr,
uint16_t *acl_buffer_count_ptr,
uint8_t *sco_data_size_ptr,
uint16_t *sco_buffer_count_ptr
);
void (*parse_read_local_version_info_response)(

View file

@ -89,7 +89,9 @@
#include "bta/bta_sys.h"
#include "osi/allocator.h"
//#include "bta_ag_int.h"
#if BTA_HF_INCLUDED == TRUE
#include "bta_hf_client_int.h"
#endif
#if BTA_SDP_INCLUDED == TRUE
#include "bta_sdp_int.h"
@ -227,7 +229,13 @@ void BTE_InitStack(void)
memset((void *)bta_dm_search_cb_ptr, 0, sizeof(tBTA_DM_SEARCH_CB));
memset((void *)bta_dm_di_cb_ptr, 0, sizeof(tBTA_DM_DI_CB));
//memset((void *)bta_prm_cb_ptr, 0, sizeof(tBTA_PRM_CB));
//memset((void *)bta_ag_cb_ptr, 0, sizeof(tBTA_AG_CB));
#if (defined BTA_HF_INCLUDED && BTA_HF_INCLUDED == TRUE)
if ((bta_hf_client_cb_ptr = (tBTA_HF_CLIENT_CB *)osi_malloc(sizeof(tBTA_HF_CLIENT_CB))) == NULL) {
return;
}
memset((void *)bta_hf_client_cb_ptr, 0, sizeof(tBTA_HF_CLIENT_CB));
#endif
#if (defined BTA_JV_INCLUDED && BTA_JV_INCLUDED == TRUE)
if ((bta_jv_cb_ptr = (tBTA_JV_CB *)osi_malloc(sizeof(tBTA_JV_CB))) == NULL) {
return;
@ -327,6 +335,10 @@ void BTE_DeinitStack(void)
osi_free(bta_jv_cb_ptr);
bta_jv_cb_ptr = NULL;
#endif //JV
#if (defined BTA_HF_INCLUDED && BTA_HF_INCLUDED == TRUE)
osi_free(bta_hf_client_cb_ptr);
bta_hf_client_cb_ptr = NULL;
#endif
osi_free(bta_dm_di_cb_ptr);
bta_dm_di_cb_ptr = NULL;
osi_free(bta_dm_search_cb_ptr);
@ -354,4 +366,4 @@ void BTE_DeinitStack(void)
#if (defined(A2D_INCLUDED) && A2D_INCLUDED == TRUE)
A2D_Deinit();
#endif
}
}

View file

@ -170,6 +170,9 @@ static void reset_complete(void)
btm_pm_reset();
l2c_link_processs_num_bufs(controller->get_acl_buffer_count_classic());
#if BTM_SCO_HCI_INCLUDED == TRUE
btm_sco_process_num_bufs(controller->get_sco_buffer_count());
#endif
#if (BLE_INCLUDED == TRUE)
#if (defined BLE_PRIVACY_SPT && BLE_PRIVACY_SPT == TRUE)

View file

@ -30,6 +30,7 @@
#include "stack/hcimsgs.h"
#include "stack/btu.h"
#include "stack/btm_api.h"
#include "osi/allocator.h"
#include "btm_int.h"
#include "stack/hcidefs.h"
//#include "bt_utils.h"
@ -109,6 +110,11 @@ void btm_sco_init (void)
{
#if 0 /* cleared in btm_init; put back in if called from anywhere else! */
memset (&btm_cb.sco_cb, 0, sizeof(tSCO_CB));
#endif
#if (BTM_SCO_HCI_INCLUDED == TRUE)
for (int i = 0; i < BTM_MAX_SCO_LINKS; i++) {
btm_cb.sco_cb.sco_db[i].xmit_data_q = fixed_queue_new(SIZE_MAX);
}
#endif
/* Initialize nonzero defaults */
btm_cb.sco_cb.sco_disc_reason = BTM_INVALID_SCO_DISC_REASON;
@ -207,6 +213,66 @@ static void btm_esco_conn_rsp (UINT16 sco_inx, UINT8 hci_status, BD_ADDR bda,
#if BTM_SCO_HCI_INCLUDED == TRUE
void btm_sco_process_num_bufs (UINT16 num_lm_sco_bufs)
{
BTM_TRACE_ERROR("%s, %d", __FUNCTION__, num_lm_sco_bufs);
btm_cb.sco_cb.num_lm_sco_bufs = btm_cb.sco_cb.xmit_window_size = num_lm_sco_bufs;
}
/*******************************************************************************
**
** Function BTM_ConfigScoPath
**
** Description This function enable/disable SCO over HCI and registers SCO
** data callback if SCO over HCI is enabled.
**
** Parameter path: SCO or HCI
** p_sco_data_cb: callback function or SCO data if path is set
** to transport.
** p_pcm_param: pointer to the PCM interface parameter. If a NULL
** pointer is used, PCM parameter maintained in
** the control block will be used; otherwise update
** control block value.
** err_data_rpt: Lisbon feature to enable the erronous data report
** or not.
**
** Returns BTM_SUCCESS if the successful.
** BTM_NO_RESOURCES: no rsource to start the command.
** BTM_ILLEGAL_VALUE: invalid callback function pointer.
** BTM_CMD_STARTED :Command sent. Waiting for command cmpl event.
**
**
*******************************************************************************/
//extern
tBTM_STATUS BTM_ConfigScoPath (tBTM_SCO_ROUTE_TYPE path,
tBTM_SCO_DATA_CB *p_sco_data_cb,
tBTM_SCO_PCM_PARAM *p_pcm_param,
BOOLEAN err_data_rpt)
{
UNUSED(err_data_rpt);
UNUSED(p_pcm_param);
btm_cb.sco_cb.sco_path = path;
if (path == BTM_SCO_ROUTE_PCM) {
return BTM_SUCCESS;
} else if (path == BTM_SCO_ROUTE_HCI) {
if (p_sco_data_cb) {
btm_cb.sco_cb.p_data_cb = p_sco_data_cb;
}
}
return BTM_SUCCESS;
}
static void hci_sco_data_to_lower(BT_HDR *p_buf)
{
p_buf->event = BT_EVT_TO_LM_HCI_SCO;
if (p_buf->offset == 0) {
BTM_TRACE_ERROR("offset cannot be 0");
osi_free(p_buf);
}
bte_main_hci_send(p_buf, (UINT16)(BT_EVT_TO_LM_HCI_SCO | LOCAL_BLE_CONTROLLER_ID));
}
/*******************************************************************************
**
** Function btm_sco_check_send_pkts
@ -224,16 +290,58 @@ void btm_sco_check_send_pkts (UINT16 sco_inx)
/* If there is data to send, send it now */
BT_HDR *p_buf;
while ((p_buf = (BT_HDR *)fixed_queue_try_dequeue(p_ccb->xmit_data_q)) != NULL)
while (p_cb->xmit_window_size != 0)
{
if ((p_buf = (BT_HDR *)fixed_queue_try_dequeue(p_ccb->xmit_data_q)) == NULL) {
break;
}
#if BTM_SCO_HCI_DEBUG
BTM_TRACE_DEBUG("btm: [%d] buf in xmit_data_q",
fixed_queue_length(p_ccb->xmit_data_q) + 1);
#endif
/* Don't go negative */
p_cb->xmit_window_size -= 1;
p_ccb->sent_not_acked += 1;
HCI_SCO_DATA_TO_LOWER(p_buf);
// HCI_SCO_DATA_TO_LOWER(p_buf);
hci_sco_data_to_lower(p_buf);
}
}
void btm_sco_process_num_completed_pkts (UINT8 *p)
{
UINT8 num_handles, xx;
UINT16 handle;
UINT16 num_sent;
UINT16 sco_inx;
tSCO_CB *p_cb = &btm_cb.sco_cb;
tSCO_CONN * p_ccb;
STREAM_TO_UINT8 (num_handles, p);
for (xx = 0; xx < num_handles; xx++) {
STREAM_TO_UINT16 (handle, p);
handle &= 0x7ff; // walk around for bad handle bit mask from controller
STREAM_TO_UINT16 (num_sent, p);
if ((sco_inx = btm_find_scb_by_handle(handle & 0x7ff)) == BTM_MAX_SCO_LINKS) {
continue;
}
BTM_TRACE_DEBUG("%s, %d, %u", __FUNCTION__, handle, p_cb->xmit_window_size); //debug
p_ccb = &p_cb->sco_db[sco_inx];
p_ccb->sent_not_acked -= num_sent;
// don't go negative
if (p_ccb->sent_not_acked < 0) {
BTM_TRACE_WARNING("SCO: un-acked underf: %u", p_ccb->sent_not_acked);
p_ccb->sent_not_acked = 0;
}
p_cb->xmit_window_size += num_sent;
if (p_cb->xmit_window_size > p_cb->num_lm_sco_bufs) {
BTM_TRACE_WARNING("SCO xwind: %d, max %d", p_cb->xmit_window_size, p_cb->num_lm_sco_bufs);
p_cb->xmit_window_size = p_cb->num_lm_sco_bufs;
}
btm_sco_check_send_pkts (sco_inx);
}
return;
}
#endif /* BTM_SCO_HCI_INCLUDED == TRUE */
/*******************************************************************************
@ -259,7 +367,7 @@ void btm_route_sco_data(BT_HDR *p_msg)
handle = HCID_GET_HANDLE (handle);
STREAM_TO_UINT8 (pkt_size, p);
UNUSED(pkt_size);
if ((sco_inx = btm_find_scb_by_handle(handle)) != BTM_MAX_SCO_LINKS ) {
/* send data callback */
if (!btm_cb.sco_cb.p_data_cb )
@ -272,6 +380,7 @@ void btm_route_sco_data(BT_HDR *p_msg)
} else { /* no mapping handle SCO connection is active, free the buffer */
osi_free (p_msg);
}
BTM_TRACE_DEBUG ("SCO: hdl %x, len %d, pkt_sz %d\n", handle, p_msg->len, pkt_size);
#else
osi_free(p_msg);
#endif
@ -295,11 +404,13 @@ void btm_route_sco_data(BT_HDR *p_msg)
** BTM_NO_RESOURCES: no resources.
** BTM_UNKNOWN_ADDR: unknown SCO connection handle, or SCO is not
** routed via HCI.
** BTM_ERR_PROCESSING: transmit queue overflow
**
**
*******************************************************************************/
tBTM_STATUS BTM_WriteScoData (UINT16 sco_inx, BT_HDR *p_buf)
{
APPL_TRACE_DEBUG("%s", __FUNCTION__);
#if (BTM_SCO_HCI_INCLUDED == TRUE) && (BTM_MAX_SCO_LINKS>0)
tSCO_CONN *p_ccb = &btm_cb.sco_cb.sco_db[sco_inx];
UINT8 *p;
@ -310,7 +421,6 @@ tBTM_STATUS BTM_WriteScoData (UINT16 sco_inx, BT_HDR *p_buf)
/* Ensure we have enough space in the buffer for the SCO and HCI headers */
if (p_buf->offset < HCI_SCO_PREAMBLE_SIZE) {
BTM_TRACE_ERROR ("BTM SCO - cannot send buffer, offset: %d", p_buf->offset);
osi_free (p_buf);
status = BTM_ILLEGAL_VALUE;
} else { /* write HCI header */
/* Step back 3 bytes to add the headers */
@ -327,20 +437,27 @@ tBTM_STATUS BTM_WriteScoData (UINT16 sco_inx, BT_HDR *p_buf)
}
UINT8_TO_STREAM (p, (UINT8)p_buf->len);
BTM_TRACE_DEBUG ("BTM SCO hdl %x, len %u", p_ccb->hci_handle, p_buf->len);
p_buf->len += HCI_SCO_PREAMBLE_SIZE;
fixed_queue_enqueue(p_ccb->xmit_data_q, p_buf);
btm_sco_check_send_pkts (sco_inx);
if (fixed_queue_length(p_ccb->xmit_data_q) < BTM_SCO_XMIT_QUEUE_THRS) {
fixed_queue_enqueue(p_ccb->xmit_data_q, p_buf);
btm_sco_check_send_pkts (sco_inx);
} else {
BTM_TRACE_WARNING ("SCO xmit Q overflow, pkt dropped");
status = BTM_ERR_PROCESSING;
}
}
} else {
osi_free(p_buf);
BTM_TRACE_WARNING ("BTM_WriteScoData, invalid sco index: %d at state [%d]",
sco_inx, btm_cb.sco_cb.sco_db[sco_inx].state);
status = BTM_UNKNOWN_ADDR;
}
if (status != BTM_SUCCESS && status != BTM_SCO_BAD_LENGTH) {
BTM_TRACE_WARNING ("stat %d", status);
osi_free(p_buf);
}
return (status);
#else
@ -839,7 +956,7 @@ void btm_sco_connected (UINT8 hci_status, BD_ADDR bda, UINT16 hci_handle,
#endif
btm_cb.sco_cb.sco_disc_reason = hci_status;
BTM_TRACE_ERROR("%s, handle %x", __FUNCTION__, hci_handle);
#if (BTM_MAX_SCO_LINKS>0)
for (xx = 0; xx < BTM_MAX_SCO_LINKS; xx++, p++) {
if (((p->state == SCO_ST_CONNECTING) ||
@ -876,7 +993,9 @@ void btm_sco_connected (UINT8 hci_status, BD_ADDR bda, UINT16 hci_handle,
if (p->state == SCO_ST_LISTENING) {
spt = TRUE;
}
#if BTM_SCO_HCI_INCLUDED == TRUE
p->sent_not_acked = 0;
#endif
p->state = SCO_ST_CONNECTED;
p->hci_handle = hci_handle;
@ -1022,6 +1141,14 @@ void btm_sco_removed (UINT16 hci_handle, UINT8 reason)
btm_sco_flush_sco_data(xx);
p->state = SCO_ST_UNUSED;
#if BTM_SCO_HCI_INCLUDED == TRUE
btm_cb.sco_cb.xmit_window_size += p->sent_not_acked;
/* avoid overflow */
if (btm_cb.sco_cb.xmit_window_size > btm_cb.sco_cb.num_lm_sco_bufs) {
btm_cb.sco_cb.xmit_window_size = btm_cb.sco_cb.num_lm_sco_bufs;
}
p->sent_not_acked = 0;
#endif
p->hci_handle = BTM_INVALID_HCI_HANDLE;
p->rem_bd_known = FALSE;
p->esco.p_esco_cback = NULL; /* Deregister eSCO callback */

View file

@ -365,7 +365,9 @@ typedef struct {
typedef struct {
tBTM_ESCO_INFO esco; /* Current settings */
#if BTM_SCO_HCI_INCLUDED == TRUE
#define BTM_SCO_XMIT_QUEUE_THRS 20
fixed_queue_t *xmit_data_q; /* SCO data transmitting queue */
INT16 sent_not_acked;
#endif
tBTM_SCO_CB *p_conn_cb; /* Callback for when connected */
tBTM_SCO_CB *p_disc_cb; /* Callback for when disconnect */
@ -382,6 +384,7 @@ typedef struct {
#if BTM_SCO_HCI_INCLUDED == TRUE
tBTM_SCO_DATA_CB *p_data_cb; /* Callback for SCO data over HCI */
UINT32 xmit_window_size; /* Total SCO window in bytes */
UINT16 num_lm_sco_bufs;
#endif
tSCO_CONN sco_db[BTM_MAX_SCO_LINKS];
tBTM_ESCO_PARAMS def_esco_parms;
@ -996,6 +999,10 @@ void btm_pm_proc_mode_change (UINT8 hci_status, UINT16 hci_handle, UINT8 mode,
void btm_pm_proc_ssr_evt (UINT8 *p, UINT16 evt_len);
#if BTM_SCO_INCLUDED == TRUE
void btm_sco_chk_pend_unpark (UINT8 hci_status, UINT16 hci_handle);
#if (BTM_SCO_HCI_INCLUDED == TRUE )
void btm_sco_process_num_bufs (UINT16 num_lm_sco_bufs);
void btm_sco_process_num_completed_pkts (UINT8 *p);
#endif /* (BTM_SCO_HCI_INCLUDED == TRUE ) */
#else
#define btm_sco_chk_pend_unpark(hci_status, hci_handle)
#endif /* BTM_SCO_INCLUDED */

View file

@ -1292,7 +1292,9 @@ static void btu_hcif_num_compl_data_pkts_evt (UINT8 *p)
l2c_link_process_num_completed_pkts (p);
/* Send on to SCO */
/*?? No SCO for now */
#if (BTM_SCO_HCI_INCLUDED == TRUE) && (BTM_SCO_INCLUDED == TRUE)
btm_sco_process_num_completed_pkts (p);
#endif
}
/*******************************************************************************

View file

@ -955,8 +955,8 @@ typedef UINT8 tBTM_SCO_TYPE;
/*******************
** SCO Routing Path
********************/
#define BTM_SCO_ROUTE_PCM HCI_BRCM_SCO_ROUTE_PCM
#define BTM_SCO_ROUTE_HCI HCI_BRCM_SCO_ROUTE_HCI
#define BTM_SCO_ROUTE_PCM (0) // HCI_BRCM_SCO_ROUTE_PCM
#define BTM_SCO_ROUTE_HCI (1) // HCI_BRCM_SCO_ROUTE_HCI
typedef UINT8 tBTM_SCO_ROUTE_TYPE;

View file

@ -833,7 +833,7 @@ void PORT_DataInd (tRFC_MCB *p_mcb, UINT8 dlci, BT_HDR *p_buf)
//osi_free (p_buf);
return;
} else {
RFCOMM_TRACE_ERROR("PORT_DataInd, p_port:%p, p_data_co_callback is null", p_port);
RFCOMM_TRACE_DEBUG("PORT_DataInd, p_port:%p, p_data_co_callback is null", p_port);
}
/* If client registered callback we can just deliver receive data */
if (p_port->p_data_callback) {
@ -1094,4 +1094,4 @@ void port_get_credits (tPORT *p_port, UINT8 k)
}
#endif ///(defined RFCOMM_INCLUDED && RFCOMM_INCLUDED == TRUE)
#endif ///(defined RFCOMM_INCLUDED && RFCOMM_INCLUDED == TRUE)

View file

@ -97,6 +97,7 @@ extern int ble_txpwr_set(int power_type, int power_level);
extern int ble_txpwr_get(int power_type);
extern int bredr_txpwr_set(int min_power_level, int max_power_level);
extern int bredr_txpwr_get(int *min_power_level, int *max_power_level);
extern void bredr_sco_datapath_set(uint8_t data_path);
extern char _bss_start_btdm;
extern char _bss_end_btdm;
@ -1103,4 +1104,13 @@ void esp_bt_controller_wakeup_request(void)
btdm_wakeup_request();
}
esp_err_t esp_bredr_sco_datapath_set(esp_sco_data_path_t data_path)
{
if (btdm_controller_status != ESP_BT_CONTROLLER_STATUS_ENABLED) {
return ESP_ERR_INVALID_STATE;
}
bredr_sco_datapath_set(data_path);
return ESP_OK;
}
#endif /* CONFIG_BT_ENABLED */

View file

@ -25,6 +25,7 @@ ifdef CONFIG_BLUEDROID_ENABLED
COMPONENT_PRIV_INCLUDEDIRS += bluedroid/bta/include \
bluedroid/bta/ar/include \
bluedroid/bta/av/include \
bluedroid/bta/hf_client/include \
bluedroid/bta/dm/include \
bluedroid/bta/gatt/include \
bluedroid/bta/hh/include \
@ -75,6 +76,7 @@ COMPONENT_SRCDIRS += bluedroid/bta/dm \
bluedroid/bta/ar \
bluedroid/bta/sys \
bluedroid/bta/jv \
bluedroid/bta/hf_client \
bluedroid/bta \
bluedroid/btcore \
bluedroid/btif \
@ -92,6 +94,7 @@ COMPONENT_SRCDIRS += bluedroid/bta/dm \
bluedroid/btc/profile/std/a2dp \
bluedroid/btc/profile/std/avrc \
bluedroid/btc/profile/std/spp \
bluedroid/btc/profile/std/hf_client \
bluedroid/btc/profile \
bluedroid/stack/btm \
bluedroid/stack/btu \
@ -111,5 +114,4 @@ COMPONENT_SRCDIRS += bluedroid/bta/dm \
bluedroid/utils \
bluedroid/api \
bluedroid
endif

View file

@ -122,6 +122,14 @@ typedef enum {
ESP_PWR_LVL_P7 = 7, /*!< Corresponding to 7dbm */
} esp_power_level_t;
/**
* @brief Bluetooth audio data transport path
*/
typedef enum {
ESP_SCO_DATA_PATH_HCI = 0, /*!< data over HCI transport */
ESP_SCO_DATA_PATH_PCM = 1, /*!< data over PCM interface */
} esp_sco_data_path_t;
/**
* @brief Set BLE TX power
* Connection Tx power should only be set after connection created.
@ -164,6 +172,13 @@ esp_err_t esp_bredr_tx_power_set(esp_power_level_t min_power_level, esp_power_le
*/
esp_err_t esp_bredr_tx_power_get(esp_power_level_t *min_power_level, esp_power_level_t *max_power_level);
/**
* @brief set default SCO data path
* Should be called after controller is enabled, and before (e)SCO link is established
* @param data_path: SCO data path
* @return ESP_OK - success, other - failed
*/
esp_err_t esp_bredr_sco_datapath_set(esp_sco_data_path_t data_path);
/**
* @brief Initialize BT controller to allocate task and other resource.

@ -1 +1 @@
Subproject commit 700d2bc914b755b840a0adeaa9d1ff45b398b6fa
Subproject commit 16516d7009f1c31c21939047447a95238194de40

View file

@ -1704,6 +1704,7 @@ PROVIDE ( ets_update_cpu_frequency_rom = 0x40008550 ); /* Updates g_ticks_per_u
PROVIDE ( hci_tl_env = 0x3ffb8154 );
PROVIDE ( ld_acl_env = 0x3ffb8258 );
PROVIDE ( ea_env = 0x3ffb80ec );
PROVIDE ( lc_sco_data_path_config = 0x3ffb81f8 );
PROVIDE ( ld_active_ch_map = 0x3ffb8334 );
PROVIDE ( ld_bcst_acl_env = 0x3ffb8274 );
PROVIDE ( ld_csb_rx_env = 0x3ffb8278 );

View file

@ -51,6 +51,8 @@ INPUT = \
../../components/bt/bluedroid/api/include/api/esp_a2dp_api.h \
../../components/bt/bluedroid/api/include/api/esp_avrc_api.h \
../../components/bt/bluedroid/api/include/api/esp_spp_api.h \
../../components/bt/bluedroid/api/include/api/esp_hf_defs.h \
../../components/bt/bluedroid/api/include/api/esp_hf_client_api.h \
##
## Ethernet - API Reference
##

View file

@ -8,3 +8,5 @@ CLASSIC BT
BT A2DP <esp_a2dp>
BT AVRC <esp_avrc>
BT SPP <esp_spp>
BT HFP Define <esp_hf_defs>
BT HFP Client <esp_hf_client>

View file

@ -0,0 +1,14 @@
HFP CLIENT API
==============
Overview
--------
`Instructions`_
.. _Instructions: ../template.html
API Reference
-------------
.. include:: /_build/inc/esp_hf_client_api.inc

View file

@ -0,0 +1,16 @@
HFP DEFINES
===========
Overview
--------
`Instructions`_
.. _Instructions: ../template.html
API Reference
-------------
.. include:: /_build/inc/esp_hf_defs.inc

View file

@ -0,0 +1 @@
.. include:: ../../../en/api-reference/bluetooth/esp_hf_client.rst

View file

@ -0,0 +1 @@
.. include:: ../../../en/api-reference/bluetooth/esp_hf_defs.rst