📄 wmt_keyb.c
字号:
/*Because after interrupt handle finish, the irq will open automatically need it need close irq.
*/
if (use_delay_20 == 1){
del_timer(&delay_20);
use_delay_20 = 0;
}
else if (use_delay_100 == 1){
del_timer(&delay_100);
use_delay_100 = 0;
}
else if (use_delay_300 == 1){
del_timer(&delay_300);
use_delay_300 = 0;
}
tmp = GPLR0;
irq_state = tmp & 0x0004; //get interrupt line(GPIO2) state.
/*If the irq(the bit is 0) is still occur, it means press a key.
Otherwise it means no key pressed, it need finish this interrupt handle.
*/
if(irq_state == 0){
buf = inl(KBD_WMT_DATA);
scancode = buf & 0xFF;
/*if scancode isn't which we need, it should enable irq, and return 0*/
if((scancode!=CODE_1)&&(scancode!=CODE_2)&&(scancode!=CODE_3)&&
(scancode!=CODE_4)&&(scancode!=CODE_5)&&(scancode!=CODE_6)&&
(scancode!=CODE_7)&&(scancode!=CODE_8)&&(scancode!=CODE_9)&&
(scancode!=CODE_0)&&(scancode!=CODE_XIN)&&(scancode!=CODE_JIN)&&
(scancode!=CODE_UP)&&(scancode!=CODE_DOWN)&&
(scancode!=CODE_LEFT)&&(scancode!=CODE_RIGHT)&&
(scancode!=CODE_OK)&&(scancode!=CODE_CANCEL)&&
(scancode!=CODE_LISTEN)&&(scancode!=CODE_SWITCH)&&
(scancode!=MOUSE_OK)&&(scancode!=MOUSE_LEFT)&&
(scancode!=MOUSE_RIGHT)&&(scancode!=MOUSE_UP)&&
(scancode!=MOUSE_DOWN)&&(scancode!=MOUSE_UPLEFT)&&
(scancode!=MOUSE_UPRIGHT)&&(scancode!=MOUSE_DOWNLEFT)&&
(scancode!=MOUSE_DOWNRIGHT)){
#ifdef DEBUG_KBD
printk("The key isn't what we need, it should return right now.\n");
#endif
tmp = GFER0;
GFER0 = tmp |0x0004; //open irq;
handling_interrupt = 0;
return 0;
}
/*If twice press isn't the same key, save current key, and eliminate tingle again.
And if they are the same key, it means press a effective key, handle it.
*/
if (scancode != prev_scancode){
prev_scancode = scancode;
init_timer(&delay_20);
delay_20.expires = jiffies + 2;
delay_20.function = wmt_handle_kbd2_event;
delay_20.data = 0;
add_timer(&delay_20);
use_delay_20 = 1;
return 0;
}
#ifdef DEBUG_KBD
printk("after eliminate tingle, scancode is %x, it need send to upper layer. \n",scancode);
#endif
if ((scancode == MOUSE_OK)||(scancode == MOUSE_UP)||
(scancode == MOUSE_DOWN)||(scancode == MOUSE_LEFT)||
(scancode == MOUSE_RIGHT)||(scancode == MOUSE_UPLEFT)||
(scancode == MOUSE_UPRIGHT)||(scancode == MOUSE_DOWNLEFT)||
(scancode == MOUSE_DOWNRIGHT)){
#ifdef DEBUG_KBD
printk("It is mouse key, it need translate into mouse message.\n");
#endif
wmt_handle_mouse_event(scancode);
if (scancode != MOUSE_OK){
init_timer(&delay_100);
delay_100.expires = jiffies + 10;
delay_100.function = wmt_handle_kbd2_event;
delay_100.data = 0;
add_timer(&delay_100);
use_delay_100 = 1;
return 0;
}
else{
init_timer(&delay_300);
delay_300.expires = jiffies + 30;
delay_300.function = wmt_handle_kbd2_event;
delay_300.data = 0;
add_timer(&delay_300);
use_delay_300 = 1;
return 0;
}
}
else{
#ifdef DEBUG_KBD
printk("It is keyboard key, it need put into tty buffer.\n");
#endif
wmt_handle_keyboard_event(scancode);
/* Finish handle this press key, delay 300ms to handle next key.*/
init_timer(&delay_300);
delay_300.expires = jiffies + 30;
delay_300.function = wmt_handle_kbd2_event;
delay_300.data = 0;
add_timer(&delay_300);
use_delay_300 = 1;
return 0;
}
}
tmp = GFER0;
GFER0 = tmp | 0x0004; //open irq;
handling_interrupt = 0;
return 0;
}
static void wmt_keyboard_interrupt(int irq, void *dev_id, struct pt_regs *regs)
{
unsigned long flags;
#ifdef CONFIG_VT
kbd_pt_regs = regs;
#endif
spin_lock_irqsave(&kbd_controller_lock, flags);
wmt_handle_kbd_event();
spin_unlock_irqrestore(&kbd_controller_lock, flags);
}
/*
* send_data sends a character to the keyboard and waits
* for an acknowledge, possibly retrying if asked to. Returns
* the success status.
*
* Don't use 'jiffies', so that we don't depend on interrupts
*/
void wmt_leds(unsigned char leds)
{
if (kbd_exists) {
kbd_exists = 0;
}
}
/*
* Test the keyboard interface. We basically check to make sure that
* we can drive each line to the keyboard independently of each other.
*/
int __init wmt_kbd_init_hw(void)
{
//unsigned int tmp;
/*
tmp = GPDR0;
GPDR0 = tmp & ~(0x0004); //configure GPIO2 become input.
#ifdef DEBUG_KBD
printk(KERN_DEBUG "after configure, GPDR0 is %x \n",GPDR0);
#endif
tmp = GFER0;
GFER0 = tmp | 0x0004; //configure GPIO2 become falling-edge detect.
#ifdef DEBUG_KBD
printk(KERN_DEBUG "after configure, GFER0 is %x \n",GFER0);
#endif
tmp = GRER0;
GRER0 = tmp & ~(0x0004); //disable GPIO2 rasing-edge detect.
#ifdef DEBUG_KBD
printk(KERN_DEBUG "after configure, GRER0 is %x \n",GRER0);
#endif
*/
set_GPIO_IRQ_edge(2, GPIO_FALLING_EDGE); //set GPIO2 as interrup source.
wmt_mouse_init();
k_setkeycode = wmt_setkeycode;
k_getkeycode = wmt_getkeycode;
k_translate = wmt_translate;
k_unexpected_up = wmt_unexpected_up;
k_leds = wmt_leds;
#ifdef CONFIG_MAGIC_SYSRQ
k_sysrq_xlate = wmt_sysrq_xlate;
k_sysrq_key = 0x54;
#endif
/* Ok, finally allocate the IRQ, and off we go.. */
if (request_irq(KEYBOARD_IRQ, wmt_keyboard_interrupt, 0, "keyboard", NULL)){
printk("init keyboard failed.\n");
return -EBUSY;
}
#ifdef DEBUG_KBD
printk("Init keyboard successful.\n");
#endif
return 0;
}
static inline void wmt_handle_mouse_event(unsigned char scancode)
{
int button = 0;
int dx = 0;
int dy = 0;
static int old_scancode;
static int press_number;
static int time;
static int oldtime;
int interval_time;
add_mouse_randomness(scancode);
time = jiffies;
if (old_scancode == scancode){
interval_time = time - oldtime;
//if press the same key in a short time, we need accelerate mouse move.
if(interval_time<50){
press_number = press_number + 1;
if (press_number >= MOVE_MAX)
press_number = MOVE_MAX;
}
else
press_number = 0; //if time is too long, it needn't accelerate mouse move.
}
else
press_number = 0;
oldtime = time;
if (scancode == MOUSE_OK){
button = 0x01; //means left button down.
press_number = 0;
}
else if (scancode == MOUSE_UP)
dy = MOVE_FIRST+MOVE_LEN*press_number;
else if (scancode == MOUSE_DOWN){
/*
It will make dy become a unsigned char when transfer to uppre layre,
And the dy as a negative number will become a big int number. So we need
set button to notify upper layer that it need dy-256 to get the negative number.
*/
dy = -1*MOVE_FIRST-MOVE_LEN*press_number;
button = button + 32;
}
else if (scancode == MOUSE_LEFT){
dx = -1*MOVE_FIRST-MOVE_LEN*press_number;
button = button + 16;
}
else if (scancode == MOUSE_RIGHT)
dx = MOVE_FIRST+MOVE_LEN*press_number;
else if (scancode == MOUSE_UPLEFT){
dx = -1*MOVE_FIRST-MOVE_LEN*press_number;
button = button + 16;
dy = MOVE_FIRST+MOVE_LEN*press_number;
}
else if (scancode == MOUSE_UPRIGHT){
dx = MOVE_FIRST+MOVE_LEN*press_number;
dy = MOVE_FIRST+MOVE_LEN*press_number;
}
else if (scancode == MOUSE_DOWNLEFT){
dx = -1*MOVE_FIRST-MOVE_LEN*press_number;
button = button + 16;
dy = -1*MOVE_FIRST-MOVE_LEN*press_number;
button = button + 32;
}
else if (scancode == MOUSE_DOWNRIGHT){
dx = MOVE_FIRST+MOVE_LEN*press_number;
dy = -1*MOVE_FIRST-MOVE_LEN*press_number;
button = button + 32;
}
old_scancode = scancode;
if (aux_count) {
int head = queue->head;
queue->buf[head] = button;
head = (head + 1) & (AUX_BUF_SIZE-1);
queue->buf[head] = dx;
head = (head + 1) & (AUX_BUF_SIZE-1);
queue->buf[head] = dy;
head = (head + 1) & (AUX_BUF_SIZE-1);
/*
Because in our WMT system, it just occurs the key-down, and the upper
layer need key-down and key-down. And when press mouse left button
down, it need add a message of mouse left buuton up.
*/
if (scancode == MOUSE_OK){
queue->buf[head] = 0; //means left button up
head = (head + 1) & (AUX_BUF_SIZE-1);
queue->buf[head] = dx;
head = (head + 1) & (AUX_BUF_SIZE-1);
queue->buf[head] = dy;
head = (head + 1) & (AUX_BUF_SIZE-1);
}
if (head != queue->tail) {
queue->head = head;
kill_fasync(&queue->fasync, SIGIO, POLL_IN);
wake_up_interruptible(&queue->proc_list);
}
}
}
static unsigned char get_from_queue(void)
{
unsigned char result;
unsigned long flags;
spin_lock_irqsave(&kbd_controller_lock, flags);
result = queue->buf[queue->tail];
queue->tail = (queue->tail + 1) & (AUX_BUF_SIZE - 1);
spin_unlock_irqrestore(&kbd_controller_lock, flags);
return result;
}
static inline int queue_empty(void)
{
return queue->head == queue->tail;
}
static int fasync_mouse(int fd, struct file *filp, int on)
{
int retval;
retval = fasync_helper(fd, filp, on, &queue->fasync);
if (retval < 0)
return retval;
return 0;
}
/*
* Random magic cookie for the aux device
*/
#define AUX_DEV ((void *)queue)
static int release_mouse(struct inode *inode, struct file *file)
{
fasync_mouse(-1, file, 0);
if (--aux_count) {
return 0;
}
return 0;
}
/*
* Install interrupt handler.
* Enable auxiliary device.
*/
static int open_mouse(struct inode *inode, struct file *file)
{
if (aux_count++) {
return 0;
}
queue->head = queue->tail = 0; /* Flush input queue */
return 0;
}
/*
* Put bytes from input queue to buffer.
*/
static ssize_t
read_mouse(struct file *file, char *buffer, size_t count, loff_t * ppos)
{
DECLARE_WAITQUEUE(wait, current);
ssize_t i = count;
unsigned char c;
if (queue_empty()) {
if (file->f_flags & O_NONBLOCK)
return -EAGAIN;
add_wait_queue(&queue->proc_list, &wait);
repeat:
set_current_state(TASK_INTERRUPTIBLE);
if (queue_empty() && !signal_pending(current)) {
schedule();
goto repeat;
}
current->state = TASK_RUNNING;
remove_wait_queue(&queue->proc_list, &wait);
}
while (i > 0 && !queue_empty()) {
c = get_from_queue();
put_user(c, buffer++);
i--;
}
if (count - i) {
file->f_dentry->d_inode->i_atime = CURRENT_TIME;
return count - i;
}
if (signal_pending(current))
return -ERESTARTSYS;
return 0;
}
/*
* Write to the aux device.
*/
static ssize_t
write_mouse(struct file *file, const char *buffer, size_t count,
loff_t * ppos)
{
ssize_t retval = 0;
if (count) {
ssize_t written = 0;
if (count > 32)
count = 32; /* Limit to 32 bytes. */
do {
char c;
get_user(c, buffer++);
written++;
}
while (--count);
retval = -EIO;
if (written) {
retval = written;
file->f_dentry->d_inode->i_mtime = CURRENT_TIME;
}
}
return retval;
}
static unsigned int mouse_poll(struct file *file, poll_table * wait)
{
poll_wait(file, &queue->proc_list, wait);
if (!queue_empty())
return POLLIN | POLLRDNORM;
return 0;
}
struct file_operations wmtmouse_fops = {
read: read_mouse,
write: write_mouse,
poll: mouse_poll,
open: open_mouse,
release: release_mouse,
fasync: fasync_mouse,
};
/*
* Initialize driver.
*/
static struct miscdevice wmt_mouse = {
8, "wmtmouse", &wmtmouse_fops
};
static int __init wmt_mouse_init(void)
{
int retval;
if ((retval = misc_register(&wmt_mouse))){
printk("wmt_mouse register failed.\n");
return retval;
}
#ifdef DEBUG_KBD
printk("wmt_mouse register successful.\n");
#endif
queue = (struct aux_queue *) kmalloc(sizeof(*queue), GFP_KERNEL);
if (queue == NULL) {
printk(KERN_ERR "wmtmouse_init(): out of memory\n");
misc_deregister(&wmt_mouse);
return -ENOMEM;
}
memset(queue, 0, sizeof(*queue));
queue->head = queue->tail = 0;
init_waitqueue_head(&queue->proc_list);
return 0;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -