打印

input子系统驱动实例(在Easy-iMX257开发板通过),如果对你有帮助,请回复

[复制链接]
666|0
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
beixiaobin|  楼主 | 2015-10-6 11:25 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
#include <linux/init.h>

#include <linux/module.h>

#include <linux/fs.h>

#include <linux/device.h>

#include <linux/cdev.h>

#include <linux/uaccess.h>

#include <linux/io.h>

#include <linux/irq.h>

#include <linux/interrupt.h>

#include <linux/module.h>

#include <linux/init.h>

#include <linux/kernel.h>

#include <linux/delay.h>

#include <linux/types.h>

#include <linux/ioctl.h>

#include <linux/gpio.h>

#include <linux/fs.h>

#include <linux/device.h>

#include <linux/uaccess.h>

#include <linux/irq.h>

#include <linux/wait.h>

#include <linux/sched.h>//error: ‘TASK_INTERRUPTIBLE‘ undeclared

#include <linux/interrupt.h>

#include <linux/workqueue.h>

#include <linux/poll.h>

#include <asm/gpio.h>

#include <asm/atomic.h>



#include "iomux.h"

#include "mx25.h"

#include "mxc.h"

#include "mx25_pins.h"

#include "irqs.h"



MODULE_LICENSE("GPL");

MODULE_AUTHOR("beixiaobin62@163.com");

MODULE_DESCRIPTION("button kernel module");

MODULE_VERSION("V2.0.0");



#define GPIO2_21    MX25_PIN_CLKO



static int major;

static struct cdev btn_cdev;

static struct class *cls;



//分配等待队列头

static wait_queue_head_t btn_wq;

static int ispress; //=1,按键有操作;=0,按键无操作



static unsigned char key_val; //上报按键的值



//btn_read函数实现

static ssize_t btn_read(struct file *file,

char __user *buf, //对应用户的第二个参数

size_t count, //对应用户第三个参数

loff_t *ppos //文件指针

)

{

int reval;

/*0.判断是否采用非阻塞方式*/

if(file->f_flags & O_NONBLOCK)

{

//非阻塞方式

if(!ispress) //判断按键是否有操作,如果没有立即返回

{

printk("No Data\n");

return -EAGAIN; //再次读

}

}

//阻塞方式

/*1.判断按键是否有操作,通过ippress来判断,如果有操作,ispress=1*/

//这个函数立即返回,如果ispress=0,没有操作,进程进入休眠状态。

//一旦被唤醒,就可以读取按键值给用户

printk("Process:%d(%s) to Sleeping ...\n",

current->pid, current->comm);

/*2.进入可中断的休眠*/

reval = wait_event_interruptible(btn_wq, ispress);

if(reval)

{

/*信号唤醒的睡眠*/

printk("RECV SIGNAL!\n");

return -ERESTARTSYS;//返回用户空间的read

}

else

{

ispress = 0;

printk("Process:%d(%s) Wake UP!\n",

current->pid, current->comm);

/*2.一旦被唤醒,上报按键数据*/

copy_to_user(buf, &key_val, sizeof(key_val));

}

return count;

}



//监听功能

static unsigned int btn_poll(struct file *file,

struct poll_table_struct *wait)

{

unsigned int mask = 0;

//1.将进程添加到等待队列头所在的数据链中,切记进程并没有进入真正的休眠

poll_wait(file, &btn_wq, wait);

//2.判断按键键值是否可用,如果可用,返回非0,否则返回0

if(ispress){ //按键有操作

mask = POLLIN|POLLRDNORM; //设备数据可读

}

return mask;

}



static struct file_operations btn_fops = {

.owner = THIS_MODULE,

.read = btn_read, //获取按键接口

.poll = btn_poll //被监听功能接口

};



static irqreturn_t button_isr(int irq, void *dev_id)

{

unsigned int pinstatus;

/*1.获取按键对应的状态*/

pinstatus = gpio_get_value(IOMUX_TO_GPIO(GPIO2_21));

/*2.获取按键对应的状态,设置要上报的按键值*/

if(pinstatus == 1)//松开

key_val = 0x50;

else if(pinstatus == 0)//按下

key_val = 0x51;

/*3.唤醒休眠进程*/

ispress = 1; //按键有操作,按键数据可用

wake_up_interruptible(&btn_wq);

return IRQ_HANDLED;

}

  

static int btn_init(void)

{

dev_t dev;

//1.申请设备号

alloc_chrdev_region(&dev, 0, 1, "button");

major = MAJOR(dev);

//2.初始化注册cdev

cdev_init(&btn_cdev, &btn_fops);

cdev_add(&btn_cdev, dev, 1);

//3.自动创建设备节点是/dev/mybutton

cls = class_create(THIS_MODULE,"BUTTON");

device_create(cls, NULL, dev, NULL, "mybutton");

/*4.向内核申请为GPIO功能*/

mxc_request_iomux(GPIO2_21, MUX_CONFIG_ALT5);



/*5.申请GPIO资源*/

gpio_request(IOMUX_TO_GPIO(GPIO2_21), "BUTTON");

/*6.设置输入脚各项参数*/

mxc_iomux_set_pad(GPIO2_21, PAD_CTL_HYS_SCHMITZ | PAD_CTL_PKE_ENABLE |

PAD_CTL_PUE_PULL | PAD_CTL_22K_PU);

/*7.注册中断*/

request_irq(IOMUX_TO_IRQ(GPIO2_21), button_isr, IRQF_TRIGGER_FALLING |

IRQF_TRIGGER_RISING, "KEY", NULL);

/*8.初始化等待队列*/

init_waitqueue_head(&btn_wq);



return 0;

}



static void btn_exit(void)

{

dev_t dev = MKDEV(major, 0);

/*1.释放中断,注意注册中断传递的参数和释放中断传递的参数必须一致!!!*/

printk("unregister irq!\n");

free_irq(IOMUX_TO_IRQ(GPIO2_21), NULL);

/*2.释放GPIO资源*/

gpio_free(IOMUX_TO_GPIO(GPIO2_21));

/*3.取消GPIO功能*/

mxc_free_iomux(GPIO2_21, MUX_CONFIG_ALT5);

//4.删除设备节点

device_destroy(cls, dev);

class_destroy(cls);

//5.卸载cdev

cdev_del(&btn_cdev);

//6.释放设备号

unregister_chrdev_region(dev, 1);

printk("unregister irq!\n");

}



module_init(btn_init);

module_exit(btn_exit);

相关帖子

发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

1

主题

1

帖子

0

粉丝