安卓驱动、HAL、JNI与java

最近看了安卓驱动层到应用层的实现,总结一下所学,新手学习,不足之处请指正(以LED为例):

网址:http://blog.csdn.net/liruicom/article/details/8517948

由驱动层到应用层的流程Linux驱动->HAL->JNI->APK

首先是驱动层:

1)创建cdev与实现file_operations 。

2)module_init与module_exit的实现:在module_init中实现cdev_init()、register_chrdev_region()或alloc_chrdev_region()与cdev_add(),同时实现class_create()、device_class()。在module_exit中实现device_destroy()、class_destroy()与unregister_chrdev_region()。

3)open与release函数的实现,open函数中实现gpio_request()、s3c_gpio_cfgpin()、gpio_direction_output()函数。release函数中实现gpio_free()。

4)ioctl函数实现

5)MODULE_LICENSE("GPL")

6)对Makefile与Kconfig函数修改。

其次HAL层实现:

HAL层的入口函数为HAL_MODULE_INFO_SYM,调用过程为HAL_MODULE_INFO_SYM-> hw_module_methods_t->open,在open中对包含hw_device_t的结构体进行一系列初始化,并打开LED驱动设备。具体实现过程如下:

1)定义结构体和宏

hw_module_t,hw_device_t及IO,HAL规定不可直接使用hw_module_t结构体,因此,需要在hw_module_t外再套一层结构体。hw_module_t及hw_device_t自定义结构体内的第一个成员变量数据结构必须为hw_module_t与hw_device_t。在hw_device_t自定义的结构体内可定义函数指针,函数指针的数量与参数可自己定义,但必须与上层调用形式保存一致。

2)编写HAL模块的open函数

(1)初始化hw_device_t子结构体、必要操作、硬件操作函数指针。

(2)打开设备文件。

(3)初始化寄存器

3)定义hw_module_methods_t结构体变量

4)定义HAL_MODULE_INFO_SYM变量,一般为hw_module_t或子结构体,并对其初始化。

5)编写HAL模块close函数

6)编写控制函数

7)编写Android.mk

再次编写JNI函数

1)编写JNI_Onload函数,系统在成功装载JNI共享库后自动调用,一般用于初始化JNI,函数如下:主要实现功能:告诉JavaVm使用虚拟机那一个版本:初值设定获取JavaVm接口

/*没有理解JNI_OnLoad函数与register_android_server_LedService函数,若您理解了之后可以留言教我一下吗*/

jint JNI_OnLoad(JavaVM* vm, void* reserved)
{
JNIEnv* env = NULL;
jint result = -1;
if (vm->GetEnv((void**) &env, JNI_VERSION_1_4) != JNI_OK) {
LOGE("GetEnv failed!");
return result;
}
LOG_ASSERT(env, "Could not retrieve the env !");
register_android_server_LedService( env );//将JNI程序库与Java类绑定
return JNI_VERSION_1_4;
}

int register_android_server_LedService(JNIEnv *env)
{
static const char* const kClassName = " android /server/LedService";/*kclassname‍ 指定了需要调用该Jni库的Java APP类*/
jclass clazz;
/* look up the class */
clazz = env->FindClass(kClassName);
if (clazz == NULL)
{
LOGE("Can't find class %s/n", kClassName);
return -1;
}
/* register all the methods */
if (env->RegisterNatives(clazz, method_table,
sizeof(method_table) / sizeof(method_table[0])) != JNI_OK)
{
LOGE("Failed registering methods for %s/n", kClassName);
return -1;
}

/* fill out the rest of the ID cache */
return 0;
}

/*JNI与JAVA对应映射表,格式:要注册到java类中的方法名;方法参数与返回值的类型;要注册到JNI的指针函数*/

