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 234static unsigned char mem[4];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 = 0; i < 4; i++) {        if (buf[i] == '1') {            tmp &= (~(1 << i));        } else {            tmp |= (1 << 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 > 4) {        tmp = 4;        }    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 = 0;    int err = 0;    cdev_init(&leds_cdev, &leds_fops);    leds_cdev.owner = THIS_MODULE;    if (major > 0) {        leds_number = MKDEV(major, minor);        err = register_chrdev_region(leds_number, DEVICE_COUNT, DEVICE_NAME);        if (err < 0) {            printk(KERN_WARNING "register_chardev_region() failed.\n");            return err;        }    } else {        err = alloc_chrdev_region(&leds_cdev.dev, 10,                DEVICE_COUNT, DEVICE_NAME);        if (err < 0) {            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.mkLOCAL_PATH := $(call my-dir)include $(CLEAR_VARS)LOCAL_PRELINK_MODULE := falseLOCAL_MODULE_PATH := $(TARGET_OUT_SHARED_LIBRARIES)/hwLOCAL_SHARED_LIBRARIES := liblogLOCAL_SRC_FILES := leds_hal.cLOCAL_MODULE := leds_hal.defaultLOCAL_MODULE_TAGS := enginclude $(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 = 0;int leds_switch(struct leds_device_t *dev, int32_t led, int32_t on_off){    unsigned char buf[3];    if (led < 0 && led > 3) {        LOGI("Led Stub : no this led.\n");        return -1;    }    if (on_off == 1) {        LOGI("Led Stub : set %d led on", led);        buf[led] = '1';    } else {        LOGI("Led Stub : set %d led off", led);        buf[led] = '0';    }    write(fd_leds, buf, 4);    return 0;}int leds_on(struct leds_device_t *dev, int32_t led){    return leds_switch(dev, led, 1);}int leds_off(struct leds_device_t *dev, int32_t led){    return leds_switch(dev, led, 0);}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 0;}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, 0, sizeof(*leds_dev));    leds_dev->hw_device.tag = HARDWARE_DEVICE_TAG;    leds_dev->hw_device.version = 0;    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 < 0) {        LOGI("Led Stub : open /dev/s3c6410_leds_hal fail.\n");    } else {        LOGI("Led Stub : open /dev/s3c6410_leds_hal success.\n");    }    return 0;}    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: 1,        version_minor: 0,        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_SYMhw_module_thw_device_thw_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

ok6410 android driver(11)_第1张图片

  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

ok6410 android driver(11)_第2张图片

  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 linuxmodule_init(leds_init);// The entrance is a variable HAL_MODULE_INFO_SYM automaticlly loaded by the systemstruct leds_module_t HAL_MODULE_INFO_SYM = {         hw_module : {                   tag: HARDWARE_MODULE_TAG,                version_major: 1,                version_minor: 0,                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 devicestatic struct cdev leds_cdev;// Basic struct in android is a structure with function open, we use the "function" to create our devicestatic 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, 0, sizeof(*leds_dev));        leds_dev->hw_device.tag = HARDWARE_DEVICE_TAG;        leds_dev->hw_device.version = 0;        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 < 0) {                LOGI("Led Stub : open /dev/s3c6410_leds_hal fail.\n");        } else {                LOGI("Led Stub : open /dev/s3c6410_leds_hal success.\n");        }        return 0;}

  [ 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_tstruct 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.

  

  

  

更多相关文章

  1. 不停地切换两张图片ViewFlipper
  2. Android实现图片缩放与旋转
  3. Android Studio点击按钮更换背景图片
  4. android图片放大 缩小 旋转
  5. Android 怎么给图片添加一个边框
  6. Android漏洞——将Android恶意代码隐藏在图片中
  7. Android imageView图片按比例缩放
  8. android中使用afinal一行代码显示网络图片

随机推荐

  1. Android沉浸式标题栏状态栏字体颜色修改(
  2. Android Canvas绘图详解(图文)
  3. Android(安卓)事件分发机制
  4. Android深入理解WebView——上
  5. 一个现代化的JSON库Moshi针对Android和Ja
  6. Android Selector
  7. Android事件分发机制完全解析,带你从源码
  8. Android NDK初识
  9. android中自己画一个按钮,和自己设置一个
  10. Android:可复制的TextView、EditText