Hello! I’m trying to create a L2CAP connection between nRF52840DK and RPI’s native bluetooth. The nRF52840 running RIOT OS and nimble stack, RPI uses BlueZ 5.50 bluetooth stack.
What hardware and software am I using?
I have a raspberry pi 3b+ and few nRF52840DK board. I’m try to use the RPI’s native bluetooth module rather than a dongle. The BlueZ version is 5.50, the nRF52840DK is running nimble_l2cap_server example
What works?
I have successfully run the example IPv6-over-BLE with my hardware.
I tried to write a C program based on BlueZ stack to create L2CAP connection. For now, the RPI can discover nRF52840 using function hci_le_scan()
and create GAP connection using hci_le_create_conn()
successfully. During the connection establishment phase, the node reveived two GAP event, which is BLE_GAP_EVENT_CONNECT (code 0)
and BLE_GAP_EVENT_MTU (code 15)
. The MTU event change the MTU of ATT from 0 to 256.
What is the problem?
However, when I use connect()
to create L2CAP socket connection, timeout occured and returns an error: Host is down
and error code -1. The nRF52840 received a BLE_GAP_EVENT_DISCONNECT (code 1)
. Maybe there is some mistakes in my code because there are few related codes online. How can I make it right?
The nRF output is:
and my C program based on BlueZ is:
#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));
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);
}
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);
}
Thanks a lot!