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 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
to_code(u8 scancode)144 static const struct set2_scancode *to_code(u8 scancode)
145 {
146 return &keymap[scancode];
147 }
148
149 static gboolean
kvm_gtk_configure_event(GtkWidget * widget,GdkEventConfigure * event,gpointer data)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
kvm_gtk_draw(GtkWidget * widget,cairo_t * cr,gpointer data)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
kvm_gtk_destroy(void)179 static void kvm_gtk_destroy(void)
180 {
181 if (surface)
182 cairo_surface_destroy(surface);
183
184 gtk_main_quit();
185 }
186
kvm_gtk_redraw(GtkWidget * window)187 static gboolean kvm_gtk_redraw(GtkWidget * window)
188 {
189 gtk_widget_queue_draw(window);
190
191 return TRUE;
192 }
193
194 static gboolean
kvm_gtk_key_press(GtkWidget * widget,GdkEventKey * event,gpointer user_data)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
kvm_gtk_thread(void * p)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
kvm_gtk_start(struct framebuffer * fb)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
kvm_gtk_stop(struct framebuffer * fb)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
kvm_gtk_init(struct kvm * kvm)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
kvm_gtk_exit(struct kvm * kvm)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