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 SDL_WM_SetCaption("KVM tool", "KVM tool"); 99 100 screen = SDL_SetVideoMode(fb->width, fb->height, fb->depth, flags); 101 if (!screen) 102 die("Unable to set SDL video mode"); 103 104 SDL_EnableKeyRepeat(200, 50); 105 106 for (;;) { 107 SDL_BlitSurface(guest_screen, NULL, screen, NULL); 108 SDL_Flip(screen); 109 110 while (SDL_PollEvent(&ev)) { 111 switch (ev.type) { 112 case SDL_KEYDOWN: { 113 u8 code = to_code(ev.key.keysym.scancode); 114 if (code) 115 kbd_queue(code); 116 else 117 pr_warning("key '%d' not found in keymap", ev.key.keysym.scancode); 118 break; 119 } 120 case SDL_KEYUP: { 121 u8 code = to_code(ev.key.keysym.scancode); 122 if (code) { 123 kbd_queue(0xf0); 124 kbd_queue(code); 125 } 126 break; 127 } 128 case SDL_QUIT: 129 goto exit; 130 } 131 } 132 133 SDL_Delay(1000 / FRAME_RATE); 134 } 135 exit: 136 kill(0, SIGKVMSTOP); 137 138 return NULL; 139 } 140 141 static int sdl__start(struct framebuffer *fb) 142 { 143 pthread_t thread; 144 145 if (pthread_create(&thread, NULL, sdl__thread, fb) != 0) 146 return -1; 147 148 return 0; 149 } 150 151 static struct fb_target_operations sdl_ops = { 152 .start = sdl__start, 153 }; 154 155 void sdl__init(struct framebuffer *fb) 156 { 157 fb__attach(fb, &sdl_ops); 158 } 159