树莓派4B android 系统添加led灯 Hal 层

embedded/2025/2/7 0:37:03/

一、Hal 层的实现

1.Hal 层的实现一般放在 vendor 目录下,我们在 vendor 目录下创建如下的目录

aosp/vendor/arpi/hardware/interfaces/rbg_led_control_hidl/1.0

接着在aosp/vendor/arpi/hardware/interfaces/rbg_led_control_hidl/1.0 目录下创建Hal文件ILedControl.hal

//定义包名,最后跟一个版本号
package arpi.hardware.rbg_led_control_hidl@1.0;
//定义 hidl 服务对外提供的接口
interface ILedControl {//开灯openLed(uint32_t red,uint32_t blue,uint32_t green) generates (uint32_t result);//读 hello 驱动closeLed() generates (uint32_t result);
};

2. hal 文件生成 C++ 源文件

接着我们使用 hidl-gen 命令将我们写的 hal 文件转换为 C++ 文件:

source build/envsetup.sh
lunch rpi4-eng
PACKAGE=arpi.hardware.rbg_led_control_hidl@1.0
LOC=vendor/arpi/hardware/interfaces/rbg_led_control_hidl/1.0/default
hidl-gen -o $LOC -Lc++-impl -rarpi.hardware:vendor/arpi/hardware/interfaces $PACKAGE

接着就会生成一些 C++ 代码:生成下图中的LedControl.h  LedControl.cpp

接着修改 LedControl.cpp

// FIXME: your file license if you have one#include "LedControl.h"
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdio.h>
#include <string.h>namespace arpi::hardware::rbg_led_control_hidl::implementation {// Methods from ::arpi::hardware::rbg_led_control_hidl::V1_0::ILedControl follow.
Return<uint32_t> LedControl::openLed(uint32_t red, uint32_t blue, uint32_t green) {int fd = open("/dev/led_drv", O_RDWR);if (fd == -1){printf("can not open file /dev/led_drv\n");return  uint32_t { 0 };}char r[]="red";char b[]="blue";char g[]="green";char cmd[14]="";if(red==1){strcat(cmd, r);}if(blue==1){strcat(cmd, b);}if(green==1){strcat(cmd, g);}::write(fd, cmd, strlen(cmd) +1);close(fd);return uint32_t {1};
}Return<uint32_t> LedControl::closeLed() {int fd = open("/dev/led_drv", O_RDWR);if (fd == -1){printf("can not open file /dev/led_drv\n");return  uint32_t { 0 };}char cmd[14]="";::write(fd, cmd, strlen(cmd) +1);close(fd);return uint32_t {1};
}// Methods from ::android::hidl::base::V1_0::IBase follow.//ILedControl* HIDL_FETCH_ILedControl(const char* /* name */) {//return new LedControl();
//}
//
}  // namespace arpi::hardware::rbg_led_control_hidl::implementation

这里主要是对我们的协议进行实现,实现了对上一节实现的设备文件 /dev/led_drv 的读写。至此我们的 hidl 服务就定义好了

3. 服务端实现

接着我们需要写一个 Server 端来向 HwServiceManager 注册我们的服务。在vendor/arpi/hardware/interfaces/rbg_led_control_hidl/1.0/default 目录下添加 service.cpp(参考上图)

#include <hidl/HidlTransportSupport.h>
#include <utils/Looper.h>
#include <utils/StrongPointer.h>
#include <log/log.h>
#include "LedControl.h"using android::hardware::configureRpcThreadpool;
using android::hardware::joinRpcThreadpool;
using arpi::hardware::rbg_led_control_hidl::V1_0::ILedControl;
using arpi::hardware::rbg_led_control_hidl::implementation::LedControl;int main() {ALOGD("hello-hidl is starting...");configureRpcThreadpool(4, true /* callerWillJoin */);android::sp<ILedControl> service = new LedControl();android::status_t ret = service->registerAsService();if (ret != android::NO_ERROR) {}joinRpcThreadpool();return 0;//Passthrough模式//return defaultPassthroughServiceImplementation<IHello>(4);
}

