vfs: check userland buffers before reading them.
[haiku.git] / src / add-ons / kernel / debugger / usb_keyboard / usb_keyboard.cpp
blob94d79add64d311cc891a1dbf7216e1d595fef4db
1 /*
2 * Copyright 2009-2011, Haiku, Inc. All rights reserved.
3 * Distributed under the terms of the MIT License.
5 * Authors:
6 * Michael Lotz <mmlr@mlotz.ch>
7 */
9 #include <debug.h>
10 #include <debugger_keymaps.h>
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;
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;
25 #define MODIFIER_CONTROL 0x01
26 #define MODIFIER_SHIFT 0x02
27 #define MODIFIER_ALT 0x04
29 static uint32 sModifierTable[] = {
30 MODIFIER_CONTROL,
31 MODIFIER_SHIFT,
32 MODIFIER_ALT,
34 MODIFIER_CONTROL,
35 MODIFIER_SHIFT,
36 MODIFIER_ALT,
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 =
147 static size_t sKeyTableSize = sizeof(sKeyTable) / sizeof(sKeyTable[0]);
150 static void
151 enter_debugger(void)
153 if (!has_debugger_command("get_usb_keyboard_config")
154 || !has_debugger_command("get_usb_pipe_for_id")
155 || !has_debugger_command("usb_process_transfer")) {
156 return;
159 unset_debug_variable("_usbPipe");
160 unset_debug_variable("_usbReportSize");
162 evaluate_debug_command("get_usb_keyboard_config");
163 sUSBTransferLength = get_debug_variable("_usbReportSize", 0);
164 if (sUSBTransferLength == 0 || sUSBTransferLength > sizeof(sUSBTransferData))
165 return;
167 evaluate_debug_command("get_usb_pipe_for_id");
168 sUSBPipe = (void *)get_debug_variable("_usbPipe", 0);
169 if (sUSBPipe == NULL)
170 return;
172 sUseUSBKeyboard = true;
176 static void
177 exit_debugger(void)
179 if (sUseUSBKeyboard) {
180 // make sure a possibly pending transfer is canceled
181 set_debug_variable("_usbPipe", (uint64)sUSBPipe);
182 evaluate_debug_command("usb_process_transfer cancel");
183 sUseUSBKeyboard = false;
188 static void
189 write_key(int key)
191 sBufferedChars[sBufferWriteIndex++] = key;
192 sBufferWriteIndex %= sBufferSize;
193 sBufferedCharCount++;
197 static int
198 debugger_getchar(void)
200 if (!sUseUSBKeyboard)
201 return -1;
203 if (sBufferedCharCount == 0) {
204 set_debug_variable("_usbPipe", (uint64)sUSBPipe);
205 set_debug_variable("_usbTransferData", (uint64)sUSBTransferData);
206 set_debug_variable("_usbTransferLength", (uint64)sUSBTransferLength);
208 status_t status = evaluate_debug_command("usb_process_transfer");
209 if (status == B_DEV_PENDING)
210 return -1;
212 if (status != B_OK) {
213 // try clearing a possibly set halt due to toggle mismatches
214 evaluate_debug_command("usb_clear_stall");
215 return -1;
218 bool phantomState = true;
219 for (size_t i = 2; i < sUSBTransferLength; i++) {
220 if (sUSBTransferData[i] != 0x01) {
221 phantomState = false;
222 break;
226 if (phantomState)
227 return -1;
229 uint8 modifiers = 0;
230 for (uint32 i = 0; i < 8; i++) {
231 if (sUSBTransferData[0] & (1 << i))
232 modifiers |= sModifierTable[i];
235 uint8 *current = sUSBTransferData;
236 uint8 *compare = sLastTransferData;
237 for (uint32 i = 2; i < sUSBTransferLength; i++) {
238 if (current[i] == 0x00 || current[i] == 0x01)
239 continue;
241 bool found = false;
242 for (uint32 j = 2; j < sUSBTransferLength; j++) {
243 if (compare[j] == current[i]) {
244 found = true;
245 break;
249 if (found)
250 continue;
252 if (current[i] >= sKeyTableSize)
253 continue;
255 int result = -1;
256 uint8 key = sKeyTable[current[i]];
257 if (key & 0x80) {
258 write_key(27);
259 write_key('[');
261 key &= ~0x80;
262 write_key(key);
264 if (key == '5' || key == '6' || key == '3')
265 write_key('~');
267 continue;
268 } else if (modifiers & MODIFIER_CONTROL) {
269 char c = kShiftedKeymap[key];
270 if (c >= 'A' && c <= 'Z')
271 result = 0x1f & c;
272 } else if (modifiers & MODIFIER_ALT)
273 result = kAltedKeymap[key];
274 else if (modifiers & MODIFIER_SHIFT)
275 result = kShiftedKeymap[key];
276 else
277 result = kUnshiftedKeymap[key];
279 if (result < 0)
280 continue;
282 write_key(result);
285 for (uint32 i = 0; i < sUSBTransferLength; i++)
286 sLastTransferData[i] = sUSBTransferData[i];
289 if (sBufferedCharCount == 0)
290 return -1;
292 int result = sBufferedChars[sBufferReadIndex++];
293 sBufferReadIndex %= sBufferSize;
294 sBufferedCharCount--;
295 return result;
299 static status_t
300 std_ops(int32 op, ...)
302 if (op == B_MODULE_INIT || op == B_MODULE_UNINIT)
303 return B_OK;
305 return B_BAD_VALUE;
309 static struct debugger_module_info sModuleInfo = {
311 "debugger/usb_keyboard/v1",
313 &std_ops
316 &enter_debugger,
317 &exit_debugger,
318 NULL,
319 &debugger_getchar
322 module_info *modules[] = {
323 (module_info *)&sModuleInfo,
324 NULL