ioctl设备操作

您所在的位置:网站首页 ioctl接口 ioctl设备操作

ioctl设备操作

#ioctl设备操作| 来源: 网络整理| 查看: 265

目录

前提背景:

NDK环境搭建和Demo代码实现

环境搭建

下载NDK包和配置环境变量

代码实现

创建Android.mk, Application.mk, touch.cpp这3个文件

 应用层app demo实现

 使用android studio创建默认工程

 引用libtouch.so库文件

 编译运行安装touch应用

设备驱动程序ioctl实现关键代码

前提背景:

1. 底层设备驱动已经实现ioctl相关操作接口

2. 本篇主要讲如何实现JNI层和应用层的ioctl相关内容

3. 这里是基于sda810开发板调试,其他arm开发板搭载安卓系统均可以调试

NDK环境搭建和Demo代码实现 环境搭建 下载NDK包和配置环境变量

 1.到官网下载android-ndk-r13b-windows-x86_64.zip(我用的是这个版本,最新版本)

 2.解压缩后将目录添加到PATH中,我这里是d:\android-ndk-r13b\

 3.测试如下图,表示配置成功

 

代码实现 创建Android.mk, Application.mk, touch.cpp这3个文件

Note:这3个文件放在同一目录,我这里放在jni目录

1. Android.mk

LOCAL_PATH := $(call my-dir) include $(CLEAR_VARS) LOCAL_LDLIBS :=-llog LOCAL_MODULE := touch LOCAL_SRC_FILES := touch.cpp include $(BUILD_SHARED_LIBRARY)

2. Application.mk

APP_ABI := all #编译所有平台

3. touch.cpp (文件名和Android.mk 的 MODULE匹配, JNI里面的语法知识不做介绍)

#include #include #include #define TAG "TOUCH-JNI" // 这个是自定义的LOG的标识 #define LOGD(...) __android_log_print(ANDROID_LOG_DEBUG,TAG ,__VA_ARGS__) #define LOGI(...) __android_log_print(ANDROID_LOG_INFO,TAG ,__VA_ARGS__) #define LOGW(...) __android_log_print(ANDROID_LOG_WARN,TAG ,__VA_ARGS__) #define LOGE(...) __android_log_print(ANDROID_LOG_ERROR,TAG ,__VA_ARGS__) #define LOGF(...) __android_log_print(ANDROID_LOG_FATAL,TAG ,__VA_ARGS__) #define CTS_TOOL_IOCTL_GET_DRIVER_VERSION 0x80084300 #define CTS_TOOL_IOCTL_GET_DEVICE_TYPE 0x80084301 #define CTS_TOOL_IOCTL_GET_FW_VERSION 0x80084302 #define CTS_TOOL_IOCTL_GET_RESOLUTION 0x80084303 #define CTS_TOOL_IOCTL_GET_ROW_COL 0x80084304 #define CTS_TOOL_IOCTL_TEST 0xc0084310 #define CTS_TOOL_IOCTL_RDWR_REG 0xc0084320 #define CTS_TOOL_IOCTL_UPGRADE_FW 0xc0084321 extern "C" { jstring Java_com_chipone_touch_MainActivity_getStringFromJni(JNIEnv* jni, jobject obj) { return jni->NewStringUTF("Hello jni!"); } jlong Java_com_chipone_touch_MainActivity_ioctl(JNIEnv* jni, jobject obj, jint code, jlong arg) { char path[30] = "/proc/icn85xx_tool"; int fd = 0; LOGE("code:0x%x arg:0x%x", code, arg); fd = open(path, O_RDWR); if (fd < 0) { LOGE("Open file failed"); return -1; } switch (code) { case CTS_TOOL_IOCTL_GET_DRIVER_VERSION: case CTS_TOOL_IOCTL_GET_DEVICE_TYPE: case CTS_TOOL_IOCTL_GET_FW_VERSION: case CTS_TOOL_IOCTL_GET_RESOLUTION: case CTS_TOOL_IOCTL_GET_ROW_COL: case CTS_TOOL_IOCTL_TEST: case CTS_TOOL_IOCTL_RDWR_REG: case CTS_TOOL_IOCTL_UPGRADE_FW: ioctl(fd, code, &arg);//注意这里是核心代码 LOGE("arg:0x%x", arg); break; default: LOGE("CTLCODE was not right"); } close(fd); LOGE("ioctl successfully"); return arg; } }//extern "C"

4.到这里基本的jni层相关代码都配置OK了,接下来编译

        a.打开命令窗口进入jni目录,输入ndk-build,

        b.如下图,可以看到相关平台的so文件都已经编译成功

        c.编译好了之后so文件在jni同级目录的libs目录下  (libtouch.so以生成)

        d.到这里就为应用层app调用jni so库文件做好了准备

 应用层app demo实现  使用android studio创建默认工程

 1.创建好的工程目录如下(怎么创建android demo工程这里就不赘述了,只需要创建一个空壳应用就好):

 2.将ndk编译好的libs目录拷贝到touch工程中的main目录下,如上图

 引用libtouch.so库文件

 1.在app工程目录下的build.gradle文件中添加 ndk和sourceSets.main这两个代码段

android { compileSdkVersion 30 buildToolsVersion "30.0.3" defaultConfig { applicationId "com.chipone.touch" minSdkVersion 15 targetSdkVersion 30 versionCode 1 versionName "1.0" testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" ndk { //1.添加ndk模块名 moduleName "touch" } } sourceSets.main{ //2.添加jni lib目录 jni.srcDirs=[] jniLibs.srcDir "src/main/libs" } }

 3.然后在MainActivity中载入touch模块

 4.然后在onCreate中调用

 5.MainActivity完整代码如下(到这里,引用和调用都以完成):

package com.chipone.touch; import android.os.Bundle; import com.google.android.material.bottomnavigation.BottomNavigationView; import androidx.appcompat.app.AppCompatActivity; import androidx.annotation.NonNull; import android.util.Log; import android.view.MenuItem; import android.view.View; import android.widget.Button; import android.widget.TextView; import java.io.File; public class MainActivity extends AppCompatActivity { private TextView mTextMessage; private Button mButton; static { System.loadLibrary("touch"); } public native long ioctl(int a, long b); private BottomNavigationView.OnNavigationItemSelectedListener mOnNavigationItemSelectedListener = new BottomNavigationView.OnNavigationItemSelectedListener() { @Override public boolean onNavigationItemSelected(@NonNull MenuItem item) { switch (item.getItemId()) { case R.id.navigation_home: mTextMessage.setText(R.string.title_home); return true; case R.id.navigation_dashboard: mTextMessage.setText(R.string.title_dashboard); return true; case R.id.navigation_notifications: mTextMessage.setText(R.string.title_notifications); return true; } return false; } }; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); BottomNavigationView navView = findViewById(R.id.nav_view); mTextMessage = findViewById(R.id.message); navView.setOnNavigationItemSelectedListener(mOnNavigationItemSelectedListener); mButton = findViewById(R.id.button); mButton.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { long arg = 0; Log.e("TOUCH-APP", "0x" + Long.toHexString(ioctl(0x80084300, arg))); Log.e("TOUCH-APP", "0x" + Long.toHexString(ioctl(0x80084301, arg))); Log.e("TOUCH-APP", "0x" + Long.toHexString(ioctl(0x80084302, arg))); Log.e("TOUCH-APP", "0x" + Long.toHexString(ioctl(0x80084303, arg))); Log.e("TOUCH-APP", "0x" + Long.toHexString(ioctl(0x80084304, arg))); Log.e("TOUCH-APP", "0x" + Long.toHexString(ioctl(0xc0084310, arg))); Log.e("TOUCH-APP", "0x" + Long.toHexString(ioctl(0xc0084320, arg))); Log.e("TOUCH-APP", "0x" + Long.toHexString(ioctl(0xc0084321, arg))); } }); } }  编译运行安装touch应用

  1.安装后的应用

  2.点击按钮运行,同时抓取logcat log(如下图),这里可以看到app层和jni层的log都有打印出来,但是有没有被底层识别呢,接下来我们再看底层设备驱动的简单实现

