在蓝牙使能后enable 过程中  调用 hal_open函数(system\bt\hci\src\hci_hal_mct.c)

  event_stream = hci_reader_new(uart_fds[CH_EVT], HCI_HAL_SERIAL_BUFFER_SIZE, SIZE_MAX,thread, event_event_stream_has_bytes);if (!event_stream) {LOG_ERROR("%s unable to create hci reader for the event uart serial port.", __func__);goto error;}acl_stream = hci_reader_new(uart_fds[CH_ACL_IN], HCI_HAL_SERIAL_BUFFER_SIZE, SIZE_MAX,thread, event_acl_stream_has_bytes);if (!acl_stream) {LOG_ERROR("%s unable to create hci reader for the acl-in uart serial port.", __func__);goto error;}

当SCO链路层有数据event_event_stream_has_bytes函数会被执行:

static void event_event_stream_has_bytes(void *context) {int bytes_read;hci_reader_t *reader = (hci_reader_t *) context;bytes_read = read(reader->inbound_fd, reader->data_buffer+reader->wr_ptr,reader->buffer_size - reader->wr_ptr);if (bytes_read <= 0) {LOG_ERROR("%s could not read HCI message type", __func__);return;}reader->wr_ptr += bytes_read;callbacks->data_ready(DATA_TYPE_EVENT);
}

当ACL链路层有数据 event_acl_stream_has_bytes函数会被调用;

static void event_acl_stream_has_bytes(void *context) {// No real concept of incoming SCO typed data, just ACLint bytes_read;hci_reader_t *reader = (hci_reader_t *) context;bytes_read = read(reader->inbound_fd, reader->data_buffer+reader->wr_ptr,reader->buffer_size - reader->wr_ptr);if (bytes_read <= 0) {LOG_ERROR("%s could not read HCI message type", __func__);return;}reader->wr_ptr += bytes_read;callbacks->data_ready(DATA_TYPE_ACL);
}
static bool hal_init(const hci_hal_callbacks_t *upper_callbacks, thread_t *upper_thread) {assert(upper_callbacks != NULL);assert(upper_thread != NULL);
/*  hal->init(&hal_callbacks, thread);callbacks = hal_callbacks = hal_says_data_ready*/callbacks = upper_callbacks;   // callbacks 等于  hal_says_data_ready/*upper_thread 为 hci_layer.c  调用start_up函数创建   thread= thread_new("hci_thread");  hal->init(&hal_callbacks, thread);*/thread = upper_thread; return true;
}

callbacks回调在hal_init的时候已经初始化,    callbacks->data_ready 函数对应hal_says_data_ready函数;

hal_says_data_ready函数定义在 system\bt\hci\src\hci_layer.c文件中

// 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 reset;uint8_t byte;while (hal->read_data(type, &byte, 1) != 0) {if (soc_type == BT_SOC_SMD) {reset = hal->dev_in_reset();if (reset) {incoming = &incoming_packets[PACKET_TYPE_TO_INBOUND_INDEX(type = DATA_TYPE_EVENT)];if(!create_hw_reset_evt_packet(incoming))break;else {//Reset SOC status to trigger hciattach serviceif(property_set("bluetooth.status", "off") < 0) {LOG_ERROR(LOG_TAG, "SSR: Error resetting SOC status\n ");} else {ALOGE("SSR: SOC Status is reset\n ");}}}}switch (incoming->state) {case BRAND_NEW:// Initialize and prepare to jump to the preamble reading stateincoming->bytes_remaining = preamble_sizes[PACKET_TYPE_TO_INDEX(type)];memset(incoming->preamble, 0, PREAMBLE_BUFFER_SIZE);incoming->index = 0;incoming->state = PREAMBLE;// INTENTIONAL FALLTHROUGHcase 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 lengthincoming->bytes_remaining = (type == DATA_TYPE_ACL) ? RETRIEVE_ACL_LENGTH(incoming->preamble) : byte;size_t buffer_size = BT_HDR_SIZE + incoming->index + incoming->bytes_remaining;if (buffer_size > MCA_USER_RX_BUF_SIZE) {LOG_ERROR(LOG_TAG, "%s buffer_size(%zu) exceeded allowed packet size, allocation not possible", __func__, buffer_size);incoming = &incoming_packets[PACKET_TYPE_TO_INBOUND_INDEX(type = DATA_TYPE_EVENT)];if(create_hw_reset_evt_packet(incoming))break;elsereturn;}incoming->buffer = (BT_HDR *)buffer_allocator->alloc(buffer_size);if (!incoming->buffer) {LOG_ERROR(LOG_TAG, "%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 outincoming->state = incoming->bytes_remaining == 0 ? BRAND_NEW : IGNORE;break;}// Initialize the bufferincoming->buffer->offset = 0;incoming->buffer->layer_specific = 0;incoming->buffer->event = outbound_event_types[PACKET_TYPE_TO_INDEX(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);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). #badnewsbearshal->packet_finished(type);return;}break;case FINISHED:LOG_ERROR(LOG_TAG, "%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);if (type != DATA_TYPE_EVENT) {if(hci_state == HCI_READY) {packet_fragmenter->reassemble_and_dispatch(incoming->buffer);} else {LOG_WARN("%s, Ignoring the ACL pkt received", __func__);buffer_allocator->free(incoming->buffer);}} else if (!filter_incoming_event(incoming->buffer)) {if (hci_state == HCI_READY) {// Dispatch the event by event codeuint8_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);} else {LOG_WARN("%s, Ignoring the event pkt received", __func__);buffer_allocator->free(incoming->buffer);}}// We don't control the buffer anymoreincoming->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;}}
}

hal->read_data(type, &byte, 1) ;  对应hci_hal_mct.c文件的read_data函数

static size_t read_data(serial_data_type_t type, uint8_t *buffer, size_t max_size) {
#if (defined(REMOVE_EAGER_THREADS) && (REMOVE_EAGER_THREADS == TRUE))if (type == DATA_TYPE_ACL) {return hci_reader_read(acl_stream, buffer, max_size);} else if (type == DATA_TYPE_EVENT) {return hci_reader_read(event_stream, buffer, max_size);}
#elseif (type == DATA_TYPE_ACL) {return eager_reader_read(acl_stream, buffer, max_size);} else if (type == DATA_TYPE_EVENT) {return eager_reader_read(event_stream, buffer, max_size);}
#endifLOG_ERROR(LOG_TAG, "%s invalid data type: %d", __func__, type);return 0;
}
size_t hci_reader_read(hci_reader_t *reader, uint8_t *buffer, size_t req_size) {int bytes_read = 0;assert(reader != NULL);assert(buffer != NULL);// If the caller wants nonblocking behavior, poll to see if we have// any bytes available before reading.if (reader->rd_ptr < reader->wr_ptr) {bytes_read = reader->wr_ptr - reader->rd_ptr;if ((size_t) bytes_read > req_size)bytes_read = req_size;memcpy(buffer, reader->data_buffer+reader->rd_ptr, bytes_read);reader->rd_ptr += bytes_read;} else {bytes_read = read(reader->inbound_fd, buffer, req_size);if(bytes_read == -1)bytes_read = 0;}return bytes_read;
}

hal_says_data_ready函数中,处理读到的数据 存入incoming->buffer , 调用函数reassemble_and_dispatch进行数据组装;

typedef struct {receive_state_t state;uint16_t bytes_remaining;uint8_t preamble[PREAMBLE_BUFFER_SIZE];uint16_t index;BT_HDR *buffer;
} packet_receive_data_t;packet_receive_data_t *incoming = &incoming_packets[PACKET_TYPE_TO_INBOUND_INDEX(type)];

incoming->buffer 对应的结构体为BT_HDR

packet_fragmenter->reassemble_and_dispatch(incoming->buffer);


