• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2    Copyright (C) 2002-2010 Karl J. Runge <runge@karlrunge.com>
3    All rights reserved.
4 
5 This file is part of x11vnc.
6 
7 x11vnc is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2 of the License, or (at
10 your option) any later version.
11 
12 x11vnc is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15 GNU General Public License for more details.
16 
17 You should have received a copy of the GNU General Public License
18 along with x11vnc; if not, write to the Free Software
19 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA
20 or see <http://www.gnu.org/licenses/>.
21 
22 In addition, as a special exception, Karl J. Runge
23 gives permission to link the code of its release of x11vnc with the
24 OpenSSL project's "OpenSSL" library (or with modified versions of it
25 that use the same license as the "OpenSSL" library), and distribute
26 the linked executables.  You must obey the GNU General Public License
27 in all respects for all of the code used other than "OpenSSL".  If you
28 modify this file, you may extend this exception to your version of the
29 file, but you are not obligated to do so.  If you do not wish to do
30 so, delete this exception statement from your version.
31 */
32 
33 /* -- linuxfb.c -- */
34 
35 #include "x11vnc.h"
36 #include "cleanup.h"
37 #include "scan.h"
38 #include "xinerama.h"
39 #include "screen.h"
40 #include "pointer.h"
41 #include "allowed_input_t.h"
42 #include "uinput.h"
43 #include "keyboard.h"
44 #include "macosx.h"
45 
46 #if LIBVNCSERVER_HAVE_SYS_IOCTL_H
47 #include <sys/ioctl.h>
48 #endif
49 #if LIBVNCSERVER_HAVE_LINUX_FB_H
50 #include <linux/fb.h>
51 #endif
52 
53 char *console_guess(char *str, int *fd);
54 void console_key_command(rfbBool down, rfbKeySym keysym, rfbClientPtr client);
55 void console_pointer_command(int mask, int x, int y, rfbClientPtr client);
56 
57 
58 void linux_dev_fb_msg(char *);
59 
console_guess(char * str,int * fd)60 char *console_guess(char *str, int *fd) {
61 	char *q, *in = strdup(str);
62 	char *atparms = NULL, *file = NULL;
63 	int do_input, have_uinput, tty = -1;
64 
65 #ifdef MACOSX
66 	return macosx_console_guess(str, fd);
67 #endif
68 
69 
70 	if (strstr(in, "/dev/fb") == in) {
71 		free(in);
72 		in = (char *) malloc(strlen("console:") + strlen(str) + 1);
73 		sprintf(in, "console:%s", str);
74 	} else if (strstr(in, "fb") == in) {
75 		free(in);
76 		in = (char *) malloc(strlen("console:/dev/") + strlen(str) + 1);
77 		sprintf(in, "console:/dev/%s", str);
78 	} else if (strstr(in, "vt") == in) {
79 		free(in);
80 		in = (char *) malloc(strlen("console_") + strlen(str) + 1);
81 		sprintf(in, "console_%s", str);
82 	}
83 
84 	if (strstr(in, "console") != in) {
85 		rfbLog("console_guess: unrecognized console/fb format: %s\n", str);
86 		free(in);
87 		return NULL;
88 	}
89 
90 	q = strrchr(in, '@');
91 	if (q) {
92 		atparms = strdup(q+1);
93 		*q = '\0';
94 	}
95 	q = strrchr(in, ':');
96 	if (q) {
97 		file = strdup(q+1);
98 		*q = '\0';
99 	}
100 	if (! file || file[0] == '\0')  {
101 		file = strdup("/dev/fb");
102 	}
103 	if (strstr(file, "fb") == file) {
104 		q = (char *) malloc(strlen("/dev/") + strlen(file) + 1);
105 		sprintf(q, "/dev/%s", file);
106 		free(file);
107 		file = q;
108 	}
109 	if (!strcmp(file, "/dev/fb")) {
110 		/* sometimes no sylink fb -> fb0 */
111 		struct stat sbuf;
112 		if (stat(file, &sbuf) != 0) {
113 			free(file);
114 			file = strdup("/dev/fb0");
115 		}
116 	}
117 
118 	do_input = 1;
119 	if (pipeinput_str) {
120 		have_uinput = 0;
121 		do_input = 0;
122 	} else {
123 		have_uinput = check_uinput();
124 	}
125 	if (strstr(in, "console_vt")) {
126 		have_uinput = 0;
127 	}
128 
129 	if (!strcmp(in, "consolex")) {
130 		do_input = 0;
131 	} else if (strstr(in, "console_vtx")) {
132 		have_uinput = 0;
133 		do_input = 0;
134 	} else if (!strcmp(in, "console")) {
135 		/* current active VT: */
136 		if (! have_uinput) {
137 			tty = 0;
138 		}
139 	} else {
140 		int n;
141 		if (sscanf(in, "console%d", &n) == 1)  {
142 			tty = n;
143 			have_uinput = 0;
144 		} else if (sscanf(in, "console_vt%d", &n) == 1)  {
145 			tty = n;
146 			have_uinput = 0;
147 		}
148 	}
149 	if (strstr(in, "console_vt") == in) {
150 		char tmp[100];
151 		int fd, rows = 30, cols = 80, w, h;
152 		sprintf(tmp, "/dev/vcsa%d", tty);
153 		file = strdup(tmp);
154 		fd = open(file, O_RDWR);
155 		if (fd >= 0) {
156 			read(fd, tmp, 4);
157 			rows = (unsigned char) tmp[0];
158 			cols = (unsigned char) tmp[1];
159 			close(fd);
160 		}
161 		w = cols * 8;
162 		h = rows * 16;
163 		rfbLog("%s %dx%d\n", file, cols, rows);
164 		if (getenv("RAWFB_VCSA_BPP")) {
165 			/* 8bpp, etc */
166 			int bt = atoi(getenv("RAWFB_VCSA_BPP"));
167 			if (bt > 0 && bt <=32) {
168 				sprintf(tmp, "%dx%dx%d", w, h, bt);
169 			} else {
170 				sprintf(tmp, "%dx%dx16", w, h);
171 			}
172 		} else {
173 			/* default 16bpp */
174 			sprintf(tmp, "%dx%dx16", w, h);
175 		}
176 		atparms = strdup(tmp);
177 	}
178 	rfbLog("console_guess: file is %s\n", file);
179 
180 	if (! atparms) {
181 #if LIBVNCSERVER_HAVE_LINUX_FB_H
182 #if LIBVNCSERVER_HAVE_SYS_IOCTL_H
183 		struct fb_var_screeninfo var_info;
184 		int d = open(file, O_RDWR);
185 		if (d >= 0) {
186 			int w, h, b;
187 			unsigned long rm = 0, gm = 0, bm = 0;
188 			if (ioctl(d, FBIOGET_VSCREENINFO, &var_info) != -1) {
189 				w = (int) var_info.xres;
190 				h = (int) var_info.yres;
191 				b = (int) var_info.bits_per_pixel;
192 
193 				rm = (1 << var_info.red.length)   - 1;
194 				gm = (1 << var_info.green.length) - 1;
195 				bm = (1 << var_info.blue.length)  - 1;
196 				rm = rm << var_info.red.offset;
197 				gm = gm << var_info.green.offset;
198 				bm = bm << var_info.blue.offset;
199 
200 				if (b == 8 && rm == 0xff && gm == 0xff && bm == 0xff) {
201 					/* I don't believe it... */
202 					rm = 0x07;
203 					gm = 0x38;
204 					bm = 0xc0;
205 				}
206 				if (b <= 8 && (rm == gm && gm == bm)) {
207 					if (b == 4) {
208 						rm = 0x07;
209 						gm = 0x38;
210 						bm = 0xc0;
211 					}
212 				}
213 
214 				/* @66666x66666x32:0xffffffff:... */
215 				atparms = (char *) malloc(200);
216 				sprintf(atparms, "%dx%dx%d:%lx/%lx/%lx",
217 				    w, h, b, rm, gm, bm);
218 				*fd = d;
219 			} else {
220 				perror("ioctl");
221 				close(d);
222 			}
223 		} else {
224 			rfbLog("could not open: %s\n", file);
225 			rfbLogPerror("open");
226 			linux_dev_fb_msg(file);
227 			close(d);
228 		}
229 #endif
230 #endif
231 	}
232 
233 	if (atparms) {
234 		int gw, gh, gb;
235 		if (sscanf(atparms, "%dx%dx%d", &gw, &gh, &gb) == 3)  {
236 			fb_x = gw;
237 			fb_y = gh;
238 			fb_b = gb;
239 		}
240 	}
241 
242 	if (do_input) {
243 		if (tty >=0 && tty < 64) {
244 			pipeinput_str = (char *) malloc(10);
245 			sprintf(pipeinput_str, "CONSOLE%d", tty);
246 			rfbLog("console_guess: file pipeinput %s\n",
247 			    pipeinput_str);
248 			initialize_pipeinput();
249 		} else if (have_uinput) {
250 			pipeinput_str = strdup("UINPUT");
251 			rfbLog("console_guess: file pipeinput %s\n",
252 			    pipeinput_str);
253 			initialize_pipeinput();
254 		}
255 	}
256 
257 	if (! atparms) {
258 		rfbLog("console_guess: could not get @ parameters.\n");
259 		return NULL;
260 	}
261 
262 	q = (char *) malloc(strlen("mmap:") + strlen(file) + 1 + strlen(atparms) + 1);
263 	if (strstr(in, "console_vt")) {
264 		sprintf(q, "snap:%s@%s", file, atparms);
265 	} else {
266 		sprintf(q, "map:%s@%s", file, atparms);
267 	}
268 	free(atparms);
269 	return q;
270 }
271 
console_key_command(rfbBool down,rfbKeySym keysym,rfbClientPtr client)272 void console_key_command(rfbBool down, rfbKeySym keysym, rfbClientPtr client) {
273 	static int control = 0, alt = 0;
274 	allowed_input_t input;
275 
276 	if (debug_keyboard) fprintf(stderr, "console_key_command: %d %s\n", (int) keysym, down ? "down" : "up");
277 
278 	if (pipeinput_cons_fd < 0) {
279 		return;
280 	}
281 	if (view_only) {
282 		return;
283 	}
284 	get_allowed_input(client, &input);
285 	if (! input.keystroke) {
286 		return;
287 	}
288 
289 	/* From LinuxVNC.c: */
290 	if (keysym == XK_Control_L || keysym == XK_Control_R) {
291 		if (! down) {
292 			if (control > 0) {
293 				control--;
294 			}
295 		} else {
296 			control++;
297 		}
298 		return;
299 	}
300 	if (keysym == XK_Alt_L || keysym == XK_Alt_R) {
301 		if (! down) {
302 			if (alt > 0) {
303 				alt--;
304 			}
305 		} else {
306 			alt++;
307 		}
308 		return;
309 	}
310 	if (!down) {
311 		return;
312 	}
313 	if (keysym == XK_Escape) {
314 		keysym = 27;
315 	}
316 	if (control) {
317 		/* shift down to the "control" zone */
318 		if (keysym >= 'a' && keysym <= 'z') {
319 			keysym -= ('a' - 1);
320 		} else if (keysym >= 'A' && keysym <= 'Z') {
321 			keysym -= ('A' - 1);
322 		} else {
323 			keysym = 0xffff;
324 		}
325 	} else if (alt) {
326 		/* shift up to the upper half Latin zone */
327 		if (keysym >= '!' && keysym <= '~') {
328 			keysym += 128;
329 		}
330 	}
331 	if (debug_keyboard) fprintf(stderr, "keysym now: %d\n", (int) keysym);
332 	if (keysym == XK_Tab) {
333 		keysym = '\t';
334 	} else if (keysym == XK_Return || keysym == XK_KP_Enter) {
335 		keysym = '\r';
336 	} else if (keysym == XK_BackSpace) {
337 		keysym = 8;
338 	} else if (keysym == XK_Home || keysym == XK_KP_Home) {
339 		keysym = 1;
340 	} else if (keysym == XK_End || keysym == XK_KP_End) {
341 		keysym = 5;
342 	} else if (keysym == XK_Up || keysym == XK_KP_Up) {
343 		keysym = 16;
344 	} else if (keysym == XK_Down || keysym == XK_KP_Down) {
345 		keysym = 14;
346 	} else if (keysym == XK_Right || keysym == XK_KP_Right) {
347 		keysym = 6;
348 	} else if (keysym == XK_Next || keysym == XK_KP_Next) {
349 		keysym = 6;
350 	} else if (keysym == XK_Left || keysym == XK_KP_Left) {
351 		keysym = 2;
352 	} else if (keysym == XK_Prior || keysym == XK_KP_Prior) {
353 		keysym = 2;
354 	} else {
355 		if (keysym >= XK_KP_Multiply && keysym <= XK_KP_Equal) {
356 			keysym -= 0xFF80;
357 		}
358 	}
359 #if LIBVNCSERVER_HAVE_SYS_IOCTL_H && defined(TIOCSTI)
360 	if (keysym < 0x100) {
361 		if (ioctl(pipeinput_cons_fd, TIOCSTI, &keysym) != -1) {
362 			return;
363 		}
364 		perror("ioctl");
365 		close(pipeinput_cons_fd);
366 		pipeinput_cons_fd = -1;
367 		if (! pipeinput_cons_dev) {
368 			return;
369 		}
370 		pipeinput_cons_fd = open(pipeinput_cons_dev, O_WRONLY);
371 		if (pipeinput_cons_fd < 0) {
372 			rfbLog("pipeinput: could not reopen %s\n",
373 			    pipeinput_cons_dev);
374 			perror("open");
375 			return;
376 		}
377 		if (ioctl(pipeinput_cons_fd, TIOCSTI, &keysym) == -1) {
378 			perror("ioctl");
379 			close(pipeinput_cons_fd);
380 			pipeinput_cons_fd = -1;
381 			rfbLog("pipeinput: could not reopen %s\n",
382 			    pipeinput_cons_dev);
383 		}
384 	}
385 #endif
386 
387 	if (client) {}
388 }
389 
console_pointer_command(int mask,int x,int y,rfbClientPtr client)390 void console_pointer_command(int mask, int x, int y, rfbClientPtr client) {
391 	/* do not forget viewonly perms */
392 	if (mask || x || y || client) {}
393 }
394 
395