1*aba1efa5SPekka Enberg #include "kvm/vnc.h" 2*aba1efa5SPekka Enberg 3*aba1efa5SPekka Enberg #include "kvm/framebuffer.h" 4*aba1efa5SPekka Enberg #include "kvm/i8042.h" 5*aba1efa5SPekka Enberg 6*aba1efa5SPekka Enberg #include <linux/types.h> 7*aba1efa5SPekka Enberg #include <rfb/rfb.h> 8*aba1efa5SPekka Enberg #include <pthread.h> 9*aba1efa5SPekka Enberg 10*aba1efa5SPekka Enberg #define VESA_QUEUE_SIZE 128 11*aba1efa5SPekka Enberg #define VESA_IRQ 14 12*aba1efa5SPekka Enberg 13*aba1efa5SPekka Enberg /* 14*aba1efa5SPekka Enberg * This "6000" value is pretty much the result of experimentation 15*aba1efa5SPekka Enberg * It seems that around this value, things update pretty smoothly 16*aba1efa5SPekka Enberg */ 17*aba1efa5SPekka Enberg #define VESA_UPDATE_TIME 6000 18*aba1efa5SPekka Enberg 19*aba1efa5SPekka Enberg static void vnc__write(struct framebuffer *fb, u64 addr, u8 *data, u32 len) 20*aba1efa5SPekka Enberg { 21*aba1efa5SPekka Enberg memcpy(&fb->mem[addr - fb->mem_addr], data, len); 22*aba1efa5SPekka Enberg } 23*aba1efa5SPekka Enberg 24*aba1efa5SPekka Enberg static void *vnc__thread(void *p) 25*aba1efa5SPekka Enberg { 26*aba1efa5SPekka Enberg struct framebuffer *fb = p; 27*aba1efa5SPekka Enberg /* 28*aba1efa5SPekka Enberg * Make a fake argc and argv because the getscreen function 29*aba1efa5SPekka Enberg * seems to want it. 30*aba1efa5SPekka Enberg */ 31*aba1efa5SPekka Enberg char argv[1][1] = {{0}}; 32*aba1efa5SPekka Enberg int argc = 1; 33*aba1efa5SPekka Enberg 34*aba1efa5SPekka Enberg rfbScreenInfoPtr server; 35*aba1efa5SPekka Enberg 36*aba1efa5SPekka Enberg server = rfbGetScreen(&argc, (char **) argv, fb->width, fb->height, 8, 3, 4); 37*aba1efa5SPekka Enberg server->frameBuffer = fb->mem; 38*aba1efa5SPekka Enberg server->alwaysShared = TRUE; 39*aba1efa5SPekka Enberg server->kbdAddEvent = kbd_handle_key; 40*aba1efa5SPekka Enberg server->ptrAddEvent = kbd_handle_ptr; 41*aba1efa5SPekka Enberg rfbInitServer(server); 42*aba1efa5SPekka Enberg 43*aba1efa5SPekka Enberg while (rfbIsActive(server)) { 44*aba1efa5SPekka Enberg rfbMarkRectAsModified(server, 0, 0, fb->width, fb->height); 45*aba1efa5SPekka Enberg rfbProcessEvents(server, server->deferUpdateTime * VESA_UPDATE_TIME); 46*aba1efa5SPekka Enberg } 47*aba1efa5SPekka Enberg return NULL; 48*aba1efa5SPekka Enberg } 49*aba1efa5SPekka Enberg 50*aba1efa5SPekka Enberg static int vnc__start(struct framebuffer *fb) 51*aba1efa5SPekka Enberg { 52*aba1efa5SPekka Enberg pthread_t thread; 53*aba1efa5SPekka Enberg 54*aba1efa5SPekka Enberg if (pthread_create(&thread, NULL, vnc__thread, fb) != 0) 55*aba1efa5SPekka Enberg return -1; 56*aba1efa5SPekka Enberg 57*aba1efa5SPekka Enberg return 0; 58*aba1efa5SPekka Enberg } 59*aba1efa5SPekka Enberg 60*aba1efa5SPekka Enberg static struct fb_target_operations vnc_ops = { 61*aba1efa5SPekka Enberg .start = vnc__start, 62*aba1efa5SPekka Enberg .write = vnc__write, 63*aba1efa5SPekka Enberg }; 64*aba1efa5SPekka Enberg 65*aba1efa5SPekka Enberg void vnc__init(struct framebuffer *fb) 66*aba1efa5SPekka Enberg { 67*aba1efa5SPekka Enberg fb__attach(fb, &vnc_ops); 68*aba1efa5SPekka Enberg } 69