Skip to content

Commit d08b486

Browse files
committed
Fix keyboard events occasionally being dropped
AdbKeyboard would copy the event into its own fields and set the changed field, so that we could return the event when register was 0. However, if a subsequent event was received before ADB polling, the previous event would be overwritten and lost. Fix this by maintaining a queue of events, so that we can return everything since the last poll.
1 parent d37d83c commit d08b486

File tree

2 files changed

+36
-32
lines changed

2 files changed

+36
-32
lines changed

devices/common/adb/adbkeyboard.cpp

Lines changed: 32 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -34,47 +34,50 @@ AdbKeyboard::AdbKeyboard(std::string name) : AdbDevice(name) {
3434
}
3535

3636
void AdbKeyboard::event_handler(const KeyboardEvent& event) {
37-
this->key = event.key;
38-
if (event.flags & KEYBOARD_EVENT_DOWN) {
39-
this->key_state = 0;
40-
}
41-
else if (event.flags & KEYBOARD_EVENT_UP) {
42-
this->key_state = 1;
43-
}
44-
this->changed = true;
37+
this->pending_events.push_back(std::make_unique<KeyboardEvent>(event));
4538
}
4639

4740
void AdbKeyboard::reset() {
4841
this->my_addr = ADB_ADDR_KBD;
4942
this->dev_handler_id = 2; // Extended ADB keyboard
5043
this->exc_event_flag = 1;
5144
this->srq_flag = 1; // enable service requests
52-
this->key = 0;
53-
this->key_state = 0;
54-
this->changed = false;
45+
this->pending_events.clear();
5546
}
5647

5748
bool AdbKeyboard::get_register_0() {
58-
if (this->changed) {
59-
uint8_t* out_buf = this->host_obj->get_output_buf();
60-
61-
out_buf[0] = (this->key_state << 7) | (this->key & 0x7F);
62-
// It's possible that we get two events before the host polls us, but
63-
// in practice it has not come up. We need to set the key status bit to
64-
// 1 (released), and the key to a non-existent one (0x7F). Otherwise if
65-
// we leave it empty, the host will think that the 'a' key (code 0) is
66-
// pressed.
67-
out_buf[1] = 0xFF;
68-
69-
this->key = 0;
70-
this->key_state = 0;
71-
this->changed = false;
72-
73-
this->host_obj->set_output_count(2);
74-
return true;
49+
if (this->pending_events.empty()) {
50+
return false;
51+
}
52+
uint8_t* out_buf = this->host_obj->get_output_buf();
53+
out_buf[0] = this->consume_pending_event();
54+
out_buf[1] = this->consume_pending_event();
55+
this->host_obj->set_output_count(2);
56+
return true;
57+
}
58+
59+
uint8_t AdbKeyboard::consume_pending_event() {
60+
if (this->pending_events.empty()) {
61+
// In most cases we have only on pending event when the host polls us,
62+
// but we need to fill two entries of the output buffer. We need to set
63+
// the key status bit to 1 (released), and the key to a non-existent
64+
// one (0x7F). Otherwise if we leave it empty, the host will think that
65+
// the 'a' key (code 0) is pressed (status 0).
66+
return 0xFF;
67+
}
68+
std::unique_ptr<KeyboardEvent> event = std::move(this->pending_events.front());
69+
this->pending_events.pop_front();
70+
71+
uint8_t key_state = 0;
72+
if (event->flags & KEYBOARD_EVENT_DOWN) {
73+
key_state = 0;
74+
} else if (event->flags & KEYBOARD_EVENT_UP) {
75+
key_state = 1;
76+
} else {
77+
LOG_F(WARNING, "%s: unknown keyboard event flags %x", this->name.c_str(), event->flags);
7578
}
7679

77-
return false;
80+
return (key_state << 7) | (event->key & 0x7F);
7881
}
7982

8083
void AdbKeyboard::set_register_2() {

devices/common/adb/adbkeyboard.h

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ along with this program. If not, see <https://www.gnu.org/licenses/>.
2727
#include <devices/common/adb/adbdevice.h>
2828
#include <devices/common/hwcomponent.h>
2929

30+
#include <deque>
3031
#include <memory>
3132
#include <string>
3233

@@ -50,9 +51,9 @@ class AdbKeyboard : public AdbDevice {
5051

5152

5253
private:
53-
uint32_t key = 0;
54-
uint8_t key_state = 0;
55-
bool changed = false;
54+
std::deque<std::unique_ptr<KeyboardEvent>> pending_events;
55+
56+
uint8_t consume_pending_event();
5657
};
5758

5859
// ADB Extended Keyboard raw key codes (most of which eventually became virtual

0 commit comments

Comments
 (0)