Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

at v2.6.17 149 lines 3.0 kB view raw
1/* 2 * $Id: scan_keyb.c,v 1.2 2000/07/04 06:24:42 yaegashi 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#if 0 53 printk("0x%x %s\n", *table, (*new&bit)?"released":"pressed"); 54#endif 55 } 56 table++; 57 } 58 } 59 new++; old++; 60 } 61 62 if(need_tasklet_schedule) 63 tasklet_schedule(&keyboard_tasklet); 64} 65 66 67static void scan_kbd(unsigned long dummy) 68{ 69 struct scan_keyboard *kbd; 70 71 scan_jiffies++; 72 73 for(kbd=keyboards; kbd!=NULL; kbd=kbd->next) { 74 if(scan_jiffies&1) { 75 if(!kbd->scan(kbd->s0)) 76 check_kbd(kbd->table, 77 kbd->s0, kbd->s1, kbd->length); 78 else 79 memcpy(kbd->s0, kbd->s1, kbd->length); 80 } 81 else { 82 if(!kbd->scan(kbd->s1)) 83 check_kbd(kbd->table, 84 kbd->s1, kbd->s0, kbd->length); 85 else 86 memcpy(kbd->s1, kbd->s0, kbd->length); 87 } 88 89 } 90 91 init_timer(&scan_timer); 92 scan_timer.expires = jiffies + SCANHZ; 93 scan_timer.data = 0; 94 scan_timer.function = scan_kbd; 95 add_timer(&scan_timer); 96} 97 98 99int register_scan_keyboard(int (*scan)(unsigned char *buffer), 100 const unsigned char *table, 101 int length) 102{ 103 struct scan_keyboard *kbd; 104 105 kbd = kmalloc(sizeof(struct scan_keyboard), GFP_KERNEL); 106 if (kbd == NULL) 107 goto error_out; 108 109 kbd->scan=scan; 110 kbd->table=table; 111 kbd->length=length; 112 113 kbd->s0 = kmalloc(length, GFP_KERNEL); 114 if (kbd->s0 == NULL) 115 goto error_free_kbd; 116 117 kbd->s1 = kmalloc(length, GFP_KERNEL); 118 if (kbd->s1 == NULL) 119 goto error_free_s0; 120 121 memset(kbd->s0, -1, kbd->length); 122 memset(kbd->s1, -1, kbd->length); 123 124 kbd->next=keyboards; 125 keyboards=kbd; 126 127 return 0; 128 129 error_free_s0: 130 kfree(kbd->s0); 131 132 error_free_kbd: 133 kfree(kbd); 134 135 error_out: 136 return -ENOMEM; 137} 138 139 140void __init scan_kbd_init(void) 141{ 142 init_timer(&scan_timer); 143 scan_timer.expires = jiffies + SCANHZ; 144 scan_timer.data = 0; 145 scan_timer.function = scan_kbd; 146 add_timer(&scan_timer); 147 148 printk(KERN_INFO "Generic scan keyboard driver initialized\n"); 149}