This essay, I go to a deeply studying to android HAL device driver program.

  

  According to the android architecture we disscus in last essay, when we are designing a android device driver, we should follow the steps below :

  (1) linux device driver

  In this driver, we should try our best to cut down the mechanism and change them to be more concise.

  (2) HAL libraries

  The HAL serves as a standard interface that allows the Android system to call into the device driver layer while being agnostic about the lower-level implementations of your drivers and hardware.

  (3)Service libraries

  System service access the hardware in HAL libraries and provide the APIs for android framework. Service libraries usually are JNI libraries or Linux libraries.

  1、linux device driver

//s3c6410_leds_hal.c
#include <linux/fs.h>
#include <linux/cdev.h>
#include <linux/pci.h>
#include <asm/uaccess.h>
#include <mach/map.h>
#include <mach/regs-gpio.h>
#include <mach/gpio-bank-m.h> #define DEVICE_NAME "s3c6410_leds_hal"
#define DEVICE_COUNT 1
#define S3C6410_LEDS_MAJOR 0
#define S3C6410_LEDS_MINOR 234 static unsigned char mem[];
static int major = S3C6410_LEDS_MAJOR;
static int minor = S3C6410_LEDS_MINOR;
static dev_t leds_number;
static struct class *leds_class = NULL; static void write_io(unsigned char buf[])
{
int i;
unsigned int tmp;
tmp = ioread32(S3C64XX_GPMDAT);
for (i = ; i < ; i++) {
if (buf[i] == '') {
tmp &= (~( << i));
} else {
tmp |= ( << i);
}
}
iowrite32(tmp, S3C64XX_GPMDAT);
} static ssize_t s3c6410_leds_hal_write(struct file *filp,
const char __user *buf, size_t count, loff_t *ppos)
{
unsigned int tmp = count; if (count > ) {
tmp = ;
} if (copy_from_user(mem, buf, tmp)) {
return -EFAULT;
} else {
write_io(mem);
}
return count;
} static struct file_operations leds_fops = {
.owner = THIS_MODULE,
.write = s3c6410_leds_hal_write,
};
static struct cdev leds_cdev; static int leds_create_device(void)
{
int ret = ;
int err = ; cdev_init(&leds_cdev, &leds_fops);
leds_cdev.owner = THIS_MODULE;
if (major > ) {
leds_number = MKDEV(major, minor);
err = register_chrdev_region(leds_number, DEVICE_COUNT, DEVICE_NAME);
if (err < ) {
printk(KERN_WARNING "register_chardev_region() failed.\n");
return err;
}
} else {
err = alloc_chrdev_region(&leds_cdev.dev, ,
DEVICE_COUNT, DEVICE_NAME);
if (err < ) {
printk(KERN_WARNING "register_chardev_region() failed.\n");
return err;
}
major = MAJOR(leds_cdev.dev);
minor = MINOR(leds_cdev.dev);
leds_number = leds_cdev.dev;
} ret = cdev_add(&leds_cdev, leds_number, DEVICE_COUNT);
leds_class = class_create(THIS_MODULE, DEVICE_NAME);
device_create(leds_class, NULL, leds_number, NULL, DEVICE_NAME);
return ret; } static int leds_init(void)
{
int ret;
ret = leds_create_device();
printk(DEVICE_NAME "\tinitialized.\n"); return ret;
} static void leds_exit(void) {
device_destroy(leds_class, leds_number);
if (leds_class) {
unregister_chrdev_region(leds_number, DEVICE_COUNT);
return;
}
printk(DEVICE_NAME"\texit.\n");
} module_init(leds_init);
module_exit(leds_exit); MODULE_LICENSE("GPL");

  Yes, this file is the same as the previous driver file, because there aren't any business-related codes in this simple led driver.

  Then we focus more in the HAL libraries and Service libraries coding.

  2、HAL libraries

  HAL modules would be compile to a Linux shared library (*.so), and these *.so files could be automaticlly loaded by android system.

  Each HAL module should provide a variable for android system loading : HAL_MODULE_INFO_SYM (never change it.)  

