Skip to content

Commit 07dab95

Browse files
committed
Fixed bug in German keyboard layout see issue#3
1 parent e6762ef commit 07dab95

File tree

5 files changed

+5455
-5512
lines changed

5 files changed

+5455
-5512
lines changed

digistump-avr-1.6.8.zip

3.84 KB
Binary file not shown.

digistump-avr/libraries/DigisparkKeyboard/DigiKeyboard.h

+153-152
Original file line numberDiff line numberDiff line change
@@ -16,15 +16,11 @@
1616
#include "usbdrv.h"
1717
#include "keylayouts.h"
1818

19-
2019
typedef uint8_t byte;
2120

22-
2321
#define BUFFER_SIZE 2 // Minimum of 2: 1 for modifiers + 1 for keystroke
2422

25-
26-
static uchar idleRate; // in 4 ms units
27-
23+
static uchar idleRate; // in 4 ms units
2824

2925
/* We use a simplifed keyboard report descriptor which does not support the
3026
* boot protocol. We don't allow setting status LEDs and but we do allow
@@ -35,26 +31,25 @@ static uchar idleRate; // in 4 ms units
3531
* for the second INPUT item.
3632
*/
3733
const PROGMEM uchar usbHidReportDescriptor[USB_CFG_HID_REPORT_DESCRIPTOR_LENGTH] = { /* USB report descriptor */
38-
0x05, 0x01, // USAGE_PAGE (Generic Desktop)
39-
0x09, 0x06, // USAGE (Keyboard)
40-
0xa1, 0x01, // COLLECTION (Application)
41-
0x05, 0x07, // USAGE_PAGE (Keyboard)
42-
0x19, 0xe0, // USAGE_MINIMUM (Keyboard LeftControl)
43-
0x29, 0xe7, // USAGE_MAXIMUM (Keyboard Right GUI)
44-
0x15, 0x00, // LOGICAL_MINIMUM (0)
45-
0x25, 0x01, // LOGICAL_MAXIMUM (1)
46-
0x75, 0x01, // REPORT_SIZE (1)
47-
0x95, 0x08, // REPORT_COUNT (8)
48-
0x81, 0x02, // INPUT (Data,Var,Abs)
49-
0x95, 0x01, // REPORT_COUNT (simultaneous keystrokes)
50-
0x75, 0x08, // REPORT_SIZE (8)
51-
0x25, 0x65, // LOGICAL_MAXIMUM (101)
52-
0x19, 0x00, // USAGE_MINIMUM (Reserved (no event indicated))
53-
0x29, 0x65, // USAGE_MAXIMUM (Keyboard Application)
54-
0x81, 0x00, // INPUT (Data,Ary,Abs)
55-
0xc0 // END_COLLECTION
56-
};
57-
34+
0x05, 0x01, // USAGE_PAGE (Generic Desktop)
35+
0x09, 0x06, // USAGE (Keyboard)
36+
0xa1, 0x01, // COLLECTION (Application)
37+
0x05, 0x07, // USAGE_PAGE (Keyboard)
38+
0x19, 0xe0, // USAGE_MINIMUM (Keyboard LeftControl)
39+
0x29, 0xe7, // USAGE_MAXIMUM (Keyboard Right GUI)
40+
0x15, 0x00, // LOGICAL_MINIMUM (0)
41+
0x25, 0x01, // LOGICAL_MAXIMUM (1)
42+
0x75, 0x01, // REPORT_SIZE (1)
43+
0x95, 0x08, // REPORT_COUNT (8)
44+
0x81, 0x02, // INPUT (Data,Var,Abs)
45+
0x95, 0x01, // REPORT_COUNT (simultaneous keystrokes)
46+
0x75, 0x08, // REPORT_SIZE (8)
47+
0x25, 0x65, // LOGICAL_MAXIMUM (101)
48+
0x19, 0x00, // USAGE_MINIMUM (Reserved (no event indicated))
49+
0x29, 0x65, // USAGE_MAXIMUM (Keyboard Application)
50+
0x81, 0x00, // INPUT (Data,Ary,Abs)
51+
0xc0 // END_COLLECTION
52+
};
5853

