summaryrefslogblamecommitdiff
path: root/src/kernel/dev/keyboard.cpp
blob: ce8e77bc2d27594165e44db6746c5bb794b38921 (plain) (tree)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16















                                                                                                                                                          
                                                                                       










































































                                                                                                                              
                         



                                                                               

                                                          






























                                                                               
                                                             

                             
                                                            

                             
                                                             







                                                


                                              


                           



                                                                                

         














                                        
#include "keyboard.h"

#include <ui/vt.h>

int ctrlkeys[] = {
/* 0x00 */	0, KB_ESCAPE, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, KB_BACKSPACE, KB_TAB,
/* 0x10 */	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, KB_ENTER, KB_LCTRL, 0, 0,
/* 0x20 */	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, KB_LSHIFT, 0, 0, 0, 0, 0,
/* 0x30 */	0, 0, 0, 0, 0, 0, KB_RSHIFT, 0, KB_ALT, 0, KB_CAPSLOCK, KB_F1, KB_F2, KB_F3, KB_F4, KB_F5,
/* 0x40 */	KB_F6, KB_F7, KB_F8, KB_F9, KB_F10, KB_NUMLOCK, KB_SCRLLOCK, KB_KPHOME, KB_KPUP, KB_KPPGUP, 0, KB_KPLEFT, KB_KP5, KB_KPRIGHT, 0, KB_KPEND,
/* 0x50 */	KB_KPDOWN, KB_KPPGDOWN, KB_KPINS, KB_KPDEL, KB_SYSREQ, 0, 0, KB_F11, KB_F12, 0, 0, 0, 0, 0, 0, 0,
/* 0x60 */	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
/* 0x70 */	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
/* 0x80 */	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
/* 0x90 */	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, KB_ENTER, KB_RCTRL, 0, 0,
/* 0xA0 */	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
/* 0xB0 */	0, 0, 0, 0, 0, KB_KPSLASH, 0, KB_PRTSCN, KB_ALTGR, 0, 0, 0, 0, 0, 0, 0,
/* 0xC0 */	0, 0, 0, 0, 0, 0, 0, KB_HOME, KB_UP, KB_PGUP, 0, KB_LEFT, 0, KB_RIGHT, 0, KB_END,
/* 0xD0 */	KB_DOWN, KB_PGDOWN, KB_INS, KB_DEL, 0, 0, 0, 0, 0, 0, 0, KB_LSUPER, KB_RSUPER, KB_MENU, 0, 0,
/* 0xE0 */	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
/* 0xF0 */	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
};

static keymap default_km = {
	{		// normal
	/* 0x00 */	0, 0, '&', L'é', '"', '\'', '(', '-', L'è', '_', L'ç', L'à', ')', '=', 0, 0, 
	/* 0x10 */	'a', 'z', 'e', 'r', 't', 'y', 'u', 'i', 'o', 'p', '^', '$', 0, 0, 'q', 's',
	/* 0x20 */	'd', 'f', 'g', 'h', 'j', 'k', 'l', 'm', L'ù', L'²', 0, '*', 'w', 'x', 'c', 'v',
	/* 0x30 */	'b', 'n', ',', ';', ':', '!', 0, '*', 0, ' ', 0, 0, 0, 0, 0, 0,
	/* 0x40 */	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, '-', 0, 0, 0, '+', 0, 
	/* 0x50 */  0, 0, 0, 0, 0, 0, '<', 0, 0, 0, 0, 0, 0, 0, 0, 0,
	/* 0x60 */	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
	/* 0x70 */	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
	},
	{		// shift
	/* 0x00 */	0, 0, '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', L'°', '+', 0, 0, 
	/* 0x10 */	'A', 'Z', 'E', 'R', 'T', 'Y', 'U', 'I', 'O', 'P', L'¨', L'£', 0, 0, 'Q', 'S',
	/* 0x20 */	'D', 'F', 'G', 'H', 'J', 'K', 'L', 'M', '%', '~', 0, L'µ', 'W', 'X', 'C', 'V',
	/* 0x30 */	'B', 'N', '?', '.', '/', L'§', 0, '*', 0, ' ', 0, 0, 0, 0, 0, 0,
	/* 0x40 */	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, '-', 0, 0, 0, '+', 0,
	/* 0x50 */  0, 0, 0, 0, 0, 0, '>', 0, 0, 0, 0, 0, 0, 0, 0, 0,
	/* 0x60 */	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
	/* 0x70 */	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
	},
	{		// caps
	/* 0x00 */	0, 0, '&', L'É', '"', '\'', '(', '-', L'È', '_', L'Ç', L'À', ')', '=', 0, 0, 
	/* 0x10 */	'A', 'Z', 'E', 'R', 'T', 'Y', 'U', 'I', 'O', 'P', L'¨', '$', 0, 0, 'Q', 'S',
	/* 0x20 */	'D', 'F', 'G', 'H', 'J', 'K', 'L', 'M', L'Ù', L'²', 0, '*', 'W', 'X', 'C', 'V',
	/* 0x30 */	'B', 'N', ',', ';', ':', '!', 0, '*', 0, ' ', 0, 0, 0, 0, 0, 0,
	/* 0x40 */	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, '-', 0, 0, 0, '+', 0,
	/* 0x50 */  0, 0, 0, 0, 0, 0, '>', 0, 0, 0, 0, 0, 0, 0, 0, 0,
	/* 0x60 */	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
	/* 0x70 */	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
	},
	{		// alt gr
	/* 0x00 */	0, 0, L'¹', '~', '#', '{', '[', '|', '`', '\\', '^', '@', ']', '}', 0, 0, 
	/* 0x10 */	L'æ', L'«', L'€', L'¶', L'ŧ', L'←', L'↓', L'→', 
				L'ø', L'þ', L'¨', L'¤', 0, 0, '@', L'ß',
	/* 0x20 */	L'ð', L'đ', L'ŋ', L'ħ', 'j', L'ĸ', L'ł', L'µ',
			 	'^', L'¬', 0, '`', L'ł', L'»', L'¢', L'“',
	/* 0x30 */	L'”', 'n', L'´', ';', L'·', '!', 0, '*', 0, ' ', 0, 0, 0, 0, 0, 0,
	/* 0x40 */	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, '-', 0, 0, 0, '+', 0,
	/* 0x50 */  0, 0, 0, 0, 0, 0, '|', 0, 0, 0, 0, 0, 0, 0, 0, 0,
	/* 0x60 */	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
	/* 0x70 */	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
	},
	{		// shift + alt gr
	/* 0x00 */	0, 0, L'¡', L'⅛', L'£', '$', L'⅜', L'⅝', L'⅞', L'™', L'±', L'°', L'¿', L'˛', 0, 0, 
	/* 0x10 */	L'Æ', '<', L'¢', L'®', L'Ŧ', L'¥', L'↑', L'ı', L'Ø', L'Þ', L'°', L'¯', 0, 0, L'Ω', L'§',
	/* 0x20 */	L'Ð', L'ª', L'Ŋ', L'Ħ', 'J', '&', L'Ł', L'º', L'ˇ', L'¬', 0, L'˘', L'Ł', '>', L'©', L'‘',
	/* 0x30 */	L'’', 'N', L'˝', L'×', L'÷', L'˙', 0, '*', 0, ' ', 0, 0, 0, 0, 0, 0,
	/* 0x40 */	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, '-', 0, 0, 0, '+', 0,
	/* 0x50 */  0, 0, 0, 0, 0, 0, L'¦', 0, 0, 0, 0, 0, 0, 0, 0, 0,
	/* 0x60 */	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
	/* 0x70 */	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
	}
};

