GATT Over BR/EDR 使用说明
GATT Over BR/EDR 让原本属于 BLE 的 GATT 协议,也能够在经典蓝牙( BR/EDR )上传输和使用,从而提升数据速率和设备兼容性。 本文以 AirSync 服务为例,介绍基于 SDK 如何实现 GATT over BR/EDR。
备注
直接打开全局宏
F_APP_AIRSYNC_SERVICE_SUPPORT
,如下的配置 SDK 中都已包含。
-
配置 BLE 广播的
ADV_TYPE_FLAGS
不能带有GAP_ADTYPE_FLAGS_BREDR_NOT_SUPPORTED
。static uint8_t adv_data[31] = { 0x02, GAP_ADTYPE_FLAGS, GAP_ADTYPE_FLAGS_GENERAL, ... }
-
AirSync 服务的源文件和头文件分别为
airsync_ble_service.c
和airsync_ble_service.h
。 区别于普通 BLE 服务,service table 中 Attribute flags 需要配置ATTRIB_FLAG_BREDR
。const T_ATTRIB_APPL airsync_ble_service_tbl[] = { /* <<Primary Service>>, 0.. */ { (ATTRIB_FLAG_VALUE_INCL | ATTRIB_FLAG_LE | ATTRIB_FLAG_BREDR), /* wFlags */ { /* bTypeValue */ LO_WORD(GATT_UUID_PRIMARY_SERVICE), HI_WORD(GATT_UUID_PRIMARY_SERVICE), LO_WORD(GATT_UUID_AIRSYNC_SERVICE), /* service UUID */ HI_WORD(GATT_UUID_AIRSYNC_SERVICE) }, UUID_16BIT_SIZE, /* bValueLen */ NULL, /* pValueContext */ GATT_PERM_READ /* wPermissions */ }, ... };
-
在
app_ble_service.c
中添加服务,并调用bt_att_init()
初始化 ATT 注册 callback。#include "bt_att.h" #include "airsync_ble_service.h" // add service id T_SERVER_ID air_ser_id; //callback 函数 void att_callback(uint8_t bd_addr[6], T_BT_ATT_MSG_TYPE msg_type, void *p_msg) { APP_PRINT_INFO1("att_callback msg_type = 0x%x", msg_type); } void app_ble_service_init(void) { //init bt att bt_att_init(att_callback); //add service air_ser_id = airsync_add_service((void *)app_profile_callback); }
-
在
app_sdp.c
中添加 AirSync service 的 SDP table。static const uint8_t att_sdp_record[] = { SDP_DATA_ELEM_SEQ_HDR, 0x2b, //attribute SDP_ATTR_SRV_CLASS_ID_LIST SDP_UNSIGNED_TWO_BYTE, (uint8_t)(SDP_ATTR_SRV_CLASS_ID_LIST >> 8), (uint8_t)SDP_ATTR_SRV_CLASS_ID_LIST, SDP_DATA_ELEM_SEQ_HDR, 0x03, SDP_UUID16_HDR, //According to UUID (uint8_t)(0xFEE7 >> 8), (uint8_t)(0xFEE7), //attribute SDP_ATTR_PROTO_DESC_LIST SDP_UNSIGNED_TWO_BYTE, (uint8_t)(SDP_ATTR_PROTO_DESC_LIST >> 8), (uint8_t)SDP_ATTR_PROTO_DESC_LIST, SDP_DATA_ELEM_SEQ_HDR, 0x13, SDP_DATA_ELEM_SEQ_HDR, 0x06, SDP_UUID16_HDR, (uint8_t)(UUID_L2CAP >> 8), (uint8_t)(UUID_L2CAP), SDP_UNSIGNED_TWO_BYTE, (uint8_t)(PSM_ATT >> 8), (uint8_t)(PSM_ATT), SDP_DATA_ELEM_SEQ_HDR, 0x09, SDP_UUID16_HDR, (uint8_t)(UUID_ATT >> 8), (uint8_t)(UUID_ATT), SDP_UNSIGNED_TWO_BYTE, //According to service start handle 0x00, 0x10, SDP_UNSIGNED_TWO_BYTE, //According to service end handle 0x00, 0x18, //attribute SDP_ATTR_BROWSE_GROUP_LIST SDP_UNSIGNED_TWO_BYTE, (uint8_t)(SDP_ATTR_BROWSE_GROUP_LIST >> 8), (uint8_t)SDP_ATTR_BROWSE_GROUP_LIST, SDP_DATA_ELEM_SEQ_HDR, 0x03, SDP_UUID16_HDR, (uint8_t)(UUID_PUBLIC_BROWSE_GROUP >> 8), (uint8_t)(UUID_PUBLIC_BROWSE_GROUP), }; void app_sdp_init(void) { ...... bt_sdp_record_add((void *)att_sdp_record); }
-
如上 SDP table,需要填写起始 handle 和结束 handle, 介绍获取 handle 的两种方法:
-
-
调用
server_ext_send_data()
去发 Notification/Indication。uint16_t conn_handle; uint16_t cid; uint8_t cid_num; for (uint8_t i = 0; i < MAX_BR_LINK_NUM; i++) { if (app_db.br_link[i].used == true) { gap_chann_get_handle(app_db.br_link[i].bd_addr, 0x10/*BTIF_REMOTE_ADDR_CLASSIC*/, &conn_handle); gap_chann_get_cid(conn_handle, 1, &cid, &cid_num); server_ext_send_data(conn_handle, cid, airsync_ser_id, 2, p_data, data_len, GATT_PDU_TYPE_ANY); break; } } //le notification server_send_data(conn_id, airsync_ser_id, 2, p_data, data_len, GATT_PDU_TYPE_NOTIFICATION);
备注
如果存在 ATT 无法正常连线情况下, 可尝试 HFP 连上后 delay 5s 左右的时间主动发起 ATT 连线,调用:
bt_att_connect_req()
。上述 AirSync 服务通过 GATT over BR/EDR 的传输方式适用于 Android 微信运动, iOS 的微信运动可以仍然通过 BLE。