xref: /plan9/sys/src/libdraw/keyboard.c (revision 3ff48bf5ed603850fcd251ddf13025d23d693782)
17dd7cddfSDavid du Colombier #include <u.h>
27dd7cddfSDavid du Colombier #include <libc.h>
37dd7cddfSDavid du Colombier #include <draw.h>
47dd7cddfSDavid du Colombier #include <thread.h>
57dd7cddfSDavid du Colombier #include <keyboard.h>
67dd7cddfSDavid du Colombier 
77dd7cddfSDavid du Colombier 
87dd7cddfSDavid du Colombier void
closekeyboard(Keyboardctl * kc)97dd7cddfSDavid du Colombier closekeyboard(Keyboardctl *kc)
107dd7cddfSDavid du Colombier {
117dd7cddfSDavid du Colombier 	if(kc == nil)
127dd7cddfSDavid du Colombier 		return;
137dd7cddfSDavid du Colombier 
147dd7cddfSDavid du Colombier 	postnote(PNPROC, kc->pid, "kill");
157dd7cddfSDavid du Colombier 
167dd7cddfSDavid du Colombier #ifdef BUG
177dd7cddfSDavid du Colombier 	/* Drain the channel */
187dd7cddfSDavid du Colombier 	while(?kc->c)
197dd7cddfSDavid du Colombier 		<-kc->c;
207dd7cddfSDavid du Colombier #endif
217dd7cddfSDavid du Colombier 
227dd7cddfSDavid du Colombier 	close(kc->ctlfd);
237dd7cddfSDavid du Colombier 	close(kc->consfd);
247dd7cddfSDavid du Colombier 	free(kc->file);
257dd7cddfSDavid du Colombier 	free(kc->c);
267dd7cddfSDavid du Colombier 	free(kc);
277dd7cddfSDavid du Colombier }
287dd7cddfSDavid du Colombier 
297dd7cddfSDavid du Colombier static
307dd7cddfSDavid du Colombier void
_ioproc(void * arg)31*3ff48bf5SDavid du Colombier _ioproc(void *arg)
327dd7cddfSDavid du Colombier {
337dd7cddfSDavid du Colombier 	int m, n;
347dd7cddfSDavid du Colombier 	char buf[20];
357dd7cddfSDavid du Colombier 	Rune r;
367dd7cddfSDavid du Colombier 	Keyboardctl *kc;
377dd7cddfSDavid du Colombier 
387dd7cddfSDavid du Colombier 	kc = arg;
397dd7cddfSDavid du Colombier 	threadsetname("kbdproc");
407dd7cddfSDavid du Colombier 	kc->pid = getpid();
417dd7cddfSDavid du Colombier 	n = 0;
427dd7cddfSDavid du Colombier 	for(;;){
437dd7cddfSDavid du Colombier 		while(n>0 && fullrune(buf, n)){
447dd7cddfSDavid du Colombier 			m = chartorune(&r, buf);
457dd7cddfSDavid du Colombier 			n -= m;
467dd7cddfSDavid du Colombier 			memmove(buf, buf+m, n);
477dd7cddfSDavid du Colombier 			send(kc->c, &r);
487dd7cddfSDavid du Colombier 		}
497dd7cddfSDavid du Colombier 		m = read(kc->consfd, buf+n, sizeof buf-n);
507dd7cddfSDavid du Colombier 		if(m <= 0){
519a747e4fSDavid du Colombier 			yield();	/* if error is due to exiting, we'll exit here */
529a747e4fSDavid du Colombier 			fprint(2, "keyboard read error: %r\n");
537dd7cddfSDavid du Colombier 			threadexits("error");
547dd7cddfSDavid du Colombier 		}
557dd7cddfSDavid du Colombier 		n += m;
567dd7cddfSDavid du Colombier 	}
577dd7cddfSDavid du Colombier }
587dd7cddfSDavid du Colombier 
597dd7cddfSDavid du Colombier Keyboardctl*
initkeyboard(char * file)607dd7cddfSDavid du Colombier initkeyboard(char *file)
617dd7cddfSDavid du Colombier {
627dd7cddfSDavid du Colombier 	Keyboardctl *kc;
637dd7cddfSDavid du Colombier 	char *t;
647dd7cddfSDavid du Colombier 
657dd7cddfSDavid du Colombier 	kc = mallocz(sizeof(Keyboardctl), 1);
667dd7cddfSDavid du Colombier 	if(kc == nil)
677dd7cddfSDavid du Colombier 		return nil;
687dd7cddfSDavid du Colombier 	if(file == nil)
697dd7cddfSDavid du Colombier 		file = "/dev/cons";
707dd7cddfSDavid du Colombier 	kc->file = strdup(file);
717dd7cddfSDavid du Colombier 	kc->consfd = open(file, ORDWR|OCEXEC);
727dd7cddfSDavid du Colombier 	t = malloc(strlen(file)+16);
737dd7cddfSDavid du Colombier 	if(kc->consfd<0 || t==nil){
747dd7cddfSDavid du Colombier Error1:
757dd7cddfSDavid du Colombier 		free(kc);
767dd7cddfSDavid du Colombier 		return nil;
777dd7cddfSDavid du Colombier 	}
787dd7cddfSDavid du Colombier 	sprint(t, "%sctl", file);
797dd7cddfSDavid du Colombier 	kc->ctlfd = open(t, OWRITE|OCEXEC);
807dd7cddfSDavid du Colombier 	if(kc->ctlfd < 0){
819a747e4fSDavid du Colombier 		fprint(2, "initkeyboard: can't open %s: %r\n", t);
827dd7cddfSDavid du Colombier Error2:
837dd7cddfSDavid du Colombier 		close(kc->consfd);
847dd7cddfSDavid du Colombier 		free(t);
857dd7cddfSDavid du Colombier 		goto Error1;
867dd7cddfSDavid du Colombier 	}
877dd7cddfSDavid du Colombier 	if(ctlkeyboard(kc, "rawon") < 0){
889a747e4fSDavid du Colombier 		fprint(2, "initkeyboard: can't turn on raw mode on %s: %r\n", t);
897dd7cddfSDavid du Colombier 		close(kc->ctlfd);
907dd7cddfSDavid du Colombier 		goto Error2;
917dd7cddfSDavid du Colombier 	}
927dd7cddfSDavid du Colombier 	free(t);
937dd7cddfSDavid du Colombier 	kc->c = chancreate(sizeof(Rune), 20);
94*3ff48bf5SDavid du Colombier 	proccreate(_ioproc, kc, 4096);
957dd7cddfSDavid du Colombier 	return kc;
967dd7cddfSDavid du Colombier }
977dd7cddfSDavid du Colombier 
987dd7cddfSDavid du Colombier int
ctlkeyboard(Keyboardctl * kc,char * m)997dd7cddfSDavid du Colombier ctlkeyboard(Keyboardctl *kc, char *m)
1007dd7cddfSDavid du Colombier {
1017dd7cddfSDavid du Colombier 	return write(kc->ctlfd, m, strlen(m));
1027dd7cddfSDavid du Colombier }
103