130|root@msm8994:/ # logcat | grep TOUCH E/TOUCH-JNI(14217): code:0x80084300 arg:0x0 E/TOUCH-JNI(14217): arg:0x10310 E/TOUCH-JNI(14217): ioctl successfully E/TOUCH-APP(14217): 0x10310 E/TOUCH-JNI(14217): code:0x80084301 arg:0x0 E/TOUCH-JNI(14217): arg:0x991110 E/TOUCH-JNI(14217): ioctl successfully E/TOUCH-APP(14217): 0x991110 E/TOUCH-JNI(14217): code:0x80084302 arg:0x0 E/TOUCH-JNI(14217): arg:0x212 E/TOUCH-JNI(14217): ioctl successfully E/TOUCH-APP(14217): 0x212 E/TOUCH-JNI(14217): code:0x80084303 arg:0x0 E/TOUCH-JNI(14217): arg:0x61702cf E/TOUCH-JNI(14217): ioctl successfully E/TOUCH-APP(14217): 0x61702cf E/TOUCH-JNI(14217): code:0x80084304 arg:0x0 E/TOUCH-JNI(14217): arg:0x120020 E/TOUCH-JNI(14217): ioctl successfully E/TOUCH-APP(14217): 0x120020 E/TOUCH-JNI(14217): code:0xc0084310 arg:0x0 E/TOUCH-JNI(14217): arg:0x0 E/TOUCH-JNI(14217): ioctl successfully E/TOUCH-APP(14217): 0x0 E/TOUCH-JNI(14217): code:0xc0084320 arg:0x0 E/TOUCH-JNI(14217): arg:0x0 E/TOUCH-JNI(14217): ioctl successfully E/TOUCH-APP(14217): 0x0 E/TOUCH-JNI(14217): code:0xc0084321 arg:0x0 E/TOUCH-JNI(14217): arg:0x0 E/TOUCH-JNI(14217): ioctl successfully E/TOUCH-APP(14217): 0x0

       

设备驱动程序ioctl实现关键代码

1.代码如下:

static long tool_ioctl(struct file *file, unsigned int cmd, unsigned long arg) { struct ts_data *data; struct device *dev; pr_info("ioctl, cmd=0x%08x, arg=0x%08lx", cmd, arg); data = file->private_data; if (data == NULL) { pr_err("IOCTL with private data = NULL"); return -EFAULT; } switch (cmd) { case TOOL_IOCTL_GET_DRIVER_VERSION: return put_user(CTS_DRIVER_VERSION_CODE, (unsigned int __user *)arg); case TOOL_IOCTL_GET_DEVICE_TYPE: return put_user(dev->hwdata->hwid, (unsigned int __user *)arg); case TOOL_IOCTL_GET_FW_VERSION: return put_user(dev->fwdata.version, (unsigned short __user *)arg); case TOOL_IOCTL_GET_RESOLUTION: return put_user((dev->fwdata.res_y fwdata.res_x, (unsigned int __user *)arg); case TOOL_IOCTL_GET_ROW_COL: return put_user((dev->fwdata.cols fwdata.rows, (unsigned int __user *)arg); default: pr_err("Unsupported ioctl cmd=0x%08x, arg=0x%08lx", cmd, arg); break; } return -ENOTSUPP; } static int tool_open(struct inode *inode, struct file *file) { file->private_data = PDE_DATA(inode); return 0; } static struct file_operations tool_fops = { .owner = THIS_MODULE, .llseek = no_llseek, .open = tool_open, .unlocked_ioctl = tool_ioctl, };

 2.这时候抓取kernel log如下(cat dev/kmsg):

  这里可以看到应用层传下来的cmd,底层设备驱动已经接收到了,这就说明从app-jni-kernel的ioctl功能已经实现

Tool ioctl, cmd=0x80084300, arg=0x7fd4dc4508 Tool ioctl, cmd=0x80084301, arg=0x7fd4dc4508 Tool ioctl, cmd=0x80084302, arg=0x7fd4dc4508 Tool ioctl, cmd=0x80084303, arg=0x7fd4dc4508 Tool ioctl, cmd=0x80084304, arg=0x7fd4dc4508

======== 完 =========

到这里,从应用层到JNI层再到kernel层,功能实现OK,这就是上层应用来控制底层设备的大概逻辑。

以上,如有错误欢迎大家指出,共同进步,谢谢!



【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3