|
@@ -18,6 +18,13 @@
|
18
|
18
|
|
19
|
19
|
typedef uint8_t byte;
|
20
|
20
|
|
|
21
|
+#define WAIT_USB do { \
|
|
22
|
+ UsbKeyboard.update(); \
|
|
23
|
+ if (!usbInterruptIsReady()) \
|
|
24
|
+ { \
|
|
25
|
+ return; \
|
|
26
|
+ } \
|
|
27
|
+} while(0)
|
21
|
28
|
|
22
|
29
|
#define BUFFER_SIZE 4 // Minimum of 2: 1 for modifiers + 1 for keystroke
|
23
|
30
|
|
|
@@ -25,243 +32,46 @@ typedef uint8_t byte;
|
25
|
32
|
static uchar idleRate; // in 4 ms units
|
26
|
33
|
|
27
|
34
|
|
28
|
|
-/* We use a simplifed keyboard report descriptor which does not support the
|
29
|
|
- * boot protocol. We don't allow setting status LEDs and but we do allow
|
30
|
|
- * simultaneous key presses.
|
31
|
|
- * The report descriptor has been created with usb.org's "HID Descriptor Tool"
|
32
|
|
- * which can be downloaded from http://www.usb.org/developers/hidpage/.
|
33
|
|
- * Redundant entries (such as LOGICAL_MINIMUM and USAGE_PAGE) have been omitted
|
34
|
|
- * for the second INPUT item.
|
35
|
|
- */
|
36
|
|
-PROGMEM const char usbHidReportDescriptor[35] = { /* USB report descriptor */
|
37
|
|
- 0x05, 0x01, // USAGE_PAGE (Generic Desktop)
|
38
|
|
- 0x09, 0x06, // USAGE (Keyboard)
|
39
|
|
- 0xa1, 0x01, // COLLECTION (Application)
|
40
|
|
- 0x05, 0x07, // USAGE_PAGE (Keyboard)
|
41
|
|
- 0x19, 0xe0, // USAGE_MINIMUM (Keyboard LeftControl)
|
42
|
|
- 0x29, 0xe7, // USAGE_MAXIMUM (Keyboard Right GUI)
|
43
|
|
- 0x15, 0x00, // LOGICAL_MINIMUM (0)
|
44
|
|
- 0x25, 0x01, // LOGICAL_MAXIMUM (1)
|
45
|
|
- 0x75, 0x01, // REPORT_SIZE (1)
|
46
|
|
- 0x95, 0x08, // REPORT_COUNT (8)
|
47
|
|
- 0x81, 0x02, // INPUT (Data,Var,Abs)
|
48
|
|
- 0x95, BUFFER_SIZE-1, // REPORT_COUNT (simultaneous keystrokes)
|
49
|
|
- 0x75, 0x08, // REPORT_SIZE (8)
|
50
|
|
- 0x25, 0x65, // LOGICAL_MAXIMUM (101)
|
51
|
|
- 0x19, 0x00, // USAGE_MINIMUM (Reserved (no event indicated))
|
52
|
|
- 0x29, 0x65, // USAGE_MAXIMUM (Keyboard Application)
|
53
|
|
- 0x81, 0x00, // INPUT (Data,Ary,Abs)
|
54
|
|
- 0xc0 // END_COLLECTION
|
55
|
|
-};
|
56
|
|
-
|
57
|
|
-
|
58
|
|
-
|
59
|
|
-/* Keyboard usage values, see usb.org's HID-usage-tables document, chapter
|
60
|
|
- * 10 Keyboard/Keypad Page for more codes.
|
61
|
|
- */
|
62
|
|
-#define MOD_CONTROL_LEFT (1<<0)
|
63
|
|
-#define MOD_SHIFT_LEFT (1<<1)
|
64
|
|
-#define MOD_ALT_LEFT (1<<2)
|
65
|
|
-#define MOD_GUI_LEFT (1<<3)
|
66
|
|
-#define MOD_CONTROL_RIGHT (1<<4)
|
67
|
|
-#define MOD_SHIFT_RIGHT (1<<5)
|
68
|
|
-#define MOD_ALT_RIGHT (1<<6)
|
69
|
|
-#define MOD_GUI_RIGHT (1<<7)
|
70
|
|
-
|
71
|
|
-#define KEY_A 4
|
72
|
|
-#define KEY_B 5
|
73
|
|
-#define KEY_C 6
|
74
|
|
-#define KEY_D 7
|
75
|
|
-#define KEY_E 8
|
76
|
|
-#define KEY_F 9
|
77
|
|
-#define KEY_G 10
|
78
|
|
-#define KEY_H 11
|
79
|
|
-#define KEY_I 12
|
80
|
|
-#define KEY_J 13
|
81
|
|
-#define KEY_K 14
|
82
|
|
-#define KEY_L 15
|
83
|
|
-#define KEY_M 16
|
84
|
|
-#define KEY_N 17
|
85
|
|
-#define KEY_O 18
|
86
|
|
-#define KEY_P 19
|
87
|
|
-#define KEY_Q 20
|
88
|
|
-#define KEY_R 21
|
89
|
|
-#define KEY_S 22
|
90
|
|
-#define KEY_T 23
|
91
|
|
-#define KEY_U 24
|
92
|
|
-#define KEY_V 25
|
93
|
|
-#define KEY_W 26
|
94
|
|
-#define KEY_X 27
|
95
|
|
-#define KEY_Y 28
|
96
|
|
-#define KEY_Z 29
|
97
|
|
-#define KEY_1 30
|
98
|
|
-#define KEY_2 31
|
99
|
|
-#define KEY_3 32
|
100
|
|
-#define KEY_4 33
|
101
|
|
-#define KEY_5 34
|
102
|
|
-#define KEY_6 35
|
103
|
|
-#define KEY_7 36
|
104
|
|
-#define KEY_8 37
|
105
|
|
-#define KEY_9 38
|
106
|
|
-#define KEY_0 39
|
107
|
|
-
|
108
|
|
-#define KEY_ENTER 40
|
109
|
|
-#define KEY_ESCAPE 41
|
110
|
|
-#define KEY_BSPACE 42
|
111
|
|
-#define KEY_TAB 43
|
112
|
|
-#define KEY_SPACE 44
|
113
|
|
-
|
114
|
|
-
|
115
|
|
-#define KEY_HYPHEN 45
|
116
|
|
-#define KEY_EQUAL 46
|
117
|
|
-#define KEY_LBRACKET 47
|
118
|
|
-#define KEY_RBRACKET 48
|
119
|
|
-#define KEY_BSLASH 49
|
120
|
|
-#define KEY_HASHTAG 50
|
121
|
|
-#define KEY_SEMICOLON 51
|
122
|
|
-#define KEY_QUOTE 52
|
123
|
|
-#define KEY_TILDE 53
|
124
|
|
-#define KEY_COMMA 54
|
125
|
|
-#define KEY_DOT 55
|
126
|
|
-#define KEY_SLASH 56
|
127
|
|
-#define KEY_CAPSLOCK 57
|
128
|
|
-
|
129
|
|
-#define KEY_F1 58
|
130
|
|
-#define KEY_F2 59
|
131
|
|
-#define KEY_F3 60
|
132
|
|
-#define KEY_F4 61
|
133
|
|
-#define KEY_F5 62
|
134
|
|
-#define KEY_F6 63
|
135
|
|
-#define KEY_F7 64
|
136
|
|
-#define KEY_F8 65
|
137
|
|
-#define KEY_F9 66
|
138
|
|
-#define KEY_F10 67
|
139
|
|
-#define KEY_F11 68
|
140
|
|
-#define KEY_F12 69
|
141
|
|
-
|
142
|
|
-#define KEY_PRINTSCREEN 70
|
143
|
|
-#define KEY_SCROLLLOCK 71
|
144
|
|
-#define KEY_PAUSE 72
|
145
|
|
-#define KEY_INSERT 73
|
146
|
|
-#define KEY_HOME 74
|
147
|
|
-#define KEY_PAGEUP 75
|
148
|
|
-#define KEY_DELETE 76
|
149
|
|
-#define KEY_END 77
|
150
|
|
-#define KEY_PAGEDOWN 78
|
151
|
|
-
|
152
|
|
-#define KEY_ARROW_RIGHT 79
|
153
|
|
-#define KEY_ARROW_LEFT 80
|
154
|
|
-#define KEY_ARROW_DOWN 81
|
155
|
|
-#define KEY_ARROW_UP 82
|
156
|
|
-
|
157
|
|
-
|
158
|
|
-#define KEY_NUMLOCK 83
|
159
|
|
-#define KEYP_SLASH 84
|
160
|
|
-#define KEYP_STAR 85
|
161
|
|
-#define KEYP_MINUS 86
|
162
|
|
-#define KEYP_PLUS 87
|
163
|
|
-#define KEYP_ENTER 88
|
164
|
|
-
|
165
|
|
-
|
166
|
|
-#define KEYP_NUS_BSLASH 100
|
|
35
|
+#include "keycodes.h"
|
167
|
36
|
|
168
|
37
|
class UsbKeyboardDevice {
|
169
|
38
|
public:
|
170
|
|
- UsbKeyboardDevice () {
|
171
|
|
- PORTD = 0; // TODO: Only for USB pins?
|
172
|
|
- DDRD |= ~USBMASK;
|
173
|
|
-
|
174
|
|
- cli();
|
175
|
|
- usbDeviceDisconnect();
|
176
|
|
- usbDeviceConnect();
|
|
39
|
+ UsbKeyboardDevice (const char* layout);
|
177
|
40
|
|
|
41
|
+ void setLayout(const char* layout);
|
178
|
42
|
|
179
|
|
- usbInit();
|
180
|
|
-
|
181
|
|
- sei();
|
182
|
|
-
|
183
|
|
- // TODO: Remove the next two lines once we fix
|
184
|
|
- // missing first keystroke bug properly.
|
185
|
|
- memset(reportBuffer, 0, sizeof(reportBuffer));
|
186
|
|
- usbSetInterrupt(reportBuffer, sizeof(reportBuffer));
|
187
|
|
- }
|
|
43
|
+ bool isUsbReady();
|
188
|
44
|
|
189
|
45
|
void update() {
|
190
|
46
|
usbPoll();
|
191
|
47
|
}
|
192
|
|
-
|
|
48
|
+
|
|
49
|
+ void sendKeyStrokes(const char* str);
|
|
50
|
+
|
193
|
51
|
void sendKeyStroke(byte keyStroke) {
|
194
|
52
|
sendKeyStroke(keyStroke, 0);
|
195
|
53
|
}
|
196
|
54
|
|
197
|
|
- void sendKeyStroke(byte keyStroke, byte modifiers) {
|
198
|
|
-
|
199
|
|
- while (!usbInterruptIsReady()) {
|
200
|
|
- // Note: We wait until we can send keystroke
|
201
|
|
- // so we know the previous keystroke was
|
202
|
|
- // sent.
|
203
|
|
- }
|
204
|
|
-
|
205
|
|
- memset(reportBuffer, 0, sizeof(reportBuffer));
|
|
55
|
+ void sendKeyStroke(byte keyStroke, byte modifiers);
|
206
|
56
|
|
207
|
|
- reportBuffer[0] = modifiers;
|
208
|
|
- reportBuffer[1] = keyStroke;
|
209
|
|
-
|
210
|
|
- usbSetInterrupt(reportBuffer, sizeof(reportBuffer));
|
211
|
|
-
|
212
|
|
- while (!usbInterruptIsReady()) {
|
213
|
|
- // Note: We wait until we can send keystroke
|
214
|
|
- // so we know the previous keystroke was
|
215
|
|
- // sent.
|
216
|
|
- }
|
217
|
|
-
|
218
|
|
- // This stops endlessly repeating keystrokes:
|
219
|
|
- memset(reportBuffer, 0, sizeof(reportBuffer));
|
220
|
|
- usbSetInterrupt(reportBuffer, sizeof(reportBuffer));
|
|
57
|
+#ifdef ARD_USBKBD_AZERTY
|
|
58
|
+ static int charToKeyAzerty(int, int*);
|
|
59
|
+#endif
|
221
|
60
|
|
222
|
|
- }
|
|
61
|
+#ifdef ARD_USBKBD_QWERTY
|
|
62
|
+ static int charToKeyQwerty(int, int*);
|
|
63
|
+#endif
|
223
|
64
|
|
224
|
65
|
//private: TODO: Make friend?
|
225
|
66
|
uchar reportBuffer[4]; // buffer for HID reports [ 1 modifier byte + (len-1) key strokes]
|
226
|
67
|
|
227
|
|
-};
|
228
|
|
-
|
229
|
|
-UsbKeyboardDevice UsbKeyboard = UsbKeyboardDevice();
|
230
|
|
-
|
231
|
|
-#ifdef __cplusplus
|
232
|
|
-extern "C"{
|
233
|
|
-#endif
|
234
|
|
- // USB_PUBLIC uchar usbFunctionSetup
|
235
|
|
-uchar usbFunctionSetup(uchar data[8])
|
236
|
|
- {
|
237
|
|
- usbRequest_t *rq = (usbRequest_t *)((void *)data);
|
238
|
|
-
|
239
|
|
- usbMsgPtr = UsbKeyboard.reportBuffer; //
|
240
|
|
- if((rq->bmRequestType & USBRQ_TYPE_MASK) == USBRQ_TYPE_CLASS){
|
241
|
|
- /* class request type */
|
242
|
|
-
|
243
|
|
- if(rq->bRequest == USBRQ_HID_GET_REPORT){
|
244
|
|
- /* wValue: ReportType (highbyte), ReportID (lowbyte) */
|
|
68
|
+private:
|
|
69
|
+ char* _layout;
|
|
70
|
+ static int charModAltGr(char, int*);
|
|
71
|
+ static int charModShift(char, int*);
|
245
|
72
|
|
246
|
|
- /* we only have one report type, so don't look at wValue */
|
247
|
|
- // TODO: Ensure it's okay not to return anything here?
|
248
|
|
- return 0;
|
249
|
|
-
|
250
|
|
- }else if(rq->bRequest == USBRQ_HID_GET_IDLE){
|
251
|
|
- // usbMsgPtr = &idleRate;
|
252
|
|
- // return 1;
|
253
|
|
- return 0;
|
254
|
|
- }else if(rq->bRequest == USBRQ_HID_SET_IDLE){
|
255
|
|
- idleRate = rq->wValue.bytes[1];
|
256
|
|
- }
|
257
|
|
- }else{
|
258
|
|
- /* no vendor specific requests implemented */
|
259
|
|
- }
|
260
|
|
- return 0;
|
261
|
|
- }
|
262
|
|
-#ifdef __cplusplus
|
263
|
|
-} // extern "C"
|
264
|
|
-#endif
|
|
73
|
+};
|
265
|
74
|
|
|
75
|
+#include "UsbKeyboard.hxx"
|
266
|
76
|
|
267
|
77
|
#endif // __UsbKeyboard_h__
|