xref: /kvmtool/ui/sdl.c (revision 2a77516ba8fb4541cb1ff730c8f5df888314c47e)
1 #include "kvm/sdl.h"
2 
3 #include "kvm/framebuffer.h"
4 #include "kvm/i8042.h"
5 #include "kvm/util.h"
6 #include "kvm/kvm.h"
7 
8 #include <SDL/SDL.h>
9 #include <pthread.h>
10 #include <signal.h>
11 
12 #define FRAME_RATE		25
13 
14 static u8 keymap[255] = {
15 	[10]		= 0x16,		/* 1 */
16 	[11]		= 0x1e,		/* 2 */
17 	[12]		= 0x26,		/* 3 */
18 	[13]		= 0x25,		/* 4 */
19 	[14]		= 0x27,		/* 5 */
20 	[15]		= 0x36,		/* 6 */
21 	[16]		= 0x3d,		/* 7 */
22 	[17]		= 0x3e,		/* 8 */
23 	[18]		= 0x46,		/* 9 */
24 	[19]		= 0x45,		/* 9 */
25 	[20]		= 0x4e,		/* - */
26 	[21]		= 0x55,		/* + */
27 	[22]		= 0x66,		/* <backspace> */
28 
29 	[24]		= 0x15,		/* q */
30 	[25]		= 0x1d,		/* w */
31 	[26]		= 0x24,		/* e */
32 	[27]		= 0x2d,		/* r */
33 	[28]		= 0x2c,		/* t */
34 	[29]		= 0x35,		/* y */
35 	[30]		= 0x3c,		/* u */
36 	[31]		= 0x43,		/* i */
37 	[32]		= 0x44,		/* o */
38 	[33]		= 0x4d,		/* p */
39 
40 	[36]		= 0x5a,		/* <enter> */
41 
42 	[38]		= 0x1c,		/* a */
43 	[39]		= 0x1b,		/* s */
44 	[40]		= 0x23,		/* d */
45 	[41]		= 0x2b,		/* f */
46 	[42]		= 0x34,		/* g */
47 	[43]		= 0x33,		/* h */
48 	[44]		= 0x3b,		/* j */
49 	[45]		= 0x42,		/* k */
50 	[46]		= 0x4b,		/* l */
51 
52 	[50]		= 0x12,		/* <left shift> */
53 	[51]		= 0x5d,		/* | */
54 
55 
56 	[52]		= 0x1a,		/* z */
57 	[53]		= 0x22,		/* x */
58 	[54]		= 0x21,		/* c */
59 	[55]		= 0x2a,		/* v */
60 	[56]		= 0x32,		/* b */
61 	[57]		= 0x31,		/* n */
62 	[58]		= 0x3a,		/* m */
63 	[59]		= 0x41,		/* < */
64 	[60]		= 0x49,		/* > */
65 	[61]		= 0x4a,		/* / */
66 	[62]		= 0x59,		/* <right shift> */
67 	[65]		= 0x29,		/* <space> */
68 };
69 
70 static u8 to_code(u8 scancode)
71 {
72 	return keymap[scancode];
73 }
74 
75 static void *sdl__thread(void *p)
76 {
77 	Uint32 rmask, gmask, bmask, amask;
78 	struct framebuffer *fb = p;
79 	SDL_Surface *guest_screen;
80 	SDL_Surface *screen;
81 	SDL_Event ev;
82 	Uint32 flags;
83 
84 	if (SDL_Init(SDL_INIT_VIDEO) != 0)
85 		die("Unable to initialize SDL");
86 
87 	rmask = 0x000000ff;
88 	gmask = 0x0000ff00;
89 	bmask = 0x00ff0000;
90 	amask = 0x00000000;
91 
92 	guest_screen = SDL_CreateRGBSurfaceFrom(fb->mem, fb->width, fb->height, fb->depth, fb->width * fb->depth / 8, rmask, gmask, bmask, amask);
93 	if (!guest_screen)
94 		die("Unable to create SDL RBG surface");
95 
96 	flags = SDL_HWSURFACE | SDL_ASYNCBLIT | SDL_HWACCEL | SDL_DOUBLEBUF;
97 
98 	SDL_WM_SetCaption("KVM tool", "KVM tool");
99 
100 	screen = SDL_SetVideoMode(fb->width, fb->height, fb->depth, flags);
101 	if (!screen)
102 		die("Unable to set SDL video mode");
103 
104 	SDL_EnableKeyRepeat(200, 50);
105 
106 	for (;;) {
107 		SDL_BlitSurface(guest_screen, NULL, screen, NULL);
108 		SDL_Flip(screen);
109 
110 		while (SDL_PollEvent(&ev)) {
111 			switch (ev.type) {
112 			case SDL_KEYDOWN: {
113 				u8 code = to_code(ev.key.keysym.scancode);
114 				if (code)
115 					kbd_queue(code);
116 				else
117 					pr_warning("key '%d' not found in keymap", ev.key.keysym.scancode);
118 				break;
119 			}
120 			case SDL_KEYUP: {
121 				u8 code = to_code(ev.key.keysym.scancode);
122 				if (code) {
123 					kbd_queue(0xf0);
124 					kbd_queue(code);
125 				}
126 				break;
127 			}
128 			case SDL_QUIT:
129 				goto exit;
130 			}
131 		}
132 
133 		SDL_Delay(1000 / FRAME_RATE);
134 	}
135 exit:
136 	kill(0, SIGKVMSTOP);
137 
138 	return NULL;
139 }
140 
141 static int sdl__start(struct framebuffer *fb)
142 {
143 	pthread_t thread;
144 
145 	if (pthread_create(&thread, NULL, sdl__thread, fb) != 0)
146 		return -1;
147 
148 	return 0;
149 }
150 
151 static struct fb_target_operations sdl_ops = {
152 	.start			= sdl__start,
153 };
154 
155 void sdl__init(struct framebuffer *fb)
156 {
157 	fb__attach(fb, &sdl_ops);
158 }
159