📄 kbd_drv.c
字号:
#include <linux/slab.h>
#include <linux/init.h>
#include <asm/irq.h>
#include "ep7312_sys.h"
// ioctl 命令ID
#define KBD_GETKEY 1
// 定义键盘的主设备号
#define KEYBOARD_MAJOR 59
static char KeyValue; /* 键值 */
// 设置键盘设备
void setup_kbd(void)
{
// 设置系统寄存器
SYSCON1 &= ~0xf;
SYSCON1 |= 0x8;
SYSCON2 |= 0x000000008;
PADDR |= 0xfffffffff;
// 初始化键值
KeyValue = 0;
}
// 键盘中断服务程序
void kbd_Interrupt(int irq, void *dev_id, struct pt_regs *regs)
{
unsigned char LHB_PortA; /* 端口A数据寄存器的低4位 */
unsigned char row, col; /* 按键的行列值 */
unsigned char keypressed; /* 是否有键按下的标志 */
// 屏蔽键盘中断
disable_irq(16);
printk("kbd_Interrupt\n");
// 获取端口A数据寄存器的低4位
LHB_PortA = PADR & 0xf;
// 判断列值:
// 系统寄存器1的低4位为1000B, 列值为0
// 系统寄存器1的低4位为1001B, 列值为1
// 系统寄存器1的低4位为1010B, 列值为2
// 系统寄存器1的低4位为1011B, 列值为3
col = (SYSCON1 & 0xF) - 0x8;
// 判断行值:
// 端口A数据寄存器的低4位为0001B, 行值为0
// 端口A数据寄存器的低4位为0010B, 行值为1
// 端口A数据寄存器的低4位为0100B, 行值为2
// 端口A数据寄存器的低4位为1000B, 行值为3
keypressed = 0;
for (row = 0; row < 4; row++)
{
if ((LHB_PortA >> row) & 0x1)
{
keypressed = 1;
break;
}
}
printk("keypressed = %d\n", keypressed);
printk("row = %d, col = %d\n", row, col);
// 计算键值
if(keypressed)
{
KeyValue = (row * 4 + 1) + col;
}
else
enable_irq(16);
}
// 获取一个键值
int kbd_kernel_getkey()
{
int i, j, k;
// 开启键盘中断
enable_irq(16);
// 初始化键值
KeyValue=0;
// 循环将各列扫描线为高电平,
// 检测是否有键按下
for (i = 0; i < 4; i++)
{
// 循环置列线为高电平
// 系统寄存器1的低4位为1000B, 列线0高电平
// 系统寄存器1的低4位为1001B, 列线1高电平
// 系统寄存器1的低4位为1010B, 列线2高电平
// 系统寄存器1的低4位为1011B, 列线3高电平
SYSCON1 &= ~0xf;
SYSCON1 |= i % 4 + 8;
// 延时循环, 避免键盘抖动
for (j = 0; j < 1000; j++)
for (k = 0; k < 650; k++)
;
// 如果有键按下, 则返回键值
printk("kbd_kernel_getkey(): KeyValue = %d\n", KeyValue );
if (KeyValue)
{
return KeyValue;
}
}
// 无键按下, 返回0
return 0;
}
// 打开键盘设备文件
int kbd_kernel_open(struct inode * inode, struct file * file)
{
printk("<1> kbd_kernel_open()\n");
return 0;
}
// 对键盘设备文件进行读写之外的其它操作
int kbd_kernel_ioctl(struct inode *inode,struct file *file, unsigned int cmd, unsigned long arg)
{
printk("kbd_kernel_ioctl()\n");
switch (cmd)
{
// 接收一个按键
case KBD_GETKEY:
return kbd_kernel_getkey();
default:
printk("Unknown Keyboard command ID.\n");
}
return 0;
}
// 键盘设备文件操作结构
struct file_operations Kbd_fops = {
open: kbd_kernel_open, /* 打开设备文件 */
ioctl: kbd_kernel_ioctl, /* 设备文件的其它操作 */
};
// 初始化键盘设备
int kbd_kernel_init(void)
{
int result; /* 注册设备结果 */
// 注册键盘设备
printk("\nRegistering Keyboard Device\t--->\t");
result = register_chrdev(KEYBOARD_MAJOR, "keyboard_ep7312", &Kbd_fops);
printk("%d", result);
if (result < 0)
{
printk(KERN_INFO "[FAILED: Cannot register keyboard_ep7312!]\n");
return result;
}
else
printk("[OK]\n");
printk("Initializing Keybaord Deviec\t--->\t");
// 设置键盘设备
setup_kbd();
// 注册键盘中断
if (request_irq(16, kbd_Interrupt, 0, "kbd_interrupt", NULL))
{
printk(KERN_INFO "[FAILED: Cannot register keybaord interrupt!]\n");
return -EBUSY;
}
else
printk("[OK]\n");
// 显示成功加载信息
printk("\nEP7312 Keyboard Driver installed.\n");
printk("Written by BIT200009123.\n");
return 0;
}
// 释放键盘设备
static void kbd_kernel_exit(void)
{
printk("Unregistering Keyboard Device\t--->\t");
// 注销键盘中断
free_irq(16, NULL);
// 注销键盘设备
unregister_chrdev(KEYBOARD_MAJOR, "keyboard_ep7312");
printk("[OK]\n");
return;
}
// 初始化模块
module_init(kbd_kernel_init);
// 卸载模块
module_exit(kbd_kernel_exit);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -