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