繁体   English   中英

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

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

  1. 问题描述

我正在尝试使用蓝牙 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
  1. 解决方案尝试

我首先尝试记录自己有关 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.

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