1/* 2 * $Id: scan_keyb.c,v 1.1.1.1 2008/10/15 03:26:28 james26_jang Exp $ 3 * Copyright (C) 2000 YAEGASHI Takeshi 4 * Generic scan keyboard driver 5 */ 6 7#include <linux/spinlock.h> 8#include <linux/sched.h> 9#include <linux/interrupt.h> 10#include <linux/tty.h> 11#include <linux/mm.h> 12#include <linux/signal.h> 13#include <linux/init.h> 14#include <linux/kbd_ll.h> 15#include <linux/delay.h> 16#include <linux/random.h> 17#include <linux/poll.h> 18#include <linux/miscdevice.h> 19#include <linux/slab.h> 20#include <linux/kbd_kern.h> 21#include <linux/timer.h> 22 23#define SCANHZ (HZ/20) 24 25struct scan_keyboard { 26 struct scan_keyboard *next; 27 int (*scan)(unsigned char *buffer); 28 const unsigned char *table; 29 unsigned char *s0, *s1; 30 int length; 31}; 32 33static int scan_jiffies=0; 34static struct scan_keyboard *keyboards=NULL; 35struct timer_list scan_timer; 36 37static void check_kbd(const unsigned char *table, 38 unsigned char *new, unsigned char *old, int length) 39{ 40 int need_tasklet_schedule=0; 41 unsigned int xor, bit; 42 43 while(length-->0) { 44 if((xor=*new^*old)==0) { 45 table+=8; 46 } 47 else { 48 for(bit=0x01; bit<0x100; bit<<=1) { 49 if(xor&bit) { 50 handle_scancode(*table, !(*new&bit)); 51 need_tasklet_schedule=1; 52 } 53 table++; 54 } 55 } 56 new++; old++; 57 } 58 59 if(need_tasklet_schedule) 60 tasklet_schedule(&keyboard_tasklet); 61} 62 63 64static void scan_kbd(unsigned long dummy) 65{ 66 struct scan_keyboard *kbd; 67 68 scan_jiffies++; 69 70 for(kbd=keyboards; kbd!=NULL; kbd=kbd->next) { 71 if(scan_jiffies&1) { 72 if(!kbd->scan(kbd->s0)) 73 check_kbd(kbd->table, 74 kbd->s0, kbd->s1, kbd->length); 75 else 76 memcpy(kbd->s0, kbd->s1, kbd->length); 77 } 78 else { 79 if(!kbd->scan(kbd->s1)) 80 check_kbd(kbd->table, 81 kbd->s1, kbd->s0, kbd->length); 82 else 83 memcpy(kbd->s1, kbd->s0, kbd->length); 84 } 85 86 } 87 88 init_timer(&scan_timer); 89 scan_timer.expires = jiffies + SCANHZ; 90 scan_timer.data = 0; 91 scan_timer.function = scan_kbd; 92 add_timer(&scan_timer); 93} 94 95 96int register_scan_keyboard(int (*scan)(unsigned char *buffer), 97 const unsigned char *table, 98 int length) 99{ 100 struct scan_keyboard *kbd; 101 102 kbd = kmalloc(sizeof(struct scan_keyboard), GFP_KERNEL); 103 if (kbd == NULL) 104 goto error_out; 105 106 kbd->scan=scan; 107 kbd->table=table; 108 kbd->length=length; 109 110 kbd->s0 = kmalloc(length, GFP_KERNEL); 111 if (kbd->s0 == NULL) 112 goto error_free_kbd; 113 114 kbd->s1 = kmalloc(length, GFP_KERNEL); 115 if (kbd->s1 == NULL) 116 goto error_free_s0; 117 118 memset(kbd->s0, -1, kbd->length); 119 memset(kbd->s1, -1, kbd->length); 120 121 kbd->next=keyboards; 122 keyboards=kbd; 123 124 return 0; 125 126 error_free_s0: 127 kfree(kbd->s0); 128 129 error_free_kbd: 130 kfree(kbd); 131 132 error_out: 133 return -ENOMEM; 134} 135 136 137void __init scan_kbd_init(void) 138{ 139 init_timer(&scan_timer); 140 scan_timer.expires = jiffies + SCANHZ; 141 scan_timer.data = 0; 142 scan_timer.function = scan_kbd; 143 add_timer(&scan_timer); 144 145 printk(KERN_INFO "Generic scan keyboard driver initialized\n"); 146} 147