Detect and ignore the HID keyboard "phantom condition" (excessive roll-over).

This commit is contained in:
Martin Whitaker 2022-05-01 22:40:42 +01:00
parent ddaa8bff3f
commit 260c113bb2
6 changed files with 21 additions and 12 deletions

View File

@ -458,8 +458,9 @@ static void poll_keyboards(const usb_hcd_t *hcd)
uint8_t error_mask = EHCI_QTD_HALTED | EHCI_QTD_DB_ERR | EHCI_QTD_BABBLE | EHCI_QTD_TR_ERR | EHCI_QTD_MMF | EHCI_QTD_PS;
if (~status & error_mask) {
hid_kbd_rpt_t *prev_kbd_rpt = &ws->prev_kbd_rpt[kbd_idx];
process_usb_keyboard_report(hcd, kbd_rpt, prev_kbd_rpt);
*prev_kbd_rpt = *kbd_rpt;
if (process_usb_keyboard_report(hcd, kbd_rpt, prev_kbd_rpt)) {
*prev_kbd_rpt = *kbd_rpt;
}
}
ehci_qhd_t *kbd_qhd = &ws->qhd[1 + kbd_idx];

View File

@ -376,8 +376,9 @@ static void poll_keyboards(const usb_hcd_t *hcd)
if ((td->control & OHCI_TD_CC) == OHCI_TD_CC_NO_ERR) {
hid_kbd_rpt_t *prev_kbd_rpt = &ws->prev_kbd_rpt[kbd_idx];
process_usb_keyboard_report(hcd, kbd_rpt, prev_kbd_rpt);
*prev_kbd_rpt = *kbd_rpt;
if (process_usb_keyboard_report(hcd, kbd_rpt, prev_kbd_rpt)) {
*prev_kbd_rpt = *kbd_rpt;
}
}
ohci_td_t *next_td = (ohci_td_t *)((uintptr_t)td->next_td);

View File

@ -391,8 +391,9 @@ static void poll_keyboards(const usb_hcd_t *hcd)
uint32_t error_mask = UHCI_TD_STALLED | UHCI_TD_DB_ERR | UHCI_TD_BABBLE | UHCI_TD_NAK_RX | UHCI_TD_CRC_TO | UHCI_TD_BS_ERR;
if (~status & error_mask) {
hid_kbd_rpt_t *prev_kbd_rpt = &ws->prev_kbd_rpt[kbd_idx];
process_usb_keyboard_report(hcd, kbd_rpt, prev_kbd_rpt);
*prev_kbd_rpt = *kbd_rpt;
if (process_usb_keyboard_report(hcd, kbd_rpt, prev_kbd_rpt)) {
*prev_kbd_rpt = *kbd_rpt;
}
write32(&kbd_td->token, read32(&kbd_td->token) ^ UHCI_TD_DT(1));
}

View File

@ -679,13 +679,14 @@ bool find_attached_usb_keyboards(const usb_hcd_t *hcd, const usb_hub_t *hub, int
return keyboard_found;
}
void process_usb_keyboard_report(const usb_hcd_t *hcd, hid_kbd_rpt_t *report, hid_kbd_rpt_t *prev_report)
bool process_usb_keyboard_report(const usb_hcd_t *hcd, hid_kbd_rpt_t *report, hid_kbd_rpt_t *prev_report)
{
hcd_workspace_t *ws = hcd->ws;
int error_count = 0;
for (int i = 0; i < 6; i++) {
uint8_t key_code = report->key_code[i];
if (key_code != 0) {
if (key_code > 0x03) {
// Check if we've already seen this key press.
for (int j = 0; j < 6; j++) {
if (prev_report->key_code[j] == key_code) {
@ -702,8 +703,11 @@ void process_usb_keyboard_report(const usb_hcd_t *hcd, hid_kbd_rpt_t *report, hi
ws->kc_index_i = kc_index_n;
}
}
} else if (key_code != 0x00) {
error_count++;
}
}
return error_count < 6;
}
//------------------------------------------------------------------------------

View File

@ -269,11 +269,12 @@ bool find_attached_usb_keyboards(const usb_hcd_t *hcd, const usb_hub_t *hub, int
/**
* Scans the latest keyboard report from a HID keyboard for key presses that
* weren't present in the previous report from that keyboard. Appends the HID
* key code for each new key press to the driver's key code buffer.
* key code for each new key press to the driver's key code buffer. Returns
* false if the report signals the phantom condition, otherwise returns true.
*
* Used internally by the various HCI drivers.
*/
void process_usb_keyboard_report(const usb_hcd_t *hcd, hid_kbd_rpt_t *report, hid_kbd_rpt_t *prev_report);
bool process_usb_keyboard_report(const usb_hcd_t *hcd, hid_kbd_rpt_t *report, hid_kbd_rpt_t *prev_report);
/**
* Scans the attached USB devices and initialises all HID keyboard devices

View File

@ -893,8 +893,9 @@ static void poll_keyboards(const usb_hcd_t *hcd)
hid_kbd_rpt_t *kbd_rpt = &ws->kbd_rpt[kbd_idx];
hid_kbd_rpt_t *prev_kbd_rpt = &ws->prev_kbd_rpt[kbd_idx];
process_usb_keyboard_report(hcd, kbd_rpt, prev_kbd_rpt);
*prev_kbd_rpt = *kbd_rpt;
if (process_usb_keyboard_report(hcd, kbd_rpt, prev_kbd_rpt)) {
*prev_kbd_rpt = *kbd_rpt;
}
ep_tr_t *kbd_tr = &ws->kbd_tr[kbd_idx];
issue_normal_trb(kbd_tr, kbd_rpt, XHCI_TRB_DIR_IN, sizeof(hid_kbd_rpt_t));