Android字符设备驱动开发基于高通msm8916原创
Posted 请给我倒杯茶
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Android字符设备驱动开发基于高通msm8916原创 相关的知识,希望对你有一定的参考价值。
本人才疏浅学,写一篇文档总结自己在msm8916平台上移植自己编写的简单的字符设备驱动开发的整个流程。这个小项目的主要功能是开发一个简单的APP,APP通过JNI去调用位于kernel的字符设备驱动。
APP的设计,开发平台android Studio
主要的文件是下面的三个文件:
MainActivity.java文件的内容如下:
1 package com.example.administrator.myled; 2 3 import android.nfc.Tag; 4 import android.support.v7.app.AppCompatActivity; 5 import android.os.Bundle; 6 import android.util.Log; 7 import android.view.View; 8 import android.widget.Button; 9 import android.widget.Toast; 10 11 12 import com.zbahuang.led.lowlevel.LedNative; 13 14 public class MainActivity extends AppCompatActivity implements View.OnClickListener { 15 private final static String TAG = "zbzhuang"; 16 Button btn_led_on; 17 Button btn_led_off; 18 LedNative myled; 19 20 21 @Override 22 protected void onCreate(Bundle savedInstanceState) { 23 super.onCreate(savedInstanceState); 24 setContentView(R.layout.activity_main); 25 26 initUI(); 27 28 myled = new LedNative(); 29 myled.openDev(); 30 Log.d(TAG,"app:open Dev"); 31 } 32 33 private void initUI() { 34 btn_led_on = (Button) findViewById(R.id.btn_led_on); 35 btn_led_on.setOnClickListener(this); 36 37 btn_led_off = (Button) findViewById(R.id.btn_led_off); 38 btn_led_off.setOnClickListener(this); 39 } 40 41 @Override 42 public void onClick(View v) { 43 switch (v.getId()){ 44 case R.id.btn_led_on: 45 Toast.makeText(MainActivity.this,"拉灯-->",Toast.LENGTH_SHORT).show(); 46 Log.d(TAG,"app:LED on"); 47 myled.devOn(); 48 break; 49 case R.id.btn_led_off: 50 Toast.makeText(MainActivity.this,"灭灯-->",Toast.LENGTH_SHORT).show(); 51 Log.d(TAG,"app:LED off"); 52 myled.devOff(); 53 break; 54 default: 55 break; 56 } 57 58 } 59 60 @Override 61 protected void onDestroy() { 62 super.onDestroy(); 63 myled.closeDev(); 64 Log.d(TAG,"app:close Dev"); 65 } 66 }
LedNative.java文件的内容如下:
在这个文件中所声明的方法是在jni中实现的啊。使用了特殊的关键字表示该方法是在JNI当中实现的啊。
1 package com.zbahuang.led.lowlevel; 2 3 /** 4 * Created by Administrator on 2017/3/29 0029. 5 */ 6 7 public class LedNative { 8 9 static { 10 System.loadLibrary("led_jni"); 11 } 12 13 public native int openDev(); 14 public native int devOn(); 15 public native int devOff(); 16 public native int closeDev(); 17 } 18 package com.zbahuang.led.lowlevel; 19 20 /** 21 * Created by Administrator on 2017/3/29 0029. 22 */ 23 24 public class LedNative { 25 26 static { 27 System.loadLibrary("led_jni"); 28 } 29 30 public native int openDev(); 31 public native int devOn(); 32 public native int devOff(); 33 public native int closeDev(); 34 }
activity_main.xml文件的内容如下:
1 <?xml version="1.0" encoding="utf-8"?> 2 <android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android" 3 xmlns:app="http://schemas.android.com/apk/res-auto" 4 xmlns:tools="http://schemas.android.com/tools" 5 android:layout_width="match_parent" 6 android:layout_height="match_parent" 7 tools:context="com.example.administrator.myled.MainActivity"> 8 9 10 <RelativeLayout 11 android:layout_width="394dp" 12 android:layout_height="520dp" 13 tools:layout_editor_absoluteX="-5dp" 14 tools:layout_editor_absoluteY="-10dp"> 15 16 <Button 17 android:id="@+id/btn_led_on" 18 android:layout_width="wrap_content" 19 android:layout_height="wrap_content" 20 android:layout_alignParentStart="true" 21 android:layout_alignParentTop="true" 22 android:layout_marginStart="56dp" 23 android:layout_marginTop="109dp" 24 android:text="拉灯" /> 25 26 <Button 27 android:id="@+id/btn_led_off" 28 android:layout_width="wrap_content" 29 android:layout_height="wrap_content" 30 android:layout_alignBaseline="@+id/btn_led_on" 31 android:layout_alignBottom="@+id/btn_led_on" 32 android:layout_marginStart="81dp" 33 android:layout_toEndOf="@+id/btn_led_on" 34 android:text="灭灯" /> 35 </RelativeLayout> 36 </android.support.constraint.ConstraintLayout>
JNI的文件:
led_jni.cpp
1 #include <sys/types.h> 2 #include <sys/stat.h> 3 #include <fcntl.h> 4 #include <unistd.h> 5 #include <errno.h> 6 #include <string.h> 7 8 9 #define LOG_TAG "zbzhuang" 10 #include <utils/Log.h> 11 12 #include "jni.h" 13 14 15 16 17 static jint fd; 18 19 20 static jint open_led(JNIEnv *env,jobject thiz) 21 { 22 ALOGD("JNI:-----------%s--------------",__FUNCTION__); 23 24 fd = open("/dev/led1",O_RDWR); 25 if(fd < 0){ 26 ALOGD("JNI:open error:%s\\n",strerror(errno)); 27 return -1; 28 } 29 30 return 0; 31 } 32 33 34 static jint led_on(JNIEnv *env,jobject thiz) 35 { 36 ALOGD("JNI:-----------%s--------------",__FUNCTION__); 37 jint ret ; 38 jint on = 1; 39 40 ret = write(fd,&on,4); 41 if(ret < 0){ 42 ALOGD("JNI:write off error:%s\\n",strerror(errno)); 43 return -1; 44 } 45 46 47 return 0; 48 } 49 50 51 static jint led_off(JNIEnv *env,jobject thiz) 52 { 53 ALOGD("JNI:-----------%s--------------",__FUNCTION__); 54 jint ret; 55 jint off = 0; 56 57 ret = write(fd,&off,4); 58 if(ret < 0){ 59 ALOGD("JNI:write off error:%s\\n",strerror(errno)); 60 return -1; 61 } 62 63 return 0; 64 } 65 66 67 static jint close_led(JNIEnv *env,jobject thiz) 68 { 69 ALOGD("JNI:-----------%s--------------",__FUNCTION__); 70 close(fd); 71 72 return 0; 73 } 74 75 76 77 78 79 const JNINativeMethod led_jni_methods[] = { 80 {"openDev","()I",(void *)open_led}, 81 {"devOn","()I",(void *)led_on}, 82 {"devOff","()I",(void *)led_off}, 83 {"closeDev","()I",(void *)close_led}, 84 85 86 }; 87 88 89 90 91 92 93 94 jint JNI_OnLoad(JavaVM * vm,void * reserved) 95 { 96 JNIEnv *env = NULL; 97 jint ret ; 98 99 100 101 ALOGD("%s[%s:%d]JNI:--------------^_&--------------------\\n",__func__,__FILE__,__LINE__); 102 ret = vm->GetEnv((void * *)&env,JNI_VERSION_1_4); 103 if(ret != JNI_OK){ 104 ALOGE("JNI:vm->GetEnv error"); 105 return -1; 106 } 107 108 jclass clz = env->FindClass("com/zbahuang/led/lowlevel/LedNative"); 109 110 if(clz == NULL){ 111 ALOGE("%s[%s:%d]JNI:env->FindClass error",__func__,__FILE__,__LINE__); 112 return -1; 113 } 114 115 ret = env->RegisterNatives(clz, 116 led_jni_methods, 117 sizeof(led_jni_methods)/sizeof(led_jni_methods[0])); 118 119 if(ret < 0){ 120 ALOGE("%s[%s:%d]JNI:env->RegisterNatives error\\n",__func__,__FILE__,__LINE__); 121 return -1; 122 } 123 124 125 126 return JNI_VERSION_1_4; 127 128 129 130 }
Android.mk
1 LOCAL_PATH:= $(call my-dir) 2 include $(CLEAR_VARS) 3 4 LOCAL_MODULE_TAGS := optional 5 6 LOCAL_MODULE:= libled_jni 7 8 LOCAL_SRC_FILES:= \\ 9 led_jni.cpp 10 11 LOCAL_SHARED_LIBRARIES := \\ 12 libutils liblog 13 14 LOCAL_C_INCLUDES += \\ 15 $(JNI_H_INCLUDE) 16 17 include $(BUILD_SHARED_LIBRARY)
执行: mmm mytest/led_jni/ 之后会生成动态库放在 out/target/product/msm8916_64/obj/lib/libled_jni.so
将这个库推送到平板电脑就可以通过这个库去调用驱动。
内核的驱动文件:kernel/drivers/input/misc/led.c
1 /*1. 头文件*/ 2 #include<linux/init.h> 3 #include<linux/module.h> 4 #include<linux/fs.h> 5 #include<linux/device.h> 6 #include<linux/slab.h> 7 #include<linux/cdev.h> 8 #include<asm/uaccess.h> 9 #include<asm/io.h> 10 11 static unsigned int led_major=0; 12 volatile unsigned long *gpc0con = NULL; 13 volatile unsigned long *gpc0dat = NULL; 14 15 struct led_device{ 16 struct class *led_class ; //表示一类设备, 存储某些信息 17 struct device *led_device ; //表示一个设备 18 struct cdev *led_cdev; 19 unsigned int val; 20 21 }; 22 23 struct led_device *s5pv_led_dev; 24 25 26 /*可用于查询LED的状态*/ 27 static ssize_t led_read(struct file *file, char __user *buf, size_t count, loff_t *opps) 28 { 29 int ret; 30 31 ret = copy_to_user(buf, &s5pv_led_dev->val, count); 32 if(ret>0) 33 { 34 printk(KERN_ERR "zbzhuang### copy to user failed!\\n"); 35 return ret; 36 } 37 38 printk(KERN_INFO "zbzhuang### val=%d\\n", s5pv_led_dev->val); 39 40 return ret?0:count; 41 } 42 static ssize_t led_write(struct file *file, const char __user *buf, size_t count, loff_t *opps) 43 { 44 int ret; 45 46 /*拷贝成功,返回0; 拷贝失败, 返回没有被拷贝的字节数*/ 47 ret = copy_from_user(&s5pv_led_dev->val, buf, count); 48 if(ret>0) 49 { 50 printk(KERN_ERR "zbzhuang### copy from user failed!\\n"); 51 return ret; 52 } 53 54 if(s5pv_led_dev->val) 55 { 56 /*点亮LED*/ 57 //*gpc0dat |= ((0x1<<3)|(0x1<<4)); 58 printk(KERN_ERR "zbzhuang### led on\\n"); 59 } 60 else 61 { 62 /*熄灭LED*/ 63 // *gpc0dat &= ~((0x1<<3)|(0x1<<4)); 64 printk(KERN_ERR "zbzhuang### led off\\n"); 65 } 66 67 return ret?0:count; 68 } 69 70 71 72 static int led_open(struct inode *inode, struct file *file) 73 { 74 #if 0 75 /*1. 将物理地址映射为虚拟地址*/ 76 gpc0con = ioremap(0xE0200060, 8); 77 gpc0dat = gpc0con +1; 78 79 /*2. 初始化GPC0_3,4引脚功能为输出*/ 80 *gpc0con &= ~((0xf<<12)|(0xf<<16)); 81 *gpc0con |= ((0x1<<12)|(0x1<<16)); 82 #endif 83 printk(KERN_ERR "zbzhuang### -----------%s-------------\\n",__FUNCTION__); 84 85 return 0; 86 } 87 88 static int led_close(struct inode *inode, struct file *file) 89 { 90 #if 0 91 92 *gpc0con &= ~((0xf<<12)|(0xf<<16)); 93 iounmap(gpc0con); 94 #endif 95 printk(KERN_ERR "zbzhuang### ------------%s-----------------\\n",__FUNCTION__); 96 97 return 0; 98 99 } 100 101 /*硬件操作方法*/ 102 struct file_operations led_fops={ 103 .owner = THIS_MODULE, //当前模块所用 104 .open = led_open, 105 .write = led_write, 106 .read = led_read, 107 .release = led_close, 108 109 }; 110 111 static void setup_led_cdev(void) 112 { 113 /*1. 为cdev结构体分配空间*/ 114 s5pv_led_dev->led_cdev = cdev_alloc(); 115 116 /*2. 初始化cdev结构体*/ 117 cdev_init(s5pv_led_dev->led_cdev, &led_fops); 118 119 /*3. 注册cdev,加载到内核哈希表中*/ 120 cdev_add(s5pv_led_dev->led_cdev, MKDEV(led_major, 0), 1); 121 122 } 123 124 /*2. 实现模块加载函数*/ 125 static int __init led_init(void) 126 { 127 dev_t devno; 128 int ret; 129 /*1. 新的申请主设备号的方法*/ 130 if(led_major) 131 { 132 /*静态申请*/ 133 devno = MKDEV(led_major, 0); 134 register_chrdev_region(devno, 1, "led"); 135 } 136 else 137 { 138 /*动态申请*/ 139 alloc_chrdev_region(&devno, 0, 1, "led"); 140 led_m以上是关于Android字符设备驱动开发基于高通msm8916原创 的主要内容,如果未能解决你的问题,请参考以下文章