xref: /plan9/sys/src/libdraw/keyboard.c (revision 3ff48bf5ed603850fcd251ddf13025d23d693782)
1 #include <u.h>
2 #include <libc.h>
3 #include <draw.h>
4 #include <thread.h>
5 #include <keyboard.h>
6 
7 
8 void
closekeyboard(Keyboardctl * kc)9 closekeyboard(Keyboardctl *kc)
10 {
11 	if(kc == nil)
12 		return;
13 
14 	postnote(PNPROC, kc->pid, "kill");
15 
16 #ifdef BUG
17 	/* Drain the channel */
18 	while(?kc->c)
19 		<-kc->c;
20 #endif
21 
22 	close(kc->ctlfd);
23 	close(kc->consfd);
24 	free(kc->file);
25 	free(kc->c);
26 	free(kc);
27 }
28 
29 static
30 void
_ioproc(void * arg)31 _ioproc(void *arg)
32 {
33 	int m, n;
34 	char buf[20];
35 	Rune r;
36 	Keyboardctl *kc;
37 
38 	kc = arg;
39 	threadsetname("kbdproc");
40 	kc->pid = getpid();
41 	n = 0;
42 	for(;;){
43 		while(n>0 && fullrune(buf, n)){
44 			m = chartorune(&r, buf);
45 			n -= m;
46 			memmove(buf, buf+m, n);
47 			send(kc->c, &r);
48 		}
49 		m = read(kc->consfd, buf+n, sizeof buf-n);
50 		if(m <= 0){
51 			yield();	/* if error is due to exiting, we'll exit here */
52 			fprint(2, "keyboard read error: %r\n");
53 			threadexits("error");
54 		}
55 		n += m;
56 	}
57 }
58 
59 Keyboardctl*
initkeyboard(char * file)60 initkeyboard(char *file)
61 {
62 	Keyboardctl *kc;
63 	char *t;
64 
65 	kc = mallocz(sizeof(Keyboardctl), 1);
66 	if(kc == nil)
67 		return nil;
68 	if(file == nil)
69 		file = "/dev/cons";
70 	kc->file = strdup(file);
71 	kc->consfd = open(file, ORDWR|OCEXEC);
72 	t = malloc(strlen(file)+16);
73 	if(kc->consfd<0 || t==nil){
74 Error1:
75 		free(kc);
76 		return nil;
77 	}
78 	sprint(t, "%sctl", file);
79 	kc->ctlfd = open(t, OWRITE|OCEXEC);
80 	if(kc->ctlfd < 0){
81 		fprint(2, "initkeyboard: can't open %s: %r\n", t);
82 Error2:
83 		close(kc->consfd);
84 		free(t);
85 		goto Error1;
86 	}
87 	if(ctlkeyboard(kc, "rawon") < 0){
88 		fprint(2, "initkeyboard: can't turn on raw mode on %s: %r\n", t);
89 		close(kc->ctlfd);
90 		goto Error2;
91 	}
92 	free(t);
93 	kc->c = chancreate(sizeof(Rune), 20);
94 	proccreate(_ioproc, kc, 4096);
95 	return kc;
96 }
97 
98 int
ctlkeyboard(Keyboardctl * kc,char * m)99 ctlkeyboard(Keyboardctl *kc, char *m)
100 {
101 	return write(kc->ctlfd, m, strlen(m));
102 }
103