Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Remove resetting of key states after sending a report #9

Merged
merged 2 commits into from
May 28, 2024

Conversation

lonesometraveler
Copy link
Contributor

This pull request aims to improve the behavior of the keyboard events. Currently, the report.keycodes is being cleared immediately after sending a report. However, this approach can lead to the loss of the current state of pressed keys, hindering the ability to handle multiple key presses.

The proposed change removes the resetting of report.keycodes after sending a report. By retaining the current state of pressed keys until they are released, we ensure that the report.keycodes accurately reflects the keyboard's state, enabling better management of key presses and releases.

@HaoboGu
Copy link
Owner

HaoboGu commented Mar 15, 2024

This few lines cancel previous pressed key if there is a new key stroke. It prevents a rare case that one key is kept pressed forever when somehow the release report is not sent successfully.

Theoretically it has nothing bad for multi-key processing because the keyboard actually holds a keystate matrix which always reflects the real state of matrix scanning.

@lonesometraveler
Copy link
Contributor Author

Maybe I should explain my use case. I'm using a custom keyboard as a joystick for playing games. Currently, it is not possible to press "N" (jump key) while pressing "D" (move-to-right key). This is because the matrix doesn't accurately reflect the current state of the pressed keys.

Here's what is happening:

When "D" is pressed

  • The report ["D", 0, 0, 0, 0, 0] is sent
  • The local keycodes are cleared [0, 0, 0, 0, 0, 0]
  • The host still thinks "D" is pressed.

When "N" is pressed,

  • "N" is added to the keycodes and the report ["N", 0, 0, 0, 0, 0] is sent.
  • "D" is ignored because key_state is not changed (still held down).
  • Since "D" is not in the report, the host assumes "D" is released, and "N" is pressed.

@HaoboGu
Copy link
Owner

HaoboGu commented Mar 15, 2024

Ah, that's normal for a keyboard IMO. I just tried on my macbook's keyboard: first I pressed "N" and held, "N" was kept triggered. Then I tapped "D" while "N" was pressed. In this case "N" was cancelled.

You could also try your own keyboard to verify this. I don't know much about joysticks, so in your case this behavior might be not expected. That makes sense.

@lonesometraveler
Copy link
Contributor Author

Each application processes reports differently, so one app's behavior does not necessarily reflect the standard HID behavior. We should evaluate the debug outputs and see how the reports look like. I believe adhering to the HID protocol involves changing registered values to 0 only when the corresponding keys are released.

If our concern is preventing keys from getting stuck, resetting keycodes each cycle makes sense. But if we do that, we should adjust how we read the matrix. We need to ensure that held-down keys are reinserted into the keycodes along with newly pressed keys.

@HaoboGu
Copy link
Owner

HaoboGu commented Mar 15, 2024

If our concern is preventing keys from getting stuck, resetting keycodes each cycle makes sense. But if we do that, we should adjust how we read the matrix. We need to ensure that held-down keys are reinserted into the keycodes along with newly pressed keys.

Agreed, do you have time to take a look? I'm doing some refactoring about storage/keymap, after that I could get some time on this issue.

@lonesometraveler
Copy link
Contributor Author

Since one of my projects now relies on this crate, improving it is my priority. 😀

I need to study the codebase first, and I may send small PRs as I learn. Some of them may not seem directly related to this issue, but please understand that this is how I learn a new codebase.

@lonesometraveler
Copy link
Contributor Author

This few lines cancel previous pressed key if there is a new key stroke. It prevents a rare case that one key is kept pressed forever when somehow the release report is not sent successfully.

Shouldn't we try to resend the report if it fails? I've made a commit demonstrating that. Currently, write_serialize suppresses errors without propagating them. However, by propagating errors, we could implement retry logic, as shown in the code. Wouldn't this address our concern about keys getting stuck?

@HaoboGu
Copy link
Owner

HaoboGu commented Mar 17, 2024

write_serialize returns error when there is an error of writing stage. I guess the reason of stuck keys might due to packet loss in transmission(especially for BLE). In this case, writing is successful.

For example, when writing via USB, write_serialize returns errors in only two situations: BufferOverflow and UsbDisabled, both of them couldn't be solved by retrying.

@HaoboGu
Copy link
Owner

HaoboGu commented May 28, 2024

I'm doing some refactoring to improve it. I'm merging it first. Thanks @lonesometraveler !

@HaoboGu HaoboGu merged commit 5459e38 into HaoboGu:main May 28, 2024
1 check passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

2 participants