Android-HAL (一) hw_module_t 的类型实现

HAL module架构主要分为三个结构体

struct hw_module_t;    //硬件抽象模块

struct hw_module_methods_t;    //方法

struct hw_device_t;    //模块中的设备


hardware/libhardware/include/hardware/hardware.h

1 每一个 hardware 硬件抽象模块必须有一个module结构体,名字是 HAL_MODULE_INFO_SYM,即HMI,这个模块第一个成员变量是 hw_module_t

hw_module_t 的tag的值必须为 HARDWARE_MODULE_TAG,这个值就是用来标识硬件抽象的结构体

3 id这个属性代表这个module的唯一性

4 methods代表每个硬件抽象模块的方法结构体,hw_module_methods_t

typedef struct hw_module_t {
    /** tag must be initialized to HARDWARE_MODULE_TAG */
    uint32_t tag;

    uint16_t module_api_version;
#define version_major module_api_version

    uint16_t hal_api_version;
#define version_minor hal_api_version

    /** Identifier of module */
    const char *id;    //模块唯一id

    /** Name of this module */
    const char *name;  //id  

    /** Author/owner/implementor of the module */
    const char *author;

    /** Modules methods */
    struct hw_module_methods_t* methods;    //方法的结构体

    /** module's dso */
    void* dso;

#ifdef __LP64__
    uint64_t reserved[32-7];
#else
    /** padding to 128 bytes, reserved for future use */
    uint32_t reserved[32-7];
#endif

} hw_module_t;

hw_module_methods_t 结构体

typedef struct hw_module_methods_t {
    /** Open a specific device */
    int (*open)(const struct hw_module_t* module, const char* id,
            struct hw_device_t** device);
    //id --设备id
    //根据id返回设备

} hw_module_methods_t;

hw_device_t 结构体

1 每个硬件需要定义一个 hw_device_t

2 tag为所在硬件模块HARDWARE_DEVICE_TAG,代表是硬件设备结构体

//hardware/libhardware/include/hardware/hardware.h

    #define HARDWARE_DEVICE_TAG MAKE_TAG_CONSTANT('H', 'W', 'D', 'T')

3 close指针用于关闭设备

typedef struct hw_device_t {
    /** tag must be initialized to HARDWARE_DEVICE_TAG */
    uint32_t tag;

    uint32_t version;

    /** reference to the module this device belongs to */
    struct hw_module_t* module;

    /** padding reserved for future use */
#ifdef __LP64__
    uint64_t reserved[12];
#else
    uint32_t reserved[12];
#endif

    /** Close this device */
    int (*close)(struct hw_device_t* device);

} hw_device_t;
struct sensors_poll_device_t {
    struct hw_device_t common;
    int (*activate)(struct sensors_poll_device_t *dev,
            int sensor_handle, int enabled);
    int (*setDelay)(struct sensors_poll_device_t *dev,
            int sensor_handle, int64_t sampling_period_ns);
    int (*poll)(struct sensors_poll_device_t *dev,
            sensors_event_t* data, int count);
};


实现方式

定义结构体

//hardware/libhardware/include/hardware/sensors.h

#define SENSORS_HARDWARE_MODULE_ID "sensors"

struct sensors_module_t {
    struct hw_module_t common;

    // ...
};

//实现
static struct hw_module_methods_t sensors_module_methods = {
    .open = open_sensors
};

struct sensors_module_t HAL_MODULE_INFO_SYM = {
    .common = {
        .tag = HARDWARE_MODULE_TAG,
        .version_major = 1,
        .version_minor = 1,
        .id = SENSORS_HARDWARE_MODULE_ID,
        .name = "MultiHal Sensor Module",
        .author = "Google, Inc",
        .methods = &sensors_module_methods,
        .dso = NULL,
        .reserved = {0},
    },
    .get_sensors_list = module__get_sensors_list
};

static int open_sensors(const struct hw_module_t* hw_module, const char* name,
        struct hw_device_t** hw_device_out) {
    // ...
   // Create proxy device, to return later.
    sensors_poll_context_t *dev = new sensors_poll_context_t();
    memset(dev, 0, sizeof(sensors_poll_device_1_t));
    dev->proxy_device.common.tag = HARDWARE_DEVICE_TAG;
    dev->proxy_device.common.version = SENSORS_DEVICE_API_VERSION_1_4;
    dev->proxy_device.common.module = const_cast<hw_module_t*>(hw_module);
    dev->proxy_device.common.close = device__close;
    dev->proxy_device.activate = device__activate;
    dev->proxy_device.setDelay = device__setDelay;
    dev->proxy_device.poll = device__poll;
    dev->proxy_device.batch = device__batch;
    dev->proxy_device.flush = device__flush;
    dev->proxy_device.inject_sensor_data = device__inject_sensor_data;
    dev->proxy_device.register_direct_channel = device__register_direct_channel;
    dev->proxy_device.config_direct_report = device__config_direct_report;

    dev->nextReadIndex = 0;
    // ...
    return 0;
}


实战

hardware/libhardware/include/hardware/mytest.h

hardware/libhardware/include_all/hardware/mytest.h

#ifndef HARDWARE_MYTEST_H
#define HARDWARE_MYTEST_H

#include <hardware/hardware.h>

__BEGIN_DECLS

#define MYTEST_HARDWARE_MODULE_ID "mytest"

struct mytest_module_t {
    struct hw_module_t common;
};

struct mytest_device_t {
    struct hw_device_t common;
    int (*testAdd)(struct mytest_device_t* dev, int a, int b);
};

__END_DECLS

#endif // HARDWARE_MYTEST_H

hardware/libhardware/modules/mytest/mytest.cpp


#include <malloc.h>
#include <string.h>

#include <hardware/hardware.h>
#include <hardware/mytest.h>

//实现
static int device_close(struct hw_device_t* device) {
    mytest_device_t* dev = (mytest_device_t*) device;
    delete dev;
    return 0;
}

static int device_testAdd(struct mytest_device_t* dev, int a, int b) {
    if (dev != NULL) {

    }
    
    return a + b * 10;
}

static int open_sensors(const struct hw_module_t* hw_module, const char* name,
        struct hw_device_t** hw_device_out) {
    if (strcmp(name, "test") != 0) {
        //return -EINVAL;
    }
    // Create proxy device, to return later.
    mytest_device_t* dev = new mytest_device_t();
    memset(dev, 0, sizeof(mytest_device_t));
    dev->common.tag = HARDWARE_DEVICE_TAG;
    dev->common.version = 1;
    dev->common.module = const_cast<hw_module_t*>(hw_module);
    dev->common.close = device_close;
    // Add your device-specific fields here
    dev->testAdd = device_testAdd;

    *hw_device_out = &dev->common;
    return 0;
}

static struct hw_module_methods_t mytest_module_methods = {
    .open = open_sensors
};

struct mytest_module_t HAL_MODULE_INFO_SYM = {
    .common = {
        .tag = HARDWARE_MODULE_TAG,
        .version_major = 1,
        .version_minor = 1,
        .id = MYTEST_HARDWARE_MODULE_ID,
        .name = "Mytest Sensor Module",
        .author = "godv",
        .methods = &mytest_module_methods,
        .dso = NULL,
        .reserved = {0},
    },
};

hardware/libhardware/modules/mytest/mytestapp.cpp


#include <string.h>
#include <stdio.h>
#include <hardware/hardware.h>
#include <hardware/mytest.h>

int main(int /* argc */, char** /* argv */)
{
    int err;
    struct mytest_device_t* device;
    struct mytest_module_t* module;

    err = hw_get_module(MYTEST_HARDWARE_MODULE_ID, (hw_module_t const**)&module);
    if (err != 0) {
        printf("hw_get_module() failed (%s)\n", strerror(-err));
        return 0;
    }

    module->common.methods->open(&module->common, "godv", (hw_device_t**)&device);
    int result = device->testAdd(device, 3, 4);
    printf("testAdd(3, 4) = %d\n", result);

    device->common.close(&device->common);
    return 0;
}

hardware/libhardware/modules/mytest/Android.bp

package {
    default_applicable_licenses: ["hardware_libhardware_license"],
}

cc_library_shared {
    name: "mytest.default",
    relative_install_path: "hw",
    proprietary: true,
    srcs: ["mytest.cpp"],
    cflags: ["-Wall", "-Werror"],
    header_libs: ["libhardware_headers"],
    shared_libs: [
        "liblog",
    ],
}

