Android Fingerprint -- HAL层的初始化工作


<p>转自: http://www.cnblogs.com/happy-leon/p/5655614.html   http://blog.csdn<a href="http://lib.csdn.net/base/dotnet" class="replace_word" title=".NET知识库" target="_blank" style="color:#df3434; font-weight:bold;">.NET</a>/liuxd3000/article/details/42424179</p>
<p><br>
</p>
<p><strong><span style="font-family:SimSun">序文:如何调用Hal层库文件</span></strong></p>
<p><span style="font-family:SimSun; font-size:12px">每个Hal层库文件有一个入口,即<span style="color:rgb(51,51,51)">HAL_MODULE_INFO_SYM,上层在调用hal层库文件时会在/system/lib/hw/下面寻找对应库文件,找到对应库文件后便从入口<span style="color:rgb(51,51,51); font-size:12px">HAL_MODULE_INFO_SYM调用Hal层里面的open,
 init, write, read等接口,Hal层再通过这个接口去读写设备节点。</span></span></span></p>
<p></p>
<h3 id="一-fingerprint.default.so" style="margin:10px 0px; padding:0px; font-size:16px; line-height:1.5; font-family:Verdana,Arial,Helvetica,sans-serif"><a name="t0" target="_blank"></a>
一、 fingerprint.default.so</h3>
<hr style="margin:0px; padding:0px; color:rgb(51,51,51); font-family:Verdana,Arial,Helvetica,sans-serif; font-size:13.3333px">
<p></p>
<p style="margin:10px auto; padding-top:0px; padding-bottom:0px; color:rgb(51,51,51); font-family:Verdana,Arial,Helvetica,sans-serif; font-size:13.3333px">
1、上一篇讲 Frameworks层初始化指纹模块的时候,Fingerprintd 调用hw_get_module函数获取了一个fingerprint_module_t类型的<a href="http://lib.csdn.net/base/datastructure" class="replace_word" title="算法与数据结构知识库" target="_blank" style="color:#df3434; font-weight:bold;">数据结构</a>。 这个就是在fingerprint.default.so中,由指纹芯片厂商填充实现的。</p>
<pre style="margin-top:10px; margin-bottom:10px; padding:0px; white-space:pre-wrap; word-wrap:break-word; color:rgb(51,51,51); font-size:13.3333px; background-color:rgb(255,255,255)"><code class="hljs cpp" style="margin:auto; vertical-align:middle; display:block; height:auto; overflow-x:auto; color:rgb(0,0,0); padding:5px!important; line-height:1.5!important; font-family:"Courier New",sans-serif!important; font-size:12px!important; border:1px solid rgb(204,204,204)!important"><span class="hljs-comment" style="margin:0px; padding:0px; color:green">//根据名称获取指纹hal层模块。hw_module这个一般由指纹芯片厂商根据 fingerprint.h实现</span>
<span class="hljs-keyword" style="margin:0px; padding:0px; color:rgb(0,0,255)">if</span> (<span class="hljs-number" style="margin:0px; padding:0px">0</span> != (err = hw_get_module(FINGERPRINT_HARDWARE_MODULE_ID, &hw_module))) {
    ALOGE(<span class="hljs-string" style="margin:0px; padding:0px; color:rgb(163,21,21)">"Can't open fingerprint HW Module, error: %d"</span>, err);
    <span class="hljs-keyword" style="margin:0px; padding:0px; color:rgb(0,0,255)">return</span> <span class="hljs-number" style="margin:0px; padding:0px">0</span>;
}</code></pre>
<p style="margin:10px auto; padding-top:0px; padding-bottom:0px; color:rgb(51,51,51); font-family:Verdana,Arial,Helvetica,sans-serif; font-size:13.3333px">
我们继续往下看fingerprint.default.so。</p>
<pre style="margin-top:10px; margin-bottom:10px; padding:0px; white-space:pre-wrap; word-wrap:break-word; color:rgb(51,51,51); font-size:13.3333px; background-color:rgb(255,255,255)"><code class="hljs cpp" style="margin:auto; vertical-align:middle; display:block; height:auto; overflow-x:auto; color:rgb(0,0,0); padding:5px!important; line-height:1.5!important; font-family:"Courier New",sans-serif!important; font-size:12px!important; border:1px solid rgb(204,204,204)!important"><span class="hljs-keyword" style="margin:0px; padding:0px; color:rgb(0,0,255)">static</span> <span class="hljs-keyword" style="margin:0px; padding:0px; color:rgb(0,0,255)">struct</span> <span class="hljs-keyword" style="margin:0px; padding:0px; color:rgb(0,0,255)">hw_module_methods_t</span> fingerprint_module_methods = {
.open = fingerprint_open,
};

<span class="hljs-keyword" style="margin:0px; padding:0px; color:rgb(0,0,255)">fingerprint_module_t</span> HAL_MODULE_INFO_SYM = {
    .common = {
        .tag                = HARDWARE_MODULE_TAG,
        .module_api_version = FINGERPRINT_MODULE_API_VERSION_2_0,
        .hal_api_version    = HARDWARE_HAL_API_VERSION,
        .id                 = FINGERPRINT_HARDWARE_MODULE_ID,
        .name               = <span class="hljs-string" style="margin:0px; padding:0px; color:rgb(163,21,21)">"Fingerprint HAL"</span>,
        .author             = <span class="hljs-string" style="margin:0px; padding:0px; color:rgb(163,21,21)">"xxx"</span>,
        .methods            = &fingerprint_module_methods,
        .dso                = <span class="hljs-literal" style="margin:0px; padding:0px; color:rgb(163,21,21)">NULL</span>
    },
};</code></pre>
<p style="margin:10px auto; padding-top:0px; padding-bottom:0px; color:rgb(51,51,51); font-family:Verdana,Arial,Helvetica,sans-serif; font-size:13.3333px">
hw_get_module就是根据.id = FINGERPRINT_HARDWARE_MODULE_ID这个id来找到对应的fingerprint_module_t。hal层可能有多个指纹芯片厂商的模块,可以根据这个id来做兼容,选择性的加载不同的指纹模组。</p>
<p style="margin:10px auto; padding-top:0px; padding-bottom:0px; color:rgb(51,51,51); font-family:Verdana,Arial,Helvetica,sans-serif; font-size:13.3333px">
2、fingerprintd得到了相应的fingerprint_module_t,之后就会去调用它的open函数。我们来看一下初始化指纹最核心的fingerprint_open。</p>
<pre style="margin-top:10px; margin-bottom:10px; padding:0px; white-space:pre-wrap; word-wrap:break-word; color:rgb(51,51,51); font-size:13.3333px; background-color:rgb(255,255,255)"><code class="hljs cpp" style="margin:auto; vertical-align:middle; display:block; height:auto; overflow-x:auto; color:rgb(0,0,0); padding:5px!important; line-height:1.5!important; font-family:"Courier New",sans-serif!important; font-size:12px!important; border:1px solid rgb(204,204,204)!important"><span class="hljs-function" style="margin:0px; padding:0px"><span class="hljs-keyword" style="margin:0px; padding:0px; color:rgb(0,0,255)">static</span> <span class="hljs-keyword" style="margin:0px; padding:0px; color:rgb(0,0,255)">int</span> <span class="hljs-title" style="margin:0px; padding:0px; color:rgb(163,21,21)">fingerprint_open</span><span class="hljs-params" style="margin:0px; padding:0px">(<span class="hljs-keyword" style="margin:0px; padding:0px; color:rgb(0,0,255)">const</span> hw_module_t* module, <span class="hljs-keyword" style="margin:0px; padding:0px; color:rgb(0,0,255)">const</span> <span class="hljs-keyword" style="margin:0px; padding:0px; color:rgb(0,0,255)">char</span> __unused *id,
                        hw_device_t** device)</span>
</span>{
    ALOGV(<span class="hljs-string" style="margin:0px; padding:0px; color:rgb(163,21,21)">"fingerprint_open"</span>);

    <span class="hljs-keyword" style="margin:0px; padding:0px; color:rgb(0,0,255)">if</span> (device == <span class="hljs-literal" style="margin:0px; padding:0px; color:rgb(163,21,21)">NULL</span>) {
        ALOGE(<span class="hljs-string" style="margin:0px; padding:0px; color:rgb(163,21,21)">"NULL device on open"</span>);
        <span class="hljs-keyword" style="margin:0px; padding:0px; color:rgb(0,0,255)">return</span> -EINVAL;
    }

    <span class="hljs-keyword" style="margin:0px; padding:0px; color:rgb(0,0,255)">fingerprint_device_t</span> *dev = (<span class="hljs-keyword" style="margin:0px; padding:0px; color:rgb(0,0,255)">fingerprint_device_t</span> *)
        <span class="hljs-built_in" style="margin:0px; padding:0px; color:rgb(0,0,255)">malloc</span>(<span class="hljs-keyword" style="margin:0px; padding:0px; color:rgb(0,0,255)">sizeof</span>(<span class="hljs-keyword" style="margin:0px; padding:0px; color:rgb(0,0,255)">fingerprint_device_t</span>));
    <span class="hljs-built_in" style="margin:0px; padding:0px; color:rgb(0,0,255)">memset</span>(dev, <span class="hljs-number" style="margin:0px; padding:0px">0</span>, <span class="hljs-keyword" style="margin:0px; padding:0px; color:rgb(0,0,255)">sizeof</span>(<span class="hljs-keyword" style="margin:0px; padding:0px; color:rgb(0,0,255)">fingerprint_device_t</span>));

    dev->common.tag = HARDWARE_DEVICE_TAG;
    dev->common.version = FINGERPRINT_MODULE_API_VERSION_2_0;
    dev->common.module = (<span class="hljs-keyword" style="margin:0px; padding:0px; color:rgb(0,0,255)">struct</span> <span class="hljs-keyword" style="margin:0px; padding:0px; color:rgb(0,0,255)">hw_module_t</span>*) module;
    dev->common.close = fingerprint_close;

    dev->pre_enroll = fingerprint_pre_enroll;
    dev->enroll = fingerprint_enroll;
    dev->post_enroll = fingerprint_post_enroll;
    dev->get_authenticator_id = fingerprint_get_auth_id;
    dev->cancel = fingerprint_cancel;
    dev->remove = fingerprint_remove;
    dev->set_active_group = fingerprint_set_active_group;
    dev->authenticate = fingerprint_authenticate;
    dev->set_notify = set_notify_callback;
    dev->notify = <span class="hljs-literal" style="margin:0px; padding:0px; color:rgb(163,21,21)">NULL</span>;

    g_device = dev;
    <span class="hljs-keyword" style="margin:0px; padding:0px; color:rgb(0,0,255)">if</span>(g_device == <span class="hljs-literal" style="margin:0px; padding:0px; color:rgb(163,21,21)">NULL</span>) {
        ALOGV(<span class="hljs-string" style="margin:0px; padding:0px; color:rgb(163,21,21)">"g_device is NULL"</span>);
    } <span class="hljs-keyword" style="margin:0px; padding:0px; color:rgb(0,0,255)">else</span> {
        ALOGV(<span class="hljs-string" style="margin:0px; padding:0px; color:rgb(163,21,21)">"g_device is not NULL"</span>);
    }

    *device = (<span class="hljs-keyword" style="margin:0px; padding:0px; color:rgb(0,0,255)">hw_device_t</span>*) dev;
    
    hal_init(mDevice);

    <span class="hljs-keyword" style="margin:0px; padding:0px; color:rgb(0,0,255)">return</span> <span class="hljs-number" style="margin:0px; padding:0px">0</span>;
}</code></pre>
<p style="margin:10px auto; padding-top:0px; padding-bottom:0px; color:rgb(51,51,51); font-family:Verdana,Arial,Helvetica,sans-serif; font-size:13.3333px">
就是填充实现<a href="http://lib.csdn.net/base/android" class="replace_word" title="Android知识库" target="_blank" style="color:#df3434; font-weight:bold;">Android</a> 在fingerprint_device.h定义fingerprint_device_t需要实现的这些接口。然后赋给指针device。上层,也就是fingerprintd,就能用这个device来操作hal层的指纹模块了。</p>
<h3 id="二重要的hal_init函数" style="margin:10px 0px; padding:0px; font-size:16px; line-height:1.5; font-family:Verdana,Arial,Helvetica,sans-serif"><a name="t1" target="_blank"></a>
二、重要的hal_init函数。</h3>
<hr style="margin:0px; padding:0px; color:rgb(51,51,51); font-family:Verdana,Arial,Helvetica,sans-serif; font-size:13.3333px">
<p style="margin:10px auto; padding-top:0px; padding-bottom:0px; color:rgb(51,51,51); font-family:Verdana,Arial,Helvetica,sans-serif; font-size:13.3333px">
hal init有如下几个重要的工作要做:</p>
<p style="margin:10px auto; padding-top:0px; padding-bottom:0px; color:rgb(51,51,51); font-family:Verdana,Arial,Helvetica,sans-serif; font-size:13.3333px">
1、 hal_device_open()的工作很简单,就是打开指纹驱动层的设备节点,然后初始化一个用来接收驱动层消息的消息队列。当然在此之前,指纹的驱动层肯定已经正常probe,生成了相应的设备节点。</p>
<pre style="margin-top:10px; margin-bottom:10px; padding:0px; white-space:pre-wrap; word-wrap:break-word; color:rgb(51,51,51); font-size:13.3333px; background-color:rgb(255,255,255)"><code class="hljs dts" style="margin:auto; vertical-align:middle; display:block; height:auto; overflow-x:auto; color:rgb(0,0,0); padding:5px!important; line-height:1.5!important; font-family:"Courier New",sans-serif!important; font-size:12px!important; border:1px solid rgb(204,204,204)!important">fd = open(<span class="hljs-meta-keyword" style="margin:0px; padding:0px">/dev/</span>xxx_fp, O_RDWR);
...
TAILQ_INIT(<span class="hljs-variable" style="margin:0px; padding:0px; color:green">&head</span>);
...</code></pre>
<p style="margin:10px auto; padding-top:0px; padding-bottom:0px; color:rgb(51,51,51); font-family:Verdana,Arial,Helvetica,sans-serif; font-size:13.3333px">
2、检查指纹芯片是否已经正常工作了(在驱动层probe阶段,就会给芯片上电复位,并且加载相应的指纹固件和配置,正常指纹芯片已经开始正常工作了)。如果没有正常工作,就会给芯片复位。将其重新拉到正常的工作状态。</p>
<pre style="margin-top:10px; margin-bottom:10px; padding:0px; white-space:pre-wrap; word-wrap:break-word; color:rgb(51,51,51); font-size:13.3333px; background-color:rgb(255,255,255)"><code class="hljs perl" style="margin:auto; vertical-align:middle; display:block; height:auto; overflow-x:auto; color:rgb(0,0,0); padding:5px!important; line-height:1.5!important; font-family:"Courier New",sans-serif!important; font-size:12px!important; border:1px solid rgb(204,204,204)!important">    err = hal_get_fw_info(&download_fw_flag);
    <span class="hljs-keyword" style="margin:0px; padding:0px; color:rgb(0,0,255)">if</span> (err != GF_SUCCESS) {
        LOG_E(LOG_TAG <span class="hljs-string" style="margin:0px; padding:0px; color:rgb(163,21,21)">"[%s] failed to get firmware info"</span>, __func_<span class="hljs-number" style="margin:0px; padding:0px">_</span>);
    }
    <span class="hljs-keyword" style="margin:0px; padding:0px; color:rgb(0,0,255)">if</span> (!download_fw_flag) {
        hal_reset_chip();
    }</code></pre>
