Skip to content

Commit 6cb95d7

Browse files
authored
Add LED Reporting support to Keyboard emulation.
Relies on pull request for HID in the ArduinoCore-avr #358 ( arduino/ArduinoCore-avr#358 )
1 parent 716d286 commit 6cb95d7

File tree

2 files changed

+64
-30
lines changed

2 files changed

+64
-30
lines changed

src/Keyboard.cpp

Lines changed: 57 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -35,32 +35,42 @@ static const uint8_t _hidReportDescriptor[] PROGMEM = {
3535
0xa1, 0x01, // COLLECTION (Application)
3636
0x85, 0x02, // REPORT_ID (2)
3737
0x05, 0x07, // USAGE_PAGE (Keyboard)
38-
38+
3939
0x19, 0xe0, // USAGE_MINIMUM (Keyboard LeftControl)
4040
0x29, 0xe7, // USAGE_MAXIMUM (Keyboard Right GUI)
4141
0x15, 0x00, // LOGICAL_MINIMUM (0)
4242
0x25, 0x01, // LOGICAL_MAXIMUM (1)
4343
0x75, 0x01, // REPORT_SIZE (1)
44-
44+
4545
0x95, 0x08, // REPORT_COUNT (8)
4646
0x81, 0x02, // INPUT (Data,Var,Abs)
4747
0x95, 0x01, // REPORT_COUNT (1)
4848
0x75, 0x08, // REPORT_SIZE (8)
4949
0x81, 0x03, // INPUT (Cnst,Var,Abs)
50-
50+
51+
0x95, 0x05, // REPORT_COUNT (5)
52+
0x75, 0x01, // REPORT_SIZE (1)
53+
0x05, 0x08, // USAGE_PAGE (LEDs)
54+
0x19, 0x01, // USAGE_MINIMUM (1)
55+
0x29, 0x05, // USAGE_MAXIMUM (5)
56+
0x91, 0x02, // OUTPUT (Data,Var,Abs) // LED report
57+
0x95, 0x01, // REPORT_COUNT (1)
58+
0x75, 0x03, // REPORT_SIZE (3)
59+
0x91, 0x01, // OUTPUT (Constant) // padding
60+
5161
0x95, 0x06, // REPORT_COUNT (6)
5262
0x75, 0x08, // REPORT_SIZE (8)
5363
0x15, 0x00, // LOGICAL_MINIMUM (0)
5464
0x25, 0x73, // LOGICAL_MAXIMUM (115)
5565
0x05, 0x07, // USAGE_PAGE (Keyboard)
56-
66+
5767
0x19, 0x00, // USAGE_MINIMUM (Reserved (no event indicated))
5868
0x29, 0x73, // USAGE_MAXIMUM (Keyboard Application)
5969
0x81, 0x00, // INPUT (Data,Ary,Abs)
6070
0xc0, // END_COLLECTION
6171
};
6272

