symbian-qemu-0.9.1-12/qemu-symbian-svp/hw/vmmouse.c
changeset 1 2fb8b9db1c86
equal deleted inserted replaced
0:ffa851df0825 1:2fb8b9db1c86
       
     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 "hw.h"
       
    25 #include "console.h"
       
    26 #include "ps2.h"
       
    27 #include "pc.h"
       
    28 
       
    29 /* debug only vmmouse */
       
    30 //#define DEBUG_VMMOUSE
       
    31 
       
    32 /* VMMouse Commands */
       
    33 #define VMMOUSE_GETVERSION	10
       
    34 #define VMMOUSE_DATA		39
       
    35 #define VMMOUSE_STATUS		40
       
    36 #define VMMOUSE_COMMAND		41
       
    37 
       
    38 #define VMMOUSE_READ_ID			0x45414552
       
    39 #define VMMOUSE_DISABLE			0x000000f5
       
    40 #define VMMOUSE_REQUEST_RELATIVE	0x4c455252
       
    41 #define VMMOUSE_REQUEST_ABSOLUTE	0x53424152
       
    42 
       
    43 #define VMMOUSE_QUEUE_SIZE	1024
       
    44 
       
    45 #define VMMOUSE_VERSION		0x3442554a
       
    46 
       
    47 #ifdef DEBUG_VMMOUSE
       
    48 #define DPRINTF(fmt, ...) printf(fmt, ## __VA_ARGS__)
       
    49 #else
       
    50 #define DPRINTF(fmt, ...) do { } while (0)
       
    51 #endif
       
    52 
       
    53 typedef struct _VMMouseState
       
    54 {
       
    55     uint32_t queue[VMMOUSE_QUEUE_SIZE];
       
    56     uint16_t nb_queue;
       
    57     uint16_t status;
       
    58     uint8_t absolute;
       
    59     QEMUPutMouseEntry *entry;
       
    60     void *ps2_mouse;
       
    61 } VMMouseState;
       
    62 
       
    63 static uint32_t vmmouse_get_status(VMMouseState *s)
       
    64 {
       
    65     DPRINTF("vmmouse_get_status()\n");
       
    66     return (s->status << 16) | s->nb_queue;
       
    67 }
       
    68 
       
    69 static void vmmouse_mouse_event(void *opaque, int x, int y, int dz, int buttons_state)
       
    70 {
       
    71     VMMouseState *s = opaque;
       
    72     int buttons = 0;
       
    73 
       
    74     if (s->nb_queue > (VMMOUSE_QUEUE_SIZE - 4))
       
    75         return;
       
    76 
       
    77     DPRINTF("vmmouse_mouse_event(%d, %d, %d, %d)\n",
       
    78             x, y, dz, buttons_state);
       
    79 
       
    80     if ((buttons_state & MOUSE_EVENT_LBUTTON))
       
    81         buttons |= 0x20;
       
    82     if ((buttons_state & MOUSE_EVENT_RBUTTON))
       
    83         buttons |= 0x10;
       
    84     if ((buttons_state & MOUSE_EVENT_MBUTTON))
       
    85         buttons |= 0x08;
       
    86 
       
    87     if (s->absolute) {
       
    88         x <<= 1;
       
    89         y <<= 1;
       
    90     }
       
    91 
       
    92     s->queue[s->nb_queue++] = buttons;
       
    93     s->queue[s->nb_queue++] = x;
       
    94     s->queue[s->nb_queue++] = y;
       
    95     s->queue[s->nb_queue++] = dz;
       
    96 
       
    97     /* need to still generate PS2 events to notify driver to
       
    98        read from queue */
       
    99     ps2_mouse_fake_event(s->ps2_mouse);
       
   100 }
       
   101 
       
   102 static void vmmouse_update_handler(VMMouseState *s)
       
   103 {
       
   104     if (s->entry) {
       
   105         qemu_remove_mouse_event_handler(s->entry);
       
   106         s->entry = NULL;
       
   107     }
       
   108     if (s->status == 0)
       
   109         s->entry = qemu_add_mouse_event_handler(vmmouse_mouse_event,
       
   110                                                 s, s->absolute,
       
   111                                                 "vmmouse");
       
   112 }
       
   113 
       
   114 static void vmmouse_read_id(VMMouseState *s)
       
   115 {
       
   116     DPRINTF("vmmouse_read_id()\n");
       
   117 
       
   118     if (s->nb_queue == VMMOUSE_QUEUE_SIZE)
       
   119         return;
       
   120 
       
   121     s->queue[s->nb_queue++] = VMMOUSE_VERSION;
       
   122     s->status = 0;
       
   123     vmmouse_update_handler(s);
       
   124 }
       
   125 
       
   126 static void vmmouse_request_relative(VMMouseState *s)
       
   127 {
       
   128     DPRINTF("vmmouse_request_relative()\n");
       
   129     s->absolute = 0;
       
   130     vmmouse_update_handler(s);
       
   131 }
       
   132 
       
   133 static void vmmouse_request_absolute(VMMouseState *s)
       
   134 {
       
   135     DPRINTF("vmmouse_request_absolute()\n");
       
   136     s->absolute = 1;
       
   137     vmmouse_update_handler(s);
       
   138 }
       
   139 
       
   140 static void vmmouse_disable(VMMouseState *s)
       
   141 {
       
   142     DPRINTF("vmmouse_disable()\n");
       
   143     s->status = 0xffff;
       
   144     vmmouse_update_handler(s);
       
   145 }
       
   146 
       
   147 static void vmmouse_data(VMMouseState *s, uint32_t *data, uint32_t size)
       
   148 {
       
   149     int i;
       
   150 
       
   151     DPRINTF("vmmouse_data(%d)\n", size);
       
   152 
       
   153     if (size == 0 || size > 6 || size > s->nb_queue) {
       
   154         printf("vmmouse: driver requested too much data %d\n", size);
       
   155         s->status = 0xffff;
       
   156         vmmouse_update_handler(s);
       
   157         return;
       
   158     }
       
   159 
       
   160     for (i = 0; i < size; i++)
       
   161         data[i] = s->queue[i];
       
   162 
       
   163     s->nb_queue -= size;
       
   164     if (s->nb_queue)
       
   165         memmove(s->queue, &s->queue[size], sizeof(s->queue[0]) * s->nb_queue);
       
   166 }
       
   167 
       
   168 static void vmmouse_get_data(uint32_t *data)
       
   169 {
       
   170     CPUState *env = cpu_single_env;
       
   171 
       
   172     data[0] = env->regs[R_EAX]; data[1] = env->regs[R_EBX];
       
   173     data[2] = env->regs[R_ECX]; data[3] = env->regs[R_EDX];
       
   174     data[4] = env->regs[R_ESI]; data[5] = env->regs[R_EDI];
       
   175 
       
   176     DPRINTF("get_data = {%x, %x, %x, %x, %x, %x}\n",
       
   177             data[0], data[1], data[2], data[3], data[4], data[5]);
       
   178 }
       
   179 
       
   180 static void vmmouse_set_data(const uint32_t *data)
       
   181 {
       
   182     CPUState *env = cpu_single_env;
       
   183 
       
   184     DPRINTF("set_data = {%x, %x, %x, %x, %x, %x}\n",
       
   185             data[0], data[1], data[2], data[3], data[4], data[5]);
       
   186 
       
   187     env->regs[R_EAX] = data[0]; env->regs[R_EBX] = data[1];
       
   188     env->regs[R_ECX] = data[2]; env->regs[R_EDX] = data[3];
       
   189     env->regs[R_ESI] = data[4]; env->regs[R_EDI] = data[5];
       
   190 }
       
   191 
       
   192 static uint32_t vmmouse_ioport_read(void *opaque, uint32_t addr)
       
   193 {
       
   194     VMMouseState *s = opaque;
       
   195     uint32_t data[6];
       
   196     uint16_t command;
       
   197 
       
   198     vmmouse_get_data(data);
       
   199 
       
   200     command = data[2] & 0xFFFF;
       
   201 
       
   202     switch (command) {
       
   203     case VMMOUSE_STATUS:
       
   204         data[0] = vmmouse_get_status(s);
       
   205         break;
       
   206     case VMMOUSE_COMMAND:
       
   207         switch (data[1]) {
       
   208         case VMMOUSE_DISABLE:
       
   209             vmmouse_disable(s);
       
   210             break;
       
   211         case VMMOUSE_READ_ID:
       
   212             vmmouse_read_id(s);
       
   213             break;
       
   214         case VMMOUSE_REQUEST_RELATIVE:
       
   215             vmmouse_request_relative(s);
       
   216             break;
       
   217         case VMMOUSE_REQUEST_ABSOLUTE:
       
   218             vmmouse_request_absolute(s);
       
   219             break;
       
   220         default:
       
   221             printf("vmmouse: unknown command %x\n", data[1]);
       
   222             break;
       
   223         }
       
   224         break;
       
   225     case VMMOUSE_DATA:
       
   226         vmmouse_data(s, data, data[1]);
       
   227         break;
       
   228     default:
       
   229         printf("vmmouse: unknown command %x\n", command);
       
   230         break;
       
   231     }
       
   232 
       
   233     vmmouse_set_data(data);
       
   234     return data[0];
       
   235 }
       
   236 
       
   237 static void vmmouse_save(QEMUFile *f, void *opaque)
       
   238 {
       
   239     VMMouseState *s = opaque;
       
   240     int i;
       
   241 
       
   242     qemu_put_be32(f, VMMOUSE_QUEUE_SIZE);
       
   243     for (i = 0; i < VMMOUSE_QUEUE_SIZE; i++)
       
   244         qemu_put_be32s(f, &s->queue[i]);
       
   245     qemu_put_be16s(f, &s->nb_queue);
       
   246     qemu_put_be16s(f, &s->status);
       
   247     qemu_put_8s(f, &s->absolute);
       
   248 }
       
   249 
       
   250 static int vmmouse_load(QEMUFile *f, void *opaque, int version_id)
       
   251 {
       
   252     VMMouseState *s = opaque;
       
   253     int i;
       
   254 
       
   255     if (version_id != 0)
       
   256         return -EINVAL;
       
   257 
       
   258     if (qemu_get_be32(f) != VMMOUSE_QUEUE_SIZE)
       
   259         return -EINVAL;
       
   260     for (i = 0; i < VMMOUSE_QUEUE_SIZE; i++)
       
   261         qemu_get_be32s(f, &s->queue[i]);
       
   262     qemu_get_be16s(f, &s->nb_queue);
       
   263     qemu_get_be16s(f, &s->status);
       
   264     qemu_get_8s(f, &s->absolute);
       
   265 
       
   266     vmmouse_update_handler(s);
       
   267 
       
   268     return 0;
       
   269 }
       
   270 
       
   271 void *vmmouse_init(void *m)
       
   272 {
       
   273     VMMouseState *s = NULL;
       
   274 
       
   275     DPRINTF("vmmouse_init\n");
       
   276 
       
   277     s = qemu_mallocz(sizeof(VMMouseState));
       
   278     if (!s)
       
   279         return NULL;
       
   280 
       
   281     s->status = 0xffff;
       
   282     s->ps2_mouse = m;
       
   283 
       
   284     vmport_register(VMMOUSE_STATUS, vmmouse_ioport_read, s);
       
   285     vmport_register(VMMOUSE_COMMAND, vmmouse_ioport_read, s);
       
   286     vmport_register(VMMOUSE_DATA, vmmouse_ioport_read, s);
       
   287     register_savevm("vmmouse", 0, 0, vmmouse_save, vmmouse_load, s);
       
   288 
       
   289     return s;
       
   290 }