Root/cap_keyboard/src/teclado/cap_keyboard.c

1/*Atmel QT-60486 drivers
2 *Sistemas Embebidos
3 *UNAL
4 *Authors: amasprillav,jsbuendiag,jamonsalveh
5 *Year: 2010-II*/
6
7#include <linux/module.h> /* Needed by all modules */
8#include <linux/kernel.h> /* Needed for KERN_INFO */
9#include <linux/ioport.h>
10#include <linux/device.h>
11#include <linux/interrupt.h> /* We want an interrupt */
12#include <linux/irq.h> /* We want an interrupt */
13#include <linux/platform_device.h>
14#include <linux/fs.h>
15#include <asm/delay.h>
16#include <asm/uaccess.h>
17#include <asm/io.h>
18#include <linux/gpio.h>
19#include <asm/mach-jz4740/gpio.h>
20#include <linux/input.h>
21#define FPGA_IRQ_PIN JZ_GPIO_PORTC(15) //pin del irq
22#define FPGA_BASE 0xB5000000 //direccion virtual base de la FPGA
23
24MODULE_AUTHOR("amasprillav <amasprillav at unal dot edu dot co");
25MODULE_DESCRIPTION("Atmel QT60486 Capacitive Keyboard Driver");
26MODULE_LICENSE("GPL");
27
28static unsigned int fn=0, anterior;//variables globales para indicar si la tecla fn ha sido oprimida
29//y para controlar que no se escriba una tecla mas de una vez respectivamente
30
31//arreglo que posee el keycode de las teclas posibles
32static unsigned int cap_keycode[] = {
33    KEY_1, KEY_2, KEY_3, KEY_4, KEY_5, KEY_6, KEY_7, KEY_8, KEY_9, KEY_0,
34    KEY_Q, KEY_W, KEY_E, KEY_R, KEY_T, KEY_Y, KEY_U, KEY_I, KEY_O, KEY_P,
35    KEY_A, KEY_S, KEY_D, KEY_F, KEY_G, KEY_H, KEY_J, KEY_K, KEY_L, KEY_BACKSPACE,
36    KEY_ESC, KEY_Z, KEY_X, KEY_C, KEY_V, KEY_B, KEY_N, KEY_M, KEY_EQUAL, KEY_ENTER,
37    KEY_TAB, KEY_LEFTBRACE, KEY_RIGHTBRACE, KEY_COMMA, KEY_DOT, KEY_BACKSLASH, KEY_SLASH, KEY_APOSTROPHE, KEY_UP, KEY_SEMICOLON,
38    KEY_LEFTSHIFT, KEY_RIGHTALT, KEY_LEFTALT, KEY_SPACE, KEY_RIGHTCTRL, KEY_LEFT, KEY_DOWN, KEY_RIGHT, KEY_MINUS, KEY_RIGHTALT
39};
40
41unsigned int irq;//variable global del numero del irq asignado
42
43//funcion del codificador normal
44static unsigned int keydecode(unsigned char valor){
45    unsigned int salida;//variable la cual tiene el valor del keycode para ser usada en las demas funciones
46    //codificador para cuando se oprime una tecla normalmente
47    switch(valor){
48        case 150:salida=KEY_Q;break;
49        case 200:salida=KEY_W;break;
50        case 170:salida=KEY_E;break;
51        case 244:salida=KEY_R;break;
52        case 22:salida=KEY_T;break;
53        case 72:salida=KEY_Y;break;
54        case 41:salida=KEY_U;break;
55        case 119:salida=KEY_I;break;
56        case 149:salida=KEY_O;break;
57        case 203:salida=KEY_P;break;
58        case 116:salida=KEY_A;break;
59        case 169:salida=KEY_S;break;
60        case 104:salida=KEY_D;break;
61        case 54:salida=KEY_F;break;
62        case 212:salida=KEY_G;break;
63        case 138:salida=KEY_H;break;
64        case 235:salida=KEY_J;break;
65        case 181:salida=KEY_K;break;
66        case 87:salida=KEY_L;break;
67        case 9:salida=KEY_BACKSPACE;break;
68        case 42:salida=KEY_ESC;break;
69        case 247:salida=KEY_Z;break;
70        case 55:salida=KEY_X;break;
71        case 105:salida=KEY_C;break;
72        case 139:salida=KEY_V;break;
73        case 213:salida=KEY_B;break;
74        case 180:salida=KEY_N;break;
75        case 234:salida=KEY_M;break;
76        case 8:salida=KEY_EQUAL;break;
77        case 86:salida=KEY_ENTER;break;
78        case 75:salida=KEY_TAB;break;
79        case 21:salida=KEY_LEFTBRACE;break;
80        case 245:salida=KEY_RIGHTBRACE;break;
81        case 171:salida=KEY_COMMA;break;
82        case 73:salida=KEY_DOT;break;
83        case 23:salida=KEY_BACKSLASH;break;
84        case 118:salida=KEY_SLASH;break;
85        case 40:salida=KEY_APOSTROPHE;break;
86        case 202:salida=KEY_UP;break;
87        case 137:salida=KEY_LEFTSHIFT;break;
88        case 215:salida=KEY_RIGHTALT;break;
89        case 53:salida=KEY_LEFTALT;break;
90        case 107:salida=KEY_SPACE;break;
91        case 10:salida=KEY_RIGHTCTRL;break;
92        case 84:salida=KEY_LEFT;break;
93        case 182:salida=KEY_DOWN;break;
94        case 232:salida=KEY_RIGHT;break;
95        default: salida=0;break;
96        }
97
98
99
100
101
102return salida;
103}
104
105
106//funcion del codificador FN
107static unsigned int keydecodefn(unsigned char valor){
108    unsigned int salida; //variable la cual tiene el valor del keycode para ser usada en las demas funciones
109    //codificador para cuando se oprime una tecla una vez se ha oprimida la tecla FN
110    switch(valor){
111        case 150:salida=KEY_1;break;
112        case 200:salida=KEY_2;break;
113        case 170:salida=KEY_3;break;
114        case 244:salida=KEY_4;break;
115        case 22:salida=KEY_5;break;
116        case 72:salida=KEY_6;break;
117        case 41:salida=KEY_7;break;
118        case 119:salida=KEY_8;break;
119        case 149:salida=KEY_9;break;
120        case 203:salida=KEY_P;break;
121        case 116:salida=KEY_7;break;
122        case 169:salida=KEY_8;break;
123        case 104:salida=KEY_9;break;
124        case 54:salida=KEY_0;break;
125        case 212:salida=KEY_MINUS;break;
126        case 138:salida=KEY_H;break;
127        case 235:salida=KEY_4;break;
128        case 181:salida=KEY_5;break;
129        case 87:salida=KEY_6;break;
130        case 9:salida=KEY_BACKSPACE;break;
131        case 42:salida=KEY_ESC;break;
132        case 247:salida=KEY_Z;break;
133        case 55:salida=KEY_X;break;
134        case 105:salida=KEY_C;break;
135        case 139:salida=KEY_V;break;
136        case 213:salida=KEY_B;break;
137        case 180:salida=KEY_1;break;
138        case 234:salida=KEY_2;break;
139        case 8:salida=KEY_3;break;
140        case 86:salida=KEY_ENTER;break;
141        case 75:salida=KEY_TAB;break;
142        case 21:salida=KEY_LEFTBRACE;break;
143        case 245:salida=KEY_RIGHTBRACE;break;
144        case 171:salida=KEY_COMMA;break;
145        case 73:salida=KEY_DOT;break;
146        case 23:salida=KEY_BACKSLASH;break;
147        case 118:salida=KEY_0;break;
148        case 40:salida=KEY_MINUS;break;
149        case 202:salida=KEY_UP;break;
150        case 137:salida=KEY_LEFTSHIFT;break;
151        case 215:salida=KEY_RIGHTALT;break;
152        case 53:salida=KEY_LEFTALT;break;
153        case 107:salida=KEY_SPACE;break;
154        case 10:salida=KEY_RIGHTCTRL;break;
155        case 84:salida=KEY_LEFT;break;
156        case 182:salida=KEY_DOWN;break;
157        case 232:salida=KEY_RIGHT;break;
158        default: salida=0;break;
159        }
160
161
162return salida;
163}
164
165
166
167
168static struct input_dev *cap_keyboard;//estructura que define el dispositivo de entrada
169
170static irqreturn_t irq_handler(int irq, void *dev_id){ //funcion que atiende las interrupciones y define las acciones a tomar
171
172      if(inb(FPGA_BASE)==anterior){ //condicional para deshabilitar la multiple lectura de una tecla
173        return IRQ_HANDLED;
174      }
175
176      else if(inb(FPGA_BASE)==85){ //condicional para evitar que se escriba algo del valor mandado por defecto del integrado
177          anterior=inb(FPGA_BASE);
178        return IRQ_HANDLED;
179      }
180
181
182    else if (inb(FPGA_BASE)==148){ //condicional para activacion de la tecla FN
183
184        input_sync(cap_keyboard);
185         anterior=inb(FPGA_BASE);
186        fn=1;
187           return IRQ_HANDLED;}
188
189    //condicional para evaluar la activacion de las teclas alt, alt gr, ctrl y shift
190    else if ((inb(FPGA_BASE)==137) || (inb(FPGA_BASE)==215) || (inb(FPGA_BASE)==10) || (inb(FPGA_BASE)==53)){
191        input_report_key(cap_keyboard,keydecode(inb(FPGA_BASE)),1);//funcion que detecta la tecla y la pone en 1 o 0 logico
192        input_sync(cap_keyboard); //sincronizar el buffer tty con la ultima tecla oprimida
193        anterior=inb(FPGA_BASE); //asignacion a la variable global de la ultima tecla oprimida
194        return IRQ_HANDLED; //retorno de interrupcion controlada
195      }
196
197    else if(fn!=1) { //condicional para detectar la tecla ya sea en modo normal o con combinacion de ctrl, alt o shift
198        input_report_key(cap_keyboard,keydecode(inb(FPGA_BASE)),1);
199            input_report_key(cap_keyboard,KEY_LEFTSHIFT,0);
200            input_report_key(cap_keyboard,KEY_RIGHTALT,0);
201            input_report_key(cap_keyboard,KEY_LEFTALT,0);
202            input_report_key(cap_keyboard,KEY_RIGHTCTRL,0);
203        input_report_key(cap_keyboard,keydecode(inb(FPGA_BASE)),0);
204        input_sync(cap_keyboard);
205        anterior=inb(FPGA_BASE);
206           return IRQ_HANDLED;}
207
208    //condicional que indica que hacer en el caso de haber oprimido FN y otra letra. La mayoria son numeros
209    else if ((inb(FPGA_BASE)==41) ||(inb(FPGA_BASE)==119) ||(inb(FPGA_BASE)==149) ||(inb(FPGA_BASE)==235) ||(inb(FPGA_BASE)==181) ||(inb(FPGA_BASE)==87) ||(inb(FPGA_BASE)==180) ||(inb(FPGA_BASE)==234) ||(inb(FPGA_BASE)==8) ||(inb(FPGA_BASE)==118) ||(inb(FPGA_BASE)==40)){
210    
211        input_report_key(cap_keyboard,KEY_LEFTSHIFT,0);
212            input_report_key(cap_keyboard,KEY_RIGHTALT,0);
213            input_report_key(cap_keyboard,KEY_RIGHTCTRL,0);
214            input_report_key(cap_keyboard,KEY_LEFTALT,0);
215        input_report_key(cap_keyboard,keydecodefn(inb(FPGA_BASE)),1);
216        input_report_key(cap_keyboard,keydecodefn(inb(FPGA_BASE)),0);
217        input_sync(cap_keyboard);
218        fn=0;
219        anterior=inb(FPGA_BASE);
220           return IRQ_HANDLED;}
221    
222    //condicional que indica que hacer en el caso de haber oprimido FN y otra letra. Estas son teclas que requieren de shift para ilustrarlas
223    else
224         {input_report_key(cap_keyboard,KEY_LEFTSHIFT,1);
225            input_report_key(cap_keyboard,KEY_RIGHTALT,0);
226            input_report_key(cap_keyboard,KEY_RIGHTCTRL,0);
227            input_report_key(cap_keyboard,KEY_LEFTALT,0);
228        input_report_key(cap_keyboard,keydecodefn(inb(FPGA_BASE)),1);
229        input_report_key(cap_keyboard,keydecodefn(inb(FPGA_BASE)),0);
230         input_report_key(cap_keyboard,KEY_LEFTSHIFT,0);
231        input_sync(cap_keyboard);
232        fn=0;
233         anterior=inb(FPGA_BASE);
234           return IRQ_HANDLED;}
235
236      return IRQ_HANDLED;
237}
238
239static int __init atakbd_init(void)//funcion de inicializacion del teclado
240{
241    int i, error,res;
242
243
244    cap_keyboard = input_allocate_device(); // ubica memoria para el dispositivo de entrada
245    if (!cap_keyboard)
246        return -ENOMEM;
247
248    cap_keyboard->name = "CAP Keyboard"; //asignacion de datos del teclado
249    cap_keyboard->phys = "capkey/input0"; //direccion fisica
250    cap_keyboard->id.bustype = BUS_HOST;//tipo de bus
251    cap_keyboard->id.vendor = 0x0010;
252    cap_keyboard->id.product = 0x0001;
253    cap_keyboard->id.version = 0x001;
254
255    cap_keyboard->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_REP);
256    cap_keyboard->keycode = cap_keycode;//asignacion del arreglo del keycode
257    cap_keyboard->keycodesize = sizeof(unsigned char);
258    cap_keyboard->keycodemax = ARRAY_SIZE(cap_keycode);
259
260    for (i = 0; i <= 60; i++) { //funcion que ubica las 48 teclas (keycode) en memoria
261        set_bit(cap_keycode[i], cap_keyboard->keybit);
262    }
263
264    error = input_register_device(cap_keyboard);//indica al sistema el nuevo dispositivo de entrada
265    if (error) {
266        input_free_device(cap_keyboard);
267        return error;
268    }
269
270        irq = gpio_to_irq(FPGA_IRQ_PIN);//asigna el numero del irq al pin fisico del procesador
271  
272        res = request_irq(irq, irq_handler, IRQF_DISABLED | IRQF_TRIGGER_RISING, "cap_keyboard", NULL); // asignar el valor del irq y la funcion que lo utiliza
273    return 0;
274}
275
276static void __exit atakbd_exit(void)
277{
278    input_unregister_device(cap_keyboard);//libera los recursos utilizados por el dispositivo
279    free_irq(irq, NULL);
280}
281
282module_init(atakbd_init);
283module_exit(atakbd_exit);
284

Archive Download this file

Branches:
master



interactive