63-
Keyboard_::Keyboard_(void)
73+
Keyboard_::Keyboard_(void)
6474
{
6575
static HIDSubDescriptor node(_hidReportDescriptor, sizeof(_hidReportDescriptor));
6676
HID().AppendDescriptor(&node);
@@ -91,16 +101,16 @@ const uint8_t _asciimap[128] =
91101
0x00, // ETX
92102
0x00, // EOT
93103
0x00, // ENQ
94-
0x00, // ACK
104+
0x00, // ACK
95105
0x00, // BEL
96106
0x2a, // BS Backspace
97107
0x2b, // TAB Tab
98108
0x28, // LF Enter
99-
0x00, // VT
100-
0x00, // FF
101-
0x00, // CR
102-
0x00, // SO
103-
0x00, // SI
109+
0x00, // VT
110+
0x00, // FF
111+
0x00, // CR
112+
0x00, // SO
113+
0x00, // SI
104114
0x00, // DEL
105115
0x00, // DC1
106116
0x00, // DC2
@@ -110,13 +120,13 @@ const uint8_t _asciimap[128] =
110120
0x00, // SYN
111121
0x00, // ETB
112122
0x00, // CAN
113-
0x00, // EM
123+
0x00, // EM
114124
0x00, // SUB
115125
0x00, // ESC
116-
0x00, // FS
117-
0x00, // GS
118-
0x00, // RS
119-
0x00, // US
126+
0x00, // FS
127+
0x00, // GS
128+
0x00, // RS
129+
0x00, // US
120130

121131
0x2c, // ' '
122132
0x1e|SHIFT, // !
@@ -220,10 +230,10 @@ const uint8_t _asciimap[128] =
220230
uint8_t USBPutChar(uint8_t c);
221231

222232
// press() adds the specified key (printing, non-printing, or modifier)
223-
// to the persistent key report and sends the report. Because of the way
224-
// USB HID works, the host acts like the key remains pressed until we
233+
// to the persistent key report and sends the report. Because of the way
234+
// USB HID works, the host acts like the key remains pressed until we
225235
// call release(), releaseAll(), or otherwise clear the report and resend.
226-
size_t Keyboard_::press(uint8_t k)
236+
size_t Keyboard_::press(uint8_t k)
227237
{
228238
uint8_t i;
229239
if (k >= 136) { // it's a non-printing key (not a modifier)
@@ -242,13 +252,13 @@ size_t Keyboard_::press(uint8_t k)
242252
k &= 0x7F;
243253
}
244254
}
245-
255+
246256
// Add k to the key report only if it's not already present
247257
// and if there is an empty slot.
248-
if (_keyReport.keys[0] != k && _keyReport.keys[1] != k &&
258+
if (_keyReport.keys[0] != k && _keyReport.keys[1] != k &&
249259
_keyReport.keys[2] != k && _keyReport.keys[3] != k &&
250260
_keyReport.keys[4] != k && _keyReport.keys[5] != k) {
251-
261+
252262
for (i=0; i<6; i++) {
253263
if (_keyReport.keys[i] == 0x00) {
254264
_keyReport.keys[i] = k;
@@ -258,7 +268,7 @@ size_t Keyboard_::press(uint8_t k)
258268
if (i == 6) {
259269
setWriteError();
260270
return 0;
261-
}
271+
}
262272
}
263273
sendReport(&_keyReport);
264274
return 1;
@@ -267,7 +277,7 @@ size_t Keyboard_::press(uint8_t k)
267277
// release() takes the specified key out of the persistent key report and
268278
// sends the report. This tells the OS the key is no longer pressed and that
269279
// it shouldn't be repeated any more.
270-
size_t Keyboard_::release(uint8_t k)
280+
size_t Keyboard_::release(uint8_t k)
271281
{
272282
uint8_t i;
273283
if (k >= 136) { // it's a non-printing key (not a modifier)
@@ -285,7 +295,7 @@ size_t Keyboard_::release(uint8_t k)
285295
k &= 0x7F;
286296
}
287297
}
288-
298+
289299
// Test the key report to see if k is present. Clear it if it exists.
290300
// Check all positions in case the key is present more than once (which it shouldn't be)
291301
for (i=0; i<6; i++) {
@@ -301,11 +311,11 @@ size_t Keyboard_::release(uint8_t k)
301311
void Keyboard_::releaseAll(void)
302312
{
303313
_keyReport.keys[0] = 0;
304-
_keyReport.keys[1] = 0;
314+
_keyReport.keys[1] = 0;
305315
_keyReport.keys[2] = 0;
306-
_keyReport.keys[3] = 0;
316+
_keyReport.keys[3] = 0;
307317
_keyReport.keys[4] = 0;
308-
_keyReport.keys[5] = 0;
318+
_keyReport.keys[5] = 0;
309319
_keyReport.modifiers = 0;
310320
sendReport(&_keyReport);
311321
}
@@ -332,7 +342,25 @@ size_t Keyboard_::write(const uint8_t *buffer, size_t size) {
332342
return n;
333343
}
334344

345+
bool Keyboard_::getLedStatus(uint8_t led)
346+
{
347+
uint8_t _keyboardLedsStatus = HID().getKeyboardLedsStatus();
348+
if (led == LED_CAPS_LOCK) {
349+
if (_keyboardLedsStatus == 2 || _keyboardLedsStatus == 3 || _keyboardLedsStatus == 6 || _keyboardLedsStatus == 7) {
350+
return true;
351+
}
352+
} else if (led == LED_NUM_LOCK) {
353+
if (_keyboardLedsStatus == 1 || _keyboardLedsStatus == 3 || _keyboardLedsStatus == 5 || _keyboardLedsStatus == 7) {
354+
return true;
355+
}
356+
} else if (led == LED_SCROLL_LOCK) {
357+
if (_keyboardLedsStatus == 4 || _keyboardLedsStatus == 5 || _keyboardLedsStatus == 6 || _keyboardLedsStatus == 7) {
358+
return true;
359+
}
360+
}
361+
return false;
362+
}
363+
335364
Keyboard_ Keyboard;
336365

337366
#endif
338-

src/Keyboard.h

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,8 @@
5858
#define KEY_HOME 0xD2
5959
#define KEY_END 0xD5
6060
#define KEY_CAPS_LOCK 0xC1
61+
#define KEY_NUM_LOCK 0xDB
62+
#define KEY_SCROLL_LOCK 0xCF
6163
#define KEY_F1 0xC2
6264
#define KEY_F2 0xC3
6365
#define KEY_F3 0xC4
@@ -84,6 +86,10 @@
8486
#define KEY_F24 0xFB
8587

8688

89+
#define LED_CAPS_LOCK 0x02
90+
#define LED_NUM_LOCK 0x01
91+
#define LED_SCROLL_LOCK 0x04
92+
8793
// Low level key report: up to 6 keys and shift, ctrl etc at once
8894
typedef struct
8995
{
@@ -106,9 +112,9 @@ class Keyboard_ : public Print
106112
size_t press(uint8_t k);
107113
size_t release(uint8_t k);
108114
void releaseAll(void);
115+
bool getLedStatus(uint8_t led);
109116
};
110117
extern Keyboard_ Keyboard;
111118

112119
#endif
113120
#endif
114-

0 commit comments

Comments
 (0)