xref: /plan9/sys/src/9/port/devkbmap.c (revision e29df7b0e1465888597fc56c7bb3d27bbfad66d2)
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