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 394c61e7f8SCyrill Gorcunov static const struct set2_scancode const 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 144571cf4baSAlessandro Guido static const struct set2_scancode *to_code(u8 scancode) 145175f8e86SPekka Enberg { 146571cf4baSAlessandro Guido return &keymap[scancode]; 147571cf4baSAlessandro Guido } 148571cf4baSAlessandro Guido 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 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 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 209*a4d8c55eSSasha Levin kvm__set_thread_name("kvm-sdl-worker"); 210*a4d8c55eSSasha 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: 268df4239fbSSasha Levin kvm_cpu__reboot(fb->kvm); 2691c48f5f8SPekka Enberg 2703f838fecSPekka Enberg return NULL; 2713f838fecSPekka Enberg } 2723f838fecSPekka Enberg 2733f838fecSPekka Enberg static int sdl__start(struct framebuffer *fb) 2743f838fecSPekka Enberg { 2753f838fecSPekka Enberg pthread_t thread; 2763f838fecSPekka Enberg 27748d9e01aSSasha Levin running = true; 27848d9e01aSSasha Levin 2793f838fecSPekka Enberg if (pthread_create(&thread, NULL, sdl__thread, fb) != 0) 2803f838fecSPekka Enberg return -1; 2813f838fecSPekka Enberg 2823f838fecSPekka Enberg return 0; 2833f838fecSPekka Enberg } 2843f838fecSPekka Enberg 28548d9e01aSSasha Levin static int sdl__stop(struct framebuffer *fb) 28648d9e01aSSasha Levin { 28748d9e01aSSasha Levin running = false; 28848d9e01aSSasha Levin while (done == false) 28948d9e01aSSasha Levin sleep(0); 29048d9e01aSSasha Levin 29148d9e01aSSasha Levin return 0; 29248d9e01aSSasha Levin } 29348d9e01aSSasha Levin 2943f838fecSPekka Enberg static struct fb_target_operations sdl_ops = { 2953f838fecSPekka Enberg .start = sdl__start, 2968fbd1187SAsias He .stop = sdl__stop, 2973f838fecSPekka Enberg }; 2983f838fecSPekka Enberg 29907d52d77SSasha Levin int sdl__init(struct kvm *kvm) 3003f838fecSPekka Enberg { 30107d52d77SSasha Levin struct framebuffer *fb; 30207d52d77SSasha Levin 30307d52d77SSasha Levin if (!kvm->cfg.sdl) 30407d52d77SSasha Levin return 0; 30507d52d77SSasha Levin 30607d52d77SSasha Levin fb = vesa__init(kvm); 30707d52d77SSasha Levin if (IS_ERR(fb)) { 30807d52d77SSasha Levin pr_err("vesa__init() failed with error %ld\n", PTR_ERR(fb)); 30907d52d77SSasha Levin return PTR_ERR(fb); 31007d52d77SSasha Levin } 31107d52d77SSasha Levin 31248d9e01aSSasha Levin return fb__attach(fb, &sdl_ops); 31348d9e01aSSasha Levin } 31449a8afd1SSasha Levin dev_init(sdl__init); 31548d9e01aSSasha Levin 31607d52d77SSasha Levin int sdl__exit(struct kvm *kvm) 31748d9e01aSSasha Levin { 31849a8afd1SSasha Levin if (kvm->cfg.sdl) 31907d52d77SSasha Levin return sdl__stop(NULL); 32049a8afd1SSasha Levin 32149a8afd1SSasha Levin return 0; 3223f838fecSPekka Enberg } 32349a8afd1SSasha Levin dev_exit(sdl__exit); 324