我们的服务端需要在开机时启动,vendor/arpi/hardware/interfaces/rbg_led_control_hidl/1.0/default 目录下创建arpi.hardware.rbg_led_control_hidl@1.0-service.rc 文件

service vendor_rbg_led_control_hidl_service /vendor/bin/hw/arpi.hardware.rbg_led_control_hidl@1.0-serviceclass haluser systemgroup system

接着我们需要添加 VINTF 对象,对于注册到 hwservicemanager 的服务都需要添加一个 VINTF 对象。对于编码来说 VINTF 对象就是一个 xml 文件,vendor/arpi/hardware/interfaces/rbg_led_control_hidl/1.0/default 目录下创建arpi.hardware.rbg_led_control_hidl@1.0-service.xml

<manifest version="1.0" type="device"><hal format="hidl"><name>arpi.hardware.rbg_led_control_hidl</name><transport>hwbinder</transport><version>1.0</version><interface><name>ILedControl</name><instance>default</instance></interface></hal>
</manifest>

4 生成 Android.bp

hidl-gen -o $LOC -Landroidbp-impl -rarpi.hardware:vendor/arpi/hardware/interfaces $PACKAGE

该命令会在vendor/arpi/hardware/interfaces/rbg_led_control_hidl/1.0/default 目录下创建Android.bp

简单修改该文件:

// FIXME: your file license if you have onecc_library_shared {// FIXME: this should only be -impl for a passthrough hal.// In most cases, to convert this to a binderized implementation, you should:// - change '-impl' to '-service' here and make it a cc_binary instead of a//   cc_library_shared.// - add a *.rc file for this module.// - delete HIDL_FETCH_I* functions.// - call configureRpcThreadpool and registerAsService on the instance.// You may also want to append '-impl/-service' with a specific identifier like// '-vendor' or '-<hardware identifier>' etc to distinguish it.name: "arpi.hardware.rbg_led_control_hidl@1.0-impl",relative_install_path: "hw",// FIXME: this should be 'vendor: true' for modules that will eventually be// on AOSP.proprietary: true,srcs: ["LedControl.cpp",],shared_libs: ["libhidlbase","libhidltransport","libutils","arpi.hardware.rbg_led_control_hidl@1.0","liblog",],
}cc_binary {name: "arpi.hardware.rbg_led_control_hidl@1.0-service",init_rc: ["arpi.hardware.rbg_led_control_hidl@1.0-service.rc"],vintf_fragments: ["arpi.hardware.rbg_led_control_hidl@1.0-service.xml"],defaults: ["hidl_defaults"],relative_install_path: "hw",vendor: true,srcs: ["service.cpp", "LedControl.cpp"],shared_libs: ["arpi.hardware.rbg_led_control_hidl@1.0","libhardware","libhidlbase","libhidltransport","libutils","liblog",],
}

生成的库里面有一个依赖 arpi.hardware.rbg_led_control_hidl@1.0,接着我们来生成这个库对应的 Android.bp:

在vendor/arpi/hardware/interfaces/下创建update-makefiles.sh 

#!/bin/bashsource $ANDROID_BUILD_TOP/system/tools/hidl/update-makefiles-helper.shdo_makefiles_update \"arpi.hardware:vendor/arpi/hardware/interfaces"

接着执行:

./vendor/arpi/hardware/interfaces/update-makefiles.sh

结果生成文件aosp/vendor/arpi/hardware/interfaces/rbg_led_control_hidl/Android.bp 

// This file is autogenerated by hidl-gen -Landroidbp.hidl_interface {name: "arpi.hardware.rbg_led_control_hidl@1.0",root: "arpi.hardware",system_ext_specific: true,srcs: ["ILedControl.hal",],interfaces: ["android.hidl.base@1.0",],gen_java: true,
}

