xref: /kvmtool/ui/vnc.c (revision aba1efa5fb47776d4212c7626e5013331f550712)
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