cc_binary {
    name: "test-mytest",

    srcs: ["mytestapp.cpp"],

    cflags: ["-Wall", "-Werror"],

    shared_libs: [
        "libcutils",
        "libhardware",
    ],
}

hw_get_module 分析
hardware/libhardware/hardware.c

int hw_get_module(const char *id, const struct hw_module_t **module)
{
    return hw_get_module_by_class(id, NULL, module);
}

int hw_get_module_by_class(const char *class_id, const char *inst,
                           const struct hw_module_t **module)
{
    //...  先找    NX563J:/ # getprop | grep ro.hardware                                                                                                                                                                             
    //                      [ro.hardware]: [qcom]

    /* First try a property specific to the class and possibly instance */
    snprintf(prop_name, sizeof(prop_name), "ro.hardware.%s", name);

    // xxxx.qcom.so
    if (property_get(prop_name, prop, NULL) > 0) {
        if (hw_module_exists(path, sizeof(path), name, prop) == 0) {
            goto found;
        }
    }
    
    /*
    static const char *variant_keys[] = {
        "ro.hardware",
        "ro.product.board",
        "ro.board.platform",
        "ro.arch"
    };
    */
    /* Loop through the configuration variants looking for a module */
    for (i=0 ; i<HAL_VARIANT_KEYS_COUNT; i++) {
        if (property_get(variant_keys[i], prop, NULL) == 0) {
            continue;
        }
        if (hw_module_exists(path, sizeof(path), name, prop) == 0) {
            goto found;
        }
    }

    /* Nothing found, try the default */
    if (hw_module_exists(path, sizeof(path), name, "default") == 0) {
        goto found;
    }

    return -ENOENT;

found:
    /* load the module, if this fails, we're doomed, and we should not try
     * to load a different variant. */
    return load(class_id, path, module);
}


static int hw_module_exists(char *path, size_t path_len, const char *name,
                            const char *subname)
{
// ...
/*
#if defined(__LP64__)
#define HAL_LIBRARY_SUBDIR "lib64/hw"
#else
#define HAL_LIBRARY_SUBDIR "lib/hw"
#endif

#define HAL_LIBRARY_PATH1 "/system/" HAL_LIBRARY_SUBDIR
#define HAL_LIBRARY_PATH2 "/vendor/" HAL_LIBRARY_SUBDIR
#define HAL_LIBRARY_PATH3 "/odm/" HAL_LIBRARY_SUBDIR
*/
#else // __ANDROID_APEX__
    snprintf(path, path_len, "%s/%s.%s.so",
             HAL_LIBRARY_PATH3, name, subname);
    if (path_in_path(path, HAL_LIBRARY_PATH3) && access(path, R_OK) == 0)
        return 0;

    snprintf(path, path_len, "%s/%s.%s.so",
             HAL_LIBRARY_PATH2, name, subname);
    if (path_in_path(path, HAL_LIBRARY_PATH2) && access(path, R_OK) == 0)
        return 0;

#ifndef __ANDROID_VNDK__
    snprintf(path, path_len, "%s/%s.%s.so",
             HAL_LIBRARY_PATH1, name, subname);
    if (path_in_path(path, HAL_LIBRARY_PATH1) && access(path, R_OK) == 0)
        return 0;
#endif

#endif // __ANDROID_APEX__

    return -ENOENT;
}


static int load(const char *id,
        const char *path,
        const struct hw_module_t **pHmi)
{
    //...
#if defined(__ANDROID_RECOVERY__) || !defined(__ANDROID__) || defined(__ANDROID_APEX__)
        handle = dlopen(path, RTLD_NOW);
#else
        handle = android_load_sphal_library(path, RTLD_NOW);
#endif
    }
//...

    /* Get the address of the struct hal_module_info. 

    #define HAL_MODULE_INFO_SYM_AS_STR  "HMI"
    #define HAL_MODULE_INFO_SYM         HMI
*/
    const char *sym = HAL_MODULE_INFO_SYM_AS_STR;
    hmi = (struct hw_module_t *)dlsym(handle, sym);
    if (hmi == NULL) {
        ALOGE("load: couldn't find symbol %s", sym);
        status = -EINVAL;
        goto done;
    }
//...

    return status;
}



https://blog.csdn.net/we1less/article/details/121129577?spm=1001.2014.3001.5502

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值