<p style="margin:10px auto; padding-top:0px; padding-bottom:0px; color:rgb(51,51,51); font-family:Verdana,Arial,Helvetica,sans-serif; font-size:13.3333px">
3、与指纹ta建立session,然后调用接口初始化指纹ta。</p>
<pre style="margin-top:10px; margin-bottom:10px; padding:0px; white-space:pre-wrap; word-wrap:break-word; color:rgb(51,51,51); font-size:13.3333px; background-color:rgb(255,255,255)"><code class="hljs r" style="margin:auto; vertical-align:middle; display:block; height:auto; overflow-x:auto; color:rgb(0,0,0); padding:5px!important; line-height:1.5!important; font-family:"Courier New",sans-serif!important; font-size:12px!important; border:1px solid rgb(204,204,204)!important">result = TEEC_OpenSession(g_context, g_session,
             &UUID, TEEC_LOGIN_PUBLIC, <span class="hljs-literal" style="margin:0px; padding:0px; color:rgb(163,21,21)">NULL</span>, &operation, <span class="hljs-literal" style="margin:0px; padding:0px; color:rgb(163,21,21)">NULL</span>);
<span class="hljs-keyword" style="margin:0px; padding:0px; color:rgb(0,0,255)">...</span>

TEEC_Operation operation = { <span class="hljs-number" style="margin:0px; padding:0px">0</span> };
operation.paramTypes = GF_CMD_TEEC_PARAM_TYPES;
operation.params[<span class="hljs-number" style="margin:0px; padding:0px">0</span>].tmpref.buffer = GF_CMD_INIT;
operation.params[<span class="hljs-number" style="margin:0px; padding:0px">0</span>].tmpref.size = len;
ret = TEEC_InvokeCommand(g_session, GF_OPERATION_ID, &operation, <span class="hljs-literal" style="margin:0px; padding:0px; color:rgb(163,21,21)">NULL</span>);
<span class="hljs-keyword" style="margin:0px; padding:0px; color:rgb(0,0,255)">...</span></code></pre>
<p style="margin:10px auto; padding-top:0px; padding-bottom:0px; color:rgb(51,51,51); font-family:Verdana,Arial,Helvetica,sans-serif; font-size:13.3333px">
对<a href="http://lib.csdn.net/base/android" class="replace_word" title="Android知识库" target="_blank" style="color:#df3434; font-weight:bold;">android</a>指纹模块不了解的人可能会问指纹ta是什么?我们先说一下TEE, Trusted Execution Environment (TEE)是主控芯片厂商(mtk,高通等)提供的一个安全的硬件运行环境。指纹ta就是运行在这样一个硬件安全环境下的程序。它保证了指纹敏感数据的安全性。</p>
<p style="margin:10px auto; padding-top:0px; padding-bottom:0px; color:rgb(51,51,51); font-family:Verdana,Arial,Helvetica,sans-serif; font-size:13.3333px">
4、与指纹驱动层建立通信。这里给大家看一种基于netlink,巧妙而简洁的方式。</p>
<p style="margin:10px auto; padding-top:0px; padding-bottom:0px; color:rgb(51,51,51); font-family:Verdana,Arial,Helvetica,sans-serif; font-size:13.3333px">
4.1.1、通信的接收端(hal层)做了哪些处理?我们往下看</p>
<pre style="margin-top:10px; margin-bottom:10px; padding:0px; white-space:pre-wrap; word-wrap:break-word; color:rgb(51,51,51); font-size:13.3333px; background-color:rgb(255,255,255)"><code class="hljs cpp" style="margin:auto; vertical-align:middle; display:block; height:auto; overflow-x:auto; color:rgb(0,0,0); padding:5px!important; line-height:1.5!important; font-family:"Courier New",sans-serif!important; font-size:12px!important; border:1px solid rgb(204,204,204)!important"><span class="hljs-comment" style="margin:0px; padding:0px; color:green">//初始化信号量 g_sem,配合消息队列,用于从消息接受者hal_netlink_recv</span>
<span class="hljs-comment" style="margin:0px; padding:0px; color:green">//到消息处理者handle_thread的消息传递</span>
<span class="hljs-keyword" style="margin:0px; padding:0px; color:rgb(0,0,255)">if</span> (<span class="hljs-number" style="margin:0px; padding:0px">0</span> != sem_init(&g_sem, <span class="hljs-number" style="margin:0px; padding:0px">0</span>, <span class="hljs-number" style="margin:0px; padding:0px">0</span>)) {
    LOG_E(LOG_TAG, <span class="hljs-string" style="margin:0px; padding:0px; color:rgb(163,21,21)">"[%s] init semaphore failed"</span>, __func__);
    <span class="hljs-keyword" style="margin:0px; padding:0px; color:rgb(0,0,255)">break</span>;
}

