Android上层apk调用驱动开发(一)

安卓驱动开发和linux驱动开发是一摸一样的,只不过安卓驱动要被上层应用调用到与linux的方式不同

Android 应用调用驱动:

上层apk---->jni层--->驱动层   (这只是一个访问的路径示意图,中间还需要为SElinux和init.rc赋予给apk访问驱动权限问题)

一,驱动层:
1.在驱动路径下新建test目录和修改Makefile

cjx@ubuntu:~/work/linux$ mkdir drivers/test 
cjx@ubuntu:~/work/linux$ vim drivers/Makefile

drivers/Makefile文件末尾添加

obj-y                           += test/

2.新建test.c文件和Makefile

cjx@ubuntu:~/work/linux$ cd drivers/test
cjx@ubuntu:~/work/linux/drivers/test$ vim test.c;vim Makefile

test.c内容如下

#include <linux/delay.h>
#include <linux/errno.h>
#include <linux/input.h>
#include <linux/interrupt.h>
#include <linux/kernel.h>
#include <linux/log2.h>
#include <linux/module.h>
#include <linux/of.h>
#include <linux/platform_device.h>
#include <linux/reboot.h>
#include <linux/regmap.h>
#include <linux/slab.h>
#include <linux/input/sparse-keymap.h>
#include <linux/gpio_keys.h>

#include <linux/ioport.h>
#include <linux/init.h>
#include <linux/wait.h>
#include <linux/fs.h>
#include <linux/cdev.h>
#include <asm/uaccess.h>       


typedef struct _test_t {
	timming_t timing;
	unsigned long long pininfo;
	RTK_GPIO_ID gid;
	struct cdev cdev;
	struct class *class;
}test_t;
static dev_t devno_base;


static
int test_open(struct inode *inode, struct file *file)
{
	printk(KERN_ALERT  "cjx open================================\n");

	return 0;
}

static
int test_release(struct inode *inode, struct file *file)
{
	return 0;
}


static
long test_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
{
	printk(KERN_ALERT  "cjx============================\n", cmd, arg);
	return 0;
}

static struct file_operations test_fops = {
	.owner = THIS_MODULE,
	.unlocked_ioctl = test_ioctl,
	.open = test_open,
	.release = test_release,
};

static char *test_devnode(struct device *dev, mode_t *mode)
{
	if(mode)
		*mode = 0666;
	return NULL;
}


static int __init test_module_init(void)
{
	unsigned int result = 0;
	int major_node = 0;
	int minor_node = 0;
	
	if (alloc_chrdev_region(&devno_base, 0, 1, "test") != 0)
			return -EFAULT;
		
	major_node = MAJOR(devno_base);
	test_info.class = class_create(THIS_MODULE, "test-dev"); 
	if (IS_ERR(test_info.class)) {
			result = PTR_ERR(test_info.class);
			goto err_create_class_failed;
	}
	test_info.class->devnode = test_devnode;  
	
	cdev_init(&test_info.cdev, &test_fops);
	test_info.cdev.owner = THIS_MODULE;
	test_info.cdev.ops = &test_fops;
	cdev_add (&test_info.cdev, MKDEV(major_node, minor_node), 1);
	device_create(test_info.class, NULL, MKDEV(major_node, minor_node), NULL, "test");

	return 0;

err_create_class_failed:
	unregister_chrdev_region(devno_base, 1);
	return result;
}

static void __exit test_module_exit(void)
{
	device_destroy(test_info.class, MKDEV(0, 0));
	cdev_del(&test_info.cdev);
    unregister_chrdev_region(devno_base, 1);
	class_destroy(test_info.class);
}

MODULE_LICENSE("GPL");
module_init(test_module_init);
module_exit(test_module_exit);

Makefile:

obj-y += test.o

到这里驱动层已经添加完毕,编译烧录后会产生/dev/test文件

二:应用层和jni层:

在要调用的驱动的apk的代码下新建test.java

mkdir src/android/hikeen/
vim src/android/hikeen/test.java

 

/***test.java:***/
package android.hikeen;

public class test {
        private static test mtest = null;
        private static boolean isOpen = false;

        static {
                System.loadLibrary("test");
        }
        public native void inittest();
        public native void test(int direction, int repeat, int time);
        public native void move(int direction, int repeat, int time);
        public native void closetest();
        public native int istesting();

        public static test getInstance(){
                if (mtest == null) {
                        mtest = new test();
                }
                return mtest;
        };

