|
|
|
/* -*- c-basic-offset: 8 -*-
|
|
|
|
rdesktop: A Remote Desktop Protocol client.
|
|
|
|
fb calls
|
|
|
|
Copyright (C) Jay Sorg 2006
|
|
|
|
|
|
|
|
This program is free software; you can redistribute it and/or modify
|
|
|
|
it under the terms of the GNU General Public License as published by
|
|
|
|
the Free Software Foundation; either version 2 of the License, or
|
|
|
|
(at your option) any later version.
|
|
|
|
|
|
|
|
This program is distributed in the hope that it will be useful,
|
|
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
GNU General Public License for more details.
|
|
|
|
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
|
|
along with this program; if not, write to the Free Software
|
|
|
|
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include <stdio.h>
|
|
|
|
#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 <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[];
|
|
|
|
extern char g_servername[];
|
|
|
|
extern char g_password[];
|
|
|
|
extern char g_shell[];
|
|
|
|
extern char g_directory[];
|
|
|
|
extern char g_domain[];
|
|
|
|
extern int g_width;
|
|
|
|
extern int g_height;
|
|
|
|
extern int g_tcp_sck;
|
|
|
|
extern int g_server_depth;
|
|
|
|
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];
|
|
|
|
unsigned char xormask[32 * 32];
|
|
|
|
int x;
|
|
|
|
int y;
|
|
|
|
int w;
|
|
|
|
int h;
|
|
|
|
};
|
|
|
|
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)
|
|
|
|
{
|
|
|
|
printf(msg);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*****************************************************************************/
|
|
|
|
void
|
|
|
|
mi_warning(char * msg)
|
|
|
|
{
|
|
|
|
printf(msg);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*****************************************************************************/
|
|
|
|
int
|
|
|
|
mi_read_keyboard_state(void)
|
|
|
|
{
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*****************************************************************************/
|
|
|
|
/* returns non zero if ok */
|
|
|
|
int
|
|
|
|
mi_create_window(void)
|
|
|
|
{
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*****************************************************************************/
|
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*****************************************************************************/
|
|
|
|
void
|
|
|
|
mi_add_to(int x, int y, int cx, int cy)
|
|
|
|
{
|
|
|
|
int right;
|
|
|
|
int bottom;
|
|
|
|
|
|
|
|
if (g_rect.h == 0 && g_rect.w == 0)
|
|
|
|
{
|
|
|
|
g_rect.x = x;
|
|
|
|
g_rect.y = y;
|
|
|
|
g_rect.w = cx;
|
|
|
|
g_rect.h = cy;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
right = g_rect.x + g_rect.w;
|
|
|
|
bottom = g_rect.y + g_rect.h;
|
|
|
|
if (x + cx > right)
|
|
|
|
{
|
|
|
|
right = x + cx;
|
|
|
|
}
|
|
|
|
if (y + cy > bottom)
|
|
|
|
{
|
|
|
|
bottom = y + cy;
|
|
|
|
}
|
|
|
|
if (x < g_rect.x)
|
|
|
|
{
|
|
|
|
g_rect.x = x;
|
|
|
|
}
|
|
|
|
if (y < g_rect.y)
|
|
|
|
{
|
|
|
|
g_rect.y = y;
|
|
|
|
}
|
|
|
|
g_rect.w = right - g_rect.x;
|
|
|
|
g_rect.h = bottom - g_rect.y;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/*****************************************************************************/
|
|
|
|
void
|
|
|
|
mi_invalidate(int x, int y, int cx, int cy)
|
|
|
|
{
|
|
|
|
mi_add_to(x, y, cx, cy);
|
|
|
|
mi_update_screen();
|
|
|
|
}
|
|
|
|
|
|
|
|
/*****************************************************************************/
|
|
|
|
/* return boolean */
|
|
|
|
int
|
|
|
|
mi_create_bs(void)
|
|
|
|
{
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*****************************************************************************/
|
|
|
|
void
|
|
|
|
mi_begin_update(void)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
/*****************************************************************************/
|
|
|
|
void
|
|
|
|
mi_end_update(void)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
/*****************************************************************************/
|
|
|
|
void
|
|
|
|
mi_fill_rect(int x, int y, int cx, int cy, int colour)
|
|
|
|
{
|
|
|
|
if (g_no_draw)
|
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
mi_add_to(x, y, cx, cy);
|
|
|
|
mi_update_screen();
|
|
|
|
}
|
|
|
|
|
|
|
|
/*****************************************************************************/
|
|
|
|
void
|
|
|
|
mi_line(int x1, int y1, int x2, int y2, int colour)
|
|
|
|
{
|
|
|
|
if (g_no_draw)
|
|
|
|
{
|
|
|
|
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();
|
|
|
|
}
|
|
|
|
|
|
|
|
/*****************************************************************************/
|
|
|
|
void
|
|
|
|
mi_screen_copy(int x, int y, int cx, int cy, int srcx, int srcy)
|
|
|
|
{
|
|
|
|
if (g_no_draw)
|
|
|
|
{
|
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*****************************************************************************/
|
|
|
|
void *
|
|
|
|
mi_create_cursor(unsigned int x, unsigned int y,
|
|
|
|
int width, int height,
|
|
|
|
unsigned char * andmask, unsigned char * xormask)
|
|
|
|
{
|
|
|
|
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);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*****************************************************************************/
|
|
|
|
void
|
|
|
|
mi_set_cursor(void * cursor)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
/*****************************************************************************/
|
|
|
|
void
|
|
|
|
mi_set_null_cursor(void)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
/*****************************************************************************/
|
|
|
|
static void
|
|
|
|
out_params(void)
|
|
|
|
{
|
|
|
|
fprintf(stderr, "rdesktop: A Remote Desktop Protocol client.\n");
|
|
|
|
fprintf(stderr, "Version 1.4.1. Copyright (C) 1999-2006 Matt Chapman.\n");
|
|
|
|
fprintf(stderr, "direct framebuffer uiport by Jay Sorg\n");
|
|
|
|
fprintf(stderr, "See http://www.rdesktop.org/ for more information.\n\n");
|
|
|
|
fprintf(stderr, "Usage: dfbrdesktop [options] server\n");
|
|
|
|
fprintf(stderr, " -u: user name\n");
|
|
|
|
fprintf(stderr, " -n: client hostname\n");
|
|
|
|
fprintf(stderr, " -s: shell\n");
|
|
|
|
fprintf(stderr, " -p: password\n");
|
|
|
|
fprintf(stderr, " -d: domain\n");
|
|
|
|
fprintf(stderr, " -c: working directory\n");
|
|
|
|
fprintf(stderr, " -a: colour depth\n");
|
|
|
|
fprintf(stderr, " -wfp x y pixel: skip screen updates till x, y pixel is \
|
|
|
|
this colour\n");
|
|
|
|
fprintf(stderr, " -trans pixel: transparent colour\n");
|
|
|
|
fprintf(stderr, "\n");
|
|
|
|
}
|
|
|
|
|
|
|
|
/*****************************************************************************/
|
|
|
|
static int
|
|
|
|
parse_parameters(int in_argc, char ** in_argv)
|
|
|
|
{
|
|
|
|
int i;
|
|
|
|
|
|
|
|
if (in_argc <= 1)
|
|
|
|
{
|
|
|
|
out_params();
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
for (i = 1; i < in_argc; i++)
|
|
|
|
{
|
|
|
|
strcpy(g_servername, in_argv[i]);
|
|
|
|
if (strcmp(in_argv[i], "-h") == 0)
|
|
|
|
{
|
|
|
|
out_params();
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
else if (strcmp(in_argv[i], "-u") == 0)
|
|
|
|
{
|
|
|
|
strcpy(g_username, in_argv[i + 1]);
|
|
|
|
}
|
|
|
|
else if (strcmp(in_argv[i], "-n") == 0)
|
|
|
|
{
|
|
|
|
strcpy(g_hostname, in_argv[i + 1]);
|
|
|
|
}
|
|
|
|
else if (strcmp(in_argv[i], "-s") == 0)
|
|
|
|
{
|
|
|
|
strcpy(g_shell, in_argv[i + 1]);
|
|
|
|
}
|
|
|
|
else if (strcmp(in_argv[i], "-p") == 0)
|
|
|
|
{
|
|
|
|
strcpy(g_password, in_argv[i + 1]);
|
|
|
|
}
|
|
|
|
else if (strcmp(in_argv[i], "-d") == 0)
|
|
|
|
{
|
|
|
|
strcpy(g_domain, in_argv[i + 1]);
|
|
|
|
}
|
|
|
|
else if (strcmp(in_argv[i], "-c") == 0)
|
|
|
|
{
|
|
|
|
strcpy(g_directory, in_argv[i + 1]);
|
|
|
|
}
|
|
|
|
else if (strcmp(in_argv[i], "-a") == 0)
|
|
|
|
{
|
|
|
|
g_server_depth = atoi(in_argv[i + 1]);
|
|
|
|
}
|
|
|
|
else if (strcmp(in_argv[i], "-wfp") == 0)
|
|
|
|
{
|
|
|
|
g_wfpx = atoi(in_argv[i + 1]);
|
|
|
|
g_wfpy = atoi(in_argv[i + 2]);
|
|
|
|
g_wfpv = atoi(in_argv[i + 3]);
|
|
|
|
if (g_wfpv == 0)
|
|
|
|
{
|
|
|
|
g_show_wfp = 1;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
g_no_draw = 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else if (strcmp(in_argv[i], "-trans") == 0)
|
|
|
|
{
|
|
|
|
g_use_trans = 1;
|
|
|
|
g_trans_colour = atoi(in_argv[i + 1]);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*****************************************************************************/
|
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*****************************************************************************/
|
|
|
|
/* returns non zero ok */
|
|
|
|
int
|
|
|
|
librdesktop_init(long obj1, long obj2, long obj3, int in_argc, char ** in_argv)
|
|
|
|
{
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*****************************************************************************/
|
|
|
|
/* returns non zero ok */
|
|
|
|
int
|
|
|
|
librdesktop_connect(void)
|
|
|
|
{
|
|
|
|
return ui_lib_main();
|
|
|
|
}
|
|
|
|
|
|
|
|
/*****************************************************************************/
|
|
|
|
/* returns non zero ok */
|
|
|
|
int
|
|
|
|
librdesktop_check_wire(void)
|
|
|
|
{
|
|
|
|
fd_set rfds;
|
|
|
|
int rv;
|
|
|
|
int fd;
|
|
|
|
struct timeval tv;
|
|
|
|
|
|
|
|
fd = g_tcp_sck;
|
|
|
|
FD_ZERO(&rfds);
|
|
|
|
FD_SET(g_tcp_sck, &rfds);
|
|
|
|
tv.tv_sec = 0;
|
|
|
|
tv.tv_usec = 0;
|
|
|
|
rv = select(fd + 1, &rfds, 0, 0, &tv);
|
|
|
|
if (rv > -1)
|
|
|
|
{
|
|
|
|
if (rv > 0)
|
|
|
|
{
|
|
|
|
if (FD_ISSET(g_tcp_sck, &rfds))
|
|
|
|
{
|
|
|
|
if (!ui_read_wire())
|
|
|
|
{
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*****************************************************************************/
|
|
|
|
int
|
|
|
|
librdesktop_mouse_move(int x, int y)
|
|
|
|
{
|
|
|
|
ui_mouse_move(x, y);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*****************************************************************************/
|
|
|
|
int
|
|
|
|
librdesktop_mouse_button(int button, int x, int y, int down)
|
|
|
|
{
|
|
|
|
ui_mouse_button(button, x, y, down);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*****************************************************************************/
|
|
|
|
int
|
|
|
|
librdesktop_key_down(int key, int ext)
|
|
|
|
{
|
|
|
|
ui_key_down(key, ext);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*****************************************************************************/
|
|
|
|
int
|
|
|
|
librdesktop_key_up(int key, int ext)
|
|
|
|
{
|
|
|
|
ui_key_up(key, ext);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*****************************************************************************/
|
|
|
|
int
|
|
|
|
librdesktop_quit(void)
|
|
|
|
{
|
|
|
|
return 1;
|
|
|
|
}
|