keyboard::keyboard(node *parent) : node(parent, FT_DEV) {
	dev_type = DT_KEYBOARD;

	km = &default_km;
	num = true;
	caps = scroll = false;
	shift = altgr = alt = ctrl = false;
}

void keyboard::handle(int scancode, bool pressed) {
	keypress kp;
	kp.scancode = scancode;
	kp.pressed = pressed;
	kp.command = ctrlkeys[scancode];
	kp.character = 0;
	if (kp.command == 0) kp.command = ctrlkeys[scancode & 0x7F];

	if (kp.command == 0) {
		kp.command = (alt ? KB_CMD_ALT : 0) | (ctrl ? KB_CMD_CTRL : 0);
		scancode = scancode & 0x7F;
		if ((shift || caps) && !(shift && caps)) {
			if (altgr) {
				kp.character = km->shiftaltgr[scancode];
			} else {
				if (shift) {
					kp.character = km->shift[scancode];
				} else {
					kp.character = km->caps[scancode];
				}
			}
		} else {
			if (altgr) {
				kp.character = km->altgr[scancode];
			} else {
				kp.character = km->normal[scancode];
			}
		}
	} else if (kp.command >= KB_KPDEL && kp.command <= KB_KPPGUP && num) {
		if (kp.command == KB_KPDEL) {
			kp.character = '.';
		} else {
			kp.character = '0' + kp.command - KB_KPINS;
		}
		kp.command = (alt ? KB_CMD_ALT : 0) | (ctrl ? KB_CMD_CTRL : 0);
	} else if (kp.command == KB_ALT) {
		alt = pressed;
	} else if (kp.command == KB_ALTGR) {
		altgr = pressed;
	} else if (kp.command == KB_LCTRL || kp.command == KB_RCTRL) {
		ctrl = pressed;
	} else if (kp.command == KB_LSHIFT || kp.command == KB_RSHIFT) {
		shift = pressed;
	} else if (kp.command == KB_CAPSLOCK && kp.pressed) {
		caps = !caps;
		updateLeds();
	} else if (kp.command == KB_NUMLOCK && kp.pressed) {
		num = !num;
		updateLeds();
	} else if (kp.command == KB_SCRLLOCK && kp.pressed) {
		scroll = !scroll;
		updateLeds();
	} else if (kp.command == KB_TAB) {
		kp.character = '\t';
	} else if (kp.command == KB_BACKSPACE) {
		kp.character = '\b';
	} else if (kp.command == KB_ENTER) {
		kp.character = '\n';
	} else if (kp.command == KB_KPSLASH) {
		kp.character = '/';
		kp.command = 0;
	}

	// process keypress
	if (output != 0) {
		output->keyboardInput(kp);
	} else {
		// TODO: enable reading directly keypresses from keyboard device
	}
}

void keyboard::outputTo(vt *vt) {
	output = vt;
}

int keyboard::link(node* to, int mode) {
	if (mode == LM_OUTPUT_TO) {
		vt *v = to->as_vt();
		if (v != 0) {
			outputTo(v);
			return 0;
		}
	}
	return E_NOT_IMPLEMENTED;
}