13901e6d0SDavid du Colombier /*
23901e6d0SDavid du Colombier * keyboard map
33901e6d0SDavid du Colombier */
43901e6d0SDavid du Colombier
53901e6d0SDavid du Colombier #include "u.h"
63901e6d0SDavid du Colombier #include "../port/lib.h"
73901e6d0SDavid du Colombier #include "mem.h"
83901e6d0SDavid du Colombier #include "dat.h"
93901e6d0SDavid du Colombier #include "fns.h"
103901e6d0SDavid du Colombier #include "../port/error.h"
113901e6d0SDavid du Colombier
123901e6d0SDavid du Colombier enum{
133901e6d0SDavid du Colombier Qdir,
143901e6d0SDavid du Colombier Qdata,
153901e6d0SDavid du Colombier };
163901e6d0SDavid du Colombier Dirtab kbmaptab[]={
173901e6d0SDavid du Colombier ".", {Qdir, 0, QTDIR}, 0, 0555,
183901e6d0SDavid du Colombier "kbmap", {Qdata, 0}, 0, 0600,
193901e6d0SDavid du Colombier };
203901e6d0SDavid du Colombier #define NKBFILE sizeof(kbmaptab)/sizeof(kbmaptab[0])
213901e6d0SDavid du Colombier
223901e6d0SDavid du Colombier #define KBLINELEN (3*NUMSIZE+1) /* t code val\n */
233901e6d0SDavid du Colombier
243901e6d0SDavid du Colombier static Chan *
kbmapattach(char * spec)253901e6d0SDavid du Colombier kbmapattach(char *spec)
263901e6d0SDavid du Colombier {
273901e6d0SDavid du Colombier return devattach(L'κ', spec);
283901e6d0SDavid du Colombier }
293901e6d0SDavid du Colombier
303901e6d0SDavid du Colombier static Walkqid*
kbmapwalk(Chan * c,Chan * nc,char ** name,int nname)313901e6d0SDavid du Colombier kbmapwalk(Chan *c, Chan *nc, char **name, int nname)
323901e6d0SDavid du Colombier {
333901e6d0SDavid du Colombier return devwalk(c, nc, name, nname, kbmaptab, NKBFILE, devgen);
343901e6d0SDavid du Colombier }
353901e6d0SDavid du Colombier
363901e6d0SDavid du Colombier static int
kbmapstat(Chan * c,uchar * dp,int n)373901e6d0SDavid du Colombier kbmapstat(Chan *c, uchar *dp, int n)
383901e6d0SDavid du Colombier {
393901e6d0SDavid du Colombier return devstat(c, dp, n, kbmaptab, NKBFILE, devgen);
403901e6d0SDavid du Colombier }
413901e6d0SDavid du Colombier
423901e6d0SDavid du Colombier static Chan*
kbmapopen(Chan * c,int omode)433901e6d0SDavid du Colombier kbmapopen(Chan *c, int omode)
443901e6d0SDavid du Colombier {
453901e6d0SDavid du Colombier if(!iseve())
463901e6d0SDavid du Colombier error(Eperm);
473901e6d0SDavid du Colombier return devopen(c, omode, kbmaptab, NKBFILE, devgen);
483901e6d0SDavid du Colombier }
493901e6d0SDavid du Colombier
503901e6d0SDavid du Colombier static void
kbmapclose(Chan * c)513901e6d0SDavid du Colombier kbmapclose(Chan *c)
523901e6d0SDavid du Colombier {
533901e6d0SDavid du Colombier if(c->aux){
543901e6d0SDavid du Colombier free(c->aux);
553901e6d0SDavid du Colombier c->aux = nil;
563901e6d0SDavid du Colombier }
573901e6d0SDavid du Colombier }
583901e6d0SDavid du Colombier
593901e6d0SDavid du Colombier static long
kbmapread(Chan * c,void * a,long n,vlong offset)603901e6d0SDavid du Colombier kbmapread(Chan *c, void *a, long n, vlong offset)
613901e6d0SDavid du Colombier {
623901e6d0SDavid du Colombier char *bp;
633901e6d0SDavid du Colombier char tmp[KBLINELEN+1];
643901e6d0SDavid du Colombier int t, sc;
653901e6d0SDavid du Colombier Rune r;
663901e6d0SDavid du Colombier
673901e6d0SDavid du Colombier if(c->qid.type == QTDIR)
683901e6d0SDavid du Colombier return devdirread(c, a, n, kbmaptab, NKBFILE, devgen);
693901e6d0SDavid du Colombier
703901e6d0SDavid du Colombier switch((int)(c->qid.path)){
713901e6d0SDavid du Colombier case Qdata:
723901e6d0SDavid du Colombier if(kbdgetmap(offset/KBLINELEN, &t, &sc, &r)) {
733901e6d0SDavid du Colombier bp = tmp;
743901e6d0SDavid du Colombier bp += readnum(0, bp, NUMSIZE, t, NUMSIZE);
753901e6d0SDavid du Colombier bp += readnum(0, bp, NUMSIZE, sc, NUMSIZE);
763901e6d0SDavid du Colombier bp += readnum(0, bp, NUMSIZE, r, NUMSIZE);
773901e6d0SDavid du Colombier *bp++ = '\n';
783901e6d0SDavid du Colombier *bp = 0;
793901e6d0SDavid du Colombier n = readstr(offset%KBLINELEN, a, n, tmp);
803901e6d0SDavid du Colombier } else
813901e6d0SDavid du Colombier n = 0;
823901e6d0SDavid du Colombier break;
833901e6d0SDavid du Colombier default:
843901e6d0SDavid du Colombier n=0;
853901e6d0SDavid du Colombier break;
863901e6d0SDavid du Colombier }
873901e6d0SDavid du Colombier return n;
883901e6d0SDavid du Colombier }
893901e6d0SDavid du Colombier
903901e6d0SDavid du Colombier static long
kbmapwrite(Chan * c,void * a,long n,vlong)913901e6d0SDavid du Colombier kbmapwrite(Chan *c, void *a, long n, vlong)
923901e6d0SDavid du Colombier {
933901e6d0SDavid du Colombier char line[100], *lp, *b;
943901e6d0SDavid du Colombier int key, m, l;
953901e6d0SDavid du Colombier Rune r;
963901e6d0SDavid du Colombier
973901e6d0SDavid du Colombier if(c->qid.type == QTDIR)
983901e6d0SDavid du Colombier error(Eperm);
993901e6d0SDavid du Colombier
1003901e6d0SDavid du Colombier switch((int)(c->qid.path)){
1013901e6d0SDavid du Colombier case Qdata:
1023901e6d0SDavid du Colombier b = a;
1033901e6d0SDavid du Colombier l = n;
1043901e6d0SDavid du Colombier lp = line;
1053901e6d0SDavid du Colombier if(c->aux){
1063901e6d0SDavid du Colombier strcpy(line, c->aux);
1073901e6d0SDavid du Colombier lp = line+strlen(line);
1083901e6d0SDavid du Colombier free(c->aux);
1093901e6d0SDavid du Colombier c->aux = nil;
1103901e6d0SDavid du Colombier }
1113901e6d0SDavid du Colombier while(--l >= 0) {
1123901e6d0SDavid du Colombier *lp++ = *b++;
1133901e6d0SDavid du Colombier if(lp[-1] == '\n' || lp == &line[sizeof(line)-1]) {
1143901e6d0SDavid du Colombier *lp = 0;
1153901e6d0SDavid du Colombier if(*line == 0)
1163901e6d0SDavid du Colombier error(Ebadarg);
1173901e6d0SDavid du Colombier if(*line == '\n' || *line == '#'){
1183901e6d0SDavid du Colombier lp = line;
1193901e6d0SDavid du Colombier continue;
1203901e6d0SDavid du Colombier }
121*e29df7b0SDavid du Colombier lp = line;
122*e29df7b0SDavid du Colombier while(*lp == ' ' || *lp == '\t')
123*e29df7b0SDavid du Colombier lp++;
1243901e6d0SDavid du Colombier m = strtoul(line, &lp, 0);
1253901e6d0SDavid du Colombier key = strtoul(lp, &lp, 0);
1263901e6d0SDavid du Colombier while(*lp == ' ' || *lp == '\t')
1273901e6d0SDavid du Colombier lp++;
1283901e6d0SDavid du Colombier r = 0;
1293901e6d0SDavid du Colombier if(*lp == '\'' && lp[1])
1303901e6d0SDavid du Colombier chartorune(&r, lp+1);
131*e29df7b0SDavid du Colombier else if(*lp == '^' && lp[1]){
132*e29df7b0SDavid du Colombier chartorune(&r, lp+1);
133*e29df7b0SDavid du Colombier if(0x40 <= r && r < 0x60)
134*e29df7b0SDavid du Colombier r -= 0x40;
135*e29df7b0SDavid du Colombier else
136*e29df7b0SDavid du Colombier error(Ebadarg);
137*e29df7b0SDavid du Colombier }else if(*lp == 'M' && ('1' <= lp[1] && lp[1] <= '5'))
138*e29df7b0SDavid du Colombier r = 0xF900+lp[1]-'0';
1393901e6d0SDavid du Colombier else if(*lp>='0' && *lp<='9') /* includes 0x... */
1403901e6d0SDavid du Colombier r = strtoul(lp, &lp, 0);
1413901e6d0SDavid du Colombier else
1423901e6d0SDavid du Colombier error(Ebadarg);
1433901e6d0SDavid du Colombier kbdputmap(m, key, r);
1443901e6d0SDavid du Colombier lp = line;
1453901e6d0SDavid du Colombier }
1463901e6d0SDavid du Colombier }
1473901e6d0SDavid du Colombier if(lp != line){
1483901e6d0SDavid du Colombier l = lp-line;
1493901e6d0SDavid du Colombier c->aux = lp = smalloc(l+1);
1503901e6d0SDavid du Colombier memmove(lp, line, l);
1513901e6d0SDavid du Colombier lp[l] = 0;
1523901e6d0SDavid du Colombier }
1533901e6d0SDavid du Colombier break;
1543901e6d0SDavid du Colombier default:
1553901e6d0SDavid du Colombier error(Ebadusefd);
1563901e6d0SDavid du Colombier }
1573901e6d0SDavid du Colombier return n;
1583901e6d0SDavid du Colombier }
1593901e6d0SDavid du Colombier
1603901e6d0SDavid du Colombier Dev kbmapdevtab = {
1613901e6d0SDavid du Colombier L'κ',
1623901e6d0SDavid du Colombier "kbmap",
1633901e6d0SDavid du Colombier
1643901e6d0SDavid du Colombier devreset,
1653901e6d0SDavid du Colombier devinit,
1663901e6d0SDavid du Colombier devshutdown,
1673901e6d0SDavid du Colombier kbmapattach,
1683901e6d0SDavid du Colombier kbmapwalk,
1693901e6d0SDavid du Colombier kbmapstat,
1703901e6d0SDavid du Colombier kbmapopen,
1713901e6d0SDavid du Colombier devcreate,
1723901e6d0SDavid du Colombier kbmapclose,
1733901e6d0SDavid du Colombier kbmapread,
1743901e6d0SDavid du Colombier devbread,
1753901e6d0SDavid du Colombier kbmapwrite,
1763901e6d0SDavid du Colombier devbwrite,
1773901e6d0SDavid du Colombier devremove,
1783901e6d0SDavid du Colombier devwstat,
1793901e6d0SDavid du Colombier };
180