HAL详解

一、直通式HAL

这里使用一个案例来介绍直通式HAL,选择MTK的NFC HIDL 1.0为例,因为比较简单,代码量也比较小,其源码路径:vendor/hardware/interfaces/nfc/1.0/

1、NFC HAL的定义

1)NFC HAL数据类型

通常定义在types.hal里面,其语法和java/c/c++可能不一致,详细参考https://source.android.com/docs/core/architecture/hidl/types?hl=zh-cn

2)NFC HAL回调接口

HAL的回调接口,即通常被定义为IXXXCallback

INfcClientCallback从命名可以知道给客户端的回调接口,即给客户端进程或者framework层提供的回调接口,即hal可以通过该接口向对方回调数据

3)NFC HAL接口定义

HAL的正式接口,同前面的回调接口刚好相反,即

HAL接口:客户端/Framework ------->  HAL进程(HAL进程是被调用者)

CALL接口:HAL进程  ------>客户端/Framework (HAL进程主动发起)

2、NFC HAL的逻辑

NFC HAL 1.0的版本是一个典型的直通式,其源码就nfc.cpp,逻辑相对比较简单

//vendor/hardware/interfaces/nfc/1.0/default/Nfc.h
#ifndef ANDROID_HARDWARE_NFC_V1_0_NFC_H
#define ANDROID_HARDWARE_NFC_V1_0_NFC_H#include <android/hardware/nfc/1.0/INfc.h>
#include <hidl/Status.h>
#include <hardware/hardware.h>
#include <hardware/nfc.h>
namespace android {
namespace hardware {
namespace nfc {
namespace V1_0 {
namespace implementation {using ::android::hardware::nfc::V1_0::INfc;
using ::android::hardware::nfc::V1_0::INfcClientCallback;
using ::android::hardware::Return;
using ::android::hardware::Void;
using ::android::hardware::hidl_vec;
using ::android::hardware::hidl_string;
using ::android::sp;struct Nfc : public INfc, public hidl_death_recipient {Nfc(nfc_nci_device_t* device);::android::hardware::Return<NfcStatus> open(const sp<INfcClientCallback>& clientCallback) override;::android::hardware::Return<uint32_t> write(const hidl_vec<uint8_t>& data) override;::android::hardware::Return<NfcStatus> coreInitialized(const hidl_vec<uint8_t>& data) override;::android::hardware::Return<NfcStatus> prediscover() override;::android::hardware::Return<NfcStatus> close() override;::android::hardware::Return<NfcStatus> controlGranted() override;::android::hardware::Return<NfcStatus> powerCycle() override;static void eventCallback(uint8_t event, uint8_t status) {if (mCallback != nullptr) {auto ret = mCallback->sendEvent((::android::hardware::nfc::V1_0::NfcEvent)event,(::android::hardware::nfc::V1_0::NfcStatus)status);if (!ret.isOk()) {ALOGW("Failed to call back into NFC process.");}}}static void dataCallback(uint16_t data_len, uint8_t* p_data) {hidl_vec<uint8_t> data;data.setToExternal(p_data, data_len);if (mCallback != nullptr) {auto ret = mCallback->sendData(data);if (!ret.isOk()) {ALOGW("Failed to call back into NFC process.");}}}virtual void serviceDied(uint64_t /*cookie*/,const wp<::android::hidl::base::V1_0::IBase>& /*who*/) {close();}private:static sp<INfcClientCallback> mCallback;const nfc_nci_device_t*       mDevice;
};extern "C" INfc* HIDL_FETCH_INfc(const char* name);}  // namespace implementation
}  // namespace V1_0
}  // namespace nfc
}  // namespace hardware
}  // namespace android#endif  // ANDROID_HARDWARE_NFC_V1_0_NFC_H//vendor/hardware/interfaces/nfc/1.0/default/Nfc.cpp
#define LOG_TAG "android.hardware.nfc@1.0-impl"#include <log/log.h>#include <hardware/hardware.h>
#include <hardware/nfc.h>
#include "Nfc.h"namespace android {
namespace hardware {
namespace nfc {
namespace V1_0 {
namespace implementation {sp<INfcClientCallback> Nfc::mCallback = nullptr;Nfc::Nfc(nfc_nci_device_t* device) : mDevice(device) {}// Methods from ::android::hardware::nfc::V1_0::INfc follow.
::android::hardware::Return<NfcStatus> Nfc::open(const sp<INfcClientCallback>& clientCallback)  {mCallback = clientCallback;if (mDevice == nullptr || mCallback == nullptr) {return NfcStatus::FAILED;}mCallback->linkToDeath(this, 0 /*cookie*/);int ret = mDevice->open(mDevice, eventCallback, dataCallback);return ret == 0 ? NfcStatus::OK : NfcStatus::FAILED;
}::android::hardware::Return<uint32_t> Nfc::write(const hidl_vec<uint8_t>& data)  {if (mDevice == nullptr) {return -1;}return mDevice->write(mDevice, data.size(), &data[0]);
}::android::hardware::Return<NfcStatus> Nfc::coreInitialized(const hidl_vec<uint8_t>& data)  {hidl_vec<uint8_t> copy = data;if (mDevice == nullptr || copy.size() == 0) {return NfcStatus::FAILED;}int ret = mDevice->core_initialized(mDevice, &copy[0]);return ret == 0 ? NfcStatus::OK : NfcStatus::FAILED;
}::android::hardware::Return<NfcStatus> Nfc::prediscover()  {if (mDevice == nullptr) {return NfcStatus::FAILED;}return mDevice->pre_discover(mDevice) ? NfcStatus::FAILED : NfcStatus::OK;
}::android::hardware::Return<NfcStatus> Nfc::close()  {if (mDevice == nullptr || mCallback == nullptr) {return NfcStatus::FAILED;}mCallback->unlinkToDeath(this);return mDevice->close(mDevice) ? NfcStatus::FAILED : NfcStatus::OK;
}::android::hardware::Return<NfcStatus> Nfc::controlGranted()  {if (mDevice == nullptr) {return NfcStatus::FAILED;}return mDevice->control_granted(mDevice) ? NfcStatus::FAILED : NfcStatus::OK;
}::android::hardware::Return<NfcStatus> Nfc::powerCycle()  {if (mDevice == nullptr) {return NfcStatus::FAILED;}return mDevice->power_cycle(mDevice) ? NfcStatus::FAILED : NfcStatus::OK;
}INfc* HIDL_FETCH_INfc(const char * /*name*/) {nfc_nci_device_t* nfc_device;int ret = 0;const hw_module_t* hw_module = nullptr;ret = hw_get_module (NFC_NCI_HARDWARE_MODULE_ID, &hw_module);if (ret == 0) {ret = nfc_nci_open (hw_module, &nfc_device);if (ret != 0) {ALOGE ("nfc_nci_open failed: %d", ret);}}elseALOGE ("hw_get_module %s failed: %d", NFC_NCI_HARDWARE_MODULE_ID, ret);if (ret == 0) {return new Nfc(nfc_device);} else {ALOGE("Passthrough failed to load legacy HAL.");return nullptr;}
}} // namespace implementation
}  // namespace V1_0
}  // namespace nfc
}  // namespace hardware
}  // namespace android

1)如何集成了驱动?

首先在nfc.h定义了很关键的成员变量mDevice,熟悉C/C++代码的从命名来看应该是一个驱动关联的句柄:

 const nfc_nci_device_t*       mDevice;

在nfc.cpp代码中可以很明显的看到通过linux和hal的机制去打开nfc驱动设备节点:

因此有理由相信这里的mDevice其实就是nfc驱动设备节点的一个句柄,所以解析来的代码逻辑其实就是对nfc驱动设备节点的文件操作了。

2)客户端如何通过hal调用驱动?

对驱动设备节点的第一个操作就是open,在open之后我们就可以对设备节点进行write或者其他操作,如下几个函数,都是NFC HAL接口的定义,因此HAL进程这里都是作为被动调用的一方,最后通过mDevice->XXX的方式调用驱动代码,驱动代码实现具体功能。

3)驱动阶段如何主动返回数据?

那么如果驱动程序想主动返回数据给到客户端,或者给到系统framework层,那么如何操作呢?

这时需要在看看open函数:

我们来看看函数指针eventCallback和dataCallback如何实现?

3、NFC HAL 流程图

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/901890.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Vue自定义指令-防抖节流

Vue2版本 // 防抖 // <el-button v-debounce"[reset,click,300]" ></el-button> // <el-button v-debounce"[reset]" ></el-button> Vue.directive(debounce, { inserted: function (el, binding) { let [fn, event "cl…

AI知识补全(十六):A2A - 谷歌开源的agent通信协议是什么?

名人说&#xff1a;一笑出门去&#xff0c;千里落花风。——辛弃疾《水调歌头我饮不须劝》 创作者&#xff1a;Code_流苏(CSDN)&#xff08;一个喜欢古诗词和编程的Coder&#x1f60a;&#xff09; 上一篇&#xff1a;AI知识补全&#xff08;十五&#xff09;&#xff1a;AI可解…

【机器人创新创业应需明确产品定位与方向指南】

机器人领域的创新创业, 需要对公司和产品的定位和生态进行深入思考, 明确其定位与发展目标, 明确产品在是为G、为B还是为C进行服务。 本文引用地址&#xff1a;https://www.eepw.com.cn/article/202504/469401.htm 超前的、探索性的创新技术一般是面向G端, 而不是面向B端或者C…

网安加·百家讲坛 | 刘志诚:AI安全风险与未来展望

作者简介&#xff1a;刘志诚&#xff0c;乐信集团信息安全中心总监、OWASP广东区域负责人、网安加社区特聘专家。专注于企业数字化过程中网络空间安全风险治理&#xff0c;对大数据、人工智能、区块链等新技术在金融风险治理领域的应用&#xff0c;以及新技术带来的技术风险治理…

TOA与AOA联合定位的高精度算法,三维、4个基站的情况,MATLAB例程,附完整代码

本代码实现了三维空间内目标的高精度定位,结合到达角(AOA) 和到达时间(TOA) 两种测量方法,通过4个基站的协同观测,利用最小二乘法解算目标位置。代码支持噪声模拟、误差分析及三维可视化,适用于无人机导航、室内定位等场景。订阅专栏后可获得完整代码 文章目录 运行结果…

2025MathorcupC题 音频文件的高质量读写与去噪优化 保姆级教程讲解|模型讲解

2025Mathorcup数学建模挑战赛&#xff08;妈妈杯&#xff09;C题保姆级分析完整思路代码数据教学 C题&#xff1a;音频文件的高质量读写与去噪优化 随着数字媒体技术的迅速发展&#xff0c;音频处理成为信息时代的关键技术之一。在日常生活中&#xff0c;从录音设备捕捉的原始…

Deno Dep:颠覆传统的模块化未来

一、重新定义依赖管理&#xff1a;Deno Dep 的革新哲学 Deno Dep&#xff08;原Deno包管理器&#xff09;彻底重构了JavaScript/TypeScript的依赖管理方式&#xff0c;其核心突破体现在&#xff1a; 1. 浏览器优先的模块化&#xff08;URL-Centric Modules&#xff09; // 直…

欧拉系统升级openssh 9.7p1

开发的系统准备上线&#xff0c;甲方对欧拉服务器进行了扫描&#xff0c;发现openssh版本为8.2p1&#xff0c;存在漏洞&#xff0c;因此需要升级openssh至9.7p1。欧拉系统版本为20.03 SP3。 1、下载openssh 9.7p1 https://www.openssh.com/releasenotes.html&#xff0c; 将下…

如何精通C++编程?

如果从学生时代算起的话&#xff0c;我学习和使用C已经差不多快十年了&#xff0c;仍然不敢说自己已经掌握了C的全部特性&#xff0c;但或许能够给出一些有用的建议吧。 我学习C全靠自学&#xff0c;花费了不少的功夫&#xff0c;在这里分享一些学习心得&#xff0c;希望对大家…

提高Qt工作线程的运行速度

1. 使用线程池&#xff08;QThreadPool&#xff09;替代单一线程 做过&#xff0c;但是当时没想到。。。 目的&#xff1a;减少线程创建和销毁的开销&#xff0c;复用线程资源。 实现步骤&#xff1a; 创建自定义任务类&#xff1a;继承QRunnable&#xff0c;实现run()方法。…

Solon AI MCP Server 入门:Helloworld (支持 java8 到 java24。国产解决方案)

