我正在尝试在 nRF52840DK 和 RPI 的本机蓝牙之间创建 L2CAP 连接。nRF52840 运行 RIOT OS 和灵活的堆栈,RPI 使用 BlueZ 5.50 蓝牙堆栈。
目前,RPI 可以发现 nRF52840 并hci_le_create_conn
成功创建 GAP 连接。在连接建立阶段,节点接收到两个 GAP 事件,即BLE_GAP_EVENT_CONNECT (code 0)
和BLE_GAP_EVENT_MTU (code 15)
。MTU 事件将 ATT 的 MTU 从 0 更改为 256。
但是,当我使用connect()
创建 L2CAP 套接字连接时,发生超时并返回错误Host is down
。nRF52840 收到了一个BLE_GAP_EVENT_DISCONNECT (code 1)
. 可能我的代码有一些错误,因为网上相关的代码很少。我怎样才能使它正确?
nRF52840DK 正在运行nimble_l2cap_server 示例,输出为:
user@ubuntu:/mnt/hgfs/DATA_SHARE/RIOT/tests/nimble_l2cap_server$ rv -s 1 -vt
rtt viewer appiation
Connectiong to sn: 1
SN = 1 log file writing enabled
SN = 1 Connecting...
SN = 1 Connected
Auto init xtimer.
Auto init NimBLE.
main(): This is RIOT! (Version: 2021.04-devel-903-g89939)
NimBLE L2CAP test server
# now advertising
# GAP event 0
current att mtu = 0
# GAP event 15
my handle = 1, conn handle = 1 cid = 4, mtu value = 256
current att mtu = 256
# GAP event 1
我的 BlueZ 代码是:
#include "blescan.h"
#include <sys/socket.h>
#include <bluetooth/l2cap.h>
int main(int argc, char *argv[]){
int id_type;
char *id;
bdaddr_t src_addr;
uint16_t le_conn_handle = 0;
char dest_addr_str[18];
// to check wether the device is advertisiing
if (argc < 3){
perror("Too few arguments");
exit(0);
}
id = argv[2];
if (strcmp(argv[1], "-m") == 0){
id_type = ID_TYPE_MAC;
}
else if (strcmp(argv[1], "-n") == 0){
id_type = ID_TYPE_NAME;
}
else{
perror("Unknow argument");
exit(0);
}
memset(dest_addr_str, 0, sizeof(dest_addr_str));
int res = blescan(id_type, id, 100, dest_addr_str);
if (res == 0){ // Cannot find the corresponding BLE device
perror("Can not find the target device");
exit(0);
}
printf("find the target\n");
// open a hci socket
int device_id = hci_get_route(NULL);
int hci_socket = hci_open_dev(device_id);
hci_devba(device_id, &src_addr);
// Create a le connection
bdaddr_t dest_bdaddr;
memset(&dest_bdaddr, 0, sizeof(dest_bdaddr));
str2ba(dest_addr_str, &dest_bdaddr);
res = hci_le_create_conn(hci_socket, htobs(0x04), htobs(0x04), 0, LE_RANDOM_ADDRESS,
dest_bdaddr, LE_PUBLIC_ADDRESS, htobs(0x0018), htobs(0x0028),
htobs(0), htobs(0x0100), htobs(0x0000), htobs(0x0000),
&le_conn_handle, 25000);
if (res != 0){
perror("Connection error");
goto hciclose;
}
// Create a L2CAP socket
struct sockaddr_l2 dest_sockaddr;
memset(&dest_sockaddr, 0, sizeof(dest_sockaddr));
memset(&src_sockaddr, 0, sizeof(src_sockaddr));
dest_sockaddr.l2_family = AF_BLUETOOTH;
dest_sockaddr.l2_psm = htobs(0x0235);
str2ba(dest_addr_str, &dest_sockaddr.l2_bdaddr);
int l2cap_client_socket = socket(AF_BLUETOOTH, SOCK_SEQPACKET, BTPROTO_L2CAP);
if (l2cap_client_socket < 0){
perror("Can not open l2cap socket");
goto hciclose;
}
// Connect to nrf52840 failed with a timeout
res = connect(l2cap_client_socket, (struct sockaddr *)&dest_sockaddr, sizeof(dest_sockaddr));
if (res == 0){
res = write(l2cap_client_socket, "hello from linux", 17);
}
> Blockquote
else if(res < 0){
printf("error code = %d\n", res);
perror("l2cap socket connction failed");
hci_disconnect(hci_socket, le_conn_handle, HCI_OE_USER_ENDED_CONNECTION, 1000);
goto hciclose;
}
hciclose:
if (le_conn_handle != 0){
hci_disconnect(hci_socket, le_conn_handle, HCI_OE_USER_ENDED_CONNECTION, 1000);
}
hci_close_dev(device_id);
exit(0);
}