Android 驱动开发系列三

写blog的时候,发现跳章了,HAL硬件抽象层都没有写就到JNI了,这里补回来。

 

1、添加HAL头文件

进入到 android-4.0.4_r1.2/hardware/libhardware/include/hardware 目录,创建 ttt.h 文件:

root@brantyou-ubuntu:~/workspace/android-4.0.4_r1.2/hardware/libhardware/include/hardware# gedit ttt.h

文件内容如下:

#ifndef	ANDROID_TTT_INTERFACE_H
#define	ANDROID_TTT_INTERFACE_H
#include <hardware/hardware.h>

__BEGIN_DECLS

// 定义模块ID
#define	HELLO_HARDWARE_MODULE_ID	"ttt"

// 硬件模块结构体
struct ttt_module_t{
    struct hw_module_t common;
};

// hardware interface struct
struct ttt_device_t{
	struct hw_device_t common;
	int fd;
	int(*set_val)(struct ttt_device_t* dev, int val);
	int(*get_val)(struct ttt_device_t* dev, int* val);
};

__END_DECLS


#endif

这里按照Android硬件抽象层规范的要求,分别定义模块ID、模块结构体以及硬件接口结构体。

2、实现HAL

进入android-4.0.4_r1.2/hardware/libhardware/modules 目录,创建 ttt 目录:

root@brantyou-ubuntu:~/workspace/android-4.0.4_r1.2/hardware/libhardware/modules# mkdir ttt

进入到新创建的ttt目录下面,并创建 ttt.c 文件:

root@brantyou-ubuntu:~/workspace/android-4.0.4_r1.2/hardware/libhardware/modules/ttt# gedit ttt.c

其内容如下:

#define	LOG_TAG		"TTTStub"

#include <hardware/hardware.h>
#include <hardware/ttt.h>
#include <fcntl.h>
#include <errno.h>
#include <cutils/log.h>
#include <cutils/atomic.h>

#define	DEVICE_NAME	"/dev/ttt"
#define	MODULE_NAME	"TTT"
#define	MODULE_AUTHOR	"[email protected]"

// open/close device interface
static int ttt_device_open(const struct hw_module_t* module, const char* name, struct hw_device_t** device);
static int ttt_device_close(struct hw_device_t* device);

// device interfaces
static int ttt_set_val(struct ttt_device_t* dev, int val);
static int ttt_get_val(struct ttt_device_t* dev, int* val);

// module methods
static struct hw_module_methods_t ttt_module_methods = {
	open: ttt_device_open
};

// module variables
const struct ttt_module_t HAL_MODULE_INFO_SYM = {
	common: {
		tag: HARDWARE_MODULE_TAG,
		version_major: 1,
		version_minor: 0,
		id: HELLO_HARDWARE_MODULE_ID,
		name: MODULE_NAME,
		author: MODULE_AUTHOR,
		methods: &ttt_module_methods,
	}
};


// * device set value interface
static int ttt_set_val(struct ttt_device_t* dev, int val)
{
    LOGI("TTT Stub: set value %d to device.", val);

    write(dev->fd, &val, sizeof(val));

    return 0;
}

// * device get value interface
static int ttt_get_val(struct ttt_device_t* dev, int* val)
{
    if(!val){
        LOGE("TTT Stub: error val pointer.");
        return -EFAULT;
    }

    read(dev->fd, val, sizeof(*val));
    LOGI("TTT Stub: get value %d from device.", *val);

    return 0;
}

// * close device interface
static int ttt_device_close(struct hw_device_t* device)
{
    struct ttt_device_t* ttt_device = (struct ttt_device_t*)device;

    if(ttt_device){
        close(ttt_device->fd);
        free(ttt_device);
    }

    return 0;
}

// * open device interface
static int ttt_device_open(const struct hw_module_t* module, const char* name, struct hw_device_t** device)
{
	struct ttt_device_t* dev;
	dev = (struct ttt_device_t*)malloc( sizeof(struct ttt_device_t) );

	if(!dev){
		LOGE("TTT stub: failed to alloc space");
		return -EFAULT;
	}

	memset(dev, 0, sizeof(struct ttt_device_t));
	dev->common.tag = HARDWARE_DEVICE_TAG;
	dev->common.version = 0;
	dev->common.module = (hw_module_t*)module;
	dev->common.close = ttt_device_close;
	dev->set_val = ttt_set_val;
	dev->get_val = ttt_get_val;

	if( (dev->fd = open(DEVICE_NAME, O_RDWR)) == -1){
	    LOGE("TTT Stub: failed to open /dev/ttt -- %s.", strerror(errno));
	    free(dev);
	    return -EFAULT;
	}

	*device = &(dev->common);
    LOGI("TTT Stub: open /dev/ttt successfully.");

    return 0;
}


