1)硬件抽象层具有与硬件的密切相关性。
2) 硬件抽象层具有与操作系统无关性。
3) 接口定义的功能应该包含硬件或者系统所需硬件支持的所有功能。
4) 接口简单明了,太多接口函数会增加软件模拟的复杂性。
5) 具有可预测的接口设计有利于系统的软、硬件测试和集成。
1)libhardware_legacy :过去的目录,采取链接库模块观念来架构
2)libhardware: 新版的目录,被调整为用HAL stub 观念来架构
3)ril: 是Radio 接口层
4)msm7k : 和QUAL 平台相关的信息
/*
Value for the hw_module_t.tag field
*/
/**
Every hardware module must have a data structure named HAL_MODULE_INFO_SYM
and the fields of this data structure must begin with hw_module_t
followed by module specific information.
_/
typedef struct hw_module_t {
/_* tag must be initialized to HARDWARE_MODULE_TAG */
uint32_t tag;
/**
The API version of the implemented module. The module owner is
responsible for updating the version when a module interface has
changed.
The derived modules such as gralloc and audio own and manage this field.
The module user must interpret the version field to decide whether or
not to inter-operate with the supplied module implementation.
For example, SurfaceFlinger is responsible for making sure that
it knows how to manage different versions of the gralloc-module API,
and AudioFlinger must know how to do the same for audio-module API.
The module API version should include a major and a minor component.
For example, version 1.0 could be represented as 0x0100. This format
implies that versions 0x0100-0x01ff are all API-compatible.
In the future, libhardware will expose a hw_get_module_version()
(or equivalent) function that will take minimum/maximum supported
versions as arguments and would be able to reject modules with
versions outside of the supplied range.
*/
uint16_t module_api_version;
/**
* version_major/version_minor defines are supplied here for temporary
* source code compatibility. They will be removed in the next version.
* ALL clients must convert to the new version format.
*/
/**
* The API version of the HAL module interface. This is meant to
* version the hw_module_t, hw_module_methods_t, and hw_device_t
* structures and definitions.
*
* The HAL interface owns this field. Module users/implementations
* must NOT rely on this value for version information.
*
* Presently, 0 is the only valid value.
*/
uint16_t hal_api_version;
/** Identifier of module */
const char *id;
/** Name of this module */
const char *name;
/** Author/owner/implementor of the module */
const char *author;
/** Modules methods */
struct hw_module_methods_t* methods;
/** module's dso */
void* dso;
uint64_t reserved[32-7];
/** padding to 128 bytes, reserved for future use */
uint32_t reserved[32-7];
} hw_module_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);
} hw_module_methods_t;
hw_module_methods_t 只有一个函数指针成员变量,用来打开硬件抽闲层模块中的硬件设备。
2)成员变量的参数module表示要打开的硬件设备所在模块;
3)成员变量的参数id表示要打开的硬件设备的ID;
4)成员变量的参数device是一个输出参数,用来描述一个已经打开的硬件设备。
struct hw_device_t
/**
Every device data structure must begin with hw_device_t
followed by module specific public methods and attributes.
_/
typedef struct hw_device_t {
/_* tag must be initialized to HARDWARE_DEVICE_TAG */
uint32_t tag;
/**
Version of the module-specific device API. This value is used by
the derived-module user to manage different device implementations.
The module user is responsible for checking the module_api_version
and device version fields to ensure that the user is capable of
communicating with the specific module implementation.
One module can support multiple devices with different versions. This
can be useful when a device interface changes in an incompatible way
but it is still necessary to support older implementations at the same
time. One such example is the Camera 2.0 API.
This field is interpreted by the module user and is ignored by the
HAL interface itself.
*/
uint32_t version;
/** reference to the module this device belongs to _/
struct hw_module_t_ module;
/** padding reserved for future use */
uint64_t reserved[12];
uint32_t reserved[12];
/** Close this device */
int (*close)(struct hw_device_t* device);
} hw_device_t;
1)从hw_device_t 注释可以看出硬件抽象层模块的每一个硬件设备都必须自定义一个硬件设备结构体,且他的第一个成员变量的类型必须是hw_device_t。
2)hw_device_t.tag 的值必须是 **HARDWARE_DEVICE_TAG ** ,即(H) << 24) | ((W) << 16) | ((D) << 8) | (T) ,用来标识硬件抽象中的硬件设备结构体。
3)结构体hw_device_t 的成员变量close是一个函数指针,它用来关闭一个硬件设备。
函数hw_get_module()。
/** Base path of the hal modules */
/**
There are a set of variant filename for modules. The form of the filename
is "
of base "ro.product.board", "ro.board.platform" and "ro.arch" would be:
led.trout.so
led.msm7k.so
led.ARMV6.so
led.default.so
*/
static const char _variant_keys[] = {
"ro.hardware", /_ This goes first so that it can pick up a different
file on the emulator. */ //emulator : 仿真器;pick up :获取
"ro.product.board",
"ro.board.platform",
"ro.arch"
};
static const int HAL_VARIANT_KEYS_COUNT =
(sizeof(variant_keys)/sizeof(variant_keys[0]));
/**
Load the file defined by the variant and if successful
return the dlopen handle and the hmi.
@return 0 = success, !0 = failure.
*/
static int load(const char *id,
const char *path,
const struct hw_module_t **pHmi)
{
int status = -EINVAL;
void *handle = NULL;
struct hw_module_t *hmi = NULL;
/*
load the symbols resolving undefined symbols before
dlopen returns. Since RTLD_GLOBAL is not or'd in with
RTLD_NOW the external symbols will not be global
_/
if (strncmp(path, "/system/", 8) == 0) {
/_ If the library is in system partition, no need to check
sphal namespace. Open it with dlopen.
*/
handle = dlopen(path, RTLD_NOW);
} else {
handle = android_load_sphal_library(path, RTLD_NOW);
}
if (handle == NULL) {
char const *err_str = dlerror();
ALOGE("load: module=%s\n%s", path, err_str?err_str:"unknown");
status = -EINVAL;
goto done;
}
/* Get the address of the struct hal_module_info. */
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;
}
/* Check that the id matches */
if (strcmp(id, hmi->id) != 0) {
ALOGE("load: id=%s != hmi->id=%s", id, hmi->id);
status = -EINVAL;
goto done;
}
hmi->dso = handle;
/* success */
status = 0;
done:
if (status != 0) {
hmi = NULL;
if (handle != NULL) {
dlclose(handle);
handle = NULL;
}
} else {
ALOGV("loaded HAL id=%s path=%s hmi=%p handle=%p",
id, path, *pHmi, handle);
}
*pHmi = hmi;
return status;
}
/*
Check if a HAL with given name and subname exists, if so return 0, otherwise
otherwise return negative. On success path will contain the path to the HAL.
*/
static int hw_module_exists(char *path, size_t path_len, const char *name,
const char *subname)
{
snprintf(path, path_len, "%s/%s.%s.so",
HAL_LIBRARY_PATH3, name, subname);
if (access(path, R_OK) == 0)
return 0;
snprintf(path, path_len, "%s/%s.%s.so",
HAL_LIBRARY_PATH2, name, subname);
if (access(path, R_OK) == 0)
return 0;
snprintf(path, path_len, "%s/%s.%s.so",
HAL_LIBRARY_PATH1, name, subname);
if (access(path, R_OK) == 0)
return 0;
return -ENOENT;
}
int hw_get_module_by_class(const char *class_id, const char *inst,
const struct hw_module_t **module)
{
int i = 0;
char prop[PATH_MAX] = {0};
char path[PATH_MAX] = {0};
char name[PATH_MAX] = {0};
char prop_name[PATH_MAX] = {0};
if (inst)
snprintf(name, PATH_MAX, "%s.%s", class_id, inst);
else
strlcpy(name, class_id, PATH_MAX);
/*
* Here we rely on the fact that calling dlopen multiple times on
* the same .so will simply increment a refcount (and not load
* a new copy of the library).
* We also assume that dlopen() is thread-safe.
*/
/* First try a property specific to the class and possibly instance */
snprintf(prop_name, sizeof(prop_name), "ro.hardware.%s", name);
if (property_get(prop_name, prop, NULL) > 0) {
if (hw_module_exists(path, sizeof(path), name, prop) == 0) {
goto found;
}
}
/* 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);
}
int hw_get_module(const char *id, const struct hw_module_t **module)
{
return hw_get_module_by_class(id, NULL, module);
}
手机扫一扫
移动阅读更方便
你可能感兴趣的文章