FBVNC

fbvnc.c

fbvnc.c
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/mman.h>
 
#include <linux/input.h>
#include <linux/uinput.h>
#include <linux/fb.h>
 
#include <rfb/rfb.h>
#include <rfb/keysym.h>
 
/* Struct returned by ioctl when getting actual display properies (needed for resolution) */
struct fb_var_screeninfo vinfo;
 
/* Functions to convert screen to touchscreen coordinates */
static int normx(int x) {
  return 110 + x * (3880.0 - 110.0)/vinfo.xres;
}
static int normy(int y) {
  return 3870 - y * (3870.0 - 150.0)/vinfo.yres;
}
 
/* uinput devices handlers */
int uinputts;
int uinputkb;
 
/* Function executed by VNC when user click given screen point (x,y) */
static void doPtr(int buttonMask, int x, int y, rfbClientPtr cl)
{
  struct input_event ev;
 
  if (buttonMask != 1) return; /* Only left mouse button */
 
  /* Key pressed */
  memset(&ev, 0, sizeof(struct input_event));
  gettimeofday(&ev.time, NULL);
  ev.type = EV_KEY;
  ev.code = BTN_TOUCH;
  ev.value = 1;
  write(uinputts, &ev, sizeof(struct input_event));
 
  /* Pointer position */
  memset(&ev, 0, sizeof(struct input_event));
  gettimeofday(&ev.time, NULL); 
  ev.type = EV_ABS;
  ev.code = ABS_X;
  ev.value = normx(x);
  write(uinputts, &ev, sizeof(struct input_event));
 
  memset(&ev, 0, sizeof(struct input_event));
  gettimeofday(&ev.time, NULL); 
  ev.type = EV_ABS;
  ev.code = ABS_Y;
  ev.value = normy(y);
  write(uinputts, &ev, sizeof(struct input_event));
 
  /* Pressure */
  memset(&ev, 0, sizeof(struct input_event));
  gettimeofday(&ev.time, NULL); 
  ev.type = EV_ABS;
  ev.code = ABS_PRESSURE;
  ev.value = 14000;
  write(uinputts, &ev, sizeof(struct input_event));
 
  /* Sync event */
  memset(&ev, 0, sizeof(struct input_event));
  gettimeofday(&ev.time, NULL); 
  ev.type = EV_SYN;
  ev.code = SYN_REPORT;
  ev.value = 0;
  write(uinputts, &ev, sizeof(struct input_event));
 
  /* Key released */
  memset(&ev, 0, sizeof(struct input_event));
  gettimeofday(&ev.time, NULL); 
  ev.type = EV_KEY;
  ev.code = BTN_TOUCH;
  ev.value = 0;
  write(uinputts, &ev, sizeof(struct input_event));
 
  /* Pressure (depressed) */
  memset(&ev, 0, sizeof(struct input_event));
  gettimeofday(&ev.time, NULL); 
  ev.type = EV_ABS;
  ev.code = ABS_PRESSURE;
  ev.value = 0;
  write(uinputts, &ev, sizeof(struct input_event));
 
  /* Sync event */
  memset(&ev, 0, sizeof(struct input_event));
  gettimeofday(&ev.time, NULL); 
  ev.type = EV_SYN;
  ev.code = SYN_REPORT;
  ev.value = 0;
  write(uinputts, &ev, sizeof(struct input_event));
}
 
/* Function executed by VNC, when it receives keyboard event from user */
static void doKey(rfbBool down,rfbKeySym key,rfbClientPtr cl)
{
  int ukey;               /* Key code for input framework */
  struct input_event ev;
 
  if(!down) return;
 
  switch(key)             /* Key code translation */
  {
    case XK_Escape:       /* Client is disconnected */
      rfbCloseClient(cl);
      break;
    case XK_BackSpace:
      ukey = KEY_BACKSPACE;
      break;
    case XK_Return:
      ukey = KEY_ENTER;
      break;
    case XK_0:
      ukey = KEY_0;
      break;
    case XK_1:
      ukey = KEY_1;
      break;
    /* ... */
    case XK_9:
      ukey = KEY_9;
      break;
  }
  /* Key pressed */
  memset(&ev, 0, sizeof(struct input_event));
  gettimeofday(&ev.time, NULL);
  ev.type = EV_KEY;
  ev.code = ukey;
  ev.value = 1;
  write(uinputkb, &ev, sizeof(struct input_event));
 
  /* Key released */
  memset(&ev, 0, sizeof(struct input_event));
  gettimeofday(&ev.time, NULL); 
  ev.type = EV_KEY;
  ev.code = ukey;
  ev.value = 0;
  write(uinputkb, &ev, sizeof(struct input_event));
 
  /* Sync event */
  memset(&ev, 0, sizeof(struct input_event));
  gettimeofday(&ev.time, NULL); 
  ev.type = EV_SYN;
  ev.code = SYN_REPORT;
  ev.value = 0;
  write(uinputkb, &ev, sizeof(struct input_event));
}  
 
