简体   繁体   English

如何使用 Linux 蓝牙 C 库连接 BLE 设备

[英]How to connect BLE devices using Linux bluetooth C library

  1. Description of the problem问题描述

I am trying to connect my Bluetooth devices with BLE to a Linux system using the Bluetooth C libraries (I am programming using C++), so here is the code I am currently using:我正在尝试使用蓝牙 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;
}

NOTE : You need to set a specific MAC in connect function parameter.注意:您需要在connect功能参数中设置特定的 MAC。 I am also compiling with g++ using the following command:我还使用以下命令使用 g++ 进行编译:

/usr/bin/g++ -g /home/maria/projects/TestStackOverBLE/main.cpp -o /home/maria/projects/TestStackOverBLE/main -lbluetooth

Here are more information about my hci0 device using hciconfig -a command:以下是有关使用 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)

I am also using Ubuntu 18.04 with:我也在使用Ubuntu 18.04

bluetoothctl v5.64

dbus v1.12.2-1ubuntu1

bluez v5.48-0ubuntu3 . bluez v5.48-0ubuntu3

And the result I am getting when I run the application is the following:运行应用程序时得到的结果如下:

Error: Connecting device: Input/output error
  1. Solution attempts解决方案尝试

I first tried to document myself about how the bluetooth C libraries for Linux works (itis difficult to find any documentation and less for BLE), I need to connect using BLE since my device does not allow communication using Bluetooth classic and I cannot find the reason for the problem I am having.我首先尝试记录自己有关 Linux 的蓝牙 C 库的工作原理(很难找到任何文档,而 BLE 的文档更少),我需要使用 BLE 连接,因为我的设备不允许使用蓝牙经典进行通信,我找不到原因对于我遇到的问题。 I also have tried to restart both the bluetooth service (using sudo service bluetooth restart ) and the hci0 device (using sudo hciconfig hci0 reset ) several times but none worked, I also tried restarting the PC and neither, I even tried the steps mentioned here that are quite similar to my case since previously the "Connection timeout" error has also happened to me but it didn't work either, it just returned the following code in case it was useful: Executing this command: hcitool cmd 0x08 0x000E I received the following output:我也尝试过多次重启蓝牙服务(使用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

What can I do about this problem?我能做些什么来解决这个问题?

EDIT: I was researching and found that making dbus calls to the bluetooth service using C/C++ could work for me but it is quite difficult to find good documentation or concrete connection examples despite having reviewed lots of github projects as most of the code is too convoluted, included in many files and/or consecutive calls for what I am trying to find/understand编辑:我正在研究并发现使用 C/C++ 对蓝牙服务进行 dbus 调用可能对我有用,但是尽管审查了许多 github 项目,但很难找到好的文档或具体的连接示例,因为大多数代码也是令人费解,包含在许多文件中和/或连续调用我要查找/理解的内容

This is what the old hci_xxx bluetooth C functions are doing at the lowest level.这就是旧的 hci_xxx 蓝牙 C 函数在最低级别所做的事情。 They probably don't work now because bluez/dbus is getting in the way.它们现在可能不工作了,因为 bluez/dbus 妨碍了。 The following code works on a Raspberry Pi because it disables bluez first, and could be the basis of a C program - but it would be much easier to use one of the github libraries mentioned in the comments.以下代码适用于 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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM