完善资料让更多小伙伴认识你,还能领取20积分哦, 立即完善>
7.1系统Hal层添加服务流程
一.hardware层编写 1.准备工作 确保物理设备正常连接,cd dev/目录下查看可用设备,可以看到设备dev路径,如果遇到打开设备PemissionDenied问题,进入system/core/rootdir/uenentd.rc,添加/dev/xxx 0666 root root 权限 2.hardware目录新建硬件服务 2.1在源码根目录下:hardware/libhardware/include/hardware 新建het.h丶IDeviceCallback.h丶types.h文件 het.h #ifndef _HARDWARE_IHET_H #define _HARDWARE_IHET_H #include #include #include #include #include "IDeviceCallback.h" #include #include #include #include #include #include #include #include #include #include #include #include "types.h" __BEGIN_DECLS #define IHET_HARDWARE_MODULE_ID "het" #define VL6180_IOCTL_INIT _IO('p', 0x01) bool threadLoop(); int open_ranging_device(int on); void get_event(int fd); void event_callback(int what, std::string msg); struct ihet_module_t { struct hw_module_t common; }; typedef struct ihet_device { struct hw_device_t common; int fd; std::string(*setState)(struct ihet_device *ihet_module,const DeviceType& type); std::string(*getState)(struct ihet_device *ihet_module,int32_t type); bool(*setCallback)(struct ihet_device *ihet_module,const android::sp void(*release)(); } ihet_device_t; __END_DECLS #endif IDeviceCallback.h #ifndef _HARDWARE_IDEVICECALLBACK_H #define _HARDWARE_IDEVICECALLBACK_H #include #include #include "types.h" #include #include using namespace android; class IDeviceCallback : public LightRefBase { private: /* data */ public: IDeviceCallback(/* args */); ~IDeviceCallback(); void onDeviceEvent(DeviceEvent __event); }; IDeviceCallback::IDeviceCallback(/* args */) { } IDeviceCallback::~IDeviceCallback() { } void IDeviceCallback::onDeviceEvent(DeviceEvent __event){ } #endif types.h #ifndef _HARDWARE_TYPES_H #define _HARDWARE_TYPES_H #include #include struct DeviceType{ int32_t type; int32_t state; }; struct DeviceEvent{ int32_t what; std::string msg; }; 2.2在源码目录下:hardware/libhardware/modules 新建het目录,在该目录下新建het.cpp 和 Android.mk 文件 het.cpp #define LOG_TAG "Het_cpp" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include /*****************************************************************************/ // 门: 只读 #define DOOR_PATH "/dev/door" // 锁头+: 只写 #define LOCK_P_PATH "/dev/lock_p" // 锁头-: 只写 #define LOCK_N_PATH "/dev/lock_n" // 手柄充电状态: 只读 #define CHARGER_PATH "/dev/charger" // 紫外灯: 只写 #define UV_LAMP_PATH "/dev/uv_lamp" // 距离 #define RANGING_PATH "/dev/ranging" // 温度 #define THERMOMETRY_PATH "/dev/thermometry" #define DEVICE_NAME "/dev/het" #define MODULE_NAME "het" #define MODULE_AUTHOR "nailliu@gmail.com" android::sp bool m_exit = true; int range_fd = -1, event_fd = -1; int g_bl_fd = 0; //backlight fd int g_btn_fd = 0; //button light fd int g_bat_fd = 0; //battery charger fd static int read_int(char const *path) { int fd; static int already_warned; already_warned = 0; ALOGE("read_int: path %s", path); fd = open(path, O_RDWR); if (fd >= 0) { //char buffer[20]; //memset(&buffer, 0, sizeof(buffer)); int result; int amt = read(fd, &result, 4); //for(int i=0;i close(fd); return amt == -1 ? -1 : result; } else { if (already_warned == 0) { ALOGE("read_int failed to open %sn", path); already_warned = 1; } return -1; } } static int write_int(char const *path, int value) { int fd; static int already_warned; already_warned = 0; ALOGE("write_int: path %s, value %d", path, value); fd = open(path, O_RDWR); if (fd >= 0) { //char buffer[20]; //int bytes = sprintf(buffer, "%d", value); int amt = write(fd, &value, sizeof(int)); close(fd); return amt == -1 ? -errno : 0; } else { if (already_warned == 0) { ALOGE("write_int failed to open %d, %sn", fd, path); already_warned = 1; } return -errno; } } // Methods from IHet follow. static std::string het_setState(struct ihet_device *dev,const DeviceType& type) { // TODO implement int ret = 0; char buffer[20]; memset(buffer, 0, sizeof(buffer)); if (type.type == 0) { // lock ret = write_int(LOCK_P_PATH, type.state); //usleep(50000); ret = write_int(LOCK_N_PATH, !type.state); } else if (type.type == 1) { // uv_lamp ret = write_int(UV_LAMP_PATH, type.state); } else if (type.type == 2) { // range ret = open_ranging_device(type.state); } else if (type.type == 3) { // range ret = write_int(THERMOMETRY_PATH, type.state); } else if (type.type == 5) { // range ret = write_int(LOCK_P_PATH, 0); ret = write_int(LOCK_N_PATH, 0); } return ""; } static std::string het_getState(struct ihet_device *dev,int32_t type) { // TODO implement int ret = 0; char buffer[20]; memset(buffer, 0, sizeof(buffer)); ALOGE("getState: %d", type); //sleep(5); if (type == 0) { // door ret = read_int(DOOR_PATH); } else if (type == 1) { // charger ret = read_int(CHARGER_PATH); } //sleep(3); return ""; } static bool het_setCallback(struct ihet_device *dev,const android::sp mCallback = callback; bool res = false; if(mCallback != nullptr) { ALOGE("setCallback: done"); res = true; } return res; } static void het_release() { m_exit = true; ALOGE("release:"); return; } bool threadLoop(){ ALOGI("threadLoop====n"); int ret; char buf[] = "/dev/input/event1"; DeviceEvent event; /*打开设备文件*/ range_fd = open(RANGING_PATH, O_RDWR); if (range_fd < 0) { ALOGE("open dev RANGING_PATH err!n"); event_callback(-1, "open dev RANGING_PATH err"); return false; } ALOGI("threadLoop range_fd = %dn", range_fd); ret = ioctl(range_fd, VL6180_IOCTL_INIT); if (ret == -1) { ALOGE("ioctl VL6180_IOCTL_INIT : %sn", strerror(errno)); event_callback(-1, "ioctl VL6180_IOCTL_INIT"); close(range_fd); range_fd = -1; return false; } ALOGI("threadLoop ret = %dn", ret); usleep(200 * 1000); ALOGI("threadLoop ret1 = %dn", ret); event_fd = open(buf, O_RDONLY); if (event_fd < 0) { ALOGE("%s opened event =%d n", buf, event_fd); event_callback(-1, "opened event failed"); close(range_fd); range_fd = -1; return false; } m_exit = false; while (!m_exit) { get_event(event_fd); } if (range_fd > 0) { close(range_fd); range_fd = -1; } if (event_fd > 0) { close(event_fd); event_fd = -1; } ALOGE("threadLoop: exit"); return false; } /** * 开关距离传感器设备 * * @param on 0-关闭|1-打开 * @return */ int open_ranging_device(int on) { //int on = atoi(value.c_str()); ALOGI("open_ranging_device = %dn", on); if (on == 0) { ALOGI("open_ranging_device m_exit = %dn", m_exit); ALOGI("open_ranging_device range_fd = %dn", range_fd); ALOGI("open_ranging_device event_fd = %dn", event_fd); m_exit = true; return 0; } else { if (range_fd > 0 && event_fd > 0 && !m_exit) { ALOGE("range_fd =%d, event_fd =%d m_exit =%dn", range_fd, event_fd, m_exit); return 0; } ALOGI("open_ranging_device m_exit = %dn", m_exit); ALOGI("open_ranging_device range_fd = %dn", range_fd); ALOGI("open_ranging_device event_fd = %dn", event_fd); run("read_event_thread"); } return 0; } void get_event(int fd) { //ALOGI("get_event = %dn", fd); int ret; struct input_event event;//对输入设备封装一个结构体 if (fd < 0) { return; } ret = read(fd, &event, sizeof(event));// //ALOGI("ret = %dn", ret); switch (event.type) {///事件类型的分类 case EV_ABS: if (event.code == ABS_HAT1X) { // 毫米 ALOGI("ABS_HAT1X range_mm = %dn", event.value); event_callback(event.code, std::to_string(event.value)); } else if (event.code == ABS_HAT1Y) { // 状态码 ALOGE("ABS_HAT1Y errorStatus= %dn", event.value); if (event.value == 0) { break; event_callback(event.code, std::to_string(event.value)); } else if (event.code == ABS_HAT3Y) { //ALOGI("===============ABS_HAT3Y DMax = %dn", event.value); break; } break; default: break; } return; } } /** * 事件回调到framework层 * * @param what * @param msg */ void event_callback(int what, std::string msg) { DeviceEvent event; event.what = what; event.msg = msg; if(mCallback != nullptr) { mCallback->onDeviceEvent(event); } return; } static int het_device_close(struct hw_device_t* device) { struct ihet_device* ihet_device = (struct ihet_device*)device; if(ihet_device) { close(ihet_device->fd); free(ihet_device); } return 0; } static int het_device_open(const struct hw_module_t* module, const char* name, struct hw_device_t** device) { struct ihet_device* dev;dev = (struct ihet_device*)malloc(sizeof(struct ihet_device)); if(!dev) { ALOGE("Hello Stub: failed to alloc space"); return -EFAULT; } memset(dev, 0, sizeof(struct ihet_device)); dev->common.tag = HARDWARE_DEVICE_TAG; dev->common.version = 0; dev->common.module = (hw_module_t*)module; dev->common.close = het_device_close; dev->setState = het_setState; dev->getState = het_getState; dev->setCallback = het_setCallback; dev->release = het_release; if((dev->fd = open(DEVICE_NAME, O_RDWR)) == -1) { ALOGE("Het Stub: failed to open /dev/het -- %s.", strerror(errno));free(dev); return -EFAULT; } *device = &(dev->common); ALOGI("Het Stub: open /dev/het successfully."); return 0; } static struct hw_module_methods_t ihet_module_methods = { .open = het_device_open, }; struct ihet_module_t HAL_MODULE_INFO_SYM = { common: { tag: HARDWARE_MODULE_TAG, version_major: 1, version_minor: 0, id: IHET_HARDWARE_MODULE_ID, name: MODULE_NAME, author: MODULE_AUTHOR, methods: &ihet_module_methods, } }; Android.mk LOCAL_PATH := $(call my-dir) include $(CLEAR_VARS) LOCAL_MODULE := het.default LOCAL_MODULE_RELATIVE_PATH := hw LOCAL_SRC_FILES := Het.cpp LOCAL_SHARED_LIBRARIES := liblog libcutils LOCAL_MODULE_TAGS := optional include $(BUILD_SHARED_LIBRARY) 2.3在源码根目录下:hardware/libhardware/modules 修改Android.mk 添加het 文件夹名 hardware_modules := gralloc hwcomposer audio nfc nfc-nci local_time power u***audio audio_remote_submix camera u***camera consumerir sensors vibrator tv_input fingerprint input vehicle thermal vr het include $(call all-named-subdir-makefiles,$(hardware_modules)) 2.4编译hardware的.so库 在源码根目录下执行:mmm hardware/libhardware/modules/het/ 会对het 模块进行编译 在源码根目录下产生 out/target/product/rk3288/obj/lib/het.default.so.toc 3.编写JNI,提供JAVA和C/C++交互接口 #include "jni.h" #include "JNIHelp.h" #include "android_runtime/AndroidRuntime.h" #include #include #include #include #include namespace android { struct iic_device *iic_dev = NULL; static void iic_setVal(JNIEnv* env, jobject clazz, jint slaveAddr, jint regAddr, jint databuf) { if(!iic_dev) { ALOGE("iic JNI: device is not open."); } iic_dev->iic_write(iic_dev,slaveAddr,regAddr,databuf); } static jint iic_getVal(JNIEnv* env, jobject clazz,jint slaveAddr, jint regAddr) { unsigned char data[1] = {0}; iic_dev->iic_read(iic_dev,slaveAddr,regAddr,data); if(!iic_dev) { ALOGE("iic JNI: device is not open."); } return data[0]; } /*通过硬件模块ID来加载指定的硬件抽象层模块并打开硬件*/ static ***oolean iic_init(JNIEnv* env, jclass clazz) { iic_module_t *module; int err; err = hw_get_module(IIC_HARDWARE_MODULE_ID,(const struct hw_module_t**)&module); if (err != 0) { ALOGE("Error acquiring iic hardware module: %d", err); return 0; } err = iic_open(&(module->common), &iic_dev); if (err != 0) { ALOGE("Error opening iic hardware module: %d", err); return 0; } ALOGE("iic device is opening..."); return 1; } /*JNI方法表*/ static const JNINativeMethod method_table[] = { {"init_native", "()Z", (void*)iic_init}, {"setVal_native", "(III)V", (void*)iic_setVal}, {"getVal_native", "(II)I", (void*)iic_getVal}, }; /*注册JNI方法*/ int register_android_server_IICService(JNIEnv *env) { return jniRegisterNativeMethods(env, "com/android/server/IICService", method_table, NELEM(method_table)); } }; 在源码根目录下:frameworks/base/services/core/jni 新建com_android_server_HETService.cpp,然后需要让Android启动时加载此jni模块 在同目录下修改onload.cpp: 在namespace android中添加一行: int register_android_server_HETService(JNIEnv *env); 在JNI_onLoad方法中添加一行: register_android_server_HETService(env); 在同目录下修改Android.mk: LOCAL_SRC_FILES增加一行: $(LOCAL_REL_DIR)/com_android_server_HETService.cpp 在源码根目录下执行:mmm frameworks/base/services/core/jni 对该模块进行编译 |
|
|
|
二.编写系统服务JAVA代码
1.定义好服务可以调用的方法的aidl 在源码根目录下:frameworks/base/core/java/android/os/het 1)新建IHetService.aidl丶DeviceListenerEvent.aidl和IDeviceEventListener.aidl文件 2)修改frameworks/base下的Android.mk编译文件,在LOCAL_SRC_FILES中增加 core/java/android/os/IHetService.aidl和 core/java/android/os/het/IDeviceEventListener.aidl IHetService.aidl package android.os.het; import android.os.het.IDeviceEventListener; // Declare any non-default types here with import statements interface IHetService { /** * Demonstrates some basic types that you can use as parameters * and return values in AIDL. */ String setState(int type, int state); String getState(int type); boolean setDeviceEventListener(IDeviceEventListener listener); void release(); } DeviceListenerEvent.aidl package android.os.het; // Declare any non-default types here with import statements parcelable DeviceListenerEvent; IDeviceEventListener.aidl package android.os.het; import android.os.het.DeviceListenerEvent; // Declare any non-default types here with import statements interface IDeviceEventListener { /** * Demonstrates some basic types that you can use as parameters * and return values in AIDL. */ void onEvent (inout DeviceListenerEvent event); } 在源码根目录下执行:mmm frameworks/base 对该模块进行编译 2.实现DeviceListenerEvent.aidl和IDeviceEventListener.aidl的Java方法 2.1在源码根目录下:frameworks/base/core/java/android/os/het,编写DeviceEventListener.java和DeviceListenerEvent.java DeviceEventListener.java package android.os.het; /** * android.os.het * * 2020/6/29 */ public abstract class DeviceEventListener extends IDeviceEventListener.Stub { } DeviceListenerEvent.java package android.os.het; import android.os.Parcel; import android.os.Parcelable; /** * android.os.het.DeviceListenerEvent */ public class DeviceListenerEvent implements Parcelable { private int what; private String msg; public DeviceListenerEvent(int what, String msg) { this.what = what; this.msg = msg; } public DeviceListenerEvent(Parcel in) { what = in.readInt(); msg = in.readString(); } public void setWhat(int what) { this.what = what; } public void setMsg(String msg) { this.msg = msg; } public int getWhat() { return what; } public String getMsg() { return msg; } public static final Creator @Override public DeviceListenerEvent createFromParcel(Parcel in) { return new DeviceListenerEvent(in); } @Override public DeviceListenerEvent[] newArray(int size) { return new DeviceListenerEvent[size]; } }; @Override public int describeContents() { return 0; } @Override public void writeToParcel(Parcel dest, int flags) { dest.writeInt(what); dest.writeString(msg); } /** * 从parcel中读取,从parcel中读取,顺序与write一致 * 如果要支持为 out 或者 inout 的定向 tag 的话,需要实现 readFromParcel() 方法 * @param dest */ public void readFromParcel(Parcel dest) { what = dest.readInt(); msg = dest.readString(); } } 2.2编写HetManager.java提供给上层访问 HetManager.java package android.os.het; /** * ---------------------------------------------------------------- * Copyright (C) 2014-2020, by het, Shenzhen, All rights reserved. * ---------------------------------------------------------------- *
|
|
|
|
你正在撰写答案
如果你是对答案或其他答案精选点评或询问,请使用“评论”功能。
1988 浏览 1 评论
synopsys 的design ware:DW_fpv_div,浮点数除法器,默认32位下,想提升覆盖率(TMAX),如果用功能case去提升覆盖率呢?
2490 浏览 1 评论
RK3588 GStreamer调试四路鱼眼摄像头四宫格显示报错
5272 浏览 1 评论
【飞凌嵌入式OK3576-C开发板体验】RKNN神经网络-YOLO图像识别
254 浏览 0 评论
【飞凌嵌入式OK3576-C开发板体验】SSH远程登录网络配置及CAN通讯
1336 浏览 0 评论
小黑屋| 手机版| Archiver| 电子发烧友 ( 湘ICP备2023018690号 )
GMT+8, 2024-11-24 22:20 , Processed in 0.657097 second(s), Total 75, Slave 58 queries .
Powered by 电子发烧友网
© 2015 bbs.elecfans.com
关注我们的微信
下载发烧友APP
电子发烧友观察
版权所有 © 湖南华秋数字科技有限公司
电子发烧友 (电路图) 湘公网安备 43011202000918 号 电信与信息服务业务经营许可证:合字B2-20210191 工商网监 湘ICP备2023018690号