<span class="hljs-comment" style="margin:0px; padding:0px; color:green">//消息处理线程handle_thread</span>
<span class="hljs-keyword" style="margin:0px; padding:0px; color:rgb(0,0,255)">if</span> (pthread_create(&g_handle_thread, <span class="hljs-literal" style="margin:0px; padding:0px; color:rgb(163,21,21)">NULL</span>, handle_thread, <span class="hljs-literal" style="margin:0px; padding:0px; color:rgb(163,21,21)">NULL</span>) != <span class="hljs-number" style="margin:0px; padding:0px">0</span>) {
    LOG_E(LOG_TAG, <span class="hljs-string" style="margin:0px; padding:0px; color:rgb(163,21,21)">"[%s] pthread_create failed"</span>, __func__);
    <span class="hljs-keyword" style="margin:0px; padding:0px; color:rgb(0,0,255)">break</span>;
}
<span class="hljs-comment" style="margin:0px; padding:0px; color:green">//用ioctl的方式将netlink描述符g_netlink_route传递给驱动层。</span>
<span class="hljs-comment" style="margin:0px; padding:0px; color:green">//这样驱动层就能用这个g_netlink_route与hal层建立消息管道</span>
<span class="hljs-keyword" style="margin:0px; padding:0px; color:rgb(0,0,255)">if</span> (ioctl(fd, GF_IOC_INIT, &g_netlink_route) != <span class="hljs-number" style="margin:0px; padding:0px">0</span>) {
    LOG_E(LOG_TAG, <span class="hljs-string" style="margin:0px; padding:0px; color:rgb(163,21,21)">"[%s] GF_IOC_INIT ioctl failed"</span>, __func__);
    err = GF_ERROR_OPEN_DEVICE_FAILED;
    <span class="hljs-keyword" style="margin:0px; padding:0px; color:rgb(0,0,255)">break</span>;
}
LOG_I(LOG_TAG, <span class="hljs-string" style="margin:0px; padding:0px; color:rgb(163,21,21)">"[%s] g_netlink_route = %d"</span>, __func__, g_netlink_route);

