xref: /haiku/src/add-ons/kernel/debugger/usb_keyboard/usb_keyboard.cpp (revision 91054f1d38dd7827c0f0ba9490c213775ec7b471)
1 /*
2  * Copyright 2009, Haiku Inc. All rights reserved.
3  * Distributed under the terms of the MIT License.
4  *
5  * Authors:
6  *		Michael Lotz <mmlr@mlotz.ch>
7  */
8 
9 #include <debug.h>
10 #include <debugger_keymaps.h>
11 
12 static bool sUseUSBKeyboard = false;
13 static uint8 sUSBTransferData[64];
14 static uint8 sLastTransferData[64];
15 static size_t sUSBTransferLength = 0;
16 static void *sUSBPipe = NULL;
17 
18 // simple ring buffer
19 static int sBufferedChars[32];
20 static uint8 sBufferSize = sizeof(sBufferedChars) / sizeof(sBufferedChars[0]);
21 static uint8 sBufferedCharCount = 0;
22 static uint8 sBufferWriteIndex = 0;
23 static uint8 sBufferReadIndex = 0;
24 
25 #define MODIFIER_CONTROL	0x01
26 #define MODIFIER_SHIFT		0x02
27 #define MODIFIER_ALT		0x04
28 
29 static uint32 sModifierTable[] = {
30 	MODIFIER_CONTROL,
31 	MODIFIER_SHIFT,
32 	MODIFIER_ALT,
33 	0,
34 	MODIFIER_CONTROL,
35 	MODIFIER_SHIFT,
36 	MODIFIER_ALT,
37 	0
38 };
39 
40 static uint8 sKeyTable[] = {
41 	0,	// ERROR
42 	0,	// ERROR
43 	0,	// ERROR
44 	0,	// ERROR
45 	30,	// A
46 	48,	// B
47 	46,	// C
48 	32,	// D
49 	18,	// E
50 	33,	// F
51 	34,	// G
52 	35,	// H
53 	23,	// I
54 	36,	// J
55 	37,	// K
56 	38,	// L
57 	50,	// M
58 	49,	// N
59 	24,	// O
60 	25,	// P
61 	16,	// Q
62 	19,	// R
63 	31,	// S
64 	20,	// T
65 	22,	// U
66 	47,	// V
67 	17,	// W
68 	45,	// X
69 	21,	// Y
70 	44,	// Z
71 	2,	// 1
72 	3,	// 2
73 	4,	// 3
74 	5,	// 4
75 	6,	// 5
76 	7,	// 6
77 	8,	// 7
78 	9,	// 8
79 	10,	// 9
80 	11,	// 0
81 	28,	// enter
82 	1,	// Esc
83 	14,	// Backspace
84 	15,	// Tab
85 	57,	// Space
86 	12,	// -
87 	13,	// =
88 	26,	// [
89 	27,	// ]
90 	43,	// backslash
91 	80,	// backslash
92 	39,	// ;
93 	40,	// '
94 	41,	// `
95 	51,	// ,
96 	52,	// .
97 	53,	// /
98 	0,	// Caps
99 	0,	// F1
100 	0,	// F2
101 	0,	// F3
102 	0,	// F4
103 	0,	// F5
104 	0,	// F6
105 	0,	// F7
106 	0,	// F8
107 	0,	// F9
108 	0,	// F10
109 	0,	// F11
110 	0,	// F12
111 	0,	// PrintScreen
112 	0,	// Scroll Lock
113 	0,	// Pause (0x7f with Ctrl)
114 	0,	// Insert
115 	0x80 | 'H',	// Home
116 	0x80 | '5',	// Page up
117 	0x80 | '3',	// Delete
118 	0x80 | 'F',	// End
119 	0x80 | '6',	// Page down
120 	0x80 | 'C',	// Right arrow
121 	0x80 | 'D',	// Left arrow
122 	0x80 | 'B',	// Down arrow
123 	0x80 | 'A',	// Up arrow
124 	0,	// Num Lock
125 	53,	// Pad /
126 	55,	// Pad *
127 	12,	// Pad -
128 	54,	// Pad +
129 	28,	// Pad Enter
130 	2,	// Pad 1
131 	3,	// Pad 2
132 	4,	// Pad 3
133 	5,	// Pad 4
134 	6,	// Pad 5
135 	7,	// Pad 6
136 	8,	// Pad 7
137 	9,	// Pad 8
138 	10,	// Pad 9
139 	11,	// Pad 0
140 	52,	// Pad .
141 	86,	// <
142 	0,	// Menu
143 	0,	// Power
144 	13	// Pad =
145 };
146 
147 static size_t sKeyTableSize = sizeof(sKeyTable) / sizeof(sKeyTable[0]);
148 
149 
150 static void
151 enter_debugger(void)
152 {
153 	if (!has_debugger_command("get_usb_keyboard_config")
154 		|| !has_debugger_command("get_usb_pipe_for_id")
155 		|| (!has_debugger_command("uhci_process_transfer")
156 			&& !has_debugger_command("ohci_process_transfer")))
157 		return;
158 
159 	unset_debug_variable("_usbPipe");
160 	unset_debug_variable("_usbReportSize");
161 
162 	evaluate_debug_command("get_usb_keyboard_config");
163 	sUSBTransferLength = get_debug_variable("_usbReportSize", 0);
164 	if (sUSBTransferLength == 0 || sUSBTransferLength > sizeof(sUSBTransferData))
165 		return;
166 
167 	evaluate_debug_command("get_usb_pipe_for_id");
168 	sUSBPipe = (void *)get_debug_variable("_usbPipe", 0);
169 	if (sUSBPipe == NULL)
170 		return;
171 
172 	sUseUSBKeyboard = true;
173 }
174 
175 
176 static void
177 exit_debugger(void)
178 {
179 	sUseUSBKeyboard = false;
180 }
181 
182 
183 static void
184 write_key(int key)
185 {
186 	sBufferedChars[sBufferWriteIndex++] = key;
187 	sBufferWriteIndex %= sBufferSize;
188 	sBufferedCharCount++;
189 }
190 
191 
192 static int
193 debugger_getchar(void)
194 {
195 	if (!sUseUSBKeyboard)
196 		return -1;
197 
198 	while (sBufferedCharCount == 0) {
199 		set_debug_variable("_usbPipe", (uint64)sUSBPipe);
200 		set_debug_variable("_usbTransferData", (uint64)sUSBTransferData);
201 		set_debug_variable("_usbTransferLength", (uint64)sUSBTransferLength);
202 		evaluate_debug_command("uhci_process_transfer");
203 
204 		bool phantomState = true;
205 		for (size_t i = 2; i < sUSBTransferLength; i++) {
206 			if (sUSBTransferData[i] != 0x01) {
207 				phantomState = false;
208 				break;
209 			}
210 		}
211 
212 		if (phantomState)
213 			continue;
214 
215 		uint8 modifiers = 0;
216 		for (uint32 i = 0; i < 8; i++) {
217 			if (sUSBTransferData[0] & (1 << i))
218 				modifiers |= sModifierTable[i];
219 		}
220 
221 		uint8 *current = sUSBTransferData;
222 		uint8 *compare = sLastTransferData;
223 		for (uint32 i = 2; i < sUSBTransferLength; i++) {
224 			if (current[i] == 0x00 || current[i] == 0x01)
225 				continue;
226 
227 			bool found = false;
228 			for (uint32 j = 2; j < sUSBTransferLength; j++) {
229 				if (compare[j] == current[i]) {
230 					found = true;
231 					break;
232 				}
233 			}
234 
235 			if (found)
236 				continue;
237 
238 			if (current[i] >= sKeyTableSize)
239 				continue;
240 
241 			int result = -1;
242 			uint8 key = sKeyTable[current[i]];
243 			if (key & 0x80) {
244 				write_key(27);
245 				write_key('[');
246 
247 				key &= ~0x80;
248 				write_key(key);
249 
250 				if (key == '5' || key == '6' || key == '3')
251 					write_key('~');
252 
253 				continue;
254 			} else if (modifiers & MODIFIER_CONTROL) {
255 				char c = kShiftedKeymap[key];
256 				if (c >= 'A' && c <= 'Z')
257 					result = 0x1f & c;
258 			} else if (modifiers & MODIFIER_ALT)
259 				result = kAltedKeymap[key];
260 			else if (modifiers & MODIFIER_SHIFT)
261 				result = kShiftedKeymap[key];
262 			else
263 				result = kUnshiftedKeymap[key];
264 
265 			if (result < 0)
266 				continue;
267 
268 			write_key(result);
269 		}
270 
271 		for (uint32 i = 0; i < sUSBTransferLength; i++)
272 			sLastTransferData[i] = sUSBTransferData[i];
273 	}
274 
275 	int result = sBufferedChars[sBufferReadIndex++];
276 	sBufferReadIndex %= sBufferSize;
277 	sBufferedCharCount--;
278 	return result;
279 }
280 
281 
282 static status_t
283 std_ops(int32 op, ...)
284 {
285 	if (op == B_MODULE_INIT || op == B_MODULE_UNINIT)
286 		return B_OK;
287 
288 	return B_BAD_VALUE;
289 }
290 
291 
292 static struct debugger_module_info sModuleInfo = {
293 	{
294 		"debugger/usb_keyboard/v1",
295 		0,
296 		&std_ops
297 	},
298 
299 	&enter_debugger,
300 	&exit_debugger,
301 	NULL,
302 	&debugger_getchar
303 };
304 
305 module_info *modules[] = {
306 	(module_info *)&sModuleInfo,
307 	NULL
308 };
309 
310