5954
#define MOD_CONTROL_LEFT MODIFIERKEY_LEFT_CTRL
6055
#define MOD_SHIFT_LEFT MODIFIERKEY_LEFT_SHIFT
@@ -65,158 +60,164 @@ const PROGMEM uchar usbHidReportDescriptor[USB_CFG_HID_REPORT_DESCRIPTOR_LENGTH]
6560
#define MOD_ALT_RIGHT MODIFIERKEY_RIGHT_ALT
6661
#define MOD_GUI_RIGHT MODIFIERKEY_RIGHT_GUI
6762

68-
class DigiKeyboardDevice : public Print {
69-
public:
70-
DigiKeyboardDevice () {
71-
cli();
72-
usbDeviceDisconnect();
73-
_delay_ms(250);
74-
usbDeviceConnect();
75-
76-
77-
usbInit();
78-
79-
sei();
80-
81-
// TODO: Remove the next two lines once we fix
82-
// missing first keystroke bug properly.
83-
memset(reportBuffer, 0, sizeof(reportBuffer));
84-
usbSetInterrupt(reportBuffer, sizeof(reportBuffer));
85-
}
86-
87-
void update() {
88-
usbPoll();
89-
}
90-
91-
// delay while updating until we are finished delaying
92-
void delay(long milli) {
93-
unsigned long last = millis();
94-
while (milli > 0) {
95-
unsigned long now = millis();
96-
milli -= now - last;
97-
last = now;
98-
update();
99-
}
100-
}
101-
102-
//sendKeyStroke: sends a key press AND release
103-
void sendKeyStroke(byte keyStroke) {
104-
sendKeyStroke(keyStroke, 0);
105-
}
106-
107-
//sendKeyStroke: sends a key press AND release with modifiers
108-
void sendKeyStroke(byte keyStroke, byte modifiers) {
109-
sendKeyPress(keyStroke, modifiers);
110-
// This stops endlessly repeating keystrokes:
111-
sendKeyPress(0,0);
112-
}
113-
114-
//sendKeyPress: sends a key press only - no release
115-
//to release the key, send again with keyPress=0
116-
void sendKeyPress(byte keyPress) {
117-
sendKeyPress(keyPress, 0);
118-
}
119-
120-
//sendKeyPress: sends a key press only, with modifiers - no release
121-
//to release the key, send again with keyPress=0
122-
void sendKeyPress(byte keyPress, byte modifiers) {
123-
while (!usbInterruptIsReady()) {
124-
// Note: We wait until we can send keyPress
125-
// so we know the previous keyPress was
126-
// sent.
127-
usbPoll();
128-
_delay_ms(5);
63+
class DigiKeyboardDevice: public Print {
64+
public:
65+
DigiKeyboardDevice() {
66+
noInterrupts();
67+
usbDeviceDisconnect();
68+
_delay_ms(250);
69+
usbDeviceConnect();
70+
71+
usbInit();
72+
73+
interrupts();
74+
75+
// TODO: Remove the next two lines once we fix
76+
// missing first keystroke bug properly.
77+
memset(reportBuffer, 0, sizeof(reportBuffer));
78+
usbSetInterrupt(reportBuffer, sizeof(reportBuffer));
12979
}
13080

131-
memset(reportBuffer, 0, sizeof(reportBuffer));
132-
133-
reportBuffer[0] = modifiers;
134-
reportBuffer[1] = keyPress;
135-
136-
usbSetInterrupt(reportBuffer, sizeof(reportBuffer));
137-
}
138-
139-
uint8_t keycode_to_modifier(KEYCODE_TYPE keycode){
140-
uint8_t modifier=0;
141-
142-
#ifdef SHIFT_MASK
143-
if (keycode & SHIFT_MASK) modifier |= MODIFIERKEY_SHIFT;
144-
#endif
145-
#ifdef ALTGR_MASK
146-
if (keycode & ALTGR_MASK) modifier |= MODIFIERKEY_RIGHT_ALT;
147-
#endif
148-
#ifdef RCTRL_MASK
149-
if (keycode & RCTRL_MASK) modifier |= MODIFIERKEY_RIGHT_CTRL;
150-
#endif
151-
return modifier;
152-
}
153-
154-
uint8_t keycode_to_key(KEYCODE_TYPE keycode){
155-
uint8_t key = keycode & 0x3F;
156-
#ifdef KEY_NON_US_100
157-
if (key == KEY_NON_US_100) key = 100;
158-
#endif
159-
return key;
160-
}
161-
162-
size_t write(uint8_t chr) {
163-
uint8_t data = 0;
164-
if (chr == 0x09) {
165-
data = (uint8_t)KEY_TAB;
166-
}else if (chr == 0x0a) {
167-
data = (uint8_t)KEY_ENTER;
168-
}else if (chr >= 0x20) {
169-
data = pgm_read_byte_near(keycodes_ascii + (chr - 0x20));
81+
void update() {
82+
usbPoll();
17083
}
171-
if (data) {
172-
sendKeyStroke(keycode_to_key(data), keycode_to_modifier(data));
84+
85+
// delay while updating until we are finished delaying
86+
void delay(long milli) {
87+
unsigned long last = millis();
88+
while (milli > 0) {
89+
unsigned long now = millis();
90+
milli -= now - last;
91+
last = now;
92+
update();
93+
}
94+
}
95+
96+
//sendKeyStroke: sends a key press AND release
97+
void sendKeyStroke(byte keyStroke) {
98+
sendKeyStroke(keyStroke, 0);
99+
}
100+
101+
//sendKeyStroke: sends a key press AND release with modifiers
102+
void sendKeyStroke(byte keyStroke, byte modifiers) {
103+
sendKeyPress(keyStroke, modifiers);
104+
// This stops endlessly repeating keystrokes:
105+
sendKeyPress(0, 0);
106+
}
107+
108+
//sendKeyPress: sends a key press only - no release
109+
//to release the key, send again with keyPress=0
110+
void sendKeyPress(byte keyPress) {
111+
sendKeyPress(keyPress, 0);
173112
}
174-
return 1;
175-
}
176113

177-
//private: TODO: Make friend?
178-
uchar reportBuffer[2]; // buffer for HID reports [ 1 modifier byte + (len-1) key strokes]
179-
using Print::write;
114+
//sendKeyPress: sends a key press only, with modifiers - no release
115+
//to release the key, send again with keyPress=0
116+
void sendKeyPress(byte keyPress, byte modifiers) {
117+
while (!usbInterruptIsReady()) {
118+
// Note: We wait until we can send keyPress
119+
// so we know the previous keyPress was
120+
// sent.
121+
usbPoll();
122+
_delay_ms(5);
123+
}
124+
125+
memset(reportBuffer, 0, sizeof(reportBuffer));
126+
127+
reportBuffer[0] = modifiers;
128+
reportBuffer[1] = keyPress;
129+
130+
usbSetInterrupt(reportBuffer, sizeof(reportBuffer));
131+
}
132+
133+
uint8_t keycode_to_modifier(KEYCODE_TYPE keycode) {
134+
uint8_t modifier = 0;
135+
136+
#ifdef SHIFT_MASK
137+
if (keycode & SHIFT_MASK)
138+
modifier |= MODIFIERKEY_SHIFT;
139+
#endif
140+
#ifdef ALTGR_MASK
141+
if (keycode & ALTGR_MASK)
142+
modifier |= MODIFIERKEY_RIGHT_ALT;
143+
#endif
144+
#ifdef RCTRL_MASK
145+
if (keycode & RCTRL_MASK) modifier |= MODIFIERKEY_RIGHT_CTRL;
146+
#endif
147+
return modifier;
148+
}
149+
150+
uint8_t keycode_to_key(KEYCODE_TYPE keycode) {
151+
uint8_t key = keycode & 0x3F;
152+
#ifdef KEY_NON_US_100
153+
if (key == KEY_NON_US_100) {
154+
key = 100;
155+
}
156+
#endif
157+
return key;
158+
}
159+
160+
/*
161+
* Convert ASCII to USB code
162+
*/
163+
size_t write(uint8_t chr) {
164+
uint8_t data = 0;
165+
if (chr == 0x09) {
166+
data = (uint8_t) KEY_TAB;
167+
} else if (chr == 0x0a) {
168+
data = (uint8_t) KEY_ENTER;
169+
} else if (chr >= 0x20) {
170+
// read from mapping table
171+
data = pgm_read_byte_near(keycodes_ascii + (chr - 0x20));
172+
}
173+
if (data) {
174+
sendKeyStroke(keycode_to_key(data), keycode_to_modifier(data));
175+
}
176+
return 1;
177+
}
178+
179+
//private: TODO: Make friend?
180+
uchar reportBuffer[2]; // buffer for HID reports [ 1 modifier byte + (len-1) key strokes]
181+
using Print::write;
180182
};
181183

182184
DigiKeyboardDevice DigiKeyboard = DigiKeyboardDevice();
183185

184186
#ifdef __cplusplus
185-
extern "C"{
187+
extern "C" {
186188
#endif
187-
// USB_PUBLIC uchar usbFunctionSetup
188-
uchar usbFunctionSetup(uchar data[8]) {
189-
usbRequest_t *rq = (usbRequest_t *)((void *)data);
189+
// USB_PUBLIC uchar usbFunctionSetup
190+
uchar usbFunctionSetup(uchar data[8]) {
191+
usbRequest_t *rq = (usbRequest_t *) ((void *) data);
190192

191193
usbMsgPtr = DigiKeyboard.reportBuffer; //
192194
if ((rq->bmRequestType & USBRQ_TYPE_MASK) == USBRQ_TYPE_CLASS) {
193-
/* class request type */
195+
/* class request type */
194196

195-
if (rq->bRequest == USBRQ_HID_GET_REPORT) {
196-
/* wValue: ReportType (highbyte), ReportID (lowbyte) */
197+
if (rq->bRequest == USBRQ_HID_GET_REPORT) {
198+
/* wValue: ReportType (highbyte), ReportID (lowbyte) */
197199

198-
/* we only have one report type, so don't look at wValue */
199-
// TODO: Ensure it's okay not to return anything here?
200-
return 0;
200+
/* we only have one report type, so don't look at wValue */
201+
// TODO: Ensure it's okay not to return anything here?
202+
return 0;
201203

202-
} else if (rq->bRequest == USBRQ_HID_GET_IDLE) {
203-
//usbMsgPtr = &idleRate;
204-
//return 1;
205-
return 0;
204+
} else if (rq->bRequest == USBRQ_HID_GET_IDLE) {
205+
//usbMsgPtr = &idleRate;
206+
//return 1;
207+
return 0;
206208

207-
} else if (rq->bRequest == USBRQ_HID_SET_IDLE) {
208-
idleRate = rq->wValue.bytes[1];
209+
} else if (rq->bRequest == USBRQ_HID_SET_IDLE) {
210+
idleRate = rq->wValue.bytes[1];
209211

210-
}
212+
}
211213
} else {
212-
/* no vendor specific requests implemented */
214+
/* no vendor specific requests implemented */
213215
}
214216

215217
return 0;
216-
}
218+
}
217219
#ifdef __cplusplus
218220
} // extern "C"
219221
#endif
220222

221-
222223
#endif // __DigiKeyboard_h__

0 commit comments

Comments
 (0)