1 #include "kvm/gtk3.h" 2 3 #include "kvm/framebuffer.h" 4 #include "kvm/kvm-cpu.h" 5 #include "kvm/i8042.h" 6 #include "kvm/vesa.h" 7 #include "kvm/kvm.h" 8 9 #include <gtk/gtk.h> 10 #include <pthread.h> 11 #include <linux/err.h> 12 13 #define FRAME_RATE 25 14 15 #define SCANCODE_UNKNOWN 0 16 #define SCANCODE_NORMAL 1 17 #define SCANCODE_ESCAPED 2 18 #define SCANCODE_KEY_PAUSE 3 19 #define SCANCODE_KEY_PRNTSCRN 4 20 21 struct set2_scancode { 22 u8 code; 23 u8 type; 24 }; 25 26 #define DEFINE_SC(_code) { \ 27 .code = _code, \ 28 .type = SCANCODE_NORMAL, \ 29 } 30 31 /* escaped scancodes */ 32 #define DEFINE_ESC(_code) { \ 33 .code = _code, \ 34 .type = SCANCODE_ESCAPED, \ 35 } 36 37 static const struct set2_scancode const keymap[256] = { 38 [9] = DEFINE_SC(0x76), /* <esc> */ 39 [10] = DEFINE_SC(0x16), /* 1 */ 40 [11] = DEFINE_SC(0x1e), /* 2 */ 41 [12] = DEFINE_SC(0x26), /* 3 */ 42 [13] = DEFINE_SC(0x25), /* 4 */ 43 [14] = DEFINE_SC(0x2e), /* 5 */ 44 [15] = DEFINE_SC(0x36), /* 6 */ 45 [16] = DEFINE_SC(0x3d), /* 7 */ 46 [17] = DEFINE_SC(0x3e), /* 8 */ 47 [18] = DEFINE_SC(0x46), /* 9 */ 48 [19] = DEFINE_SC(0x45), /* 9 */ 49 [20] = DEFINE_SC(0x4e), /* - */ 50 [21] = DEFINE_SC(0x55), /* + */ 51 [22] = DEFINE_SC(0x66), /* <backspace> */ 52 [23] = DEFINE_SC(0x0d), /* <tab> */ 53 [24] = DEFINE_SC(0x15), /* q */ 54 [25] = DEFINE_SC(0x1d), /* w */ 55 [26] = DEFINE_SC(0x24), /* e */ 56 [27] = DEFINE_SC(0x2d), /* r */ 57 [28] = DEFINE_SC(0x2c), /* t */ 58 [29] = DEFINE_SC(0x35), /* y */ 59 [30] = DEFINE_SC(0x3c), /* u */ 60 [31] = DEFINE_SC(0x43), /* i */ 61 [32] = DEFINE_SC(0x44), /* o */ 62 [33] = DEFINE_SC(0x4d), /* p */ 63 [34] = DEFINE_SC(0x54), /* [ */ 64 [35] = DEFINE_SC(0x5b), /* ] */ 65 [36] = DEFINE_SC(0x5a), /* <enter> */ 66 [37] = DEFINE_SC(0x14), /* <left ctrl> */ 67 [38] = DEFINE_SC(0x1c), /* a */ 68 [39] = DEFINE_SC(0x1b), /* s */ 69 [40] = DEFINE_SC(0x23), /* d */ 70 [41] = DEFINE_SC(0x2b), /* f */ 71 [42] = DEFINE_SC(0x34), /* g */ 72 [43] = DEFINE_SC(0x33), /* h */ 73 [44] = DEFINE_SC(0x3b), /* j */ 74 [45] = DEFINE_SC(0x42), /* k */ 75 [46] = DEFINE_SC(0x4b), /* l */ 76 [47] = DEFINE_SC(0x4c), /* ; */ 77 [48] = DEFINE_SC(0x52), /* ' */ 78 [49] = DEFINE_SC(0x0e), /* ` */ 79 [50] = DEFINE_SC(0x12), /* <left shift> */ 80 [51] = DEFINE_SC(0x5d), /* \ */ 81 [52] = DEFINE_SC(0x1a), /* z */ 82 [53] = DEFINE_SC(0x22), /* x */ 83 [54] = DEFINE_SC(0x21), /* c */ 84 [55] = DEFINE_SC(0x2a), /* v */ 85 [56] = DEFINE_SC(0x32), /* b */ 86 [57] = DEFINE_SC(0x31), /* n */ 87 [58] = DEFINE_SC(0x3a), /* m */ 88 [59] = DEFINE_SC(0x41), /* < */ 89 [60] = DEFINE_SC(0x49), /* > */ 90 [61] = DEFINE_SC(0x4a), /* / */ 91 [62] = DEFINE_SC(0x59), /* <right shift> */ 92 [63] = DEFINE_SC(0x7c), /* keypad * */ 93 [64] = DEFINE_SC(0x11), /* <left alt> */ 94 [65] = DEFINE_SC(0x29), /* <space> */ 95 96 [67] = DEFINE_SC(0x05), /* <F1> */ 97 [68] = DEFINE_SC(0x06), /* <F2> */ 98 [69] = DEFINE_SC(0x04), /* <F3> */ 99 [70] = DEFINE_SC(0x0c), /* <F4> */ 100 [71] = DEFINE_SC(0x03), /* <F5> */ 101 [72] = DEFINE_SC(0x0b), /* <F6> */ 102 [73] = DEFINE_SC(0x83), /* <F7> */ 103 [74] = DEFINE_SC(0x0a), /* <F8> */ 104 [75] = DEFINE_SC(0x01), /* <F9> */ 105 [76] = DEFINE_SC(0x09), /* <F10> */ 106 107 [79] = DEFINE_SC(0x6c), /* keypad 7 */ 108 [80] = DEFINE_SC(0x75), /* keypad 8 */ 109 [81] = DEFINE_SC(0x7d), /* keypad 9 */ 110 [82] = DEFINE_SC(0x7b), /* keypad - */ 111 [83] = DEFINE_SC(0x6b), /* keypad 4 */ 112 [84] = DEFINE_SC(0x73), /* keypad 5 */ 113 [85] = DEFINE_SC(0x74), /* keypad 6 */ 114 [86] = DEFINE_SC(0x79), /* keypad + */ 115 [87] = DEFINE_SC(0x69), /* keypad 1 */ 116 [88] = DEFINE_SC(0x72), /* keypad 2 */ 117 [89] = DEFINE_SC(0x7a), /* keypad 3 */ 118 [90] = DEFINE_SC(0x70), /* keypad 0 */ 119 [91] = DEFINE_SC(0x71), /* keypad . */ 120 121 [94] = DEFINE_SC(0x61), /* <INT 1> */ 122 [95] = DEFINE_SC(0x78), /* <F11> */ 123 [96] = DEFINE_SC(0x07), /* <F12> */ 124 125 [104] = DEFINE_ESC(0x5a), /* keypad <enter> */ 126 [105] = DEFINE_ESC(0x14), /* <right ctrl> */ 127 [106] = DEFINE_ESC(0x4a), /* keypad / */ 128 [108] = DEFINE_ESC(0x11), /* <right alt> */ 129 [110] = DEFINE_ESC(0x6c), /* <home> */ 130 [111] = DEFINE_ESC(0x75), /* <up> */ 131 [112] = DEFINE_ESC(0x7d), /* <pag up> */ 132 [113] = DEFINE_ESC(0x6b), /* <left> */ 133 [114] = DEFINE_ESC(0x74), /* <right> */ 134 [115] = DEFINE_ESC(0x69), /* <end> */ 135 [116] = DEFINE_ESC(0x72), /* <down> */ 136 [117] = DEFINE_ESC(0x7a), /* <pag down> */ 137 [118] = DEFINE_ESC(0x70), /* <ins> */ 138 [119] = DEFINE_ESC(0x71), /* <delete> */ 139 }; 140 141 static cairo_surface_t *surface; 142 static bool done; 143 144 static const struct set2_scancode *to_code(u8 scancode) 145 { 146 return &keymap[scancode]; 147 } 148 149 static gboolean 150 kvm_gtk_configure_event(GtkWidget * widget, GdkEventConfigure * event, gpointer data) 151 { 152 struct framebuffer *fb = data; 153 int stride; 154 155 if (surface) 156 cairo_surface_destroy(surface); 157 158 stride = cairo_format_stride_for_width(CAIRO_FORMAT_RGB24, fb->width); 159 160 surface = 161 cairo_image_surface_create_for_data((void *) fb->mem, 162 CAIRO_FORMAT_RGB24, 163 fb->width, 164 fb->height, 165 stride); 166 167 return TRUE; 168 } 169 170 static gboolean kvm_gtk_draw(GtkWidget *widget, cairo_t *cr, gpointer data) 171 { 172 cairo_set_source_surface(cr, surface, 0, 0); 173 174 cairo_paint(cr); 175 176 return FALSE; 177 } 178 179 static void kvm_gtk_destroy(void) 180 { 181 if (surface) 182 cairo_surface_destroy(surface); 183 184 gtk_main_quit(); 185 } 186 187 static gboolean kvm_gtk_redraw(GtkWidget * window) 188 { 189 gtk_widget_queue_draw(window); 190 191 return TRUE; 192 } 193 194 static gboolean 195 kvm_gtk_key_press(GtkWidget *widget, GdkEventKey *event, gpointer user_data) 196 { 197 const struct set2_scancode *sc = to_code(event->hardware_keycode); 198 199 switch (sc->type) { 200 case SCANCODE_ESCAPED: 201 kbd_queue(0xe0); 202 /* fallthrough */ 203 case SCANCODE_NORMAL: 204 kbd_queue(sc->code); 205 break; 206 case SCANCODE_KEY_PAUSE: 207 kbd_queue(0xe1); 208 kbd_queue(0x14); 209 kbd_queue(0x77); 210 kbd_queue(0xe1); 211 kbd_queue(0xf0); 212 kbd_queue(0x14); 213 kbd_queue(0x77); 214 break; 215 case SCANCODE_KEY_PRNTSCRN: 216 kbd_queue(0xe0); 217 kbd_queue(0x12); 218 kbd_queue(0xe0); 219 kbd_queue(0x7c); 220 break; 221 } 222 223 return TRUE; 224 } 225 226 static void *kvm_gtk_thread(void *p) 227 { 228 struct framebuffer *fb = p; 229 GtkWidget *window; 230 GtkWidget *frame; 231 GtkWidget *da; 232 233 gtk_init(NULL, NULL); 234 235 window = gtk_window_new(GTK_WINDOW_TOPLEVEL); 236 237 gtk_window_set_title(GTK_WINDOW(window), "VM"); 238 239 g_signal_connect(window, "destroy", G_CALLBACK(kvm_gtk_destroy), NULL); 240 241 gtk_container_set_border_width(GTK_CONTAINER(window), 8); 242 243 frame = gtk_frame_new(NULL); 244 245 gtk_frame_set_shadow_type(GTK_FRAME(frame), GTK_SHADOW_IN); 246 gtk_container_add(GTK_CONTAINER(window), frame); 247 248 da = gtk_drawing_area_new(); 249 250 gtk_widget_set_size_request(da, 100, 100); 251 252 gtk_container_add(GTK_CONTAINER(frame), da); 253 254 g_signal_connect(da, "draw", G_CALLBACK(kvm_gtk_draw), NULL); 255 g_signal_connect(da, "configure-event", 256 G_CALLBACK(kvm_gtk_configure_event), fb); 257 g_signal_connect(G_OBJECT (window), "key_press_event", G_CALLBACK(kvm_gtk_key_press), NULL); 258 259 260 gtk_widget_set_events(da, gtk_widget_get_events(da) 261 | GDK_BUTTON_PRESS_MASK 262 | GDK_POINTER_MOTION_MASK 263 | GDK_POINTER_MOTION_HINT_MASK); 264 265 gtk_widget_show_all(window); 266 267 g_timeout_add(1000 / FRAME_RATE, (GSourceFunc) kvm_gtk_redraw, window); 268 269 gtk_main(); 270 271 done = true; 272 273 return NULL; 274 } 275 276 static int kvm_gtk_start(struct framebuffer *fb) 277 { 278 pthread_t thread; 279 280 if (pthread_create(&thread, NULL, kvm_gtk_thread, fb) != 0) 281 return -1; 282 283 return 0; 284 } 285 286 static int kvm_gtk_stop(struct framebuffer *fb) 287 { 288 gtk_main_quit(); 289 290 while (!done) 291 sleep(0); 292 293 return 0; 294 } 295 296 static struct fb_target_operations kvm_gtk_ops = { 297 .start = kvm_gtk_start, 298 .stop = kvm_gtk_stop, 299 }; 300 301 int kvm_gtk_init(struct kvm *kvm) 302 { 303 struct framebuffer *fb; 304 305 if (!kvm->cfg.gtk) 306 return 0; 307 308 fb = vesa__init(kvm); 309 if (IS_ERR(fb)) { 310 pr_err("vesa__init() failed with error %ld\n", PTR_ERR(fb)); 311 return PTR_ERR(fb); 312 } 313 314 return fb__attach(fb, &kvm_gtk_ops); 315 } 316 317 int kvm_gtk_exit(struct kvm *kvm) 318 { 319 if (kvm->cfg.gtk) 320 return kvm_gtk_stop(NULL); 321 322 return 0; 323 } 324 325 dev_init(kvm_gtk_init); 326 dev_exit(kvm_gtk_exit); 327