xref: /kvmtool/ui/sdl.c (revision 2a77516ba8fb4541cb1ff730c8f5df888314c47e)
13f838fecSPekka Enberg #include "kvm/sdl.h"
23f838fecSPekka Enberg 
33f838fecSPekka Enberg #include "kvm/framebuffer.h"
4175f8e86SPekka Enberg #include "kvm/i8042.h"
53f838fecSPekka Enberg #include "kvm/util.h"
61c48f5f8SPekka Enberg #include "kvm/kvm.h"
73f838fecSPekka Enberg 
83f838fecSPekka Enberg #include <SDL/SDL.h>
93f838fecSPekka Enberg #include <pthread.h>
101c48f5f8SPekka Enberg #include <signal.h>
113f838fecSPekka Enberg 
123f838fecSPekka Enberg #define FRAME_RATE		25
133f838fecSPekka Enberg 
14175f8e86SPekka Enberg static u8 keymap[255] = {
15175f8e86SPekka Enberg 	[10]		= 0x16,		/* 1 */
16175f8e86SPekka Enberg 	[11]		= 0x1e,		/* 2 */
17175f8e86SPekka Enberg 	[12]		= 0x26,		/* 3 */
18175f8e86SPekka Enberg 	[13]		= 0x25,		/* 4 */
19175f8e86SPekka Enberg 	[14]		= 0x27,		/* 5 */
20175f8e86SPekka Enberg 	[15]		= 0x36,		/* 6 */
21175f8e86SPekka Enberg 	[16]		= 0x3d,		/* 7 */
22175f8e86SPekka Enberg 	[17]		= 0x3e,		/* 8 */
23175f8e86SPekka Enberg 	[18]		= 0x46,		/* 9 */
24175f8e86SPekka Enberg 	[19]		= 0x45,		/* 9 */
25dada7106SSasha Levin 	[20]		= 0x4e,		/* - */
26dada7106SSasha Levin 	[21]		= 0x55,		/* + */
27175f8e86SPekka Enberg 	[22]		= 0x66,		/* <backspace> */
28175f8e86SPekka Enberg 
29175f8e86SPekka Enberg 	[24]		= 0x15,		/* q */
30175f8e86SPekka Enberg 	[25]		= 0x1d,		/* w */
31175f8e86SPekka Enberg 	[26]		= 0x24,		/* e */
32175f8e86SPekka Enberg 	[27]		= 0x2d,		/* r */
33175f8e86SPekka Enberg 	[28]		= 0x2c,		/* t */
34175f8e86SPekka Enberg 	[29]		= 0x35,		/* y */
35175f8e86SPekka Enberg 	[30]		= 0x3c,		/* u */
36175f8e86SPekka Enberg 	[31]		= 0x43,		/* i */
37175f8e86SPekka Enberg 	[32]		= 0x44,		/* o */
38175f8e86SPekka Enberg 	[33]		= 0x4d,		/* p */
39175f8e86SPekka Enberg 
40175f8e86SPekka Enberg 	[36]		= 0x5a,		/* <enter> */
41175f8e86SPekka Enberg 
42175f8e86SPekka Enberg 	[38]		= 0x1c,		/* a */
43175f8e86SPekka Enberg 	[39]		= 0x1b,		/* s */
44175f8e86SPekka Enberg 	[40]		= 0x23,		/* d */
45175f8e86SPekka Enberg 	[41]		= 0x2b,		/* f */
46175f8e86SPekka Enberg 	[42]		= 0x34,		/* g */
47175f8e86SPekka Enberg 	[43]		= 0x33,		/* h */
48175f8e86SPekka Enberg 	[44]		= 0x3b,		/* j */
49175f8e86SPekka Enberg 	[45]		= 0x42,		/* k */
50175f8e86SPekka Enberg 	[46]		= 0x4b,		/* l */
51175f8e86SPekka Enberg 
52175f8e86SPekka Enberg 	[50]		= 0x12,		/* <left shift> */
53dada7106SSasha Levin 	[51]		= 0x5d,		/* | */
54dada7106SSasha Levin 
55175f8e86SPekka Enberg 
56175f8e86SPekka Enberg 	[52]		= 0x1a,		/* z */
57175f8e86SPekka Enberg 	[53]		= 0x22,		/* x */
58175f8e86SPekka Enberg 	[54]		= 0x21,		/* c */
59175f8e86SPekka Enberg 	[55]		= 0x2a,		/* v */
60175f8e86SPekka Enberg 	[56]		= 0x32,		/* b */
61175f8e86SPekka Enberg 	[57]		= 0x31,		/* n */
62175f8e86SPekka Enberg 	[58]		= 0x3a,		/* m */
63dada7106SSasha Levin 	[59]		= 0x41,		/* < */
64dada7106SSasha Levin 	[60]		= 0x49,		/* > */
65dada7106SSasha Levin 	[61]		= 0x4a,		/* / */
66175f8e86SPekka Enberg 	[62]		= 0x59,		/* <right shift> */
67175f8e86SPekka Enberg 	[65]		= 0x29,		/* <space> */
68175f8e86SPekka Enberg };
69175f8e86SPekka Enberg 
70175f8e86SPekka Enberg static u8 to_code(u8 scancode)
71175f8e86SPekka Enberg {
72175f8e86SPekka Enberg 	return keymap[scancode];
73175f8e86SPekka Enberg }
74175f8e86SPekka Enberg 
753f838fecSPekka Enberg static void *sdl__thread(void *p)
763f838fecSPekka Enberg {
773f838fecSPekka Enberg 	Uint32 rmask, gmask, bmask, amask;
783f838fecSPekka Enberg 	struct framebuffer *fb = p;
793f838fecSPekka Enberg 	SDL_Surface *guest_screen;
803f838fecSPekka Enberg 	SDL_Surface *screen;
813f838fecSPekka Enberg 	SDL_Event ev;
823f838fecSPekka Enberg 	Uint32 flags;
833f838fecSPekka Enberg 
843f838fecSPekka Enberg 	if (SDL_Init(SDL_INIT_VIDEO) != 0)
853f838fecSPekka Enberg 		die("Unable to initialize SDL");
863f838fecSPekka Enberg 
873f838fecSPekka Enberg 	rmask = 0x000000ff;
883f838fecSPekka Enberg 	gmask = 0x0000ff00;
893f838fecSPekka Enberg 	bmask = 0x00ff0000;
903f838fecSPekka Enberg 	amask = 0x00000000;
913f838fecSPekka Enberg 
923f838fecSPekka Enberg 	guest_screen = SDL_CreateRGBSurfaceFrom(fb->mem, fb->width, fb->height, fb->depth, fb->width * fb->depth / 8, rmask, gmask, bmask, amask);
933f838fecSPekka Enberg 	if (!guest_screen)
943f838fecSPekka Enberg 		die("Unable to create SDL RBG surface");
953f838fecSPekka Enberg 
96268d0f1bSSasha Levin 	flags = SDL_HWSURFACE | SDL_ASYNCBLIT | SDL_HWACCEL | SDL_DOUBLEBUF;
973f838fecSPekka Enberg 
98*2a77516bSPekka Enberg 	SDL_WM_SetCaption("KVM tool", "KVM tool");
99*2a77516bSPekka Enberg 
1003f838fecSPekka Enberg 	screen = SDL_SetVideoMode(fb->width, fb->height, fb->depth, flags);
1013f838fecSPekka Enberg 	if (!screen)
1023f838fecSPekka Enberg 		die("Unable to set SDL video mode");
1033f838fecSPekka Enberg 
10468770058SLiming Wang 	SDL_EnableKeyRepeat(200, 50);
10568770058SLiming Wang 
1063f838fecSPekka Enberg 	for (;;) {
1073f838fecSPekka Enberg 		SDL_BlitSurface(guest_screen, NULL, screen, NULL);
108268d0f1bSSasha Levin 		SDL_Flip(screen);
109175f8e86SPekka Enberg 
1103f838fecSPekka Enberg 		while (SDL_PollEvent(&ev)) {
1113f838fecSPekka Enberg 			switch (ev.type) {
112175f8e86SPekka Enberg 			case SDL_KEYDOWN: {
113175f8e86SPekka Enberg 				u8 code = to_code(ev.key.keysym.scancode);
114175f8e86SPekka Enberg 				if (code)
115175f8e86SPekka Enberg 					kbd_queue(code);
116175f8e86SPekka Enberg 				else
117175f8e86SPekka Enberg 					pr_warning("key '%d' not found in keymap", ev.key.keysym.scancode);
118175f8e86SPekka Enberg 				break;
119175f8e86SPekka Enberg 			}
120175f8e86SPekka Enberg 			case SDL_KEYUP: {
121175f8e86SPekka Enberg 				u8 code = to_code(ev.key.keysym.scancode);
122175f8e86SPekka Enberg 				if (code) {
123175f8e86SPekka Enberg 					kbd_queue(0xf0);
124175f8e86SPekka Enberg 					kbd_queue(code);
125175f8e86SPekka Enberg 				}
126175f8e86SPekka Enberg 				break;
127175f8e86SPekka Enberg 			}
1283f838fecSPekka Enberg 			case SDL_QUIT:
1293f838fecSPekka Enberg 				goto exit;
1303f838fecSPekka Enberg 			}
1313f838fecSPekka Enberg 		}
132175f8e86SPekka Enberg 
1333f838fecSPekka Enberg 		SDL_Delay(1000 / FRAME_RATE);
1343f838fecSPekka Enberg 	}
1353f838fecSPekka Enberg exit:
1361c48f5f8SPekka Enberg 	kill(0, SIGKVMSTOP);
1371c48f5f8SPekka Enberg 
1383f838fecSPekka Enberg 	return NULL;
1393f838fecSPekka Enberg }
1403f838fecSPekka Enberg 
1413f838fecSPekka Enberg static int sdl__start(struct framebuffer *fb)
1423f838fecSPekka Enberg {
1433f838fecSPekka Enberg 	pthread_t thread;
1443f838fecSPekka Enberg 
1453f838fecSPekka Enberg 	if (pthread_create(&thread, NULL, sdl__thread, fb) != 0)
1463f838fecSPekka Enberg 		return -1;
1473f838fecSPekka Enberg 
1483f838fecSPekka Enberg 	return 0;
1493f838fecSPekka Enberg }
1503f838fecSPekka Enberg 
1513f838fecSPekka Enberg static struct fb_target_operations sdl_ops = {
1523f838fecSPekka Enberg 	.start			= sdl__start,
1533f838fecSPekka Enberg };
1543f838fecSPekka Enberg 
1553f838fecSPekka Enberg void sdl__init(struct framebuffer *fb)
1563f838fecSPekka Enberg {
1573f838fecSPekka Enberg 	fb__attach(fb, &sdl_ops);
1583f838fecSPekka Enberg }
159