<span class="hljs-comment" style="margin:0px; padding:0px; color:green">//消息接收线程hal_netlink_recv</span>
<span class="hljs-keyword" style="margin:0px; padding:0px; color:rgb(0,0,255)">if</span> (pthread_create(&g_netlink_thread, <span class="hljs-literal" style="margin:0px; padding:0px; color:rgb(163,21,21)">NULL</span>, hal_netlink_recv, <span class="hljs-literal" style="margin:0px; padding:0px; color:rgb(163,21,21)">NULL</span>) != <span class="hljs-number" style="margin:0px; padding:0px">0</span>) {
    LOG_E(LOG_TAG, <span class="hljs-string" style="margin:0px; padding:0px; color:rgb(163,21,21)">"[%s] pthread_create failed"</span>, __func__);
    <span class="hljs-keyword" style="margin:0px; padding:0px; color:rgb(0,0,255)">break</span>;
}</code></pre>
<p style="margin:10px auto; padding-top:0px; padding-bottom:0px; color:rgb(51,51,51); font-family:Verdana,Arial,Helvetica,sans-serif; font-size:13.3333px">
4.1.2、我们先看消息接收线程hal_netlink_recv做了什么。</p>
<pre style="margin-top:10px; margin-bottom:10px; padding:0px; white-space:pre-wrap; word-wrap:break-word; color:rgb(51,51,51); font-size:13.3333px; background-color:rgb(255,255,255)"><code class="hljs cs" style="margin:auto; vertical-align:middle; display:block; height:auto; overflow-x:auto; color:rgb(0,0,0); padding:5px!important; line-height:1.5!important; font-family:"Courier New",sans-serif!important; font-size:12px!important; border:1px solid rgb(204,204,204)!important">        <span class="hljs-comment" style="margin:0px; padding:0px; color:green">/* 初始化netlink并binder 下面这些都是netlink的标准流程*/</span>
        g_netlink_sock_id = socket(AF_NETLINK, SOCK_RAW, g_netlink_route);
        <span class="hljs-keyword" style="margin:0px; padding:0px; color:rgb(0,0,255)">if</span> (g_netlink_sock_id < <span class="hljs-number" style="margin:0px; padding:0px">0</span>) {
            <span class="hljs-keyword" style="margin:0px; padding:0px; color:rgb(0,0,255)">break</span>;
        }

        memset(&local, <span class="hljs-number" style="margin:0px; padding:0px">0</span>, <span class="hljs-keyword" style="margin:0px; padding:0px; color:rgb(0,0,255)">sizeof</span>(<span class="hljs-keyword" style="margin:0px; padding:0px; color:rgb(0,0,255)">struct</span> sockaddr_nl));
        local.nl_family = AF_NETLINK;
        local.nl_pid = getpid();<span class="hljs-comment" style="margin:0px; padding:0px; color:green">/*local process id*/</span>

        local.nl_groups = <span class="hljs-number" style="margin:0px; padding:0px">0</span>;

        ret = bind(g_netlink_sock_id, (<span class="hljs-keyword" style="margin:0px; padding:0px; color:rgb(0,0,255)">struct</span> sockaddr*) &local, 
                    <span class="hljs-keyword" style="margin:0px; padding:0px; color:rgb(0,0,255)">sizeof</span>(<span class="hljs-keyword" style="margin:0px; padding:0px; color:rgb(0,0,255)">struct</span> sockaddr_nl));
        <span class="hljs-keyword" style="margin:0px; padding:0px; color:rgb(0,0,255)">if</span> (ret != <span class="hljs-number" style="margin:0px; padding:0px">0</span>) {
            <span class="hljs-keyword" style="margin:0px; padding:0px; color:rgb(0,0,255)">break</span>;
        }
        

        <span class="hljs-comment" style="margin:0px; padding:0px; color:green">/* send init message */</span>
        memset(&dest, <span class="hljs-number" style="margin:0px; padding:0px">0</span>, <span class="hljs-keyword" style="margin:0px; padding:0px; color:rgb(0,0,255)">sizeof</span>(<span class="hljs-keyword" style="margin:0px; padding:0px; color:rgb(0,0,255)">struct</span> sockaddr_nl));
        dest.nl_family = AF_NETLINK;
        dest.nl_pid = <span class="hljs-number" style="margin:0px; padding:0px">0</span>; <span class="hljs-comment" style="margin:0px; padding:0px; color:green">/*destination is kernel so set to 0*/</span>
        dest.nl_groups = <span class="hljs-number" style="margin:0px; padding:0px">0</span>;

        nlh = (<span class="hljs-keyword" style="margin:0px; padding:0px; color:rgb(0,0,255)">struct</span> nlmsghdr *) malloc(NLMSG_SPACE(MAX_NL_MSG_LEN));
        <span class="hljs-keyword" style="margin:0px; padding:0px; color:rgb(0,0,255)">if</span> (NULL == nlh) {
            LOG_E(LOG_TAG, <span class="hljs-string" style="margin:0px; padding:0px; color:rgb(163,21,21)">"[%s] nlh out of memery"</span>, __func__);
            <span class="hljs-keyword" style="margin:0px; padding:0px; color:rgb(0,0,255)">break</span>;
        }
        nlh->nlmsg_len = NLMSG_SPACE(MAX_NL_MSG_LEN);
        nlh->nlmsg_pid = getpid();
        nlh->nlmsg_flags = <span class="hljs-number" style="margin:0px; padding:0px">0</span>;
        strcpy(NLMSG_DATA(nlh), <span class="hljs-string" style="margin:0px; padding:0px; color:rgb(163,21,21)">"GF"</span>);

        iov.iov_base = (<span class="hljs-keyword" style="margin:0px; padding:0px; color:rgb(0,0,255)">void</span>*) nlh;
        iov.iov_len = nlh->nlmsg_len;

        memset(&msg, <span class="hljs-number" style="margin:0px; padding:0px">0</span>, <span class="hljs-keyword" style="margin:0px; padding:0px; color:rgb(0,0,255)">sizeof</span>(<span class="hljs-keyword" style="margin:0px; padding:0px; color:rgb(0,0,255)">struct</span> msghdr));
        msg.msg_iov = &iov;
        msg.msg_iovlen = <span class="hljs-number" style="margin:0px; padding:0px">1</span>;
        msg.msg_name = (<span class="hljs-keyword" style="margin:0px; padding:0px; color:rgb(0,0,255)">void</span>*) &dest;
        msg.msg_namelen = <span class="hljs-keyword" style="margin:0px; padding:0px; color:rgb(0,0,255)">sizeof</span>(<span class="hljs-keyword" style="margin:0px; padding:0px; color:rgb(0,0,255)">struct</span> sockaddr_nl);
        
        <span class="hljs-comment" style="margin:0px; padding:0px; color:green">//发送一个包含pid的消息给驱动层,相当于握手,告诉驱动层,我这边已经准备ok了。</span>
        <span class="hljs-keyword" style="margin:0px; padding:0px; color:rgb(0,0,255)">if</span> (sendmsg(g_netlink_sock_id, &msg, <span class="hljs-number" style="margin:0px; padding:0px">0</span>) < <span class="hljs-number" style="margin:0px; padding:0px">0</span>) {
            <span class="hljs-keyword" style="margin:0px; padding:0px; color:rgb(0,0,255)">break</span>;
        }
        LOG_D(LOG_TAG, <span class="hljs-string" style="margin:0px; padding:0px; color:rgb(163,21,21)">"[%s] send init msg to kernel"</span>, __func__);

        <span class="hljs-comment" style="margin:0px; padding:0px; color:green">/* 开启一个循环,接收来自驱动层的消息 */</span>
        memset(nlh, <span class="hljs-number" style="margin:0px; padding:0px">0</span>, NLMSG_SPACE(MAX_NL_MSG_LEN));
        
        <span class="hljs-keyword" style="margin:0px; padding:0px; color:rgb(0,0,255)">while</span> (<span class="hljs-number" style="margin:0px; padding:0px">1</span>) {
            <span class="hljs-comment" style="margin:0px; padding:0px; color:green">//LOG_D(LOG_TAG, "here wait message from kernel");</span>
            ret = recvmsg(g_netlink_sock_id, &msg, <span class="hljs-number" style="margin:0px; padding:0px">0</span>);
            <span class="hljs-keyword" style="margin:0px; padding:0px; color:rgb(0,0,255)">if</span> (ret < <span class="hljs-number" style="margin:0px; padding:0px">0</span>) {
                LOG_E(LOG_TAG, <span class="hljs-string" style="margin:0px; padding:0px; color:rgb(163,21,21)">"[%s] recvmsg failed, ret %d"</span>, __func__, ret);
                <span class="hljs-keyword" style="margin:0px; padding:0px; color:rgb(0,0,255)">continue</span>;
            }
            <span class="hljs-keyword" style="margin:0px; padding:0px; color:rgb(0,0,255)">if</span> (<span class="hljs-number" style="margin:0px; padding:0px">0</span> == ret) {
                LOG_E(LOG_TAG, <span class="hljs-string" style="margin:0px; padding:0px; color:rgb(163,21,21)">"[%s] recvmsg failed, ret %d"</span>, __func__, ret);
                <span class="hljs-keyword" style="margin:0px; padding:0px; color:rgb(0,0,255)">continue</span>;
            }
            <span class="hljs-keyword" style="margin:0px; padding:0px; color:rgb(0,0,255)">value</span> = *((<span class="hljs-keyword" style="margin:0px; padding:0px; color:rgb(0,0,255)">char</span> *) NLMSG_DATA(nlh));
            <span class="hljs-comment" style="margin:0px; padding:0px; color:green">//根据消息类别做处理</span>
            <span class="hljs-keyword" style="margin:0px; padding:0px; color:rgb(0,0,255)">if</span> (GF_NETLINK_TEST == <span class="hljs-keyword" style="margin:0px; padding:0px; color:rgb(0,0,255)">value</span>) {
                LOG_D(LOG_TAG, <span class="hljs-string" style="margin:0px; padding:0px; color:rgb(163,21,21)">"[%s] received GF_NETLINK_TEST command"</span>, __func__);

            } <span class="hljs-function" style="margin:0px; padding:0px"><span class="hljs-keyword" style="margin:0px; padding:0px; color:rgb(0,0,255)">else</span> <span class="hljs-title" style="margin:0px; padding:0px; color:rgb(163,21,21)">if</span> (<span class="hljs-params" style="margin:0px; padding:0px">NETLINK_IRQ == <span class="hljs-keyword" style="margin:0px; padding:0px; color:rgb(0,0,255)">value</span> || NETLINK_SCREEN_OFF == <span class="hljs-keyword" style="margin:0px; padding:0px; color:rgb(0,0,255)">value</span>
                    || NETLINK_SCREEN_ON == <span class="hljs-keyword" style="margin:0px; padding:0px; color:rgb(0,0,255)">value</span></span>) </span>{
                <span class="hljs-comment" style="margin:0px; padding:0px; color:green">//如果是中断消息,或者亮灭屏事件,就把消息值push到消息队列。</span>
                <span class="hljs-comment" style="margin:0px; padding:0px; color:green">//然后post信号量,让消息处理线程去处理了。</span>
                enqueue(<span class="hljs-keyword" style="margin:0px; padding:0px; color:rgb(0,0,255)">value</span>);
                sem_post(&g_netlink_sem);
                LOG_D(LOG_TAG, <span class="hljs-string" style="margin:0px; padding:0px; color:rgb(163,21,21)">"[%s] send message : %d"</span>, __func__, <span class="hljs-keyword" style="margin:0px; padding:0px; color:rgb(0,0,255)">value</span>);
            } <span class="hljs-keyword" style="margin:0px; padding:0px; color:rgb(0,0,255)">else</span> {
                LOG_E(LOG_TAG, <span class="hljs-string" style="margin:0px; padding:0px; color:rgb(163,21,21)">"[%s] wrong netlink command %d"</span>, __func__, <span class="hljs-keyword" style="margin:0px; padding:0px; color:rgb(0,0,255)">value</span>);
            }
        }</code></pre>