在该目录下创建对应的Android.mk文件:

root@brantyou-ubuntu:~/workspace/android-4.0.4_r1.2/hardware/libhardware/modules/ttt# gedit 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 := ttt.c
LOCAL_MODULE := ttt.default
include $(BUILD_SHARED_LIBRARY)

 


3、添加权限

由于设备文件是在内核驱动里面通过 device_create 创建的,而 device_create 创建的设备文件默认只有 root 用户

可读写,而 ttt_device_open 一般是由上层APP来调用的,这些 APP 一般不具有 root 权限,这时候就有可能导致打开设备文件失败,提示类似于:

Permission denied.

解决办法是类似 linux 的udev 规则,

进入到 android-4.0.4_r1.2/system/core/rootdir 目录,打开 uenentd.rc 文件:

root@brantyou-ubuntu:~/workspace/android-4.0.4_r1.2/system/core/rootdir# gedit ueventd.rc

在里面添加一句:

/dev/ttt                  0666   root       root



4、开始编译


执行命令如下:

root@brantyou-ubuntu:~/workspace/android-4.0.4_r1.2# mmm hardware/libhardware/modules/ttt
============================================
PLATFORM_VERSION_CODENAME=REL
PLATFORM_VERSION=4.0.4
TARGET_PRODUCT=full_smdkv210
TARGET_BUILD_VARIANT=eng
TARGET_BUILD_TYPE=release
TARGET_BUILD_APPS=
TARGET_ARCH=arm
TARGET_ARCH_VARIANT=armv7-a-neon
HOST_ARCH=x86
HOST_OS=linux
HOST_BUILD_TYPE=release
BUILD_ID=IMM76I
============================================
make:进入目录'/home/brantyou/workspace/android-4.0.4_r1.2'
target thumb C: ttt.default <= hardware/libhardware/modules/ttt/ttt.c
target SharedLib: ttt.default (out/target/product/smdkv210/obj/SHARED_LIBRARIES/ttt.default_intermediates/LINKED/ttt.default.so)
target Symbolic: ttt.default (out/target/product/smdkv210/symbols/system/lib/hw/ttt.default.so)
target Strip: ttt.default (out/target/product/smdkv210/obj/lib/ttt.default.so)
Install: out/target/product/smdkv210/system/lib/hw/ttt.default.so
make:离开目录“/home/brantyou/workspace/android-4.0.4_r1.2”
root@brantyou-ubuntu:~/workspace/android-4.0.4_r1.2# 

重新打包system.img:

root@brantyou-ubuntu:~/workspace/android-4.0.4_r1.2# make snod
============================================
PLATFORM_VERSION_CODENAME=REL
PLATFORM_VERSION=4.0.4
TARGET_PRODUCT=full_smdkv210
TARGET_BUILD_VARIANT=eng
TARGET_BUILD_TYPE=release
TARGET_BUILD_APPS=
TARGET_ARCH=arm
TARGET_ARCH_VARIANT=armv7-a-neon
HOST_ARCH=x86
HOST_OS=linux
HOST_BUILD_TYPE=release
BUILD_ID=IMM76I
============================================
build/core/Makefile:25: 警告:覆盖关于目标“out/target/product/smdkv210/system/bin/pppd”的命令
build/core/base_rules.mk:523: 警告:忽略关于目标“out/target/product/smdkv210/system/bin/pppd”的旧命令
make snod: ignoring dependencies
Target system fs image: out/target/product/smdkv210/system.img
out/target/product/smdkv210/system.img total size is 150853824
root@brantyou-ubuntu:~/workspace/android-4.0.4_r1.2# 




 

到此,HAL层的就编写完了,下一篇就是编写对应的JNI接口了。

 

你可能感兴趣的:(android,驱动)