26 typedef struct Key Key;
27 typedef struct Scan Scan;
78 char Eshort[] = "read count too small";
79 char Ebadarg[] = "invalid argument";
80 char Eperm[] = "permission denied";
81 char Einuse[] = "file in use";
82 char Enonexist[] = "file does not exist";
83 char Ebadspec[] = "bad attach specifier";
84 char Ewalk[] = "walk in non directory";
85 char Ephase[] = "the front fell off";
86 char Eintr[] = "interrupted";
98 Channel *keychan; /* chan(Key) */
100 Channel *kbdreqchan; /* chan(Req*) */
101 Channel *consreqchan; /* chan(Req*) */
103 Channel *ctlchan; /* chan(int) */
105 Channel *rawchan; /* chan(Rune) */
106 Channel *runechan; /* chan(Rune) */
108 Channel *conschan; /* chan(char*) */
109 Channel *kbdchan; /* chan(char*) */
112 * The codes at 0x79 and 0x7b are produced by the PFU Happy Hacking keyboard.
113 * A 'standard' keyboard doesn't produce anything above 0x58.
117 [0x00] 0, 0x1b, '1', '2', '3', '4', '5', '6',
118 [0x08] '7', '8', '9', '0', '-', '=', '\b', '\t',
119 [0x10] 'q', 'w', 'e', 'r', 't', 'y', 'u', 'i',
120 [0x18] 'o', 'p', '[', ']', '\n', Kctl, 'a', 's',
121 [0x20] 'd', 'f', 'g', 'h', 'j', 'k', 'l', ';',
122 [0x28] '\'', '`', Kshift, '\\', 'z', 'x', 'c', 'v',
123 [0x30] 'b', 'n', 'm', ',', '.', '/', Kshift, '*',
124 [0x38] Kalt, ' ', Kctl, KF|1, KF|2, KF|3, KF|4, KF|5,
125 [0x40] KF|6, KF|7, KF|8, KF|9, KF|10, Knum, Kscroll, '7',
126 [0x48] '8', '9', '-', '4', '5', '6', '+', '1',
127 [0x50] '2', '3', '0', '.', 0, 0, 0, KF|11,
128 [0x58] KF|12, 0, 0, 0, 0, 0, 0, 0,
129 [0x60] 0, 0, 0, 0, 0, 0, 0, 0,
130 [0x68] 0, 0, 0, 0, 0, 0, 0, 0,
131 [0x70] 0, 0, 0, 0, 0, 0, 0, 0,
132 [0x78] 0, Kdown, 0, Kup, 0, 0, 0, 0,
135 Rune kbtabshift[Nscan] =
137 [0x00] 0, 0x1b, '!', '@', '#', '$', '%', '^',
138 [0x08] '&', '*', '(', ')', '_', '+', '\b', '\t',
139 [0x10] 'Q', 'W', 'E', 'R', 'T', 'Y', 'U', 'I',
140 [0x18] 'O', 'P', '{', '}', '\n', Kctl, 'A', 'S',
141 [0x20] 'D', 'F', 'G', 'H', 'J', 'K', 'L', ':',
142 [0x28] '"', '~', Kshift, '|', 'Z', 'X', 'C', 'V',
143 [0x30] 'B', 'N', 'M', '<', '>', '?', Kshift, '*',
144 [0x38] Kalt, ' ', Kctl, KF|1, KF|2, KF|3, KF|4, KF|5,
145 [0x40] KF|6, KF|7, KF|8, KF|9, KF|10, Knum, Kscroll, '7',
146 [0x48] '8', '9', '-', '4', '5', '6', '+', '1',
147 [0x50] '2', '3', '0', '.', 0, 0, 0, KF|11,
148 [0x58] KF|12, 0, 0, 0, 0, 0, 0, 0,
149 [0x60] 0, 0, 0, 0, 0, 0, 0, 0,
150 [0x68] 0, 0, 0, 0, 0, 0, 0, 0,
151 [0x70] 0, 0, 0, 0, 0, 0, 0, 0,
152 [0x78] 0, Kup, 0, Kup, 0, 0, 0, 0,
155 Rune kbtabesc1[Nscan] =
157 [0x00] 0, 0, 0, 0, 0, 0, 0, 0,
158 [0x08] 0, 0, 0, 0, 0, 0, 0, 0,
159 [0x10] 0, 0, 0, 0, 0, 0, 0, 0,
160 [0x18] 0, 0, 0, 0, '\n', Kctl, 0, 0,
161 [0x20] 0, 0, 0, 0, 0, 0, 0, 0,
162 [0x28] 0, 0, Kshift, 0, 0, 0, 0, 0,
163 [0x30] 0, 0, 0, 0, 0, '/', 0, Kprint,
164 [0x38] Kaltgr, 0, 0, 0, 0, 0, 0, 0,
165 [0x40] 0, 0, 0, 0, 0, 0, Kbreak, Khome,
166 [0x48] Kup, Kpgup, 0, Kleft, 0, Kright, 0, Kend,
167 [0x50] Kdown, Kpgdown, Kins, Kdel, 0, 0, 0, 0,
168 [0x58] 0, 0, 0, 0, 0, 0, 0, 0,
169 [0x60] 0, 0, 0, 0, 0, 0, 0, 0,
170 [0x68] 0, 0, 0, 0, 0, 0, 0, 0,
171 [0x70] 0, 0, 0, 0, 0, 0, 0, 0,
172 [0x78] 0, Kup, 0, 0, 0, 0, 0, 0,
175 Rune kbtabaltgr[Nscan] =
177 [0x00] 0, 0, 0, 0, 0, 0, 0, 0,
178 [0x08] 0, 0, 0, 0, 0, 0, 0, 0,
179 [0x10] 0, 0, 0, 0, 0, 0, 0, 0,
180 [0x18] 0, 0, 0, 0, '\n', Kctl, 0, 0,
181 [0x20] 0, 0, 0, 0, 0, 0, 0, 0,
182 [0x28] 0, 0, Kshift, 0, 0, 0, 0, 0,
183 [0x30] 0, 0, 0, 0, 0, '/', 0, Kprint,
184 [0x38] Kaltgr, 0, 0, 0, 0, 0, 0, 0,
185 [0x40] 0, 0, 0, 0, 0, 0, Kbreak, Khome,
186 [0x48] Kup, Kpgup, 0, Kleft, 0, Kright, 0, Kend,
187 [0x50] Kdown, Kpgdown, Kins, Kdel, 0, 0, 0, 0,
188 [0x58] 0, 0, 0, 0, 0, 0, 0, 0,
189 [0x60] 0, 0, 0, 0, 0, 0, 0, 0,
190 [0x68] 0, 0, 0, 0, 0, 0, 0, 0,
191 [0x70] 0, 0, 0, 0, 0, 0, 0, 0,
192 [0x78] 0, Kup, 0, 0, 0, 0, 0, 0,
195 Rune kbtabctl[Nscan] =
197 [0x00] 0, '
\e', '
\11', '
\12', '
\13', '
\14', '
\15', '
\16',
198 [0x08] '
\17', '
\18', '
\19', '
\10', '
\r', '
\1d', '\b', '\t',
199 [0x10] '
\11', '
\17', '
\ 5', '
\12', '
\14', '
\19', '
\15', '\t',
200 [0x18] '
\ f', '
\10', '
\e', '
\1d', '\n', Kctl, '
\ 1', '
\13',
201 [0x20] '
\ 4', '
\ 6', '
\a', '\b', '\n', '
\v', '
\f', '
\e',
202 [0x28] '
\a', 0, Kshift, '
\1c', '
\1a', '
\18', '
\ 3', '
\16',
203 [0x30] '
\ 2', '
\ e', '
\r', '
\f', '
\ e', '
\ f', Kshift, '\n',
204 [0x38] Kalt, 0, Kctl, '
\ 5', '
\ 6', '
\a', '
\ 4', '
\ 5',
205 [0x40] '
\ 6', '
\a', '
\f', '
\r', '
\ e', '
\ 5', '
\ 6', '
\17',
206 [0x48] '
\18', '
\19', '
\r', '
\14', '
\15', '
\16', '
\v', '
\11',
207 [0x50] '
\12', '
\13', '
\10', '
\ e', 0, 0, 0, '
\ f',
208 [0x58] '
\f', 0, 0, 0, 0, 0, 0, 0,
209 [0x60] 0, 0, 0, 0, 0, 0, 0, 0,
210 [0x68] 0, 0, 0, 0, 0, 0, 0, 0,
211 [0x70] 0, 0, 0, 0, 0, 0, 0, 0,
212 [0x78] 0, '
\a', 0, '\b', 0, 0, 0, 0,
218 * Scan code processing
221 kbdputsc(Scan *scan, int c)
226 * e0's is the first of a 2 character sequence, e1 the first
227 * of a 3 character sequence (on the safari)
232 } else if(c == 0xe1){
237 key.down = (c & 0x80) == 0;
244 key.r = kbtabesc1[key.c];
246 key.r = kbtabshift[key.c];
248 key.r = kbtabaltgr[key.c];
250 key.r = kbtabctl[key.c];
252 key.r = kbtab[key.c];
269 key.b = kbtab[key.c];
271 if(scan->caps && key.r<='z' && key.r>='a')
274 if(scan->ctl && scan->alt && key.r == Kdel)
286 scan->shift = key.down;
289 scan->ctl = key.down;
292 scan->altgr = key.down;
295 scan->alt = key.down;
298 scan->num ^= key.down;
301 scan->caps ^= key.down;
307 setleds(Scan *scan, int leds)
311 if(ledsfd < 0 || scan->leds == leds)
314 snprint(buf, sizeof(buf), "%d", leds);
315 pwrite(ledsfd, buf, strlen(buf), 0);
320 * Read scan codes from scanfd
329 threadsetname("scanproc");
331 memset(&scan, 0, sizeof scan);
332 while((n = read(scanfd, buf, sizeof buf)) > 0){
334 kbdputsc(&scan, buf[i]);
335 setleds(&scan, (scan.num<<1) | (scan.caps<<2));
340 utfconv(Rune *r, int n)
345 l = runenlen(r, n) + 1;
347 for(p = s; n > 0; r++, n--)
348 p += runetochar(p, r);
354 * Read key events from keychan and produce characters to
355 * rawchan and keystate in kbdchan. this way here is only
356 * one global keystate even if multiple keyboards are used.
367 threadsetname("keyproc");
370 while(recv(keychan, &key) > 0){
371 if(key.down && key.r)
372 send(rawchan, &key.r);
375 for(i=0; i<nb && cb[i] != key.c; i++)
378 while(i < nb && cb[i] == key.c){
379 memmove(cb+i, cb+i+1, (nb-i+1) * sizeof(cb[0]));
380 memmove(rb+i+1, rb+i+2, (nb-i+1) * sizeof(rb[0]));
384 } else if(i == nb && nb < nelem(cb) && key.b){
388 if(nb < nelem(cb) && key.r && key.b != key.r){
396 if(key.r == Kshift && mctlfd >= 0){
398 fprint(mctlfd, "buttonmap 132");
400 fprint(mctlfd, "swap");
401 fprint(mctlfd, "swap");
406 s = utfconv(rb, nb+1);
407 if(nbsendp(kbdchan, s) <= 0)
415 * Read characters from consfd (serial console)
420 char *p, *e, *x, buf[64];
424 threadsetname("consproc");
428 e = buf + sizeof(buf);
429 while((n = read(consfd, p, e - p)) > 0){
431 while(p < x && fullrune(p, x - p)){
432 p += chartorune(&r, p);
450 nextrune(Channel *ch, Rune *r)
452 while(recv(ch, r) > 0){
459 /* ignore modifiers */
464 /* composing escapes */
473 * Read runes from rawchan, possibly compose special characters
474 * and output the new runes to runechan
480 char *ld; /* must be seen before using this conversion */
481 char *si; /* options for last input characters */
482 Rune *so; /* the corresponding Rune for each si entry */
490 threadsetname("runeproc");
493 while((i = nextrune(rawchan, &r)) >= 0){
507 * emulators like qemu and vmware use Ctrl+Alt to lock
508 * keyboard input so dont confuse them for a compose
514 if(nextrune(rawchan, &r))
519 for(i = 0; i<4; i++){
520 if(nextrune(rawchan, &rr))
523 if(rr >= '0' && rr <= '9')
525 else if(rr >= 'a' && rr <= 'f')
526 r |= 10 + (rr - 'a');
527 else if(rr >= 'A' && rr <= 'F')
528 r |= 10 + (rr - 'A');
535 if(nextrune(rawchan, &rr))
537 for(i = 0; i<nelem(tab); i++){
538 if(tab[i].ld[0] != r)
540 if(tab[i].ld[1] == 0)
542 if(tab[i].ld[1] == rr){
543 nextrune(rawchan, &rr);
547 if(i == nelem(tab) || rr == 0)
549 for(j = 0; tab[i].si[j]; j++){
550 if(tab[i].si[j] != rr)
560 * Cook lines for cons
572 threadsetname("lineproc");
580 case '\0': /* flush */
583 case Kbs: /* ^H: erase character */
584 case Knack: /* ^U: erase line */
585 case Ketb: /* ^W: erase word */
591 if(r == Ketb && utfrune(" \t", rb[nr]))
595 case Keof: /* ^D: eof */
605 } while(!done && nr < nelem(rb));
607 if(nbsendp(conschan, s) <= 0)
613 * Reads Tread and Tflush requests from reqchan and responds
614 * to them with data received on the string channel.
619 enum { AREQ, ASTR, AEND };
626 threadsetname("reqproc");
635 a[AREQ].op = CHANRCV;
636 a[AREQ].c = ac[0]; /* chan(Req*) */
639 a[ASTR].c = ac[1]; /* chan(char*) */
642 a[AEND].op = CHANEND;
645 a[ASTR].op = s ? CHANNOP : CHANRCV;
649 if(r->ifcall.type == Tflush){
652 for(rr = &q; *rr; rr=xx){
654 if(*rr == r->oldreq){
655 if((*rr = *xx) == nil)
657 respond(r->oldreq, Eintr);
663 } else if(r->ifcall.type != Tread){
678 if((q = q->aux) == nil)
682 if(p == s && r->fid->qid.path == Qkbd)
683 e++; /* send terminating \0 if its kbd file */
685 if(n > r->ifcall.count)
689 memmove(r->ofcall.data, p, n);
703 * Keep track of rawing state and distribute the runes from
704 * runechan to the right channels depending on the state.
709 Channel *cook, *aconsr[2], *akbdr[2];
710 enum { ACTL, ARUNE, AEND };
716 threadsetname("ctlproc");
719 proccreate(scanproc, nil, STACK); /* scanfd -> keychan */
721 proccreate(consproc, nil, STACK); /* consfd -> runechan */
723 threadcreate(keyproc, nil, STACK); /* keychan -> rawchan, kbdchan */
724 threadcreate(runeproc, nil, STACK); /* rawchan -> runechan */
726 aconsr[0] = consreqchan;
727 aconsr[1] = conschan;
728 threadcreate(reqproc, aconsr, STACK); /* consreqchan,conschan -> respond */
730 akbdr[0] = kbdreqchan;
732 threadcreate(reqproc, akbdr, STACK); /* kbdreqchan,kbdchan -> respond */
734 cook = chancreate(sizeof(Rune), 0);
735 threadcreate(lineproc, cook, STACK); /* cook -> conschan */
741 a[ACTL].op = CHANRCV;
743 a[ARUNE].c = runechan;
745 a[ARUNE].op = CHANRCV;
747 a[AEND].op = CHANEND;
755 if(raw = (c == Rawon)){
763 s = emalloc9p(UTFmax+2);
765 s[1+runetochar(s+1, &r)] = 0;
766 if(nbsendp(kbdchan, s) <= 0)
771 s = emalloc9p(UTFmax+1);
772 s[runetochar(s, &r)] = 0;
773 if(nbsendp(conschan, s) <= 0)
784 * Keyboard layout maps
788 kbmapent(int t, int sc)
790 if(sc < 0 || sc >= Nscan)
798 return &kbtabshift[sc];
800 return &kbtabesc1[sc];
802 return &kbtabaltgr[sc];
804 return &kbtabctl[sc];
815 off = req->ifcall.offset/(sizeof(tmp)-1);
818 if(rp = kbmapent(t, sc))
819 sprint(tmp, "%11d %11d %11d\n", t, sc, *rp);
823 if(req->ifcall.count < n)
824 n = req->ifcall.count;
825 req->ofcall.count = n;
826 memmove(req->ofcall.data, tmp, n);
833 char line[100], *lp, *b;
839 b = req->ifcall.data;
840 l = req->ifcall.count;
843 strcpy(line, f->aux);
844 lp = line+strlen(line);
850 if(lp[-1] == '\n' || lp == &line[sizeof(line)-1]) {
854 respond(req, Ebadarg);
857 if(*line == '\n' || *line == '#'){
862 while(*lp == ' ' || *lp == '\t')
864 t = strtoul(line, &lp, 0);
865 sc = strtoul(lp, &lp, 0);
866 while(*lp == ' ' || *lp == '\t')
868 if((rp = kbmapent(t, sc)) == nil)
871 if(*lp == '\'' && lp[1])
872 chartorune(&r, lp+1);
873 else if(*lp == '^' && lp[1]){
874 chartorune(&r, lp+1);
875 if(0x40 <= r && r < 0x60)
879 }else if(*lp == 'M' && ('1' <= lp[1] && lp[1] <= '5'))
880 r = 0xF900+lp[1]-'0';
881 else if(*lp>='0' && *lp<='9') /* includes 0x... */
882 r = strtoul(lp, &lp, 0);
891 f->aux = lp = emalloc9p(l+1);
892 memmove(lp, line, l);
895 req->ofcall.count = req->ifcall.count;
906 static char user[64];
912 if((fd = open("/dev/user", OREAD)) < 0)
913 strcpy(user, "none");
915 n = read(fd, user, (sizeof user)-1);
918 strcpy(user, "none");
926 fillstat(ulong qid, Dir *d)
930 memset(d, 0, sizeof *d);
934 d->qid = (Qid){qid, 0, 0};
938 d->qid.type = t->type;
948 spec = r->ifcall.aname;
950 respond(r, Ebadspec);
953 r->fid->qid = (Qid){Qroot, 0, QTDIR};
954 r->ofcall.qid = r->fid->qid;
961 fillstat((ulong)r->fid->qid.path, &r->d);
962 r->d.name = estrdup9p(r->d.name);
963 r->d.uid = estrdup9p(r->d.uid);
964 r->d.gid = estrdup9p(r->d.gid);
965 r->d.muid = estrdup9p(r->d.muid);
970 fswalk1(Fid *fid, char *name, Qid *qid)
975 path = fid->qid.path;
978 if (strcmp(name, "..") == 0) {
979 *qid = (Qid){Qroot, 0, QTDIR};
983 for(i = fid->qid.path; i<Nqid; i++){
984 if(strcmp(name, qtab[i].name) != 0)
986 *qid = (Qid){i, 0, 0};
1001 static int need[4] = { 4, 2, 6, 1 };
1006 t = qtab + f->qid.path;
1007 n = need[r->ifcall.mode & 3]<<6;
1008 if((n & t->mode) != n)
1012 switch((ulong)f->qid.path){
1029 readtopdir(Fid*, uchar *buf, long off, int cnt, int blen)
1037 for (i = 1; i < Nqid; i++){
1039 m = convD2M(&d, &buf[n], blen-n);
1041 if(m <= BIT16SZ || m > cnt)
1057 switch((ulong)f->qid.path){
1062 r->ofcall.count = readtopdir(f, (void*)r->ofcall.data, r->ifcall.offset,
1063 r->ifcall.count, r->ifcall.count);
1066 sendp(kbdreqchan, r);
1069 sendp(consreqchan, r);
1086 switch((ulong)f->qid.path){
1092 n = r->ifcall.count;
1093 if(write(1, r->ifcall.data, n) != n){
1097 r->ofcall.count = n;
1102 n = r->ifcall.count;
1103 if(n >= 5 && memcmp(p, "rawon", 5) == 0)
1104 sendul(ctlchan, Rawon);
1105 else if(n >= 6 && memcmp(p, "rawoff", 6) == 0)
1106 sendul(ctlchan, Rawoff);
1108 respond(r, Ebadarg);
1111 r->ofcall.count = n;
1116 f->aux = emalloc9p(sizeof(Scan));
1117 memset(f->aux, 0, sizeof(Scan));
1119 for(i=0; i<r->ifcall.count; i++)
1120 kbdputsc((Scan*)f->aux, (uchar)r->ifcall.data[i]);
1121 r->ofcall.count = i;
1135 switch((ulong)r->oldreq->fid->qid.path) {
1137 sendp(kbdreqchan, r);
1140 sendp(consreqchan, r);
1147 fsdestroyfid(Fid *f)
1152 switch((ulong)f->qid.path){
1164 if(--consctlopen == 0)
1165 sendul(ctlchan, Rawoff);
1173 threadexitsall(nil);
1184 .destroyfid= fsdestroyfid,
1196 if((fd = open("/dev/reboot", OWRITE)) < 0){
1197 fprint(2, "can't open /dev/reboot: %r\n");
1200 fprint(fd, "reboot\n");
1214 snprint(buf, sizeof(buf), "/proc/%d/ctl", getpid());
1215 if((fd = open(buf, OWRITE)) < 0){
1216 fprint(2, "can't open %s: %r\n", buf);
1220 /* get higher than normal priority */
1221 fprint(fd, "pri 16\n");
1223 /* always present in physical memory */
1224 fprint(fd, "noswap\n");
1226 /* dont let anybody kill us */
1227 if(d = dirfstat(fd)){
1229 nd.mode = d->mode & ~0222;
1241 fprint(2, "usage: %s [ -dD ] [ -s srv ] [ -m mntpnt ] [ file ]\n", argv0);
1246 threadmain(int argc, char** argv)
1248 char *mtpt = "/dev";
1261 srv = EARGF(usage());
1264 mtpt = EARGF(usage());
1270 if((scanfd = open("/dev/scancode", OREAD)) < 0)
1271 fprint(2, "%s: warning: can't open /dev/scancode: %r\n", argv0);
1272 if((ledsfd = open("/dev/leds", OWRITE)) < 0)
1273 fprint(2, "%s: warning: can't open /dev/leds: %r\n", argv0);
1274 if((mctlfd = open("/dev/mousectl", OWRITE)) < 0)
1275 fprint(2, "%s: warning: can't open /dev/mousectl: %r\n", argv0);
1278 if((consfd = open(*argv, OREAD)) < 0)
1279 fprint(2, "%s: warning: can't open %s: %r\n", argv0, *argv);
1281 consreqchan = chancreate(sizeof(Req*), 0);
1282 kbdreqchan = chancreate(sizeof(Req*), 0);
1284 keychan = chancreate(sizeof(Key), 8);
1285 ctlchan = chancreate(sizeof(int), 0);
1286 rawchan = chancreate(sizeof(Rune), 0);
1287 runechan = chancreate(sizeof(Rune), 32);
1288 conschan = chancreate(sizeof(char*), 16);
1289 kbdchan = chancreate(sizeof(char*), 16);
1292 procrfork(ctlproc, nil, STACK, RFNAMEG|RFNOTEG);
1293 threadpostmountsrv(&fs, srv, mtpt, MBEFORE);