<p style="margin:10px auto; padding-top:0px; padding-bottom:0px; color:rgb(51,51,51); font-family:Verdana,Arial,Helvetica,sans-serif; font-size:13.3333px">
4.1.3、再看处理线程,等待信号量,收到之后就从消息队列里边取出消息。然后根据不同的值调用相应的处理函数。</p>
<pre style="margin-top:10px; margin-bottom:10px; padding:0px; white-space:pre-wrap; word-wrap:break-word; color:rgb(51,51,51); font-size:13.3333px; background-color:rgb(255,255,255)"><code class="hljs cs" style="margin:auto; vertical-align:middle; display:block; height:auto; overflow-x:auto; color:rgb(0,0,0); padding:5px!important; line-height:1.5!important; font-family:"Courier New",sans-serif!important; font-size:12px!important; border:1px solid rgb(204,204,204)!important"><span class="hljs-keyword" style="margin:0px; padding:0px; color:rgb(0,0,255)">void</span> *handle_thread(<span class="hljs-keyword" style="margin:0px; padding:0px; color:rgb(0,0,255)">void</span> *handle) {

    <span class="hljs-keyword" style="margin:0px; padding:0px; color:rgb(0,0,255)">while</span> (<span class="hljs-number" style="margin:0px; padding:0px">1</span>) {
        sem_wait(&g_netlink_sem);

        err = dequeue(&<span class="hljs-keyword" style="margin:0px; padding:0px; color:rgb(0,0,255)">value</span>);
        <span class="hljs-keyword" style="margin:0px; padding:0px; color:rgb(0,0,255)">if</span> (err != GF_SUCCESS) {
            <span class="hljs-keyword" style="margin:0px; padding:0px; color:rgb(0,0,255)">continue</span>;
        }

        <span class="hljs-keyword" style="margin:0px; padding:0px; color:rgb(0,0,255)">if</span> (GF_NETLINK_IRQ == <span class="hljs-keyword" style="margin:0px; padding:0px; color:rgb(0,0,255)">value</span>) {
            hal_irq();

        } <span class="hljs-function" style="margin:0px; padding:0px"><span class="hljs-keyword" style="margin:0px; padding:0px; color:rgb(0,0,255)">else</span> <span class="hljs-title" style="margin:0px; padding:0px; color:rgb(163,21,21)">if</span> (<span class="hljs-params" style="margin:0px; padding:0px">GF_NETLINK_SCREEN_OFF == <span class="hljs-keyword" style="margin:0px; padding:0px; color:rgb(0,0,255)">value</span></span>) </span>{
            hal_screen_off();

        } <span class="hljs-function" style="margin:0px; padding:0px"><span class="hljs-keyword" style="margin:0px; padding:0px; color:rgb(0,0,255)">else</span> <span class="hljs-title" style="margin:0px; padding:0px; color:rgb(163,21,21)">if</span> (<span class="hljs-params" style="margin:0px; padding:0px">GF_NETLINK_SCREEN_ON == <span class="hljs-keyword" style="margin:0px; padding:0px; color:rgb(0,0,255)">value</span></span>) </span>{
            hal_screen_on();
        }
    } 
}</code></pre>
<p style="margin:10px auto; padding-top:0px; padding-bottom:0px; color:rgb(51,51,51); font-family:Verdana,Arial,Helvetica,sans-serif; font-size:13.3333px">
hal层的设计很清晰。由于中断来的很快,频率也很高,所以这边使用快速接收中断,缓存起来,再慢慢处理的方式处理中断事件,类似于内核中断上下文的处理方式。</p>
<p style="margin:10px auto; padding-top:0px; padding-bottom:0px; color:rgb(51,51,51); font-family:Verdana,Arial,Helvetica,sans-serif; font-size:13.3333px">
4.2.1、讲到这里,肯定对驱动层怎么发送接收消息产生了好奇?本来打算在写驱动层的地方讲的,但是这样这部分内容就中断了,还是现在这里写完吧。很简单,直接看下面的代码注释就能理解。</p>
<pre style="margin-top:10px; margin-bottom:10px; padding:0px; white-space:pre-wrap; word-wrap:break-word; color:rgb(51,51,51); font-size:13.3333px; background-color:rgb(255,255,255)"><code class="hljs cpp" style="margin:auto; vertical-align:middle; display:block; height:auto; overflow-x:auto; color:rgb(0,0,0); padding:5px!important; line-height:1.5!important; font-family:"Courier New",sans-serif!important; font-size:12px!important; border:1px solid rgb(204,204,204)!important"><span class="hljs-function" style="margin:0px; padding:0px"><span class="hljs-keyword" style="margin:0px; padding:0px; color:rgb(0,0,255)">static</span> <span class="hljs-keyword" style="margin:0px; padding:0px; color:rgb(0,0,255)">int</span> <span class="hljs-title" style="margin:0px; padding:0px; color:rgb(163,21,21)">netlink_init</span><span class="hljs-params" style="margin:0px; padding:0px">(<span class="hljs-keyword" style="margin:0px; padding:0px; color:rgb(0,0,255)">void</span>)</span>
</span>{
    <span class="hljs-keyword" style="margin:0px; padding:0px; color:rgb(0,0,255)">struct</span> netlink_kernel_cfg cfg;
    <span class="hljs-built_in" style="margin:0px; padding:0px; color:rgb(0,0,255)">memset</span>(&cfg, <span class="hljs-number" style="margin:0px; padding:0px">0</span>, <span class="hljs-keyword" style="margin:0px; padding:0px; color:rgb(0,0,255)">sizeof</span>(<span class="hljs-keyword" style="margin:0px; padding:0px; color:rgb(0,0,255)">struct</span> netlink_kernel_cfg));
    cfg.input = netlink_recv;
    <span class="hljs-comment" style="margin:0px; padding:0px; color:green">//创建netlink 驱动层的接收hal层消息函数,注意NETLINK_ROUTE要与hal层一致。</span>
    g_dev->nl_sk = netlink_kernel_create(&init_net, NETLINK_ROUTE, &cfg);
}</code></pre>
<p style="margin:10px auto; padding-top:0px; padding-bottom:0px; color:rgb(51,51,51); font-family:Verdana,Arial,Helvetica,sans-serif; font-size:13.3333px">
4.2.2、接收消息的处理:</p>
<pre style="margin-top:10px; margin-bottom:10px; padding:0px; white-space:pre-wrap; word-wrap:break-word; color:rgb(51,51,51); font-size:13.3333px; background-color:rgb(255,255,255)"><code class="hljs cpp" style="margin:auto; vertical-align:middle; display:block; height:auto; overflow-x:auto; color:rgb(0,0,0); padding:5px!important; line-height:1.5!important; font-family:"Courier New",sans-serif!important; font-size:12px!important; border:1px solid rgb(204,204,204)!important"><span class="hljs-function" style="margin:0px; padding:0px"><span class="hljs-keyword" style="margin:0px; padding:0px; color:rgb(0,0,255)">static</span> <span class="hljs-keyword" style="margin:0px; padding:0px; color:rgb(0,0,255)">void</span> <span class="hljs-title" style="margin:0px; padding:0px; color:rgb(163,21,21)">netlink_recv</span><span class="hljs-params" style="margin:0px; padding:0px">(<span class="hljs-keyword" style="margin:0px; padding:0px; color:rgb(0,0,255)">struct</span> sk_buff *__skb)</span>
</span>{
    
    skb = skb_get(__skb);

    <span class="hljs-comment" style="margin:0px; padding:0px; color:green">//消息大于5byte才做处理</span>

    <span class="hljs-keyword" style="margin:0px; padding:0px; color:rgb(0,0,255)">if</span> (skb->len >= NLMSG_SPACE(<span class="hljs-number" style="margin:0px; padding:0px">0</span>)) {
        nlh = nlmsg_hdr(skb);
        <span class="hljs-built_in" style="margin:0px; padding:0px; color:rgb(0,0,255)">memcpy</span>(str, NLMSG_DATA(nlh), <span class="hljs-keyword" style="margin:0px; padding:0px; color:rgb(0,0,255)">sizeof</span>(str));
        <span class="hljs-comment" style="margin:0px; padding:0px; color:green">//拿到了hal层穿下来的pid,保存起来。</span>
        g_gf_dev->pid = nlh->nlmsg_pid;
        
    } <span class="hljs-keyword" style="margin:0px; padding:0px; color:rgb(0,0,255)">else</span> {
        debug(ERR_LOG, <span class="hljs-string" style="margin:0px; padding:0px; color:rgb(163,21,21)">"[%s] : not enough data length\n"</span>, __func__);
    }

    kfree_skb(skb);
}</code></pre>
<p style="margin:10px auto; padding-top:0px; padding-bottom:0px; color:rgb(51,51,51); font-family:Verdana,Arial,Helvetica,sans-serif; font-size:13.3333px">
4.2.3、收到中断或者亮灭屏事件,就调用netlink_send通知hal层:</p>
<pre style="margin-top:10px; margin-bottom:10px; padding:0px; white-space:pre-wrap; word-wrap:break-word; color:rgb(51,51,51); font-size:13.3333px; background-color:rgb(255,255,255)"><code class="hljs cpp" style="margin:auto; vertical-align:middle; display:block; height:auto; overflow-x:auto; color:rgb(0,0,0); padding:5px!important; line-height:1.5!important; font-family:"Courier New",sans-serif!important; font-size:12px!important; border:1px solid rgb(204,204,204)!important"><span class="hljs-function" style="margin:0px; padding:0px"><span class="hljs-keyword" style="margin:0px; padding:0px; color:rgb(0,0,255)">void</span> <span class="hljs-title" style="margin:0px; padding:0px; color:rgb(163,21,21)">netlink_send</span><span class="hljs-params" style="margin:0px; padding:0px">(<span class="hljs-keyword" style="margin:0px; padding:0px; color:rgb(0,0,255)">const</span> <span class="hljs-keyword" style="margin:0px; padding:0px; color:rgb(0,0,255)">int</span> command)</span>
</span>{
    <span class="hljs-comment" style="margin:0px; padding:0px; color:green">//netlink kernel层发送消息的典型流程,就是构造一个消息结构体,然后</span>
    <span class="hljs-comment" style="margin:0px; padding:0px; color:green">//用api netlink_unicast发出去</span>
    skb = alloc_skb(MAX_NL_MSG_LEN, GFP_ATOMIC);
    <span class="hljs-keyword" style="margin:0px; padding:0px; color:rgb(0,0,255)">if</span> (skb == <span class="hljs-literal" style="margin:0px; padding:0px; color:rgb(163,21,21)">NULL</span>) {
        gf_debug(ERR_LOG, <span class="hljs-string" style="margin:0px; padding:0px; color:rgb(163,21,21)">"[%s] : allocate skb failed\n"</span>, __func__);
        <span class="hljs-keyword" style="margin:0px; padding:0px; color:rgb(0,0,255)">return</span>;
    }

    nlh = nlmsg_put(skb, <span class="hljs-number" style="margin:0px; padding:0px">0</span>, <span class="hljs-number" style="margin:0px; padding:0px">0</span>, <span class="hljs-number" style="margin:0px; padding:0px">0</span>, MAX_NL_MSG_LEN, <span class="hljs-number" style="margin:0px; padding:0px">0</span>);
    <span class="hljs-keyword" style="margin:0px; padding:0px; color:rgb(0,0,255)">if</span> (!nlh) {
        kfree_skb(skb);
        <span class="hljs-keyword" style="margin:0px; padding:0px; color:rgb(0,0,255)">return</span>;
    }

    NETLINK_CB(skb).portid = <span class="hljs-number" style="margin:0px; padding:0px">0</span>;
    NETLINK_CB(skb).dst_group = <span class="hljs-number" style="margin:0px; padding:0px">0</span>;
    <span class="hljs-comment" style="margin:0px; padding:0px; color:green">//消息类型的赋值,中断,亮灭屏等</span>
    *(<span class="hljs-keyword" style="margin:0px; padding:0px; color:rgb(0,0,255)">char</span> *)NLMSG_DATA(nlh) = command;
    ret = netlink_unicast(g_gf_dev->nl_sk, skb, g_gf_dev->pid, MSG_DONTWAIT);
}</code></pre>
<p style="margin:10px auto; padding-top:0px; padding-bottom:0px; color:rgb(51,51,51); font-family:Verdana,Arial,Helvetica,sans-serif; font-size:13.3333px">
这样,hal层和驱动层就建立好了通信管道。以后中断等事件就能从驱动层报给hal层,hal层会根据事件类型,做相应处理。</p>
<p style="margin:10px auto; padding-top:0px; padding-bottom:0px; color:rgb(51,51,51); font-family:Verdana,Arial,Helvetica,sans-serif; font-size:13.3333px">
5、调用ta init,初始化ta。</p>
<p style="margin:10px auto; padding-top:0px; padding-bottom:0px; color:rgb(51,51,51); font-family:Verdana,Arial,Helvetica,sans-serif; font-size:13.3333px">
6、开启看门狗,监听ic状态,如果ic挂了就重启ic。</p>
<p style="margin:10px auto; padding-top:0px; padding-bottom:0px; color:rgb(51,51,51); font-family:Verdana,Arial,Helvetica,sans-serif; font-size:13.3333px">
至此,hal层就算初始化完毕了。接下来,上层就可以开始注册指纹了。</p>
<br>
   


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值