/* Main program function. Open framebuffer device file, read display parameters, register uinput devices and start VNC server. */
int main(int argc,char** argv)
{
  /* Framebuffer device file handler */
  int fbfd = 0;
  /* Screen parameters */
  long int screensize = 0;
  char *fbp = 0;
  /* Variables used for registering devices */
  struct uinput_user_dev uidev;
 
  /* Open framebuffer and read parameters */
  fbfd = open("/dev/fb0", O_RDONLY);
  ioctl(fbfd, FBIOGET_VSCREENINFO, &vinfo);
  /* Buffer size (in bytes). */
  screensize = vinfo.xres * vinfo.yres * vinfo.bits_per_pixel / 8;
 
  /* Mmap framebuffer. */
  fbp = (char *)mmap(0, screensize, PROT_READ, MAP_SHARED, fbfd, 0);
 
  /* Init uinput device (touchscreen) */
  uinputts = open("/dev/input/uinput", O_WRONLY | O_NONBLOCK);
  /* Set parameters */
  memset(&uidev, 0, sizeof(uidev));
  snprintf(uidev.name, UINPUT_MAX_NAME_SIZE, "uinput-touchscreen");
  uidev.id.bustype = BUS_HOST;
  uidev.id.vendor  = 0x1;
  uidev.id.product = 0x1;
  uidev.id.version = 1;
 
  uidev.absmin[ABS_X] = 1;
  uidev.absmax[ABS_X] = vinfo.xres;
 
  uidev.absmin[ABS_Y] = 1;
  uidev.absmax[ABS_Y] = vinfo.yres;
 
  uidev.absmin[ABS_PRESSURE] = 0; 
  uidev.absmax[ABS_PRESSURE] = 15000; 
 
  /* Create device */
  write(uinputts, &uidev, sizeof(uidev));
  ioctl(uinputts, UI_SET_EVBIT, EV_KEY);
  ioctl(uinputts, UI_SET_KEYBIT, BTN_TOUCH);
  ioctl(uinputts, UI_SET_EVBIT, EV_ABS);
  ioctl(uinputts, UI_SET_ABSBIT, ABS_X);
  ioctl(uinputts, UI_SET_ABSBIT, ABS_Y);
  ioctl(uinputts, UI_SET_ABSBIT, ABS_PRESSURE);
  ioctl(uinputts, UI_SET_EVBIT, EV_SYN);
  ioctl(uinputts, UI_DEV_CREATE);
 
  /* Init another uinput device (keyboard) */
  uinputkb = open("/dev/input/uinput", O_WRONLY | O_NONBLOCK);
  /* Set parameters */
  memset(&uidev, 0, sizeof(uidev));
  snprintf(uidev.name, UINPUT_MAX_NAME_SIZE, "uinput-keyboard");
  uidev.id.bustype = BUS_HOST;
  uidev.id.vendor  = 0x1;
  uidev.id.product = 0x2;
  uidev.id.version = 1;
  write(uinputkb, &uidev, sizeof(uidev));
  ioctl(uinputkb, UI_SET_EVBIT, EV_KEY);
  ioctl(uinputkb, UI_SET_KEYBIT, KEY_1);
  /* ... */
  ioctl(uinputkb, UI_SET_KEYBIT, KEY_9);
  ioctl(uinputkb, UI_SET_KEYBIT, KEY_0);
 
  ioctl(uinputkb, UI_SET_KEYBIT, KEY_ENTER);
  ioctl(uinputkb, UI_SET_KEYBIT, KEY_BACKSPACE);
  ioctl(uinputkb, UI_SET_EVBIT, EV_SYN);
  ioctl(uinputkb, UI_DEV_CREATE);
 
  /* VNC */
  rfbScreenInfoPtr server =
    rfbGetScreen(&argc,argv,vinfo.xres,vinfo.yres,8,3,vinfo.bits_per_pixel / 8);
  server->desktopName = "fbVNC";
  server->alwaysShared = FALSE;
  /* Connect callback functions to VNC  */
  server->ptrAddEvent = doPtr;
  server->kbdAddEvent = doKey;
  /* Buffer contsining the screen */
  server->frameBuffer=(char*)fbp;
 
  /* Start server */
  rfbInitServer(server);
  while (rfbIsActive(server)) {
    /* Mark whole screen as mogified (whole screen will be redrawed) */
    rfbMarkRectAsModified(server,0,0,vinfo.xres,vinfo.yres);
    /* Wait the given number of microseconds and process requests */
    rfbProcessEvents(server,400000);
  }
}

Makefile

Makefile
fbvnc: fbvnc.c
        $(CC) -lvncserver -o fbvnc fbvnc.c
 
clean:
        rm -rf fbvnc

libVNCserver

build-libvncserver.sh
#!/bin/bash
#STAGING - path to install compilled library to.
#CROSS_COMPILE - cross-toolchain prefix.
 
wget -c http://downloads.sourceforge.net/project/libvncserver/libvncserver/0.9.7/LibVNCServer-0.9.7.tar.gz
tar -xf libVNCServer-0.9.7.tar.gz
 
cd LibVNCServer-0.9.7
 
CPPFLAGS="-I$STAGING/usr/include $CF" \
LDFLAGS="-L$STAGING/usr/lib $LF -ljpeg" \
./configure \
       --prefix=/usr \
       --host=$CROSS_COMPILE
 
#Only if there are errors while building.
sed -i -e "s%libdir='/usr/lib'%libdir=\'$STAGING/usr/lib\'%" \
$STAGING/usr/lib/libjpeg.la
 
make
make DESTDIR=$STAGING install
 
chrpath -d $STAGING/usr/lib/libvnc{server,client}.so.0.0.0
ostatnio zmienione: 2011/06/29 00:35