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

本文内容需要用到我上一篇文章做的驱动,可以先看文章https://blog.csdn.net/ange_li/article/details/136759249

一、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-service
	class hal
	user system
	group 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 one

cc_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/bash

source $ANDROID_BUILD_TOP/system/tools/hidl/update-makefiles-helper.sh

do_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.sh
 lunch rpi4-eng
 make ramdisk systemimage vendorimage

最后测试(点亮led):

rbg_led_control_hidl_test &

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Apache DolphinScheduler 限制秒级别的定时调度

背景 Apache DolphinScheduler 定时任务配置采用的 7 位 Crontab 表达式&#xff0c;分别对应秒、分、时、月天、月、周天、年。 在团队日常开发工作中&#xff0c;工作流的定时调度一般不会细化到秒级别。但历史上出现过因配置的疏忽大意而产生故障时间&#xff0c;如应该配…

MTK Android12 开机向导

文章目录 需求-场景参考资料&#xff1a;博客资料官网参考资料&#xff1a;参考资料注意点 附件资料文件说明&#xff1a;推荐工具&#xff1a;配置定制的 声明叠加层 APK需求实现替换字符、删减开机向导界面、添加开机向导界面删除部分界面需求&#xff0c;官网说明如下更新部…

Text2SQL(NL2sql)对话数据库:设计、实现细节与挑战

Text2SQL&#xff08;NL2sql&#xff09;对话数据库&#xff1a;设计、实现细节与挑战 前言1.何为Text2SQL&#xff08;NL2sql&#xff09;2.Text2SQL结构与挑战3.金融领域实际业务场景4.注意事项5.总结 前言 随着信息技术的迅猛发展&#xff0c;人机交互的方式也在不断演进。…

长沙数字孪生工业互联网三维可视化技术,赋能新型工业化智能制造工厂

长沙正积极拥抱数字化转型的浪潮&#xff0c;特别是在工业互联网和智能制造领域&#xff0c;长沙数字孪生技术的广泛应用&#xff0c;为新型工业化智能制造工厂的建设与发展注入了强劲动力。 在长沙智能制造工厂内&#xff0c;三维可视化技术被广泛应用于产线设计仿真优化和产…

FPGA工作原理、架构及底层资源

FPGA工作原理、架构及底层资源 文章目录 FPGA工作原理、架构及底层资源前言一、FPGA工作原理二、FPGA架构及底层资源 1.FPGA架构2.FPGA底层资源 2.1可编程输入/输出单元简称&#xff08;IOB&#xff09;2.2可配置逻辑块2.3丰富的布线资源2.4数字时钟管理模块(DCM)2.5嵌入式块 …

计算机网络期末常见问答题总结

1、试说明为什么在运输建立时使用三报文握手&#xff0c;如果不采用三报文握手会出现什么情况&#xff1f; TCP三次握手的目的是确保客户端和服务器都能够接收对方的连接请求,并建立起可靠的连接。如果只进行两次握手,可能会导致以下情况的发生: - 如果客户端发送的SYN包在网…

Redis篇-4--原理篇3--Redis发布/订阅(Pub/Sub)

1、概述 Redis 发布/订阅&#xff08;Publish/Subscribe&#xff0c;简称 Pub/Sub&#xff09;是一种消息传递模式&#xff0c;允许客户端订阅一个或多个通道&#xff08;channel&#xff09;&#xff0c;并接收其他客户端发布到这些通道的消息。 2、Redis 发布/订阅的主要概…

第六届地博会世界酒中国菜助力广州龙美地标美食公司推动地标发展

第六届知交会暨地博会&#xff1a;世界酒中国菜助力广州龙美地标美食公司推动地标产品创新发展 2024年12月9日至11日&#xff0c;第六届粤港澳大湾区知识产权交易博览会暨国际地理标志产品交易博览会在中新广州知识城盛大启幕。本届盛会吸引了全球众多知识产权领域的专业人士和…

【CSS in Depth 2 精译_074】第 12 章 CSS 排版与间距概述 + 12.1 间距设置(下):行内元素的间距设置

当前内容所在位置&#xff08;可进入专栏查看其他译好的章节内容&#xff09; 第四部分 视觉增强技术 ✔️【第 12 章 CSS 排版与间距】 ✔️ 12.1 间距设置 12.1.1 使用 em 还是 px12.1.2 对行高的深入思考12.1.3 行内元素的间距设置 ✔️ 12.2 Web 字体12.3 谷歌字体 文章目…

基于FPGA的智能电子密码指纹锁(开源全免)

