hci_uart 分析

先从初始化开始
__init hci_uart_init(void)
……    //注册ldisc
        hci_uart_ldisc.magic = TTY_LDISC_MAGIC;    //通过i = N_HCI; if (ioctl(fd,  TIOCSETD, &i) < 0)获得
        hci_uart_ldisc.name = "n_hci";
        hci_uart_ldisc.open = hci_uart_tty_open;
        hci_uart_ldisc.close = hci_uart_tty_close;
        hci_uart_ldisc.read = hci_uart_tty_read;
        hci_uart_ldisc.write = hci_uart_tty_write;
        hci_uart_ldisc.ioctl = hci_uart_tty_ioctl;
        hci_uart_ldisc.poll = hci_uart_tty_poll;
        hci_uart_ldisc.receive_buf = hci_uart_tty_receive;
        hci_uart_ldisc.write_wakeup = hci_uart_tty_wakeup;    // ldisc对应的处理函数
        hci_uart_ldisc.owner = THIS_MODULE;
……
if ((err =   tty_register_ldisc(N_HCI, &hci_uart_ldisc)))
……
bcsp_init();        //取决于hciattach中选择的uart[]
……
}

源码在/drivers/char/tty_io.c
int tty_register_ldisc(int disc, struct   tty_ldisc *new_ldisc)
{
unsigned long flags;
int ret = 0;

if (disc < N_TTY || disc >=   NR_LDISCS)
return -EINVAL;

spin_lock_irqsave(&tty_ldisc_lock, flags);
tty_ldiscs[disc] = *new_ldisc;
tty_ldiscs[disc].num = disc;
tty_ldiscs[disc].flags |= LDISC_FLAG_DEFINED;
tty_ldiscs[disc].refcount = 0;
spin_unlock_irqrestore(&tty_ldisc_lock, flags);

return ret;
}
/* Line disc dispatch table */
static struct tty_ldisc tty_ldiscs[NR_LDISCS];

bcsp_init()--> hci_uart_register_proto(&bcsp);    //注册proto操作函数
{
if (p->id >= HCI_UART_MAX_PROTO)
return -EINVAL;

if (hup[p->id])
return -EEXIST;

hup[p->id] = p;    //static struct hci_uart_proto *hup[HCI_UART_MAX_PROTO];

return 0;
}

struct   hci_uart_proto {
unsigned int id;
int (*open)(struct hci_uart *hu);
int (*close)(struct hci_uart *hu);
int (*flush)(struct hci_uart *hu);
int (*recv)(struct hci_uart *hu, void *data, int len);
int (*enqueue)(struct hci_uart *hu, struct sk_buff *skb);
struct sk_buff *(*dequeue)(struct hci_uart *hu);
};

struct   hci_uart {
struct tty_struct *tty;
struct hci_dev *hdev;
unsigned long flags;
unsigned long hdev_flags;

struct hci_uart_proto *proto;
void *priv;

struct sk_buff *tx_skb;
unsigned long tx_state;
spinlock_t rx_lock;
};




### HCI_UART 协议栈实现 HCI (Host Controller Interface) 是蓝牙协议堆栈中的一个重要组成部分,它定义了主机(Host)和控制器(Controller)之间的通信接口。通过 UART 作为物理传输层,可以实现主机与控制器之间基于 HCI 的数据交换。 #### HCI_UART 数据帧结构 在 UART 上发送的 HCI 数据包通常遵循 H4 或者类似的封装协议。H4 将不同的 HCI 数据包类型映射到特定的前导字节上: | 前导字节 | 数据包类型 | |----------|------------------| | `0x01` | HCI Command | | `0x04` | HCI Event | | `0x02` | HCI ACL Data | | `0x0C` | HCI SCO Data | | `0x0F` | HCI ISO Data | 每种类型的 HCI 数据包都具有固定的头部格式以及可变长度的有效载荷部分[^1]。 #### 主要功能模块设计 以下是实现一个完整的 HCI_UART 协议栈所需的主要组件及其职责描述: ##### 1. **UART 驱动** 负责管理串口设备的操作,包括初始化、配置波特率、读写缓冲区等功能。这是整个系统的底层硬件支持。 ```c void uart_init(int baud_rate); int uart_read(unsigned char *buffer, int length); int uart_write(const unsigned char *data, int size); ``` ##### 2. **分组解析器** 用于区分接收到的数据属于哪种类型的 HCI 包,并调用相应的处理函数来进一步分析其具体内容。 ```c typedef enum { HCI_PACKET_TYPE_COMMAND, HCI_PACKET_TYPE_EVENT, HCI_PACKET_TYPE_ACL_DATA, HCI_PACKET_TYPE_SCO_DATA, HCI_PACKET_TYPE_ISO_DATA } hci_packet_type_t; hci_packet_type_t parse_hci_packet_header(unsigned char header_byte); ``` ##### 3. **命令处理器** 当检测到来自应用层发起的一个新命令请求时,此模块会构建对应的 HCI_Command_Packet 并经由 UART 发送给远程蓝牙控制端。 ```c void send_command_to_controller(hci_opcode_t opcode, void *parameters, uint8_t param_len); ``` ##### 4. **事件监听器** 接收来自蓝牙芯片返回的状态更新或其他异步通知消息并传递给高层逻辑进行后续操作。 ```c void handle_incoming_event(hci_event_code_t event_code, const unsigned char *payload, uint8_t payload_length); ``` ##### 5. **ACL/Sync/Iso 流量管理者** 针对不同类型的应用级流量流提供独立通道管理和调度机制;比如电话音频可能走SCO链路而多媒体播放则依赖于ISO路径等等。 ```c bool transmit_acl_data(uint16_t connection_handle, const unsigned char *data, uint16_t data_total_size); bool receive_synchronous_connection_audio_stream(); // For Core Spec v5.2+ bool establish_iso_channel_configuration(); ``` #### 示例代码片段 下面展示了一个简单的伪代码例子演示如何利用上述各子系统完成一次基本连接建立过程: ```c #include "uart_driver.h" #include "hci_parser.h" #define DEFAULT_BAUD_RATE 9600 int main() { uart_init(DEFAULT_BAUD_RATE); while (true) { unsigned char byte; if (!uart_read(&byte, sizeof(byte))) continue; // Wait until there's something to read switch(parse_hci_packet_header(byte)) { case HCI_PACKET_TYPE_COMMAND: process_outgoing_commands(); break; case HCI_PACKET_TYPE_EVENT: handle_incoming_events(); break; default: /* Handle other packet types as needed */ manage_generic_traffic_streams();break; } } return 0; } ```
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值