
分类
其他
杰理AC63_BT_SDK 学习笔记 (10 Dongle)
简介
基于杰理官方的通用蓝牙软件包 fw-AC63_BT_SDK-master,学习和了解AC695/6系列芯片的功能和应用。主要从SPP_BLE、MASH、HID三个方面学习和了解相关的协议和应用。
简介: 基于杰理官方的通用蓝牙软件包 fw-AC63_BT_SDK-master,学习和了解AC695/6系列芯片的功能和应用。主要从SPP_BLE、MASH、HID三个方面学习和了解相关的协议和应用。



// USB → BLE 数据转发 (HID输出)
void dongle_hid_output_handler(u8 report_type, u8 report_id, u8 *packet, u16 size)
{ #if (TCFG_USER_EDR_ENABLE)
edr_hid_data_send_ext(report_type, report_id, packet, size);
#elif (TCFG_USER_BLE_ENABLE)
ble_hid_data_send_ext(report_type, report_id, packet, size);
#endif
}
2 BLE中央设备 - ble_dg_central.c
2.1 扫描配置
// 搜索参数
#define SET_SCAN_TYPE SCAN_ACTIVE // 主动扫描
#define SET_SCAN_INTERVAL ADV_SCAN_MS(24) // 24 * 0.625ms = 15ms
#define SET_SCAN_WINDOW ADV_SCAN_MS(8) // 8 * 0.625ms = 5ms
// 连接参数
#define SET_CONN_INTERVAL (BASE_INTERVAL_MIN*3) // 18 * 1.25ms = 22.5ms
#define SET_CONN_LATENCY 0
#define SET_CONN_TIMEOUT 100 // 1秒超时
// 匹配设备列表
static const client_match_cfg_t dg_match_device_table[] =
{.create_conn_mode = BIT(CLI_CREAT_BY_NAME), // 按名称匹配
.compare_data_len = sizeof(dg_test_remoter_name1) - 1,
.compare_data = dg_test_remoter_name1, // "AC695X_1(BLE)"
.filter_pdu_bitmap = 0,
},
{.create_conn_mode = BIT(CLI_CREAT_BY_NAME),
.compare_data_len = sizeof(dg_test_remoter_name2) - 1,
.compare_data = dg_test_remoter_name2, // "AC897N_MX(BLE)"
.filter_pdu_bitmap = 0,
},
{ .create_conn_mode = BIT(CLI_CREAT_BY_TAG), // 按自定义Tag匹配
.compare_data_len = sizeof(user_config_tag_string) - 1,
.compare_data = user_config_tag_string, // "abc123"
.filter_pdu_bitmap = 0,
},
3.2.2 GATT服务搜索配置
static const target_uuid_t dongle_search_ble_uuid_table[] = {
// 设备名称 (GAP服务)
{.services_uuid16 = 0x1800,
.characteristic_uuid16 = 0x2a00,
.opt_type = ATT_PROPERTY_READ,
},
// PNP信息 (设备信息服务)
{.services_uuid16 = 0x180a,
.characteristic_uuid16 = 0x2a50,
.opt_type = ATT_PROPERTY_READ,
},
// 报告映射 (HID服务)
{.services_uuid16 = 0x1812,
.characteristic_uuid16 = 0x2a4b,
.opt_type = ATT_PROPERTY_READ,
.read_long_enable = 1,
},
// 输入报告 (HID服务 - Notify)
{.services_uuid16 = 0x1812,
.characteristic_uuid16 = 0x2a4d,
.opt_type = ATT_PROPERTY_NOTIFY,
.read_report_reference = 1,
},
// RCSP OTA服务 (自定义)
#if RCSP_BTMATE_EN
{.services_uuid16 = 0xae00,
.characteristic_uuid16 = 0xae01,
.opt_type = ATT_PROPERTY_WRITE_WITHOUT_RESPONSE,
},
{.services_uuid16 = 0xae00,
.characteristic_uuid16 = 0xae02,
.opt_type = ATT_PROPERTY_NOTIFY,
},
#endif
};
3.2.3 配对信息管理
// 配对信息结构
struct ctl_pair_info_t {
u8 head_tag; // PAIR_BOND_TAG (0x53)
u8 match_dev_id; // 匹配设备ID
u8 pair_flag; // 配对标志
u8 peer_address_info[7]; // 对端地址 (addr_type + address)
u16 conn_handle; // 连接句柄
u16 conn_interval; // 连接间隔
u16 conn_latency; // 延迟
u16 conn_timeout; // 超时
u16 write_handle; // 写特征值句柄 (OTA用)
// VM存储 (ID 30)
#define CFG_BLE_BONDING_REMOTE_INFO2 30
// 读取/写入配对信息
static int dg_pair_vm_do(struct ctl_pair_info_t *info, u8 rw_flag)
if (rw_flag == 0) // 从VM读取
ret = syscfg_read (CFG_BLE_BONDING_REMOTE_INFO2, (u8 *)&record_bond_info,
uint_len * SUPPORT_MAX_GATT_CLIENT);
else // 写入VM
syscfg_write(CFG_BLE_BONDING_REMOTE_INFO2, (u8 *)&record_bond_info,
uint_len * SUPPORT_MAX_GATT_CLIENT);
3.2.4 事件处理 - 核心回调
static int dg_central_event_packet_handler(int event, u8 *packet, u16 size, u8 *ext_param)
{switch (event)
// 1. 扫描到匹配设备
case GATT_COMM_EVENT_SCAN_DEV_MATCH:
log_info("match_dev:addr_type= %d", packet[0]);
// 保存设备信息,准备发起连接
cur_conn_info.match_dev_id = packet[9];
if (packet[9] < SUPPORT_MAX_GATT_CLIENT) // 已配对设备 → 使用记录的连接参数
dg_scan_conn_config_set(&record_bond_info[packet[9]]);
else // 新设备 → 使用默认参数
dg_scan_conn_config_set(NULL);
break;
// 2. 连接完成
case GATT_COMM_EVENT_CONNECTION_COMPLETE:
log_info("connection_handle:%04x", little_endian_read_16(packet, 0));
// 保存连接信息
memcpy(cur_conn_info.peer_address_info, &ext_param[7], 7);
cur_conn_info.conn_handle = little_endian_read_16(packet, 0);
bt_connected = 1;
break;
// 3. 加密完成 (配对)
case GATT_COMM_EVENT_ENCRYPTION_CHANGE:
if (packet[3] == LINK_ENCRYPTION_RECONNECT)
log_info("reconnect..."); // 回连:直接使能通知
dg_enable_notify_ccc(little_endian_read_16(packet, 0));
else
log_info("first pair..."); // 首次配对:搜索GATT服务
dg_client_bond_config.search_uuid_count =
(sizeof(dongle_search_ble_uuid_table) / sizeof(target_uuid_t));
// 保存配对信息到VM
cur_conn_info.head_tag = PAIR_BOND_TAG;
cur_conn_info.pair_flag = 1;
dg_pair_vm_do(&cur_conn_info, 1);
break;
// 4. 收到数据 (Notify)
case GATT_COMM_EVENT_GATT_DATA_REPORT:
report_data = (void *)packet;
if (report_data->packet_type == GATT_EVENT_NOTIFICATION)
// 根据handle识别设备类型
if (report_data->value_handle == mouse_notify_handle[0])
usb_send_packet[0] = 1; // Report ID 1
dongle_ble_hid_input_handler(usb_send_packet, blob_length + 1);
else if (report_data->value_handle == standard_keyboard_notify_handle[0])
usb_send_packet[0] = 4; // Report ID 4
dongle_second_ble_hid_input_handler(usb_send_packet, blob_length + 1);
break;
// 5. 断开连接
case GATT_COMM_EVENT_DISCONNECT_COMPLETE:
log_info("disconnect_handle:%04x, reason= %02x",
little_endian_read_16(packet, 0), packet[2]);
// 清空连接句柄,重新开启扫描
if (conn_handle == dg_conn_handle)
dg_conn_handle = 0;
bt_connected = 0;
break;
return 0;
3.2.5 USB唤醒处理
// USB挂起时,需要唤醒后再发送数据
static u8 wait_usb_wakeup = 1;
// 收到BLE数据时检查USB状态
if (usb_status_ret == USB_SUSPEND)
wait_usb_wakeup = 0;
usb_remote_wakeup(0); // 发送远程唤醒
break;
else if (usb_status_ret == USB_RESUME_OK) // USB已唤醒,正常发送
wait_usb_wakeup = 1;
// 发送数据前检查
if (wait_usb_wakeup)
memcpy(&usb_send_packet[1], report_data->blob, report_data->blob_length);
else // USB未唤醒,发送空包(保持连接)
memset(&usb_send_packet[1], 0 , report_data->blob_length);
八、完整工作流程
- 上电启动 (app_main)
选择 "dongle" 应用
- 应用启动 (dongle_app_start)
├── 初始化BLE协议栈 (btstack_init)
├── 注册USB HID描述符 (鼠标/键盘/消费类)
├── 启动USB设备 (usb_start)
└── 扫描匹配设备 (BLE扫描)
- BLE扫描与匹配 (ble_dg_central.c)
├── 主动扫描 (SCAN_ACTIVE)
├── 匹配设备名称: "AC695X_1(BLE)" 或 "AC897N_MX(BLE)"
├── 匹配自定义Tag: "abc123"
└── 发现匹配 → 自动发起连接
- 连接与配对
├── 建立BLE连接
├── 加密配对 (如果使能SM)
├── 保存配对信息到VM (断电不丢失)
└── 搜索GATT服务 (HID服务等)







评论