基于FPGA的智能电子密码指纹锁 一、功能描述硬件资源需求 二、整体框架知识准备AS608指纹模块4*4数字键盘模块 三、Verilog代码实现以及仿真验证1.AS608_data模块2.check_hand模块3.four_four_key模块4.check_mima模块5.change_mima模块6.seg_ctrl模块7.uart_top模块8.key_debo…

汽车网络安全 -- IDPS如何帮助OEM保证车辆全生命周期的信息安全

目录 1.强标的另一层解读 2.什么是IDPS 2.1 IDPS技术要点 2.2 车辆IDPS系统示例 3.车辆纵深防御架构 4.小结 1.强标的另一层解读 在最近发布的国家汽车安全强标《GB 44495》,在7.2节明确提出了12条关于通信安全的要求,分别涉及到车辆与车辆制造商云平台通信、车辆与车辆…

【C++】快速排序详解与优化

博客主页&#xff1a; [小ᶻ☡꙳ᵃⁱᵍᶜ꙳] 本文专栏: C 文章目录 &#x1f4af;前言&#x1f4af;快速排序的核心思想1. 算法原理2. 算法复杂度分析时间复杂度空间复杂度 &#x1f4af;快速排序的代码实现与解析代码实现代码解析1. 递归终止条件2. 动态分配子数组3. 分区…

Redis从入门到进阶(总结)

以下内容均以CentOS7为背景。 一、Redis安装及启动 mysql&#xff08;读&#xff1a;2000/s&#xff1b;写&#xff1a;600/s&#xff09; redis&#xff08;读&#xff1a;10w/s&#xff1b;写&#xff1a;8w/s&#xff09;通过官方给出的数据单机并发可以达到10w/s&#xf…

设计模式——单例模式和工厂模式

单例模式:一个类只创建一个类对象&#xff08;节省内存减少类对象数量,一个类对象多次重复使用&#xff09; 格式: class a: pass ba() z1b z2b #z1和z2为同一个类对象 工厂模式&#xff1a;&#xff08;大批量创建具体的类对象,统一类对象入口便于维护&#xf…

Flume基础概念

目录 作用组件构成ClientFlowAgentSourceSinkEvent 和Log4j的区别与定位事务传出流程输入到sourcesource端输入Channel 接收输入到SinkSink输出 作用 Flume可以从各种来源&#xff08;如日志文件、消息队列、网络数据、文件系统、数据库等&#xff09;收集数据&#xff0c;并将…

PHP语法学习(第七天)-循环语句,魔术常量

老套路了&#xff0c;朋友们&#xff0c;先回忆昨天讲的内容PHP语法学习(第六天)主要讲了PHP中的if…else语句、关联数组以及数组排序。 想要学习更多PHP语法相关内容点击“PHP专栏&#xff01;” 下列代码都是在PHP在线测试运行环境中得到的&#xff01;&#xff01; 还记得电…

生成:安卓证书uniapp

地址&#xff1a; https://ask.dcloud.net.cn/article/35777 // 使用keytool -genkey命令生成证书&#xff1a; 官网&#xff1a; keytool -genkey -alias testalias -keyalg RSA -keysize 2048 -validity 36500 -keystore test.keystore ----------------------------------…

Vue.js:代码架构组成与布局设置

前言&#xff1a;最近在弄一个开源的管理系统项目&#xff0c;前后端分离开发&#xff0c;这里对前端的Vue框架做一个总结&#xff0c;有遗漏和错误的地方欢迎大家指出~ &#x1f3e1;个人主页&#xff1a;謬熙&#xff0c;欢迎各位大佬到访❤️❤️❤️~ &#x1f472;个人简介…

【优选算法-滑动窗口】长度最小的子数组、无重复字符的最长子串、最大连续1的个数、将x减为0的最小操作数、水果成篮

一、长度最小的子数组 题目链接&#xff1a; 209. 长度最小的子数组 - 力扣&#xff08;LeetCode&#xff09; 题目介绍&#xff1a; 给定一个含有 n 个正整数的数组和一个正整数 target 。 找出该数组中满足其总和大于等于 target 的长度最小的 子数组 [numsl, numsl1, .…

appium学习之二:adb命令

1、查看设备 adb devices 2、连接 adb connect IP:端口 3、安装 adb install xxx.apk 4、卸载 adb uninstall 【包名】 5、把对应目录下的1.txt文件传到手机sdcard下 adb push 1.txt /sdcard 6、进入对应的设备里 adb shell 7、切入sdcard目录 cd /sdcard 8、ls 查…