1 /* 2 * QEMU System Emulator 3 * 4 * Copyright (c) 2003-2008 Fabrice Bellard 5 * 6 * Permission is hereby granted, free of charge, to any person obtaining a copy 7 * of this software and associated documentation files (the "Software"), to deal 8 * in the Software without restriction, including without limitation the rights 9 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 * copies of the Software, and to permit persons to whom the Software is 11 * furnished to do so, subject to the following conditions: 12 * 13 * The above copyright notice and this permission notice shall be included in 14 * all copies or substantial portions of the Software. 15 * 16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 19 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 * THE SOFTWARE. 23 */ 24 25 #include "sysemu/sysemu.h" 26 #include "monitor/monitor.h" 27 #include "ui/console.h" 28 #include "qapi/error.h" 29 #include "qmp-commands.h" 30 #include "qapi-types.h" 31 #include "ui/keymaps.h" 32 #include "ui/input.h" 33 34 struct QEMUPutMouseEntry { 35 QEMUPutMouseEvent *qemu_put_mouse_event; 36 void *qemu_put_mouse_event_opaque; 37 int qemu_put_mouse_event_absolute; 38 39 /* new input core */ 40 QemuInputHandler h; 41 QemuInputHandlerState *s; 42 int axis[INPUT_AXIS_MAX]; 43 int buttons; 44 }; 45 46 struct QEMUPutKbdEntry { 47 QEMUPutKBDEvent *put_kbd; 48 void *opaque; 49 QemuInputHandlerState *s; 50 }; 51 52 struct QEMUPutLEDEntry { 53 QEMUPutLEDEvent *put_led; 54 void *opaque; 55 QTAILQ_ENTRY(QEMUPutLEDEntry) next; 56 }; 57 58 static QTAILQ_HEAD(, QEMUPutLEDEntry) led_handlers = 59 QTAILQ_HEAD_INITIALIZER(led_handlers); 60 static QTAILQ_HEAD(, QEMUPutMouseEntry) mouse_handlers = 61 QTAILQ_HEAD_INITIALIZER(mouse_handlers); 62 63 int index_from_key(const char *key) 64 { 65 int i; 66 67 for (i = 0; QKeyCode_lookup[i] != NULL; i++) { 68 if (!strcmp(key, QKeyCode_lookup[i])) { 69 break; 70 } 71 } 72 73 /* Return Q_KEY_CODE_MAX if the key is invalid */ 74 return i; 75 } 76 77 static KeyValue **keyvalues; 78 static int keyvalues_size; 79 static QEMUTimer *key_timer; 80 81 static void free_keyvalues(void) 82 { 83 g_free(keyvalues); 84 keyvalues = NULL; 85 keyvalues_size = 0; 86 } 87 88 static void release_keys(void *opaque) 89 { 90 while (keyvalues_size > 0) { 91 qemu_input_event_send_key(NULL, keyvalues[--keyvalues_size], 92 false); 93 } 94 95 free_keyvalues(); 96 } 97 98 static KeyValue *copy_key_value(KeyValue *src) 99 { 100 KeyValue *dst = g_new(KeyValue, 1); 101 memcpy(dst, src, sizeof(*src)); 102 return dst; 103 } 104 105 void qmp_send_key(KeyValueList *keys, bool has_hold_time, int64_t hold_time, 106 Error **errp) 107 { 108 KeyValueList *p; 109 110 if (!key_timer) { 111 key_timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, release_keys, NULL); 112 } 113 114 if (keyvalues != NULL) { 115 timer_del(key_timer); 116 release_keys(NULL); 117 } 118 119 if (!has_hold_time) { 120 hold_time = 100; 121 } 122 123 for (p = keys; p != NULL; p = p->next) { 124 qemu_input_event_send_key(NULL, copy_key_value(p->value), true); 125 126 keyvalues = g_realloc(keyvalues, sizeof(KeyValue *) * 127 (keyvalues_size + 1)); 128 keyvalues[keyvalues_size++] = copy_key_value(p->value); 129 } 130 131 /* delayed key up events */ 132 timer_mod(key_timer, qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) + 133 muldiv64(get_ticks_per_sec(), hold_time, 1000)); 134 } 135 136 static void legacy_kbd_event(DeviceState *dev, QemuConsole *src, 137 InputEvent *evt) 138 { 139 QEMUPutKbdEntry *entry = (QEMUPutKbdEntry *)dev; 140 int scancodes[3], i, count; 141 142 if (!entry || !entry->put_kbd) { 143 return; 144 } 145 count = qemu_input_key_value_to_scancode(evt->key->key, 146 evt->key->down, 147 scancodes); 148 for (i = 0; i < count; i++) { 149 entry->put_kbd(entry->opaque, scancodes[i]); 150 } 151 } 152 153 static QemuInputHandler legacy_kbd_handler = { 154 .name = "legacy-kbd", 155 .mask = INPUT_EVENT_MASK_KEY, 156 .event = legacy_kbd_event, 157 }; 158 159 QEMUPutKbdEntry *qemu_add_kbd_event_handler(QEMUPutKBDEvent *func, void *opaque) 160 { 161 QEMUPutKbdEntry *entry; 162 163 entry = g_new0(QEMUPutKbdEntry, 1); 164 entry->put_kbd = func; 165 entry->opaque = opaque; 166 entry->s = qemu_input_handler_register((DeviceState *)entry, 167 &legacy_kbd_handler); 168 qemu_input_handler_activate(entry->s); 169 return entry; 170 } 171 172 void qemu_remove_kbd_event_handler(QEMUPutKbdEntry *entry) 173 { 174 qemu_input_handler_unregister(entry->s); 175 g_free(entry); 176 } 177 178 static void legacy_mouse_event(DeviceState *dev, QemuConsole *src, 179 InputEvent *evt) 180 { 181 static const int bmap[INPUT_BUTTON_MAX] = { 182 [INPUT_BUTTON_LEFT] = MOUSE_EVENT_LBUTTON, 183 [INPUT_BUTTON_MIDDLE] = MOUSE_EVENT_MBUTTON, 184 [INPUT_BUTTON_RIGHT] = MOUSE_EVENT_RBUTTON, 185 }; 186 QEMUPutMouseEntry *s = (QEMUPutMouseEntry *)dev; 187 188 switch (evt->kind) { 189 case INPUT_EVENT_KIND_BTN: 190 if (evt->btn->down) { 191 s->buttons |= bmap[evt->btn->button]; 192 } else { 193 s->buttons &= ~bmap[evt->btn->button]; 194 } 195 if (evt->btn->down && evt->btn->button == INPUT_BUTTON_WHEEL_UP) { 196 s->qemu_put_mouse_event(s->qemu_put_mouse_event_opaque, 197 s->axis[INPUT_AXIS_X], 198 s->axis[INPUT_AXIS_Y], 199 -1, 200 s->buttons); 201 } 202 if (evt->btn->down && evt->btn->button == INPUT_BUTTON_WHEEL_DOWN) { 203 s->qemu_put_mouse_event(s->qemu_put_mouse_event_opaque, 204 s->axis[INPUT_AXIS_X], 205 s->axis[INPUT_AXIS_Y], 206 1, 207 s->buttons); 208 } 209 break; 210 case INPUT_EVENT_KIND_ABS: 211 s->axis[evt->abs->axis] = evt->abs->value; 212 break; 213 case INPUT_EVENT_KIND_REL: 214 s->axis[evt->rel->axis] += evt->rel->value; 215 break; 216 default: 217 break; 218 } 219 } 220 221 static void legacy_mouse_sync(DeviceState *dev) 222 { 223 QEMUPutMouseEntry *s = (QEMUPutMouseEntry *)dev; 224 225 s->qemu_put_mouse_event(s->qemu_put_mouse_event_opaque, 226 s->axis[INPUT_AXIS_X], 227 s->axis[INPUT_AXIS_Y], 228 0, 229 s->buttons); 230 231 if (!s->qemu_put_mouse_event_absolute) { 232 s->axis[INPUT_AXIS_X] = 0; 233 s->axis[INPUT_AXIS_Y] = 0; 234 } 235 } 236 237 QEMUPutMouseEntry *qemu_add_mouse_event_handler(QEMUPutMouseEvent *func, 238 void *opaque, int absolute, 239 const char *name) 240 { 241 QEMUPutMouseEntry *s; 242 243 s = g_malloc0(sizeof(QEMUPutMouseEntry)); 244 245 s->qemu_put_mouse_event = func; 246 s->qemu_put_mouse_event_opaque = opaque; 247 s->qemu_put_mouse_event_absolute = absolute; 248 249 s->h.name = name; 250 s->h.mask = INPUT_EVENT_MASK_BTN | 251 (absolute ? INPUT_EVENT_MASK_ABS : INPUT_EVENT_MASK_REL); 252 s->h.event = legacy_mouse_event; 253 s->h.sync = legacy_mouse_sync; 254 s->s = qemu_input_handler_register((DeviceState *)s, 255 &s->h); 256 257 return s; 258 } 259 260 void qemu_activate_mouse_event_handler(QEMUPutMouseEntry *entry) 261 { 262 qemu_input_handler_activate(entry->s); 263 } 264 265 void qemu_remove_mouse_event_handler(QEMUPutMouseEntry *entry) 266 { 267 qemu_input_handler_unregister(entry->s); 268 269 g_free(entry); 270 } 271 272 QEMUPutLEDEntry *qemu_add_led_event_handler(QEMUPutLEDEvent *func, 273 void *opaque) 274 { 275 QEMUPutLEDEntry *s; 276 277 s = g_malloc0(sizeof(QEMUPutLEDEntry)); 278 279 s->put_led = func; 280 s->opaque = opaque; 281 QTAILQ_INSERT_TAIL(&led_handlers, s, next); 282 return s; 283 } 284 285 void qemu_remove_led_event_handler(QEMUPutLEDEntry *entry) 286 { 287 if (entry == NULL) 288 return; 289 QTAILQ_REMOVE(&led_handlers, entry, next); 290 g_free(entry); 291 } 292 293 void kbd_put_ledstate(int ledstate) 294 { 295 QEMUPutLEDEntry *cursor; 296 297 QTAILQ_FOREACH(cursor, &led_handlers, next) { 298 cursor->put_led(cursor->opaque, ledstate); 299 } 300 } 301