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 8 #include <SDL/SDL.h> 9 #include <pthread.h> 10 #include <signal.h> 11 12 #define FRAME_RATE 25 13 14 static u8 keymap[255] = { 15 [10] = 0x16, /* 1 */ 16 [11] = 0x1e, /* 2 */ 17 [12] = 0x26, /* 3 */ 18 [13] = 0x25, /* 4 */ 19 [14] = 0x27, /* 5 */ 20 [15] = 0x36, /* 6 */ 21 [16] = 0x3d, /* 7 */ 22 [17] = 0x3e, /* 8 */ 23 [18] = 0x46, /* 9 */ 24 [19] = 0x45, /* 9 */ 25 [20] = 0x4e, /* - */ 26 [21] = 0x55, /* + */ 27 [22] = 0x66, /* <backspace> */ 28 29 [24] = 0x15, /* q */ 30 [25] = 0x1d, /* w */ 31 [26] = 0x24, /* e */ 32 [27] = 0x2d, /* r */ 33 [28] = 0x2c, /* t */ 34 [29] = 0x35, /* y */ 35 [30] = 0x3c, /* u */ 36 [31] = 0x43, /* i */ 37 [32] = 0x44, /* o */ 38 [33] = 0x4d, /* p */ 39 40 [36] = 0x5a, /* <enter> */ 41 42 [38] = 0x1c, /* a */ 43 [39] = 0x1b, /* s */ 44 [40] = 0x23, /* d */ 45 [41] = 0x2b, /* f */ 46 [42] = 0x34, /* g */ 47 [43] = 0x33, /* h */ 48 [44] = 0x3b, /* j */ 49 [45] = 0x42, /* k */ 50 [46] = 0x4b, /* l */ 51 52 [50] = 0x12, /* <left shift> */ 53 [51] = 0x5d, /* | */ 54 55 56 [52] = 0x1a, /* z */ 57 [53] = 0x22, /* x */ 58 [54] = 0x21, /* c */ 59 [55] = 0x2a, /* v */ 60 [56] = 0x32, /* b */ 61 [57] = 0x31, /* n */ 62 [58] = 0x3a, /* m */ 63 [59] = 0x41, /* < */ 64 [60] = 0x49, /* > */ 65 [61] = 0x4a, /* / */ 66 [62] = 0x59, /* <right shift> */ 67 [65] = 0x29, /* <space> */ 68 }; 69 70 static u8 to_code(u8 scancode) 71 { 72 return keymap[scancode]; 73 } 74 75 static void *sdl__thread(void *p) 76 { 77 Uint32 rmask, gmask, bmask, amask; 78 struct framebuffer *fb = p; 79 SDL_Surface *guest_screen; 80 SDL_Surface *screen; 81 SDL_Event ev; 82 Uint32 flags; 83 84 if (SDL_Init(SDL_INIT_VIDEO) != 0) 85 die("Unable to initialize SDL"); 86 87 rmask = 0x000000ff; 88 gmask = 0x0000ff00; 89 bmask = 0x00ff0000; 90 amask = 0x00000000; 91 92 guest_screen = SDL_CreateRGBSurfaceFrom(fb->mem, fb->width, fb->height, fb->depth, fb->width * fb->depth / 8, rmask, gmask, bmask, amask); 93 if (!guest_screen) 94 die("Unable to create SDL RBG surface"); 95 96 flags = SDL_HWSURFACE | SDL_ASYNCBLIT | SDL_HWACCEL | SDL_DOUBLEBUF; 97 98 screen = SDL_SetVideoMode(fb->width, fb->height, fb->depth, flags); 99 if (!screen) 100 die("Unable to set SDL video mode"); 101 102 SDL_EnableKeyRepeat(200, 50); 103 104 for (;;) { 105 SDL_BlitSurface(guest_screen, NULL, screen, NULL); 106 SDL_Flip(screen); 107 108 while (SDL_PollEvent(&ev)) { 109 switch (ev.type) { 110 case SDL_KEYDOWN: { 111 u8 code = to_code(ev.key.keysym.scancode); 112 if (code) 113 kbd_queue(code); 114 else 115 pr_warning("key '%d' not found in keymap", ev.key.keysym.scancode); 116 break; 117 } 118 case SDL_KEYUP: { 119 u8 code = to_code(ev.key.keysym.scancode); 120 if (code) { 121 kbd_queue(0xf0); 122 kbd_queue(code); 123 } 124 break; 125 } 126 case SDL_QUIT: 127 goto exit; 128 } 129 } 130 131 SDL_Delay(1000 / FRAME_RATE); 132 } 133 exit: 134 kill(0, SIGKVMSTOP); 135 136 return NULL; 137 } 138 139 static int sdl__start(struct framebuffer *fb) 140 { 141 pthread_t thread; 142 143 if (pthread_create(&thread, NULL, sdl__thread, fb) != 0) 144 return -1; 145 146 return 0; 147 } 148 149 static struct fb_target_operations sdl_ops = { 150 .start = sdl__start, 151 }; 152 153 void sdl__init(struct framebuffer *fb) 154 { 155 fb__attach(fb, &sdl_ops); 156 } 157