这个过程会生成一些so 库。

随后在aosp/vendor/arpi/hardware/interfaces下创建Android.bp (告诉编译系统包名与路径的映射关系)

hidl_package_root {name: "arpi.hardware",path: "vendor/arpi/hardware/interfaces",
}

接着创建aosp/vendor/arpi/hardware/interfaces/current.txt

ecf0cea3adff3da5319d360d2e86c3a4b336aa64e798f1fc4eb3dc2abbd6905f arpi.hardware.rbg_led_control_hidl@1.0::ILedControl

再执行一遍 update-makefiles.sh,这个时候就会发现提示 hash 值不正确了,同时会给出正确的 hash 值,我们把正确的 hash 值替换到 current.txt 即可。

5 test客户端编写

vendor/arpi/hardware/interfaces/rbg_led_control_hidl/1.0/default 目录下创建test文件夹

Android.bp

cc_binary {name: "rbg_led_control_hidl_test",srcs: ["rbg_led_control_hidl_test.cpp"],vendor: true,shared_libs: ["liblog","arpi.hardware.rbg_led_control_hidl@1.0","libhidlbase","libhidltransport","libhwbinder","libutils",],
}
#include <arpi/hardware/rbg_led_control_hidl/1.0/ILedControl.h>
#include <hidl/LegacySupport.h>#define LOG_TAG "rbg_led_control_hidl"
#include <log/log.h>using android::sp;
using arpi::hardware::rbg_led_control_hidl::V1_0::ILedControl;
using android::hardware::Return;
using android::hardware::hidl_string;int main(){android::sp<ILedControl> hw_device = ILedControl::getService();if (hw_device == nullptr) {ALOGD("failed to get rbg_led_control_hidl");return -1;}ALOGD("success to rbg_led_control_hidl....");hw_device->openLed(1,0,0);return 0;
} 

上面测试代码可以点亮led 红灯

6 selinux 配置

在aosp/device/arpi/rpi4/sepolicy 目录下

device.te 中添加如下内容:

type led_drv_t, dev_type;

hwservice.te:

type rbg_led_control_hidl_hwservice, hwservice_manager_type;

rbg_led_control_hidl.te:

# type rbg_led_control_hidl, domain;type rbg_led_control_hidl, domain;
type rbg_led_control_hidl_exec, exec_type, vendor_file_type, file_type;init_daemon_domain(rbg_led_control_hidl);
add_hwservice(rbg_led_control_hidl, rbg_led_control_hidl_hwservice)
hwbinder_use(rbg_led_control_hidl)allow rbg_led_control_hidl hidl_base_hwservice:hwservice_manager { add };
allow rbg_led_control_hidl led_drv_t:chr_file { open read write };
binder_call(rbg_led_control_hidl,hwservicemanager)
get_prop(rbg_led_control_hidl,hwservicemanager_prop)

hwservice_contexts:

arpi.hardware.rbg_led_control_hidl::ILedControl      u:object_r:rbg_led_control_hidl_hwservice:s0

rbg_led_control_hidl_test.te:

type  rbg_led_control_hidl_test, domain;
type  rbg_led_control_hidl_test_exec, exec_type, vendor_file_type, file_type;domain_auto_trans(shell, rbg_led_control_hidl_test_exec, rbg_led_control_hidl_test);get_prop(rbg_led_control_hidl_test, hwservicemanager_prop);
allow rbg_led_control_hidl_test rbg_led_control_hidl_hwservice:hwservice_manager find;
hwbinder_use(rbg_led_control_hidl_test);

file_contexts:

/dev/led_drv                    u:object_r:led_drv_t:s0
/vendor/bin/hw/arpi\.hardware\.rbg_led_control_hidl@1\.0-service    u:object_r:rbg_led_control_hidl_exec:s0

7 编译执行

