hci层编程
作者:互联网
主机控制器接口协议(hci)
一.概述
Hci是主机与控制器之间的接口,即主机与控制器之间通信的协议规范,其规定了指令、事件和数据的封装格式。在物理链路上又规定如何传输这些数据报。其主要的两个任务:
1. 发送命令给控制器和接收来自控制器的事件,达到对本地的配置和状态的监控。
2. 接收和发送来自对端设备的数据,设备之间信息传输。
在蓝牙规范中,描述了四种主机与控制器间传输数据的方法:
1)UART
2)USB
3)RS232
4)SD
二.HCI数据格式
1) HCI指令分组 (针对指令):HCI指令分组用于从主机向控制器发送指令,一般当控制器完成主机发送来的命令时,将返回一个指令完成状态事件给主机,让主机知道指令执行的结果。其数据报格式如下:
操作码(OpCode)用来唯一标识HCI Command.它由2部分组成,10bit的Opcode Command. 6bit的Opcode Group。
OpCode Group Flag(OGF) 表明指令的类型,在bluez中定义以下的OGF
0X01 | OGF_LINK_CTL | 链路控制 |
0X02 | OGF_LINK_POLICY | 链路策略 |
0X03 | OGF_HOST_CTL | 主机控制 |
0X04 | OGF_INFO_PARAM | 主机策略 |
0X05 | OGF_STATUS_PARAM | 状态策略 |
0X08 | OGF_LE_CTL | ble设备控制 |
0X3E | OGF_TESTING_CMD | 测试命令 |
0X3F | OGF_VENDOR_CMD |
厂商测试 |
Opcode Command Flag (OCF)表明了所要执行的指令,每个不同类型的指令(OGF)都有一系列OCF来指明要操作的
参数:每个指令都有与之关联的参数,这些参数及其大小有指令定义。
例:对于蓝牙查询模式(搜索附近蓝牙设备的指令)bluez有以下声明:
#define OGF_LINK_CTL 0x01 //OGF,查询模式为链路控制的指令
#define OCF_INQUIRY 0x0001 //查询模式指令的OCF
typedef struct {
uint8_t lap[3]; //24位地址低端部分
uint8_t length; /* 1.28s units */
uint8_t num_rsp;
} __attribute__ ((packed)) inquiry_cp; //定义的参数
#define INQUIRY_CP_SIZE 5 //参数长度
1) HCI数据分组 (针对数据)
HCI数据分组用于在主机和控制器之间交换数据。数据分组根据ACL和SCO数据分组类型进行定义
1.HCI ACL分组数据包格式及解析
PB flag | |
值 | 参数描述 |
00 | 保留 |
01 |
用于高层报文的数据分组分段 |
10 |
高层报文的第一个数据分段 |
11 | 保留 |
BC flag | |
值 | 参数描述 |
00 | 没有广播 |
01 | 激活广播:数据报发往所有激活的从单元 |
10 | 比克网广播:数据报发往所有的从单元,包括休眠单元 |
11 | 保留 |
连接句柄:
值 | 参数描述 |
0xXXX | 范围:0x0000-0xEFFF.一个连接句柄就是用于唯一标识蓝牙设备之间SCO或ACL连接的12bit的标识符,连接句柄通过唯一标识两蓝牙设备之间的数据管道进行访问。每个设备应在建立远程连接的整个周期内保持连接句柄。在两个设备间可以拥有多个连接句柄但只能保持一个ACL连接。 |
2.HCI SCO分组
|
保留位:由HCI SCO数据分组中第2字节的4~7bit组成
2) HCI 事件分组
HCI事件分组用于在事件发生时通知主机,由控制器发往主机。当主机接收到事件分组时解析分组以确定发生了那个事件。
事件码:每个事件都指定1字节事件码,以唯一标识不停事件类型。
参数总长:所有参数总长,单位为字节
事件参数:每个指令都有与之关联的参数,根据指令定义。
三.HCI 编程——搜索发现远程设备
1.相关函数讲解
1)int hci_get_route(bdaddr_t *bdaddr)
/*根据其bdaddr得到相应的设备id
*如果 bdaddr 为 NULL,则返回第一可用设备的ID
*返回值小于0获取失败*/
2)int hci_open_dev(int dev_id)
/* hci_open_dev会使用socket()创建一个AF_BLUETOOTH域的套接字描述符,并与指定的本地设备绑定,这样就可以用通过创建的描述符操作该设备。
* dev_id :打开的本地设备的设备ID
* Returns :创建的套接字描述符,小于0则创建失败*/
3)int hci_close_dev(int dd)
/*关闭套接字描述符*/
4)int hci_send_req(int dd, struct hci_request *r, int to)
/*该函数用于向控制器发送一个指令
*dd :hci_open_dev创建的描述符
* r :要发送的HCI指令分组以及返回的事件分组,格式如下
* struct hci_request {
* uint16_t ogf; //操作组段
* uint16_t ocf; //操作码指令段
* int event; //返回事件类型
* void *cparam; //参数
* int clen; //参数长度
* void *rparam; //返回的事件分组参数
* int rlen; //事件分组长度
*}
*to :超时时间,单位ms*/
/* Filter types */
#define FLT_CLEAR_ALL 0x00
#define FLT_INQ_RESULT 0x01
#define FLT_CONN_SETUP 0x02
5)int hci_le_set_scan_parameters(int dd, uint8_t type,uint16_t interval, uint16_t window,uint8_t own_type, uint8_t filter, int to)
/* hci_le_set_scan_parameters函数会向主机发送一个HCI指令分组用于对搜索参的配置
* dd : hci_open_dev函数打开的套接字
* type:搜索类型,为0是被动搜索
* interval: 搜索的时间 =N*1.25
* window : 搜索数量
* own_tpe: 地址类型
* filter :过滤器 FLT_CLEAR_ALL(清除所有过滤器)FLT_INQ_RESULT(过滤已经搜索到的设备)
* to :超时时间,单位ms
*/
6)int hci_le_set_scan_enable(int dd, uint8_t enable, uint8_t filter_dup, int to)
/*dd :hci_open_dev函数打开的套接字
*enable : 为1是开始扫描,0停止扫描
*filter_dup:事件过滤器 为0是每次返回所有事件(返回所有搜索到的设备信息),为1是过滤已出现的事件(不返回前面已经得到的设备信息)
*to :超时时间,单位ms
*/
标签:hci,int,编程,指令,分组,HCI,OGF 来源: https://www.cnblogs.com/amateur-writer-2019-1-12/p/11198026.html