From 279f35495a122c9892198545f83e03c6fc50fa08 Mon Sep 17 00:00:00 2001 From: runge Date: Sun, 7 May 2006 00:50:13 +0000 Subject: x11vnc: support for video4linux webcams & tv-tuners, -24to32 bpp option, -rawfb console. --- x11vnc/linuxfb.c | 234 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 234 insertions(+) create mode 100644 x11vnc/linuxfb.c (limited to 'x11vnc/linuxfb.c') 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 +#endif +#if LIBVNCSERVER_HAVE_LINUX_FB_H +#include +#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) {} +} + -- cgit v1.2.1