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 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 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 189 write_key(int key) 190 { 191 sBufferedChars[sBufferWriteIndex++] = key; 192 sBufferWriteIndex %= sBufferSize; 193 sBufferedCharCount++; 194 } 195 196 197 static int 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 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