1.ハードウェアインターフェイスHALスタブフレームワーク
HALスタブのフレームワークには、321アーキテクチャと呼ばれる、3つの構造、2つの定数、および1つの関数があります。android4.4バージョンは次のように定義されています。
@ハードウェア/ libhardware /インクルード/ハードウェア
/hardware.h@ハードウェア/ libhardware / Hardware.c
[1]:
すべてのハードウェアは、ハードウェアオブジェクトと呼ばれるhw_module_tによって記述されます。
struct hw_module_t{
uint32_t tag; // 该值必须声明为HARDWARE_MODULE_TAG
uint16_t version_major; // 主版本号
uint16_t version_minor; // 次版本号
const char *id; //硬件id名,唯一标识module
const char *name; // 硬件module名字
const char * author; // 作者
struct hw_module_methods_t* methods; //指向封装有open函数指针的结构体
void* dso; // module’s dso
uint32_t reserved[32-7]; // 128字节补齐
};
``
可以“继承”这个hw_module_t,然后扩展自己的属性,硬件对象必须定义为一个固定的名字:HMI,即:Hardware Module Information的简写.
【2】
hw_device_t结构体描述硬件模块,我们称之为:硬件的操作接口
```cpp
struct hw_device_t{
uint32_t tag; // 必须赋值为HARDWARE_DEVICE_TAG
uint32_t version; // 版本号
struct hw_module_t* module; // 该设备操作属于哪个硬件对象,可以看成硬件操作接口与对象的联系
uint32_t reserved[12]; // 字节补齐
int (*close)(struct hw_device_t * device); // 该设备的关闭函数指针,可以看做硬件的close方法
};
[3]
hw_module_methods_t構造、ハードウェアモジュールオブジェクトによって提供されるメソッド、
struct hw_module_methods_t{
// 只封装了open函数指针
int (*open)(const struct hw_module_t * module, const char * id,
struct hw_device_t ** device);
};
```每一个硬件对象里都封装了一个函数指针open用于打开该硬件,我们理解为硬件对象的open方法,
open调用后返回这个硬件对应的Operation interface。
【4】
上述三个结构之间关系紧密,每个硬件对象由一个 hw_module_t 来描述,只要我们拿到了这个硬件对象,就可以调用它的open方法,返回这个硬件对象的硬件操作接口,然后就可以通过这些硬件操作接口来间接操作硬件了。
那用户程序如何才能拿到硬件对象呢?
答案是通过硬件id名来拿。
```cpp
// 这个就是HAL Stub对象固定的名字
#define HAL_MODULE_INFO_SYM HMI
// 这是字符串形式的名字
#define HAL_MODULE_INFO_SYM_AS_STR "HMI"
//这个函数是通过硬件名来获得硬件HAL Stub对象
int hw_get_module(const char *id, const struct hw_module_t **module);
ユーザーがhw_get_module関数を呼び出すと、最初のパラメーターがハードウェアID名を渡します。次に、この関数は、現在のシステムに登録されているハードウェアオブジェクトから、渡されたID名に対応するハードウェアオブジェクトを見つけて返します。
[5]
発信者の観点からは、基本的に障害はありません。ハードウェアオブジェクトを登録するにはどうすればよいですか。
非常に簡単です。構造を宣言するだけで済みます。次のLEDスタブ登録の例を見てください。
const struct led_module_t HAL_MODULE_INFO_SYM = {
common: {
// 初始化父结构hw_module_t成员
tag: HARDWARE_MODULE_TAG,
version_major: 1,
version_minor: 0,
id: LED_HARDWARE_MODULE_ID,
name: "led HAL Stub",
author: "farsight",
methods: &led_module_methods,
},
// 扩展属性放在这儿
};
HAL_MODULE_INFO_SYMという名前の構造体led_moduel_tを宣言するだけで済みます。これは、固定名HMIであり、この構造体に入力します。
led_module_tとはどのような構造タイプですか?hw_modult_tタイプの以前の分析では、hw_module_tタイプを「継承」し、独自のハードウェアオブジェクトを作成してから、独自の属性を自分で拡張できると述べました。led_module_tは次のように定義されています。
struct led_module_t {
struct hw_module_t common;
};
ここでのled_module_tは「継承された」hw_module_tタイプです。C言語には継承の概念がないため、継承は二重引用符で囲まれていることに注意してください。このように理解しましょう。
構造体led_module_tはhw_module_t構造体をカプセル化します。つまり、新しい(子)構造体led_module_tには古い(親)構造体が含まれ、一部の新しいメンバーは新しい構造体で拡張できます。構造自体には、オブジェクト指向のカプセル化と継承に似たカプセル化特性があります。
[6]
openメソッドはmethods:methodsだけでなく、サブ構造によって「継承」されます。led_module_methodsのアドレスに初期化します。構造のタイプはhw_module_methods_tです。宣言コードは次のとおりです。
static struct hw_module_methods_t led_module_methods = {
open: led_device_open
};
【7】
static int led_device_open(const struct hw_module_t* module, const char* name,
struct hw_device_t** device)
{
struct led_device_t *led_device;
LOGI("%s E ", __func__);
led_device = (struct led_device_t *)malloc(sizeof(*led_device));
memset(led_device, 0, sizeof(*led_device));
// init hw_device_t
led_device->common.tag= HARDWARE_DEVICE_TAG;
led_device->common.version = 0;
led_device->common.module= module;
led_device->common.close = led_device_close;
// init operation interface
led_device->set_on= led_set_on;
led_device->set_off= led_set_off;
led_device->get_led_count = led_getcount;
*device= (struct hw_device_t *)led_device;
if((fd=open("/dev/leds",O_RDWR))==-1)
{
LOGI("open error");
return -1;
}else
LOGI("open ok\n");
return 0;
}
led_device_open関数の関数:
Øハードウェア操作の動作を説明するハードウェアデバイス操作構造led_device_tを割り当てます
Øled_device_tの親構造のhw_device_tメンバーを初期化します
Øled_device_tで拡張操作インターフェースを初期化します
Øデバイスを開き、led_device_t構造を親構造タイプとして返します(オブジェクト指向のポリモーフィズム)
[8]
led_device_tとその親構造hw_device_tの関係を見てください。
struct led_device_t {
struct hw_device_t common; // led_devict_t的父结构,它里面只封装了close方法
// 下面三个函数指针是子结构 led_device_t 对父结构 hw_device_t 的扩展,可以理解为子类扩展了父类增加了三个方法
int (*getcount_led)(struct led_device_t *dev);
int (*set_on)(struct led_device_t *dev);
int (*set_off)(struct led_device_t *dev);
};
残りの作業は、下部構造に3つの新しく拡張されたインターフェイスを実装することです。
static int led_getcount(struct led_control_device_t*dev)
{
LOGI("led_getcount");
return 4;
}
static int led_set_on(struct led_control_device_t *dev)
{
LOGI("led_set_on");
ioctl(fd,GPG3DAT2_ON,NULL);
return 0;
}
static int led_set_off(struct led_control_device_t*dev)
{
LOGI("led_set_off");
ioctl(fd,GPG3DAT2_OFF,NULL);
return 0;
}
これらの3つのインターフェイス機能は、基盤となるドライバーと直接対話してハードウェアを制御します。特定のドライバーは、Linux部分のドライバーの知識です。これは、Androidが321を使用して基盤となるLinuxドライバーとインターフェースする一般的な方法です。
結論として:
このID呼び出しhw_get_module(char * id、struct hw_module_t ** module)関数を使用して、現在のシステムに登録されているidに対応するハードウェアオブジェクトを検索して返すハードウェアID名
があります。hw_module_methods_t構造によってカプセル化されたハードウェアオブジェクトがあります。オープン関数ポインタは、このオープン関数をコールバックし、ハードウェア操作インターフェイスをカプセル化したled_device_t構造を返すため、このハードウェアインターフェイスを介してハードウェアに間接的にアクセスできます。
このプロセスでは、hw_get_moduleは部分構造タイプled_module_tを返します。関数の2番目のパラメータータイプはhw_module_tのスーパータイプですが、ここではオブジェクト指向のポリモーフィズムの概念が使用されています。
レコード
を
整理するには、Great Godのブログhttps://outfox.blog.csdn.net/article/details/8074549を参照してください。