框图
这里主要关注➕右下角部分 添加新模块即可。本章节详细解读了android新模块从驱动层、HAL层、framework层、APP层的流程。上面的图添加新模块部分可能会看不清,这里单独截取该部分,如下所示:
这样就清晰多了。本章节主要描述了android系统从上到下添加一个模块的流程,因为仅针对流程,所以关于其使用的原理本部分不会涉及,但在binder以及其他章节中会有所涉及。
1 添加驱动程序(源码见wd_hello_driver),添加流程如下:
1.1 添加代码
对应代码位置-->kernel/drivers/wd_hello,驱动层代码如下:
1 wd_hello.h
#ifndef _WD_HELLO_ANDROID_H_
#define _WD_HELLO_ANDROID_H_
#include <linux/cdev.h>
#include <linux/semaphore.h>
#define WD_HELLO_DEVICE_NODE_NAME "wd_hello"
#define WD_HELLO_DEVICE_FILE_NAME "wd_hello"
#define WD_HELLO_DEVICE_PROC_NAME "wd_hello"
#define WD_HELLO_DEVICE_CLASS_NAME "wd_hello"
struct wd_hello_android_dev {
int val;
struct semaphore sem;
struct cdev dev;
};
#endif
2 wd_hello.c
#include <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 <asm/uaccess.h>
#include <linux/slab.h>
#include "wd_hello.h"
/*主设备和从设备号变量*/
static int wd_hello_major = 0;
static int wd_hello_minor = 0;
/*设备类别和设备变量*/
static struct class* wd_hello_class = NULL;
static struct wd_hello_android_dev* wd_hello_dev = NULL;
/*传统的设备文件操作方法*/
static int wd_hello_open(struct inode* inode, struct file* filp);
static int wd_hello_release(struct inode* inode, struct file* filp);
static ssize_t wd_hello_read(struct file* filp, char __user *buf, size_t count, loff_t* f_pos);
static ssize_t wd_hello_write(struct file* filp, const char __user *buf, size_t count, loff_t* f_pos);
/*设备文件操作方法表*/
static struct file_operations wd_hello_fops = {
.owner = THIS_MODULE,
.open = wd_hello_open,
.release = wd_hello_release,
.read = wd_hello_read,
.write = wd_hello_write,
};
#if 0
/*访问设置属性方法*/
static ssize_t wd_hello_val_show(struct device* dev, struct device_attribute* attr, char* buf);
static ssize_t wd_hello_val_store(struct device* dev, struct device_attribute* attr, const char* buf, size_t count);
/*定义设备属性*/
static DEVICE_ATTR(val, S_IRUGO | S_IWUSR, wd_hello_val_show, wd_hello_val_store);
#endif
///
/*打开设备方法*/
static int wd_hello_open(struct inode* inode, struct file* filp) {
struct wd_hello_android_dev* dev;
/*将自定义设备结构体保存在文件指针的私有数据域中,以便访问设备时拿来用*/
dev = container_of(inode->i_cdev, struct wd_hello_android_dev, dev);
filp->private_data = dev;
return 0;
}
/*设备文件释放时调用,空实现*/
static int wd_hello_release(struct inode* inode, struct file* filp) {
return 0;
}
/*读取设备的寄存器val的值*/
static ssize_t wd_hello_read(struct file* filp, char __user *buf, size_t count, loff_t* f_pos) {
ssize_t err = 0;
struct wd_hello_android_dev* dev = filp->private_data;
/*同步访问*/
if(down_interruptible(&(dev->sem))) {
return -ERESTARTSYS;
}
if(count < sizeof(dev->val)) {
goto out;
}
/*将寄存器val的值拷贝到用户提供的缓冲区*/
if(copy_to_user(buf, &(dev->val), sizeof(dev->val))) {
err = -EFAULT;
goto out;
}
err = sizeof(dev->val);
out:
up(&(dev->sem));
return err;
}
/*写设备的寄存器值val*/
static ssize_t wd_hello_write(struct file* filp, const char __user *buf, size_t count, loff_t* f_pos) {
struct wd_hello_android_dev* dev = filp->private_data;
ssize_t err = 0;
/*同步访问*/
if(down_interruptible(&(dev->sem))) {
return -ERESTARTSYS;
}
if(count != sizeof(dev->val)) {
goto out;
}
/*将用户提供的缓冲区的值写到设备寄存器去*/
if(copy_from_user(&(dev->val), buf, count)) {
err = -EFAULT;
goto out;
}
err = sizeof(dev->val);
out:
up(&(dev->sem));
return err;
}
#if 0
///
/*读取寄存器val的值到缓冲区buf中,内部使用*/
static ssize_t __wd_hello_get_val(struct wd_hello_android_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);
}
/*把缓冲区buf的值写到设备寄存器val中去,内部使用*/
static ssize_t __wd_hello_set_val(struct wd_hello_android_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;
}
/*读取设备属性val*/
static ssize_t wd_hello_val_show(struct device* dev, struct device_attribute* attr, char* buf) {
struct wd_hello_android_dev* hdev = (struct wd_hello_android_dev*)dev_get_drvdata(dev);
return __wd_hello_get_val(hdev, buf);
}
/*写设备属性val*/
static ssize_t wd_hello_val_store(struct device* dev, struct device_attribute* attr, const char* buf, size_t count) {
struct wd_hello_android_dev* hdev = (struct wd_hello_android_dev*)dev_get_drvdata(dev);
return __wd_hello_set_val(hdev, buf, count);
}
///
/*读取设备寄存器val的值,保存在page缓冲区中*/
static ssize_t wd_hello_proc_read(char* page, char** start, off_t off, int count, int* eof, void* data) {
if(off > 0) {
*eof = 1;
return 0;
}
return __wd_hello_get_val(wd_hello_dev, page);
}
/*把缓冲区的值buff保存到设备寄存器val中去*/
static ssize_t wd_hello_proc_write(struct file* filp, const char __user *buff, unsigned long len, void* data) {
int err = 0;
char* page = NULL;
if(len > PAGE_SIZE) {
printk(KERN_ALERT"The buff is too large: %lu.\n", len);
return -EFAULT;
}
page = (char*)__get_free_page(GFP_KERNEL);
if(!page) {
printk(KERN_ALERT"Failed to alloc page.\n");
return -ENOMEM;
}
/*先把用户提供的缓冲区值拷贝到内核缓冲区中去*/
if(copy_from_user(page, buff, len)) {
printk(KERN_ALERT"Failed to copy buff from user.\n");
err = -EFAULT;
goto out;
}
err = __wd_hello_set_val(wd_hello_dev, page, len);
out:
free_page((unsigned long)page);
return err;
}
/*创建/proc/hello文件*/
sta