<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="zh-Hans-CN">
	<id>https://www.mywiki.cn/Hovercool/index.php?action=history&amp;feed=atom&amp;title=hal</id>
	<title>hal - 版本历史</title>
	<link rel="self" type="application/atom+xml" href="https://www.mywiki.cn/Hovercool/index.php?action=history&amp;feed=atom&amp;title=hal"/>
	<link rel="alternate" type="text/html" href="https://www.mywiki.cn/Hovercool/index.php?title=hal&amp;action=history"/>
	<updated>2026-09-01T03:59:04Z</updated>
	<subtitle>本wiki上该页面的版本历史</subtitle>
	<generator>MediaWiki 1.45.1</generator>
	<entry>
		<id>https://www.mywiki.cn/Hovercool/index.php?title=hal&amp;diff=820&amp;oldid=prev</id>
		<title>2015年5月6日 (三) 11:48 Hovercool</title>
		<link rel="alternate" type="text/html" href="https://www.mywiki.cn/Hovercool/index.php?title=hal&amp;diff=820&amp;oldid=prev"/>
		<updated>2015-05-06T11:48:35Z</updated>

		<summary type="html">&lt;p&gt;&lt;/p&gt;
&lt;p&gt;&lt;b&gt;新页面&lt;/b&gt;&lt;/p&gt;&lt;div&gt;== 三个重要结构体 ==&lt;br /&gt;
&lt;br /&gt;
*hw_module_t&lt;br /&gt;
&amp;lt;pre class=&amp;quot;prettyprint&amp;quot;&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
 * Every hardware module must have a data structure named HAL_MODULE_INFO_SYM&lt;br /&gt;
 * and the fields of this data structure must begin with hw_module_t&lt;br /&gt;
 * followed by module specific information.&lt;br /&gt;
 */&lt;br /&gt;
typedef struct hw_module_t {&lt;br /&gt;
    /** tag must be initialized to HARDWARE_MODULE_TAG */&lt;br /&gt;
    uint32_t tag;&lt;br /&gt;
&lt;br /&gt;
    /** major version number for the module */&lt;br /&gt;
    uint16_t version_major;&lt;br /&gt;
&lt;br /&gt;
    /** minor version number of the module */&lt;br /&gt;
    uint16_t version_minor;&lt;br /&gt;
&lt;br /&gt;
    /** Identifier of module */&lt;br /&gt;
    const char *id;&lt;br /&gt;
&lt;br /&gt;
    /** Name of this module */&lt;br /&gt;
    const char *name;&lt;br /&gt;
&lt;br /&gt;
    /** Author/owner/implementor of the module */&lt;br /&gt;
    const char *author;&lt;br /&gt;
&lt;br /&gt;
    /** Modules methods */&lt;br /&gt;
    //模块方法列表,指向hw_module_methods_t*&lt;br /&gt;
    struct hw_module_methods_t* methods;&lt;br /&gt;
&lt;br /&gt;
    /** module&amp;#039;s dso */&lt;br /&gt;
    void* dso;&lt;br /&gt;
&lt;br /&gt;
    /** padding to 128 bytes, reserved for future use */&lt;br /&gt;
    uint32_t reserved[32-7];&lt;br /&gt;
&lt;br /&gt;
} hw_module_t;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*hw_module_methods_t&lt;br /&gt;
&amp;lt;pre class=&amp;quot;prettyprint&amp;quot;&amp;gt;&lt;br /&gt;
typedef struct hw_module_methods_t {                 //硬件模块方法列表的定义，这里只定义了一个open函数&lt;br /&gt;
    /** Open a specific device */&lt;br /&gt;
    int (*open)(const struct hw_module_t* module, const char* id,&lt;br /&gt;
                  struct hw_device_t** device);&lt;br /&gt;
} hw_module_methods_t;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*hw_device_t&lt;br /&gt;
&amp;lt;pre class=&amp;quot;prettyprint&amp;quot;&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
 * Every device data structure must begin with hw_device_t&lt;br /&gt;
 * followed by module specific public methods and attributes.&lt;br /&gt;
 */&lt;br /&gt;
typedef struct hw_device_t {&lt;br /&gt;
    /** tag must be initialized to HARDWARE_DEVICE_TAG */&lt;br /&gt;
    uint32_t tag;&lt;br /&gt;
&lt;br /&gt;
    /** version number for hw_device_t */&lt;br /&gt;
    uint32_t version;&lt;br /&gt;
&lt;br /&gt;
    /** reference to the module this device belongs to */&lt;br /&gt;
    struct hw_module_t* module;&lt;br /&gt;
&lt;br /&gt;
    /** padding reserved for future use */&lt;br /&gt;
    uint32_t reserved[12];&lt;br /&gt;
&lt;br /&gt;
    /** Close this device */&lt;br /&gt;
    int (*close)(struct hw_device_t* device);&lt;br /&gt;
&lt;br /&gt;
} hw_device_t;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== 定义自己的hal模块 ==&lt;br /&gt;
&lt;br /&gt;
=== 一、在.h文件中“继承”hw_module_t、hw_device_t ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre class=&amp;quot;prettyprint&amp;quot;&amp;gt;&lt;br /&gt;
//led.h&lt;br /&gt;
&lt;br /&gt;
/* HAL规定不能直接使用hw_module_t结构，因此需要做这么一个继承 */&lt;br /&gt;
struct led_module_t {&lt;br /&gt;
   struct hw_module_t common;&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
struct led_control_device_t {  &lt;br /&gt;
   /* 自定义的一个针对Led控制的结构，包含hw_device_t和支持的API操作 */&lt;br /&gt;
   struct hw_device_t common;&lt;br /&gt;
&lt;br /&gt;
   /*可用于具体的设备描述符，如指向/dev/xxx */&lt;br /&gt;
   int fd;&lt;br /&gt;
&lt;br /&gt;
   /* 在这里定义自己的控制api */&lt;br /&gt;
   int (*set_on)(struct led_control_device_t *dev, int32_t led);&lt;br /&gt;
   int (*set_off)(struct led_control_device_t *dev, int32_t led);&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
/* 定义一个MODULE_ID，HAL层可以根据这个ID找到我们这个HAL stub */&lt;br /&gt;
#define LED_HARDWARE_MODULE_ID &amp;quot;led&amp;quot;  &lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== 二、.c文件中定义相关变量、实现相关函数 ===&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
1、定义相关变量&lt;br /&gt;
&lt;br /&gt;
由本文件第一节“三个重要的结构体”可知，hw_device_t包含hw_module_t类型指针，hw_module_t包含hw_module_methods_t类型指针，而上面.h头文件我们自定义的led_control_device_t结构体又包含hw_device_t结构体，因此这四个结构体的复用情况如下：&lt;br /&gt;
 hw_module_methods_t &amp;lt;- hw_module_t &amp;lt;- hw_device_t &amp;lt;- led_control_device_t&lt;br /&gt;
也就是说，通过led_control_device_t我们可以找到hal三大结构体类型（变量），而上一小节的代码中也说明了我们自定义的一些控制api也是放在led_control_device_t中的。&lt;br /&gt;
&lt;br /&gt;
因此自然而然，我们应该很容易想到我们应该首先定义一个led_control_device_t变量：&lt;br /&gt;
&amp;lt;pre class=&amp;quot;prettyprint&amp;quot;&amp;gt;&lt;br /&gt;
//led.c&lt;br /&gt;
static struct hw_module_methods_t led_module_methods = {&lt;br /&gt;
    open: led_device_open&lt;br /&gt;
};&lt;br /&gt;
const struct led_module_t HAL_MODULE_INFO_SYM = {&lt;br /&gt;
//定义这个对象等于向系统注册了一个ID为LED_HARDWARE_MODULE_ID的stub。注意这里HAL_MODULE_INFO_SYM的名称不能改。&lt;br /&gt;
    common: {&lt;br /&gt;
        tag: HARDWARE_MODULE_TAG,  //这里HARDWARE_MODULE_TAG也是规范中固定死的&lt;br /&gt;
        version_major: 1,&lt;br /&gt;
        version_minor: 0,&lt;br /&gt;
        id: LED_HARDWARE_MODULE_ID,&lt;br /&gt;
        name: &amp;quot;Sample LED Stub&amp;quot;,&lt;br /&gt;
        author: &amp;quot;The Mokoid Open Source Project&amp;quot;,&lt;br /&gt;
        methods: &amp;amp;led_module_methods,  //实现了一个open的方法供jni层调用，&lt;br /&gt;
                                       //从而实例化led_control_device_t&lt;br /&gt;
    }&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
从上面可以看出，实际并不是这样的，这里并没有定义led_control_device_t变量，却定义了led_module_t变量，而这个函数仅包括了一个hw_module_methods_t类型指针，而hw_module_methods_t中却只有一个open函数，那其他接口函数是如何传给jni的呢？&lt;br /&gt;
&lt;br /&gt;
其实，关键也就在于这个open函数(可以先查看下一节的led_device_open函数)，正是通过这个函数将hw_device_t类型指针返回给上层jni的，而在led_control_device_t结构体中，hw_device_t类型指针是第一个变量(规范要求必须为第一个变量)，如此在jni上通过将hw_device_t类型指针的强制转换为led_control_device_t类型，则完成了接口函数的传递过程。&lt;br /&gt;
&lt;br /&gt;
如果对这个感兴趣的话可以参阅下这篇文章：[http://blog.csdn.net/flydream0/article/details/7086273 Android中HAL如何向上层提供接口总结]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
2、定义相关函数&lt;br /&gt;
&lt;br /&gt;
有哪些函数需要定义呢？我们先来统计一下，我们按照以下“包含”关系自底向上来进行统计：&lt;br /&gt;
 hw_module_methods_t &amp;lt;- hw_module_t &amp;lt;- hw_device_t &amp;lt;- led_control_device_t&lt;br /&gt;
(1)hw_module_methods_t中的&amp;lt;span style=&amp;quot;color:#FF0000;&amp;quot;&amp;gt;open&amp;lt;/span&amp;gt;函数；&lt;br /&gt;
&lt;br /&gt;
(2)hw_module_t中无；&lt;br /&gt;
&lt;br /&gt;
(3)hw_device_t中的&amp;lt;span style=&amp;quot;color:#FF0000;&amp;quot;&amp;gt;close&amp;lt;/span&amp;gt;函数；&lt;br /&gt;
&lt;br /&gt;
(4)led_control_device_t中自定义的&amp;lt;span style=&amp;quot;color:#FF0000;&amp;quot;&amp;gt;api函数&amp;lt;/span&amp;gt;；&lt;br /&gt;
&lt;br /&gt;
统计是准确的：&lt;br /&gt;
&amp;lt;pre class=&amp;quot;prettyprint&amp;quot;&amp;gt;&lt;br /&gt;
//led.c&lt;br /&gt;
int led_device_close(struct hw_device_t* device)&lt;br /&gt;
{&lt;br /&gt;
	struct led_control_device_t* ctx = (struct led_control_device_t*)device;&lt;br /&gt;
	if (ctx) {&lt;br /&gt;
		free(ctx);&lt;br /&gt;
	}&lt;br /&gt;
	return 0;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
int led_on(struct led_control_device_t *dev, int32_t led)&lt;br /&gt;
{&lt;br /&gt;
	LOGI(&amp;quot;LED Stub: set %d on.&amp;quot;, led);&lt;br /&gt;
&lt;br /&gt;
	return 0;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
int led_off(struct led_control_device_t *dev, int32_t led)&lt;br /&gt;
{&lt;br /&gt;
	LOGI(&amp;quot;LED Stub: set %d off.&amp;quot;, led);&lt;br /&gt;
&lt;br /&gt;
	return 0;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
static int led_device_open(const struct hw_module_t* module, const char* name,&lt;br /&gt;
        struct hw_device_t** device) &lt;br /&gt;
{&lt;br /&gt;
	struct led_control_device_t *dev;&lt;br /&gt;
&lt;br /&gt;
	dev = (struct led_control_device_t *)malloc(sizeof(*dev));&lt;br /&gt;
	memset(dev, 0, sizeof(*dev));&lt;br /&gt;
&lt;br /&gt;
	dev-&amp;gt;common.tag =  HARDWARE_DEVICE_TAG;&lt;br /&gt;
	dev-&amp;gt;common.version = 0;&lt;br /&gt;
	dev-&amp;gt;common.module = module;&lt;br /&gt;
	dev-&amp;gt;common.close = led_device_close;&lt;br /&gt;
&lt;br /&gt;
	dev-&amp;gt;set_on = led_on;&lt;br /&gt;
	dev-&amp;gt;set_off = led_off;&lt;br /&gt;
&lt;br /&gt;
	*device = &amp;amp;dev-&amp;gt;common;&lt;br /&gt;
&lt;br /&gt;
success:&lt;br /&gt;
	return 0;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== 思考 ==&lt;br /&gt;
为什么hal在往上传接口时要以hw_module_t类型给出，然后在jni中对指针进行强制转换，而不直接以用户定义的类型(如led_control_device_t)传出？&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
参考资料：&lt;br /&gt;
&lt;br /&gt;
[http://blog.csdn.net/hongtao_liu/article/details/6060734 Android HAL实例解析-刘洪涛的专栏]&lt;br /&gt;
&lt;br /&gt;
[http://blog.csdn.net/flydream0/article/details/7086273 Android中HAL如何向上层提供接口总结]&lt;br /&gt;
&lt;br /&gt;
注：&lt;br /&gt;
&lt;br /&gt;
本文引用的是台湾的Jollen的[http://mokoid.googlecode.com/svn/trunk/ mokoid]工程代码&lt;/div&gt;</summary>
		<author><name>Hovercool</name></author>
	</entry>
</feed>