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

Fixed NKRO issue caused by HID_SET_PROTOCOL on Chibios platform #17588

Merged
merged 2 commits into from
Dec 8, 2022

Conversation

lokher
Copy link
Contributor

@lokher lokher commented Jul 7, 2022

Description

NKRO is forced to turn on by mistake when receiving HID_SET_PROTOCOL.

Types of Changes

  • Core
  • Bugfix
  • New feature
  • Enhancement/optimization
  • Keyboard (addition or update)
  • Keymap/layout/userspace (addition or update)
  • Documentation

Issues Fixed or Closed by This PR

Checklist

  • My code follows the code style of this project: C, Python
  • I have read the PR Checklist document and have made the appropriate changes.
  • My change requires a change to the documentation.
  • I have updated the documentation accordingly.
  • I have read the CONTRIBUTING document.
  • I have added tests to cover my changes.
  • I have tested the changes and verified that they work and don't break anything (as well as I can manage).

Fixed zero length hid interrupt report issue at endpoint other than EP0
@github-actions github-actions bot added the core label Jul 7, 2022
@tzarc tzarc requested a review from a team July 7, 2022 21:41
@drashna drashna requested a review from fauxpark July 7, 2022 21:53
tzarc
tzarc previously approved these changes Aug 13, 2022
@tzarc
Copy link
Member

tzarc commented Aug 13, 2022

Weak approval, untested.

@sigprof
Copy link
Contributor

sigprof commented Aug 13, 2022

Looks like there are two separate fixes here:

  1. The tmk_core/protocol/chibios/usb_main.c change looks correct (there might be other problems nearby — e.g., the idle handling apparently should not be constrained to the boot protocol, but that's a different problem, and might not be important in practice if real OSes don't use SET_IDLE with keyboard devices).
  2. The tmk_core/protocol/chibios/usb_driver.c change apparently removes sending of zero-length packets for non-bulk endpoints. This might not be 100% correct — the HID spec says that if an interface uses multiple reports, the longest of those reports does not require a short packet terminator even if its length is a multiple of wMaxPacketSize, but any shorter reports require such terminator, and that might be a zero-length packet if the length of some shorter report happens to be a multiple of wMaxPacketSize. However, I'm not sure whether QMK can trigger this case currently.

@lokher
Copy link
Contributor Author

lokher commented Aug 14, 2022

Looks like there are two separate fixes here:

  1. The tmk_core/protocol/chibios/usb_main.c change looks correct (there might be other problems nearby — e.g., the idle handling apparently should not be constrained to the boot protocol, but that's a different problem, and might not be important in practice if real OSes don't use SET_IDLE with keyboard devices).
  2. The tmk_core/protocol/chibios/usb_driver.c change apparently removes sending of zero-length packets for non-bulk endpoints. This might not be 100% correct — the HID spec says that if an interface uses multiple reports, the longest of those reports does not require a short packet terminator even if its length is a multiple of wMaxPacketSize, but any shorter reports require such terminator, and that might be a zero-length packet if the length of some shorter report happens to be a multiple of wMaxPacketSize. However, I'm not sure whether QMK can trigger this case currently.

I did some more research, something is ambiguous in USB spec, but seems zero-length packet is not an issue, I will remove the change of zero length packet.

5.7.3 Interrupt Transfer Packet Size Constraints
An interrupt transfer is complete when the endpoint does one of the following:`

  • Has transferred exactly the amount of data expected
  • Transfers a packet with a payload size less than wMaxPacketSize or transfers a zero-length packet

When an interrupt transfer is complete, the Host Controller retires the current IRP and advances to the next IRP. If a data payload is received that is larger than expected, the interrupt IRP will be aborted/retired and the pipe will stall future IRPs until the condition is corrected and acknowledged.

5.8.3 Bulk Transfer Packet Size Constraints
A bulk transfer is complete when the endpoint does one of the following:

  • Has transferred exactly the amount of data expected
  • Transfers a packet with a payload size less than wMaxPacketSize or transfers a zero-length packet

When a bulk transfer is complete, the Host Controller retires the current IRP and advances to the next IRP. If a data payload is received that is larger than expected, all pending bulk IRPs for that endpoint will be aborted/retired."

@tzarc tzarc added the bug label Aug 14, 2022
Copy link
Member

@drashna drashna left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Been using, doesn't seem to break anything, at least.

@drashna drashna requested a review from a team August 25, 2022 17:04
Copy link
Member

@fauxpark fauxpark left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

keymap_config.nkro should follow the SET_PROTOCOL request, so I think this change is wrong.
https://wiki.osdev.org/USB_Human_Interface_Devices#.22SetProtocol.22_request

@tzarc tzarc dismissed their stale review August 26, 2022 01:22

faux's comment seems to point towards it being incorrect, revoking

@lokher
Copy link
Contributor Author

lokher commented Aug 26, 2022

keymap_config.nkro should follow the SET_PROTOCOL request, so I think this change is wrong. https://wiki.osdev.org/USB_Human_Interface_Devices#.22SetProtocol.22_request

keyboard_protocol is set according to SET_PROTOCOL request. keyboard_protocol and keymap_config.nkro value in void host_keyboard_send(report_keyboard_t *report) determine if nkro report is to be sent:

if (keyboard_protocol && keymap_config.nkro) {
/* The callers of this function assume that report->mods is where mods go in.
* But report->nkro.mods can be at a different offset if core keyboard does not have a report ID.
*/
report->nkro.mods = report->mods;
report->nkro.report_id = REPORT_ID_NKRO;
} else
#endif
{
#ifdef KEYBOARD_SHARED_EP
report->report_id = REPORT_ID_KEYBOARD;

Current issue is if the keymap_config.nkro is initially disabled, SET_PROTOCOL request during USB enumeration or OS boot will enable it automaticlly which is buggy.

@tzarc
Copy link
Member

tzarc commented Nov 13, 2022

Move to next quarter for a day-one merge. Can sort out the problems during the develop cycle.

Copy link
Member

@tzarc tzarc left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As previously mentioned -- tested and found no issue. Giving the develop cycle a chance to iron out issues with other people.

@tzarc tzarc merged commit 0d7edbb into qmk:develop Dec 8, 2022
@KeychronMacro KeychronMacro deleted the fix_nkro branch December 12, 2022 03:05
@KeychronMacro KeychronMacro restored the fix_nkro branch December 12, 2022 03:06
@sigprof sigprof mentioned this pull request Dec 18, 2022
14 tasks
omikronik pushed a commit to omikronik/qmk_firmware that referenced this pull request Jan 22, 2023
@lokher lokher deleted the fix_nkro branch August 12, 2024 02:57
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants