mirror of
https://github.com/espressif/esp-idf.git
synced 2024-10-05 20:47:46 -04:00
Merge branch 'feature/btdm_classic_discovery' into 'master'
component/bt: implement Classic Bluetooth GAP APIs for device and service discovery See merge request !1576
This commit is contained in:
commit
a567de1576
@ -20,7 +20,21 @@
|
||||
#include "btc_manage.h"
|
||||
#include "btc_gap_bt.h"
|
||||
|
||||
#if BTC_GAP_BT_INCLUDED
|
||||
#if (BTC_GAP_BT_INCLUDED == TRUE)
|
||||
|
||||
esp_err_t esp_bt_gap_register_callback(esp_bt_gap_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_GAP_BT, callback);
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t esp_bt_gap_set_scan_mode(esp_bt_scan_mode_t mode)
|
||||
{
|
||||
@ -30,7 +44,7 @@ esp_err_t esp_bt_gap_set_scan_mode(esp_bt_scan_mode_t mode)
|
||||
if (esp_bluedroid_get_status() != ESP_BLUEDROID_STATUS_ENABLED) {
|
||||
return ESP_ERR_INVALID_STATE;
|
||||
}
|
||||
|
||||
|
||||
msg.sig = BTC_SIG_API_CALL;
|
||||
msg.pid = BTC_PID_GAP_BT;
|
||||
msg.act = BTC_GAP_BT_ACT_SET_SCAN_MODE;
|
||||
@ -39,4 +53,92 @@ esp_err_t esp_bt_gap_set_scan_mode(esp_bt_scan_mode_t mode)
|
||||
return (btc_transfer_context(&msg, &arg, sizeof(btc_gap_bt_args_t), NULL) == BT_STATUS_SUCCESS ? ESP_OK : ESP_FAIL);
|
||||
}
|
||||
|
||||
#endif /* #if BTC_GAP_BT_INCLUDED */
|
||||
esp_err_t esp_bt_gap_start_discovery(esp_bt_inq_mode_t mode, uint8_t inq_len, uint8_t num_rsps)
|
||||
{
|
||||
btc_msg_t msg;
|
||||
btc_gap_bt_args_t arg;
|
||||
|
||||
if (esp_bluedroid_get_status() != ESP_BLUEDROID_STATUS_ENABLED) {
|
||||
return ESP_ERR_INVALID_STATE;
|
||||
}
|
||||
|
||||
if (mode != ESP_BT_INQ_MODE_GENERAL_INQUIRY &&
|
||||
mode != ESP_BT_INQ_MODE_LIMITED_INQIURY) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
|
||||
if (inq_len < ESP_BT_GAP_MIN_INQ_LEN ||
|
||||
inq_len > ESP_BT_GAP_MAX_INQ_LEN) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
|
||||
msg.sig = BTC_SIG_API_CALL;
|
||||
msg.pid = BTC_PID_GAP_BT;
|
||||
msg.act = BTC_GAP_BT_ACT_START_DISCOVERY;
|
||||
|
||||
arg.start_disc.mode = mode;
|
||||
arg.start_disc.inq_len = inq_len;
|
||||
arg.start_disc.num_rsps = num_rsps;
|
||||
|
||||
return (btc_transfer_context(&msg, &arg, sizeof(btc_gap_bt_args_t), NULL) == BT_STATUS_SUCCESS ? ESP_OK : ESP_FAIL);
|
||||
}
|
||||
|
||||
esp_err_t esp_bt_gap_cancel_discovery(void)
|
||||
{
|
||||
btc_msg_t msg;
|
||||
|
||||
if (esp_bluedroid_get_status() != ESP_BLUEDROID_STATUS_ENABLED) {
|
||||
return ESP_ERR_INVALID_STATE;
|
||||
}
|
||||
|
||||
msg.sig = BTC_SIG_API_CALL;
|
||||
msg.pid = BTC_PID_GAP_BT;
|
||||
msg.act = BTC_GAP_BT_ACT_CANCEL_DISCOVERY;
|
||||
|
||||
return (btc_transfer_context(&msg, NULL, 0, NULL) == BT_STATUS_SUCCESS ? ESP_OK : ESP_FAIL);
|
||||
}
|
||||
|
||||
esp_err_t esp_bt_gap_get_remote_services(esp_bd_addr_t remote_bda)
|
||||
{
|
||||
btc_msg_t msg;
|
||||
btc_gap_bt_args_t arg;
|
||||
|
||||
if (esp_bluedroid_get_status() != ESP_BLUEDROID_STATUS_ENABLED) {
|
||||
return ESP_ERR_INVALID_STATE;
|
||||
}
|
||||
|
||||
msg.sig = BTC_SIG_API_CALL;
|
||||
msg.pid = BTC_PID_GAP_BT;
|
||||
msg.act = BTC_GAP_BT_ACT_GET_REMOTE_SERVICES;
|
||||
|
||||
memcpy(&arg.bda, remote_bda, sizeof(bt_bdaddr_t));
|
||||
return (btc_transfer_context(&msg, &arg, sizeof(btc_gap_bt_args_t), NULL) == BT_STATUS_SUCCESS ? ESP_OK : ESP_FAIL);
|
||||
}
|
||||
|
||||
esp_err_t esp_bt_gap_get_remote_service_record(esp_bd_addr_t remote_bda, esp_bt_uuid_t *uuid)
|
||||
{
|
||||
btc_msg_t msg;
|
||||
btc_gap_bt_args_t arg;
|
||||
|
||||
if (esp_bluedroid_get_status() != ESP_BLUEDROID_STATUS_ENABLED) {
|
||||
return ESP_ERR_INVALID_STATE;
|
||||
}
|
||||
|
||||
msg.sig = BTC_SIG_API_CALL;
|
||||
msg.pid = BTC_PID_GAP_BT;
|
||||
msg.act = BTC_GAP_BT_ACT_GET_REMOTE_SERVICE_RECORD;
|
||||
|
||||
memcpy(&arg.get_rmt_srv_rcd.bda, remote_bda, sizeof(bt_bdaddr_t));
|
||||
memcpy(&arg.get_rmt_srv_rcd.uuid, uuid, sizeof(esp_bt_uuid_t));
|
||||
return (btc_transfer_context(&msg, &arg, sizeof(btc_gap_bt_args_t), NULL) == BT_STATUS_SUCCESS ? ESP_OK : ESP_FAIL);
|
||||
}
|
||||
|
||||
uint8_t *esp_bt_gap_resolve_eir_data(uint8_t *eir, esp_bt_eir_type_t type, uint8_t *length)
|
||||
{
|
||||
if (!eir) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return BTM_CheckEirData(eir, type, length);
|
||||
}
|
||||
#endif /* #if BTC_GAP_BT_INCLUDED == TRUE */
|
||||
|
@ -28,9 +28,227 @@ extern "C" {
|
||||
typedef enum {
|
||||
ESP_BT_SCAN_MODE_NONE = 0, /*!< Neither discoverable nor connectable */
|
||||
ESP_BT_SCAN_MODE_CONNECTABLE, /*!< Connectable but not discoverable */
|
||||
ESP_BT_SCAN_MODE_CONNECTABLE_DISCOVERABLE /*!< both discoverable and connectaable */
|
||||
ESP_BT_SCAN_MODE_CONNECTABLE_DISCOVERABLE /*!< both discoverable and connectable */
|
||||
} esp_bt_scan_mode_t;
|
||||
|
||||
/// Bluetooth Device Property type
|
||||
typedef enum {
|
||||
ESP_BT_GAP_DEV_PROP_BDNAME = 1, /*!< Bluetooth device name, value type is int8_t [] */
|
||||
ESP_BT_GAP_DEV_PROP_COD, /*!< Class of Device, value type is uint32_t */
|
||||
ESP_BT_GAP_DEV_PROP_RSSI, /*!< Received Signal strength Indication, value type is int8_t, ranging from -128 to 127 */
|
||||
ESP_BT_GAP_DEV_PROP_EIR, /*!< Extended Inquiry Response, value type is uint8_t [] */
|
||||
} esp_bt_gap_dev_prop_type_t;
|
||||
|
||||
/// Maximum bytes of Bluetooth device name
|
||||
#define ESP_BT_GAP_MAX_BDNAME_LEN (248)
|
||||
|
||||
/// Maximum size of EIR Significant part
|
||||
#define ESP_BT_GAP_EIR_DATA_LEN (240)
|
||||
|
||||
/// Bluetooth Device Property Descriptor
|
||||
typedef struct {
|
||||
esp_bt_gap_dev_prop_type_t type; /*!< device property type */
|
||||
int len; /*!< device property value length */
|
||||
void *val; /*!< devlice prpoerty value */
|
||||
} esp_bt_gap_dev_prop_t;
|
||||
|
||||
/// Extended Inquiry Response data type
|
||||
typedef enum {
|
||||
ESP_BT_EIR_TYPE_FLAGS = 0x01, /*!< Flag with information such as BR/EDR and LE support */
|
||||
ESP_BT_EIR_TYPE_INCMPL_16BITS_UUID = 0x02, /*!< Incomplete list of 16-bit service UUIDs */
|
||||
ESP_BT_EIR_TYPE_CMPL_16BITS_UUID = 0x03, /*!< Complete list of 16-bit service UUIDs */
|
||||
ESP_BT_EIR_TYPE_INCMPL_32BITS_UUID = 0x04, /*!< Incomplete list of 32-bit service UUIDs */
|
||||
ESP_BT_EIR_TYPE_CMPL_32BITS_UUID = 0x05, /*!< Complete list of 32-bit service UUIDs */
|
||||
ESP_BT_EIR_TYPE_INCMPL_128BITS_UUID = 0x06, /*!< Incomplete list of 128-bit service UUIDs */
|
||||
ESP_BT_EIR_TYPE_CMPL_128BITS_UUID = 0x07, /*!< Complete list of 128-bit service UUIDs */
|
||||
ESP_BT_EIR_TYPE_SHORT_LOCAL_NAME = 0x08, /*!< Shortened Local Name */
|
||||
ESP_BT_EIR_TYPE_CMPL_LOCAL_NAME = 0x09, /*!< Complete Local Name */
|
||||
ESP_BT_EIR_TYPE_TX_POWER_LEVEL = 0x0a, /*!< Tx power level, value is 1 octet ranging from -127 to 127, unit is dBm*/
|
||||
ESP_BT_EIR_TYPE_MANU_SPECIFIC = 0xff, /*!< Manufacturer specific data */
|
||||
} esp_bt_eir_type_t;
|
||||
|
||||
/// Major service class field of Class of Device, mutiple bits can be set
|
||||
typedef enum {
|
||||
ESP_BT_COD_SRVC_NONE = 0, /*!< None indicates an invalid value */
|
||||
ESP_BT_COD_SRVC_LMTD_DISCOVER = 0x1, /*!< Limited Discoverable Mode */
|
||||
ESP_BT_COD_SRVC_POSITIONING = 0x8, /*!< Positioning (Location identification) */
|
||||
ESP_BT_COD_SRVC_NETWORKING = 0x10, /*!< Networking, e.g. LAN, Ad hoc */
|
||||
ESP_BT_COD_SRVC_RENDERING = 0x20, /*!< Rendering, e.g. Printing, Speakers */
|
||||
ESP_BT_COD_SRVC_CAPTURING = 0x40, /*!< Capturing, e.g. Scanner, Microphone */
|
||||
ESP_BT_COD_SRVC_OBJ_TRANSFER = 0x80, /*!< Object Transfer, e.g. v-Inbox, v-Folder */
|
||||
ESP_BT_COD_SRVC_AUDIO = 0x100, /*!< Audio, e.g. Speaker, Microphone, Headerset service */
|
||||
ESP_BT_COD_SRVC_TELEPHONY = 0x200, /*!< Telephony, e.g. Cordless telephony, Modem, Headset service */
|
||||
ESP_BT_COD_SRVC_INFORMATION = 0x400, /*!< Information, e.g., WEB-server, WAP-server */
|
||||
} esp_bt_cod_srvc_t;
|
||||
|
||||
/// Bits of major service class field
|
||||
#define ESP_BT_COD_SRVC_BIT_MASK (0xffe000) /*!< Major service bit mask */
|
||||
#define ESP_BT_COD_SRVC_BIT_OFFSET (13) /*!< Major service bit offset */
|
||||
|
||||
/// Major device class field of Class of Device
|
||||
typedef enum {
|
||||
ESP_BT_COD_MAJOR_DEV_MISC = 0, /*!< Miscellaneous */
|
||||
ESP_BT_COD_MAJOR_DEV_COMPUTER = 1, /*!< Computer */
|
||||
ESP_BT_COD_MAJOR_DEV_PHONE = 2, /*!< Phone(cellular, cordless, pay phone, modem */
|
||||
ESP_BT_COD_MAJOR_DEV_LAN_NAP = 3, /*!< LAN, Network Access Point */
|
||||
ESP_BT_COD_MAJOR_DEV_AV = 4, /*!< Audio/Video(headset, speaker, stereo, video display, VCR */
|
||||
ESP_BT_COD_MAJOR_DEV_PERIPHERAL = 5, /*!< Peripheral(mouse, joystick, keyboard) */
|
||||
ESP_BT_COD_MAJOR_DEV_IMAGING = 6, /*!< Imaging(printer, scanner, camera, display */
|
||||
ESP_BT_COD_MAJOR_DEV_WEARABLE = 7, /*!< Wearable */
|
||||
ESP_BT_COD_MAJOR_DEV_TOY = 8, /*!< Toy */
|
||||
ESP_BT_COD_MAJOR_DEV_HEALTH = 9, /*!< Health */
|
||||
ESP_BT_COD_MAJOR_DEV_UNCATEGORIZED = 31, /*!< Uncategorized: device not specified */
|
||||
} esp_bt_cod_major_dev_t;
|
||||
|
||||
/// Bits of major device class field
|
||||
#define ESP_BT_COD_MAJOR_DEV_BIT_MASK (0x1f00) /*!< Major device bit mask */
|
||||
#define ESP_BT_COD_MAJOR_DEV_BIT_OFFSET (8) /*!< Major device bit offset */
|
||||
|
||||
/// Bits of minor device class field
|
||||
#define ESP_BT_COD_MINOR_DEV_BIT_MASK (0xfc) /*!< Minor device bit mask */
|
||||
#define ESP_BT_COD_MINOR_DEV_BIT_OFFSET (2) /*!< Minor device bit offset */
|
||||
|
||||
/// Bits of format type
|
||||
#define ESP_BT_COD_FORMAT_TYPE_BIT_MASK (0x03) /*!< Format type bit mask */
|
||||
#define ESP_BT_COD_FORMAT_TYPE_BIT_OFFSET (0) /*!< Format type bit offset */
|
||||
|
||||
/// Class of device format type 1
|
||||
#define ESP_BT_COD_FORMAT_TYPE_1 (0x00)
|
||||
|
||||
/** Bluetooth Device Discovery state */
|
||||
typedef enum {
|
||||
ESP_BT_GAP_DISCOVERY_STOPPED, /*!< device discovery stopped */
|
||||
ESP_BT_GAP_DISCOVERY_STARTED, /*!< device discovery started */
|
||||
} esp_bt_gap_discovery_state_t;
|
||||
|
||||
/// BT GAP callback events
|
||||
typedef enum {
|
||||
ESP_BT_GAP_DISC_RES_EVT = 0, /*!< device discovery result event */
|
||||
ESP_BT_GAP_DISC_STATE_CHANGED_EVT, /*!< discovery state changed event */
|
||||
ESP_BT_GAP_RMT_SRVCS_EVT, /*!< get remote services event */
|
||||
ESP_BT_GAP_RMT_SRVC_REC_EVT, /*!< get remote service record event */
|
||||
} esp_bt_gap_cb_event_t;
|
||||
|
||||
/** Inquiry Mode */
|
||||
typedef enum {
|
||||
ESP_BT_INQ_MODE_GENERAL_INQUIRY, /*!< General inquiry mode */
|
||||
ESP_BT_INQ_MODE_LIMITED_INQIURY, /*!< Limited inquiry mode */
|
||||
} esp_bt_inq_mode_t;
|
||||
|
||||
/** Minimum and Maximum inquiry length*/
|
||||
#define ESP_BT_GAP_MIN_INQ_LEN (0x01) /*!< Minimum inquiry duration, unit is 1.28s */
|
||||
#define ESP_BT_GAP_MAX_INQ_LEN (0x30) /*!< Maximum inquiry duration, unit is 1.28s */
|
||||
|
||||
/// A2DP state callback parameters
|
||||
typedef union {
|
||||
/**
|
||||
* @brief ESP_BT_GAP_DISC_RES_EVT
|
||||
*/
|
||||
struct disc_res_param {
|
||||
esp_bd_addr_t bda; /*!< remote bluetooth device address*/
|
||||
int num_prop; /*!< number of properties got */
|
||||
esp_bt_gap_dev_prop_t *prop; /*!< properties discovered from the new device */
|
||||
} disc_res; /*!< discovery result paramter struct */
|
||||
|
||||
/**
|
||||
* @brief ESP_BT_GAP_DISC_STATE_CHANGED_EVT
|
||||
*/
|
||||
struct disc_state_changed_param {
|
||||
esp_bt_gap_discovery_state_t state; /*!< discovery state */
|
||||
} disc_st_chg; /*!< discovery state changed parameter struct */
|
||||
|
||||
/**
|
||||
* @brief ESP_BT_GAP_RMT_SRVCS_EVT
|
||||
*/
|
||||
struct rmt_srvcs_param {
|
||||
esp_bd_addr_t bda; /*!< remote bluetooth device address*/
|
||||
esp_bt_status_t stat; /*!< service search status */
|
||||
int num_uuids; /*!< number of UUID in uuid_list */
|
||||
esp_bt_uuid_t *uuid_list; /*!< list of service UUIDs of remote device */
|
||||
} rmt_srvcs; /*!< services of remote device parameter struct */
|
||||
|
||||
/**
|
||||
* @brief ESP_BT_GAP_RMT_SRVC_REC_EVT
|
||||
*/
|
||||
struct rmt_srvc_rec_param {
|
||||
esp_bd_addr_t bda; /*!< remote bluetooth device address*/
|
||||
esp_bt_status_t stat; /*!< service search status */
|
||||
} rmt_srvc_rec; /*!< specific service record from remote device parameter struct */
|
||||
} esp_bt_gap_cb_param_t;
|
||||
|
||||
/**
|
||||
* @brief bluetooth GAP callback function type
|
||||
* @param event : Event type
|
||||
* @param param : Pointer to callback parameter
|
||||
*/
|
||||
typedef void (* esp_bt_gap_cb_t)(esp_bt_gap_cb_event_t event, esp_bt_gap_cb_param_t *param);
|
||||
|
||||
/**
|
||||
* @brief get major service field of COD
|
||||
* @param[in] cod: Class of Device
|
||||
* @return major service bits
|
||||
*/
|
||||
inline uint32_t esp_bt_gap_get_cod_srvc(uint32_t cod)
|
||||
{
|
||||
return (cod & ESP_BT_COD_SRVC_BIT_MASK) >> ESP_BT_COD_SRVC_BIT_OFFSET;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief get major device field of COD
|
||||
* @param[in] cod: Class of Device
|
||||
* @return major device bits
|
||||
*/
|
||||
inline uint32_t esp_bt_gap_get_cod_major_dev(uint32_t cod)
|
||||
{
|
||||
return (cod & ESP_BT_COD_MAJOR_DEV_BIT_MASK) >> ESP_BT_COD_MAJOR_DEV_BIT_OFFSET;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief get minor service field of COD
|
||||
* @param[in] cod: Class of Device
|
||||
* @return minor service bits
|
||||
*/
|
||||
inline uint32_t esp_bt_gap_get_cod_minor_dev(uint32_t cod)
|
||||
{
|
||||
return (cod & ESP_BT_COD_MINOR_DEV_BIT_MASK) >> ESP_BT_COD_MINOR_DEV_BIT_OFFSET;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief get format type of COD
|
||||
* @param[in] cod: Class of Device
|
||||
* @return format type
|
||||
*/
|
||||
inline uint32_t esp_bt_gap_get_cod_format_type(uint32_t cod)
|
||||
{
|
||||
return (cod & ESP_BT_COD_FORMAT_TYPE_BIT_MASK);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief decide the integrity of COD
|
||||
* @param[in] cod: Class of Device
|
||||
* @return
|
||||
* - true if cod is valid
|
||||
* - false otherise
|
||||
*/
|
||||
inline bool esp_bt_gap_is_valid_cod(uint32_t cod)
|
||||
{
|
||||
if (esp_bt_gap_get_cod_format_type(cod) == ESP_BT_COD_FORMAT_TYPE_1 &&
|
||||
esp_bt_gap_get_cod_srvc(cod) != ESP_BT_COD_SRVC_NONE) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief register callback function. This function should be called after esp_bluedroid_enable() completes successfully
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK : Succeed
|
||||
* - ESP_FAIL: others
|
||||
*/
|
||||
esp_err_t esp_bt_gap_register_callback(esp_bt_gap_cb_t callback);
|
||||
|
||||
/**
|
||||
* @brief Set discoverability and connectability mode for legacy bluetooth. This function should
|
||||
* be called after esp_bluedroid_enable() completes successfully
|
||||
@ -45,6 +263,69 @@ typedef enum {
|
||||
*/
|
||||
esp_err_t esp_bt_gap_set_scan_mode(esp_bt_scan_mode_t mode);
|
||||
|
||||
/**
|
||||
* @brief Start device discovery. This function should be called after esp_bluedroid_enable() completes successfully.
|
||||
* esp_bt_gap_cb_t will is called with ESP_BT_GAP_DISC_STATE_CHANGED_EVT if discovery is started or halted.
|
||||
* esp_bt_gap_cb_t will is called with ESP_BT_GAP_DISC_RES_EVT if discovery result is got.
|
||||
*
|
||||
* @param[in] mode - inquiry mode
|
||||
* @param[in] inq_len - inquiry duration in 1.28 sec units, ranging from 0x01 to 0x30
|
||||
* @param[in] num_rsps - number of inquiry responses that can be received, value 0 indicates an unlimited number of responses
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK : Succeed
|
||||
* - ESP_INVALID_STATE: if bluetooth stack is not yet enabled
|
||||
* - ESP_ERR_INVALID_ARG: if invalid parameters are provided
|
||||
* - ESP_FAIL: others
|
||||
*/
|
||||
esp_err_t esp_bt_gap_start_discovery(esp_bt_inq_mode_t mode, uint8_t inq_len, uint8_t num_rsps);
|
||||
|
||||
/**
|
||||
* @brief Cancel device discovery. This function should be called after esp_bluedroid_enable() completes successfully
|
||||
* esp_bt_gap_cb_t will is called with ESP_BT_GAP_DISC_STATE_CHANGED_EVT if discovery is stopped.
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK : Succeed
|
||||
* - ESP_INVALID_STATE: if bluetooth stack is not yet enabled
|
||||
* - ESP_FAIL: others
|
||||
*/
|
||||
esp_err_t esp_bt_gap_cancel_discovery(void);
|
||||
|
||||
/**
|
||||
* @brief Start SDP to get remote services. This function should be called after esp_bluedroid_enable() completes successfully.
|
||||
* esp_bt_gap_cb_t will is called with ESP_BT_GAP_RMT_SRVCS_EVT after service discovery ends
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK : Succeed
|
||||
* - ESP_INVALID_STATE: if bluetooth stack is not yet enabled
|
||||
* - ESP_FAIL: others
|
||||
*/
|
||||
esp_err_t esp_bt_gap_get_remote_services(esp_bd_addr_t remote_bda);
|
||||
|
||||
/**
|
||||
* @brief Start SDP to look up the service matching uuid on the remote device. This function should be called after
|
||||
* esp_bluedroid_enable() completes successfully
|
||||
*
|
||||
* esp_bt_gap_cb_t will is called with ESP_BT_GAP_RMT_SRVC_REC_EVT after service discovery ends
|
||||
* @return
|
||||
* - ESP_OK : Succeed
|
||||
* - ESP_INVALID_STATE: if bluetooth stack is not yet enabled
|
||||
* - ESP_FAIL: others
|
||||
*/
|
||||
esp_err_t esp_bt_gap_get_remote_service_record(esp_bd_addr_t remote_bda, esp_bt_uuid_t *uuid);
|
||||
|
||||
/**
|
||||
* @brief This function is called to get EIR data for a specific type.
|
||||
*
|
||||
* @param[in] eir - pointer of raw eir data to be resolved
|
||||
* @param[in] type - specific EIR data type
|
||||
* @param[out] length - return the length of EIR data excluding fields of length and data type
|
||||
*
|
||||
* @return pointer of starting position of eir data excluding eir data type, NULL if not found
|
||||
*
|
||||
*/
|
||||
uint8_t *esp_bt_gap_resolve_eir_data(uint8_t *eir, esp_bt_eir_type_t type, uint8_t *length);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
@ -1560,11 +1560,9 @@ void bta_dm_sdp_result (tBTA_DM_MSG *p_data)
|
||||
|| (p_data->sdp_event.sdp_result == SDP_DB_FULL)) {
|
||||
APPL_TRACE_DEBUG("sdp_result::0x%x", p_data->sdp_event.sdp_result);
|
||||
do {
|
||||
|
||||
p_sdp_rec = NULL;
|
||||
if ( bta_dm_search_cb.service_index == (BTA_USER_SERVICE_ID + 1) ) {
|
||||
p_sdp_rec = SDP_FindServiceUUIDInDb(bta_dm_search_cb.p_sdp_db, &bta_dm_search_cb.uuid, p_sdp_rec);
|
||||
|
||||
if (p_sdp_rec && SDP_FindProtocolListElemInRec(p_sdp_rec, UUID_PROTOCOL_RFCOMM, &pe)) {
|
||||
bta_dm_search_cb.peer_scn = (UINT8) pe.params[0];
|
||||
scn_found = TRUE;
|
||||
@ -1580,7 +1578,6 @@ void bta_dm_sdp_result (tBTA_DM_MSG *p_data)
|
||||
p_uuid += (bta_dm_search_cb.num_uuid - bta_dm_search_cb.uuid_to_search);
|
||||
/* only support 16 bits UUID for now */
|
||||
service = p_uuid->uu.uuid16;
|
||||
|
||||
}
|
||||
/* all GATT based services */
|
||||
do {
|
||||
@ -1613,7 +1610,7 @@ void bta_dm_sdp_result (tBTA_DM_MSG *p_data)
|
||||
if (((p_data->sdp_event.sdp_result == SDP_DB_FULL) &&
|
||||
bta_dm_search_cb.services != BTA_ALL_SERVICE_MASK) ||
|
||||
(p_sdp_rec != NULL)) {
|
||||
if (service != UUID_SERVCLASS_PNP_INFORMATION) {
|
||||
if (service != UUID_SERVCLASS_PNP_INFORMATION && service != 0) {
|
||||
UINT16 tmp_svc = 0xFFFF;
|
||||
bta_dm_search_cb.services_found |=
|
||||
(tBTA_SERVICE_MASK)(BTA_SERVICE_ID_TO_SERVICE_MASK(bta_dm_search_cb.service_index - 1));
|
||||
@ -1640,11 +1637,8 @@ void bta_dm_sdp_result (tBTA_DM_MSG *p_data)
|
||||
} else { /* regular one service per search or PNP search */
|
||||
break;
|
||||
}
|
||||
|
||||
} while (bta_dm_search_cb.service_index <= BTA_MAX_SERVICE_ID);
|
||||
|
||||
// osi_free(bta_dm_search_cb.p_sdp_db);
|
||||
// bta_dm_search_cb.p_sdp_db = NULL;
|
||||
APPL_TRACE_DEBUG("%s services_found = %04x", __FUNCTION__,
|
||||
bta_dm_search_cb.services_found);
|
||||
|
||||
@ -2054,13 +2048,13 @@ static void bta_dm_find_services ( BD_ADDR bd_addr)
|
||||
memset (&uuid, 0, sizeof(tSDP_UUID));
|
||||
|
||||
while (bta_dm_search_cb.service_index < BTA_MAX_SERVICE_ID) {
|
||||
if ( bta_dm_search_cb.services_to_search
|
||||
& (tBTA_SERVICE_MASK)(BTA_SERVICE_ID_TO_SERVICE_MASK(bta_dm_search_cb.service_index))) {
|
||||
tBTA_SERVICE_MASK this_service_mask = (tBTA_SERVICE_MASK)(BTA_SERVICE_ID_TO_SERVICE_MASK(bta_dm_search_cb.service_index));
|
||||
if ( bta_dm_search_cb.services_to_search & this_service_mask) {
|
||||
if ((bta_dm_search_cb.p_sdp_db = (tSDP_DISCOVERY_DB *)osi_malloc(BTA_DM_SDP_DB_SIZE)) != NULL) {
|
||||
APPL_TRACE_DEBUG("bta_dm_search_cb.services = %04x***********", bta_dm_search_cb.services);
|
||||
/* try to search all services by search based on L2CAP UUID */
|
||||
if (bta_dm_search_cb.services == BTA_ALL_SERVICE_MASK ) {
|
||||
LOG_INFO("%s services_to_search=%08x", __func__, bta_dm_search_cb.services_to_search);
|
||||
APPL_TRACE_DEBUG("%s services_to_search=%08x", __func__, bta_dm_search_cb.services_to_search);
|
||||
if (bta_dm_search_cb.services_to_search & BTA_RES_SERVICE_MASK) {
|
||||
uuid.uu.uuid16 = bta_service_id_to_uuid_lkup_tbl[0];
|
||||
bta_dm_search_cb.services_to_search &= ~BTA_RES_SERVICE_MASK;
|
||||
@ -2071,7 +2065,7 @@ static void bta_dm_find_services ( BD_ADDR bd_addr)
|
||||
} else {
|
||||
#if BLE_INCLUDED == TRUE && BTA_GATT_INCLUDED == TRUE
|
||||
/* for LE only profile */
|
||||
if (bta_dm_search_cb.service_index == BTA_BLE_SERVICE_ID) {
|
||||
if (this_service_mask == BTA_BLE_SERVICE_MASK) {
|
||||
if (bta_dm_search_cb.uuid_to_search > 0 && bta_dm_search_cb.p_srvc_uuid) {
|
||||
memcpy(&uuid,
|
||||
(const void *)(bta_dm_search_cb.p_srvc_uuid + \
|
||||
@ -2102,11 +2096,11 @@ static void bta_dm_find_services ( BD_ADDR bd_addr)
|
||||
uuid.len = LEN_UUID_16;
|
||||
}
|
||||
|
||||
if (bta_dm_search_cb.service_index == BTA_USER_SERVICE_ID) {
|
||||
if (this_service_mask == BTA_USER_SERVICE_MASK) {
|
||||
memcpy(&uuid, &bta_dm_search_cb.uuid, sizeof(tSDP_UUID));
|
||||
}
|
||||
|
||||
LOG_INFO("%s search UUID = %04x", __func__, uuid.uu.uuid16);
|
||||
APPL_TRACE_DEBUG("%s search UUID = %04x", __func__, uuid.uu.uuid16);
|
||||
SDP_InitDiscoveryDb (bta_dm_search_cb.p_sdp_db, BTA_DM_SDP_DB_SIZE, 1, &uuid, 0, NULL);
|
||||
|
||||
memset(g_disc_raw_data_buf, 0, sizeof(g_disc_raw_data_buf));
|
||||
@ -2123,9 +2117,9 @@ static void bta_dm_find_services ( BD_ADDR bd_addr)
|
||||
|
||||
} else {
|
||||
#if BLE_INCLUDED == TRUE && BTA_GATT_INCLUDED == TRUE
|
||||
if ((bta_dm_search_cb.service_index == BTA_BLE_SERVICE_ID &&
|
||||
if ((this_service_mask == BTA_BLE_SERVICE_MASK &&
|
||||
bta_dm_search_cb.uuid_to_search == 0) ||
|
||||
bta_dm_search_cb.service_index != BTA_BLE_SERVICE_ID)
|
||||
this_service_mask != BTA_BLE_SERVICE_MASK)
|
||||
#endif
|
||||
bta_dm_search_cb.service_index++;
|
||||
return;
|
||||
|
@ -28,6 +28,9 @@
|
||||
#include "bta_gatt_api.h"
|
||||
#include "allocator.h"
|
||||
|
||||
#if (BTC_GAP_BT_INCLUDED == TRUE)
|
||||
#include "btc_gap_bt.h"
|
||||
#endif /* BTC_GAP_BT_INCLUDED == TRUE */
|
||||
|
||||
/******************************************************************************
|
||||
** Constants & Macros
|
||||
@ -481,6 +484,14 @@ void btc_dm_sec_cb_handler(btc_msg_t *msg)
|
||||
break;
|
||||
}
|
||||
case BTA_DM_BUSY_LEVEL_EVT:
|
||||
#if (BTC_GAP_BT_INCLUDED == TRUE)
|
||||
{
|
||||
if (p_data->busy_level.level_flags & BTM_BL_INQUIRY_PAGING_MASK) {
|
||||
btc_gap_bt_busy_level_updated(p_data->busy_level.level_flags);
|
||||
}
|
||||
break;
|
||||
}
|
||||
#endif /* BTC_GAP_BT_INCLUDED == TRUE */
|
||||
case BTA_DM_LINK_UP_EVT:
|
||||
case BTA_DM_LINK_DOWN_EVT:
|
||||
case BTA_DM_HW_ERROR_EVT:
|
||||
|
@ -14,6 +14,7 @@
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include "bt_target.h"
|
||||
#include "btc_task.h"
|
||||
#include "bt_trace.h"
|
||||
#include "thread.h"
|
||||
@ -29,7 +30,9 @@
|
||||
#include "btc_alarm.h"
|
||||
#include "bta_gatt_api.h"
|
||||
#if CONFIG_CLASSIC_BT_ENABLED
|
||||
#if (BTC_GAP_BT_INCLUDED == TRUE)
|
||||
#include "btc_gap_bt.h"
|
||||
#endif /* BTC_GAP_BT_INCLUDED == TRUE */
|
||||
#include "btc_profile_queue.h"
|
||||
#include "btc_av.h"
|
||||
#include "btc_avrc.h"
|
||||
@ -57,7 +60,9 @@ static btc_func_t profile_tab[BTC_PID_NUM] = {
|
||||
[BTC_PID_DM_SEC] = {NULL, btc_dm_sec_cb_handler },
|
||||
[BTC_PID_ALARM] = {btc_alarm_handler, NULL },
|
||||
#if CONFIG_CLASSIC_BT_ENABLED
|
||||
#if (BTC_GAP_BT_INCLUDED == TRUE)
|
||||
[BTC_PID_GAP_BT] = {btc_gap_bt_call_handler, NULL },
|
||||
#endif /* (BTC_GAP_BT_INCLUDED == TRUE) */
|
||||
[BTC_PID_PRF_QUE] = {btc_profile_queue_handler, NULL },
|
||||
[BTC_PID_A2DP] = {btc_a2dp_call_handler, btc_a2dp_cb_handler },
|
||||
[BTC_PID_AVRC] = {btc_avrc_call_handler, NULL },
|
||||
|
@ -129,6 +129,7 @@ UINT32 devclass2uint(DEV_CLASS dev_class)
|
||||
}
|
||||
return cod;
|
||||
}
|
||||
|
||||
void uint2devclass(UINT32 cod, DEV_CLASS dev_class)
|
||||
{
|
||||
dev_class[2] = (UINT8)cod;
|
||||
@ -136,61 +137,26 @@ void uint2devclass(UINT32 cod, DEV_CLASS dev_class)
|
||||
dev_class[0] = (UINT8)(cod >> 16);
|
||||
}
|
||||
|
||||
static const UINT8 sdp_base_uuid[] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00,
|
||||
0x80, 0x00, 0x00, 0x80, 0x5F, 0x9B, 0x34, 0xFB
|
||||
};
|
||||
static const UINT8 base_uuid_be[] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00,
|
||||
0x80, 0x00, 0x00, 0x80, 0x5F, 0x9B, 0x34, 0xFB};
|
||||
|
||||
void uuid16_to_uuid128(uint16_t uuid16, bt_uuid_t *uuid128)
|
||||
void uuid128_be_to_esp_uuid(esp_bt_uuid_t *u, uint8_t* uuid128)
|
||||
{
|
||||
uint16_t uuid16_bo;
|
||||
memset(uuid128, 0, sizeof(bt_uuid_t));
|
||||
|
||||
memcpy(uuid128->uu, sdp_base_uuid, MAX_UUID_SIZE);
|
||||
uuid16_bo = ntohs(uuid16);
|
||||
memcpy(uuid128->uu + 2, &uuid16_bo, sizeof(uint16_t));
|
||||
}
|
||||
|
||||
void string_to_uuid(char *str, bt_uuid_t *p_uuid)
|
||||
{
|
||||
uint32_t uuid0, uuid4;
|
||||
uint16_t uuid1, uuid2, uuid3, uuid5;
|
||||
|
||||
sscanf(str, "%08x-%04hx-%04hx-%04hx-%08x%04hx",
|
||||
&uuid0, &uuid1, &uuid2, &uuid3, &uuid4, &uuid5);
|
||||
|
||||
uuid0 = htonl(uuid0);
|
||||
uuid1 = htons(uuid1);
|
||||
uuid2 = htons(uuid2);
|
||||
uuid3 = htons(uuid3);
|
||||
uuid4 = htonl(uuid4);
|
||||
uuid5 = htons(uuid5);
|
||||
|
||||
memcpy(&(p_uuid->uu[0]), &uuid0, 4);
|
||||
memcpy(&(p_uuid->uu[4]), &uuid1, 2);
|
||||
memcpy(&(p_uuid->uu[6]), &uuid2, 2);
|
||||
memcpy(&(p_uuid->uu[8]), &uuid3, 2);
|
||||
memcpy(&(p_uuid->uu[10]), &uuid4, 4);
|
||||
memcpy(&(p_uuid->uu[14]), &uuid5, 2);
|
||||
if (memcmp(base_uuid_be+4, uuid128 + 4, 12) != 0) {
|
||||
u->len = ESP_UUID_LEN_128;
|
||||
uint8_t *p_i = uuid128 + ESP_UUID_LEN_128 - 1;
|
||||
uint8_t *p_o = u->uuid.uuid128;
|
||||
uint8_t *p_end = p_o + ESP_UUID_LEN_128;
|
||||
for (; p_o != p_end; *p_o++ = *p_i--)
|
||||
;
|
||||
} else if (uuid128[0] == 0 && uuid128[1] == 0) {
|
||||
u->len = 2;
|
||||
u->uuid.uuid16 = (uuid128[2] << 8) + uuid128[3];
|
||||
} else {
|
||||
u->len = 4;
|
||||
u->uuid.uuid32 = (uuid128[2] << 8) + uuid128[3];
|
||||
u->uuid.uuid32 += (uuid128[0] << 24) + (uuid128[1] << 16);
|
||||
}
|
||||
|
||||
return;
|
||||
|
||||
}
|
||||
|
||||
void uuid_to_string_legacy(bt_uuid_t *p_uuid, char *str)
|
||||
{
|
||||
uint32_t uuid0, uuid4;
|
||||
uint16_t uuid1, uuid2, uuid3, uuid5;
|
||||
|
||||
memcpy(&uuid0, &(p_uuid->uu[0]), 4);
|
||||
memcpy(&uuid1, &(p_uuid->uu[4]), 2);
|
||||
memcpy(&uuid2, &(p_uuid->uu[6]), 2);
|
||||
memcpy(&uuid3, &(p_uuid->uu[8]), 2);
|
||||
memcpy(&uuid4, &(p_uuid->uu[10]), 4);
|
||||
memcpy(&uuid5, &(p_uuid->uu[14]), 2);
|
||||
|
||||
sprintf((char *)str, "%.8x-%.4x-%.4x-%.4x-%.8x%.4x",
|
||||
ntohl(uuid0), ntohs(uuid1),
|
||||
ntohs(uuid2), ntohs(uuid3),
|
||||
ntohl(uuid4), ntohs(uuid5));
|
||||
return;
|
||||
}
|
||||
|
@ -18,6 +18,7 @@
|
||||
#include <stdbool.h>
|
||||
#include "bt_types.h"
|
||||
#include "bt_defs.h"
|
||||
#include "esp_bt_defs.h"
|
||||
|
||||
/*******************************************************************************
|
||||
** Constants & Macros
|
||||
@ -39,9 +40,6 @@ const char *dump_rc_pdu(UINT8 pdu);
|
||||
|
||||
UINT32 devclass2uint(DEV_CLASS dev_class);
|
||||
void uint2devclass(UINT32 dev, DEV_CLASS dev_class);
|
||||
void uuid16_to_uuid128(uint16_t uuid16, bt_uuid_t *uuid128);
|
||||
|
||||
void uuid_to_string_legacy(bt_uuid_t *p_uuid, char *str);
|
||||
void string_to_uuid(char *str, bt_uuid_t *p_uuid);
|
||||
void uuid128_be_to_esp_uuid(esp_bt_uuid_t *u, uint8_t* uuid128);
|
||||
|
||||
#endif /* __BTC_UTIL_H__ */
|
||||
|
@ -12,30 +12,37 @@
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#include <string.h>
|
||||
#include "esp_bt_defs.h"
|
||||
#include "esp_gap_bt_api.h"
|
||||
#include "btc_gap_bt.h"
|
||||
#include "bta_api.h"
|
||||
#include "bt_trace.h"
|
||||
#include <string.h>
|
||||
#include "bt_target.h"
|
||||
#include "btc_manage.h"
|
||||
#include "btc_util.h"
|
||||
#include "allocator.h"
|
||||
|
||||
#if BTC_GAP_BT_INCLUDED
|
||||
void btc_gap_bt_arg_deep_copy(btc_msg_t *msg, void *p_dest, void *p_src)
|
||||
{
|
||||
switch (msg->act) {
|
||||
default:
|
||||
// LOG_ERROR("Unhandled deep copy %d\n", msg->act);
|
||||
break;
|
||||
}
|
||||
}
|
||||
#if (BTC_GAP_BT_INCLUDED == TRUE)
|
||||
|
||||
static void btc_gap_bt_arg_deep_free(btc_msg_t *msg)
|
||||
#define COD_UNCLASSIFIED ((0x1F) << 8)
|
||||
|
||||
#define BTC_STORAGE_FILL_PROPERTY(p_prop, t, l, p_v) \
|
||||
(p_prop)->type = t;(p_prop)->len = l; (p_prop)->val = (p_v);
|
||||
|
||||
static void bte_search_devices_evt(tBTA_DM_SEARCH_EVT event, tBTA_DM_SEARCH *p_data);
|
||||
static void bte_dm_search_services_evt(tBTA_DM_SEARCH_EVT event, tBTA_DM_SEARCH *p_data);
|
||||
static void bte_dm_remote_service_record_evt(tBTA_DM_SEARCH_EVT event, tBTA_DM_SEARCH *p_data);
|
||||
static void search_services_copy_cb(btc_msg_t *msg, void *p_dest, void *p_src);
|
||||
static void search_service_record_copy_cb(btc_msg_t *msg, void *p_dest, void *p_src);
|
||||
|
||||
static bool btc_gap_bt_inquiry_in_progress = false;
|
||||
|
||||
static inline void btc_gap_bt_cb_to_app(esp_bt_gap_cb_event_t event, esp_bt_gap_cb_param_t *param)
|
||||
{
|
||||
LOG_DEBUG("%s \n", __func__);
|
||||
switch (msg->act) {
|
||||
default:
|
||||
// LOG_DEBUG("Unhandled deep free %d\n", msg->act);
|
||||
break;
|
||||
esp_bt_gap_cb_t cb = (esp_bt_gap_cb_t)btc_profile_cb_get(BTC_PID_GAP_BT);
|
||||
if (cb) {
|
||||
cb(event, param);
|
||||
}
|
||||
}
|
||||
|
||||
@ -69,6 +76,497 @@ static void btc_bt_set_scan_mode(esp_bt_scan_mode_t mode)
|
||||
return;
|
||||
}
|
||||
|
||||
static void btc_gap_bt_start_discovery(btc_gap_bt_args_t *arg)
|
||||
{
|
||||
tBTA_DM_INQ inq_params;
|
||||
tBTA_SERVICE_MASK services = 0;
|
||||
|
||||
BTIF_TRACE_EVENT("%s", __FUNCTION__);
|
||||
|
||||
inq_params.mode = (arg->start_disc.mode == ESP_BT_INQ_MODE_GENERAL_INQUIRY) ?
|
||||
BTA_DM_GENERAL_INQUIRY : BTA_DM_LIMITED_INQUIRY;
|
||||
inq_params.duration = arg->start_disc.inq_len;
|
||||
inq_params.max_resps = arg->start_disc.num_rsps;
|
||||
|
||||
inq_params.report_dup = TRUE;
|
||||
inq_params.filter_type = BTA_DM_INQ_CLR;
|
||||
/* TODO: Filter device by BDA needs to be implemented here */
|
||||
|
||||
/* Will be enabled to TRUE once inquiry busy level has been received */
|
||||
btc_gap_bt_inquiry_in_progress = FALSE;
|
||||
/* find nearby devices */
|
||||
BTA_DmSearch(&inq_params, services, bte_search_devices_evt);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
static void btc_gap_bt_cancel_discovery(void)
|
||||
{
|
||||
BTA_DmSearchCancel();
|
||||
}
|
||||
|
||||
static void btc_gap_bt_get_remote_services(bt_bdaddr_t *remote_bda)
|
||||
{
|
||||
BTA_DmDiscover(remote_bda->address, BTA_ALL_SERVICE_MASK,
|
||||
bte_dm_search_services_evt, TRUE);
|
||||
}
|
||||
|
||||
static void btc_gap_bt_get_remote_service_record(btc_gap_bt_args_t *arg)
|
||||
{
|
||||
esp_bt_uuid_t *uuid = &arg->get_rmt_srv_rcd.uuid;
|
||||
bt_bdaddr_t *remote_bda = &arg->get_rmt_srv_rcd.bda;
|
||||
|
||||
tSDP_UUID sdp_uuid;
|
||||
|
||||
sdp_uuid.len = uuid->len;
|
||||
memcpy(&sdp_uuid.uu, &uuid->uuid, uuid->len);
|
||||
|
||||
BTA_DmDiscoverUUID(remote_bda->address, &sdp_uuid,
|
||||
bte_dm_remote_service_record_evt, TRUE);
|
||||
}
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
** Function search_devices_copy_cb
|
||||
**
|
||||
** Description Deep copy callback for search devices event
|
||||
**
|
||||
** Returns void
|
||||
**
|
||||
*******************************************************************************/
|
||||
static void search_devices_copy_cb(btc_msg_t *msg, void *p_dest, void *p_src)
|
||||
{
|
||||
tBTA_DM_SEARCH *p_dest_data = (tBTA_DM_SEARCH *) p_dest;
|
||||
tBTA_DM_SEARCH *p_src_data = (tBTA_DM_SEARCH *) p_src;
|
||||
|
||||
if (!p_src) {
|
||||
return;
|
||||
}
|
||||
|
||||
switch (msg->aid) {
|
||||
case BTA_DM_INQ_RES_EVT: {
|
||||
if (p_src_data->inq_res.p_eir) {
|
||||
p_dest_data->inq_res.p_eir = (UINT8 *)(p_dest + sizeof(tBTA_DM_SEARCH));
|
||||
memcpy(p_dest_data->inq_res.p_eir, p_src_data->inq_res.p_eir, HCI_EXT_INQ_RESPONSE_LEN);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case BTA_DM_DISC_RES_EVT: {
|
||||
if (p_src_data->disc_res.raw_data_size && p_src_data->disc_res.p_raw_data) {
|
||||
p_dest_data->disc_res.p_raw_data = (UINT8 *)(p_dest + sizeof(tBTA_DM_SEARCH));
|
||||
memcpy(p_dest_data->disc_res.p_raw_data,
|
||||
p_src_data->disc_res.p_raw_data,
|
||||
p_src_data->disc_res.raw_data_size);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
** Function search_service_record_copy_cb
|
||||
**
|
||||
** Description Deep copy callback for search service record event
|
||||
**
|
||||
** Returns void
|
||||
**
|
||||
*******************************************************************************/
|
||||
static void search_service_record_copy_cb(btc_msg_t *msg, void *p_dest, void *p_src)
|
||||
{
|
||||
tBTA_DM_SEARCH *p_dest_data = (tBTA_DM_SEARCH *) p_dest;
|
||||
tBTA_DM_SEARCH *p_src_data = (tBTA_DM_SEARCH *) p_src;
|
||||
|
||||
if (!p_src) {
|
||||
return;
|
||||
}
|
||||
|
||||
switch (msg->aid) {
|
||||
case BTA_DM_DISC_RES_EVT: {
|
||||
if (p_src_data->disc_res.p_raw_data && p_src_data->disc_res.raw_data_size > 0) {
|
||||
p_dest_data->disc_res.p_raw_data = (UINT8 *)(p_dest + sizeof(tBTA_DM_SEARCH));
|
||||
memcpy(p_dest_data->disc_res.p_raw_data,
|
||||
p_src_data->disc_res.p_raw_data,
|
||||
p_src_data->disc_res.raw_data_size);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
** Function check_eir_remote_name
|
||||
**
|
||||
** Description Check if remote name is in the EIR data
|
||||
**
|
||||
** Returns TRUE if remote name found
|
||||
** Populate p_remote_name, if provided and remote name found
|
||||
**
|
||||
*******************************************************************************/
|
||||
static BOOLEAN check_eir_remote_name(tBTA_DM_SEARCH *p_search_data,
|
||||
UINT8 *p_remote_name, UINT8 *p_remote_name_len)
|
||||
{
|
||||
UINT8 *p_eir_remote_name = NULL;
|
||||
UINT8 remote_name_len = 0;
|
||||
|
||||
/* Check EIR for remote name and services */
|
||||
if (p_search_data->inq_res.p_eir) {
|
||||
p_eir_remote_name = BTM_CheckEirData(p_search_data->inq_res.p_eir,
|
||||
BTM_EIR_COMPLETE_LOCAL_NAME_TYPE, &remote_name_len);
|
||||
if (!p_eir_remote_name) {
|
||||
p_eir_remote_name = BTM_CheckEirData(p_search_data->inq_res.p_eir,
|
||||
BTM_EIR_SHORTENED_LOCAL_NAME_TYPE, &remote_name_len);
|
||||
}
|
||||
|
||||
if (p_eir_remote_name) {
|
||||
if (remote_name_len > BD_NAME_LEN) {
|
||||
remote_name_len = BD_NAME_LEN;
|
||||
}
|
||||
|
||||
if (p_remote_name && p_remote_name_len) {
|
||||
memcpy(p_remote_name, p_eir_remote_name, remote_name_len);
|
||||
*(p_remote_name + remote_name_len) = 0;
|
||||
*p_remote_name_len = remote_name_len;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
** Function bte_search_devices_evt
|
||||
**
|
||||
** Description Switches context from BTE to BTIF for DM search events
|
||||
**
|
||||
** Returns void
|
||||
**
|
||||
*******************************************************************************/
|
||||
static void bte_search_devices_evt(tBTA_DM_SEARCH_EVT event, tBTA_DM_SEARCH *p_data)
|
||||
{
|
||||
UINT16 param_len = 0;
|
||||
|
||||
if (p_data) {
|
||||
param_len += sizeof(tBTA_DM_SEARCH);
|
||||
}
|
||||
/* Allocate buffer to hold the pointers (deep copy). The pointers will point to the end of the tBTA_DM_SEARCH */
|
||||
switch (event) {
|
||||
case BTA_DM_INQ_RES_EVT: {
|
||||
if (p_data->inq_res.p_eir) {
|
||||
param_len += HCI_EXT_INQ_RESPONSE_LEN;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case BTA_DM_DISC_RES_EVT: {
|
||||
if (p_data->disc_res.raw_data_size && p_data->disc_res.p_raw_data) {
|
||||
param_len += p_data->disc_res.raw_data_size;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
/* if remote name is available in EIR, set the flag so that stack doesn't trigger RNR */
|
||||
if (event == BTA_DM_INQ_RES_EVT) {
|
||||
p_data->inq_res.remt_name_not_required = check_eir_remote_name(p_data, NULL, NULL);
|
||||
}
|
||||
|
||||
do {
|
||||
btc_msg_t msg;
|
||||
msg.sig = BTC_SIG_API_CALL;
|
||||
msg.pid = BTC_PID_GAP_BT;
|
||||
msg.act = BTC_GAP_BT_ACT_SEARCH_DEVICES;
|
||||
msg.aid = event;
|
||||
|
||||
btc_transfer_context(&msg, p_data, param_len,
|
||||
(param_len > sizeof(tBTA_DM_SEARCH)) ? search_devices_copy_cb : NULL);
|
||||
} while (0);
|
||||
}
|
||||
|
||||
static void btc_gap_bt_search_devices_evt(tBTA_DM_SEARCH_EVT event, tBTA_DM_SEARCH *p_data)
|
||||
{
|
||||
switch (event) {
|
||||
case BTA_DM_DISC_RES_EVT: {
|
||||
/* remote name update */
|
||||
uint32_t bdname_len = strlen((const char *)p_data->disc_res.bd_name);
|
||||
if (bdname_len) {
|
||||
esp_bt_gap_dev_prop_t prop[1];
|
||||
|
||||
BTC_STORAGE_FILL_PROPERTY(&prop[0], ESP_BT_GAP_DEV_PROP_BDNAME, bdname_len + 1, p_data->disc_res.bd_name);
|
||||
|
||||
esp_bt_gap_cb_param_t param;
|
||||
bdcpy(param.disc_res.bda, p_data->disc_res.bd_addr);
|
||||
param.disc_res.num_prop = 1;
|
||||
param.disc_res.prop = prop;
|
||||
btc_gap_bt_cb_to_app(ESP_BT_GAP_DISC_RES_EVT, ¶m);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case BTA_DM_INQ_RES_EVT: {
|
||||
/* inquiry result */
|
||||
uint32_t cod = devclass2uint (p_data->inq_res.dev_class);
|
||||
|
||||
if (cod == 0) {
|
||||
LOG_DEBUG("%s cod is 0, set as unclassified", __func__);
|
||||
cod = COD_UNCLASSIFIED;
|
||||
}
|
||||
|
||||
do {
|
||||
esp_bt_gap_dev_prop_t prop[3];
|
||||
int num_prop = 0;
|
||||
|
||||
memset(prop, 0, sizeof(prop));
|
||||
BTC_STORAGE_FILL_PROPERTY(&prop[0], ESP_BT_GAP_DEV_PROP_COD, sizeof(cod), &cod);
|
||||
num_prop++;
|
||||
|
||||
BTC_STORAGE_FILL_PROPERTY(&prop[1], ESP_BT_GAP_DEV_PROP_RSSI, 1, &(p_data->inq_res.rssi));
|
||||
num_prop++;
|
||||
|
||||
if (p_data->inq_res.p_eir) {
|
||||
BTC_STORAGE_FILL_PROPERTY(&prop[2], ESP_BT_GAP_DEV_PROP_EIR, HCI_EXT_INQ_RESPONSE_LEN, p_data->inq_res.p_eir);
|
||||
num_prop++;
|
||||
}
|
||||
|
||||
/* Callback to notify upper layer of device */
|
||||
esp_bt_gap_cb_param_t param;
|
||||
bdcpy(param.disc_res.bda, p_data->inq_res.bd_addr);
|
||||
param.disc_res.num_prop = num_prop;
|
||||
param.disc_res.prop = prop;
|
||||
btc_gap_bt_cb_to_app(ESP_BT_GAP_DISC_RES_EVT, ¶m);
|
||||
} while (0);
|
||||
}
|
||||
break;
|
||||
|
||||
case BTA_DM_INQ_CMPL_EVT:
|
||||
break;
|
||||
case BTA_DM_DISC_CMPL_EVT: {
|
||||
esp_bt_gap_cb_param_t param;
|
||||
param.disc_st_chg.state = ESP_BT_GAP_DISCOVERY_STOPPED;
|
||||
btc_gap_bt_cb_to_app(ESP_BT_GAP_DISC_STATE_CHANGED_EVT, ¶m);
|
||||
break;
|
||||
}
|
||||
case BTA_DM_SEARCH_CANCEL_CMPL_EVT: {
|
||||
/* if inquiry is not in progress and we get a cancel event, then
|
||||
* it means we are done with inquiry, but remote_name fetches are in
|
||||
* progress
|
||||
*
|
||||
* if inquiry is in progress, then we don't want to act on this cancel_cmpl_evt
|
||||
* but instead wait for the cancel_cmpl_evt_via the busy level
|
||||
*/
|
||||
if (btc_gap_bt_inquiry_in_progress == false) {
|
||||
esp_bt_gap_cb_param_t param;
|
||||
param.disc_st_chg.state = ESP_BT_GAP_DISCOVERY_STOPPED;
|
||||
btc_gap_bt_cb_to_app(ESP_BT_GAP_DISC_STATE_CHANGED_EVT, ¶m);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
/*******************************************************************************
|
||||
**
|
||||
** Function btc_gap_bt_search_service_record
|
||||
**
|
||||
** Description Executes search service record event in btif context
|
||||
**
|
||||
** Returns void
|
||||
**
|
||||
*******************************************************************************/
|
||||
static void btc_gap_bt_search_service_record(UINT16 event, char *p_param)
|
||||
{
|
||||
tBTA_DM_SEARCH *p_data = (tBTA_DM_SEARCH *)p_param;
|
||||
|
||||
switch (event) {
|
||||
case BTA_DM_DISC_RES_EVT: {
|
||||
esp_bt_gap_cb_param_t param;
|
||||
memcpy(param.rmt_srvcs.bda, p_data->disc_res.bd_addr, BD_ADDR_LEN);
|
||||
if (p_data->disc_res.p_raw_data && p_data->disc_res.raw_data_size > 0) {
|
||||
param.rmt_srvc_rec.stat = ESP_BT_STATUS_SUCCESS;
|
||||
// param.rmt_srvc_rec.raw_data_size = p_data->disc_res.raw_data_size;
|
||||
// param.rmt_srvc_rec.raw_data = p_data->disc_res.p_raw_data;
|
||||
} else {
|
||||
param.rmt_srvc_rec.stat = ESP_BT_STATUS_FAIL;
|
||||
// param.rmt_srvc_rec.raw_data_size = 0;
|
||||
// param.rmt_srvc_rec.raw_data = NULL;
|
||||
}
|
||||
btc_gap_bt_cb_to_app(ESP_BT_GAP_RMT_SRVC_REC_EVT, ¶m);
|
||||
}
|
||||
break;
|
||||
case BTA_DM_DISC_CMPL_EVT:
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
** Function bte_dm_remote_service_record_evt
|
||||
**
|
||||
** Description Switches context from BTE to BTC for DM search service
|
||||
** record event
|
||||
**
|
||||
** Returns void
|
||||
**
|
||||
*******************************************************************************/
|
||||
static void bte_dm_remote_service_record_evt(tBTA_DM_SEARCH_EVT event, tBTA_DM_SEARCH *p_data)
|
||||
{
|
||||
UINT16 param_len = 0;
|
||||
|
||||
if (p_data) {
|
||||
param_len += sizeof(tBTA_DM_SEARCH);
|
||||
}
|
||||
/* Allocate buffer to hold the pointers (deep copy). The pointers will point to the end of the tBTA_DM_SEARCH */
|
||||
if (event == BTA_DM_DISC_RES_EVT) {
|
||||
if (p_data->disc_res.raw_data_size && p_data->disc_res.p_raw_data) {
|
||||
param_len += p_data->disc_res.raw_data_size;
|
||||
}
|
||||
}
|
||||
|
||||
do {
|
||||
btc_msg_t msg;
|
||||
msg.sig = BTC_SIG_API_CALL;
|
||||
msg.pid = BTC_PID_GAP_BT;
|
||||
msg.act = BTC_GAP_BT_ACT_SEARCH_SERVICE_RECORD;
|
||||
msg.aid = event;
|
||||
|
||||
btc_transfer_context(&msg, p_data, param_len,
|
||||
(param_len > sizeof(tBTA_DM_SEARCH)) ? search_service_record_copy_cb : NULL);
|
||||
|
||||
} while (0);
|
||||
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
** Function btc_gap_bt_search_services
|
||||
**
|
||||
** Description Executes search services event in btc context
|
||||
**
|
||||
** Returns void
|
||||
**
|
||||
*******************************************************************************/
|
||||
static void btc_gap_bt_search_services(UINT16 event, char *p_param)
|
||||
{
|
||||
tBTA_DM_SEARCH *p_data = (tBTA_DM_SEARCH *)p_param;
|
||||
|
||||
switch (event) {
|
||||
case BTA_DM_DISC_RES_EVT: {
|
||||
esp_bt_gap_cb_param_t param;
|
||||
esp_bt_uuid_t *uuid_list = NULL;
|
||||
memcpy(param.rmt_srvcs.bda, p_data->disc_res.bd_addr, BD_ADDR_LEN);
|
||||
|
||||
param.rmt_srvcs.stat = ESP_BT_STATUS_FAIL;
|
||||
if (p_data->disc_res.result == BTA_SUCCESS) {
|
||||
uuid_list = malloc(sizeof(esp_bt_uuid_t) * p_data->disc_res.num_uuids);
|
||||
if (uuid_list) {
|
||||
param.rmt_srvcs.stat = ESP_BT_STATUS_SUCCESS;
|
||||
param.rmt_srvcs.num_uuids = p_data->disc_res.num_uuids;
|
||||
param.rmt_srvcs.uuid_list = uuid_list;
|
||||
// copy UUID list
|
||||
uint8_t *i_uu = (uint8_t *)p_data->disc_res.p_uuid_list;
|
||||
esp_bt_uuid_t *o_uu = uuid_list;
|
||||
for (int i = 0; i < p_data->disc_res.num_uuids; i++, i_uu += ESP_UUID_LEN_128, o_uu++) {
|
||||
uuid128_be_to_esp_uuid(o_uu, i_uu);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (param.rmt_srvcs.stat == ESP_BT_STATUS_FAIL) {
|
||||
param.rmt_srvcs.num_uuids = 0;
|
||||
param.rmt_srvcs.uuid_list = NULL;
|
||||
}
|
||||
btc_gap_bt_cb_to_app(ESP_BT_GAP_RMT_SRVCS_EVT, ¶m);
|
||||
|
||||
if (uuid_list) {
|
||||
osi_free(uuid_list);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case BTA_DM_DISC_BLE_RES_EVT:
|
||||
case BTA_DM_DISC_CMPL_EVT:
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
** Function bte_dm_search_services_evt
|
||||
**
|
||||
** Description Switches context from BTE to BTIF for DM search services
|
||||
** event
|
||||
**
|
||||
** Returns void
|
||||
**
|
||||
*******************************************************************************/
|
||||
static void bte_dm_search_services_evt(tBTA_DM_SEARCH_EVT event, tBTA_DM_SEARCH *p_data)
|
||||
{
|
||||
UINT16 param_len = 0;
|
||||
if (p_data) {
|
||||
param_len += sizeof(tBTA_DM_SEARCH);
|
||||
}
|
||||
|
||||
switch (event) {
|
||||
case BTA_DM_DISC_RES_EVT: {
|
||||
if ((p_data->disc_res.result == BTA_SUCCESS) && (p_data->disc_res.num_uuids > 0)) {
|
||||
param_len += (p_data->disc_res.num_uuids * MAX_UUID_SIZE);
|
||||
}
|
||||
} break;
|
||||
}
|
||||
|
||||
/* TODO: The only other member that needs a deep copy is the p_raw_data. But not sure
|
||||
* if raw_data is needed. */
|
||||
do {
|
||||
btc_msg_t msg;
|
||||
msg.sig = BTC_SIG_API_CALL;
|
||||
msg.pid = BTC_PID_GAP_BT;
|
||||
msg.act = BTC_GAP_BT_ACT_SEARCH_SERVICES;
|
||||
msg.aid = event;
|
||||
|
||||
btc_transfer_context(&msg, p_data, param_len,
|
||||
(param_len > sizeof(tBTA_DM_SEARCH)) ? search_services_copy_cb : NULL);
|
||||
} while (0);
|
||||
}
|
||||
|
||||
static void search_services_copy_cb(btc_msg_t *msg, void *p_dest, void *p_src)
|
||||
{
|
||||
tBTA_DM_SEARCH *p_dest_data = (tBTA_DM_SEARCH *) p_dest;
|
||||
tBTA_DM_SEARCH *p_src_data = (tBTA_DM_SEARCH *) p_src;
|
||||
|
||||
if (!p_src) {
|
||||
return;
|
||||
}
|
||||
|
||||
switch (msg->aid) {
|
||||
case BTA_DM_DISC_RES_EVT: {
|
||||
if (p_src_data->disc_res.result == BTA_SUCCESS) {
|
||||
if (p_src_data->disc_res.num_uuids > 0) {
|
||||
p_dest_data->disc_res.p_uuid_list = (UINT8 *)(p_dest + sizeof(tBTA_DM_SEARCH));
|
||||
memcpy(p_dest_data->disc_res.p_uuid_list, p_src_data->disc_res.p_uuid_list,
|
||||
p_src_data->disc_res.num_uuids * MAX_UUID_SIZE);
|
||||
osi_free(p_src_data->disc_res.p_uuid_list);
|
||||
p_src_data->disc_res.p_uuid_list = NULL;
|
||||
}
|
||||
if (p_src_data->disc_res.p_raw_data != NULL) {
|
||||
osi_free(p_src_data->disc_res.p_raw_data);
|
||||
p_src_data->disc_res.p_raw_data = NULL;
|
||||
}
|
||||
}
|
||||
} break;
|
||||
}
|
||||
}
|
||||
|
||||
void btc_gap_bt_call_handler(btc_msg_t *msg)
|
||||
{
|
||||
btc_gap_bt_args_t *arg = (btc_gap_bt_args_t *)msg->arg;
|
||||
@ -78,10 +576,55 @@ void btc_gap_bt_call_handler(btc_msg_t *msg)
|
||||
btc_bt_set_scan_mode(arg->set_scan_mode.mode);
|
||||
break;
|
||||
}
|
||||
case BTC_GAP_BT_ACT_START_DISCOVERY: {
|
||||
btc_gap_bt_start_discovery(msg->arg);
|
||||
break;
|
||||
}
|
||||
case BTC_GAP_BT_ACT_SEARCH_DEVICES: {
|
||||
btc_gap_bt_search_devices_evt(msg->aid, msg->arg);
|
||||
break;
|
||||
}
|
||||
case BTC_GAP_BT_ACT_CANCEL_DISCOVERY: {
|
||||
btc_gap_bt_cancel_discovery();
|
||||
break;
|
||||
}
|
||||
case BTC_GAP_BT_ACT_GET_REMOTE_SERVICES: {
|
||||
btc_gap_bt_get_remote_services(msg->arg);
|
||||
break;
|
||||
}
|
||||
case BTC_GAP_BT_ACT_SEARCH_SERVICES: {
|
||||
btc_gap_bt_search_services(msg->aid, msg->arg);
|
||||
break;
|
||||
}
|
||||
case BTC_GAP_BT_ACT_GET_REMOTE_SERVICE_RECORD: {
|
||||
btc_gap_bt_get_remote_service_record(msg->arg);
|
||||
break;
|
||||
}
|
||||
case BTC_GAP_BT_ACT_SEARCH_SERVICE_RECORD: {
|
||||
btc_gap_bt_search_service_record(msg->aid, msg->arg);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
btc_gap_bt_arg_deep_free(msg);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
#endif /* #if BTC_GAP_BT_INCLUDED */
|
||||
void btc_gap_bt_busy_level_updated(uint8_t bl_flags)
|
||||
{
|
||||
esp_bt_gap_cb_param_t param;
|
||||
|
||||
if (bl_flags == BTM_BL_INQUIRY_STARTED) {
|
||||
param.disc_st_chg.state = ESP_BT_GAP_DISCOVERY_STARTED;
|
||||
btc_gap_bt_cb_to_app(ESP_BT_GAP_DISC_STATE_CHANGED_EVT, ¶m);
|
||||
btc_gap_bt_inquiry_in_progress = true;
|
||||
} else if (bl_flags == BTM_BL_INQUIRY_CANCELLED ||
|
||||
bl_flags == BTM_BL_INQUIRY_COMPLETE) {
|
||||
param.disc_st_chg.state = ESP_BT_GAP_DISCOVERY_STOPPED;
|
||||
btc_gap_bt_cb_to_app(ESP_BT_GAP_DISC_STATE_CHANGED_EVT, ¶m);
|
||||
btc_gap_bt_inquiry_in_progress = false;
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* (BTC_GAP_BT_INCLUDED == TRUE) */
|
||||
|
@ -15,12 +15,23 @@
|
||||
#ifndef __BTC_GAP_BT_H__
|
||||
#define __BTC_GAP_BT_H__
|
||||
|
||||
#include "bt_target.h"
|
||||
#include "esp_bt_defs.h"
|
||||
#include "esp_gap_bt_api.h"
|
||||
#include "btc_task.h"
|
||||
|
||||
#if (BTC_GAP_BT_INCLUDED == TRUE)
|
||||
|
||||
typedef enum {
|
||||
BTC_GAP_BT_ACT_SET_SCAN_MODE = 0,
|
||||
BTC_GAP_BT_ACT_REG_CB,
|
||||
BTC_GAP_BT_ACT_START_DISCOVERY,
|
||||
BTC_GAP_BT_ACT_SEARCH_DEVICES,
|
||||
BTC_GAP_BT_ACT_CANCEL_DISCOVERY,
|
||||
BTC_GAP_BT_ACT_GET_REMOTE_SERVICES,
|
||||
BTC_GAP_BT_ACT_SEARCH_SERVICES,
|
||||
BTC_GAP_BT_ACT_GET_REMOTE_SERVICE_RECORD,
|
||||
BTC_GAP_BT_ACT_SEARCH_SERVICE_RECORD,
|
||||
} btc_gap_bt_act_t;
|
||||
|
||||
/* btc_bt_gap_args_t */
|
||||
@ -29,10 +40,28 @@ typedef union {
|
||||
struct set_bt_scan_mode_args {
|
||||
esp_bt_scan_mode_t mode;
|
||||
} set_scan_mode;
|
||||
|
||||
// BTC_GAP_BT_ACT_START_DISCOVERY
|
||||
struct start_disc_args {
|
||||
esp_bt_inq_mode_t mode;
|
||||
uint8_t inq_len;
|
||||
uint8_t num_rsps;
|
||||
} start_disc;
|
||||
|
||||
// BTC_BT_GAP_ACT_GET_REMOTE_SERVICES
|
||||
bt_bdaddr_t bda;
|
||||
|
||||
// BTC_BT_GAP_ACT_GET_REMTOE_SERVICE_RECORD
|
||||
struct get_rmt_srv_rcd_args {
|
||||
bt_bdaddr_t bda;
|
||||
esp_bt_uuid_t uuid;
|
||||
} get_rmt_srv_rcd;
|
||||
} btc_gap_bt_args_t;
|
||||
|
||||
void btc_gap_bt_call_handler(btc_msg_t *msg);
|
||||
|
||||
void btc_gap_bt_arg_deep_copy(btc_msg_t *msg, void *p_dest, void *p_src);
|
||||
void btc_gap_bt_busy_level_updated(uint8_t bl_flags);
|
||||
|
||||
#endif /* #if BTC_GAP_BT_INCLUDED */
|
||||
|
||||
#endif /* __BTC_GAP_BT_H__ */
|
||||
|
9
examples/bluetooth/bt_discovery/Makefile
Executable file
9
examples/bluetooth/bt_discovery/Makefile
Executable file
@ -0,0 +1,9 @@
|
||||
#
|
||||
# This is a project Makefile. It is assumed the directory this Makefile resides in is a
|
||||
# project subdirectory.
|
||||
#
|
||||
|
||||
PROJECT_NAME := bt_discovery
|
||||
|
||||
include $(IDF_PATH)/make/project.mk
|
||||
|
14
examples/bluetooth/bt_discovery/README.rst
Executable file
14
examples/bluetooth/bt_discovery/README.rst
Executable file
@ -0,0 +1,14 @@
|
||||
ESP-IDF BT-INQUIRY demo
|
||||
======================
|
||||
|
||||
Demo of Classic Bluetooth Device and Service Discovery
|
||||
|
||||
This is the demo for user to use ESP_APIs to perform inquiry to search for a target device and then performs service search via SDP.
|
||||
|
||||
Options choose step:
|
||||
1. make menuconfig.
|
||||
2. enter menuconfig "Component config", choose "Bluetooth"
|
||||
3. enter menu Bluetooth, choose "Classic Bluetooth" and do not choose "Release DRAM from Classic BT controller"
|
||||
4. choose your options.
|
||||
|
||||
After the program started, the device will start inquiry to search for a device with Major device type "PHONE" in the Class of Device Field. Then it will cancel the inquiry and started to perform service discovering on this remote device.
|
310
examples/bluetooth/bt_discovery/main/bt_discovery.c
Normal file
310
examples/bluetooth/bt_discovery/main/bt_discovery.c
Normal file
@ -0,0 +1,310 @@
|
||||
// Copyright 2015-2017 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 file is for Classic Bluetooth device and service discovery Demo.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/task.h"
|
||||
#include "nvs.h"
|
||||
#include "nvs_flash.h"
|
||||
#include "esp_system.h"
|
||||
#include "esp_log.h"
|
||||
#include "bt.h"
|
||||
#include "esp_bt_main.h"
|
||||
#include "esp_bt_device.h"
|
||||
#include "esp_gap_bt_api.h"
|
||||
|
||||
#define GAP_TAG "GAP"
|
||||
|
||||
typedef enum {
|
||||
APP_GAP_STATE_IDLE = 0,
|
||||
APP_GAP_STATE_DEVICE_DISCOVERING,
|
||||
APP_GAP_STATE_DEVICE_DISCOVER_COMPLETE,
|
||||
APP_GAP_STATE_SERVICE_DISCOVERING,
|
||||
APP_GAP_STATE_SERVICE_DISCOVER_COMPLETE,
|
||||
} app_gap_state_t;
|
||||
|
||||
typedef struct {
|
||||
bool dev_found;
|
||||
uint8_t bdname_len;
|
||||
uint8_t eir_len;
|
||||
uint8_t rssi;
|
||||
uint32_t cod;
|
||||
uint8_t eir[ESP_BT_GAP_EIR_DATA_LEN];
|
||||
uint8_t bdname[ESP_BT_GAP_MAX_BDNAME_LEN + 1];
|
||||
esp_bd_addr_t bda;
|
||||
app_gap_state_t state;
|
||||
} app_gap_cb_t;
|
||||
|
||||
static app_gap_cb_t m_dev_info;
|
||||
|
||||
static char *bda2str(esp_bd_addr_t bda, char *str, size_t size)
|
||||
{
|
||||
if (bda == NULL || str == NULL || size < 18) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
uint8_t *p = bda;
|
||||
sprintf(str, "%02x:%02x:%02x:%02x:%02x:%02x",
|
||||
p[0], p[1], p[2], p[3], p[4], p[5]);
|
||||
return str;
|
||||
}
|
||||
|
||||
static char *uuid2str(esp_bt_uuid_t *uuid, char *str, size_t size)
|
||||
{
|
||||
if (uuid == NULL || str == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (uuid->len == 2 && size >= 5) {
|
||||
sprintf(str, "%04x", uuid->uuid.uuid16);
|
||||
} else if (uuid->len == 4 && size >= 9) {
|
||||
sprintf(str, "%08x", uuid->uuid.uuid32);
|
||||
} else if (uuid->len == 16 && size >= 37) {
|
||||
uint8_t *p = uuid->uuid.uuid128;
|
||||
sprintf(str, "%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x",
|
||||
p[15], p[14], p[13], p[12], p[11], p[10], p[9], p[8],
|
||||
p[7], p[6], p[5], p[4], p[3], p[2], p[1], p[0]);
|
||||
} else {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return str;
|
||||
}
|
||||
|
||||
static bool get_name_from_eir(uint8_t *eir, uint8_t *bdname, uint8_t *bdname_len)
|
||||
{
|
||||
uint8_t *rmt_bdname = NULL;
|
||||
uint8_t rmt_bdname_len = 0;
|
||||
|
||||
if (!eir) {
|
||||
return false;
|
||||
}
|
||||
|
||||
rmt_bdname = esp_bt_gap_resolve_eir_data(eir, ESP_BT_EIR_TYPE_CMPL_LOCAL_NAME, &rmt_bdname_len);
|
||||
if (!rmt_bdname) {
|
||||
rmt_bdname = esp_bt_gap_resolve_eir_data(eir, ESP_BT_EIR_TYPE_SHORT_LOCAL_NAME, &rmt_bdname_len);
|
||||
}
|
||||
|
||||
if (rmt_bdname) {
|
||||
if (rmt_bdname_len > ESP_BT_GAP_MAX_BDNAME_LEN) {
|
||||
rmt_bdname_len = ESP_BT_GAP_MAX_BDNAME_LEN;
|
||||
}
|
||||
|
||||
if (bdname) {
|
||||
memcpy(bdname, rmt_bdname, rmt_bdname_len);
|
||||
bdname[rmt_bdname_len] = '\0';
|
||||
}
|
||||
if (bdname_len) {
|
||||
*bdname_len = rmt_bdname_len;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static void update_device_info(esp_bt_gap_cb_param_t *param)
|
||||
{
|
||||
char bda_str[18];
|
||||
uint32_t cod = 0;
|
||||
int32_t rssi = -129; /* invalid value */
|
||||
esp_bt_gap_dev_prop_t *p;
|
||||
|
||||
ESP_LOGI(GAP_TAG, "Device found: %s", bda2str(param->disc_res.bda, bda_str, 18));
|
||||
for (int i = 0; i < param->disc_res.num_prop; i++) {
|
||||
p = param->disc_res.prop + i;
|
||||
switch (p->type) {
|
||||
case ESP_BT_GAP_DEV_PROP_COD:
|
||||
cod = *(uint32_t *)(p->val);
|
||||
ESP_LOGI(GAP_TAG, "--Class of Device: 0x%x", cod);
|
||||
break;
|
||||
case ESP_BT_GAP_DEV_PROP_RSSI:
|
||||
rssi = *(int8_t *)(p->val);
|
||||
ESP_LOGI(GAP_TAG, "--RSSI: %d", rssi);
|
||||
break;
|
||||
case ESP_BT_GAP_DEV_PROP_BDNAME:
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* search for device with MAJOR service class as "rendering" in COD */
|
||||
app_gap_cb_t *p_dev = &m_dev_info;
|
||||
if (p_dev->dev_found && 0 != memcmp(param->disc_res.bda, p_dev->bda, ESP_BD_ADDR_LEN)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!esp_bt_gap_is_valid_cod(cod) ||
|
||||
!(esp_bt_gap_get_cod_major_dev(cod) == ESP_BT_COD_MAJOR_DEV_PHONE)) {
|
||||
return;
|
||||
}
|
||||
|
||||
memcpy(p_dev->bda, param->disc_res.bda, ESP_BD_ADDR_LEN);
|
||||
p_dev->dev_found = true;
|
||||
for (int i = 0; i < param->disc_res.num_prop; i++) {
|
||||
p = param->disc_res.prop + i;
|
||||
switch (p->type) {
|
||||
case ESP_BT_GAP_DEV_PROP_COD:
|
||||
p_dev->cod = *(uint32_t *)(p->val);
|
||||
break;
|
||||
case ESP_BT_GAP_DEV_PROP_RSSI:
|
||||
p_dev->rssi = *(int8_t *)(p->val);
|
||||
break;
|
||||
case ESP_BT_GAP_DEV_PROP_BDNAME: {
|
||||
uint8_t len = (p->len > ESP_BT_GAP_MAX_BDNAME_LEN) ? ESP_BT_GAP_MAX_BDNAME_LEN :
|
||||
(uint8_t)p->len;
|
||||
memcpy(p_dev->bdname, (uint8_t *)(p->val), len);
|
||||
p_dev->bdname[len] = '\0';
|
||||
p_dev->bdname_len = len;
|
||||
break;
|
||||
}
|
||||
case ESP_BT_GAP_DEV_PROP_EIR: {
|
||||
memcpy(p_dev->eir, (uint8_t *)(p->val), p->len);
|
||||
p_dev->eir_len = p->len;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (p_dev->eir && p_dev->bdname_len == 0) {
|
||||
get_name_from_eir(p_dev->eir, p_dev->bdname, &p_dev->bdname_len);
|
||||
ESP_LOGI(GAP_TAG, "Found a target device, address %s, name %s", bda_str, p_dev->bdname);
|
||||
p_dev->state = APP_GAP_STATE_DEVICE_DISCOVER_COMPLETE;
|
||||
ESP_LOGI(GAP_TAG, "Cancel device discovery ...");
|
||||
esp_bt_gap_cancel_discovery();
|
||||
}
|
||||
}
|
||||
|
||||
void bt_app_gap_init(void)
|
||||
{
|
||||
app_gap_cb_t *p_dev = &m_dev_info;
|
||||
memset(p_dev, 0, sizeof(app_gap_cb_t));
|
||||
}
|
||||
|
||||
void bt_app_gap_cb(esp_bt_gap_cb_event_t event, esp_bt_gap_cb_param_t *param)
|
||||
{
|
||||
app_gap_cb_t *p_dev = &m_dev_info;
|
||||
char bda_str[18];
|
||||
char uuid_str[37];
|
||||
|
||||
switch (event) {
|
||||
case ESP_BT_GAP_DISC_RES_EVT: {
|
||||
update_device_info(param);
|
||||
break;
|
||||
}
|
||||
case ESP_BT_GAP_DISC_STATE_CHANGED_EVT: {
|
||||
if (param->disc_st_chg.state == ESP_BT_GAP_DISCOVERY_STOPPED) {
|
||||
ESP_LOGI(GAP_TAG, "Device discovery stopped.");
|
||||
if ( (p_dev->state == APP_GAP_STATE_DEVICE_DISCOVER_COMPLETE ||
|
||||
p_dev->state == APP_GAP_STATE_DEVICE_DISCOVERING)
|
||||
&& p_dev->dev_found) {
|
||||
p_dev->state = APP_GAP_STATE_SERVICE_DISCOVERING;
|
||||
ESP_LOGI(GAP_TAG, "Discover services ...");
|
||||
esp_bt_gap_get_remote_services(p_dev->bda);
|
||||
}
|
||||
} else if (param->disc_st_chg.state == ESP_BT_GAP_DISCOVERY_STARTED) {
|
||||
ESP_LOGI(GAP_TAG, "Discovery started.");
|
||||
}
|
||||
break;
|
||||
}
|
||||
case ESP_BT_GAP_RMT_SRVCS_EVT: {
|
||||
if (memcmp(param->rmt_srvcs.bda, p_dev->bda, ESP_BD_ADDR_LEN) == 0 &&
|
||||
p_dev->state == APP_GAP_STATE_SERVICE_DISCOVERING) {
|
||||
p_dev->state = APP_GAP_STATE_SERVICE_DISCOVER_COMPLETE;
|
||||
if (param->rmt_srvcs.stat == ESP_BT_STATUS_SUCCESS) {
|
||||
ESP_LOGI(GAP_TAG, "Services for device %s found", bda2str(p_dev->bda, bda_str, 18));
|
||||
for (int i = 0; i < param->rmt_srvcs.num_uuids; i++) {
|
||||
esp_bt_uuid_t *u = param->rmt_srvcs.uuid_list + i;
|
||||
ESP_LOGI(GAP_TAG, "--%s", uuid2str(u, uuid_str, 37));
|
||||
// ESP_LOGI(GAP_TAG, "--%d", u->len);
|
||||
}
|
||||
} else {
|
||||
ESP_LOGI(GAP_TAG, "Services for device %s not found", bda2str(p_dev->bda, bda_str, 18));
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
case ESP_BT_GAP_RMT_SRVC_REC_EVT:
|
||||
default: {
|
||||
ESP_LOGI(GAP_TAG, "event: %d", event);
|
||||
break;
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
void bt_app_gap_start_up(void)
|
||||
{
|
||||
char *dev_name = "ESP_GAP_INQRUIY";
|
||||
esp_bt_dev_set_device_name(dev_name);
|
||||
|
||||
/* set discoverable and connectable mode, wait to be connected */
|
||||
esp_bt_gap_set_scan_mode(ESP_BT_SCAN_MODE_CONNECTABLE_DISCOVERABLE);
|
||||
|
||||
/* register GAP callback function */
|
||||
esp_bt_gap_register_callback(bt_app_gap_cb);
|
||||
|
||||
/* inititialize device information and status */
|
||||
app_gap_cb_t *p_dev = &m_dev_info;
|
||||
memset(p_dev, 0, sizeof(app_gap_cb_t));
|
||||
|
||||
/* start to discover nearby Bluetooth devices */
|
||||
p_dev->state = APP_GAP_STATE_DEVICE_DISCOVERING;
|
||||
esp_bt_gap_start_discovery(ESP_BT_INQ_MODE_GENERAL_INQUIRY, 10, 0);
|
||||
}
|
||||
|
||||
void app_main()
|
||||
{
|
||||
/* Initialize NVS — it is used to store PHY calibration data */
|
||||
esp_err_t ret = nvs_flash_init();
|
||||
if (ret == ESP_ERR_NVS_NO_FREE_PAGES) {
|
||||
ESP_ERROR_CHECK(nvs_flash_erase());
|
||||
ret = nvs_flash_init();
|
||||
}
|
||||
ESP_ERROR_CHECK( ret );
|
||||
|
||||
esp_bt_controller_config_t bt_cfg = BT_CONTROLLER_INIT_CONFIG_DEFAULT();
|
||||
if (esp_bt_controller_init(&bt_cfg) != ESP_OK) {
|
||||
ESP_LOGE(GAP_TAG, "%s initialize controller failed\n", __func__);
|
||||
return;
|
||||
}
|
||||
|
||||
if (esp_bt_controller_enable(ESP_BT_MODE_BTDM) != ESP_OK) {
|
||||
ESP_LOGE(GAP_TAG, "%s enable controller failed\n", __func__);
|
||||
return;
|
||||
}
|
||||
|
||||
if (esp_bluedroid_init() != ESP_OK) {
|
||||
ESP_LOGE(GAP_TAG, "%s initialize bluedroid failed\n", __func__);
|
||||
return;
|
||||
}
|
||||
|
||||
if (esp_bluedroid_enable() != ESP_OK) {
|
||||
ESP_LOGE(GAP_TAG, "%s enable bluedroid failed\n", __func__);
|
||||
return;
|
||||
}
|
||||
|
||||
bt_app_gap_start_up();
|
||||
}
|
5
examples/bluetooth/bt_discovery/main/component.mk
Executable file
5
examples/bluetooth/bt_discovery/main/component.mk
Executable file
@ -0,0 +1,5 @@
|
||||
#
|
||||
# "main" pseudo-component makefile.
|
||||
#
|
||||
# (Uses default behaviour of compiling all source files in directory, adding 'include' to include path.)
|
||||
|
5
examples/bluetooth/bt_discovery/sdkconfig.defaults
Normal file
5
examples/bluetooth/bt_discovery/sdkconfig.defaults
Normal file
@ -0,0 +1,5 @@
|
||||
# Override some defaults so BT stack is enabled and
|
||||
# Classic BT is enabled and BT_DRAM_RELEASE is disabled
|
||||
CONFIG_BT_ENABLED=y
|
||||
CONFIG_CLASSIC_BT_ENABLED=y
|
||||
|
Loading…
Reference in New Issue
Block a user