static JNINativeMethod method_table[] = {
{ "led_init", "()Z", (void*)Java_com_embedsky_led_LedActivity_ledInit },
{ "led_setOn", "(I)Z", (void*)Java_com_embedsky_led_LedActivity_ledSetOn },
{ "led_setOff", "(I)Z", (void*)Java_com_embedsky_led_LedActivity_ledSetOff },
{ "led_close", "()Z", (void*)Java_com_embedsky_led_LedActivity_ledClose },

2)实现method_table[] 中JNI的指针函数,在init中调用hw_get_module函数,实现通过调用hw_get_module函数找到HAL中定义头文件的ID来查找HAL模块,并获得hw_module_t的子结构,来调用hw_module_methods_t中的open函数来初始化hw_device_t的子结构体。

最后实现JAVA函数

1)package xxx/*声明源文件中的类属于哪个具体包,包的名字是有层次的,各层之间以点分割,必须与文件系统结构相同*/

2)import xxx /*将其他包中的类引入当前名字空间中*/

3)public class LedActivity extends Activity {
static {
System.loadLibrary("led");??
作用是什么,不太理解?
}
/*在C++中实现native函数,需要特定格式,可以用javah来帮助声明用javac编译我们的java类,获得class文件,然后javah xxx.class 生成.h文件JNI格式按.h文件书写*/

public static native boolean ledInit();/*要将JNI调用的方法做本地声明,关键词native*/
public static native boolean ledClose();
private static native boolean ledSetOn(int number);
private static native boolean ledSetOff(int number);

CheckBox[] cb = new CheckBox[8];
CheckBox cbAll;// 全选
Button btnQuit;// 退出按钮
@Override
/*重写父类,加 @Override系统可以帮你检查方法的正确性*/
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);

setContentView(R.layout.main);
// 获取 xml 中对应的控件
cb[0] = (CheckBox) findViewById(R.id.cbLed1);
cb[1] = (CheckBox) findViewById(R.id.cbLed2);
cb[2] = (CheckBox) findViewById(R.id.cbLed3);
cb[3] = (CheckBox) findViewById(R.id.cbLed4);
cb[4] = (CheckBox) findViewById(R.id.cbLed5);
cb[5] = (CheckBox) findViewById(R.id.cbLed6);
cb[6] = (CheckBox) findViewById(R.id.cbLed7);
cb[7] = (CheckBox) findViewById(R.id.cbLed8);
cbAll = (CheckBox) findViewById(R.id.cbLedAll);
btnQuit = (Button) findViewById(R.id.btnQuit);
// 初始化点击事件对象

// 初始化点击事件对象
MyClickListener myClickListern = new MyClickListener();
// LED1-LED8 选中 / 取消事件
for (int i = 0; i < 8; i++) {
cb[i].setOnClickListener(myClickListern);
}
// 全选选中 / 取消事件
cbAll.setOnClickListener(myClickListern);
// 退出按钮点击事件处理
btnQuit.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
finish();
}
}
// led 初始化
if (!ledInit()) {
new AlertDialog.Builder(this).setTitle("init led fail").show();
//led 初始化失败,则使控件不可点击

for (int i = 0; i < 8; i++)
cb[i].setEnabled(false);
cbAll.setEnabled(false);
}
}

// 自定义的事件监听器类,用来处理 CheckBox 选中和取消事件
public class MyClickListener implements OnClickListener {

@Override
public void onClick(View v) {
// 遍历数组,判断是哪个 led 控件被选中
for (int i = 0; i < 8; i++) {
if (v == cb[i]) {
// 根据选中 / 取消状态来控制 led 灯的亮 / 灭
controlLed(i + 1, cb[i].isChecked());
return;
}
}
// 全选按钮,遍历数组,对所有 led 灯做控制
if (v == cbAll) {
for (int i = 0; i < 8; i++) {
controlLed(i + 1, cbAll.isChecked());
cb[i].setChecked(cbAll.isChecked());
}
}
}

/*******************************************/
// 功能: LED 亮 / 灭处理
// 参数:
// number : 灯编号
// on :true ,亮 ;fase, 灭
/*******************************************/
private void controlLed(int number, boolean on) {
if (on) {
ledSetOn(number);
} else {
ledSetOff(number);
}
}

}

http://blog.csdn.net/liruicom/article/details/8517948

你可能感兴趣的:(安卓驱动、HAL、JNI与java)