[英]How to connect BLE devices using Linux bluetooth C library
我正在尝试使用蓝牙 C 库(我正在使用 C++ 编程)将我的蓝牙设备与 BLE 连接到 Linux 系统,所以这是我目前使用的代码:
#include <string>
#include <iostream>
#include <bluetooth/bluetooth.h>
#include <bluetooth/rfcomm.h>
#include <bluetooth/hci.h>
#include <bluetooth/hci_lib.h>
#define CONNECT_TIMEOUT 60 /* sec */
#define BLE_ERROR(e) std::cout << "Error: " << e << ": " << strerror(errno) << std::endl;
void connect(std::string addr){
uint16_t handle = 0;
uint8_t initiator_filter = 0;
uint8_t peer_type = LE_PUBLIC_ADDRESS;
uint8_t own_type = LE_PUBLIC_ADDRESS;
uint16_t interval = htobs(0x0005);
uint16_t window = htobs(0x0005);
uint16_t min_interval = 15;
uint16_t max_interval = 15;
uint16_t latency = 0;
uint16_t timeout = 0;
uint16_t min_ce_length = 1;
uint16_t max_ce_length = 1;
bdaddr_t bdaddr;
int r, dev_id, dd = -1;
dev_id = hci_get_route(NULL);
if (dev_id < 0)
{
BLE_ERROR("No local device");
goto finish;
}
dd = hci_open_dev(dev_id);
if (dd < 0)
{
BLE_ERROR("Cannot open socket");
goto finish;
}
r = str2ba(addr.c_str(), &bdaddr);
if(r < 0){
BLE_ERROR("Getting baddr");
goto finish;
}
r = hci_le_create_conn(dd,interval,window,initiator_filter,peer_type,
bdaddr,own_type,min_interval,max_interval,latency,timeout,min_ce_length,max_ce_length,
&handle,CONNECT_TIMEOUT * 1000000);
if(r < 0){
BLE_ERROR("Connecting device");
goto finish;
}
printf("\tHandle: %d (0x%04x)\n", handle, handle);
finish:
hci_close_dev(dd);
}
int main(){
connect(""); //TODO Complete with a functional MAC Address
return 0;
}
注意:您需要在connect
功能参数中设置特定的 MAC。 我还使用以下命令使用 g++ 进行编译:
/usr/bin/g++ -g /home/maria/projects/TestStackOverBLE/main.cpp -o /home/maria/projects/TestStackOverBLE/main -lbluetooth
以下是有关使用 hciconfig hciconfig -a
命令的 hci0 设备的更多信息:
hci0: Type: Primary Bus: USB
BD Address: 24:4B:FE:3A:1A:B6 ACL MTU: 1021:6 SCO MTU: 255:12
UP RUNNING PSCAN
RX bytes:141559 acl:0 sco:0 events:5409 errors:0
TX bytes:59986 acl:0 sco:0 commands:2084 errors:0
Features: 0xff 0xff 0xff 0xfe 0xdb 0xfd 0x7b 0x87
Packet type: DM1 DM3 DM5 DH1 DH3 DH5 HV1 HV2 HV3
Link policy: RSWITCH HOLD SNIFF PARK
Link mode: SLAVE ACCEPT
Name: 'maria'
Class: 0x3c010c
Service Classes: Rendering, Capturing, Object Transfer, Audio
Device Class: Computer, Laptop
HCI Version: (0xa) Revision: 0x999
LMP Version: (0xa) Subversion: 0x646b
Manufacturer: Realtek Semiconductor Corporation (93)
我也在使用Ubuntu 18.04
:
bluetoothctl v5.64
dbus v1.12.2-1ubuntu1
bluez v5.48-0ubuntu3
。
运行应用程序时得到的结果如下:
Error: Connecting device: Input/output error
我首先尝试记录自己有关 Linux 的蓝牙 C 库的工作原理(很难找到任何文档,而 BLE 的文档更少),我需要使用 BLE 连接,因为我的设备不允许使用蓝牙经典进行通信,我找不到原因对于我遇到的问题。 我也尝试过多次重启蓝牙服务(使用sudo service bluetooth restart
)和 hci0 设备(使用sudo hciconfig hci0 reset
),但都没有成功,我也尝试过重启电脑,但都没有,我什至尝试了这里提到的步骤这与我的情况非常相似,因为以前“连接超时”错误也发生在我身上,但它也不起作用,它只是返回以下代码以防万一它有用:执行此命令: hcitool cmd 0x08 0x000E
我收到以下输出:
< HCI Command: ogf 0x08, ocf 0x000e, plen 0
> HCI Event: 0x0e plen 4
02 0E 20 0C
我能做些什么来解决这个问题?
编辑:我正在研究并发现使用 C/C++ 对蓝牙服务进行 dbus 调用可能对我有用,但是尽管审查了许多 github 项目,但很难找到好的文档或具体的连接示例,因为大多数代码也是令人费解,包含在许多文件中和/或连续调用我要查找/理解的内容
这就是旧的 hci_xxx 蓝牙 C 函数在最低级别所做的事情。 它们现在可能不工作了,因为 bluez/dbus 妨碍了。 以下代码适用于 Raspberry Pi,因为它首先禁用 bluez,并且可能是 C 程序的基础 - 但使用评论中提到的 github 库之一会更容易。
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <time.h>
#include <sys/socket.h>
#include <sys/ioctl.h>
struct sockaddr_hci
{
unsigned short hci_family;
unsigned short hci_dev;
unsigned short hci_channel;
};
struct hci_filter
{
unsigned long type_mask;
unsigned long event_mask[2];
unsigned short opcode;
};
#define BTPROTO_HCI 1
#define SOL_HCI 0
#define HCI_FILTER 2
#define HCIDEVDOWN 0x400448CA
unsigned char eventmask[16] = { 1,1,0x0C,8,0xFF,0xFF,0xFB,0xFF,0x07,0xF8,0xBF,0x3D };
unsigned char lemask[16] = { 0x01,0x01,0x20,0x08,0xBF,0x05,0,0,0,0,0,0 };
unsigned char leopen[30] = {1,0x0D,0x20,0x19,0x60,0,0x60,0,0,0,0x66,0x55,0x44,0x33,0x22,0x11,0,0x18,0,0x28,0,0,0,0x11,0x01,0,0,0,0};
int main()
{
int n,len,dd;
struct sockaddr_hci sa;
struct hci_filter flt;
char buf[256];
// set board address 00:1E:C0:2D:17:7C
leopen[15] = 0x00;
leopen[14] = 0x1E;
leopen[13] = 0xC0;
leopen[12] = 0x2D;
leopen[11] = 0x17;
leopen[10] = 0x7C;
dd = socket(31, SOCK_RAW | SOCK_CLOEXEC | SOCK_NONBLOCK, BTPROTO_HCI);
if(dd < 0)
{
printf("Socket open error\n");
return(0);
}
ioctl(dd,HCIDEVDOWN,0); // hci0
close(dd);
// AF_BLUETOOTH=31
dd = socket(31, SOCK_RAW | SOCK_CLOEXEC | SOCK_NONBLOCK, BTPROTO_HCI);
if(dd < 0)
{
printf("Socket open error\n");
return(0);
}
sa.hci_family = 31; // AF_BLUETOOTH;
sa.hci_dev = 0; // hci0/1/2...
sa.hci_channel = 1; // HCI_CHANNEL_USER
if(bind(dd,(struct sockaddr *)&sa,sizeof(sa)) < 0)
{
printf("Bind failed\n");
close(dd);
return(0);
}
write(dd,eventmask,12);
write(dd,lemask,12);
printf("Send hci LE connect\n");
write(dd,leopen,29);
printf("If get reply = 04 3E 13 01 00.. then has connected OK\n");
printf("REPLY =");
for(n = 0 ; n < 10 ; ++ n)
{
len = read(dd,buf,sizeof(buf));
for(n = 0 ; n < len ; ++n)
printf(" %02X",buf[n]);
printf("\n");
sleep(1);
}
printf("\nExit and disconnect\n");
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.