Commit 548df2acc6fcd12169583e7e7e25b33600cc20e7

Authored by ths
1 parent 3ad4bb2d

VMMouse Emulation, by Anthony Liguori.


git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2514 c046a42c-6fe2-441c-8c8c-71466251a162
Makefile.target
... ... @@ -377,7 +377,7 @@ ifeq ($(TARGET_BASE_ARCH), i386)
377 377 VL_OBJS+= ide.o pckbd.o ps2.o vga.o $(SOUND_HW) dma.o $(AUDIODRV)
378 378 VL_OBJS+= fdc.o mc146818rtc.o serial.o i8259.o i8254.o pcspk.o pc.o
379 379 VL_OBJS+= cirrus_vga.o mixeng.o apic.o parallel.o acpi.o piix_pci.o
380   -VL_OBJS+= usb-uhci.o smbus_eeprom.o
  380 +VL_OBJS+= usb-uhci.o smbus_eeprom.o vmmouse.o
381 381 CPPFLAGS += -DHAS_AUDIO
382 382 endif
383 383 ifeq ($(TARGET_BASE_ARCH), ppc)
... ...
hw/pckbd.c
... ... @@ -372,6 +372,9 @@ void i8042_init(int kbd_irq_lvl, int mouse_irq_lvl, uint32_t io_base)
372 372  
373 373 s->kbd = ps2_kbd_init(kbd_update_kbd_irq, s);
374 374 s->mouse = ps2_mouse_init(kbd_update_aux_irq, s);
  375 +#ifdef TARGET_I386
  376 + vmmouse_init(s->mouse);
  377 +#endif
375 378 qemu_register_reset(kbd_reset, s);
376 379 }
377 380  
... ...
hw/ps2.c
... ... @@ -324,6 +324,11 @@ static void ps2_mouse_event(void *opaque,
324 324 }
325 325 }
326 326  
  327 +void ps2_mouse_fake_event(void *opaque)
  328 +{
  329 + ps2_mouse_event(opaque, 1, 0, 0, 0);
  330 +}
  331 +
327 332 void ps2_write_mouse(void *opaque, int val)
328 333 {
329 334 PS2MouseState *s = (PS2MouseState *)opaque;
... ...
hw/vmmouse.c 0 → 100644
  1 +/*
  2 + * QEMU VMMouse emulation
  3 + *
  4 + * Copyright (C) 2007 Anthony Liguori <anthony@codemonkey.ws>
  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 +#include "vl.h"
  25 +
  26 +/* debug only vmmouse */
  27 +//#define DEBUG_VMMOUSE
  28 +
  29 +/* VMMouse Commands */
  30 +#define VMMOUSE_GETVERSION 10
  31 +#define VMMOUSE_DATA 39
  32 +#define VMMOUSE_STATUS 40
  33 +#define VMMOUSE_COMMAND 41
  34 +
  35 +#define VMMOUSE_READ_ID 0x45414552
  36 +#define VMMOUSE_DISABLE 0x000000f5
  37 +#define VMMOUSE_REQUEST_RELATIVE 0x4c455252
  38 +#define VMMOUSE_REQUEST_ABSOLUTE 0x53424152
  39 +
  40 +#define VMMOUSE_QUEUE_SIZE 1024
  41 +
  42 +#define VMMOUSE_MAGIC 0x564D5868
  43 +#define VMMOUSE_VERSION 0x3442554a
  44 +
  45 +#ifdef DEBUG_VMMOUSE
  46 +#define DPRINTF(fmt, ...) printf(fmt, ## __VA_ARGS__)
  47 +#else
  48 +#define DPRINTF(fmt, ...) do { } while (0)
  49 +#endif
  50 +
  51 +typedef struct _VMMouseState
  52 +{
  53 + uint32_t queue[VMMOUSE_QUEUE_SIZE];
  54 + uint16_t nb_queue;
  55 + uint16_t status;
  56 + uint8_t absolute;
  57 + QEMUPutMouseEntry *entry;
  58 + void *ps2_mouse;
  59 +} VMMouseState;
  60 +
  61 +static uint32_t vmmouse_get_version(VMMouseState *s, uint32_t *magic)
  62 +{
  63 + DPRINTF("vmmouse_get_version(%x)\n", *magic);
  64 + *magic = VMMOUSE_MAGIC;
  65 + return VMMOUSE_VERSION;
  66 +}
  67 +
  68 +static uint32_t vmmouse_get_status(VMMouseState *s)
  69 +{
  70 + DPRINTF("vmmouse_get_status()\n");
  71 + return (s->status << 16) | s->nb_queue;
  72 +}
  73 +
  74 +static void vmmouse_mouse_event(void *opaque, int x, int y, int dz, int buttons_state)
  75 +{
  76 + VMMouseState *s = opaque;
  77 + int buttons = 0;
  78 +
  79 + if (s->nb_queue > (VMMOUSE_QUEUE_SIZE - 4))
  80 + return;
  81 +
  82 + DPRINTF("vmmouse_mouse_event(%d, %d, %d, %d)\n",
  83 + x, y, dz, buttons_state);
  84 +
  85 + if ((buttons_state & MOUSE_EVENT_LBUTTON))
  86 + buttons |= 0x20;
  87 + if ((buttons_state & MOUSE_EVENT_RBUTTON))
  88 + buttons |= 0x10;
  89 + if ((buttons_state & MOUSE_EVENT_MBUTTON))
  90 + buttons |= 0x08;
  91 +
  92 + if (s->absolute) {
  93 + x <<= 1;
  94 + y <<= 1;
  95 + }
  96 +
  97 + s->queue[s->nb_queue++] = buttons;
  98 + s->queue[s->nb_queue++] = x;
  99 + s->queue[s->nb_queue++] = y;
  100 + s->queue[s->nb_queue++] = dz;
  101 +
  102 + /* need to still generate PS2 events to notify driver to
  103 + read from queue */
  104 + ps2_mouse_fake_event(s->ps2_mouse);
  105 +}
  106 +
  107 +static void vmmouse_update_handler(VMMouseState *s)
  108 +{
  109 + if (s->entry) {
  110 + qemu_remove_mouse_event_handler(s->entry);
  111 + s->entry = NULL;
  112 + }
  113 + if (s->status == 0)
  114 + s->entry = qemu_add_mouse_event_handler(vmmouse_mouse_event,
  115 + s, s->absolute,
  116 + "vmmouse");
  117 +}
  118 +
  119 +static void vmmouse_read_id(VMMouseState *s)
  120 +{
  121 + DPRINTF("vmmouse_read_id()\n");
  122 +
  123 + if (s->nb_queue == VMMOUSE_QUEUE_SIZE)
  124 + return;
  125 +
  126 + s->queue[s->nb_queue++] = VMMOUSE_VERSION;
  127 + s->status = 0;
  128 + vmmouse_update_handler(s);
  129 +}
  130 +
  131 +static void vmmouse_request_relative(VMMouseState *s)
  132 +{
  133 + DPRINTF("vmmouse_request_relative()\n");
  134 + s->absolute = 0;
  135 + vmmouse_update_handler(s);
  136 +}
  137 +
  138 +static void vmmouse_request_absolute(VMMouseState *s)
  139 +{
  140 + DPRINTF("vmmouse_request_absolute()\n");
  141 + s->absolute = 1;
  142 + vmmouse_update_handler(s);
  143 +}
  144 +
  145 +static void vmmouse_disable(VMMouseState *s)
  146 +{
  147 + DPRINTF("vmmouse_disable()\n");
  148 + s->status = 0xffff;
  149 + vmmouse_update_handler(s);
  150 +}
  151 +
  152 +static void vmmouse_data(VMMouseState *s, uint32_t *data, uint32_t size)
  153 +{
  154 + int i;
  155 +
  156 + DPRINTF("vmmouse_data(%d)\n", size);
  157 +
  158 + if (size == 0 || size > 6 || size > s->nb_queue) {
  159 + printf("vmmouse: driver requested too much data %d\n", size);
  160 + s->status = 0xffff;
  161 + vmmouse_update_handler(s);
  162 + return;
  163 + }
  164 +
  165 + for (i = 0; i < size; i++)
  166 + data[i] = s->queue[i];
  167 +
  168 + s->nb_queue -= size;
  169 + if (s->nb_queue)
  170 + memmove(s->queue, &s->queue[size], sizeof(s->queue[0]) * s->nb_queue);
  171 +}
  172 +
  173 +static void vmmouse_get_data(uint32_t *data)
  174 +{
  175 + CPUState *env = cpu_single_env;
  176 +
  177 + data[0] = env->regs[R_EAX]; data[1] = env->regs[R_EBX];
  178 + data[2] = env->regs[R_ECX]; data[3] = env->regs[R_EDX];
  179 + data[4] = env->regs[R_ESI]; data[5] = env->regs[R_EDI];
  180 +
  181 + DPRINTF("get_data = {%x, %x, %x, %x, %x, %x}\n",
  182 + data[0], data[1], data[2], data[3], data[4], data[5]);
  183 +}
  184 +
  185 +static void vmmouse_set_data(const uint32_t *data)
  186 +{
  187 + CPUState *env = cpu_single_env;
  188 +
  189 + DPRINTF("set_data = {%x, %x, %x, %x, %x, %x}\n",
  190 + data[0], data[1], data[2], data[3], data[4], data[5]);
  191 +
  192 + env->regs[R_EAX] = data[0]; env->regs[R_EBX] = data[1];
  193 + env->regs[R_ECX] = data[2]; env->regs[R_EDX] = data[3];
  194 + env->regs[R_ESI] = data[4]; env->regs[R_EDI] = data[5];
  195 +}
  196 +
  197 +static uint32_t vmmouse_ioport_read(void *opaque, uint32_t addr)
  198 +{
  199 + VMMouseState *s = opaque;
  200 + uint32_t data[6];
  201 + uint16_t command;
  202 +
  203 + vmmouse_get_data(data);
  204 + if (data[0] != VMMOUSE_MAGIC)
  205 + goto error;
  206 +
  207 + command = data[2] & 0xFFFF;
  208 +
  209 + switch (command) {
  210 + case VMMOUSE_GETVERSION:
  211 + data[0] = vmmouse_get_version(s, &data[1]);
  212 + break;
  213 + case VMMOUSE_STATUS:
  214 + data[0] = vmmouse_get_status(s);
  215 + break;
  216 + case VMMOUSE_COMMAND:
  217 + switch (data[1]) {
  218 + case VMMOUSE_DISABLE:
  219 + vmmouse_disable(s);
  220 + break;
  221 + case VMMOUSE_READ_ID:
  222 + vmmouse_read_id(s);
  223 + break;
  224 + case VMMOUSE_REQUEST_RELATIVE:
  225 + vmmouse_request_relative(s);
  226 + break;
  227 + case VMMOUSE_REQUEST_ABSOLUTE:
  228 + vmmouse_request_absolute(s);
  229 + break;
  230 + default:
  231 + printf("vmmouse: unknown command %x\n", data[1]);
  232 + break;
  233 + }
  234 + break;
  235 + case VMMOUSE_DATA:
  236 + vmmouse_data(s, data, data[1]);
  237 + break;
  238 + default:
  239 + printf("vmmouse: unknown command %x\n", command);
  240 + break;
  241 + }
  242 +
  243 +error:
  244 + vmmouse_set_data(data);
  245 + return data[0];
  246 +}
  247 +
  248 +static void vmmouse_save(QEMUFile *f, void *opaque)
  249 +{
  250 + VMMouseState *s = opaque;
  251 + int i;
  252 +
  253 + qemu_put_be32(f, VMMOUSE_QUEUE_SIZE);
  254 + for (i = 0; i < VMMOUSE_QUEUE_SIZE; i++)
  255 + qemu_put_be32s(f, &s->queue[i]);
  256 + qemu_put_be16s(f, &s->nb_queue);
  257 + qemu_put_be16s(f, &s->status);
  258 + qemu_put_8s(f, &s->absolute);
  259 +}
  260 +
  261 +static int vmmouse_load(QEMUFile *f, void *opaque, int version_id)
  262 +{
  263 + VMMouseState *s = opaque;
  264 + int i;
  265 +
  266 + if (version_id != 0)
  267 + return -EINVAL;
  268 +
  269 + if (qemu_get_be32(f) != VMMOUSE_QUEUE_SIZE)
  270 + return -EINVAL;
  271 + for (i = 0; i < VMMOUSE_QUEUE_SIZE; i++)
  272 + qemu_get_be32s(f, &s->queue[i]);
  273 + qemu_get_be16s(f, &s->nb_queue);
  274 + qemu_get_be16s(f, &s->status);
  275 + qemu_get_8s(f, &s->absolute);
  276 +
  277 + vmmouse_update_handler(s);
  278 +
  279 + return 0;
  280 +}
  281 +
  282 +void *vmmouse_init(void *m)
  283 +{
  284 + VMMouseState *s = NULL;
  285 +
  286 + DPRINTF("vmmouse_init\n");
  287 +
  288 + s = qemu_mallocz(sizeof(VMMouseState));
  289 + if (!s)
  290 + return NULL;
  291 +
  292 + s->status = 0xffff;
  293 + s->ps2_mouse = m;
  294 +
  295 + register_ioport_read(0x5658, 1, 4, vmmouse_ioport_read, s);
  296 + register_savevm("vmmouse", 0, 0, vmmouse_save, vmmouse_load, s);
  297 +
  298 + return s;
  299 +}
  300 +
... ...
... ... @@ -1005,6 +1005,8 @@ void pci_pcnet_init(PCIBus *bus, NICInfo *nd, int devfn);
1005 1005 void pcnet_h_reset(void *opaque);
1006 1006 void *lance_init(NICInfo *nd, uint32_t leaddr, void *dma_opaque);
1007 1007  
  1008 +/* vmmouse.c */
  1009 +void *vmmouse_init(void *m);
1008 1010  
1009 1011 /* pckbd.c */
1010 1012  
... ... @@ -1326,6 +1328,7 @@ void ps2_write_keyboard(void *, int val);
1326 1328 uint32_t ps2_read_data(void *);
1327 1329 void ps2_queue(void *, int b);
1328 1330 void ps2_keyboard_set_translation(void *opaque, int mode);
  1331 +void ps2_mouse_fake_event(void *opaque);
1329 1332  
1330 1333 /* smc91c111.c */
1331 1334 void smc91c111_init(NICInfo *, uint32_t, void *, int);
... ...