接着在aosp/device/arpi/rpi4/rpi4.mk 加入程序

PRODUCT_PACKAGES += \arpi.hardware.rbg_led_control_hidl@1.0-service \rbg_led_control_hidl_test \arpi.hardware.rbg_led_control_hidl@1.0-impl \
 source build/envsetup.shlunch rpi4-engmake ramdisk systemimage vendorimage

最后测试(点亮led):

rbg_led_control_hidl_test &


http://www.ppmy.cn/embedded/144200.html

相关文章

计算机毕业设计Python动物图像识别分类系统 机器学习 深度学习 数据可视化 爬虫 卷积神经网络CNN 预测算法 图像识别

温馨提示&#xff1a;文末有 CSDN 平台官方提供的学长联系方式的名片&#xff01; 温馨提示&#xff1a;文末有 CSDN 平台官方提供的学长联系方式的名片&#xff01; 温馨提示&#xff1a;文末有 CSDN 平台官方提供的学长联系方式的名片&#xff01; 作者简介&#xff1a;Java领…

Mitel MiCollab 企业协作平台 任意文件读取漏洞复现(CVE-2024-41713)

0x01 产品简介 Mitel MiCollab是加拿大Mitel(敏迪)公司推出的一款企业级协作平台,旨在为企业提供统一、高效、安全的通信与协作解决方案。通过该平台,员工可以在任何时间、任何地点,使用任何设备,实现即时通信、语音通话、视频会议、文件共享等功能,从而提升工作效率和…

基于爬虫技术在小程序环境的菜谱语音播放系统设计与实现

基于爬虫技术在小程序环境的菜谱语音播放系统设计与实现 PS:因为计算机专业毕业需要做毕业设计,有些人会花钱找别人做。作为过来人,如果找别人,一定要看清楚设计是否符合当年,比如设计出现不是当年的年份,比如2024年,结果系统是2019、图片显示的年份不一致等等。这样是很…

shell基础用法

shell基础知识 shell中的多行注释 :<<EOF read echo $REPLY # read不指定变量&#xff0c;则默认写入$REPLY EOF # :<<EOF ...EOF 多行注释&#xff0c;EOF可以替换为&#xff01;# 等文件目录和执行目录 echo $0$0 # ./demo.sh echo $0的realpath$(realpath…

执行存储过程报:This function has none of DETERMINISTIC, NO SQL ???

执行存储过程时报如下错你该怎么整&#xff1f; [Err] 1418 - This function has none of DETERMINISTIC, NO SQL, or READS SQL DATA in its declaration and binary logging is enabled (you *might* want to use the less safe log_bin_trust_function_creators variable)来…

利用 360 安全卫士极速版关闭电脑开机自启动软件教程

在使用电脑的过程中&#xff0c;过多的开机自启动软件会严重拖慢电脑的开机速度&#xff0c;影响我们的使用体验。本教程中简鹿办公将详细介绍如何使用 360 安全卫士极速版关闭电脑开机自启动软件&#xff0c;让您的电脑开机更加迅速流畅。 一、打开 360 安全卫士极速版 在电…

PDF文件打开之后不能打印,怎么解决?

正常的PDF文件是可以打印的&#xff0c;如果PDF文件打开之后发现文件不能打印&#xff0c;我们需要先查看一下自己的打印机是否能够正常运行&#xff0c;如果打印机是正常的&#xff0c;我们再查看一下&#xff0c;文件中的打印功能按钮是否是灰色的状态。 如果PDF中的大多数功…

[并查集] UVA11987 Almost Union-Find

问题描述 有 n n n 个集合&#xff0c; m m m 次操作。规定第 i i i 个集合里初始只有 i i i 。 有三种操作&#xff1a; 输入两个元素 p p p 和 q q q &#xff0c;若 p p p 和 q q q 不在一个集合中&#xff0c;合并两个元素的集合。输入两个元素 p p p 和 q q q …