You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
There is a bug in the USBHIDKeyboard.cpp source file that will not allow just modifier keys to be sent in an HID report. This means that, for example, if shift is being held, the computer will only know that when another key is pushed. This also means the only way shift can be released on the computer side is if shift is released on the keyboard while another key is being pressed. I hope that makes sense.
This also causes issues in games like CS2 where crouch is set to control but a crouch command is not send until another key is pushed and this also causes some very strange behavior.
In the source code you can see that if a modifier is pressed with USBHIDKeyboard::press it is stored in the keyreport and then it calls pressRaw(). The issue is in pressedRaw() is looking for a modifier in the range of 0xE0-0xE8(these are keypad numbers?) but shift(0x80) is not in that range nor are any other modifiers so pressRaw() will just return 0 without sending the keyreport. Additionally pressRaw() should not be trying to store modifiers in the keyreport since press() already did. I'm not sure what the right fix should be but for my use case if I comment out return 0 in pressRaw and releaseRaw this solves the problem(but also makes it possible to send invalid keys commands-ill just be careful lol).
Sketch
size_tUSBHIDKeyboard::pressRaw(uint8_t k) {
uint8_t i;
if (k >= 0xE0 && k < 0xE8) {
// it's a modifier key
_keyReport.modifiers |= (1 << (k - 0xE0));
} elseif (k && k < 0xA5) {
// Add k to the key report only if it's not already present// and if there is an empty slot.if (_keyReport.keys[0] != k && _keyReport.keys[1] != k && _keyReport.keys[2] != k && _keyReport.keys[3] != k && _keyReport.keys[4] != k
&& _keyReport.keys[5] != k) {
for (i = 0; i < 6; i++) {
if (_keyReport.keys[i] == 0x00) {
_keyReport.keys[i] = k;
break;
}
}
if (i == 6) {
return0;
}
}
} else {
//not a modifier and not a keyreturn0;
}
sendReport(&_keyReport);
return1;
}
size_tUSBHIDKeyboard::releaseRaw(uint8_t k) {
uint8_t i;
if (k >= 0xE0 && k < 0xE8) {
// it's a modifier key
_keyReport.modifiers &= ~(1 << (k - 0xE0));
} elseif (k && k < 0xA5) {
// Test the key report to see if k is present. Clear it if it exists.// Check all positions in case the key is present more than once (which it shouldn't be)for (i = 0; i < 6; i++) {
if (0 != k && _keyReport.keys[i] == k) {
_keyReport.keys[i] = 0x00;
}
}
} else {
//not a modifier and not a keyreturn0;
}
sendReport(&_keyReport);
return1;
}
// press() adds the specified key (printing, non-printing, or modifier)// to the persistent key report and sends the report. Because of the way// USB HID works, the host acts like the key remains pressed until we// call release(), releaseAll(), or otherwise clear the report and resend.size_tUSBHIDKeyboard::press(uint8_t k) {
if (k >= 0x88) { // it's a non-printing key (not a modifier)
k = k - 0x88;
} elseif (k >= 0x80) { // it's a modifier key
_keyReport.modifiers |= (1 << (k - 0x80));
k = 0;
} else { // it's a printing key
k = _asciimap[k];
if (!k) {
return0;
}
if (k & 0x80) { // it's a capital letter or other character reached with shift// At boot, some PCs need a separate report with the shift key down like a real keyboard.if (shiftKeyReports) {
pressRaw(HID_KEY_SHIFT_LEFT);
} else {
_keyReport.modifiers |= 0x02; // the left shift modifier
}
k &= 0x7F;
}
}
returnpressRaw(k);
}
// release() takes the specified key out of the persistent key report and// sends the report. This tells the OS the key is no longer pressed and that// it shouldn't be repeated any more.size_tUSBHIDKeyboard::release(uint8_t k) {
if (k >= 0x88) { // it's a non-printing key (not a modifier)
k = k - 0x88;
} elseif (k >= 0x80) { // it's a modifier key
_keyReport.modifiers &= ~(1 << (k - 0x80));
k = 0;
} else { // it's a printing key
k = _asciimap[k];
if (!k) {
return0;
}
if (k & 0x80) { // it's a capital letter or other character reached with shiftif (shiftKeyReports) {
releaseRaw(k & 0x7F); // Release key without shift modifier
k = HID_KEY_SHIFT_LEFT; // Below, release shift modifier
} else {
_keyReport.modifiers &= ~(0x02); // the left shift modifier
k &= 0x7F;
}
}
}
returnreleaseRaw(k);
}
Debug Message
No Debug messaged
Other Steps to Reproduce
Try using USBHIDKeyboard.h to send just a shift press and release and use a website like keyboardtester to see what happens, compare that with your normal keyboard and see what happens.
I have checked existing issues, online documentation and the Troubleshooting Guide
I confirm I have checked existing issues, online documentation and Troubleshooting guide.
The text was updated successfully, but these errors were encountered:
Board
esp32s2
Device Description
N/A
Hardware Configuration
N/A
Version
v3.0.4
IDE Name
Arduino IDE
Operating System
Windows 11
Flash frequency
40
PSRAM enabled
yes
Upload speed
921600
Description
There is a bug in the USBHIDKeyboard.cpp source file that will not allow just modifier keys to be sent in an HID report. This means that, for example, if shift is being held, the computer will only know that when another key is pushed. This also means the only way shift can be released on the computer side is if shift is released on the keyboard while another key is being pressed. I hope that makes sense.
This also causes issues in games like CS2 where crouch is set to control but a crouch command is not send until another key is pushed and this also causes some very strange behavior.
In the source code you can see that if a modifier is pressed with USBHIDKeyboard::press it is stored in the keyreport and then it calls pressRaw(). The issue is in pressedRaw() is looking for a modifier in the range of 0xE0-0xE8(these are keypad numbers?) but shift(0x80) is not in that range nor are any other modifiers so pressRaw() will just return 0 without sending the keyreport. Additionally pressRaw() should not be trying to store modifiers in the keyreport since press() already did. I'm not sure what the right fix should be but for my use case if I comment out return 0 in pressRaw and releaseRaw this solves the problem(but also makes it possible to send invalid keys commands-ill just be careful lol).
Sketch
Debug Message
Other Steps to Reproduce
Try using USBHIDKeyboard.h to send just a shift press and release and use a website like keyboardtester to see what happens, compare that with your normal keyboard and see what happens.
I have checked existing issues, online documentation and the Troubleshooting Guide
The text was updated successfully, but these errors were encountered: