第一章 介绍与环境说明
环境:适用于所有的linux驱动
第二章 proc文件系统介绍
/proc文件系统包含了一些目录(用作组织信息的方式)和虚拟文件。虚拟文件可以向用户呈现内核中的一些信息,也可以用作一种从用户空间向内核发送信息的手段。
/proc 文件系统是一个虚拟文件系统,通过它可以使用一种新的方法在 Linux内核空间和用户间之间进行通信。在 /proc 文件系统中,我们可以将对虚拟文件的读写作为与内核中实体进行通信的一种手段,但是与普通文件不同的是,这些虚拟文件的内容都是动态创建的。具体内容本文不做介绍。
在proc下创建的一些节点的作用是,比如查看固件信息、电源信息、cpuinfo等内核的信息,自己创建文件的原则也是如此。
第三章 创建proc路径下文件节点的例程
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/interrupt.h>
#include <linux/irq.h>
#include <linux/gpio.h>
#include <linux/proc_fs.h>
#include <linux/input/mt.h>
#include <linux/of_gpio.h>
#include <linux/of_irq.h>
#include <linux/sysfs.h>
#include <linux/device.h>
#include <linux/uaccess.h>
//写一份代码实现拉对应gpio的管脚
//-----------------------dts----------------------
/*
mynode :test_node {
compatible = "test,test_node";
test-gpio = <&pio 45 0>;//45表示gpio的编号
};
*/
//-----------------------drv----------------------
const struct of_device_id proc_test_of_match[] = {
{ .compatible = "test,test_node", },
{}
};
//------------------------创建设备节点:/sys/class/test_node-------------
static int test_gpio;
static int status=-1;
void gpio_status_exchange(int cmd)
{
gpio_set_value(test_gpio,cmd);
return;
}
static long test_proc_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
{
uint32_t res = 0;
char order[10] = { 0 };
res = copy_from_user(order, (uint8_t *) arg, 1);
if (res < 0) {
printk("%s:Failed to copy data from user space\n",__func__);
return res;
}
status = order[0];
gpio_status_exchange(status);
printk("%s status = %d\n",__func__,status);
return res;
}
static ssize_t test_proc_ioctl_read(struct file *filp, char __user *buff, size_t size, loff_t *pPos)
{
int len;
len = copy_to_user((uint32_t *) buff, &status, size);
if (len < 0) {
printk("Failed to copy data to user space\n");
}
printk("%s status = %d\n",__func__,status);
return len;
}
static ssize_t test_proc_ioctl_write(struct file *filp, const char __user *buff, size_t size, loff_t *pPos)
{
uint32_t len = 0;
uint8_t cmd[2] = { 0 };
if (size < 4095) {
len = copy_from_user(cmd, buff, size - 1);
if (len < 0) {
printk("copy data from user space, failed\n");
return -1;
}
}
status = cmd[0];
gpio_status_exchange(status);
printk("%s status = %d\n",__func__,status);
return len;
}
struct file_operations test_fops = {
.unlocked_ioctl = test_proc_ioctl,
.read = test_proc_ioctl_read,
.write = test_proc_ioctl_write,
};
struct proc_dir_entry *proc_node;
struct proc_dir_entry *proc_dir_test;
char *node_name = "proc_test_node";
static int test_node_create_proc(void)
{
proc_dir_test = proc_mkdir("test_node", NULL);
proc_node = proc_create(node_name,0666,proc_dir_test,&test_fops);
if(proc_node == NULL){
printk("%s failed to create proc file\n",__func__);
return -ENODEV;
}
printk("%s end\n",__func__);
return 0;
}
static int test_node_init(void)
{
struct device_node *test_node = NULL;//定义一个节点
int ret;
printk("%s() begin!\n", __func__);
//通过compatible找到dts中的节点
test_node = of_find_matching_node(test_node,&proc_test_of_match[0]);
if (IS_ERR(test_node)) {
printk("----^_^ %s---dts'node has found---------\n",__FUNCTION__);
}
//获取gpio号
test_gpio = of_get_named_gpio(test_node, "test-gpio", 0);
if(test_gpio<0){
printk("get gpio error,failed");
return -1;
}
ret = test_node_create_proc();
if(ret<0){
printk("test_node_create_proc error,failed\n");
}
printk("%s() ok!\n", __func__);
return 0;
}
static void test_node_exit(void)
{
remove_proc_entry(node_name,proc_dir_test);
printk("%s()!\n", __func__);
}
module_init(test_node_init);
module_exit(test_node_exit);
MODULE_DESCRIPTION("MTK gpio driver");
MODULE_AUTHOR("<huangzb>");
MODULE_LICENSE("GPL");