xref: /plan9-contrib/sys/src/9/omap/kbd.c (revision 58da3067adcdccaaa043d0bfde28ba83b7ced07d)
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