C Linux:从蓝牙设备接收数据

C Linux:从蓝牙设备接收数据,c,linux,bluetooth-lowenergy,C,Linux,Bluetooth Lowenergy,我希望使用蓝牙LE向微控制器发送/接收数据。 我一直在尝试使用socket使用BTPROTO\uhci协议 sock = socket(AF_BLUETOOTH, SOCK_RAW, BTPROTO_HCI) addr.hci_family = AF_BLUETOOTH; hci_dev = hci_devid( "XX:XX:XX:XX:XX:XX" ); // Replace with actual MAC of device bind(sock, (struct sockaddr *)

我希望使用蓝牙LE向微控制器发送/接收数据。 我一直在尝试使用socket使用BTPROTO\uhci协议

sock = socket(AF_BLUETOOTH, SOCK_RAW, BTPROTO_HCI)

addr.hci_family = AF_BLUETOOTH;
hci_dev = hci_devid( "XX:XX:XX:XX:XX:XX" );  // Replace with actual MAC of device
bind(sock, (struct sockaddr *)&addr, sizeof(addr) 
我正在做的是接收数据

recvmsg(sock, &msg, 0))
但是我没有收到味精

Android中有串行蓝牙终端,可以连接蓝牙LE设备,通过蓝牙LE发送/接收数据。在这个应用程序中,我从微控制器接收数据

代码

#include <sys/types.h>
#include <asm/types.h>
#include <sys/socket.h>
#include <stdlib.h>
#include <bluetooth/bluetooth.h>
#include <bluetooth/hci.h>
#include <bluetooth/hci_lib.h>

struct dump_hdr 
{
  __u16 len;
  __u8  in;
  __u8  pad;
  __u32 ts_sec;
  __u32   ts_usec;
} __attribute__ ((packed));
#define DUMP_HDR_SIZE (sizeof(struct dump_hdr))

struct frame 
{
  void  *data;
  int   data_len;
  void  *ptr;
  int   len;
  int   in;
  int   handle;
  long  flags;
  struct timeval ts;
};

int main(void)
{
    printf("Starting...");
    struct sockaddr_hci addr;
    struct hci_filter filter;
    int sock, one = 1;
    char packet[HCI_MAX_FRAME_SIZE];
    struct cmsghdr *cmsg;
    struct msghdr msg;
    struct iovec  iv;
    struct dump_hdr *dh;
    struct frame frm;

    char *buf, *ctrl;

    if((sock = socket(AF_BLUETOOTH, SOCK_RAW, BTPROTO_HCI)) < 0)
    {
         perror("socket");
         exit(1);
    }

    if(setsockopt(sock, SOL_HCI, HCI_DATA_DIR, &one, sizeof(one)) < 0) 
    {
        perror("Can't enable data direction info");
        exit(1);
    }

    if(setsockopt(sock, SOL_HCI, HCI_TIME_STAMP, &one, sizeof(one)) < 0) 
    {
        perror("Can't enable time stamp");
        exit(1);
    }

    hci_filter_clear(&filter);
    hci_filter_all_ptypes(&filter);
    hci_filter_all_events(&filter);

   if(setsockopt(sock, SOL_HCI, HCI_FILTER, &filter, sizeof(filter)) < 0) 
   {
      perror("Can't set HCI filter");
      exit(1);
   }

   addr.hci_family = AF_BLUETOOTH;
   addr.hci_dev = hci_devid( "XX:XX:XX:XX:XX:XX" );//eplace with actual MAC of device


   if(bind(sock, (struct sockaddr *)&addr, sizeof(addr)) < 0) 
   {
       perror("bind");
       exit(1);
   }

   if (!(buf = malloc(DUMP_HDR_SIZE))) 
   {
       perror("Can't allocate data buffer");
       exit(1);
   }

   dh = (void *) buf;
   frm.data = buf + DUMP_HDR_SIZE;

   if (!(ctrl = malloc(100))) 
   {
       perror("Can't allocate control buffer");
       exit(1);
   }

   memset(&msg, 0, sizeof(msg));

   while (1) 
   {
       printf(".");
      iv.iov_base = frm.data;
      iv.iov_len  = sizeof(frm.data);//snap_len;

      msg.msg_iov = &iv;
      msg.msg_iovlen = 1;
      msg.msg_control = ctrl;
      msg.msg_controllen = 100;
      if ((frm.data_len = recvmsg(sock, &msg, 0)) < 0) 
      {
          perror("Receive failed");
          exit(1);
       }

       /* Process control message */
       frm.in = 0;
       cmsg = CMSG_FIRSTHDR(&msg);

       while (cmsg) 
       {
           printf("%s\r\n", cmsg);
           switch (cmsg->cmsg_type) 
           {
               case HCI_CMSG_DIR:
                 frm.in = *((int *)CMSG_DATA(cmsg));
                 break;
               case HCI_CMSG_TSTAMP:
                 frm.ts = *((struct timeval *)CMSG_DATA(cmsg));
               break;
          }

         cmsg = CMSG_NXTHDR(&msg, cmsg);
      }

       frm.ptr = frm.data;
       frm.len = frm.data_len;

       /* Parse and print */
       hci_dump(&frm);
   }

   close(sock);
   return 0;
}

