1 /*
2 * Copyright 2009-2011, 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
enter_debugger(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("usb_process_transfer")) {
156 return;
157 }
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
exit_debugger(void)177 exit_debugger(void)
178 {
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;
184 }
185 }
186
187
188 static void
write_key(int key)189 write_key(int key)
190 {
191 sBufferedChars[sBufferWriteIndex++] = key;
192 sBufferWriteIndex %= sBufferSize;
193 sBufferedCharCount++;
194 }
195
196
197 static int
debugger_getchar(void)198 debugger_getchar(void)
199 {
200 if (!sUseUSBKeyboard)
201 return -1;
202
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);
207
208 status_t status = evaluate_debug_command("usb_process_transfer");
209 if (status == B_DEV_PENDING)
210 return -1;
211
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;
216 }
217
218 bool phantomState = true;
219 for (size_t i = 2; i < sUSBTransferLength; i++) {
220 if (sUSBTransferData[i] != 0x01) {
221 phantomState = false;
222 break;
223 }
224 }
225
226 if (phantomState)
227 return -1;
228
229 uint8 modifiers = 0;
230 for (uint32 i = 0; i < 8; i++) {
231 if (sUSBTransferData[0] & (1 << i))
232 modifiers |= sModifierTable[i];
233 }
234
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;
240
241 bool found = false;
242 for (uint32 j = 2; j < sUSBTransferLength; j++) {
243 if (compare[j] == current[i]) {
244 found = true;
245 break;
246 }
247 }
248
249 if (found)
250 continue;
251
252 if (current[i] >= sKeyTableSize)
253 continue;
254
255 int result = -1;
256 uint8 key = sKeyTable[current[i]];
257 if (key & 0x80) {
258 write_key(27);
259 write_key('[');
260
261 key &= ~0x80;
262 write_key(key);
263
264 if (key == '5' || key == '6' || key == '3')
265 write_key('~');
266
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];
278
279 if (result < 0)
280 continue;
281
282 write_key(result);
283 }
284
285 for (uint32 i = 0; i < sUSBTransferLength; i++)
286 sLastTransferData[i] = sUSBTransferData[i];
287 }
288
289 if (sBufferedCharCount == 0)
290 return -1;
291
292 int result = sBufferedChars[sBufferReadIndex++];
293 sBufferReadIndex %= sBufferSize;
294 sBufferedCharCount--;
295 return result;
296 }
297
298
299 static status_t
std_ops(int32 op,...)300 std_ops(int32 op, ...)
301 {
302 if (op == B_MODULE_INIT || op == B_MODULE_UNINIT)
303 return B_OK;
304
305 return B_BAD_VALUE;
306 }
307
308
309 static struct debugger_module_info sModuleInfo = {
310 {
311 "debugger/usb_keyboard/v1",
312 0,
313 &std_ops
314 },
315
316 &enter_debugger,
317 &exit_debugger,
318 NULL,
319 &debugger_getchar
320 };
321
322 module_info *modules[] = {
323 (module_info *)&sModuleInfo,
324 NULL
325 };
326
327