1 /*
2 * simulated keyboard input for systems with none (except via uart or usb)
3 *
4 * gutted version of ps2 version from ../pc
5 */
6 #include "u.h"
7 #include "../port/lib.h"
8 #include "mem.h"
9 #include "dat.h"
10 #include "fns.h"
11 #include "io.h"
12 #include "../port/error.h"
13
14 enum {
15 Spec= 0xF800, /* Unicode private space */
16 PF= Spec|0x20, /* num pad function key */
17 View= Spec|0x00, /* view (shift window up) */
18 KF= 0xF000, /* function key (begin Unicode private space) */
19 Shift= Spec|0x60,
20 Break= Spec|0x61,
21 Ctrl= Spec|0x62,
22 Latin= Spec|0x63,
23 Caps= Spec|0x64,
24 Num= Spec|0x65,
25 Middle= Spec|0x66,
26 Altgr= Spec|0x67,
27 Kmouse= Spec|0x100,
28 No= 0x00, /* peter */
29
30 Home= KF|13,
31 Up= KF|14,
32 Pgup= KF|15,
33 Print= KF|16,
34 Left= KF|17,
35 Right= KF|18,
36 End= KF|24,
37 Down= View,
38 Pgdown= KF|19,
39 Ins= KF|20,
40 Del= 0x7F,
41 Scroll= KF|21,
42
43 Nscan= 128,
44
45 Int= 0, /* kbscans indices */
46 Ext,
47 Nscans,
48 };
49
50 /*
51 * The codes at 0x79 and 0x7b are produced by the PFU Happy Hacking keyboard.
52 * A 'standard' keyboard doesn't produce anything above 0x58.
53 */
54 Rune kbtab[Nscan] =
55 {
56 [0x00] No, 0x1b, '1', '2', '3', '4', '5', '6',
57 [0x08] '7', '8', '9', '0', '-', '=', '\b', '\t',
58 [0x10] 'q', 'w', 'e', 'r', 't', 'y', 'u', 'i',
59 [0x18] 'o', 'p', '[', ']', '\n', Ctrl, 'a', 's',
60 [0x20] 'd', 'f', 'g', 'h', 'j', 'k', 'l', ';',
61 [0x28] '\'', '`', Shift, '\\', 'z', 'x', 'c', 'v',
62 [0x30] 'b', 'n', 'm', ',', '.', '/', Shift, '*',
63 [0x38] Latin, ' ', Ctrl, KF|1, KF|2, KF|3, KF|4, KF|5,
64 [0x40] KF|6, KF|7, KF|8, KF|9, KF|10, Num, Scroll, '7',
65 [0x48] '8', '9', '-', '4', '5', '6', '+', '1',
66 [0x50] '2', '3', '0', '.', No, No, No, KF|11,
67 [0x58] KF|12, No, No, No, No, No, No, No,
68 [0x60] No, No, No, No, No, No, No, No,
69 [0x68] No, No, No, No, No, No, No, No,
70 [0x70] No, No, No, No, No, No, No, No,
71 [0x78] No, View, No, Up, No, No, No, No,
72 };
73
74 Rune kbtabshift[Nscan] =
75 {
76 [0x00] No, 0x1b, '!', '@', '#', '$', '%', '^',
77 [0x08] '&', '*', '(', ')', '_', '+', '\b', '\t',
78 [0x10] 'Q', 'W', 'E', 'R', 'T', 'Y', 'U', 'I',
79 [0x18] 'O', 'P', '{', '}', '\n', Ctrl, 'A', 'S',
80 [0x20] 'D', 'F', 'G', 'H', 'J', 'K', 'L', ':',
81 [0x28] '"', '~', Shift, '|', 'Z', 'X', 'C', 'V',
82 [0x30] 'B', 'N', 'M', '<', '>', '?', Shift, '*',
83 [0x38] Latin, ' ', Ctrl, KF|1, KF|2, KF|3, KF|4, KF|5,
84 [0x40] KF|6, KF|7, KF|8, KF|9, KF|10, Num, Scroll, '7',
85 [0x48] '8', '9', '-', '4', '5', '6', '+', '1',
86 [0x50] '2', '3', '0', '.', No, No, No, KF|11,
87 [0x58] KF|12, No, No, No, No, No, No, No,
88 [0x60] No, No, No, No, No, No, No, No,
89 [0x68] No, No, No, No, No, No, No, No,
90 [0x70] No, No, No, No, No, No, No, No,
91 [0x78] No, Up, No, Up, No, No, No, No,
92 };
93
94 Rune kbtabesc1[Nscan] =
95 {
96 [0x00] No, No, No, No, No, No, No, No,
97 [0x08] No, No, No, No, No, No, No, No,
98 [0x10] No, No, No, No, No, No, No, No,
99 [0x18] No, No, No, No, '\n', Ctrl, No, No,
100 [0x20] No, No, No, No, No, No, No, No,
101 [0x28] No, No, Shift, No, No, No, No, No,
102 [0x30] No, No, No, No, No, '/', No, Print,
103 [0x38] Altgr, No, No, No, No, No, No, No,
104 [0x40] No, No, No, No, No, No, Break, Home,
105 [0x48] Up, Pgup, No, Left, No, Right, No, End,
106 [0x50] Down, Pgdown, Ins, Del, No, No, No, No,
107 [0x58] No, No, No, No, No, No, No, No,
108 [0x60] No, No, No, No, No, No, No, No,
109 [0x68] No, No, No, No, No, No, No, No,
110 [0x70] No, No, No, No, No, No, No, No,
111 [0x78] No, Up, No, No, No, No, No, No,
112 };
113
114 Rune kbtabshiftesc1[Nscan] =
115 {
116 [0x00] No, No, No, No, No, No, No, No,
117 [0x08] No, No, No, No, No, No, No, No,
118 [0x10] No, No, No, No, No, No, No, No,
119 [0x18] No, No, No, No, No, No, No, No,
120 [0x20] No, No, No, No, No, No, No, No,
121 [0x28] No, No, No, No, No, No, No, No,
122 [0x30] No, No, No, No, No, No, No, No,
123 [0x38] No, No, No, No, No, No, No, No,
124 [0x40] No, No, No, No, No, No, No, No,
125 [0x48] Up, No, No, No, No, No, No, No,
126 [0x50] No, No, No, No, No, No, No, No,
127 [0x58] No, No, No, No, No, No, No, No,
128 [0x60] No, No, No, No, No, No, No, No,
129 [0x68] No, No, No, No, No, No, No, No,
130 [0x70] No, No, No, No, No, No, No, No,
131 [0x78] No, Up, No, No, No, No, No, No,
132 };
133
134 Rune kbtabctrlesc1[Nscan] =
135 {
136 [0x00] No, No, No, No, No, No, No, No,
137 [0x08] No, No, No, No, No, No, No, No,
138 [0x10] No, No, No, No, No, No, No, No,
139 [0x18] No, No, No, No, No, No, No, No,
140 [0x20] No, No, No, No, No, No, No, No,
141 [0x28] No, No, No, No, No, No, No, No,
142 [0x30] No, No, No, No, No, No, No, No,
143 [0x38] No, No, No, No, No, No, No, No,
144 [0x40] No, No, No, No, No, No, No, No,
145 [0x48] Up, No, No, No, No, No, No, No,
146 [0x50] No, No, No, No, No, No, No, No,
147 [0x58] No, No, No, No, No, No, No, No,
148 [0x60] No, No, No, No, No, No, No, No,
149 [0x68] No, No, No, No, No, No, No, No,
150 [0x70] No, No, No, No, No, No, No, No,
151 [0x78] No, Up, No, No, No, No, No, No,
152 };
153
154 Rune kbtabaltgr[Nscan] =
155 {
156 [0x00] No, No, No, No, No, No, No, No,
157 [0x08] No, No, No, No, No, No, No, No,
158 [0x10] No, No, No, No, No, No, No, No,
159 [0x18] No, No, No, No, '\n', Ctrl, No, No,
160 [0x20] No, No, No, No, No, No, No, No,
161 [0x28] No, No, Shift, No, No, No, No, No,
162 [0x30] No, No, No, No, No, '/', No, Print,
163 [0x38] Altgr, No, No, No, No, No, No, No,
164 [0x40] No, No, No, No, No, No, Break, Home,
165 [0x48] Up, Pgup, No, Left, No, Right, No, End,
166 [0x50] Down, Pgdown, Ins, Del, No, No, No, No,
167 [0x58] No, No, No, No, No, No, No, No,
168 [0x60] No, No, No, No, No, No, No, No,
169 [0x68] No, No, No, No, No, No, No, No,
170 [0x70] No, No, No, No, No, No, No, No,
171 [0x78] No, Up, No, No, No, No, No, No,
172 };
173
174 Rune kbtabctrl[Nscan] =
175 {
176 [0x00] No, '', '', '', '', '', '', '',
177 [0x08] '', '', '', '', '
178 ', '', '\b', '\t',
179 [0x10] '', '', '', '', '', '', '', '\t',
180 [0x18] '', '', '', '', '\n', Ctrl, '', '',
181 [0x20] '', '', '', '\b', '\n', '', '', '',
182 [0x28] '', No, Shift, '', '', '', '', '',
183 [0x30] '', '', '
184 ', '', '', '', Shift, '\n',
185 [0x38] Latin, No, Ctrl, '', '', '', '', '',
186 [0x40] '', '', '', '
187 ', '', '', '', '',
188 [0x48] '', '', '
189 ', '', '', '', '', '',
190 [0x50] '', '', '', '', No, No, No, '',
191 [0x58] '', No, No, No, No, No, No, No,
192 [0x60] No, No, No, No, No, No, No, No,
193 [0x68] No, No, No, No, No, No, No, No,
194 [0x70] No, No, No, No, No, No, No, No,
195 [0x78] No, '', No, '\b', No, No, No, No,
196 };
197
198 int mouseshifted;
199 void (*kbdmouse)(int);
200
201 static int kdebug;
202
203 typedef struct Kbscan Kbscan;
204 struct Kbscan {
205 int esc1;
206 int esc2;
207 int alt;
208 int altgr;
209 int caps;
210 int ctl;
211 int num;
212 int shift;
213 int collecting;
214 int nk;
215 Rune kc[5];
216 int buttons;
217 };
218
219 Kbscan kbscans[Nscans]; /* kernel and external scan code state */
220
kbdputsc(int c,int external)221 /*
222 * Scan code processing
223 */
224 void
225 kbdputsc(int c, int external)
226 {
227 int i, keyup;
228 Kbscan *kbscan;
229
230 if(external)
231 kbscan = &kbscans[Ext];
232 else
233 kbscan = &kbscans[Int];
234
235 if(kdebug)
236 print("sc %x ms %d\n", c, mouseshifted);
237 /*
238 * e0's is the first of a 2 character sequence, e1 the first
239 * of a 3 character sequence (on the safari)
240 */
241 if(c == 0xe0){
242 kbscan->esc1 = 1;
243 return;
244 } else if(c == 0xe1){
245 kbscan->esc2 = 2;
246 return;
247 }
248
249 keyup = c & 0x80;
250 c &= 0x7f;
251 if(c > sizeof kbtab){
252 c |= keyup;
253 if(c != 0xFF) /* these come fairly often: CAPSLOCK U Y */
254 print("unknown key %ux\n", c);
255 return;
256 }
257
258 if(kbscan->esc1 && kbscan->shift){
259 c = kbtabshiftesc1[c];
260 kbscan->esc1 = 0;
261 } else if(kbscan->esc1){
262 c = kbtabesc1[c];
263 kbscan->esc1 = 0;
264 } else if(kbscan->esc2){
265 kbscan->esc2--;
266 return;
267 } else if(kbscan->shift)
268 c = kbtabshift[c];
269 else if(kbscan->altgr)
270 c = kbtabaltgr[c];
271 else if(kbscan->ctl)
272 c = kbtabctrl[c];
273 else
274 c = kbtab[c];
275
276 if(kbscan->caps && c<='z' && c>='a')
277 c += 'A' - 'a';
278
279 /*
280 * keyup only important for shifts
281 */
282 if(keyup){
283 switch(c){
284 case Latin:
285 kbscan->alt = 0;
286 break;
287 case Shift:
288 kbscan->shift = 0;
289 mouseshifted = 0;
290 if(kdebug)
291 print("shiftclr\n");
292 break;
293 case Ctrl:
294 kbscan->ctl = 0;
295 break;
296 case Altgr:
297 kbscan->altgr = 0;
298 break;
299 case Kmouse|1:
300 case Kmouse|2:
301 case Kmouse|3:
302 case Kmouse|4:
303 case Kmouse|5:
304 kbscan->buttons &= ~(1<<(c-Kmouse-1));
305 if(kbdmouse)
306 kbdmouse(kbscan->buttons);
307 break;
308 }
309 return;
310 }
311
312 /*
313 * normal character
314 */
315 if(!(c & (Spec|KF))){
316 if(kbscan->ctl)
317 if(kbscan->alt && c == Del)
318 exit(0);
319 if(!kbscan->collecting){
320 kbdputc(kbdq, c);
321 return;
322 }
323 kbscan->kc[kbscan->nk++] = c;
324 c = latin1(kbscan->kc, kbscan->nk);
325 if(c < -1) /* need more keystrokes */
326 return;
327 if(c != -1) /* valid sequence */
328 kbdputc(kbdq, c);
329 else /* dump characters */
330 for(i=0; i<kbscan->nk; i++)
331 kbdputc(kbdq, kbscan->kc[i]);
332 kbscan->nk = 0;
333 kbscan->collecting = 0;
334 return;
335 } else {
336 switch(c){
337 case Caps:
338 kbscan->caps ^= 1;
339 return;
340 case Num:
341 kbscan->num ^= 1;
342 return;
343 case Shift:
344 kbscan->shift = 1;
345 if(kdebug)
346 print("shift\n");
347 mouseshifted = 1;
348 return;
349 case Latin:
350 kbscan->alt = 1;
351 /*
352 * VMware and Qemu use Ctl-Alt as the key combination
353 * to make the VM give up keyboard and mouse focus.
354 * This has the unfortunate side effect that when you
355 * come back into focus, Plan 9 thinks you want to type
356 * a compose sequence (you just typed alt).
357 *
358 * As a clumsy hack around this, we look for ctl-alt and
359 * don't treat it as the start of a compose sequence.
360 */
361 if(!kbscan->ctl){
362 kbscan->collecting = 1;
363 kbscan->nk = 0;
364 }
365 return;
366 case Ctrl:
367 kbscan->ctl = 1;
368 return;
369 case Altgr:
370 kbscan->altgr = 1;
371 return;
372 case Kmouse|1:
373 case Kmouse|2:
374 case Kmouse|3:
375 case Kmouse|4:
376 case Kmouse|5:
377 kbscan->buttons |= 1<<(c-Kmouse-1);
378 if(kbdmouse)
379 kbdmouse(kbscan->buttons);
380 return;
381 case KF|11:
382 print("kbd debug on, F12 turns it off\n");
383 kdebug = 1;
384 break;
385 case KF|12:
386 kdebug = 0;
387 break;
388 }
389 }
390 kbdputc(kbdq, c);
391 }
392
393 void
394 kbdenable(void)
395 {
396 #ifdef notdef
397 kbdq = qopen(4*1024, 0, 0, 0);
398 if(kbdq == nil)
399 panic("kbdinit");
400 qnoblock(kbdq, 1);
401 #endif
kbdputmap(ushort m,ushort scanc,Rune r)402 kbscans[Int].num = 0;
403 }
404
405 void
406 kbdputmap(ushort m, ushort scanc, Rune r)
407 {
408 if(scanc >= Nscan)
409 error(Ebadarg);
410 switch(m) {
411 default:
412 error(Ebadarg);
413 case 0:
414 kbtab[scanc] = r;
415 break;
416 case 1:
417 kbtabshift[scanc] = r;
418 break;
419 case 2:
420 kbtabesc1[scanc] = r;
421 break;
422 case 3:
423 kbtabaltgr[scanc] = r;
424 break;
425 case 4:
426 kbtabctrl[scanc] = r;
427 break;
428 case 5:
429 kbtabctrlesc1[scanc] = r;
430 break;
431 case 6:
432 kbtabshiftesc1[scanc] = r;
433 break;
kbdgetmap(uint offset,int * t,int * sc,Rune * r)434 }
435 }
436
437 int
438 kbdgetmap(uint offset, int *t, int *sc, Rune *r)
439 {
440 if ((int)offset < 0)
441 error(Ebadarg);
442 *t = offset/Nscan;
443 *sc = offset%Nscan;
444 switch(*t) {
445 default:
446 return 0;
447 case 0:
448 *r = kbtab[*sc];
449 return 1;
450 case 1:
451 *r = kbtabshift[*sc];
452 return 1;
453 case 2:
454 *r = kbtabesc1[*sc];
455 return 1;
456 case 3:
457 *r = kbtabaltgr[*sc];
458 return 1;
459 case 4:
460 *r = kbtabctrl[*sc];
461 return 1;
462 case 5:
463 *r = kbtabctrlesc1[*sc];
464 return 1;
465 case 6:
466 *r = kbtabshiftesc1[*sc];
467 return 1;
468 }
469 }
470