27 typedef struct Key Key;
28 typedef struct Scan Scan;
32 Rune b; /* button, unshifted key */
33 Rune r; /* rune, shifted key */
83 char Eshort[] = "read count too small";
84 char Ebadarg[] = "invalid argument";
85 char Eperm[] = "permission denied";
86 char Einuse[] = "file in use";
87 char Enonexist[] = "file does not exist";
88 char Ebadspec[] = "bad attach specifier";
89 char Ewalk[] = "walk in non directory";
90 char Ephase[] = "the front fell off";
91 char Eintr[] = "interrupted";
106 char *mntpt = "/dev";
111 Channel *keychan; /* chan(Key) */
112 Channel *mctlchan; /* chan(Key) */
114 Channel *kbdreqchan; /* chan(Req*) */
115 Channel *consreqchan; /* chan(Req*) */
117 Channel *ctlchan; /* chan(int) */
119 Channel *rawchan; /* chan(Rune) */
120 Channel *runechan; /* chan(Rune) */
122 Channel *conschan; /* chan(char*) */
123 Channel *kbdchan; /* chan(char*) */
124 Channel *intchan; /* chan(int) */
127 * The codes at 0x79 and 0x7b are produced by the PFU Happy Hacking keyboard.
128 * A 'standard' keyboard doesn't produce anything above 0x58.
132 [0x00] 0, 0x1b, '1', '2', '3', '4', '5', '6',
133 [0x08] '7', '8', '9', '0', '-', '=', '\b', '\t',
134 [0x10] 'q', 'w', 'e', 'r', 't', 'y', 'u', 'i',
135 [0x18] 'o', 'p', '[', ']', '\n', Kctl, 'a', 's',
136 [0x20] 'd', 'f', 'g', 'h', 'j', 'k', 'l', ';',
137 [0x28] '\'', '`', Kshift, '\\', 'z', 'x', 'c', 'v',
138 [0x30] 'b', 'n', 'm', ',', '.', '/', Kshift, '*',
139 [0x38] Kalt, ' ', Kctl, KF|1, KF|2, KF|3, KF|4, KF|5,
140 [0x40] KF|6, KF|7, KF|8, KF|9, KF|10, Knum, Kscroll,'7',
141 [0x48] '8', '9', '-', '4', '5', '6', '+', '1',
142 [0x50] '2', '3', '0', '.', 0, 0, 0, KF|11,
143 [0x58] KF|12, 0, 0, 0, 0, 0, 0, 0,
144 [0x60] 0, 0, 0, 0, 0, 0, 0, 0,
145 [0x68] 0, 0, 0, 0, 0, 0, 0, 0,
146 [0x70] 0, 0, 0, 0, 0, 0, 0, 0,
147 [0x78] 0, Kdown, 0, Kup, 0, 0, 0, 0,
150 Rune kbtabshift[Nscan] =
152 [0x00] 0, 0x1b, '!', '@', '#', '$', '%', '^',
153 [0x08] '&', '*', '(', ')', '_', '+', '\b', '\t',
154 [0x10] 'Q', 'W', 'E', 'R', 'T', 'Y', 'U', 'I',
155 [0x18] 'O', 'P', '{', '}', '\n', Kctl, 'A', 'S',
156 [0x20] 'D', 'F', 'G', 'H', 'J', 'K', 'L', ':',
157 [0x28] '"', '~', Kshift, '|', 'Z', 'X', 'C', 'V',
158 [0x30] 'B', 'N', 'M', '<', '>', '?', Kshift, '*',
159 [0x38] Kalt, ' ', Kctl, KF|1, KF|2, KF|3, KF|4, KF|5,
160 [0x40] KF|6, KF|7, KF|8, KF|9, KF|10, Knum, Kscroll,'7',
161 [0x48] '8', '9', '-', '4', '5', '6', '+', '1',
162 [0x50] '2', '3', '0', '.', 0, 0, 0, KF|11,
163 [0x58] KF|12, 0, 0, 0, 0, 0, 0, 0,
164 [0x60] 0, 0, 0, 0, 0, 0, 0, 0,
165 [0x68] 0, 0, 0, 0, 0, 0, 0, 0,
166 [0x70] 0, 0, 0, 0, 0, 0, 0, 0,
167 [0x78] 0, Kdown, 0, Kup, 0, 0, 0, 0,
170 Rune kbtabesc1[Nscan] =
172 [0x00] 0, 0, 0, 0, 0, 0, 0, 0,
173 [0x08] 0, 0, 0, 0, 0, 0, 0, 0,
174 [0x10] 0, 0, 0, 0, 0, 0, 0, 0,
175 [0x18] 0, 0, 0, 0, '\n', Kctl, 0, 0,
176 [0x20] 0, 0, 0, 0, 0, 0, 0, 0,
177 [0x28] 0, 0, 0, 0, 0, 0, 0, 0,
178 [0x30] 0, 0, 0, 0, 0, '/', 0, Kprint,
179 [0x38] Kaltgr, 0, 0, 0, 0, 0, 0, 0,
180 [0x40] 0, 0, 0, 0, 0, 0, Kbreak, Khome,
181 [0x48] Kup, Kpgup, 0, Kleft, 0, Kright, 0, Kend,
182 [0x50] Kdown, Kpgdown,Kins, Kdel, 0, 0, 0, 0,
183 [0x58] 0, 0, 0, Kmod4, 0, 0, 0, 0,
184 [0x60] 0, 0, 0, 0, 0, 0, 0, 0,
185 [0x68] 0, 0, 0, 0, 0, 0, 0, 0,
186 [0x70] 0, 0, 0, 0, 0, 0, 0, 0,
187 [0x78] 0, Kup, 0, 0, 0, 0, 0, 0,
190 Rune kbtabshiftesc1[Nscan] =
192 [0x00] 0, 0, 0, 0, 0, 0, 0, 0,
193 [0x08] 0, 0, 0, 0, 0, 0, 0, 0,
194 [0x10] 0, 0, 0, 0, 0, 0, 0, 0,
195 [0x18] 0, 0, 0, 0, 0, 0, 0, 0,
196 [0x20] 0, 0, 0, 0, 0, 0, 0, 0,
197 [0x28] 0, 0, 0, 0, 0, 0, 0, 0,
198 [0x30] 0, 0, 0, 0, 0, 0, 0, 0,
199 [0x38] 0, 0, 0, 0, 0, 0, 0, 0,
200 [0x40] 0, 0, 0, 0, 0, 0, 0, 0,
201 [0x48] Kup, 0, 0, 0, 0, 0, 0, 0,
202 [0x50] 0, 0, 0, 0, 0, 0, 0, 0,
203 [0x58] 0, 0, 0, 0, 0, 0, 0, 0,
204 [0x60] 0, 0, 0, 0, 0, 0, 0, 0,
205 [0x68] 0, 0, 0, 0, 0, 0, 0, 0,
206 [0x70] 0, 0, 0, 0, 0, 0, 0, 0,
207 [0x78] 0, Kup, 0, 0, 0, 0, 0, 0,
210 Rune kbtabctrlesc1[Nscan] =
212 [0x00] 0, 0, 0, 0, 0, 0, 0, 0,
213 [0x08] 0, 0, 0, 0, 0, 0, 0, 0,
214 [0x10] 0, 0, 0, 0, 0, 0, 0, 0,
215 [0x18] 0, 0, 0, 0, 0, 0, 0, 0,
216 [0x20] 0, 0, 0, 0, 0, 0, 0, 0,
217 [0x28] 0, 0, 0, 0, 0, 0, 0, 0,
218 [0x30] 0, 0, 0, 0, 0, 0, 0, 0,
219 [0x38] 0, 0, 0, 0, 0, 0, 0, 0,
220 [0x40] 0, 0, 0, 0, 0, 0, 0, 0,
221 [0x48] Kup, 0, 0, 0, 0, 0, 0, 0,
222 [0x50] 0, 0, 0, 0, 0, 0, 0, 0,
223 [0x58] 0, 0, 0, 0, 0, 0, 0, 0,
224 [0x60] 0, 0, 0, 0, 0, 0, 0, 0,
225 [0x68] 0, 0, 0, 0, 0, 0, 0, 0,
226 [0x70] 0, 0, 0, 0, 0, 0, 0, 0,
227 [0x78] 0, Kup, 0, 0, 0, 0, 0, 0,
230 Rune kbtabaltgr[Nscan] =
232 [0x00] 0, 0, 0, 0, 0, 0, 0, 0,
233 [0x08] 0, 0, 0, 0, 0, 0, 0, 0,
234 [0x10] 0, 0, 0, 0, 0, 0, 0, 0,
235 [0x18] 0, 0, 0, 0, '\n', Kctl, 0, 0,
236 [0x20] 0, 0, 0, 0, 0, 0, 0, 0,
237 [0x28] 0, 0, Kshift, 0, 0, 0, 0, 0,
238 [0x30] 0, 0, 0, 0, 0, '/', 0, Kprint,
239 [0x38] Kaltgr, 0, 0, 0, 0, 0, 0, 0,
240 [0x40] 0, 0, 0, 0, 0, 0, Kbreak, Khome,
241 [0x48] Kup, Kpgup, 0, Kleft, 0, Kright, 0, Kend,
242 [0x50] Kdown, Kpgdown,Kins, Kdel, 0, 0, 0, 0,
243 [0x58] 0, 0, 0, 0, 0, 0, 0, 0,
244 [0x60] 0, 0, 0, 0, 0, 0, 0, 0,
245 [0x68] 0, 0, 0, 0, 0, 0, 0, 0,
246 [0x70] 0, 0, 0, 0, 0, 0, 0, 0,
247 [0x78] 0, Kup, 0, 0, 0, 0, 0, 0,
250 Rune kbtabctl[Nscan] =
252 [0x00] 0, '
\e', '
\11', '
\12', '
\13', '
\14', '
\15', '
\16',
253 [0x08] '
\17', '
\18', '
\19', '
\10', '
\r', '
\1d', '\b', '\t',
254 [0x10] '
\11', '
\17', '
\ 5', '
\12', '
\14', '
\19', '
\15', '\t',
255 [0x18] '
\ f', '
\10', '
\e', '
\1d', '\n', Kctl, '
\ 1', '
\13',
256 [0x20] '
\ 4', '
\ 6', '
\a', '\b', '\n', '
\v', '
\f', '
\e',
257 [0x28] '
\a', 0, Kshift, '
\1c', '
\1a', '
\18', '
\ 3', '
\16',
258 [0x30] '
\ 2', '
\ e', '
\r', '
\f', '
\ e', '
\ f', Kshift, '\n',
259 [0x38] Kalt, 0, Kctl, '
\ 5', '
\ 6', '
\a', '
\ 4', '
\ 5',
260 [0x40] '
\ 6', '
\a', '
\f', '
\r', '
\ e', '
\ 5', '
\ 6', '
\17',
261 [0x48] '
\18', '
\19', '
\r', '
\14', '
\15', '
\16', '
\v', '
\11',
262 [0x50] '
\12', '
\13', '
\10', '
\ e', 0, 0, 0, '
\ f',
263 [0x58] '
\f', 0, 0, 0, 0, 0, 0, 0,
264 [0x60] 0, 0, 0, 0, 0, 0, 0, 0,
265 [0x68] 0, 0, 0, 0, 0, 0, 0, 0,
266 [0x70] 0, 0, 0, 0, 0, 0, 0, 0,
267 [0x78] 0, '
\a', 0, '\b', 0, 0, 0, 0,
270 Rune kbtabshiftaltgr[Nscan] =
272 [0x00] 0, 0, 0, 0, 0, 0, 0, 0,
273 [0x08] 0, 0, 0, 0, 0, 0, 0, 0,
274 [0x10] 0, 0, 0, 0, 0, 0, 0, 0,
275 [0x18] 0, 0, 0, 0, 0, 0, 0, 0,
276 [0x20] 0, 0, 0, 0, 0, 0, 0, 0,
277 [0x28] 0, 0, 0, 0, 0, 0, 0, 0,
278 [0x30] 0, 0, 0, 0, 0, 0, 0, 0,
279 [0x38] 0, 0, 0, 0, 0, 0, 0, 0,
280 [0x40] 0, 0, 0, 0, 0, 0, 0, 0,
281 [0x48] 0, 0, 0, 0, 0, 0, 0, 0,
282 [0x50] 0, 0, 0, 0, 0, 0, 0, 0,
283 [0x58] 0, 0, 0, 0, 0, 0, 0, 0,
284 [0x60] 0, 0, 0, 0, 0, 0, 0, 0,
285 [0x68] 0, 0, 0, 0, 0, 0, 0, 0,
286 [0x70] 0, 0, 0, 0, 0, 0, 0, 0,
287 [0x78] 0, 0, 0, 0, 0, 0, 0, 0,
290 Rune kbtabmod4[Nscan] =
292 [0x00] 0, 0, 0, 0, 0, 0, 0, 0,
293 [0x08] 0, 0, 0, 0, 0, 0, 0, 0,
294 [0x10] 0, 0, 0, 0, 0, 0, 0, 0,
295 [0x18] 0, 0, 0, 0, 0, 0, 0, 0,
296 [0x20] 0, 0, 0, 0, 0, 0, 0, 0,
297 [0x28] 0, 0, 0, 0, 0, 0, 0, 0,
298 [0x30] 0, 0, 0, 0, 0, 0, 0, 0,
299 [0x38] 0, 0, 0, 0, 0, 0, 0, 0,
300 [0x40] 0, 0, 0, 0, 0, 0, 0, 0,
301 [0x48] 0, 0, 0, 0, 0, 0, 0, 0,
302 [0x50] 0, 0, 0, 0, 0, 0, 0, 0,
303 [0x58] 0, 0, 0, 0, 0, 0, 0, 0,
304 [0x60] 0, 0, 0, 0, 0, 0, 0, 0,
305 [0x68] 0, 0, 0, 0, 0, 0, 0, 0,
306 [0x70] 0, 0, 0, 0, 0, 0, 0, 0,
307 [0x78] 0, 0, 0, 0, 0, 0, 0, 0,
310 Rune kbtabaltgrmod4[Nscan] =
312 [0x00] 0, 0, 0, 0, 0, 0, 0, 0,
313 [0x08] 0, 0, 0, 0, 0, 0, 0, 0,
314 [0x10] 0, 0, 0, 0, 0, 0, 0, 0,
315 [0x18] 0, 0, 0, 0, 0, 0, 0, 0,
316 [0x20] 0, 0, 0, 0, 0, 0, 0, 0,
317 [0x28] 0, 0, 0, 0, 0, 0, 0, 0,
318 [0x30] 0, 0, 0, 0, 0, 0, 0, 0,
319 [0x38] 0, 0, 0, 0, 0, 0, 0, 0,
320 [0x40] 0, 0, 0, 0, 0, 0, 0, 0,
321 [0x48] 0, 0, 0, 0, 0, 0, 0, 0,
322 [0x50] 0, 0, 0, 0, 0, 0, 0, 0,
323 [0x58] 0, 0, 0, 0, 0, 0, 0, 0,
324 [0x60] 0, 0, 0, 0, 0, 0, 0, 0,
325 [0x68] 0, 0, 0, 0, 0, 0, 0, 0,
326 [0x70] 0, 0, 0, 0, 0, 0, 0, 0,
327 [0x78] 0, 0, 0, 0, 0, 0, 0, 0,
333 static char *buf = nil;
335 buf = smprint("%s/%s", mntpt, file);
340 eopen(char *name, int mode)
344 fd = open(name, mode);
346 fprint(2, "%s: warning: can't open %s: %r\n", argv0, name);
358 if((fd = eopen(dev("reboot"), OWRITE)) < 0)
360 fprint(fd, "reboot\n");
368 write(notefd, "hangup", 6);
370 write(killfd, "hangup", 6);
377 Key key = { .down = 0, .r = Kshift, .b = Kshift };
382 * Scan code processing
385 kbdputsc(Scan *scan, int c)
390 * e0's is the first of a 2 character sequence, e1 and e2 the first
391 * of a 3 character sequence (on the safari)
396 } else if(c == 0xe1 || c == 0xe2){
399 } else if(c == 0xe0){
404 key.down = (c & 0x80) == 0;
410 /* qemu workarround: emulate e0 for numpad */
411 if(c != 0 && strchr("GHIKMOPQRS", c) != nil)
412 scan->esc1 |= !scan->num;
414 if(scan->esc1 && scan->ctl && kbtabctrlesc1[c] != 0)
415 key.r = kbtabctrlesc1[c];
416 else if(scan->esc1 && scan->shift && kbtabshiftesc1[c] != 0)
417 key.r = kbtabshiftesc1[c];
419 key.r = kbtabesc1[c];
420 else if(scan->altgr && scan->mod4 && kbtabaltgrmod4[c] != 0)
421 key.r = kbtabaltgrmod4[c];
422 else if(scan->mod4 && kbtabmod4[c] != 0)
423 key.r = kbtabmod4[c];
424 else if(scan->shift && scan->altgr && kbtabshiftaltgr[c] != 0)
425 key.r = kbtabshiftaltgr[c];
427 key.r = kbtabshift[c];
429 key.r = kbtabaltgr[c];
435 if(scan->esc1 || kbtab[c] == 0)
440 if(scan->caps && key.r<='z' && key.r>='a')
443 if(scan->ctl && scan->alt && key.r == Kdel){
455 scan->shift = key.down;
458 scan->ctl = key.down;
461 scan->altgr = key.down;
464 scan->mod4 = key.down;
467 scan->alt = key.down;
470 scan->num ^= key.down;
473 scan->caps ^= key.down;
480 kbdin(Scan *a, char *p, int n)
486 if(n > 0 && p[n-1] != 0){
488 * old format as used by bitsy keyboard:
489 * just a string of characters, no keyup
497 p += chartorune(&k.r, p);
511 chartorune(&k.r, p+1);
515 k.down = (p[0] == 'r');
516 for(i=0; i<Nscan; i++){
517 if(kbtab[i] == k.r || kbtabshift[i] == k.r || (i >= 16 && kbtabctl[i] == k.r)){
518 /* assign button from kbtab */
520 /* handle ^X forms */
521 if(k.r == kbtab[i] && kbtabctl[i] && !a->shift && !a->altgr && a->ctl)
526 /* button unknown to kbtab, use rune if no modifier keys are active */
527 if(k.b == 0 && !a->shift && !a->altgr && !a->ctl)
531 else if(k.r == Kaltgr)
533 else if(k.r == Kmod4)
541 chartorune(&k.r, p+1);
542 nbsend(runechan, &k.r);
551 if(nbsendp(kbdchan, s) <= 0)
560 setleds(Scan *scan, int leds)
564 if(ledsfd < 0 || scan->leds == leds)
567 snprint(buf, sizeof(buf), "%d", leds);
568 pwrite(ledsfd, buf, strlen(buf), 0);
573 * Read scan codes from scanfd
582 threadsetname("scanproc");
584 memset(&scan, 0, sizeof scan);
585 while((n = read(scanfd, buf, sizeof buf)) > 0){
587 kbdputsc(&scan, buf[i]);
588 setleds(&scan, (scan.num<<1) | (scan.caps<<2));
601 threadsetname("kbdiproc");
603 memset(&a, 0, sizeof(a));
604 while((n = read(kbdifd, buf, sizeof buf)) > 0)
611 utfconv(Rune *r, int n)
616 l = runenlen(r, n) + 1;
618 for(p = s; n > 0; r++, n--)
619 p += runetochar(p, r);
625 * Read key events from keychan and produce characters to
626 * rawchan and keystate in kbdchan.
636 threadsetname("keyproc");
639 while(recv(keychan, &key) > 0){
640 if(key.r >= Kmouse+1 && key.r <= Kmouse+5){
642 send(mctlchan, &key);
647 for(i=0; i<nb && rb[i+1] != key.b; i++)
650 while(i < nb && rb[i+1] == key.b){
651 memmove(rb+i+1, rb+i+2, (nb-i+1) * sizeof(rb[0]));
655 } else if(i == nb && nb < nelem(rb)-1 && key.b){
662 s = utfconv(rb, nb+1);
663 if(nbsendp(kbdchan, s) <= 0)
667 send(mctlchan, &key);
669 if(key.down && key.r)
670 send(rawchan, &key.r);
675 * Read characters from consfd (serial console)
680 char *p, *e, *x, buf[64];
684 threadsetname("consproc");
688 e = buf + sizeof(buf);
689 while((n = read(consfd, p, e - p)) > 0){
692 while((n = x - p) > 0){
697 p += chartorune(&r, p);
698 if(r == 021 || r == 023) /* XON/XOFF */
700 if(r == 0 || r == Runeerror){
720 nextrune(Channel *ch, Rune *r)
722 while(recv(ch, r) > 0){
730 /* ignore modifiers */
735 /* composing escapes */
744 * Read runes from rawchan, possibly compose special characters
745 * and output the new runes to runechan
751 char *ld; /* must be seen before using this conversion */
752 char *si; /* options for last input characters */
753 Rune *so; /* the corresponding Rune for each si entry */
761 threadsetname("runeproc");
764 while((i = nextrune(rawchan, &r)) >= 0){
778 * emulators like qemu and vmware use Ctrl+Alt to lock
779 * keyboard input so dont confuse them for a compose
785 if(nextrune(rawchan, &r))
788 if(r == 'x' || r == 'X'){
789 i = (r == 'X') ? 4 : 6;
792 if(nextrune(rawchan, &rr))
794 if(rr >= '0' && rr <= '9')
795 r = (r << 4) | (rr - '0');
796 else if(rr >= 'a' && rr <= 'f')
797 r = (r << 4) | (10 + (rr - 'a'));
798 else if(rr >= 'A' && rr <= 'F')
799 r = (r << 4) | (10 + (rr - 'A'));
803 if((i == 0 || rr == ';') && r != 0 && r <= Runemax)
806 if(nextrune(rawchan, &rr))
808 for(i = 0; i<nelem(tab); i++){
809 if(tab[i].ld[0] != r)
811 if(tab[i].ld[1] == 0)
813 if(tab[i].ld[1] == rr){
814 nextrune(rawchan, &rr);
818 if(i == nelem(tab) || rr == 0)
820 for(j = 0; tab[i].si[j]; j++){
821 if(tab[i].si[j] != rr)
831 * Need to do this in a separate proc because if process we're interrupting
832 * is dying and trying to print tombstone, kernel is blocked holding p->debug lock.
837 threadsetname("intrproc");
839 while(recv(intchan, nil) > 0)
840 write(notefd, "interrupt", 9);
844 * Process Kmouse keys and mouse button swap on shift,
845 * unblank screen by twiching.
853 threadsetname("mctlproc");
856 if(nbrecv(mctlchan, &key) <= 0){
858 fprint(mctlfd, "twitch");
859 if(recv(mctlchan, &key) <= 0)
863 if(mctlfd >= 0 && key.r == Kshift){
865 fprint(mctlfd, "buttonmap 132");
867 fprint(mctlfd, "swap");
868 fprint(mctlfd, "swap");
873 if(msinfd >= 0 && key.r >= Kmouse+1 && key.r <= Kmouse+5){
874 i = 1<<(key.r-(Kmouse+1));
879 fprint(msinfd, "m%11d %11d %11d", 0, 0, mouseb);
886 * Cook lines for cons
898 threadsetname("lineproc");
907 if(nbsend(intchan, ¬efd) <= 0)
910 case '\0': /* flush */
913 case Kbs: /* ^H: erase character */
914 case Knack: /* ^U: erase line */
915 case Ketb: /* ^W: erase word */
921 if(r == Ketb && utfrune(" \t", rb[nr]))
925 case Keof: /* ^D: eof */
935 } while(!done && nr < nelem(rb));
937 if(nbsendp(conschan, s) <= 0)
943 * Reads Tread and Tflush requests from reqchan and responds
944 * to them with data received on the string channel.
949 enum { AREQ, ASTR, AEND };
956 threadsetname("reqproc");
966 a[AREQ].op = CHANRCV;
967 a[AREQ].c = ac[0]; /* chan(Req*) */
970 a[ASTR].c = ac[1]; /* chan(char*) */
973 a[AEND].op = CHANEND;
976 a[ASTR].op = s != nil ? CHANNOP : CHANRCV;
980 if(r->ifcall.type == Tflush){
983 for(rr = &q; *rr; rr=xx){
985 if(*rr == r->oldreq){
986 if((*rr = *xx) == nil)
988 respond(r->oldreq, Eintr);
994 } else if(r->ifcall.type != Tread){
1007 while(s != nil && q != nil){
1009 if((q = q->aux) == nil)
1011 r->ofcall.count = 0;
1015 if(r->fid->qid.path == Qkbd)
1016 e++; /* send terminating \0 if its kbd file */
1019 m = r->ifcall.count - r->ofcall.count;
1021 if(r->ofcall.count > 0){
1027 memmove((char*)r->ofcall.data + r->ofcall.count, p, n);
1028 r->ofcall.count += n;
1032 s = nbrecvp(a[ASTR].c);
1045 * Keep track of rawing state and distribute the runes from
1046 * runechan to the right channels depending on the state.
1051 Channel *cook, *aconsr[2], *akbdr[2];
1052 enum { ACTL, ARUNE, AEND };
1058 threadsetname("ctlproc");
1061 proccreate(kbdiproc, nil, STACK); /* kbdifd -> kbdin() */
1062 if(mctlfd >= 0 || msinfd >= 0)
1063 proccreate(mctlproc, nil, STACK); /* mctlchan -> mctlfd, msinfd */
1065 proccreate(scanproc, nil, STACK); /* scanfd -> keychan */
1067 proccreate(consproc, nil, STACK); /* consfd -> runechan */
1069 proccreate(intrproc, nil, STACK); /* intchan -> notefd */
1071 threadcreate(keyproc, nil, STACK); /* keychan -> mctlchan, rawchan, kbdchan */
1072 threadcreate(runeproc, nil, STACK); /* rawchan -> runechan */
1074 aconsr[0] = consreqchan;
1075 aconsr[1] = conschan;
1076 threadcreate(reqproc, aconsr, STACK); /* consreqchan,conschan -> respond */
1078 akbdr[0] = kbdreqchan;
1080 threadcreate(reqproc, akbdr, STACK); /* kbdreqchan,kbdchan -> respond */
1082 cook = chancreate(sizeof(Rune), 0);
1083 threadcreate(lineproc, cook, STACK); /* cook -> conschan */
1087 a[ACTL].c = ctlchan;
1089 a[ACTL].op = CHANRCV;
1091 a[ARUNE].c = runechan;
1093 a[ARUNE].op = CHANRCV;
1095 a[AEND].op = CHANEND;
1103 if(raw = (c == Rawon)){
1111 s = emalloc9p(UTFmax+2);
1113 s[1+runetochar(s+1, &r)] = 0;
1114 if(nbsendp(kbdchan, s) <= 0)
1119 s = emalloc9p(UTFmax+1);
1120 s[runetochar(s, &r)] = 0;
1121 if(nbsendp(conschan, s) <= 0)
1132 * Keyboard layout maps
1136 kbmapent(int t, int sc)
1138 static Rune *tabs[] = {
1144 /* 5 */ kbtabctrlesc1,
1145 /* 6 */ kbtabshiftesc1,
1146 /* 7 */ kbtabshiftaltgr,
1148 /* 9 */ kbtabaltgrmod4,
1150 if(t >= 0 && t < nelem(tabs) && sc >= 0 && sc < Nscan)
1151 return &tabs[t][sc];
1159 int t, sc, soff, off, n;
1162 off = req->ifcall.offset/(sizeof(tmp)-1);
1163 soff = req->ifcall.offset%(sizeof(tmp)-1);
1166 if(rp = kbmapent(t, sc)){
1167 sprint(tmp, "%11d %11d %11d\n", t, sc, *rp);
1168 n = strlen(&tmp[soff]);
1169 if(req->ifcall.count < n)
1170 n = req->ifcall.count;
1171 req->ofcall.count = n;
1172 memmove(req->ofcall.data, &tmp[soff], n);
1174 req->ofcall.count = 0;
1181 static Rune o = Spec|0x60, tab[] = {
1182 Kshift, Kbreak, Kctl, Kalt,
1183 Kcaps, Knum, Kmiddle, Kaltgr,
1186 if(r >= o && r < o+nelem(tab))
1192 kbmapwrite(Req *req)
1194 char line[100], *lp, *b;
1200 b = req->ifcall.data;
1201 l = req->ifcall.count;
1204 strcpy(line, f->aux);
1205 lp = line+strlen(line);
1211 if(lp[-1] == '\n' || lp == &line[sizeof(line)-1]) {
1215 respond(req, Ebadarg);
1218 if(*line == '\n' || *line == '#'){
1223 while(*lp == ' ' || *lp == '\t')
1225 t = strtoul(line, &lp, 0);
1226 sc = strtoul(lp, &lp, 0);
1227 while(*lp == ' ' || *lp == '\t')
1229 if((rp = kbmapent(t, sc)) == nil)
1232 if(*lp == '\'' && lp[1])
1233 chartorune(&r, lp+1);
1234 else if(*lp == '^' && lp[1]){
1235 chartorune(&r, lp+1);
1236 if(0x40 <= r && r < 0x60)
1240 }else if(*lp == 'M' && ('1' <= lp[1] && lp[1] <= '5'))
1241 r = Kmouse+lp[1]-'0';
1242 else if(*lp>='0' && *lp<='9') /* includes 0x... */
1243 r = strtoul(lp, &lp, 0);
1252 f->aux = lp = emalloc9p(l+1);
1253 memmove(lp, line, l);
1256 req->ofcall.count = req->ifcall.count;
1265 fillstat(ulong qid, Dir *d)
1269 memset(d, 0, sizeof *d);
1270 d->uid = d->gid = user;
1272 d->qid = (Qid){qid, 0, 0};
1276 d->qid.type = t->type;
1286 spec = r->ifcall.aname;
1287 if(spec && spec[0]){
1288 respond(r, Ebadspec);
1291 r->fid->qid = (Qid){Qroot, 0, QTDIR};
1292 r->ofcall.qid = r->fid->qid;
1299 fillstat((ulong)r->fid->qid.path, &r->d);
1300 r->d.name = estrdup9p(r->d.name);
1301 r->d.uid = estrdup9p(r->d.uid);
1302 r->d.gid = estrdup9p(r->d.gid);
1303 r->d.muid = estrdup9p(r->d.muid);
1308 fswalk1(Fid *fid, char *name, Qid *qid)
1313 path = fid->qid.path;
1316 if (strcmp(name, "..") == 0) {
1317 *qid = (Qid){Qroot, 0, QTDIR};
1321 for(i = fid->qid.path; i<Nqid; i++){
1322 if(strcmp(name, qtab[i].name) != 0)
1324 *qid = (Qid){i, 0, 0};
1339 static int need[4] = { 4, 2, 6, 1 };
1344 t = qtab + f->qid.path;
1345 n = need[r->ifcall.mode & 3]<<6;
1346 if((n & t->mode) != n)
1350 switch((ulong)f->qid.path){
1367 readtopdir(Fid*, uchar *buf, long off, int cnt, int blen)
1375 for (i = 1; i < Nqid; i++){
1377 m = convD2M(&d, &buf[n], blen-n);
1379 if(m <= BIT16SZ || m > cnt)
1395 switch((ulong)f->qid.path){
1400 r->ofcall.count = readtopdir(f, (void*)r->ofcall.data, r->ifcall.offset,
1401 r->ifcall.count, r->ifcall.count);
1404 sendp(kbdreqchan, r);
1407 sendp(consreqchan, r);
1425 n = r->ifcall.count;
1426 switch((ulong)f->qid.path){
1432 if(write(1, p, n) != n){
1439 if(n >= 5 && memcmp(p, "rawon", 5) == 0)
1440 sendul(ctlchan, Rawon);
1441 else if(n >= 6 && memcmp(p, "rawoff", 6) == 0)
1442 sendul(ctlchan, Rawoff);
1444 respond(r, Ebadarg);
1452 f->aux = emalloc9p(sizeof(Scan));
1453 memset(f->aux, 0, sizeof(Scan));
1455 if(f->qid.path == Qkbin){
1457 kbdputsc((Scan*)f->aux, (uchar)p[i]);
1459 kbdin((Scan*)f->aux, p, n);
1468 r->ofcall.count = n;
1475 switch((ulong)r->oldreq->fid->qid.path) {
1477 sendp(kbdreqchan, r);
1480 sendp(consreqchan, r);
1487 fsdestroyfid(Fid *f)
1492 switch((ulong)f->qid.path){
1505 if(--consctlopen == 0)
1506 sendul(ctlchan, Rawoff);
1512 procopen(int pid, char *name, int mode)
1516 snprint(buf, sizeof(buf), "/proc/%d/%s", pid, name);
1517 return eopen(buf, mode);
1529 if((fd = procopen(getpid(), "ctl", OWRITE)) < 0)
1532 /* get higher than normal priority */
1533 fprint(fd, "pri 16\n");
1535 /* always present in physical memory */
1536 fprint(fd, "noswap\n");
1538 /* dont let anybody kill us */
1539 if(d = dirfstat(fd)){
1541 nd.mode = d->mode & ~0222;
1552 killfd = procopen(getpid(), "notepg", OWRITE);
1554 proccreate(ctlproc, nil, STACK);
1572 .destroyfid= fsdestroyfid,
1579 fprint(2, "usage: %s [ -qdD ] [ -s sname ] [ -m mntpnt ] [ file ]\n", argv0);
1584 threadmain(int argc, char** argv)
1594 sname = EARGF(usage());
1597 mntpt = EARGF(usage());
1607 consfd = eopen(*argv, OREAD);
1609 kbdifd = open(dev("kbd"), OREAD);
1611 scanfd = eopen(dev("scancode"), OREAD);
1612 ledsfd = eopen(dev("leds"), OWRITE);
1614 mctlfd = eopen(dev("mousectl"), OWRITE);
1615 msinfd = eopen(dev("mousein"), OWRITE);
1617 notefd = procopen(getpid(), "notepg", OWRITE);
1619 consreqchan = chancreate(sizeof(Req*), 0);
1620 kbdreqchan = chancreate(sizeof(Req*), 0);
1622 keychan = chancreate(sizeof(Key), 64);
1623 mctlchan = chancreate(sizeof(Key), 64);
1624 ctlchan = chancreate(sizeof(int), 0);
1625 rawchan = chancreate(sizeof(Rune), 0);
1626 runechan = chancreate(sizeof(Rune), 256);
1627 conschan = chancreate(sizeof(char*), 128);
1628 kbdchan = chancreate(sizeof(char*), 128);
1629 intchan = chancreate(sizeof(int), 0);
1632 threadpostmountsrv(&fs, sname, mntpt, MBEFORE);