xref: /kvmtool/ui/sdl.c (revision 2aa76b2616bcace1d668a879d834679dfa00dc8c)
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 #include "kvm/kvm-cpu.h"
8 #include "kvm/vesa.h"
9 
10 #include <SDL/SDL.h>
11 #include <pthread.h>
12 #include <signal.h>
13 #include <linux/err.h>
14 
15 #define FRAME_RATE		25
16 
17 #define SCANCODE_UNKNOWN      0
18 #define SCANCODE_NORMAL       1
19 #define SCANCODE_ESCAPED      2
20 #define SCANCODE_KEY_PAUSE    3
21 #define SCANCODE_KEY_PRNTSCRN 4
22 
23 struct set2_scancode {
24 	u8 code;
25 	u8 type;
26 };
27 
28 #define DEFINE_SC(_code) {\
29 	.code = _code,\
30 	.type = SCANCODE_NORMAL,\
31 }
32 
33 /* escaped scancodes */
34 #define DEFINE_ESC(_code) {\
35 	.code = _code,\
36 	.type = SCANCODE_ESCAPED,\
37 }
38 
39 static const struct set2_scancode keymap[256] = {
40 	[9]	= DEFINE_SC(0x76),	/* <esc> */
41 	[10]	= DEFINE_SC(0x16),	/* 1 */
42 	[11]	= DEFINE_SC(0x1e),	/* 2 */
43 	[12]	= DEFINE_SC(0x26),	/* 3 */
44 	[13]	= DEFINE_SC(0x25),	/* 4 */
45 	[14]	= DEFINE_SC(0x2e),	/* 5 */
46 	[15]	= DEFINE_SC(0x36),	/* 6 */
47 	[16]	= DEFINE_SC(0x3d),	/* 7 */
48 	[17]	= DEFINE_SC(0x3e),	/* 8 */
49 	[18]	= DEFINE_SC(0x46),	/* 9 */
50 	[19]	= DEFINE_SC(0x45),	/* 9 */
51 	[20]	= DEFINE_SC(0x4e),	/* - */
52 	[21]	= DEFINE_SC(0x55),	/* + */
53 	[22]	= DEFINE_SC(0x66),	/* <backspace> */
54 	[23]	= DEFINE_SC(0x0d),	/* <tab> */
55 	[24]	= DEFINE_SC(0x15),	/* q */
56 	[25]	= DEFINE_SC(0x1d),	/* w */
57 	[26]	= DEFINE_SC(0x24),	/* e */
58 	[27]	= DEFINE_SC(0x2d),	/* r */
59 	[28]	= DEFINE_SC(0x2c),	/* t */
60 	[29]	= DEFINE_SC(0x35),	/* y */
61 	[30]	= DEFINE_SC(0x3c),	/* u */
62 	[31]	= DEFINE_SC(0x43),	/* i */
63 	[32]	= DEFINE_SC(0x44),	/* o */
64 	[33]	= DEFINE_SC(0x4d),	/* p */
65 	[34]	= DEFINE_SC(0x54),	/* [ */
66 	[35]	= DEFINE_SC(0x5b),	/* ] */
67 	[36]	= DEFINE_SC(0x5a),	/* <enter> */
68 	[37]	= DEFINE_SC(0x14),	/* <left ctrl> */
69 	[38]	= DEFINE_SC(0x1c),	/* a */
70 	[39]	= DEFINE_SC(0x1b),	/* s */
71 	[40]	= DEFINE_SC(0x23),	/* d */
72 	[41]	= DEFINE_SC(0x2b),	/* f */
73 	[42]	= DEFINE_SC(0x34),	/* g */
74 	[43]	= DEFINE_SC(0x33),	/* h */
75 	[44]	= DEFINE_SC(0x3b),	/* j */
76 	[45]	= DEFINE_SC(0x42),	/* k */
77 	[46]	= DEFINE_SC(0x4b),	/* l */
78 	[47]	= DEFINE_SC(0x4c),	/* ; */
79 	[48]	= DEFINE_SC(0x52),	/* ' */
80 	[49]	= DEFINE_SC(0x0e),	/* ` */
81 	[50]	= DEFINE_SC(0x12),	/* <left shift> */
82 	[51]	= DEFINE_SC(0x5d),	/* \ */
83 	[52]	= DEFINE_SC(0x1a),	/* z */
84 	[53]	= DEFINE_SC(0x22),	/* x */
85 	[54]	= DEFINE_SC(0x21),	/* c */
86 	[55]	= DEFINE_SC(0x2a),	/* v */
87 	[56]	= DEFINE_SC(0x32),	/* b */
88 	[57]	= DEFINE_SC(0x31),	/* n */
89 	[58]	= DEFINE_SC(0x3a),	/* m */
90 	[59]	= DEFINE_SC(0x41),	/* < */
91 	[60]	= DEFINE_SC(0x49),	/* > */
92 	[61]	= DEFINE_SC(0x4a),	/* / */
93 	[62]	= DEFINE_SC(0x59),	/* <right shift> */
94 	[63]	= DEFINE_SC(0x7c),	/* keypad * */
95 	[64]	= DEFINE_SC(0x11),	/* <left alt> */
96 	[65]	= DEFINE_SC(0x29),	/* <space> */
97 
98 	[67]	= DEFINE_SC(0x05),	/* <F1> */
99 	[68]	= DEFINE_SC(0x06),	/* <F2> */
100 	[69]	= DEFINE_SC(0x04),	/* <F3> */
101 	[70]	= DEFINE_SC(0x0c),	/* <F4> */
102 	[71]	= DEFINE_SC(0x03),	/* <F5> */
103 	[72]	= DEFINE_SC(0x0b),	/* <F6> */
104 	[73]	= DEFINE_SC(0x83),	/* <F7> */
105 	[74]	= DEFINE_SC(0x0a),	/* <F8> */
106 	[75]	= DEFINE_SC(0x01),	/* <F9> */
107 	[76]	= DEFINE_SC(0x09),	/* <F10> */
108 
109 	[79]	= DEFINE_SC(0x6c),	/* keypad 7 */
110 	[80]	= DEFINE_SC(0x75),	/* keypad 8 */
111 	[81]	= DEFINE_SC(0x7d),	/* keypad 9 */
112 	[82]	= DEFINE_SC(0x7b),	/* keypad - */
113 	[83]	= DEFINE_SC(0x6b),	/* keypad 4 */
114 	[84]	= DEFINE_SC(0x73),	/* keypad 5 */
115 	[85]	= DEFINE_SC(0x74),	/* keypad 6 */
116 	[86]	= DEFINE_SC(0x79),	/* keypad + */
117 	[87]	= DEFINE_SC(0x69),	/* keypad 1 */
118 	[88]	= DEFINE_SC(0x72),	/* keypad 2 */
119 	[89]	= DEFINE_SC(0x7a),	/* keypad 3 */
120 	[90]	= DEFINE_SC(0x70),	/* keypad 0 */
121 	[91]	= DEFINE_SC(0x71),	/* keypad . */
122 
123 	[94]	= DEFINE_SC(0x61),	/* <INT 1> */
124 	[95]	= DEFINE_SC(0x78),	/* <F11> */
125 	[96]	= DEFINE_SC(0x07),	/* <F12> */
126 
127 	[104]	= DEFINE_ESC(0x5a),	/* keypad <enter> */
128 	[105]	= DEFINE_ESC(0x14),	/* <right ctrl> */
129 	[106]	= DEFINE_ESC(0x4a),	/* keypad / */
130 	[108]	= DEFINE_ESC(0x11),	/* <right alt> */
131 	[110]	= DEFINE_ESC(0x6c),	/* <home> */
132 	[111]	= DEFINE_ESC(0x75),	/* <up> */
133 	[112]	= DEFINE_ESC(0x7d),	/* <pag up> */
134 	[113]	= DEFINE_ESC(0x6b),	/* <left> */
135 	[114]	= DEFINE_ESC(0x74),	/* <right> */
136 	[115]	= DEFINE_ESC(0x69),	/* <end> */
137 	[116]	= DEFINE_ESC(0x72),	/* <down> */
138 	[117]	= DEFINE_ESC(0x7a),	/* <pag down> */
139 	[118]	= DEFINE_ESC(0x70),	/* <ins> */
140 	[119]	= DEFINE_ESC(0x71),	/* <delete> */
141 };
142 static bool running, done;
143 
to_code(u8 scancode)144 static const struct set2_scancode *to_code(u8 scancode)
145 {
146 	return &keymap[scancode];
147 }
148 
key_press(const struct set2_scancode * sc)149 static void key_press(const struct set2_scancode *sc)
150 {
151 	switch (sc->type) {
152 	case SCANCODE_ESCAPED:
153 		kbd_queue(0xe0);
154 		/* fallthrough */
155 	case SCANCODE_NORMAL:
156 		kbd_queue(sc->code);
157 		break;
158 	case SCANCODE_KEY_PAUSE:
159 		kbd_queue(0xe1);
160 		kbd_queue(0x14);
161 		kbd_queue(0x77);
162 		kbd_queue(0xe1);
163 		kbd_queue(0xf0);
164 		kbd_queue(0x14);
165 		kbd_queue(0x77);
166 		break;
167 	case SCANCODE_KEY_PRNTSCRN:
168 		kbd_queue(0xe0);
169 		kbd_queue(0x12);
170 		kbd_queue(0xe0);
171 		kbd_queue(0x7c);
172 		break;
173 	}
174 }
175 
key_release(const struct set2_scancode * sc)176 static void key_release(const struct set2_scancode *sc)
177 {
178 	switch (sc->type) {
179 	case SCANCODE_ESCAPED:
180 		kbd_queue(0xe0);
181 		/* fallthrough */
182 	case SCANCODE_NORMAL:
183 		kbd_queue(0xf0);
184 		kbd_queue(sc->code);
185 		break;
186 	case SCANCODE_KEY_PAUSE:
187 		/* nothing to do */
188 		break;
189 	case SCANCODE_KEY_PRNTSCRN:
190 		kbd_queue(0xe0);
191 		kbd_queue(0xf0);
192 		kbd_queue(0x7c);
193 		kbd_queue(0xe0);
194 		kbd_queue(0xf0);
195 		kbd_queue(0x12);
196 		break;
197 	}
198 }
199 
sdl__thread(void * p)200 static void *sdl__thread(void *p)
201 {
202 	Uint32 rmask, gmask, bmask, amask;
203 	struct framebuffer *fb = p;
204 	SDL_Surface *guest_screen;
205 	SDL_Surface *screen;
206 	SDL_Event ev;
207 	Uint32 flags;
208 
209 	kvm__set_thread_name("kvm-sdl-worker");
210 
211 	if (SDL_Init(SDL_INIT_VIDEO) != 0)
212 		die("Unable to initialize SDL");
213 
214 	rmask = 0x000000ff;
215 	gmask = 0x0000ff00;
216 	bmask = 0x00ff0000;
217 	amask = 0x00000000;
218 
219 	guest_screen = SDL_CreateRGBSurfaceFrom(fb->mem, fb->width, fb->height, fb->depth, fb->width * fb->depth / 8, rmask, gmask, bmask, amask);
220 	if (!guest_screen)
221 		die("Unable to create SDL RBG surface");
222 
223 	flags = SDL_HWSURFACE | SDL_ASYNCBLIT | SDL_HWACCEL | SDL_DOUBLEBUF;
224 
225 	SDL_WM_SetCaption("KVM tool", "KVM tool");
226 
227 	screen = SDL_SetVideoMode(fb->width, fb->height, fb->depth, flags);
228 	if (!screen)
229 		die("Unable to set SDL video mode");
230 
231 	SDL_EnableKeyRepeat(200, 50);
232 
233 	while (running) {
234 		SDL_BlitSurface(guest_screen, NULL, screen, NULL);
235 		SDL_Flip(screen);
236 
237 		while (SDL_PollEvent(&ev)) {
238 			switch (ev.type) {
239 			case SDL_KEYDOWN: {
240 				const struct set2_scancode *sc = to_code(ev.key.keysym.scancode);
241 				if (sc->type == SCANCODE_UNKNOWN) {
242 					pr_warning("key '%d' not found in keymap", ev.key.keysym.scancode);
243 					break;
244 				}
245 				key_press(sc);
246 				break;
247 			}
248 			case SDL_KEYUP: {
249 				const struct set2_scancode *sc = to_code(ev.key.keysym.scancode);
250 				if (sc->type == SCANCODE_UNKNOWN)
251 					break;
252 				key_release(sc);
253 				break;
254 			}
255 			case SDL_QUIT:
256 				goto exit;
257 			}
258 		}
259 
260 		SDL_Delay(1000 / FRAME_RATE);
261 	}
262 
263 	if (running == false && done == false) {
264 		done = true;
265 		return NULL;
266 	}
267 exit:
268 	done = true;
269 	kvm__reboot(fb->kvm);
270 
271 	return NULL;
272 }
273 
sdl__start(struct framebuffer * fb)274 static int sdl__start(struct framebuffer *fb)
275 {
276 	pthread_t thread;
277 
278 	running = true;
279 
280 	if (pthread_create(&thread, NULL, sdl__thread, fb) != 0)
281 		return -1;
282 
283 	return 0;
284 }
285 
sdl__stop(struct framebuffer * fb)286 static int sdl__stop(struct framebuffer *fb)
287 {
288 	running = false;
289 	while (done == false)
290 		sleep(0);
291 
292 	return 0;
293 }
294 
295 static struct fb_target_operations sdl_ops = {
296 	.start	= sdl__start,
297 	.stop	= sdl__stop,
298 };
299 
sdl__init(struct kvm * kvm)300 int sdl__init(struct kvm *kvm)
301 {
302 	struct framebuffer *fb;
303 
304 	if (!kvm->cfg.sdl)
305 		return 0;
306 
307 	fb = vesa__init(kvm);
308 	if (IS_ERR(fb)) {
309 		pr_err("vesa__init() failed with error %ld\n", PTR_ERR(fb));
310 		return PTR_ERR(fb);
311 	}
312 
313 	return fb__attach(fb, &sdl_ops);
314 }
315 dev_init(sdl__init);
316 
sdl__exit(struct kvm * kvm)317 int sdl__exit(struct kvm *kvm)
318 {
319 	if (kvm->cfg.sdl)
320 		return sdl__stop(NULL);
321 
322 	return 0;
323 }
324 dev_exit(sdl__exit);
325