Implemented keyboard probing using reset and self test.

Implemented setting of typematic rate and delay support.


git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@16361 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Marcus Overhagen 2006-02-12 16:05:50 +00:00
parent 61ed8caf39
commit 21af4fdbff
4 changed files with 118 additions and 54 deletions

View File

@ -140,11 +140,6 @@ ps2_command(uint8 cmd, const uint8 *out, int out_count, uint8 *in, int in_count)
return res; return res;
} }
status_t
ps2_keyboard_command(uint8 cmd, const uint8 *out, int out_count, uint8 *in, int in_count)
{
return ps2_dev_command(&ps2_device[PS2_DEVICE_KEYB], cmd, out, out_count, in, in_count);
}
// #pragma mark - // #pragma mark -

View File

@ -32,7 +32,8 @@
#define PS2_CTRL_MOUSE_DISABLE 0xa7 #define PS2_CTRL_MOUSE_DISABLE 0xa7
#define PS2_CTRL_MOUSE_ENABLE 0xa8 #define PS2_CTRL_MOUSE_ENABLE 0xa8
#define PS2_CTRL_MOUSE_TEST 0xa9 #define PS2_CTRL_MOUSE_TEST 0xa9
#define PS2_CTRL_KEYBOARD_SELF_TEST 0xaa #define PS2_CTRL_SELF_TEST 0xaa
#define PS2_CTRL_KEYBOARD_TEST 0xab
#define PS2_CTRL_KEYBOARD_ACTIVATE 0xae #define PS2_CTRL_KEYBOARD_ACTIVATE 0xae
#define PS2_CTRL_KEYBOARD_DEACTIVATE 0xad #define PS2_CTRL_KEYBOARD_DEACTIVATE 0xad
@ -47,12 +48,13 @@
#define PS2_BITS_TRANSLATE_SCANCODES 0x40 #define PS2_BITS_TRANSLATE_SCANCODES 0x40
// data words // data words
#define PS2_CMD_ECHO 0xee
#define PS2_CMD_TEST_PASSED 0xaa #define PS2_CMD_TEST_PASSED 0xaa
#define PS2_CMD_GET_DEVICE_ID 0xf2 #define PS2_CMD_GET_DEVICE_ID 0xf2
#define PS2_CMD_SET_SAMPLE_RATE 0xf3 #define PS2_CMD_SET_SAMPLE_RATE 0xf3
#define PS2_CMD_ENABLE_MOUSE 0xf4 #define PS2_CMD_ENABLE_MOUSE 0xf4
#define PS2_CMD_DISABLE_MOUSE 0xf5 #define PS2_CMD_DISABLE_MOUSE 0xf5
#define PS2_CMD_RESET_MOUSE 0xff #define PS2_CMD_RESET 0xff
// reply codes // reply codes
#define PS2_REPLY_TEST_PASSED 0x55 #define PS2_REPLY_TEST_PASSED 0x55

View File

@ -40,6 +40,8 @@ static sem_id sKeyboardSem;
static struct packet_buffer *sKeyBuffer; static struct packet_buffer *sKeyBuffer;
static bool sIsExtended = false; static bool sIsExtended = false;
static int32 sKeyboardRepeatRate;
static bigtime_t sKeyboardRepeatDelay;
static status_t static status_t
set_leds(led_info *ledInfo) set_leds(led_info *ledInfo)
@ -55,7 +57,39 @@ set_leds(led_info *ledInfo)
if (ledInfo->caps_lock) if (ledInfo->caps_lock)
leds |= LED_CAPS; leds |= LED_CAPS;
return ps2_keyboard_command(PS2_DATA_SET_LEDS, &leds, 1, NULL, 0); return ps2_dev_command(&ps2_device[PS2_DEVICE_KEYB], PS2_DATA_SET_LEDS, &leds, 1, NULL, 0);
}
static status_t
set_typematic(int32 rate, bigtime_t delay)
{
uint8 value;
dprintf("ps2: set_typematic rate %ld, delay %Ld\n", rate, delay);
// input server and keyboard preferences *seem* to use a range of 20-300
if (rate < 20)
rate = 20;
if (rate > 300)
rate = 300;
// map this into range 0-31
rate = ((rate - 20) * 31) / (300 - 20);
// keyboard uses 0 == fast, 31 == slow
value = 31 - rate;
if (delay >= 875000)
value |= 3 << 5;
else if (delay >= 625000)
value |= 2 << 5;
else if (delay >= 375000)
value |= 1 << 5;
else
value |= 0 << 5;
return ps2_dev_command(&ps2_device[PS2_DEVICE_KEYB], 0xf3, &value, 1, NULL, 0);
} }
@ -133,65 +167,42 @@ read_keyboard_packet(at_kbd_io *userBuffer)
} }
static status_t
enable_keyboard(void)
{
uint32 tries = 3;
while (tries-- > 0) {
// keyboard_empty_data();
if (ps2_keyboard_command(PS2_ENABLE_KEYBOARD, NULL, 0, NULL, 0) == B_OK)
return B_OK;
}
dprintf("enable_keyboard() failed\n");
return B_ERROR;
}
// #pragma mark - // #pragma mark -
status_t status_t
probe_keyboard(void) probe_keyboard(void)
{ {
int32 tries; uint8 data;
status_t status;
// ToDo: for now there just is a keyboard ready to be used...
// Keyboard detection does not seem to be working always correctly // status = ps2_command(PS2_CTRL_KEYBOARD_ACTIVATE, const uint8 *out, int out_count, uint8 *in, int in_count)
// not sure if this is the correct way status = ps2_command(PS2_CTRL_KEYBOARD_TEST, NULL, 0, &data, 1);
ps2_keyboard_command(PS2_CTRL_KEYBOARD_SELF_TEST, NULL, 0, NULL, 0); if (status != B_OK || data != 0x00) {
ps2_keyboard_command(PS2_CTRL_KEYBOARD_SELF_TEST, NULL, 0, NULL, 0); dprintf("ps2: keyboard test failed, status 0x%08lx, data 0x%02x\n", status, data);
#if 0
// Keyboard self-test
if (ps2_write_ctrl(PS2_CTRL_KEYBOARD_SELF_TEST) != B_OK)
return B_ERROR; return B_ERROR;
tries = 3;
while (tries-- > 0) {
uint8 acknowledged;
if (ps2_read_data(&acknowledged) == B_OK && acknowledged == PS2_REPLY_ACK)
break;
} }
// This selftest appears to fail quite frequently we'll just disable it status = ps2_dev_command(&ps2_device[PS2_DEVICE_KEYB], PS2_CMD_RESET, NULL, 0, &data, 1);
/*if (tries < 0) if (status != B_OK || data != 0xaa) {
return B_ERROR;*/ dprintf("ps2: keyboard reset failed, status 0x%08lx, data 0x%02x\n", status, data);
// Activate keyboard
if (ps2_write_ctrl(PS2_CTRL_KEYBOARD_ACTIVATE) != B_OK)
return B_ERROR; return B_ERROR;
}
// Enable keyboard // default settings after keyboard reset: delay = 0x01 (500 ms), rate = 0x0b (10.9 chr/sec)
sKeyboardRepeatRate = ((31 - 0x0b) * 280) / 31 + 20;
sKeyboardRepeatDelay = 500000;
// status = ps2_dev_command(&ps2_device[PS2_DEVICE_KEYB], PS2_ENABLE_KEYBOARD, NULL, 0, NULL, 0);
// On my notebook, the keyboard controller does NACK the echo command.
// status = ps2_dev_command(&ps2_device[PS2_DEVICE_KEYB], PS2_CMD_ECHO, NULL, 0, &data, 1);
// if (status != B_OK || data != 0xee) {
// dprintf("ps2: keyboard echo test failed, status 0x%08lx, data 0x%02x\n", status, data);
// return B_ERROR;
// }
return enable_keyboard();
#endif
return B_OK; return B_OK;
} }
@ -208,6 +219,12 @@ keyboard_open(const char *name, uint32 flags, void **_cookie)
if (atomic_or(&sKeyboardOpenMask, 1) != 0) if (atomic_or(&sKeyboardOpenMask, 1) != 0)
return B_BUSY; return B_BUSY;
status = probe_keyboard();
if (status != B_OK) {
dprintf("ps2: keyboard probing failed\n");
goto err1;
}
sKeyboardSem = create_sem(0, "keyboard_sem"); sKeyboardSem = create_sem(0, "keyboard_sem");
if (sKeyboardSem < 0) { if (sKeyboardSem < 0) {
@ -300,8 +317,58 @@ keyboard_ioctl(void *cookie, uint32 op, void *buffer, size_t length)
return set_leds(&info); return set_leds(&info);
} }
case KB_SET_KEY_REPEATING: case KB_SET_KEY_REPEATING:
{
// 0xFA (Set All Keys Typematic/Make/Break) - Keyboard responds with "ack" (0xFA).
return ps2_dev_command(&ps2_device[PS2_DEVICE_KEYB], 0xfa, NULL, 0, NULL, 0);
}
case KB_SET_KEY_NONREPEATING: case KB_SET_KEY_NONREPEATING:
{
// 0xF8 (Set All Keys Make/Break) - Keyboard responds with "ack" (0xFA).
return ps2_dev_command(&ps2_device[PS2_DEVICE_KEYB], 0xf8, NULL, 0, NULL, 0);
}
case KB_SET_KEY_REPEAT_RATE:
{
int32 key_repeat_rate;
if (user_memcpy(&key_repeat_rate, buffer, sizeof(key_repeat_rate)) < B_OK)
return B_BAD_ADDRESS;
dprintf("ps2: KB_SET_KEY_REPEAT_RATE %ld\n", key_repeat_rate);
if (set_typematic(key_repeat_rate, sKeyboardRepeatDelay) < B_OK)
return B_ERROR;
sKeyboardRepeatRate = key_repeat_rate;
return B_OK;
}
case KB_GET_KEY_REPEAT_RATE:
{
return user_memcpy(buffer, &sKeyboardRepeatRate, sizeof(sKeyboardRepeatRate));
}
case KB_SET_KEY_REPEAT_DELAY:
{
bigtime_t key_repeat_delay;
if (user_memcpy(&key_repeat_delay, buffer, sizeof(key_repeat_delay)) < B_OK)
return B_BAD_ADDRESS;
dprintf("ps2: KB_SET_KEY_REPEAT_DELAY %Ld\n", key_repeat_delay);
if (set_typematic(sKeyboardRepeatRate, key_repeat_delay) < B_OK)
return B_ERROR;
sKeyboardRepeatDelay = key_repeat_delay;
return B_OK;
}
case KB_GET_KEY_REPEAT_DELAY:
{
return user_memcpy(buffer, &sKeyboardRepeatDelay, sizeof(sKeyboardRepeatDelay));
}
case KB_GET_KEYBOARD_ID:
case KB_SET_CONTROL_ALT_DEL_TIMEOUT:
case KB_CANCEL_CONTROL_ALT_DEL:
case KB_DELAY_CONTROL_ALT_DEL:
TRACE(("ps2_hid: ioctl 0x%lx not implemented yet, returning B_OK\n", op)); TRACE(("ps2_hid: ioctl 0x%lx not implemented yet, returning B_OK\n", op));
return B_OK; return B_OK;

View File

@ -98,7 +98,7 @@ ps2_reset_mouse(mouse_cookie *cookie)
TRACE(("ps2_reset_mouse()\n")); TRACE(("ps2_reset_mouse()\n"));
status = ps2_dev_command(cookie->dev, PS2_CMD_RESET_MOUSE, NULL, 0, data, 2); status = ps2_dev_command(cookie->dev, PS2_CMD_RESET, NULL, 0, data, 2);
if (status == B_OK && data[0] != 0xAA && data[1] != 0x00) { if (status == B_OK && data[0] != 0xAA && data[1] != 0x00) {
TRACE(("reset mouse failed, response was: 0x%02x 0x%02x\n", data[0], data[1])); TRACE(("reset mouse failed, response was: 0x%02x 0x%02x\n", data[0], data[1]));