        public void open(){
                if (!isOpen) {
                        inittest();
                }
                isOpen = true;
        };

        public void close(){
                if (isOpen) {
                        closetest();
                }
                isOpen = false;
        };
}
cd src;
javah android.hikeen.test   //在当前文件夹下就会产生android_hikeen_test.h文件,这个就是jni c++的头文件

一般写jni的位置在源码/external下
mkdir 源码/external/test/
将android_hikeen_test.h 移到 源码/external/test/
然后在源码/external/test/路径下新建Android.mk  android_hikeen_test.cpp

/***android_hikeen_test.cpp***/
#include <jni.h>
#include <android/bitmap.h>
#include <stdio.h>
#include <stdlib.h>
#include <android/log.h>

#include <math.h>                                                                                                    

#include <unistd.h>
#include <stdio.h>
#include <fcntl.h>
#include <linux/fb.h>
#include <sys/mman.h>
#include <stdlib.h>
#include <sys/ioctl.h>
#include <string.h>

#include <errno.h>
#include <linux/input.h>
#include <stdint.h>


#include <pthread.h>

#define SCROLL_UP		0
#define SCROLL_DOWN		1
#define SCROLL_LEFT		2
#define SCROLL_RIGHT	3
#include<android/log.h>

#define MOVE_UP			11
#define MOVE_DOWN		22

#include "android_hikeen_test.h"

#ifdef __cplusplus
extern "C" {
#endif
int fd;

#define TAG "myDemo-jni" // 这个是自定义的LOG的标识 
#define LOGD(...) __android_log_print(ANDROID_LOG_DEBUG,TAG ,__VA_ARGS__) // 定义LOGD类型 
#define LOGI(...) __android_log_print(ANDROID_LOG_INFO,TAG ,__VA_ARGS__) // 定义LOGI类型 
#define LOGW(...) __android_log_print(ANDROID_LOG_WARN,TAG ,__VA_ARGS__) // 定义LOGW类型 
#define LOGE(...) __android_log_print(ANDROID_LOG_ERROR,TAG ,__VA_ARGS__) // 定义LOGE类型 
#define LOGF(...) __android_log_print(ANDROID_LOG_FATAL,TAG ,__VA_ARGS__) // 定义LOGF类型 

JNIEXPORT void JNICALL Java_android_hikeen_test_inittest(JNIEnv *, jobject)
  {
	  fd = open("/dev/test", O_RDWR);
	  if(fd < 0) {
		LOGD("open test file error %d",fd);
      }
	
  }

JNIEXPORT void JNICALL Java_android_hikeen_test_test(JNIEnv *, jobject , jint direction, jint repeat, jint time)
{
	int i=direction+repeat+time,ret;
	LOGD(" test test i= %d",i);
	ret=ioctl(fd,1);
	
	if(ret<0){
		LOGD("ioctl test file error %d",ret);
	}
	return ;
}

JNIEXPORT void JNICALL Java_android_hikeen_test_move(JNIEnv *, jobject , jint direction, jint repeat, jint time)
{
	int i=direction+repeat+time,ret=0;
	LOGD(" test test i= %d",i);
	ret=ioctl(fd,1);
	if(ret<0){
		LOGD(" move test file error %d",ret);
	}
	return ;
	
}

JNIEXPORT void JNICALL Java_android_hikeen_test_closetest(JNIEnv *, jobject)
  {
	  close(fd);
	  LOGD(" close test file error");
  }
JNIEXPORT jint JNICALL Java_android_hikeen_test_istesting(JNIEnv *, jobject)
  {
	  return 0;
  }

#ifdef __cplusplus
}
#endif
/***Android.mk***/
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)

LOCAL_MODULE  := libtest


LOCAL_CFLAGS += -DGL_GLEXT_PROTOTYPES -DEGL_EGLEXT_PROTOTYPES

LOCAL_CFLAGS += -Wall -Werror -Wunused -Wunreachable-code -Wunused-parameter

LOCAL_SRC_FILES := android_hikeen_test.cpp

LOCAL_MODULE_TAGS := eng debug

	
LOCAL_LDLIBS := -ljnigraphics	
LOCAL_LDLIBS += -llog

include $(BUILD_SHARED_LIBRARY)

编译烧录完成后在板子上的system/lib/下就有libtest.so这个文件,这个就是test 的jni库

到现在还未完成,因为还需要赋权限和SELinux的权限才能正常调用

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

hmbbPdx_

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值