Android开发之应用层到驱动层的接口实现(一)
来源:互联网 发布:企业审计软件 编辑:程序博客网 时间:2024/04/18 05:20
应用层到驱动层的接口实现(一)
----硬件抽象层
该系列的文章主要是介绍实现从应用层(app)实现对硬件驱动层的访问,也就是通过读写文件节点的方式,访问Linux内核驱动程序。
在这便文章中介绍的是第一部分:即如何在硬件抽象层中增加硬件模块来和内核驱动程序交互。主要通过android项目翻盖机如果有子屏的话对后屏(sublcd)进行驱动操作(打开关闭)。
一、添加sublcd.h文件
1.1、文件目录:
/hardware/libhardware/include/hardware/
1.2、sublcd.h文件内容:
#ifndef ANDROID_SUBLCD_INTERFACE_H#define ANDROID_SUBLCD_INTERFACE_H#include <hardware/hardware.h>__BEGIN_DECLS/*定义模块 ID*/#define SUBLCD_HARDWARE_MODULE_ID "sublcd"/*硬件模块结构体*/struct sublcd_module_t {struct hw_module_t common;};/*硬件接口结构体*/struct sublcd_device_t {struct hw_device_t common;int fd;int (*set_val)(struct sublcd_device_t* dev, int val);int (*get_val)(struct sublcd_device_t* dev, int* val);};__END_DECLS#endif
1.3、代码解释:
这里的数据结构定义完全按照Android硬件抽象层规范的要求,分别定义模块ID、模块结构体以及硬件接口结构体。在硬件接口结构体中,fd表示设备文件描述符,对应我们将要处理的设备文件节点"/sys/class/ktd20xx/ktd2026/back_light_led",set_val和get_val为该HAL对上提供的函数接口。
模块ID的名字是生成的.so文件的前缀名,在framework层就是通过模块ID(SUBLCD_HARDWARE_MODULE_ID)去寻找生成的.so文件。所以该ID必须和后面要介绍到的sublcd目录下的Android.mk中定义的LOCAL_MODULE名字(前缀)一致,否则会导致在framework层往下调用HAL层定义的函数接口时失败。
二、添加sublcd文件夹
2.1、文件目录:
/hardware/libhardware/modules/
2.2、/sublcd/sublcd.c文件内容:
//相关头文件#define LOG_TAG "SubLcdStub"#include <hardware/hardware.h>#include <hardware/sublcd.h>#include <fcntl.h>#include <errno.h>#include <cutils/log.h>#include <cutils/atomic.h>
//相关数据结构与宏的定义及函数声明#define DEVICE_NAME "/sys/class/ktd20xx/ktd2026/back_light_led"#define MODULE_NAME "Sublcd"#define MODULE_AUTHOR "xiangang.zhu@tcl.com"static int light_sublcd();static int died_sublcd();/*Open and close sublcd device*/static int sublcd_device_open(const struct hw_module_t* module, const char* name, struct hw_device_t** device);static int sublcd_device_close(struct hw_device_t* device);/*Point to Interface*/static int sublcd_set_val(struct sublcd_device_t* dev, int val);static int sublcd_get_val(struct sublcd_device_t* dev, int* val);/*Table of Module*/static struct hw_module_methods_t sublcd_module_methods = {open: sublcd_device_open};struct sublcd_module_t HAL_MODULE_INFO_SYM = {common: {tag: HARDWARE_MODULE_TAG,version_major: 1,version_minor: 0,id: SUBLCD_HARDWARE_MODULE_ID,name: MODULE_NAME,author: MODULE_AUTHOR,methods: &sublcd_module_methods,}};
//打开和关闭文件节点方法定义(包括相关数据结构初始化)static int sublcd_device_open(const struct hw_module_t* module, const char* name, struct hw_device_t** device) {ALOGI("SublcdStub: Sublcd_device_open");struct sublcd_device_t* dev;dev = (struct sublcd_device_t*)malloc(sizeof(struct sublcd_device_t));if(!dev) {ALOGI("SublcdStub: failed to alloc space");return -EFAULT;}memset(dev, 0, sizeof(struct sublcd_device_t));dev->common.tag = HARDWARE_DEVICE_TAG;dev->common.version = 0;dev->common.module = (hw_module_t*)module;dev->common.close = sublcd_device_close;dev->set_val = sublcd_set_val;dev->get_val = sublcd_get_val;if((dev->fd = open(DEVICE_NAME, O_RDWR)) == -1) {ALOGI("SublcdStub: failed to open /dev/graphics/fb2 -- %s.", strerror(errno));free(dev);return -EFAULT;}*device = &(dev->common);ALOGI("SublcdStub: open /dev/graphics/fb2 successfully.");return 0;}static int sublcd_device_close(struct hw_device_t* device){ALOGI("SublcdStub: sublcd_device_close");struct sublcd_device_t* sublcd_device = (struct sublcd_device_t*)device;if(sublcd_device) {close(sublcd_device->fd);free(sublcd_device);}return 0;}
//往上(HAL)接口函数和文件系统节点操作函数具体定义static int sublcd_set_val(struct sublcd_device_t* dev, int val) {int iflight,ifsublcdTest;if(iflight = light_sublcd() == -1){ALOGI("SublcdStub: iflight == -1");return -EFAULT;}return 0;}static int sublcd_get_val(struct sublcd_device_t* dev, int* val) {int ifdied_sublcd,ifsublcdTest_exit;if(ifdied_sublcd = died_sublcd() == -1){ALOGI("SublcdStub: iflight == -1");return -EFAULT;}return 0;}static int light_sublcd(){char *aa = "200";int back_fd = -1; back_fd = open(DEVICE_NAME, O_RDWR); if (back_fd < 0) {ALOGI("SublcdStub: light_sublcd failed");return -EFAULT; } write(back_fd, aa, 3); if(back_fd){ close(back_fd); } return 0;}static int died_sublcd(){char *aa = "0";int back_fd = -1; back_fd = open(DEVICE_NAME, O_RDWR); if (back_fd < 0) {ALOGI("SublcdStub: died_sublcd failed");return -EFAULT; } write(back_fd, aa, 1); if(back_fd){ close(back_fd); } return 0;}
以上便是sublcd.c的全部内容,主要是定义相关方法接口供framework层调用驱动,并实现对内核驱动程序的访问。
需要注意的是:
open函数直接打开的是文件系统节点,当打开失败的时候返回的值<0,可以此判断open函数是否成功。open函数的第二个参数是文件系统节点的打开方式权限定义,其中:O_RDONLY(只读)、O_WRONLY(只写)、O_RDWR(可读可写)……
write函数是对文件系统节点写入需要写入的值,需要注意的是第一个参数是open函数的返回,第二个参数是需要写入的值,是字符串类型,最后一个参数是该段字符串的长度。Write函数的返回值是该函数的最后一个参数。
2.3、/sublcd/Android.mk文件内容:
#android.mkLOCAL_PATH := $(call my-dir)include $(CLEAR_VARS)LOCAL_MODULE_TAGS := optionalLOCAL_PRELINK_MODULE := falseLOCAL_MODULE_PATH := $(TARGET_OUT_SHARED_LIBRARIES)/hwLOCAL_SHARED_LIBRARIES := liblogLOCAL_SRC_FILES := sublcd.cLOCAL_MODULE := sublcd.defaultinclude $(BUILD_SHARED_LIBRARY)
需要注意的是LOCAL_MODULE:= sublcd.default中sublcd便是上面所提到的模块ID,需要对应。
三、修改Android.mk文件
3.1、文件目录
/hardware/libhardware/modules/Android.mk
3.2、修改内容:
hardware_modules := ……sublcd ……
说明:在hardware_modules下添加对新增文件sublcd的编译。
至此便实现了硬件抽象层的方法接口,到hardware/libhardware/modules/sublcd下执行mm编译会在out/target/product/(projectName)/system/lib/hw生成sublcd.default.so。可使用adbpush直接导入到手机的/system/lib/hw/下,或者执行makesnod重新打包system.img,导入手机。
附:
问题:HelloStub: failed to open /dev/hello -- Permission denied.
解决:解决办法是类似于Linux的udev规则,打开Android源代码工程目录下,进入到system/core/rootdir目录,里面有一个名为ueventd.rc文件,往里面添加一行:
/dev/hello0666 root root
以上是在驱动层的接口实现,在上层(应用层)怎么去调用这边封装好的接口呢?请参加下篇Bolg介绍:
· 应用层到驱动层的接口实现(二) ---- 应用框架层&&app应用层
- Android开发之应用层到驱动层的接口实现(一)
- Android开发之应用层到驱动层的接口实现(二)
- s5p4418 Android 4.4.2 驱动层 HAL层 服务层 应用层 开发流程记录(一 硬件驱动层)
- 应用层到驱动层
- linux驱动层到应用层的重要接口sys文件系统---/sys目录详解
- Android应用层到Framework到HAL再到驱动层的整个流程分析
- 写陀螺仪smi130的驱动,以及hardware 层的接口之驱动(一)
- s5p4418 Android 4.4.2 驱动层 HAL层 服务层 应用层 开发流程记录(三 APP应用)
- 从驱动层到应用层打通Android系统通路
- 应用层对i2c通用驱动接口与eeprom的i2c驱动接口从应用层到内核层调用区别和联系
- 从应用层的mmap到驱动层的mmap
- android开发---8.framework层的java应用接口demo
- android soundrecorder之二 应用层到HAL实现
- android soundrecorder之二 应用层到HAL实现
- Android应用开发 led 驱动层 hal硬件抽象层 应用层 详细教程记录(含源码)
- 驱动层与应用层通信的实现
- android平台led开发之内核硬件驱动层(一)
- Android从驱动层到应用程序层的通信
- 未能加载文件或程序集“System.Web.WebPages.Razor, Version=2.0.0.0, Culture=neutral, PublicKeyToken=31bf3856a...
- 守护进程原理分析以及linux下的daemon函数使用
- 面试题-螺旋队列
- Python 基础知识点 001
- 设计模式六大原则之三:依赖倒置原则
- Android开发之应用层到驱动层的接口实现(一)
- Office365批量分配许可(License)
- java代码实现打印菱形
- Pycharm连接Oracle数据库
- 在 Android Native 程序中输出 LOG
- sql:常用sql语句整理二 (连接查询)
- 使用Thrift的网络框架搭建一般性网络应用
- 阅读笔记_《effective-csharp》
- Python MySQLdb连接数据库的应用