static void reassemble_and_dispatch(UNUSED_ATTR BT_HDR *packet) {/*判断packet->event事件类型 如果是MSG_HC_TO_STACK_HCI_ACL执行以下, 如果不是执行callbacks->reassembled(packet);*/if ((packet->event & MSG_EVT_MASK) == MSG_HC_TO_STACK_HCI_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(LOG_TAG, "%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);}if (acl_length < L2CAP_HEADER_SIZE) {LOG_WARN(LOG_TAG, "%s L2CAP packet too small (%d < %d). Dropping it.", __func__, packet->len, L2CAP_HEADER_SIZE);buffer_allocator->free(packet);return;}uint16_t full_length = l2cap_length + L2CAP_HEADER_SIZE + HCI_ACL_PREAMBLE_SIZE;// Check for buffer overflow and that the full packet size + BT_HDR size is less than// the max buffer sizeif (check_uint16_overflow(l2cap_length, (L2CAP_HEADER_SIZE + HCI_ACL_PREAMBLE_SIZE)) ||((full_length + sizeof(BT_HDR)) > BT_DEFAULT_BUFFER_SIZE)) {LOG_ERROR(LOG_TAG, "%s L2CAP packet has invalid length (%d). Dropping it.", __func__, l2cap_length);buffer_allocator->free(packet);return;}if (full_length <= packet->len) {if (full_length < packet->len)LOG_WARN(LOG_TAG, "%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 lengthstream = partial_packet->data;STREAM_SKIP_UINT16(stream); // skip the handleUINT16_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 anymorebuffer_allocator->free(packet);} else {if (!partial_packet) {LOG_WARN(LOG_TAG, "%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 lengthLOG_WARN(LOG_TAG, "%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 anymorebuffer_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);}}} else {callbacks->reassembled(packet);}
}

函数中的callbacks在init的时候赋值为 packet_fragmenter_callbacks


static const packet_fragmenter_callbacks_t packet_fragmenter_callbacks = {transmit_fragment,dispatch_reassembled,fragmenter_transmit_finished
};

dispatch_reassembled函数中通过发送消息给upwards_data_queue队列处理,

// Callback for the fragmenter to dispatch up a completely reassembled packet
static void dispatch_reassembled(BT_HDR *packet) {// Events should already have been dispatched before this pointassert((packet->event & MSG_EVT_MASK) != MSG_HC_TO_STACK_HCI_EVT);assert(upwards_data_queue != NULL);if (upwards_data_queue) {fixed_queue_enqueue(upwards_data_queue, packet);} else {LOG_ERROR(LOG_TAG, "%s had no queue to place upwards data packet in. Dropping it on the floor.", __func__);buffer_allocator->free(packet);}
}
static void set_data_queue(fixed_queue_t *queue) {upwards_data_queue = queue;
}

upwards_data_queue  在函数 set_data_queue 进行赋值  
      set_data_queue 函数在bte_main_boot_entry被调用 upwards_data_queue 赋值为

btu_hci_msg_queue。 btu_hci_msg_queue为初期HCI发送回来的消息队列,所有消息在btu_hci_msg_ready函数中处理

btu_hci_msg_ready定义如下:

system\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);
#if (defined(HCILP_INCLUDED) && HCILP_INCLUDED == TRUE)/* If the host receives events which it doesn't responsd to, *//* it should start an idle timer to enter sleep mode.        */btu_check_bt_sleep ();
#endifbreak;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 == TRUEbtm_route_sco_data (p_msg);break;
#endifcase BT_EVT_TO_BTU_HCI_EVT:btu_hcif_process_event ((UINT8)(p_msg->event & BT_SUB_EVT_MASK), p_msg);osi_free(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 ();
#endifbreak;case BT_EVT_TO_BTU_HCI_CMD:btu_hcif_send_cmd ((UINT8)(p_msg->event & BT_SUB_EVT_MASK), p_msg);break;default:osi_free(p_msg);break;}
}

控制器数据数据到btu_hci_msg_process调用流程相关推荐

  1. 使用jQuery.Ajax向ASP.NET MVC控制器Post数据

    jQuery自带了Ajax的函数,你可以使用它从远程服务器下载网页,但问题是,大部分Ajax都是通过GET这种方式与远程服务器交互的. 但如果你想通过Ajax向远程服务器传递数据呢?当然jQuery. ...

  2. ASP.NET MVC 5 学习教程:控制器传递数据给视图

    起飞网 ASP.NET MVC 5 学习教程目录: 添加控制器 添加视图 修改视图和布局页 控制器传递数据给视图 添加模型 创建连接字符串 通过控制器访问模型的数据 生成的代码详解 使用 SQL Se ...

  3. Mr.Xiong使用jQuery从控制器获取数据

    使用jQuery实现从控制器获取数据 之前我们写了简单的get提交和post提交,之后又写了post通过XMLHTTPRequest对象提交表单,这次我们就从控制器获取数据,把数据获取到表单上,先把之 ...

  4. html页面信息属于结构化数据,网页结构化数据的信息提取方法与流程

    本发明属于网络信息处理领域,尤其涉及一种网页结构化数据的信息提取方法. 背景技术: 互联网的迅速发展带来了信息的爆炸式增长,Web己经发展为一个巨大的信息仓库,成为日益重要和最具潜力的全球信息传递与共 ...

  5. 数据科学项目的完整流程介绍

    和那些数据科学比赛不同,在真实的数据科学中,我们可能更多的时间不是在做算法的开发,而是对需求的定义和数据的治理.所以,如何更好的结合现实业务,让数据真正产生价值成了 个更有意义的话题. 数据科学项目的 ...

  6. 百亿数据分库分表核心流程详解

    前言 俗话说:面试造火箭,入职拧螺丝.尽管99.99%的业务都不需要用到分库分表,但是分库分表还是频繁出现在大厂的面试中. 分库分表涉及到的内容非常多,有很多细节,如果在面试中被问到了,既是挑战,也是 ...

  7. MPB:亚热带生态所谭支良组-基于微生物成分数据的差异zOTU分析流程

    为进一步提高<微生物组实验手册>稿件质量,本项目新增大众评审环节.文章在通过同行评审后,采用公众号推送方式分享全文,任何人均可在线提交修改意见.公众号格式显示略有问题,建议电脑端点击文末阅 ...

  8. 效率最高的Excel数据导入---(c#调用SSIS Package将数据库数据导入到Excel文件中【附源代码下载】)...

     本文目录: (一)背景 (二)数据库数据导入到Excel的方法比较    (三)SSIS的简介    (四)数据库中存储过程示例(SSIS应用需要) (五)Excel模板的制作(这步这么简单,稍微介 ...

  9. 视图中获取控制器中数据的方式

    在视图中获取控制器中数据的方式有两种: 一种是在控制器的操作中渲染视图时候分配模板数据,这种方式叫推送. 另外一种是在视图中手动获取控制器中的数据,包括控制器中的属性和方法及控制器id,通过$this ...

最新文章

  1. java mp3播放器 ×××面
  2. 给一个金额字符串插入逗号分隔 保留两位有效数字
  3. 实现工控机4U断电后自动重启功能
  4. mac电脑如何与手机同步复制粘贴_苹果换安卓手机如何同步手机自带备忘录便签?...
  5. C++字符串和数字转换完全攻略
  6. matplotlib的colorbar设置显示的刻度个数和指定的刻度值
  7. Maven依赖排除 禁止依赖传递 取消依赖的方法
  8. microstation添加txt文件_C开发实战-文件操作
  9. 修改tomcat的conf/server.xml解决网页乱码
  10. windows server上存储提示“由于管理员设置的策略,该磁盘处于脱机状态”
  11. Atitit.分布式远程调用  rpc  rmi  CORBA的关系
  12. 《Renewable Energy》论文格式
  13. 记录破解某网站 php代码 加密
  14. 瑞利商(Rayleigh Quotient)及瑞利定理(Rayleigh-Ritz theorem)的证明
  15. 深入理解计算机系统_3e 第四章家庭作业(部分) CS:APP3e chapter 4 homework
  16. 你还没有变成真正的孙悟空托世
  17. 一种新兴计数方式-视觉计数
  18. 基于GPS的公交车站点播报调试第四天
  19. React Native开发之——Webstorm开发RN配置
  20. windows php client,Installation and using elasticsearch php client on Windows Xampp

热门文章

  1. 4G/5G多卡聚合设备在公安无线传输中的解决方案
  2. 程序设计【Week8】作业
  3. 被这5个资源网站惊到了!老司机秒懂!
  4. Java Script如何实现创建一个按钮
  5. Win10中Pro/E鼠标滚轮不能缩放该怎么办?
  6. APS选型时需要考虑哪些因素?
  7. CSS参考手册自用版(新增flex布局)
  8. 黑客攻防从入门到精通-手机安全篇
  9. CREO1——CREO 2.0画沉头孔
  10. threeJS对光有反应的材质