📄 kbd7312.c
字号:
#include <linux/config.h>
#include <linux/utsname.h>
#include <linux/kernel.h>
#include <linux/major.h>
#include <linux/string.h>
#include <linux/fcntl.h>
#include <linux/slab.h>
#include <linux/timer.h>
#include <linux/module.h>
#include <linux/init.h>
#include <linux/poll.h>
#include <asm/irq.h>
#include <asm/segment.h>
#define KBD_IRQ_NUM 0
#define KEYBOARD_MAJOR 59
static short Ready;
static char KeyValue;
static DECLARE_WAIT_QUEUE_HEAD(KbdWait);
static int col_global;
static int keypressed = 0;
void dly(int n)
{
int i, j;
for(i = 0; i < 1000; i++)
for(j = 0; j < n; j++)
;
}
static void KbdInterrupt(int irq, void *dev_id, struct pt_regs *regs)
{
unsigned char value;
Ready = 0;
value = *(unsigned char *)0xff000000;
keypressed = 1;
if(col_global == 0) {
if(value == 0x1) {
KeyValue = 1;
printk("KeyValue = %d\n", KeyValue);
// printk("col = %d, row = 1\n", col_global + 1);
}
if(value & 0x2) {
KeyValue = 5;
printk("KeyValue = %d\n", KeyValue);
// printk("col = %d, row = 2\n", col_global + 1);
}
if(value & 0x4) {
KeyValue = 9;
printk("KeyValue = %d\n", KeyValue);
// printk("col = %d, row = 3\n", col_global + 1);
}
if(value & 0x8) {
KeyValue = 13;
printk("KeyValue = %d\n", KeyValue);
// printk("col = %d, row = 4\n", col_global + 1);
}
dly(1000);
}
else if (col_global == 1) {
if(value & 0x1) {
KeyValue = 2;
printk("KeyValue = %d\n", KeyValue);
// printk("col = %d, row = 1\n", col_global + 1);
}
if(value & 0x2) {
KeyValue = 6;
printk("KeyValue = %d\n", KeyValue);
// printk("col = %d, row = 2\n", col_global + 1);
}
if(value & 0x4) {
KeyValue = 10;
printk("KeyValue = %d\n", KeyValue);
// printk("col = %d, row = 3\n", col_global + 1);
}
if(value & 0x8) {
KeyValue = 14;
printk("KeyValue = %d\n", KeyValue);
// printk("col = %d, row = 4\n", col_global + 1);
}
dly(1000);
}
else if(col_global == 2) {
if(value & 0x1) {
KeyValue = 3;
printk("KeyValue = %d\n", KeyValue);
// printk("col = %d, row = 1\n", col_global + 1);
}
if(value & 0x2) {
KeyValue = 7;
printk("KeyValue = %d\n", KeyValue);
// printk("col = %d, row = 2\n", col_global + 1);
}
if(value & 0x4) {
KeyValue = 11;
printk("KeyValue = %d\n", KeyValue);
// printk("col = %d, row = 3\n", col_global + 1);
}
if(value & 0x8) {
KeyValue = 15;
printk("KeyValue = %d\n", KeyValue);
// printk("col = %d, row = 4\n", col_global + 1);
}
dly(1000);
}
else if(col_global == 3) {
if(value & 0x1) {
KeyValue = 4;
printk("KeyValue = %d\n", KeyValue);
// printk("col = %d, row = 1\n", col_global + 1);
}
if(value & 0x2) {
KeyValue = 8;
printk("KeyValue = %d\n", KeyValue);
// printk("col = %d, row = 2\n", col_global + 1);
}
if(value & 0x4) {
KeyValue = 12;
printk("KeyValue = %d\n", KeyValue);
// printk("col = %d, row = 3\n", col_global + 1);
}
if(value & 0x8) {
KeyValue = 16;
printk("KeyValue = %d\n", KeyValue);
// printk("col = %d, row = 4\n", col_global + 1);
}
dly(1000);
}
#if 0 //test ok
if(value & 0x1) {
printk("col = %d, row = 1\n", col_global + 1);
}
if(value & 0x2) {
printk("col = %d, row = 2\n", col_global + 1);
}
if(value & 0x4) {
printk("col = %d, row = 3\n", col_global + 1);
}
if(value & 0x8) {
printk("col = %d, row = 4\n", col_global + 1);
}
// printk("value = 0x%02x\n", value);
dly(500);
#endif
#if 0
while(1){
again:
printk("\n0x80000100 : 0x%08x\n", *(unsigned char *)0xff000100);
printk("0x80000000 : 0x%08x\n", *(unsigned char *)0xff000000);
printk("n= %d\n", n);
printk("interrupt\n");
value = *(unsigned char *)0xff000000;
if(value & 0x1) {
printk("col = %d, row = 1\n", n + 1);
}
if(value & 0x2) {
printk("col = %d, row = 2\n", n + 1);
}
if(value & 0x4) {
printk("col = %d, row = 3\n", n + 1);
}
if(value & 0x8) {
printk("col = %d, row = 4\n", n + 1);
}
// printk("value = 0x%02x\n", value);
dly(500);
*(unsigned long *)0xff000100 += 1;
*(unsigned long *)0xff001700 |= 0xff; //clear
n += 1;
if( n == 4) {
*(unsigned long *)0xff000100 -= 4;
n -= 4;
goto scan_exit;
}
goto again;
}
#endif
// *(unsigned long *)0xff001700 |= 0xff; //clear
}
static int KbdClose(struct inode * inode, struct file * file)
{
MOD_DEC_USE_COUNT;
return 0;
}
static int KbdOpen(struct inode * inode, struct file * file)
{
MOD_INC_USE_COUNT;
*(unsigned long *)0xff000040 |= 0xfffffffff;
*(unsigned long *)0xff001100 |= 0x000000008;
*(unsigned long *)0xff000100 |= 0x000000009;
enable_irq(16);
return 0;
}
static int KbdRead(struct file * file, char * buffer, size_t count, loff_t *ppos)
{
unsigned char *kbuf=kmalloc(16, GFP_KERNEL);
*kbuf = KeyValue;
copy_to_user(buffer, kbuf, 1);
kfree(kbuf);
//copy_to_user(buffer, &KeyValue, sizeof KeyValue);
//Ready = 0;
return sizeof 1;
}
/*
* select for mouse input
*/
static unsigned int KbdSelect(
struct file *file,
struct poll_table_struct *wait)
{
if (Ready)
return 1;
poll_wait(file, &KbdWait, wait);
return 0;
}
static int KbdIoctl(
struct inode *inode,
struct file *file,
unsigned int cmd,
unsigned long arg
)
{
int flag = 0;
keypressed = 0;
switch(cmd) {
case 0:
for(col_global = 0; col_global < 4; col_global++){
if(col_global == 0 ) {
*(unsigned long *)0xff000100 &= ~0xf;
*(unsigned long *)0xff000100 |= 0x8;
dly(1000);
}
else if( col_global == 1) {
*(unsigned long *)0xff000100 &= ~0xf;
*(unsigned long *)0xff000100 |= 0x9;
dly(1000);
}
else if( col_global == 2) {
*(unsigned long *)0xff000100 &= ~0xf;
*(unsigned long *)0xff000100 |= 0xa;
dly(1000);
}
else if( col_global == 3) {
*(unsigned long *)0xff000100 &= ~0xf;
*(unsigned long *)0xff000100 |= 0xb;
dly(1000);
}
}
if (keypressed == 1)
{
keypressed = 0;
return KeyValue;
}
break;
case 2:
if( flag == 0) {
*(unsigned long *)0xff000100 += 1;
flag = 1;
} else if (flag == 1){
*(unsigned long *)0xff000100 -= 1;
flag = 0;
}
break;
case 1:
{
unsigned char value;
int n = 0;
while(1){
again:
// printk("0x80000100 : 0x%08x\n", *(unsigned char *)0xff000100);
// printk("0x80000000 : 0x%08x\n", *(unsigned char *)0xff000000);
// printk("n= %d\n", n);
value = *(unsigned char *)0xff000000;
if(value & 0x1) {
printk("col = %d, row = 1\n", n + 1);
}
if(value & 0x2) {
printk("col = %d, row = 2\n", n + 1);
}
if(value & 0x4) {
printk("col = %d, row = 3\n", n + 1);
}
if(value & 0x8) {
printk("col = %d, row = 4\n", n + 1);
}
// printk("value = 0x%02x\n", value);
dly(500);
*(unsigned long *)0xff000100 += 1;
n += 1;
if( n == 4) {
*(unsigned long *)0xff000100 -= 4;
n -= 4;
break;
}
goto again;
}// end for
break;
} //end case 0
default:
return -EINVAL;
}
//return 1;
}
struct file_operations Kbd_fops = {
read: KbdRead,
poll: KbdSelect, /* select */
open: KbdOpen,
ioctl: KbdIoctl,
release: KbdClose,
};
int keyboard_init(void)
{
int rc;
Ready = 0;
rc = register_chrdev(KEYBOARD_MAJOR, "ep7312-keyboard", &Kbd_fops);
if (rc < 0) {
printk(KERN_WARNING "Keyboard: can't get Major %d\n",
KEYBOARD_MAJOR);
return rc;
}
printk("Keyboard Driver Support\n");
*(unsigned long *)0xff000040 |= 0xfffffffff;
*(unsigned long *)0xff001100 |= 0x000000008;
*(unsigned long *)0xff000100 |= 0x000000009;
if ( request_irq(16, KbdInterrupt, 0, "mykbd", NULL) ) {
printk("Keyboard: Cannot register interrupt.\n");
return -EBUSY;
}
return 0;
}
void keyboard_cleanup(void)
{
free_irq(16, NULL);
unregister_chrdev(KEYBOARD_MAJOR, "ep7312-keyboard");
return;
}
module_init(keyboard_init);
module_exit(keyboard_cleanup);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -