xref: /kvmtool/ui/sdl.c (revision 175f8e86a188a573b6e058133b189d09ea41343e)
13f838fecSPekka Enberg #include "kvm/sdl.h"
23f838fecSPekka Enberg 
33f838fecSPekka Enberg #include "kvm/framebuffer.h"
4*175f8e86SPekka Enberg #include "kvm/i8042.h"
53f838fecSPekka Enberg #include "kvm/util.h"
63f838fecSPekka Enberg 
73f838fecSPekka Enberg #include <SDL/SDL.h>
83f838fecSPekka Enberg #include <pthread.h>
93f838fecSPekka Enberg 
103f838fecSPekka Enberg #define FRAME_RATE		25
113f838fecSPekka Enberg 
123f838fecSPekka Enberg static void sdl__write(struct framebuffer *fb, u64 addr, u8 *data, u32 len)
133f838fecSPekka Enberg {
143f838fecSPekka Enberg 	memcpy(&fb->mem[addr - fb->mem_addr], data, len);
153f838fecSPekka Enberg }
163f838fecSPekka Enberg 
17*175f8e86SPekka Enberg static u8 keymap[255] = {
18*175f8e86SPekka Enberg 	[10]		= 0x16,		/* 1 */
19*175f8e86SPekka Enberg 	[11]		= 0x1e,		/* 2 */
20*175f8e86SPekka Enberg 	[12]		= 0x26,		/* 3 */
21*175f8e86SPekka Enberg 	[13]		= 0x25,		/* 4 */
22*175f8e86SPekka Enberg 	[14]		= 0x27,		/* 5 */
23*175f8e86SPekka Enberg 	[15]		= 0x36,		/* 6 */
24*175f8e86SPekka Enberg 	[16]		= 0x3d,		/* 7 */
25*175f8e86SPekka Enberg 	[17]		= 0x3e,		/* 8 */
26*175f8e86SPekka Enberg 	[18]		= 0x46,		/* 9 */
27*175f8e86SPekka Enberg 	[19]		= 0x45,		/* 9 */
28*175f8e86SPekka Enberg 
29*175f8e86SPekka Enberg 	[22]		= 0x66,		/* <backspace> */
30*175f8e86SPekka Enberg 
31*175f8e86SPekka Enberg 	[24]		= 0x15,		/* q */
32*175f8e86SPekka Enberg 	[25]		= 0x1d,		/* w */
33*175f8e86SPekka Enberg 	[26]		= 0x24,		/* e */
34*175f8e86SPekka Enberg 	[27]		= 0x2d,		/* r */
35*175f8e86SPekka Enberg 	[28]		= 0x2c,		/* t */
36*175f8e86SPekka Enberg 	[29]		= 0x35,		/* y */
37*175f8e86SPekka Enberg 	[30]		= 0x3c,		/* u */
38*175f8e86SPekka Enberg 	[31]		= 0x43,		/* i */
39*175f8e86SPekka Enberg 	[32]		= 0x44,		/* o */
40*175f8e86SPekka Enberg 	[33]		= 0x4d,		/* p */
41*175f8e86SPekka Enberg 
42*175f8e86SPekka Enberg 	[36]		= 0x5a,		/* <enter> */
43*175f8e86SPekka Enberg 
44*175f8e86SPekka Enberg 	[38]		= 0x1c,		/* a */
45*175f8e86SPekka Enberg 	[39]		= 0x1b,		/* s */
46*175f8e86SPekka Enberg 	[40]		= 0x23,		/* d */
47*175f8e86SPekka Enberg 	[41]		= 0x2b,		/* f */
48*175f8e86SPekka Enberg 	[42]		= 0x34,		/* g */
49*175f8e86SPekka Enberg 	[43]		= 0x33,		/* h */
50*175f8e86SPekka Enberg 	[44]		= 0x3b,		/* j */
51*175f8e86SPekka Enberg 	[45]		= 0x42,		/* k */
52*175f8e86SPekka Enberg 	[46]		= 0x4b,		/* l */
53*175f8e86SPekka Enberg 
54*175f8e86SPekka Enberg 	[50]		= 0x12,		/* <left shift> */
55*175f8e86SPekka Enberg 
56*175f8e86SPekka Enberg 	[52]		= 0x1a,		/* z */
57*175f8e86SPekka Enberg 	[53]		= 0x22,		/* x */
58*175f8e86SPekka Enberg 	[54]		= 0x21,		/* c */
59*175f8e86SPekka Enberg 	[55]		= 0x2a,		/* v */
60*175f8e86SPekka Enberg 	[56]		= 0x32,		/* b */
61*175f8e86SPekka Enberg 	[57]		= 0x31,		/* n */
62*175f8e86SPekka Enberg 	[58]		= 0x3a,		/* m */
63*175f8e86SPekka Enberg 
64*175f8e86SPekka Enberg 	[61]		= 0x4e,		/* - */
65*175f8e86SPekka Enberg 	[62]		= 0x59,		/* <right shift> */
66*175f8e86SPekka Enberg 	[65]		= 0x29,		/* <space> */
67*175f8e86SPekka Enberg };
68*175f8e86SPekka Enberg 
69*175f8e86SPekka Enberg static u8 to_code(u8 scancode)
70*175f8e86SPekka Enberg {
71*175f8e86SPekka Enberg 	return keymap[scancode];
72*175f8e86SPekka Enberg }
73*175f8e86SPekka Enberg 
743f838fecSPekka Enberg static void *sdl__thread(void *p)
753f838fecSPekka Enberg {
763f838fecSPekka Enberg 	Uint32 rmask, gmask, bmask, amask;
773f838fecSPekka Enberg 	struct framebuffer *fb = p;
783f838fecSPekka Enberg 	SDL_Surface *guest_screen;
793f838fecSPekka Enberg 	SDL_Surface *screen;
803f838fecSPekka Enberg 	SDL_Event ev;
813f838fecSPekka Enberg 	Uint32 flags;
823f838fecSPekka Enberg 
833f838fecSPekka Enberg 	if (SDL_Init(SDL_INIT_VIDEO) != 0)
843f838fecSPekka Enberg 		die("Unable to initialize SDL");
853f838fecSPekka Enberg 
863f838fecSPekka Enberg 	rmask = 0x000000ff;
873f838fecSPekka Enberg 	gmask = 0x0000ff00;
883f838fecSPekka Enberg 	bmask = 0x00ff0000;
893f838fecSPekka Enberg 	amask = 0x00000000;
903f838fecSPekka Enberg 
913f838fecSPekka Enberg 	guest_screen = SDL_CreateRGBSurfaceFrom(fb->mem, fb->width, fb->height, fb->depth, fb->width * fb->depth / 8, rmask, gmask, bmask, amask);
923f838fecSPekka Enberg 	if (!guest_screen)
933f838fecSPekka Enberg 		die("Unable to create SDL RBG surface");
943f838fecSPekka Enberg 
953f838fecSPekka Enberg 	flags = SDL_HWSURFACE | SDL_ASYNCBLIT | SDL_HWACCEL;
963f838fecSPekka Enberg 
973f838fecSPekka Enberg 	screen = SDL_SetVideoMode(fb->width, fb->height, fb->depth, flags);
983f838fecSPekka Enberg 	if (!screen)
993f838fecSPekka Enberg 		die("Unable to set SDL video mode");
1003f838fecSPekka Enberg 
1013f838fecSPekka Enberg 	for (;;) {
1023f838fecSPekka Enberg 		SDL_BlitSurface(guest_screen, NULL, screen, NULL);
1033f838fecSPekka Enberg 		SDL_UpdateRect(screen, 0, 0, 0, 0);
104*175f8e86SPekka Enberg 
1053f838fecSPekka Enberg 		while (SDL_PollEvent(&ev)) {
1063f838fecSPekka Enberg 			switch (ev.type) {
107*175f8e86SPekka Enberg 			case SDL_KEYDOWN: {
108*175f8e86SPekka Enberg 				u8 code = to_code(ev.key.keysym.scancode);
109*175f8e86SPekka Enberg 				if (code)
110*175f8e86SPekka Enberg 					kbd_queue(code);
111*175f8e86SPekka Enberg 				else
112*175f8e86SPekka Enberg 					pr_warning("key '%d' not found in keymap", ev.key.keysym.scancode);
113*175f8e86SPekka Enberg 				break;
114*175f8e86SPekka Enberg 			}
115*175f8e86SPekka Enberg 			case SDL_KEYUP: {
116*175f8e86SPekka Enberg 				u8 code = to_code(ev.key.keysym.scancode);
117*175f8e86SPekka Enberg 				if (code) {
118*175f8e86SPekka Enberg 					kbd_queue(0xf0);
119*175f8e86SPekka Enberg 					kbd_queue(code);
120*175f8e86SPekka Enberg 				}
121*175f8e86SPekka Enberg 				break;
122*175f8e86SPekka Enberg 			}
1233f838fecSPekka Enberg 			case SDL_QUIT:
1243f838fecSPekka Enberg 				goto exit;
1253f838fecSPekka Enberg 			}
1263f838fecSPekka Enberg 		}
127*175f8e86SPekka Enberg 
1283f838fecSPekka Enberg 		SDL_Delay(1000 / FRAME_RATE);
1293f838fecSPekka Enberg 	}
1303f838fecSPekka Enberg exit:
1313f838fecSPekka Enberg 	return NULL;
1323f838fecSPekka Enberg }
1333f838fecSPekka Enberg 
1343f838fecSPekka Enberg static int sdl__start(struct framebuffer *fb)
1353f838fecSPekka Enberg {
1363f838fecSPekka Enberg 	pthread_t thread;
1373f838fecSPekka Enberg 
1383f838fecSPekka Enberg 	if (pthread_create(&thread, NULL, sdl__thread, fb) != 0)
1393f838fecSPekka Enberg 		return -1;
1403f838fecSPekka Enberg 
1413f838fecSPekka Enberg 	return 0;
1423f838fecSPekka Enberg }
1433f838fecSPekka Enberg 
1443f838fecSPekka Enberg static struct fb_target_operations sdl_ops = {
1453f838fecSPekka Enberg 	.start			= sdl__start,
1463f838fecSPekka Enberg 	.write			= sdl__write,
1473f838fecSPekka Enberg };
1483f838fecSPekka Enberg 
1493f838fecSPekka Enberg void sdl__init(struct framebuffer *fb)
1503f838fecSPekka Enberg {
1513f838fecSPekka Enberg 	fb__attach(fb, &sdl_ops);
1523f838fecSPekka Enberg }
153