void hci_dump(struct frame *frm)
{
   __u8 type = *(__u8 *)frm->ptr; 

   frm->ptr++; frm->len--;

   if(type == HCI_ACLDATA_PKT)
   {
       hci_acl_hdr *hdr = (void *) frm->ptr;
      __u16 handle = btohs(hdr->handle);
      __u16 dlen = btohs(hdr->dlen);
      __u8 flags = acl_flags(handle);
      printf("ACL data: handle 0x%4.4x flags 0x%2.2x dlen %d\n",
      acl_handle(handle), flags, dlen);
}
#包括
#包括
#包括
#包括
#包括
#包括
#包括
结构转储
{
__u16-len;
__u8英寸;
__u8垫;
__u32秒;
__u32 ts_usec;
}_uuu属性_uuu((压缩));
#定义DUMP_HDR_大小(sizeof(struct DUMP_HDR))
结构框架
{
作废*数据;
国际数据中心;
无效*ptr;
内伦;
int-in;
int句柄;
长旗;
结构时间值ts;
};
内部主(空)
{
printf(“开始…”);
结构sockaddr\u hci addr;
结构hci_过滤器;
int sock,1=1;
字符包[HCI_MAX_FRAME_SIZE];
结构cmsghdr*cmsg;
结构msghdr msg;
结构iovec iv;
结构转储_hdr*dh;
结构框架;
char*buf,*ctrl;
if((sock=socket(蓝牙、sock\u原始、BTPROTO\u HCI))<0)
{
佩罗(“插座”);
出口(1);
}
if(setsockopt(sock,SOL_HCI,HCI_DATA_DIR,&one,sizeof(one))小于0)
{
perror(“无法启用数据方向信息”);
出口(1);
}
if(setsockopt(sock,SOL_HCI,HCI_TIME_STAMP,&one,sizeof(one))小于0)
{
perror(“无法启用时间戳”);
出口(1);
}
hci\u过滤器\u清除(&filter);
hci_过滤器_所有类型(&filter);
hci\u过滤器\u所有\u事件(&filter);
如果(设置锁定选项(锁定、SOL_HCI、HCI_过滤器和过滤器,大小(过滤器))<0)
{
perror(“无法设置HCI过滤器”);
出口(1);
}
addr.hci_family=AF_蓝牙;
addr.hci_dev=hci_devid(“XX:XX:XX:XX:XX:XX”);//替换设备的实际MAC
if(bind(sock,(struct sockaddr*)&addr,sizeof(addr))<0)
{
佩罗(“绑定”);
出口(1);
}
如果(!(buf=malloc(转储HDR大小)))
{
perror(“无法分配数据缓冲区”);
出口(1);
}
dh=(无效*)buf;
frm.data=buf+DUMP\U HDR\U大小;
如果(!(ctrl=malloc(100)))
{
perror(“无法分配控制缓冲区”);
出口(1);
}
memset(&msg,0,sizeof(msg));
而(1)
{
printf(“.”);
iv.iov_base=frm.data;
iv.iov_len=sizeof(frm.data);//snap_len;
msg.msg_iov=&iv;
msg.msg_iovlen=1;
msg.msg_control=ctrl;
msg.msg_controllen=100;
如果((frm.data_len=recvmsg(sock,&msg,0))<0)
{
perror(“接收失败”);
出口(1);
}
/*过程控制消息*/
frm.in=0;
cmsg=cmsg_FIRSTHDR(&msg);
while(cmsg)
{
printf(“%s\r\n”,cmsg);
开关(cmsg->cmsg\U型)
{
案例HCI\U CMSG\U主任:
frm.in=*((int*)CMSG_数据(CMSG));
打破
案例HCI\U CMSG\U TSTAMP:
frm.ts=*((struct timeval*)CMSG_DATA(CMSG));
打破
}
cmsg=cmsg_NXTHDR(&msg,cmsg);
}
frm.ptr=frm.data;
frm.len=frm.data_len;
/*解析和打印*/
hci_转储(和frm);
}
关闭(袜子);
返回0;
}
无效hci_转储(结构帧*frm)
{
__u8类型=*(uuuU8*)frm->ptr;
frm->ptr++;frm->len--;
if(type==HCI\u ACLDATA\u PKT)
{
hci_acl_hdr*hdr=(无效*)frm->ptr;
__u16手柄=btohs(hdr->手柄);
__u16 dlen=btohs(hdr->dlen);
__u8标志=acl_标志(句柄);
printf(“ACL数据:处理0x%4.4x标志0x%2.2x数据项%d\n”,
acl_句柄(句柄)、标志、dlen);
}

}

您需要使用
hci\u设备的结果

hci_dev = hci_devid( "XX:XX:XX:XX:XX:XX" );
应该成为

addr.hci_dev = hci_devid( "XX:XX:XX:XX:XX:XX" );

虽然我不希望
hci\u dev
在当前范围内被定义为一个单独的变量。

看起来您缺少了一个
位于该代码块的最后一行。我认为这是一个复制错误,但它仍然丢失。请不要使用像BLE这样令人困惑的首字母缩写词。在计算中,BLE从一开始就是“位长度编码”的意思。@Lundin BLE是一个非常常见的术语,比位长度编码更被广泛接受和认可为蓝牙低能量。@ChuckClaunch只是因为一些dua决定发明另一个TLA。虽然我有点同意蓝牙的BLE是一个比两年前我写这篇评论时更常见的术语。@Lundin BLE这个术语至少已经存在十年了。我个人开发BLE相关软件至少有五六年了。在一个与蓝牙低能量相关的问题上,把BLE称为一个令人困惑的术语似乎很愚蠢。