当前位置:网站首页>1. Hal driven development
1. Hal driven development
2022-07-03 11:11:00 【MrPeng1991】
1.hal Drive development
2. hal Hardware abstraction layer
3 Android Hardware access services JNI Realization
1 coded
Directory structure
~/Android/kernel/goldfish
drivers
freg
freg.h # Source code file
freg.c # Source code file
Kconfig # Compile options configuration file
Makefile # Compile script file
// kernel\goldfish\drivers\freg\freg.h
#ifndef _FAKE_REG_H_
#define _FAKE_REG_H_
#include <linux/cdev.h>
#include <linux/semaphore.h>
// Four string constants are defined , Respectively used to describe virtual hardware devices freg Name in the device file system
#define FREG_DEVICE_NODE_NAME "freg"
#define FREG_DEVICE_FILE_NAME "freg"
#define FREG_DEVICE_PROC_NAME "freg"
#define FREG_DEVICE_CLASS_NAME "freg"
// Describe the virtual hardware device freg
struct fake_reg_dev
{
// Describe a virtual register
int val;
// A semaphore , Used to synchronously access virtual registers val
struct semaphore sem;
// A standard Linux Character device structure variables , Used to mark the virtual hardware device freg The type of is character device
struct cdev dev;
};
#endif
//kernel\goldfinsh\drivers\freg\freg.c
nclude <linux/init.h>
#include <linux/module.h>
#include <linux/types.h>
#include <linux/fs.h>
#include <linux/proc_fs.h>
#include <linux/device.h>
#include <linux/slab.h>
#include <linux/seq_file.h>
#include <asm/uaccess.h>
#include "freg.h"
static int freg_major = 0;// The main equipment,
static int freg_minor = 0;// From the device number
static struct class* freg_class = NULL;
static struct fake_reg_dev* freg_dev = NULL;
// Table of traditional file operation methods
static int freg_open(struct inode* inode, struct file* filp);
static int freg_release(struct inode* inode, struct file* filp);
static ssize_t freg_read(struct file* filp, char __user *buf, size_t count, loff_t* f_pos);
static ssize_t freg_write(struct file* filp, const char __user *buf, size_t count, loff_t* f_pos);
static struct file_operations freg_fops = {
.owner = THIS_MODULE,
.open = freg_open,
.release = freg_release,
.read = freg_read,
.write = freg_write,
};
#define SEQ_printf(m, x...) \ do { \ if (m) \ seq_printf(m, x); \ else \ pr_err(x); \ } while (0)
// Read the device register val Value
static int freg_proc_show(struct seq_file *m, void *v)
{
SEQ_printf(m, "%d\n", freg_dev->val);
return 0;
}
// Open the device register
static int freg_proc_open(struct inode *inode, struct file *file)
{
return single_open(file, freg_proc_show, inode->i_private);
}
// Put the cache buf Write the value of to the device register val in , For internal use , freg_val_store freg_proc_write call
static ssize_t __freg_set_val(struct fake_reg_dev* dev, const char* buf, size_t count){
int val = 0;
val = simple_strtol(buf, NULL, 10);
if(down_interruptible(&(dev->sem))){
return -ERESTARTSYS;
}
dev->val = val;
up(&(dev->sem));
return count;
}
/* static ssize_t freg_proc_read(char* page, char** start, off_t off, int count, int* eof, void* data){ if(off >0 ){ *eof = 1; return 0; } return __freg_get_val(freg_dev, page); }*/
// Put the value of the buffer buff Save to device register val in
static ssize_t freg_proc_write(struct file *filp, const char *ubuf, size_t cnt, loff_t *data){
int err = 0;
char* page = NULL;
if(cnt > PAGE_SIZE){
printk(KERN_ALERT"The buff is too large: %lu.\n", cnt);
return -EFAULT;
}
page = (char*) __get_free_page(GFP_KERNEL);
if(!page){
printk(KERN_ALERT"Failed to alloc page.\n");
return -ENOMEM;
}
// First copy the value of the buffer provided by the user into the kernel buffer
if(copy_from_user(page, ubuf, cnt)){
printk(KERN_ALERT"Failed to copy buff from user.\n");
err = -EFAULT;
goto out;
}
err = __freg_set_val(freg_dev, page, cnt);
out:
free_page((unsigned long)page);
return err;
}
static const struct file_operations freg_proc_fops = {
.open = freg_proc_open,
.write = freg_proc_write,
.read = seq_read,
.llseek = seq_lseek,
.release = single_release,
};
//devfs File system device attribute operation method
static ssize_t freg_val_show(struct device* dev, struct device_attribute* attr, char* buf);
static ssize_t freg_val_store(struct device* dev, struct device_attribute* attr, const char* buf, size_t count);
//devfs File system device properties
static DEVICE_ATTR(val, S_IRUGO | S_IWUSR, freg_val_show, freg_val_store);
// How to open the device
static int freg_open(struct inode * inode, struct file * filp){
struct fake_reg_dev * dev;
// Save the custom device structure in the private data field of the file pointer , So that it can be used directly when accessing the device
dev = container_of(inode->i_cdev, struct fake_reg_dev, dev);
filp->private_data = dev;
return 0;
}
// Call... When the device file is released , Empty implementation
static int freg_release(struct inode* inode, struct file* filp){
return 0;
}
// Read the device register val Value
static ssize_t freg_read(struct file* filp, char __user *buf, size_t count, loff_t* f_pos){
ssize_t err = 0;
struct fake_reg_dev* dev = filp->private_data;
// Synchronous access
if(down_interruptible(&(dev->sem))){
return -ERESTARTSYS;
}
if(count < sizeof(dev->val)){
goto out;
}
// Register val The value of is copied into the buffer provided by the user
if(copy_to_user(buf, &(dev->val), sizeof(dev->val))){
err = -EFAULT;
goto out;
}
err = sizeof(dev->val);
out:
// Undo synchronization
up(&(dev->sem));
return err;
}
// Write device register val Value
static ssize_t freg_write(struct file * filp, const char __user * buf, size_t count, loff_t * f_pos){
struct fake_reg_dev* dev = filp->private_data;
ssize_t err = 0;
if(down_interruptible(&(dev->sem))){
return -ERESTARTSYS;
}
if(count != sizeof(dev->val)){
goto out;
}
// Register val The value of is read into the buffer buf in , For internal use ,freg_val_show call
if(copy_from_user(&(dev->val), buf, count)){
err = -EFAULT;
goto out;
}
err = sizeof(dev->val);
out:
up(&(dev->sem));
return err;
}
static ssize_t __freg_get_val(struct fake_reg_dev* dev, char* buf){
int val = 0;
if(down_interruptible(&dev->sem)){
return -ERESTARTSYS;
}
val = dev->val;
up(&(dev->sem));
return snprintf(buf, PAGE_SIZE, "%d\n", val);
}
// All device attributes val value
static ssize_t freg_val_show(struct device* dev, struct device_attribute* attr, char* buf){
struct fake_reg_dev* hdev = (struct fake_reg_dev*)dev_get_drvdata(dev);
return __freg_get_val(hdev, buf);
}
// Write device properties val
static ssize_t freg_val_store(struct device*dev, struct device_attribute* attr, const char* buf, size_t count){
struct fake_reg_dev* hdev = (struct fake_reg_dev*)dev_get_drvdata(dev);
return __freg_set_val(hdev, buf, count);
}
// establish /proc/freg file
static void freg_create_proc(void){
proc_create(FREG_DEVICE_PROC_NAME, 0644, 0, &freg_proc_fops);
}
static void freg_remove_proc(void){
remove_proc_entry(FREG_DEVICE_PROC_NAME, NULL);
}
// Initialization equipment
static int __freg_setup_dev(struct fake_reg_dev* dev){
int err;
dev_t devno = MKDEV(freg_major, freg_minor);
memset(dev, 0, sizeof(struct fake_reg_dev));
// Initialize character device
cdev_init(&(dev->dev), &freg_fops);
dev->dev.owner = THIS_MODULE;
dev->dev.ops = &freg_fops;
// Register character device
err = cdev_add(&(dev->dev), devno, 1);
if(err){
return err;
}
// Initialize semaphores
//init_MUTEX(&(dev->sem));
sema_init(&(dev->sem), 1);
// Initialization register val value
dev->val = 0;
return 0;
}
// Module loading method
static int __init freg_init(void){
int err = -1;
dev_t dev = 0;
struct device* temp = NULL;
printk(KERN_ALERT"Initializing freg device.\n");
// Dynamically assign master device number and slave device number
err = alloc_chrdev_region(&dev, 0, 1, FREG_DEVICE_NODE_NAME);
if(err < 0){
printk(KERN_ALERT"Failed to alloc char dev region.\n");
goto fail;
}
freg_major = MAJOR(dev);
freg_minor = MINOR(dev);
// Distribute freg Equipment structure
freg_dev = kmalloc(sizeof(struct fake_reg_dev), GFP_KERNEL);
if(!freg_dev){
err = -ENOMEM;
printk(KERN_ALERT"Failed to alloc freg device.\n");
goto unregister;
}
// Initialization equipment
err = __freg_setup_dev(freg_dev);
if(err){
printk(KERN_ALERT"Failed to setup freg device: %d.\n", err);
goto cleanup;
}
// stay sys/class Create a device category directory under the directory freg
freg_class = class_create(THIS_MODULE, FREG_DEVICE_CLASS_NAME);
if(IS_ERR(freg_class)){
err = PTR_ERR(freg_class);
printk(KERN_ALERT"Failed to create freg device class.\n");
goto destroy_cdev;
}
//dev Contents and /syst/class/freg Create device files under the directory freg
temp = device_create(freg_class, NULL, dev, NULL, "%s", FREG_DEVICE_FILE_NAME);
if(IS_ERR(temp)){
err = PTR_ERR(temp);
printk(KERN_ALERT"Failed to create freg device.\n");
goto destroy_class;
}
// stay /sys/class/freg/freg Create a property file under the directory val
err = device_create_file(temp, &dev_attr_val);
if(err < 0){
printk(KERN_ALERT"Failed to create attribute val of freg device.\n");
goto destroy_device;
}
dev_set_drvdata(temp, freg_dev);
freg_create_proc();
printk(KERN_ALERT"Succedded to initialize freg device.\n");
return 0;
destroy_device:
device_destroy(freg_class, dev);
destroy_class:
class_destroy(freg_class);
destroy_cdev:
cdev_del(&(freg_dev->dev));
cleanup:
kfree(freg_dev);
unregister:
unregister_chrdev_region(MKDEV(freg_major, freg_minor), 1);
fail:
return err;
}
// Module uninstall
static void __exit freg_exit(void){
dev_t devno = MKDEV(freg_major, freg_minor);
printk(KERN_ALERT"Destory freg device.\n");
// Delete /proc/freg file
freg_remove_proc();
// Log off device category and device
if(freg_class){
device_destroy(freg_class, MKDEV(freg_major, freg_minor));
class_destroy(freg_class);
}
// Delete character device and free device memory
if(freg_dev){
cdev_del(&(freg_dev->dev));
kfree(freg_dev);
}
// Release device number resource
unregister_chrdev_region(devno, 1);
}
MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("Fake Register Driver");
module_init(freg_init);
module_exit(freg_exit);
2 compile
# kernel\goldfish\drivers\freg\Kconfig
config FREG
tristate "Fake Register Driver"
default y
help
This is the freg driver for android system
# kernel\goldfish\drivers\freg\Makefile
obj -y += freg/
driver Add under the directory
obj-y += freg/
compile :
build/build.sh
3 verification
adopt proc File system and devfs File system to verify whether the function is correct
# Use Get the kernel image file zImage To start up Android Simulator
emulator -kernel kernel/goldfish/arch/arm/boot/zImage &
# # use adb Tool connection
adb shell
# Get into /dev Under the table of contents
cd dev
# see A device file freg
# There is , Description: successfully registered to the device file system
ls freg
# Enter into /proc
cd proc
# Read the file freg The content of
cat freg
# To file freg Write a new content in
echo '5' > freg
# Will file freg Read out the contents of
cat freg
# Have the same value , explain proc File system interface succeeded
# Enter into /sys/class/freg/freg
cd sys/class/freg/freg
# Read val The content of the document
cat val
# To file val Write a new content in
echo '0' > freg
# Will file val Read out the contents in
cat freg
# Have the same value , explain devfs File system interface succeeded
4 Development c Executable program verification android Hardware drivers
Android In the source code environment It can be used c/c++ Develop executable programs , You can develop dynamic link libraries , namely so file , In the device /system/bin /system/lib Directory .
Executable program source files are generally saved in extern Directory .
~/Android
exiternal
freg
freg.c # Source file
Android.mk # Compile script file
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#define FREG_DEVICE_NAME "/dev/freg"
int main(int argc, char** argv)
{
int fd = -1;
int val = 0;
// Open the device file in read-write mode /dev/freg
fd = open(FREG_DEVICE_NAME, O_RDWR);
if(fd == -1)
{
printf("Failed to open device %s.\n", FREG_DEVICE_NAME);
return -1;
}
printf("Read original value:\n");
// Read its contents , That is, read virtual hardware devices freg The register of val The content of
read(fd, &val, sizeof(val));
// Print out
printf("%d.\n\n", val);
val = 5;
printf("Write value %d to %s.\n\n", val, FREG_DEVICE_NAME);
// Put an integer 5 Write to virtual hardware device freg The register of val in
write(fd, &val, sizeof(val));
printf("Read the value again:\n");
// Read its contents , That is, read virtual hardware devices freg The register of val The content of
read(fd, &val, sizeof(val));
// Print
printf("%d.\n\n", val);
close(fd);
return 0;
}
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#define FREG_DEVICE_NAME "/dev/freg"
int main(int argc, char** argv)
{
int fd = -1;
int val = 0;
// Open the device file in read-write mode /dev/freg
fd = open(FREG_DEVICE_NAME, O_RDWR);
if(fd == -1)
{
printf("Failed to open device %s.\n", FREG_DEVICE_NAME);
return -1;
}
printf("Read original value:\n");
// Read its contents , That is, read virtual hardware devices freg The register of val The content of
read(fd, &val, sizeof(val));
// Print out
printf("%d.\n\n", val);
val = 5;
printf("Write value %d to %s.\n\n", val, FREG_DEVICE_NAME);
// Put an integer 5 Write to virtual hardware device freg The register of val in
write(fd, &val, sizeof(val));
printf("Read the value again:\n");
// Read its contents , That is, read virtual hardware devices freg The register of val The content of
read(fd, &val, sizeof(val));
// Print
printf("%d.\n\n", val);
close(fd);
return 0;
}
After successful compilation , You can go to out/target/product/gerneric/system/bin I see a freg file ;
边栏推荐
- 封装一个koa分布式锁中间件来解决幂等或重复请求的问题
- 公司里只有一个测试是什么体验?听听他们怎么说吧
- Commonly used discrete random distribution
- MAUI Developer Day in GCR
- Use ml.net+onnx pre training model to liven the classic "Huaqiang buys melons" in station B
- What is the salary level of 17k? Let's take a look at the whole interview process of post-95 Test Engineers
- I have been doing software testing for three years, and my salary is less than 20K. Today, I put forward my resignation
- 面试题总结(2) IO模型,集合,NIO 原理,缓存穿透,击穿雪崩
- 表空间创建管理及控制文件管理
- 有赞CTO崔玉松:有赞Jarvis核心目标是使产品变得更加聪明和可靠
猜你喜欢
硬 货 | 一改测试步骤代码就全写?为什么不试试用 Yaml实现数据驱动?
What is the salary level of 17k? Let's take a look at the whole interview process of post-95 Test Engineers
测试理论概述
【Proteus仿真】74HC154 四线转12线译码器组成的16路流水灯
MAUI Developer Day in GCR
QT: QSS custom qtableview instance
Clion debug
可以写进简历的软件测试电商项目,不进来get一下?
独家分析 | 关于简历和面试的真 相
12. Nacos server service registration of source code analysis of Nacos service registration
随机推荐
【Proteus仿真】74HC154 四线转12线译码器组成的16路流水灯
英特尔13代酷睿旗舰曝光,单核5.5GHz
我对测试工作的一些认识(资深测试人员总结)
测试理论概述
QT: QSS custom qtoolbutton instance
Use ml.net+onnx pre training model to liven the classic "Huaqiang buys melons" in station B
反正切熵(Arctangent entropy):2022.7月最新SCI论文
游戏测试相关 测试一个英雄的技能(春招被问比较多的一道题)
月薪过万的测试员,是一种什么样的生活状态?
QT: QSS custom qtreeview instance
Qt:qss custom qlistview instance
redis那些事儿
Hal -- writing hardware drivers
QT: QSS custom qtabwidget and qtabbar instances
QT: QSS custom qtableview instance
Crawl with requests
Game test related tests a hero's skills (spring moves are asked more questions)
做软件测试三年,薪资不到20K,今天,我提出了辞职…
Typescript learning summary
Have you learned the new technology to improve sales in 2021?