//Android.mk
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS) LOCAL_PRELINK_MODULE := false
LOCAL_MODULE_PATH := $(TARGET_OUT_SHARED_LIBRARIES)/hw
LOCAL_SHARED_LIBRARIES := liblog
LOCAL_SRC_FILES := leds_hal.c
LOCAL_MODULE := leds_hal.default
LOCAL_MODULE_TAGS := eng
include $(BUILD_SHARED_LIBRARY) //leds_hal.h
#include <hardware/hardware.h>
#include <fcntl.h>
#include <cutils/log.h> struct leds_module_t {
struct hw_module_t hw_module;
}; struct leds_device_t {
struct hw_device_t hw_device;
int (*set_on)(struct leds_device_t *dev, int32_t led);
int (*set_off)(struct leds_device_t *dev, int32_t led);
}; #define LED_HARDWARE_MODULE_ID "leds_hal"
//leds_hal.c
#include "leds_hal.h" int fd_leds = ; int leds_switch(struct leds_device_t *dev, int32_t led, int32_t on_off)
{
unsigned char buf[]; if (led < && led > ) {
LOGI("Led Stub : no this led.\n");
return -;
} if (on_off == ) {
LOGI("Led Stub : set %d led on", led);
buf[led] = '';
} else {
LOGI("Led Stub : set %d led off", led);
buf[led] = '';
} write(fd_leds, buf, );
return ;
} int leds_on(struct leds_device_t *dev, int32_t led)
{
return leds_switch(dev, led, );
} int leds_off(struct leds_device_t *dev, int32_t led)
{
return leds_switch(dev, led, );
} int leds_device_close(struct hw_device_t *device)
{
struct leds_device_t *ldt = (struct leds_device_t *) device; if (ldt)
free(ldt); close(fd_leds);
return ;
} static int leds_device_open(const struct hw_module_t *module, const char *name,
struct hw_device_t **device)
{
struct leds_device_t *leds_dev;
leds_dev = (struct leds_device_t *) malloc(sizeof(*leds_dev)); memset(leds_dev, , sizeof(*leds_dev)); leds_dev->hw_device.tag = HARDWARE_DEVICE_TAG;
leds_dev->hw_device.version = ;
leds_dev->hw_device.module = (struct hw_module_t *) module;
leds_dev->hw_device.close = leds_device_close;
leds_dev->set_on = leds_on;
leds_dev->set_off = leds_off; *device = (hw_device_t *) leds_dev; fd_leds = open("/dev/s3c6410_leds_hal", O_RDWR); if (fd_leds < ) {
LOGI("Led Stub : open /dev/s3c6410_leds_hal fail.\n");
} else {
LOGI("Led Stub : open /dev/s3c6410_leds_hal success.\n");
} return ;
} static struct hw_module_methods_t leds_module_methods = {
.open = leds_device_open
}; struct leds_module_t HAL_MODULE_INFO_SYM = {
hw_module : {
tag: HARDWARE_MODULE_TAG,
version_major: ,
version_minor: ,
id: LED_HARDWARE_MODULE_ID,
name: "Led HAL Stub",
methods: &leds_module_methods,
}
};

  Acturely, in this simple leds HAL module, we didn't get much messages about "business-related", but we can treat the leds switch functions as.

  And the more important messages we need to know are listing follow :

HAL_MODULE_INFO_SYM
hw_module_t
hw_device_t
hw_module_methods_t

  Ok, let's stop here. I wanna to talk some more about the module both in linux and android.

  In my opnions, there are a lot of design logic share with this two system.

  (1) linux

  In the picture, we can see what we should do to design a device driver :

  Create a entrance function;

  Declare a basic struct;

  Extand the struct with special operations.

  (2) android

  In the picture, we can see the android HAL is the same as linux device driver in the three absractions :

  Entrance, basic struct, expend struct.

  Then I will discuss the different between the two system ;

  [ Entrance ]

// We use functions to build the device driver in linux
module_init(leds_init); // The entrance is a variable HAL_MODULE_INFO_SYM automaticlly loaded by the system
struct leds_module_t HAL_MODULE_INFO_SYM = {
hw_module : {
tag: HARDWARE_MODULE_TAG,
version_major: ,
version_minor: ,
id: LED_HARDWARE_MODULE_ID,
name: "Led HAL Stub",
methods: &leds_module_methods,
}
};

  [ Basic Struct ]

// Basic struct in linux is a structure, we use the "struct" to create our device
static struct cdev leds_cdev; // Basic struct in android is a structure with function open, we use the "function" to create our device
static int leds_device_open(const struct hw_module_t *module, const char *name,
struct hw_device_t **device)
{
struct leds_device_t *leds_dev;
leds_dev = (struct leds_device_t *) malloc(sizeof(*leds_dev)); memset(leds_dev, , sizeof(*leds_dev)); leds_dev->hw_device.tag = HARDWARE_DEVICE_TAG;
leds_dev->hw_device.version = ;
leds_dev->hw_device.module = (struct hw_module_t *) module;
leds_dev->hw_device.close = leds_device_close;
leds_dev->set_on = leds_on;
leds_dev->set_off = leds_off; *device = (hw_device_t *) leds_dev; fd_leds = open("/dev/s3c6410_leds_hal", O_RDWR); if (fd_leds < ) {
LOGI("Led Stub : open /dev/s3c6410_leds_hal fail.\n");
} else {
LOGI("Led Stub : open /dev/s3c6410_leds_hal success.\n");
} return ;
}

  [ Extend Struct ]

