kbc: Handle setting typematic rate/delay

Per [1], use a default delay of 500ms and a rate of 10.9 CPS. When the
Linux kernel starts, this will be updated by atkbd to the fastest
settings possible [2]: 250ms delay and 30 CPS.

Modifying these values with kbdrate to test settings will cause two
spurious ACKs in the kernel. This behavior is also present in the
proprietary firmware.

[1]: https://web.archive.org/web/20180217074705/http://computer-engineering.org/ps2keyboard/
[2]: c5f8689118/drivers/input/keyboard/atkbd.c (L863-L868)
This commit is contained in:
Tim Crawford 2020-02-25 14:20:13 -07:00
parent a8f921fcab
commit a176da0ebe
9 changed files with 198 additions and 9 deletions

View File

@ -7,6 +7,11 @@
extern bool kbscan_enabled;
// ms between repeating key
extern uint16_t kbscan_repeat_period;
// ms between pressing key and repeating
extern uint16_t kbscan_repeat_delay;
void kbscan_init(void);
void kbscan_event(void);

View File

@ -22,6 +22,42 @@ bool kbc_second = false;
// for basically no good reason
static bool kbc_translate = true;
// Values from linux/drivers/input/keyboard/atkbd.c
static const uint16_t kbc_typematic_period[32] = {
33, // 30.0 cps = ~33.33ms
37, // 26.7 cps = ~37.45ms
42, // 24.0 cps = ~41.67ms
46, // 21.8 cps = ~45.87ms
50, // 20.7 cps = ~48.30ms
54, // 18.5 cps = ~54.05ms
58, // 17.1 cps = ~58.48ms
63, // 16.0 cps = ~62.50ms
67, // 15.0 cps = ~66.67ms
75, // 13.3 cps = ~75.19ms
83, // 12.0 cps = ~83.33ms
92, // 10.9 cps = ~91.74ms
100, // 10.0 cps = 100ms
109, // 9.2 cps = ~108.70ms
116, // 8.6 cps = ~116.28ms
125, // 8.0 cps = 125ms
133, // 7.5 cps = ~133.33ms
149, // 6.7 cps = ~149.25ms
167, // 6.0 cps = ~166.67ms
182, // 5.5 cps = ~181.82ms
200, // 5.0 cps = 200ms
217, // 4.6 cps = ~217.39ms
232, // 4.3 cps = ~232.56ms
250, // 4.0 cps = 250ms
270, // 3.7 cps = ~270.27ms
303, // 3.3 cps = ~303.03ms
333, // 3.0 cps = ~333.33ms
370, // 2.7 cps = ~370.37ms
400, // 2.5 cps = 400ms
435, // 2.3 cps = ~434.78ms
470, // 2.1 cps = ~478.19ms
500, // 2.0 cps = 500ms
};
bool kbc_scancode(struct Kbc * kbc, uint16_t key, bool pressed) {
if (!kbc_first) return true;
if (kbc_translate) {
@ -55,6 +91,7 @@ enum KbcState {
KBC_STATE_WRITE_CONFIG,
KBC_STATE_SET_LEDS,
KBC_STATE_SCANCODE,
KBC_STATE_TYPEMATIC,
KBC_STATE_WRITE_PORT,
KBC_STATE_FIRST_PORT_OUTPUT,
KBC_STATE_SECOND_PORT_OUTPUT,
@ -172,6 +209,11 @@ void kbc_event(struct Kbc * kbc) {
}
}
break;
case 0xF3:
TRACE(" set typematic rate/delay\n");
state = KBC_STATE_TYPEMATIC;
kbc_keyboard(kbc, 0xFA, KBC_TIMEOUT);
break;
case 0xF4:
TRACE(" enable scanning\n");
kbscan_enabled = true;
@ -228,6 +270,21 @@ void kbc_event(struct Kbc * kbc) {
#endif
kbc_keyboard(kbc, 0xFA, KBC_TIMEOUT);
break;
case KBC_STATE_TYPEMATIC:
TRACE(" set typematic rate/delay\n");
state = KBC_STATE_NORMAL;
{
// Rate: bits 0-4
uint16_t period = kbc_typematic_period[data & 0x1F];
kbscan_repeat_period = period;
// Delay: bits 5-6
static const uint16_t delay[4] = {250, 500, 750, 1000};
uint8_t idx = (data & 0x60) >> 5;
kbscan_repeat_delay = delay[idx];
}
kbc_keyboard(kbc, 0xFA, KBC_TIMEOUT);
break;
case KBC_STATE_WRITE_PORT:
TRACE(" write port byte\n");
state = KBC_STATE_NORMAL;

View File

@ -9,6 +9,8 @@
#include <common/debug.h>
bool kbscan_enabled = false;
uint16_t kbscan_repeat_period = 91;
uint16_t kbscan_repeat_delay = 500;
uint8_t sci_extra = 0;
@ -232,7 +234,7 @@ void kbscan_event(void) {
if (time < repeat_key_time) {
// Overflow, reset repeat_key_time
repeat_key_time = time;
} else if ((time - repeat_key_time) >= 500) {
} else if ((time - repeat_key_time) >= kbscan_repeat_delay) {
// Typematic repeat
repeat = true;
repeat_start = time;
@ -240,8 +242,7 @@ void kbscan_event(void) {
}
if (repeat) {
// FIXME: resend key at typematic rate
if ((time - repeat_start) > 60) {
if ((time - repeat_start) > kbscan_repeat_period) {
kbscan_press(repeat_key, true, &layer);
repeat_start = time;
}

View File

@ -7,6 +7,11 @@
extern bool kbscan_enabled;
// ms between repeating key
extern uint16_t kbscan_repeat_period;
// ms between pressing key and repeating
extern uint16_t kbscan_repeat_delay;
void kbscan_init(void);
void kbscan_event(void);

View File

@ -22,6 +22,42 @@ bool kbc_second = false;
// for basically no good reason
static bool kbc_translate = true;
// Values from linux/drivers/input/keyboard/atkbd.c
static const uint16_t kbc_typematic_period[32] = {
33, // 30.0 cps = ~33.33ms
37, // 26.7 cps = ~37.45ms
42, // 24.0 cps = ~41.67ms
46, // 21.8 cps = ~45.87ms
50, // 20.7 cps = ~48.30ms
54, // 18.5 cps = ~54.05ms
58, // 17.1 cps = ~58.48ms
63, // 16.0 cps = ~62.50ms
67, // 15.0 cps = ~66.67ms
75, // 13.3 cps = ~75.19ms
83, // 12.0 cps = ~83.33ms
92, // 10.9 cps = ~91.74ms
100, // 10.0 cps = 100ms
109, // 9.2 cps = ~108.70ms
116, // 8.6 cps = ~116.28ms
125, // 8.0 cps = 125ms
133, // 7.5 cps = ~133.33ms
149, // 6.7 cps = ~149.25ms
167, // 6.0 cps = ~166.67ms
182, // 5.5 cps = ~181.82ms
200, // 5.0 cps = 200ms
217, // 4.6 cps = ~217.39ms
232, // 4.3 cps = ~232.56ms
250, // 4.0 cps = 250ms
270, // 3.7 cps = ~270.27ms
303, // 3.3 cps = ~303.03ms
333, // 3.0 cps = ~333.33ms
370, // 2.7 cps = ~370.37ms
400, // 2.5 cps = 400ms
435, // 2.3 cps = ~434.78ms
470, // 2.1 cps = ~478.19ms
500, // 2.0 cps = 500ms
};
bool kbc_scancode(struct Kbc * kbc, uint16_t key, bool pressed) {
if (!kbc_first) return true;
if (kbc_translate) {
@ -55,6 +91,7 @@ enum KbcState {
KBC_STATE_WRITE_CONFIG,
KBC_STATE_SET_LEDS,
KBC_STATE_SCANCODE,
KBC_STATE_TYPEMATIC,
KBC_STATE_WRITE_PORT,
KBC_STATE_FIRST_PORT_OUTPUT,
KBC_STATE_SECOND_PORT_OUTPUT,
@ -172,6 +209,11 @@ void kbc_event(struct Kbc * kbc) {
}
}
break;
case 0xF3:
TRACE(" set typematic rate/delay\n");
state = KBC_STATE_TYPEMATIC;
kbc_keyboard(kbc, 0xFA, KBC_TIMEOUT);
break;
case 0xF4:
TRACE(" enable scanning\n");
kbscan_enabled = true;
@ -228,6 +270,21 @@ void kbc_event(struct Kbc * kbc) {
#endif
kbc_keyboard(kbc, 0xFA, KBC_TIMEOUT);
break;
case KBC_STATE_TYPEMATIC:
TRACE(" set typematic rate/delay\n");
state = KBC_STATE_NORMAL;
{
// Rate: bits 0-4
uint16_t period = kbc_typematic_period[data & 0x1F];
kbscan_repeat_period = period;
// Delay: bits 5-6
static const uint16_t delay[4] = {250, 500, 750, 1000};
uint8_t idx = (data & 0x60) >> 5;
kbscan_repeat_delay = delay[idx];
}
kbc_keyboard(kbc, 0xFA, KBC_TIMEOUT);
break;
case KBC_STATE_WRITE_PORT:
TRACE(" write port byte\n");
state = KBC_STATE_NORMAL;

View File

@ -10,6 +10,8 @@
#include <common/debug.h>
bool kbscan_enabled = false;
uint16_t kbscan_repeat_period = 91;
uint16_t kbscan_repeat_delay = 500;
uint8_t sci_extra = 0;
@ -231,7 +233,7 @@ void kbscan_event(void) {
if (time < repeat_key_time) {
// Overflow, reset repeat_key_time
repeat_key_time = time;
} else if ((time - repeat_key_time) >= 500) {
} else if ((time - repeat_key_time) >= kbscan_repeat_delay) {
// Typematic repeat
repeat = true;
repeat_start = time;
@ -239,8 +241,7 @@ void kbscan_event(void) {
}
if (repeat) {
// FIXME: resend key at typematic rate
if ((time - repeat_start) > 60) {
if ((time - repeat_start) > kbscan_repeat_period) {
kbscan_press(repeat_key, true, &layer);
repeat_start = time;
}

View File

@ -7,6 +7,11 @@
extern bool kbscan_enabled;
// ms between repeating key
extern uint16_t kbscan_repeat_period;
// ms between pressing key and repeating
extern uint16_t kbscan_repeat_delay;
void kbscan_init(void);
void kbscan_event(void);

View File

@ -22,6 +22,42 @@ bool kbc_second = false;
// for basically no good reason
static bool kbc_translate = true;
// Values from linux/drivers/input/keyboard/atkbd.c
static const uint16_t kbc_typematic_period[32] = {
33, // 30.0 cps = ~33.33ms
37, // 26.7 cps = ~37.45ms
42, // 24.0 cps = ~41.67ms
46, // 21.8 cps = ~45.87ms
50, // 20.7 cps = ~48.30ms
54, // 18.5 cps = ~54.05ms
58, // 17.1 cps = ~58.48ms
63, // 16.0 cps = ~62.50ms
67, // 15.0 cps = ~66.67ms
75, // 13.3 cps = ~75.19ms
83, // 12.0 cps = ~83.33ms
92, // 10.9 cps = ~91.74ms
100, // 10.0 cps = 100ms
109, // 9.2 cps = ~108.70ms
116, // 8.6 cps = ~116.28ms
125, // 8.0 cps = 125ms
133, // 7.5 cps = ~133.33ms
149, // 6.7 cps = ~149.25ms
167, // 6.0 cps = ~166.67ms
182, // 5.5 cps = ~181.82ms
200, // 5.0 cps = 200ms
217, // 4.6 cps = ~217.39ms
232, // 4.3 cps = ~232.56ms
250, // 4.0 cps = 250ms
270, // 3.7 cps = ~270.27ms
303, // 3.3 cps = ~303.03ms
333, // 3.0 cps = ~333.33ms
370, // 2.7 cps = ~370.37ms
400, // 2.5 cps = 400ms
435, // 2.3 cps = ~434.78ms
470, // 2.1 cps = ~478.19ms
500, // 2.0 cps = 500ms
};
bool kbc_scancode(struct Kbc * kbc, uint16_t key, bool pressed) {
if (!kbc_first) return true;
if (kbc_translate) {
@ -55,6 +91,7 @@ enum KbcState {
KBC_STATE_WRITE_CONFIG,
KBC_STATE_SET_LEDS,
KBC_STATE_SCANCODE,
KBC_STATE_TYPEMATIC,
KBC_STATE_WRITE_PORT,
KBC_STATE_FIRST_PORT_OUTPUT,
KBC_STATE_SECOND_PORT_OUTPUT,
@ -172,6 +209,11 @@ void kbc_event(struct Kbc * kbc) {
}
}
break;
case 0xF3:
TRACE(" set typematic rate/delay\n");
state = KBC_STATE_TYPEMATIC;
kbc_keyboard(kbc, 0xFA, KBC_TIMEOUT);
break;
case 0xF4:
TRACE(" enable scanning\n");
kbscan_enabled = true;
@ -228,6 +270,21 @@ void kbc_event(struct Kbc * kbc) {
#endif
kbc_keyboard(kbc, 0xFA, KBC_TIMEOUT);
break;
case KBC_STATE_TYPEMATIC:
TRACE(" set typematic rate/delay\n");
state = KBC_STATE_NORMAL;
{
// Rate: bits 0-4
uint16_t period = kbc_typematic_period[data & 0x1F];
kbscan_repeat_period = period;
// Delay: bits 5-6
static const uint16_t delay[4] = {250, 500, 750, 1000};
uint8_t idx = (data & 0x60) >> 5;
kbscan_repeat_delay = delay[idx];
}
kbc_keyboard(kbc, 0xFA, KBC_TIMEOUT);
break;
case KBC_STATE_WRITE_PORT:
TRACE(" write port byte\n");
state = KBC_STATE_NORMAL;

View File

@ -10,6 +10,8 @@
#include <common/debug.h>
bool kbscan_enabled = false;
uint16_t kbscan_repeat_period = 91;
uint16_t kbscan_repeat_delay = 500;
uint8_t sci_extra = 0;
@ -231,7 +233,7 @@ void kbscan_event(void) {
if (time < repeat_key_time) {
// Overflow, reset repeat_key_time
repeat_key_time = time;
} else if ((time - repeat_key_time) >= 500) {
} else if ((time - repeat_key_time) >= kbscan_repeat_delay) {
// Typematic repeat
repeat = true;
repeat_start = time;
@ -239,8 +241,7 @@ void kbscan_event(void) {
}
if (repeat) {
// FIXME: resend key at typematic rate
if ((time - repeat_start) > 60) {
if ((time - repeat_start) > kbscan_repeat_period) {
kbscan_press(repeat_key, true, &layer);
repeat_start = time;
}