#include <linux/init.h>
#include <linux/module.h>
#include <linux/cdev.h>
#include <linux/fs.h>
#include <linux/device.h>
#include <linux/uaccess.h>
#include <linux/fcntl.h>
#include <linux/gpio.h>
#include <linux/interrupt.h>
#include <linux/signal.h>
#include <asm-generic/siginfo.h>
#define NAME "cdev_demo"
#define COUNT 3
#define KBUFSIZE 64
#define GPIOA28 28
dev_t dev_no;
struct cdev *cdevp = NULL;
struct class *cls = NULL;
struct device *devp = NULL;
char Kbuf[KBUFSIZE] = {'\0'};
int Kbufcount = 0;
int irq_a28 = 0;
struct fasync_struct *fasync;
irqreturn_t key_irq_handler(int irqno, void *args)
{
kill_fasync(&fasync,SIGIO,POLL_IN);
printk(KERN_DEBUG "[%s-%s-%d]:Interrupt...\n",\
__FILE__,__func__,__LINE__);
return IRQ_HANDLED;
}
static int demo_open(struct inode *inode, struct file *filp)
{
printk(KERN_DEBUG "[%s-%s-%d]: runned...\n",__FILE__,__func__,__LINE__);
return 0;
}
static int demo_release(struct inode *inode, struct file *filp)
{
printk(KERN_DEBUG "[%s-%s-%d]: runned...\n",\
__FILE__,__func__,__LINE__);
return 0;
}
ssize_t demo_read(struct file *filp, char __user *buf, size_t size, loff_t *pos)
{
if(size > Kbufcount){
size = Kbufcount;
}
if(copy_to_user(buf, Kbuf, size)){
printk(KERN_ERR "[%s-%s-%d]: copy_to_user failed...\n",\
__FILE__,__func__,__LINE__);
return -EAGAIN;
}
Kbufcount = 0;
printk(KERN_DEBUG "[%s-%s-%d]: runned...\n",\
__FILE__,__func__,__LINE__);
return size;
}
ssize_t demo_write(struct file *filp, const char __user *buf, size_t size, loff_t *pos)
{
if(size > KBUFSIZE){
size = KBUFSIZE;
}
if(copy_from_user(Kbuf,buf, size)){
printk(KERN_ERR "[%s-%s-%d]: copy_from_user failed...\n",\
__FILE__,__func__,__LINE__);
return -EAGAIN;
}
Kbufcount = size;
printk(KERN_DEBUG "[%s-%s-%d]: Kbuf:%s...\n",\
__FILE__,__func__,__LINE__,Kbuf);
return size;
}
int demo_fasync(int fd, struct file *filp, int on)
{
return fasync_helper(fd, filp, on , &fasync);
}
struct file_operations fops = {
.owner = THIS_MODULE,
.open = demo_open,
.release = demo_release,
.read = demo_read,
.write = demo_write,
.fasync = demo_fasync,
};
static int __init demo_init(void)
{
int ret = 0 ,i = 0;
//0、申请设备号
ret = alloc_chrdev_region(&dev_no, 0 , COUNT , NAME);
if(ret < 0){
printk(KERN_ERR "[%s-%s-%d]:alloc_chrdev_region failed...\n",\
__FILE__,__func__,__LINE__);
goto err0;
}
printk(KERN_DEBUG "[%s-%s-%d]:devno->major:%d--minor:%d--...\n",\
__FILE__,__func__,__LINE__,MAJOR(dev_no),MINOR(dev_no));
//1、分配cdev结构体
cdevp = cdev_alloc();
if(cdevp == NULL){
printk(KERN_ERR "[%s-%s-%d]:cdev_alloc failed...\n",\
__FILE__,__func__,__LINE__);
ret = -ENOMEM;
goto err1;
}
//2、初始化cdev结构体
cdev_init(cdevp, &fops);
//3、添加到内核中,由内核统一管理
ret = cdev_add(cdevp, dev_no, COUNT);
if(ret < 0){
goto err1;
}
//4、class create
cls = class_create(THIS_MODULE,NAME);
if(IS_ERR(cls)){
printk(KERN_ERR "[%s-%s-%d]:class_create...\n",\
__FILE__,__func__,__LINE__);
ret = PTR_ERR(cls);
goto err2;
}
//5、device create
for(i = 0 ; i < COUNT ; i++){
devp = device_create(cls, NULL , MKDEV(MAJOR(dev_no),i) , NULL, "%s%d",NAME,i);
if(IS_ERR(devp)){
printk(KERN_ERR "[%s-%s-%d]:device_create[%d]...\n",\
__FILE__,__func__,__LINE__,i);
ret = PTR_ERR(devp);
goto err3;
}
}
irq_a28 = gpio_to_irq(GPIOA28);
if(irq_a28 < 0){
printk(KERN_ERR "[%s-%s-%d]:call failed...\n",\
__FILE__,__func__,__LINE__);
ret = irq_a28;
goto err3;
}
ret = request_irq(irq_a28,key_irq_handler,IRQF_TRIGGER_FALLING,"gpioa28_key", NULL);
if(ret < 0){
printk(KERN_ERR "[%s-%s-%d]:call failed...\n",\
__FILE__,__func__,__LINE__);
goto err3;
}
return 0;
err3:
for(--i;i>=0;i--){
device_destroy(cls,MKDEV(MAJOR(dev_no),i));
}
class_destroy(cls);
err2:
cdev_del(cdevp);
err1:
unregister_chrdev_region(dev_no, COUNT);
err0:
return ret;
}
static void __exit demo_exit(void)
{
int i = 0;
free_irq(irq_a28, NULL);
for(i=0;i < COUNT;i++){
device_destroy(cls,MKDEV(MAJOR(dev_no),i));
}
class_destroy(cls);
//cdev从内核中删除
cdev_del(cdevp);
//设备号资源释放
unregister_chrdev_region(dev_no, COUNT);
}
module_init(demo_init);
module_exit(demo_exit);
MODULE_LICENSE("GPL");
KDIR:=/home/edu/SAMBA_SHARE/BK2101/Driver/03_kernel/kernel-3.4.39
#KDIR:= /lib/modules/`uname -r`/build
PWD := $(shell pwd)
obj-m += demo.o
modules:
make -C $(KDIR) M=$(PWD) modules
#cp *.ko ~/rootfs/home
clean:
make -C $(KDIR) M=$(PWD) clean
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <signal.h>
char buf[32];
fd_set r_fds;
void sig_callback(int sig)
{
printf("sig callback...\n");
}
int main(int argc, const char *argv[])
{
int ret = 0;
signal(SIGIO, sig_callback);
int fd = open("/dev/cdev_demo0",O_RDWR);
if(fd < 0){
perror("open");
return -1;
}
fcntl(fd,F_SETOWN,getpid());
fcntl(fd,F_SETFL,fcntl(fd,F_GETFL)|FASYNC);
while(1){
}
//close(fd);
return 0;
}