/*******************************************************************************************
*应用程序对设备文件/dev/keyboard执行open(...)时,
* 就会调用key_open函数
********************************************************************************************/
static int key_open(struct inode *inode, struct file *file)
{
int i;
int err;
for (i = 0; i < KEY_NUM; i++)
{
set_irq_type(key_irqs[i].irq,IRQF_TRIGGER_LOW);
//set_external_irq(key_irqs[i].irq,EXT_LOWLEVEL,GPIO_PULLUP_DIS);
//将对应的引脚设置成中断功能
s3c2410_gpio_cfgpin(key_irqs[i].pin,key_irqs[i].pin_setting);
// 申请中断,注册中断处理函数
err = request_irq(key_irqs[i].irq, key_interrupt, NULL,
key_irqs[i].name, (void *)&key_irqs[i]); //将&key_irqs[i]作为参数传入中断处理程序
if (err)
break;
}
if (err)
{
// 释放已经注册的中断
i--;
for (; i >= 0; i--)
{
disable_irq(key_irqs[i].irq);
free_irq(key_irqs[i].irq, (void *)&key_irqs[i]);
}
return -EBUSY;
}
return 0;
}
/********************************************************************************************
* 应用程序对设备文件/dev/keyboard执行close(...)时,
* 就会调用key_close函数
*********************************************************************************************/
static int key_close(struct inode *inode, struct file *file)
{
int i;
for (i = 0; i < KEY_NUM; i++)
{
// 释放已经注册的中断
disable_irq(key_irqs[i].irq);
free_irq(key_irqs[i].irq, (void *)&key_irqs[i]);
}
return 0;
}
/********************************************************************************************
*应用程序对设备文件/dev/keyboard执行read(...)时,
* 就会调用key_read函数
*********************************************************************************************/
static int key_read(struct file *filp, char __user *buff, size_t count, loff_t *offp)
{
unsigned long err;
retry:if(key_devp->key_values_flag==1)
{
/* 将按键状态复制给用户,并清0 */
//printk(KERN_ALERT "key value:%d %d %d %d\n",key_devp->key_values[0],key_devp->key_values[1],key_devp->key_values[2],key_devp->key_values[3]);
err = copy_to_user(buff, (const void *)key_devp->key_values, min(KEY_NUM, count));
memset((void *)key_devp->key_values, 0, min(KEY_NUM, count));
key_devp->key_values_flag=0;
}
else
{
if (filp->f_flags & O_NONBLOCK)
return -EAGAIN;
else
{
/* 如果key_values_flag等于0,休眠 */
wait_event_interruptible(key_devp->key_waitq, key_devp->key_values_flag);
goto retry;
}
}
return err ? -EFAULT : min(KEY_NUM, count);
}
/********************************************************************************************
* 轮询函数判断是否能非阻塞的读取或写入
* 当用户程序调用select函数时,本函数被调用
* 如果有按键数据,则select函数会立刻返回
* 如果没有按键数据,本函数使用poll_wait等待
********************************************************************************************/
static unsigned int key_poll( struct file *file, struct poll_table_struct *wait)
{
unsigned int mask = 0;
poll_wait(file, &(key_devp->key_waitq), wait); // 此处将当前进程加入到等待队列中,但并不阻塞
if (key_devp->key_values_flag)
mask |= POLLIN | POLLRDNORM;
return mask;
}
/*********************************************************************************************
*这个结构是字符设备驱动程序的核心
* 当应用程序操作设备文件时所调用的open、read、write等函数,
* 最终会调用这个结构中的对应函数
*********************************************************************************************/
static struct file_operations key_fops =
{
.owner = THIS_MODULE, /* 这是一个宏,指向编译模块时自动创建的__this_module变量 */
.open = key_open,
.release = key_close,
.read = key_read,
.poll = key_poll,
};