Linux kernel & device driver programming

Cross-Referenced Linux and Device Driver Code

[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ]
Version: [ 2.6.11.8 ] [ 2.6.25 ] [ 2.6.25.8 ] [ 2.6.31.13 ] Architecture: [ i386 ]
  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 
 25 struct 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 
 33 static int scan_jiffies=0;
 34 static struct scan_keyboard *keyboards=NULL;
 35 struct timer_list scan_timer;
 36 
 37 static 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 
 67 static 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 
 99 int 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                               
140 void __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 }
150 
  This page was automatically generated by the LXR engine.