本文是学习罗升阳的《安卓系统源代码情景分析》的笔记和总结
感觉这块主要就是要理解hw_module、hw_module_methods_t、hw_device之间的关系。
思路:hw_module主要是通过hw_module_mehtods_t根据具体的device id打开具体的hw_device,其中hw_device是对底层的驱动文件的抽象,hw_device里面可以自定义一些方法来对底层驱动进行操作,这样一来,在用户空间操作hw_device就相当于操作了内核空间的底层驱动,形成这样的调用关系hw_module---->hw_device----->底层驱动,注意hw_device由hw_module打开,关闭的方法则是自带的,关系图如下:
代码的具体位置和老罗的没区别,主要是头文件改动了些,然后device的名字等也有改变
hardware/libhardware/include/hardware/freg.h
#ifndef ANDROID_FREG_INTERFACE_H
#define ANDROID_FREG_INTERFACE_H
#include <hardware/hardware.h>
__BEGIN_DECLS
/*第一步:自定义模块和设备结构体
*
*类似于java里面的新建一个类(比如这里的freg_module_t)继承某个类(比如
*这里的hw_module_t),只不过在c中没有继承这一说法,所以采用结构体包含
*结构体的方法实现
*/
struct freg_module_t {
struct hw_module_t moduleBase;
};
struct freg_device_t{
struct hw_device_t deviceBase;
int fd;
int (* set_val) (struct freg_device_t * dev ,int val );
int (* get_val) (struct freg_device_t * dev , int * val);
};
__END_DECLS
#endif
hardware/libhardware/modules/freg/freg.cpp
#define LOG_TAG "FregStub"
#include <hardware/hardware.h>
#include <hardware/freg.h>
#include <fcntl.h>
#include <errno.h>
#include <cutils/log.h>
#include <cutils/atomic.h>
#define FREG_MODULE_NAME "Freg"
#define FREG_MODULE_ID "freg_module"
#define FREG_DEVICE_NAME "/dev/myfreg"
#define FREG_DEVICE_ID "freg_device"
/*设备打开、关闭函数*/
static int freg_device_open (const struct hw_module_t* module, const char* id,
struct hw_device_t** device);
static int freg_device_close (struct hw_device_t* device);
static int freg_set_val (struct freg_device_t * dev ,int val );
static int freg_get_val (struct freg_device_t * dev , int * val);
/*模块操作方法结构体变量,就是通过open成员方法把module和device联系起来的*/
static struct hw_module_methods_t module_methods ={
open : freg_device_open
};
/*这里类似于java中的创建一个类的对象并初始化*/
struct freg_module_t HAL_MODULE_INFO_SYM ={
moduleBase : {
tag : HARDWARE_MODULE_TAG,
version_major : 1,
version_minor : 0,
id : FREG_MODULE_ID,
name : FREG_MODULE_NAME,
author: "wanglx", //不初始化会报错
methods : &module_methods,
dso : NULL, //不初始化会报错
reserved :{0} , //不初始化会报错
}
};
static int freg_device_open (const struct hw_module_t* module, const char* id,
struct hw_device_t** device)
{
if(!strcmp(id,FREG_DEVICE_ID))
{
//初始化device
struct freg_device_t * dev;
dev=(struct freg_device_t *)malloc(sizeof(struct freg_device_t));
if(!dev){
LOGE("Failed to alloc space for freg_device_t");
return -EFAULT;
}
memset(dev,0,sizeof(struct freg_device_t));
dev->deviceBase.tag =HARDWARE_DEVICE_TAG;
dev->deviceBase.version=0;
dev->deviceBase.module =(hw_module_t *)module;
dev->deviceBase.close= freg_device_close;
dev->get_val = freg_get_val;
dev->set_val =freg_set_val ;
if((dev->fd =open(FREG_DEVICE_NAME,O_RDWR))==-1){
LOGE("Failed to open freg_device");
free(dev);
return -EFAULT;
}
*device =&(dev->deviceBase);
LOGE("success to open freg_device");
return 0;
}
return -EFAULT;
}
static int freg_device_close (struct hw_device_t* device)
{
//这里传入hw_device_t的指针类型,下面再进行强制类型转化增加了这个函数的复用性
struct freg_device_t * freg_device =(struct freg_device_t *)device;
if(freg_device)
{
close(freg_device->fd);
free(freg_device);
}
return 0;
}
static int freg_set_val (struct freg_device_t * dev ,int val )
{
if(!dev){
LOGE("Null dev pointer");
return -EFAULT;
}
write(dev->fd,&val,sizeof(val));
return 0;
}
static int freg_get_val (struct freg_device_t * dev , int * val)
{
if(!dev){
LOGE("Null dev pointer");
return -EFAULT;
}
if(!val){
LOGE("Null val pointer");
return -EFAULT;
}
read(dev->fd,val,sizeof(*val));
return 0;
}
Android.mk:
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE_TAGS := optional
LOCAL_PRELINK_MODULE := false
LOCAL_MODULE_PATH := $(TARGET_OUT_SHARED_LIBRARIES)/hw
LOCAL_SHARED_LIBRARIES := liblog
LOCAL_SRC_FILES := freg.cpp
#注意这里的名字是freg_module,也就是MODULE_ID
LOCAL_MODULE := freg_module.default
include $(BUILD_SHARED_LIBRARY)
这里要主要mk文件里面MODULE的名字要和MODULE_ID对应
结果: