按键读取我们需要实现read函数,
read 函数的 第二个参数被__user 修饰,原则上在内核层我们不能直接访问,需要调用
copy_to_user()这个函数,从内核获取数据到上层。
copy_to_user(void __user volatile * to, const void * from, unsigned long n)
参数1:目标地址,
参数2:数据从哪里来
参数3:多少个字节
当我们想实现write时,就需要使用,copy_from_user() 从上层获取数据到内核,
copy_from_user(void * to, const void __user volatile * from, unsigned long n)
参数1:目标地址
参数2:数据从哪里来
参数3:多少字节
下面来实现驱动代码
#include "linux/cdev.h"
#include "linux/device.h"
#include "linux/device/class.h"
#include "linux/export.h"
#include "linux/fs.h"
#include "linux/gpio.h"
#include "linux/module.h"
#include "linux/of_device.h"
#include "linux/of_gpio.h"
#include "linux/platform_device.h"
#include "linux/types.h"
#include "linux/uaccess.h"
#include "linux/zconf.h"
uint32_t pin;
dev_t dev_num;
struct cdev *cdev;
struct class *cls;
ssize_t read(struct file *f, char __user *b, size_t s, loff_t *offt)
{
uint8_t val=gpio_get_value(pin);
int a=copy_to_user(b,&val,1);
copy_from_user(void * to, const void __user volatile * from, unsigned long n)
if(a)
{
}
return 0;
}
struct file_operations fops={
.owner=THIS_MODULE,
.read=read,
};
int probe(struct platform_device *d)
{
pin=of_get_named_gpio(d->dev.of_node,"key_pin",0);
printk("%d\r\n",pin);
gpio_request(pin,"key");
gpio_direction_input(pin);
alloc_chrdev_region(&dev_num, 0, 1,"key");
cdev=cdev_alloc();
cdev->ops=&fops;
cdev_add(cdev,dev_num,1);
cls=class_create(THIS_MODULE, "key");
device_create(cls, NULL,dev_num,NULL,"key");
return 0;
}
int remove(struct platform_device *d)
{
return 0;
}
static struct of_device_id match={
.compatible="key",
};
static struct platform_driver driver={
.probe=probe,
.remove=remove,
.driver={
.name="key",
.of_match_table=&match,
},
};
static int __init start(void)
{
platform_driver_register(&driver);
printk(KERN_INFO "Hello, world!\n");
return 0;
}
static void __exit stop(void)
{
platform_driver_unregister(&driver);
printk(KERN_INFO "Goodbye, world!\n");
}
module_init(start);
module_exit(stop);
MODULE_LICENSE("GPL");