summaryrefslogtreecommitdiff
path: root/src/kernel/dev/keyboard.cpp
blob: 3f54b99f3ff315401ed74dd4ae47a9b46ef0c56a (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
#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, this);
	} 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;
}