0

我正在尝试在 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);
}
4

0 回答 0