164 lines
		
	
	
		
			3.5 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			164 lines
		
	
	
		
			3.5 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
| /*
 | |
| Copyright (C) 2015-2019 The University of Notre Dame
 | |
| This software is distributed under the GNU General Public License.
 | |
| See the file LICENSE for details.
 | |
| */
 | |
| 
 | |
| #include "console.h"
 | |
| #include "ioports.h"
 | |
| #include "interrupt.h"
 | |
| #include "kernel/ascii.h"
 | |
| #include "kernelcore.h"
 | |
| #include "event_queue.h"
 | |
| 
 | |
| #define KEYBOARD_PORT 0x60
 | |
| 
 | |
| #define KEYMAP_SHIFT    1
 | |
| #define KEYMAP_ALT      2
 | |
| #define KEYMAP_CTRL     3
 | |
| #define KEYMAP_CAPSLOCK 4
 | |
| #define KEYMAP_NUMLOCK  5
 | |
| #define KEYMAP_ALPHA    6
 | |
| #define KEYMAP_NUMPAD   8
 | |
| #define KEYMAP_ALTGR    9
 | |
| 
 | |
| /* sent before certain keys such as up, down, left, or right. */
 | |
| #define KEYCODE_EXTRA (uint8_t)0xE0
 | |
| #define KEYCODE_UP    (uint8_t)0x48
 | |
| #define KEYCODE_DOWN  (uint8_t)0x42
 | |
| #define KEYCODE_LEFT  (uint8_t)0x4B
 | |
| #define KEYCODE_RIGHT (uint8_t)0x4D
 | |
| 
 | |
| #define BUFFER_SIZE 256
 | |
| 
 | |
| struct keymap {
 | |
| 	char normal;
 | |
| 	char shifted;
 | |
| 	char ctrled;
 | |
| 	char special;
 | |
| };
 | |
| 
 | |
| static struct keymap keymap[] = {
 | |
| #include "keymap.de.pc.c"
 | |
| };
 | |
| 
 | |
| static int shift_mode = 0;
 | |
| static int alt_mode = 0;
 | |
| static int altgr_mode = 0;
 | |
| static int ctrl_mode = 0;
 | |
| static int capslock_mode = 0;
 | |
| static int numlock_mode = 0;
 | |
| 
 | |
| static void keyboard_interrupt_l2( uint8_t code )
 | |
| {
 | |
| 	int direction;
 | |
| 	int event;
 | |
| 
 | |
| 	if(code & 0x80) {
 | |
| 		direction = 0;
 | |
| 		event = EVENT_KEY_UP;
 | |
| 		code = code & 0x7f;
 | |
| 	} else {
 | |
| 		direction = 1;
 | |
| 		event = EVENT_KEY_DOWN;
 | |
| 	}
 | |
| 
 | |
| 	struct keymap *k = &keymap[code];
 | |
| 	if(k->special == KEYMAP_SHIFT) {
 | |
| 		shift_mode = direction;
 | |
| 	} else if(k->special == KEYMAP_ALT) {
 | |
| 		alt_mode = direction;
 | |
| 	} else if(k->special == KEYMAP_ALTGR) {
 | |
|     // @blab+ ALTGR hack
 | |
| 		altgr_mode = direction;
 | |
| 	} else if(k->special == KEYMAP_CTRL) {
 | |
| 		ctrl_mode = direction;
 | |
| 	} else if(k->special == KEYMAP_CAPSLOCK) {
 | |
| 		if(direction == 0) capslock_mode = !capslock_mode;
 | |
| 	} else if(k->special == KEYMAP_NUMLOCK) {
 | |
| 		if(direction == 0) numlock_mode = !numlock_mode;
 | |
| 	} else {
 | |
| 		if(direction && ctrl_mode && alt_mode && k->normal == ASCII_DEL) {
 | |
| 			reboot();
 | |
| 		} else if(capslock_mode) {
 | |
| 			if(k->special==KEYMAP_ALPHA && !shift_mode) {
 | |
| 				event_queue_post_root(event,k->shifted,0,0);
 | |
| 			} else {
 | |
| 				event_queue_post_root(event,k->normal,0,0);
 | |
| 			}	
 | |
| 		} else if(numlock_mode) {
 | |
| 			if(k->special==KEYMAP_NUMPAD && !shift_mode) {
 | |
| 				event_queue_post_root(event,k->shifted,0,0);
 | |
| 			} else {
 | |
| 				event_queue_post_root(event,k->normal,0,0);
 | |
| 			}	
 | |
| 		} else if(shift_mode) {
 | |
| 			event_queue_post_root(event,k->shifted,0,0);
 | |
| 		} else if(ctrl_mode) {
 | |
| 			event_queue_post_root(event,k->ctrled,0,0);
 | |
| 		} else if(altgr_mode) {
 | |
| 		  // @blab+ ALTGR hack
 | |
| 			event_queue_post_root(event,k->special,0,0);
 | |
| 		} else {
 | |
| 			event_queue_post_root(event,k->normal,0,0);
 | |
| 		}
 | |
| 	}
 | |
| }
 | |
| 
 | |
| static int expect_extra = 0;
 | |
| 
 | |
| static void keyboard_interrupt(int i, int intr_code)
 | |
| {
 | |
| 	uint8_t code = inb(KEYBOARD_PORT);
 | |
| 	uint8_t c = KEY_INVALID;
 | |
| 
 | |
|   // printf("[%x]",code);
 | |
| 
 | |
| 	if(code == KEYCODE_EXTRA) {
 | |
| 		expect_extra = 1;
 | |
| 		return;
 | |
| 	} else if(expect_extra) {
 | |
| 		expect_extra = 0;
 | |
| 		switch(code) {
 | |
| 		  // @blab+ ALTGR hack
 | |
| 		  case 0x38:
 | |
| 		  case 0xb8:
 | |
| 		    // keymap: use next reserved row (normally nulled)
 | |
| 		    // {KEY_INVALID, KEY_INVALID, KEY_INVALID, KEYMAP_ALT},#
 | |
| 		    // ..
 | |
|         // {KEY_INVALID, KEY_INVALID, KEY_INVALID, KEYMAP_ALTGR},
 | |
| 		    c = code+3;
 | |
| 		    break;
 | |
| 			case KEYCODE_UP:
 | |
| 				c = KEY_UP;
 | |
| 				break;
 | |
| 			case KEYCODE_DOWN:
 | |
| 				c = KEY_DOWN;
 | |
| 				break;
 | |
| 			case KEYCODE_LEFT:
 | |
| 				c = KEY_LEFT;
 | |
| 				break;
 | |
| 			case KEYCODE_RIGHT:
 | |
| 				c = KEY_RIGHT;
 | |
| 				break;
 | |
| 			default:
 | |
| 				return;
 | |
| 		}
 | |
| 	} else {
 | |
| 		c = code;
 | |
| 	}
 | |
| 
 | |
| 	keyboard_interrupt_l2(c);
 | |
| }
 | |
| 
 | |
| void keyboard_init()
 | |
| {
 | |
| 	interrupt_register(33, keyboard_interrupt);
 | |
| 	interrupt_enable(33);
 | |
| 	printf("keyboard: ready\n");
 | |
| }
 | |
| 
 | |
| 
 | |
| 
 | |
| 
 |