frame buffer work

This commit is contained in:
jsorg71 2006-08-06 20:22:38 +00:00
parent 66cbf378ed
commit f9aa0b9b10
2 changed files with 723 additions and 7 deletions

View File

@ -22,11 +22,17 @@
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include <termios.h>
#include <pwd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/mman.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <linux/fb.h>
#include <linux/kd.h>
#include "uimain.h"
#include "bsops.h"
extern char g_username[];
extern char g_hostname[];
@ -43,8 +49,24 @@ extern int g_tcp_port_rdp; /* in tcp.c */
extern int g_bytes_in;
extern int pal_entries[];
extern int g_bs_bpp;
extern int g_bs_Bpp;
extern char * g_bs;
static int g_bpp = 8;
static int g_Bpp = 1;
/* keys */
struct key
{
int scancode;
int rdpcode;
int ext;
};
static struct key g_keys[256];
static char g_keyfile[64] = "./default.key";
struct cursor
{
unsigned char andmask[32 * 32];
@ -57,18 +79,53 @@ struct cursor
static struct cursor g_mcursor; /* current mouse */
static int g_mouse_x = 0;
static int g_mouse_y = 0;
static int g_mouse_buttons = 0; /* mouse button states */
static int g_mousefd = 0; /* mouse fd */
static int g_mouse_state = 0; /* used when reading mouse device */
static int g_uts = 0; /* updates to skip */
static int g_alt_down = 0; /* used to disable control alt delete */
static int g_control_down = 0;
static int g_shift_down = 0;
static int g_disable_cad = 0; /* disable control alt delete */
/* and ctrl shift esc */
static int g_wfpx = 0; /* wait for pixel stuff */
static int g_wfpy = 0;
static int g_wfpv = 0;
static int g_show_wfp = 0;
static int g_no_draw = 0; /* this means don't draw the screen but draw on
backingstore */
/* for transparent colour */
static int g_use_trans = 0;
static int g_trans_colour = 0;
/* clip */
static int g_clip_left = 0;
static int g_clip_top = 0;
static int g_clip_right = 0;
static int g_clip_bottom = 0;
static int g_kbfd = 0; /* keyboard fd */
static int g_fbfd = 0; /* framebuffer fd */
static char * g_sdata = 0;
static struct fb_var_screeninfo g_vinfo;
static struct fb_fix_screeninfo g_finfo;
static short g_saved_red[256]; /* original hw palette */
static short g_saved_green[256];
static short g_saved_blue[256];
struct my_rect
{
int x;
int y;
int w;
int h;
};
static struct my_rect g_rect = {0, 0, 0, 0};
/*****************************************************************************/
void
mi_error(char * msg)
@ -102,12 +159,270 @@ mi_create_window(void)
void
mi_update_screen(void)
{
int i;
int j;
int endi;
int endj;
int x;
int y;
int pixel;
int r;
int g;
int b;
endi = UI_MIN(g_rect.y + g_rect.h, g_clip_bottom);
endj = UI_MIN(g_rect.x + g_rect.w, g_clip_right);
x = UI_MAX(g_rect.x, g_clip_left);
y = UI_MAX(g_rect.y, g_clip_top);
//printf("hi %d %d %d %d\n", x, y, endi, endj);
if (g_bpp == 16 && g_bs_bpp == 32)
{
for (i = y; i < endi; i++)
{
for (j = x; j < endj; j++)
{
pixel = ((unsigned int *) g_bs)[i * g_width + j];
SPLIT_COLOUR32(pixel, b, g, r);
MAKE_COLOUR16(pixel, r, g, b);
((unsigned short *) g_sdata)[i * g_width + j] = pixel;
}
}
}
g_rect.x = 0;
g_rect.y = 0;
g_rect.w = 0;
g_rect.h = 0;
//printf("bye\n");
}
/*****************************************************************************/
static void
process_keyboard(void)
{
char buf[128];
unsigned char ch;
int count;
int index;
int keyup;
int rdpkey;
int ext;
ext = 0;
index = 0;
count = read(g_kbfd, buf, 128);
while (index < count)
{
ch = (unsigned char)buf[index];
//printf("%2.2x\n", ch);
keyup = ch & 0x80;
rdpkey = ch & 0x7f;
ext = g_keys[rdpkey].ext ? 0x100 : 0;
rdpkey = g_keys[rdpkey].rdpcode;
if (rdpkey == 0x1d) /* control */
{
g_control_down = !keyup;
}
if (rdpkey == 0x38) /* alt */
{
g_alt_down = !keyup;
}
if (rdpkey == 0x2a || rdpkey == 0x36) /* shift */
{
g_shift_down = !keyup;
}
if (g_disable_cad) /* diable control alt delete and control shift escape */
{
if (rdpkey == 0x53 && g_alt_down && g_control_down) /* delete */
{
rdpkey = 0;
}
if (rdpkey == 0x01 && g_shift_down && g_control_down) /* escape */
{
rdpkey = 0;
}
}
if (rdpkey > 0 && g_mouse_buttons == 0)
{
if (!keyup)
{
ui_key_down(rdpkey, ext);
}
else
{
ui_key_up(rdpkey, ext);
}
}
index++;
}
}
/*****************************************************************************/
static int
process_mouse(void)
{
char d[128];
int c;
int i;
int b;
int old_x;
int old_y;
int old_but1;
int old_but2;
int mouse_x; /* hot spot */
int mouse_y; /* hot spot */
mouse_x = g_mouse_x + g_mcursor.x;
mouse_y = g_mouse_y + g_mcursor.y;
old_x = mouse_x;
old_y = mouse_y;
old_but1 = g_mouse_buttons & 1;
old_but2 = g_mouse_buttons & 2;
c = read(g_mousefd, &d, 128);
for (i = 0; i < c; i++)
{
b = (unsigned char)d[i];
switch (g_mouse_state)
{
case 0:
if (b & 0x08) /* PS2_CTRL_BYTE */
{
g_mouse_buttons = b & (1 | 2);
g_mouse_state = 1;
}
break;
case 1: /* x */
if (b > 127)
{
b -= 256;
}
mouse_x += b;
if (mouse_x < 0)
{
mouse_x = 0;
}
else if (mouse_x >= g_width)
{
mouse_x = g_width - 1;
}
g_mouse_state = 2;
break;
case 2: /* y */
if (b > 127)
{
b -= 256;
}
mouse_y += -b;
if (mouse_y < 0)
{
mouse_y = 0;
}
else if (mouse_y >= g_height)
{
mouse_y = g_height - 1;
}
g_mouse_state = 0;
break;
}
}
if (old_x != mouse_x || old_y != mouse_y) /* mouse pos changed */
{
ui_mouse_move(mouse_x, mouse_y);
}
if (old_but1 != (g_mouse_buttons & 1)) /* left button changed */
{
if (g_mouse_buttons & 1)
{
ui_mouse_button(1, mouse_x, mouse_y, 1);
}
else
{
ui_mouse_button(1, mouse_x, mouse_y, 0);
}
}
if (old_but2 != (g_mouse_buttons & 2)) /* right button changed */
{
if (g_mouse_buttons & 2)
{
ui_mouse_button(2, mouse_x, mouse_y, 1);
}
else
{
ui_mouse_button(2, mouse_x, mouse_y, 0);
}
}
//undraw_mouse();
g_mouse_x = mouse_x - g_mcursor.x;
g_mouse_y = mouse_y - g_mcursor.y;
//draw_mouse();
return 0;
}
/*****************************************************************************/
int
mi_main_loop(void)
{
fd_set rfds;
// fd_set wfds;
int rv;
int fd;
struct timeval tv;
fd = UI_MAX(g_tcp_sck, UI_MAX(g_mousefd, g_kbfd));
FD_ZERO(&rfds);
FD_SET(g_tcp_sck, &rfds);
FD_SET(g_mousefd, &rfds);
FD_SET(g_kbfd, &rfds);
tv.tv_sec = 0;
tv.tv_usec = 0;
rv = select(fd + 1, &rfds, 0, 0, &tv);
while (rv > -1)
{
if (rv == 0)
{
usleep(0);
}
if (FD_ISSET(g_kbfd, &rfds))
{
process_keyboard();
}
if (FD_ISSET(g_mousefd, &rfds))
{
process_mouse();
}
if (FD_ISSET(g_tcp_sck, &rfds))
{
if (!ui_read_wire())
{
return 0;
}
}
fd = UI_MAX(g_tcp_sck, UI_MAX(g_mousefd, g_kbfd));
FD_ZERO(&rfds);
FD_SET(g_tcp_sck, &rfds);
FD_SET(g_mousefd, &rfds);
FD_SET(g_kbfd, &rfds);
#ifdef WITH_RDPSND
// if (g_rdpsnd && g_dsp_busy)
// {
// fd = MAX(fd, g_dsp_fd);
// FD_ZERO(&wfds);
// FD_SET(g_dsp_fd, &wfds);
// rv = select(fd + 1, &rfds, &wfds, 0, 0);
// if (rv > 0 && FD_ISSET(g_dsp_fd, &wfds))
// {
// wave_out_play();
// }
// }
// else
// {
// rv = select(fd + 1, &rfds, 0, 0, 0);
// }
#else
tv.tv_sec = 0;
tv.tv_usec = 0;
rv = select(fd + 1, &rfds, 0, 0, &tv);
#endif
}
return 0;
}
@ -115,7 +430,6 @@ mi_main_loop(void)
void
mi_add_to(int x, int y, int cx, int cy)
{
/*
int right;
int bottom;
@ -149,7 +463,6 @@ mi_add_to(int x, int y, int cx, int cy)
g_rect.w = right - g_rect.x;
g_rect.h = bottom - g_rect.y;
}
*/
}
/*****************************************************************************/
@ -188,6 +501,8 @@ mi_fill_rect(int x, int y, int cx, int cy, int colour)
{
return;
}
mi_add_to(x, y, cx, cy);
mi_update_screen();
}
/*****************************************************************************/
@ -198,6 +513,17 @@ mi_line(int x1, int y1, int x2, int y2, int colour)
{
return;
}
int x;
int y;
int cx;
int cy;
x = UI_MIN(x1, x2);
y = UI_MIN(y1, y2);
cx = (UI_MAX(x1, x2) + 1) - x;
cy = (UI_MAX(y1, y2) + 1) - y;
mi_add_to(x, y, cx, cy);
mi_update_screen();
}
/*****************************************************************************/
@ -208,18 +534,32 @@ mi_screen_copy(int x, int y, int cx, int cy, int srcx, int srcy)
{
return;
}
mi_add_to(x, y, cx, cy);
mi_update_screen();
}
/*****************************************************************************/
void
mi_set_clip(int x, int y, int cx, int cy)
{
g_clip_left = x;
g_clip_top = y;
g_clip_right = x + cx;
g_clip_bottom = y + cy;
g_clip_left = UI_MAX(g_clip_left, 0);
g_clip_top = UI_MAX(g_clip_top, 0);
g_clip_right = UI_MIN(g_clip_right, g_width);
g_clip_bottom = UI_MIN(g_clip_bottom, g_height);
}
/*****************************************************************************/
void
mi_reset_clip(void)
{
g_clip_left = 0;
g_clip_top = 0;
g_clip_right = g_width;
g_clip_bottom = g_height;
}
/*****************************************************************************/
@ -228,13 +568,41 @@ mi_create_cursor(unsigned int x, unsigned int y,
int width, int height,
unsigned char * andmask, unsigned char * xormask)
{
return (void *) 1;
struct cursor * c;
int i;
int j;
c = (struct cursor *) malloc(sizeof(struct cursor));
memset(c, 0, sizeof(struct cursor));
c->w = width;
c->h = height;
c->x = x;
c->y = y;
for (i = 0; i < 32; i++)
{
for (j = 0; j < 32; j++)
{
if (bs_is_pixel_on(andmask, j, i, 32, 1))
{
bs_set_pixel_on(c->andmask, j, 31 - i, 32, 8, 255);
}
if (bs_is_pixel_on(xormask, j, i, 32, 1))
{
bs_set_pixel_on(c->xormask, j, 31 - i, 32, 8, 255);
}
}
}
return c;
}
/*****************************************************************************/
void
mi_destroy_cursor(void * cursor)
{
struct cursor * c;
c = (struct cursor *) cursor;
free(c);
}
/*****************************************************************************/
@ -342,12 +710,351 @@ parse_parameters(int in_argc, char ** in_argv)
}
/*****************************************************************************/
int
main(int argc, char ** argv)
static void
get_username_and_hostname(void)
{
char fullhostname[64];
char * p;
struct passwd * pw;
strncpy(g_username, "unknown", 255);
strncpy(g_hostname, "unknown", 255);
pw = getpwuid(getuid());
if (pw != 0)
{
if (pw->pw_name != 0)
{
strncpy(g_username, pw->pw_name, 255);
}
}
if (gethostname(fullhostname, sizeof(fullhostname)) != -1)
{
p = strchr(fullhostname, '.');
if (p != 0)
{
*p = 0;
}
strncpy(g_hostname, fullhostname, 255);
}
}
/*****************************************************************************/
static void
save_palette(void)
{
struct fb_cmap cmap;
cmap.start = 0;
if (g_bpp == 15)
{
cmap.len = 16;
}
else
{
cmap.len = 256;
}
cmap.red = (unsigned short *) g_saved_red;
cmap.green = (unsigned short *) g_saved_green;
cmap.blue = (unsigned short *) g_saved_blue;
cmap.transp = 0;
ioctl(g_fbfd, FBIOGETCMAP, &cmap);
}
/*****************************************************************************/
static void
restore_palette(void)
{
struct fb_cmap cmap;
cmap.start = 0;
if (g_bpp == 15)
{
cmap.len = 16;
}
else
{
cmap.len = 256;
}
cmap.red = (unsigned short *) g_saved_red;
cmap.green = (unsigned short *) g_saved_green;
cmap.blue = (unsigned short *) g_saved_blue;
cmap.transp = 0;
ioctl(g_fbfd, FBIOPUTCMAP, &cmap);
}
/*****************************************************************************/
static void
set_directcolor_palette(void)
{
short r[256];
int i;
struct fb_cmap cmap;
if (g_bpp == 15)
{
for (i = 0; i < 32; i++)
{
r[i] = i << 11;
}
cmap.len = 32;
}
else
{
for (i = 0; i < 256; i++)
{
r[i] = i << 8;
}
cmap.len = 256;
}
cmap.start = 0;
cmap.red = (unsigned short *) r;
cmap.green = (unsigned short *) r;
cmap.blue = (unsigned short *) r;
cmap.transp = 0;
ioctl(g_fbfd, FBIOPUTCMAP, &cmap);
}
/*****************************************************************************/
static int
htoi(char * val)
{
int rv;
rv = 0;
switch (val[0])
{
case '1': rv = 16; break;
case '2': rv = 16 * 2; break;
case '3': rv = 16 * 3; break;
case '4': rv = 16 * 4; break;
case '5': rv = 16 * 5; break;
case '6': rv = 16 * 6; break;
case '7': rv = 16 * 7; break;
case '8': rv = 16 * 8; break;
case '9': rv = 16 * 9; break;
case 'a': rv = 16 * 10; break;
case 'b': rv = 16 * 11; break;
case 'c': rv = 16 * 12; break;
case 'd': rv = 16 * 13; break;
case 'e': rv = 16 * 14; break;
case 'f': rv = 16 * 15; break;
}
switch (val[1])
{
case '1': rv += 1; break;
case '2': rv += 2; break;
case '3': rv += 3; break;
case '4': rv += 4; break;
case '5': rv += 5; break;
case '6': rv += 6; break;
case '7': rv += 7; break;
case '8': rv += 8; break;
case '9': rv += 9; break;
case 'a': rv += 10; break;
case 'b': rv += 11; break;
case 'c': rv += 12; break;
case 'd': rv += 13; break;
case 'e': rv += 14; break;
case 'f': rv += 15; break;
}
return rv;
}
/*****************************************************************************/
static int
load_keys(void)
{
int fd;
int len;
int index;
int i1;
int comment;
int val1;
int val2;
int val3;
char all_lines[8192];
char line[256];
char val[4];
memset(g_keys, 0, sizeof(g_keys));
fd = open(g_keyfile, O_RDWR);
if (fd > 0)
{
i1 = 0;
line[0] = 0;
comment = 0;
len = read(fd, all_lines, 8192);
for (index = 0; index < len ; index++)
{
if (all_lines[index] == '#')
{
comment = 1;
}
else if (all_lines[index] == 13 || all_lines[index] == 10)
{
if (strlen(line) > 7)
{
val[0] = line[0];
val[1] = line[1];
val[2] = 0;
val1 = htoi(val);
val[0] = line[3];
val[1] = line[4];
val[2] = 0;
val2 = htoi(val);
val[0] = line[6];
val[1] = line[7];
val[2] = 0;
val3 = htoi(val);
g_keys[val1].scancode = val1;
g_keys[val1].rdpcode = val2;
g_keys[val1].ext = val3;
}
line[0] = 0;
i1 = 0;
comment = 0;
}
else if (!comment)
{
line[i1] = all_lines[index];
i1++;
line[i1] = 0;
}
}
close(fd);
}
return 0;
}
/*****************************************************************************/
int
main(int in_argc, char ** in_argv)
{
int rv;
int screensize;
struct termios new_termios;
rv = 0;
g_server_depth = 24;
memset(&g_mcursor, 0, sizeof(struct cursor));
get_username_and_hostname();
/* read command line options */
if (!parse_parameters(in_argc, in_argv))
{
exit(0);
}
/* Open the file for reading and writing */
g_fbfd = open("/dev/fb0", O_RDWR);
if (g_fbfd == -1)
{
printf("Error: cannot open framebuffer device.\n");
exit(101);
}
printf("The framebuffer device was opened successfully.\n");
/* Get fixed screen information */
if (ioctl(g_fbfd, FBIOGET_FSCREENINFO, &g_finfo))
{
printf("Error reading fixed information.\n");
exit(102);
}
/* Get variable screen information */
if (ioctl(g_fbfd, FBIOGET_VSCREENINFO, &g_vinfo))
{
printf("Error reading variable information.\n");
exit(103);
}
g_bpp = g_vinfo.bits_per_pixel;
g_Bpp = (g_bpp + 7) / 8;
g_width = g_vinfo.xres;
g_height = g_vinfo.yres;
g_clip_right = g_width;
g_clip_bottom = g_height;
printf("%dx%d, %dbpp\n", g_vinfo.xres, g_vinfo.yres, g_vinfo.bits_per_pixel);
/* Figure out the size of the screen in bytes */
screensize = g_vinfo.xres * g_vinfo.yres * g_Bpp;
/* Map the device to memory */
g_sdata = (char *) mmap(0, screensize, PROT_READ | PROT_WRITE, MAP_SHARED,
g_fbfd, 0);
g_bs = malloc(screensize);
if ((int) g_sdata == -1)
{
printf("Error: failed to map framebuffer device to memory.\n");
exit(104);
}
printf("The framebuffer device was mapped to memory successfully.\n");
/* open mouse */
g_mousefd = open("/dev/mouse", O_RDWR);
if (g_mousefd == -1)
{
g_mousefd = open("/dev/psaux", O_RDWR);
}
if (g_mousefd == -1)
{
printf("Error: failed to open /dev/mouse or /dev/psaux\n");
exit(105);
}
g_kbfd = open("/dev/tty0", O_RDWR);
if (g_kbfd == -1)
{
printf("Error: failed to open /dev/tty0\n");
exit(106);
}
/* check fb type */
if (g_finfo.visual != FB_VISUAL_DIRECTCOLOR &&
g_finfo.visual != FB_VISUAL_TRUECOLOR)
{
printf("unsupports fb\n");
exit(107);
}
if (g_finfo.visual == FB_VISUAL_DIRECTCOLOR)
{
/* save hardware palette */
save_palette();
/* set palette to match truecolor */
set_directcolor_palette();
}
/* clear the screen */
mi_fill_rect(0, 0, g_width, g_height, 0);
/* connect */
#ifdef WITH_RDPSND
/* init sound */
// if (g_rdpsnd)
// {
// rdpsnd_init();
// }
#endif
#if 0
/* setup keyboard */
ioctl(g_kbfd, KDGKBMODE, &g_org_kbmode); /* save this */
tcgetattr(g_kbfd, &org_termios); /* save this */
new_termios = org_termios;
new_termios.c_lflag &= ~(ICANON | ECHO | ISIG);
new_termios.c_iflag &= ~(ISTRIP | IGNCR | ICRNL | INLCR | IXOFF | IXON);
new_termios.c_cc[VMIN] = 0;
new_termios.c_cc[VTIME] = 0;
tcsetattr(g_kbfd, TCSAFLUSH, &new_termios);
ioctl(g_kbfd, KDSKBMODE, K_MEDIUMRAW);
#endif
load_keys();
/* do it all here */
rv = ui_main();
/* clear the screen when done */
mi_fill_rect(0, 0, g_width, g_height, 0);
/* restore some stuff */
if (g_finfo.visual == FB_VISUAL_DIRECTCOLOR)
{
restore_palette();
}
munmap(g_sdata, screensize);
close(g_fbfd);
close(g_mousefd);
#if 0
ioctl(g_kbfd, KDSKBMODE, g_org_kbmode);
tcsetattr(g_kbfd, TCSANOW, &org_termios);
#endif
close(g_kbfd);
free(g_bs);
return rv;
}

View File

@ -70,6 +70,15 @@ ui_set_modifier_state(int code);
); \
}
#define MAKE_COLOUR16(c, r, g, b) \
{ \
c = ( \
(((r & 0xff) >> 3) << 11) | \
(((g & 0xff) >> 2) << 5) | \
(((b & 0xff) >> 3) << 0) \
); \
}
#define MAKE_COLOUR32(c, r, g, b) \
{ \
c = ( \