1.  蓝牙协议栈里面的各组件的通信是通过消息队列,例如:
btu_task 和bta直接就是通过队列bt/stack/btu/btu_task.c
// Communication queue between btu_task and hci.
extern fixed_queue_t *btu_hci_msg_queue;

2. 这个队列的初始化在

bt/main/bte_main.c

void bte_main_boot_entry(void)
{
module_init(get_module(GKI_MODULE));
module_init(get_module(COUNTER_MODULE));

hci = hci_layer_get_interface();
if (!hci)
LOG_ERROR("%s could not get hci layer interface.", __func__);

btu_hci_msg_queue= fixed_queue_new(SIZE_MAX);
if (btu_hci_msg_queue == NULL) {
LOG_ERROR("%s unable to allocate hci message queue.", __func__);
return;
}

之后需要在btu初始化的时候,把这个队列和相关的线程关联起来,这样发送完消息后,就可以通知相关的线程去队列里面取消息并进行处理
在文件bt/stack/btu/btu_task.c,

void btu_task_start_up(UNUSED_ATTR void *context) {

..................
fixed_queue_register_dequeue(btu_hci_msg_queue,
thread_get_reactor(bt_workqueue_thread),
btu_hci_msg_ready,
NULL);


}

发送消息的方式如下:
在文件bt/stack/btu/btu_hcif.c或btu_init.c中,
fixed_queue_enqueue(btu_hci_msg_queue, event);

发送到队列后,开始使用如下的方法进行处理:

在文件bt/stack/btu/btu_task.c中,
void btu_hci_msg_ready(fixed_queue_t *queue, UNUSED_ATTR void *context) {
BT_HDR *p_msg = (BT_HDR *)fixed_queue_dequeue(queue);
btu_hci_msg_process(p_msg);
}


static void btu_hci_msg_process(BT_HDR *p_msg) {
/* Determine the input message type. */
switch (p_msg->event & BT_EVT_MASK)
{
case BTU_POST_TO_TASK_NO_GOOD_HORRIBLE_HACK: // TODO(zachoverflow): remove this
((post_to_task_hack_t *)(&p_msg->data[0]))->callback(p_msg);
break;
case BT_EVT_TO_BTU_HCI_ACL:
/* All Acl Data goes to L2CAP */
l2c_rcv_acl_data (p_msg);
break;

case BT_EVT_TO_BTU_L2C_SEG_XMIT:
/* L2CAP segment transmit complete */
l2c_link_segments_xmitted (p_msg);
break;

case BT_EVT_TO_BTU_HCI_SCO:
#if BTM_SCO_INCLUDED == TRUE
btm_route_sco_data (p_msg);
break;
#endif

case BT_EVT_TO_BTU_HCI_EVT:
btu_hcif_process_event((UINT8)(p_msg->event & BT_SUB_EVT_MASK), p_msg);
GKI_freebuf(p_msg);

#if (defined(HCILP_INCLUDED) && HCILP_INCLUDED == TRUE)
/* If host receives events which it doesn't response to, */
/* host should start idle timer to enter sleep mode.     */
btu_check_bt_sleep ();
#endif
break;

case BT_EVT_TO_BTU_HCI_CMD:
btu_hcif_send_cmd((UINT8)(p_msg->event & BT_SUB_EVT_MASK), p_msg);
break;

default:;
int i = 0;
uint16_t mask = (UINT16) (p_msg->event & BT_EVT_MASK);
BOOLEAN handled = FALSE;

for (; !handled && i < BTU_MAX_REG_EVENT; i++)
{
if (btu_cb.event_reg[i].event_cb == NULL) // btu_cb.event_reg[i].event_cb 这个callback是在哪里初始化的??
continue;

if (mask == btu_cb.event_reg[i].event_range)
{
if (btu_cb.event_reg[i].event_cb)
{
btu_cb.event_reg[i].event_cb(p_msg);
handled = TRUE;
}
}
}

if (handled == FALSE)
GKI_freebuf (p_msg);

break;
}

}


我们以一个调用btu_hcif_send_cmd给controller发送指令为例子,如下的一个为例:

void btu_hcif_send_cmd(UNUSED_ATTR UINT8 controller_id, BT_HDR *p_buf)
{
if (!p_buf)
return;

uint16_t opcode;
uint8_t *stream = p_buf->data + p_buf->offset;
void * vsc_callback = NULL;

STREAM_TO_UINT16(opcode, stream);

// Eww...horrible hackery here
/* If command was a VSC, then extract command_complete callback */
if ((opcode & HCI_GRP_VENDOR_SPECIFIC) == HCI_GRP_VENDOR_SPECIFIC
#if BLE_INCLUDED == TRUE
|| (opcode == HCI_BLE_RAND)
|| (opcode == HCI_BLE_ENCRYPT)
#endif
) {
vsc_callback = *((void **)(p_buf + 1));
}

hci_layer_get_interface()->transmit_command(
p_buf,
btu_hcif_command_complete_evt,
btu_hcif_command_status_evt,
vsc_callback);

#if (defined(HCILP_INCLUDED) && HCILP_INCLUDED == TRUE)
btu_check_bt_sleep ();
#endif
}

hci_layer_get_interface这个方法调用hci_layer_get_interface后会返回一个函数指针,

const hci_t *hci_layer_get_interface() {
buffer_allocator = buffer_allocator_get_interface();
hal = hci_hal_get_interface();
btsnoop = btsnoop_get_interface();
hci_inject = hci_inject_get_interface();
packet_fragmenter = packet_fragmenter_get_interface();
vendor = vendor_get_interface();
low_power_manager = low_power_manager_get_interface();

#ifdef BLUETOOTH_RTK
hci_h5 =  hci_get_h5_interface();
#endif
#ifdef BLUETOOTH_RTK_COEX
rtk_parse_manager = rtk_parse_manager_get_interface();
#endif
init_layer_interface();
return &interface;
}


static void init_layer_interface() {
if (!interface_created) {
interface.send_low_power_command = low_power_manager->post_command;
interface.do_postload = do_postload;

// It's probably ok for this to live forever. It's small and
// there's only one instance of the hci interface.
interface.event_dispatcher = data_dispatcher_new("hci_layer");
if (!interface.event_dispatcher) {
LOG_ERROR("%s could not create upward dispatcher.", __func__);
return;
}

interface.set_data_queue = set_data_queue;
#ifdef BLUETOOTH_RTK
interface.transmit_int_command = transmit_int_command;
#endif
interface.transmit_commandtransmit_command;
interface.transmit_command_futured = transmit_command_futured;
interface.transmit_downward = transmit_downward;
interface_created = true;
}
}

然后调用bt/hci/src/hci_layer.c中的transmit_command方法,


static void transmit_command(
BT_HDR *command,
command_complete_cb complete_callback,
command_status_cb status_callback,
void *context) {
waiting_command_t *wait_entry= osi_calloc(sizeof(waiting_command_t));
if (!wait_entry) {
LOG_ERROR("%s couldn't allocate space for wait entry.", __func__);
return;
}

uint8_t *stream = command->data + command->offset;
STREAM_TO_UINT16(wait_entry->opcode, stream);
wait_entry->complete_callback = complete_callback;
wait_entry->status_callback = status_callback;
wait_entry->command = command;
wait_entry->context = context;

// Store the command message type in the event field
// in case the upper layer didn't already
command->event = MSG_STACK_TO_HC_HCI_CMD;

fixed_queue_enqueue(command_queuewait_entry);
}
这里会把command封装成一个wait_entry再发送到一个command_queue队列里面,


command_queue队列又是在start_up里面初始化的,

static future_t *start_up(void) {
LOG_INFO("%s", __func__);
.........................
command_queue= fixed_queue_new(SIZE_MAX);
if (!command_queue) {
LOG_ERROR("%s unable to create pending command queue.", __func__);
goto error;
}

.........................................

然后这个队列又与一个线程相关联起来,并使用event_command_ready来处理事件,
fixed_queue_register_dequeue(command_queue, thread_get_reactor(thread), event_command_ready, NULL);

// Command/packettransmitting functions

static void event_command_ready(fixed_queue_t *queue, UNUSED_ATTR void *context) {
if (command_credits > 0) {
waiting_command_t *wait_entry = fixed_queue_dequeue(queue);
command_credits--;

// Move it to the list of commands awaiting response
pthread_mutex_lock(&commands_pending_response_lock);
list_append(commands_pending_response, wait_entry);
pthread_mutex_unlock(&commands_pending_response_lock);

// Send it off
low_power_manager->wake_assert();
#ifdef BLUETOOTH_RTK
if(bluetooth_rtk_h5_flag)
hci_h5->send(wait_entry->command);
else
packet_fragmenter->fragment_and_dispatch(wait_entry->command);
#else
packet_fragmenter->fragment_and_dispatch(wait_entry->command);// 调用packet_fragmenter.c里面的fragment_and_dispatch方法,
#endif
low_power_manager->transmit_done();

#ifdef BLUETOOTH_RTK
if(!bluetooth_rtk_h5_flag){
non_repeating_timer_restart_if(command_response_timer, !list_is_empty(commands_pending_response));
}
#else
non_repeating_timer_restart_if(command_response_timer, !list_is_empty(commands_pending_response));
#endif
}
}


packet_fragmenter这个变量的初始化也是在hci_layer.c中的hci_layer_get_interface初始化的,在发送过程中会回调之前在hci_layer.c中start_up()中packet_fragmenter->init(&packet_fragmenter_callbacks);注册的packet_fragmenter_callbacks这个结构体,这个结构体如下:

static const packet_fragmenter_callbacks_t packet_fragmenter_callbacks = {
transmit_fragment,
dispatch_reassembled,
#ifdef BLUETOOTH_RTK
fragmenter_transmit_finished,
filter_incoming_event
#else
fragmenter_transmit_finished
#endif
};

在文件packet_fragmenter.c中,
static void fragment_and_dispatch(BT_HDR *packet) {
assert(packet != NULL);

uint16_t event = packet->event & MSG_EVT_MASK;
uint8_t *stream = packet->data + packet->offset;

// We only fragment ACL packets
if (event != MSG_STACK_TO_HC_HCI_ACL) {
callbacks->fragmented(packet, true); // 调用hci_layer.c文件中的packet_fragmenter_callbacks 结构体中的transmit_fragment
return;
}

uint16_t max_data_size =
SUB_EVENT(packet->event) == LOCAL_BR_EDR_CONTROLLER_ID ?
controller->get_acl_data_size_classic() :
controller->get_acl_data_size_ble();

uint16_t max_packet_size = max_data_size + HCI_ACL_PREAMBLE_SIZE;
uint16_t remaining_length = packet->len;

uint16_t continuation_handle;
STREAM_TO_UINT16(continuation_handle, stream);
continuation_handle = APPLY_CONTINUATION_FLAG(continuation_handle);

while (remaining_length > max_packet_size) {
// Make sure we use the right ACL packet size
stream = packet->data + packet->offset;
STREAM_SKIP_UINT16(stream);
UINT16_TO_STREAM(stream, max_data_size);

packet->len = max_packet_size;
callbacks->fragmented(packet, false);// 调用hci_layer.c文件中的packet_fragmenter_callbacks 结构体中的transmit_fragment

packet->offset += max_data_size;
remaining_length -= max_data_size;
packet->len = remaining_length;

// Write the ACL header for the next fragment
stream = packet->data + packet->offset;
UINT16_TO_STREAM(stream, continuation_handle);
UINT16_TO_STREAM(stream, remaining_length - HCI_ACL_PREAMBLE_SIZE);

// Apparently L2CAP can set layer_specific to a max number of segments to transmit
if (packet->layer_specific) {
packet->layer_specific--;

if (packet->layer_specific == 0) {
packet->event = MSG_HC_TO_STACK_L2C_SEG_XMIT;
callbacks->transmit_finished(packet, false);// 调用hci_layer.c文件中的packet_fragmenter_callbacks 结构体中的fragmenter_transmit_finished
return;
}
}
}

callbacks->fragmented(packet, true);// 调用hci_layer.c文件中的packet_fragmenter_callbacks 结构体中的transmit_fragment
}



上面的commands_pending_response的这个列表是在start_up里面创建的,然后在发送指令的时候会把相关的指令加到这个列表里面再等待响应,

commands_pending_response= list_new(NULL);
if (!commands_pending_response) {
LOG_ERROR("%s unable to create list for commands pending response.", __func__);
goto error;
}


command_response_timer= non_repeating_timer_new(COMMAND_PENDING_TIMEOUT, command_timed_out, NULL);
if (!command_response_timer) {
LOG_ERROR("%s unable to create command response timer.", __func__);
goto error;
}


如果响应超时的话,会回调command_timed_out重启bluetooth这个进程,static const uint32_t COMMAND_PENDING_TIMEOUT = 8000;这里会等待8S的超时,就会把自己kill掉,

static void command_timed_out(UNUSED_ATTR void *context) {
pthread_mutex_lock(&commands_pending_response_lock);

if (list_is_empty(commands_pending_response)) {
LOG_ERROR("%s with no commands pending response", __func__);
} else {
waiting_command_t *wait_entry = list_front(commands_pending_response);
pthread_mutex_unlock(&commands_pending_response_lock);

// We shouldn't try to recover the stack from this command timeout.
// If it's caused by a software bug, fix it. If it's a hardware bug, fix it.
LOG_ERROR("%s hci layer timeout waiting for response to a command. opcode: 0x%x", __func__, wait_entry->opcode);
}

LOG_ERROR("%s restarting the bluetooth process.", __func__);
usleep(10000);
kill(getpid(), SIGKILL);
}


在hci_layer.c中的start_up方法里面,

thread= thread_new("hci_thread");
if (!thread) {
LOG_ERROR("%s unable to create thread.", __func__);
goto error;
}


hal->init(&hal_callbacksthread);// 这个方法是调用hci_hal_h4.c中的方法hal_init()

static const hci_hal_callbacks_t hal_callbacks= {
hal_says_data_ready
};


那么如上的方法就是把hal_callbacks (hci_hal_callbacks_t )的成员变量hal_says_data_ready 赋给data_ready,那么在有事件发生的时候就回调方法hal_says_data_ready

// See what data is waiting, and notify the upper layer
static void event_uart_has_bytes(eager_reader_t *reader, UNUSED_ATTR void *context) {
#ifdef BLUETOOTH_RTK
if(!bluetooth_rtk_h5_flag) {
#endif
if (stream_has_interpretation) {
callbacks->data_ready(current_data_type);
} else {
uint8_t type_byte;
if (eager_reader_read(reader, &type_byte, 1, true) == 0) {
LOG_ERROR("%s could not read HCI message type", __func__);
return;
}
if (type_byte < DATA_TYPE_ACL || type_byte > DATA_TYPE_EVENT) {
LOG_ERROR("%s Unknown HCI message type. Dropping this byte 0x%x, min %x, max %x", __func__, type_byte, DATA_TYPE_ACL, DATA_TYPE_EVENT);
return;
}

stream_has_interpretation = true;
current_data_type = type_byte;
}
#ifdef BLUETOOTH_RTK
} else {
stream_has_interpretation = true;
current_data_type = DATA_TYPE_H5;
callbacks->data_ready(current_data_type);
}
#endif
}


// Event/packet receiving functions

// This function is not required to read all of a packet in one go, so
// be wary of reentry. But this function must return after finishing a packet.
static void hal_says_data_ready(serial_data_type_t type) {
packet_receive_data_t *incoming = &incoming_packets[PACKET_TYPE_TO_INBOUND_INDEX(type)];

uint8_t byte;
#ifdef BLUETOOTH_RTK
if(bluetooth_rtk_h5_flag){
while(hal->read_data(type, &byte, 1, false) != 0) {
hci_h5->rcv(&byte);
}
} else {
#endif
while (hal->read_data(type, &byte, 1, false) != 0) {
switch (incoming->state) {
case BRAND_NEW:
// Initialize and prepare to jump to the preamble reading state
incoming->bytes_remaining = preamble_sizes[PACKET_TYPE_TO_INDEX(type)];
memset(incoming->preamble, 0, PREAMBLE_BUFFER_SIZE);
incoming->index = 0;
incoming->state = PREAMBLE;
// INTENTIONAL FALLTHROUGH
case PREAMBLE://报文头
incoming->preamble[incoming->index] = byte;
incoming->index++;
incoming->bytes_remaining--;

if (incoming->bytes_remaining == 0) {
// For event and sco preambles, the last byte we read is the length
incoming->bytes_remaining = (type == DATA_TYPE_ACL) ? RETRIEVE_ACL_LENGTH(incoming->preamble) : byte;

size_t buffer_size = BT_HDR_SIZE + incoming->index + incoming->bytes_remaining;
incoming->buffer = (BT_HDR *)buffer_allocator->alloc(buffer_size);

if (!incoming->buffer) {
LOG_ERROR("%s error getting buffer for incoming packet of type %d and size %zd", __func__, type, buffer_size);
// Can't read any more of this current packet, so jump out
incoming->state = incoming->bytes_remaining == 0 ? BRAND_NEW : IGNORE;
break;
}

// Initialize the buffer
incoming->buffer->offset = 0;
incoming->buffer->layer_specific = 0;
incoming->buffer->event = outbound_event_types[PACKET_TYPE_TO_INDEX(type)]; //这里会把HCI到来的event type存起来,可以看到事件的类型可以在报文头里面得到
memcpy(incoming->buffer->data, incoming->preamble, incoming->index);

incoming->state = incoming->bytes_remaining > 0 ? BODY : FINISHED;
}

break;
case BODY: //报文的内容
incoming->buffer->data[incoming->index] = byte;
incoming->index++;
incoming->bytes_remaining--;

size_t bytes_read = hal->read_data(type, (incoming->buffer->data + incoming->index), incoming->bytes_remaining, false);
incoming->index += bytes_read;
incoming->bytes_remaining -= bytes_read;

incoming->state = incoming->bytes_remaining == 0 ? FINISHED : incoming->state;
break;
case IGNORE:
incoming->bytes_remaining--;
if (incoming->bytes_remaining == 0) {
incoming->state = BRAND_NEW;
// Don't forget to let the hal know we finished the packet we were ignoring.
// Otherwise we'll get out of sync with hals that embed extra information
// in the uart stream (like H4). #badnewsbears
hal->packet_finished(type);
return;
}

break;
case FINISHED:
LOG_ERROR("%s the state machine should not have been left in the finished state.", __func__);
break;
}

if (incoming->state == FINISHED) {
incoming->buffer->len = incoming->index;
btsnoop->capture(incoming->buffer, true);//接受报文完成后会保存到BT SNOOP里面

if (type != DATA_TYPE_EVENT) {
packet_fragmenter->reassemble_and_dispatch(incoming->buffer); //如果改报文不是事件类型,就继续上传到上层
} else if (!filter_incoming_event(incoming->buffer)) {//如果报文是事件类型,也会上传
// Dispatch the event by event code
uint8_t *stream = incoming->buffer->data;
uint8_t event_code;
STREAM_TO_UINT8(event_code, stream);

data_dispatcher_dispatch(
interface.event_dispatcher,
event_code,
incoming->buffer
);//这个方法里面的interface.event_dispatcher是在bte_main.c中入口函数bte_main_boot_entry()里面的data_dispatcher_register_default(hci->event_dispatcher, btu_hci_msg_queue);初始化的,那么这里就会往btu_hci_msg_queue这个队列里面放相关的事件报文包
}

// We don't control the buffer anymore
incoming->buffer = NULL;
incoming->state = BRAND_NEW;
hal->packet_finished(type);

// We return after a packet is finished for two reasons:
// 1. The type of the next packet could be different.
// 2. We don't want to hog cpu time.
return;
}
}
#ifdef BLUETOOTH_RTK
}
#endif
}

调用packet_fragmenter.c里面的reassemble_and_dispatch方法,

static void reassemble_and_dispatch(UNUSED_ATTR BT_HDR *packet) {
if ((packet->event & MSG_EVT_MASK) == MSG_HC_TO_STACK_HCI_ACL) {//如果接受到报文消息是ACL类型
uint8_t *stream = packet->data;
uint16_t handle;
uint16_t l2cap_length;
uint16_t acl_length;

STREAM_TO_UINT16(handle, stream);
STREAM_TO_UINT16(acl_length, stream);
STREAM_TO_UINT16(l2cap_length, stream);

assert(acl_length == packet->len - HCI_ACL_PREAMBLE_SIZE);

uint8_t boundary_flag = GET_BOUNDARY_FLAG(handle);
handle = handle & HANDLE_MASK;

BT_HDR *partial_packet = (BT_HDR *)hash_map_get(partial_packets, (void *)(uintptr_t)handle);

if (boundary_flag == START_PACKET_BOUNDARY) {//如果是获取的报文的边界
if (partial_packet) {
LOG_WARN("%s found unfinished packet for handle with start packet. Dropping old.", __func__);

hash_map_erase(partial_packets, (void *)(uintptr_t)handle);
buffer_allocator->free(partial_packet);
}

uint16_t full_length = l2cap_length + L2CAP_HEADER_SIZE + HCI_ACL_PREAMBLE_SIZE;
if (full_length <= packet->len) {
if (full_length < packet->len)
LOG_WARN("%s found l2cap full length %d less than the hci length %d.", __func__, l2cap_length, packet->len);

callbacks->reassembled(packet);
return;
}

partial_packet = (BT_HDR *)buffer_allocator->alloc(full_length + sizeof(BT_HDR));
partial_packet->event = packet->event;
partial_packet->len = full_length;
partial_packet->offset = packet->len;

memcpy(partial_packet->data, packet->data, packet->len);

// Update the ACL data size to indicate the full expected length
stream = partial_packet->data;
STREAM_SKIP_UINT16(stream); // skip the handle
UINT16_TO_STREAM(stream, full_length - HCI_ACL_PREAMBLE_SIZE);

hash_map_set(partial_packets, (void *)(uintptr_t)handle, partial_packet);
// Free the old packet buffer, since we don't need it anymore
buffer_allocator->free(packet);
} else {
if (!partial_packet) {
LOG_WARN("%s got continuation for unknown packet. Dropping it.", __func__);
buffer_allocator->free(packet);
return;
}

packet->offset = HCI_ACL_PREAMBLE_SIZE;
uint16_t projected_offset = partial_packet->offset + (packet->len - HCI_ACL_PREAMBLE_SIZE);
if (projected_offset > partial_packet->len) { // len stores the expected length
LOG_WARN("%s got packet which would exceed expected length of %d. Truncating.", __func__, partial_packet->len);
packet->len = partial_packet->len - partial_packet->offset;
projected_offset = partial_packet->len;
}

memcpy(
partial_packet->data + partial_packet->offset,
packet->data + packet->offset,
packet->len - packet->offset
);

// Free the old packet buffer, since we don't need it anymore
buffer_allocator->free(packet);
partial_packet->offset = projected_offset;

if (partial_packet->offset == partial_packet->len) {
hash_map_erase(partial_packets, (void *)(uintptr_t)handle);
partial_packet->offset = 0;
callbacks->reassembled(partial_packet);//组装报文,调用hci_layer.c中的dispatch_reassembled()
}
}
} else {
callbacks->reassembled(packet);//组装报文,调用hci_layer.c中的dispatch_reassembled()
}
}


在文件hci_layer.c中的dispatch_reassembled()方法
// Callbackfor the fragmenter to dispatch up a completely reassembled packet
static void dispatch_reassembled(BT_HDR *packet) {
// Events should already have been dispatched before this point
#ifdef BLUETOOTH_RTK
if(!bluetooth_rtk_h5_flag)
assert((packet->event & MSG_EVT_MASK) != MSG_HC_TO_STACK_HCI_EVT);
#else
assert((packet->event & MSG_EVT_MASK) != MSG_HC_TO_STACK_HCI_EVT);//判断改报文的事件类型是否是MSG_HC_TO_STACK_HCI_EVT,在这里应该是MSG_HC_TO_STACK_HCI_EVT事件类型
#endif
assert(upwards_data_queue != NULL);
#ifdef BLUETOOTH_RTK_COEX
if(!bluetooth_rtk_h5_flag) {
if ((packet->event& MSG_EVT_MASK) == MSG_HC_TO_STACK_HCI_ACL) {
uint8_t *pp = ((uint8_t *)(packet + 1)) + packet->offset;
rtk_parse_manager->rtk_parse_l2cap_data(pp,0);
}
}
#endif
/*BOARD_HAVE_BLUETOOTH_RTK_COEX end*/

if (upwards_data_queue) {
fixed_queue_enqueue(upwards_data_queue, packet);
} else {
LOG_ERROR("%s had no queue to place upwards data packet in. Dropping it on the floor.", __func__);
buffer_allocator->free(packet);
}
}

会把整个报文放到upwards_data_queue这个队列里面,
这个队列的定义如下:
// The hand-off point for data going to a higher layer, set by the higher layer
static fixed_queue_t *upwards_data_queue;

如上的注释,可以看出这个队列会被上层设定并使用,
它的初始化是在文件bt/main/bte_main.c中的bte_main_boot_entry方法,
******************************************************************************/
void bte_main_boot_entry(void)
{
module_init(get_module(GKI_MODULE));
module_init(get_module(COUNTER_MODULE));

hci = hci_layer_get_interface();
if (!hci)
LOG_ERROR("%s could not get hci layer interface.", __func__);

btu_hci_msg_queue= fixed_queue_new(SIZE_MAX);
if (btu_hci_msg_queue == NULL) {
LOG_ERROR("%s unable to allocate hci message queue.", __func__);
return;
}

data_dispatcher_register_default(hci->event_dispatcher, btu_hci_msg_queue);
hci->set_data_queue(btu_hci_msg_queue);

...................
}

如上的hci的接口就是hci_layer.c文件中hci_layer_get_interface()这个方法返回的,
然后在这个接口的初始化的时候会指定set_data_queue这个函数指针的成员变量,
我们可以到hci_t这个结构体中的这个函数指针的成员变量定义,
// Set the queue to receive ACL data in
void (*set_data_queue)(fixed_queue_t *queue);


static void init_layer_interface() {
if (!interface_created) {
interface.send_low_power_command = low_power_manager->post_command;
interface.do_postload = do_postload;

// It's probably ok for this to live forever. It's small and
// there's only one instance of the hci interface.
interface.event_dispatcher = data_dispatcher_new("hci_layer");
if (!interface.event_dispatcher) {
LOG_ERROR("%s could not create upward dispatcher.", __func__);
return;
}

interface.set_data_queue = set_data_queue;
#ifdef BLUETOOTH_RTK
interface.transmit_int_command = transmit_int_command;
#endif
interface.transmit_command = transmit_command;
interface.transmit_command_futured = transmit_command_futured;
interface.transmit_downward = transmit_downward;
interface_created = true;
}
}

所以如上的hci->set_data_queue(btu_hci_msg_queue);之后,那就是upwards_data_queue所指向的队列就是btu_hci_msg_queue ,那就是接受HCI的消息后通过组装分发到这队列里面来,

那么收到ACL DATA后,接下来会进一步的处理





=======================================================

以另外一个BT_EVT_TO_BTU_HCI_EVT事件为例子

case BT_EVT_TO_BTU_HCI_EVT:
btu_hcif_process_event((UINT8)(p_msg->event & BT_SUB_EVT_MASK), p_msg);
GKI_freebuf(p_msg);


在文件bt/stack/btu/btu_hcif.c中,

void btu_hcif_process_event (UNUSED_ATTR UINT8 controller_id, BT_HDR *p_msg)
{
UINT8   *p = (UINT8 *)(p_msg + 1) + p_msg->offset;
UINT8   hci_evt_code, hci_evt_len;
#if BLE_INCLUDED == TRUE
UINT8   ble_sub_code;
#endif
STREAM_TO_UINT8  (hci_evt_code, p);
STREAM_TO_UINT8  (hci_evt_len, p);

switch (hci_evt_code)
{
case HCI_INQUIRY_COMP_EVT:
btu_hcif_inquiry_comp_evt (p);
break;
case HCI_INQUIRY_RESULT_EVT:
btu_hcif_inquiry_result_evt (p);
break;


.............................................

#if (BLE_LLT_INCLUDED == TRUE)
case HCI_BLE_RC_PARAM_REQ_EVT:
btu_ble_rc_param_req_evt(p);
break;
#endif
case HCI_BLE_DATA_LENGTH_CHANGE_EVT:
btu_ble_data_length_change_evt(p, hci_evt_len);
break;
}
break;
#endif /* BLE_INCLUDED */
case HCI_VENDOR_SPECIFIC_EVT:
btm_vendor_specific_evt (p, hci_evt_len);
#ifdef BLUETOOTH_RTK_API
rtkbt_api_Hook(RTKBT_HOOK_RECEIVE_EVENT,(void *)p_msg,hci_evt_len);
#endif
break;
}
}






























static void btu_hcif_command_status_evt(uint8_t status, BT_HDR *command, void *context)
{
BT_HDR *event = osi_calloc(sizeof(BT_HDR) + sizeof(command_status_hack_t));
command_status_hack_t *hack = (command_status_hack_t *)&event->data[0];

hack->callback = btu_hcif_command_status_evt_on_task;
hack->status = status;
hack->command = command;
hack->context = context;

event->event = BTU_POST_TO_TASK_NO_GOOD_HORRIBLE_HACK;

fixed_queue_enqueue(btu_hci_msg_queue, event);
}

Android BT STACK BTU 和 HCI之间的消息传递相关推荐

  1. android bluetooth stack-scan

    AdapterService.java 上层一点搜索的button就开始走到底层so的JNI调用 start_discovery btif_dm_start_discoveryBTA_DmBleSca ...

  2. Android应用程序与SurfaceFlinger服务之间的共享UI元数据(SharedClient)的创建过程分析...

    在前面一篇文章中,我们分析了Android应用程序与SurfaceFlinger服务的连接过程.Android应用程序成功连接上SurfaceFlinger服务之后,还需要一块匿名共享内存来和Surf ...

  3. android jni 将BYTE* 和 jbyteArray 之间的转换

     今天,简单讲讲如何在jni中将  BYTE* 转成 jbyteArray. 这个是我在做jni时碰到的问题.因为c传回的值是BYTE*,而返回给java代码是byte[],对应的jni的数据 ...

  4. Android JSON数据与实体类之间的相互转化-------GSON的简单用法

    Android JSON数据与实体类之间的相互转化-------GSON的用法 1_Gson的导入 1.1_方法一:直接导入jar包 1.2_方法二:引入依赖 2_json形式的字符串互转实体对象 2 ...

  5. 开发一个基于Dalvik字节码的相似性检测引擎,比较同一款Android应用程序的不同版本之间的代码差异(二)

    上文我们说过,<针对Dalvik字节码的相似性检测引擎,比较同一款Android应用程序的不同版本之间的代码差异>这篇文章计划分两个部分来讲解,上文只介绍了如何利用Quarkslab公司开 ...

  6. 自架 Android BT / NAS 機:超靜音超省錢超低功耗

    [转载:自架 Android BT / NAS 機:超靜音超省錢超低功耗,原文地址:http://www.metamuse.net/2012/11/android-bt-nas.html] 其實我根本 ...

  7. android布局距边距,Android初学者填充和边距之间的区别

    Android初学者填充和边距之间的区别 这个问题已经在这里有了答案: 视图的填充和边距之间的区别 14个答案 我已经提到了有关SO的问题. 还检查了答案: 填充是边框内部,边框和实际视图内容之间的空 ...

  8. Activity、Service、子线程之间的消息传递轻松实现

    引子 以前工作中实现界面之间消息传递.service与activity之间的消息传递需要broadcastReceiver来实现不经设计麻烦,而且代码冗余.后来通过查看代码时发现了一个挺不错的方法来实 ...

  9. 开发FireFox浏览器扩展(Extension)并实现与原生应用之间的消息传递

    一.什么是插件(Plug-in),什么是扩展(Extension). 插件指的是在页面HTML源代码里通过<object> 或者 <embed> 标签声明的部分,工作在内核层面 ...

  10. 用USB代替网络通讯,实现Cartographer上位机与下位机之间的消息传递

    任务动机:用USB代替网络通讯,实现Cartographer上位机与下位机之间的消息传递. 任务描述:根据任务动机,研发实现用USB代替网络通讯,形成文档. 1. 在Toybrick-RK3399 P ...

最新文章

  1. C++:随笔5---this指针和类的继承
  2. docker Cannot start container [8] System error: exec format error
  3. Custom Url Helper for Zend View
  4. [Unity] 3D数学基础 - 坐标系、向量、矩阵
  5. 救援模式下解决boot.local修改后无法登陆系统
  6. SAP Cloud Application Programming bookshop 例子 Vue页面不能正常显示的原因分析
  7. C两个小例子(数组与指针)
  8. java怎么判断mysql中是否存在我们查找的索引_10张图告诉你,MySQL 是如何查找数据的?...
  9. onu光功率多少是正常_ONU、机顶盒、路由器常见网络问题及处理方法
  10. 一个SpringBoot项目,开发业务前至少应该引入哪些配置?
  11. mysql 调用存储过程 inout_MySQL存储过程in、out和inout参数示例和总结
  12. python输出excel能够识别的utf-8格式csv文件
  13. 【软件】HP惠普打印机能打印不能用扫描软件解决办法
  14. Win10系统 禁止某个程序\软件联网
  15. linux 机房安全管理,提示尊敬的用户您好:您访问的网站被机房安全管理系统拦截怎么办?...
  16. 安卓桌面软件_iOS便签软件求推荐,有可以在iOS系统上使用的桌面便签软件吗 - 学显...
  17. python image.open 参数作用,python基础(python Image Library)
  18. unit自动驾驶怎么使用_自动驾驶与驾驶辅助系统 正确使用驾驶辅助系统
  19. IDEA设置护眼背景及字体大小
  20. canvas实现3D魔方

热门文章

  1. 宝峰c1对讲机写频软件_宝峰写频软件-宝峰对讲机写频软件 附USB线驱动 7.01 官方版 - 河东下载站...
  2. sou.php,phpsou RiSearchPHP是一个高效 联合开发网 - pudn.com
  3. 职业经理人十大修炼指南 [完全版]
  4. linux查看数据库实例名端口号,查看数据库tns配置
  5. 晶体管放大电路与Multisim仿真学习笔记
  6. bat计算机清理原理,电脑清理系统垃圾bat的操作步骤
  7. 哈尔滨理工大学计算机学院竞赛,计算机学院成功举办学院Arduino创意设计竞赛...
  8. 打印机不弹出打印窗口_打印CAD图纸总是留白?做好这个操作,能打印出你想要的CAD图纸...
  9. WM8960的音量控制测试程序
  10. 手机经纬度在线转换工具链接