}
// 按键设备驱动文件操作结构体,主要实现打开、释放和读函数
static struct file_operations at91sam9260_key_fops =
{
.owner = THIS_MODULE,
.open = at91sam9260_key_open, // 启动设备
.release = at91sam9260_key_release, // 关闭设备
.read = at91sam9260_key_read, // 读取按键的键值
};
// 模块加载函数包括:设备号申请、cdev的添加,另:申请中断、初始化定时器和队列;
// 模块卸载函数恰好相反
static int __init at91sam9260_key_init(void)
{
int i;
int result;
// 申请设备号
dev_t dev = MKDEV(button_major, DP_MINOR);
/* 申请设备号 */
if (button_major)
result = register_chrdev_region(dev, 1, DEVICE_NAME);
else /* 动态申请设备号 */
{
result = alloc_chrdev_region(&dev, 0, 1, DEVICE_NAME);
button_major = MAJOR(dev);
printk(KERN_INFO "Todo: mknod /dev/%s c %d 0\n", DEVICE_NAME, button_major);
}
// 分配设备结构体的内存
key_devp = kmalloc(sizeof(key_dev),GFP_KERNEL);
if(!key_devp)
{
result = - ENOMEM;
goto fail_malloc;
}
// 添加cdev
memset(key_devp,0,sizeof(key_dev));
cdev_init(&key_dev.cdev, &at91sam9260_key_fops);
if(cdev_add(&key_dev.cdev, dev, 1)){
printk(KERN_ALERT"Add char dev error!\n");
}
key_dev.head = key_dev.tail = 0; // 初始化结构体
for(i = 0; i < KEY_NUM; i++)
{
key_dev.keyStatus[i] = KEYSTATUS_UP;
}
init_waitqueue_head(&(key_dev.wq)); // 等待队列
// 初始化定时器,实现软件的去抖动
/* 初始化定时器 */
for(i = 0; i < KEY_NUM; i++)
{
key_timer[i]. = key_timer_handler;
key_timer[i].data = i;
init_timer(&key_timer[i]);
}
at91sam9260_key_io_init(); // 初始化
// 注册中断函数
if(-1 == request_irqs())
{
printk(KERN_NOTICE "request_irqs failed!\r\n");
}
else
{
printk(KERN_NOTICE "request_irqs success!\r\n");
}
/*
for(i = 0; i < KEY_NUM; i++)
{
setup_timer(&key_timer[i],key_timer_handler,i);
}
*/
fail_malloc:unregister_chrdev_region(dev,1);
return result;
}
// 按键设备驱动的模块卸载函数
static void __exit at91sam9260_key_exit(void)
{
free_irqs(); // 注销中断
// 释放设备号,删除cdev
cdev_del(&key_dev.cdev); // 删除字符设备结构体
kfree(key_devp);
unregister_chrdev_region(MKDEV(button_major,DP_MINOR),1); // 删除字符设备
}
MODULE_AUTHOR("launch");
MODULE_LICENSE("Dual BSD/GPL");
module_init(at91sam9260_key_init);
module_exit(at91sam9260_key_exit);