当前位置:操作系统 > 安卓/Android >>

Android HAL技术详解

本人喜欢用代码+伪代码的方式写笔记。文中的花括号可能是方便记录而已。
如:
hw_get_module(LED_HARDWARE_MODULE_ID, (const hw_module_t**)&module)
{
    问:怎么获得模块信息的?
    答:hardware\libhardware\Hardware.c
    ...........
}

第一部分:HAL层
hardware\led\include\Led.h
定义常见数据结构
struct led_module_t {
   struct hw_module_t common;
};

struct led_control_device_t { 
   struct hw_device_t common;  /*表示硬件设备*/
   /* 属性 */
   int fd;
   /* 提供出来的方法 */
   int (*set_on)(struct led_control_device_t *dev, int32_t led);
   int (*set_off)(struct led_control_device_t *dev, int32_t led);
};

nstruct led_control_context_t {
    struct led_control_device_t device;
};


hardware\led\led\Led.cpp 分析

static int led_device_open(const struct hw_module_t* module, const char* name,
        struct hw_device_t** device)
{
    struct led_control_device_t *dev;
    /* 分配设备 */
    dev = (struct led_control_device_t *)malloc(sizeof(*dev));
    memset(dev, 0, sizeof(*dev));

    dev->common.tag =  HARDWARE_DEVICE_TAG;
    dev->common.version = 0;
    dev->common.module = (struct hw_module_t*)module;  /*设置是属于哪个模块 */
    dev->common.close = led_device_close;
   
    dev->set_on = led_on{ 
        /*自定义方法*/
        int led_off(struct led_control_device_t *dev, int32_t led)
        {
            ioctl(g_fd, 0, led); //led on
        }
    }
    dev->set_off = led_off;    /*自定义方法*/

    *device = &dev->common;
    /*
    /dev/leds0 内核驱动的device_create创建的
    假如打开设备时候发生:Hello Stub: failed to open /dev/leds0 -- Permission denied.
    进入到system/core/rootdir目录,里面有一个名为ueventd.rc文件,往里面添加一行:
     /dev/hello 0666 root leds0
    */
     g_fd = open("/dev/leds0", 0);
    return 0;
}

/*模块方法表*/ 
static struct hw_module_methods_t led_module_methods = {
    open: led_device_open
};
/* 
    模块信息
    实例变量名必须为HAL_MODULE_INFO_SYM,
    tag也必须为HARDWARE_MODULE_TAG,这是Android硬件抽象层规范规定的。
*/
extern "C" ① const struct led_module_t HAL_MODULE_INFO_SYM = {
    common: {
        tag: HARDWARE_MODULE_TAG, 
        version_major: 1,
        version_minor: 0,
        id: LED_HARDWARE_MODULE_ID,
        name: "Sample LED Stub",
        author: "The Forlinx Open Source Project",
        methods: &led_module_methods,  /*设置方法  */
    }
    /* supporting APIs go here */
};

① extern "C" :C++编写的代码片段可能被使用在其它语言编写的代码中。不同语言编写的代码互相调用是困难的。
为了使它们遵守统一规则,可以使用extern指定一个编译和连接规约。extern "C"指令中的C,表示的一种编译和连接规约,
而不是一种语言。C表示符合C语言的编译和连接规约的任何语言。


第二层: JNI  层次编写
frameworks\base\services\forlinx_led_jni\LedService.cpp
struct led_control_device_t *sLedDevice = NULL;//硬件设备的公告属性和方法
//方法描述
gMethods[] = {
    { "_init","()Z",(void *)forlinx_init {
        jboolean forlinx_init(JNIEnv *env, jclass clazz)
        {
            led_module_t* module;
            hw_get_module(LED_HARDWARE_MODULE_ID, (const hw_module_t**)&module)
            {
                问:怎么获得模块信息的?
                答:hardware\libhardware\Hardware.c
                hw_get_module(const char *id, const struct hw_module_t **module)
                {
                    char prop[PATH_MAX];
                    char path[PATH_MAX];
                    for (i=0 ; i<HAL_VARIANT_KEYS_COUNT+1 ; i++)
                    {
                        property_get(variant_keys[i], prop, NULL)
                        {
                            问: variant_keys的数据是什么?
                            答: static const char *variant_keys[] = {
                                "ro.hardware", 
                                "ro.product.board",
                                "ro.board.platform",
                                "ro.arch"
                            };
 &nbs

补充:移动开发 , Android ,
CopyRight © 2022 站长资源库 编程知识问答 zzzyk.com All Rights Reserved
部分文章来自网络,