32
32
#include "shared/runtime/interrupt_char.h"
33
33
#include "supervisor/usb.h"
34
34
35
+ #ifndef DEBUG
36
+ #define DEBUG (0)
37
+ #endif
38
+
35
39
// Buffer the incoming serial data in the background so that we can look for the
36
40
// interrupt character.
37
41
STATIC ringbuf_t _incoming_ringbuf ;
38
42
STATIC uint8_t _buf [16 ];
39
43
40
- uint8_t _dev_addr ;
41
- uint8_t _interface ;
42
-
43
- #define FLAG_ALPHABETIC (1)
44
- #define FLAG_SHIFT (2)
45
- #define FLAG_NUMLOCK (4)
46
- #define FLAG_CTRL (8)
47
- #define FLAG_LUT (16)
48
-
49
- const char * const lut [] = {
50
- "!@#$%^&*()" , /* 0 - shifted numeric keys */
51
- "\r\x1b\10\t -=[]\\#;'`,./" , /* 1 - symbol keys */
52
- "\n\x1b\177\t _+{}|~:\"~<>?" , /* 2 - shifted */
53
- "\12\13\10\22" , /* 3 - arrow keys RLDU */
54
- "/*-+\n1234567890." , /* 4 - keypad w/numlock */
55
- "/*-+\n\xff\2\xff\4\xff\3\xff\1\xff\xff." , /* 5 - keypad w/o numlock */
56
- };
44
+ STATIC uint8_t _dev_addr ;
45
+ STATIC uint8_t _interface ;
46
+
47
+ #define FLAG_SHIFT (1)
48
+ #define FLAG_NUMLOCK (2)
49
+ #define FLAG_CTRL (4)
50
+ #define FLAG_STRING (8)
51
+
52
+ STATIC uint8_t user_keymap [384 ];
53
+ STATIC size_t user_keymap_len = 0 ;
54
+
55
+ void usb_keymap_set (const uint8_t * buf , size_t len ) {
56
+ user_keymap_len = len = MIN (len , sizeof (user_keymap ));
57
+ memcpy (user_keymap , buf , len );
58
+ memset (user_keymap + len , 0 , sizeof (user_keymap ) - len );
59
+ }
57
60
58
61
struct keycode_mapper {
59
62
uint8_t first , last , code , flags ;
60
- } keycode_to_ascii [] = {
61
- { HID_KEY_A , HID_KEY_Z , 'a' , FLAG_ALPHABETIC , },
63
+ const char * data ;
64
+ };
62
65
63
- { HID_KEY_1 , HID_KEY_9 , 0 , FLAG_SHIFT | FLAG_LUT , },
66
+ #define SEP "\0" // separator in FLAG_STRING sequences
67
+ #define NOTHING "" // in FLAG_STRING sequences
68
+ #define CURSOR_UP "\e[A"
69
+ #define CURSOR_DOWN "\e[B"
70
+ #define CURSOR_LEFT "\e[D"
71
+ #define CURSOR_RIGHT "\e[C"
72
+ #define CURSOR_PGUP "\e[5~"
73
+ #define CURSOR_PGDN "\e[6~"
74
+ #define CURSOR_HOME "\e[H"
75
+ #define CURSOR_END "\e[F"
76
+ #define CURSOR_INS "\e[2~"
77
+ #define CURSOR_DEL "\e[3~"
78
+
79
+ STATIC struct keycode_mapper keycode_to_ascii [] = {
80
+ { HID_KEY_A , HID_KEY_Z , 'a' , 0 , NULL },
81
+
82
+ { HID_KEY_1 , HID_KEY_9 , 0 , FLAG_SHIFT , "!@#$%^&*()" },
64
83
{ HID_KEY_1 , HID_KEY_9 , '1' , 0 , },
65
84
{ HID_KEY_0 , HID_KEY_0 , ')' , FLAG_SHIFT , },
66
85
{ HID_KEY_0 , HID_KEY_0 , '0' , 0 , },
67
86
68
87
{ HID_KEY_ENTER , HID_KEY_ENTER , '\n' , FLAG_CTRL },
69
- { HID_KEY_ENTER , HID_KEY_SLASH , 2 , FLAG_SHIFT | FLAG_LUT , },
70
- { HID_KEY_ENTER , HID_KEY_SLASH , 1 , FLAG_LUT , },
88
+ { HID_KEY_ENTER , HID_KEY_SLASH , 0 , FLAG_SHIFT , "\n\x1b\177\t _+{}|~:\"~<>?" },
89
+ { HID_KEY_ENTER , HID_KEY_SLASH , 0 , 0 , "\r\x1b\10\t -=[]\\#;'`,./" },
71
90
72
91
{ HID_KEY_F1 , HID_KEY_F1 , 0x1e , 0 , }, // help key on xerox 820 kbd
73
92
74
- { HID_KEY_ARROW_RIGHT , HID_KEY_ARROW_UP , 3 , FLAG_LUT },
93
+ { HID_KEY_KEYPAD_DIVIDE , HID_KEY_KEYPAD_DECIMAL , 0 , FLAG_NUMLOCK | FLAG_STRING ,
94
+ "/\0" "*\0" "-\0" "+\0" "\n\0" CURSOR_END SEP CURSOR_DOWN SEP CURSOR_PGDN SEP CURSOR_LEFT SEP NOTHING SEP CURSOR_RIGHT SEP CURSOR_HOME SEP CURSOR_UP SEP CURSOR_PGDN SEP CURSOR_INS SEP CURSOR_DEL },
95
+ { HID_KEY_KEYPAD_DIVIDE , HID_KEY_KEYPAD_DECIMAL , 0 , 0 , "/*-+\n1234567890." },
96
+
97
+ { HID_KEY_ARROW_RIGHT , HID_KEY_ARROW_UP , 0 , FLAG_STRING , CURSOR_RIGHT SEP CURSOR_LEFT SEP CURSOR_DOWN SEP CURSOR_UP },
75
98
76
- { HID_KEY_KEYPAD_DIVIDE , HID_KEY_KEYPAD_DECIMAL , 4 , FLAG_NUMLOCK | FLAG_LUT },
77
- { HID_KEY_KEYPAD_DIVIDE , HID_KEY_KEYPAD_DECIMAL , 5 , FLAG_LUT },
78
99
};
79
100
80
101
STATIC bool report_contains (const hid_keyboard_report_t * report , uint8_t key ) {
@@ -86,30 +107,63 @@ STATIC bool report_contains(const hid_keyboard_report_t *report, uint8_t key) {
86
107
return false;
87
108
}
88
109
89
- int old_ascii = -1 ;
90
- uint32_t repeat_timeout ;
110
+ STATIC const char * old_buf = NULL ;
111
+ STATIC size_t buf_size = 0 ;
91
112
// this matches Linux default of 500ms to first repeat, 1/20s thereafter
92
- const uint32_t default_repeat_time = 50 ;
93
- const uint32_t initial_repeat_time = 500 ;
113
+ STATIC const uint32_t initial_repeat_time = 500 ;
94
114
95
- STATIC void send_ascii (uint8_t code , uint32_t repeat_time ) {
96
- old_ascii = code ;
115
+ STATIC void send_bufn (const char * buf , size_t n , uint32_t repeat_time ) {
116
+ old_buf = buf ;
117
+ buf_size = n ;
97
118
// repeat_timeout = millis() + repeat_time;
98
- if (code == mp_interrupt_char ) {
99
- mp_sched_keyboard_interrupt ();
100
- return ;
119
+ for (; n -- ; buf ++ ) {
120
+ int code = * buf ;
121
+ if (code == mp_interrupt_char ) {
122
+ mp_sched_keyboard_interrupt ();
123
+ return ;
124
+ }
125
+ if (ringbuf_num_empty (& _incoming_ringbuf ) == 0 ) {
126
+ // Drop on the floor
127
+ return ;
128
+ }
129
+ ringbuf_put (& _incoming_ringbuf , code );
101
130
}
102
- if (ringbuf_num_empty (& _incoming_ringbuf ) == 0 ) {
103
- // Drop on the floor
104
- return ;
131
+ }
132
+
133
+ STATIC void send_bufz (const char * buf , uint32_t repeat_time ) {
134
+ send_bufn (buf , strlen (buf ), repeat_time );
135
+ }
136
+
137
+ STATIC void send_byte (uint8_t code , uint32_t repeat_time ) {
138
+ static char buf [1 ];
139
+ buf [0 ] = code ;
140
+ send_bufn (buf , 1 , repeat_time );
141
+ }
142
+
143
+ #if 0
144
+ STATIC uint32_t repeat_timeout ;
145
+ STATIC const uint32_t default_repeat_time = 50 ;
146
+ // TODO: nothing actually SENDS the repetitions...
147
+ STATIC void send_repeat () {
148
+ if (old_buf ) {
149
+ send_bufn (old_buf , old_buf_size , default_repeat_time );
105
150
}
106
- ringbuf_put (& _incoming_ringbuf , code );
107
151
}
152
+ #endif
108
153
109
154
hid_keyboard_report_t old_report ;
110
155
156
+ STATIC const char * skip_nuls (const char * buf , size_t n ) {
157
+ while (n -- ) {
158
+ buf += strlen (buf ) + 1 ;
159
+ }
160
+ return buf ;
161
+ }
162
+
111
163
STATIC void process_event (uint8_t dev_addr , uint8_t instance , const hid_keyboard_report_t * report ) {
112
- bool alt = report -> modifier & 0x44 ;
164
+ bool has_altgr = (user_keymap_len > 256 );
165
+ bool altgr = has_altgr && report -> modifier & 0x40 ;
166
+ bool alt = has_altgr ? report -> modifier & 0x4 : report -> modifier & 0x44 ;
113
167
bool shift = report -> modifier & 0x22 ;
114
168
bool ctrl = report -> modifier & 0x11 ;
115
169
bool caps = old_report .reserved & 1 ;
@@ -122,7 +176,7 @@ STATIC void process_event(uint8_t dev_addr, uint8_t instance, const hid_keyboard
122
176
}
123
177
124
178
// something was pressed or release, so cancel any key repeat
125
- old_ascii = -1 ;
179
+ old_buf = NULL ;
126
180
127
181
for (int i = 0 ; i < 6 ; i ++ ) {
128
182
uint8_t keycode = report -> keycode [i ];
@@ -139,6 +193,22 @@ STATIC void process_event(uint8_t dev_addr, uint8_t instance, const hid_keyboard
139
193
} else if (keycode == HID_KEY_CAPS_LOCK ) {
140
194
caps = !caps ;
141
195
} else {
196
+ size_t idx = keycode + (altgr ? 256 : shift ? 128 : 0 );
197
+ uint8_t ascii = user_keymap [idx ];
198
+ #if DEBUG
199
+ mp_printf (& mp_plat_print , "lookup HID keycode %d mod %x at idx %d -> ascii %d (%c)\n" ,
200
+ keycode , report -> modifier , idx , ascii , ascii >= 32 && ascii <= 126 ? ascii : '.' );
201
+ #endif
202
+ if (ascii != 0 ) {
203
+ if (ctrl ) {
204
+ ascii &= 0x1f ;
205
+ } else if (ascii >= 'a' && ascii <= 'z' && caps ) {
206
+ ascii ^= ('a' ^ 'A' );
207
+ }
208
+ send_byte (ascii , initial_repeat_time );
209
+ continue ;
210
+ }
211
+
142
212
for (size_t j = 0 ; j < MP_ARRAY_SIZE (keycode_to_ascii ); j ++ ) {
143
213
struct keycode_mapper * mapper = & keycode_to_ascii [j ];
144
214
if (!(keycode >= mapper -> first && keycode <= mapper -> last )) {
@@ -153,23 +223,24 @@ STATIC void process_event(uint8_t dev_addr, uint8_t instance, const hid_keyboard
153
223
if (mapper -> flags & FLAG_CTRL && !ctrl ) {
154
224
continue ;
155
225
}
156
- if (mapper -> flags & FLAG_LUT ) {
157
- code = lut [mapper -> code ][keycode - mapper -> first ];
226
+ if (mapper -> flags & FLAG_STRING ) {
227
+ const char * msg = skip_nuls (mapper -> data , keycode - mapper -> first );
228
+ send_bufz (msg , initial_repeat_time );
229
+ } else if (mapper -> data ) {
230
+ code = mapper -> data [keycode - mapper -> first ];
158
231
} else {
159
232
code = keycode - mapper -> first + mapper -> code ;
160
233
}
161
- if (mapper -> flags & FLAG_ALPHABETIC ) {
162
- if (shift ^ caps ) {
163
- code ^= ('a' ^ 'A' );
164
- }
234
+ if (code >= 'a' && code <= 'z' && (shift ^ caps )) {
235
+ code ^= ('a' ^ 'A' );
165
236
}
166
237
if (ctrl ) {
167
238
code &= 0x1f ;
168
239
}
169
240
if (alt ) {
170
241
code ^= 0x80 ;
171
242
}
172
- send_ascii (code , initial_repeat_time );
243
+ send_byte (code , initial_repeat_time );
173
244
break ;
174
245
}
175
246
}
0 commit comments