📌一、分析
什么是misc设备
[[misc设备]]
📌二、实现
1. 添加驱动代码
只是简单的验证功能,没有处理越界及加锁
`kernel/drivers/hello/hello.c`
#include <linux/fs.h>
#include <linux/miscdevice.h>
#include <linux/module.h>
#include <linux/uaccess.h>
#define DEVICE_NAME "hello"
static char my_data[100] = "Hello, this is my_misc_device!\n";
static ssize_t my_read(struct file *file, char __user *buf, size_t count,
loff_t *ppos)
{
if (copy_to_user(buf, my_data, count)) {
return -EFAULT;
}
return count;
}
static ssize_t my_write(struct file *file, const char __user *buf, size_t count,
loff_t *ppos)
{
if (copy_from_user(my_data, buf, count)) {
return -EFAULT;
}
return count;
}
static const struct file_operations my_fops = {
.owner = THIS_MODULE,
.read = my_read,
.write = my_write,
};
static struct miscdevice my_misc_device = {
.minor = MISC_DYNAMIC_MINOR,
.name = DEVICE_NAME,
.fops = &my_fops,
};
static int __init my_init(void)
{
int ret = misc_register(&my_misc_device);
if (ret) {
pr_err("Failed to register misc device\n");
return ret;
}
return 0;
}
static void __exit my_exit(void)
{
misc_deregister(&my_misc_device);
}
module_init(my_init);
module_exit(my_exit);
MODULE_DESCRIPTION("hello misc device");
MODULE_LICENSE("GPL");
MODULE_AUTHOR("lucius");
2. 修改Kconfig和Makfile
3. 编译后添加模块
将生成的hello.ko,推送到开发板后insmod,可以查看到设备节点`/dev/hello`
📌三、测试
1. NDK
test-misc_hello.c
#include <stdio.h>
#include <sys/ioctl.h>
#include <fcntl.h>
#include <sys/types.h>
#include <unistd.h>
#include <malloc.h>
#include <string.h>
int main(int argc, char *argv[])
{
char *tTempBuff = (char *)malloc(100);
int tTempFd = -1;
tTempBuff[99] = '\0';
if (argc < 2)
{
return 0;
}
tTempFd = open("/dev/hello", O_RDWR);
if (tTempFd < 0)
{
printf("open /dev/mycdev err\n");
return -1;
}
if (!strcmp("write", argv[1]))
{
write(tTempFd, argv[2], strlen(argv[2]));
printf("write %s to /dev/hello buf\n\n", argv[2]);
}
else if (!strcmp("read", argv[1]))
{
read(tTempFd, tTempBuff, 99);
printf("read data form /dev/hello : %s\n\n", tTempBuff);
}
else
{
printf("please use write or read cmd\n");
}
close(tTempFd);
return 0;
}
编译后推送到开发板验证./test-misc_hello read
2. APP
2.1. jni动态库
test-misc_hello-jni.c
#include <jni.h>
#include <fcntl.h>
#include <unistd.h>
#include <string.h>
#include <stdio.h>
static int fd = -1;
JNIEXPORT jint JNICALL Java_com_example_helloservice_HelloNative_openDevice(JNIEnv *env, jclass cls)
{
if (fd >= 0)
return fd;
fd = open("/dev/hello", O_RDWR);
if (fd < 0)
return -1;
return fd;
}
JNIEXPORT jint JNICALL Java_com_example_helloservice_HelloNative_writeDevice(JNIEnv *env, jclass cls, jbyteArray arr)
{
if (fd < 0)
return -1;
jsize len = (*env)->GetArrayLength(env, arr);
jbyte *buf = (*env)->GetByteArrayElements(env, arr, NULL);
int w = write(fd, buf, len);
(*env)->ReleaseByteArrayElements(env, arr, buf, 0);
return w;
}
JNIEXPORT jbyteArray JNICALL Java_com_example_helloservice_HelloNative_readDevice(JNIEnv *env, jclass cls, jint maxlen)
{
if (fd < 0)
return NULL;
char tmp[256];
int r = read(fd, tmp, maxlen > 255 ? 255 : maxlen);
if (r <= 0)
return NULL;
jbyteArray out = (*env)->NewByteArray(env, r);
(*env)->SetByteArrayRegion(env, out, 0, r, (jbyte *)tmp);
return out;
}
JNIEXPORT void JNICALL Java_com_example_helloservice_HelloNative_closeDevice(JNIEnv *env, jclass cls)
{
if (fd >= 0)
{
close(fd);
fd = -1;
}
}
2.2. Android studio工程
HelloNative.java
package com.example.app;
public class HelloNative {
/* 加载JNI库 */
static {
System.loadLibrary("test-misc_hello_jni");
}
/* 声明本地方法 */
public static native int openDevice();
public static native int writeDevice(byte[] data);
public static native byte[] readDevice(int maxlen);
public static native void closeDevice();
}
MainActivity.java
package com.example.app;
import static com.example.app.HelloNative.closeDevice;
import static com.example.app.HelloNative.readDevice;
import static com.example.app.HelloNative.writeDevice;
import androidx.appcompat.app.AppCompatActivity;
import android.os.Bundle;
import android.widget.TextView;
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
TextView textView = findViewById(R.id.textViewHello);
int fd = HelloNative.openDevice();
if (fd >= 0) {
textView.setText("Hello misc");
} else {
textView.setText("Open /dev/hello failed");
}
String msg = "Hello Kernel!";
byte[] data = msg.getBytes();
int written = writeDevice(data);
System.out.println("写入字节数: " + written);
byte[] readData = readDevice(128);
if (readData != null) {
System.out.println("读取到数据: " + new String(readData));
} else {
System.out.println("读取失败或无数据");
}
closeDevice();
System.out.println("设备已关闭");
}
}
📁四、附言
参考文章
rk3566-Android11 从驱动到 app 第一章添加驱动程序_rk3566 安卓11-CSDN博客
代码
https://git.luciusxu.cn/25Oct30-Test-MISC_Hello/25Oct30-Test-MISC_Hello.git