hciattach 分析

hciattach的功能是:建立串口和蓝牙协议层的数据连接通道。
源代码参考 tools/hciattach.c
先看hciattach的 用法
hciattach [-n] [-p] [-b] [-r] [-t timeout] [-s initial_speed] <tty> <type | id> [speed] [flow|noflow] [bdaddr]
hciattach -l

hciattach的结构体
struct uart_t {
char *type;
int  m_id;
int  p_id;
int  proto;
int  init_speed;
int  speed;
int  flags;
char *bdaddr;
int  (*init) (int fd, struct uart_t *u, struct termios *ti);
int  (*post) (int fd, struct uart_t *u, struct termios *ti);
};

从main 函数开始,
while ((opt= getopt(argc, argv, "bnpt:s:lr")) != EOF)   //为什么,请看上面的用法
解析main函数的参数,然后switch(opt) 进入选择。
init_speed = atoi(optarg);
……

n = argc - optind;
if (n < 2) {
usage();
exit(1);
}
这是参数不对,调用使用方法
for (n = 0; optind < argc; n++, optind++) {
char *opt;

opt = argv[optind];

switch(n) {
case 0:
dev[0] = 0;
if (! strchr(opt, '/'))    //查找opt中首次出现/的地方  
strcpy(dev, "/dev/");
strcat(dev, opt);    //opt追加到dev后
break;
                case 1:
                        if (strchr(argv[optind], ',')) {
int m_id, p_id;
sscanf(argv[optind], "%x,%x", &m_id, &p_id);
u =   get_by_id(m_id, p_id);    //获取uart_t,返回 uart[],对应其中的初始化函数等。假如是uart[1]就是bcsp
} else {
u =   get_by_type(opt);
}
                ……
前面都是对hciattach用法的解析。
struct uart_t   uart[] = {
{ "any",        0x0000, 0x0000, HCI_UART_H4,   115200, 115200, FLOW_CTL, NULL, NULL     },
{ "bcsp",       0x0000, 0x0000, HCI_UART_BCSP, 115200, 115200, 0,         NULL, bcsp     },
        ……
上面粗体标注  对应u->init,u->post。这里蓝牙供应商会添加自己的配置和通讯方式。


设置好了通讯方式,在初始化串口调用。
init_uart函数分析
static int init_uart(char *dev, struct uart_t *u, int send_break, int raw)
{
struct termios ti;
int fd, i;
unsigned long flags = 0;
if (raw)
flags |= 1 << HCI_UART_RAW_DEVICE;

fd = open(dev, O_RDWR | O_NOCTTY);     //可进行读写,不将此设备分配作为此进程的控制终端,即Ctrl+C 不能结束此进程
if (fd < 0) {
perror("Can't open serial port");
return -1;
}

tcflush(fd, TCIOFLUSH);    //清空数据线

if (tcgetattr(fd, &ti) < 0) {        //获得串口设置
perror("Can't get port settings");
return -1;
}

cfmakeraw(&ti);    //将终端设置为原始模式控制终端

ti.c_cflag |= CLOCAL;
if (u->flags & FLOW_CTL)    //设置流控
ti.c_cflag |= CRTSCTS;
else
ti.c_cflag &= ~CRTSCTS;    //本地连接,无调制解调器控制
if (tcsetattr(fd, TCSANOW, &ti) < 0) {    //设置串口
perror("Can't set port settings");
return -1;
}

/* Set initial baudrate */
if (set_speed(fd, &ti, u->init_speed) < 0) {    
perror("Can't set initial baud rate");
return -1;
}

tcflush(fd, TCIOFLUSH);

if (send_break) {
tcsendbreak(fd, 0);    //在串口线上发送0值
usleep(500000);    //0.5s发送一个break
}

if (u->init && u->init(fd, u, &ti) < 0)    
//所有bluez支持的蓝牙串口设备类型构成了一个uart结构数组,通过查找对应的uart类型,并调用这个uart的init成员函数。
return -1;

tcflush(fd, TCIOFLUSH);

/* Set actual baudrate */        //设置实际的波特率
if (set_speed(fd, &ti, u->speed) < 0) {
perror("Can't set baud rate");
return -1;
}

/* Set TTY to N_HCI line discipline */
i = N_HCI;
if (ioctl(fd,   TIOCSETD, &i) < 0) {        // 调用内核的tty_ioctl,采用ldisc机制改变hci行规
perror("Can't set line discipline");
return -1;
}

if (flags && ioctl(fd, HCIUARTSETFLAGS, flags) < 0) {    //设置串口参数
perror("Can't set UART flags");
return -1;
}
if (ioctl(fd,   HCIUARTSETPROTO, u->proto) < 0) {   
 //调用内核的tty_ioctl,注册一个hci设备,设置proto为hci设备的proto操作函数集
perror("Can't set device");
return -1;
}

if (u->post && u->post(fd, u, &ti) < 0)    //调用这个uart的post成员函数
return -1;

return fd;
}
其中TIOCSETD,HCIUARTSETPROTO需要内核处理

重新回到main(),后面信号处理  

恢复行规
ld = N_TTY;
if (ioctl(n, TIOCSETD, &ld) < 0) {
perror("Can't restore line discipline");
exit(1);
}
 
到此为止,hciattach的工作介绍完毕。

 
 
 
要深入了解Linux系统中使用Bluez框架进行蓝牙驱动的初始化和数据传递,推荐参考《蓝牙驱动与Bluez操作流程详解》。该文档对蓝牙技术在Linux中的实现流程进行了深入的解析,特别是Bluez框架下的蓝牙驱动分析及使用过程。 参考资源链接:[蓝牙驱动与Bluez操作流程详解](https://wenku.csdn.net/doc/3g6ti5hbu6?spm=1055.2569.3001.10343) 初始化蓝牙驱动是整个蓝牙通信过程的基石。首先,模块上电后进行初始化,这包括设置PSKEY以及初始化串口驱动。HCIATTACH是Bluez中负责蓝牙硬件抽象层与物理层通信的关键部分,它在内核层面上负责初始化蓝牙控制器并启动蓝牙协议栈。具体操作包括加载HCI驱动模块,配置UART层参数,以及执行实际的ATTACH命令,将HCI层与UART层连接起来。 数据传递流程是理解蓝牙通信的核心。UART层作为最基础的通信接口,负责接收和发送原始数据。当数据到达UART层后,它们首先通过HCI_UART驱动处理,转换成HCI层可以理解的格式。HCI层进一步将数据封装成L2CAP、AVDTP等协议的数据包,以适应不同的服务和应用。这一过程涉及到HCI命令、事件、数据分组的交互,每一步都是数据正确传递的关键。 为了更具体地理解这一过程,你可以通过示例代码观察HCIATTACH命令的使用,了解如何通过UART层发送和接收数据,以及如何处理内核层与用户空间之间的交互。 在深入掌握了初始化和数据传递的基础之后,建议继续学习《蓝牙驱动与Bluez操作流程详解》中的高级应用部分,包括A2DP音频流媒体服务、HFP/HSP协议的Handsfree功能等,这将帮助你更好地理解蓝牙技术在实际应用中的运作机制。 参考资源链接:[蓝牙驱动与Bluez操作流程详解](https://wenku.csdn.net/doc/3g6ti5hbu6?spm=1055.2569.3001.10343)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值