#include "fbvncserver.h"
#include <sys/ioctl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/time.h>
#include <fcntl.h>
#include <linux/fb.h>
#include <signal.h>
#include "keysym2scancode.h"
Include dependency graph for fbvncserver.c:
Go to the source code of this file.
Functions | |
void | clientleft (rfbClientPtr cl) |
void | emit_scancode (unsigned int s, rfbBool down) |
emit a keyboard scancode/keycode | |
int | emit_touchscreen_sequence (ARTIFICIAL_TS_EVENT *s) |
void | keyevent (rfbBool down, rfbKeySym key, rfbClientPtr cl) |
int | main (int argc, char **argv) |
void | print_usage (char *arg0) |
void | ptrevent (int buttonMask, int x, int y, rfbClientPtr cl) |
Variables | |
unsigned short int * | cmpfbbuf = NULL |
unsigned short int * | fbbuf = NULL |
kbd_layout_t * | kbd_layout = NULL |
unsigned short int * | rfbbuf = NULL |
fb_var_screeninfo | vscrinfo |
Definition in file fbvncserver.c.
void clientleft | ( | rfbClientPtr | cl | ) |
void emit_scancode | ( | unsigned int | s, | |
rfbBool | down | |||
) |
emit a keyboard scancode/keycode
Definition at line 47 of file fbvncserver.c.
References dev_uinput_key(), TRACE2, and TRACE3.
Referenced by keyevent().
00047 { 00049 unsigned short keycode = s; 00050 00051 if (uinput_fd_kbd && uinput) { 00052 TRACE3("emitting keycode ... %d (%#x) [down: %d] \n", keycode, keycode, down); 00053 dev_uinput_key(uinput_fd_kbd,keycode,down); 00054 } else { 00055 TRACE2(" [W]: unable to emit keycode - uinput not ready ... (uinput: %d, fd: %d)", uinput, uinput_fd_kbd); 00056 } // end of [if] 00057 } // end of [emit_scancode]
Here is the call graph for this function:
int emit_touchscreen_sequence | ( | ARTIFICIAL_TS_EVENT * | s | ) |
Emit touchscreen event sequence, The sequence is terminated with an event that has x==-1 called by ptrevent
Definition at line 71 of file fbvncserver.c.
Referenced by ptrevent().
00071 { 00072 int fd; 00073 int ret; 00074 ret = 0; 00075 00076 if((fd=open("/dev/tssim",O_WRONLY))>=0) { 00077 while(s->x!=-1) { 00078 write(fd,s,sizeof(ARTIFICIAL_TS_EVENT)); 00079 s++; 00080 } 00081 close(fd); 00082 } else { 00083 fprintf(stderr, " unable to open /dev/tssim for write-only access \n"); 00084 ret=-1; 00085 } 00086 return(ret); 00087 }
void keyevent | ( | rfbBool | down, | |
rfbKeySym | key, | |||
rfbClientPtr | cl | |||
) |
Keyboard event handler
Definition at line 164 of file fbvncserver.c.
References emit_scancode(), kbd_layout, keysym2scancode(), TRACE1, and TRACE2.
Referenced by main().
00165 { 00166 unsigned int scancode; 00167 00168 scancode = keysym2scancode(kbd_layout, key); 00169 TRACE2 (" [I]: KeyEvent: Key %#x - %d \n",key,down); 00170 TRACE1 (" => Scancode: %#x \n",scancode); 00171 emit_scancode(scancode, down); 00172 return; 00173 }
Here is the call graph for this function:
int main | ( | int | argc, | |
char ** | argv | |||
) |
Definition at line 267 of file fbvncserver.c.
References cmpfbbuf, DEFAULT_KBD_LAYOUT, DESKTOP_NAME, dev_uinput_close(), dev_uinput_init_kbd(), dev_uinput_init_mouse(), fbbuf, init_keyboard_layout(), kbd_layout, keyevent(), notEqual(), PACKAGE_STRING, print_usage(), ptrevent(), rfbbuf, rotate0(), rotate180(), rotate270(), rotate90(), TRACE, TRACE1, TRACE2, TRUE, UINPUT_KBD_NAME, UINPUT_TS_NAME, and vscrinfo.
00267 { 00268 int 00269 i,fbfd; 00270 00271 rfbScreenInfoPtr 00272 rfbScreen; 00273 00274 unsigned long int 00275 compareBufferSize = 0, 00276 remoteBufferSize = 0, 00277 bytesPerPixel = 0; 00278 00279 char 00280 keyboard_layout[10] = DEFAULT_KBD_LAYOUT; 00281 00282 div_t 00283 divresult; 00284 00285 printf("%s (%s %s) \n",PACKAGE_STRING,__DATE__, __TIME__ ); 00288 // ... process commandline arguments. 00289 for(i=1;i<argc;i++) { 00290 if ( !strcmp(argv[i],"-h") 00291 || !strcmp(argv[i],"-help") 00292 || !strcmp(argv[i],"--help") 00293 || !strcmp(argv[i],"-?") ) { 00294 print_usage(argv[0]); 00295 exit(1); 00296 } else if(!strcmp(argv[i],"-debug")) debug = 1; 00297 else if(!strcmp(argv[i],"-keymap")) { 00298 if (argc > i++) { 00299 if ( strlen(argv[i]) < sizeof(keyboard_layout) ) { 00300 strcpy(&keyboard_layout[0], argv[i]); 00301 } else { 00302 printf(" [W] invalid argument for -keymap: %s => I will use [%s] \n",argv[i], keyboard_layout[0]); 00303 } // end of [if] 00304 } // end of [if] 00305 } // end of [if] 00306 else if(!strcmp(argv[i],"-ccw")) rotate = 3; 00307 else if(!strcmp(argv[i],"-cw")) { 00308 if (++rotate > 3) { 00309 fprintf(stderr," [F]: only 0,90,180 & 270 rotations are supported\n"); 00310 fprintf(stderr," => 0 will be used. \n "); 00311 rotate = 0; 00312 } 00313 } 00314 } // end of [for] 00315 00316 #ifdef DEBUG 00317 if (debug) rfbLogEnable(1); 00318 else rfbLogEnable(0); 00319 #else 00320 rfbLogEnable(0); 00321 #endif 00322 00323 // open framebuffer 00324 TRACE(" [I]: open framebuffer (/dev/fb0) ... \n"); 00325 00326 if((fbfd=open("/dev/fb0",O_RDONLY))<0) { 00327 perror("Opening /dev/fb0"); 00328 return(-1); 00329 } 00330 00331 TRACE(" [I]: requesting fb info via ioctl ...\n"); 00332 00333 // Request the framebuffer's screen info 00334 if (ioctl(fbfd,FBIOGET_VSCREENINFO,&vscrinfo) <0 ) { 00335 close(fbfd); 00336 perror("ioctl(FBIOGET_VSCREENINFO)"); 00337 return(-1); 00338 } 00339 00340 TRACE1(" visible resolution [x]: %d px \n", vscrinfo.xres ); 00341 TRACE1(" [y]: %d px \n", vscrinfo.yres ); 00342 TRACE1(" virtual resolution [x]: %d px \n", vscrinfo.xres_virtual); 00343 TRACE1(" [y]: %d px \n", vscrinfo.yres_virtual); 00344 TRACE (" offset from virtual to visible resolution \n"); 00345 TRACE1(" [x]: %d px \n", vscrinfo.xoffset); 00346 TRACE1(" [y]: %d px \n", vscrinfo.yoffset); 00347 TRACE1(" grayscale (0 = false) : %d \n", vscrinfo.grayscale); 00348 TRACE1(" bits per pixel : %d \n", vscrinfo.bits_per_pixel); 00349 if (!vscrinfo.grayscale) { 00350 TRACE2 (" color offsets red : %2d length : %d \n", vscrinfo.red.offset, vscrinfo.red.length); 00351 TRACE2 (" green : %2d length : %d \n", vscrinfo.green.offset, vscrinfo.green.length); 00352 TRACE2 (" blue : %2d length : %d \n", vscrinfo.blue.offset, vscrinfo.blue.length); 00353 } 00354 if (!vscrinfo.nonstd) { 00355 TRACE (" standard pixel format \n"); 00356 } else { 00357 TRACE (" [W]: using non standard pixel format \n"); 00358 }; 00359 00360 if (vscrinfo.height > 0) TRACE1 (" height of picture : %d mm\n", vscrinfo.height); 00361 if (vscrinfo.width > 0) TRACE1 (" width : %d mm\n", vscrinfo.width); 00362 00363 // adjust fb-dimensions accordnig to our needs 00364 if ((rotate == 1) || // for 90 & 270 degree we have to swap 00365 (rotate == 3)) { 00366 vscrinfo.xres = vscrinfo.xres + vscrinfo.yres; // two reason for doing it "in place" 00367 vscrinfo.yres = vscrinfo.xres - vscrinfo.yres; // 1. just for the fun of it 00368 vscrinfo.xres = vscrinfo.xres - vscrinfo.yres; // 2. I do not care about the type/size of the vars 00369 TRACE (" [I]: swap'ed width vs. height to adjust dimensions \n"); 00370 }; 00371 00372 // ... allocate memory for compare-buffer 00373 divresult = div(vscrinfo.bits_per_pixel,8); // note: bytesPerPixel = ceil(vscrinfo.bits_per_pixel/8); <= soemtimes this doesn't work (don't know why) 00374 00375 if (divresult.rem != 0) bytesPerPixel = divresult.quot + 1; 00376 else bytesPerPixel = divresult.quot; 00377 00378 compareBufferSize = vscrinfo.xres * vscrinfo.yres * bytesPerPixel; 00379 TRACE2(" [I]: %d bytes per pixel => I will allocate %d bytes \n", bytesPerPixel, compareBufferSize); 00380 TRACE (" [I]: allocate memory for compare-buffer ... \n"); 00381 00382 if((cmpfbbuf=(unsigned short int *)malloc(compareBufferSize)) == NULL) { 00383 close(fbfd); 00384 perror("malloc"); 00385 return(-1); 00386 } 00387 memset(cmpfbbuf,0x00,compareBufferSize); 00388 00389 // ... allocate and initialize the remote framebuffer 00390 TRACE (" [I]: allocate and initialize the remote framebuffer ... \n"); 00391 00392 remoteBufferSize = vscrinfo.xres * vscrinfo.yres * bytesPerPixel; 00393 if((rfbbuf=(unsigned short int *)malloc(remoteBufferSize))==NULL) { 00394 close(fbfd); 00395 free(cmpfbbuf); 00396 perror("malloc"); 00397 return(-1); 00398 } 00399 // ... mmap the fb 00400 TRACE (" [I]: mapping fb to memory ... \n"); 00401 if((fbbuf=(unsigned short int *)mmap(0, /* */ 00402 compareBufferSize, /* */ 00403 PROT_READ, /* Data can be read */ 00404 MAP_SHARED, /* changes are shared */ 00405 fbfd, /* file handle (framebuffer) */ 00406 0) /* offset */ 00407 /* 00408 * WARNING: ... it might be that we need to specify/calculate an offset in case 00409 * virtual resolution != visible resolution. 00410 */ 00411 ) <0 00412 ) { 00413 close(fbfd); 00414 free(cmpfbbuf); 00415 free(rfbbuf); 00416 perror("mmap"); 00417 return(-1); 00418 } 00419 00420 /* 00421 * check if we can use uinput for Keyboard-Events 00422 */ 00423 if (uinput) { 00424 TRACE (" [I]: check if we have uinput device nodes ... \n"); 00425 uinput_fd_kbd = dev_uinput_init_kbd(UINPUT_KBD_NAME); 00426 uinput_fd_mouse = dev_uinput_init_mouse(UINPUT_TS_NAME); 00427 00428 if ((uinput_fd_kbd > 0) & 00429 (uinput_fd_mouse > 0)) { 00430 TRACE1(" => Keyboard OK (fd=%d). \n",uinput_fd_kbd); 00431 TRACE1(" => Mouse OK (fd=%d). \n",uinput_fd_mouse); 00432 00433 kbd_layout = init_keyboard_layout(keyboard_layout); 00434 if (kbd_layout) { 00435 TRACE1(" [I]: keyboard [%s] loaded \n", keyboard_layout); 00436 } else { 00437 TRACE1(" [W]: keyboard layout [%s] NOT loaded \n", keyboard_layout); 00438 dev_uinput_close(uinput_fd_kbd); 00439 uinput_fd_kbd = 0; 00440 TRACE (" [W]: ... => keyboard event source released. \n") 00441 } // end of [if] 00442 } else { 00443 uinput = 0; 00444 TRACE(" [W]: => unable to initialize uinput \n "); 00445 } 00446 } 00447 00448 /* 00449 * initialize remote fb screen structure 00450 */ 00451 rfbScreen = rfbGetScreen(&argc, // &argc 00452 argv, // argv 00453 vscrinfo.xres, // width 00454 vscrinfo.yres, // height 00455 5, // bits per sample 00456 2, // samles per pixel 00457 bytesPerPixel); // bytes per pixel 00458 00459 #ifdef HAVE_RFBSETPROTOCOLVERSION 00460 #ifdef HAVE_STRUCT_RFBSCREEN_PERMITFILETRANSFER 00461 /* 00462 * UltraVNC 1.0.2 win32 00463 * uses the rfb version to identify that it is talking 00464 * to an UltraVNC compatible server. 00465 * This is technically wrong to assume this as the rfb 00466 * version identifies the rfb handshake and not the 00467 * supported messages ... 00468 */ 00469 rfbSetProtocolVersion(rfbScreen, 3, 6); 00470 #endif 00471 #endif 00472 00473 rfbScreen -> desktopName = DESKTOP_NAME; 00474 rfbScreen -> frameBuffer = (char *)rfbbuf; 00475 rfbScreen -> alwaysShared = TRUE; 00476 rfbScreen -> serverFormat.bitsPerPixel = vscrinfo.bits_per_pixel; 00477 00478 // set callback functions 00479 rfbScreen -> ptrAddEvent = ptrevent; // pointer 00480 rfbScreen -> kbdAddEvent = keyevent; // keyboard 00481 rfbScreen -> newClientHook = newclient; // new client 00482 // file transfer permission 00483 #ifdef HAVE_STRUCT_RFBSCREEN_GETFILETRANSFERPERMISSION 00484 rfbScreen -> getFileTransferPermission = getFileTransferPermission; 00485 #endif 00486 #ifdef HAVE_STRUCT_RFBSCREEN_PERMITFILETRANSFER 00487 rfbScreen -> permitFileTransfer = TRUE; 00488 #endif 00489 #ifdef HAVE_RFBREGISTERTIGHTVNCFILETRANSFEREXTENSION 00490 rfbRegisterTightVNCFileTransferExtension(); // register TightVNC file transfer protocol extension(s) 00491 #endif 00492 /* if TRUE, an ignoring signal handler is installed for SIGPIPE */ 00493 rfbScreen -> ignoreSIGPIPE = TRUE; 00494 /* if not zero, only a slice of this height is processed every time 00495 * an update should be sent. This should make working on a slow 00496 * link more interactive. */ 00497 rfbScreen -> progressiveSliceHeight = 0; 00498 00499 if (!vscrinfo.grayscale) { 00500 rfbScreen -> serverFormat.redMax = pow(2,vscrinfo.red.length) -1; 00501 rfbScreen -> serverFormat.greenMax = pow(2,vscrinfo.green.length)-1; 00502 rfbScreen -> serverFormat.blueMax = pow(2,vscrinfo.blue.length) -1; 00503 rfbScreen -> serverFormat.redShift = vscrinfo.red.offset; 00504 rfbScreen -> serverFormat.greenShift = vscrinfo.green.offset; 00505 rfbScreen -> serverFormat.blueShift = vscrinfo.blue.offset; 00506 00507 } // end of [if] 00508 #ifdef HTTP 00509 rfbScreen->httpDir = HTTP; 00510 #endif 00511 00512 rfbInitServer(rfbScreen); // initialize the remote framebuffer & start VNC-Server 00513 rfbRunEventLoop(rfbScreen,-1,TRUE); // non-blocking event loop; a background thread is started 00514 00515 while (1) { 00516 if (rfbScreen -> clientHead != NULL) { // only update the fb if there are connected clients 00517 if (notEqual(fbbuf,cmpfbbuf,compareBufferSize) == 1) { // check if the screen has changed 00518 if (rotate == 0) { rotate0 (rfbScreen,fbbuf,cmpfbbuf); }; // end of [if] 00519 if (rotate == 1) { rotate90 (rfbScreen,fbbuf,cmpfbbuf); }; // end of [if] 00520 if (rotate == 2) { rotate180(rfbScreen,fbbuf,cmpfbbuf); }; // end of [if] 00521 if (rotate == 3) { rotate270(rfbScreen,fbbuf,cmpfbbuf); }; // end of [if] 00522 usleep(5000); 00523 } else { // no screen changes => no update needed 00524 usleep(50000); 00525 }; // end of [if] 00526 } else { // no clients connected @ the moment 00527 sleep(1); 00528 }; 00529 }; // end of [while] 00530 00531 rfbScreenCleanup(rfbScreen); 00532 00533 free(fbbuf); 00534 free(cmpfbbuf); 00535 00536 if (uinput_fd_kbd) dev_uinput_close(uinput_fd_kbd); 00537 if (uinput_fd_mouse) dev_uinput_close(uinput_fd_mouse); 00538 00539 exit (0); 00540 }
Here is the call graph for this function:
void print_usage | ( | char * | arg0 | ) |
Definition at line 194 of file fbvncserver.c.
References DEFAULT_KBD_LAYOUT.
Referenced by main().
00194 { 00195 printf("Usage: %s [options] \n", arg0); 00196 #ifdef DEBUG 00197 printf(" -debug\n"); 00198 #endif 00199 printf("\n"); 00200 printf(" -cw rotate 90 \n"); 00201 printf(" -cw -cw rotate 180 \n"); 00202 printf(" -cw -cw -cw | -ccw rotate 270 \n"); 00203 printf("\n"); 00204 printf(" -keymap <map> name of the keymap to be used for event \n"); 00205 printf(" translation (default: %s) \n", DEFAULT_KBD_LAYOUT); 00206 printf("\n"); 00207 printf("# *** \n"); 00208 printf("# * libVNCServer options (excerpt) \n"); 00209 printf("# **** \n"); 00210 printf(" -rfbport port TCP port for RFB protocol\n"); 00211 printf(" -rfbwait time max time in ms to wait for RFB client\n"); 00212 printf(" -rfbauth passwd-file use authentication on RFB protocol\n"); 00213 printf(" (use 'storepasswd' to create a password file)\n"); 00214 // printf(" -rfbversion 3.x Set the version of the RFB we choose to advertise\n"); 00215 #ifndef HAVE_STRUCT_RFBSCREEN_PERMITFILETRANSFER 00216 // printf(" -permitfiletransfer permit file transfer support\n"); 00218 #endif 00219 printf(" -passwd plain-password use authentication\n"); 00220 printf(" (use plain-password as password, USE AT YOUR RISK)\n"); 00221 printf(" -deferupdate time time in ms to defer updates (default 40)\n"); 00222 printf(" -deferptrupdate time time in ms to defer pointer updates (default none)\n"); 00223 // printf(" -desktop name VNC desktop name\n"); 00224 // printf(" -alwaysshared always treat new clients as shared\n"); 00225 // printf(" -nevershared never treat new clients as shared\n"); 00226 // printf(" -dontdisconnect don't disconnect existing clients when a new non-shared\n"); 00227 // printf(" connection comes in (refuse new connection instead)\n"); 00228 // printf(" -httpdir dir-path enable http server using dir-path home\n"); 00229 // printf(" -httpport portnum use portnum for http connection\n"); 00230 // printf(" -enablehttpproxy enable http proxy support\n"); 00231 printf(" -progressive height enable progressive updating for slow links\n"); 00232 printf("\n"); 00233 #ifndef HAVE_STRUCT_RFBSCREEN_PERMITFILETRANSFER 00234 printf(" -disablefiletransfer disable file transfer (tight)\n"); 00235 printf(" -ftproot string set ftp root (tight)\n"); 00236 printf("\n"); 00237 #endif 00238 printf("# *** \n"); 00239 printf("# * additional info (build option(s) used) \n"); 00240 printf("# **** \n"); 00241 #ifndef DEBUG 00242 printf(" [I]: release build (-debug not supported)\n"); 00243 #endif 00244 #ifdef HTTP 00245 printf(" [I]: http connections to port 5800 supported\n"); 00246 #else 00247 printf(" [I]: http connections NOT supported \n"); 00248 #endif 00249 00250 #ifndef HAVE_STRUCT_RFBSCREEN_PERMITFILETRANSFER 00251 printf(" [I]: ultra-file transfer NOT supported \n"); 00252 #else 00253 printf(" [I]: ultra-file transfer supported \n"); 00254 #endif 00255 00256 #ifndef HAVE_RFBREGISTERTIGHTVNCFILETRANSFEREXTENSION 00257 printf(" [I]: tight-file transfer NOT supported \n "); 00258 #else 00259 printf(" [I]: tight-file transfer supported \n "); 00260 #endif 00261 printf("\n"); 00262 } // end of [print_usage]
void ptrevent | ( | int | buttonMask, | |
int | x, | |||
int | y, | |||
rfbClientPtr | cl | |||
) |
Event-Handler for remote pointer events
Definition at line 92 of file fbvncserver.c.
References button_click(), dev_uinput_sync(), emit_touchscreen_sequence(), ptr_abs(), and TRACE4.
Referenced by main().
00093 { 00094 00095 ARTIFICIAL_TS_EVENT touchscreen_sequence[5]; 00096 int i, buffer = 0; 00097 if ((x < 0 ) || 00098 (y < 0 ) || 00099 (x > cl -> screen -> width) || 00100 (y > cl -> screen -> height)) { 00101 TRACE4(" [W] ptrevent() - invalid ts event (x: %d, y: %d [%3d,%3d]) \n", 00102 cl -> screen -> width, 00103 cl -> screen -> height, 00104 x,y); 00105 return; 00106 }; 00107 00108 switch (rotate) { 00109 case 0: break; 00110 case 1: break; 00111 case 2: break; 00112 case 3: 00113 buffer = x; 00114 x = -y + (cl -> screen -> height); 00115 y = buffer; 00116 break; 00117 default: ; 00118 } 00119 00120 if(buttonMask!=0) { 00121 for(i=0;i<(last_pen_down?1:5);i++) { 00122 touchscreen_sequence[i].x=x; 00123 touchscreen_sequence[i].y=y; 00124 touchscreen_sequence[i].pressure=1; 00125 } 00126 touchscreen_sequence[i].x=-1; 00127 rfbLog ( " pointer event @ x: %d, y:%d (down) \n", x, y); 00128 if (uinput_fd_mouse && uinput) { 00129 ptr_abs(uinput_fd_mouse,x,y); 00130 button_click(uinput_fd_mouse,1); 00131 dev_uinput_sync(uinput_fd_mouse); 00132 rfbLog (" => sent to uinput. \n"); 00133 00134 } else { 00135 emit_touchscreen_sequence(touchscreen_sequence); 00136 }; 00137 } else { 00138 if(last_pen_down) { 00139 touchscreen_sequence[0].x=x; 00140 touchscreen_sequence[0].y=y; 00141 touchscreen_sequence[0].pressure=0; 00142 touchscreen_sequence[1].x=-1; 00143 00144 rfbLog (" pointer event @ x: %d, y:%d (up) \n", x, y); 00145 if (uinput_fd_mouse && uinput) { 00146 ptr_abs(uinput_fd_mouse,x,y); 00147 button_click(uinput_fd_mouse,0); 00148 dev_uinput_sync(uinput_fd_mouse); 00149 rfbLog (" => sent to uinput. \n"); 00150 00151 } else { 00152 emit_touchscreen_sequence(touchscreen_sequence); 00153 }; 00154 }; 00155 }; 00156 last_pen_down=(buttonMask!=0); 00157 return; 00158 }
Here is the call graph for this function:
unsigned short int * cmpfbbuf = NULL |
unsigned short int* fbbuf = NULL |
struct kbd_layout_t* kbd_layout = NULL |
unsigned short int * rfbbuf = NULL |
struct fb_var_screeninfo vscrinfo |