Bluedroid协议栈HCI线程分析

蓝牙进程中有多个线程,其中HCI 线程是负责处理蓝牙主机端和控制器的数据处理和收发的工作。

本篇文章就是分析一下该线程的数据处理流程。

1.跟HCI相关的接口

首先看看hci的相关的接口:在hci_layer.c中:

const hci_t *hci_layer_get_interface() {
  buffer_allocator = buffer_allocator_get_interface();
  hal = hci_hal_get_interface();//hal模块
  btsnoop = btsnoop_get_interface();
  hci_inject = hci_inject_get_interface();
  packet_fragmenter = packet_fragmenter_get_interface();//组装分块
  vendor = vendor_get_interface();//vendor模块
  low_power_manager = low_power_manager_get_interface();
  init_layer_interface();
  return &interface;
}

主要是结构是:hal,packet_fragmenter以及vendor,下面看看这个接口的结构:

hal模块接口

static const hci_hal_t interface = {
  hal_init,
  hal_open,//通过vendor模块发送指令VENDOR_OPEN_USERIAL,打开host与controller的通信节点,并且在hci线程中一直poll该节点,有数据就传上层协议栈
  hal_close,
  read_data,
  packet_finished,
  transmit_data,
};

const hci_hal_t *hci_hal_h4_get_interface() {
  vendor = vendor_get_interface();//获取了vendor接口
  return &interface;
}

分析代码发现hal_open主要是通过vendor来和底层的模块通信的。可见hal层在vendor的上面。

packet_fragmenter模块接口

static const packet_fragmenter_t interface = {
  init,
  cleanup,
  fragment_and_dispatch,//分片,然后回调到hci_layer,通过hal层发送
  reassemble_and_dispatch//重装,然后回调到hci_layer,塞到btu_hci_queue队列里面
};

const packet_fragmenter_t *packet_fragmenter_get_interface() {
  controller = controller_get_interface();//获取控制器的接口
  buffer_allocator = buffer_allocator_get_interface();
  return &interface;
}

该模块主要负责数据的分片和重组,当hci向下发送数据的时候,会将数据放置到packet_queue,然后调用到该模块的fragment_and_dispatch,然后经过HAL模块发送到vendor,最后抵达controller

当controller有数据上传的时候,底层的bt driver会将数据发送到host与controller的通信节点。hci_thread会一直poll这个节点,然后读出数据,经过hal以及fragment_and_dispatch,最后总到btu线程。

vendor模块接口

static const vendor_t interface = {
  vendor_open,//加载libbt-vendor模块并对模块初始化
  vendor_close,
  send_command,//通过libbt-vendor进行发送op命令,非hci opcode
  send_async_command,
  set_callback,
};

const vendor_t *vendor_get_interface() {
  buffer_allocator = buffer_allocator_get_interface();
  return &interface;
}

vendor模块主要是初始化libbt-vendor模块,一些与厂商相关的接口定义。具体的实现是厂商自己的实现,比如打开底层的通信节点,downloaf 卡片的patch等等。

2.线程的创建

线程的创建在hci_layer.c里面,在hci 模块的start_up函数里面:

static future_t *start_up(void) {
  LOG_INFO("%s", __func__);
...  
command_queue = fixed_queue_new(SIZE_MAX);//创建命令队列,用于发送命令
packet_queue = fixed_queue_new(SIZE_MAX);//创建数据队列,用于发送数据
  thread = thread_new("hci_thread");//创建hci线程
...
  packet_fragmenter->init(&packet_fragmenter_callbacks);//初始化“组装分块”模块

  fixed_queue_register_dequeue(command_queue, thread_get_reactor(thread), event_command_ready, NULL);//hci_thread绑定命令队列
  fixed_queue_register_dequeue(packet_queue, thread_get_reactor(thread), event_packet_ready, NULL);//hci_thread 绑定数据队列
...
  vendor->open(btif_local_bd_addr.address, &interface);//调用vendor模块的open
  hal->init(&hal_callbacks, thread);//初始化hal模块
...
 thread_post(thread, event_finish_startup, NULL);//继续完成hci模块的启动工作,这里主要做的是继续初始化vendor模块
...

猜你喜欢

转载自www.cnblogs.com/libs-liu/p/9218460.html