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"
7f9911ebaSSasha Levin #include "kvm/kvm-cpu.h"
807d52d77SSasha Levin #include "kvm/vesa.h"
93f838fecSPekka Enberg
103f838fecSPekka Enberg #include <SDL/SDL.h>
113f838fecSPekka Enberg #include <pthread.h>
121c48f5f8SPekka Enberg #include <signal.h>
1307d52d77SSasha Levin #include <linux/err.h>
143f838fecSPekka Enberg
153f838fecSPekka Enberg #define FRAME_RATE 25
163f838fecSPekka Enberg
17571cf4baSAlessandro Guido #define SCANCODE_UNKNOWN 0
18571cf4baSAlessandro Guido #define SCANCODE_NORMAL 1
19571cf4baSAlessandro Guido #define SCANCODE_ESCAPED 2
20571cf4baSAlessandro Guido #define SCANCODE_KEY_PAUSE 3
21571cf4baSAlessandro Guido #define SCANCODE_KEY_PRNTSCRN 4
22175f8e86SPekka Enberg
23571cf4baSAlessandro Guido struct set2_scancode {
24571cf4baSAlessandro Guido u8 code;
25571cf4baSAlessandro Guido u8 type;
26175f8e86SPekka Enberg };
27175f8e86SPekka Enberg
28571cf4baSAlessandro Guido #define DEFINE_SC(_code) {\
29571cf4baSAlessandro Guido .code = _code,\
30571cf4baSAlessandro Guido .type = SCANCODE_NORMAL,\
31571cf4baSAlessandro Guido }
32571cf4baSAlessandro Guido
33571cf4baSAlessandro Guido /* escaped scancodes */
34571cf4baSAlessandro Guido #define DEFINE_ESC(_code) {\
35571cf4baSAlessandro Guido .code = _code,\
36571cf4baSAlessandro Guido .type = SCANCODE_ESCAPED,\
37571cf4baSAlessandro Guido }
38571cf4baSAlessandro Guido
39369c27e6SAndre Przywara static const struct set2_scancode keymap[256] = {
40571cf4baSAlessandro Guido [9] = DEFINE_SC(0x76), /* <esc> */
41571cf4baSAlessandro Guido [10] = DEFINE_SC(0x16), /* 1 */
42571cf4baSAlessandro Guido [11] = DEFINE_SC(0x1e), /* 2 */
43571cf4baSAlessandro Guido [12] = DEFINE_SC(0x26), /* 3 */
44571cf4baSAlessandro Guido [13] = DEFINE_SC(0x25), /* 4 */
45a022099dSAlessandro Guido [14] = DEFINE_SC(0x2e), /* 5 */
46571cf4baSAlessandro Guido [15] = DEFINE_SC(0x36), /* 6 */
47571cf4baSAlessandro Guido [16] = DEFINE_SC(0x3d), /* 7 */
48571cf4baSAlessandro Guido [17] = DEFINE_SC(0x3e), /* 8 */
49571cf4baSAlessandro Guido [18] = DEFINE_SC(0x46), /* 9 */
50571cf4baSAlessandro Guido [19] = DEFINE_SC(0x45), /* 9 */
51571cf4baSAlessandro Guido [20] = DEFINE_SC(0x4e), /* - */
52571cf4baSAlessandro Guido [21] = DEFINE_SC(0x55), /* + */
53571cf4baSAlessandro Guido [22] = DEFINE_SC(0x66), /* <backspace> */
54571cf4baSAlessandro Guido [23] = DEFINE_SC(0x0d), /* <tab> */
55571cf4baSAlessandro Guido [24] = DEFINE_SC(0x15), /* q */
56571cf4baSAlessandro Guido [25] = DEFINE_SC(0x1d), /* w */
57571cf4baSAlessandro Guido [26] = DEFINE_SC(0x24), /* e */
58571cf4baSAlessandro Guido [27] = DEFINE_SC(0x2d), /* r */
59571cf4baSAlessandro Guido [28] = DEFINE_SC(0x2c), /* t */
60571cf4baSAlessandro Guido [29] = DEFINE_SC(0x35), /* y */
61571cf4baSAlessandro Guido [30] = DEFINE_SC(0x3c), /* u */
62571cf4baSAlessandro Guido [31] = DEFINE_SC(0x43), /* i */
63571cf4baSAlessandro Guido [32] = DEFINE_SC(0x44), /* o */
64571cf4baSAlessandro Guido [33] = DEFINE_SC(0x4d), /* p */
65571cf4baSAlessandro Guido [34] = DEFINE_SC(0x54), /* [ */
66571cf4baSAlessandro Guido [35] = DEFINE_SC(0x5b), /* ] */
67571cf4baSAlessandro Guido [36] = DEFINE_SC(0x5a), /* <enter> */
68571cf4baSAlessandro Guido [37] = DEFINE_SC(0x14), /* <left ctrl> */
69571cf4baSAlessandro Guido [38] = DEFINE_SC(0x1c), /* a */
70571cf4baSAlessandro Guido [39] = DEFINE_SC(0x1b), /* s */
71571cf4baSAlessandro Guido [40] = DEFINE_SC(0x23), /* d */
72571cf4baSAlessandro Guido [41] = DEFINE_SC(0x2b), /* f */
73571cf4baSAlessandro Guido [42] = DEFINE_SC(0x34), /* g */
74571cf4baSAlessandro Guido [43] = DEFINE_SC(0x33), /* h */
75571cf4baSAlessandro Guido [44] = DEFINE_SC(0x3b), /* j */
76571cf4baSAlessandro Guido [45] = DEFINE_SC(0x42), /* k */
77571cf4baSAlessandro Guido [46] = DEFINE_SC(0x4b), /* l */
78571cf4baSAlessandro Guido [47] = DEFINE_SC(0x4c), /* ; */
79571cf4baSAlessandro Guido [48] = DEFINE_SC(0x52), /* ' */
80571cf4baSAlessandro Guido [49] = DEFINE_SC(0x0e), /* ` */
81571cf4baSAlessandro Guido [50] = DEFINE_SC(0x12), /* <left shift> */
82571cf4baSAlessandro Guido [51] = DEFINE_SC(0x5d), /* \ */
83571cf4baSAlessandro Guido [52] = DEFINE_SC(0x1a), /* z */
84571cf4baSAlessandro Guido [53] = DEFINE_SC(0x22), /* x */
85571cf4baSAlessandro Guido [54] = DEFINE_SC(0x21), /* c */
86571cf4baSAlessandro Guido [55] = DEFINE_SC(0x2a), /* v */
87571cf4baSAlessandro Guido [56] = DEFINE_SC(0x32), /* b */
88571cf4baSAlessandro Guido [57] = DEFINE_SC(0x31), /* n */
89571cf4baSAlessandro Guido [58] = DEFINE_SC(0x3a), /* m */
90571cf4baSAlessandro Guido [59] = DEFINE_SC(0x41), /* < */
91571cf4baSAlessandro Guido [60] = DEFINE_SC(0x49), /* > */
92571cf4baSAlessandro Guido [61] = DEFINE_SC(0x4a), /* / */
93571cf4baSAlessandro Guido [62] = DEFINE_SC(0x59), /* <right shift> */
94571cf4baSAlessandro Guido [63] = DEFINE_SC(0x7c), /* keypad * */
95571cf4baSAlessandro Guido [64] = DEFINE_SC(0x11), /* <left alt> */
96571cf4baSAlessandro Guido [65] = DEFINE_SC(0x29), /* <space> */
97571cf4baSAlessandro Guido
98571cf4baSAlessandro Guido [67] = DEFINE_SC(0x05), /* <F1> */
99571cf4baSAlessandro Guido [68] = DEFINE_SC(0x06), /* <F2> */
100571cf4baSAlessandro Guido [69] = DEFINE_SC(0x04), /* <F3> */
101571cf4baSAlessandro Guido [70] = DEFINE_SC(0x0c), /* <F4> */
102571cf4baSAlessandro Guido [71] = DEFINE_SC(0x03), /* <F5> */
103571cf4baSAlessandro Guido [72] = DEFINE_SC(0x0b), /* <F6> */
104571cf4baSAlessandro Guido [73] = DEFINE_SC(0x83), /* <F7> */
105571cf4baSAlessandro Guido [74] = DEFINE_SC(0x0a), /* <F8> */
106571cf4baSAlessandro Guido [75] = DEFINE_SC(0x01), /* <F9> */
107571cf4baSAlessandro Guido [76] = DEFINE_SC(0x09), /* <F10> */
108571cf4baSAlessandro Guido
109571cf4baSAlessandro Guido [79] = DEFINE_SC(0x6c), /* keypad 7 */
110571cf4baSAlessandro Guido [80] = DEFINE_SC(0x75), /* keypad 8 */
111571cf4baSAlessandro Guido [81] = DEFINE_SC(0x7d), /* keypad 9 */
112571cf4baSAlessandro Guido [82] = DEFINE_SC(0x7b), /* keypad - */
113571cf4baSAlessandro Guido [83] = DEFINE_SC(0x6b), /* keypad 4 */
114571cf4baSAlessandro Guido [84] = DEFINE_SC(0x73), /* keypad 5 */
115571cf4baSAlessandro Guido [85] = DEFINE_SC(0x74), /* keypad 6 */
116571cf4baSAlessandro Guido [86] = DEFINE_SC(0x79), /* keypad + */
117571cf4baSAlessandro Guido [87] = DEFINE_SC(0x69), /* keypad 1 */
118571cf4baSAlessandro Guido [88] = DEFINE_SC(0x72), /* keypad 2 */
119571cf4baSAlessandro Guido [89] = DEFINE_SC(0x7a), /* keypad 3 */
120571cf4baSAlessandro Guido [90] = DEFINE_SC(0x70), /* keypad 0 */
121571cf4baSAlessandro Guido [91] = DEFINE_SC(0x71), /* keypad . */
122571cf4baSAlessandro Guido
123571cf4baSAlessandro Guido [94] = DEFINE_SC(0x61), /* <INT 1> */
124571cf4baSAlessandro Guido [95] = DEFINE_SC(0x78), /* <F11> */
125571cf4baSAlessandro Guido [96] = DEFINE_SC(0x07), /* <F12> */
126571cf4baSAlessandro Guido
127571cf4baSAlessandro Guido [104] = DEFINE_ESC(0x5a), /* keypad <enter> */
128571cf4baSAlessandro Guido [105] = DEFINE_ESC(0x14), /* <right ctrl> */
129571cf4baSAlessandro Guido [106] = DEFINE_ESC(0x4a), /* keypad / */
130571cf4baSAlessandro Guido [108] = DEFINE_ESC(0x11), /* <right alt> */
131571cf4baSAlessandro Guido [110] = DEFINE_ESC(0x6c), /* <home> */
132571cf4baSAlessandro Guido [111] = DEFINE_ESC(0x75), /* <up> */
133571cf4baSAlessandro Guido [112] = DEFINE_ESC(0x7d), /* <pag up> */
134571cf4baSAlessandro Guido [113] = DEFINE_ESC(0x6b), /* <left> */
135571cf4baSAlessandro Guido [114] = DEFINE_ESC(0x74), /* <right> */
136571cf4baSAlessandro Guido [115] = DEFINE_ESC(0x69), /* <end> */
137571cf4baSAlessandro Guido [116] = DEFINE_ESC(0x72), /* <down> */
138571cf4baSAlessandro Guido [117] = DEFINE_ESC(0x7a), /* <pag down> */
139571cf4baSAlessandro Guido [118] = DEFINE_ESC(0x70), /* <ins> */
140571cf4baSAlessandro Guido [119] = DEFINE_ESC(0x71), /* <delete> */
141571cf4baSAlessandro Guido };
14248d9e01aSSasha Levin static bool running, done;
143571cf4baSAlessandro Guido
to_code(u8 scancode)144571cf4baSAlessandro Guido static const struct set2_scancode *to_code(u8 scancode)
145175f8e86SPekka Enberg {
146571cf4baSAlessandro Guido return &keymap[scancode];
147571cf4baSAlessandro Guido }
148571cf4baSAlessandro Guido
key_press(const struct set2_scancode * sc)149571cf4baSAlessandro Guido static void key_press(const struct set2_scancode *sc)
150571cf4baSAlessandro Guido {
151571cf4baSAlessandro Guido switch (sc->type) {
152571cf4baSAlessandro Guido case SCANCODE_ESCAPED:
153571cf4baSAlessandro Guido kbd_queue(0xe0);
154571cf4baSAlessandro Guido /* fallthrough */
155571cf4baSAlessandro Guido case SCANCODE_NORMAL:
156571cf4baSAlessandro Guido kbd_queue(sc->code);
157571cf4baSAlessandro Guido break;
158571cf4baSAlessandro Guido case SCANCODE_KEY_PAUSE:
159571cf4baSAlessandro Guido kbd_queue(0xe1);
160571cf4baSAlessandro Guido kbd_queue(0x14);
161571cf4baSAlessandro Guido kbd_queue(0x77);
162571cf4baSAlessandro Guido kbd_queue(0xe1);
163571cf4baSAlessandro Guido kbd_queue(0xf0);
164571cf4baSAlessandro Guido kbd_queue(0x14);
165571cf4baSAlessandro Guido kbd_queue(0x77);
166571cf4baSAlessandro Guido break;
167571cf4baSAlessandro Guido case SCANCODE_KEY_PRNTSCRN:
168571cf4baSAlessandro Guido kbd_queue(0xe0);
169571cf4baSAlessandro Guido kbd_queue(0x12);
170571cf4baSAlessandro Guido kbd_queue(0xe0);
171571cf4baSAlessandro Guido kbd_queue(0x7c);
172571cf4baSAlessandro Guido break;
173571cf4baSAlessandro Guido }
174571cf4baSAlessandro Guido }
175571cf4baSAlessandro Guido
key_release(const struct set2_scancode * sc)176571cf4baSAlessandro Guido static void key_release(const struct set2_scancode *sc)
177571cf4baSAlessandro Guido {
178571cf4baSAlessandro Guido switch (sc->type) {
179571cf4baSAlessandro Guido case SCANCODE_ESCAPED:
180571cf4baSAlessandro Guido kbd_queue(0xe0);
181571cf4baSAlessandro Guido /* fallthrough */
182571cf4baSAlessandro Guido case SCANCODE_NORMAL:
183571cf4baSAlessandro Guido kbd_queue(0xf0);
184571cf4baSAlessandro Guido kbd_queue(sc->code);
185571cf4baSAlessandro Guido break;
186571cf4baSAlessandro Guido case SCANCODE_KEY_PAUSE:
187571cf4baSAlessandro Guido /* nothing to do */
188571cf4baSAlessandro Guido break;
189571cf4baSAlessandro Guido case SCANCODE_KEY_PRNTSCRN:
190571cf4baSAlessandro Guido kbd_queue(0xe0);
191571cf4baSAlessandro Guido kbd_queue(0xf0);
192571cf4baSAlessandro Guido kbd_queue(0x7c);
193571cf4baSAlessandro Guido kbd_queue(0xe0);
194571cf4baSAlessandro Guido kbd_queue(0xf0);
195571cf4baSAlessandro Guido kbd_queue(0x12);
196571cf4baSAlessandro Guido break;
197571cf4baSAlessandro Guido }
198175f8e86SPekka Enberg }
199175f8e86SPekka Enberg
sdl__thread(void * p)2003f838fecSPekka Enberg static void *sdl__thread(void *p)
2013f838fecSPekka Enberg {
2023f838fecSPekka Enberg Uint32 rmask, gmask, bmask, amask;
2033f838fecSPekka Enberg struct framebuffer *fb = p;
2043f838fecSPekka Enberg SDL_Surface *guest_screen;
2053f838fecSPekka Enberg SDL_Surface *screen;
2063f838fecSPekka Enberg SDL_Event ev;
2073f838fecSPekka Enberg Uint32 flags;
2083f838fecSPekka Enberg
209a4d8c55eSSasha Levin kvm__set_thread_name("kvm-sdl-worker");
210a4d8c55eSSasha Levin
2113f838fecSPekka Enberg if (SDL_Init(SDL_INIT_VIDEO) != 0)
2123f838fecSPekka Enberg die("Unable to initialize SDL");
2133f838fecSPekka Enberg
2143f838fecSPekka Enberg rmask = 0x000000ff;
2153f838fecSPekka Enberg gmask = 0x0000ff00;
2163f838fecSPekka Enberg bmask = 0x00ff0000;
2173f838fecSPekka Enberg amask = 0x00000000;
2183f838fecSPekka Enberg
2193f838fecSPekka Enberg guest_screen = SDL_CreateRGBSurfaceFrom(fb->mem, fb->width, fb->height, fb->depth, fb->width * fb->depth / 8, rmask, gmask, bmask, amask);
2203f838fecSPekka Enberg if (!guest_screen)
2213f838fecSPekka Enberg die("Unable to create SDL RBG surface");
2223f838fecSPekka Enberg
223268d0f1bSSasha Levin flags = SDL_HWSURFACE | SDL_ASYNCBLIT | SDL_HWACCEL | SDL_DOUBLEBUF;
2243f838fecSPekka Enberg
2252a77516bSPekka Enberg SDL_WM_SetCaption("KVM tool", "KVM tool");
2262a77516bSPekka Enberg
2273f838fecSPekka Enberg screen = SDL_SetVideoMode(fb->width, fb->height, fb->depth, flags);
2283f838fecSPekka Enberg if (!screen)
2293f838fecSPekka Enberg die("Unable to set SDL video mode");
2303f838fecSPekka Enberg
23168770058SLiming Wang SDL_EnableKeyRepeat(200, 50);
23268770058SLiming Wang
23348d9e01aSSasha Levin while (running) {
2343f838fecSPekka Enberg SDL_BlitSurface(guest_screen, NULL, screen, NULL);
235268d0f1bSSasha Levin SDL_Flip(screen);
236175f8e86SPekka Enberg
2373f838fecSPekka Enberg while (SDL_PollEvent(&ev)) {
2383f838fecSPekka Enberg switch (ev.type) {
239175f8e86SPekka Enberg case SDL_KEYDOWN: {
240571cf4baSAlessandro Guido const struct set2_scancode *sc = to_code(ev.key.keysym.scancode);
241571cf4baSAlessandro Guido if (sc->type == SCANCODE_UNKNOWN) {
242175f8e86SPekka Enberg pr_warning("key '%d' not found in keymap", ev.key.keysym.scancode);
243175f8e86SPekka Enberg break;
244175f8e86SPekka Enberg }
245571cf4baSAlessandro Guido key_press(sc);
246571cf4baSAlessandro Guido break;
247175f8e86SPekka Enberg }
248571cf4baSAlessandro Guido case SDL_KEYUP: {
249571cf4baSAlessandro Guido const struct set2_scancode *sc = to_code(ev.key.keysym.scancode);
250571cf4baSAlessandro Guido if (sc->type == SCANCODE_UNKNOWN)
251571cf4baSAlessandro Guido break;
252571cf4baSAlessandro Guido key_release(sc);
253175f8e86SPekka Enberg break;
254175f8e86SPekka Enberg }
2553f838fecSPekka Enberg case SDL_QUIT:
2563f838fecSPekka Enberg goto exit;
2573f838fecSPekka Enberg }
2583f838fecSPekka Enberg }
259175f8e86SPekka Enberg
2603f838fecSPekka Enberg SDL_Delay(1000 / FRAME_RATE);
2613f838fecSPekka Enberg }
26248d9e01aSSasha Levin
26348d9e01aSSasha Levin if (running == false && done == false) {
26448d9e01aSSasha Levin done = true;
26548d9e01aSSasha Levin return NULL;
26648d9e01aSSasha Levin }
2673f838fecSPekka Enberg exit:
26861ebda77SLin Ming done = true;
269*2aa76b26SWill Deacon kvm__reboot(fb->kvm);
2701c48f5f8SPekka Enberg
2713f838fecSPekka Enberg return NULL;
2723f838fecSPekka Enberg }
2733f838fecSPekka Enberg
sdl__start(struct framebuffer * fb)2743f838fecSPekka Enberg static int sdl__start(struct framebuffer *fb)
2753f838fecSPekka Enberg {
2763f838fecSPekka Enberg pthread_t thread;
2773f838fecSPekka Enberg
27848d9e01aSSasha Levin running = true;
27948d9e01aSSasha Levin
2803f838fecSPekka Enberg if (pthread_create(&thread, NULL, sdl__thread, fb) != 0)
2813f838fecSPekka Enberg return -1;
2823f838fecSPekka Enberg
2833f838fecSPekka Enberg return 0;
2843f838fecSPekka Enberg }
2853f838fecSPekka Enberg
sdl__stop(struct framebuffer * fb)28648d9e01aSSasha Levin static int sdl__stop(struct framebuffer *fb)
28748d9e01aSSasha Levin {
28848d9e01aSSasha Levin running = false;
28948d9e01aSSasha Levin while (done == false)
29048d9e01aSSasha Levin sleep(0);
29148d9e01aSSasha Levin
29248d9e01aSSasha Levin return 0;
29348d9e01aSSasha Levin }
29448d9e01aSSasha Levin
2953f838fecSPekka Enberg static struct fb_target_operations sdl_ops = {
2963f838fecSPekka Enberg .start = sdl__start,
2978fbd1187SAsias He .stop = sdl__stop,
2983f838fecSPekka Enberg };
2993f838fecSPekka Enberg
sdl__init(struct kvm * kvm)30007d52d77SSasha Levin int sdl__init(struct kvm *kvm)
3013f838fecSPekka Enberg {
30207d52d77SSasha Levin struct framebuffer *fb;
30307d52d77SSasha Levin
30407d52d77SSasha Levin if (!kvm->cfg.sdl)
30507d52d77SSasha Levin return 0;
30607d52d77SSasha Levin
30707d52d77SSasha Levin fb = vesa__init(kvm);
30807d52d77SSasha Levin if (IS_ERR(fb)) {
30907d52d77SSasha Levin pr_err("vesa__init() failed with error %ld\n", PTR_ERR(fb));
31007d52d77SSasha Levin return PTR_ERR(fb);
31107d52d77SSasha Levin }
31207d52d77SSasha Levin
31348d9e01aSSasha Levin return fb__attach(fb, &sdl_ops);
31448d9e01aSSasha Levin }
31549a8afd1SSasha Levin dev_init(sdl__init);
31648d9e01aSSasha Levin
sdl__exit(struct kvm * kvm)31707d52d77SSasha Levin int sdl__exit(struct kvm *kvm)
31848d9e01aSSasha Levin {
31949a8afd1SSasha Levin if (kvm->cfg.sdl)
32007d52d77SSasha Levin return sdl__stop(NULL);
32149a8afd1SSasha Levin
32249a8afd1SSasha Levin return 0;
3233f838fecSPekka Enberg }
32449a8afd1SSasha Levin dev_exit(sdl__exit);
325