// The extend struct means the functions include in file_operations, we have to build the callback functions in linux.
static struct file_operations leds_fops = {
.owner = THIS_MODULE,
.write = s3c6410_leds_hal_write,
}; // Instead of using the prototype, the HAL specification suggest us to create two new struct with the first element hw_module_t/hw_device_t in android.
// We can see that it is useless to create a struct in a prototype to hw_device_t, because there is no callback functions in this struct.
// If we want to extend the hw_device_t, we should create the new struct as the substruct of hw_device_t
struct leds_device_t {
struct hw_device_t hw_device;
int (*set_on)(struct leds_device_t *dev, int32_t led);
int (*set_off)(struct leds_device_t *dev, int32_t led);
};

  After compiling, we should push the leds_hal.default.so to dir /system/lib/hw in ok6410.

  I will discuss the "Service libraries" in next essay.

  

  

  

ok6410 android driver(11)的更多相关文章

  1. ok6410 android driver(5)

    Test the android driver by JNI (Java Native Interface), In the third article, we know how to compile ...

  2. ok6410 android driver(9)

    In this essay, I will write the JNI to test our leds device. If you don't know how to create a jni p ...

  3. ok6410 android driver(8)

    In the past, we know how to create and run a simple character device driver on pc, goldfish and ok64 ...

  4. ok6410 android driver(3)

    This article discusses the Makefile and how to port the module to different platform (localhost and ...

  5. ok6410 android driver(12)

    In this essay, I will talk about how to write the service libraries. TIPS : I won't discuss the name ...

  6. ok6410 android driver(10)

    From this essay, we go to a new discussion "Android Hardware Abstraction Layer". In this e ...

  7. ok6410 android driver(7)

    This article talk about how to test device driver on JNI. There are two ways to test the device driv ...

  8. ok6410 android driver(6)

    This is a short essay about the mistakes in compiling ok6410 android-2.3 source codes. If there is n ...

  9. ok6410 android driver(1)

    target system : Android (OK6410) host system : Debian Wheezy AMD64 1.Set up android system in ok6410 ...

随机推荐

  1. 互联网的寒冬来了,BAT都不社招了

    一 总理上次来到创业街,是四个月,要不就是五个月前了. 之后,全国创业形势一路走红,锣鼓喧天鞭炮齐鸣.大众创业万众创新,颇有大炼钢铁亩产万斤之势,尤其在媒体上. 再之后,2015 进入下半年,风投圈的 ...

  2. 山寨版Quartz.Net任务统一调度框架

    TaskScheduler 在日常工作中,大家都会经常遇到Win服务,在我工作的这些年中一直在使用Quartz.Net这个任务统一调度框架,也非常好用,配置简单,但是如果多个项目组的多个服务部署到一台 ...

  3. Road to the future——伪MVVM库Q.js

    模仿Vuejs的伪MVVM库,下面是使用说明 项目地址:https://github.com/miniflycn/Q.js 相关项目:https://github.com/miniflycn/Ques ...

  4. 用etckeeper来解救运维工程师

    对于运维工程师来讲,etc环境是一个痛点,各种配置,各种修改,某些软件的配置关联因素过多的话,那就更加痛苦了,改完发现不对再想改回去都千难万难, 现在有一个好的解决方案,那就是用etckeeper,绝 ...

  5. 搞不清FastCgi与PHP-fpm之间是个什么样的关系(转载)

    刚开始对这个问题我也挺纠结的,看了<HTTP权威指南>后,感觉清晰了不少. 首先,CGI是干嘛的?CGI是为了保证web server传递过来的数据是标准格式的,方便CGI程序的编写者. ...

  6. 正则指引-字符组demo

    class Program { static void Main(string[] args) { string str = "b"; var result1 = Regex.Is ...

  7. Google 面试题:Java实现用最大堆和最小堆查找中位数 Find median with min heap and max heap in Java

    Google面试题 股市上一个股票的价格从开市开始是不停的变化的,需要开发一个系统,给定一个股票,它能实时显示从开市到当前时间的这个股票的价格的中位数(中值). SOLUTION 1: 1.维持两个h ...

  8. iOS开发——高级技术精选&底层开发之越狱开发第一篇

    底层开发之越狱开发第一篇 做越狱开发也有一些时间了,有很多东西想总结一下,希望给他人一些借鉴,也是自己对过去开发经历的一些总结.个人不推荐使用盗版,这里主要以技术介绍为主. 这个系列里面主要介绍怎样进 ...

  9. 水晶报表设置FiledObject支持HTML格式的数据

    经常遇见把数据拼接成html格式后,然后在水晶报表中按照这种格式进行展现. 这就需要我们对次FiledObject设置成html文本: 设置方式: 格式编辑器->段落->文本解释,然后选择 ...

  10. 解决企业In-House安装APP需HTTPS支持的问题(转载)

    同事写的一篇文章,感觉不错,转过来. 解决企业In-House安装APP需HTTPS支持的问题 问题背景: 能否通过应用服务器发布企业应用: 解决iOS7.1后,发布地址必须为HTTPS服务器. 写作 ...