27 typedef struct Key Key;
28 typedef struct Scan Scan;
79 char Eshort[] = "read count too small";
80 char Ebadarg[] = "invalid argument";
81 char Eperm[] = "permission denied";
82 char Einuse[] = "file in use";
83 char Enonexist[] = "file does not exist";
84 char Ebadspec[] = "bad attach specifier";
85 char Ewalk[] = "walk in non directory";
86 char Efront[] = "the front fell off";
98 Channel *keychan; /* Key */
100 Channel *reqchan; /* Req* */
101 Channel *ctlchan; /* int */
103 Channel *rawchan; /* Rune */
104 Channel *runechan; /* Rune */
105 Channel *linechan; /* char * */
106 Channel *kbdchan; /* char* */
109 * The codes at 0x79 and 0x7b are produced by the PFU Happy Hacking keyboard.
110 * A 'standard' keyboard doesn't produce anything above 0x58.
114 [0x00] 0, 0x1b, '1', '2', '3', '4', '5', '6',
115 [0x08] '7', '8', '9', '0', '-', '=', '\b', '\t',
116 [0x10] 'q', 'w', 'e', 'r', 't', 'y', 'u', 'i',
117 [0x18] 'o', 'p', '[', ']', '\n', Kctl, 'a', 's',
118 [0x20] 'd', 'f', 'g', 'h', 'j', 'k', 'l', ';',
119 [0x28] '\'', '`', Kshift, '\\', 'z', 'x', 'c', 'v',
120 [0x30] 'b', 'n', 'm', ',', '.', '/', Kshift, '*',
121 [0x38] Kalt, ' ', Kctl, KF|1, KF|2, KF|3, KF|4, KF|5,
122 [0x40] KF|6, KF|7, KF|8, KF|9, KF|10, Knum, Kscroll, '7',
123 [0x48] '8', '9', '-', '4', '5', '6', '+', '1',
124 [0x50] '2', '3', '0', '.', 0, 0, 0, KF|11,
125 [0x58] KF|12, 0, 0, 0, 0, 0, 0, 0,
126 [0x60] 0, 0, 0, 0, 0, 0, 0, 0,
127 [0x68] 0, 0, 0, 0, 0, 0, 0, 0,
128 [0x70] 0, 0, 0, 0, 0, 0, 0, 0,
129 [0x78] 0, Kdown, 0, Kup, 0, 0, 0, 0,
132 Rune kbtabshift[Nscan] =
134 [0x00] 0, 0x1b, '!', '@', '#', '$', '%', '^',
135 [0x08] '&', '*', '(', ')', '_', '+', '\b', '\t',
136 [0x10] 'Q', 'W', 'E', 'R', 'T', 'Y', 'U', 'I',
137 [0x18] 'O', 'P', '{', '}', '\n', Kctl, 'A', 'S',
138 [0x20] 'D', 'F', 'G', 'H', 'J', 'K', 'L', ':',
139 [0x28] '"', '~', Kshift, '|', 'Z', 'X', 'C', 'V',
140 [0x30] 'B', 'N', 'M', '<', '>', '?', Kshift, '*',
141 [0x38] Kalt, ' ', Kctl, KF|1, KF|2, KF|3, KF|4, KF|5,
142 [0x40] KF|6, KF|7, KF|8, KF|9, KF|10, Knum, Kscroll, '7',
143 [0x48] '8', '9', '-', '4', '5', '6', '+', '1',
144 [0x50] '2', '3', '0', '.', 0, 0, 0, KF|11,
145 [0x58] KF|12, 0, 0, 0, 0, 0, 0, 0,
146 [0x60] 0, 0, 0, 0, 0, 0, 0, 0,
147 [0x68] 0, 0, 0, 0, 0, 0, 0, 0,
148 [0x70] 0, 0, 0, 0, 0, 0, 0, 0,
149 [0x78] 0, Kup, 0, Kup, 0, 0, 0, 0,
152 Rune kbtabesc1[Nscan] =
154 [0x00] 0, 0, 0, 0, 0, 0, 0, 0,
155 [0x08] 0, 0, 0, 0, 0, 0, 0, 0,
156 [0x10] 0, 0, 0, 0, 0, 0, 0, 0,
157 [0x18] 0, 0, 0, 0, '\n', Kctl, 0, 0,
158 [0x20] 0, 0, 0, 0, 0, 0, 0, 0,
159 [0x28] 0, 0, Kshift, 0, 0, 0, 0, 0,
160 [0x30] 0, 0, 0, 0, 0, '/', 0, Kprint,
161 [0x38] Kaltgr, 0, 0, 0, 0, 0, 0, 0,
162 [0x40] 0, 0, 0, 0, 0, 0, Kbreak, Khome,
163 [0x48] Kup, Kpgup, 0, Kleft, 0, Kright, 0, Kend,
164 [0x50] Kdown, Kpgdown, Kins, Kdel, 0, 0, 0, 0,
165 [0x58] 0, 0, 0, 0, 0, 0, 0, 0,
166 [0x60] 0, 0, 0, 0, 0, 0, 0, 0,
167 [0x68] 0, 0, 0, 0, 0, 0, 0, 0,
168 [0x70] 0, 0, 0, 0, 0, 0, 0, 0,
169 [0x78] 0, Kup, 0, 0, 0, 0, 0, 0,
172 Rune kbtabaltgr[Nscan] =
174 [0x00] 0, 0, 0, 0, 0, 0, 0, 0,
175 [0x08] 0, 0, 0, 0, 0, 0, 0, 0,
176 [0x10] 0, 0, 0, 0, 0, 0, 0, 0,
177 [0x18] 0, 0, 0, 0, '\n', Kctl, 0, 0,
178 [0x20] 0, 0, 0, 0, 0, 0, 0, 0,
179 [0x28] 0, 0, Kshift, 0, 0, 0, 0, 0,
180 [0x30] 0, 0, 0, 0, 0, '/', 0, Kprint,
181 [0x38] Kaltgr, 0, 0, 0, 0, 0, 0, 0,
182 [0x40] 0, 0, 0, 0, 0, 0, Kbreak, Khome,
183 [0x48] Kup, Kpgup, 0, Kleft, 0, Kright, 0, Kend,
184 [0x50] Kdown, Kpgdown, Kins, Kdel, 0, 0, 0, 0,
185 [0x58] 0, 0, 0, 0, 0, 0, 0, 0,
186 [0x60] 0, 0, 0, 0, 0, 0, 0, 0,
187 [0x68] 0, 0, 0, 0, 0, 0, 0, 0,
188 [0x70] 0, 0, 0, 0, 0, 0, 0, 0,
189 [0x78] 0, Kup, 0, 0, 0, 0, 0, 0,
192 Rune kbtabctl[Nscan] =
194 [0x00] 0, '
\e', '
\11', '
\12', '
\13', '
\14', '
\15', '
\16',
195 [0x08] '
\17', '
\18', '
\19', '
\10', '
\r', '
\1d', '\b', '\t',
196 [0x10] '
\11', '
\17', '
\ 5', '
\12', '
\14', '
\19', '
\15', '\t',
197 [0x18] '
\ f', '
\10', '
\e', '
\1d', '\n', Kctl, '
\ 1', '
\13',
198 [0x20] '
\ 4', '
\ 6', '
\a', '\b', '\n', '
\v', '
\f', '
\e',
199 [0x28] '
\a', 0, Kshift, '
\1c', '
\1a', '
\18', '
\ 3', '
\16',
200 [0x30] '
\ 2', '
\ e', '
\r', '
\f', '
\ e', '
\ f', Kshift, '\n',
201 [0x38] Kalt, 0, Kctl, '
\ 5', '
\ 6', '
\a', '
\ 4', '
\ 5',
202 [0x40] '
\ 6', '
\a', '
\f', '
\r', '
\ e', '
\ 5', '
\ 6', '
\17',
203 [0x48] '
\18', '
\19', '
\r', '
\14', '
\15', '
\16', '
\v', '
\11',
204 [0x50] '
\12', '
\13', '
\10', '
\ e', 0, 0, 0, '
\ f',
205 [0x58] '
\f', 0, 0, 0, 0, 0, 0, 0,
206 [0x60] 0, 0, 0, 0, 0, 0, 0, 0,
207 [0x68] 0, 0, 0, 0, 0, 0, 0, 0,
208 [0x70] 0, 0, 0, 0, 0, 0, 0, 0,
209 [0x78] 0, '
\a', 0, '\b', 0, 0, 0, 0,
215 * Scan code processing
218 kbdputsc(Scan *scan, int c)
223 * e0's is the first of a 2 character sequence, e1 the first
224 * of a 3 character sequence (on the safari)
229 } else if(c == 0xe1){
234 key.down = (c & 0x80) == 0;
241 key.r = kbtabesc1[key.c];
243 key.r = kbtabshift[key.c];
245 key.r = kbtabaltgr[key.c];
247 key.r = kbtabctl[key.c];
249 key.r = kbtab[key.c];
266 key.b = kbtab[key.c];
268 if(scan->caps && key.r<='z' && key.r>='a')
271 if(scan->ctl && scan->alt && key.r == Kdel)
283 scan->shift = key.down;
286 scan->ctl = key.down;
289 scan->altgr = key.down;
292 scan->alt = key.down;
295 scan->num ^= key.down;
298 scan->caps ^= key.down;
304 setleds(Scan *scan, int leds)
308 if(ledsfd < 0 || scan->leds == leds)
311 snprint(buf, sizeof(buf), "%d", leds);
312 pwrite(ledsfd, buf, strlen(buf), 0);
317 * Read scan codes from scanfd
326 threadsetname("scanproc");
328 memset(&scan, 0, sizeof scan);
329 while((n = read(scanfd, buf, sizeof buf)) > 0){
331 kbdputsc(&scan, buf[i]);
332 setleds(&scan, (scan.num<<1) | (scan.caps<<2));
337 utfconv(Rune *r, int n)
342 l = runenlen(r, n) + 1;
344 for(p = s; n > 0; r++, n--)
345 p += runetochar(p, r);
351 * Read key events from keychan and produce characters to
352 * rawchan and keystate in kbdchan. this way here is only
353 * one global keystate even if multiple keyboards are used.
364 threadsetname("keyproc");
367 while(recv(keychan, &key) > 0){
368 if(key.down && key.r)
369 nbsend(rawchan, &key.r);
372 for(i=0; i<nb && cb[i] != key.c; i++)
375 while(i < nb && cb[i] == key.c){
376 memmove(cb+i, cb+i+1, (nb-i+1) * sizeof(cb[0]));
377 memmove(rb+i+1, rb+i+2, (nb-i+1) * sizeof(rb[0]));
381 } else if(i == nb && nb < nelem(cb) && key.b){
385 if(nb < nelem(cb) && key.r && key.b != key.r){
393 s = utfconv(rb, nb+1);
394 if(nbsendp(kbdchan, s) <= 0)
401 * Read characters from consfd (serial console)
406 char *p, *e, *x, buf[64];
410 threadsetname("consproc");
414 e = buf + sizeof(buf);
415 while((n = read(consfd, p, e - p)) > 0){
417 while(p < x && fullrune(p, x - p)){
418 p += chartorune(&r, p);
436 nextrune(Channel *ch, Rune *r)
438 while(recv(ch, r) > 0){
445 /* ignore modifiers */
450 /* composing escapes */
459 * Read runes from rawchan, possibly compose special characters
460 * and output the new runes to runechan
466 char *ld; /* must be seen before using this conversion */
467 char *si; /* options for last input characters */
468 Rune *so; /* the corresponding Rune for each si entry */
476 threadsetname("runeproc");
479 while((i = nextrune(rawchan, &r)) >= 0){
493 * emulators like qemu and vmware use Ctrl+Alt to lock
494 * keyboard input so dont confuse them for a compose
500 if(nextrune(rawchan, &r))
505 for(i = 0; i<4; i++){
506 if(nextrune(rawchan, &rr))
509 if(rr >= '0' && rr <= '9')
511 else if(rr >= 'a' && rr <= 'f')
512 r |= 10 + (rr - 'a');
513 else if(rr >= 'A' && rr <= 'F')
514 r |= 10 + (rr - 'A');
521 if(nextrune(rawchan, &rr))
523 for(i = 0; i<nelem(tab); i++){
524 if(tab[i].ld[0] != r)
526 if(tab[i].ld[1] == 0)
528 if(tab[i].ld[1] == rr){
529 nextrune(rawchan, &rr);
533 if(i == nelem(tab) || rr == 0)
535 for(j = 0; tab[i].si[j]; j++){
536 if(tab[i].si[j] != rr)
546 * Cook lines for cons
557 threadsetname("lineproc");
565 case '\0': /* flush */
568 case '\b': /* backspace */
587 } while(!done && nr < nelem(rb));
588 sendp(linechan, utfconv(rb, nr));
593 * Queue reads to cons and kbd, flushing and
594 * relay data between 9p and rawchan / kbdchan.
603 enum { Areq, Actl, Arune, Aline, Akbd, Aend };
612 threadsetname("ctlproc");
614 cook = chancreate(sizeof(Rune), 0);
617 proccreate(scanproc, nil, STACK); /* scanfd -> keychan */
619 proccreate(consproc, nil, STACK); /* consfd -> runechan */
621 threadcreate(keyproc, nil, STACK); /* keychan -> rawchan, kbdchan */
622 threadcreate(runeproc, nil, STACK); /* rawchan -> runechan */
623 threadcreate(lineproc, cook, STACK); /* cook -> linechan */
634 memset(a, 0, sizeof a);
638 a[Areq].op = CHANRCV;
642 a[Actl].op = CHANRCV;
644 a[Arune].c = runechan;
646 a[Arune].op = CHANRCV;
648 a[Aline].c = linechan;
650 a[Aline].op = CHANRCV;
654 a[Akbd].op = CHANRCV;
656 a[Aend].op = CHANEND;
662 a[Arune].op = qkbd.h ? CHANRCV : CHANNOP;
663 a[Akbd].op = qkbd.h ? CHANRCV : CHANNOP;
664 a[Aline].op = CHANNOP;
666 a[Arune].op = (b == nil) ? CHANRCV : CHANNOP;
667 a[Akbd].op = CHANRCV;
668 a[Aline].op = (b == nil) ? CHANRCV : CHANNOP;
674 if(req->ifcall.type == Tflush){
677 fid = req->oldreq->fid;
678 q = fid->qid.path == Qcons ? &qcons : &qkbd;
679 for(rr = &q->h; *rr && *rr != req->oldreq; rr = &((*rr)->aux))
681 if(*rr == req->oldreq){
682 if((*rr = req->oldreq->aux) == nil)
684 req->oldreq->aux = nil;
685 respond(req->oldreq, "interrupted");
688 } else if(req->ifcall.type == Tread){
689 q = fid->qid.path == Qcons ? &qcons : &qkbd;
695 respond(req, Efront);
702 if(raw = (c == Rawon)){
703 while(s = nbrecvp(linechan))
712 while(s = nbrecvp(kbdchan))
720 s = emalloc9p(UTFmax+2);
722 s[1+runetochar(s+1, &r)] = 0;
727 s = emalloc9p(UTFmax+1);
728 s[runetochar(s, &r)] = 0;
741 while(b && (req = qcons.h)){
742 if((qcons.h = req->aux) == nil)
745 if(req->ifcall.count < n)
746 n = req->ifcall.count;
747 req->ofcall.count = n;
748 memmove(req->ofcall.data, p, n);
761 if((qkbd.h = req->aux) == nil)
764 if(n > req->ifcall.count)
765 respond(req, Eshort);
767 req->ofcall.count = n;
768 memmove(req->ofcall.data, s, n);
779 * Keyboard layout maps
783 kbmapent(int t, int sc)
785 if(sc < 0 || sc >= Nscan)
793 return &kbtabshift[sc];
795 return &kbtabesc1[sc];
797 return &kbtabaltgr[sc];
799 return &kbtabctl[sc];
810 off = req->ifcall.offset/(sizeof(tmp)-1);
813 if(rp = kbmapent(t, sc))
814 sprint(tmp, "%11d %11d %11d\n", t, sc, *rp);
818 if(req->ifcall.count < n)
819 n = req->ifcall.count;
820 req->ofcall.count = n;
821 memmove(req->ofcall.data, tmp, n);
828 char line[100], *lp, *b;
834 b = req->ifcall.data;
835 l = req->ifcall.count;
838 strcpy(line, f->aux);
839 lp = line+strlen(line);
845 if(lp[-1] == '\n' || lp == &line[sizeof(line)-1]) {
849 respond(req, Ebadarg);
852 if(*line == '\n' || *line == '#'){
857 while(*lp == ' ' || *lp == '\t')
859 t = strtoul(line, &lp, 0);
860 sc = strtoul(lp, &lp, 0);
861 while(*lp == ' ' || *lp == '\t')
863 if((rp = kbmapent(t, sc)) == nil)
866 if(*lp == '\'' && lp[1])
867 chartorune(&r, lp+1);
868 else if(*lp == '^' && lp[1]){
869 chartorune(&r, lp+1);
870 if(0x40 <= r && r < 0x60)
874 }else if(*lp == 'M' && ('1' <= lp[1] && lp[1] <= '5'))
875 r = 0xF900+lp[1]-'0';
876 else if(*lp>='0' && *lp<='9') /* includes 0x... */
877 r = strtoul(lp, &lp, 0);
886 f->aux = lp = emalloc9p(l+1);
887 memmove(lp, line, l);
890 req->ofcall.count = req->ifcall.count;
901 static char user[64];
907 if((fd = open("/dev/user", OREAD)) < 0)
908 strcpy(user, "none");
910 n = read(fd, user, (sizeof user)-1);
913 strcpy(user, "none");
921 fillstat(ulong qid, Dir *d)
925 memset(d, 0, sizeof *d);
929 d->qid = (Qid){qid, 0, 0};
933 d->qid.type = t->type;
943 spec = r->ifcall.aname;
945 respond(r, Ebadspec);
948 r->fid->qid = (Qid){Qroot, 0, QTDIR};
949 r->ofcall.qid = r->fid->qid;
956 fillstat((ulong)r->fid->qid.path, &r->d);
957 r->d.name = estrdup9p(r->d.name);
958 r->d.uid = estrdup9p(r->d.uid);
959 r->d.gid = estrdup9p(r->d.gid);
960 r->d.muid = estrdup9p(r->d.muid);
965 fswalk1(Fid *fid, char *name, Qid *qid)
970 path = fid->qid.path;
973 if (strcmp(name, "..") == 0) {
974 *qid = (Qid){Qroot, 0, QTDIR};
978 for(i = fid->qid.path; i<Nqid; i++){
979 if(strcmp(name, qtab[i].name) != 0)
981 *qid = (Qid){i, 0, 0};
996 static int need[4] = { 4, 2, 6, 1 };
1001 t = qtab + f->qid.path;
1002 n = need[r->ifcall.mode & 3]<<6;
1003 if((n & t->mode) != n)
1007 switch((ulong)f->qid.path){
1014 sendul(ctlchan, Kbdflush);
1028 readtopdir(Fid*, uchar *buf, long off, int cnt, int blen)
1036 for (i = 1; i < Nqid; i++){
1038 m = convD2M(&d, &buf[n], blen-n);
1040 if(m <= BIT16SZ || m > cnt)
1056 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);
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) {
1145 fsdestroyfid(Fid *f)
1150 switch((ulong)f->qid.path){
1165 if(--consctlopen == 0)
1166 sendul(ctlchan, Rawoff);
1174 threadexitsall(nil);
1185 .destroyfid= fsdestroyfid,
1197 if((fd = open("/dev/reboot", OWRITE)) < 0){
1198 fprint(2, "can't open /dev/reboot: %r\n");
1201 fprint(fd, "reboot\n");
1215 snprint(buf, sizeof(buf), "/proc/%d/ctl", getpid());
1216 if((fd = open(buf, OWRITE)) < 0){
1217 fprint(2, "can't open %s: %r\n", buf);
1221 /* get higher than normal priority */
1222 fprint(fd, "pri 16\n");
1224 /* always present in physical memory */
1225 fprint(fd, "noswap\n");
1227 /* dont let anybody kill us */
1228 if(d = dirfstat(fd)){
1230 nd.mode = d->mode & ~0222;
1242 fprint(2, "usage: %s [ -dD ] [ -s srv ] [ -m mntpnt ] [ file ]\n", argv0);
1247 threadmain(int argc, char** argv)
1249 char *mtpt = "/dev";
1262 srv = EARGF(usage());
1265 mtpt = EARGF(usage());
1271 if((scanfd = open("/dev/scancode", OREAD)) < 0)
1272 fprint(2, "%s: warning: can't open /dev/scancode: %r\n", argv0);
1273 if((ledsfd = open("/dev/leds", OWRITE)) < 0)
1274 fprint(2, "%s: warning: can't open /dev/leds: %r\n", argv0);
1277 if((consfd = open(*argv, OREAD)) < 0)
1278 fprint(2, "%s: warning: can't open %s: %r\n", argv0, *argv);
1280 keychan = chancreate(sizeof(Key), 8);
1281 reqchan = chancreate(sizeof(Req*), 0);
1282 ctlchan = chancreate(sizeof(int), 0);
1283 rawchan = chancreate(sizeof(Rune), 16);
1284 runechan = chancreate(sizeof(Rune), 32);
1285 linechan = chancreate(sizeof(char*), 16);
1286 kbdchan = chancreate(sizeof(char*), 16);
1288 if(!(keychan && reqchan && ctlchan && rawchan && runechan && linechan && kbdchan))
1289 sysfatal("allocating chans");
1292 procrfork(ctlproc, nil, STACK, RFNAMEG|RFNOTEG);
1293 threadpostmountsrv(&fs, srv, mtpt, MBEFORE);