~ahs3/+junk/cq-qemu

« back to all changes in this revision

Viewing changes to hw/vmmouse.c

  • Committer: Al Stone
  • Date: 2012-02-09 01:17:20 UTC
  • Revision ID: albert.stone@canonical.com-20120209011720-tztl7ik3qayz80p4
first commit to bzr for qemu

Show diffs side-by-side

added added

removed removed

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