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