代码拉取完成,页面将自动刷新
#include <linux/init.h>
#include <linux/types.h>
#include <linux/idr.h>
#include <linux/input/mt.h>
#include <linux/module.h>
#include <linux/slab.h>
#include <linux/random.h>
#include <linux/major.h>
#include <linux/proc_fs.h>
#include <linux/sched.h>
#include <linux/seq_file.h>
#include <linux/poll.h>
#include <linux/device.h>
#include <linux/mutex.h>
#include <linux/rcupdate.h>
#include <linux/cdev.h>
#include <linux/interrupt.h>
#include <linux/ioctl.h>
#include <linux/gpio.h>
#include <linux/timer.h>
#define DEVICE_NAME "ioinput" //设备名称
#define IRQNUM1 (IRQ_GPIO_START+0x0103)//中断号 //GPIOP_PI3
#define IRQNUM2 (IRQ_GPIO_START+0x0104)//中断号 //GPIO_PI4
#define IRQNUM3 (IRQ_GPIO_START+0x0105)//中断号 //GPIO_PI5
#define IRQNUM4 (IRQ_GPIO_START+0x0106)//中断号 //GPIO_PI6
struct conf
{
unsigned char sample_io;
unsigned char sample_io_enable;
unsigned char action_io;
};
unsigned char sample_flag = 0;
unsigned int cnt =0;
struct conf tps_conf={.sample_io=0,.sample_io_enable=0,.action_io=0};
int light_major = 200;
static struct class *firstdrv_class;
static struct device *firstdrv_device;
static volatile int ev_press = 0;
static DECLARE_WAIT_QUEUE_HEAD(io_waitq);
struct ioput_data {
struct cdev cdev;
int vaild; //
int cnt;//计数
};
struct ioput_data *myinput;
struct timer_list mytimer;//定义一个定时器
static unsigned char flag=0;
static unsigned long delay = 500;
static unsigned char t1= 0,t2=0,t3=0,t4=0;
#define N 10
void timeout(void)
{
printk("\nTime out\n");
flag = 0;
del_timer(&mytimer);
//add();
}
static irqreturn_t ioinput_interrupt1(int irq, void *dev_id)
{
struct ioput_data *io_irqs = (struct ioput_data *)dev_id;
if(tps_conf.sample_io_enable==1)
{
if(tps_conf.sample_io==1)
{
sample_flag = 1;
}
if(tps_conf.action_io==1)
{
if(sample_flag==1)
{
cnt++;
sample_flag=0;
}
}
}else if(tps_conf.action_io==1)
{
if(flag==1)
{
t1++;
if(t1==N)
{
t1 = 0;
flag = 0;
del_timer(&mytimer);
}
}
if(flag ==0)
{
cnt++;
sample_flag=0;
mytimer.expires = jiffies+msecs_to_jiffies(delay);
mytimer.function = timeout;
add_timer(&mytimer);
flag = 1;
t1 = 0;
}
}
ev_press = 1;
wake_up_interruptible(&io_waitq); /*唤醒等待队列*/
printk ("\tInterrupt11!\n");
return IRQ_HANDLED;
}
static irqreturn_t ioinput_interrupt2(int irq, void *dev_id)
{
struct ioput_data *io_irqs = (struct ioput_data *)dev_id;
io_irqs->cnt =2;
int ret = 0;
if(tps_conf.sample_io_enable==1)
{
if(tps_conf.sample_io==2)
{
sample_flag = 1;
}
if(tps_conf.action_io==2)
{
if(sample_flag==1)
{
cnt++;
sample_flag=0;
}
}
}else if(tps_conf.action_io==2)
{
if(flag==1)
{
t2++;
if(t2==N)
{
t2 = 0;
flag = 0;
del_timer(&mytimer);
}
}
if(flag ==0)
{
cnt++;
t2 =0;
sample_flag=0;
mytimer.expires = jiffies+msecs_to_jiffies(delay);
mytimer.function = timeout;
add_timer(&mytimer);
t2=0;
}
}
ev_press = 2;
wake_up_interruptible(&io_waitq); /*唤醒等待队列*/
printk ("\tInterrupt222!\n");
return IRQ_HANDLED;
}
static irqreturn_t ioinput_interrupt3(int irq, void *dev_id)
{
struct ioput_data *io_irqs = (struct ioput_data *)dev_id;
io_irqs->cnt =2;
if(tps_conf.sample_io_enable==1)
{
if(tps_conf.sample_io==3)
{
sample_flag = 1;
}
if(tps_conf.action_io==3)
{
if(sample_flag==1)
{
cnt++;
sample_flag=0;
}
}
}else if(tps_conf.action_io==3)
{
if(flag==1)
{
t3++;
if(t3==N)
{
t3 = 0;
flag = 0;
del_timer(&mytimer);
}
}
if(flag ==0)
{
cnt++;
sample_flag=0;
mytimer.expires = jiffies+msecs_to_jiffies(delay);
mytimer.function = timeout;
add_timer(&mytimer);
flag = 1;
t3=0;
}
}
wake_up_interruptible(&io_waitq); /*唤醒等待队列*/
ev_press = 3;
printk ("\tInterrupt333!\n");
return IRQ_HANDLED;
}
static irqreturn_t ioinput_interrupt4(int irq, void *dev_id)
{
struct ioput_data *io_irqs = (struct ioput_data *)dev_id;
io_irqs->cnt =2;
if(tps_conf.sample_io_enable==1)
{
if(tps_conf.sample_io==4)
{
sample_flag = 1;
}
if(tps_conf.action_io==4)
{
if(sample_flag==1)
{
cnt++;
sample_flag=0;
}
}
}else if(tps_conf.action_io==4)
{
if(flag==1)
{
t4++;
if(t4==N)
{
t4 = 0;
flag = 0;
del_timer(&mytimer);
}
}
if(flag ==0)
{
cnt++;
sample_flag=0;
mytimer.expires = jiffies+msecs_to_jiffies(delay);
mytimer.function = timeout;
add_timer(&mytimer);
flag = 1;
t4= 0;
}
}
wake_up_interruptible(&io_waitq); /*唤醒等待队列*/
ev_press = 4;
printk ("\tInterrupt444!\n");
return IRQ_HANDLED;
}
static int ioinput_open(struct inode *inode, struct file *file)
{
int err = 0;
// IRQF_TRIGGER_HIGH 0x00000004 指定中断触发类型:高电平有效。新增加的标志
file->private_data = container_of(inode->i_cdev,struct ioput_data,cdev);
/*注册中断函数*/
err = request_irq(IRQNUM1, ioinput_interrupt1, IRQF_TRIGGER_RISING, "ioinput", myinput);///* IRQF_TRIGGER_RISING 指定中断触发类型:沿有效*/
if (err)
{
/*如果出错,释放已经注册的中断,并返回*/
disable_irq(IRQNUM1);
free_irq(IRQNUM1, myinput);
printk("request irq IRQNUM1 %d failed\n",IRQNUM1);
return -EBUSY;
}
/*注册中断函数*/
err = request_irq(IRQNUM2, ioinput_interrupt2, IRQF_TRIGGER_RISING, "ioinput", myinput);/* IRQF_TRIGGER_RISING 指定中断触发类型:上升沿有效*/
if (err)
{
/*如果出错,释放已经注册的中断,并返回*/
disable_irq(IRQNUM2);
free_irq(IRQNUM2, myinput);
printk("request irq IRQNU2 %d failed\n",IRQNUM2);
return -EBUSY;
}
err = request_irq(IRQNUM3, ioinput_interrupt3, IRQF_TRIGGER_RISING, "ioinput", myinput);/* IRQF_TRIGGER_RISING 指定中断触发类型:上升沿有效*/
if (err)
{
/*如果出错,释放已经注册的中断,并返回*/
disable_irq(IRQNUM3);
free_irq(IRQNUM3, myinput);
printk("request irq IRQNU3 %d failed\n",IRQNUM3);
return -EBUSY;
}
err = request_irq(IRQNUM4, ioinput_interrupt4, IRQF_TRIGGER_RISING, "ioinput", myinput);/* IRQF_TRIGGER_RISING 指定中断触发类型:上升沿有效*/
if (err)
{
/*如果出错,释放已经注册的中断,并返回*/
disable_irq(IRQNUM4);
free_irq(IRQNUM4, myinput);
printk("request irq IRQNU4 %d failed\n",IRQNUM4);
return -EBUSY;
}
ev_press = 1;
/*正常返回*/
return 0;
}
static int ioinput_close(struct inode *inode, struct file *file)
{
free_irq(IRQNUM1, myinput);
free_irq(IRQNUM2, myinput);
free_irq(IRQNUM3, myinput);
free_irq(IRQNUM4, myinput);
return 0;
}
static int ioinput_read(struct file *filp, char __user *buff, size_t count, loff_t *offp)
{
unsigned long err=0;
struct ioput_data *dev = filp->private_data;
if (!ev_press)
{
if (filp->f_flags & O_NONBLOCK)
/*当中断标识为0 时,并且该设备是以非阻塞方式打开时,返回*/
return -EAGAIN;
else
/*当中断标识为0 时,并且该设备是以阻塞方式打开时,进入休眠状态,等待被唤醒*/
wait_event_interruptible(io_waitq, ev_press);
}
/*把中断标识清零*/
//ev_press = 0;
/*传递到用户空间*/
err = copy_to_user(buff, (const void *)&cnt, sizeof(int));
if(err!=0)
return -1;
printk("kernel cnt =%d \n",cnt);
ev_press = 0;
return sizeof(int);
}
int tttt = 0;
static int ioinput_write(struct file *filp,const char __user *buff, size_t count, loff_t *offp)
{
unsigned long err=0;
char buf[10]={0};
struct ioput_data *dev = filp->private_data;
err = copy_from_user(buf, buff, 6);
printk("kernel===buf[0]=%d\n",buf[0]);
if(err!=0)
return -1;
/*设置到cnt*/
if(buf[0]==0x01)
{
cnt = 0; //clear cnt
sample_flag=0;
}
if(buf[0]==0x02) //conf tps_conf
{
memset(&tps_conf.sample_io,0x00,sizeof(struct conf));
memcpy(&tps_conf.sample_io,&buf[1],3);
delay = 500;
memcpy(&delay,&buf[4],2);
delay = delay&0xffff;
//cnt = 0; //just clear
sample_flag =0;
printk("kernel===buf[0]=%d sample_io =%d sample_enable=%d actio_io=%d buf[4] =%d buf[5]=%d delay=%d\n",buf[0],buf[1],buf[2],buf[3],buf[4],buf[5],delay);
}
return ;
}
static unsigned int ioinput_poll( struct file *file, struct poll_table_struct *wait)
{
unsigned int mask = 0;
/*把调用poll 或者select 的进程挂入队列,以便被驱动程序唤醒*/
poll_wait(file, &io_waitq, wait);
if (ev_press) //中断事件发生,这时有数据可读,在mask中标记是可读事件发生
mask |= POLLIN | POLLRDNORM;
return mask;
}
/*设备操作集*/
static struct file_operations dev_fops = {
.owner = THIS_MODULE,
.open = ioinput_open,
.release = ioinput_close,
.read = ioinput_read,
.write = ioinput_write,
.poll = ioinput_poll,
};
static void ioinput_setup_cdev(struct ioput_data *dev,int index)
{
int err,devno = MKDEV(light_major,index);
cdev_init(&dev->cdev,&dev_fops);
dev->cdev.owner = THIS_MODULE;
dev->cdev.ops = &dev_fops;
err = cdev_add(&dev->cdev,devno,1);
if(err)
{
printk(KERN_NOTICE "Error %d adding LED%d",err,index);
}
}
int ioinput_init(void)
{
int result=0;
printk("ioinput dev init... ..\n");
dev_t dev = MKDEV(light_major,0);
init_timer(&mytimer); //初始化定时器
//mytimer.expires = jiffies+4*HZ;
//mytimer.function = timeout;
//add_timer(&mytimer);
if(light_major)
{
result = register_chrdev_region(dev,1,"io_input");
/* io_input */
firstdrv_class = class_create(THIS_MODULE, "ioinput");
/* 在ioinput类下创建设备,供应用程序打开设备*/
firstdrv_device = device_create(firstdrv_class, NULL, MKDEV(light_major, 0), NULL, DEVICE_NAME);
}
if(result < 0)
{
return result;
}
myinput = kmalloc(sizeof(struct ioput_data),GFP_KERNEL);
if(!myinput)
{
result = - ENOMEM;
unregister_chrdev_region(dev,1);
return result;
}
memset(myinput,0,sizeof(struct ioput_data));
ioinput_setup_cdev(myinput,0);
printk("ioinput dev init ok\n");
return 0;
}
/*注销设备*/
static void __exit dev_exit(void)
{
printk("ioinput dev exit ....\n");
del_timer(&mytimer);
cdev_del(&myinput->cdev);
kfree(myinput);
unregister_chrdev_region(MKDEV(light_major,0),1);
device_unregister(firstdrv_device); //卸载类下的设备
class_destroy(firstdrv_class); //卸载类
printk("ioinput dev exit ok\n");
}
module_init(ioinput_init); //模块初始化,仅当使用insmod/podprobe 命令加载时有用,如果设备不是通过模块方式加载,此处将不会被调用
module_exit(dev_exit); //卸载模块,当该设备通过模块方式加载后,可以通过rmmod 命令卸载,将调用此函数
MODULE_LICENSE("GPL");//版权信息
MODULE_AUTHOR("Madest Inc.");//作者名字
此处可能存在不合适展示的内容,页面不予展示。您可通过相关编辑功能自查并修改。
如您确认内容无涉及 不当用语 / 纯广告导流 / 暴力 / 低俗色情 / 侵权 / 盗版 / 虚假 / 无价值内容或违法国家有关法律法规的内容,可点击提交进行申诉,我们将尽快为您处理。