* Copyright 2009-2011, Haiku, Inc. All rights reserved.
* Distributed under the terms of the MIT License.
*
* Authors:
* Michael Lotz <mmlr@mlotz.ch>
*/
#include <debug.h>
#include <debugger_keymaps.h>
static bool sUseUSBKeyboard = false;
static uint8 sUSBTransferData[64];
static uint8 sLastTransferData[64];
static size_t sUSBTransferLength = 0;
static void *sUSBPipe = NULL;
static int sBufferedChars[32];
static uint8 sBufferSize = sizeof(sBufferedChars) / sizeof(sBufferedChars[0]);
static uint8 sBufferedCharCount = 0;
static uint8 sBufferWriteIndex = 0;
static uint8 sBufferReadIndex = 0;
#define MODIFIER_CONTROL 0x01
#define MODIFIER_SHIFT 0x02
#define MODIFIER_ALT 0x04
static uint32 sModifierTable[] = {
MODIFIER_CONTROL,
MODIFIER_SHIFT,
MODIFIER_ALT,
0,
MODIFIER_CONTROL,
MODIFIER_SHIFT,
MODIFIER_ALT,
0
};
static uint8 sKeyTable[] = {
0,
0,
0,
0,
30,
48,
46,
32,
18,
33,
34,
35,
23,
36,
37,
38,
50,
49,
24,
25,
16,
19,
31,
20,
22,
47,
17,
45,
21,
44,
2,
3,
4,
5,
6,
7,
8,
9,
10,
11,
28,
1,
14,
15,
57,
12,
13,
26,
27,
43,
80,
39,
40,
41,
51,
52,
53,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0x80 | 'H',
0x80 | '5',
0x80 | '3',
0x80 | 'F',
0x80 | '6',
0x80 | 'C',
0x80 | 'D',
0x80 | 'B',
0x80 | 'A',
0,
53,
55,
12,
54,
28,
2,
3,
4,
5,
6,
7,
8,
9,
10,
11,
52,
86,
0,
0,
13
};
static size_t sKeyTableSize = sizeof(sKeyTable) / sizeof(sKeyTable[0]);
static void
enter_debugger(void)
{
if (!has_debugger_command("get_usb_keyboard_config")
|| !has_debugger_command("get_usb_pipe_for_id")
|| !has_debugger_command("usb_process_transfer")) {
return;
}
unset_debug_variable("_usbPipe");
unset_debug_variable("_usbReportSize");
evaluate_debug_command("get_usb_keyboard_config");
sUSBTransferLength = get_debug_variable("_usbReportSize", 0);
if (sUSBTransferLength == 0 || sUSBTransferLength > sizeof(sUSBTransferData))
return;
evaluate_debug_command("get_usb_pipe_for_id");
sUSBPipe = (void *)get_debug_variable("_usbPipe", 0);
if (sUSBPipe == NULL)
return;
sUseUSBKeyboard = true;
}
static void
exit_debugger(void)
{
if (sUseUSBKeyboard) {
set_debug_variable("_usbPipe", (uint64)sUSBPipe);
evaluate_debug_command("usb_process_transfer cancel");
sUseUSBKeyboard = false;
}
}
static void
write_key(int key)
{
sBufferedChars[sBufferWriteIndex++] = key;
sBufferWriteIndex %= sBufferSize;
sBufferedCharCount++;
}
static int
debugger_getchar(void)
{
if (!sUseUSBKeyboard)
return -1;
if (sBufferedCharCount == 0) {
set_debug_variable("_usbPipe", (uint64)sUSBPipe);
set_debug_variable("_usbTransferData", (uint64)sUSBTransferData);
set_debug_variable("_usbTransferLength", (uint64)sUSBTransferLength);
status_t status = evaluate_debug_command("usb_process_transfer");
if (status == B_DEV_PENDING)
return -1;
if (status != B_OK) {
evaluate_debug_command("usb_clear_stall");
return -1;
}
bool phantomState = true;
for (size_t i = 2; i < sUSBTransferLength; i++) {
if (sUSBTransferData[i] != 0x01) {
phantomState = false;
break;
}
}
if (phantomState)
return -1;
uint8 modifiers = 0;
for (uint32 i = 0; i < 8; i++) {
if (sUSBTransferData[0] & (1 << i))
modifiers |= sModifierTable[i];
}
uint8 *current = sUSBTransferData;
uint8 *compare = sLastTransferData;
for (uint32 i = 2; i < sUSBTransferLength; i++) {
if (current[i] == 0x00 || current[i] == 0x01)
continue;
bool found = false;
for (uint32 j = 2; j < sUSBTransferLength; j++) {
if (compare[j] == current[i]) {
found = true;
break;
}
}
if (found)
continue;
if (current[i] >= sKeyTableSize)
continue;
int result = -1;
uint8 key = sKeyTable[current[i]];
if (key & 0x80) {
write_key(27);
write_key('[');
key &= ~0x80;
write_key(key);
if (key == '5' || key == '6' || key == '3')
write_key('~');
continue;
} else if (modifiers & MODIFIER_CONTROL) {
char c = kShiftedKeymap[key];
if (c >= 'A' && c <= 'Z')
result = 0x1f & c;
} else if (modifiers & MODIFIER_ALT)
result = kAltedKeymap[key];
else if (modifiers & MODIFIER_SHIFT)
result = kShiftedKeymap[key];
else
result = kUnshiftedKeymap[key];
if (result < 0)
continue;
write_key(result);
}
for (uint32 i = 0; i < sUSBTransferLength; i++)
sLastTransferData[i] = sUSBTransferData[i];
}
if (sBufferedCharCount == 0)
return -1;
int result = sBufferedChars[sBufferReadIndex++];
sBufferReadIndex %= sBufferSize;
sBufferedCharCount--;
return result;
}
static status_t
std_ops(int32 op, ...)
{
if (op == B_MODULE_INIT || op == B_MODULE_UNINIT)
return B_OK;
return B_BAD_VALUE;
}
static struct debugger_module_info sModuleInfo = {
{
"debugger/usb_keyboard/v1",
0,
&std_ops
},
&enter_debugger,
&exit_debugger,
NULL,
&debugger_getchar
};
module_info *modules[] = {
(module_info *)&sModuleInfo,
NULL
};