summaryrefslogtreecommitdiffstats
path: root/x11vnc/linuxfb.c
diff options
context:
space:
mode:
Diffstat (limited to 'x11vnc/linuxfb.c')
-rw-r--r--x11vnc/linuxfb.c234
1 files changed, 234 insertions, 0 deletions
diff --git a/x11vnc/linuxfb.c b/x11vnc/linuxfb.c
new file mode 100644
index 0000000..2f4e0be
--- /dev/null
+++ b/x11vnc/linuxfb.c
@@ -0,0 +1,234 @@
+/* -- linuxfb.c -- */
+
+#include "x11vnc.h"
+#include "cleanup.h"
+#include "scan.h"
+#include "xinerama.h"
+#include "screen.h"
+#include "pointer.h"
+
+#if LIBVNCSERVER_HAVE_SYS_IOCTL_H
+#include <sys/ioctl.h>
+#endif
+#if LIBVNCSERVER_HAVE_LINUX_FB_H
+#include <linux/fb.h>
+#endif
+
+char *console_guess(char *str, int *fd);
+void console_key_command(rfbBool down, rfbKeySym keysym, rfbClientPtr client);
+void console_pointer_command(int mask, int x, int y, rfbClientPtr client);
+
+char *console_guess(char *str, int *fd) {
+ char *q, *in = strdup(str);
+ char *atparms = NULL, *file = NULL;
+ int tty = -1;
+ if (strstr(in, "/dev/fb") == in) {
+ free(in);
+ in = (char *) malloc(strlen("cons:") + strlen(str) + 1);
+ sprintf(in, "cons:%s", str);
+ } else if (strstr(in, "fb") == in) {
+ free(in);
+ in = (char *) malloc(strlen("cons:/dev/") + strlen(str) + 1);
+ sprintf(in, "cons:/dev/%s", str);
+ }
+
+ if (strstr(in, "cons") != in) {
+ rfbLog("console_guess: unrecognized console/fb format: %s\n", str);
+ free(in);
+ return NULL;
+ }
+
+ q = strrchr(in, '@');
+ if (q) {
+ atparms = strdup(q+1);
+ *q = '\0';
+ }
+ q = strrchr(in, ':');
+ if (q) {
+ file = strdup(q+1);
+ *q = '\0';
+ }
+ if (! file || file[0] == '\0') {
+ file = strdup("/dev/fb");
+ }
+ if (strstr(file, "fb") == file) {
+ q = (char *) malloc(strlen("/dev/") + strlen(file) + 1);
+ sprintf(q, "/dev/%s", file);
+ free(file);
+ file = q;
+ }
+ if (!strcmp(file, "/dev/fb")) {
+ /* sometimes no sylink fb -> fb0 */
+ struct stat sbuf;
+ if (stat(file, &sbuf) != 0) {
+ free(file);
+ file = strdup("/dev/fb0");
+ }
+ }
+ rfbLog("console_guess: file is %s\n", file);
+
+ if (!strcmp(in, "cons") || !strcmp(in, "console")) {
+ /* current active VT: */
+ tty = 0;
+ } else {
+ int n;
+ if (sscanf(in, "cons%d", &n) == 1) {
+ tty = n;
+ } else if (sscanf(in, "console%d", &n) != 1) {
+ tty = n;
+ }
+ }
+ if (tty >=0 && tty < 64) {
+ if (pipeinput_str == NULL) {
+ pipeinput_str = (char *) malloc(10);
+ sprintf(pipeinput_str, "CONS%d", tty);
+ rfbLog("console_guess: file pipeinput %s\n", pipeinput_str);
+ initialize_pipeinput();
+ }
+ }
+ if (! atparms) {
+#if LIBVNCSERVER_HAVE_LINUX_FB_H
+#if LIBVNCSERVER_HAVE_SYS_IOCTL_H
+ struct fb_var_screeninfo var_info;
+ int d = open(file, O_RDWR);
+ if (d >= 0) {
+ int w, h, b;
+ unsigned long rm = 0, gm = 0, bm = 0;
+ if (ioctl(d, FBIOGET_VSCREENINFO, &var_info) != -1) {
+ w = (int) var_info.xres;
+ h = (int) var_info.yres;
+ b = (int) var_info.bits_per_pixel;
+
+ rm = (1 << var_info.red.length) - 1;
+ gm = (1 << var_info.green.length) - 1;
+ bm = (1 << var_info.blue.length) - 1;
+ rm = rm << var_info.red.offset;
+ gm = gm << var_info.green.offset;
+ bm = bm << var_info.blue.offset;
+
+ if (b == 8 && rm == 0xff && gm == 0xff && bm == 0xff) {
+ /* I don't believe it... */
+ rm = 0x07;
+ gm = 0x38;
+ bm = 0xc0;
+ }
+
+ /* @66666x66666x32:0xffffffff:... */
+ atparms = (char *) malloc(200);
+ sprintf(atparms, "%dx%dx%d:%lx/%lx/%lx",
+ w, h, b, rm, gm, bm);
+ *fd = d;
+ } else {
+ perror("ioctl");
+ close(d);
+ }
+ } else {
+ rfbLog("could not open: %s\n", file);
+ perror("open");
+ close(d);
+ }
+#endif
+#endif
+ }
+
+ if (! atparms) {
+ rfbLog("console_guess: could not get @ parameters.\n");
+ return NULL;
+ }
+
+ q = (char *) malloc(strlen("map:") + strlen(file) + 1 + strlen(atparms) + 1);
+ sprintf(q, "map:%s@%s", file, atparms);
+ return q;
+}
+
+void console_key_command(rfbBool down, rfbKeySym keysym, rfbClientPtr client) {
+ static int control = 0;
+ if (debug_keyboard) fprintf(stderr, "console_key_command: %d %s\n", (int) keysym, down ? "down" : "up");
+ if (pipeinput_cons_fd < 0) {
+ return;
+ }
+
+ /* From LinuxVNC.c: */
+ if (keysym == XK_Control_L || keysym == XK_Control_R) {
+ if (! down) {
+ if (control > 0) {
+ control--;
+ }
+ } else {
+ control++;
+ }
+ return;
+ }
+ if (!down) {
+ return;
+ }
+ if (keysym == XK_Escape) {
+ keysym = 27;
+ }
+ if (control) {
+ if (keysym >= 'a' && keysym <= 'z') {
+ keysym -= ('a' - 1);
+ } else if (keysym >= 'A' && keysym <= 'Z') {
+ keysym -= ('A' - 1);
+ } else {
+ keysym = 0xffff;
+ }
+ }
+ if (keysym == XK_Tab) {
+ keysym = '\t';
+ } else if (keysym == XK_Return) {
+ keysym = '\r';
+ } else if (keysym == XK_BackSpace) {
+ keysym = 8;
+ } else if (keysym == XK_Home || keysym == XK_KP_Home) {
+ keysym = 1;
+ } else if (keysym == XK_End || keysym == XK_KP_End) {
+ keysym = 5;
+ } else if (keysym == XK_Up || keysym == XK_KP_Up) {
+ keysym = 16;
+ } else if (keysym == XK_Down || keysym == XK_KP_Down) {
+ keysym = 14;
+ } else if (keysym == XK_Right || keysym == XK_KP_Right) {
+ keysym = 6;
+ } else if (keysym == XK_Next || keysym == XK_KP_Next) {
+ keysym = 6;
+ } else if (keysym == XK_Left || keysym == XK_KP_Left) {
+ keysym = 2;
+ } else if (keysym == XK_Prior || keysym == XK_KP_Prior) {
+ keysym = 2;
+ }
+#if LIBVNCSERVER_HAVE_SYS_IOCTL_H && defined(TIOCSTI)
+ if (keysym < 0x100) {
+ if (ioctl(pipeinput_cons_fd, TIOCSTI, &keysym) != -1) {
+ return;
+ }
+ perror("ioctl");
+ close(pipeinput_cons_fd);
+ pipeinput_cons_fd = -1;
+ if (! pipeinput_cons_dev) {
+ return;
+ }
+ pipeinput_cons_fd = open(pipeinput_cons_dev, O_WRONLY);
+ if (pipeinput_cons_fd < 0) {
+ rfbLog("pipeinput: could not reopen %s\n",
+ pipeinput_cons_dev);
+ perror("open");
+ return;
+ }
+ if (ioctl(pipeinput_cons_fd, TIOCSTI, &keysym) == -1) {
+ perror("ioctl");
+ close(pipeinput_cons_fd);
+ pipeinput_cons_fd = -1;
+ rfbLog("pipeinput: could not reopen %s\n",
+ pipeinput_cons_dev);
+ }
+ }
+#endif
+
+ if (client) {}
+}
+
+void console_pointer_command(int mask, int x, int y, rfbClientPtr client) {
+ if (mask || x || y || client) {}
+}
+