栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 系统运维 > 运维 > Linux

Linux驱动怎么在Android上使用

Linux 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

Linux驱动怎么在Android上使用

  最近有Android的项目,学习下在Android上调用Linux驱动的开发流程,找到两个不错的资源。
  推荐一篇文章和一个视频:
  文章:Android硬件抽象层(HAL)概要介绍和学习计划
  视频:Android HAL编程实战
  都讲得很好,浅显易懂。
  

  • HAL层
  • JNI层
  • framework Service
  • APP

  然后讲下自己的理解:

HAL层

  Android 的Hal层是为了给不开放源码的厂商准备,编译Hal代码时会将其编译为.so文件使用。在Hal层中有几个主要的结构,分别是struct hw_module_t、struct hw_module_methods_t 以及struct hw_device_t,这三个结构的主要关系如下图:

  这三个结构体在使用时候是以被包含的形式存在,并且包含它的结构体必须把其放在第一个成员的位置上,这样可以进行相关结构的强制转换。例如上述文章链接中Hal的代码:

  
struct hello_module_t {  
    struct hw_module_t common;  
};  
  
struct hello_device_t {  
    struct hw_device_t common;  
    int fd;  
    int (*set_val)(struct hello_device_t* dev, int val);  
    int (*get_val)(struct hello_device_t* dev, int* val);  
};  

  通常,我们会在hardware/libhardware/include/hardware下定义头文件,在hardware/libhardware/modules/下创建新的文件夹用于存放源文件。
  源文件中会对上述三个结构体进行实例化,并且实现相关功能函数,包括open、close、自定义功能函数等。
  完成Hal的源文件代码编写后,在源文件的同目录下增加Android.mk文件,将Hal代码加入Android系统中。可以使用mmm命令对其单独编译,编译后生成.so的库文件。
  得到库文件后,上层可以使用hw_get_module() 函数,获取对应的struct hw_module_t结构,hw_get_module() 函数的调用关系如下图:

  HAL涉及的文件(参考上述文章):

文件名hello.hhello.cuevent.rcandroid.mkhello.default.so
所在目录hardware/libhardware/include/hardwarehardware/libhardware/modules/hellosystem/core/rootdirhardware/libhardware/modules/helloout/target/product/generic/system/lib/hw
作用定义设备hal相关结构hal层访问linux内核驱动的源码改变设备节点权限,让Hal可以调用编译加载编译完成后输出的库文件
JNI层

  JNI(Java Native Interface),用于提供接口给Java framework Server,代码路径为:frameworks/base/services/jni。
  JNI的接口代码中使用hw_get_module() 函数获得struct hw_module_t结构,利用struct hw_module_t结构去调用open、close等相关功能函数,代码如下:

         
    static jboolean hello_init(JNIEnv* env, jclass clazz) {  
        hello_module_t* module;  
          
        LOGI("Hello JNI: initializing......");  
        if(hw_get_module(HELLO_HARDWARE_MODULE_ID, (const struct hw_module_t**)&module) == 0) {  
            LOGI("Hello JNI: hello Stub found.");  
            if(hello_device_open(&(module->common), &hello_device) == 0) {  
                LOGI("Hello JNI: hello device is open.");  
                return 0;  
            }  
            LOGE("Hello JNI: failed to open hello device.");  
            return -1;  
        }  
        LOGE("Hello JNI: failed to get hello stub module.");  
        return -1;        
    }  

  完成这些接口代码后,使用jniRegisterNativeMethods() 函数进行JNI方法注册。注册代码如下:

          
    static const JNINativeMethod method_table[] = {  
        {"init_native", "()Z", (void*)hello_init},  
        {"setVal_native", "(I)V", (void*)hello_setVal},  
        {"getVal_native", "()I", (void*)hello_getVal},  
    };  
          
    int register_android_server_HelloService(JNIEnv *env) {  
            return jniRegisterNativeMethods(env, "com/android/server/HelloService", method_table, NELEM(method_table));  
    }  

  完成JNI方法注册后,需要通过修改onload.cpp 文件将JNI的源文件加载到Android系统中,并进行相关编译生成.so文件,具体可以参考上述文章链接中的JNI部分。
  JNI涉及的文件:

文件名com_android_server_HelloService.cpponload.cppAndroid.mk
所在目录frameworks/base/services/jniframeworks/base/services/jniframeworks/base/services/jni
作用jni接口源码编译jni编译jni接口源码
framework Service

  framework Service需要编写aidl文件和相关服务的java文件。
  aidl(Android interface definition language),是为了实现Android进程间通信而设计的语言。aidl文件的代码内容如下:

package android.os;  
   
interface IHelloService {  
    void setVal(int val);  
    int getVal();  
}  

  Android系统编译时会根据aidl文件生成相应的stub接口,而java文件中定义的类会继承stub接口,我们只需在java文件中利用JNI提供的接口去实现setVal和getVal两个功能函数即可,具体代码如下:

package com.android.server;  
import android.content.Context;  
import android.os.IHelloService;  
import android.util.Slog;  
public class HelloService extends IHelloService.Stub {  
    private static final String TAG = "HelloService"; 
    //构造函数 
    HelloService() {  
        init_native();  
    }  
    public void setVal(int val) {  
        setVal_native(val);  
    }     
    public int getVal() {  
        return getVal_native();  
    }  
    
    //JNI的接口函数声明
    private static native boolean init_native();  
    private static native void setVal_native(int val);  
    private static native int getVal_native();  
};  

  framework Service涉及的文件

文件名IHelloService.aidlAndroid.mkHelloService.javaSystemServer.java
所在目录frameworks/base/core/java/android/osframeworks/baseframeworks/base/services/java/com/android/serverframeworks/base/services/java/com/android/server
作用与硬件服务进程通讯,增加操作接口配置需要编译的源文件调用jni方法,为frameworks提供硬件服务接口系统服务
APP

  APP不会写。看资料是根据stub函数提供的接口,转换为aidl的接口,再用aidl提供的两个setVal和getVal函数进行相关操作。
  
  
  
  
  
  
  
  
  

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/323972.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号