Skip to content

Commit 54a7a3e

Browse files
feat(usb_hid_keyboard): Adds Keyboard Layout and Sends reports just for Modifier Keys (espressif#10591)
* feat(usb_kb): add keyboard layouts. new pt_br layout * feat(usb_kb): add kb layout and fixes modifier key press * feat(usb_kb): update cmakelists.txt to add new kb layout code * ci(pre-commit): Apply automatic fixes --------- Co-authored-by: pre-commit-ci-lite[bot] <117423508+pre-commit-ci-lite[bot]@users.noreply.github.com>
1 parent 1a8e53f commit 54a7a3e

23 files changed

+1835
-148
lines changed

Diff for: CMakeLists.txt

+10
Original file line numberDiff line numberDiff line change
@@ -205,6 +205,16 @@ set(ARDUINO_LIBRARY_USB_SRCS
205205
libraries/USB/src/USBMIDI.cpp
206206
libraries/USB/src/USBHIDMouse.cpp
207207
libraries/USB/src/USBHIDKeyboard.cpp
208+
libraries/USB/src/keyboardLayout/KeyboardLayout_da_DK.cpp
209+
libraries/USB/src/keyboardLayout/KeyboardLayout_de_DE.cpp
210+
libraries/USB/src/keyboardLayout/KeyboardLayout_en_US.cpp
211+
libraries/USB/src/keyboardLayout/KeyboardLayout_es_ES.cpp
212+
libraries/USB/src/keyboardLayout/KeyboardLayout_fr_FR.cpp
213+
libraries/USB/src/keyboardLayout/KeyboardLayout_hu_HU.cpp
214+
libraries/USB/src/keyboardLayout/KeyboardLayout_it_IT.cpp
215+
libraries/USB/src/keyboardLayout/KeyboardLayout_pt_BR.cpp
216+
libraries/USB/src/keyboardLayout/KeyboardLayout_pt_PT.cpp
217+
libraries/USB/src/keyboardLayout/KeyboardLayout_sv_SE.cpp
208218
libraries/USB/src/USBHIDGamepad.cpp
209219
libraries/USB/src/USBHIDConsumerControl.cpp
210220
libraries/USB/src/USBHIDSystemControl.cpp

Diff for: libraries/USB/src/USBHIDKeyboard.cpp

+25-145
Original file line numberDiff line numberDiff line change
@@ -24,14 +24,15 @@
2424
#if CONFIG_TINYUSB_HID_ENABLED
2525

2626
#include "USBHIDKeyboard.h"
27+
#include "keyboardLayout/KeyboardLayout.h"
2728

2829
ESP_EVENT_DEFINE_BASE(ARDUINO_USB_HID_KEYBOARD_EVENTS);
2930
esp_err_t arduino_usb_event_post(esp_event_base_t event_base, int32_t event_id, void *event_data, size_t event_data_size, TickType_t ticks_to_wait);
3031
esp_err_t arduino_usb_event_handler_register_with(esp_event_base_t event_base, int32_t event_id, esp_event_handler_t event_handler, void *event_handler_arg);
3132

3233
static const uint8_t report_descriptor[] = {TUD_HID_REPORT_DESC_KEYBOARD(HID_REPORT_ID(HID_REPORT_ID_KEYBOARD))};
3334

34-
USBHIDKeyboard::USBHIDKeyboard() : hid(HID_ITF_PROTOCOL_KEYBOARD), shiftKeyReports(true) {
35+
USBHIDKeyboard::USBHIDKeyboard() : hid(HID_ITF_PROTOCOL_KEYBOARD), _asciimap(KeyboardLayout_en_US), shiftKeyReports(false) {
3536
static bool initialized = false;
3637
if (!initialized) {
3738
initialized = true;
@@ -45,7 +46,8 @@ uint16_t USBHIDKeyboard::_onGetDescriptor(uint8_t *dst) {
4546
return sizeof(report_descriptor);
4647
}
4748

48-
void USBHIDKeyboard::begin() {
49+
void USBHIDKeyboard::begin(const uint8_t *layout) {
50+
_asciimap = layout;
4951
hid.begin();
5052
}
5153

@@ -80,139 +82,6 @@ void USBHIDKeyboard::setShiftKeyReports(bool set) {
8082
shiftKeyReports = set;
8183
}
8284

83-
#define SHIFT 0x80
84-
const uint8_t _asciimap[128] = {
85-
0x00, // NUL
86-
0x00, // SOH
87-
0x00, // STX
88-
0x00, // ETX
89-
0x00, // EOT
90-
0x00, // ENQ
91-
0x00, // ACK
92-
0x00, // BEL
93-
0x2a, // BS Backspace
94-
0x2b, // TAB Tab
95-
0x28, // LF Enter
96-
0x00, // VT
97-
0x00, // FF
98-
0x00, // CR
99-
0x00, // SO
100-
0x00, // SI
101-
0x00, // DEL
102-
0x00, // DC1
103-
0x00, // DC2
104-
0x00, // DC3
105-
0x00, // DC4
106-
0x00, // NAK
107-
0x00, // SYN
108-
0x00, // ETB
109-
0x00, // CAN
110-
0x00, // EM
111-
0x00, // SUB
112-
0x00, // ESC
113-
0x00, // FS
114-
0x00, // GS
115-
0x00, // RS
116-
0x00, // US
117-
118-
0x2c, // ' '
119-
0x1e | SHIFT, // !
120-
0x34 | SHIFT, // "
121-
0x20 | SHIFT, // #
122-
0x21 | SHIFT, // $
123-
0x22 | SHIFT, // %
124-
0x24 | SHIFT, // &
125-
0x34, // '
126-
0x26 | SHIFT, // (
127-
0x27 | SHIFT, // )
128-
0x25 | SHIFT, // *
129-
0x2e | SHIFT, // +
130-
0x36, // ,
131-
0x2d, // -
132-
0x37, // .
133-
0x38, // /
134-
0x27, // 0
135-
0x1e, // 1
136-
0x1f, // 2
137-
0x20, // 3
138-
0x21, // 4
139-
0x22, // 5
140-
0x23, // 6
141-
0x24, // 7
142-
0x25, // 8
143-
0x26, // 9
144-
0x33 | SHIFT, // :
145-
0x33, // ;
146-
0x36 | SHIFT, // <
147-
0x2e, // =
148-
0x37 | SHIFT, // >
149-
0x38 | SHIFT, // ?
150-
0x1f | SHIFT, // @
151-
0x04 | SHIFT, // A
152-
0x05 | SHIFT, // B
153-
0x06 | SHIFT, // C
154-
0x07 | SHIFT, // D
155-
0x08 | SHIFT, // E
156-
0x09 | SHIFT, // F
157-
0x0a | SHIFT, // G
158-
0x0b | SHIFT, // H
159-
0x0c | SHIFT, // I
160-
0x0d | SHIFT, // J
161-
0x0e | SHIFT, // K
162-
0x0f | SHIFT, // L
163-
0x10 | SHIFT, // M
164-
0x11 | SHIFT, // N
165-
0x12 | SHIFT, // O
166-
0x13 | SHIFT, // P
167-
0x14 | SHIFT, // Q
168-
0x15 | SHIFT, // R
169-
0x16 | SHIFT, // S
170-
0x17 | SHIFT, // T
171-
0x18 | SHIFT, // U
172-
0x19 | SHIFT, // V
173-
0x1a | SHIFT, // W
174-
0x1b | SHIFT, // X
175-
0x1c | SHIFT, // Y
176-
0x1d | SHIFT, // Z
177-
0x2f, // [
178-
0x31, // bslash
179-
0x30, // ]
180-
0x23 | SHIFT, // ^
181-
0x2d | SHIFT, // _
182-
0x35, // `
183-
0x04, // a
184-
0x05, // b
185-
0x06, // c
186-
0x07, // d
187-
0x08, // e
188-
0x09, // f
189-
0x0a, // g
190-
0x0b, // h
191-
0x0c, // i
192-
0x0d, // j
193-
0x0e, // k
194-
0x0f, // l
195-
0x10, // m
196-
0x11, // n
197-
0x12, // o
198-
0x13, // p
199-
0x14, // q
200-
0x15, // r
201-
0x16, // s
202-
0x17, // t
203-
0x18, // u
204-
0x19, // v
205-
0x1a, // w
206-
0x1b, // x
207-
0x1c, // y
208-
0x1d, // z
209-
0x2f | SHIFT, // {
210-
0x31 | SHIFT, // |
211-
0x30 | SHIFT, // }
212-
0x35 | SHIFT, // ~
213-
0 // DEL
214-
};
215-
21685
size_t USBHIDKeyboard::pressRaw(uint8_t k) {
21786
uint8_t i;
21887
if (k >= 0xE0 && k < 0xE8) {
@@ -234,7 +103,7 @@ size_t USBHIDKeyboard::pressRaw(uint8_t k) {
234103
return 0;
235104
}
236105
}
237-
} else {
106+
} else if (_keyReport.modifiers == 0) {
238107
//not a modifier and not a key
239108
return 0;
240109
}
@@ -255,11 +124,8 @@ size_t USBHIDKeyboard::releaseRaw(uint8_t k) {
255124
_keyReport.keys[i] = 0x00;
256125
}
257126
}
258-
} else {
259-
//not a modifier and not a key
260-
return 0;
261127
}
262-
128+
// Allowing for the release of a modifier key without a corresponding press
263129
sendReport(&_keyReport);
264130
return 1;
265131
}
@@ -274,19 +140,26 @@ size_t USBHIDKeyboard::press(uint8_t k) {
274140
} else if (k >= 0x80) { // it's a modifier key
275141
_keyReport.modifiers |= (1 << (k - 0x80));
276142
k = 0;
277-
} else { // it's a printing key
143+
} else { // it's a printing key (k is a ASCII 0..127)
278144
k = _asciimap[k];
279145
if (!k) {
280146
return 0;
281147
}
282-
if (k & 0x80) { // it's a capital letter or other character reached with shift
148+
if ((k & SHIFT) == SHIFT) { // it's a capital letter or other character reached with shift
283149
// At boot, some PCs need a separate report with the shift key down like a real keyboard.
284150
if (shiftKeyReports) {
285151
pressRaw(HID_KEY_SHIFT_LEFT);
286152
} else {
287153
_keyReport.modifiers |= 0x02; // the left shift modifier
288154
}
289-
k &= 0x7F;
155+
k &= ~SHIFT;
156+
}
157+
if ((k & ALT_GR) == ALT_GR) {
158+
_keyReport.modifiers |= 0x40; // AltGr = right Alt
159+
k &= ~ALT_GR;
160+
}
161+
if (k == ISO_REPLACEMENT) {
162+
k = ISO_KEY;
290163
}
291164
}
292165
return pressRaw(k);
@@ -306,15 +179,22 @@ size_t USBHIDKeyboard::release(uint8_t k) {
306179
if (!k) {
307180
return 0;
308181
}
309-
if (k & 0x80) { // it's a capital letter or other character reached with shift
182+
if ((k & SHIFT) == SHIFT) { // it's a capital letter or other character reached with shift
310183
if (shiftKeyReports) {
311184
releaseRaw(k & 0x7F); // Release key without shift modifier
312185
k = HID_KEY_SHIFT_LEFT; // Below, release shift modifier
313186
} else {
314187
_keyReport.modifiers &= ~(0x02); // the left shift modifier
315-
k &= 0x7F;
188+
k &= ~SHIFT;
316189
}
317190
}
191+
if ((k & ALT_GR) == ALT_GR) {
192+
_keyReport.modifiers &= ~(0x40); // AltGr = right Alt
193+
k &= ~ALT_GR;
194+
}
195+
if (k == ISO_REPLACEMENT) {
196+
k = ISO_KEY;
197+
}
318198
}
319199
return releaseRaw(k);
320200
}

Diff for: libraries/USB/src/USBHIDKeyboard.h

+34-3
Original file line numberDiff line numberDiff line change
@@ -50,20 +50,32 @@ typedef union {
5050
uint8_t leds;
5151
} arduino_usb_hid_keyboard_event_data_t;
5252

53+
// Supported keyboard layouts
54+
extern const uint8_t KeyboardLayout_de_DE[];
55+
extern const uint8_t KeyboardLayout_en_US[];
56+
extern const uint8_t KeyboardLayout_es_ES[];
57+
extern const uint8_t KeyboardLayout_fr_FR[];
58+
extern const uint8_t KeyboardLayout_it_IT[];
59+
extern const uint8_t KeyboardLayout_pt_PT[];
60+
extern const uint8_t KeyboardLayout_sv_SE[];
61+
extern const uint8_t KeyboardLayout_da_DK[];
62+
extern const uint8_t KeyboardLayout_hu_HU[];
63+
extern const uint8_t KeyboardLayout_pt_BR[];
64+
5365
#define KEY_LEFT_CTRL 0x80
5466
#define KEY_LEFT_SHIFT 0x81
5567
#define KEY_LEFT_ALT 0x82
5668
#define KEY_LEFT_GUI 0x83
5769
#define KEY_RIGHT_CTRL 0x84
5870
#define KEY_RIGHT_SHIFT 0x85
59-
#define KEY_RIGHT_ALT 0x86
71+
#define KEY_RIGHT_ALT 0x86 // AltGr (Right Alt) Key
6072
#define KEY_RIGHT_GUI 0x87
6173

6274
#define KEY_UP_ARROW 0xDA
6375
#define KEY_DOWN_ARROW 0xD9
6476
#define KEY_LEFT_ARROW 0xD8
6577
#define KEY_RIGHT_ARROW 0xD7
66-
#define KEY_MENU 0xFE
78+
#define KEY_MENU 0xED // "Keyboard Application" in USB standard
6779
#define KEY_SPACE 0x20
6880
#define KEY_BACKSPACE 0xB2
6981
#define KEY_TAB 0xB3
@@ -111,6 +123,24 @@ typedef union {
111123
#define LED_COMPOSE 0x08
112124
#define LED_KANA 0x10
113125

126+
// Numeric keypad
127+
#define KEY_KP_SLASH 0xDC
128+
#define KEY_KP_ASTERISK 0xDD
129+
#define KEY_KP_MINUS 0xDE
130+
#define KEY_KP_PLUS 0xDF
131+
#define KEY_KP_ENTER 0xE0
132+
#define KEY_KP_1 0xE1
133+
#define KEY_KP_2 0xE2
134+
#define KEY_KP_3 0xE3
135+
#define KEY_KP_4 0xE4
136+
#define KEY_KP_5 0xE5
137+
#define KEY_KP_6 0xE6
138+
#define KEY_KP_7 0xE7
139+
#define KEY_KP_8 0xE8
140+
#define KEY_KP_9 0xE9
141+
#define KEY_KP_0 0xEA
142+
#define KEY_KP_DOT 0xEB
143+
114144
// Low level key report: up to 6 keys and shift, ctrl etc at once
115145
typedef struct {
116146
uint8_t modifiers;
@@ -122,11 +152,12 @@ class USBHIDKeyboard : public USBHIDDevice, public Print {
122152
private:
123153
USBHID hid;
124154
KeyReport _keyReport;
155+
const uint8_t *_asciimap;
125156
bool shiftKeyReports;
126157

127158
public:
128159
USBHIDKeyboard(void);
129-
void begin(void);
160+
void begin(const uint8_t *layout = KeyboardLayout_en_US);
130161
void end(void);
131162
size_t write(uint8_t k);
132163
size_t write(const uint8_t *buffer, size_t size);

0 commit comments

Comments
 (0)