目前网上能看到的 MCP Server 基本上都是基于 Python 或者 nodejs &#xff0c;虽然也有 Java 版本的 MCP SDK&#xff0c;但是鲜有基于 Java 开发的。 作为Java 开发中的国产顶级框架 Solon 已经基于 MCP SDK 在进行 Solon AI MCP 框架开发了&#xff0c;本文将使用 Solon AI …

STL之迭代器(iterator)

迭代器的基本概念 迭代器(iterator)模式又称为游标(Cursor)模式&#xff0c;用于提供一种方法顺序访问一个聚合对象中各个元素, 而又不需暴露该对象的内部表示。或者这样说可能更容易理解&#xff1a;Iterator模式是运用于聚合对象的一种模式&#xff0c;通过运用该模式&#…

Android系统通知机制深度解析:Framework至SystemUI全链路剖析

1. 前言 在Android 13的ROM定制化开发中&#xff0c;系统通知机制作为用户交互的核心组件&#xff0c;其实现涉及Framework层到SystemUI的复杂协作。本文将深入剖析从Notification发送到呈现的全链路流程&#xff0c;重点解析关键类的作用机制及系统服务间的交互逻辑&#xff…

UE5角色状态机中跳跃落地移动衔接问题

UE5系列文章目录 文章目录 UE5系列文章目录前言一、状态机设置二、主要蓝图 前言 先说说遇到的问题&#xff0c;在我按空格键跳跃落地以后&#xff0c;角色落地再按WSAD键移动就出现了画面中角色抽搐的情况 一、状态机设置 在Unreal Engine 5中创建角色时&#xff0c;处理跳…

使用SVM对心脏数据是否患病进行分类预测

作者简介 杜嘉宝&#xff0c;男&#xff0c;西安工程大学电子信息学院&#xff0c;2024级研究生 研究方向&#xff1a;变压器故障预警与检测 电子邮件&#xff1a;djb857497378gmail.com 王子谦&#xff0c;男&#xff0c;西安工程大学电子信息学院&#xff0c;2024级研究生&a…

Node做BFF中间层架构优化前端开发体验并提升系统整体性能。

文章目录 1. BFF 层的定位2. 技术选型3. 架构设计3.1 分层设计3.2 示例架构 4. 核心功能实现4.1 数据聚合4.2 权限校验4.3 缓存优化 5、实战示例1. 场景说明2. ECharts 数据格式要求3. BFF 层实现步骤3.1 接收前端参数3.2 调用后端服务获取数据 4. 前端使用 总结 在使用 Node.j…

文件系统 软硬连接

&#x1f33b;个人主页&#xff1a;路飞雪吖~ &#x1f320;专栏&#xff1a;Linux 目录 一、理解文件系统 &#x1f320;磁盘结构 二、软硬连接 &#x1f31f;软硬链接 &#x1f320;软链接&#xff1a; &#x1f320;硬链接&#xff1a; &#x1f31f;理解软硬链接的应…

单片机 | 基于51单片机的自动循迹小车设计

以下是一个基于51单片机的自动循迹小车设计详解,包含原理、公式和完整代码: 一、系统原理 核心模块: 传感器:红外对管(TCRT5000)x4主控芯片:STC89C52RC(51单片机)电机驱动:L298N驱动模块电源:7.4V锂电池(电机) + 5V稳压(单片机)工作原理: 红外对管发射红外线,…

2025.04.17【Stacked area】| 生信数据可视化:堆叠区域图深度解析

文章目录 生信数据可视化&#xff1a;堆叠区域图深度解析堆叠面积图简介为什么使用堆叠面积图如何使用R语言创建堆叠面积图安装和加载ggplot2包创建堆叠面积图的基本步骤示例代码 解读堆叠面积图堆叠面积图的局限性实际应用案例示例&#xff1a;基因表达量随时间变化 结论 生信…

基于单片机的智能养生油炸炉系统设计与实现

标题:基于单片机的智能养生油炸炉系统设计与实现 内容:1.摘要 本文针对传统油炸炉功能单一、无法满足现代养生需求的问题&#xff0c;设计并实现了基于单片机的智能养生油炸炉系统。通过采用STC89C52单片机作为控制核心&#xff0c;结合温度传感器、液位传感器、继电器等硬件&…